Graphql-code-generator: enumValues with different names in .graphql and .ts break in babel.

Created on 28 Mar 2020  路  6Comments  路  Source: dotansimha/graphql-code-generator

Describe the bug

Given:

schema:
  - ./src/main.graphql

generates:
  ./src/types.ts:
    plugins:
      - typescript
      - typescript-operations
    config:
      enumValues:
        UserStatusNotOk: ./Enums#USER_STATUS_NOT_OK
        UserStatusOk: ./Enums#UserStatusOk

It seems as if enumValues which do not have the same name in the .ts and .graphql files are now generating:

import { USER_STATUS_NOT_OK } from './Enums';
import UserStatusNotOk = USER_STATUS_NOT_OK; // <--

instead of the previous:

import { USER_STATUS_NOT_OK as UserStatusNotOk } from './Enums';

I am not sure if this is a bug, or expected behaviour, but it breaks the usage of those types with bable and @babel/plugin-transform-typescript.

To Reproduce
I have created a simple repo here:
https://github.com/philiiiiiipp/Grapqhl-Generator-Enum-Bug

Expected behavior

I would expect that this to still work with a project using babel and typescript.

Additional information

The last known working version was

"@graphql-codegen/cli": "^1.10.0",
"@graphql-codegen/typescript": "^1.10.0",
"@graphql-codegen/typescript-operations": "^1.10.0",
"@graphql-codegen/typescript-resolvers": "^1.10.0",
bug plugins

Most helpful comment

Ok great I will try that out. If this works fine should I add a PR with a note in https://graphql-code-generator.com/docs/plugins/typescript#enumvalues-enumvaluesmap describing the workaround?

All 6 comments

Hi @philiiiiiipp
It's not a bug, but something we changed to have better TS support. I guess we didn't know that Babel-TS doesn't support aliasing using import.

As a workaround, you can point enumValues only to the name, and then import it manually with add plugin.

schema:
  - ./src/main.graphql

generates:
  ./src/types.ts:
    plugins:
      - add: "import { USER_STATUS_NOT_OK, UserStatusOk } from './Enums';"
      - typescript
      - typescript-operations
    config:
      enumValues:
        UserStatusNotOk: USER_STATUS_NOT_OK
        UserStatusOk: UserStatusOk

Ok great I will try that out. If this works fine should I add a PR with a note in https://graphql-code-generator.com/docs/plugins/typescript#enumvalues-enumvaluesmap describing the workaround?

@philiiiiiipp sounds good!
Note that those documentation files are generated from the comments we have on the code.

I tried using the add plugin, but it does not seem to use the imported values. It just ignores those and generates the enums again.

schema:
  - ./src/main.graphql

generates:
  ./src/types.ts:
    plugins:
      - add: "import { USER_STATUS_NOT_OK, UserStatusOk } from './Enums';"
      - typescript
      - typescript-operations
    config:
      enumValues:
        # UserStatusNotOk: ./Enums#USER_STATUS_NOT_OK
        # UserStatusOk: ./Enums#UserStatusOk
        UserStatusNotOk: USER_STATUS_NOT_OK
        UserStatusOk: UserStatusOk

generates

import { USER_STATUS_NOT_OK, UserStatusOk } from './Enums';
export type Maybe<T> = T | null;

/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

export enum UserStatusNotOk {
  Pending = 'Pending',
  InvitedPending = 'InvitedPending',
  Invited = 'Invited',
  Active = 'Active',
  Inactive = 'Inactive'
}

export enum UserStatusOk {
  Pending = 'Pending',
  InvitedPending = 'InvitedPending',
  Invited = 'Invited',
  Active = 'Active',
  Inactive = 'Inactive'
}

This then of course ends with the syntaxt error

SyntaxError: /Users/philipp/node/dev/dh/gql-types-test/src/types.ts: Identifier 'UserStatusOk' has already been declared (21:12)

  19 | }
  20 | 
> 21 | export enum UserStatusOk {
     |             ^
  22 |   Pending = 'Pending',
  23 |   InvitedPending = 'InvitedPending',
  24 |   Invited = 'Invited',
    at Object._raise (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/parser/location.js:241:45)
    at Object.raiseWithData (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/parser/location.js:236:17)
    at Object.raise (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/parser/location.js:220:17)
    at TypeScriptScopeHandler.checkRedeclarationInScope (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/util/scope.js:137:12)
    at TypeScriptScopeHandler.declareName (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/util/scope.js:98:12)
    at TypeScriptScopeHandler.declareName (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/plugins/typescript/scope.js:51:11)
    at Object.checkLVal (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/parser/lval.js:392:22)
    at Object.checkLVal (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/plugins/typescript/index.js:2508:17)
    at Object.tsParseEnumDeclaration (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/plugins/typescript/index.js:1242:12)
    at Object.tsParseDeclaration (/Users/philipp/node/dev/dh/gql-types-test/node_modules/@babel/core/node_modules/@babel/parser/src/plugins/typescript/index.js:1517:25) {
  loc: Position { line: 21, column: 12 },
  pos: 449,
  code: 'BABEL_PARSE_ERROR'
}

* EDIT *
I updated the test repository to reflect the changes

So how about using aliases or * in the imports then;

schema:
  - ./src/main.graphql

generates:
  ./src/types.ts:
    plugins:
      - add: "import * as Enums from './Enums';"
      - typescript
      - typescript-operations
    config:
      enumValues:
        # UserStatusNotOk: ./Enums#USER_STATUS_NOT_OK
        # UserStatusOk: ./Enums#UserStatusOk
        UserStatusNotOk: Enums.USER_STATUS_NOT_OK
        UserStatusOk: Enums.UserStatusOk

or

schema:
  - ./src/main.graphql

generates:
  ./src/types.ts:
    plugins:
      - add: "import { USER_STATUS_NOT_OK, UserStatusOk as USER_STATUS_OK } from './Enums';"
      - typescript
      - typescript-operations
    config:
      enumValues:
        # UserStatusNotOk: ./Enums#USER_STATUS_NOT_OK
        # UserStatusOk: ./Enums#UserStatusOk
        UserStatusNotOk: USER_STATUS_NOT_OK
        UserStatusOk: USER_STATUS_OK

The problem is that the enum values are not getting picked up from the generated file itself.

E.g.:

import { USER_STATUS_NOT_OK as UserStatusNotOk, UserStatusOk } from './Enums';
export type Maybe<T> = T | null;

/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

export enum UserStatusNotOk {
  Pending = 'Pending',
  InvitedPending = 'InvitedPending',
  Invited = 'Invited',
  Active = 'Active',
  Inactive = 'Inactive'
}

export enum UserStatusOk {
  Pending = 'Pending',
  InvitedPending = 'InvitedPending',
  Invited = 'Invited',
  Active = 'Active',
  Inactive = 'Inactive'
}

Is the generated file using - add: "import { USER_STATUS_NOT_OK as UserStatusNotOk, UserStatusOk } from './Enums';"

while it should have been

import { USER_STATUS_NOT_OK as UserStatusNotOk, UserStatusOk } from './Enums';
export type Maybe<T> = T | null;

/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

export { UserStatusNotOk };
export { UserStatusOk };

I have also tried your suggestions, but they all have the issues.

Was this page helpful?
0 / 5 - 0 ratings