diff --git a/.changeset/breezy-tomatoes-sing.md b/.changeset/breezy-tomatoes-sing.md new file mode 100644 index 000000000..72994c5a1 --- /dev/null +++ b/.changeset/breezy-tomatoes-sing.md @@ -0,0 +1,5 @@ +--- +'@urql/exchange-graphcache': minor +--- + +Allow @_required directive to be used in combination with configured schemas diff --git a/exchanges/graphcache/src/cacheExchange.test.ts b/exchanges/graphcache/src/cacheExchange.test.ts index 832d32f63..cda29dc2b 100644 --- a/exchanges/graphcache/src/cacheExchange.test.ts +++ b/exchanges/graphcache/src/cacheExchange.test.ts @@ -1544,6 +1544,71 @@ describe('directives', () => { expect(reexecuteOperation).toHaveBeenCalledTimes(0); expect(result.mock.calls[0][0].data).toEqual(null); }); + + it('does not return missing fields when nullable fields from a defined schema are marked as required in the query', () => { + const client = createClient({ + url: 'http://0.0.0.0', + exchanges: [], + }); + const { source: ops$, next } = makeSubject(); + + const query = gql` + { + latestTodo { + id + text + completed @_required + } + } + `; + + const operation = client.createRequestOperation('query', { + key: 1, + query, + variables: undefined, + }); + + const queryResult: OperationResult = { + ...queryResponse, + operation, + data: { + __typename: 'Query', + latestTodo: [ + { + id: '1', + text: 'learn urql', + completed: null, + __typename: 'Todo', + }, + ], + }, + }; + + const response = vi.fn((forwardOp: Operation): OperationResult => { + if (forwardOp.key === 1) return queryResult; + return undefined as any; + }); + + const result = vi.fn(); + const forward: ExchangeIO = ops$ => pipe(ops$, map(response), share); + + pipe( + cacheExchange({ + schema: minifyIntrospectionQuery( + // eslint-disable-next-line + require('./test-utils/simple_schema.json') + ), + })({ forward, client, dispatchDebug })(ops$), + tap(result), + publish + ); + + next(operation); + + console.log(result.mock.calls[0][0]) + + expect(result.mock.calls[0][0].data).toEqual(null); + }); }); describe('optimistic updates', () => { diff --git a/exchanges/graphcache/src/operations/query.ts b/exchanges/graphcache/src/operations/query.ts index 54b9c5cd5..3ad90a2ec 100644 --- a/exchanges/graphcache/src/operations/query.ts +++ b/exchanges/graphcache/src/operations/query.ts @@ -534,7 +534,8 @@ const readSelection = ( (directives.optional || (optionalRef && !directives.required) || !!getFieldError(ctx) || - (!directives.required && store.schema && + (!directives.required && + store.schema && isFieldNullable(store.schema, typename, fieldName, ctx.store.logger))) ) { // The field is uncached or has errored, so it'll be set to null and skipped