Repository navigation
fix(desktop): resolve the packaged pnpm entry from app.asar.unpacked - #830
Open
eatmoreduck wants to merge 1 commit into
Open
eatmoreduck wants to merge 1 commit into
eatmoreduck wants to merge 1 commit into
Conversation
Every plugin-market install fails in the packaged app with spawn ENOTDIR: both pnpm entry resolutions (the desktop main process that injects DSH_DESKTOP_PNPM_ENTRY, and the market installer's resolvePnpmEntry that writes the .desktop-bin shims) return the app.asar member spelling. Electron's asar-aware fs validates it, but pnpm is executed by node-mode children that cannot read archive members, and the OS answers ENOTDIR because app.asar is a regular file. The build now unpacks node_modules/pnpm (it has no external dependencies, so the copy is self-contained) and both resolvers rewrite the archive segment to its app.asar.unpacked sibling — the same rule node-pty, ripgrep, and the Office engine already follow. Development installs carry no archive segment and are unchanged; a build without the unpacked copy surfaces a missing-entry error at resolution instead of a cryptic spawn failure. Fixes dataelement#829
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.
Fixes #829.
What
Every plugin-market install fails in the packaged app with
{"error":"spawn ENOTDIR"}. Both pnpm entry resolutions hand out anapp.asarmember path:src/main/index.tsbundledPnpmEntryPath()builds<resources>/app.asar/node_modules/pnpm/bin/pnpm.cjsand injects it asDSH_DESKTOP_PNPM_ENTRY;packages/dsh-desktop-market-installer/index.jsresolvePnpmEntry()returns the same spelling for the.desktop-binshims.Electron's asar-aware
fsvalidates those paths, but pnpm is executed by node-mode children (ELECTRON_RUN_AS_NODE=1— the Harness hand-off viabuildPackagedPnpmInvocation, and the shims) that cannot read archive members. The OS seesapp.asaras a regular file, so traversingapp.asar/node_modules/...fails withENOTDIR— exactly the reported error, for every install, on every platform.The comment above
bundledRuntimeRoot()already states the design — "native files the OS executes are unpacked and reached through their own resolution (node-pty, ripgrep, and the Office engine hook)" — pnpm was missing from that list.Change
package.json:asarUnpackgainsnode_modules/pnpm/**/*. pnpm has zero external dependencies (bin/pnpm.cjs→ the self-contained 8.6 MBdist/pnpm.cjsbundle), so the unpacked copy is self-contained; its nativereflink.*.nodefiles were already covered by**/*.{node}.src/main/bundled-pnpm.ts(new):unpackedBundledPath()rewrites theapp.asarpath segment to itsapp.asar.unpackedsibling (archive root or member,/or\);bundledPnpmEntryFrom()picks the entry from the unpackedbin.bundledPnpmEntryPath()insrc/main/index.tsnow delegates to it.resolvePnpmEntry()in the market installer rewritesdirname(require.resolve('pnpm'))the same way before probingbin/pnpm.{cjs,mjs}.Development installs carry no archive segment and are returned unchanged. A packaged build without the unpacked copy now surfaces a missing-entry miss at resolution time (downstream:
buildPackagedPnpmInvocationfalls back to PATH pnpm with its existing warning) instead of a cryptic spawn failure.Test plan
test/bundled-pnpm.test.ts: archive-member and archive-root rewrites (posix + Windows separators), non-archive passthrough, packaged-entry selection preferring the physical copy, and the fallback spelling when nothing physical exists.test/market-installer.test.js: a fixture tree with bothapp.asar/node_modules/pnpmandapp.asar.unpacked/node_modules/pnpm—resolvePnpmEntryreturns the unpackedpnpm.cjs. Verified red onorigin/main(returns the archive path) and green with the fix.test/market-installer.test.js+test/bundled-pnpm.test.ts+test/harness-node-entry.test.ts: 52 passed.npm run typecheck: clean.npm test): 2,853 passed / 3 failed — the three failures (office-runtimereal-subprocess cases ×2,security-policymedia grant,signed-test-buildgit-history tag walk) reproduce identically on a cleanorigin/maincheckout in this environment; none touch pnpm/asar resolution.package:macbuild with a plugin-market install — no signing/notarization environment here. The unit contracts above pin both resolutions; the asarUnpack glob is the same mechanism the Office engine already ships through.Notes
pnpm.cmd/pnpm) and the runner staging were already physical files and are unaffected.stagePnpmRunnercan still return an archive spelling if the copy fails, but that path was already best-effort and is not what 插件市场安装插件返回spawn ENOTDIR #829 exercises.