@devframes/hub 0.8.0 → 0.8.2

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.
@@ -1,8 +1,8 @@
1
1
  import { N as NavTarget, O as DevframeViewIframe, P as RemoteConnectionInfo, a as DevframeCommandEntry, g as DevframeDockEntry, h as DevframeDockEntriesGrouped, n as DevframeClientCommand, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings, x as DevframeDockUserEntry, y as DevframeDockEntryIcon } from "../settings-Byh48aCd.mjs";
2
2
  import { DEFAULT_CATEGORIES_ORDER } from "../constants.mjs";
3
- import { w as DevframeMessagesClient, y as DevframeMessageEntryInput } from "../context-Cw5sDVoA.mjs";
4
- import "../index-Bx3T-R7i.mjs";
5
- import { DevframeClientRpcHost, DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientOptions, DevframeRpcContext, RpcClientEvents, RpcClientEvents as RpcClientEvents$1 } from "devframe/client";
3
+ import { w as DevframeMessagesClient, y as DevframeMessageEntryInput } from "../context-BSgzLnsu.mjs";
4
+ import "../index-IzywMKfP.mjs";
5
+ import { DevframeClientRpcHost, DevframeConnection, DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientOptions, DevframeRpcContext, RpcClientEvents, RpcClientEvents as RpcClientEvents$1 } from "devframe/client";
6
6
  import { EventEmitter } from "devframe/types";
7
7
  import { SharedState } from "devframe/utils/shared-state";
8
8
  import { WhenContext } from "devframe/utils/when";
@@ -256,6 +256,16 @@ declare function getDevframeClientContext(): DevframeClientContext | undefined;
256
256
  */
257
257
  declare function setDevframeClientContext(ctx: DevframeClientContext | undefined): void;
258
258
  //#endregion
259
+ //#region src/client/dock-resources.d.ts
260
+ /**
261
+ * Resolve a dock iframe URL relative to the Devframe server that provided the
262
+ * dock entry. This keeps root-relative and dot-relative paths on the host
263
+ * server when an external viewer renders the hub.
264
+ */
265
+ declare function resolveDockUrl(url: string, connection: DevframeConnection): string;
266
+ /** Resolve URL-backed dock icons while preserving Iconify names and data URLs. */
267
+ declare function resolveDockIcon(icon: DevframeDockEntryIcon, connection: DevframeConnection): DevframeDockEntryIcon;
268
+ //#endregion
259
269
  //#region src/client/frame-nav.d.ts
260
270
  /**
261
271
  * Shared-iframe soft navigation — the viewer-side half of a host↔iframe
@@ -463,8 +473,18 @@ interface MessagesClientOptions {
463
473
  */
464
474
  declare function createMessagesClient(rpc: DevframeRpcClient, options?: MessagesClientOptions): DevframeMessagesClient;
465
475
  //#endregion
476
+ //#region src/remote-url.d.ts
477
+ /** Remove the remote connection descriptor from a URL before displaying or copying it. */
478
+ declare function stripRemoteConnectionFromUrl(input: string): string;
479
+ //#endregion
466
480
  //#region src/client/remote.d.ts
467
481
  type ConnectRemoteDevframeOptions = Omit<DevframeRpcClientOptions, 'connectionMeta' | 'authToken'>;
482
+ /**
483
+ * Build an external viewer URL from an existing trusted Devframe connection.
484
+ * Returns the original URL if the connection has no auth token, does not use
485
+ * WebSockets, or has an invalid metadata URL.
486
+ */
487
+ declare function buildRemoteDevframeUrl(url: string, connection: DevframeConnection): string;
468
488
  /**
469
489
  * Parse a {@link RemoteConnectionInfo} descriptor from the current page's URL
470
490
  * (or a provided URL/string). Checks the URL fragment first, then the query.
@@ -484,4 +504,4 @@ declare function parseRemoteConnection(input?: string): RemoteConnectionInfo | n
484
504
  */
485
505
  declare function connectRemoteDevframe(options?: ConnectRemoteDevframeOptions): Promise<DevframeRpcClient>;
486
506
  //#endregion
487
- export { CLIENT_CONTEXT_KEY, CommandsContext, ConnectRemoteDevframeOptions, DEFAULT_CATEGORIES_ORDER, DevframeClientContext, DevframeClientHost, DevframeClientHostOptions, type DevframeClientRpcHost, DockClientScriptContext, DockClientType, DockEntryState, DockEntryStateEvents, DockPanelStorage, DockRegistration, DockRenderer, DockRendererInstance, DockRendererMountOptions, DockRenderersContext, DocksConnectionContext, DocksContext, DocksEntriesContext, DocksPanelContext, FRAME_NAV_CHANNEL, FRAME_NAV_VERSION, FrameNavClient, FrameNavClientOptions, FrameNavEnvelope, FrameNavFrameMessage, FrameNavHostMessage, FrameNavHostPayload, FrameNavListenTarget, FrameTab, MessagesClientOptions, type RpcClientEvents, WhenClauseContext, attachFrameNavClient, connectRemoteDevframe, createDevframeClientHost, createMessagesClient, getDevframeClientContext, parseRemoteConnection, setDevframeClientContext };
507
+ export { CLIENT_CONTEXT_KEY, CommandsContext, ConnectRemoteDevframeOptions, DEFAULT_CATEGORIES_ORDER, DevframeClientContext, DevframeClientHost, DevframeClientHostOptions, type DevframeClientRpcHost, DockClientScriptContext, DockClientType, DockEntryState, DockEntryStateEvents, DockPanelStorage, DockRegistration, DockRenderer, DockRendererInstance, DockRendererMountOptions, DockRenderersContext, DocksConnectionContext, DocksContext, DocksEntriesContext, DocksPanelContext, FRAME_NAV_CHANNEL, FRAME_NAV_VERSION, FrameNavClient, FrameNavClientOptions, FrameNavEnvelope, FrameNavFrameMessage, FrameNavHostMessage, FrameNavHostPayload, FrameNavListenTarget, FrameTab, MessagesClientOptions, type RpcClientEvents, WhenClauseContext, attachFrameNavClient, buildRemoteDevframeUrl, connectRemoteDevframe, createDevframeClientHost, createMessagesClient, getDevframeClientContext, parseRemoteConnection, resolveDockIcon, resolveDockUrl, setDevframeClientContext, stripRemoteConnectionFromUrl };
@@ -1,6 +1,7 @@
1
1
  import { DEFAULT_CATEGORIES_ORDER, DEFAULT_STATE_USER_SETTINGS } from "../constants.mjs";
2
+ import { n as stripRemoteConnectionFromUrl, t as buildRemoteConnectionUrl } from "../remote-url-KVXtKP47.mjs";
2
3
  import { REMOTE_CONNECTION_KEY } from "devframe/constants";
3
- import { connectDevframe, getDevframeRpcClient } from "devframe/client";
4
+ import { connectDevframe, getDevframeRpcClient, resolveWsUrl } from "devframe/client";
4
5
  import { createEventEmitter } from "devframe/utils/events";
5
6
  import { destr } from "destr";
6
7
  export * from "devframe/client";
@@ -21,6 +22,53 @@ function setDevframeClientContext(ctx) {
21
22
  globalThis[CLIENT_CONTEXT_KEY] = ctx;
22
23
  }
23
24
  //#endregion
25
+ //#region src/client/dock-resources.ts
26
+ const URL_SCHEME_RE = /^[a-z][a-z\d+.-]*:/i;
27
+ function resolveResourceUrl(value, connection) {
28
+ const url = value.trim();
29
+ if (!url || URL_SCHEME_RE.test(url) || url.startsWith("//")) return url;
30
+ if (!url.startsWith("/") && !url.startsWith("./") && !url.startsWith("../")) return url;
31
+ try {
32
+ return new URL(url, connection.metaBaseUrl).href;
33
+ } catch {
34
+ return url;
35
+ }
36
+ }
37
+ function resolveIconUrl(value, connection) {
38
+ const url = value.trim();
39
+ if (!url || URL_SCHEME_RE.test(url) || url.startsWith("//")) return url;
40
+ if (!url.includes("/") && !url.includes(".")) return url;
41
+ try {
42
+ return new URL(url, connection.metaBaseUrl).href;
43
+ } catch {
44
+ return url;
45
+ }
46
+ }
47
+ /**
48
+ * Resolve a dock iframe URL relative to the Devframe server that provided the
49
+ * dock entry. This keeps root-relative and dot-relative paths on the host
50
+ * server when an external viewer renders the hub.
51
+ */
52
+ function resolveDockUrl(url, connection) {
53
+ const resolved = resolveResourceUrl(url, connection);
54
+ if (resolved !== url.trim()) return resolved;
55
+ const value = url.trim();
56
+ if (!value || URL_SCHEME_RE.test(value) || value.startsWith("//")) return /^localhost:\d/i.test(value) ? `http://${value}` : value;
57
+ try {
58
+ return new URL(`http://${value}`).href;
59
+ } catch {
60
+ return value;
61
+ }
62
+ }
63
+ /** Resolve URL-backed dock icons while preserving Iconify names and data URLs. */
64
+ function resolveDockIcon(icon, connection) {
65
+ if (typeof icon === "string") return resolveIconUrl(icon, connection);
66
+ return {
67
+ light: resolveIconUrl(icon.light, connection),
68
+ dark: resolveIconUrl(icon.dark, connection)
69
+ };
70
+ }
71
+ //#endregion
24
72
  //#region src/client/frame-nav.ts
25
73
  /**
26
74
  * Shared-iframe soft navigation — the viewer-side half of a host↔iframe
@@ -650,6 +698,27 @@ function base64UrlDecode(value) {
650
698
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
651
699
  return new TextDecoder().decode(bytes);
652
700
  }
701
+ /**
702
+ * Build an external viewer URL from an existing trusted Devframe connection.
703
+ * Returns the original URL if the connection has no auth token, does not use
704
+ * WebSockets, or has an invalid metadata URL.
705
+ */
706
+ function buildRemoteDevframeUrl(url, connection) {
707
+ if (!connection.authToken || connection.connectionMeta.backend !== "websocket") return url;
708
+ let base;
709
+ try {
710
+ base = new URL(connection.metaBaseUrl);
711
+ } catch {
712
+ return url;
713
+ }
714
+ return buildRemoteConnectionUrl(url, {
715
+ v: 1,
716
+ backend: "websocket",
717
+ websocket: resolveWsUrl(connection.connectionMeta.websocket, connection.metaBaseUrl, base),
718
+ authToken: connection.authToken,
719
+ origin: base.origin
720
+ });
721
+ }
653
722
  function extractKeyFromFragment(hash) {
654
723
  if (!hash) return null;
655
724
  const raw = hash.startsWith("#") ? hash.slice(1) : hash;
@@ -726,4 +795,4 @@ async function connectRemoteDevframe(options = {}) {
726
795
  });
727
796
  }
728
797
  //#endregion
729
- export { CLIENT_CONTEXT_KEY, DEFAULT_CATEGORIES_ORDER, FRAME_NAV_CHANNEL, FRAME_NAV_VERSION, attachFrameNavClient, connectRemoteDevframe, createDevframeClientHost, createMessagesClient, getDevframeClientContext, parseRemoteConnection, setDevframeClientContext };
798
+ export { CLIENT_CONTEXT_KEY, DEFAULT_CATEGORIES_ORDER, FRAME_NAV_CHANNEL, FRAME_NAV_VERSION, attachFrameNavClient, buildRemoteDevframeUrl, connectRemoteDevframe, createDevframeClientHost, createMessagesClient, getDevframeClientContext, parseRemoteConnection, resolveDockIcon, resolveDockUrl, setDevframeClientContext, stripRemoteConnectionFromUrl };
@@ -319,6 +319,7 @@ interface DevframeChildProcessTerminalSession extends DevframeTerminalSession {
319
319
  */
320
320
  getResult: () => DevframeChildProcessResult;
321
321
  terminate: () => Promise<void>;
322
+ /** Throws `DF8206` once the session's output stream has closed (after a natural exit or `terminate()`) — drop it with `ctx.terminals.remove(session)` and start a fresh session instead. */
322
323
  restart: () => Promise<void>;
323
324
  }
324
325
  interface DevframePtyExecuteOptions {
@@ -342,6 +343,7 @@ interface DevframePtyTerminalSession extends DevframeTerminalSession {
342
343
  /** Current foreground process name, when the backend can resolve it. */
343
344
  getProcessName: () => string | undefined;
344
345
  terminate: () => Promise<void>;
346
+ /** Throws `DF8206` once the session's output stream has closed (after a natural exit or `terminate()`) — drop it with `ctx.terminals.remove(session)` and start a fresh session instead. */
345
347
  restart: () => Promise<void>;
346
348
  }
347
349
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import "./settings-Byh48aCd.mjs";
2
- import "./context-Cw5sDVoA.mjs";
2
+ import "./context-BSgzLnsu.mjs";
3
3
  import { RpcDefinitionsFilter, RpcDefinitionsToFunctions } from "devframe/rpc";
4
4
  import { ConnectionMeta as ConnectionMeta$1, DevframeCapabilities, DevframeDiagnosticsDefinition, DevframeDiagnosticsHost, DevframeDiagnosticsLogger, DevframeHost as DevframeHost$1, DevframeNodeRpcSession, DevframeRpcClientFunctions, DevframeRpcServerFunctions, DevframeRpcSharedStates, DevframeViewHost, EntriesToObject, EventEmitter as EventEmitter$1, EventUnsubscribe, EventsMap, PartialWithoutId, RpcBroadcastOptions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, RpcStreamingChannel, RpcStreamingChannelOptions, RpcStreamingHost, Thenable } from "devframe/types";
5
5
  export { RpcStreamingChannel as C, Thenable as E, RpcSharedStateHost as S, RpcStreamingHost as T, RpcBroadcastOptions as _, DevframeDiagnosticsLogger as a, RpcFunctionsHost as b, DevframeRpcClientFunctions as c, DevframeViewHost as d, EntriesToObject as f, PartialWithoutId as g, EventsMap as h, DevframeDiagnosticsHost as i, DevframeRpcServerFunctions as l, EventUnsubscribe as m, DevframeCapabilities as n, DevframeHost$1 as o, EventEmitter$1 as p, DevframeDiagnosticsDefinition as r, DevframeNodeRpcSession as s, ConnectionMeta$1 as t, DevframeRpcSharedStates as u, RpcDefinitionsFilter as v, RpcStreamingChannelOptions as w, RpcSharedStateGetOptions as x, RpcDefinitionsToFunctions as y };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { A as DevframeViewLauncher, C as DevframeDocksHost, D as DevframeViewGroup, E as DevframeViewCustomRender, F as RemoteDockOptions, I as JsonRenderElement, L as JsonRenderSpec, M as FrameSubTabsConfig, N as NavTarget, O as DevframeViewIframe, P as RemoteConnectionInfo, R as JsonRenderer, S as DevframeDocksActiveState, T as DevframeViewBuiltin, _ as DevframeDockEntryBase, a as DevframeCommandEntry, b as DevframeDockEntryRegistry, c as DevframeCommandShortcutOverrides, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, g as DevframeDockEntry, h as DevframeDockEntriesGrouped, i as DevframeCommandBase, j as DevframeViewLauncherStatus, k as DevframeViewJsonRender, l as DevframeCommandsHost, m as DevframeDockActivation, n as DevframeClientCommand, o as DevframeCommandHandle, p as ClientScriptEntry, r as DevframeCommandAgentOptions, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings, u as DevframeCommandsHostEvents, v as DevframeDockEntryCategory, w as DevframeViewAction, x as DevframeDockUserEntry, y as DevframeDockEntryIcon } from "./settings-Byh48aCd.mjs";
2
2
  import { DEFAULT_CATEGORIES_ORDER } from "./constants.mjs";
3
- import { C as DevframeMessageShortcutInput, D as DevframeMessagesListDelta, E as DevframeMessagesLevelShortcuts, S as DevframeMessageLevel, T as DevframeMessagesHost, _ as DevframeMessageEntry, a as DevframeChildProcessOutput, b as DevframeMessageFilePosition, c as DevframePtyExecuteOptions, d as DevframeTerminalSessionBase, f as DevframeTerminalStatus, g as DevframeMessageElementPosition, h as DevframeMessageActivateAction, i as DevframeChildProcessExecuteOptions, l as DevframePtyTerminalSession, m as DevframeMessageAction, n as DevframeHubContext, o as DevframeChildProcessResult, p as DevframeTerminalsHost, s as DevframeChildProcessTerminalSession, t as CreateHubContextOptions, u as DevframeTerminalSession, v as DevframeMessageEntryFrom, w as DevframeMessagesClient, x as DevframeMessageHandle, y as DevframeMessageEntryInput } from "./context-Cw5sDVoA.mjs";
4
- import { C as RpcStreamingChannel, E as Thenable, S as RpcSharedStateHost, T as RpcStreamingHost, _ as RpcBroadcastOptions, a as DevframeDiagnosticsLogger, b as RpcFunctionsHost, c as DevframeRpcClientFunctions, d as DevframeViewHost, f as EntriesToObject, g as PartialWithoutId, h as EventsMap, i as DevframeDiagnosticsHost, l as DevframeRpcServerFunctions, m as EventUnsubscribe, n as DevframeCapabilities, o as DevframeHost, p as EventEmitter, r as DevframeDiagnosticsDefinition, s as DevframeNodeRpcSession, t as ConnectionMeta, u as DevframeRpcSharedStates, v as RpcDefinitionsFilter, w as RpcStreamingChannelOptions, x as RpcSharedStateGetOptions, y as RpcDefinitionsToFunctions } from "./index-Bx3T-R7i.mjs";
3
+ import { C as DevframeMessageShortcutInput, D as DevframeMessagesListDelta, E as DevframeMessagesLevelShortcuts, S as DevframeMessageLevel, T as DevframeMessagesHost, _ as DevframeMessageEntry, a as DevframeChildProcessOutput, b as DevframeMessageFilePosition, c as DevframePtyExecuteOptions, d as DevframeTerminalSessionBase, f as DevframeTerminalStatus, g as DevframeMessageElementPosition, h as DevframeMessageActivateAction, i as DevframeChildProcessExecuteOptions, l as DevframePtyTerminalSession, m as DevframeMessageAction, n as DevframeHubContext, o as DevframeChildProcessResult, p as DevframeTerminalsHost, s as DevframeChildProcessTerminalSession, t as CreateHubContextOptions, u as DevframeTerminalSession, v as DevframeMessageEntryFrom, w as DevframeMessagesClient, x as DevframeMessageHandle, y as DevframeMessageEntryInput } from "./context-BSgzLnsu.mjs";
4
+ import { C as RpcStreamingChannel, E as Thenable, S as RpcSharedStateHost, T as RpcStreamingHost, _ as RpcBroadcastOptions, a as DevframeDiagnosticsLogger, b as RpcFunctionsHost, c as DevframeRpcClientFunctions, d as DevframeViewHost, f as EntriesToObject, g as PartialWithoutId, h as EventsMap, i as DevframeDiagnosticsHost, l as DevframeRpcServerFunctions, m as EventUnsubscribe, n as DevframeCapabilities, o as DevframeHost, p as EventEmitter, r as DevframeDiagnosticsDefinition, s as DevframeNodeRpcSession, t as ConnectionMeta, u as DevframeRpcSharedStates, v as RpcDefinitionsFilter, w as RpcStreamingChannelOptions, x as RpcSharedStateGetOptions, y as RpcDefinitionsToFunctions } from "./index-IzywMKfP.mjs";
5
5
  import { WhenContext, WhenExpression } from "devframe/utils/when";
6
6
  //#region src/define.d.ts
7
7
  declare const defineHubRpcFunction: <NAME extends string, TYPE extends import("devframe/rpc").RpcFunctionType, ARGS extends any[], RETURN = void, const AS extends import("devframe/rpc").RpcArgsSchema | undefined = undefined, const RS extends import("devframe/rpc").RpcReturnSchema | undefined = undefined>(definition: import("devframe/rpc").RpcFunctionDefinition<NAME, TYPE, ARGS, RETURN, AS, RS, DevframeHubContext>) => import("devframe/rpc").RpcFunctionDefinition<NAME, TYPE, ARGS, RETURN, AS, RS, DevframeHubContext>;
@@ -1,6 +1,6 @@
1
1
  import { C as DevframeDocksHost$1, O as DevframeViewIframe, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, g as DevframeDockEntry, l as DevframeCommandsHost$1, o as DevframeCommandHandle, p as ClientScriptEntry, t as DevframeDocksUserSettings, x as DevframeDockUserEntry } from "../settings-Byh48aCd.mjs";
2
2
  import { DEFAULT_CATEGORIES_ORDER } from "../constants.mjs";
3
- import { C as DevframeMessageShortcutInput, D as DevframeMessagesListDelta, T as DevframeMessagesHost$1, _ as DevframeMessageEntry, c as DevframePtyExecuteOptions, d as DevframeTerminalSessionBase, i as DevframeChildProcessExecuteOptions, l as DevframePtyTerminalSession, n as DevframeHubContext, p as DevframeTerminalsHost$1, r as createHubContext, s as DevframeChildProcessTerminalSession, t as CreateHubContextOptions, u as DevframeTerminalSession, x as DevframeMessageHandle, y as DevframeMessageEntryInput } from "../context-Cw5sDVoA.mjs";
3
+ import { C as DevframeMessageShortcutInput, D as DevframeMessagesListDelta, T as DevframeMessagesHost$1, _ as DevframeMessageEntry, c as DevframePtyExecuteOptions, d as DevframeTerminalSessionBase, i as DevframeChildProcessExecuteOptions, l as DevframePtyTerminalSession, n as DevframeHubContext, p as DevframeTerminalsHost$1, r as createHubContext, s as DevframeChildProcessTerminalSession, t as CreateHubContextOptions, u as DevframeTerminalSession, x as DevframeMessageHandle, y as DevframeMessageEntryInput } from "../context-BSgzLnsu.mjs";
4
4
  import { RpcFunctionDefinitionAny } from "devframe/rpc";
5
5
  import { DevframeDefinition } from "devframe/types";
6
6
  import { SharedState } from "devframe/utils/shared-state";
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_CATEGORIES_ORDER, DEFAULT_STATE_USER_SETTINGS } from "../constants.mjs";
2
2
  import { r as defineHubRpcFunction } from "../define-Pbx8dsKz.mjs";
3
- import { REMOTE_CONNECTION_KEY } from "devframe/constants";
3
+ import { t as buildRemoteConnectionUrl } from "../remote-url-KVXtKP47.mjs";
4
4
  import { createEventEmitter } from "devframe/utils/events";
5
5
  import { coerceAgentPositionalArgs, createHostContext, createStorage } from "devframe/node";
6
6
  import { debounce } from "perfect-debounce";
@@ -76,6 +76,10 @@ const diagnostics = defineDiagnostics({
76
76
  why: (p) => `Terminal session "${p.id}" is not restartable`,
77
77
  fix: "It was registered with `restartable: false`; restart it through its owner's controls, or spawn it with `restartable: true` (the default) to allow in-place restarts."
78
78
  },
79
+ DF8206: {
80
+ why: (p) => `Terminal session "${p.id}" cannot be restarted — its output stream is already closed`,
81
+ fix: "The session already exited (or was terminated) and its stream is spent. Drop it with `ctx.terminals.remove(session)`, then spawn a replacement via `ctx.terminals.startChildProcess()` or `ctx.terminals.startPtySession()` with a fresh id."
82
+ },
79
83
  DF8400: { why: (p) => `Command "${p.id}" is already registered` },
80
84
  DF8401: { why: "Cannot change the id of a command. Use register() to add new commands" },
81
85
  DF8402: { why: (p) => `Command "${p.id}" is not registered` },
@@ -231,45 +235,6 @@ function normaliseRemoteOptions(remote) {
231
235
  originLock: opts.originLock ?? true
232
236
  };
233
237
  }
234
- function base64UrlEncode(value) {
235
- const bytes = new TextEncoder().encode(value);
236
- let binary = "";
237
- for (const byte of bytes) binary += String.fromCharCode(byte);
238
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
239
- }
240
- function buildRemoteUrl(baseUrl, payload, transport) {
241
- const encoded = base64UrlEncode(JSON.stringify(payload));
242
- const param = `${REMOTE_CONNECTION_KEY}=${encoded}`;
243
- if (transport === "fragment") {
244
- const hashIdx = baseUrl.indexOf("#");
245
- if (hashIdx === -1) return `${baseUrl}#${param}`;
246
- const before = baseUrl.slice(0, hashIdx);
247
- const rawHash = baseUrl.slice(hashIdx + 1);
248
- if (!rawHash) return `${before}#${param}`;
249
- const routeQueryIdx = rawHash.indexOf("?");
250
- if (routeQueryIdx !== -1) {
251
- const beforeQuery = rawHash.slice(0, routeQueryIdx + 1);
252
- const params = new URLSearchParams(rawHash.slice(routeQueryIdx + 1));
253
- params.set(REMOTE_CONNECTION_KEY, encoded);
254
- return `${before}#${beforeQuery}${params.toString()}`;
255
- }
256
- const parts = rawHash.split("&");
257
- const existingIdx = parts.findIndex((part) => {
258
- const [key] = part.split("=");
259
- return key === REMOTE_CONNECTION_KEY;
260
- });
261
- if (existingIdx >= 0) {
262
- parts[existingIdx] = param;
263
- return `${before}#${parts.join("&")}`;
264
- }
265
- return `${before}#${rawHash}&${param}`;
266
- }
267
- const qIdx = baseUrl.indexOf("?");
268
- const hashIdx = baseUrl.indexOf("#");
269
- const hash = hashIdx === -1 ? "" : baseUrl.slice(hashIdx);
270
- const beforeHash = hashIdx === -1 ? baseUrl : baseUrl.slice(0, hashIdx);
271
- return `${beforeHash}${qIdx === -1 || qIdx >= (hashIdx === -1 ? beforeHash.length : hashIdx) ? "?" : "&"}${param}${hash}`;
272
- }
273
238
  var DevframeDocksHost = class {
274
239
  context;
275
240
  views = /* @__PURE__ */ new Map();
@@ -303,7 +268,7 @@ var DevframeDocksHost = class {
303
268
  };
304
269
  return {
305
270
  ...view,
306
- url: buildRemoteUrl(view.url, payload, record.options.transport)
271
+ url: buildRemoteConnectionUrl(view.url, payload, record.options.transport)
307
272
  };
308
273
  }
309
274
  resolveDevServerOrigin() {
@@ -739,7 +704,7 @@ var DevframeTerminalsHost = class {
739
704
  }
740
705
  cp = createChildProcess();
741
706
  const restart = async () => {
742
- if (streamClosed) return;
707
+ if (streamClosed) throw diagnostics.DF8206({ id: terminal.id });
743
708
  cp?.kill();
744
709
  cp = createChildProcess();
745
710
  markStatus("running");
@@ -870,7 +835,7 @@ var DevframeTerminalsHost = class {
870
835
  markStatus("stopped");
871
836
  },
872
837
  restart: async () => {
873
- if (streamClosed) return;
838
+ if (streamClosed) throw diagnostics.DF8206({ id: terminal.id });
874
839
  pty?.kill();
875
840
  pty = spawnPty();
876
841
  markStatus("running");
@@ -0,0 +1,73 @@
1
+ import { REMOTE_CONNECTION_KEY } from "devframe/constants";
2
+ //#region src/remote-url.ts
3
+ function base64UrlEncode(value) {
4
+ const bytes = new TextEncoder().encode(value);
5
+ let binary = "";
6
+ for (const byte of bytes) binary += String.fromCharCode(byte);
7
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
8
+ }
9
+ function setRemoteConnectionParam(value, param) {
10
+ const parts = value ? value.split("&") : [];
11
+ const existingIdx = parts.findIndex((part) => part.split("=")[0] === REMOTE_CONNECTION_KEY);
12
+ if (existingIdx >= 0) parts[existingIdx] = param;
13
+ else parts.push(param);
14
+ return parts.join("&");
15
+ }
16
+ /** Encode a remote connection descriptor into an external viewer URL. */
17
+ function buildRemoteConnectionUrl(baseUrl, payload, transport = "fragment") {
18
+ const param = `${REMOTE_CONNECTION_KEY}=${base64UrlEncode(JSON.stringify(payload))}`;
19
+ if (transport === "fragment") {
20
+ const hashIdx = baseUrl.indexOf("#");
21
+ if (hashIdx === -1) return `${baseUrl}#${param}`;
22
+ const beforeHash = baseUrl.slice(0, hashIdx);
23
+ const rawHash = baseUrl.slice(hashIdx + 1);
24
+ if (!rawHash) return `${beforeHash}#${param}`;
25
+ const routeQueryIdx = rawHash.indexOf("?");
26
+ if (routeQueryIdx !== -1) return `${beforeHash}#${rawHash.slice(0, routeQueryIdx + 1)}${setRemoteConnectionParam(rawHash.slice(routeQueryIdx + 1), param)}`;
27
+ return `${beforeHash}#${setRemoteConnectionParam(rawHash, param)}`;
28
+ }
29
+ const hashIdx = baseUrl.indexOf("#");
30
+ const hash = hashIdx === -1 ? "" : baseUrl.slice(hashIdx);
31
+ const beforeHash = hashIdx === -1 ? baseUrl : baseUrl.slice(0, hashIdx);
32
+ return `${beforeHash}${beforeHash.includes("?") ? "&" : "?"}${param}${hash}`;
33
+ }
34
+ /** Remove the remote connection descriptor from a URL before displaying or copying it. */
35
+ function stripRemoteConnectionFromUrl(input) {
36
+ function stripParamList(value) {
37
+ const parts = value.split("&");
38
+ const filtered = parts.filter((part) => part.split("=")[0] !== REMOTE_CONNECTION_KEY);
39
+ return [filtered.join("&"), filtered.length !== parts.length];
40
+ }
41
+ const hashIdx = input.indexOf("#");
42
+ let beforeHash = hashIdx === -1 ? input : input.slice(0, hashIdx);
43
+ let hash = hashIdx === -1 ? void 0 : input.slice(hashIdx + 1);
44
+ let changed = false;
45
+ if (hash !== void 0) {
46
+ const routeQueryIdx = hash.indexOf("?");
47
+ if (routeQueryIdx === -1) {
48
+ const [nextHash, didChange] = stripParamList(hash);
49
+ hash = nextHash;
50
+ changed ||= didChange;
51
+ } else {
52
+ const route = hash.slice(0, routeQueryIdx);
53
+ const [query, didChange] = stripParamList(hash.slice(routeQueryIdx + 1));
54
+ if (didChange) {
55
+ hash = query ? `${route}?${query}` : route;
56
+ changed = true;
57
+ }
58
+ }
59
+ }
60
+ const queryIdx = beforeHash.indexOf("?");
61
+ if (queryIdx !== -1) {
62
+ const path = beforeHash.slice(0, queryIdx);
63
+ const [query, didChange] = stripParamList(beforeHash.slice(queryIdx + 1));
64
+ if (didChange) {
65
+ beforeHash = query ? `${path}?${query}` : path;
66
+ changed = true;
67
+ }
68
+ }
69
+ if (!changed) return input;
70
+ return hash ? `${beforeHash}#${hash}` : beforeHash;
71
+ }
72
+ //#endregion
73
+ export { stripRemoteConnectionFromUrl as n, buildRemoteConnectionUrl as t };
@@ -1,4 +1,4 @@
1
1
  import { A as DevframeViewLauncher, C as DevframeDocksHost, D as DevframeViewGroup, E as DevframeViewCustomRender, F as RemoteDockOptions, I as JsonRenderElement, L as JsonRenderSpec, M as FrameSubTabsConfig, N as NavTarget, O as DevframeViewIframe, P as RemoteConnectionInfo, R as JsonRenderer, S as DevframeDocksActiveState, T as DevframeViewBuiltin, _ as DevframeDockEntryBase, a as DevframeCommandEntry, b as DevframeDockEntryRegistry, c as DevframeCommandShortcutOverrides, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, g as DevframeDockEntry, h as DevframeDockEntriesGrouped, i as DevframeCommandBase, j as DevframeViewLauncherStatus, k as DevframeViewJsonRender, l as DevframeCommandsHost, m as DevframeDockActivation, n as DevframeClientCommand, o as DevframeCommandHandle, p as ClientScriptEntry, r as DevframeCommandAgentOptions, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings, u as DevframeCommandsHostEvents, v as DevframeDockEntryCategory, w as DevframeViewAction, x as DevframeDockUserEntry, y as DevframeDockEntryIcon } from "../settings-Byh48aCd.mjs";
2
- import { C as DevframeMessageShortcutInput, D as DevframeMessagesListDelta, E as DevframeMessagesLevelShortcuts, S as DevframeMessageLevel, T as DevframeMessagesHost, _ as DevframeMessageEntry, a as DevframeChildProcessOutput, b as DevframeMessageFilePosition, c as DevframePtyExecuteOptions, d as DevframeTerminalSessionBase, f as DevframeTerminalStatus, g as DevframeMessageElementPosition, h as DevframeMessageActivateAction, i as DevframeChildProcessExecuteOptions, l as DevframePtyTerminalSession, m as DevframeMessageAction, n as DevframeHubContext, o as DevframeChildProcessResult, p as DevframeTerminalsHost, s as DevframeChildProcessTerminalSession, t as CreateHubContextOptions, u as DevframeTerminalSession, v as DevframeMessageEntryFrom, w as DevframeMessagesClient, x as DevframeMessageHandle, y as DevframeMessageEntryInput } from "../context-Cw5sDVoA.mjs";
3
- import { C as RpcStreamingChannel, E as Thenable, S as RpcSharedStateHost, T as RpcStreamingHost, _ as RpcBroadcastOptions, a as DevframeDiagnosticsLogger, b as RpcFunctionsHost, c as DevframeRpcClientFunctions, d as DevframeViewHost, f as EntriesToObject, g as PartialWithoutId, h as EventsMap, i as DevframeDiagnosticsHost, l as DevframeRpcServerFunctions, m as EventUnsubscribe, n as DevframeCapabilities, o as DevframeHost, p as EventEmitter, r as DevframeDiagnosticsDefinition, s as DevframeNodeRpcSession, t as ConnectionMeta, u as DevframeRpcSharedStates, v as RpcDefinitionsFilter, w as RpcStreamingChannelOptions, x as RpcSharedStateGetOptions, y as RpcDefinitionsToFunctions } from "../index-Bx3T-R7i.mjs";
2
+ import { C as DevframeMessageShortcutInput, D as DevframeMessagesListDelta, E as DevframeMessagesLevelShortcuts, S as DevframeMessageLevel, T as DevframeMessagesHost, _ as DevframeMessageEntry, a as DevframeChildProcessOutput, b as DevframeMessageFilePosition, c as DevframePtyExecuteOptions, d as DevframeTerminalSessionBase, f as DevframeTerminalStatus, g as DevframeMessageElementPosition, h as DevframeMessageActivateAction, i as DevframeChildProcessExecuteOptions, l as DevframePtyTerminalSession, m as DevframeMessageAction, n as DevframeHubContext, o as DevframeChildProcessResult, p as DevframeTerminalsHost, s as DevframeChildProcessTerminalSession, t as CreateHubContextOptions, u as DevframeTerminalSession, v as DevframeMessageEntryFrom, w as DevframeMessagesClient, x as DevframeMessageHandle, y as DevframeMessageEntryInput } from "../context-BSgzLnsu.mjs";
3
+ import { C as RpcStreamingChannel, E as Thenable, S as RpcSharedStateHost, T as RpcStreamingHost, _ as RpcBroadcastOptions, a as DevframeDiagnosticsLogger, b as RpcFunctionsHost, c as DevframeRpcClientFunctions, d as DevframeViewHost, f as EntriesToObject, g as PartialWithoutId, h as EventsMap, i as DevframeDiagnosticsHost, l as DevframeRpcServerFunctions, m as EventUnsubscribe, n as DevframeCapabilities, o as DevframeHost, p as EventEmitter, r as DevframeDiagnosticsDefinition, s as DevframeNodeRpcSession, t as ConnectionMeta, u as DevframeRpcSharedStates, v as RpcDefinitionsFilter, w as RpcStreamingChannelOptions, x as RpcSharedStateGetOptions, y as RpcDefinitionsToFunctions } from "../index-IzywMKfP.mjs";
4
4
  export { ClientScriptEntry, type ConnectionMeta, type CreateHubContextOptions, type DevframeCapabilities, DevframeChildProcessExecuteOptions, DevframeChildProcessOutput, DevframeChildProcessResult, DevframeChildProcessTerminalSession, DevframeClientCommand, DevframeCommandAgentOptions, DevframeCommandBase, DevframeCommandEntry, DevframeCommandHandle, DevframeCommandKeybinding, DevframeCommandShortcutOverrides, DevframeCommandsHost, DevframeCommandsHostEvents, type DevframeDiagnosticsDefinition, type DevframeDiagnosticsHost, type DevframeDiagnosticsLogger, DevframeDockActivation, DevframeDockEntriesGrouped, DevframeDockEntry, DevframeDockEntryBase, DevframeDockEntryCategory, DevframeDockEntryIcon, DevframeDockEntryRegistry, DevframeDockUserEntry, DevframeDocksActiveState, DevframeDocksHost, DevframeDocksUserSettings, type DevframeHost, type DevframeHubContext, DevframeMessageAction, DevframeMessageActivateAction, DevframeMessageElementPosition, DevframeMessageEntry, DevframeMessageEntryFrom, DevframeMessageEntryInput, DevframeMessageFilePosition, DevframeMessageHandle, DevframeMessageLevel, DevframeMessageShortcutInput, DevframeMessagesClient, DevframeMessagesHost, DevframeMessagesLevelShortcuts, DevframeMessagesListDelta, type DevframeNodeRpcSession, DevframePtyExecuteOptions, DevframePtyTerminalSession, type DevframeRpcClientFunctions, type DevframeRpcServerFunctions, type DevframeRpcSharedStates, DevframeServerCommandEntry, DevframeServerCommandInput, DevframeTerminalSession, DevframeTerminalSessionBase, DevframeTerminalStatus, DevframeTerminalsHost, DevframeViewAction, DevframeViewBuiltin, DevframeViewCustomRender, DevframeViewGroup, type DevframeViewHost, DevframeViewIframe, DevframeViewJsonRender, DevframeViewLauncher, DevframeViewLauncherStatus, type EntriesToObject, type EventEmitter, type EventUnsubscribe, type EventsMap, FrameSubTabsConfig, JsonRenderElement, JsonRenderSpec, JsonRenderer, NavTarget, type PartialWithoutId, RemoteConnectionInfo, RemoteDockOptions, type RpcBroadcastOptions, type RpcDefinitionsFilter, type RpcDefinitionsToFunctions, type RpcFunctionsHost, type RpcSharedStateGetOptions, type RpcSharedStateHost, type RpcStreamingChannel, type RpcStreamingChannelOptions, type RpcStreamingHost, type Thenable };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devframes/hub",
3
3
  "type": "module",
4
- "version": "0.8.0",
4
+ "version": "0.8.2",
5
5
  "description": "Framework-neutral hub layer for devframe — docks, terminals, messages, commands.",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  "dist"
34
34
  ],
35
35
  "peerDependencies": {
36
- "devframe": "0.8.0"
36
+ "devframe": "0.8.2"
37
37
  },
38
38
  "dependencies": {
39
39
  "@standard-schema/spec": "^1.1.0",
@@ -41,7 +41,7 @@
41
41
  "nostics": "^1.2.0",
42
42
  "pathe": "^2.0.3",
43
43
  "perfect-debounce": "^2.1.0",
44
- "tinyexec": "^1.2.4",
44
+ "tinyexec": "^1.3.0",
45
45
  "zigpty": "^0.2.1"
46
46
  },
47
47
  "devDependencies": {
@@ -49,7 +49,7 @@
49
49
  "mlly": "^1.8.2",
50
50
  "tsdown": "^0.22.14",
51
51
  "valibot": "^1.4.2",
52
- "devframe": "0.8.0"
52
+ "devframe": "0.8.2"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "tsdown",