chore: run TypeScript scripts with node instead of tsx - #201
Merged
Merged
Conversation
Node 26 (this repo's engines.node floor) makes type stripping stable and default, so every script/CLI entry that used to run through tsx --tsconfig now runs as `node <file>.ts` directly, and tsx is dropped from devDependencies. Fixes required to make that work under Node's stricter, bundler-free resolution: - Root-level scripts (bench/*, release/*, build-sea) import workspace packages by bare specifier (`@be-music/json`, etc.); tsx resolved these via tsconfig paths, but node needs an actual node_modules link, so the root package.json now depends on every @be-music/* workspace package. - Node's type stripping rejects parameter properties as non-erasable syntax (ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX). Rewrote the 9 constructors that used them (RulesetGauge, LuaRuntimeOwner, and 7 player-web view classes) as plain field declarations + assignment; generated .d.ts constructor signatures are unchanged. - fengari-web ships a webpack UMD bundle whose module.exports is built at runtime, so Node's static cjs-module-lexer can't discover its named exports the way tsx's esbuild-based loader did. Switched lua.ts to a default import and updated the hand-written .d.ts to match. - audio-renderer's package.json advertised a `./triggers` subpath export that tsdown.config.ts never actually built (tsx's tsconfig paths quietly bypassed the gap by resolving straight to source). Added the missing tsdown entry so the built dist/ matches the declared exports. - Dropped the TSX_TSCONFIG_PATH env var the three worker-spawning helpers (node-ui-runtime, node-gameplay-runtime, bga-video) set for their child workers — it configured tsx's own tsconfig lookup, which no longer runs. The --conditions=source exec flag stays: it's Node's own flag and still lets an in-source run resolve workspace packages via their exports 'source' condition. Verified: full pnpm run build/lint/typecheck/test green, plus manual smoke tests of every converted entry point (parser/stringifier/ audio-renderer/editor CLIs, all player-tui commands including a real TUI session under a pseudo-tty, build-sea.ts, the root and per-package bench scripts, and both release scripts). Pre-existing bug found in passing (not fixed, out of scope): packages/ beatoraja-skin/scripts/bench.ts is referenced by its package.json but has never existed in git history. CI never invokes it (only the root bench script, which enumerates all packages independently), so it's dead outside manual `pnpm --filter @be-music/beatoraja-skin run bench`.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
be-music-player-demo | eea6ba7 | Commit Preview URL Branch Preview URL |
Sep 06 2026, 07:07 AM |
The CI benchmark job installs dependencies but never runs pnpm run build, so the previous commit's dist-only resolution broke it: node scripts/bench/exports.ts couldn't find @be-music/json/dist/ index.js because nothing had built it yet. The same gap silently broke every dev/bench/playlog/diag:* command run without a prior build too — tsx never had this problem because its tsconfig paths resolved straight to source. Every workspace package's exports already carries a "source" condition pointing at the .ts file (used by tsx before this migration), so passing Node's own --conditions=source flag to every node-invoked script/CLI restores that behavior without needing a build first. Applied to every package.json script that runs a .ts entry point, plus the two CI workflow steps that call node directly (build-sea.ts, the two release scripts). Resolving straight to source instead of dist surfaced two more parameter-property constructors that a single-line grep missed because their argument lists span multiple lines (PlaylogSimulation, BeatorajaSceneBgmPlayer) — a proper paren-depth-aware rescan confirms these were the last two. Rewrote them the same way as the previous commit's nine. Verified by fully cleaning dist/, doing a frozen-lockfile install with no build step (matching the CI benchmark job exactly), and re-running every entry point that failed before: root and per-package bench, all player-tui commands including a real TUI session under a pseudo-tty, and both SEA builds. Then rebuilt normally and re-ran the full build/lint/typecheck/test suite green.
Exports Benchmark
Summary
Top Regressions
Top Improvements
|
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.
Node 26 (this repo's
engines.nodefloor) makes type stripping stable and default, so every script/CLI entry that used to run throughtsx --tsconfig ...now runs asnode <file>.tsdirectly, andtsxis dropped fromdevDependencies.Fixes required to make that work under Node's stricter, bundler-free resolution
scripts/bench/*,scripts/release/*,scripts/build-sea.ts) import workspace packages by bare specifier (@be-music/json, etc.).tsxresolved these viatsconfig.typecheck.jsonpaths, butnodeneeds an actualnode_moduleslink, so the rootpackage.jsonnow depends on every@be-music/*workspace package.ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX). Rewrote the 9 constructors that used them (RulesetGauge,LuaRuntimeOwner, and 7player-webview classes) as plain field declarations + assignment; generated.d.tsconstructor signatures are unchanged.fengari-webships a webpack UMD bundle whosemodule.exportsis built at runtime, so Node's staticcjs-module-lexercan't discover its named exports the waytsx's esbuild-based loader did. Switchedlua.tsto a default import and updated the hand-written.d.tsto match.audio-renderer'spackage.jsonadvertised a./triggerssubpath export thattsdown.config.tsnever actually built (tsx's tsconfig paths quietly bypassed the gap by resolving straight to source). Added the missingtsdownentry so the builtdist/matches the declared exports.TSX_TSCONFIG_PATHenv var the three worker-spawning helpers (node-ui-runtime,node-gameplay-runtime,bga-video) set for their child workers — it configuredtsx's own tsconfig lookup, which no longer runs. The--conditions=sourceexec flag stays: it's Node's own flag and still lets an in-source run resolve workspace packages via theirexports"source"condition.Testing
pnpm run build/lint/typecheck/testgreen.parser/stringifier/audio-renderer/editorCLIs, allplayer-tuicommands including a real TUI session under a pseudo-tty (script),build-sea.ts, the root and per-packagebenchscripts, and bothreleasescripts.Pre-existing bug found in passing (not fixed, out of scope)
packages/beatoraja-skin/scripts/bench.tsis referenced by itspackage.jsonbut has never existed in git history. CI never invokes it (only the root bench script, which enumerates all packages independently), so it's dead outside a manualpnpm --filter @be-music/beatoraja-skin run bench.🤖 Generated with Claude Code