@linxin666/dsh-remote-web-ui 0.1.15 → 0.1.16
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.i18n.yaml +2 -2
- package/README.md +9 -5
- package/README.zh.md +1 -1
- package/lib/client.js +58 -10
- package/lib/client.js.map +1 -1
- package/lib/index.js +110 -11
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PluginSettingsCard.js +3 -1
- package/lib/types/client/UpdatePanel.js +2 -0
- package/lib/types/client/locales.d.ts +4 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +4 -0
- package/lib/types/client/settings-form.d.ts +62 -0
- package/lib/types/client/settings-form.d.ts.map +1 -1
- package/lib/types/client/settings-form.js +61 -12
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +36 -10
- package/lib/types/update.d.ts +44 -4
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +118 -8
- package/package.json +1 -1
- package/src/client/PluginSettingsCard.tsx +7 -1
- package/src/client/UpdatePanel.tsx +2 -0
- package/src/client/locales.ts +4 -0
- package/src/client/settings-card.module.css +3 -0
- package/src/client/settings-form.ts +114 -12
- package/src/index.ts +34 -10
- package/src/update.ts +128 -9
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: c1e5ea0deaca90a5a188342db0d38256f5917369
|
|
6
|
+
README.zh.md: 9be2fbeb481ea23f05aa06f732234b2310c3d16a
|
package/README.md
CHANGED
|
@@ -38,12 +38,16 @@ actions, and the update panel that probes and runs the update.
|
|
|
38
38
|
- **Remote update**: the download trigger in the sidebar foot (left of the
|
|
39
39
|
phone icon) opens the update panel, which probes the npm registry for the
|
|
40
40
|
installed `@linxin666/dsh-*` family releases. When a newer release exists
|
|
41
|
-
the panel runs the update automatically (`pnpm update` inside the
|
|
42
|
-
dsh profile; when pnpm is missing it falls back to `corepack pnpm`
|
|
43
|
-
then `npx --yes pnpm`, and on Windows the command runs through
|
|
44
|
-
so npm-installed `.cmd` shims resolve; the loopback-only
|
|
41
|
+
the panel runs the update automatically (`pnpm update --latest` inside the
|
|
42
|
+
owning dsh profile; when pnpm is missing it falls back to `corepack pnpm`
|
|
43
|
+
and then `npx --yes pnpm`, and on Windows the command runs through
|
|
44
|
+
`cmd.exe` so npm-installed `.cmd` shims resolve; the loopback-only
|
|
45
45
|
`/api/update/status` + `/api/update/run` endpoints drive it) and asks for
|
|
46
|
-
a dsh web restart to pick it up.
|
|
46
|
+
a dsh web restart to pick it up. After a green pnpm exit the installed
|
|
47
|
+
versions are re-checked against the registry: a green exit that left every
|
|
48
|
+
version in place (e.g. the pnpm `minimumReleaseAge` gate silently skipping
|
|
49
|
+
same-day releases) is reported as a stale update with configuration
|
|
50
|
+
guidance instead of a false success. Local
|
|
47
51
|
link installs (development mode) are detected and report the npm state
|
|
48
52
|
without updating.
|
|
49
53
|
|
package/README.zh.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- **手机侧**:扫码将手机与一次性、限时令牌绑定,并落地到 **`/m` 独立移动端界面**——一款专为小屏设计的轻客户端(见[截图](#截图)),而不是把桌面 UI 塞进手机。链接携带 `workspace` 参数,手机落地到桌面正在查看的同一工作区。
|
|
14
14
|
- **安全**:一个有效的一次性令牌(刷新会使旧链接失效;已接受的令牌不可复用;令牌会过期)。停止会撤销每一台已配对设备与当前令牌——已配对设备在下一次请求时被切断。当插件 `requirePairingForLan` 门开启(默认)时,每个非 loopback 的 `/api` 请求必须携带有效的已配对设备 cookie,因此二维码是进入暴露在局域网上的 dsh web 的唯一途径。
|
|
15
15
|
- **实时状态**:桌面面板经 SSE 流实时镜像配对状态(等待 → 已连接 → 已断开)。
|
|
16
|
-
- **远程更新**:侧边栏底部的下载触发按钮(手机图标左侧)打开更新面板,它探测 npm registry 上已安装的 `@linxin666/dsh-*` 全家桶版本。当存在较新版本时,面板自动执行更新(在所属 dsh profile 内 `pnpm update`;pnpm 缺失时依次回退 `corepack pnpm`、`npx --yes pnpm`,Windows 上经 `cmd.exe` 执行以解析 npm 安装的 `.cmd` shim;由仅 loopback 的 `/api/update/status` + `/api/update/run` 端点驱动)并请求重启 dsh web
|
|
16
|
+
- **远程更新**:侧边栏底部的下载触发按钮(手机图标左侧)打开更新面板,它探测 npm registry 上已安装的 `@linxin666/dsh-*` 全家桶版本。当存在较新版本时,面板自动执行更新(在所属 dsh profile 内 `pnpm update --latest`;pnpm 缺失时依次回退 `corepack pnpm`、`npx --yes pnpm`,Windows 上经 `cmd.exe` 执行以解析 npm 安装的 `.cmd` shim;由仅 loopback 的 `/api/update/status` + `/api/update/run` 端点驱动)并请求重启 dsh web 以生效。pnpm 绿色退出后还会对照 registry 复核已装版本:绿色退出但版本纹丝不动(例如 pnpm 的 `minimumReleaseAge` 门禁静默跳过同日发布的新版本)会报告为「未更新成功」并附配置指引,而不是误报成功。本地 link 安装(开发模式)会被探测到,只报告 npm 状态而不更新。
|
|
17
17
|
|
|
18
18
|
## 截图
|
|
19
19
|
|
package/lib/client.js
CHANGED
|
@@ -1877,6 +1877,8 @@ window.__ModuleLoader__.load({
|
|
|
1877
1877
|
case "not-found": return t("update.error.notFound");
|
|
1878
1878
|
case "link": return t("update.error.link");
|
|
1879
1879
|
case "pnpm-failed": return t("update.error.pnpmFailed", { code: String(result.exitCode ?? "?") });
|
|
1880
|
+
case "stale": return t("update.error.stale");
|
|
1881
|
+
case "verify-failed": return t("update.error.verifyFailed");
|
|
1880
1882
|
default: return result.error ?? t("update.error.unknown");
|
|
1881
1883
|
}
|
|
1882
1884
|
}
|
|
@@ -2217,7 +2219,7 @@ window.__ModuleLoader__.load({
|
|
|
2217
2219
|
}
|
|
2218
2220
|
//#endregion
|
|
2219
2221
|
//#region \0dsh-css:packages/dsh-remote-web-ui/src/client/settings-card.module.css.mjs
|
|
2220
|
-
const css = ".Kwoi6G_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.Kwoi6G_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.Kwoi6G_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Kwoi6G_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Kwoi6G_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Kwoi6G_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Kwoi6G_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Kwoi6G_chevronOpen{transform:rotate(180deg)}.Kwoi6G_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.Kwoi6G_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.Kwoi6G_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.Kwoi6G_discard,.Kwoi6G_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Kwoi6G_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Kwoi6G_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Kwoi6G_discard:disabled,.Kwoi6G_save:disabled{opacity:.4;cursor:default}.Kwoi6G_discard:focus-visible,.Kwoi6G_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Kwoi6G_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.Kwoi6G_field+.Kwoi6G_field{border-top:1px solid var(--dsw-alias-border-l2)}.Kwoi6G_head{align-items:center;gap:8px;display:flex}.Kwoi6G_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.Kwoi6G_badges{align-items:center;gap:8px;display:inline-flex}.Kwoi6G_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.Kwoi6G_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.Kwoi6G_reset:disabled{cursor:default}.Kwoi6G_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.Kwoi6G_input,.Kwoi6G_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_input:focus-visible,.Kwoi6G_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.Kwoi6G_input:disabled,.Kwoi6G_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.Kwoi6G_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.Kwoi6G_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.Kwoi6G_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.Kwoi6G_card,.Kwoi6G_header,.Kwoi6G_chevron,.Kwoi6G_chevronOpen,.Kwoi6G_discard,.Kwoi6G_save{transition:none}}";
|
|
2222
|
+
const css = ".Kwoi6G_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.Kwoi6G_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.Kwoi6G_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Kwoi6G_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Kwoi6G_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Kwoi6G_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Kwoi6G_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Kwoi6G_chevronOpen{transform:rotate(180deg)}.Kwoi6G_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.Kwoi6G_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.Kwoi6G_failed{min-width:0;color:var(--dsw-alias-label-error);text-overflow:ellipsis;white-space:nowrap;flex:1;margin:0;font-size:12px;line-height:1.5;overflow:hidden}.Kwoi6G_discard,.Kwoi6G_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Kwoi6G_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Kwoi6G_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Kwoi6G_discard:disabled,.Kwoi6G_save:disabled{opacity:.4;cursor:default}.Kwoi6G_discard:focus-visible,.Kwoi6G_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Kwoi6G_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.Kwoi6G_field+.Kwoi6G_field{border-top:1px solid var(--dsw-alias-border-l2)}.Kwoi6G_head{align-items:center;gap:8px;display:flex}.Kwoi6G_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.Kwoi6G_badges{align-items:center;gap:8px;display:inline-flex}.Kwoi6G_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.Kwoi6G_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.Kwoi6G_reset:disabled{cursor:default}.Kwoi6G_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.Kwoi6G_input,.Kwoi6G_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_input:focus-visible,.Kwoi6G_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.Kwoi6G_input:disabled,.Kwoi6G_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.Kwoi6G_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.Kwoi6G_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.Kwoi6G_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.Kwoi6G_card,.Kwoi6G_header,.Kwoi6G_chevron,.Kwoi6G_chevronOpen,.Kwoi6G_discard,.Kwoi6G_save{transition:none}}";
|
|
2221
2223
|
const tagId = "@linxin666/dsh-remote-web-ui/settings-card.module.css";
|
|
2222
2224
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2223
2225
|
const tag = document.createElement("style");
|
|
@@ -2373,10 +2375,10 @@ window.__ModuleLoader__.load({
|
|
|
2373
2375
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2374
2376
|
className: settings_card_module_css_default.footer,
|
|
2375
2377
|
children: [
|
|
2376
|
-
state.failed ? /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2378
|
+
state.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
2377
2379
|
className: settings_card_module_css_default.failed,
|
|
2378
2380
|
role: "status",
|
|
2379
|
-
children: props.t("settings.saveFailed")
|
|
2381
|
+
children: [props.t("settings.saveFailed"), state.failedReason ? " - " + state.failedReason : ""]
|
|
2380
2382
|
}) : null,
|
|
2381
2383
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2382
2384
|
type: "button",
|
|
@@ -2568,6 +2570,7 @@ window.__ModuleLoader__.load({
|
|
|
2568
2570
|
listeners = /* @__PURE__ */ new Set();
|
|
2569
2571
|
saving = false;
|
|
2570
2572
|
failed = false;
|
|
2573
|
+
failedReason;
|
|
2571
2574
|
/** @param scope - the bound settings scope for this card's namespace. */
|
|
2572
2575
|
constructor(scope, specs) {
|
|
2573
2576
|
this.scope = scope;
|
|
@@ -2595,7 +2598,8 @@ window.__ModuleLoader__.load({
|
|
|
2595
2598
|
dirty: plan.length > 0,
|
|
2596
2599
|
invalid: plan.some((item) => item.run === void 0),
|
|
2597
2600
|
saving: this.saving,
|
|
2598
|
-
failed: this.failed
|
|
2601
|
+
failed: this.failed,
|
|
2602
|
+
...this.failedReason === void 0 ? {} : { failedReason: this.failedReason }
|
|
2599
2603
|
};
|
|
2600
2604
|
}
|
|
2601
2605
|
/** Read one field's state from the effective section and its staged draft. */
|
|
@@ -2636,29 +2640,50 @@ window.__ModuleLoader__.load({
|
|
|
2636
2640
|
if (this.staged.size === 0 && !this.failed) return;
|
|
2637
2641
|
this.staged.clear();
|
|
2638
2642
|
this.failed = false;
|
|
2643
|
+
this.failedReason = void 0;
|
|
2639
2644
|
this.publish();
|
|
2640
2645
|
}
|
|
2641
2646
|
};
|
|
2642
2647
|
}
|
|
2643
2648
|
/**
|
|
2644
2649
|
* Write every staged edit, then re-seed from what the Host accepted.
|
|
2650
|
+
*
|
|
2651
|
+
* When the scope carries the optional batch surface (the dsh-web-ui
|
|
2652
|
+
* bridge scope), every planned write rides one mutation so cross-field
|
|
2653
|
+
* validate hooks (baseURL+model) judge the batch as a unit instead of
|
|
2654
|
+
* deadlocking on per-field writes. Otherwise the per-field loop runs.
|
|
2655
|
+
* A field lands only when the Host reports it held the staged value; a
|
|
2656
|
+
* landed field's draft is dropped, a failed one stays staged for the user.
|
|
2645
2657
|
* @returns settlement after every write and the read-back.
|
|
2646
2658
|
*/
|
|
2647
2659
|
async save() {
|
|
2648
2660
|
const plan = this.plan();
|
|
2649
|
-
const
|
|
2650
|
-
if (plan.length === 0 || this.saving ||
|
|
2661
|
+
const valid = plan.filter((item) => item.run !== void 0);
|
|
2662
|
+
if (plan.length === 0 || this.saving || valid.length !== plan.length) return;
|
|
2663
|
+
const plannedWrites = valid.map((item) => item.op);
|
|
2651
2664
|
const fields = new Set(plan.map((item) => item.field));
|
|
2652
2665
|
this.saving = true;
|
|
2653
2666
|
this.failed = false;
|
|
2667
|
+
this.failedReason = void 0;
|
|
2654
2668
|
this.publish();
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
if (
|
|
2669
|
+
const landed = /* @__PURE__ */ new Set();
|
|
2670
|
+
const batch = this.batchedScope();
|
|
2671
|
+
if (batch !== void 0) {
|
|
2672
|
+
const result = await batch.mutate(plannedWrites);
|
|
2673
|
+
if (result.ok) {
|
|
2674
|
+
for (const field of result.fields) if (field.landed) landed.add(field.field);
|
|
2675
|
+
} else this.failedReason = result.message;
|
|
2676
|
+
} else for (const item of valid) if (await item.run()) landed.add(item.field);
|
|
2677
|
+
for (const field of fields) if (landed.has(field)) this.staged.delete(field);
|
|
2658
2678
|
this.saving = false;
|
|
2659
|
-
this.failed =
|
|
2679
|
+
this.failed = landed.size !== fields.size;
|
|
2660
2680
|
this.publish();
|
|
2661
2681
|
}
|
|
2682
|
+
/** The scope's batch surface when it supports one; undefined conservatively otherwise. */
|
|
2683
|
+
batchedScope() {
|
|
2684
|
+
const candidate = this.scope;
|
|
2685
|
+
return typeof candidate?.mutate === "function" ? candidate : void 0;
|
|
2686
|
+
}
|
|
2662
2687
|
/**
|
|
2663
2688
|
* Every staged edit a save would write. An entry whose draft is not a value
|
|
2664
2689
|
* its field accepts carries no write: the form is still dirty, and the save
|
|
@@ -2673,6 +2698,10 @@ window.__ModuleLoader__.load({
|
|
|
2673
2698
|
if (staged.clear) {
|
|
2674
2699
|
if (this.stored(field)) plan.push({
|
|
2675
2700
|
field,
|
|
2701
|
+
op: {
|
|
2702
|
+
field,
|
|
2703
|
+
op: "unset"
|
|
2704
|
+
},
|
|
2676
2705
|
run: () => this.clear(field)
|
|
2677
2706
|
});
|
|
2678
2707
|
continue;
|
|
@@ -2681,14 +2710,27 @@ window.__ModuleLoader__.load({
|
|
|
2681
2710
|
const write = spec.parse(staged.text);
|
|
2682
2711
|
if (write === void 0) plan.push({
|
|
2683
2712
|
field,
|
|
2713
|
+
op: {
|
|
2714
|
+
field,
|
|
2715
|
+
op: "unset"
|
|
2716
|
+
},
|
|
2684
2717
|
run: void 0
|
|
2685
2718
|
});
|
|
2686
2719
|
else if (write.kind === "clear") plan.push({
|
|
2687
2720
|
field,
|
|
2721
|
+
op: {
|
|
2722
|
+
field,
|
|
2723
|
+
op: "unset"
|
|
2724
|
+
},
|
|
2688
2725
|
run: () => this.clear(field)
|
|
2689
2726
|
});
|
|
2690
2727
|
else plan.push({
|
|
2691
2728
|
field,
|
|
2729
|
+
op: {
|
|
2730
|
+
field,
|
|
2731
|
+
op: "set",
|
|
2732
|
+
value: write.value
|
|
2733
|
+
},
|
|
2692
2734
|
run: () => this.store(field, write.value)
|
|
2693
2735
|
});
|
|
2694
2736
|
}
|
|
@@ -2700,11 +2742,13 @@ window.__ModuleLoader__.load({
|
|
|
2700
2742
|
}
|
|
2701
2743
|
async store(field, value) {
|
|
2702
2744
|
await this.scope.set(field, value);
|
|
2745
|
+
if (this.specOf(field).secret) return true;
|
|
2703
2746
|
return this.userLayer()?.[field] === value;
|
|
2704
2747
|
}
|
|
2705
2748
|
stage(field, edit) {
|
|
2706
2749
|
this.staged.set(field, edit);
|
|
2707
2750
|
this.failed = false;
|
|
2751
|
+
this.failedReason = void 0;
|
|
2708
2752
|
this.publish();
|
|
2709
2753
|
}
|
|
2710
2754
|
specOf(field) {
|
|
@@ -3040,6 +3084,8 @@ window.__ModuleLoader__.load({
|
|
|
3040
3084
|
"update.error.notFound": "未找到 dsh-web-ui 聚合包安装,无法更新。",
|
|
3041
3085
|
"update.error.link": "当前为本地开发模式(链接安装),无法自动更新。",
|
|
3042
3086
|
"update.error.pnpmFailed": "更新执行失败(pnpm 退出码 {code}),详见下方输出。",
|
|
3087
|
+
"update.error.stale": "更新命令已执行,但安装版本未变化。常见原因:pnpm 11 的 minimumReleaseAge 门禁会静默跳过发布不足 24 小时的新版本。请在 profile 目录(~/.dsh/profiles/<profile>)的 pnpm-workspace.yaml 中配置 minimumReleaseAgeExclude(例如 \"@linxin666/*\")或 minimumReleaseAge: 0 后重新点击更新。",
|
|
3088
|
+
"update.error.verifyFailed": "更新命令已执行,但无法核对安装后的版本(可能是 registry 探测失败或安装路径变化)。请查看下方输出,或稍后重试。",
|
|
3043
3089
|
"update.error.unknown": "更新失败,请重试。"
|
|
3044
3090
|
};
|
|
3045
3091
|
/** English dictionary, checked complete against the zh key set. */
|
|
@@ -3142,6 +3188,8 @@ window.__ModuleLoader__.load({
|
|
|
3142
3188
|
"update.error.notFound": "The dsh-web-ui aggregate package is not installed; nothing to update.",
|
|
3143
3189
|
"update.error.link": "Local development mode (link install) — automatic update is unavailable.",
|
|
3144
3190
|
"update.error.pnpmFailed": "The update failed (pnpm exited with code {code}); see the output below.",
|
|
3191
|
+
"update.error.stale": "The update command ran but the installed versions did not change. Likely cause: the pnpm 11 minimumReleaseAge gate silently skips releases published less than 24 hours ago. Add minimumReleaseAgeExclude (e.g. \"@linxin666/*\") or set minimumReleaseAge: 0 in pnpm-workspace.yaml under the profile directory (~/.dsh/profiles/<profile>), then run the update again.",
|
|
3192
|
+
"update.error.verifyFailed": "The update command ran but the installed versions could not be verified afterwards (registry probe failed or the install path changed). Inspect the output below, or retry later.",
|
|
3145
3193
|
"update.error.unknown": "Update failed; try again."
|
|
3146
3194
|
};
|
|
3147
3195
|
//#endregion
|