Skip to content

fix: dist 产物 ESM require 崩溃 + dsh-qaq 插件零运行时依赖 - #1

Open
Townrain wants to merge 1 commit into
WTStarMark:mainfrom
Townrain:fix/esm-bundle-and-plugin-deps
Open

fix: dist 产物 ESM require 崩溃 + dsh-qaq 插件零运行时依赖#1
Townrain wants to merge 1 commit into
WTStarMark:mainfrom
Townrain:fix/esm-bundle-and-plugin-deps

Conversation

@Townrain

Copy link
Copy Markdown

背景

在 Windows + Node 24 上实际部署时发现两个「开箱即崩」的缺陷,均会阻断正常的本地部署流程。两处修改均经过真实验证。

修复 1:pnpm build 产物启动即崩溃

dist/qaq.mjs 在 Node 24 下启动立刻抛错:

Error: Dynamic require of "events" is not supported
    at node_modules/.pnpm/ws@8.21.3/node_modules/ws/lib/websocket.js

原因:esbuild 把 CJS 依赖 ws 打进 ESM 产物后,ws 内部对 Node 内置模块(events/stream 等)的 require() 落到 esbuild 生成的 __require 帮助器上,在 ESM 作用域里没有 require 可用,直接抛错。测试套件从未暴露这个问题——pnpm smoke 走的是 tsx src/cli.ts 源码头,从不执行 dist 产物,而 bin/qaq.mjs 与 .cmd 启动器优先用 dist。

修复:构建命令加 esbuild banner,用 createRequire(import.meta.url) 在产物顶层提供 requirepackage.json)。

修复 2:qaq install-plugin 可能弄崩它要守护的启动

插件 packages/dsh-qaq 在运行时 import '@deepseek-ai/dsh-home-paths'。但插件是通过 junction 链接挂进 profile 的(目录在 QAQ 仓库内,不在 DSH 树里),裸标识符解析会沿着 QAQ 仓库的 node_modules 向上找——那里永远不会包含 @deepseek-ai/*(pnpm 布局下实测解析失败)。结果是:下次启动时插件 entry 加载失败,造成它要防的红屏本身。

修复:把 resolveDshHome(语义与 DSH 的 @deepseek-ai/dsh-home-paths 完全一致:DSH_HOME 非空优先、否则 ~/.dsh)内联进插件,并移除该 peer 依赖——插件变为零运行时依赖(产物仅 import Node 内置模块),junction 挂载后不可能因解析失败破坏 boot。lib/index.js 已同步重建并提交。

验证

  • pnpm test:53/53 全部通过
  • pnpm buildnode dist/qaq.mjs status / --help 正常运行
  • 插件从 junction 位置独立 import 成功(导出 apply, name
  • 隔离 DSH_HOME 下调用 apply() 端到端验证:正确写入 latest-good + history/<ts> + manifest(profile 正确)
  • 挂载过程中 cordis.patch.yml(用户 patch 层)保持不被触碰

…time-dependency

Two deployment-blocking bugs found while deploying on Windows/Node 24:

1. `pnpm build` output (dist/qaq.mjs) crashed immediately on launch with
   "Dynamic require of \"events\" is not supported": esbuild bundles the CJS
   `ws` dependency into ESM output, and ws's internal require() calls to
   node builtins (events/stream) hit esbuild's __require shim, which throws
   in ESM scope. The test suite never caught this because it runs the source
   through tsx, never the dist bundle. Fix: add an esbuild banner that
   defines `require` via createRequire(import.meta.url).

2. `qaq install-plugin` could break the very boot it guards: the plugin
   imported @deepseek-ai/dsh-home-paths at runtime, but the plugin is mounted
   into a profile via a junction pointing outside the DSH tree, and bare
   specifiers resolve up the QAQ repo's node_modules (which never contains
   @deepseek-ai) — so the plugin entry would fail to load on the next boot.
   Fix: inline resolveDshHome (DSH_HOME or ~/.dsh, identical semantics to
   the DSH package) so the plugin has zero runtime dependencies. The rebuilt
   lib/index.js is committed alongside.

Verified: 53/53 unit tests pass; dist/qaq.mjs runs (status/help); plugin
imports cleanly from the junction location and snapshots latest-good +
history correctly in an isolated DSH_HOME.
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.

1 participant