You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义GraphQL Schema指令@nonEmptyArray无法触发验证问题

问题分析与解决方案

问题出在GraphQL对列表类型的包装处理机制上:你给输入对象字段添加了@nonEmptyArray指令,但字段类型是[String!]!(即NonNull(List(NonNull(String)))),而你把验证逻辑添加到了INPUT_OBJECT_FIELD的配置扩展中,并没有关联到实际处理数组输入的List类型上,导致validateInput始终不会被触发。

修正方案

核心思路是:解析输入字段的类型结构,找到其中的List类型部分,将验证逻辑绑定到该List类型的扩展上,这样数组输入经过List类型处理时,就会执行空数组检查。

修正后的完整代码

import { GraphQLSchema, GraphQLInputFieldConfig, isListType, GraphQLNonNull } from 'graphql';
import { MapperKind, mapSchema, getDirective, SchemaMapper } from '@graphql-tools/utils';

class EmptyArrayError extends Error {
  constructor(fieldName: string) {
    super(`Field "${fieldName}" cannot be an empty array`);
    this.name = 'EmptyArrayError';
  }
}

const getNonEmptyArrayDirective = (schema: GraphQLSchema): SchemaMapper => ({
  [MapperKind.INPUT_OBJECT_FIELD]: (
    fieldConfig: GraphQLInputFieldConfig,
    fieldName: string,
    typeName: string,
  ) => {
    const directive = getDirective(schema, fieldConfig, 'nonEmptyArray')?.[0];
    if (directive) {
      // 逐层解析字段类型,穿透NonNull包装,找到实际的List类型
      let currentType = fieldConfig.type;
      while (currentType instanceof GraphQLNonNull) {
        currentType = currentType.ofType;
      }

      // 确认是List类型后,添加验证逻辑到其扩展中
      if (isListType(currentType)) {
        currentType.extensions = {
          ...currentType.extensions,
          validateInput: (inputValue: unknown) => {
            if (Array.isArray(inputValue) && inputValue.length === 0) {
              throw new EmptyArrayError(fieldName);
            }
            return inputValue;
          },
        };
      }
    }
    return fieldConfig;
  },
});

export default function applySchemaDirectives(
  schema: GraphQLSchema,
): GraphQLSchema {
  return mapSchema(schema, getNonEmptyArrayDirective(schema));
}

关键说明

  1. 类型解析:通过循环穿透NonNull包装,定位到实际处理数组的List类型,确保验证逻辑绑定到正确的处理节点上。
  2. 验证触发时机:List类型的validateInput会在数组输入被解析时执行,此时就能直接拿到完整的数组值进行空检查。
  3. 错误处理:自定义的EmptyArrayError会被GraphQL的错误处理机制捕获,最终返回给客户端清晰的错误提示。

内容的提问来源于stack exchange,提问作者Dan Mandel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 03:12:50