Enums GraphQL SDL枚举类型

Enums GraphQL SDL枚举类型,enums,graphql,graphql-js,Enums,Graphql,Graphql Js,我们在SDL中定义了一系列枚举类型,它们非常适合查询和变异。 在“冲突解决程序”部分中,这些映射到表示后端中那些枚举的字符串 例如,在SDL中,我们有: enum WRRole { USER PROVIDER SUPPORT ADMIN SUPER_ADMIN GUEST } WRRole: { USER: 'user', PROVIDER: 'provider', SUPPORT: 'support', ADMIN: '

我们在SDL中定义了一系列枚举类型,它们非常适合查询和变异。 在“冲突解决程序”部分中,这些映射到表示后端中那些枚举的字符串

例如,在SDL中,我们有:

enum WRRole {
    USER
    PROVIDER
    SUPPORT
    ADMIN
    SUPER_ADMIN
    GUEST
}
WRRole: {
   USER: 'user',
   PROVIDER: 'provider',
   SUPPORT: 'support',
   ADMIN: 'admin',
   SUPER_ADMIN: 'super admin',
   GUEST: 'guest'
},
在解析器部分,我们有:

enum WRRole {
    USER
    PROVIDER
    SUPPORT
    ADMIN
    SUPER_ADMIN
    GUEST
}
WRRole: {
   USER: 'user',
   PROVIDER: 'provider',
   SUPPORT: 'support',
   ADMIN: 'admin',
   SUPER_ADMIN: 'super admin',
   GUEST: 'guest'
},
解析程序使用Mongoose匹配nodejs后端中定义的枚举值,其中字段定义为:

...
roles: {
  type: [
    {
      type: String,
      enum: ['user', 'provider', 'support', 'admin', 'super admin', 'guest']
    }
  ],
  default: ['user']
},
...
GraphQL枚举存在的问题是,我们无法使用GraphQL内省内省枚举并获取映射

这会导致在构建UI时出现问题,我们希望在UI中向用户提供这些选项的下拉列表。SDL枚举值(如SUPER_USER)对于键来说非常有用,但我们希望显示实际的后端映射值以供选择

这只是我们拥有的许多枚举的一个示例。许多映射值由多个单词组成,这些单词之间有空格,或者包含SDL枚举值中不允许使用的字符,如本例中的“super admin”

所以我的问题是。。。您如何处理这样的东西,而不必重复自己的工作或在前端添加更多代码,以便将这些代码映射到更有用、更有意义的名称以供演示

无法保证顺序与后端中枚举的定义顺序匹配,因此添加到后端模型枚举将严重打乱任何假设,即超级用户实际上映射到“超级用户”,即使解析器知道这一点

问候


史蒂夫

虽然没有一个完美的解决方案 有几种方法可以解决这个问题

  • 优雅的方式
    您可以向graphql模式添加一个接收
    Enum
    名称的查询 像这样(在
    SDL
    ):

    这需要您稍微更改后端代码,例如,我将更改
    Enum
    解析器,以便从如下对象获取其数据:

    const enums = {
        WRRole: {
            USER: 'user',
            PROVIDER: 'provider',
            ...
        }
    };
    
    const enumResolver = {
        WRRole: {
           USER: enums.WRRole.USER,
           PROVIDER: enums.WRRole.PROVIDER,
           ...
        }
    };
    
    然后,
    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] 
               }))
    
          }
    };
    

  • 脏兮兮的、辱骂的但很快
    另一种可能有点滥用的方法是在
    Enum
    值上添加描述 因此,您的
    Enum
    SDL
    希望:

        enum WRRole {
          # user
          USER
          # provider
          PROVIDER
          # support
          SUPPORT
          # admin
          ADMIN
          # super admin
          SUPER_ADMIN
          # guest
          GUEST
        }
    
    然后,您可以通过以下查询获得密钥和描述之间的映射:

        {
          __type(name: "WRRole") {
            enumValues {
              description
              name
            }
          }
        }
    

  • 有趣的是,我最初尝试了您的“肮脏、滥用但快速”解决方案,但在这种情况下,用于描述的结果始终为空。我目前正在研究另一个解决方案,因为您首选的解决方案过于复杂,因为我们有大量枚举要处理。@user1790230为什么结果为空?(你在使用模式缝合吗?)看看这个例子,我很想知道你还想到了什么解决方案?是的。我们正在将4个模式缝合在一起。其中两个是远程模式,另外两个是我们服务的本地模式。似乎没有保留枚举字段上的任何注释。所有其他类型的注释都完好无损,可以很好地进行内省。一旦我有一点时间,我将致力于我心目中更通用的解决方案。这并不是说它会起作用,但我们会尝试一下,然后我会用答案更新这篇文章。谢谢你的信息丹尼尔。我刚刚升级到3.1.1,关于枚举的评论现在可以使用了。这将节省我很多努力,因此我已将你的回答标记为已接受。谢谢