You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
benchmarker is published as CommonJS, and a growing part of its dependency tree has gone ESM-only. This is no longer a per-dependency annoyance — it is now blocking security and version updates outright.
Currently blocked Dependabot PRs, both failing for the same underlying reason:
chore(deps-dev): bump the chai-stack group across 1 directory with 5 updates #89 — chai stack. The locked versions all declare "type": "module": chai 6.2.2, chai-as-promised 8.0.2, sinon-chai 4.0.1. npm run build fails with widespread TS1479 — CommonJS test files cannot statically import ESM-only packages. Compilation fails before any test runs.
chore(deps): bump puppeteer from 22.15.0 to 25.3.0 #91 — puppeteer 22 → 25. v23 and v24 are actually clean against this codebase. v25 is ESM-only, and additionally raises Puppeteer's minimum Node to 22 while this package declares "node": ">20.0.0". There is also an API rename to absorb: PuppeteerNodeLaunchOptions (imported by src/shared/env.ts) is now LaunchOptions.
Until this is resolved, both PRs are unmergeable and the repo stays pinned on older majors.
Current state
package.json no "type" field → CommonJS
main dist/src/index.js
types dist/types/src/index.d.ts
exports "." and "./database", single "default" condition, no import/require split
engines node >20.0.0
tsconfig module: node16, target: es2020, outDir: ./dist
build tsc only (no bundler)
Worth noting the setup is already partly hybrid and inconsistent:
npm test runs with NODE_OPTIONS='--loader ts-node/esm --experimental-specifier-resolution=node'
.mocharc.yml requires ts-node/register (the CommonJS loader)
npm run test:system uses neither
So the test path already has one foot in ESM while the package contract is CommonJS.
Prior art: apex-parser
apex-parser has already been through this and is the reference implementation. It went dual-build rather than ESM-only, so existing CommonJS consumers kept working.
Dual output is produced by Rollup (npm/rollup.config.js) emitting both format: "es" → dist/esm/*.js and format: "cjs" → dist/cjs/*.cjs with preserveModules: true, plus separate .d.ts / .d.cts type outputs per condition.
Useful commits to follow:
ed23f8b — update inner npm package for ESM and exports
Problem
benchmarkeris published as CommonJS, and a growing part of its dependency tree has gone ESM-only. This is no longer a per-dependency annoyance — it is now blocking security and version updates outright.Currently blocked Dependabot PRs, both failing for the same underlying reason:
"type": "module": chai 6.2.2, chai-as-promised 8.0.2, sinon-chai 4.0.1.npm run buildfails with widespread TS1479 — CommonJS test files cannot statically import ESM-only packages. Compilation fails before any test runs."node": ">20.0.0". There is also an API rename to absorb:PuppeteerNodeLaunchOptions(imported bysrc/shared/env.ts) is nowLaunchOptions.Until this is resolved, both PRs are unmergeable and the repo stays pinned on older majors.
Current state
Worth noting the setup is already partly hybrid and inconsistent:
npm testruns withNODE_OPTIONS='--loader ts-node/esm --experimental-specifier-resolution=node'.mocharc.ymlrequirests-node/register(the CommonJS loader)npm run test:systemuses neitherSo the test path already has one foot in ESM while the package contract is CommonJS.
Prior art: apex-parser
apex-parserhas already been through this and is the reference implementation. It went dual-build rather than ESM-only, so existing CommonJS consumers kept working.Its
npm/package.jsonnow looks like:{ "type": "module", "main": "./dist/cjs/index.cjs", "module": "./dist/esm/index.js", "types": "./dist/types/index.d.ts", "exports": { ".": { "browser": { "types": "...", "default": "./dist/browser/apex-parser.mjs" }, "import": { "types": "./dist/types/index.d.ts", "default": "./dist/esm/index.js" }, "require": { "types": "./dist/types/index.d.cts", "default": "./dist/cjs/index.cjs" } } } }Dual output is produced by Rollup (
npm/rollup.config.js) emitting bothformat: "es"→dist/esm/*.jsandformat: "cjs"→dist/cjs/*.cjswithpreserveModules: true, plus separate.d.ts/.d.ctstype outputs per condition.Useful commits to follow:
ed23f8b— update inner npm package for ESM and exports802347a— update src to ES modules, fix strict type errors (PR [codex] Fix TypeScript 6 test runner #79)f375e4f— add CJS and browser builds via Rollup06949ca— use dynamicimport()in the check script for ESM compatibility (PR #106)That last one is the pattern for reaching an ESM-only dependency from a CommonJS context, which is directly relevant to the Puppeteer situation.
Scope
"type": "module"; decide dual-build vs ESM-only (dual recommended, per apex-parser)tscsetupexportswith properimport/requireconditions and matching.d.ts/.d.ctsmodule/moduleResolutionintsconfig.json__dirname,require,module.exports).mocharc.ymlts-node/registervs thets-node/esmloader innpm test, plus nycengines.nodeto>=22(required if Puppeteer 25 becomes a production dependency)Related