Add reactivity to an existing source using GraphQL Mesh

Jean-Yves Couët

Introduction

Working on the code generator for svelte plugin (opens in a new tab), I was looking for a public graphQL endpoint having queries, mutations and subscriptions for nice examples. Unfortunately I didn't find anything out of the box, ready to use for my demos. So I decided to extend an existing source!

Starting Point

Across my researches I found one cool public endpoint regarding SpaceX (opens in a new tab). It has Queries and Mutations ready to use! So I decided to pimp this endpoint, and bring a bit of reactivity with subscriptions.

The idea is to publish the new user when it's inserted with this mutation:

mutation addUser {
  insert_users(objects: { name: "jyc" }) {
    affected_rows
    returning {
      name
    }
  }
}
🏎
How hard is to do this? Let's find out... Let's Pimp this GraphQL!

Implementation

Multiple ways are possible!

Spoiler alert

Thanks to graphql-mesh, it's dead easy! 🚀🚀🚀

1. Create a New Repo

mkdir newRepo
cd newRepo
yarn init

2. Add graphql-mesh Packages

yarn add @graphql-mesh/cli @graphql-mesh/graphql @graphql-mesh/transform-resolvers-composition graphql

3. Add .meshrc.yaml File in the Root Folder With

.meshrc.yaml
sources:
  - name: spacexGQL
    handler:
      graphql:
        endpoint: https://api.spacex.land/graphql/
 
additionalTypeDefs: |
  extend type Subscription {
    usersAdded: [users]
  }
 
transforms:
  - resolversComposition:
      - resolver: 'Mutation.insert_users'
        composer: ./src/composition/insert_user
 
additionalResolvers:
  - type: Subscription
    field: usersAdded
    pubsubTopic: usersAdded

Where I

  • declare the graphQL source
  • extend Subscription to listen to user added users
  • compose the existing Mutation.insert_users

4. Add ./src/composition/insert_user.js File with All the Logic for This New Mutation Composition

insert_user.js
module.exports = next => async (root, args, context, info) => {
  // add returning.id to the selection
  info.operation.selectionSet.selections[0].selectionSet.selections.push({
    kind: 'Field',
    name: {
      kind: 'Name',
      value: 'returning'
    },
    arguments: [],
    directives: [],
    selectionSet: {
      kind: 'SelectionSet',
      selections: [
        {
          kind: 'Field',
          name: {
            kind: 'Name',
            value: 'id'
          },
          arguments: [],
          directives: []
        }
      ]
    }
  })
 
  // send the mutation to the graphQL source
  const result = await next(root, args, context, info)
 
  // select returned ids
  const ids = result.returning.map(c => c.id)
 
  // Query users enforcing fields to return
  const responseUser = await context.spacexGQL.apiQuery.users(
    {
      where: { id: { _in: ids } }
    },
    {
      fields: {
        id: true,
        name: true,
        rocket: true,
        timestamp: true,
        twitter: true
      }
    }
  )
 
  // publish new users
  context.pubsub.publish('usersAdded', responseUser)
 
  return result
}

That's it!

Wrap Up

I'm now ready to work on the demo for Svelte Codegen (opens in a new tab)! Stay tunned ;)

@jycouet (opens in a new tab)

💡

Special thanks to n1ru4l (opens in a new tab) who helped me find the nicest way to do it ;)

Join our newsletter

Want to hear from us when there's something new? Sign up and stay up to date!

By subscribing, you agree with Beehiiv’s Terms of Service and Privacy Policy.

Recent issues of our newsletter

Similar articles