use*_*230 5 enums graphql graphql-js
我们在SDL中定义了一堆枚举类型,它们非常适合查询和变异。在“解析器”部分中,这些映射到代表后端中那些枚举的字符串。
例如,在SDL中,我们有:
enum WRRole {
USER
PROVIDER
SUPPORT
ADMIN
SUPER_ADMIN
GUEST
}
Run Code Online (Sandbox Code Playgroud)
在解析器部分,我们有:
WRRole: {
USER: 'user',
PROVIDER: 'provider',
SUPPORT: 'support',
ADMIN: 'admin',
SUPER_ADMIN: 'super admin',
GUEST: 'guest'
},
Run Code Online (Sandbox Code Playgroud)
解析器使用Mongoose匹配在nodejs后端中定义的枚举值,其中该字段定义为:
...
roles: {
type: [
{
type: String,
enum: ['user', 'provider', 'support', 'admin', 'super admin', 'guest']
}
],
default: ['user']
},
...
Run Code Online (Sandbox Code Playgroud)
GraphQL枚举存在的问题是,我们无法对枚举进行自省,也无法使用GraphQL自省来获取映射。
这会导致构建UI时出现问题,我们希望在其中向用户提供这些选项的下拉列表。SDL枚举值(例如SUPER_USER)非常适合这些键,但我们希望显示实际的后端映射值以供选择。
这只是我们拥有的许多枚举的一个例子。许多映射值由多个单词组成,这些单词之间有空格,或者包含SDL枚举值中不允许使用的字符(例如“ super admin”)。
所以我的问题是...你们所有人如何处理这样的事情而不必重复自己或在前端添加更多代码以将它们映射为更有用的有意义的名称以进行展示?
无法保证顺序与后端中枚举的已定义顺序匹配,因此,即使解析器知道这一点,将枚举添加到后端模型中也会严重混淆SUPER_USER实际上映射到“超级用户”的所有假设。
问候
史蒂夫
虽然这个问题没有完美的解决方案,但我有几种方法可以解决这个问题
优雅的方式
您可以向 graphql 模式添加一个接收Enum名称的查询,如下所示(在SDL):
type Query {
getEnumValues(enumName: String!): [EnumKeyValue!]!
}
type EnumKeyValue {
key: String!
value: String
}
Run Code Online (Sandbox Code Playgroud)
这需要您稍微更改后端代码,例如我会更改解析器Enum以从对象中获取数据,如下所示:
const enums = {
WRRole: {
USER: 'user',
PROVIDER: 'provider',
...
}
};
const enumResolver = {
WRRole: {
USER: enums.WRRole.USER,
PROVIDER: enums.WRRole.PROVIDER,
...
}
};
Run Code Online (Sandbox Code Playgroud)
然后解析器getEnumValues看起来像:
const queryResolvers = {
getEnumValues(source, args) {
const enumKey = args.enumName;
// enums is the same enums object from the previous example
return Object.keys(enums[enumKey]).map(key => ({
key,
value: enums[enumKey][key]
}))
}
};
Run Code Online (Sandbox Code Playgroud)
肮脏、滥用但快速
另一种可能的方法(有点滥用)是添加该Enum值的描述,以便您Enum SDL想要:
enum WRRole {
# user
USER
# provider
PROVIDER
# support
SUPPORT
# admin
ADMIN
# super admin
SUPER_ADMIN
# guest
GUEST
}
Run Code Online (Sandbox Code Playgroud)
然后您可以使用以下查询获取键和描述之间的映射:
{
__type(name: "WRRole") {
enumValues {
description
name
}
}
}
Run Code Online (Sandbox Code Playgroud)