diff --git a/packages/apollo-link-state/src/__tests__/index.ts b/packages/apollo-link-state/src/__tests__/index.ts index 92dd570..ad7b955 100644 --- a/packages/apollo-link-state/src/__tests__/index.ts +++ b/packages/apollo-link-state/src/__tests__/index.ts @@ -110,6 +110,86 @@ it('runs resolvers for client queries', done => { }, done.fail); }); +it('runs resolvers for nested client queries', done => { + const nestedQuery = gql` + query NestedQuery { + foo @client { + bar + nestedBar { + baz + } + } + } + `; + const getNestedBarById = id => + id === '42' + ? { + baz: true, + } + : null; + + const client = withClientState({ + resolvers: { + Foo: { + nestedBar: ({ nestedBar }) => getNestedBarById(nestedBar), + }, + Query: { + foo: () => ({ bar: true, nestedBar: '42', __typename: 'Foo' }), + }, + }, + }); + execute(client, { query: nestedQuery }).subscribe(({ data }) => { + expect(data).toEqual({ foo: { bar: true, nestedBar: { baz: true } } }); + done(); + }, done.fail); +}); + +it('runs resolvers for missing nested client queries with server data', done => { + const nestedQuery = gql` + query MixedNestedQuery { + foo @client { + bar + nestedBar { + baz + } + } + bar { + baz + } + } + `; + const getNestedBarById = id => + id === '42' + ? { + baz: true, + } + : null; + + const sample = new ApolloLink(() => + Observable.of({ data: { bar: { baz: false } } }), + ); + const client = withClientState({ + resolvers: { + Foo: { + nestedBar: ({ nestedBar }) => getNestedBarById(nestedBar), + }, + Query: { + foo: () => ({ bar: true, nestedBar: '42', __typename: 'Foo' }), + }, + }, + }); + execute(client.concat(sample), { query: nestedQuery }).subscribe( + ({ data }) => { + expect(data).toEqual({ + foo: { bar: true, nestedBar: { baz: true } }, + bar: { baz: true }, + }); + done(); + }, + done.fail, + ); +}); + it('runs resolvers for missing client queries with server data', done => { const query = gql` query Mixed { diff --git a/packages/apollo-link-state/src/index.ts b/packages/apollo-link-state/src/index.ts index 1c99c50..d517207 100644 --- a/packages/apollo-link-state/src/index.ts +++ b/packages/apollo-link-state/src/index.ts @@ -68,19 +68,31 @@ export const withClientState = ( //https://github.com/apollographql/apollo-client/tree/master/packages/graphql-anywhere#resolver-info const fieldValue = rootValue[info.resultKey]; - //If fieldValue is defined, server returned a value - if (fieldValue !== undefined) return fieldValue; + const useServerReturnedValue = + fieldValue !== undefined && + ((rootValue as any).__typename || type) == 'Query'; + + //If fieldValue is defined and we are at the Query level, server returned a value so we return it + if (useServerReturnedValue) { + return fieldValue; + } // Look for the field in the custom resolver map const resolverMap = resolvers[(rootValue as any).__typename || type]; if (resolverMap) { const resolve = resolverMap[fieldName]; if (resolve) return resolve(rootValue, args, context, info); + if (fieldValue !== undefined) return fieldValue; + } + if (fieldValue !== undefined) { + return fieldValue; } + //TODO: the proper thing to do here is throw an error saying to //add `client.onResetStore(link.writeDefaults);` //waiting on https://github.com/apollographql/apollo-client/pull/3010 //Currently with nested fields, this sort of return does not work + return defaults[fieldName]; };