Skip to content

feat: Publish dual CJS and ESM builds#84

Open
mykola-mokhnach wants to merge 2 commits into
masterfrom
esm
Open

feat: Publish dual CJS and ESM builds#84
mykola-mokhnach wants to merge 2 commits into
masterfrom
esm

Conversation

@mykola-mokhnach

@mykola-mokhnach mykola-mokhnach commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Publish both a CommonJS and an ESM build from the same TypeScript source (build/cjs and build/esm, each with its own package.json marker), so existing require('asyncbox') consumers keep working unchanged while new consumers can import it natively. Wired up via a conditional exports map (plus main/module/types fallbacks) and a postbuild script that stamps each output directory with its own {"type": ...}.
  • Adopt the lint/format/release tooling; swap ESLint + Prettier for oxlint/oxfmt via @appium/oxc-config, replace the hand-rolled .releaserc with @appium/semantic-release-config, and add .editorconfig.
  • Add cjs-interop.spec.cjs test that require()s the CJS build directly, so a future change that breaks CJS consumption (e.g. an ESM-only dependency bump) fails CI instead of only being caught by the ESM test suite.

Details

  • p-limit (a runtime dependency) is ESM-only. The CJS build's require('p-limit') works because it relies on Node's native require(esm) support, available on the versions already required by engines (^20.19.0 || ^22.12.0 || >=24.0.0). tsconfig.cjs.json uses moduleResolution: "Bundler" (paired with module: "CommonJS") so tsc can resolve p-limit's types, which only exist under its exports field with no top-level main/types.
  • tsconfig.json is now the shared base (no outDir) that tsconfig.esm.json (outDir: build/esm) and tsconfig.cjs.json (outDir: build/cjs) extend; it's also what editors/tsserver and oxlint's type-aware mode pick up by default.
  • Dropped the explicit typescript devDependency — @appium/tsconfig already pins and ships it as a dependency, so restating it here just risked drift.
  • Ran oxfmt over the existing source, which reordered imports (node builtins → third-party → relative, each group blank-line separated) to match the shared config's conventions — same reformatting appium-xcode#190 applied.

@mykola-mokhnach
mykola-mokhnach requested review from KazuCocoa and eglitise and removed request for eglitise July 25, 2026 13:27
Several Date.now()-based assertions in test/asyncbox.spec.ts asserted against
their exact theoretical floor/ceiling with zero slack, causing intermittent CI
failures under timer jitter (e.g. https://github.com/appium/asyncbox/actions/runs/30159766440).
Widen them to match the tolerance already used elsewhere in the same file.

Also move test/cjs-interop.spec.cjs out of the standalone smoke/ directory and
into test/, excluding it from the TypeScript project via tsconfig.json so it
isn't type-checked or duplicated into both build outputs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant