@artenx/dshb 0.1.31 → 0.1.33
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/lib/client.js +133 -22
- package/lib/client.js.map +1 -1
- package/lib/core/index.js +6 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/sync/coordinator.d.ts +2 -2
- package/lib/core/sync/coordinator.js +23 -6
- package/lib/core/sync/coordinator.js.map +1 -1
- package/lib/core/sync/internal-routes.d.ts +1 -1
- package/lib/core/sync/internal-routes.js +80 -4
- package/lib/core/sync/internal-routes.js.map +1 -1
- package/lib/core/sync/offline-archive.d.ts +1 -1
- package/lib/core/sync/offline-archive.js +1 -1
- package/lib/core/sync/offline-routes.js +1 -1
- package/lib/core/sync/protocol.d.ts +2 -2
- package/lib/core/sync/protocol.js +4 -1
- package/lib/core/sync/protocol.js.map +1 -1
- package/lib/core/sync/remote-helper.js +107 -76
- package/lib/core/sync/remote-helper.js.map +1 -1
- package/lib/core/sync/routes.d.ts +1 -1
- package/lib/core/sync/routes.js +61 -1
- package/lib/core/sync/routes.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 +2 -2
- package/lib/core/sync/session-sync.js +2 -2
- package/lib/core/sync/ssh-transport.d.ts +2 -2
- package/lib/core/sync/ssh-transport.js +267 -3
- package/lib/core/sync/ssh-transport.js.map +1 -1
- package/lib/{protocol-KaWZArY8.d.ts → protocol-DJ0zyVlB.d.ts} +5 -2
- package/lib/{session-sync-Zfo1Q-qT.d.ts → session-sync-BuOJvFxK.d.ts} +54 -2
- package/lib/{session-sync-BQt3HXkp.js → session-sync-CIqjuWkh.js} +455 -48
- package/lib/session-sync-CIqjuWkh.js.map +1 -0
- package/lib/ssh-transport-C7povM0s.d.ts +115 -0
- package/package.json +1 -1
- package/lib/session-sync-BQt3HXkp.js.map +0 -1
- package/lib/ssh-transport-Cfb_nwkY.d.ts +0 -65
package/lib/client.js
CHANGED
|
@@ -2264,6 +2264,34 @@ window.__ModuleLoader__.load({
|
|
|
2264
2264
|
secrets
|
|
2265
2265
|
};
|
|
2266
2266
|
}
|
|
2267
|
+
/**
|
|
2268
|
+
* 把探测结果回填进表单:DSH_HOME 取首个命中目录(保留用户已填的显式覆盖),
|
|
2269
|
+
* profile 取首个装有 dshb 的条目,Web 端口取握手命中值。仅在对应字段为空
|
|
2270
|
+
* 或明显是默认值时回填,避免覆盖用户手改内容。
|
|
2271
|
+
*/
|
|
2272
|
+
function applyRemoteProbeToForm(form, probe) {
|
|
2273
|
+
const detectedHome = probe.homes[0];
|
|
2274
|
+
const detectedProfile = probe.profiles.find((profile) => profile.dshbInstalled) ?? probe.profiles[0];
|
|
2275
|
+
const homeKept = form.remoteDshHome.trim() !== "" && form.remoteDshHome.trim() !== (detectedHome ?? "");
|
|
2276
|
+
const profileKept = form.remoteProfile.trim() !== "" && form.remoteProfile.trim() !== "web";
|
|
2277
|
+
return {
|
|
2278
|
+
...form,
|
|
2279
|
+
remoteDshHome: homeKept ? form.remoteDshHome : detectedHome ?? form.remoteDshHome,
|
|
2280
|
+
remoteProfile: profileKept ? form.remoteProfile : detectedProfile?.name ?? form.remoteProfile,
|
|
2281
|
+
remoteWebPort: probe.webPort !== void 0 ? String(probe.webPort) : form.remoteWebPort
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
/** 远端 profile 下拉选项:探测结果优先(dshb 已装的排前),并保留当前手填值。 */
|
|
2285
|
+
function remoteProfileOptions(form, probe) {
|
|
2286
|
+
const options = (probe?.profiles ?? []).slice().sort((left, right) => Number(right.dshbInstalled) - Number(left.dshbInstalled)).map((profile) => ({
|
|
2287
|
+
name: profile.name,
|
|
2288
|
+
dshbInstalled: profile.dshbInstalled
|
|
2289
|
+
}));
|
|
2290
|
+
const current = form.remoteProfile.trim();
|
|
2291
|
+
if (current && !options.some((option) => option.name === current)) options.push({ name: current });
|
|
2292
|
+
if (options.length === 0) options.push({ name: "web" });
|
|
2293
|
+
return options;
|
|
2294
|
+
}
|
|
2267
2295
|
//#endregion
|
|
2268
2296
|
//#region src/client/sync-peers.tsx
|
|
2269
2297
|
function shortenSessionId(id) {
|
|
@@ -2364,6 +2392,8 @@ window.__ModuleLoader__.load({
|
|
|
2364
2392
|
const [form, setForm] = (0, react.useState)(EMPTY_SYNC_PEER_FORM);
|
|
2365
2393
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
2366
2394
|
const [probing, setProbing] = (0, react.useState)(false);
|
|
2395
|
+
const [probingRemote, setProbingRemote] = (0, react.useState)(false);
|
|
2396
|
+
const [remoteProbe, setRemoteProbe] = (0, react.useState)(void 0);
|
|
2367
2397
|
const [syncing, setSyncing] = (0, react.useState)(false);
|
|
2368
2398
|
const [notice, setNotice] = (0, react.useState)(void 0);
|
|
2369
2399
|
const [hostKeyChallenge, setHostKeyChallenge] = (0, react.useState)(void 0);
|
|
@@ -2482,6 +2512,48 @@ window.__ModuleLoader__.load({
|
|
|
2482
2512
|
setProbing(false);
|
|
2483
2513
|
}
|
|
2484
2514
|
};
|
|
2515
|
+
const probeRemote = async () => {
|
|
2516
|
+
const secretReady = form.authKind === "password" ? form.password !== "" : form.privateKey !== "";
|
|
2517
|
+
if (selectedId === "new" && (!form.host.trim() || !form.username.trim() || !secretReady)) {
|
|
2518
|
+
setNotice({
|
|
2519
|
+
kind: "error",
|
|
2520
|
+
text: "探测远端前请先填写 SSH 主机、系统账号和登录凭据"
|
|
2521
|
+
});
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
setProbingRemote(true);
|
|
2525
|
+
setHostKeyChallenge(void 0);
|
|
2526
|
+
try {
|
|
2527
|
+
const useSavedCredentials = selectedId !== "new" && !secretReady;
|
|
2528
|
+
const request = buildSyncPeerFormRequest(form);
|
|
2529
|
+
const response = await fetch("/api/dshb/sync/peers/probe-remote", {
|
|
2530
|
+
method: "POST",
|
|
2531
|
+
headers: { "content-type": "application/json" },
|
|
2532
|
+
body: JSON.stringify(useSavedCredentials ? { peerId: selectedId } : {
|
|
2533
|
+
...request.fields,
|
|
2534
|
+
secrets: request.secrets
|
|
2535
|
+
})
|
|
2536
|
+
});
|
|
2537
|
+
const data = await readJsonResponse(response, "远端探测失败");
|
|
2538
|
+
if (!response.ok || !data.ok || !data.probe) throw new Error(data.error ?? "远端探测失败");
|
|
2539
|
+
const probe = data.probe;
|
|
2540
|
+
setRemoteProbe(probe);
|
|
2541
|
+
setForm((current) => applyRemoteProbeToForm(current, probe));
|
|
2542
|
+
const profileText = probe.profiles.length > 0 ? `${probe.profiles.length} 个 profile` : "未发现 profile";
|
|
2543
|
+
const portText = probe.webPort !== void 0 ? `Web 端口 ${probe.webPort}` : "未探测到运行中的 Web 端口";
|
|
2544
|
+
setNotice({
|
|
2545
|
+
kind: "ok",
|
|
2546
|
+
text: `远端探测完成:${profileText},${portText}${probe.instanceId ? `(实例 ${probe.instanceId.slice(0, 14)}…)` : ""}`
|
|
2547
|
+
});
|
|
2548
|
+
} catch (error) {
|
|
2549
|
+
setNotice({
|
|
2550
|
+
kind: "error",
|
|
2551
|
+
text: error instanceof Error ? error.message : "远端探测失败"
|
|
2552
|
+
});
|
|
2553
|
+
} finally {
|
|
2554
|
+
setProbingRemote(false);
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2485
2557
|
const trustObservedHostKey = async () => {
|
|
2486
2558
|
if (selectedId === "new" || !hostKeyChallenge) return;
|
|
2487
2559
|
const confirmation = hostKeyChallenge.code === "host-key-changed" ? `远端 SSH 主机指纹已变化。\n当前保存:${hostKeyChallenge.expected}\n本次观察:${hostKeyChallenge.fingerprint}\n确认信任新指纹?` : `首次连接观察到 SSH 主机指纹:\n${hostKeyChallenge.fingerprint}\n请核对后确认信任。`;
|
|
@@ -2886,24 +2958,41 @@ window.__ModuleLoader__.load({
|
|
|
2886
2958
|
}))
|
|
2887
2959
|
})]
|
|
2888
2960
|
})] }),
|
|
2889
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2961
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2890
2962
|
style: {
|
|
2891
2963
|
...groupTitle,
|
|
2892
|
-
marginTop: 20
|
|
2964
|
+
marginTop: 20,
|
|
2965
|
+
display: "flex",
|
|
2966
|
+
alignItems: "center",
|
|
2967
|
+
justifyContent: "space-between"
|
|
2893
2968
|
},
|
|
2894
|
-
children: "远端配置"
|
|
2969
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "远端配置" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2970
|
+
type: "button",
|
|
2971
|
+
style: probingRemote ? secondaryBtn : secondaryBtn,
|
|
2972
|
+
disabled: probingRemote,
|
|
2973
|
+
onClick: () => {
|
|
2974
|
+
probeRemote();
|
|
2975
|
+
},
|
|
2976
|
+
children: probingRemote ? "探测中…" : "通过 SSH 探测远端"
|
|
2977
|
+
})]
|
|
2895
2978
|
}),
|
|
2896
2979
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2897
2980
|
style: field,
|
|
2898
2981
|
children: [
|
|
2899
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2982
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2900
2983
|
style: label,
|
|
2901
|
-
children: "远端 DSH_HOME"
|
|
2984
|
+
children: ["远端 DSH_HOME", remoteProbe?.homes.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2985
|
+
style: {
|
|
2986
|
+
fontWeight: 400,
|
|
2987
|
+
opacity: .55
|
|
2988
|
+
},
|
|
2989
|
+
children: "(已探测)"
|
|
2990
|
+
}) : void 0]
|
|
2902
2991
|
}),
|
|
2903
2992
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2904
2993
|
style: inputStyle$1,
|
|
2905
2994
|
value: form.remoteDshHome,
|
|
2906
|
-
placeholder: "
|
|
2995
|
+
placeholder: "点击上方按钮通过 SSH 自动探测",
|
|
2907
2996
|
onChange: (e) => setForm((c) => ({
|
|
2908
2997
|
...c,
|
|
2909
2998
|
remoteDshHome: e.target.value
|
|
@@ -2911,7 +3000,7 @@ window.__ModuleLoader__.load({
|
|
|
2911
3000
|
}),
|
|
2912
3001
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2913
3002
|
style: hint,
|
|
2914
|
-
children: "
|
|
3003
|
+
children: remoteProbe?.homes.length ? `探测到 ${remoteProbe.homes.length} 个候选目录,已回填首个命中` : "留空时由探测自动发现;也可手动填写远端 DSH 数据目录"
|
|
2915
3004
|
})
|
|
2916
3005
|
]
|
|
2917
3006
|
}),
|
|
@@ -2919,24 +3008,46 @@ window.__ModuleLoader__.load({
|
|
|
2919
3008
|
className: "dshb-sync-two-col",
|
|
2920
3009
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2921
3010
|
style: field,
|
|
2922
|
-
children: [
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
})
|
|
2933
|
-
|
|
3011
|
+
children: [
|
|
3012
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3013
|
+
style: label,
|
|
3014
|
+
children: ["远端 profile", remoteProbe?.profiles.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3015
|
+
style: {
|
|
3016
|
+
fontWeight: 400,
|
|
3017
|
+
opacity: .55
|
|
3018
|
+
},
|
|
3019
|
+
children: "(已探测)"
|
|
3020
|
+
}) : void 0]
|
|
3021
|
+
}),
|
|
3022
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
3023
|
+
style: inputStyle$1,
|
|
3024
|
+
value: form.remoteProfile,
|
|
3025
|
+
onChange: (e) => setForm((c) => ({
|
|
3026
|
+
...c,
|
|
3027
|
+
remoteProfile: e.target.value
|
|
3028
|
+
})),
|
|
3029
|
+
children: remoteProfileOptions(form, remoteProbe).map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
3030
|
+
value: option.name,
|
|
3031
|
+
children: [option.name, option.dshbInstalled === true ? "(DSHB 已安装)" : option.dshbInstalled === false ? "(未安装 DSHB)" : ""]
|
|
3032
|
+
}, option.name))
|
|
3033
|
+
}),
|
|
3034
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3035
|
+
style: hint,
|
|
3036
|
+
children: "由探测列出;未探测时默认 web"
|
|
3037
|
+
})
|
|
3038
|
+
]
|
|
2934
3039
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2935
3040
|
style: field,
|
|
2936
3041
|
children: [
|
|
2937
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3042
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2938
3043
|
style: label,
|
|
2939
|
-
children: "远端 Web 端口"
|
|
3044
|
+
children: ["远端 Web 端口", remoteProbe?.webPort !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3045
|
+
style: {
|
|
3046
|
+
fontWeight: 400,
|
|
3047
|
+
opacity: .55
|
|
3048
|
+
},
|
|
3049
|
+
children: "(已探测)"
|
|
3050
|
+
}) : void 0]
|
|
2940
3051
|
}),
|
|
2941
3052
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2942
3053
|
style: inputStyle$1,
|
|
@@ -2950,7 +3061,7 @@ window.__ModuleLoader__.load({
|
|
|
2950
3061
|
}),
|
|
2951
3062
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2952
3063
|
style: hint,
|
|
2953
|
-
children: "留空使用默认 3080"
|
|
3064
|
+
children: remoteProbe?.webPort !== void 0 ? `已回填 ${remoteProbe.webPort}${remoteProbe.instanceId ? `(实例 ${remoteProbe.instanceId.slice(0, 14)}…)` : ""}${(remoteProbe.handshakes?.length ?? 0) > 1 ? `;同机检测到多个实例:${remoteProbe.handshakes?.map((hit) => hit.port).join("、") ?? ""}` : ""}` : "留空使用默认 3080;桌面版远端也走本机回环,无需公网暴露"
|
|
2954
3065
|
})
|
|
2955
3066
|
]
|
|
2956
3067
|
})]
|