Hi, im already create custom directive with apollo server express version 3, here my sample code
AuthDirective.js
const { mapSchema, getDirective, MapperKind } = require('@graphql-tools/utils');
const { defaultFieldResolver } = require('graphql');
const { ApolloError } = require('apollo-server-express');
const { logging } = require('../../helpers');
function AuthorizationDirective(schema, directiveName) {
return mapSchema(schema, {
[MapperKind.FIELD]: (fieldConfig, _fieldName, typeName) => {
const authDirective = getDirective(schema, fieldConfig, directiveName);
if (authDirective && authDirective.length) {
const requiredRoles = authDirective[0].requires;
if (requiredRoles && requiredRoles.length) {
const { resolve = defaultFieldResolver } = fieldConfig;
fieldConfig.resolve = function (source, args, context, info) {
if (requiredRoles.includes('PUBLIC')) {
console.log(`==> ${context.code || 'ANONYMOUS'} ACCESSING PUBLIC RESOLVER: ${info.fieldName}`);
logging(context, info.fieldName, args);
return resolve(source, args, context, info);
}
if (!requiredRoles.includes(context.code)) {
throw new ApolloError('NOT AUTHORIZED', 'NO_AUTH');
}
console.log(`==> ${context.code} ACCESSING PRIVATE RESOLVER: ${info.fieldName}`);
logging(context, info.fieldName, args);
return resolve(source, args, context, info);
};
return fieldConfig;
}
}
},
});
}
module.exports = AuthorizationDirective;
schema.js
# CREATE CUSTOM DIRECTIVE
directive @auth(requires: [RoleName]) on FIELD_DEFINITION
enum RoleName {
SUPERADMIN
ADMIN
}
users(role: String): [User]
@auth(requires: [SUPERADMIN, ADMIN])
app.js
// IMPORT DIRECTIVE FILE
const AuthDirective = require('./graphql/directives/AuthDirective');
// NEED WRAP YOUR SCHEMA AND RESOLVER WITH makeExecutableSchema IF USING DIRECTIVE
const { makeExecutableSchema } = require('@graphql-tools/schema');
...
...
const startApolloServer = async (typeDefs, resolvers) => {
const app = express();
const httpServer = http.createServer(app);
let schema = makeExecutableSchema({
typeDefs,
resolvers,
});
schema = AuthDirective(schema, 'auth');
...
...
}
More or less like code above, already tested in my development and production.
Here my reference Schema directives
hope it can help you.