工具

工具

在GraphQL世界中,很多文章抱怨如何处理诸如身份验证或操作的副作用之类的东西。我们应该把它放在业务逻辑中吗?我们是否应该使用更高阶的函数来增强查询和突变,例如,使用授权逻辑?或者也许使用模式指令。无论如何,没有一个答案。

Nest生态系统正试图利用守卫和拦截器等现有功能帮助解决这个问题。它们背后的想法是减少冗余,并为您提供有助于创建结构良好,可读且一致的应用程序的工具。

概观

您可以使用与简单REST应用程序相同的方式使用警卫,拦截器和管道。此外,您可以通过利用自定义装饰器功能轻松创建自己的装饰器。他们都行为相当。我们来看看下面的代码:

@Query('author') @UseGuards(AuthGuard) async getAuthor(@Args('id', ParseIntPipe) id: number) { return await this.authorsService.findOneById(id }

如您所见,GraphQL在防护和管道方面都能很好地工作。因此,您可以将身份验证逻辑移至防护,甚至可以重用与REST应用程序相同的防护类。拦截器的工作方式完全相同:

@Mutation() @UseInterceptors(EventsInterceptor) async upvotePost(@Args('postId') postId: number) { return await this.postsService.upvoteById{ id: postId } }

执行上下文

但是,ExecutionContext守卫和拦截器所接收的情况有所不同。GraphQL解析器有一个单独的参数集,分别为rootargscontext,和info。因此,我们需要将给定转换ExecutionContextGqlExecutionContext,这基本上非常简单。

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { GqlExecutionContext } from '@nestjs/graphql'; @Injectable() export class AuthGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const ctx = GqlExecutionContext.create(context return true; } }

GqlExecutionContext为每个参数公开相应的方法,比如getArgs()getContext()等等。现在,我们可以毫不费力地获取特定于当前处理的请求的每个参数。

自定义装饰器

如前所述,自定义装饰器功能也可以像GraphQL解析器一样工作。但是,工厂函数采用一组参数而不是request对象。

export const User = createParamDecorator( (data, [root, args, ctx, info]) => ctx.user,

接着:

@Mutation() async upvotePost( @User() user: UserEntity, @Args('postId') postId: number, ) {}