写在前面的话
Nest 最新的版本为V9,较之前的V7/8有不小改动,GraphQL 部分官方文档之前的V8也是本人翻译的,有很多不完善的地方,这次打算重新精细翻译一遍,会持续更新这块内容,并最后贡献给中文文档仓库,为中文社区贡献一份力量。有兴趣的小伙伴记得要关注收藏。
指令可以被附加到字段或者代码片段,并且可以以服务器期望的任何方式影响查询的执行(在此阅读更多)。GraphQL规范中提供了几个默认指令:
@include(if: Boolean)- 如果参数为真,则仅在结果中包含此字段@skip(if: Boolean)- 如果参数为真,则跳过该字段@deprecated(reason: String)- 使用备注将字段标记为已弃用
指令是一种标识符,前面有一个@符号,后面可以选择跟一个命名参数列表,它可以出现在GraphQL查询会和schema语言中的几乎任何元素之后。
自定义指令
为了说明当Apollo/Mercurius遇到你的指令时发生了什么,你可以创建一个转换器函数。该函数使用mapSchema函数遍历shcema中的位置(字段定义、类型定义等)并执行相应的转换。
import { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils';
import { defaultFieldResolver, GraphQLSchema } from 'graphql';
export function upperDirectiveTransformer(
schema: GraphQLSchema,
directiveName: string,
) {
return mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
const upperDirective = getDirective(
schema,
fieldConfig,
directiveName,
)?.[0];
if (upperDirective) {
const { resolve = defaultFieldResolver } = fieldConfig;
// Replace the original resolver with a function that *first* calls
// the original resolver, then converts its result to upper case
fieldConfig.resolve = async function (source, args, context, info) {
const result = await resolve(source, args, context, info);
if (typeof result === 'string') {
return result.toUpperCase();
}
return result;
};
return fieldConfig;
}
},
});
}
现在,使用transformSchema函数在GraphQLModule#forRoot方法中应用upperDirectiveTransformer转换函数:
GraphQLModule.forRoot({
// ...
transformSchema: (schema) => upperDirectiveTransformer(schema, 'upper'),
});
一旦注册后,@upper指令就可以被用在我们的schema中了。但是,你应用指令的方法将根据你使用的方式(代码优先或模式优先)而有所不同。