graphql-code-generator-community icon indicating copy to clipboard operation
graphql-code-generator-community copied to clipboard

Using codegen.ts in an ESM project causes cosmiconfig-typescript-loader to throw an "ES modules is not supported" error

Open tars0x9752 opened this issue 3 years ago • 27 comments

Describe the bug

I don't know if it's a bug or not, but I'm reporting it just in case. See steps to reproduce below for a more detailed bug/issue explanation.

In short, if you set "type": "module" in package.json and use codegen.ts as a config file, graphql-codegen fails because of ESM error by cosmiconfig-typescript-loader.

If you use codegen.yml or delete "type": "module" from package.json, the error will not occur.

Your Example Website or App

Not yet.

Steps to Reproduce the Bug or Issue

  1. Add "type": "module" in package.json
  2. Run npx graphql-code-generator init and leave everything as default to create codegen.ts
  3. Run generated codegen npm script graphql-codegen --config codegen.ts. It throws the following error:
TypeScriptLoader failed to compile TypeScript:
Must use import to load ES Module: /path/to/project/codegen.ts
require() of ES modules is not supported.
require() of /path/to/project/codegen.ts from /path/to/project/node_modules/cosmiconfig-typescript-loader/dist/cjs/index.js is an ES module file as it is a .ts file whose nearest parent package.json contains "type": "module" which defines all .ts files in that package scope as ES modules.
Instead change the requiring code to use import(), or remove "type": "module" from /path/to/project/package.json.

It maybe a bug in cosmiconfig-typescript-loader.

Expected behavior

Code generation completes without throwing an error.

Screenshots or Videos

No response

Platform

  • OS: Linux x86_64
  • NodeJS: 18.8.0
  • "typescript": "4.8.4"
  • "graphql": "16.6.0"
  • "@graphql-codegen/cli": "2.13.7"
  • "@graphql-codegen/typescript": "2.7.4"
  • "@graphql-codegen/typescript-resolvers": "2.7.4"

Codegen Config File

No response

Additional context

a sample tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist",
    "target": "es2021",
    "lib": ["es2021"],
    "module": "Node16",
    "moduleResolution": "Node16",
    "esModuleInterop": true
  },
  "include": ["src"]
}

tars0x9752 avatar Oct 15 '22 15:10 tars0x9752

Hey @tars0x9752,

I about to move a project of mine over to ESM and noticed that the generator has a specific section in the documentation on getting ESM working,

I'm sure you have already seen it, but just in case: https://the-guild.dev/graphql/codegen/docs/getting-started/esm-typescript-usage

I haven't started the ESM migration myself so it's possible additional steps outside of that documentation are needed.

The quick version is

  • add emitLegacyCommonJSImports: false, to your codegen.ts file.
  • set module and moduleResolution to node16 in your tsconfig.ts
  • set type to module in package.json
  • modify generator command to use graphql-codegen-esm instead of graphql-codegen

A quick (empty) project seems to indicate this works on my end, but again I haven't tested with real project yet.

Destreyf avatar Oct 16 '22 03:10 Destreyf

Thanks for the reply. As you've guessed, I've already seen that document. The thing is, even that document's exmaple doesn't use codegen.ts. They use codegen.yml in the example. And as far as I have tested, even if you follow that document it doesn't work with codegen.ts.

As I wrote in my first comment, if I use something other than codegen.ts, such as codegen.yml, then problem doesn't occur. So I'm not in that much trouble because I can use codegen.yml as a workaround.

A quick (empty) project seems to indicate this works on my end, but again I haven't tested with real project yet.

Does it work with codegen.ts?

tars0x9752 avatar Oct 16 '22 10:10 tars0x9752

@tars0x9752 I didn't look at the example project, just the documentation on that page.

I did notice that you're running the graphql-codegen executable in your initial post and not the graphql-codegen-esm executable.

What happens if you run the following:

npx graphql-codegen-esm --config codegen.ts

I'm not sure what package needs to be installed to use graphql-codegen-esm without the npx call as I haven't spent much time looking at it, npx (assuming you're using npm) will at at least run the command.

Destreyf avatar Oct 16 '22 13:10 Destreyf

Thanks, but I've already tried graphql-codegen-esm too and that didn't work either.

It looks like cosmiconfig-typescript-loader cannot import codegen.ts if it's an ESM and requires the configuration file to be a CJS. (...probably they should consider using dynamic import instead of require.) FYI: https://github.com/Codex-/cosmiconfig-typescript-loader/blob/main/lib/loader.ts#L14

But these graphql libraries here such as graphql-config and @graphql-codegen/cli seem to be dependent on cosmiconfig-typescript-loader even if we use graphql-codegen-esm and codegen.ts with "type": "module".

tars0x9752 avatar Oct 17 '22 02:10 tars0x9752

see this

sirganya avatar Oct 18 '22 12:10 sirganya

I'm also having the same issue.

sirganya avatar Oct 18 '22 12:10 sirganya

having the same issue I just switched my codegen to a yml format instead of ts so it doesn't use the TypeScriptLoader which uses require to load the codegen file. just a workaround for now, coming from the apollo docs it'd be great if they "just worked", but yml will do for now :)

podefr avatar Oct 20 '22 09:10 podefr

I'm now having an error where @graphql-tools/code-file-loader is using require

Failed to load schema from ./src/gql/schema/*.ts: Failed to find any GraphQL type definitions in: ./src/gql/schema/*.ts; - Unable to load from file "/Users/sirganya/git/bwos/shared/src/gql/schema/getFiles.ts": Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/sirganya//git/bwos/shared/src/gql/s… require() of ES modules is not supported. require() of /Users/sirganya/git/bwos/shared/src/gql/schema/getFiles.ts from /Users/me/git/bwos/shared/node_modules/@graphql-tools/code-file-loader/cjs/load-from-module.js is an ES mod… Instead change the requiring code to use import(), or remove "type": "module" from /Users/sirganya/git/bwos/shared/package.json.

sirganya avatar Oct 21 '22 16:10 sirganya

having the same issue I just switched my codegen to a yml format instead of ts so it doesn't use the TypeScriptLoader

Thanks a lot this solved my problem on a fresh sveltekit install https://github.com/dotansimha/graphql-code-generator/issues/8509

gterras avatar Oct 23 '22 10:10 gterras

Solved with this:

https://github.com/dotansimha/graphql-code-generator/issues/8511#issuecomment-1287214910

sirganya avatar Oct 24 '22 07:10 sirganya

I'm having this problem as well, had to use a .yml config file to get around it. Annoying because that defats the purpose of using the TS config file in a TS project in the first place.

elijaholmos avatar Nov 15 '22 18:11 elijaholmos

I'm having this problem as well, had to use a .yml config file to get around it. Annoying because that defats the purpose of using the TS config file in a TS project in the first place.

It isn't supposed to defeat anything really, just the extension of your codegen config file.

gterras avatar Nov 15 '22 19:11 gterras

I need a JavaScript configuration for dotenv. Is there any workaround that allows JavaScript?

boehs avatar Nov 16 '22 22:11 boehs

I guess that for now we have no other choice than using the yml config as this is an issue with cosmiconfig-typescript-loader see issue here.

You can follow the instructions here for generating ESM compliant code.

If you are generating code from an ESM typescript schema and you have an error of type ERR_UNKNOWN_FILE_EXTENSION you should be able to solve the issue by using ts-node/esm loader:

{
    "codegen": "NODE_OPTIONS=\"--loader ts-node/esm\" graphql-codegen-esm --config codegen.yml"
}

Allaoua9 avatar Dec 07 '22 08:12 Allaoua9

As a workaround and in the case you absolutely want to use a codegen.ts config you can generate a yml config from the typescript config:

// codegen.ts
import yml from 'yaml';
import type {CodegenConfig} from '@graphql-codegen/cli';
import {writeFileSync} from 'fs';

const config: CodegenConfig = {
  schema: 'src/graphql/schemas/schema.ts',
  // ...
};

// save config as yml
writeFileSync('codegen.yml', yml.stringify(config));

export default config;

Then add the following script in your package.json :

{
    // Generate codegen.yml then call graphql-codegen-esm
    "codegen": "export NODE_OPTIONS=\"--loader ts-node/esm\" && node codegen.ts && graphql-codegen-esm --config codegen.yml"
}

This worked for me.

Allaoua9 avatar Dec 07 '22 09:12 Allaoua9

As a workaround and in the case you absolutely want to use a codegen.ts config you can generate a yml config from the typescript config:

This is terrifying. Thank you

boehs avatar Dec 25 '22 22:12 boehs

Hi, I'm having the same issue but none of the solutions are working for me. I've tried .ts, .yml, .cts config files and NODE_OPTIONS=\"--loader ts-node/esm\" If it makes a difference I'm trying to run it in a Nextjs project. No matter what I change I get the same error:

yarn run v1.22.19
$ graphql-codegen-esm --config codegen.cjs
/Users/me/Desktop/PROJECTS/project/node_modules/cli-truncate/index.js:3
const stringWidth = require('string-width');
                    ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/me/Desktop/PROJECTS/project/node_modules/string-width/index.js from /Users/me/Desktop/PROJECTS/project/node_modules/cli-truncate/index.js not supported.
Instead change the require of /Users/me/Desktop/PROJECTS/project/node_modules/string-width/index.js in /Users/me/Desktop/PROJECTS/project/node_modules/cli-truncate/index.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/Users/me/Desktop/PROJECTS/project/node_modules/cli-truncate/index.js:3:21) {
  code: 'ERR_REQUIRE_ESM'
}

Any other ideas?

mrchristophy avatar Jul 17 '23 04:07 mrchristophy

I was having the same error const stringWidth = require('string-width'); so i found out I had storybook installed which was using the string-width and conflicting with it so i removed all the storybook related packages and it worked

you can run this command to check

npm ls string-width

khanakia avatar Aug 19 '23 08:08 khanakia

FYI I've created an issue that covers several issues with using typescript files (codegen and local plugins) with workarounds that might help.

leonchabbey avatar Aug 22 '23 10:08 leonchabbey

I also encountered the same error.

$ yarn codegen                              
yarn run v1.22.19
$ graphql-codegen --config codegen.ts
/Users/xxx/xxx/project_nextjs/node_modules/cliui/build/index.cjs:291
const stringWidth = require('string-width');
                    ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/xxx/xxx/project_nextjs/node_modules/string-width/index.js from /Users/xxx/xxx/project_nextjs/node_modules/cliui/build/index.cjs not supported.
Instead change the require of index.js in /Users/xxx/xxx/project_nextjs/node_modules/cliui/build/index.cjs to a dynamic import() which is available in all CommonJS modules.

It appears to be an unintentionally installed package due to a dependency.

I solved the problem by upgrading the yarn version. ( Current stable version was v1.3.2 )

$ yarn --version
1.22.19

$ yarn set version 1.3.2

$ yarn --version        
1.3.2

conayw avatar Oct 11 '23 11:10 conayw

Same issue in Next.js project (v14). Solved with this:

yarn add [email protected]

dimitriBouteille avatar Feb 06 '24 10:02 dimitriBouteille

@dimitriBouteille Was this the only thing you changed?

I am using these packages: { "name": "strapi-test", "version": "0.1.0", "private": true, "scripts": { "dev": "concurrently \"next dev\" \"yarn generate --watch\"", "build": "next build", "start": "next start", "lint": "next lint", "generate": "graphql-codegen" }, "dependencies": { "@apollo/client": "^3.9.0-rc.1", "@apollo/experimental-nextjs-app-support": "^0.8.0", "@graphql-codegen/cli": "^5.0.2", "@graphql-codegen/client-preset": "^4.2.2", "@types/dlv": "^1.1.4", "dlv": "^1.1.3", "graphql": "^16.8.1", "graphql-request": "^6.1.0", "next": "14.1.0", "react": "^18", "react-dom": "^18", "string-width": "4.2.3" }, "devDependencies": { "@graphql-codegen/cli": "^5.0.0", "@graphql-codegen/client-preset": "^4.1.0", "@parcel/watcher": "^2.3.0", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10.0.1", "concurrently": "^8.2.1", "eslint": "^8", "eslint-config-next": "14.1.0", "postcss": "^8", "tailwindcss": "^3.3.0", "ts-node": "^10.9.2" } }

I tried it with your command: yarn add [email protected]

But i still get the same error...

zewas-digital avatar Feb 14 '24 15:02 zewas-digital

Same issue in Next.js project (v14). Solved with this:

yarn add [email protected]

This solved the issue

CatalinGheorghiu avatar Feb 25 '24 11:02 CatalinGheorghiu

Same issue in Next.js project (v14). Solved with this:

yarn add [email protected]

This solved the issue

Currently afterwards this pops: const stripAnsi = require('strip-ansi');

So you also need a

yarn add -D strip-ansi

develth avatar Apr 09 '24 10:04 develth

Same issue in Next.js project (v14) & @graphql-codegen/cli v5.0.2.

Solved with this:

  "resolutions": {
    "cli-truncate": "^4.0.0",
    "wrap-ansi": "^9.0.0",
    "listr2": "^8.2.3",
    "inquirer": "^10.1.0"
  }

aya-eiya avatar Jul 23 '24 10:07 aya-eiya

Same issue in Next.js project (v14) & @graphql-codegen/cli v5.0.2.

Solved with this:

  "resolutions": {
    "cli-truncate": "^4.0.0",
    "wrap-ansi": "^9.0.0",
    "listr2": "^8.2.3",
    "inquirer": "^10.1.0"
  }

Codegen config loaded now, but client preset it can't find any documents

SPAHI4 avatar Aug 10 '24 18:08 SPAHI4

cross-env NODE_OPTIONS=--experimental-require-module graphql-codegen --config ./codegen.yaml

Solved with this. This feature enabled by default at the NodeJS 22.12.0 See: This PR

jay-l-e-e avatar Jan 07 '25 05:01 jay-l-e-e