Skip to content

whitelist omits injector/package.json, so a whole-repo (github:) install never loads###白名单漏了 injector/package.json,导致从 github: 整仓安装后插件必然加载失败 #190

Open

Description

@lmbjzsq

Environment

  • DSH Desktop 0.2.0-rc.2 (Windows)
  • pnpm 11.7.0
  • Install command: dsh plugin --profile desktop add github:yjh051108/dsh-routing-suite

Symptom

The install itself exits 0 and the package does land in node_modules, but the plugin
never loads:

  • there is no loader entry for dsh-super-injector in the host
    (the dev_* tool family never appears)
  • the plugin market keeps showing "restart required", and restarting never clears it —
    the desired state is "on" while the composed state never contains it, so the
    difference can never be resolved

Root cause

The repository root package.json:

"main": "./injector/lib/index.js",
"files": [
  "injector/lib",
  "injector/scripts",
  "cordis.patch.yml",
  "LICENSE",
  "README.md",
  "README.en.md"
]

The files whitelist does not include injector/package.json. When pnpm installs
from a git source it packs the checkout according to that whitelist, so the file never
reaches node_modules.

injector/lib/index.js reads it at module top level:

const { version } = createRequire(import.meta.url)("../package.json");

which throws on load:

Error: Cannot find module '../package.json'
Require stack:
- C:\Users\<user>\.dsh\profiles\desktop\node_modules\@dsh-external\dsh-super-injector\injector\lib\index.js

Evidence

Contents of node_modules/@dsh-external/dsh-super-injector/ after the install:

injector/lib/              <- present (built index.js / client.js)
injector/scripts/          <- present
injector/cordis.patch.yml
injector/README.md
package.json
cordis.patch.yml
(injector/package.json is missing)

Reproduce by importing the entry point directly:

node -e "import('file:///.../injector/lib/index.js')"
-> MODULE_NOT_FOUND: Cannot find module '../package.json'

Suggested fix (any one of these)

  1. Add injector/package.json to the root files whitelist — smallest and most direct.
  2. Stop reading ../package.json at runtime in injector/lib/index.js — inline the
    version at build time, or use a module constant.
  3. Decouple the repo-root distribution entry from the injector/ sub-package. The root
    name/main currently point at the injector while the published artifacts are the
    sub-package's build output, which makes relative-path omissions like this easy to miss.

Note

The standalone dsh-super-injector release tarball
(dsh-external-dsh-super-injector-0.3.5.tgz) does not have this problem: its lib/
sits at the package root, so ../package.json resolves to the package-root
package.json and it loads correctly. The issue is specific to the whole-repo install
path. As a workaround, the injector is currently installed from that release tarball.

Activity

  1. reopened this on Oct 6, 2026
  2. dingdaoyi commented on Oct 22, 2026

    @dingdaoyi

    补一份 2026-10-22 的复现与已验证修法(macOS arm64 · DSH Desktop 0.2.1-rc.2 · pnpm 11.28.5)。

    两段式失败:pnpm 11 先拦构建脚本,放行后能装进去、但插件永远不激活

    ① allowBuilds 闸

    $ dsh plugin --profile desktop add github:yjh051108/dsh-routing-suite
    [ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED] The git-hosted package
    "@dsh-external/dsh-super-injector@0.3.3" needs to execute build scripts but is
    not in the "allowBuilds" allowlist.
    

    需要在 profile 的 pnpm-workspace.yaml 放行(key 是包名 + codeload tarball 的完整 URL 与 sha):

    allowBuilds:
      '@dsh-external/dsh-super-injector@https://codeload.github.com/yjh051108/dsh-routing-suite/tar.gz/195273352f23bff7f9023ebe2ec0cdbdf9c98f10': true

    ② 放行后 install 成功,但 entry import 抛错

    prepare 用 npx tsdown 正常构建出 injector/lib/,pnpm 退出码 0:

    + @dsh-external/dsh-super-injector 0.3.3
    

    启动日志(非致命,app 照常起,但插件全废):

    dsh: warning: 1 entry did not activate
    dsh-super-injector (@dsh-external/dsh-super-injector): failed to import: Error: Cannot find module '../package.json'
    Require stack:
    - .../node_modules/@dsh-external/dsh-super-injector/injector/lib/index.js
    

    ③ 包内容确认:安装后的 injector/ = README.md cordis.patch.yml lib scripts,缺 package.json;根 files 只列了 injector/lib、injector/scripts。

    已验证修法

    根 files 补一行 injector/package.json:

    # 修前
    $ npm pack --dry-run --ignore-scripts | grep -c 'injector/package.json'
    0
    # 修后
    $ npm pack --dry-run --ignore-scripts | grep -c 'injector/package.json'
    1
    

    端到端(临时 profile:dsh-base + dsh-web-app,同一 DSH 0.2.1-rc.2):

    装的产物 启动结果
    修前(0.3.3,git 装配) 1 entry did not activate + Cannot find module '../package.json'
    修后 tgz(本修法打包) 零 warning,dsh-super-injector 正常激活

    PR:#252 → #252

    这不是 DSH 版本不兼容

    同一台机器、同一 DSH 0.2.1-rc.2 上,dsh-super-injector v0.3.5 的 Release 预构建 tgz 启动零 warning、插件正常激活。所以 0.3.3 的失败纯属打包白名单,与宿主 API 变更无关。

    合并前的临时绕过(无 prepare、无 build 脚本、不受 allowBuilds 影响):

    dsh plugin --profile <p> add \
      https://github.com/yjh051108/dsh-super-injector/releases/download/v0.3.5/dsh-external-dsh-super-injector-0.3.5.tgz

    另外两点

  3. 0xJingwei commented on Oct 23, 2026

    @0xJingwei

    补充:已验证的无需上游修复的装法(&path:/injector)+ allowBuilds key 的更耐用写法

    先说明:根因(files 白名单漏 injector/package.json)已有 #106 / #134 / #163 / #190 与本 PR #252 覆盖,这里不重复报同一根因。补充的是两件目前没有记录、且能立刻让人装上的事实。

    环境

    • macOS arm64(Darwin),DSH Desktop 0.2.1-rc.2,profile desktop
    • pnpm 11.28.5(DSH 应用内置,runtime/primary-runtime/dependencies/pnpm)
    • 安装源:github:yjh051108/dsh-routing-suite#195273352f23bff7f9023ebe2ec0cdbdf9c98f10(= main HEAD 1952733,v0.3.3)

    两道闸都确认存在

    ① ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED,与 @dingdaoyi 在 #190 的记录一致。

    ② 放行后安装 exit 0,但 entry import 失败:Cannot find module '../package.json'(injector/lib/index.js:3154 的 createRequire(import.meta.url)("../package.json"))。

    补充 1:allowBuilds 用不带 sha 的仓库 URL 更耐用

    #190 里给的 key 是 codeload tarball 完整路径 + sha:

    allowBuilds:
      '@dsh-external/dsh-super-injector@https://codeload.github.com/yjh051108/dsh-routing-suite/tar.gz/1952733...': true

    这个 form 每次 pin 的 commit 一变就要改一次。pnpm 11 支持按仓库 URL(无 hash) 匹配 git 托管包,实测同样生效,且换 commit 不用改 key:

    # <profile>/pnpm-workspace.yaml
    allowBuilds:
      "@dsh-external/dsh-super-injector@git+https://github.com/yjh051108/dsh-routing-suite.git": true

    验证方式:用全新 store 目录强制真实下载 + prepare,排除 cache 复用造成的假成功。

    rm -rf /tmp/probe-a /tmp/store-a && mkdir -p /tmp/probe-a && cd /tmp/probe-a
    printf '%s\n' '{ "name": "probe-a", "private": true }' > package.json
    cat > pnpm-workspace.yaml <<'YAML'
    packages:
      - .
    nodeLinker: hoisted
    autoInstallPeers: false
    allowBuilds:
      "@dsh-external/dsh-super-injector@git+https://github.com/yjh051108/dsh-routing-suite.git": true
    YAML
    pnpm add "github:yjh051108/dsh-routing-suite#195273352f23bff7f9023ebe2ec0cdbdf9c98f10" --store-dir /tmp/store-a
    # -> + @dsh-external/dsh-super-injector 0.3.3
    # -> node_modules/@dsh-external/dsh-super-injector/injector/lib/{index.js,client.js} 已构建

    对照实验(同一台机、同一 pnpm):裸包名 key "@dsh-external/dsh-super-injector": true 不生效,仍报同一错误。所以必须是 包名@仓库URL 这一形态。

    补充 2:装进 profile 时用 &path:/injector,绕开第二道闸

    把 spec 指向子目录,pnpm 就把 injector/ 当作包根,../package.json 于是正确解析到 injector/package.json,不需要等合并 #252:

    dsh plugin --profile desktop add \
      "github:yjh051108/dsh-routing-suite#195273352f23bff7f9023ebe2ec0cdbdf9c98f10&path:/injector"

    实测结果(DSH Desktop 0.2.1-rc.2,dev_plugin_status 实读):

    - [active] dsh-super-injector (@dsh-external/dsh-super-injector)
        entry: .../profiles/desktop/node_modules/@dsh-external/dsh-super-injector/lib/index.js
    

    安装后的目录结构与 files 白名单无关(path: 形式按子包打包,天然含 injector/package.json):

    node_modules/@dsh-external/dsh-super-injector/
      package.json          <- 就是 injector/package.json
      cordis.patch.yml
      lib/{index.js,client.js}
      scripts/
    

    端到端复验(全新 store + 删掉 node_modules 后 --frozen-lockfile 重装,两次都通过):

    # 安装后落盘的 spec
    # github:yjh051108/dsh-routing-suite#1952733...&path:/injector
    
    rm -rf node_modules
    pnpm install --frozen-lockfile --store-dir /tmp/store-c
    node --input-type=module -e \
      "import('./node_modules/@dsh-external/dsh-super-injector/lib/index.js')
         .then(m=>console.log('IMPORT OK:',Object.keys(m).join(',')))"
    # -> IMPORT OK: Config,apply,inject,name

    注意 path: 形式仍然需要 allowBuilds(injector/package.json 自己也有 prepare):不放行时的报错会把 key 提示成 @dsh-external/dsh-super-injector@https://codeload.github.com/.../tar.gz/<sha>#path:/injector;但上面补充 1 那条不带 hash 的 key 对 path: 形式同样放行,可以只用一条。

    补充 3:DSH 插件管理器的「批准构建」按钮救不了这个 case

    我读了应用内 @deepseek-ai/dsh-plugin-manager 的实际实现(app.asar):

    • 待批准项来自 recordPendingBuilds(),它只从输出里匹配 /\bIgnored build scripts: (.+)/;
    • 失败分类的 build-blocked 也只匹配 /ERR_PNPM_IGNORED_BUILDS|Ignored build scripts/。

    ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 两者都不匹配,会被归到 unknown。所以从插件管理界面点安装,不会出现「允许构建脚本」入口,只能先手改 pnpm-workspace.yaml 再重试。这解释了为什么很多人卡在这一步,看起来像「点了没反应」。

    小结

    目的 做法
    现在就能装上且能加载 &path:/injector spec + 不带 hash 的 allowBuilds key
    等官方修 合并 #252(补 files)后,普通 github: spec 才可能一次装好
    更省事的长期方案 用独立仓 dsh-super-injector 的 v0.3.5 预构建 tgz,无 prepare、不受 allowBuilds 影响(此点 @dingdaoyi 已提)

    补一句取舍:path: 装法解决的是「加载」,装的仍是仓内 v0.3.3 的那份源码,不会带来 v0.3.5 修的内容。要 v0.3.5 还是走 tgz。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions