我正在尝试实现自定义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}`);
});
答案 0 :(得分:1)
我遇到了同样的问题,并且能够从graphql-tools issue #957找到此评论。
来自changelog:
注意:graphql 14包含重大更改。我们推出了graphql-tools的主要版本来适应那些重大更改。如果您打算将graphql 14与graphql-tools 4.0.0一起使用,请确保已查看了graphql重大更改列表。
这很可能是由于
graphql-js
现在要求您在尝试使用指令之前在其架构中定义指令的缘故。例如:directive @upper on FIELD_DEFINITION type TestObject { hello: String @upper }
您可以通过在架构中预定义指令来解决此问题,但我想确认一下。如果可行,我们将需要更新文档。