build(deps): bump commander from 14.0.3 to 15.0.0 (with jest ESM transform fix) - #91
Merged
Conversation
commander 15 is ESM-only ("type": "module", was "commonjs") and requires
Node >=22.12.0. Both made it unmergeable before the Node 24 baseline
landed in #90.
Under ts-jest's CommonJS execution, importing an ESM-only package fails
with "SyntaxError: Cannot use import statement outside a module" — 28
suites failed to load on the original dependabot run. Adding commander
to the existing transformIgnorePatterns ESM allowlist (alongside
p-limit, chalk, chokidar et al.) lets ts-jest transform it.
Verified on Node 24.18.0: 231 suites / 5493 tests pass, zero failures.
Supersedes the original dependabot branch for #83; the bump is
dependabot's, the jest transform fix is the additional work needed.
This was referenced Jul 27, 2026
sjsyrek
added a commit
that referenced
this pull request
Jul 27, 2026
The watchAndSync block intermittently failed CI on unrelated dependency PRs (#81 Jun 30 Node 22, #91 and #93 Jul 27 Node 24), always as a 10s test timeout and never as an assertion, hitting a different test each time. Both #81 and #91 passed on plain re-run with no code change. Three changes, in order of importance: 1. jest.setTimeout(30_000) for the block. The suite runs in ~1.8s locally but was observed at 10.8-10.9s on GitHub runners with 232 suites competing for ~4 cores — i.e. sitting on the 10s default, which tipped an arbitrary test over each time. This is the headroom the block actually needed. 2. flushWatchSetup now waits for an observable readiness signal (mockWatcherOn having been called) instead of burning a fixed round count, then drains a settle budget. attachDebouncedWatchLoop calls watcher.on() in the same synchronous continuation as the process.on('SIGINT') registration, so listeners-attached implies the handler each test uses for shutdown is registered. A fixed count could under-wait; this cannot. On a genuine stall it throws with the pending state instead of timing out mutely. 3. Settle rounds 250 -> 25. Every test in the block passes with as few as 5 (measured), so 25 keeps a 5x margin. On method: the historical escalation was 20 -> 50 -> 250 rounds, each assuming the budget was too small. Suite duration is flat across 250/25/5 rounds, so widening it could never have worked. Four further hypotheses were tested and disproven — slow sweepStaleBackups I/O (its projectRoot '/test' does not exist, so readdir ENOENTs immediately), a hang in controller.shutdown() (microtask-only), expensive flush rounds (0.00ms per 250), and CPU contention (old code passed 12/12 under 16 spinners on 11 cores). Details in bead sync-94ua. Honest limitation: the flake could not be reproduced locally — ~58 runs across five contention profiles (CPU, I/O+CPU, full-suite, starved budget) produced one failure whose identity was lost. So this targets the signature the evidence supports rather than a reproduction, and the new diagnostic ensures the next occurrence identifies itself. Verified: 49 tests in the block pass; 20/20 under combined I/O and CPU contention; lint, type-check, and 5501 tests green on Node 24.18.0.
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.
Summary
Completes the
commander14.0.3 → 15.0.0 bump that #83 could not land on its own. Supersedes #83 — the dependency bump is dependabot's; this adds the one change needed to make it pass.Why #83 failed
commander 15 changed two things that mattered:
commonjsmodule(ESM-only)engines.node>=22.12.0Under ts-jest's CommonJS test execution, importing an ESM-only package produced:
That failed 28 suites at load time — note the original run reported
5105 passed, 0 failed, because nothing got as far as asserting.The
enginesrequirement also made it genuinely unmergeable until the Node 24 baseline landed in #90.Changes Made
package.json/package-lock.json—commander^14.0.3→^15.0.0jest.config.js— addedcommanderto the existingtransformIgnorePatternsESM allowlist, alongsidep-limit,yocto-queue,fast-glob,chalk,chokidar,readdirp:CHANGELOG.md—### Changedentry underUnreleasedNo source changes. commander 15's API is compatible with our usage; only the test harness needed adjusting. This follows the project's stated policy of refactoring for ESM rather than pinning back to avoid it.
Test Coverage
No new tests. Verified on Node 24.18.0:
Backward Compatibility
✅ No CLI behaviour change — argument parsing, help output, and exit codes are unaffected; the full integration and e2e suites pass unmodified.
⚠️ Raises the effective floor to Node ≥22.12.0 via commander's own
engines. Already satisfied by the Node 24 CI baseline, andengines.nodein this package is bumped to>=24separately as part of the v2.0.0 work.❌ Breaking changes: none.
Size: Small ✓
Three files; one dependency bump and one regex addition.
Closes #83.