Я пытаюсь реализовать пользовательскую директиву GraphQL.Насколько я понимаю, если мой SchemaDirectiveVisitor
подкласс реализует static getDirectiveDeclaration(directiveName, schema)
, то я не должен вручную объявлять директиву в моем SDL (языке определения схемы).
, потому чтоAuthDirective реализует getDirectiveDeclaration, больше не нужно, чтобы автор схемы включал объявление директивы @auth ... явно в схему.Возвращенный объект GraphQLDirective будет использоваться для принудительного применения типов аргументов и значений по умолчанию, а также для включения таких инструментов, как GraphiQL, для обнаружения директивы с помощью самоанализа схемы.Кроме того, если класс AuthDirective не сможет реализовать visitObject или visitFieldDefinition, будет выдана полезная ошибка.
Источник: https://blog.apollographql.com/reusable-graphql-schema-directives-131fb3a177d1
и
Однако, если вы реализуете повторно используемый SchemaDirectiveVisitor для публичного использования, вы, вероятно, не будете тем, кто пишет синтаксис SDL, поэтому у вас может не быть контроля над тем, какие директивы автор решает объявить и как.Вот почему хорошо реализованный, многократно используемый SchemaDirectiveVisitor должен рассмотреть возможность переопределения метода getDirectiveDeclaration
Источник: https://www.apollographql.com/docs/apollo-server/features/creating-directives.html
В моем коде, несмотря на реализацию static getDirectiveDeclaration(directiveName, schema)
, я все еще должен объявитьдиректива в SDL.
Разве она не должна работать без объявления вручную в SDL?
Полный пример кода:
const { ApolloServer, gql, SchemaDirectiveVisitor } = require('apollo-server');
const { DirectiveLocation, GraphQLDirective, defaultFieldResolver } = require("graphql");
class UpperCaseDirective extends SchemaDirectiveVisitor {
static getDirectiveDeclaration(directiveName, schema) {
console.log("inside getDirectiveDeclaration", directiveName)
return new GraphQLDirective({
name: directiveName,
locations: [
DirectiveLocation.FIELD_DEFINITION,
],
args: {}
});
}
visitFieldDefinition(field) {
console.log("inside visitFieldDefinition")
const { resolve = defaultFieldResolver } = field;
field.resolve = async function (...args) {
const result = await resolve.apply(this, args);
if (typeof result === 'string') {
return result.toUpperCase();
}
return result;
};
}
}
const books = [
{
title: 'Harry Potter and the Chamber of Secrets',
author: 'J.K. Rowling',
},
{
title: 'Jurassic Park',
author: 'Michael Crichton',
},
];
const typeDefs = gql`
#########################################
# ONLY WORKS WITH THIS LINE UNCOMMENTED #
#########################################
directive @upper on FIELD_DEFINITION
type Book {
title: String
author: String @upper
}
type Query {
books: [Book]
}
`;
const resolvers = {
Query: {
books: () => books,
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
schemaDirectives: {
upper: UpperCaseDirective
}
});
server.listen().then(({ url }) => {
console.log(`? Server ready at ${url}`);
});