feat(plugin-inventory): offline bundle and pnpm plugin install for the desktop
Adds an install surface to the plugin-inventory gateway: availableBundles lists the curated offline-installable optional bundles (AVAILABLE_BUNDLES); install composes an offline bundle into the profile's dsh.profile.bundles, or for a registry spec runs pnpm against the writable profile via the bundled Node and a vendored pnpm (gated behind the dshAllowPluginInstall context flag, set only by the desktop boot); uninstall removes a bundle layer. The reconcile logic from `dsh plugin add` moves into app-boot as shared helpers. The desktop vendored pnpm into the harness and sets the allow-install env; the plugin-list SPA gains an installable-bundles section. Tests cover the guard, install helpers, and the SPA section at 100% host coverage. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -43,4 +43,15 @@ if (!existsSync(nodeBin)) throw new Error(`node executable not found: ${nodeBin}
|
||||
cpSync(nodeBin, join(out, 'bin/node'))
|
||||
chmodSync(join(out, 'bin/node'), 0o755)
|
||||
|
||||
// Vendor pnpm so the packaged app can install third-party plugins without pnpm
|
||||
// on the target machine. npm ships with Node, so use it on the build machine
|
||||
// (which has network); a failure only disables registry install, never the
|
||||
// offline bundle install, so warn rather than abort.
|
||||
try {
|
||||
execFileSync('npm', ['install', '--prefix', join(out, 'pnpm'), 'pnpm@11.7.0'], { stdio: 'pipe' })
|
||||
console.log('vendored pnpm into harness')
|
||||
} catch {
|
||||
console.warn('could not vendor pnpm; registry plugin install will be unavailable in the packaged app')
|
||||
}
|
||||
|
||||
console.log(`assembled self-contained harness at ${out}`)
|
||||
|
||||
@@ -177,7 +177,8 @@ function startSession(): void {
|
||||
// Run the harness from its own root so relative path resolution is stable.
|
||||
cwd: harness,
|
||||
stdio: ['ignore', 'pipe', 'inherit'],
|
||||
env: { ...process.env, DSH_TELEMETRY_DISABLED: '1' },
|
||||
// The desktop is the trusted surface that opts into plugin install.
|
||||
env: { ...process.env, DSH_TELEMETRY_DISABLED: '1', DSH_ALLOW_PLUGIN_INSTALL: '1' },
|
||||
})
|
||||
let settled = false
|
||||
let buffered = ''
|
||||
|
||||
Reference in New Issue
Block a user