GraphQL SDL枚举类型

时间:2018-07-31 01:19:26

标签: enums graphql graphql-js

我们在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'
},

解析器使用Mongoose匹配在nodejs后端中定义的枚举值,其中该字段定义为:

...
roles: {
  type: [
    {
      type: String,
      enum: ['user', 'provider', 'support', 'admin', 'super admin', 'guest']
    }
  ],
  default: ['user']
},
...

GraphQL枚举存在的问题是,我们无法对枚举进行自省,也无法使用GraphQL自省来获取映射。...

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

这只是我们拥有的许多枚举的一个例子。许多映射值由多个单词组成,这些单词之间有空格,或者包含SDL枚举值中不允许使用的字符(例如“超级管理员”)。

所以我的问题是...你们都如何处理这样的事情而不必重复自己或在前端添加更多代码以将它们映射为更有用的有意义的表示形式????

不能保证顺序与后端中枚举的定义顺序匹配,因此,即使解析器知道这一点,在后端模型中添加枚举也会严重搞乱SUPER_USER实际上映射到“超级用户”的所有假设。 >

致谢

史蒂夫

1 个答案:

答案 0 :(得分:1)

虽然此恕我直言没有完美的解决方案 有两种方法可以解决这个问题

  1. 优雅的方式
    您可以将查询接收到Enum名称的查询添加到graphql模式中 像这样(在SDL中):

    type Query {
         getEnumValues(enumName: String!): [EnumKeyValue!]!
    }
    
    type EnumKeyValue {
         key: String!
         value: String
    }
    

    这需要您稍微更改后端代码,例如,我将更改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] 
               }))
    
          }
    };
    


  2. 肮脏,辱骂但很快
    另一种可能的方式是滥用,是在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
            }
          }
        }