Graphql

字段中间件

学习如何在 NestJS GraphQL 中使用字段中间件来拦截和修改字段解析过程。

字段中间件

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

字段中间件允许您在字段解析之前和之后运行任意代码,这允许您转换参数、结果,甚至完全控制字段解析。

让我们创建一个简单的中间件,将字段的字符串值转换为大写:

import { FieldMiddleware, MiddlewareContext, NextFn } from '@nestjs/graphql';

const loggerMiddleware: FieldMiddleware = async (
  ctx: MiddlewareContext,
  next: NextFn,
) => {
  const value = await next();
  console.log(value);
  return value;
};

MiddlewareContext 是一个包装器,围绕 GraphQL 解析器参数({ source, args, context, info }),而 NextFn 表示下一个中间件(在堆栈中)或实际字段解析器。

现在,让我们将此中间件应用到 name 字段:

@ObjectType()
export class Recipe {
  @Field({ middleware: [loggerMiddleware] })
  name: string;
}

现在,每当我们请求 name 字段时,其值将记录到控制台。

您还可以将中间件应用到自定义字段解析器(使用 @ResolveField() 装饰器注册的方法):

@Resolver(() => Recipe)
export class RecipeResolver {
  @ResolveField(() => String, { middleware: [loggerMiddleware] })
  name(@Parent() recipe: Recipe): string {
    return recipe.name;
  }
}

同样,您可以将中间件应用到查询/变更处理程序:

@Resolver(() => Recipe)
export class RecipeResolver {
  @Query(() => Recipe, { middleware: [loggerMiddleware] })
  recipe(): Recipe {
    return new Recipe();
  }
}

多个中间件

要将多个中间件绑定到单个字段,只需将它们传递给 middleware 数组。中间件的执行顺序与数组中的顺序相同(从左到右)。

@ObjectType()
export class Recipe {
  @Field({ middleware: [loggerMiddleware, uppercaseMiddleware] })
  name: string;
}

全局中间件

除了将中间件绑定到特定字段外,您还可以注册一个或多个全局运行的中间件(它们将在每个字段之前执行)。

GraphQLModule.forRoot({
  autoSchemaFile: 'schema.gql',
  fieldResolverEnhancers: ['middleware'],
  buildSchemaOptions: {
    fieldMiddleware: [loggerMiddleware],
  },
}),

fieldResolverEnhancers 选项允许您控制哪些增强器应该为字段解析器运行(不是根级别查询/变更/订阅处理程序)。可用的增强器有:guards(守卫)、interceptors(拦截器)、filters(过滤器)和 middleware(中间件)。