diff --git a/README.md b/README.md index 2b7e1c3..bb5e416 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ type ModuleOptions = { - `importMetaMain` (`shim`): gate `import.meta.main` with shimming/warning/error when Node support is too old. - `requireMainStrategy` (`import-meta-main`): use `import.meta.main` or the realpath-based `pathToFileURL(realpathSync(process.argv[1])).href` check. - `importMetaPrelude` (`auto`): emit a no-op `void import.meta.filename;` touch. `on` always emits; `off` never emits; `auto` emits only when helpers that reference `import.meta.*` are synthesized (e.g., `__dirname`/`__filename` in CJS→ESM, require-main shims, createRequire helpers). Useful for bundlers/transpilers that do usage-based `import.meta` polyfilling. -- `detectCircularRequires` (`off`): optionally detect relative static require cycles and warn/throw. +- `detectCircularRequires` (`off`): optionally detect relative static require cycles across `.js`/`.mjs`/`.cjs`/`.ts`/`.mts`/`.cts` (realpath-normalized) and warn/throw. - `detectDualPackageHazard` (`warn`): flag when `import` and `require` mix for the same package or root/subpath are combined in ways that can resolve to separate module instances (dual packages). Set to `error` to fail the transform. - `dualPackageHazardScope` (`file`): `file` preserves the legacy per-file detector; `project` aggregates package usage across all CLI inputs (useful in monorepos/hoisted installs) and emits one diagnostic per package. - `topLevelAwait` (`error`): throw, wrap, or preserve when TLA appears in CommonJS output. `wrap` runs the file body inside an async IIFE (exports may resolve after the initial tick); `preserve` leaves `await` at top level, which Node will reject for CJS. diff --git a/docs/roadmap.md b/docs/roadmap.md index cf3627b..da69df7 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -4,17 +4,12 @@ Status: draft ## Idiomatic Exports -Shipped: `idiomaticExports: 'safe'` is now the default for CJS → ESM, with fallback to the helper bag plus diagnostics when unsafe. Auto lifts simple `module.exports = { foo, bar }` object literals to idiomatic exports when safe. - -Next: - - Explore a true `'aggressive'` mode (mixed exports/module.exports, limited reassignments, identifier-safe computed keys) with guarded semantics and explicit diagnostics. - Consider a constrained ESM → CJS “pretty” path where live-binding and TLA semantics permit it. ## CLI -- Shipped parity CLI wrapping the core transform (targets, rewriteSpecifier, appendJsExtension/appendDirectoryIndex, detectCircularRequires, topLevelAwait, cjsDefault, diagnostics hooks, out/in-place) with stdin/stdout support, JSON/summary, and list/dry-run paths. -- Next: optional concurrency flag, `--watch` mode with minimal restarts, and a tiny stream type surface to keep test stubs and embedding clean. +- Optional concurrency flag, `--watch` mode with minimal restarts, and a tiny stream type surface to keep test stubs and embedding clean. - DX polish: keep help/examples in sync with tests; retain single-fixture CLI coverage unless new CLI-specific behaviors emerge (e.g., multi-ext glob ordering, large-input streaming), since transform semantics are already exercised in module fixtures. ## Tooling & Diagnostics @@ -24,5 +19,5 @@ Next: ## Potential Breaking Changes (flag/document clearly) -- Template literal specifier rewriting: if we ever default to skipping interpolated `TemplateLiteral` specifiers, it would change outputs. Current implementation is opt-in via `rewriteTemplateLiterals: 'static-only'` (non-breaking); future default flips would need a major/minor note. -- Cycle detection hardening: expanding extensions (.ts/.tsx/.mts/.cts) and normalize/realpath paths may surface new cycle warnings/errors, especially on Windows or mixed TS/JS projects. +- Template literal specifier rewriting: changing the default to skip interpolated template literals would be breaking. +- Cycle detection hardening: expanding scope (e.g., configurable roots, glob exclusions, or additional extensions) could alter diagnostics and should be flagged. diff --git a/package-lock.json b/package-lock.json index 8dfeb43..2417450 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@knighted/module", - "version": "1.4.0-rc.3", + "version": "1.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@knighted/module", - "version": "1.4.0-rc.3", + "version": "1.4.0", "license": "MIT", "dependencies": { "glob": "^13.0.0", diff --git a/package.json b/package.json index c12c7c8..4231640 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@knighted/module", - "version": "1.4.0-rc.3", + "version": "1.4.0", "description": "Bidirectional transform for ES modules and CommonJS.", "type": "module", "main": "dist/module.js", diff --git a/test/module.ts b/test/module.ts index e98309d..47121a7 100644 --- a/test/module.ts +++ b/test/module.ts @@ -1097,7 +1097,12 @@ describe('@knighted/module', () => { assert.equal(status, 0) const mod = requireCjs(outFile) - await delay(10) + /** + * In preserve mode the async body runs in an IIFE; require() returns before it resolves. + * Wait once for the event loop tick that resolves the TLA before asserting. + */ + await delay(50) + assert.equal(mod.value, 5) assert.equal(mod.default, 3) })