-
-
Notifications
You must be signed in to change notification settings - Fork 20
Convert codebase from CommonJS to ESM #134
Copy link
Copy link
Open
Description
Background
Several dependencies have moved to ESM-only (isbinaryfile, readdirp v5). Currently we work around this with manual mock factories and pinned versions. A full ESM conversion would unblock these upgrades and align with the Node.js ecosystem direction.
Scope
Source files (low effort)
| File | Changes needed |
|---|---|
package.json |
Add "type": "module" |
app.js |
Convert 16 require() → import, add __dirname polyfill (3 usages), handle JSON import for package.json, restructure chained patterns like require('socket.io')(http) |
lib/utils.js |
Move 2 lazy requires to top-level imports, module.exports → named export |
Test files (high effort)
| File | Difficulty | Notes |
|---|---|---|
jest.config.js |
Trivial | Rename to .cjs |
basic.test.js |
Easy | 1 require, no mocks |
lib-utils.test.js |
Easy | 1 require, no mocks |
functional.test.js |
Easy | 3 requires, no mocks |
tests/setup.js |
Medium | require.cache/require.resolve has no ESM equivalent — needs restructuring |
app.test.js |
Hard | 6 jest.mock() calls → jest.unstable_mockModule() + async restructuring |
utils.test.js |
Hard | 3 jest.mock() calls → same |
routes-simple.test.js |
Hard | 5 jest.mock() calls + 1 __dirname usage |
Totals
| Category | Count | Effort |
|---|---|---|
Source require() conversions |
18 | Low — mechanical |
__dirname polyfills |
4 | Trivial |
module.exports → export |
2 | Trivial |
JSON import (package.json) |
1 | Trivial |
jest.mock() rewrites |
14 across 3 files | High — each needs manual restructuring |
| Docker/build changes | 0 | None |
Key considerations
jest.mock()is the main pain point. It's a CJS-only synchronous hoisting trick. In ESM, it becomesjest.unstable_mockModule()which is async and still marked unstable in Jest 30.- Alternative approach: Keep test files as
.cjs(rename.test.js→.test.cjs) while converting only source code to ESM. This sidesteps the jest.mock problem entirely and tests keep working as-is. - Dependency upgrades unblocked:
readdirpv5 (ESM-only, also removes.promise()API — one call site atapp.js:186needs async iteration),isbinaryfile(ESM-only), and optionallynode-fetchv3 (or drop it for Node.js built-infetch). - No Dockerfile or shell script changes needed.
Suggested approach
- Add
"type": "module"topackage.json - Convert
lib/utils.js(simplest source file) - Convert
app.js(add__dirnamepolyfill, convert imports, handle JSON import) - Rename
jest.config.js→jest.config.cjs - Rename test files to
.test.cjsto preserve existing mock patterns (or convert tojest.unstable_mockModule()if it has stabilized by then) - Convert
tests/setup.js— replacerequire.cachepattern - Upgrade blocked dependencies:
readdirpv5,isbinaryfilelatest - Consider dropping
node-fetchfor built-infetch(Node.js 18+)
Related PRs
- Update dependency readdirp to v5 #120 —
readdirpv5 upgrade (blocked by ESM) - Fix test suite crashes from nock v14 and ESM incompatibility #132, Fix ESM parse error for isbinaryfile mock in tests #133 —
isbinaryfileESM mock workarounds
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels