devframe 0.9.0 → 0.9.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.
- package/dist/{_shared-BPmX9fqK.d.mts → _shared-BAGBgTUO.d.mts} +1 -1
- package/dist/{_shared-CbZ_yhbz.mjs → _shared-BM3PdYli.mjs} +1 -1
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +12 -9
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +4 -3
- package/dist/adapters/dev.d.mts +3 -3
- package/dist/adapters/dev.mjs +2 -2
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/embedded.mjs +2 -0
- package/dist/adapters/initiate.d.mts +2 -2
- package/dist/adapters/initiate.mjs +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/cli/main.mjs +2 -2
- package/dist/client/index.d.mts +48 -2
- package/dist/client/index.mjs +133 -23
- package/dist/constants.d.mts +74 -2
- package/dist/constants.mjs +9 -2
- package/dist/{context-xdynGSLP.mjs → context-af2w_F0_.mjs} +2 -2
- package/dist/{context-B3YUu_95.d.mts → context-al99DDJ8.d.mts} +1 -1
- package/dist/{context-CEe4PBz1.mjs → context-riPPHGiu.mjs} +339 -26
- package/dist/{dev--rAPzbvO.mjs → dev-BKm_HisC.mjs} +15 -11
- package/dist/{devframe-DJMg0WLe.d.mts → devframe-mbfgpQQC.d.mts} +774 -587
- package/dist/{diagnostics-DOQPnQmX.mjs → diagnostics-DI1HGj2I.mjs} +20 -0
- package/dist/{dist-eNI9qM_I.mjs → dist-CZXfGEkd.mjs} +1 -1
- package/dist/events-DKfSmoTj.mjs +65 -0
- package/dist/hash-DdPnc4k3.mjs +360 -0
- package/dist/{host-agent-xLCSe65D.mjs → host-agent-DVDLqjvj.mjs} +14 -13
- package/dist/{http-DYpK0cUi.mjs → http-POepPnaQ.mjs} +10 -6
- package/dist/{index-CB-fSUyn.d.mts → index-Dipgo9ji.d.mts} +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/{instance-registry-WvQkt42E.mjs → instance-registry-Dy28drtm.mjs} +4 -4
- package/dist/{instance-shell-CMFyszWJ.mjs → instance-shell-GqTY93gC.mjs} +5 -5
- package/dist/{instance-shell-CljiKq1c.d.mts → instance-shell-mU5j5xWn.d.mts} +2 -2
- package/dist/internal/index.d.mts +40 -4
- package/dist/internal/index.mjs +7 -7
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/auth.mjs +2 -2
- package/dist/node/hub-internals.d.mts +2 -2
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +10 -1
- package/dist/node/index.mjs +2 -2
- package/dist/recipes/common-rpc-functions.d.mts +11 -1
- package/dist/recipes/common-rpc-functions.mjs +10 -0
- package/dist/recipes/interactive-auth.d.mts +2 -2
- package/dist/recipes/interactive-auth.mjs +2 -2
- package/dist/{remote-assets-nTTxY2MU.mjs → remote-assets-CqxiyltC.mjs} +18 -7
- package/dist/{revoke-DZbJ7Cl0.mjs → revoke-3Q6aDKWk.mjs} +2 -1
- package/dist/{rolldown-runtime-JspESFgx.mjs → rolldown-runtime-B4iAMlE-.mjs} +1 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.mjs +1 -1
- package/dist/rpc/transports/ws-bun.d.mts +1 -1
- package/dist/rpc/transports/ws-deno.d.mts +26 -0
- package/dist/rpc/transports/ws-deno.mjs +30 -0
- package/dist/{rpc-core-DMTe-hLo.mjs → rpc-core-DRYnbxdD.mjs} +2 -2
- package/dist/{rpc-core-Cc4lucI0.d.mts → rpc-core-dV69u4lY.d.mts} +2 -2
- package/dist/{shared-state-fRRbRUtD.mjs → shared-state-DoXutg_U.mjs} +1 -1
- package/dist/{state-Cc1IeSmQ.mjs → state-CK9LjrnT.mjs} +1 -1
- package/dist/{static-BPZ1_OPA.mjs → static-DV_qUSRS.mjs} +1 -1
- package/dist/{storage-CYye7P7L.mjs → storage-BNqSAOxA.mjs} +3 -3
- package/dist/types/index.d.mts +2 -2
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/get-port.mjs +1 -1
- package/dist/utils/hash.mjs +1 -1
- package/dist/utils/launch-editor.mjs +12 -11
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/remote-assets.d.mts +7 -1
- package/dist/utils/remote-assets.mjs +1 -1
- package/dist/utils/serve-static.mjs +6 -5
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/validation-YrZH6atx.mjs +311 -0
- package/package.json +4 -3
- package/skills/devframe/SKILL.md +1 -1
- package/dist/hash-KtDZYXDN.mjs +0 -266
- package/dist/validation-CpXFB6Dz.mjs +0 -266
- package/dist/{host-h3-Crkzm42q.mjs → host-h3-fRbF9yor.mjs} +1 -1
package/dist/constants.d.mts
CHANGED
|
@@ -1,3 +1,69 @@
|
|
|
1
|
+
//#region src/events.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Centralized registry of the core devframe event names — the node-side host
|
|
4
|
+
* bus events, the client RPC connection events, and the server→client
|
|
5
|
+
* broadcast notifications — so these names live in one place instead of
|
|
6
|
+
* scattered string literals.
|
|
7
|
+
*
|
|
8
|
+
* **Keep this in sync with [`docs/guide/events.md`](../../../docs/guide/events.md)**
|
|
9
|
+
* (the "Core devframe events" section): every name here appears in that page's
|
|
10
|
+
* tables, and every name there resolves to an entry here. Add, rename, or
|
|
11
|
+
* remove a name in both places in the same change, and reference
|
|
12
|
+
* `DEVFRAME_EVENTS.*` from call sites instead of re-typing a literal.
|
|
13
|
+
*
|
|
14
|
+
* This map covers **notifications** (events, broadcasts). The request/response
|
|
15
|
+
* RPC endpoints of the shared-state, streaming, and auth-handshake protocols
|
|
16
|
+
* (`devframe:rpc:server-state:*`, `devframe:streaming:subscribe`,
|
|
17
|
+
* `anonymous:devframe:auth`, …) are defined at their handlers and typed in
|
|
18
|
+
* `types/rpc-augments.ts`; they aren't events and stay out of this map.
|
|
19
|
+
*
|
|
20
|
+
* The `EventEmitter` maps (`RpcClientEvents`, `DevframeAgentHostEvents`) and the
|
|
21
|
+
* `DevframeRpcClientFunctions` augmentation declare these names as type-level
|
|
22
|
+
* keys (a literal is unavoidable in a type position); those declarations mirror
|
|
23
|
+
* this map and move with it.
|
|
24
|
+
*/
|
|
25
|
+
declare const DEVFRAME_EVENTS: {
|
|
26
|
+
/**
|
|
27
|
+
* Node-side host `EventEmitter` events. The agent host (`ctx.agent.events`)
|
|
28
|
+
* emits these as its tool/resource surface changes; protocol adapters (e.g.
|
|
29
|
+
* MCP) subscribe to re-publish their manifest.
|
|
30
|
+
*/
|
|
31
|
+
readonly bus: {
|
|
32
|
+
readonly agentManifestChanged: "agent:manifest:changed";
|
|
33
|
+
readonly agentToolRegistered: "agent:tool:registered";
|
|
34
|
+
readonly agentToolUnregistered: "agent:tool:unregistered";
|
|
35
|
+
readonly agentResourceRegistered: "agent:resource:registered";
|
|
36
|
+
readonly agentResourceUnregistered: "agent:resource:unregistered";
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Client-side RPC connection `EventEmitter` events (`rpc.events`) a UI
|
|
40
|
+
* subscribes to for connection lifecycle and error surfacing.
|
|
41
|
+
*/
|
|
42
|
+
readonly client: {
|
|
43
|
+
readonly isTrustedUpdated: "rpc:is-trusted:updated";
|
|
44
|
+
readonly error: "rpc:error";
|
|
45
|
+
readonly connectionStatus: "connection:status";
|
|
46
|
+
readonly connectionError: "connection:error";
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Broadcast notifications the server pushes to clients (server → client),
|
|
50
|
+
* `devframe:` prefix. The paired request methods (subscribe/get/set/…) are
|
|
51
|
+
* RPC endpoints, not events, and are omitted deliberately.
|
|
52
|
+
*/
|
|
53
|
+
readonly broadcast: {
|
|
54
|
+
readonly authRevoked: "devframe:auth:revoked";
|
|
55
|
+
readonly clientStateUpdated: "devframe:rpc:client-state:updated";
|
|
56
|
+
readonly clientStatePatch: "devframe:rpc:client-state:patch";
|
|
57
|
+
readonly streamingChunk: "devframe:streaming:chunk";
|
|
58
|
+
readonly streamingEnd: "devframe:streaming:end";
|
|
59
|
+
readonly streamingUploadCancel: "devframe:streaming:upload-cancel";
|
|
60
|
+
};
|
|
61
|
+
/** `postMessage` channels the runtime posts across window boundaries. */
|
|
62
|
+
readonly postMessage: {
|
|
63
|
+
readonly remoteAssetsError: "devframe:remote-assets-error";
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
1
67
|
//#region src/constants.d.ts
|
|
2
68
|
declare const DEVFRAME_CONNECTION_META_FILENAME = "__connection.json";
|
|
3
69
|
/**
|
|
@@ -40,6 +106,12 @@ declare const DEVFRAME_MCP_ROUTE = "__mcp";
|
|
|
40
106
|
declare const DEVFRAME_RPC_DUMP_MANIFEST_FILENAME = "__rpc-dump/index.json";
|
|
41
107
|
declare const DEVFRAME_DOCK_IMPORTS_FILENAME = "__client-imports.js";
|
|
42
108
|
declare const DEVFRAME_RPC_DUMP_DIRNAME = "__rpc-dump";
|
|
109
|
+
/**
|
|
110
|
+
* Shared-state key carrying the wire-service advertisements (package name →
|
|
111
|
+
* `DevframeServiceMeta`). Written by the node services host; mirrored to
|
|
112
|
+
* clients for feature-detection via `client.services`.
|
|
113
|
+
*/
|
|
114
|
+
declare const DEVFRAME_SERVICES_STATE_KEY = "devframe:services";
|
|
43
115
|
/**
|
|
44
116
|
* URL fragment / query parameter name carrying the remote dock
|
|
45
117
|
* connection descriptor (defined as `RemoteConnectionInfo` in
|
|
@@ -77,7 +149,7 @@ declare const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin
|
|
|
77
149
|
* (`@devframes/hub-ui` does, in its iframe view). Payload shape:
|
|
78
150
|
* `RemoteAssetsErrorMessage` (`devframe/types`).
|
|
79
151
|
*/
|
|
80
|
-
declare const DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE
|
|
152
|
+
declare const DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE: string;
|
|
81
153
|
/**
|
|
82
154
|
* Prefix that marks an RPC method as callable before a connection is
|
|
83
155
|
* trusted. This is the *only* rule the pre-trust gate applies — there is no
|
|
@@ -94,4 +166,4 @@ declare const ANONYMOUS_RPC_PREFIX = "anonymous:";
|
|
|
94
166
|
*/
|
|
95
167
|
declare function isAnonymousRpcMethod(name: string): boolean;
|
|
96
168
|
//#endregion
|
|
97
|
-
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_MCP_ROUTE, DEVFRAME_OTP_URL_PARAM, DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_SSE_ROUTE, DEVFRAME_SSE_SESSION_HEADER, DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM, DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
|
169
|
+
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_EVENTS, DEVFRAME_MCP_ROUTE, DEVFRAME_OTP_URL_PARAM, DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_SERVICES_STATE_KEY, DEVFRAME_SSE_ROUTE, DEVFRAME_SSE_SESSION_HEADER, DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM, DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
package/dist/constants.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as DEVFRAME_EVENTS } from "./events-DKfSmoTj.mjs";
|
|
1
2
|
//#region src/constants.ts
|
|
2
3
|
const DEVFRAME_CONNECTION_META_FILENAME = "__connection.json";
|
|
3
4
|
/**
|
|
@@ -41,6 +42,12 @@ const DEVFRAME_RPC_DUMP_MANIFEST_FILENAME = "__rpc-dump/index.json";
|
|
|
41
42
|
const DEVFRAME_DOCK_IMPORTS_FILENAME = "__client-imports.js";
|
|
42
43
|
const DEVFRAME_RPC_DUMP_DIRNAME = "__rpc-dump";
|
|
43
44
|
/**
|
|
45
|
+
* Shared-state key carrying the wire-service advertisements (package name →
|
|
46
|
+
* `DevframeServiceMeta`). Written by the node services host; mirrored to
|
|
47
|
+
* clients for feature-detection via `client.services`.
|
|
48
|
+
*/
|
|
49
|
+
const DEVFRAME_SERVICES_STATE_KEY = "devframe:services";
|
|
50
|
+
/**
|
|
44
51
|
* URL fragment / query parameter name carrying the remote dock
|
|
45
52
|
* connection descriptor (defined as `RemoteConnectionInfo` in
|
|
46
53
|
* `@vitejs/devtools-kit`) injected into remote-UI iframe dock URLs.
|
|
@@ -77,7 +84,7 @@ const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin_token";
|
|
|
77
84
|
* (`@devframes/hub-ui` does, in its iframe view). Payload shape:
|
|
78
85
|
* `RemoteAssetsErrorMessage` (`devframe/types`).
|
|
79
86
|
*/
|
|
80
|
-
const DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE =
|
|
87
|
+
const DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE = DEVFRAME_EVENTS.postMessage.remoteAssetsError;
|
|
81
88
|
/**
|
|
82
89
|
* Prefix that marks an RPC method as callable before a connection is
|
|
83
90
|
* trusted. This is the *only* rule the pre-trust gate applies — there is no
|
|
@@ -96,4 +103,4 @@ function isAnonymousRpcMethod(name) {
|
|
|
96
103
|
return name.startsWith(ANONYMOUS_RPC_PREFIX);
|
|
97
104
|
}
|
|
98
105
|
//#endregion
|
|
99
|
-
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_MCP_ROUTE, DEVFRAME_OTP_URL_PARAM, DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_SSE_ROUTE, DEVFRAME_SSE_SESSION_HEADER, DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM, DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
|
106
|
+
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_EVENTS, DEVFRAME_MCP_ROUTE, DEVFRAME_OTP_URL_PARAM, DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_SERVICES_STATE_KEY, DEVFRAME_SSE_ROUTE, DEVFRAME_SSE_SESSION_HEADER, DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM, DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as randomToken } from "./crypto-token-XCqTSMg9.mjs";
|
|
2
|
-
import { t as createStorage } from "./storage-
|
|
3
|
-
import { n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-
|
|
2
|
+
import { t as createStorage } from "./storage-BNqSAOxA.mjs";
|
|
3
|
+
import { n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-3Q6aDKWk.mjs";
|
|
4
4
|
import { join } from "pathe";
|
|
5
5
|
//#region src/node/hub-internals/context.ts
|
|
6
6
|
const internalContextMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as DevframeNodeContext,
|
|
1
|
+
import { g as DevframeNodeContext, gt as SharedState } from "./devframe-mbfgpQQC.mjs";
|
|
2
2
|
//#region src/node/hub-internals/context.d.ts
|
|
3
3
|
interface InternalAnonymousAuthStorage {
|
|
4
4
|
trusted: Record<string, {
|
|
@@ -2,13 +2,18 @@ import { i as defineDiagnostics } from "./nostics-CzECRXpE.mjs";
|
|
|
2
2
|
import { t as diagnostics } from "./diagnostics-CD8nlgll.mjs";
|
|
3
3
|
import { RpcFunctionsCollectorBase } from "./rpc/index.mjs";
|
|
4
4
|
import { defineRpcFunction } from "./index.mjs";
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { t as
|
|
5
|
+
import { t as DEVFRAME_EVENTS } from "./events-DKfSmoTj.mjs";
|
|
6
|
+
import { DEVFRAME_SERVICES_STATE_KEY } from "./constants.mjs";
|
|
7
|
+
import { t as diagnostics$1 } from "./diagnostics-DI1HGj2I.mjs";
|
|
8
|
+
import { r as createEventEmitter, t as DevframeAgentHost } from "./host-agent-DVDLqjvj.mjs";
|
|
9
|
+
import { n as createDebug, t as resolveStaticAssetsSource } from "./remote-assets-CqxiyltC.mjs";
|
|
10
|
+
import { t as createStorage } from "./storage-BNqSAOxA.mjs";
|
|
11
|
+
import { createRequire } from "node:module";
|
|
9
12
|
import { createSharedState } from "devframe/utils/shared-state";
|
|
13
|
+
import process from "node:process";
|
|
14
|
+
import { pathToFileURL } from "node:url";
|
|
15
|
+
import { isAbsolute, join } from "pathe";
|
|
10
16
|
import { existsSync } from "node:fs";
|
|
11
|
-
import { join } from "pathe";
|
|
12
17
|
//#region src/node/host-diagnostics.ts
|
|
13
18
|
var DevframeDiagnosticsHost = class {
|
|
14
19
|
context;
|
|
@@ -25,7 +30,7 @@ var DevframeDiagnosticsHost = class {
|
|
|
25
30
|
};
|
|
26
31
|
//#endregion
|
|
27
32
|
//#region src/node/rpc-shared-state.ts
|
|
28
|
-
const debug$
|
|
33
|
+
const debug$2 = createDebug("devframe:rpc:state:changed");
|
|
29
34
|
const debugSubscribe = createDebug("devframe:rpc:state:subscribe");
|
|
30
35
|
function createRpcSharedStateServerHost(rpc) {
|
|
31
36
|
const sharedState = /* @__PURE__ */ new Map();
|
|
@@ -35,12 +40,12 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
35
40
|
const offs = [];
|
|
36
41
|
offs.push(state.on("updated", (fullState, patches, syncId) => {
|
|
37
42
|
if (patches) {
|
|
38
|
-
debug$
|
|
43
|
+
debug$2("patch", {
|
|
39
44
|
key,
|
|
40
45
|
syncId
|
|
41
46
|
});
|
|
42
47
|
rpc.broadcast({
|
|
43
|
-
method:
|
|
48
|
+
method: DEVFRAME_EVENTS.broadcast.clientStatePatch,
|
|
44
49
|
args: [
|
|
45
50
|
key,
|
|
46
51
|
patches,
|
|
@@ -49,12 +54,12 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
49
54
|
filter: (client) => client.$meta.subscribedStates.has(key)
|
|
50
55
|
});
|
|
51
56
|
} else {
|
|
52
|
-
debug$
|
|
57
|
+
debug$2("updated", {
|
|
53
58
|
key,
|
|
54
59
|
syncId
|
|
55
60
|
});
|
|
56
61
|
rpc.broadcast({
|
|
57
|
-
method:
|
|
62
|
+
method: DEVFRAME_EVENTS.broadcast.clientStateUpdated,
|
|
58
63
|
args: [
|
|
59
64
|
key,
|
|
60
65
|
fullState,
|
|
@@ -72,7 +77,7 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
72
77
|
get: async (key, options) => {
|
|
73
78
|
if (sharedState.has(key)) return sharedState.get(key);
|
|
74
79
|
if (options?.initialValue === void 0 && options?.sharedState === void 0) throw diagnostics$1.DF0013({ key });
|
|
75
|
-
debug$
|
|
80
|
+
debug$2("new-state", key);
|
|
76
81
|
const state = options.sharedState ?? createSharedState({
|
|
77
82
|
initialValue: options.initialValue,
|
|
78
83
|
enablePatches: false
|
|
@@ -402,7 +407,7 @@ function toErrorPayload(reason) {
|
|
|
402
407
|
}
|
|
403
408
|
//#endregion
|
|
404
409
|
//#region src/node/rpc-streaming.ts
|
|
405
|
-
const debug = createDebug("devframe:rpc:streaming");
|
|
410
|
+
const debug$1 = createDebug("devframe:rpc:streaming");
|
|
406
411
|
const STREAM_KEY_SEPARATOR = "";
|
|
407
412
|
function streamKey(channel, id) {
|
|
408
413
|
return `${channel}${STREAM_KEY_SEPARATOR}${id}`;
|
|
@@ -427,7 +432,7 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
427
432
|
}
|
|
428
433
|
for (const off of record.unbinders) off();
|
|
429
434
|
state.streams.delete(id);
|
|
430
|
-
debug("freed", state.name, id);
|
|
435
|
+
debug$1("freed", state.name, id);
|
|
431
436
|
}
|
|
432
437
|
function maybeFreeStream(state, id) {
|
|
433
438
|
const record = state.streams.get(id);
|
|
@@ -476,7 +481,7 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
476
481
|
cancelRetention(record);
|
|
477
482
|
const afterSeq = opts?.afterSeq ?? 0;
|
|
478
483
|
for (const buffered of record.sink.buffer) if (buffered.seq > afterSeq) rpc.broadcast({
|
|
479
|
-
method:
|
|
484
|
+
method: DEVFRAME_EVENTS.broadcast.streamingChunk,
|
|
480
485
|
args: [
|
|
481
486
|
channelName,
|
|
482
487
|
id,
|
|
@@ -488,7 +493,7 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
488
493
|
filter: (client) => client.$meta === session.meta
|
|
489
494
|
});
|
|
490
495
|
if (record.sink.closed) rpc.broadcast({
|
|
491
|
-
method:
|
|
496
|
+
method: DEVFRAME_EVENTS.broadcast.streamingEnd,
|
|
492
497
|
args: [
|
|
493
498
|
channelName,
|
|
494
499
|
id,
|
|
@@ -589,7 +594,7 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
589
594
|
state.streams.set(sink.id, record);
|
|
590
595
|
record.unbinders.push(sink.events.on("chunk", (seq, chunk) => {
|
|
591
596
|
rpc.broadcast({
|
|
592
|
-
method:
|
|
597
|
+
method: DEVFRAME_EVENTS.broadcast.streamingChunk,
|
|
593
598
|
args: [
|
|
594
599
|
name,
|
|
595
600
|
sink.id,
|
|
@@ -603,7 +608,7 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
603
608
|
}));
|
|
604
609
|
record.unbinders.push(sink.events.on("end", (error) => {
|
|
605
610
|
rpc.broadcast({
|
|
606
|
-
method:
|
|
611
|
+
method: DEVFRAME_EVENTS.broadcast.streamingEnd,
|
|
607
612
|
args: [
|
|
608
613
|
name,
|
|
609
614
|
sink.id,
|
|
@@ -636,7 +641,7 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
636
641
|
const targetMeta = inboundRecord?.uploaderMeta;
|
|
637
642
|
if (!targetMeta) return;
|
|
638
643
|
rpc.broadcast({
|
|
639
|
-
method:
|
|
644
|
+
method: DEVFRAME_EVENTS.broadcast.streamingUploadCancel,
|
|
640
645
|
args: [name, reader.id],
|
|
641
646
|
event: true,
|
|
642
647
|
optional: true,
|
|
@@ -646,7 +651,7 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
646
651
|
});
|
|
647
652
|
inboundRecord = { reader };
|
|
648
653
|
state.inbound.set(reader.id, inboundRecord);
|
|
649
|
-
debug("opened-inbound", name, reader.id);
|
|
654
|
+
debug$1("opened-inbound", name, reader.id);
|
|
650
655
|
return reader;
|
|
651
656
|
}
|
|
652
657
|
return {
|
|
@@ -758,15 +763,190 @@ var RpcFunctionsHostImpl = class extends RpcFunctionsCollectorBase {
|
|
|
758
763
|
}
|
|
759
764
|
};
|
|
760
765
|
//#endregion
|
|
766
|
+
//#region src/node/services-install.ts
|
|
767
|
+
/**
|
|
768
|
+
* Turn a `resolveFrom` value (a file path, a file URL like `import.meta.url`,
|
|
769
|
+
* or a directory) into something `createRequire` accepts — a directory gets a
|
|
770
|
+
* synthetic filename appended so resolution starts inside it.
|
|
771
|
+
*/
|
|
772
|
+
function toRequireBase(resolveFrom) {
|
|
773
|
+
if (resolveFrom.startsWith("file://")) return resolveFrom;
|
|
774
|
+
if ((resolveFrom.split(/[/\\]/).pop() ?? "").includes(".")) return resolveFrom;
|
|
775
|
+
return join(resolveFrom, "_devframe_resolve.js");
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Normalize an `install()` `resolveFrom` into a resolution base. Paths and
|
|
779
|
+
* file URLs pass through (the common case: the declaring plugin's
|
|
780
|
+
* `importMetaUrl`, so a service it declares resolves against the plugin's own
|
|
781
|
+
* dependencies); a bare npm package name resolves to that package's location
|
|
782
|
+
* from `cwd`. An unresolvable package name reads as no base (the caller's
|
|
783
|
+
* workspace fallbacks apply).
|
|
784
|
+
*/
|
|
785
|
+
function expandResolveFrom(resolveFrom, cwd) {
|
|
786
|
+
if (resolveFrom.startsWith("file://") || resolveFrom.startsWith(".") || isAbsolute(resolveFrom)) return resolveFrom;
|
|
787
|
+
const require = createRequire(join(cwd, "_devframe_resolve.js"));
|
|
788
|
+
try {
|
|
789
|
+
return require.resolve(`${resolveFrom}/package.json`);
|
|
790
|
+
} catch {}
|
|
791
|
+
try {
|
|
792
|
+
return require.resolve(resolveFrom);
|
|
793
|
+
} catch {}
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Import a service package's module, trying each `resolveFrom` candidate in
|
|
797
|
+
* order (so a plugin-declared service resolves against the plugin's own
|
|
798
|
+
* dependency tree first, then the workspace fallback). Throws the last
|
|
799
|
+
* resolution error when no candidate succeeds.
|
|
800
|
+
*/
|
|
801
|
+
async function importServicePackage(pkg, resolveFroms) {
|
|
802
|
+
const candidates = [...new Set(resolveFroms.filter((x) => typeof x === "string" && x.length > 0))];
|
|
803
|
+
let lastError = /* @__PURE__ */ new Error(`no resolution base available for "${pkg}"`);
|
|
804
|
+
for (const from of candidates) {
|
|
805
|
+
let resolved;
|
|
806
|
+
try {
|
|
807
|
+
resolved = createRequire(toRequireBase(from)).resolve(pkg);
|
|
808
|
+
} catch (error) {
|
|
809
|
+
lastError = error;
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
return await import(pathToFileURL(resolved).href);
|
|
813
|
+
}
|
|
814
|
+
throw lastError;
|
|
815
|
+
}
|
|
816
|
+
function parseVersion(input) {
|
|
817
|
+
const [core, ...prerelease] = input.trim().replace(/^v/, "").split("-");
|
|
818
|
+
if (!core) return void 0;
|
|
819
|
+
const parts = core.split(".").map((part) => Number.parseInt(part, 10));
|
|
820
|
+
if (parts.length === 0 || parts.some((part) => Number.isNaN(part) || part < 0)) return void 0;
|
|
821
|
+
while (parts.length < 3) parts.push(0);
|
|
822
|
+
return {
|
|
823
|
+
parts,
|
|
824
|
+
...prerelease.length ? { prerelease: prerelease.join("-") } : {}
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
function compareVersions(a, b) {
|
|
828
|
+
for (let i = 0; i < 3; i++) {
|
|
829
|
+
const diff = (a.parts[i] ?? 0) - (b.parts[i] ?? 0);
|
|
830
|
+
if (diff !== 0) return diff;
|
|
831
|
+
}
|
|
832
|
+
if (a.prerelease && !b.prerelease) return -1;
|
|
833
|
+
if (!a.prerelease && b.prerelease) return 1;
|
|
834
|
+
if (a.prerelease && b.prerelease) return a.prerelease < b.prerelease ? -1 : a.prerelease > b.prerelease ? 1 : 0;
|
|
835
|
+
return 0;
|
|
836
|
+
}
|
|
837
|
+
function satisfiesComparator(version, comparator) {
|
|
838
|
+
const raw = comparator.trim();
|
|
839
|
+
if (!raw || raw === "*" || raw === "x") return true;
|
|
840
|
+
const operatorMatch = raw.match(/^([\^~]|>=|<=|[><=])?(.+)$/);
|
|
841
|
+
if (!operatorMatch) return false;
|
|
842
|
+
const operator = operatorMatch[1];
|
|
843
|
+
const rest = operatorMatch[2].trim();
|
|
844
|
+
const segments = rest.replace(/\.[x*]/gi, "").split(".").filter(Boolean);
|
|
845
|
+
const base = parseVersion(rest.replace(/[x*]/gi, "0"));
|
|
846
|
+
if (!base) return false;
|
|
847
|
+
switch (operator) {
|
|
848
|
+
case ">": return compareVersions(version, base) > 0;
|
|
849
|
+
case ">=": return compareVersions(version, base) >= 0;
|
|
850
|
+
case "<": return compareVersions(version, base) < 0;
|
|
851
|
+
case "<=": return compareVersions(version, base) <= 0;
|
|
852
|
+
case "^": {
|
|
853
|
+
if (compareVersions(version, base) < 0) return false;
|
|
854
|
+
const fixedIndex = base.parts.findIndex((part) => part !== 0);
|
|
855
|
+
const lockUpTo = fixedIndex === -1 ? base.parts.length - 1 : fixedIndex;
|
|
856
|
+
for (let i = 0; i <= lockUpTo; i++) if ((version.parts[i] ?? 0) !== (base.parts[i] ?? 0)) return false;
|
|
857
|
+
return true;
|
|
858
|
+
}
|
|
859
|
+
case "~": {
|
|
860
|
+
if (compareVersions(version, base) < 0) return false;
|
|
861
|
+
const lockUpTo = segments.length >= 2 ? 1 : 0;
|
|
862
|
+
for (let i = 0; i <= lockUpTo; i++) if ((version.parts[i] ?? 0) !== (base.parts[i] ?? 0)) return false;
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
865
|
+
default:
|
|
866
|
+
for (let i = 0; i < Math.max(segments.length, 3); i++) if (i < segments.length && (version.parts[i] ?? 0) !== (base.parts[i] ?? 0)) return false;
|
|
867
|
+
return segments.length >= 3 ? compareVersions(version, base) === 0 : true;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Pragmatic semver range check for service version declarations — supports
|
|
872
|
+
* the common forms (`1.2.3`, `^1.2.3`, `~1.2`, `>=1 <3`, `1.x`, `*`, and
|
|
873
|
+
* `||`-joined alternatives) without pulling in a semver dependency. An
|
|
874
|
+
* unparseable version or range reads as **not satisfied**.
|
|
875
|
+
*/
|
|
876
|
+
function satisfiesVersionRange(version, range) {
|
|
877
|
+
const parsed = parseVersion(version);
|
|
878
|
+
if (!parsed) return false;
|
|
879
|
+
const alternatives = range.split("||").map((alt) => alt.trim()).filter(Boolean);
|
|
880
|
+
if (alternatives.length === 0) return true;
|
|
881
|
+
return alternatives.some((alternative) => alternative.split(/\s+/).every((comparator) => satisfiesComparator(parsed, comparator)));
|
|
882
|
+
}
|
|
883
|
+
function isPlainObject(value) {
|
|
884
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
885
|
+
}
|
|
886
|
+
/** Deep-merge two values with the service option-set rules (see below). */
|
|
887
|
+
function deepMergeTwo(a, b) {
|
|
888
|
+
if (Array.isArray(a) && Array.isArray(b)) return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
889
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
890
|
+
const out = { ...a };
|
|
891
|
+
for (const key of Object.keys(b)) out[key] = key in a ? deepMergeTwo(a[key], b[key]) : b[key];
|
|
892
|
+
return out;
|
|
893
|
+
}
|
|
894
|
+
return b;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Default option-set merge when a service declares no `mergeOptions`:
|
|
898
|
+
* deep-merge in declaration order — objects recurse, arrays union-dedupe,
|
|
899
|
+
* scalars take the later value. Covers the built-in services (`roots` /
|
|
900
|
+
* `langs` union, `themes` per-key last-wins) without a custom hook.
|
|
901
|
+
*/
|
|
902
|
+
function deepMergeOptionSets(sets) {
|
|
903
|
+
return sets.reduce((merged, set) => deepMergeTwo(merged, set));
|
|
904
|
+
}
|
|
905
|
+
//#endregion
|
|
761
906
|
//#region src/node/host-services.ts
|
|
907
|
+
const debug = createDebug("devframe:services");
|
|
908
|
+
function isServiceDefinition(input) {
|
|
909
|
+
return typeof input.setup === "function";
|
|
910
|
+
}
|
|
911
|
+
function validateServiceInput(input) {
|
|
912
|
+
if (!input || typeof input.package !== "string" || input.package.length === 0) throw diagnostics$1.DF0070({
|
|
913
|
+
package: String(input?.package ?? input),
|
|
914
|
+
reason: "the input has no `package` name"
|
|
915
|
+
});
|
|
916
|
+
if (isServiceDefinition(input)) validateServiceDefinition(input);
|
|
917
|
+
}
|
|
918
|
+
function validateServiceDefinition(def) {
|
|
919
|
+
if (typeof def.version !== "string" || def.version.length === 0) throw diagnostics$1.DF0070({
|
|
920
|
+
package: def.package,
|
|
921
|
+
reason: "the definition has no `version`"
|
|
922
|
+
});
|
|
923
|
+
if (typeof def.scope !== "string" || def.scope.length === 0) throw diagnostics$1.DF0070({
|
|
924
|
+
package: def.package,
|
|
925
|
+
reason: "the definition has no RPC `scope` namespace"
|
|
926
|
+
});
|
|
927
|
+
}
|
|
762
928
|
/**
|
|
763
929
|
* Cross-plugin service registry (see `types/services.ts` for the contract).
|
|
764
930
|
* Values are held per context instance; `whenAvailable` subscriptions make
|
|
765
931
|
* the mechanism robust against setup ordering between provider and consumer.
|
|
932
|
+
*
|
|
933
|
+
* On top of the in-process `provide`/`get` tier, this host implements the
|
|
934
|
+
* **wire-service** lifecycle: `install()` queues definitions/descriptors,
|
|
935
|
+
* `ready()` fires the collect-then-setup barrier — importing descriptor
|
|
936
|
+
* packages, merging option sets per service, constructing each service once,
|
|
937
|
+
* providing its node API under the package name, and advertising it to
|
|
938
|
+
* clients through the `devframe:services` shared state.
|
|
766
939
|
*/
|
|
767
940
|
var DevframeServicesHostImpl = class {
|
|
941
|
+
context;
|
|
768
942
|
services = /* @__PURE__ */ new Map();
|
|
769
943
|
listeners = /* @__PURE__ */ new Map();
|
|
944
|
+
pending = /* @__PURE__ */ new Map();
|
|
945
|
+
installed = /* @__PURE__ */ new Map();
|
|
946
|
+
readyPromise;
|
|
947
|
+
constructor(context) {
|
|
948
|
+
this.context = context;
|
|
949
|
+
}
|
|
770
950
|
provide(id, service) {
|
|
771
951
|
const key = id;
|
|
772
952
|
if (this.services.has(key)) throw diagnostics$1.DF0037({ id: key });
|
|
@@ -799,20 +979,152 @@ var DevframeServicesHostImpl = class {
|
|
|
799
979
|
keys() {
|
|
800
980
|
return Array.from(this.services.keys());
|
|
801
981
|
}
|
|
982
|
+
install(input, options) {
|
|
983
|
+
validateServiceInput(input);
|
|
984
|
+
const promise = new Promise((resolve, reject) => {
|
|
985
|
+
const entry = {
|
|
986
|
+
input,
|
|
987
|
+
resolveFrom: options?.resolveFrom,
|
|
988
|
+
resolve,
|
|
989
|
+
reject
|
|
990
|
+
};
|
|
991
|
+
if (this.readyPromise) this.flushPackage(input.package, [entry]).catch(() => {});
|
|
992
|
+
else {
|
|
993
|
+
let entries = this.pending.get(input.package);
|
|
994
|
+
if (!entries) {
|
|
995
|
+
entries = [];
|
|
996
|
+
this.pending.set(input.package, entries);
|
|
997
|
+
}
|
|
998
|
+
entries.push(entry);
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
|
+
promise.catch(() => {});
|
|
1002
|
+
return promise;
|
|
1003
|
+
}
|
|
1004
|
+
ready() {
|
|
1005
|
+
if (this.readyPromise) return this.readyPromise;
|
|
1006
|
+
this.readyPromise = this.flushAll();
|
|
1007
|
+
return this.readyPromise;
|
|
1008
|
+
}
|
|
1009
|
+
async flushAll() {
|
|
1010
|
+
if (this.context) await this.advertisementState();
|
|
1011
|
+
const groups = Array.from(this.pending.entries());
|
|
1012
|
+
this.pending.clear();
|
|
1013
|
+
for (const [pkg, entries] of groups) await this.flushPackage(pkg, entries);
|
|
1014
|
+
}
|
|
1015
|
+
async flushPackage(pkg, entries) {
|
|
1016
|
+
try {
|
|
1017
|
+
const api = await this.installPackage(pkg, entries);
|
|
1018
|
+
for (const entry of entries) entry.resolve(api);
|
|
1019
|
+
return api;
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
for (const entry of entries) entry.reject(error);
|
|
1022
|
+
throw error;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
async installPackage(pkg, entries) {
|
|
1026
|
+
if (this.installed.has(pkg)) {
|
|
1027
|
+
diagnostics$1.DF0066({ package: pkg });
|
|
1028
|
+
return this.installed.get(pkg);
|
|
1029
|
+
}
|
|
1030
|
+
let def = entries.filter((entry) => isServiceDefinition(entry.input))[0]?.input;
|
|
1031
|
+
if (!def) {
|
|
1032
|
+
const required = entries.map((entry) => entry.input).some((descriptor) => descriptor.required === true);
|
|
1033
|
+
const cwd = this.context?.cwd ?? process.cwd();
|
|
1034
|
+
const resolveFroms = [
|
|
1035
|
+
...entries.map((entry) => entry.resolveFrom && expandResolveFrom(entry.resolveFrom, cwd)),
|
|
1036
|
+
this.context?.workspaceRoot,
|
|
1037
|
+
cwd
|
|
1038
|
+
];
|
|
1039
|
+
let mod;
|
|
1040
|
+
try {
|
|
1041
|
+
mod = await importServicePackage(pkg, resolveFroms);
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1044
|
+
if (required) throw diagnostics$1.DF0067({
|
|
1045
|
+
package: pkg,
|
|
1046
|
+
reason,
|
|
1047
|
+
cause: error
|
|
1048
|
+
});
|
|
1049
|
+
debug("optional service %s not importable, skipping: %s", pkg, reason);
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
const factory = mod.default;
|
|
1053
|
+
if (typeof factory !== "function") throw diagnostics$1.DF0070({
|
|
1054
|
+
package: pkg,
|
|
1055
|
+
reason: "its default export is not a factory function"
|
|
1056
|
+
});
|
|
1057
|
+
def = await factory();
|
|
1058
|
+
if (!def || typeof def.setup !== "function") throw diagnostics$1.DF0070({
|
|
1059
|
+
package: pkg,
|
|
1060
|
+
reason: "its factory did not return a definition with a `setup` function"
|
|
1061
|
+
});
|
|
1062
|
+
if (typeof def.package !== "string" || def.package.length === 0) def = {
|
|
1063
|
+
...def,
|
|
1064
|
+
package: pkg
|
|
1065
|
+
};
|
|
1066
|
+
validateServiceDefinition(def);
|
|
1067
|
+
}
|
|
1068
|
+
for (const entry of entries) {
|
|
1069
|
+
const descriptor = entry.input;
|
|
1070
|
+
if (isServiceDefinition(entry.input) || typeof descriptor.version !== "string") continue;
|
|
1071
|
+
if (satisfiesVersionRange(def.version, descriptor.version)) continue;
|
|
1072
|
+
if (descriptor.required === true) throw diagnostics$1.DF0068({
|
|
1073
|
+
package: pkg,
|
|
1074
|
+
required: descriptor.version,
|
|
1075
|
+
installed: def.version
|
|
1076
|
+
});
|
|
1077
|
+
diagnostics$1.DF0069({
|
|
1078
|
+
package: pkg,
|
|
1079
|
+
required: descriptor.version,
|
|
1080
|
+
installed: def.version
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
const sets = entries.map((entry) => entry.input.options).filter((options) => options !== void 0);
|
|
1084
|
+
const options = def.mergeOptions ? def.mergeOptions(sets) : sets.length > 0 ? deepMergeOptionSets(sets) : void 0;
|
|
1085
|
+
if (!this.context) throw diagnostics$1.DF0070({
|
|
1086
|
+
package: pkg,
|
|
1087
|
+
reason: "this services host has no node context to install into"
|
|
1088
|
+
});
|
|
1089
|
+
debug("installing service %s@%s (scope %s)", def.package, def.version, def.scope);
|
|
1090
|
+
const scoped = this.context.scope(def.scope);
|
|
1091
|
+
const api = await def.setup(scoped, options === void 0 ? {} : { options });
|
|
1092
|
+
this.installed.set(def.package, api);
|
|
1093
|
+
this.provide(def.package, api);
|
|
1094
|
+
await this.advertise(def);
|
|
1095
|
+
return api;
|
|
1096
|
+
}
|
|
1097
|
+
advertisementState() {
|
|
1098
|
+
return this.context.rpc.sharedState.get(DEVFRAME_SERVICES_STATE_KEY, { initialValue: {} });
|
|
1099
|
+
}
|
|
1100
|
+
async advertise(def) {
|
|
1101
|
+
const state = await this.advertisementState();
|
|
1102
|
+
const { package: pkg, version, scope, meta } = def;
|
|
1103
|
+
state.mutate((value) => {
|
|
1104
|
+
value[pkg] = {
|
|
1105
|
+
package: pkg,
|
|
1106
|
+
version,
|
|
1107
|
+
scope,
|
|
1108
|
+
...meta ? { meta } : {}
|
|
1109
|
+
};
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
802
1112
|
};
|
|
803
1113
|
//#endregion
|
|
804
1114
|
//#region src/node/host-views.ts
|
|
805
1115
|
var DevframeViewHost = class {
|
|
806
1116
|
context;
|
|
1117
|
+
importMetaUrl;
|
|
807
1118
|
/**
|
|
808
1119
|
* @internal
|
|
809
1120
|
*/
|
|
810
1121
|
buildStaticDirs = [];
|
|
811
|
-
constructor(context) {
|
|
1122
|
+
constructor(context, importMetaUrl) {
|
|
812
1123
|
this.context = context;
|
|
1124
|
+
this.importMetaUrl = importMetaUrl;
|
|
813
1125
|
}
|
|
814
|
-
hostStatic(baseUrl, source) {
|
|
815
|
-
const resolved = resolveStaticAssetsSource(source, this.context.host.getStorageDir("project"));
|
|
1126
|
+
hostStatic(baseUrl, source, defaultResolveFrom = this.importMetaUrl) {
|
|
1127
|
+
const resolved = resolveStaticAssetsSource(source, this.context.host.getStorageDir("project"), defaultResolveFrom);
|
|
816
1128
|
if (typeof resolved === "string" && !existsSync(resolved)) throw diagnostics$1.DF0008({ distDir: resolved });
|
|
817
1129
|
this.buildStaticDirs.push({
|
|
818
1130
|
baseUrl,
|
|
@@ -900,7 +1212,8 @@ function createNodeSettingsStore(context, namespace, scope) {
|
|
|
900
1212
|
let statePromise;
|
|
901
1213
|
function store() {
|
|
902
1214
|
if (!statePromise) {
|
|
903
|
-
const
|
|
1215
|
+
const dir = context.host.getStorageDir(STORAGE_SCOPE[scope]);
|
|
1216
|
+
const filepath = join(dir, "settings", `${namespace}.json`);
|
|
904
1217
|
statePromise = context.rpc.sharedState.get(stateKey, { sharedState: createStorage({
|
|
905
1218
|
filepath,
|
|
906
1219
|
initialValue: {}
|
|
@@ -1003,7 +1316,7 @@ function createScopedNodeContext(context, namespace) {
|
|
|
1003
1316
|
* `commands` when mounted into Vite DevTools.
|
|
1004
1317
|
*/
|
|
1005
1318
|
async function createHostContext(options) {
|
|
1006
|
-
const { cwd, workspaceRoot = cwd, mode, host, builtinRpcDeclarations = [] } = options;
|
|
1319
|
+
const { cwd, workspaceRoot = cwd, mode, host, importMetaUrl, builtinRpcDeclarations = [] } = options;
|
|
1007
1320
|
const context = {
|
|
1008
1321
|
cwd,
|
|
1009
1322
|
workspaceRoot,
|
|
@@ -1018,12 +1331,12 @@ async function createHostContext(options) {
|
|
|
1018
1331
|
scope: void 0
|
|
1019
1332
|
};
|
|
1020
1333
|
const rpcHost = new RpcFunctionsHostImpl(context);
|
|
1021
|
-
const viewsHost = new DevframeViewHost(context);
|
|
1334
|
+
const viewsHost = new DevframeViewHost(context, importMetaUrl);
|
|
1022
1335
|
const diagnosticsHost = new DevframeDiagnosticsHost(context, [diagnostics$1, diagnostics]);
|
|
1023
1336
|
context.rpc = rpcHost;
|
|
1024
1337
|
context.views = viewsHost;
|
|
1025
1338
|
context.diagnostics = diagnosticsHost;
|
|
1026
|
-
context.services = new DevframeServicesHostImpl();
|
|
1339
|
+
context.services = new DevframeServicesHostImpl(context);
|
|
1027
1340
|
context.agent = new DevframeAgentHost(context);
|
|
1028
1341
|
const scopedCache = /* @__PURE__ */ new Map();
|
|
1029
1342
|
context.scope = ((namespace) => {
|