首页 > 解决方案 > OneGraph 和 Graphql Codegen 输出带有数值的枚举

问题描述

因此,我刚刚将我的整个项目代码库从使用直接无头 Wordpress GraphQL 端点迁移到使用 OneGraph 来支持 Google+Facebook 业务。OneGraph 是一个了不起的工具,打算在我正在编写的无头 WordPress 上的技术课程中使用它。无论如何,我收到了这个阿波罗错误,它引用了输出代码生成。这是错误:

  graphQLErrors: [
    {
      message: 'Variable "$idTypeFoot" got invalid value 2; Expected type MenuNodeIdTypeEnum.',
      path: [Array],
      extensions: [Object]
    },
    {
      message: 'Variable "$idTypeFoot" got invalid value 2; Expected type MenuNodeIdTypeEnum.',
      path: [Array],
      extensions: [Object]
    }
  ],

这是我生成的/graphql.tsx 文件中的输出代码生成定义:


export enum WordpressMenuNodeIdTypeEnum {
    /** Identify a menu node by the Database ID. */
    DATABASE_ID = 0,
    /** Identify a menu node by the (hashed) Global ID. */
    ID = 1,
    /** Identify a menu node by it's name */
    NAME = 2
}

这是在将我的代码库迁移到 onegraph 之前对同一枚举的先前定义:


/** The Type of Identifier used to fetch a single node. Default is "ID". To be used along with the "id" field. */
export enum MenuNodeIdTypeEnum {
    /** Identify a menu node by the Database ID. */
    DatabaseId = 'DATABASE_ID',
    /** Identify a menu node by the (hashed) Global ID. */
    Id = 'ID',
    /** Identify a menu node by it's name */
    Name = 'NAME'
}

这是dynamic-nav-fields.graphql父查询中使用的部分:

fragment DynamicNavFragment on WordpressMenuItem {
    id
    label
    path
    parentId
}

这是dynamic-nav.graphql父查询:

# import DynamicNavFragment from './Partials/dynamic-nav-fields.graphql'

query DynamicNav(
  $idHead: ID!
  $idTypeHead: WordpressMenuNodeIdTypeEnum!
  $idFoot: ID!
  $idTypeFoot: WordpressMenuNodeIdTypeEnum!
    ) {
    Header: wordpress {
        menu(id: $idHead, idType: $idTypeHead) {
            menuItems(where: { parentId: 0 }) {
                edges {
                    node {
                        ...DynamicNavFragment
                        childItems {
                            edges {
                                node {
                                    ...DynamicNavFragment
                                    childItems {
                                        edges {
                                            node {
                                                ...DynamicNavFragment
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    Footer: wordpress {
        menu(id: $idFoot, idType: idTypeFoot) {
            menuItems(where: { parentId: 0 }) {
                edges {
                    node {
                        ...DynamicNavFragment
                        childItems {
                            edges {
                                node {
                                    ...DynamicNavFragment
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

这是我的 codegen.yml 配置文件:

overwrite: true
schema:
  ${WORDPRESS_API_URL_YML}:
    headers:
      Authorization: Bearer ${WORDPRESS_AUTH_REFRESH_TOKEN_YML}
documents: 'graphql/**/*.graphql'
generates:
  graphql/generated/graphql.tsx:
    plugins:
      - typescript:
          constEnums: false
          enumsAsTypes: false          
          numericEnums: true
          futureProofEnums: false
          enumsAsConst: false
          onlyOperationTypes: false
          maybeValue: T | null | undefined
          noExport: false
          enumPrefix: true
          fieldWrapperValue: T
          wrapFieldDefinitions: true
          skipTypename: false
          nonOptionalTypename: false
          useTypeImports: false
          avoidOptionals: true
          declarationKind: 
            input: interface
            type: interface
      - typescript-operations:
          declarationKind:
            input: interface
            type: interface
          avoidOptionals: true
          exportFragmentSpreadSubTypes: true
      - typescript-react-apollo:
          addDocBlocks: true
          reactApolloVersion: 3
          documentMode: documentNodeImportFragments
    config:
      maybeValue: T | null | undefined
      declarationKind:
        input: interface
        type: interface
      documentNodeImportFragments: true
      reactApolloVersion: 3
      withHooks: true
      withHOC: false
      avoidOptionals: true
      withComponent: false
      exportFragmentSpreadSubTypes: true
      addDocBlocks: true
  graphql/graphql.schema.graphql:
    plugins:
      - schema-ast
    config:
      commentDescriptions: true
  graphql/graphql.schema.json:
    plugins:
      - introspection
    config:
      commentDescriptions: true
      
hooks:
  afterAllFileWrite: 
    - prettier --write

为什么 OneGraph 将生成的 Enum 值替换为 apollo 客户端无法读取的数字?如果有人知道如何解决这个问题,请告诉我

标签: typescriptenumsgraphqlnext.jscode-generation

解决方案


tldr; 改用:codegen.yml_numericEnums: false

generates:
  graphql/generated/graphql.tsx:
    plugins:
      - typescript:
          numericEnums: false

为了追踪这一点,我采用了 GraphQL SDL 定义WordpressMenuNodeIdTypeEnum

enum WordpressMenuNodeIdTypeEnum {
    # Identify a menu node by the Database ID.
    DATABASE_ID
    # Identify a menu node by the (hashed) Global ID.
    ID
    # Identify a menu node by it's name
    NAME
}

与之前的numericEnums: true设置一起,并在https://www.graphql-code-generator.comcodegen.yml的操场上使用它们 数字枚举:真

正如您在屏幕截图中看到的,SDL 定义被编译成数字枚举(运行时 typescript 枚举的标准)

然后我测试了numericEnums: false数字枚举:假

并且该输出看起来像您期望的那样,其中WordpressMenuNodeIdTypeEnum.Name等于"NAME",因此 Apollo 获得了预期值,而不是运行时 typescript-enum 值 ( 2)。


推荐阅读