Skip to content

Commit

Permalink
Progress :P
Browse files Browse the repository at this point in the history
  • Loading branch information
freiksenet committed Jan 25, 2018
1 parent db2806a commit f1b2432
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 11 deletions.
2 changes: 2 additions & 0 deletions src/stitching/delegateToSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '../transforms';
import AddArgumentsAsVariables from '../transforms/AddArgumentsAsVariables';
import FilterToSchema from '../transforms/FilterToSchema';
import AddTypenameToAbstract from '../transforms/AddTypenameToAbstract';
import CheckResultAndHandleErrors from '../transforms/CheckResultAndHandleErrors';

export default async function delegateToSchema(
Expand Down Expand Up @@ -51,6 +52,7 @@ export default async function delegateToSchema(
...transforms,
AddArgumentsAsVariables(targetSchema, args),
FilterToSchema(targetSchema),
AddTypenameToAbstract(targetSchema),
CheckResultAndHandleErrors(info, targetField),
];

Expand Down
75 changes: 75 additions & 0 deletions src/transforms/AddTypenameToAbstract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
DocumentNode,
FieldNode,
GraphQLInterfaceType,
GraphQLSchema,
GraphQLType,
GraphQLUnionType,
Kind,
SelectionSetNode,
TypeInfo,
visit,
visitWithTypeInfo,
} from 'graphql';
import { Request } from '../Interfaces';
import { Transform } from './index';

export default function AddTypenameToAbstract(
targetSchema: GraphQLSchema,
): Transform {
return {
transformRequest(originalRequest: Request): Request {
const document = addTypenameToAbstract(
targetSchema,
originalRequest.document,
);
return {
...originalRequest,
document,
};
},
};
}

function addTypenameToAbstract(
targetSchema: GraphQLSchema,
document: DocumentNode,
): DocumentNode {
const typeInfo = new TypeInfo(targetSchema);
return visit(
document,
visitWithTypeInfo(typeInfo, {
[Kind.SELECTION_SET](
node: SelectionSetNode,
): SelectionSetNode | null | undefined {
const parentType: GraphQLType = typeInfo.getParentType();
let selections = node.selections;
if (
parentType &&
(parentType instanceof GraphQLInterfaceType ||
parentType instanceof GraphQLUnionType) &&
!selections.find(
_ =>
(_ as FieldNode).kind === Kind.FIELD &&
(_ as FieldNode).name.value === '__typename',
)
) {
selections = selections.concat({
kind: Kind.FIELD,
name: {
kind: Kind.NAME,
value: '__typename',
},
});
}

if (selections !== node.selections) {
return {
...node,
selections,
};
}
},
}),
);
}
40 changes: 29 additions & 11 deletions src/transforms/FilterToSchema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ArgumentNode,
DocumentNode,
FieldNode,
FragmentDefinitionNode,
Expand All @@ -16,9 +17,9 @@ import {
OperationDefinitionNode,
SelectionSetNode,
TypeNameMetaFieldDef,
VariableDefinitionNode,
VariableNode,
visit,
VariableDefinitionNode,
} from 'graphql';
import { Request } from '../Interfaces';
import { Transform } from './index';
Expand Down Expand Up @@ -56,15 +57,19 @@ function filterDocumentToSchema(
const newOperations: Array<OperationDefinitionNode> = [];
let newFragments: Array<FragmentDefinitionNode> = [];

const validFragments: Array<string> = fragments
.filter((fragment: FragmentDefinitionNode) => {
const typeName = fragment.typeCondition.name.value;
const type = targetSchema.getType(typeName);
return Boolean(type);
})
.map((fragment: FragmentDefinitionNode) => fragment.name.value);
const validFragments: Array<
FragmentDefinitionNode
> = fragments.filter((fragment: FragmentDefinitionNode) => {
const typeName = fragment.typeCondition.name.value;
const type = targetSchema.getType(typeName);
return Boolean(type);
});

fragments.forEach((fragment: FragmentDefinitionNode) => {
const validFragmentNames: Array<string> = validFragments.map(
(fragment: FragmentDefinitionNode) => fragment.name.value,
);

validFragments.forEach((fragment: FragmentDefinitionNode) => {
const name = fragment.name.value;
const typeName = fragment.typeCondition.name.value;
const type = targetSchema.getType(typeName);
Expand All @@ -75,7 +80,7 @@ function filterDocumentToSchema(
} = filterSelectionSet(
targetSchema,
type,
validFragments,
validFragmentNames,
fragment.selectionSet,
);
usedFragments = union(usedFragments, fragmentUsedFragments);
Expand Down Expand Up @@ -108,7 +113,7 @@ function filterDocumentToSchema(
} = filterSelectionSet(
targetSchema,
type,
validFragments,
validFragmentNames,
operation.selectionSet,
);

Expand Down Expand Up @@ -171,6 +176,19 @@ function filterSelectionSet(
} else {
typeStack.push(field.type);
}

const argNames = (field.args || []).map(arg => arg.name);
if (node.arguments) {
let args = node.arguments.filter((arg: ArgumentNode) => {
return argNames.indexOf(arg.name.value) !== -1;
});
if (args.length !== node.arguments.length) {
return {
...node,
arguments: args,
};
}
}
} else if (
parentType instanceof GraphQLUnionType &&
node.name.value === '__typename'
Expand Down

0 comments on commit f1b2432

Please sign in to comment.