fix(shared): replace CJS require() with static ESM import for semver#1
Merged
Merged
Conversation
Dynamic require('semver') inside an ESM bundle causes a runtime error:
'Dynamic require of semver is not supported'
This affects all examples when run with tsx (Node ESM mode) because
tsup bundles the lazy-init require() into the .mjs output where CJS
require() is unavailable.
Fix: replace the lazy require() pattern with a static top-level import.
The lazy-loading was only an optimisation (defer cost until first call);
with a static import tsup can tree-shake unused exports and the bundle
resolves the module correctly in both CJS and ESM contexts.
Tested: pnpm build + tsx examples/agent-cli/index.tsx now starts correctly.
a50e48e to
47cb291
Compare
Contributor
Author
|
Hi @Minnzen, friendly nudge on this one. The change replaces the CJS |
Owner
|
Thanks for the catch and the clean fix, @EduardF1! 🙏 Verified locally, merging now |
Minnzen
added a commit
that referenced
this pull request
May 12, 2026
Same root cause as the 0.3.1 semver fix (#1): when a dependency is ESM-only ("type": "module" with no `require` export), our dual CJS+ESM build emits `require(...)` in the .js output that crashes on Node >= 20 with ERR_REQUIRE_ESM / ERR_PACKAGE_PATH_NOT_EXPORTED. The semver fix worked because semver ships dual CJS+ESM. ansi-tokenize and marked v17 are ESM-only, so a static import is not enough — they must be inlined into the CJS bundle via tsup's `noExternal`. Affected packages: - shared: @alcalzone/ansi-tokenize - ink-renderer: @alcalzone/ansi-tokenize - ui: marked Discovered by the new cross-env import smoke harness (next commit). All three now load cleanly under ESM, CJS, and tsx loaders.
Minnzen
added a commit
that referenced
this pull request
May 12, 2026
Adds tests/smoke/ — a tiny workspace package that imports each @claude-code-kit/* package via three loaders (ESM, CJS, tsx) and asserts named exports exist. Catches the regression class of: - 0.3.1 #1: `Dynamic require of "semver" is not supported` under tsx - the ansi-tokenize / marked CJS-require crash fixed in the previous commit (which this harness discovered) CI now runs a 3 x 3 matrix (Node 18 / 20 / 22 x esm / cjs / tsx) after the standard build job. `pnpm smoke` runs all three loaders locally; release:check now includes it. Layout: tests/smoke/ package.json # workspace deps + react + zod + tsx esm.mjs cjs.cjs tsx.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When running any example with
tsx(or any Node.js ESM loader), startup crashes immediately:Root cause:
packages/shared/src/semver.tsuses a lazy-init pattern withrequire("semver")(CJS). Whentsupbundles this into.mjsoutput for the ESM format, the dynamicrequire()call is preserved in the bundle butrequireis not available in ESM context — Node.js throws at runtime.Fix
Replace the lazy
require()with a static top-levelimport:The lazy-loading was purely a startup-cost optimisation; with a static import tsup can tree-shake unused exports and the module resolves correctly in both CJS and ESM bundles.
Testing
pnpm build npx tsx examples/agent-cli/index.tsx # now starts correctly ✅Tested on Node.js v24.15.0, pnpm v10.32.1, Windows.