GraphQL Resolver Middleware Utility
raw JSON →The `graphql-add-middleware` package, currently at version 0.3.7, offers a dedicated solution for injecting custom middleware logic directly into GraphQL schema resolvers. It enables developers to apply a function before and after resolver execution, allowing for operations such as logging, authentication checks, argument manipulation, or result transformation. The utility provides granular control, supporting global application to all resolvers, scoped application to all resolvers of a specific GraphQL type (e.g., `Query`, `Mutation`), or precise targeting of a single field within a type (e.g., `Query.posts`). Released in 2017 and last updated around that time, the package is effectively abandoned, which means it has no active development, bug fixes, or compatibility updates for newer GraphQL versions. Its primary differentiator is its singular focus on direct schema modification for middleware injection, rather than being integrated into a larger GraphQL server framework, requiring users to explicitly manage the `GraphQLSchema` object. This narrow scope can be beneficial for those who need a lightweight solution to augment an existing schema without adopting an entire framework.
Common errors
error Error: The "schema" argument must be a GraphQLSchema instance. ↓
GraphQLSchema instance, typically created using buildSchema or makeExecutableSchema, as the first argument to addMiddleware. error TypeError: next is not a function ↓
(root, args, context, info, next) as arguments and that next() is explicitly called (and awaited) to pass control to the next middleware or resolver. error Error: Must provide document (query) or AST. Cannot execute request. ↓
graphql-add-middleware (v0.3.7) and the graphql version your server is using. Downgrade graphql to ^0.13.2 or migrate away from graphql-add-middleware to a modern alternative. Warnings
breaking The package's peer dependency for `graphql` is `^0.13.2`. Modern `graphql` versions (e.g., v15, v16, v17) have undergone significant internal changes. It is highly probable that `graphql-add-middleware` is incompatible with current `graphql` versions, leading to runtime errors or unexpected behavior due to schema and resolver structure differences. ↓
gotcha The package is abandoned, with its last update 7 years ago. This means there will be no future bug fixes, security patches, or compatibility updates for newer Node.js versions, GraphQL specifications, or ecosystem changes. Using it in new projects or upgrading existing ones carries significant risk. ↓
gotcha Middleware functions must explicitly call `await next()` and `return result` to ensure the resolver chain continues and values are propagated. Forgetting either can lead to resolvers not being called, hangs, or `undefined` results. ↓
Install
npm install graphql-add-middleware yarn add graphql-add-middleware pnpm add graphql-add-middleware Imports
- addMiddleware wrong
const { addMiddleware } = require('graphql-add-middleware');correctimport { addMiddleware } from 'graphql-add-middleware';
Quickstart
import { buildSchema } from 'graphql';
import { addMiddleware } from 'graphql-add-middleware';
// Define a basic GraphQL schema
const schemaString = `
type User {
id: ID!
name: String!
}
type Post {
id: ID!
title: String!
author: User
}
type Query {
users: [User!]!
posts: [Post!]!
}
type Mutation {
createUser(name: String!): User!
}
`;
const schema = buildSchema(schemaString);
// Add a global middleware for logging all resolver calls
addMiddleware(schema, async (root, args, context, info, next) => {
console.log(`[Global Middleware] Entering resolver: ${info.parentType}.${info.fieldName}`);
const result = await next(); // Proceed to the next middleware or original resolver
console.log(`[Global Middleware] Exiting resolver: ${info.parentType}.${info.fieldName}`);
return result; // Ensure the result is returned
});
// Add middleware specifically to 'Query' type resolvers
addMiddleware(schema, 'Query', async (root, args, context, info, next) => {
console.log(`[Query Middleware] Processing Query.${info.fieldName} with args:`, args);
const result = await next();
return result;
});
// Add middleware to a specific field: Mutation.createUser
addMiddleware(schema, 'Mutation.createUser', async (root, args, context, info, next) => {
// Example of authentication check
if (!context || !context.userId) {
throw new Error('Unauthorized: You must be logged in to create a user.');
}
console.log(`[CreateUser Middleware] Attempting to create user: ${args.name}`);
const newUser = await next();
console.log(`[CreateUser Middleware] User created with ID: ${newUser.id}`);
return newUser;
});
console.log('GraphQL schema with middleware applied successfully.');
// The 'schema' object can now be passed to a GraphQL server (e.g., Apollo Server, express-graphql)