-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Which package?
Almost all @formatjs packages.
Describe the bug
When writing a library written in TypeSript, using jest and ts-jest,
we need to use extensionsToTreatAsEsm in indicates what files should be treated as ESM,
in order to use code such as import.meta
Here is an example:
// jest.config.js
/** @type {import('jest').Config} */
export default {
extensionsToTreatAsEsm: ['.ts'],
transform: {
"^.+\\.(ts|tsx|cts|mts)$": [
"ts-jest", {
"isolatedModules": true,
"useESM": true,
"diagnostics": {
"ignoreCodes": [
151001
]
}
}
]
}
}The problem with that is then jest will rely on the type field of the nearest package.json to determine if the file should be processed as ESM or not.
The @formatjs packages does not specify such field. Using @formatjs/intl as an example:
{
"main": "index.js",
"module": "lib/index.js",
"types": "index.d.ts",
"exports": {
".": {
"types": "./index.d.ts",
"import": "./lib/index.js",
"default": "./index.js"
},
"./package.json": "./package.json"
},
}This means ./lib/index.js (just like ./index.js) is treated as CJS thus getting `Unexpected token 'export' error:
.../node_modules/@formatjs/intl/lib/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export * from './src/types';To Reproduce
Codesandbox URL
Reproducible Steps/Repo
Here is a repro:
https://github.com/repobuddy/repobuddy/tree/formatjs-issue/testcases/jsdom-formatjs
Checkout the jsdom-formatjs branch, run:
pnpm i
cd testcases/jsdom-formatjs
pnpm testYou can see the error.
Then, you can comment out extensionsToTreatAsEsm: ['.ts'] in the jest.config.js and run pnpm test again, which you can see the import.meta error:
.../repobuddy/jest/testcases/jsdom-formatjs/src/feature.spec.ts:10
(0, globals_1.it)(`${(0, dirname_filename_esm_1.filename)(import.meta)} executed`, () => { });
^^^^
SyntaxError: Cannot use 'import.meta' outside a moduleExpected behavior
Able to run the code in such environment.
Screenshots
Desktop (please complete the following information):
- OS: macOS
Additional context
The fix is to add type: module to a package.json under lib folder:
- package.json // keep as-is
- index.js
- lib
- package.json // add this, containing `{ "type": "module" }`
- index.jsRecommended solution
Optimally, I would recommend completely separating cjs and esm output
What I normally do is organize the output like this:
- package.json
- cjs
- package.json // with `{}`, this will signal NodeJS to load code as CJS in this folder
- index.js
- esm
- index.jsand the package.json contains:
{ "main": "./cjs/index.js", "module": "./esm/index.js", "types": "./cjs/index.d.ts", "exports": { ".": { "import": { "types": "./esm/index.d.ts", "default": "./esm/index.js" }, "require": { "types": "./cjs/index.d.ts", "default": "./cjs/index.js" }, // optional "default": "./cjs/index.js" }, "./package.json": "./package.json" }, }