@linxin666/dsh-ssh 0.4.3 → 0.4.4
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 +72 -6
- package/lib/client.js.map +1 -1
- package/lib/types/client/api.d.ts +28 -0
- package/lib/types/client/locales.d.ts +1 -0
- package/package.json +17 -17
- package/src/client/api.ts +86 -3
- package/src/client/index.ts +3 -3
- package/src/client/locales.ts +2 -0
package/lib/client.js
CHANGED
|
@@ -115,6 +115,7 @@ window.__ModuleLoader__.load({
|
|
|
115
115
|
"terminal.ready": "终端已连接({alias})",
|
|
116
116
|
"terminal.exited": "终端已退出({alias})",
|
|
117
117
|
"terminal.error": "终端错误:{error}",
|
|
118
|
+
"terminal.noWebSocket": "当前页面不支持 WebSocket(应用外壳只转发 HTTP),请改用浏览器打开的 Web 界面使用终端。",
|
|
118
119
|
"terminal.auth.title": "二次身份验证 (2FA / 交互式认证)",
|
|
119
120
|
"terminal.auth.submit": "提交验证码",
|
|
120
121
|
"terminal.auth.cancel": "取消",
|
|
@@ -270,6 +271,7 @@ window.__ModuleLoader__.load({
|
|
|
270
271
|
"terminal.ready": "Terminal connected ({alias})",
|
|
271
272
|
"terminal.exited": "Terminal exited ({alias})",
|
|
272
273
|
"terminal.error": "Terminal error: {error}",
|
|
274
|
+
"terminal.noWebSocket": "This page cannot carry a WebSocket (the application shell forwards HTTP only). Open the Web UI in a browser to use the terminal.",
|
|
273
275
|
"terminal.auth.title": "Two-Factor Authentication (2FA)",
|
|
274
276
|
"terminal.auth.submit": "Submit Code",
|
|
275
277
|
"terminal.auth.cancel": "Cancel",
|
|
@@ -447,6 +449,63 @@ window.__ModuleLoader__.load({
|
|
|
447
449
|
const text = search.toString();
|
|
448
450
|
return text === "" ? "" : "?" + text;
|
|
449
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* The WebSocket URL the terminal route is reached at, or undefined when this
|
|
454
|
+
* page cannot carry one.
|
|
455
|
+
*
|
|
456
|
+
* A page delivered by an application on this machine (the official DSH
|
|
457
|
+
* Desktop shell serves its Web GUI from `dsh-app://app/`) has no WebSocket
|
|
458
|
+
* transport: its scheme handler forwards HTTP requests to the local host but
|
|
459
|
+
* cannot upgrade a socket, so `ws://app/...` never connects and the terminal
|
|
460
|
+
* reports "connection error" (issue #1744). Every other page is a web page and
|
|
461
|
+
* resolves the socket against its own origin, exactly as before.
|
|
462
|
+
*
|
|
463
|
+
* A blank authority is treated the same as an application scheme: there is
|
|
464
|
+
* nothing to dial, and the caller gets the actionable reason instead of a
|
|
465
|
+
* socket that can only fail.
|
|
466
|
+
*
|
|
467
|
+
* @param location - the page location to read.
|
|
468
|
+
* @param search - the query string carrying `alias` or `session`.
|
|
469
|
+
* @returns the absolute `ws:`/`wss:` URL, or undefined when the page cannot carry one.
|
|
470
|
+
*/
|
|
471
|
+
function terminalSocketUrl(location, search) {
|
|
472
|
+
if (WEB_PAGE_PROTOCOLS.includes(location.protocol)) return (location.protocol === "https:" ? "wss" : "ws") + "://" + location.host + SSH_API.terminal + search;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Schemes a network page can be delivered with. Every other scheme belongs to
|
|
476
|
+
* an application on this machine, which is the same classification the remote
|
|
477
|
+
* channel and the update seat use (`isWebPageProtocol` / `isApplicationDeliveredPage`).
|
|
478
|
+
*/
|
|
479
|
+
const WEB_PAGE_PROTOCOLS = [
|
|
480
|
+
"http:",
|
|
481
|
+
"https:",
|
|
482
|
+
"blob:",
|
|
483
|
+
"data:",
|
|
484
|
+
"about:",
|
|
485
|
+
"filesystem:"
|
|
486
|
+
];
|
|
487
|
+
/**
|
|
488
|
+
* A terminal connection that never opened: it reports one failure once the
|
|
489
|
+
* view has attached its `onExit`, so the tab shows why instead of sitting on a
|
|
490
|
+
* spinner, and every later frame is a no-op.
|
|
491
|
+
*/
|
|
492
|
+
function failedTerminal(reason) {
|
|
493
|
+
const connection = {
|
|
494
|
+
onReady: void 0,
|
|
495
|
+
onOutput: void 0,
|
|
496
|
+
onExit: void 0,
|
|
497
|
+
onAuthPrompt: void 0,
|
|
498
|
+
send: () => void 0,
|
|
499
|
+
resize: () => void 0,
|
|
500
|
+
sendAuthResponse: () => void 0,
|
|
501
|
+
detach: () => void 0,
|
|
502
|
+
close: () => void 0
|
|
503
|
+
};
|
|
504
|
+
queueMicrotask(() => {
|
|
505
|
+
connection.onExit?.(null, reason);
|
|
506
|
+
});
|
|
507
|
+
return connection;
|
|
508
|
+
}
|
|
450
509
|
/** The browser half's only data entry point. */
|
|
451
510
|
var SshApi = class {
|
|
452
511
|
async listHosts(queryText) {
|
|
@@ -674,8 +733,14 @@ window.__ModuleLoader__.load({
|
|
|
674
733
|
}
|
|
675
734
|
/** One terminal socket over either an alias (open) or a session id (attach). */
|
|
676
735
|
terminalSocket(search) {
|
|
677
|
-
const
|
|
678
|
-
|
|
736
|
+
const target = terminalSocketUrl(window.location, search);
|
|
737
|
+
if (target === void 0) return failedTerminal(tt("terminal.noWebSocket"));
|
|
738
|
+
let socket;
|
|
739
|
+
try {
|
|
740
|
+
socket = new WebSocket(target);
|
|
741
|
+
} catch (error) {
|
|
742
|
+
return failedTerminal(error instanceof Error ? error.message : String(error));
|
|
743
|
+
}
|
|
679
744
|
let leaving = false;
|
|
680
745
|
const sendFrame = (frame) => {
|
|
681
746
|
if (socket.readyState === WebSocket.OPEN) socket.send(JSON.stringify(frame));
|
|
@@ -16302,7 +16367,7 @@ window.__ModuleLoader__.load({
|
|
|
16302
16367
|
/** The building package's version, when the bundle carries it. */
|
|
16303
16368
|
function bakedVersion() {
|
|
16304
16369
|
try {
|
|
16305
|
-
return "0.4.
|
|
16370
|
+
return "0.4.4";
|
|
16306
16371
|
} catch {
|
|
16307
16372
|
return;
|
|
16308
16373
|
}
|
|
@@ -16379,7 +16444,8 @@ window.__ModuleLoader__.load({
|
|
|
16379
16444
|
const inject = [
|
|
16380
16445
|
"slots",
|
|
16381
16446
|
"locale",
|
|
16382
|
-
"configForms"
|
|
16447
|
+
"configForms",
|
|
16448
|
+
"layout"
|
|
16383
16449
|
];
|
|
16384
16450
|
/**
|
|
16385
16451
|
* Mount the SSH panel.
|
|
@@ -16401,7 +16467,7 @@ window.__ModuleLoader__.load({
|
|
|
16401
16467
|
setRuntimeTranslate(ctx.locale.bind(NS));
|
|
16402
16468
|
} catch {}
|
|
16403
16469
|
const controller = new PanelController({ panel: { select: (panelId) => {
|
|
16404
|
-
ctx.get("layout")?.selectPanel?.(panelId);
|
|
16470
|
+
(ctx.get?.("layout"))?.selectPanel?.(panelId);
|
|
16405
16471
|
} } });
|
|
16406
16472
|
const api = new SshApi();
|
|
16407
16473
|
const settings = bindSettingsReader(ctx, SETTINGS_NS, TERMINAL_FONT_FIELD);
|
|
@@ -16418,7 +16484,7 @@ window.__ModuleLoader__.load({
|
|
|
16418
16484
|
const disposers = [];
|
|
16419
16485
|
try {
|
|
16420
16486
|
disposers.push(registerSshPanel(ctx, controller, api, terminalFont));
|
|
16421
|
-
const layoutFace = ctx.get("layout");
|
|
16487
|
+
const layoutFace = ctx.get?.("layout");
|
|
16422
16488
|
if (layoutFace?.panelInfo !== void 0) {
|
|
16423
16489
|
const sync = () => {
|
|
16424
16490
|
const active = layoutFace.panelInfo.getSnapshot().activePanelId;
|