4

I am modularizing my schema for a GraphQL API and trying to merge the resolvers without using any 3rd party libraries.

Is there a simple way to do this without Lodash.merge() or equivalent?

The Apollo Documentation says to use a library such as Lodash to merge() modularized resolvers. (http://dev.apollodata.com/tools/graphql-tools/generate-schema.html#modularizing)

The problem seems to be that by their nature, the resolvers contain functions as properties, so they seem to be omitted when I access them via Object.assign() or even JSON.stringify().

If I console.log them, I see: {"Query":{},"Mutation":{}}

Here is what one of the resolvers looks like:

 const productResolvers = {
   Query: {
     myProducts: (root, { userId }, context) => {
       return [
         { id: 1, amount: 100, expiry: '12625383984343', created: '12625383984343' },
         { id: 2, amount: 200, expiry: '12561351347311', created: '12625383984343' },
         { id: 3, amount: 200, expiry: '11346347378333', created: '12625383984343' },
         { id: 4, amount: 350, expiry: '23456234523453', created: '12625383984343' },
       ];
     },
   },
   Mutation: {
     addProduct: (root, { userId }, context) => {
       return { id: 350, amount: 100, expiry: '12625383984343', created: '12625383984343' };
     },
   }
 };

Let's assume there is another one virtually identical called widgetResolvers.

Here is a fully functional block of code:

 export const schema = makeExecutableSchema({
   typeDefs: [queries, mutations, productSchema, widgetSchema],
   resolvers
 });

Here is what I'm trying to achieve:

 export const schema = makeExecutableSchema({
   typeDefs: [queries, mutations, productSchema, widgetSchema],
   resolvers: Object.assign({}, productResolvers, widgetResolvers)
 });

I haven't loaded in ability to use rest spread yet (https://babeljs.io/docs/plugins/transform-object-rest-spread/). I suspect it won't work for the same reason Object.assign() doesn't work.

Oh, and here is why I suspect this merge doesn't work: Why doesn't JSON.stringify display object properties that are functions?

agm1984
  • 15,500
  • 6
  • 89
  • 113

1 Answers1

9

If you're using Object.assign(), your Query and Mutation properties shouldn't end up empty, but you will run into an issue because, unlike lodash's merge(), it's not recursive. Object.assign() only compares the "direct" properties of the objects it's passed -- overriding properties of previous sources as it moves through the list.

Because Query and Mutation are properties of the objects being passed, each subsequent resolver override the previous object's Query and Mutation, with the resulting object only holding the Query and Mutation properties of the last object passed into Object.assign().

It's a lot less neat, but if you're bent on avoiding importing lodash, you could get the expected behavior this way:

const productResolver = {
  Query: { ... ✂ ... },
  Mutation: { ... ✂ ... }
}

const widgetResolver = {
  Query: { ... ✂ ... },
  Mutation: { ... ✂ ... }
}

const resolvers = {
  Query: Object.assign({}, widgetResolver.Query, productResolver.Query),
  Mutation: Object.assign({}, widgetResolver.Mutation, productResolver.Mutation)
}

Got type resolvers too? No problem:

const Widget = { ... ✂ ... }
const Product = { ... ✂ ... }

const resolvers = Object.assign(
  {
    Query: Object.assign({}, widgetResolver.Query, productResolver.Query),
    Mutation: Object.assign({}, widgetResolver.Mutation, productResolver.Mutation)
  },
  Widget,
  Product)
Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
  • Thanks, that is extremely helpful. – agm1984 Jul 29 '17 at 03:27
  • I will keep Lodash because I suspect that non-recursive nature will troll me one day if I use `Object.assign()` just to keep it native. – agm1984 Jul 29 '17 at 03:28
  • 1
    Yup, Lodash is super useful. I think if you look through their docs, you'll find uses for many of the other methods in the library too. If you want to avoid importing the whole library just to use one method, you can also [import the methods one module at a time](https://www.npmjs.com/browse/keyword/lodash-modularized) :) – Daniel Rearden Jul 29 '17 at 04:46