Skip to content

Commit a506b4f

Browse files
committed
Fix fragments not getting deduped when using documentMode=graphQLTag
1 parent 5fed87a commit a506b4f

2 files changed

Lines changed: 81 additions & 4 deletions

File tree

packages/plugins/other/visitor-plugin-common/src/client-side-base-visitor.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ export class ClientSideBaseVisitor<
323323
return fragmentNames.map(document => this.getFragmentVariableName(document));
324324
}
325325

326-
protected _includeFragments(fragments: string[]): string {
326+
protected _includeFragments(fragments: string[], nodeKind: 'FragmentDefinition' | 'OperationDefinition'): string {
327327
if (fragments && fragments.length > 0) {
328328
if (this.config.documentMode === DocumentMode.documentNode || this.config.documentMode === DocumentMode.string) {
329329
return Array.from(this._fragments.values())
@@ -334,6 +334,9 @@ export class ClientSideBaseVisitor<
334334
if (this.config.documentMode === DocumentMode.documentNodeImportFragments) {
335335
return '';
336336
}
337+
if (nodeKind !== 'OperationDefinition') {
338+
return '';
339+
}
337340
return String(fragments.map(name => '${' + name + '}').join('\n'));
338341
}
339342

@@ -346,13 +349,15 @@ export class ClientSideBaseVisitor<
346349

347350
protected _gql(node: FragmentDefinitionNode | OperationDefinitionNode): string {
348351
const includeNestedFragments =
349-
this.config.documentMode === DocumentMode.documentNode || this.config.documentMode === DocumentMode.string;
352+
this.config.documentMode === DocumentMode.documentNode ||
353+
this.config.documentMode === DocumentMode.string ||
354+
node.kind === 'OperationDefinition';
350355
const fragmentNames = this._extractFragments(node, includeNestedFragments);
351356
const fragments = this._transformFragments(fragmentNames);
352357

353358
const doc = this._prepareDocument(`
354359
${print(node).split('\\').join('\\\\') /* Re-escape escaped values in GraphQL syntax */}
355-
${this._includeFragments(fragments)}`);
360+
${this._includeFragments(fragments, node.kind)}`);
356361

357362
if (this.config.documentMode === DocumentMode.documentNode) {
358363
let gqlObj = gqlTag([doc]);

packages/plugins/typescript/typed-document-node/tests/typed-document-node.spec.ts

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Types } from '@graphql-codegen/plugin-helpers';
1+
import { mergeOutputs, Types } from '@graphql-codegen/plugin-helpers';
2+
import { DocumentMode } from '@graphql-codegen/visitor-plugin-common';
23
import { buildSchema, parse } from 'graphql';
34
import { plugin } from '../src/index.js';
45

@@ -9,6 +10,77 @@ describe('TypedDocumentNode', () => {
910
expect(result.prepend.length).toBe(0);
1011
});
1112

13+
it('dedupes fragments automatically when documentMode=graphQLTag', async () => {
14+
const schema = buildSchema(/* GraphQL */ `
15+
type Query {
16+
person(id: ID!): Person!
17+
}
18+
type Person {
19+
id: ID!
20+
name: String!
21+
children: [Person!]
22+
}
23+
`);
24+
25+
const document = parse(/* GraphQL */ `
26+
query Person {
27+
person(id: 1) {
28+
...PersonDetails
29+
children {
30+
...BasePersonDetails
31+
}
32+
}
33+
}
34+
35+
fragment PersonDetails on Person {
36+
...BasePersonDetails
37+
name
38+
}
39+
40+
fragment BasePersonDetails on Person {
41+
id
42+
}
43+
`);
44+
45+
const result = mergeOutputs([
46+
await plugin(
47+
schema,
48+
[{ document }],
49+
{
50+
documentMode: DocumentMode.graphQLTag,
51+
},
52+
{ outputFile: '' }
53+
),
54+
]);
55+
56+
expect(result).toMatchInlineSnapshot(`
57+
"import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
58+
import gql from 'graphql-tag';
59+
export const BasePersonDetailsFragmentDoc = gql\`
60+
fragment BasePersonDetails on Person {
61+
id
62+
}
63+
\` as unknown as DocumentNode<BasePersonDetailsFragment, unknown>;
64+
export const PersonDetailsFragmentDoc = gql\`
65+
fragment PersonDetails on Person {
66+
...BasePersonDetails
67+
name
68+
}
69+
\` as unknown as DocumentNode<PersonDetailsFragment, unknown>;
70+
export const PersonDocument = gql\`
71+
query Person {
72+
person(id: 1) {
73+
...PersonDetails
74+
children {
75+
...BasePersonDetails
76+
}
77+
}
78+
}
79+
\${PersonDetailsFragmentDoc}
80+
\${BasePersonDetailsFragmentDoc}\` as unknown as DocumentNode<PersonQuery, PersonQueryVariables>;"
81+
`);
82+
});
83+
1284
describe('addTypenameToSelectionSets', () => {
1385
it('Check is add __typename to typed document', async () => {
1486
const schema = buildSchema(/* GraphQL */ `

0 commit comments

Comments
 (0)