Skip to content

Commit

Permalink
feat: allow deferredFields works with fragment
Browse files Browse the repository at this point in the history
  • Loading branch information
ludusrusso committed Jul 26, 2023
1 parent 5829dd9 commit 3a7bd84
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ export class ClientSideBaseVisitor<
}

let metaString = '';
if (this._onExecutableDocumentNode && node.kind === Kind.OPERATION_DEFINITION) {
if (this._onExecutableDocumentNode) {
const meta = this._getGraphQLCodegenMetadata(node, definitions);

if (meta) {
Expand All @@ -428,7 +428,9 @@ export class ClientSideBaseVisitor<

if (this.config.documentMode === DocumentMode.string) {
if (node.kind === Kind.FRAGMENT_DEFINITION) {
return `new TypedDocumentString(\`${doc}\`, ${JSON.stringify({ fragmentName: node.name.value })})`;
const meta = this._getGraphQLCodegenMetadata(node, gqlTag([doc]).definitions);

return `new TypedDocumentString(\`${doc}\`, ${JSON.stringify({ fragmentName: node.name.value, ...meta })})`;
}

if (this._onExecutableDocumentNode && node.kind === Kind.OPERATION_DEFINITION) {
Expand All @@ -451,15 +453,17 @@ export class ClientSideBaseVisitor<
}

protected _getGraphQLCodegenMetadata(
node: OperationDefinitionNode,
node: OperationDefinitionNode | FragmentDefinitionNode,
definitions?: ReadonlyArray<DefinitionNode>
): Record<string, any> | void | undefined {
let meta: Record<string, any> | void | undefined;

meta = this._onExecutableDocumentNode({
kind: Kind.DOCUMENT,
definitions,
});
if (node.kind === Kind.OPERATION_DEFINITION) {
meta = this._onExecutableDocumentNode({
kind: Kind.DOCUMENT,
definitions,
});
}

const deferredFields = this._findDeferredFields(node);
if (Object.keys(deferredFields).length) {
Expand All @@ -472,7 +476,9 @@ export class ClientSideBaseVisitor<
return meta;
}

protected _findDeferredFields(node: OperationDefinitionNode): { [fargmentName: string]: string[] } {
protected _findDeferredFields(node: OperationDefinitionNode | FragmentDefinitionNode): {
[fargmentName: string]: string[];
} {
const deferredFields: { [fargmentName: string]: string[] } = {};
const queue: SelectionNode[] = [...node.selectionSet.selections];
while (queue.length) {
Expand Down
50 changes: 50 additions & 0 deletions packages/presets/client/tests/client-preset.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1868,8 +1868,14 @@ export * from "./gql.js";`);
export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' };
export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & (
{ __typename?: 'Foo' }
& { ' $fragmentRefs'?: { 'FooFragment': Incremental<FooFragment> } }
) & { ' $fragmentName'?: 'FooNestedFragment' };
export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode<FooFragment, unknown>;
export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode<FooFragment, unknown>;
export const FooNestedFragmentDoc = {"__meta__":{"deferredFields":{"foo":["id"]}},"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"fooNested"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode<FooNestedFragment, unknown>;
export const FooDocument = {"__meta__":{"deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode<FooQuery, FooQueryVariables>;
export const FoosDocument = {"__meta__":{"deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode<FoosQuery, FoosQueryVariables>;"
`);
Expand Down Expand Up @@ -1953,8 +1959,14 @@ export * from "./gql.js";`);
export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' };
export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & (
{ __typename?: 'Foo' }
& { ' $fragmentRefs'?: { 'FooFragment': Incremental<FooFragment> } }
) & { ' $fragmentName'?: 'FooNestedFragment' };
export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode<FooFragment, unknown>;
export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode<FooFragment, unknown>;
export const FooNestedFragmentDoc = {"__meta__":{"deferredFields":{"foo":["id"]}},"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"fooNested"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode<FooNestedFragment, unknown>;
export const FooDocument = {"__meta__":{"hash":"39c47d2da0fb0e6867abbe2ec942d9858f2d76c7","deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode<FooQuery, FooQueryVariables>;
export const FoosDocument = {"__meta__":{"hash":"8aba765173b2302b9857334e9959d97a2168dbc8","deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode<FoosQuery, FoosQueryVariables>;"
`);
Expand Down Expand Up @@ -2038,6 +2050,11 @@ export * from "./gql.js";`);
export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' };
export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & (
{ __typename?: 'Foo' }
& { ' $fragmentRefs'?: { 'FooFragment': Incremental<FooFragment> } }
) & { ' $fragmentName'?: 'FooNestedFragment' };
export class TypedDocumentString<TResult, TVariables>
extends String
implements DocumentTypeDecoration<TResult, TVariables>
Expand Down Expand Up @@ -2065,6 +2082,20 @@ export * from "./gql.js";`);
}
}
\`, {"fragmentName":"foo"}) as unknown as TypedDocumentString<FooFragment, unknown>;
export const FooNestedFragmentDoc = new TypedDocumentString(\`
fragment fooNested on Foo {
id
...foo @defer
}
fragment Foo on Foo {
value
}
fragment foo on Foo {
id
... on Foo @defer {
value
}
}\`, {"fragmentName":"fooNested","deferredFields":{"foo":["id"]}}) as unknown as TypedDocumentString<FooNestedFragment, unknown>;
export const FooDocument = new TypedDocumentString(\`
query Foo {
foo {
Expand Down Expand Up @@ -2179,6 +2210,11 @@ export * from "./gql.js";`);
export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' };
export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & (
{ __typename?: 'Foo' }
& { ' $fragmentRefs'?: { 'FooFragment': Incremental<FooFragment> } }
) & { ' $fragmentName'?: 'FooNestedFragment' };
export class TypedDocumentString<TResult, TVariables>
extends String
implements DocumentTypeDecoration<TResult, TVariables>
Expand Down Expand Up @@ -2206,6 +2242,20 @@ export * from "./gql.js";`);
}
}
\`, {"fragmentName":"foo"}) as unknown as TypedDocumentString<FooFragment, unknown>;
export const FooNestedFragmentDoc = new TypedDocumentString(\`
fragment fooNested on Foo {
id
...foo @defer
}
fragment Foo on Foo {
value
}
fragment foo on Foo {
id
... on Foo @defer {
value
}
}\`, {"fragmentName":"fooNested","deferredFields":{"foo":["id"]}}) as unknown as TypedDocumentString<FooNestedFragment, unknown>;
export const FooDocument = new TypedDocumentString(\`
query Foo {
foo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ const NestedFragment = gql(/* GraphQL */ `
}
}
`);

//@ts-ignore
const NestedFragmentWithFragment = gql(/* GraphQL */ `
fragment fooNested on Foo {
id
...foo @defer
}
`);

0 comments on commit 3a7bd84

Please sign in to comment.