Skip to content

Commit 3efc472

Browse files
authored
fix(client-preset): remove fragment spread and inline fragments if th… (#10298)
* fix(client-preset): remove fragment spread and inline fragments if they are defined with `@client` directive * tiny cleanup
1 parent 6d7c1d7 commit 3efc472

File tree

3 files changed

+79
-2
lines changed

3 files changed

+79
-2
lines changed

.changeset/empty-wolves-stare.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-codegen/client-preset': patch
3+
---
4+
5+
Fix a bug where fragment spreads with `@client` directives is not being removed from the generated persisted documents
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { parse } from 'graphql';
2+
import { normalizeAndPrintDocumentNode } from './persisted-documents';
3+
4+
describe('normalizeAndPrintDocumentNode', () => {
5+
it('should remove client specific directives/fields from the document', () => {
6+
const document = parse(/* GraphQL */ `
7+
query myQuery {
8+
regularField
9+
clientSideOnlyField @client
10+
}
11+
`);
12+
const result = normalizeAndPrintDocumentNode(document);
13+
expect(result).toMatchInlineSnapshot(`"query myQuery { regularField }"`);
14+
});
15+
16+
it('should remove @client when it is specified on an fragment spread', () => {
17+
const document = parse(/* GraphQL */ `
18+
query myQuery {
19+
regularField
20+
clientSideOnlyField @client
21+
...myFrag @client
22+
...myOtherFrag
23+
}
24+
25+
fragment myFrag on Query {
26+
someField
27+
}
28+
`);
29+
const result = normalizeAndPrintDocumentNode(document);
30+
expect(result).toMatchInlineSnapshot(
31+
`"fragment myFrag on Query { someField } query myQuery { regularField ...myOtherFrag }"`
32+
);
33+
});
34+
35+
it('should remove @client when it is specified on an inline fragment', () => {
36+
const document = parse(/* GraphQL */ `
37+
query myQuery {
38+
regularField
39+
clientSideOnlyField @client
40+
...myFrag @client
41+
... on Query @client {
42+
someField
43+
}
44+
... on Query {
45+
regularField
46+
}
47+
}
48+
49+
fragment myFrag on Query {
50+
someField
51+
}
52+
`);
53+
const result = normalizeAndPrintDocumentNode(document);
54+
expect(result).toMatchInlineSnapshot(
55+
`"fragment myFrag on Query { someField } query myQuery { regularField ... on Query { regularField } }"`
56+
);
57+
});
58+
});

packages/presets/client/src/persisted-documents.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { printExecutableGraphQLDocument } from '@graphql-tools/documents';
22
import * as crypto from 'crypto';
33
import { Kind, visit, type DocumentNode } from 'graphql';
44

5+
const CLIENT_DIRECTIVE_NAME = 'client';
6+
const CONNECTION_DIRECTIVE_NAME = 'connection';
7+
58
/**
69
* This function generates a hash from a document node.
710
*/
@@ -30,15 +33,26 @@ export function normalizeAndPrintDocumentNode(documentNode: DocumentNode): strin
3033
*/
3134
const sanitizedDocument = visit(documentNode, {
3235
[Kind.FIELD](field) {
33-
if (field.directives?.some(directive => directive.name.value === 'client')) {
36+
if (field.directives?.some(directive => directive.name.value === CLIENT_DIRECTIVE_NAME)) {
37+
return null;
38+
}
39+
},
40+
[Kind.FRAGMENT_SPREAD](spread) {
41+
if (spread.directives?.some(directive => directive.name.value === CLIENT_DIRECTIVE_NAME)) {
42+
return null;
43+
}
44+
},
45+
[Kind.INLINE_FRAGMENT](fragment) {
46+
if (fragment.directives?.some(directive => directive.name.value === CLIENT_DIRECTIVE_NAME)) {
3447
return null;
3548
}
3649
},
3750
[Kind.DIRECTIVE](directive) {
38-
if (directive.name.value === 'connection') {
51+
if (directive.name.value === CONNECTION_DIRECTIVE_NAME) {
3952
return null;
4053
}
4154
},
4255
});
56+
4357
return printExecutableGraphQLDocument(sanitizedDocument);
4458
}

0 commit comments

Comments
 (0)