Skip to main content

CLI 插件

warning

本章仅适用于代码优先方法。

TypeScript 的元数据反射系统有一些限制,例如不可能确定类包含哪些属性或识别给定属性是可选的还是必需的。 但是,某些约束可以在编译时解决。 Nest 提供了一个插件,通过增强 TypeScript 编译过程来减少所需的样板代码量。

note

此插件是可选的。如果您愿意,可以手动声明所有装饰器,或者只在需要时声明特定的装饰器。

概述

GraphQL 插件将自动:

  • 对所有输入对象、对象类型和参数类属性进行注释,除非使用 @HideField
  • 根据问号设置可为空属性(例如,name?: string 将设置 nullable: true
  • 根据类型设置类型属性(还支持数组)
  • 根据注释生成属性的描述(如果 introspectComments 设置为 true

请注意,为了能够通过插件分析,您的文件名必须具有以下后缀之一: ['.input.ts', '.args.ts', '.entity.ts', '.model.ts'](例如,author.entity.ts)。 如果您使用不同的后缀,可以通过指定 typeFileNameSuffix 选项调整插件的行为(见下文)。

根据我们到目前为止学到的知识,您必须复制很多代码以让包知道如何在 GraphQL 中声明您的类型。 例如,您可以定义一个简单的 Author 类如下:

authors/models/author.model.ts

@ObjectType()
export class Author {
@Field(type => ID)
id: number;

@Field({ nullable: true })
firstName?: string;

@Field({ nullable: true })
lastName?: string;

@Field(type => [Post])
posts: Post[];
}

在中等规模的项目中,这可能不是一个重大问题,但是一旦有了大量的类,就会变得冗长且难以维护。

通过启用 GraphQL 插件,上面的类定义可以简化为:

authors/models/author.model.ts

@ObjectType()
export class Author {
@Field(type => ID)
id: number;
firstName?: string;
lastName?: string;
posts: Post[];
}

该插件根据抽象语法树动态添加适当的装饰器。因此,您不必在整个代码中挣扎着使用 @Field 装饰器。

note

插件将自动生成任何缺失的 GraphQL 属性,但是如果需要覆盖它们, 只需通过 @Field() 明确设置即可。

注释内省

启用注释内省功能后,CLI 插件将根据注释为字段生成描述。

例如,给定一个示例 roles 属性:

/**
* A list of user's roles
*/
@Field(() => [String], {
description: `A list of user's roles`
})
roles: string[];

您必须复制描述值。启用 introspectComments 后, CLI 插件可以提取这些注释并根据其自动为属性提供描述。 现在,上述字段可以简单地声明如下:

/**
* A list of user's roles
*/
roles: string[];

使用 CLI 插件

要启用插件,请打开 nest-cli.json(如果使用 Nest CLI), 并添加以下插件配置:

{
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"plugins": ["@nestjs/graphql"]
}
}

您可以使用 options 属性自定义插件的行为。

"plugins": [
{
"name": "@nestjs/graphql",
"options": {
"typeFileNameSuffix": [".input.ts", ".args.ts"],
"introspectComments": true
}
}
]

options 属性必须满足以下接口:

export interface PluginOptions {
typeFileNameSuffix?: string[];
introspectComments?: boolean;
}
选项默认值描述
typeFileNameSuffix['.input.ts', '.args.ts', '.entity.ts', '.model.ts']GraphQL types files suffix
introspectCommentsfalseIf set to true, plugin will generate descriptions for properties based on comments

如果您不使用 CLI 而是有自定义的 webpack 配置,您可以将此插件与 ts-loader 结合使用:

getCustomTransformers: (program: any) => ({
before: [require('@nestjs/graphql/plugin').before({}, program)]
}),

SWC 构建器

对于标准设置(非单体库),要使用 SWC 构建器与 CLI 插件, 您需要启用类型检查,如此处所述。

nest start -b swc --type-check

对于monorepo设置, 请按照这里的说明进行操作。

npx ts-node src/generate-metadata.ts
# 或 npx ts-node apps/{YOUR_APP}/src/generate-metadata.ts

现在,元数据文件必须由 GraphQLModule 方法加载,如下所示:

import metadata from './metadata'; // <-- 文件由 "PluginMetadataGenerator" 自动生成

GraphQLModule.forRoot<...>({
..., // 其他选项
metadata,
})

ts-jest 的集成(端到端测试)

在启用此插件的情况下运行端到端测试时,可能会遇到编译模式的模式问题。例如,最常见的错误之一是:

Object type <name> must define one or more fields.

这是因为 jest 配置未在任何地方导入 @nestjs/graphql/plugin 插件。

要解决此问题,请在您的端到端测试目录中创建以下文件:

const transformer = require('@nestjs/graphql/plugin');

module.exports.name = 'nestjs-graphql-transformer';
// 每次更改下面配置的时候,您都应该更改版本号 - 否则 jest 将无法检测到更改
module.exports.version = 1;

module.exports.factory = (cs) => {
return transformer.before(
{
// @nestjs/graphql/plugin 选项(可以为空)
},
cs.program, // 旧版本的 Jest(<= v27)的 "cs.tsCompiler.program"
);
};

有了这个,从 jest 配置文件中导入 AST 转换器。 默认情况下(在启动应用程序中),端到端测试配置文件位于 test 文件夹下, 并命名为 jest-e2e.json

{
... // 其他配置
"globals": {
"ts-jest": {
"astTransformers": {
"before": ["<path to the file created above>"]
}
}
}
}

如果使用 jest@^29,请使用下面的片段,因为先前的方法已被弃用。

{
... // 其他配置
"transform": {
"^.+\\.(t|j)s$": [
"ts-jest",
{
"astTransformers": {
"before": ["<path to the file created above>"]
}
}
]
}
}