dsh-preview-market 0.1.0 → 0.1.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1
4
+
5
+ - Enable/disable installed preview plugins from the market when dsh-market is present (`/dsh-market/toggle`), with the current state read from `/dsh-market/installed`.
6
+ - Add a "Configure" entry per installed card that points to the child plugin's Settings → Plugins page.
7
+ - Without dsh-market, the toggle is disabled and the card explains where to manage it.
8
+
3
9
  ## 0.1.0
4
10
 
5
11
  - New vertical preview market plugin: catalog, installed inventory, Settings → Plugins tab.
package/README.md CHANGED
@@ -44,8 +44,26 @@ Settings → Plugins → Preview market (namespace `preview-market`):
44
44
  node --test test/*.test.js
45
45
  ```
46
46
 
47
+ Settings-tab end-to-end (requires a running host with the plugin installed):
48
+
49
+ ```sh
50
+ node scripts/e2e-settings.mjs --base http://127.0.0.1:<port> --token <token>
51
+ ```
52
+
53
+ Fallback install/copy check (requires a profile where one catalog entry is not installed):
54
+
55
+ ```sh
56
+ node scripts/e2e-fallback.mjs --base http://127.0.0.1:<port> --token <token>
57
+ ```
58
+
59
+ Toggle/configure check (requires dsh-market and an installed STL preview):
60
+
61
+ ```sh
62
+ node scripts/e2e-toggle.mjs --base http://127.0.0.1:<port> --token <token>
63
+ ```
64
+
47
65
  The client bundle is `lib/client.js` (classic `__ModuleLoader__.load` factory, no build step).
48
66
 
49
67
  ## Status
50
68
 
51
- `0.1.0` — catalog + installed inventory + settings tab. One-click install requires the package to be present in the connected dsh-market registry; otherwise use the copyable command. Enable/disable stays in **Settings → Plugins**.
69
+ `0.1.1` — catalog + installed inventory + Settings → Plugins tab + enable/disable through dsh-market. One-click install requires the package to be present in the connected dsh-market registry; otherwise use the copyable command. Configuration stays in each child plugin's own Settings → Plugins page.
package/VERIFY.md CHANGED
@@ -1,4 +1,4 @@
1
- # Verification record — dsh-preview-market 0.1.0
1
+ # Verification record — dsh-preview-market 0.1.1
2
2
 
3
3
  ## Unit tests (2026-10-23)
4
4
 
@@ -11,10 +11,45 @@
11
11
  | `test/installed.test.js` | profile `package.json` + `node_modules` inventory, missing profile, `profileContext` resolution |
12
12
  | `test/client.test.js` | bundle registers exactly one `settings.plugins.tab` entry with id `dsh-preview-market` |
13
13
 
14
+ ## Host / bundle smoke (2026-10-23, preview-test profile)
15
+
16
+ - Installed the packed tarball into a throwaway `preview-test` profile with `dsh plugin --profile preview-test add …`.
17
+ - `dsh --profile preview-test --dump-config` contains one `id: preview-market` row with `routeRoot: /api/preview-market`.
18
+ - The Web boot graph (`__DSH_BOOT__`) contains `dsh-preview-market` and injects `__DSH_PREVIEW_MARKET_CONFIG__`.
19
+ - The combo bundle URL returned **200** (16,213 B) and contains `settings.plugins.tab` + `dsh-preview-market`.
20
+
21
+ ## Settings tab e2e (2026-10-23, preview-test)
22
+
23
+ Installed `dsh-preview-market@0.1.0` plus `dsh-preview-media@0.1.4`, `dsh-preview-blender@0.1.0`, `dsh-preview-stl@0.1.0` into `preview-test`, started the Web host, and ran:
24
+
25
+ ```sh
26
+ node scripts/e2e-settings.mjs --base http://127.0.0.1:59003 --token <token>
27
+ ```
28
+
29
+ Result: **PASS** — opened Settings → Built-in plugins → Preview market and found the tab plus the three installed cards (`dsh-preview-media`, `dsh-preview-blender`, `dsh-preview-stl`). No page errors; the only console 404 is the expected `/dsh-market/status` probe when dsh-market is absent. Screenshot: `%TEMP%\dsh-preview-market-settings.png`.
30
+
31
+ ## Fallback install/copy e2e (2026-10-23, preview-test)
32
+
33
+ Removed `dsh-preview-stl` from `preview-test`, restarted the host, and ran:
34
+
35
+ ```sh
36
+ node scripts/e2e-fallback.mjs --base http://127.0.0.1:59004 --token <token>
37
+ ```
38
+
39
+ Result: **PASS** — the STL card showed `安装`; clicking it displayed `dsh plugin --profile preview-test add dsh-preview-stl@0.1.0` (dsh-market absent); the media card's copy button reported `命令已复制` and the clipboard held `dsh plugin --profile preview-test add dsh-preview-media@0.1.4`. No page errors. STL was reinstalled afterwards.
40
+
41
+ ## Toggle / configure e2e (2026-10-23, preview-test + dsh-market 1.67.0)
42
+
43
+ With dsh-market installed, ran:
44
+
45
+ ```sh
46
+ node scripts/e2e-toggle.mjs --base http://127.0.0.1:59006 --token <token>
47
+ ```
48
+
49
+ Result: **PASS** — the STL card showed `停用`; clicking it wrote `dsh-preview-stl` into `/dsh-market/installed`'s `disabled` list and showed `已切换,刷新页面后生效`; clicking `启用` removed it again. The media card's `配置` showed `在 设置 → 插件 → dsh-preview-media 配置。` No page errors; screenshot: `%TEMP%\dsh-preview-market-toggle.png`.
50
+
14
51
  ## Not yet verified live
15
52
 
16
- - The settings tab rendering inside the DSH Web client.
17
- - One-click install through dsh-market (requires the new packages in its curated registry).
18
- - Fallback command copy in a real browser.
53
+ - One-click install through dsh-market (requires the new packages in its curated registry; the market entries are scheduled for 2026-10-24).
19
54
 
20
- These are the next checks after the package is installed into a test profile.
55
+ This is the next check after the new market entries are accepted.
package/lib/client.js CHANGED
@@ -45,7 +45,15 @@ window.__ModuleLoader__.load({
45
45
  note: "安装/更新由 dsh-market 或 dsh CLI 完成;本页只做目录、状态与入口,不复制子插件代码。",
46
46
  version: "版本",
47
47
  notInstalled: "未安装",
48
- disabledHint: "启用/停用请到 设置 → 插件 列表。"
48
+ disabledHint: "启用/停用请到 设置 → 插件 列表。",
49
+ enable: "启用",
50
+ disable: "停用",
51
+ config: "配置",
52
+ configHint: "在 设置 → 插件 → {name} 配置。",
53
+ manageHint: "到 设置 → 插件 启用/停用。",
54
+ toggled: "已切换。",
55
+ toggleRefresh: "已切换,刷新页面后生效。",
56
+ toggleFailed: "切换失败"
49
57
  };
50
58
 
51
59
  const en = {
@@ -74,7 +82,15 @@ window.__ModuleLoader__.load({
74
82
  note: "Installs and updates go through dsh-market or the dsh CLI; this page only provides the catalog, status and entry points. Child plugin code is never copied.",
75
83
  version: "Version",
76
84
  notInstalled: "Not installed",
77
- disabledHint: "Enable or disable it in Settings → Plugins."
85
+ disabledHint: "Enable or disable it in Settings → Plugins.",
86
+ enable: "Enable",
87
+ disable: "Disable",
88
+ config: "Configure",
89
+ configHint: "Configure it in Settings → Plugins → {name}.",
90
+ manageHint: "Use Settings → Plugins to enable or disable it.",
91
+ toggled: "Toggled.",
92
+ toggleRefresh: "Toggled; refresh the page to apply.",
93
+ toggleFailed: "Toggle failed"
78
94
  };
79
95
 
80
96
  /** Route root published by the Host at boot. */
@@ -102,7 +118,7 @@ window.__ModuleLoader__.load({
102
118
  }
103
119
 
104
120
  /** A single catalog card. */
105
- function Card({ item, installed, profile, dshmarket, busy, onInstall, onCopy, t }) {
121
+ function Card({ item, installed, profile, dshmarket, enabled, busy, onInstall, onCopy, onToggle, onConfig, t }) {
106
122
  const current = installed !== undefined ? installed.version : "";
107
123
  const newer = current !== "" && current !== item.version;
108
124
  const formats = item.formats !== undefined
@@ -149,7 +165,27 @@ window.__ModuleLoader__.load({
149
165
  t("copy")
150
166
  ),
151
167
  current !== ""
152
- ? React.createElement("span", { className: "dsh-pm-hint" }, t("disabledHint"))
168
+ ? React.createElement(
169
+ "button",
170
+ {
171
+ type: "button",
172
+ className: "dsh-pm-button",
173
+ disabled: busy === item.name || !dshmarket,
174
+ title: dshmarket ? "" : t("manageHint"),
175
+ onClick: () => onToggle(item)
176
+ },
177
+ enabled ? t("disable") : t("enable")
178
+ )
179
+ : null,
180
+ current !== ""
181
+ ? React.createElement(
182
+ "button",
183
+ { type: "button", className: "dsh-pm-button", onClick: () => onConfig(item) },
184
+ t("config")
185
+ )
186
+ : null,
187
+ current !== "" && !dshmarket
188
+ ? React.createElement("span", { className: "dsh-pm-hint" }, t("manageHint"))
153
189
  : null
154
190
  )
155
191
  );
@@ -163,6 +199,7 @@ window.__ModuleLoader__.load({
163
199
  error: "",
164
200
  catalog: [],
165
201
  installed: [],
202
+ disabled: [],
166
203
  profile: "desktop",
167
204
  dshmarket: false
168
205
  });
@@ -172,18 +209,32 @@ window.__ModuleLoader__.load({
172
209
  const load = React.useCallback(async () => {
173
210
  setState((previous) => ({ ...previous, loading: true, error: "" }));
174
211
  try {
175
- const [catalog, inventory, status] = await Promise.all([
212
+ const status = await fetch("/dsh-market/status", { cache: "no-store" })
213
+ .then((response) => response.ok)
214
+ .catch(() => false);
215
+ const [catalog, inventory] = await Promise.all([
176
216
  getJson(`${marketRoute}/catalog`),
177
- getJson(`${marketRoute}/installed`),
178
- fetch("/dsh-market/status", { cache: "no-store" })
179
- .then((response) => response.ok)
180
- .catch(() => false)
217
+ getJson(`${marketRoute}/installed`)
181
218
  ]);
219
+ let disabled = [];
220
+ if (status === true) {
221
+ try {
222
+ const detailResponse = await fetch("/dsh-market/installed", { cache: "no-store" });
223
+ if (detailResponse.ok) {
224
+ const detail = await detailResponse.json();
225
+ if (Array.isArray(detail.disabled)) disabled = detail.disabled;
226
+ else if (Array.isArray(detail.patch?.disables)) disabled = detail.patch.disables;
227
+ }
228
+ } catch {
229
+ disabled = [];
230
+ }
231
+ }
182
232
  setState({
183
233
  loading: false,
184
234
  error: "",
185
235
  catalog: Array.isArray(catalog.plugins) ? catalog.plugins : [],
186
236
  installed: Array.isArray(inventory.installed) ? inventory.installed : [],
237
+ disabled: Array.isArray(disabled) ? disabled : [],
187
238
  profile: typeof inventory.profile === "string" && inventory.profile !== "" ? inventory.profile : "desktop",
188
239
  dshmarket: status === true
189
240
  });
@@ -235,6 +286,33 @@ window.__ModuleLoader__.load({
235
286
  }
236
287
  }, [state.profile, t]);
237
288
 
289
+ const toggle = React.useCallback(async (item) => {
290
+ setBusy(item.name);
291
+ setNotice("");
292
+ try {
293
+ const enabled = state.disabled.includes(item.name);
294
+ const response = await fetch("/dsh-market/toggle", {
295
+ method: "POST",
296
+ headers: { "content-type": "application/json" },
297
+ body: JSON.stringify({ name: item.name, enabled })
298
+ });
299
+ const body = await response.json().catch(() => null);
300
+ if (!response.ok || body === null || body.ok !== true) {
301
+ throw new Error(body !== null && typeof body.error === "string" ? body.error : `HTTP ${response.status}`);
302
+ }
303
+ setNotice(body.refresh ? t("toggleRefresh") : t("toggled"));
304
+ await load();
305
+ } catch (error) {
306
+ setNotice(`${t("toggleFailed")}: ${error instanceof Error ? error.message : String(error)}`);
307
+ } finally {
308
+ setBusy("");
309
+ }
310
+ }, [state.disabled, load, t]);
311
+
312
+ const config = React.useCallback((item) => {
313
+ setNotice(t("configHint").replace("{name}", item.name));
314
+ }, [t]);
315
+
238
316
  installStyle();
239
317
 
240
318
  return React.createElement(
@@ -277,9 +355,12 @@ window.__ModuleLoader__.load({
277
355
  installed: installedByName.get(item.name),
278
356
  profile: state.profile,
279
357
  dshmarket: state.dshmarket,
358
+ enabled: !state.disabled.includes(item.name),
280
359
  busy,
281
360
  onInstall: (entry) => void install(entry),
282
361
  onCopy: (entry) => void copy(entry),
362
+ onToggle: (entry) => void toggle(entry),
363
+ onConfig: (entry) => config(entry),
283
364
  t
284
365
  })
285
366
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-preview-market",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Vertical preview market for DeepSeek Harness: discover, install and configure preview plugins (media, Blender, STL, ...) from one panel.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -65,6 +65,9 @@
65
65
  "url": "https://github.com/439436269-ctrl/dsh-preview-market/issues"
66
66
  },
67
67
  "scripts": {
68
- "test": "node --test test/*.test.js"
68
+ "test": "node --test test/*.test.js",
69
+ "e2e": "node scripts/e2e-settings.mjs",
70
+ "e2e:fallback": "node scripts/e2e-fallback.mjs",
71
+ "e2e:toggle": "node scripts/e2e-toggle.mjs"
69
72
  }
70
73
  }