devframe 0.9.20 → 0.10.0
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-B2PZsp-J.mjs +191 -0
- package/dist/{_shared-BIUet_Jh.d.mts → _shared-Dy1UBMUN.d.mts} +13 -14
- package/dist/adapters/build.d.mts +3 -4
- package/dist/adapters/build.mjs +4 -5
- package/dist/adapters/cac.d.mts +3 -4
- package/dist/adapters/cac.mjs +3 -3
- package/dist/adapters/dev.d.mts +8 -8
- package/dist/adapters/dev.mjs +2 -2
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +8 -8
- package/dist/adapters/initiate.mjs +1 -1
- package/dist/adapters/mcp.d.mts +4 -142
- package/dist/adapters/mcp.mjs +1 -597
- package/dist/agentic-D4QQQUjE.d.mts +30 -0
- package/dist/cli/main.mjs +12 -260
- package/dist/client/index.d.mts +6 -6
- package/dist/client/index.mjs +3 -4
- package/dist/constants.d.mts +2 -1
- package/dist/constants.mjs +2 -1
- package/dist/{context-BA5FPz7K.d.mts → context-B4BKPuaa.d.mts} +1 -1
- package/dist/{context-BLXXjoBW.mjs → context-C141q8H4.mjs} +5 -5
- package/dist/{context-jXO5vzjH.mjs → context-CHpyLX8W.mjs} +1 -1
- package/dist/{context-BLHBDQcZ.d.mts → context-CTAxz9ec.d.mts} +108 -47
- package/dist/{dev-BdKKOH8S.mjs → dev-DM1mIlgi.mjs} +16 -24
- package/dist/{diagnostics-DZA6KQ_Z.mjs → diagnostics-Cx4_VjlG.mjs} +11 -3
- package/dist/dist-Bw3EbMj4.mjs +305 -0
- package/dist/dist-CO98PBnQ.mjs +265 -0
- package/dist/{host-agent-C3MBpNCd.mjs → host-agent-ZSKgzMVu.mjs} +2 -7
- package/dist/import-runtime-module-BzlEQ9PI.mjs +24 -0
- package/dist/in-page-channel/index.d.mts +2 -7
- package/dist/in-page-channel/index.mjs +1 -4
- package/dist/index-Bia1vKjL.d.mts +218 -0
- package/dist/{index-r6NstVmM.d.mts → index-CcPSKbxb.d.mts} +2 -2
- package/dist/index-CeEtxDmK.d.mts +78 -0
- package/dist/{index-CiA6C705.d.mts → index-DuEm0sDH.d.mts} +1 -1
- package/dist/index.d.mts +4 -11
- package/dist/index.mjs +1 -10
- package/dist/{instance-registry-DCq762YJ.mjs → instance-registry-DtvYxc0Y.mjs} +1 -1
- package/dist/{instance-shell-C6Vg97lg.d.mts → instance-shell-DOZSxst6.d.mts} +31 -5
- package/dist/{instance-shell-yfrM3_vK.mjs → instance-shell-wC2sfEU_.mjs} +7 -7
- package/dist/interactive-auth-BCa_iamv.mjs +384 -0
- package/dist/internal/index.d.mts +66 -22
- package/dist/internal/index.mjs +143 -8
- package/dist/mrmime-40h5OOIp.mjs +448 -0
- package/dist/node/auth.d.mts +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 +2 -4
- package/dist/node/index.mjs +2 -2
- package/dist/{nostics-0sKe5HIj.d.mts → nostics-DWvukRwa.d.mts} +11 -2
- package/dist/{origin-D_eBKEzr.mjs → origin-DZit9g29.mjs} +1 -21
- package/dist/recipes/interactive-auth.d.mts +2 -2
- package/dist/recipes/interactive-auth.mjs +1 -231
- package/dist/{remote-assets-D0StJVLp.mjs → remote-assets-B9MeWmW6.mjs} +2 -2
- package/dist/rpc/client.d.mts +1 -1
- package/dist/rpc/client.mjs +1 -1
- package/dist/rpc/dump.d.mts +2 -1
- package/dist/rpc/index.d.mts +3 -2
- package/dist/rpc/server.d.mts +1 -1
- package/dist/rpc/server.mjs +1 -1
- package/dist/rpc/transports/sse-client.d.mts +1 -1
- package/dist/rpc/transports/sse-server.d.mts +3 -3
- package/dist/rpc/transports/sse-server.mjs +1 -1
- package/dist/rpc/transports/ws-bun.d.mts +2 -2
- package/dist/rpc/transports/ws-bun.mjs +1 -1
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-deno.d.mts +2 -2
- package/dist/rpc/transports/ws-deno.mjs +1 -1
- package/dist/rpc/transports/ws-server.d.mts +1 -1
- package/dist/rpc/transports/ws-server.mjs +1 -1
- package/dist/{rpc-core-CvkU23bQ.mjs → rpc-core-BXyMjbKG.mjs} +1 -1
- package/dist/{rpc-core-BlL-Ip8n.d.mts → rpc-core-rLrwFEcw.d.mts} +4 -4
- package/dist/{services-install-Ben4yh52.mjs → services-install-D5YUwFXW.mjs} +17 -1
- package/dist/{sse-client-BcbYwXdD.d.mts → sse-client-DNdscfu_.d.mts} +2 -2
- package/dist/{storage-B70AXK64.mjs → storage-CHD1IkqU.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/{types-D2vGd7-2.d.mts → types-BmDbfHCx.d.mts} +2 -3
- package/dist/utils/debounce.d.mts +50 -0
- package/dist/utils/debounce.mjs +88 -0
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/launch-editor.d.mts +8 -0
- package/dist/utils/launch-editor.mjs +36 -1
- package/dist/utils/nostics.d.mts +2 -2
- package/dist/utils/remote-assets.mjs +1 -1
- package/dist/utils/serve-static.mjs +1 -1
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/simple-schema.d.mts +3 -2
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/utils/url.d.mts +31 -0
- package/dist/utils/url.mjs +58 -0
- package/dist/{ws-client-CNpP6Ium.d.mts → ws-client-6Mrz6eC4.d.mts} +2 -2
- package/dist/{ws-server-BB8jhxeT.d.mts → ws-server-y2R76aSW.d.mts} +2 -2
- package/package.json +10 -11
- package/dist/_shared-U8D-xzrp.mjs +0 -115
- package/dist/agent-tool-name-DGzeuWcO.mjs +0 -31
- package/dist/client-assets-DNdhagGm.mjs +0 -16
- package/dist/nostics-DD6gsDZA.mjs +0 -108
- package/dist/recipes/common-rpc-functions.d.mts +0 -70
- package/dist/recipes/common-rpc-functions.mjs +0 -115
- package/dist/simple-schema-Bi40l-P6.mjs +0 -154
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import { t as resolveClientAssets } from "./client-assets-DNdhagGm.mjs";
|
|
2
1
|
import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
|
|
3
|
-
import { t as diagnostics } from "./diagnostics-
|
|
4
|
-
import { t as createHostContext } from "./context-
|
|
5
|
-
import { t as resolveStaticAssetsSource } from "./remote-assets-
|
|
6
|
-
import { a as resolveMcpConfig, i as resolveDevServerPort, n as normalizeBasePath, r as resolveBasePath, s as
|
|
2
|
+
import { t as diagnostics } from "./diagnostics-Cx4_VjlG.mjs";
|
|
3
|
+
import { t as createHostContext } from "./context-C141q8H4.mjs";
|
|
4
|
+
import { t as resolveStaticAssetsSource } from "./remote-assets-B9MeWmW6.mjs";
|
|
5
|
+
import { a as resolveMcpConfig, c as joinURL, d as withoutLeadingSlash, i as resolveDevServerPort, l as withBase, n as normalizeBasePath, r as resolveBasePath, s as importAgenticMcp, t as loadAutoMcpAdapter } from "./_shared-B2PZsp-J.mjs";
|
|
7
6
|
import { t as createH3DevframeHost } from "./host-h3-BROI6SQ4.mjs";
|
|
8
|
-
import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-
|
|
7
|
+
import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-wC2sfEU_.mjs";
|
|
9
8
|
import { open } from "./utils/open.mjs";
|
|
10
9
|
import { mountStaticHandler } from "./utils/serve-static.mjs";
|
|
11
10
|
import { resolve } from "pathe";
|
|
12
11
|
import { createServer } from "node:http";
|
|
13
12
|
import process from "node:process";
|
|
14
|
-
import { joinURL, withBase, withoutLeadingSlash } from "ufo";
|
|
15
13
|
import { H3, toNodeHandler } from "h3";
|
|
16
14
|
//#region src/adapters/initiate.ts
|
|
17
15
|
const INSTANCE_INTERNALS = /* @__PURE__ */ new WeakMap();
|
|
@@ -38,7 +36,7 @@ function getInstanceInternals(handler) {
|
|
|
38
36
|
*/
|
|
39
37
|
function initDevframe(def, options) {
|
|
40
38
|
const base = normalizeBasePath(options.base);
|
|
41
|
-
const distDir = options.distDir === false ? void 0 : options.distDir ??
|
|
39
|
+
const distDir = options.distDir === false ? void 0 : options.distDir ?? def.clientAssets;
|
|
42
40
|
const app = options.app ?? new H3();
|
|
43
41
|
const host = options.host ?? def.cli?.host ?? "localhost";
|
|
44
42
|
const shell = createInstanceShell({
|
|
@@ -88,7 +86,7 @@ function initDevframe(def, options) {
|
|
|
88
86
|
for (const input of def.services ?? []) context.services.install(input, { resolveFrom: def.importMetaUrl });
|
|
89
87
|
await context.services.ready();
|
|
90
88
|
await def.setup(context, setupInfo);
|
|
91
|
-
const mcp = await mountMcpRoute(app, context, def, base, options.mcp ??
|
|
89
|
+
const mcp = await mountMcpRoute(app, context, def, base, options.mcp ?? "auto");
|
|
92
90
|
return {
|
|
93
91
|
context,
|
|
94
92
|
...mcp?.meta ? { mcp: mcp.meta } : {},
|
|
@@ -119,11 +117,14 @@ function initDevframe(def, options) {
|
|
|
119
117
|
}
|
|
120
118
|
/**
|
|
121
119
|
* Mount the route-based MCP server at `<base>__mcp`, before the SPA static
|
|
122
|
-
* catch-all so the exact route wins. The
|
|
123
|
-
*
|
|
124
|
-
* mounts
|
|
125
|
-
*
|
|
126
|
-
*
|
|
120
|
+
* catch-all so the exact route wins. The adapter (from the optional
|
|
121
|
+
* `@devframes/agentic` peer) is pulled in dynamically only when the route
|
|
122
|
+
* mounts, keeping it and the MCP SDK out of consumer bundles: `'auto'`
|
|
123
|
+
* mounts once `setup()` left a non-empty agent surface AND the peer is
|
|
124
|
+
* installed (an empty surface loads no MCP code; a non-empty one without the
|
|
125
|
+
* peer warns once and mounts nothing); an explicit setting mounts
|
|
126
|
+
* unconditionally, throwing DF0079 when the peer is absent. The resolved
|
|
127
|
+
* config is origin-only unless it opts into a bearer/callback.
|
|
127
128
|
*/
|
|
128
129
|
async function mountMcpRoute(app, context, def, base, setting) {
|
|
129
130
|
let module;
|
|
@@ -134,16 +135,7 @@ async function mountMcpRoute(app, context, def, base, setting) {
|
|
|
134
135
|
} else config = resolveMcpConfig(setting);
|
|
135
136
|
if (!config) return void 0;
|
|
136
137
|
const route = withoutLeadingSlash(config.path ?? "__mcp");
|
|
137
|
-
|
|
138
|
-
module = await importRuntimeModule("devframe/adapters/mcp");
|
|
139
|
-
} catch (error) {
|
|
140
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
141
|
-
throw diagnostics.DF0017({
|
|
142
|
-
transport: "http",
|
|
143
|
-
reason,
|
|
144
|
-
cause: error
|
|
145
|
-
});
|
|
146
|
-
}
|
|
138
|
+
module ??= await importAgenticMcp();
|
|
147
139
|
const mounted = module.mountMcpHttp(app, context, joinURL(base, route), {
|
|
148
140
|
serverName: `${def.id} (devframe)`,
|
|
149
141
|
serverVersion: def.version ?? "0.0.0",
|
|
@@ -68,8 +68,8 @@ const diagnostics = defineDiagnostics({
|
|
|
68
68
|
fix: "Discovery tooling (`devframe connect`) will not see this instance. Check that the registry directory is writable, point `DEVFRAME_INSTANCES_DIR` at a writable directory, or set `DEVFRAME_DISABLE_INSTANCE_REGISTRY=1` to opt out of registration."
|
|
69
69
|
},
|
|
70
70
|
DF0046: {
|
|
71
|
-
why: (p) => `\`devframe connect\` requires the optional peer dependency @
|
|
72
|
-
fix: "Install it next to devframe (e.g. `npm install @
|
|
71
|
+
why: (p) => `\`devframe connect\` requires the optional peer dependency @devframes/agentic: ${p.reason}`,
|
|
72
|
+
fix: "Install it next to devframe (e.g. `npm install @devframes/agentic`) and run `devframe connect` again."
|
|
73
73
|
},
|
|
74
74
|
DF0047: {
|
|
75
75
|
why: (p) => `Agent tool "${p.id}" is hidden from the MCP surface: its wire name "${p.name}" collides with the tool "${p.existing}".`,
|
|
@@ -89,7 +89,7 @@ const diagnostics = defineDiagnostics({
|
|
|
89
89
|
},
|
|
90
90
|
DF0051: {
|
|
91
91
|
why: (p) => `The devframe instance on port ${p.port} has no MCP endpoint.`,
|
|
92
|
-
fix: "Restart the instance with the --mcp flag
|
|
92
|
+
fix: "Restart the instance with the --mcp flag to expose its tools, then list instances again."
|
|
93
93
|
},
|
|
94
94
|
DF0052: {
|
|
95
95
|
why: (p) => `Failed to listen on ${p.host}:${p.port}: ${p.reason}`,
|
|
@@ -174,6 +174,14 @@ const diagnostics = defineDiagnostics({
|
|
|
174
174
|
DF0076: {
|
|
175
175
|
why: (p) => `\`attach\` / \`handleUpgrade\` drive a raw \`node:http\` upgrade into crossws's Node adapter, which refuses to run on ${p.runtime}.`,
|
|
176
176
|
fix: "On Bun/Deno, serve the advertised `__ws` route from `Bun.serve` / `Deno.serve` with `attachBunWsTransport` / `attachDenoWsTransport` (see the hub-deno example), or connect over the SSE endpoint instead."
|
|
177
|
+
},
|
|
178
|
+
DF0078: {
|
|
179
|
+
why: "This devframe exposes agent tools, but the MCP endpoint stays off: the optional peer \"@devframes/agentic\" is not installed.",
|
|
180
|
+
fix: "Install `@devframes/agentic` next to devframe to serve the MCP endpoint, or set `mcp: false` to opt out silently."
|
|
181
|
+
},
|
|
182
|
+
DF0079: {
|
|
183
|
+
why: (p) => `The \`mcp\` option is enabled, but the optional peer "@devframes/agentic" could not be loaded: ${p.reason}`,
|
|
184
|
+
fix: "Install `@devframes/agentic` next to devframe (the MCP adapter and the MCP SDK live there), or remove the explicit `mcp` setting."
|
|
177
185
|
}
|
|
178
186
|
}
|
|
179
187
|
});
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { colors } from "./utils/colors.mjs";
|
|
2
|
+
import { defineDiagnostics } from "nostics";
|
|
3
|
+
import { ansiFormatter } from "nostics/formatters/ansi";
|
|
4
|
+
//#region src/events.ts
|
|
5
|
+
/**
|
|
6
|
+
* Centralized registry of the core devframe event names: the node-side host
|
|
7
|
+
* bus events, the client RPC connection events, and the server→client
|
|
8
|
+
* broadcast notifications, so these names live in one place instead of
|
|
9
|
+
* scattered string literals.
|
|
10
|
+
*
|
|
11
|
+
* **Keep this in sync with [`docs/content/8.references/3.events.md`](../../../docs/content/8.references/3.events.md)**
|
|
12
|
+
* (the "Core devframe events" section): every name here appears in that page's
|
|
13
|
+
* tables, and every name there resolves to an entry here. Add, rename, or
|
|
14
|
+
* remove a name in both places in the same change, and reference
|
|
15
|
+
* `DEVFRAME_EVENTS.*` from call sites instead of re-typing a literal.
|
|
16
|
+
*
|
|
17
|
+
* This map covers **notifications** (events, broadcasts). The request/response
|
|
18
|
+
* RPC endpoints of the shared-state, streaming, and auth-handshake protocols
|
|
19
|
+
* (`devframe:rpc:server-state:*`, `devframe:streaming:subscribe`,
|
|
20
|
+
* `anonymous:devframe:auth`, …) are defined at their handlers and typed in
|
|
21
|
+
* `types/rpc-augments.ts`; they aren't events and stay out of this map.
|
|
22
|
+
*
|
|
23
|
+
* The `EventEmitter` maps (`RpcClientEvents`, `DevframeAgentHostEvents`) and the
|
|
24
|
+
* `DevframeRpcClientFunctions` augmentation declare these names as type-level
|
|
25
|
+
* keys (a literal is unavoidable in a type position); those declarations mirror
|
|
26
|
+
* this map and move with it.
|
|
27
|
+
*/
|
|
28
|
+
const DEVFRAME_EVENTS = {
|
|
29
|
+
/**
|
|
30
|
+
* Node-side host `EventEmitter` events. The agent host (`ctx.agent.events`)
|
|
31
|
+
* emits these as its tool/resource surface changes; protocol adapters (e.g.
|
|
32
|
+
* MCP) subscribe to re-publish their manifest.
|
|
33
|
+
*/
|
|
34
|
+
bus: {
|
|
35
|
+
agentManifestChanged: "agent:manifest:changed",
|
|
36
|
+
agentToolRegistered: "agent:tool:registered",
|
|
37
|
+
agentToolUnregistered: "agent:tool:unregistered",
|
|
38
|
+
agentResourceRegistered: "agent:resource:registered",
|
|
39
|
+
agentResourceUnregistered: "agent:resource:unregistered"
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Client-side RPC connection `EventEmitter` events (`rpc.events`) a UI
|
|
43
|
+
* subscribes to for connection lifecycle and error surfacing.
|
|
44
|
+
*/
|
|
45
|
+
client: {
|
|
46
|
+
isTrustedUpdated: "rpc:is-trusted:updated",
|
|
47
|
+
error: "rpc:error",
|
|
48
|
+
connectionStatus: "connection:status",
|
|
49
|
+
connectionError: "connection:error"
|
|
50
|
+
},
|
|
51
|
+
/**
|
|
52
|
+
* Broadcast notifications the server pushes to clients (server → client),
|
|
53
|
+
* `devframe:` prefix. The paired request methods (subscribe/get/set/…) are
|
|
54
|
+
* RPC endpoints, not events, and are omitted deliberately.
|
|
55
|
+
*/
|
|
56
|
+
broadcast: {
|
|
57
|
+
authRevoked: "devframe:auth:revoked",
|
|
58
|
+
clientStateUpdated: "devframe:rpc:client-state:updated",
|
|
59
|
+
clientStatePatch: "devframe:rpc:client-state:patch",
|
|
60
|
+
streamingChunk: "devframe:streaming:chunk",
|
|
61
|
+
streamingEnd: "devframe:streaming:end",
|
|
62
|
+
streamingUploadCancel: "devframe:streaming:upload-cancel"
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* In-page channel notifications the page script pushes to its panels
|
|
66
|
+
* (page script → panel), `devframe:` prefix. The paired request methods
|
|
67
|
+
* (`devframe:in-page:page-state:subscribe`/`set`/`patch`) are call
|
|
68
|
+
* endpoints, not events, and are defined at their handlers
|
|
69
|
+
* (`in-page-channel/state.ts`).
|
|
70
|
+
*/
|
|
71
|
+
inPageChannel: {
|
|
72
|
+
panelStateUpdated: "devframe:in-page:panel-state:updated",
|
|
73
|
+
panelStatePatch: "devframe:in-page:panel-state:patch"
|
|
74
|
+
},
|
|
75
|
+
/** `postMessage` channels the runtime posts across window boundaries. */
|
|
76
|
+
postMessage: {
|
|
77
|
+
remoteAssetsError: "devframe:remote-assets-error",
|
|
78
|
+
inPageChannel: "devframe:in-page-channel"
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/utils/nostics.ts
|
|
83
|
+
const formatAnsi = ansiFormatter(colors);
|
|
84
|
+
/**
|
|
85
|
+
* The reporter every {@link defineDiagnostics} call below wires in ahead of
|
|
86
|
+
* any caller-supplied ones: prints the diagnostic through devframe's own
|
|
87
|
+
* ANSI colors via `console[method]` (default `'warn'`).
|
|
88
|
+
*/
|
|
89
|
+
function devframeReporter(d, { method = "warn" } = {}) {
|
|
90
|
+
console[method](formatAnsi(d));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Drop-in replacement for `nostics`'s `defineDiagnostics()` with devframe's
|
|
94
|
+
* ANSI console reporter pre-wired ahead of any `reporters` passed in. Every
|
|
95
|
+
* `diagnostics.ts` in devframe core, `@devframes/hub`, `@devframes/json-render`,
|
|
96
|
+
* and the built-in plugins defines its codes through this instead of
|
|
97
|
+
* `nostics`'s own `defineDiagnostics`; the reporter registration lives
|
|
98
|
+
* here, once, so none of them need to build their own reporter (`colors`,
|
|
99
|
+
* `ansiFormatter`) or take a direct dependency on `nostics` themselves.
|
|
100
|
+
*/
|
|
101
|
+
function defineDiagnostics$1(options) {
|
|
102
|
+
return defineDiagnostics({
|
|
103
|
+
...options,
|
|
104
|
+
reporters: [devframeReporter, ...options.reporters ?? []]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region ../../node_modules/.pnpm/birpc@4.2.0/node_modules/birpc/dist/index.mjs
|
|
109
|
+
function createPromiseWithResolvers() {
|
|
110
|
+
let resolve;
|
|
111
|
+
let reject;
|
|
112
|
+
return {
|
|
113
|
+
promise: new Promise((res, rej) => {
|
|
114
|
+
resolve = res;
|
|
115
|
+
reject = rej;
|
|
116
|
+
}),
|
|
117
|
+
resolve,
|
|
118
|
+
reject
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const random = Math.random.bind(Math);
|
|
122
|
+
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
123
|
+
function nanoid(size = 21) {
|
|
124
|
+
let id = "";
|
|
125
|
+
let i = size;
|
|
126
|
+
while (i--) id += urlAlphabet[random() * 64 | 0];
|
|
127
|
+
return id;
|
|
128
|
+
}
|
|
129
|
+
const DEFAULT_TIMEOUT = 6e4;
|
|
130
|
+
const defaultSerialize = (i) => i;
|
|
131
|
+
const defaultDeserialize = defaultSerialize;
|
|
132
|
+
const { clearTimeout, setTimeout } = globalThis;
|
|
133
|
+
function createBirpc($functions, options) {
|
|
134
|
+
const { post, on, off = () => {}, eventNames = [], serialize = defaultSerialize, deserialize = defaultDeserialize, resolver, bind = "rpc", timeout = DEFAULT_TIMEOUT, proxify = true } = options;
|
|
135
|
+
let $closed = false;
|
|
136
|
+
const _rpcPromiseMap = /* @__PURE__ */ new Map();
|
|
137
|
+
let _promiseInit;
|
|
138
|
+
let rpc;
|
|
139
|
+
async function _call(method, args, event, optional) {
|
|
140
|
+
if ($closed) throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
|
|
141
|
+
const req = {
|
|
142
|
+
m: method,
|
|
143
|
+
a: args,
|
|
144
|
+
t: "q"
|
|
145
|
+
};
|
|
146
|
+
if (optional) req.o = true;
|
|
147
|
+
const send = async (_req) => post(serialize(_req));
|
|
148
|
+
if (event) {
|
|
149
|
+
await send(req);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (_promiseInit) try {
|
|
153
|
+
await _promiseInit;
|
|
154
|
+
} finally {
|
|
155
|
+
_promiseInit = void 0;
|
|
156
|
+
}
|
|
157
|
+
let { promise, resolve, reject } = createPromiseWithResolvers();
|
|
158
|
+
const id = nanoid();
|
|
159
|
+
req.i = id;
|
|
160
|
+
let timeoutId;
|
|
161
|
+
async function handler(newReq = req) {
|
|
162
|
+
if (timeout >= 0) {
|
|
163
|
+
timeoutId = setTimeout(() => {
|
|
164
|
+
try {
|
|
165
|
+
if (options.onTimeoutError?.call(rpc, method, args) !== true) throw new Error(`[birpc] timeout on calling "${method}"`);
|
|
166
|
+
} catch (e) {
|
|
167
|
+
reject(e);
|
|
168
|
+
}
|
|
169
|
+
_rpcPromiseMap.delete(id);
|
|
170
|
+
}, timeout);
|
|
171
|
+
if (typeof timeoutId === "object") timeoutId = timeoutId.unref?.();
|
|
172
|
+
}
|
|
173
|
+
_rpcPromiseMap.set(id, {
|
|
174
|
+
resolve,
|
|
175
|
+
reject,
|
|
176
|
+
timeoutId,
|
|
177
|
+
method
|
|
178
|
+
});
|
|
179
|
+
await send(newReq);
|
|
180
|
+
return promise;
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
if (options.onRequest) await options.onRequest.call(rpc, req, handler, resolve);
|
|
184
|
+
else await handler();
|
|
185
|
+
} catch (e) {
|
|
186
|
+
if (options.onGeneralError?.call(rpc, e) !== true) throw e;
|
|
187
|
+
return;
|
|
188
|
+
} finally {
|
|
189
|
+
clearTimeout(timeoutId);
|
|
190
|
+
_rpcPromiseMap.delete(id);
|
|
191
|
+
}
|
|
192
|
+
return promise;
|
|
193
|
+
}
|
|
194
|
+
const builtinMethods = {
|
|
195
|
+
$call: (method, ...args) => _call(method, args, false),
|
|
196
|
+
$callOptional: (method, ...args) => _call(method, args, false, true),
|
|
197
|
+
$callEvent: (method, ...args) => _call(method, args, true),
|
|
198
|
+
$callRaw: (options) => _call(options.method, options.args, options.event, options.optional),
|
|
199
|
+
$rejectPendingCalls,
|
|
200
|
+
get $closed() {
|
|
201
|
+
return $closed;
|
|
202
|
+
},
|
|
203
|
+
get $meta() {
|
|
204
|
+
return options.meta;
|
|
205
|
+
},
|
|
206
|
+
$close,
|
|
207
|
+
$functions
|
|
208
|
+
};
|
|
209
|
+
if (proxify) rpc = new Proxy({}, { get(_, method) {
|
|
210
|
+
if (Object.hasOwn(builtinMethods, method)) return builtinMethods[method];
|
|
211
|
+
if (method === "then" && !eventNames.includes("then") && !("then" in $functions)) return void 0;
|
|
212
|
+
const sendEvent = (...args) => _call(method, args, true);
|
|
213
|
+
if (eventNames.includes(method)) {
|
|
214
|
+
sendEvent.asEvent = sendEvent;
|
|
215
|
+
return sendEvent;
|
|
216
|
+
}
|
|
217
|
+
const sendCall = (...args) => _call(method, args, false);
|
|
218
|
+
sendCall.asEvent = sendEvent;
|
|
219
|
+
return sendCall;
|
|
220
|
+
} });
|
|
221
|
+
else rpc = builtinMethods;
|
|
222
|
+
function $close(customError) {
|
|
223
|
+
$closed = true;
|
|
224
|
+
_rpcPromiseMap.forEach(({ reject, method }) => {
|
|
225
|
+
const error = /* @__PURE__ */ new Error(`[birpc] rpc is closed, cannot call "${method}"`);
|
|
226
|
+
if (customError) {
|
|
227
|
+
customError.cause ??= error;
|
|
228
|
+
return reject(customError);
|
|
229
|
+
}
|
|
230
|
+
reject(error);
|
|
231
|
+
});
|
|
232
|
+
_rpcPromiseMap.clear();
|
|
233
|
+
off(onMessage);
|
|
234
|
+
}
|
|
235
|
+
function $rejectPendingCalls(handler) {
|
|
236
|
+
const handlerResults = Array.from(_rpcPromiseMap.values()).map(({ method, reject }) => {
|
|
237
|
+
if (!handler) return reject(/* @__PURE__ */ new Error(`[birpc]: rejected pending call "${method}".`));
|
|
238
|
+
return handler({
|
|
239
|
+
method,
|
|
240
|
+
reject
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
_rpcPromiseMap.clear();
|
|
244
|
+
return handlerResults;
|
|
245
|
+
}
|
|
246
|
+
async function onMessage(data, ...extra) {
|
|
247
|
+
let msg;
|
|
248
|
+
try {
|
|
249
|
+
msg = deserialize(data);
|
|
250
|
+
} catch (e) {
|
|
251
|
+
if (options.onGeneralError?.call(rpc, e) !== true) throw e;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (msg.t === "q") {
|
|
255
|
+
const { m: method, a: args, o: optional } = msg;
|
|
256
|
+
let result, error;
|
|
257
|
+
let fn = await (resolver ? resolver.call(rpc, method, $functions[method]) : $functions[method]);
|
|
258
|
+
if (optional) fn ||= () => void 0;
|
|
259
|
+
if (!fn) error = /* @__PURE__ */ new Error(`[birpc] function "${method}" not found`);
|
|
260
|
+
else try {
|
|
261
|
+
result = await fn.apply(bind === "rpc" ? rpc : $functions, args);
|
|
262
|
+
} catch (e) {
|
|
263
|
+
error = e;
|
|
264
|
+
}
|
|
265
|
+
if (msg.i) {
|
|
266
|
+
if (error && options.onFunctionError) {
|
|
267
|
+
if (options.onFunctionError.call(rpc, error, method, args) === true) return;
|
|
268
|
+
}
|
|
269
|
+
if (!error) try {
|
|
270
|
+
await post(serialize({
|
|
271
|
+
t: "s",
|
|
272
|
+
i: msg.i,
|
|
273
|
+
r: result
|
|
274
|
+
}), ...extra);
|
|
275
|
+
return;
|
|
276
|
+
} catch (e) {
|
|
277
|
+
error = e;
|
|
278
|
+
if (options.onGeneralError?.call(rpc, e, method, args) !== true) throw e;
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
await post(serialize({
|
|
282
|
+
t: "s",
|
|
283
|
+
i: msg.i,
|
|
284
|
+
e: error
|
|
285
|
+
}), ...extra);
|
|
286
|
+
} catch (e) {
|
|
287
|
+
if (options.onGeneralError?.call(rpc, e, method, args) !== true) throw e;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
const { i: ack, r: result, e: error } = msg;
|
|
292
|
+
const promise = _rpcPromiseMap.get(ack);
|
|
293
|
+
if (promise) {
|
|
294
|
+
clearTimeout(promise.timeoutId);
|
|
295
|
+
if (error) promise.reject(error);
|
|
296
|
+
else promise.resolve(result);
|
|
297
|
+
}
|
|
298
|
+
_rpcPromiseMap.delete(ack);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
_promiseInit = on(onMessage);
|
|
302
|
+
return rpc;
|
|
303
|
+
}
|
|
304
|
+
//#endregion
|
|
305
|
+
export { defineDiagnostics$1 as n, DEVFRAME_EVENTS as r, createBirpc as t };
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
//#region ../../node_modules/.pnpm/birpc@4.2.0/node_modules/birpc/dist/index.mjs
|
|
2
|
+
function createPromiseWithResolvers() {
|
|
3
|
+
let resolve;
|
|
4
|
+
let reject;
|
|
5
|
+
return {
|
|
6
|
+
promise: new Promise((res, rej) => {
|
|
7
|
+
resolve = res;
|
|
8
|
+
reject = rej;
|
|
9
|
+
}),
|
|
10
|
+
resolve,
|
|
11
|
+
reject
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const _cacheMap = /* @__PURE__ */ new WeakMap();
|
|
15
|
+
function cachedMap(items, fn) {
|
|
16
|
+
return items.map((i) => {
|
|
17
|
+
let r = _cacheMap.get(i);
|
|
18
|
+
if (!r) {
|
|
19
|
+
r = fn(i);
|
|
20
|
+
_cacheMap.set(i, r);
|
|
21
|
+
}
|
|
22
|
+
return r;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const random = Math.random.bind(Math);
|
|
26
|
+
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
27
|
+
function nanoid(size = 21) {
|
|
28
|
+
let id = "";
|
|
29
|
+
let i = size;
|
|
30
|
+
while (i--) id += urlAlphabet[random() * 64 | 0];
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
const DEFAULT_TIMEOUT = 6e4;
|
|
34
|
+
const defaultSerialize = (i) => i;
|
|
35
|
+
const defaultDeserialize = defaultSerialize;
|
|
36
|
+
const { clearTimeout, setTimeout } = globalThis;
|
|
37
|
+
function createBirpc($functions, options) {
|
|
38
|
+
const { post, on, off = () => {}, eventNames = [], serialize = defaultSerialize, deserialize = defaultDeserialize, resolver, bind = "rpc", timeout = DEFAULT_TIMEOUT, proxify = true } = options;
|
|
39
|
+
let $closed = false;
|
|
40
|
+
const _rpcPromiseMap = /* @__PURE__ */ new Map();
|
|
41
|
+
let _promiseInit;
|
|
42
|
+
let rpc;
|
|
43
|
+
async function _call(method, args, event, optional) {
|
|
44
|
+
if ($closed) throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
|
|
45
|
+
const req = {
|
|
46
|
+
m: method,
|
|
47
|
+
a: args,
|
|
48
|
+
t: "q"
|
|
49
|
+
};
|
|
50
|
+
if (optional) req.o = true;
|
|
51
|
+
const send = async (_req) => post(serialize(_req));
|
|
52
|
+
if (event) {
|
|
53
|
+
await send(req);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (_promiseInit) try {
|
|
57
|
+
await _promiseInit;
|
|
58
|
+
} finally {
|
|
59
|
+
_promiseInit = void 0;
|
|
60
|
+
}
|
|
61
|
+
let { promise, resolve, reject } = createPromiseWithResolvers();
|
|
62
|
+
const id = nanoid();
|
|
63
|
+
req.i = id;
|
|
64
|
+
let timeoutId;
|
|
65
|
+
async function handler(newReq = req) {
|
|
66
|
+
if (timeout >= 0) {
|
|
67
|
+
timeoutId = setTimeout(() => {
|
|
68
|
+
try {
|
|
69
|
+
if (options.onTimeoutError?.call(rpc, method, args) !== true) throw new Error(`[birpc] timeout on calling "${method}"`);
|
|
70
|
+
} catch (e) {
|
|
71
|
+
reject(e);
|
|
72
|
+
}
|
|
73
|
+
_rpcPromiseMap.delete(id);
|
|
74
|
+
}, timeout);
|
|
75
|
+
if (typeof timeoutId === "object") timeoutId = timeoutId.unref?.();
|
|
76
|
+
}
|
|
77
|
+
_rpcPromiseMap.set(id, {
|
|
78
|
+
resolve,
|
|
79
|
+
reject,
|
|
80
|
+
timeoutId,
|
|
81
|
+
method
|
|
82
|
+
});
|
|
83
|
+
await send(newReq);
|
|
84
|
+
return promise;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
if (options.onRequest) await options.onRequest.call(rpc, req, handler, resolve);
|
|
88
|
+
else await handler();
|
|
89
|
+
} catch (e) {
|
|
90
|
+
if (options.onGeneralError?.call(rpc, e) !== true) throw e;
|
|
91
|
+
return;
|
|
92
|
+
} finally {
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
_rpcPromiseMap.delete(id);
|
|
95
|
+
}
|
|
96
|
+
return promise;
|
|
97
|
+
}
|
|
98
|
+
const builtinMethods = {
|
|
99
|
+
$call: (method, ...args) => _call(method, args, false),
|
|
100
|
+
$callOptional: (method, ...args) => _call(method, args, false, true),
|
|
101
|
+
$callEvent: (method, ...args) => _call(method, args, true),
|
|
102
|
+
$callRaw: (options) => _call(options.method, options.args, options.event, options.optional),
|
|
103
|
+
$rejectPendingCalls,
|
|
104
|
+
get $closed() {
|
|
105
|
+
return $closed;
|
|
106
|
+
},
|
|
107
|
+
get $meta() {
|
|
108
|
+
return options.meta;
|
|
109
|
+
},
|
|
110
|
+
$close,
|
|
111
|
+
$functions
|
|
112
|
+
};
|
|
113
|
+
if (proxify) rpc = new Proxy({}, { get(_, method) {
|
|
114
|
+
if (Object.hasOwn(builtinMethods, method)) return builtinMethods[method];
|
|
115
|
+
if (method === "then" && !eventNames.includes("then") && !("then" in $functions)) return void 0;
|
|
116
|
+
const sendEvent = (...args) => _call(method, args, true);
|
|
117
|
+
if (eventNames.includes(method)) {
|
|
118
|
+
sendEvent.asEvent = sendEvent;
|
|
119
|
+
return sendEvent;
|
|
120
|
+
}
|
|
121
|
+
const sendCall = (...args) => _call(method, args, false);
|
|
122
|
+
sendCall.asEvent = sendEvent;
|
|
123
|
+
return sendCall;
|
|
124
|
+
} });
|
|
125
|
+
else rpc = builtinMethods;
|
|
126
|
+
function $close(customError) {
|
|
127
|
+
$closed = true;
|
|
128
|
+
_rpcPromiseMap.forEach(({ reject, method }) => {
|
|
129
|
+
const error = /* @__PURE__ */ new Error(`[birpc] rpc is closed, cannot call "${method}"`);
|
|
130
|
+
if (customError) {
|
|
131
|
+
customError.cause ??= error;
|
|
132
|
+
return reject(customError);
|
|
133
|
+
}
|
|
134
|
+
reject(error);
|
|
135
|
+
});
|
|
136
|
+
_rpcPromiseMap.clear();
|
|
137
|
+
off(onMessage);
|
|
138
|
+
}
|
|
139
|
+
function $rejectPendingCalls(handler) {
|
|
140
|
+
const handlerResults = Array.from(_rpcPromiseMap.values()).map(({ method, reject }) => {
|
|
141
|
+
if (!handler) return reject(/* @__PURE__ */ new Error(`[birpc]: rejected pending call "${method}".`));
|
|
142
|
+
return handler({
|
|
143
|
+
method,
|
|
144
|
+
reject
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
_rpcPromiseMap.clear();
|
|
148
|
+
return handlerResults;
|
|
149
|
+
}
|
|
150
|
+
async function onMessage(data, ...extra) {
|
|
151
|
+
let msg;
|
|
152
|
+
try {
|
|
153
|
+
msg = deserialize(data);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
if (options.onGeneralError?.call(rpc, e) !== true) throw e;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (msg.t === "q") {
|
|
159
|
+
const { m: method, a: args, o: optional } = msg;
|
|
160
|
+
let result, error;
|
|
161
|
+
let fn = await (resolver ? resolver.call(rpc, method, $functions[method]) : $functions[method]);
|
|
162
|
+
if (optional) fn ||= () => void 0;
|
|
163
|
+
if (!fn) error = /* @__PURE__ */ new Error(`[birpc] function "${method}" not found`);
|
|
164
|
+
else try {
|
|
165
|
+
result = await fn.apply(bind === "rpc" ? rpc : $functions, args);
|
|
166
|
+
} catch (e) {
|
|
167
|
+
error = e;
|
|
168
|
+
}
|
|
169
|
+
if (msg.i) {
|
|
170
|
+
if (error && options.onFunctionError) {
|
|
171
|
+
if (options.onFunctionError.call(rpc, error, method, args) === true) return;
|
|
172
|
+
}
|
|
173
|
+
if (!error) try {
|
|
174
|
+
await post(serialize({
|
|
175
|
+
t: "s",
|
|
176
|
+
i: msg.i,
|
|
177
|
+
r: result
|
|
178
|
+
}), ...extra);
|
|
179
|
+
return;
|
|
180
|
+
} catch (e) {
|
|
181
|
+
error = e;
|
|
182
|
+
if (options.onGeneralError?.call(rpc, e, method, args) !== true) throw e;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
await post(serialize({
|
|
186
|
+
t: "s",
|
|
187
|
+
i: msg.i,
|
|
188
|
+
e: error
|
|
189
|
+
}), ...extra);
|
|
190
|
+
} catch (e) {
|
|
191
|
+
if (options.onGeneralError?.call(rpc, e, method, args) !== true) throw e;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
const { i: ack, r: result, e: error } = msg;
|
|
196
|
+
const promise = _rpcPromiseMap.get(ack);
|
|
197
|
+
if (promise) {
|
|
198
|
+
clearTimeout(promise.timeoutId);
|
|
199
|
+
if (error) promise.reject(error);
|
|
200
|
+
else promise.resolve(result);
|
|
201
|
+
}
|
|
202
|
+
_rpcPromiseMap.delete(ack);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
_promiseInit = on(onMessage);
|
|
206
|
+
return rpc;
|
|
207
|
+
}
|
|
208
|
+
function createBirpcGroup(functions, channels, options = {}) {
|
|
209
|
+
const { proxify = true } = options;
|
|
210
|
+
const getChannels = () => typeof channels === "function" ? channels() : channels;
|
|
211
|
+
const getClients = (channels = getChannels()) => cachedMap(channels, (s) => createBirpc(functions, {
|
|
212
|
+
...options,
|
|
213
|
+
...s
|
|
214
|
+
}));
|
|
215
|
+
function _boardcast(options) {
|
|
216
|
+
const clients = getClients();
|
|
217
|
+
return Promise.all(clients.map((c) => c.$callRaw(options)));
|
|
218
|
+
}
|
|
219
|
+
const broadcastBuiltin = {
|
|
220
|
+
$call: (method, ...args) => _boardcast({
|
|
221
|
+
method,
|
|
222
|
+
args,
|
|
223
|
+
event: false
|
|
224
|
+
}),
|
|
225
|
+
$callOptional: (method, ...args) => _boardcast({
|
|
226
|
+
method,
|
|
227
|
+
args,
|
|
228
|
+
event: false,
|
|
229
|
+
optional: true
|
|
230
|
+
}),
|
|
231
|
+
$callEvent: (method, ...args) => _boardcast({
|
|
232
|
+
method,
|
|
233
|
+
args,
|
|
234
|
+
event: true
|
|
235
|
+
}),
|
|
236
|
+
$callRaw: (options) => _boardcast(options)
|
|
237
|
+
};
|
|
238
|
+
const broadcastProxy = proxify ? new Proxy({}, { get(_, method) {
|
|
239
|
+
if (Object.hasOwn(broadcastBuiltin, method)) return broadcastBuiltin[method];
|
|
240
|
+
const callbacks = getClients().map((c) => c[method]);
|
|
241
|
+
const sendCall = (...args) => {
|
|
242
|
+
return Promise.all(callbacks.map((i) => i(...args)));
|
|
243
|
+
};
|
|
244
|
+
sendCall.asEvent = async (...args) => {
|
|
245
|
+
await Promise.all(callbacks.map((i) => i.asEvent(...args)));
|
|
246
|
+
};
|
|
247
|
+
return sendCall;
|
|
248
|
+
} }) : broadcastBuiltin;
|
|
249
|
+
function updateChannels(fn) {
|
|
250
|
+
const channels = getChannels();
|
|
251
|
+
fn?.(channels);
|
|
252
|
+
return getClients(channels);
|
|
253
|
+
}
|
|
254
|
+
getClients();
|
|
255
|
+
return {
|
|
256
|
+
get clients() {
|
|
257
|
+
return getClients();
|
|
258
|
+
},
|
|
259
|
+
functions,
|
|
260
|
+
updateChannels,
|
|
261
|
+
broadcast: broadcastProxy
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
//#endregion
|
|
265
|
+
export { createBirpcGroup as n, createBirpc as t };
|