feat(cli): launch dsh source through the tsx ESM hook

Node 26.0.0 removed --experimental-transform-types, so the native
source-launch chain cannot start anywhere on that line, and strip-only
mode rejects the vendored syntax (parameter properties, decorators,
runtime enums/namespaces). Switch bin/dsh, the root dsh/demo:tui/
demo:web scripts, and the Code Mode TUI overlay to node --import
tsx/esm: one launch vector across the whole engines range, ~0.4s faster
than the full tsx default (the CJS hook stays off; the graph is
ESM-only).

Delete scripts/tspath-loader.ts and apps/cli/src/tsconfig-paths-loader.ts:
tsx owns both transformation and tsconfig paths projection. Add
dsh-source-launch-smoke to the node-compat gates so the 22.19/26 matrix
executes the real launch vector; no CI job did, which is how the Node 26
breakage shipped silently.

Supersedes the native-TypeScript-source-launch Agent Note (new note
records the profiling evidence and rejected alternatives).
This commit is contained in:
kingwl
2026-07-29 13:15:24 +08:00
parent 6ff2c53661
commit aebf9c863b
18 changed files with 148 additions and 429 deletions

View File

@@ -26,6 +26,6 @@ Web 和无头界面启动同一个共享组合(`cordis.yml`):两者都将
ln -sf "$(pwd)/bin/dsh" ~/.local/bin/dsh
```
源码启动会通过 Node 的 `--experimental-transform-types` 运行 `apps/cli/src/bin.ts``scripts/tspath-loader.ts` 只会将 tsconfig 的 `paths` 映射投射到模块解析中,而不会转换代码。从 CLI 源码入口可达的每个模块都遵守 Node transform-types 契约:会被擦除的绑定使用 `import type`export 使用原生 ESM整个依赖图不含 TSX/JSX也不依赖仅由 tsx/esbuild 提供的转换。设置 `TSX_TSCONFIG_PATH`loader 会读取该路径(相对路径从调用方的 cwd 解析),否则读取仓库根 tsconfig它使用根目录的 TypeScript 开发工具,而不是应用依赖。仅当 workspace import 是包自身引用或已声明的运行时依赖时loader 才会映射该 import。TUI 配置通过 `examples/package.json` 解析裸插件,Web无头 `cordis.yml` 通过本包的 `dependencies` 解析;`verify-cordis-config` 要求每个已配置的裸插件均已声明,同时允许存在无关依赖。
源码启动会通过 tsx 的 ESM-only hook`node --import tsx/esm`运行 `apps/cli/src/bin.ts`,由它转换 TypeScript 并将根 tsconfig 的 `paths` 映射投射到模块解析中。不使用 Node 原生 TypeScript 模式Node 26 移除了 `--experimental-transform-types`,而 strip-only 模式无法接受源码图依赖的语法vendor 中的参数属性、装饰器、运行时 enum/namespace。CJS hook 保持关闭,因为源码图是纯 ESM而 CJS 解析器会增加约 0.4s 启动耗时。`bin/dsh``TSX_TSCONFIG_PATH` 固定到 checkout 的根 tsconfig使解析与 cwd 无关node-compat 门禁 `dsh-source-launch-smoke` 会在每条受支持的 Node 版本线上运行这一精确启动向量。tsx 应用 `paths` 映射时不检查依赖声明,声明完整性由静态门禁保障:TUI 配置通过 `examples/package.json` 解析裸插件Web无头 `cordis.yml` 通过本包的 `dependencies` 解析;`verify-cordis-config` 要求每个已配置的裸插件均已声明,同时允许存在无关依赖。
`pnpm run dsh` 从仓库根目录运行同一入口并直接转发参数,例如 `pnpm run dsh -p "task"`。构建形式(`lib/bin.js`,通过 `pnpm run build`)会在普通 Node 下启动同一配置。