All in one solution to manage middleware in your GraphQL projects.
GraphQL Middleware is a schema wrapper which allows you to easily manage additional functionality accross multiple resolvers.
- Easiest way to handle GraphQL middleware: Intuitive, yet familiar API will get under your skin in a second.
- Powerful: Allows complete control over your resolvers (Before, After).
- Compatible: Works with any GraphQL Schema.
yarn add graphql-middleware
import { applyFieldMiddleware } from 'graphql-middleware'
import { makeExecutableSchema } from 'graphql-tools'
import { authMiddleware, metricsMiddleware } from './middlewares'
// Minimal example middleware (before & after)
const beepMiddleware = {
Query: {
hello: async (resolve, parent, args, context, info) => {
// You can you middlewares to override arguments
const argsWithDefault = { name: 'Bob', ...args }
const result = await resolve(parent, argsWithDefault, context, info)
// Or change the returned values of resolvers
return result.replace(/Trump/g, 'beep')
},
},
}
const typeDefs = `
type Query {
hello(name: String): String
}
`
const resolvers = {
Query: {
hello: (parent, { name }, context) => `Hello ${name ? name : 'world'}!`,
},
}
const schema = makeExecutableSchema({ typeDefs, resolvers })
const schemaWithFieldMiddlewares = applyFieldMiddleware(
schema,
metricsMiddleware,
authMiddleware,
beepMiddleware,
)
graphql-yoga
has built-in support forgraphql-middleware
!
import { GraphQLServer } from 'graphql-yoga'
import { authMiddleware, metricsMiddleware } from './middlewares'
const typeDefs = `
type Query {
hello(name: String): String
}
`
const resolvers = {
Query: {
hello: (parent, { name }, context) => `Hello ${name ? name : 'world'}!`,
},
}
const server = new GraphQLServer({
typeDefs,
resolvers,
fieldMiddlewares: [authMiddleware, metricsMiddleware],
documentMiddlewares: [],
})
server.start(() => console.log('Server is running on localhost:4000'))
A middleware is a resolver function that wraps another resolver function.
type IFieldMiddlewareFunction = (
resolve: Function,
parent: any,
args: any,
context: any,
info: GraphQLResolveInfo,
) => Promise<any>
interface IFieldMiddlewareTypeMap {
[key: string]: IFieldMiddlewareFunction | IFieldMiddlewareFieldMap
}
interface IFieldMiddlewareFieldMap {
[key: string]: IFieldMiddlewareFunction
}
type IFieldMiddleware = IFieldMiddlewareFunction | IFieldMiddlewareTypeMap
function applyFieldMiddleware(
schema: GraphQLSchema,
...middlewares: IFieldMiddleware[]
): GraphQLSchema
- Logging
- Metrics
- Input sanitzation
- Performance measurement
- Authorization
- Caching
- Tracing
Yes. Nevertheless we encourage you to use it in combination with Yoga, because of the many features Yoga offers combined with GraphQL-Middleware.
GraphQL-Middleware and directives
tackle the same problem in completely different way. GraphQL-Middleware allows you to implement all your middleware logic in your code, whereas directives encourage you to mix schema with your functionality.
GraphQL-Middleware allows you to modify the context of your resolvers, but we encourage you to use GraphQL-Yoga's document-middleware for this functionality instead.
Join our Slack community if you run into issues or have questions. We love talking to you!