Skip to content

Publish dual ESM and CommonJS outputs#128

Open
Fryuni wants to merge 8 commits into
masterfrom
esm-migration
Open

Publish dual ESM and CommonJS outputs#128
Fryuni wants to merge 8 commits into
masterfrom
esm-migration

Conversation

@Fryuni

@Fryuni Fryuni commented Jul 1, 2026

Copy link
Copy Markdown
Member

What Changed

  • Migrated the package to ESM with type: "module", tsup builds, and dual import/require entry points for ESM and CommonJS consumers.
  • Added export mappings for the root package and existing subpath imports so package consumers can continue resolving generated JS and type declarations.
  • Updated Jest, ESLint, README, and package-contract verification to match the new ESM build and test setup.

Risk Assessment

⚠️ Medium: The review found no substantiated material issues, but the change is a packaging/build-system and ESM/CJS migration that affects published entry points and release behavior.

Testing

The first Jest baseline run failed because the ESM test environment did not expose the global jest; after adding a test-only setup file, the full Jest suite passed, the package build/export contract passed, and a manual consumer-style ESM/CJS import check produced evidence showing the expected cache exports and methods are usable.

Evidence: ESM and CJS package consumer import transcript

{ "esm": { "inMemory": {"exportType": "function", "hasGet": true, "hasSet": true, "hasDelete": true}, "noop": {"exportType": "function", "hasGet": true, "hasSet": true, "hasDelete": true} }, "cjs": { "inMemory": {"exportType": "function", "hasGet": true, "hasSet": true, "hasDelete": true}, "noop": {"exportType": "function", "hasGet": true, "hasSet": true, "hasDelete": true} } }

{
  "esm": {
    "inMemory": {
      "exportType": "function",
      "hasGet": true,
      "hasSet": true,
      "hasDelete": true
    },
    "noop": {
      "exportType": "function",
      "hasGet": true,
      "hasSet": true,
      "hasDelete": true
    }
  },
  "cjs": {
    "inMemory": {
      "exportType": "function",
      "hasGet": true,
      "hasSet": true,
      "hasDelete": true
    },
    "noop": {
      "exportType": "function",
      "hasGet": true,
      "hasSet": true,
      "hasDelete": true
    }
  }
}

Pipeline

Updates from git push no-mistakes

⏭️ **intent** - skipped

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 3 issues found → auto-fixed ✅
  • 🚨 tsup.config.ts:19 - The old build used tsc -p tsconfig.build.json to emit declarations, but the new tsup config only builds JS and never enables declaration output while package.json points types/export type conditions at build/index.d.ts and build/index.d.cts; published TypeScript consumers will resolve to files that are not produced.
  • ⚠️ package.json:26 - Adding an exports map with only "." removes previously publishable subpath entry points such as @croct/cache/inMemory that existed because the old tsc build emitted every source module and published without an exports map; existing deep-import consumers will now fail with package subpath export errors unless this is an intentional breaking release.
  • ⚠️ README.md:223 - The README now tells maintainers to run npm run test:package, but package.json does not define that script, so the documented package-contract verification command fails immediately.

🔧 Fix: Restore package contract exports
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • npm test -- --runInBand (initial run exposed ESM Jest global setup failure)
  • Added test/setup-jest.mjs and referenced it from jest.config.mjs so existing tests can use jest.fn/jest.spyOn in ESM mode
  • npm test -- --runInBand
  • npm run test:package
  • node --input-type=module -e "import {createRequire} from 'node:module'; import {InMemoryCache as EsmInMemoryCache} from '@croct/cache/inMemory'; import {NoopCache as EsmNoopCache} from '@croct/cache'; const require = createRequire(import.meta.url); const {InMemoryCache: CjsInMemoryCache} = require('@croct/cache/inMemory'); const {NoopCache: CjsNoopCache} = require('@croct/cache'); const describeCache = Cache => ({exportType: typeof Cache, hasGet: typeof new Cache().get === 'function', hasSet: typeof new Cache().set === 'function', hasDelete: typeof new Cache().delete === 'function'}); console.log(JSON.stringify({esm:{inMemory:describeCache(EsmInMemoryCache), noop:describeCache(EsmNoopCache)}, cjs:{inMemory:describeCache(CjsInMemoryCache), noop:describeCache(CjsNoopCache)}}, null, 2));" > /tmp/no-mistakes-evidence/01KWFDTZK94WTS2XEYQ8S5JR56/package-consumer-transcript.json
  • Removed generated build/ and coverage/ directories after verification
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@Fryuni Fryuni requested review from a team as code owners July 1, 2026 18:35
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

👋 @Fryuni

Thanks for your contribution!

The approval and merge process is almost fully automated 🧙

Here's how it works:

  1. You open a new pull request
  2. Automated tests check the code
  3. Maintainers review the code
  4. Once approved, the PR is ready to merge.

👉 Omit the extended description
Please remove the commit body before merging the pull request.
Instead, include the pull request number in the title to provide the full context
about the change.

☝️ Lastly, the title for the commit will come from the pull request title. So please provide a descriptive title that summarizes the changes in 50 characters or less using the imperative mood.

Happy coding! 🎉

@Fryuni Fryuni added the maintenance Housekeeping label Jul 1, 2026
This reverts commit 842b8c8.

Revert "no-mistakes: apply CI fixes"

This reverts commit d7349a1.

Revert "no-mistakes: apply CI fixes"

This reverts commit e3ead78.
@Fryuni Fryuni changed the title feat: publish dual ESM and CommonJS outputs Publish dual ESM and CommonJS outputs Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance Housekeeping

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant