From 82f221e9a80a40ed874f562ad2074584a11b52bc Mon Sep 17 00:00:00 2001 From: jdecroock Date: Fri, 9 Dec 2022 10:00:15 +0100 Subject: [PATCH 1/7] create reproduction for missing __typename --- packages/core/src/utils/request.test.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/core/src/utils/request.test.ts b/packages/core/src/utils/request.test.ts index 0d0142685d..f3b0511808 100644 --- a/packages/core/src/utils/request.test.ts +++ b/packages/core/src/utils/request.test.ts @@ -92,6 +92,20 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(formatted)).toBe(print(formatted)); }); + it('should reprint gql documents', () => { + const request = createRequest(`query { test { field } }`, {}); + const formatted = formatDocument(request.query); + expect(print(formatted)).toMatchInlineSnapshot(` + "{ + test { + field + __typename + } + }" + `); + expect(stringifyDocument(formatted)).toBe(print(formatted)); + }); + it('should remove comments', () => { const doc = ` { #query @@ -131,7 +145,7 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(createRequest(doc, undefined).query)) .toMatchInlineSnapshot(` "{ - field(arg: + field(arg: \\"test #1\\") }" @@ -152,7 +166,7 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(createRequest(doc, undefined).query)) .toMatchInlineSnapshot(` "{ - field(arg: + field(arg: \\"\\"\\" hello From 6673abfc85d69f9db640094298b94a5489d2ed29 Mon Sep 17 00:00:00 2001 From: jdecroock Date: Fri, 9 Dec 2022 10:20:16 +0100 Subject: [PATCH 2/7] fix issue --- packages/core/src/utils/request.test.ts | 25 ++++++++++++++++++++++++- packages/core/src/utils/typenames.ts | 6 ++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/core/src/utils/request.test.ts b/packages/core/src/utils/request.test.ts index f3b0511808..adc9224907 100644 --- a/packages/core/src/utils/request.test.ts +++ b/packages/core/src/utils/request.test.ts @@ -92,7 +92,7 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(formatted)).toBe(print(formatted)); }); - it('should reprint gql documents', () => { + it('should reprint request documents', () => { const request = createRequest(`query { test { field } }`, {}); const formatted = formatDocument(request.query); expect(print(formatted)).toMatchInlineSnapshot(` @@ -106,6 +106,29 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(formatted)).toBe(print(formatted)); }); + it.only('should reprint gql documents', () => { + const request = createRequest( + gql` + query { + test { + field + } + } + `, + {} + ); + const formatted = formatDocument(request.query); + expect(print(formatted)).toMatchInlineSnapshot(` + "{ + test { + field + __typename + } + }" + `); + expect(stringifyDocument(formatted)).toBe(print(formatted)); + }); + it('should remove comments', () => { const doc = ` { #query diff --git a/packages/core/src/utils/typenames.ts b/packages/core/src/utils/typenames.ts index b6bda51721..d0a1bd7299 100755 --- a/packages/core/src/utils/typenames.ts +++ b/packages/core/src/utils/typenames.ts @@ -4,6 +4,7 @@ import { InlineFragmentNode, Kind, visit, + print, } from 'graphql'; import { KeyedDocumentNode, keyDocument } from './request'; @@ -83,6 +84,11 @@ export const formatDocument = (node: T): T => { }); formattedDocs.set(query.__key, result); + if (typeof node !== 'string' && node.loc?.source.name === 'gql') { + const printed = print(result); + node.loc.source.body = printed; + (node.loc as any).end = printed.length; + } } return (result as unknown) as T; From 0234037378a90e9672426d86e90f775f461cbb1d Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Fri, 9 Dec 2022 10:21:37 +0100 Subject: [PATCH 3/7] Update request.test.ts --- packages/core/src/utils/request.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/utils/request.test.ts b/packages/core/src/utils/request.test.ts index adc9224907..2a198e443f 100644 --- a/packages/core/src/utils/request.test.ts +++ b/packages/core/src/utils/request.test.ts @@ -106,7 +106,7 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(formatted)).toBe(print(formatted)); }); - it.only('should reprint gql documents', () => { + it('should reprint gql documents', () => { const request = createRequest( gql` query { @@ -168,7 +168,7 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(createRequest(doc, undefined).query)) .toMatchInlineSnapshot(` "{ - field(arg: + field(arg: \\"test #1\\") }" @@ -189,7 +189,7 @@ describe('stringifyDocument ', () => { expect(stringifyDocument(createRequest(doc, undefined).query)) .toMatchInlineSnapshot(` "{ - field(arg: + field(arg: \\"\\"\\" hello From ca291e7d7ea2b94483cf427e4254b3c80fffe351 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Fri, 9 Dec 2022 12:56:22 +0100 Subject: [PATCH 4/7] add missing typename --- packages/svelte-urql/src/mutationStore.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/svelte-urql/src/mutationStore.test.ts b/packages/svelte-urql/src/mutationStore.test.ts index 8c47ab39ce..49010c5858 100644 --- a/packages/svelte-urql/src/mutationStore.test.ts +++ b/packages/svelte-urql/src/mutationStore.test.ts @@ -32,6 +32,7 @@ describe('mutationStore', () => { "mutation ($input: Example!) { doExample(input: $input) { id + __typename } }" `); From c993fc80fd4d1d7d508887c0715e74fb05091025 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Fri, 9 Dec 2022 13:41:03 +0000 Subject: [PATCH 5/7] Add stricter reprint caching --- packages/core/src/utils/request.test.ts | 2 -- packages/core/src/utils/request.ts | 21 ++++++++++++--------- packages/core/src/utils/typenames.ts | 6 ------ 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/core/src/utils/request.test.ts b/packages/core/src/utils/request.test.ts index 2a198e443f..1ef3cdd145 100644 --- a/packages/core/src/utils/request.test.ts +++ b/packages/core/src/utils/request.test.ts @@ -169,7 +169,6 @@ describe('stringifyDocument ', () => { .toMatchInlineSnapshot(` "{ field(arg: - \\"test #1\\") }" `); @@ -190,7 +189,6 @@ describe('stringifyDocument ', () => { .toMatchInlineSnapshot(` "{ field(arg: - \\"\\"\\" hello #hello diff --git a/packages/core/src/utils/request.ts b/packages/core/src/utils/request.ts index 8c3d77e278..3b9d907103 100644 --- a/packages/core/src/utils/request.ts +++ b/packages/core/src/utils/request.ts @@ -29,16 +29,21 @@ const replaceOutsideStrings = (str: string, idx: number) => const sanitizeDocument = (node: string): string => node.split(GRAPHQL_STRING_RE).map(replaceOutsideStrings).join('').trim(); +const prints = new Map(); +const docs = new Map(); + export const stringifyDocument = ( node: string | DefinitionNode | DocumentNode ): string => { - const printed = sanitizeDocument( - typeof node === 'string' - ? node - : node.loc && node.loc.source.name === SOURCE_NAME - ? node.loc.source.body - : print(node) - ); + let printed: string; + if (typeof node === 'string') { + printed = sanitizeDocument(node); + } else if (node.loc && docs.get((node as KeyedDocumentNode).__key) === node) { + printed = node.loc.source.body; + } else { + printed = prints.get(node) || sanitizeDocument(print(node)); + prints.set(node, printed); + } if (typeof node !== 'string' && !node.loc) { (node as WritableLocation).loc = { @@ -67,8 +72,6 @@ const hashDocument = ( return key; }; -const docs = new Map(); - export const keyDocument = (node: string | DocumentNode): KeyedDocumentNode => { let key: HashValue; let query: DocumentNode; diff --git a/packages/core/src/utils/typenames.ts b/packages/core/src/utils/typenames.ts index d0a1bd7299..b6bda51721 100755 --- a/packages/core/src/utils/typenames.ts +++ b/packages/core/src/utils/typenames.ts @@ -4,7 +4,6 @@ import { InlineFragmentNode, Kind, visit, - print, } from 'graphql'; import { KeyedDocumentNode, keyDocument } from './request'; @@ -84,11 +83,6 @@ export const formatDocument = (node: T): T => { }); formattedDocs.set(query.__key, result); - if (typeof node !== 'string' && node.loc?.source.name === 'gql') { - const printed = print(result); - node.loc.source.body = printed; - (node.loc as any).end = printed.length; - } } return (result as unknown) as T; From b7c5ee9875c97afc736edb2cdeddf94a9ad37374 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Fri, 9 Dec 2022 13:42:58 +0000 Subject: [PATCH 6/7] Add changeset --- .changeset/large-eggs-cough.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/large-eggs-cough.md diff --git a/.changeset/large-eggs-cough.md b/.changeset/large-eggs-cough.md new file mode 100644 index 0000000000..0809304ea6 --- /dev/null +++ b/.changeset/large-eggs-cough.md @@ -0,0 +1,5 @@ +--- +'@urql/core': patch +--- + +Fix regression in `@urql/core`'s `stringifyDocument` that caused some formatted documents to not be reprinted. From 58eaab66ea9bff94e8539e920ae4a0fceed6d2c6 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Fri, 9 Dec 2022 16:32:41 +0000 Subject: [PATCH 7/7] Revert @urql/svelte test to prove there's no operation.query leak --- packages/svelte-urql/src/mutationStore.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/svelte-urql/src/mutationStore.test.ts b/packages/svelte-urql/src/mutationStore.test.ts index 49010c5858..4fb129d5af 100644 --- a/packages/svelte-urql/src/mutationStore.test.ts +++ b/packages/svelte-urql/src/mutationStore.test.ts @@ -1,3 +1,4 @@ +import { print } from 'graphql'; import { createClient } from '@urql/core'; import { get } from 'svelte/store'; import { vi, expect, it, describe } from 'vitest'; @@ -28,11 +29,10 @@ describe('mutationStore', () => { expect(get(store).operation.context.url).toBe('https://example.com'); expect(get(store).operation.variables).toBe(variables); - expect(get(store).operation.query.loc?.source.body).toMatchInlineSnapshot(` + expect(print(get(store).operation.query)).toMatchInlineSnapshot(` "mutation ($input: Example!) { doExample(input: $input) { id - __typename } }" `);