无法自定义 graphql 枚举的值

Can't custom value of graphql enum

我看过这个问题:

还有这个文档:https://www.apollographql.com/docs/graphql-tools/scalars/#internal-values

现在,我想自定义 graphql 的值 enum

typeDefs.ts:

import { gql } from 'apollo-server';

export const typeDefs = gql`
  enum Device {
    UNKNOWN
    DESKTOP
    HIGH_END_MOBILE
    TABLET
    CONNECTED_TV
  }

  type CampaignPerformanceReport {
    campaignNme: String!
    campaignId: ID!
    device: Device
  }

  type Query {
    campaignPerformanceReports: [CampaignPerformanceReport]!
  }
`;

resolvers.ts:

import { IResolvers } from 'graphql-tools';
import { IAppContext } from './appContext';

export const resolvers: IResolvers = {
  Device: {
    UNKNOWN: 'Other',
    DESKTOP: 'Computers',
    HIGH_END_MOBILE: 'Mobile devices with full browsers',
    TABLET: 'Tablets with full browsers',
    CONNECTED_TV: 'Devices streaming video content to TV screens',
  },
  Query: {
    async campaignPerformanceReports(_, __, { db }: IAppContext) {
      return db.campaignPerformanceReports;
    },
  },
};

如您所见,我在解析器中自定义了 Device 枚举的值。

db.ts: 带有数据的假数据库

enum Device {
  UNKNOWN = 'Other',
  DESKTOP = 'Computers',
  HIGH_END_MOBILE = 'Mobile devices with full browsers',
  TABLET = 'Tablets with full browsers',
  CONNECTED_TV = 'Devices streaming video content to TV screens',
}

export const db = {
  campaignPerformanceReports: [
    {
      campaignId: 1,
      campaignNme: 'test',
      device: Device.DESKTOP,
    },
  ],
};

我也为此做了集成测试:

 test.only('should query campaign performance reports correctly with executable graphql schema', async () => {
      const schema = makeExecutableSchema({ typeDefs, resolvers });
      console.log(printSchema(schema));
      const server: ApolloServerBase = new ApolloServer({ schema, context: { db } });
      const { query }: ApolloServerTestClient = createTestClient(server);
      const res: GraphQLResponse = await query({ query: Q.campaignPerformanceReports });
      expect(res).toMatchInlineSnapshot(`
        Object {
          "data": Object {
            "campaignPerformanceReports": Array [
              Object {
                "campaignId": "1",
                "campaignNme": "test",
                "device": "DESKTOP",
              },
            ],
          },
          "errors": undefined,
          "extensions": undefined,
          "http": Object {
            "headers": Headers {
              Symbol(map): Object {},
            },
          },
        }
      `);
    });

如您所见,快照测试的结果。 device 字段的值仍然是 "DESKTOP",我预计值应该是 "Computers"

依赖版本:

"apollo-server": "^2.9.3",
"apollo-server-express": "^2.9.3",
"graphql": "^14.5.4",

最小回购:https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/custom-scalar-and-enum

您为 GraphQL 枚举指定的内部值只是内部值。这在 documentation:

中说明

These don't change the public API at all, but they do allow you to use that value instead of the schema value in your resolvers

如果将枚举值 DESKTOP 映射到内部值 Computers,只有解析器的 行为会受到影响 。具体来说:

  • 如果字段接受类型为 Device 的参数,并且参数传递的值为 DESKTOP,则实际传递给解析器函数的值将为 Computers.
  • 如果一个字段本身有类型 device 而我们想要 return DESKTOP,在我们的解析器中,我们将需要 return Computers

以如下所示的架构为例:

type Query {
  someQuery(device: Device!): Device!
}

如果您指定内部值,我们的解析器会这样工作:

function (parent, args) {
  console.log(args.device) // "DESKTOP"
  return 'DESKTOP'
}

如果您指定内部值,解析器如下所示:

function (parent, args) {
  console.log(args.device) // "Computers"
  return 'Computers'
}

解析器是唯一受为每个枚举值提供内部值影响的东西。 没有改变的是:

  • 如何在响应中序列化枚举值。枚举值总是序列化为枚举值名称的字符串。
  • 如何将枚举值作为文字写入文档中。例如,如果查询上面相同的字段,我们将 always 写成:{ someQuery(device: DESKTOP) }
  • 如何将枚举值作为变量提供。 Device 类型的变量 总是 写成 "DESKTOP".

注意: 虽然该问题专门针对 Apollo Server,但上述内容也适用于 vanilla GraphQL.js。例如,这个枚举

const DeviceEnum = new GraphQLEnumType({
  name: 'Device',
  values: {
    UNKNOWN: { value: 'Other' },
    DESKTOP: { value: 'Computers' },
    HIGH_END_MOBILE: { value: 'Mobile devices with full browsers' },
    TABLET: { value: 'Tablets with full browsers' },
    CONNECTED_TV: { value: 'Devices streaming video content to TV screens' },
  }
})

仍将按照上述方式运行。