graphql - Can't custom value of graphql enum
问题描述
I have looked this question: How to use or resolve enum types with graphql-tools?
And, this doc: https://www.apollographql.com/docs/graphql-tools/scalars/#internal-values
Now, I want to custom the value of 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;
},
},
};
As you can see, I custom the value of Device
enum in the resolver.
db.ts
: a fake db with datas
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,
},
],
};
I also made an integration test for this:
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 {},
},
},
}
`);
});
As you can see, the result of snapshot testing. The value of device
field is still "DESKTOP", I expected the value should be "Computers"
Dependencies version:
"apollo-server": "^2.9.3",
"apollo-server-express": "^2.9.3",
"graphql": "^14.5.4",
The minimal repo: https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/custom-scalar-and-enum
解决方案
The internal values you specify for a GraphQL enum are just that -- internal. This is stated in the 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
If you map the enum value DESKTOP
to the internal value Computers
, only the behavior of your resolvers will be affected. Specifically:
- If a field takes an argument of the type
Device
and the argument is passed the valueDESKTOP
, the value actually passed to the resolver function will beComputers
. - If a field itself has the type device and we want to return
DESKTOP
, inside our resolver, we will need to returnComputers
instead.
Take for example a schema that looks like this:
type Query {
someQuery(device: Device!): Device!
}
If you don't specify internal values, our resolver works like this:
function (parent, args) {
console.log(args.device) // "DESKTOP"
return 'DESKTOP'
}
If you do specify internal values, the resolver looks like this:
function (parent, args) {
console.log(args.device) // "Computers"
return 'Computers'
}
The resolver is the only thing impacted by providing internal values for each enum value. What doesn't change:
- How the enum value is serialized in the response. Enum values are always serialized as strings of the enum value name.
- How the enum value is written as a literal inside a document. For example, if querying the above same field, we would always write:
{ someQuery(device: DESKTOP) }
- How the enum value is provided as a variable. A variable of the type
Device
would always be written as"DESKTOP"
.
NOTE: While the question pertains specifically to Apollo Server, the above applies to vanilla GraphQL.js as well. For example, this enum
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' },
}
})
will still behave as described above.
推荐阅读
- pytorch - 如何保存 PyTorch 的 DataLoader 实例?
- .net-core - 如何在本地运行 Azure Functions 应用程序?
- python - 如何为每个图表打开一个新窗口以便它们保持显示?
- javascript - 如何通过考虑光标的位置来添加包含图像和一些输入的 div 块
- python - 如果python中的某些条件失败,如何停止执行累积函数
- c# - 当我调整窗口大小时,带有数据选择器的 UWP Treeview 在 App.g.cs 中生成错误
- python - 如何修复 kali linux 中的 .py 错误?
- r - 如何在 Jupyter r 环境中安装我的自定义 R 包
- python - Docker:避免必须运行所有容器并且必须再次构建映像
- javascript - 推送新数据时,剑道网格数据源不更新