无法自定义 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' },
}
})
仍将按照上述方式运行。
我看过这个问题:
还有这个文档: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
,在我们的解析器中,我们将需要 returnComputers
。
以如下所示的架构为例:
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' },
}
})
仍将按照上述方式运行。