GraphQL Resolver Middleware Utility

raw JSON →
0.3.7 verified Thu Apr 23 auth: no javascript abandoned

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.

error Error: The "schema" argument must be a GraphQLSchema instance.
cause `addMiddleware` was called with an invalid or uninitialized GraphQL schema object.
fix
Ensure you are passing a valid GraphQLSchema instance, typically created using buildSchema or makeExecutableSchema, as the first argument to addMiddleware.
error TypeError: next is not a function
cause The `next` function in the middleware signature was either not called, or the middleware function itself was invoked incorrectly outside the `graphql-add-middleware` context.
fix
Verify that your middleware function correctly accepts (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.
cause This error typically originates from a GraphQL server trying to execute a query, indicating that the schema passed to the server is corrupted or incorrectly modified by an incompatible version of `graphql-add-middleware` or `graphql` itself.
fix
This often points to a fundamental incompatibility between 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.
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.
fix Consider migrating to a more actively maintained GraphQL middleware solution or a GraphQL server framework with built-in middleware capabilities (e.g., Apollo Server, GraphQL Yoga). If absolutely necessary, pin your `graphql` dependency to a compatible older version and thoroughly test.
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.
fix Evaluate alternatives like `graphql-middleware`, `graphql-shield`, or leveraging the middleware features of comprehensive GraphQL server frameworks. If continuing to use, thoroughly test across your stack and be prepared to fork or patch the library yourself.
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.
fix Always use `const result = await next();` and `return result;` within your middleware to correctly pass control and return values. Middleware functions are asynchronous by design.
npm install graphql-add-middleware
yarn add graphql-add-middleware
pnpm add graphql-add-middleware

This example demonstrates how to create a basic GraphQL schema and then apply middleware globally, to a specific type (Query), and to a specific field (Mutation.createUser) using `graphql-add-middleware`. It includes logging and a hypothetical authorization check within the middleware functions, showcasing their execution flow.

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)