Skip to content

Conversation

colinhacks
Copy link

@colinhacks colinhacks commented Aug 28, 2025

I hit against the fact that this package is CJS-only recently. I'm implementing a JavaScript action and the lack of ESM means a lot of code is ending up in my index.js bundle that should get treeshaken.

I built zshy as a build tool for Zod, and it's been working perfectly for a couple months now. It's designed for projects who are migrating from vanilla tsc, as it uses the actual TypeScript compiler (plus some TS Compiler API magic) to do ESM & CJS builds that respect your existing tsconfigs. You can see that there's pretty minimal changes here, but running npm run build now produces both ESM and CJS builds alongside each other in lib.

└── lib # generated
  ├── index.js # cjs (as before)
  ├── index.d.ts # cjs (as before)
  ├── index.mjs # esm (new)
  └── index.d.mts # esm (new)

I'd understand any concern around adding the new zshy dependency, but there's not a big learning curve. It's a comparatively thin layer over tsc, and still uses all the existing tsconfig settings (with some strategic overrides to do the ESM build, of course).

I admit I was inspired to do this because it solves my problem, and it's a demonstrative example of zshy. It also pains me to see a fully TypeScript project forgoing ESM when zshy makes it so easy. So no worries if you close this, but if you were already looking for an easy way to do ESM this is it!


PS zshy adds "exports" to package.json. This in turn makes it illegal for ESM-aware versions of Node to import from subpaths not listed in the "exports" map (e.g. import "@actions/core/lib/command.js"). That's the biggest potentially breaking change (though in general this is a good practice that promotes better encapsulation).

Closes #1770

@colinhacks colinhacks requested review from a team as code owners August 28, 2025 05:22
}

const signingCert = new X509Certificate(certBytes)
const signingCert = new X509Certificate(certBytes as Uint8Array)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were a couple tsc errors that stem from some incompatibilities in some recent versions of @types/node. Namely the addition of SharedArrayBuffer. This is a simple solution that is sound and works well. I think a "proper" solution would involve standardizing on a single version of @types/node throughout the monorepo (there are currently several different versions floating around) but I didn't want to touch too much code.

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.

Plan for transition to ESM?

2 participants