How can use SchemaDirectiveVisitor

I am implementing authorization with custom directives, however when I try to extend the class “SchemaDirectiveVisitor” from “Apollo-serve-express” I get an error saying the class I am trying to extend is null?
Can someone help me out? How do I implement custom directives with apollo-server-express?
I have tried importing the class from apollo-tools as well but had no success!

Thank you in advance!

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.

1 Like

Wow! Thank you so much, that helps a lot! May Jesus Bless you!

Great! Thanks, im happy to help you. Have a good day!