@devframes/hub 0.8.0 → 0.8.1
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/dist/client/index.d.mts +22 -2
- package/dist/client/index.mjs +71 -2
- package/dist/node/index.mjs +2 -41
- package/dist/remote-url-KVXtKP47.mjs +73 -0
- package/package.json +3 -3
package/dist/client/index.d.mts
CHANGED
|
@@ -2,7 +2,7 @@ import { N as NavTarget, O as DevframeViewIframe, P as RemoteConnectionInfo, a a
|
|
|
2
2
|
import { DEFAULT_CATEGORIES_ORDER } from "../constants.mjs";
|
|
3
3
|
import { w as DevframeMessagesClient, y as DevframeMessageEntryInput } from "../context-Cw5sDVoA.mjs";
|
|
4
4
|
import "../index-Bx3T-R7i.mjs";
|
|
5
|
-
import { DevframeClientRpcHost, DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientOptions, DevframeRpcContext, RpcClientEvents, RpcClientEvents as RpcClientEvents$1 } from "devframe/client";
|
|
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 };
|
package/dist/client/index.mjs
CHANGED
|
@@ -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 };
|
package/dist/node/index.mjs
CHANGED
|
@@ -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 {
|
|
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";
|
|
@@ -231,45 +231,6 @@ function normaliseRemoteOptions(remote) {
|
|
|
231
231
|
originLock: opts.originLock ?? true
|
|
232
232
|
};
|
|
233
233
|
}
|
|
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
234
|
var DevframeDocksHost = class {
|
|
274
235
|
context;
|
|
275
236
|
views = /* @__PURE__ */ new Map();
|
|
@@ -303,7 +264,7 @@ var DevframeDocksHost = class {
|
|
|
303
264
|
};
|
|
304
265
|
return {
|
|
305
266
|
...view,
|
|
306
|
-
url:
|
|
267
|
+
url: buildRemoteConnectionUrl(view.url, payload, record.options.transport)
|
|
307
268
|
};
|
|
308
269
|
}
|
|
309
270
|
resolveDevServerOrigin() {
|
|
@@ -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 };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devframes/hub",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.1",
|
|
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.
|
|
36
|
+
"devframe": "0.8.1"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@standard-schema/spec": "^1.1.0",
|
|
@@ -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.
|
|
52
|
+
"devframe": "0.8.1"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsdown",
|