解析器

解析器

通常,您必须手动创建解析图。的@nestjs/graphql包,在另一方面,产生解析器映射自动使用由装饰提供的元数据。为了学习库基础知识,我们将创建一个简单的作者API。首先,让我们在SDL中定义我们的类型:

type Author { id: Int! firstName: String lastName: String posts: [Post] } type Post { id: Int! title: String votes: Int } type Query { author(id: Int!): Author }

我们的GraphQL架构包含暴露的单个查询author(id: Int!): Author。现在,让我们创建一个AuthorResolver

@Resolver('Author') export class AuthorResolver { constructor( private readonly authorsService: AuthorsService, private readonly postsService: PostsService, ) {} @Query() async author(@Args('id') id: number) { return await this.authorsService.findOneById(id } @ResolveProperty() async posts(@Parent() author) { const { id } = author; return await this.postsService.findAll{ authorId: id } } }

提示如果使用@Resolver()装饰器,则不@Injectable()必将类标记为,否则,这是必要的。

@Resolver()装饰不影响查询和突变(既不@Query()也不@Mutation()装饰)。它只通知Nest @ResolveProperty()这个特定类中的每一个都有一个父类,Author在这种情况下是一个类型(Author.posts关系)。

通常,我们会使用类似getAuthor()getPosts()方法名称。通过在装饰者的括号之间移动真实姓名,我们也可以轻松地做到这一点。

@Resolver('Author') export class AuthorResolver { constructor( private readonly authorsService: AuthorsService, private readonly postsService: PostsService, ) {} @Query('author') async getAuthor(@Args('id') id: number) { return await this.authorsService.findOneById(id } @ResolveProperty('posts') async getPosts(@Parent() author) { const { id } = author; return await this.postsService.findAll{ authorId: id } } }

提示@Resolver()装饰可以在方法级别被使用。

装饰

您可能会注意到我们使用专用装饰器来引用以下参数。下面是提供的装饰器和它们代表的普通Apollo参数的比较。

@Root() 和 @Parent()root/parent
@Context(param?: string)context / context[param]
@Info(param?: string)info / info[param]
@Args(param?: string)args / args[param]

一旦我们在这里完成,我们必须在AuthorResolver某处注册,例如在新创建的内部AuthorsModule

JS

@Module{ imports: [PostsModule], providers: [AuthorsService, AuthorResolver], }) export class AuthorsModule {}

GraphQLModule会照顾反映了元数据和转化类到正确的解析器的自动映射。您应该注意的唯一事情是您需要在某处导入此模块,因此Nest将知道它AuthorsModule确实存在。

分型

单独创建GraphQL类型和相应的TypeScript定义会产生不必要的冗余。最终,我们最终没有单一的事实来源,SDL内部的每一次变化都迫使我们调整接口。因此,该@nestjs/graphql包提供了另一个有趣的功能,即使用抽象语法树(AST)自动生成TS定义。要启用它,只需自定义definitions属性即可。

GraphQLModule.forRoot{ typePaths: ['./**/*.graphql'], definitions: { path: join(process.cwd(), 'src/graphql.ts'), }, })

src/graphql.ts指示在何处保存打字稿输出。默认情况下,所有类型都转换为接口。但是,您可以通过将outputAs属性更改为切换到类class

GraphQLModule.forRoot{ typePaths: ['./**/*.graphql'], definitions: { path: join(process.cwd(), 'src/graphql.ts'), outputAs: 'class', }, })

因此,它将生成以下文件:

export class Author { id: number; firstName?: string; lastName?: string; posts?: Post[]; } export class Post { id: number; title?: string; votes?: number; } export abstract class IQuery { abstract author(id: number): Author | Promise<Author>; }

类允许您使用装饰器,这使得它们在验证方面非常有用。例如:

import { MinLength, MaxLength } from 'class-validator'; export class CreatePostInput { @MinLength(3) @MaxLength(50) title: string; }

注意要启用输入(和参数)的自动验证,必须使用ValidationPipe