工具
工具
在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解析器有一个单独的参数集,分别为root
,args
,context
,和info
。因此,我们需要将给定转换ExecutionContext
为GqlExecutionContext
,这基本上非常简单。
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,
) {}