无需在模式中显式声明的 GraphQL 自定义指令
GraphQL custom directive without declaring explicitly in schema
我正在尝试实现自定义 GraphQL 指令。我的理解是,如果我的 SchemaDirectiveVisitor
子类实现了 static getDirectiveDeclaration(directiveName, schema)
,那么我 不必 必须在我的 SDL(模式定义语言)中手动声明该指令。
Because AuthDirective implements getDirectiveDeclaration, it’s no longer necessary for the schema author to include the directive @auth ... declaration explicitly in the schema. The returned GraphQLDirective object will be used to enforce the argument types and default values, as well as enabling tools like GraphiQL to discover the directive using schema introspection. Additionally, if the AuthDirective class fails to implement visitObject or visitFieldDefinition, a helpful error will be thrown.
Source: https://blog.apollographql.com/reusable-graphql-schema-directives-131fb3a177d1
和
However, if you’re implementing a reusable SchemaDirectiveVisitor for public consumption, you will probably not be the person writing the SDL syntax, so you may not have control over which directives the schema author decides to declare, and how. That’s why a well-implemented, reusable SchemaDirectiveVisitor should consider overriding the getDirectiveDeclaration method
Source: 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}`);
});
我遇到了同样的问题,并且能够从 graphql-tools issue #957 找到这条评论。
From the changelog:
NOTE: graphql 14 includes breaking changes. We're bumping the major version of graphql-tools to accommodate those breaking changes. If you're planning on using graphql 14 with graphql-tools 4.0.0, please make sure you've reviewed the graphql breaking changes list.
这可能是由于 graphql-js
现在要求您在尝试使用指令之前先在架构中定义它们。例如:
directive @upper on FIELD_DEFINITION
type TestObject {
hello: String @upper
}
您可能可以通过在架构中预定义指令来解决此问题,但我想确认这一点。如果可行,我们需要更新文档。
我正在尝试实现自定义 GraphQL 指令。我的理解是,如果我的 SchemaDirectiveVisitor
子类实现了 static getDirectiveDeclaration(directiveName, schema)
,那么我 不必 必须在我的 SDL(模式定义语言)中手动声明该指令。
Because AuthDirective implements getDirectiveDeclaration, it’s no longer necessary for the schema author to include the directive @auth ... declaration explicitly in the schema. The returned GraphQLDirective object will be used to enforce the argument types and default values, as well as enabling tools like GraphiQL to discover the directive using schema introspection. Additionally, if the AuthDirective class fails to implement visitObject or visitFieldDefinition, a helpful error will be thrown.
Source: https://blog.apollographql.com/reusable-graphql-schema-directives-131fb3a177d1
和
However, if you’re implementing a reusable SchemaDirectiveVisitor for public consumption, you will probably not be the person writing the SDL syntax, so you may not have control over which directives the schema author decides to declare, and how. That’s why a well-implemented, reusable SchemaDirectiveVisitor should consider overriding the getDirectiveDeclaration method
Source: 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}`);
});
我遇到了同样的问题,并且能够从 graphql-tools issue #957 找到这条评论。
From the changelog:
NOTE: graphql 14 includes breaking changes. We're bumping the major version of graphql-tools to accommodate those breaking changes. If you're planning on using graphql 14 with graphql-tools 4.0.0, please make sure you've reviewed the graphql breaking changes list.
这可能是由于
graphql-js
现在要求您在尝试使用指令之前先在架构中定义它们。例如:directive @upper on FIELD_DEFINITION type TestObject { hello: String @upper }
您可能可以通过在架构中预定义指令来解决此问题,但我想确认这一点。如果可行,我们需要更新文档。