Nest 最新的版本为V9,较之前的V7/8有不小改动,GraphQL 部分官方文档之前的V8也是本人翻译的,有很多不完善的地方,这次打算重新精细翻译一遍,会持续更新这块内容,并最后贡献给中文文档仓库,为中文社区贡献一份力量。有兴趣的小伙伴记得要关注收藏。本篇为系列文档的最后一篇。
迁移至v10
为了帮助你从@nestjs/graphql 版本9迁移至版本10,本文提供了一套指导规范。这个大版本发布的重点是要提供一个更轻便、与平台无关的核心库。
介绍“驱动程序”包
在最新的版本中,我们决定把@nestjs/graphql包拆分到一些独立的库中,让你在项目中,无论选择使用Apollo(@nestjs/apollo),还是Mercurius(@nestjs/mercurius),亦或其他的GraphQL库都可以。
这意味着现在你必须明确指定你的应用程序将要使用的的驱动程序。
// Before
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
@Module({
imports: [
GraphQLModule.forRoot({
autoSchemaFile: 'schema.gql',
}),
],
})
export class AppModule {}
// After
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: 'schema.gql',
}),
],
})
export class AppModule {}
插件
Apollo服务插件允许你在响应某些事件中执行自定义的操作。由于这是Apollo独有的功能,所以我们将其从@nestjs/graphql移至新创建的@nestjs/apollo包中,因为你必须更新应用程序中的导入。
// Before
import { Plugin } from '@nestjs/graphql';
// After
import { Plugin } from '@nestjs/apollo';
指令
在@graphql-tools/schema包的v8版本中,schemaDirectives 功能已经被新的Schema指令 API取代。
// Before
import { SchemaDirectiveVisitor } from '@graphql-tools/utils';
import { defaultFieldResolver, GraphQLField } from 'graphql';
export class UpperCaseDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field: GraphQLField<any, any>) {
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;
};
}
}
// After
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;
}
},
});
}
要将此指令实现用于包含@upper指令的schema,请使用transformSchema函数:
GraphQLModule.forRoot<ApolloDriverConfig>({
...
transformSchema: schema => upperDirectiveTransformer(schema, 'upper'),
})
Federation
GraphQLFederationModule已经被相应的驱动程序类替代:
// Before
GraphQLFederationModule.forRoot({
autoSchemaFile: true,
});
// After
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
driver: ApolloFederationDriver,
autoSchemaFile: true,
});
提示
ApolloFeferationDriver类和ApolloFederationDriverConfig都是从@nestjs/apollo包中导出的。
同样的,无需使用专用的GraphQLGatewayModule,只需将适合的驱动程序类传递给你的GraphQLModule设置即可:
// Before
GraphQLGatewayModule.forRoot({
gateway: {
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'users', url: 'http://localhost:3000/graphql' },
{ name: 'posts', url: 'http://localhost:3001/graphql' },
],
}),
},
});
// After
GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
driver: ApolloGatewayDriver,
gateway: {
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'users', url: 'http://localhost:3000/graphql' },
{ name: 'posts', url: 'http://localhost:3001/graphql' },
],
}),
},
});
提示
ApolloGatewayDriver类和ApolloGatewayDriverConfig都是从@nestjs/apollo包中导出的。