dsh-plugin-marketplace 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # dsh-plugin-marketplace
2
2
 
3
- Browse GitHub's dsh-plugin topic and manage plugins in the active DSH Web or Desktop profile. Version 0.5.1 requires DSH 0.2.0-rc.2 or later 0.2.x.
3
+ Browse GitHub's dsh-plugin topic and manage plugins in the active DSH Web or Desktop profile. Version 0.5.2 requires DSH 0.2.0-rc.2 or later 0.2.x.
4
4
 
5
5
  ```sh
6
- dsh plugin --profile desktop add dsh-plugin-marketplace@0.5.1
6
+ dsh plugin --profile desktop add dsh-plugin-marketplace@0.5.2
7
7
  ```
8
8
 
9
9
  Use the Desktop-provided dsh command (Application → Manage dsh Command); use --profile web for Web. Restart DSH, then open **Plugins → Installed → dsh-plugin-marketplace**.
package/README.zh.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # dsh-plugin-marketplace
2
2
 
3
- 浏览 GitHub 的 dsh-plugin 插件,同时管理当前 DSH Web / Desktop Profile 的插件。0.5.1 需要 DSH 0.2.0-rc.2 或后续 0.2.x。
3
+ 浏览 GitHub 的 dsh-plugin 插件,同时管理当前 DSH Web / Desktop Profile 的插件。0.5.2 需要 DSH 0.2.0-rc.2 或后续 0.2.x。
4
4
 
5
5
  ```sh
6
- dsh plugin --profile desktop add dsh-plugin-marketplace@0.5.1
6
+ dsh plugin --profile desktop add dsh-plugin-marketplace@0.5.2
7
7
  ```
8
8
 
9
9
  使用 Desktop 提供的 dsh 命令(应用 → 管理 dsh 命令);Web 改用 --profile web。重启后打开 **插件 → 已安装 → dsh-plugin-marketplace** 配置页。
package/VERIFICATION.md CHANGED
@@ -1,9 +1,11 @@
1
- # v0.5.1 validation — 2026-10-12
1
+ # v0.5.2 validation — 2026-10-12
2
2
 
3
- - Full npm test passed (25 tests), including pinned-version update arguments, structural YAML cleanup, failed operations, built-in protection, HMR and profile serialization.
3
+ - Full npm test passed (26 tests), including pinned-version update arguments, structural YAML cleanup, failed operations, built-in protection, HMR and profile serialization.
4
4
  - npm pack contents include management.js, runtime.js, client.js, locale metadata and bundle patch.
5
5
  - Installed tarballs through the real Desktop bundled CLI in an isolated profile and started them using the installed Desktop 0.2.0-rc.2 runtime.
6
6
  - Settings-channel refresh, invalid-package rejection, installation, update and uninstall of dsh-motion-ui all reached the expected real installed state.
7
7
  - Browser showed the active Desktop inventory, explicit npm-name input, update/uninstall controls and protected built-in bundles.
8
8
 
9
9
  - Automated Desktop package management closes stdin and sets CI mode. A previously hanging Soul installation completed successfully in 5 seconds with the corrected subprocess options.
10
+
11
+ - Subprocess capture uses null stdin and a bounded output drain after the official CLI exits. The six-plugin suite installation completed through the real Host request channel with the corrected packaged backend.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-marketplace",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Discover, install, update and uninstall plugins in the active DSH Desktop or Web profile.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -40,7 +40,7 @@
40
40
  }
41
41
  },
42
42
  "scripts": {
43
- "test": "node --test tests/settings-write-verify.test.mjs tests/runtime.test.mjs && node --test tests/plugin-page.test.mjs && node --test tests/locale.test.mjs && node --test tests/management.test.mjs"
43
+ "test": "node --test tests/settings-write-verify.test.mjs tests/runtime.test.mjs && node --test tests/plugin-page.test.mjs && node --test tests/locale.test.mjs && node --test tests/management.test.mjs && node --test tests/process-drain.test.mjs"
44
44
  },
45
45
  "files": [
46
46
  "locale",
package/runtime.js CHANGED
@@ -1,4 +1,4 @@
1
- import { execFile } from "node:child_process";
1
+ import { spawn } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
3
  import { createRequire } from "node:module";
4
4
  import { basename, dirname, join } from "node:path";
@@ -45,12 +45,12 @@ function cliEntry(runtime = process, exists = existsSync) {
45
45
  return candidates.find((candidate) => exists(candidate));
46
46
  }
47
47
 
48
- function runInstall(pkg, profile, runtime = process, execute = execFile, exists = existsSync) {
48
+ function runInstall(pkg, profile, runtime = process, execute = executeCaptured, exists = existsSync) {
49
49
  return runPlugin(["add", pkg], profile, runtime, execute, exists);
50
50
  }
51
51
 
52
52
  /** Execute package-manager arguments through the active host's official CLI. */
53
- function runPlugin(command, profile, runtime = process, execute = execFile, exists = existsSync) {
53
+ function runPlugin(command, profile, runtime = process, execute = executeCaptured, exists = existsSync) {
54
54
  const bin = cliEntry(runtime, exists);
55
55
  if (!bin) return Promise.resolve({ code: 1, stdout: "", stderr: "cannot locate the dsh CLI entry" });
56
56
  const args = [...(runtime.versions?.electron ? ["--expose-internals"] : []),
@@ -72,6 +72,34 @@ function runPlugin(command, profile, runtime = process, execute = execFile, exis
72
72
  });
73
73
  }
74
74
 
75
+ /** Capture diagnostics while giving pnpm an actual null input descriptor. */
76
+ function executeCaptured(executable, args, options, callback) {
77
+ const child = spawn(executable, args, { env: options.env, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
78
+ let stdout = "", stderr = "", failure, completed = false, drainTimer;
79
+ const timer = setTimeout(() => { failure = new Error("package operation timed out"); child.kill(); }, options.timeout);
80
+ function finish(error) {
81
+ if (completed) return;
82
+ completed = true; clearTimeout(timer); clearTimeout(drainTimer); callback(error, stdout, stderr);
83
+ }
84
+ const collect = (kind, data) => {
85
+ if (kind === "stdout") stdout += data; else stderr += data;
86
+ if (Buffer.byteLength(stdout) + Buffer.byteLength(stderr) > options.maxBuffer) {
87
+ failure = new Error("package operation output exceeded the capture limit"); child.kill();
88
+ }
89
+ };
90
+ child.stdout.on("data", data => collect("stdout", data));
91
+ child.stderr.on("data", data => collect("stderr", data));
92
+ child.on("error", finish);
93
+ const outcome = (code, signal) => failure || (code === 0 ? null : Object.assign(new Error(`package process exited (${signal || code})`), { code: code || 1 }));
94
+ // Descendants can retain inherited output handles after the official CLI
95
+ // exits. Bound the drain using its exit status; callers verify installed files.
96
+ child.on("exit", (code, signal) => { drainTimer = setTimeout(() => {
97
+ child.stdout.destroy(); child.stderr.destroy(); finish(outcome(code, signal));
98
+ }, 2000); });
99
+ child.on("close", (code, signal) => finish(outcome(code, signal)));
100
+ return child;
101
+ }
102
+
75
103
  /** Let the current HMR transaction finish, and retry transient write refusals. */
76
104
  async function writeState(settings, ns, patch, wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
77
105
  if (!settings) throw new Error("settings service unavailable");