Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Currently building Raveshift.com, a crypto exchange and tools for crypto payment solutions.

Configuring any GraphQL server with Envelop

3 min read 1038

Configuring Any GraphQL Server With Envelop

Envelop is a lightweight GraphQL plugin library that allows you to add customized features to your GraphQL execution layer regardless of the GraphQL server you use.

GraphQL servers like Apollo GraphQL and Graphite already have platform-specific plugin systems that work well. The downside is that if you choose to move to a different implementation of GraphQL for any reason, you will need to modify the plugin to work with that specific implementation.

What is Envelop?

That’s where Envelop comes in. Envelop is not a GraphQL server — it’s a wrapper on GraphQL that allows developers to write platform-independent plugins. This means you only need to write your plugin once in order for it to work with Envelop and integrate into any GraphQL server.

To learn how to accomplish this, we’ll integrate Envelop with Fastify and Apollo GraphQL.

Here’s what you’ll need to follow along with this tutorial:

Setting up the Node app

Run the following command to install all the dependencies we’ll need:

npm install  @envelop/core fastify graphql graphql-helix --save

Next, we need to create a server. Create a server.js file and add the following code:

const { envelop, useSchema, useLogger } = require('@envelop/core');
const fastify = require('fastify');
const { processRequest, getGraphQLParameters } = require('graphql-helix');

In the code above, we’re importing envelop and its plugins. If you have used React Hooks, the naming convention for the plugins will be familiar to you. Envelop plugins are named with a prefix and the use keyword. In this example, we’ll add both the useSchema and the useLogger plugin.

For starters, we’ll use GraphQL Helix to build our GraphQL server to catch and process requests to the Fastify server.

Creating a GraphQL schema

Next, we’ll create a schema.js file, where we’ll define our schema types, mutations, and resolvers so that we can create a library of songs. This file should have the following content:

We made a custom demo for .
No really. Click here to check it out.

const {
 GraphQLObjectType,
 GraphQLSchema,
 GraphQLString,
} = require("graphql");
const schema = new GraphQLSchema({
 mutation: new GraphQLObjectType({
   name: "Mutation",
   fields: () => ({
     echo: {
       args: {
         text: {
           type: GraphQLString,
         },
       },
       type: GraphQLString,
       resolve: (_root, args) => {
         return args.text;
       },
     },
   }),
 }),
 query: new GraphQLObjectType({
   name: "Query",
   fields: () => ({
     song: {
       type: new GraphQLObjectType({
         name: "Song",
         fields: () => ({
           firstVerse: {
             type: GraphQLString,
             resolve: () => "Singing me a song is lovely.",
           },
           secondVerse: {
             type: GraphQLString,
             resolve: () =>
               new Promise((resolve) =>
                 setTimeout(
                   () => resolve("You never wanted to sing with me?"),
                   5000
                 )
               ),
           },
         }),
       }),
       resolve: () => ({}),
     },
   }),
 }),
});

module.exports = schema

Creating a Fastify server

We’ll import the schema we just created and use it just after our Helix library import in server.js, as shown below:

const { envelop, useSchema, useLogger } = require('@envelop/core');
const fastify = require('fastify');
const { processRequest, getGraphQLParameters } = require('graphql-helix');
const mySchema = require("./mySchema"); //here

Integrating Envelop with our schema

No matter what GraphQL server and integration process you are using, the next step is fairly simple. In our example, we are using two plugins, useSchema() and useLogger(). You can use as many plugins as you want — you’ll just need to add the plugin to the plugins array, like so:

const getEnveloped = envelop({
 plugins: [useSchema(mySchema), useLogger()],
});

This is a key part of the integration because it gives you a high level of abstraction and allows you to de-couple the required components for use.

Next, we’ll need to create a Fastify app and integrate Envelop.

const fastifyApp = fastify();
const port = 3000;

fastifyApp.route({
 method: ['POST'],
 url: '/graphql',
 async handler(req, res) {
   const { parse, validate, contextFactory, execute, schema } = getEnveloped({
     req,
   });
   const request = {
     body: req.body,
     headers: req.headers,
     method: req.method,
     query: req.query,
   };
   const { operationName, query, variables } = getGraphQLParameters(request);
   const result = await processRequest({
     operationName,
     query,
     variables,
     request,
     schema,
     parse,
     validate,
     execute,
     contextFactory,
   });
   if (result.type === 'RESPONSE') {
     res.status(result.status);
     res.send(result.payload);
   } else {
     res.send({ errors: [{ message: 'Not Supported' }] });
   }
 },
});
fastifyApp.listen(port, () => {
 console.log(`GraphQL server is running on port:`, port);
});

Let’s break down this code. We first set up the server and configured the GraphQL endpoint. Then we imported parse, contextFactory, execute, and schema from the Envelop instance, as shown below:

const { parse, validate, contextFactory, execute, schema } = getEnveloped({req});

These are some of the parameters from Envelop that we’ll pass to Helix to process our GraphQL requests.

 const result = await processRequest({
     operationName,
     query,
     variables,
     request,
     schema,
     parse,
     validate,
     execute,
     contextFactory,
   });

Now we can run the API with the node server.js command to start the Node server.

Testing the application with Postman

We should test out our app using Postman.

Postman GraphQL Request Page Testing Our App
Screenshot from Postman GraphQL request.

That’s it! We’ve successfully integrated Envelop and added a custom plugin to a Node application.

Integrating Envelop and Apollo GraphQL

Like I mentioned earlier, you can integrate Envelop with any GraphQL server. Let’s see an implementation with Apollo GraphQL.

In a separate directory, install GraphQL, Apollo, and GraphQL Tools by running the command below:

npm install @apollo/client graphql @graphql-tools/schema 

Create a separate JavaScript file called app.js and add the following code to it.

import { ApolloServer } from 'apollo-server';
import { envelop, useSchema, useLogger } from '@envelop/core';
import { makeExecutableSchema } from '@graphql-tools/schema';

const schema = makeExecutableSchema({
  typeDefs: /* GraphQL */ `
    type Query {
      hello: String!
    }
  `,
  resolvers: {
    Query: {
      hello: () => 'World',
    },
  },
});

const getEnveloped = envelop({
  plugins: [useSchema(schema), useLogger()],
});

const server = new ApolloServer({
  executor: async requestContext => {
    const { schema, execute, contextFactory } = getEnveloped({ req: requestContext.request.http });

    return execute({
      schema: schema,
      document: requestContext.document,
      contextValue: await contextFactory(),
      variableValues: requestContext.request.variables,
      operationName: requestContext.operationName,
    });
  },
});

server.listen(3000);

In the above snippet, we created an executable schema with GraphQL Tools, created an instance with Envelop, and added the useSchema() and the useLogger() plugins.

const getEnveloped = envelop({
  plugins: [useSchema(schema), useLogger()],
});

Note that useSchema and useLogger both come prepackaged with Envelop.

Finally, in the Apollo server object, override the executor object with parameters from the Envelop object. That’s all you need to integrate Envelop with your Apollo GraphQL server.

Conclusion

If you build applications with GraphQL, you’ll find Envelop to be a great addition to your project. This is especially true if you like to keep your code DRY, as Envelop allows you to write modular GraphQL plugins that work on all GraphQL server implementations. Thanks for reading!

Monitor failed and slow GraphQL requests in production

While GraphQL has some features for debugging requests and responses, making sure GraphQL reliably serves resources to your production app is where things get tougher. If you’re interested in ensuring network requests to the backend or third party services are successful, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Currently building Raveshift.com, a crypto exchange and tools for crypto payment solutions.

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

One Reply to “Configuring any GraphQL server with Envelop”

  1. npm install @apollo/client graphql @graphql-tools/schema
    Little typo, you must install apollo-server

Leave a Reply