diff --git a/.changeset/honest-hairs-wave.md b/.changeset/honest-hairs-wave.md new file mode 100644 index 0000000000..bf4545ec25 --- /dev/null +++ b/.changeset/honest-hairs-wave.md @@ -0,0 +1,5 @@ +--- +'@urql/core': patch +--- + +Fix `ssrExchange` not formatting query documents using `formatDocument`. Without this call we'd run the risk of not having `__typename` available on the client-side when rehydrating. diff --git a/packages/core/src/exchanges/cache.ts b/packages/core/src/exchanges/cache.ts index 87873fbc33..5d8db3627a 100755 --- a/packages/core/src/exchanges/cache.ts +++ b/packages/core/src/exchanges/cache.ts @@ -17,6 +17,18 @@ type OperationCache = Map>; const shouldSkip = ({ kind }: Operation) => kind !== 'mutation' && kind !== 'query'; +/** Adds unique typenames to query (for invalidating cache entries) */ +export const mapTypeNames = (operation: Operation): Operation => { + const query = formatDocument(operation.query); + if (query !== operation.query) { + const formattedOperation = makeOperation(operation.kind, operation); + formattedOperation.query = query; + return formattedOperation; + } else { + return operation; + } +}; + /** Default document cache exchange. * * @remarks @@ -41,13 +53,6 @@ export const cacheExchange: Exchange = ({ forward, client, dispatchDebug }) => { const resultCache: ResultCache = new Map(); const operationCache: OperationCache = new Map(); - // Adds unique typenames to query (for invalidating cache entries) - const mapTypeNames = (operation: Operation): Operation => { - const formattedOperation = makeOperation(operation.kind, operation); - formattedOperation.query = formatDocument(operation.query); - return formattedOperation; - }; - const isOperationCached = (operation: Operation) => operation.kind === 'query' && operation.context.requestPolicy !== 'network-only' && diff --git a/packages/core/src/exchanges/ssr.test.ts b/packages/core/src/exchanges/ssr.test.ts index 866a2bd586..3fd8170492 100644 --- a/packages/core/src/exchanges/ssr.test.ts +++ b/packages/core/src/exchanges/ssr.test.ts @@ -4,7 +4,7 @@ import { vi, expect, it, beforeEach, afterEach } from 'vitest'; import { Client } from '../client'; import { queryOperation, queryResponse } from '../test-utils'; import { ExchangeIO, Operation, OperationResult } from '../types'; -import { CombinedError } from '../utils'; +import { CombinedError, formatDocument } from '../utils'; import { ssrExchange } from './ssr'; let forward: ExchangeIO; @@ -254,6 +254,10 @@ it('resolves deferred, cached query results correctly', () => { }, }, }); + + expect(output.mock.calls[0][0].query).toBe( + formatDocument(queryOperation.query) + ); }); it('deletes cached results in non-suspense environments', async () => { diff --git a/packages/core/src/exchanges/ssr.ts b/packages/core/src/exchanges/ssr.ts index e36dd0e76c..c1aa1ec1f4 100644 --- a/packages/core/src/exchanges/ssr.ts +++ b/packages/core/src/exchanges/ssr.ts @@ -2,7 +2,7 @@ import type { GraphQLError } from '../utils/graphql'; import { pipe, filter, merge, map, tap } from 'wonka'; import { Exchange, OperationResult, Operation } from '../types'; import { addMetadata, CombinedError } from '../utils'; -import { reexecuteOperation } from './cache'; +import { reexecuteOperation, mapTypeNames } from './cache'; /** A serialized version of an {@link OperationResult}. * @@ -226,6 +226,7 @@ export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => { !!data[operation.key]!.hasNext || operation.context.requestPolicy === 'network-only' ), + map(mapTypeNames), forward );