I want to add a validation layer to the apollo server. It should run after every graphql query / mutation but before the resolver function. The validation layer will need to know the graphql query / mutation being called and the passed parameters. It will throw an error if its invalid and prevent the resolver function from running.
I'm unclear where to inject it without manually placing it in each resolver function.
graphql-tools
actually includes a addSchemaLevelResolveFunction
utility that allows you to wrap the resolver for every Query
, Mutation
and Subscription
field to simulate a "root level resolver":
const { makeExecutableSchema, addSchemaLevelResolveFunction } = require('graphql-tools')
const schema = makeExecutableSchema({ resolvers, typeDefs })
const rootLevelResolver = (root, args, context, info) => {
// Your validation logic here. Throwing an error will prevent the wrapped resolver from executing.
// Note: whatever you return here will be passed as the parent value to the wrapped resolver
}
addSchemaLevelResolveFunction(schema, rootLevelResolver)
This is a simple way of applying some logic to all root-level fields, but gets a bit hairy if there's only some fields you want to apply this logic to. If that's the case, now you have to maintain a list of whitelisted or blacklisted fields, separate from your schema. This can be troublesome if someone else on your team is adding a new field and isn't aware of this mechanism. It's also not all-too-helpful if you want to apply the same logic to fields outside of root level ones.
A better approach is to utilize a custom schema directive, as outlined in the docs. This allows you to indicate which fields to apply the logic to:
directive @customValidation on FIELD_DEFINITION
type Query {
someField: String @customValidation
someOtherField: String
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With