@artenx/dshb 0.1.33 → 0.1.35
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/cordis.patch.yml +8 -4
- package/lib/auth/reset-cli.d.ts +15 -0
- package/lib/auth/reset-cli.js +47 -0
- package/lib/auth/reset-cli.js.map +1 -0
- package/lib/client.js +34 -3
- package/lib/client.js.map +1 -1
- package/lib/core/index.js +1 -1
- package/lib/core/routes.d.ts +1 -1
- package/lib/core/sync/coordinator.d.ts +14 -5
- package/lib/core/sync/coordinator.js +83 -18
- package/lib/core/sync/coordinator.js.map +1 -1
- package/lib/core/sync/host-key.d.ts +1 -1
- package/lib/core/sync/internal-routes.d.ts +3 -3
- package/lib/core/sync/internal-routes.js +1 -1
- package/lib/core/sync/model.d.ts +1 -1
- package/lib/core/sync/model.js.map +1 -1
- package/lib/core/sync/node-sync.d.ts +1 -1
- package/lib/core/sync/offline-archive.d.ts +3 -3
- package/lib/core/sync/offline-archive.js +1 -1
- package/lib/core/sync/offline-routes.js +1 -1
- package/lib/core/sync/peer-manager.d.ts +2 -2
- package/lib/core/sync/routes.d.ts +1 -1
- package/lib/core/sync/routes.js +19 -0
- package/lib/core/sync/routes.js.map +1 -1
- package/lib/core/sync/session-journal.d.ts +1 -1
- package/lib/core/sync/session-journal.js +16 -0
- package/lib/core/sync/session-journal.js.map +1 -1
- package/lib/core/sync/session-routes.d.ts +1 -1
- package/lib/core/sync/session-routes.js +1 -1
- package/lib/core/sync/session-sync.d.ts +1 -1
- package/lib/core/sync/session-sync.js +1 -1
- package/lib/core/sync/ssh-transport.d.ts +1 -1
- package/lib/core/sync/ssh-transport.js +29 -2
- package/lib/core/sync/ssh-transport.js.map +1 -1
- package/lib/core/sync/stores.d.ts +1 -1
- package/lib/core/sync/stores.js +1 -1
- package/lib/core/sync/stores.js.map +1 -1
- package/lib/core/workspaces.d.ts +1 -1
- package/lib/{host-key-C5afhAUd.d.ts → host-key-CSnpIrjq.d.ts} +2 -2
- package/lib/{model-BP7Gw1yk.d.ts → model-CKTBf-Pl.d.ts} +2 -2
- package/lib/{node-sync-3Z9QLz2n.d.ts → node-sync-C3Ym-HDu.d.ts} +3 -3
- package/lib/{session-journal-pgPqcWn9.d.ts → session-journal-VE_1tA2-.d.ts} +8 -2
- package/lib/{session-sync-CIqjuWkh.js → session-sync-DLr_BdvN.js} +15 -1
- package/lib/{session-sync-CIqjuWkh.js.map → session-sync-DLr_BdvN.js.map} +1 -1
- package/lib/{session-sync-BuOJvFxK.d.ts → session-sync-DrKShc5c.d.ts} +11 -5
- package/lib/{ssh-transport-C7povM0s.d.ts → ssh-transport-BxPWfu9X.d.ts} +13 -6
- package/lib/{stores-CKyEt0yk.d.ts → stores-puyTC075.d.ts} +2 -2
- package/package.json +6 -4
- package/lib/auth/startup.d.ts +0 -15
- package/lib/auth/startup.js +0 -68
- package/lib/auth/startup.js.map +0 -1
package/cordis.patch.yml
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# DSHB 的补丁层:仅插入各功能条目。
|
|
2
|
+
#
|
|
3
|
+
# 注意:不要在这里禁用或替换上游 `web-startup`(dsh-web-app)。webserver 行
|
|
4
|
+
# `inject: [webStartup]`,运行时启用/停用插件的补丁重载一旦更换 webStartup
|
|
5
|
+
# 提供者,webServer 会被连带销毁重建,拆断桌面端正在使用的连接(0.1.33 及
|
|
6
|
+
# 之前桌面端"启用即断连、左下角重连横幅"的根因)。上游 web-startup 与历史
|
|
7
|
+
# 替换版功能等价(--host/--port/--trusted-host/--no-open),凭据重置已改为
|
|
8
|
+
# 独立命令 `dshb-auth-reset`(见 src/auth/reset-cli.ts)。
|
|
3
9
|
- insert:
|
|
4
10
|
- id: dshb-auth
|
|
5
11
|
name: "@artenx/dshb/auth"
|
|
6
|
-
- id: dshb-web-startup
|
|
7
|
-
name: "@artenx/dshb/auth/startup"
|
|
8
12
|
- id: dshb-core
|
|
9
13
|
name: "@artenx/dshb/core"
|
|
10
14
|
- id: dshb-router
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/auth/reset-cli.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* 独立的凭据重置 CLI(`dshb-auth-reset`)。
|
|
4
|
+
*
|
|
5
|
+
* 历史上它是 `dsh --profile web auth-reset` 子命令,由 dshb-web-startup 替换
|
|
6
|
+
* 上游 web-startup 实现。该替换会让 webServer 行(inject: [webStartup])在
|
|
7
|
+
* 运行时启用/停用插件的补丁重载中连带重建,拆断桌面端正在使用的连接
|
|
8
|
+
* (0.1.33 及之前桌面端"启用即断连"的根因)。上游 web-startup 与本替换版
|
|
9
|
+
* 功能等价(--host/--port/--trusted-host/--no-open 全部一致),因此 0.1.34
|
|
10
|
+
* 起不再替换,auth-reset 降级为本独立命令。
|
|
11
|
+
*/
|
|
12
|
+
declare function runAuthResetCli(argv: readonly string[]): never;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { runAuthResetCli };
|
|
15
|
+
//# sourceMappingURL=reset-cli.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { sanitizeUsername, sharedCredentialStore } from "./credentials.js";
|
|
2
|
+
//#region src/auth/reset-cli.ts
|
|
3
|
+
/**
|
|
4
|
+
* 独立的凭据重置 CLI(`dshb-auth-reset`)。
|
|
5
|
+
*
|
|
6
|
+
* 历史上它是 `dsh --profile web auth-reset` 子命令,由 dshb-web-startup 替换
|
|
7
|
+
* 上游 web-startup 实现。该替换会让 webServer 行(inject: [webStartup])在
|
|
8
|
+
* 运行时启用/停用插件的补丁重载中连带重建,拆断桌面端正在使用的连接
|
|
9
|
+
* (0.1.33 及之前桌面端"启用即断连"的根因)。上游 web-startup 与本替换版
|
|
10
|
+
* 功能等价(--host/--port/--trusted-host/--no-open 全部一致),因此 0.1.34
|
|
11
|
+
* 起不再替换,auth-reset 降级为本独立命令。
|
|
12
|
+
*/
|
|
13
|
+
function runAuthResetCli(argv) {
|
|
14
|
+
const store = sharedCredentialStore();
|
|
15
|
+
if (!store.isInitialized()) {
|
|
16
|
+
console.error("dshb-auth-reset: 尚未初始化管理员账号");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
let password;
|
|
20
|
+
let username;
|
|
21
|
+
for (let i = 0; i < argv.length; i += 1) if (argv[i] === "--password") password = argv[++i];
|
|
22
|
+
else if (argv[i] === "--username") username = argv[++i];
|
|
23
|
+
if (password === void 0 && username === void 0) {
|
|
24
|
+
console.error("dshb-auth-reset: 需要 --password <新密码> 和/或 --username <新用户名>");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
if (password !== void 0 && password.length < 8) {
|
|
28
|
+
console.error("dshb-auth-reset: 密码至少 8 个字符");
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
if (username !== void 0) {
|
|
32
|
+
username = sanitizeUsername(username);
|
|
33
|
+
if (!username) {
|
|
34
|
+
console.error("dshb-auth-reset: 用户名不能为空");
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (password !== void 0) store.changePassword(username ?? store.username, password);
|
|
39
|
+
else store.changeUsername(username);
|
|
40
|
+
console.log("dshb-auth-reset: 已更新凭据并轮换会话密钥,全部已签发会话作废");
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
if (process.argv[1]?.endsWith("reset-cli.js") === true || process.argv[1]?.endsWith("dshb-auth-reset") === true) runAuthResetCli(process.argv.slice(2));
|
|
44
|
+
//#endregion
|
|
45
|
+
export { runAuthResetCli };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=reset-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset-cli.js","names":[],"sources":["../../src/auth/reset-cli.ts"],"sourcesContent":["import { sanitizeUsername, sharedCredentialStore } from './credentials.js'\n\n/**\n * 独立的凭据重置 CLI(`dshb-auth-reset`)。\n *\n * 历史上它是 `dsh --profile web auth-reset` 子命令,由 dshb-web-startup 替换\n * 上游 web-startup 实现。该替换会让 webServer 行(inject: [webStartup])在\n * 运行时启用/停用插件的补丁重载中连带重建,拆断桌面端正在使用的连接\n * (0.1.33 及之前桌面端\"启用即断连\"的根因)。上游 web-startup 与本替换版\n * 功能等价(--host/--port/--trusted-host/--no-open 全部一致),因此 0.1.34\n * 起不再替换,auth-reset 降级为本独立命令。\n */\nexport function runAuthResetCli(argv: readonly string[]): never {\n const store = sharedCredentialStore()\n if (!store.isInitialized()) {\n console.error('dshb-auth-reset: 尚未初始化管理员账号')\n process.exit(1)\n }\n let password: string | undefined\n let username: string | undefined\n for (let i = 0; i < argv.length; i += 1) {\n if (argv[i] === '--password') password = argv[++i]\n else if (argv[i] === '--username') username = argv[++i]\n }\n if (password === undefined && username === undefined) {\n console.error('dshb-auth-reset: 需要 --password <新密码> 和/或 --username <新用户名>')\n process.exit(1)\n }\n if (password !== undefined && password.length < 8) {\n console.error('dshb-auth-reset: 密码至少 8 个字符')\n process.exit(1)\n }\n if (username !== undefined) {\n username = sanitizeUsername(username)\n if (!username) {\n console.error('dshb-auth-reset: 用户名不能为空')\n process.exit(1)\n }\n }\n if (password !== undefined) store.changePassword(username ?? store.username!, password)\n else store.changeUsername(username!)\n console.log('dshb-auth-reset: 已更新凭据并轮换会话密钥,全部已签发会话作废')\n process.exit(0)\n}\n\nconst invokedDirectly = process.argv[1]?.endsWith('reset-cli.js') === true\n || process.argv[1]?.endsWith('dshb-auth-reset') === true\nif (invokedDirectly) runAuthResetCli(process.argv.slice(2))\n"],"mappings":";;;;;;;;;;;;AAYA,SAAgB,gBAAgB,MAAgC;CAC9D,MAAM,QAAQ,sBAAsB;CACpC,IAAI,CAAC,MAAM,cAAc,GAAG;EAC1B,QAAQ,MAAM,6BAA6B;EAC3C,QAAQ,KAAK,CAAC;CAChB;CACA,IAAI;CACJ,IAAI;CACJ,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,GACpC,IAAI,KAAK,OAAO,cAAc,WAAW,KAAK,EAAE;MAC3C,IAAI,KAAK,OAAO,cAAc,WAAW,KAAK,EAAE;CAEvD,IAAI,aAAa,KAAA,KAAa,aAAa,KAAA,GAAW;EACpD,QAAQ,MAAM,4DAA4D;EAC1E,QAAQ,KAAK,CAAC;CAChB;CACA,IAAI,aAAa,KAAA,KAAa,SAAS,SAAS,GAAG;EACjD,QAAQ,MAAM,6BAA6B;EAC3C,QAAQ,KAAK,CAAC;CAChB;CACA,IAAI,aAAa,KAAA,GAAW;EAC1B,WAAW,iBAAiB,QAAQ;EACpC,IAAI,CAAC,UAAU;GACb,QAAQ,MAAM,0BAA0B;GACxC,QAAQ,KAAK,CAAC;EAChB;CACF;CACA,IAAI,aAAa,KAAA,GAAW,MAAM,eAAe,YAAY,MAAM,UAAW,QAAQ;MACjF,MAAM,eAAe,QAAS;CACnC,QAAQ,IAAI,yCAAyC;CACrD,QAAQ,KAAK,CAAC;AAChB;AAIA,IAFwB,QAAQ,KAAK,EAAE,EAAE,SAAS,cAAc,MAAM,QACjE,QAAQ,KAAK,EAAE,EAAE,SAAS,iBAAiB,MAAM,MACjC,gBAAgB,QAAQ,KAAK,MAAM,CAAC,CAAC"}
|
package/lib/client.js
CHANGED
|
@@ -2395,6 +2395,7 @@ window.__ModuleLoader__.load({
|
|
|
2395
2395
|
const [probingRemote, setProbingRemote] = (0, react.useState)(false);
|
|
2396
2396
|
const [remoteProbe, setRemoteProbe] = (0, react.useState)(void 0);
|
|
2397
2397
|
const [syncing, setSyncing] = (0, react.useState)(false);
|
|
2398
|
+
const [stopping, setStopping] = (0, react.useState)(false);
|
|
2398
2399
|
const [notice, setNotice] = (0, react.useState)(void 0);
|
|
2399
2400
|
const [hostKeyChallenge, setHostKeyChallenge] = (0, react.useState)(void 0);
|
|
2400
2401
|
(0, react.useEffect)(() => {
|
|
@@ -2432,6 +2433,7 @@ window.__ModuleLoader__.load({
|
|
|
2432
2433
|
const status = peer.progress?.lastRunStatus;
|
|
2433
2434
|
if (!peer.enabled) return "已停用";
|
|
2434
2435
|
if (status === "running") return "同步中";
|
|
2436
|
+
if (status === "stopped") return "上次已停止(未完成批次已丢弃)";
|
|
2435
2437
|
if (status === "failed") return "上次失败";
|
|
2436
2438
|
if (status === "succeeded") return "上次成功";
|
|
2437
2439
|
return "尚未同步";
|
|
@@ -2609,6 +2611,34 @@ window.__ModuleLoader__.load({
|
|
|
2609
2611
|
setSyncing(false);
|
|
2610
2612
|
}
|
|
2611
2613
|
};
|
|
2614
|
+
const stopSync = async () => {
|
|
2615
|
+
if (selectedId === "new") return;
|
|
2616
|
+
setStopping(true);
|
|
2617
|
+
try {
|
|
2618
|
+
const response = await fetch(`/api/dshb/sync/peers/${selectedId}/stop`, { method: "POST" });
|
|
2619
|
+
const data = await readJsonResponse(response, "停止同步失败");
|
|
2620
|
+
if (!response.ok || !data.ok) throw new Error(data.error ?? "停止同步失败");
|
|
2621
|
+
setPeers((current) => current.map((peer) => peer.id === selectedId ? {
|
|
2622
|
+
...peer,
|
|
2623
|
+
progress: {
|
|
2624
|
+
...peer.progress,
|
|
2625
|
+
lastRunStatus: data.stopped ? "running" : peer.progress?.lastRunStatus
|
|
2626
|
+
}
|
|
2627
|
+
} : peer));
|
|
2628
|
+
setNotice({
|
|
2629
|
+
kind: "ok",
|
|
2630
|
+
text: data.stopped ? "已请求停止:将在最近的安全边界中止,未完成的批次会被丢弃,已完成的会话保留" : "当前没有运行中的同步作业"
|
|
2631
|
+
});
|
|
2632
|
+
reload();
|
|
2633
|
+
} catch (error) {
|
|
2634
|
+
setNotice({
|
|
2635
|
+
kind: "error",
|
|
2636
|
+
text: error instanceof Error ? error.message : "停止同步失败"
|
|
2637
|
+
});
|
|
2638
|
+
} finally {
|
|
2639
|
+
setStopping(false);
|
|
2640
|
+
}
|
|
2641
|
+
};
|
|
2612
2642
|
const restoreArchive = async (branchId) => {
|
|
2613
2643
|
const archive = archives.find((entry) => entry.branchId === branchId);
|
|
2614
2644
|
if (!archive || !window.confirm(`恢复会话 ${archive.originSessionId} 的归档版本?当前版本将保留在归档中。`)) return;
|
|
@@ -2633,6 +2663,7 @@ window.__ModuleLoader__.load({
|
|
|
2633
2663
|
};
|
|
2634
2664
|
const progressLabel = (peer) => {
|
|
2635
2665
|
if (peer.progress?.lastRunStatus === "running") return "同步中";
|
|
2666
|
+
if (peer.progress?.lastRunStatus === "stopped") return "上次已停止:未完成的批次已丢弃,已完成的会话保留";
|
|
2636
2667
|
if (peer.progress?.lastRunStatus === "failed") return `上次失败:${peer.progress.lastErrorMessage ?? "同步失败"}`;
|
|
2637
2668
|
if (peer.progress?.lastSuccessAt) return `上次成功:${new Date(peer.progress.lastSuccessAt).toLocaleString()}`;
|
|
2638
2669
|
return "尚未同步";
|
|
@@ -3256,10 +3287,10 @@ window.__ModuleLoader__.load({
|
|
|
3256
3287
|
}),
|
|
3257
3288
|
!isNew && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3258
3289
|
type: "button",
|
|
3259
|
-
onClick: () => void runSync(),
|
|
3260
|
-
disabled: busy || probing ||
|
|
3290
|
+
onClick: () => void (syncInProgress ? stopSync() : runSync()),
|
|
3291
|
+
disabled: busy || probing || stopping || !selectedPeer?.enabled && !syncInProgress,
|
|
3261
3292
|
style: secondaryBtn,
|
|
3262
|
-
children: syncInProgress ? "
|
|
3293
|
+
children: stopping ? "正在停止…" : syncInProgress ? "停止同步" : "立即同步"
|
|
3263
3294
|
}),
|
|
3264
3295
|
!isNew && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3265
3296
|
type: "button",
|