生成Schema时自定义Directive无法在输入字段上显示
问题
运行时添加自定义Directive,Directive本身已在输出Schema中正确生成,但应用到特定输入字段时未显示。
创建Directive的代码
const limitDirective = new graphql.GraphQLDirective({ name: 'myDirective', locations: [ graphql.DirectiveLocation.INPUT_FIELD_DEFINITION, graphql.DirectiveLocation.FIELD_DEFINITION, graphql.DirectiveLocation.ARGUMENT_DEFINITION ], args: { constraint: { type: graphql.GraphQLString, description: 'An example argument for myDirective', }, errorCode: { type: graphql.GraphQLString, description: 'Another example argument for myDirective', }, }, isRepeatable: true, });
集成到InputField的代码
let customInput: graphql.GraphQLInputObjectType = new graphql.GraphQLInputObjectType({ name: "customInput", fields: () => ({ myField: { type: graphql.GraphQLInt, extensions: { myDirective:{constraint:"max=50", errorCode:"LIMIT_EXCEEDED"} } } }) })
问题现象
使用print-schema-with-directives函数打印Schema时,输入字段上的Directive未显示(Directive本身已生成):
预期输出
directive @myDirective( constraint: String errorCode: String ) repeatable on INPUT_FIELD_DEFINITION | FIELD_DEFINITION input customInput { myField: String @myDirective(constraint: "max=50", errorCode: "LIMIT_EXCEEDED") }
实际输出
directive @myDirective( constraint: String errorCode: String ) repeatable on INPUT_FIELD_DEFINITION | FIELD_DEFINITION input customInput { myField: String }
解决方法
print-schema-with-directives依赖Schema的AST节点信息来渲染字段上的Directive,通过extensions添加的Directive不会被该工具识别。你需要通过AST节点或Schema转换工具来正确添加Directive:
方法1:手动构建AST节点
直接为输入字段添加包含Directive的AST节点:
const { parse } = require('graphql'); // 解析生成Directive的AST节点 const directiveAst = parse(`@myDirective(constraint: "max=50", errorCode: "LIMIT_EXCEEDED")`) .definitions[0].directives[0]; let customInput: graphql.GraphQLInputObjectType = new graphql.GraphQLInputObjectType({ name: "customInput", fields: () => ({ myField: { type: graphql.GraphQLInt, astNode: { kind: 'InputValueDefinition', name: { kind: 'Name', value: 'myField' }, type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } }, directives: [directiveAst] } } }) })
方法2:使用graphql-tools的Schema转换工具
利用mapSchema修改Schema,为指定字段添加Directive:
const { mapSchema, MapperKind } = require('@graphql-tools/utils'); const { parse } = require('graphql'); // 先创建基础Schema let schema = new graphql.GraphQLSchema({ directives: [limitDirective], types: [customInput] }); // 转换Schema,为目标字段添加Directive schema = mapSchema(schema, { [MapperKind.INPUT_FIELD]: (fieldConfig, fieldName, typeName) => { if (typeName === 'customInput' && fieldName === 'myField') { // 初始化AST节点(如果不存在) fieldConfig.astNode = fieldConfig.astNode || { kind: 'InputValueDefinition', name: { kind: 'Name', value: fieldName }, type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } }, directives: [] }; // 添加Directive的AST节点 fieldConfig.astNode.directives.push( parse(`@myDirective(constraint: "max=50", errorCode: "LIMIT_EXCEEDED")`) .definitions[0].directives[0] ); } return fieldConfig; } });
完成上述修改后,再用print-schema-with-directives打印Schema,输入字段上的Directive就会正常显示。
内容的提问来源于stack exchange,提问作者Hrishikesh Thakkar
相关产品推荐
相关产品推荐

