Hey Everyone,
I am trying to build a library of custom directives to use in different subgraphs created using apollo federation. so for the PoC, I was creating a simple directive and trying to use the same in one of the implementing services. I was getting the below error when trying to start the service:
GraphQLError [Object]: Unknown directive "@auth".
at Object.Directive (/poc/service-a/node_modules/graphql/validation/rules/KnownDirectivesRule.js:56:29)
at Object.enter (/poc/service-a/node_modules/graphql/language/visitor.js:323:29)
at visit (/poc/service-a/node_modules/graphql/language/visitor.js:243:26)
at Object.validateSDL (/poc/service-a/node_modules/graphql/validation/validate.js:92:22)
at Object.buildSchemaFromSDL (/poc/service-a/node_modules/apollo-graphql/lib/schema/buildSchemaFromSDL.js:48:31)
at buildFederatedSchema (/poc/service-a/node_modules/@apollo/federation/dist/service/buildFederatedSchema.js:44:35)
at Object.<anonymous> (/poc/service-a/index.js:90:14)
at Module._compile (internal/modules/cjs/loader.js:1201:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1221:10)
at Module.load (internal/modules/cjs/loader.js:1050:32) {
locations: []
}
while my service code looks like this:
const {
ApolloServer,
gql,
SchemaDirectiveVisitor: sSchemaDirectiveVisitor,
} = require("apollo-server");
const { buildFederatedSchema } = require("@apollo/federation");
const { SchemaDirectiveVisitor } = require("graphql-tools");
// const MyAuthDirective = require("lib-directives");
class MyAuthDirective extends SchemaDirectiveVisitor {
static getDirectiveDeclaration() {
return new GraphQLDirective({
name: "auth",
locations: [DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT],
});
}
visitObject(obj) {
const token = this.context.userToken;
if (!token) throw new Error("Unauthorized Error, no token");
if (token && token.includes("DevUserToken")) {
return obj;
} else {
throw new Error("Unauthorized Access, invalid token");
}
}
visitFieldDefinition(field) {
const token = this.context.userToken;
if (!token) throw new Error("Unauthorized Error, no token");
if (token && token.includes("DevUserToken")) {
return field;
} else {
throw new Error("Unauthorized Access, invalid token");
}
}
}
const books = [
{
title: "The Awakening",
author: "Kate Chopin",
},
{
title: "City of Glass",
author: "Paul Auster",
},
];
const resolvers = {
Query: {
books: () => books,
authors: () => books.map((i) => i.author),
},
// Mutation: {
// addBook: (title, author) => {
// books.push({ title, author });
// return { title, author };
// },
// },
};
const typeDefs = gql`
type Book @key(fields: "title") {
title: String
author: String
}
type Author @key(fields: "name") {
name: String
books: [Book]
}
extend type Query {
books: [Book] @auth
authors: [String]
}
# extend type Mutation {
# addBook(title: String, author: String): Book @auth
# }
# type GetBooksAndAuthors {
# books: [Book]
# authors: [String]
# }
`;
const directives = {
auth: MyAuthDirective,
};
console.log(directives);
let schema = buildFederatedSchema([{ typeDefs, resolvers }]);
sSchemaDirectiveVisitor.visitSchemaDirectives(schema, directives);
const server = new ApolloServer({
schema,
// schemaDirectives: directives,
context: ({ req, res }) => {
const header = req.headers["user-data"];
console.log("FEDRATED SERVICE: ", header);
console.log(JSON.parse(Buffer.from(header, "base64").toString()));
return { userToken: req.headers.authorization };
},
});
server
.listen({ port: 4001 })
.then(({ url }) => console.log(`Service a started at ${url}`));
Please help me identify the issue here as I follow whatever is mentioned in the apollo federation documents.