Skip to content

Commit

Permalink
Fragment replacement
Browse files Browse the repository at this point in the history
  • Loading branch information
freiksenet committed Jan 25, 2018
1 parent e33c215 commit db2806a
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 80 deletions.
4 changes: 1 addition & 3 deletions src/stitching/delegateToSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,11 @@ export default async function delegateToSchema(
...transforms,
AddArgumentsAsVariables(targetSchema, args),
FilterToSchema(targetSchema),
CheckResultAndHandleErrors(info),
CheckResultAndHandleErrors(info, targetField),
];

const processedRequest = applyRequestTransforms(rawRequest, transforms);

console.log(print(processedRequest.document), processedRequest.variables);

if (targetOperation === 'query' || targetOperation === 'mutation') {
const rawResult = await graphql(
targetSchema,
Expand Down
7 changes: 6 additions & 1 deletion src/stitching/mergeSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
} from './schemaRecreation';
import delegateToSchema from './delegateToSchema';
import typeFromAST, { GetType } from './typeFromAST';
import ReplaceFieldWithFragment from '../transforms/ReplaceFieldWithFragment';

export default function mergeSchemas({
schemas,
Expand Down Expand Up @@ -259,6 +260,10 @@ function createMergeInfo(
info: GraphQLResolveInfo,
): any {
const schema = schemas[schemaName];
const fragmentTransform = ReplaceFieldWithFragment(
schema,
fragmentReplacements,
);
if (!schema) {
throw new Error(`No subschema named ${schemaName}.`);
}
Expand All @@ -269,7 +274,7 @@ function createMergeInfo(
args,
context,
info,
[],
[fragmentTransform],
);
},
};
Expand Down
3 changes: 2 additions & 1 deletion src/transforms/CheckResultAndHandleErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { Transform } from './index';

export default function CheckResultAndHandleErrors(
info: GraphQLResolveInfo,
fieldName?: string,
): Transform {
return {
transformResult(result: any): any {
return checkResultAndHandleErrors(result, info);
return checkResultAndHandleErrors(result, info, fieldName);
},
};
}
2 changes: 1 addition & 1 deletion src/transforms/FilterToSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ function filterSelectionSet(
}
}
},
leave(node: InlineFragmentNode): null | undefined {
leave(node: InlineFragmentNode) {
typeStack.pop();
},
},
Expand Down
124 changes: 50 additions & 74 deletions src/transforms/ReplaceFieldWithFragment.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
import {
DocumentNode,
GraphQLSchema,
GraphQLType,
InlineFragmentNode,
Kind,
SelectionSetNode,
TypeInfo,
visit,
visitWithTypeInfo,
} from 'graphql';
import { Request } from '../Interfaces';
import { Transform } from './index';

export type FieldToFragmentMapping = {
[typeName: string]: { [fieldName: string]: InlineFragmentNode };
};

export default function ReplaceFieldWithFragment(
targetSchema: GraphQLSchema,
mapping: FieldToFragmentMapping,
): Transform {
return {
transformRequest(originalRequest: Request): Request {
const document = replaceFieldsWithFragments(
targetSchema,
originalRequest.document,
mapping,
);
Expand All @@ -16,87 +36,43 @@ export default function ReplaceFieldWithFragment(
}

function replaceFieldsWithFragments(
targetSchema: GraphQLSchema,
document: DocumentNode,
mapping: FieldToFragmentMapping,
): DocumentNode {
const typeStack: Array<GraphQLType> = [type];
return visit(document, {
// [Kind.FIELD]: {
// enter(node: FieldNode): null | undefined | FieldNode {
// let parentType: GraphQLNamedType = resolveType(
// typeStack[typeStack.length - 1],
// );
// if (
// parentType instanceof GraphQLObjectType ||
// parentType instanceof GraphQLInterfaceType
// ) {
// const fields = parentType.getFields();
// const field =
// node.name.value === '__typename'
// ? TypeNameMetaFieldDef
// : fields[node.name.value];
// if (!field) {
// return null;
// } else {
// typeStack.push(field.type);
// }
// } else if (
// parentType instanceof GraphQLUnionType &&
// node.name.value === '__typename'
// ) {
// typeStack.push(TypeNameMetaFieldDef.type);
// }
// },
// leave() {
// typeStack.pop();
// },
// },
[Kind.SELECTION_SET](
node: SelectionSetNode,
): SelectionSetNode | null | undefined {
const parentType: GraphQLType = resolveType(
typeStack[typeStack.length - 1],
);
const parentTypeName = parentType.name;
const typeInfo = new TypeInfo(targetSchema);
return visit(
document,
visitWithTypeInfo(typeInfo, {
[Kind.SELECTION_SET](
node: SelectionSetNode,
): SelectionSetNode | null | undefined {
const parentType: GraphQLType = typeInfo.getParentType();
if (parentType) {
const parentTypeName = parentType.name;

if (fragmentReplacements[parentTypeName]) {
selections.forEach(selection => {
if (selection.kind === Kind.FIELD) {
const name = selection.name.value;
const fragment = fragmentReplacements[parentTypeName][name];
if (fragment) {
selections = selections.concat(fragment);
}
}
});
}
let selections = node.selections;

if (selections !== node.selections) {
return {
...node,
selections,
};
}
},
[Kind.INLINE_FRAGMENT]: {
enter(node: InlineFragmentNode): null | undefined {
if (node.typeCondition) {
const innerType = schema.getType(node.typeCondition.name.value);
const parentType: GraphQLNamedType = resolveType(
typeStack[typeStack.length - 1],
);
if (implementsAbstractType(parentType, innerType)) {
typeStack.push(innerType);
} else {
return null;
if (mapping[parentTypeName]) {
node.selections.forEach(selection => {
if (selection.kind === Kind.FIELD) {
const name = selection.name.value;
const fragment = mapping[parentTypeName][name];
if (fragment) {
selections = selections.concat(fragment);
}
}
});
}
}
},
leave(node: InlineFragmentNode): null | undefined {

typeStack.pop();
if (selections !== node.selections) {
return {
...node,
selections,
};
}
}
},
},
});
}),
);
}

0 comments on commit db2806a

Please sign in to comment.