This repository was archived by the owner on Jul 10, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 99
This repository was archived by the owner on Jul 10, 2019. It is now read-only.
Resolvers should look for a custom resolver first, but this would break the mixed @client / server query #226
Copy link
Copy link
Open
Labels
ac-local-state-readyblockingPrevents production or dev due to perf, bug, build error, etc..Prevents production or dev due to perf, bug, build error, etc..enhancement
Description
When resolving a field, the resolve
function should first look for a custom resolver, thus simulating the same behavior as on a server :
const query = gql`
query {
messages {
content
user {
username
}
}
}
`;
const resolvers = {
Message: {
user: ({ user }) => ({
...db.getUserById(user),
__typename: 'User',
}),
},
Query: {
messages: () => [{ id: "m1", content: "message 1", user: "u1", __typename: "Message" }]
}
}
With apollo-link-state
, due to this statement stating that if there is a field in the root value, it's because the server already sent something. It's not true, this statement should be valid only if we are at the Query
level.
Here is a failing test :
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);
});
// TypeError: Cannot read property 'baz' of undefined
Quick edit (to be refactored) to make all the tests pass (this one included) :
in index.js
const resolver = (fieldName, rootValue = {}, args, context, info) => {
//resultKey is where data under the field name is ultimately returned by the server
//https://github.com/apollographql/apollo-client/tree/master/packages/graphql-anywhere#resolver-info
const fieldValue = rootValue[info.resultKey];
//If fieldValue is defined and we are at the Query level, server returned a value
if (fieldValue !== undefined && (((rootValue as any).__typename || type) == 'Query')) {
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];
};
jiku, JeremyJonas, alexanderchan and richardscarrott
Metadata
Metadata
Assignees
Labels
ac-local-state-readyblockingPrevents production or dev due to perf, bug, build error, etc..Prevents production or dev due to perf, bug, build error, etc..enhancement