Typescript OneGraph和Graphql Codegen输出带有数值的枚举
因此,我刚刚将一个项目的整个代码库从使用直接无头Wordpress GraphQL端点迁移到使用OneGraph for Google+Facebook业务支持。OneGraph是一个神奇的工具,我打算在一个我正在写的无头WordPress上的科技课程中使用它。无论如何,我得到了这个阿波罗错误,它引用了输出codegen。以下是错误:Typescript OneGraph和Graphql Codegen输出带有数值的枚举,typescript,enums,graphql,next.js,code-generation,Typescript,Enums,Graphql,Next.js,Code Generation,因此,我刚刚将一个项目的整个代码库从使用直接无头Wordpress GraphQL端点迁移到使用OneGraph for Google+Facebook业务支持。OneGraph是一个神奇的工具,我打算在一个我正在写的无头WordPress上的科技课程中使用它。无论如何,我得到了这个阿波罗错误,它引用了输出codegen。以下是错误: graphQLErrors: [ { message: 'Variable "$idTypeFoot" got inv
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文件中的输出codegen定义:
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'
}
以下是父查询中使用的动态导航字段。graphql
partial:
fragment DynamicNavFragment on WordpressMenuItem {
id
label
path
parentId
}
# 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
}
}
}
}
}
}
}
}
}
以下是动态导航图ql
父查询:
fragment DynamicNavFragment on WordpressMenuItem {
id
label
path
parentId
}
# 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配置文件:
覆盖:true
模式:
${WORDPRESS\u API\u URL\u YML}:
标题:
授权:承载${WORDPRESS\u AUTH\u REFRESH\u TOKEN\u YML}
文档:“graphql/***.graphql”
生成:
graphql/generated/graphql.tsx:
插件:
-打字稿:
常量:false
枚举类型:false
数字:对
未来证明:错误
枚举常量:false
仅限操作类型:false
maybeValue:T | null |未定义
noExport:false
枚举前缀:true
fieldWrapperValue:T
wrapFieldDefinitions:true
skipTypename:false
非可选类型名称:false
useTypeImports:false
避免选项:正确
声明种类:
输入:接口
类型:接口
-类型脚本操作:
声明种类:
输入:接口
类型:接口
避免选项:正确
ExportFragments子类型:true
-阿波罗的打字脚本:
addDocBlocks:正确
新版本:3
documentMode:documentNodeImportFragments
配置:
maybeValue:T | null |未定义
声明种类:
输入:接口
类型:接口
documentNodeImportFragments:true
新版本:3
胡克:没错
withHOC:错误
避免选项:正确
withComponent:false
ExportFragments子类型:true
addDocBlocks:正确
graphql/graphql.schema.graphql:
插件:
-模式ast
配置:
注释说明:正确
graphql/graphql.schema.json:
插件:
-内省
配置:
注释说明:正确
挂钩:
文件写入后:
-更漂亮——写
为什么OneGraph用apollo客户端无法读取的数字替换生成的枚举值?如果有人知道如何解决这个问题,请让我知道更新-见@sgrove的答案,他很棒,帮助我解决了这个问题 好的,我有两个选择:(1)覆盖从以前表示_类型的字符串值转换的每个枚举,或者(2)硬编码这些值。要获取自定义枚举值,我必须将以下内容添加到codegen.yml中:
config:
枚举值:
WordPressMenuodedTypeEnum:“@/types/global enum#WordPressMenuodedTypeEnum”
它指示生成的代码从@/types/global-enums.ts导入此枚举定义
/** The Type of Identifier used to fetch a single node. Default is "ID". To be used along with the "id" field. */
export enum WordpressMenuNodeIdTypeEnum {
/** 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'
}
但是,我随后遇到了另一个问题,决定直接在我的graphql模式中为WordPressMenuDeidTypeEnum硬编码名称
值:
# import DynamicNavFragment from './Partials/dynamic-nav-fields.graphql'
query DynamicNav($idHead: ID!, $idFoot: ID!) {
Header: wordpress {
menu(id: $idHead, idType: NAME) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
}
}
Footer: wordpress {
menu(id: $idFoot, idType: NAME) {
menuItems(where: { parentId: 0 }) {
edges {
node {
...DynamicNavFragment
childItems {
edges {
node {
...DynamicNavFragment
}
}
}
}
}
}
}
}
}
然后,我遇到了apollo缓存的另一个问题,因为顶级ServicesTopQuery和DynamicNavQuery都有一个共享的顶级wordpress
字段,其中有一个对应的u typename“WordPressRootQuery”
ServicesTopQuery
和ServicesTopQueryVariables
的代码生成定义:
export type ServicesTopQueryVariables = Exact<{
popular: Scalars['String'];
other: Scalars['String'];
}>;
export type ServicesTopQuery = { __typename?: 'Query' } & {
popular: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
services: Maybe<
{ __typename?: 'WordpressRootQueryToServiceConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressRootQueryToServiceConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressService';
} & ServiceFieldsTopFragment
>;
}
>
>
>;
}
>;
}
>;
other: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
services: Maybe<
{ __typename?: 'WordpressRootQueryToServiceConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressRootQueryToServiceConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressService';
} & ServiceFieldsTopFragment
>;
}
>
>
>;
}
>;
}
>;
};
export type DynamicNavQueryVariables = Exact<{
idHead: Scalars['ID'];
idFoot: Scalars['ID'];
}>;
export type DynamicNavQuery = { __typename?: 'Query' } & {
Header: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
menu: Maybe<
{ __typename?: 'WordpressMenu' } & {
menuItems: Maybe<
{ __typename?: 'WordpressMenuToMenuItemConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressMenuItem';
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
}
>;
}
>;
Footer: Maybe<
{ __typename?: 'WordpressRootQuery' } & {
menu: Maybe<
{ __typename?: 'WordpressMenu' } & {
menuItems: Maybe<
{ __typename?: 'WordpressMenuToMenuItemConnection' } & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuToMenuItemConnectionEdge';
} & {
node: Maybe<
{ __typename?: 'WordpressMenuItem' } & {
childItems: Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnection';
} & {
edges: Maybe<
Array<
Maybe<
{
__typename?: 'WordpressMenuItemToMenuItemConnectionEdge';
} & {
node: Maybe<
{
__typename?: 'WordpressMenuItem';
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
} & DynamicNavFragmentFragment
>;
}
>
>
>;
}
>;
}
>;
}
>;
};
来自pages/index.tsx
的代码,其中最初填充了DynamicNavQuery数据,然后被ServicesTopQuery数据迅速覆盖
import { Container } from '@/components/UI';
import { initializeApollo, addApolloState } from '@/lib/apollo';
import { LandingHero } from '@/components/Landing';
import ServiceTopCoalesced from '@/components/ServicesTop/services-top-coalesced';
import AppLayout from '@/components/Layout/layout';
import {
GetStaticPropsContext,
GetStaticPropsResult,
InferGetStaticPropsType
} from 'next';
import {
ServicesTopQuery,
ServicesTopQueryVariables,
ServicesTopDocument,
DynamicNavDocument,
DynamicNavQueryVariables,
DynamicNavQuery
} from '@/graphql/generated/graphql';
export function Index({
other,
popular,
Header,
Footer
}: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<>
<AppLayout
title={'✂ The Fade Room Inc. ✂'}
Header={Header}
Footer={Footer}
hero={<LandingHero />}
>
<Container clean className='fit'>
<ServiceTopCoalesced other={other} popular={popular} />
</Container>
</AppLayout>
</>
);
}
export async function getStaticProps(
ctx: GetStaticPropsContext
): Promise<
GetStaticPropsResult<{
other: ServicesTopQuery['other'];
popular: ServicesTopQuery['popular'];
Header: DynamicNavQuery['Header'];
Footer: DynamicNavQuery['Footer'];
}>
> {
const apolloClient = initializeApollo();
await apolloClient.query<
DynamicNavQuery,
DynamicNavQueryVariables
>({
query: DynamicNavDocument,
variables: {
idHead: 'Header',
idFoot: 'Footer'
}
});
await apolloClient.query<
ServicesTopQuery,
ServicesTopQueryVariables
>({
query: ServicesTopDocument,
variables: {
other: 'all',
popular: 'popular-service'
}
});
return addApolloState(apolloClient, {
props: {},
revalidate: 10
});
}
export default Index;
上述措施防止了现有的
wordpress
字段数据被传入的wordpress
字段数据覆盖,从而解决了问题。事实证明,从无头WordPress端点迁移到OneGraph端点的过程比最初预期的要复杂得多,因此我想,如果有人在迁移过程中遇到类似问题,我会给出详细的响应;将codegen.yml
更改为使用numericEnums:false
:
生成:
graphql/generated/graphql.tsx:
插件:
-打字稿:
数字:假
为了找到这一点,我使用了wordpressMenuodedTypeEnum的GraphQL SDL定义:
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
}
与前面的codegen.yml
中的numericEnums:true
设置一起使用,并在
正如您在屏幕截图中看到的,SDL定义被编译为数字枚举(运行时typescript枚举的标准)
然后我用numericEnums:false
进行测试:
该输出看起来与您期望的一样,其中wordpressMenuodedTypeEnum.Name
等于“Name”
,因此Apollo获得的是期望值,而不是运行时typescript枚举值(2
).numericEnums:true
?它在此之前抛出了一个错误,因为onegraph输出数值枚举时不考虑标志。最初我将其设置为false,唯一的区别是将2包装为“2”,仅使用单独生成的WP类型。。。您可以在以后[通过手动工作]通过几个步骤自定义枚举。。。您可以设置自己的联合API;)架构是否可以在某个地方进行测试?我想看看数字枚举是从哪里来的!