commitlint: ERR_REQUIRE_ESM when using Node.js ESM in tandem with TypeScript config (commitlint.config.ts)

// package.json
{
  "type": "module"
}
// tsconfig.json
{
  "compilerOptions": {
    "module": "node16"
  }
}

Expected Behavior

With the given setup above, executing npx commitlint --to HEAD should not result in ERR_REQUIRE_ESM error.

Current Behavior

Currently, the above setup is giving the following output:

./node_modules/ts-node/dist-raw/node-internal-errors.js:46
  const err = new Error(getErrRequireEsmMessage(filename, parentPath, packageJsonPath))
              ^
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ./commitlint.config.ts
require() of ES modules is not supported.
require() of ./commitlint.config.ts from ./node_modules/cosmiconfig-typescript-loader/dist/loader.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 ./package.json.

    at createErrRequireEsm (./node_modules/ts-node/dist-raw/node-internal-errors.js:46:15)
    at assertScriptCanLoadAsCJSImpl (./node_modules/ts-node/dist-raw/node-internal-modules-cjs-loader.js:584:11)
    at Object.require.extensions.<computed> [as .ts] (./node_modules/ts-node/src/index.ts:1589:5)
    at Module.load (node:internal/modules/cjs/loader:988:32)
    at Function.Module._load (node:internal/modules/cjs/loader:834:12)
    at Module.require (node:internal/modules/cjs/loader:1012:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at loader (./node_modules/cosmiconfig-typescript-loader/dist/loader.js:12:28)
    at Explorer.loadFileContent (./node_modules/cosmiconfig/src/Explorer.ts:81:32)
    at Explorer.createCosmiconfigResult (./node_modules/cosmiconfig/src/Explorer.ts:89:36) {
  name: 'TypeScriptCompileError'
}

Affected packages

  • cli
  • core
  • prompt
  • config-angular

Possible Solution

  1. Support commitlint.config.cts, or
  2. Use import() to load config

Steps to Reproduce (for bugs)

  1. First step: Minimal setup of commitlint according to the official documentation with package.json and tsconfig.json supplied above.
  2. Second step: Run npx commitlint --to HEAD.
commitlint.config.ts
import type { UserConfig } from "@commitlint/types";

const config: UserConfig = {
  extends: ["@commitlint/config-conventional"],
};

export default config;

Context

Without touching tsconfig.json, if I remove "type": "module" from package.json, npx commitlint --to HEAD can be executed successfully.

But this is not plausible since I have migrated the whole repository to Node.js ESM since the release of TypeScript 4.7 officially supporting it.

Raising this issue as people with similar setup will encounter this as well.

Currently resorted to using commitlint.config.cjs, but still prefer to have commitlint.config.ts in the long run.

Your Environment

Executable Version
commitlint --version 17.0.2
git --version 2.36.1
node --version 18.4.0

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 13
  • Comments: 28 (7 by maintainers)

Commits related to this issue

Most upvoted comments

We also have the same issue after migrating to ESM, can confirm that renaming commitlint.config.js to commitlint.config.cjs works as a temporary fix

@joberstein Very nicely done❤️ I tested commitlint.config files ending with .js and .ts and using the esm syntax export default {} and they all worked fine

I changed module.exports = to export default and it worked for me.

@SalahAdDin Thanks for your feedback. Let’s close this for now.

Thank you very much!

https://github.com/stylelint/stylelint/pull/7329 seems to have fixed the problem. I don’t know if it helps.

for now, we can just set a package resolution override to "cosmiconfig": "9.0.0-alpha.3"

@ZerdoX-x thanks for digging and confirming. If there’s nothing we can do on our side we could close this again.

Happy for a PR

The issue persists, not sure why this got closed. Adding support for .cjs is a different concern and not a solution to what this issue describes.

I have a commitlint.config.ts file with package.json containing "type": "module" and receive the exact error mentioned by the author.

(Renaming file to commitlint.config.cts works fine.)

“ts-node”: { “esm”: true },

It didn’t work for me.

This is my case, it is not a direct dependency, it is a commitlint dependency, and testing the package from CLI I’m getting the bug:

 echo "[PAP-2013] feat(lang): :arrow_up: add Polish language" | pnpm commit    

> react-ts-vite-template@0.1.0 commit /home/luisalaguna/Projects/react-ts-vite-template
> commitlint

/home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/ts-node@10.9.1_xplfzyzpegygk3axf4z63vz544/node_modules/ts-node/dist-raw/node-internal-errors.js:46
  const err = new Error(getErrRequireEsmMessage(filename, parentPath, packageJsonPath))
              ^
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/luisalaguna/Projects/react-ts-vite-template/commitlint.config.ts
require() of ES modules is not supported.
require() of /home/luisalaguna/Projects/react-ts-vite-template/commitlint.config.ts from /home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/cosmiconfig-typescript-loader@4.3.0_or2qrscwofpw4jwfbychkdzroy/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 /home/luisalaguna/Projects/react-ts-vite-template/package.json.

    at createErrRequireEsm (/home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/ts-node@10.9.1_xplfzyzpegygk3axf4z63vz544/node_modules/ts-node/dist-raw/node-internal-errors.js:46:15)
    at assertScriptCanLoadAsCJSImpl (/home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/ts-node@10.9.1_xplfzyzpegygk3axf4z63vz544/node_modules/ts-node/dist-raw/node-internal-modules-cjs-loader.js:584:11)
    at Object.require.extensions.<computed> [as .ts] (/home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/ts-node@10.9.1_xplfzyzpegygk3axf4z63vz544/node_modules/ts-node/src/index.ts:1610:5)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Function.Module._load (node:internal/modules/cjs/loader:878:12)
    at Module.require (node:internal/modules/cjs/loader:1061:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at loader (/home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/cosmiconfig-typescript-loader@4.3.0_or2qrscwofpw4jwfbychkdzroy/node_modules/cosmiconfig-typescript-loader/dist/cjs/index.js:59:22)
    at Explorer.loadFileContent (/home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/Explorer.ts:81:32)
    at Explorer.createCosmiconfigResult (/home/luisalaguna/Projects/react-ts-vite-template/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/Explorer.ts:89:36) {
  name: 'TypeScriptCompileError'
}
 ELIFECYCLE  Command failed with exit code 1.

Renaming commitlint.config.ts to commitlint.config.cts doesn’t work in my case:

/Users/user/path/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/ExplorerBase.ts:109
      throw new Error(
            ^
Error: No loader specified for extension ".cts"
    at Explorer.getLoaderEntryForFile (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/ExplorerBase.ts:109:13)
    at Explorer.loadFileContent (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/Explorer.ts:80:25)
    at Explorer.createCosmiconfigResult (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/Explorer.ts:89:36)
    at runLoad (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/Explorer.ts:104:33)
    at async cacheWrapper (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/cosmiconfig@7.1.0/node_modules/cosmiconfig/src/cacheWrapper.ts:13:18)
    at async loadConfig (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/@commitlint+load@17.3.0/node_modules/@commitlint/load/src/utils/load-config.ts:42:16)
    at async load (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/@commitlint+load@17.3.0/node_modules/@commitlint/load/src/load.ts:25:17)
    at async main (/Users/zerdox/p/zerdox/zerdox.dev/node_modules/.pnpm/@commitlint+cli@17.3.0/node_modules/@commitlint/cli/src/cli.ts:214:17)
husky - commit-msg hook exited with code 1 (error)

So currently commitlint doesn’t support .(ts|cts|mts|js|mjs) configs…

Neither to me.

It seems to be a bug related to ts-node, and it seems to be unsolved yet, right now I had to remove "type": "module" from package.json, but It should not be necessary.

Is there any development on this?

#3461 might help. It was just merged but not yet released. It would be pretty enough!

Thank you!

#3461 might help. It was just merged but not yet released.

Same problem and I’m agree with @shian15810 's described context.

Executable Version
commitlint 17.0.3
git 2.36.1
node 18.3.0

I also prefer ts extension for configure commitlint.