devframe 0.9.7 → 0.9.9
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-BM3PdYli.mjs → _shared-C08SdQRl.mjs} +15 -4
- package/dist/{_shared-BJ6AmwTu.d.mts → _shared-CK3czkH4.d.mts} +25 -2
- package/dist/adapters/build.d.mts +6 -6
- package/dist/adapters/build.mjs +32 -22
- package/dist/adapters/cac.d.mts +16 -1
- package/dist/adapters/cac.mjs +8 -7
- package/dist/adapters/dev.d.mts +13 -13
- package/dist/adapters/dev.mjs +2 -2
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +28 -26
- package/dist/adapters/initiate.mjs +1 -1
- package/dist/adapters/mcp.d.mts +28 -14
- package/dist/adapters/mcp.mjs +75 -39
- package/dist/{agent-tool-name-EgfoFO8C.mjs → agent-tool-name-DGzeuWcO.mjs} +2 -2
- package/dist/cli/main.d.mts +1 -1
- package/dist/cli/main.mjs +41 -17
- package/dist/client/index.d.mts +36 -36
- package/dist/client/index.mjs +83 -51
- package/dist/client-assets-DNdhagGm.mjs +16 -0
- package/dist/constants.d.mts +8 -7
- package/dist/constants.mjs +7 -6
- package/dist/{context-BhBzOXVa.d.mts → context-4AIVRLYF.d.mts} +173 -122
- package/dist/{context-omlma_1n.mjs → context-CwPUinjn.mjs} +126 -88
- package/dist/{context-KUqAfawQ.mjs → context-DIUvJW4D.mjs} +3 -3
- package/dist/{context-HOnG-WvG.d.mts → context-rgBSPFHS.d.mts} +5 -5
- package/dist/{crypto-token-XCqTSMg9.mjs → crypto-token-TVbGGFuj.mjs} +1 -1
- package/dist/{dev-Czit5IP4.mjs → dev-Eqq5PX0k.mjs} +37 -18
- package/dist/{diagnostics-BXWW3VK-.mjs → diagnostics-BMfN8mb1.mjs} +30 -17
- package/dist/{diagnostics-CD8nlgll.mjs → diagnostics-D0EVm5M6.mjs} +2 -2
- package/dist/{events-4daw0uK9.mjs → events-BV4Dj59a.mjs} +2 -2
- package/dist/{host-h3-fRbF9yor.mjs → host-h3-BJ4siyz7.mjs} +1 -1
- package/dist/in-page-channel/index.d.mts +59 -22
- package/dist/in-page-channel/index.mjs +71 -56
- package/dist/{index-BzyopqxV.d.mts → index-pIVt92jP.d.mts} +9 -9
- package/dist/{index-DcKxIMoI.d.mts → index-pKl67H6w.d.mts} +4 -4
- package/dist/index.d.mts +11 -13
- package/dist/index.mjs +6 -7
- package/dist/{instance-registry-BjlMQbFB.mjs → instance-registry-C7-41RSp.mjs} +8 -8
- package/dist/{instance-shell-Bh4l9Vz_.d.mts → instance-shell-7Z52PE4_.d.mts} +18 -18
- package/dist/{instance-shell-CpVW4zG0.mjs → instance-shell-cdVETpfz.mjs} +227 -58
- package/dist/internal/index.d.mts +51 -21
- package/dist/internal/index.mjs +10 -9
- 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 +5 -5
- package/dist/node/index.mjs +2 -2
- package/dist/{nostics-SPGDgHEP.d.mts → nostics-0sKe5HIj.d.mts} +2 -2
- package/dist/{nostics-CzECRXpE.mjs → nostics-D0PvLZsn.mjs} +1 -1
- package/dist/origin-DGDH8BI9.d.mts +45 -0
- package/dist/origin-DZit9g29.mjs +80 -0
- package/dist/recipes/common-rpc-functions.d.mts +5 -5
- package/dist/recipes/common-rpc-functions.mjs +3 -3
- package/dist/recipes/interactive-auth.d.mts +6 -6
- package/dist/recipes/interactive-auth.mjs +6 -6
- package/dist/{remote-assets-DezQmPQU.mjs → remote-assets-BIFWOlBW.mjs} +26 -6
- package/dist/{remote-assets-B13_vRkJ.d.mts → remote-assets-eBvSKZMS.d.mts} +7 -7
- package/dist/{revoke-COLW0cOi.mjs → revoke-cqztiCX4.mjs} +1 -1
- package/dist/rpc/dump.d.mts +2 -11
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +3 -3
- package/dist/rpc/transports/sse-client.d.mts +1 -1
- package/dist/rpc/transports/sse-client.mjs +30 -14
- package/dist/rpc/transports/sse-server.d.mts +4 -4
- package/dist/rpc/transports/sse-server.mjs +7 -7
- package/dist/rpc/transports/ws-bun.d.mts +5 -5
- package/dist/rpc/transports/ws-bun.mjs +8 -2
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +2 -2
- package/dist/rpc/transports/ws-deno.d.mts +4 -4
- package/dist/rpc/transports/ws-deno.mjs +8 -2
- package/dist/rpc/transports/ws-server.d.mts +2 -1
- package/dist/rpc/transports/ws-server.mjs +232 -1
- package/dist/{rpc-core-BHUsDl7s.d.mts → rpc-core-Ceu6AUz8.d.mts} +4 -4
- package/dist/{rpc-core-DlHd276T.mjs → rpc-core-DVQ7xi89.mjs} +14 -2
- package/dist/{serialization-BGzEwAdr.mjs → serialization-DTZnPQ1-.mjs} +20 -18
- package/dist/{services-install-CqqQVls5.mjs → services-install-P_DV7VYL.mjs} +32 -21
- package/dist/session-DPfj6zQG.mjs +16 -0
- package/dist/{shared-state-DoXutg_U.mjs → shared-state-CaxB1q0h.mjs} +4 -3
- package/dist/{simple-schema-DQPZrAaZ.mjs → simple-schema-Bi40l-P6.mjs} +2 -2
- package/dist/{sse-client-DwX021ST.d.mts → sse-client-BQ4jS3eO.d.mts} +4 -4
- package/dist/{state-CK9LjrnT.mjs → state-CeQQWzM-.mjs} +4 -4
- package/dist/{static-DV_qUSRS.mjs → static-DZ8P2Kn7.mjs} +130 -135
- package/dist/{storage-BXNVhKyR.mjs → storage-Dccf_IyD.mjs} +1 -1
- package/dist/types/index.d.mts +6 -6
- package/dist/{types-CMdPYhOx.d.mts → types-Dq4i156u.d.mts} +17 -17
- package/dist/utils/agent-tool-name.d.mts +2 -2
- package/dist/utils/agent-tool-name.mjs +2 -2
- package/dist/utils/colors.d.mts +1 -1
- package/dist/utils/crypto-token.d.mts +1 -1
- package/dist/utils/crypto-token.mjs +1 -1
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/nostics.d.mts +1 -1
- package/dist/utils/nostics.mjs +1 -1
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/origin.d.mts +2 -0
- package/dist/utils/origin.mjs +80 -0
- package/dist/utils/remote-assets.d.mts +2 -2
- package/dist/utils/remote-assets.mjs +1 -1
- package/dist/utils/serve-static.d.mts +4 -4
- package/dist/utils/serve-static.mjs +56 -19
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/simple-schema.d.mts +5 -5
- package/dist/utils/simple-schema.mjs +2 -2
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/utils/streaming-channel.mjs +2 -2
- package/dist/utils/when.d.mts +5 -5
- package/dist/{validation-YrZH6atx.mjs → validation-BOy8IoFZ.mjs} +2 -2
- package/dist/{wire-codec-0K-o5MYW.mjs → wire-codec-dcCeXcSo.mjs} +3 -3
- package/dist/{ws-client-7_lZi-B9.d.mts → ws-client-Xpxt0oPA.d.mts} +3 -3
- package/dist/{ws-server-Di2oqr4q.d.mts → ws-server-D2nv68Hg.d.mts} +13 -22
- package/package.json +6 -5
- package/dist/ws-server-BdSLrhxE.mjs +0 -267
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as WsOriginRegistry } from "../../ws-server-
|
|
2
|
-
import { t as ContextRpcServer } from "../../rpc-core-
|
|
1
|
+
import { n as WsOriginRegistry } from "../../ws-server-D2nv68Hg.mjs";
|
|
2
|
+
import { t as ContextRpcServer } from "../../rpc-core-Ceu6AUz8.mjs";
|
|
3
3
|
//#region src/rpc/transports/ws-bun.d.ts
|
|
4
4
|
interface AttachBunWsTransportOptions {
|
|
5
5
|
/** Same contract as `WsRpcTransportOptions.allowedOrigins`. */
|
|
@@ -7,7 +7,7 @@ interface AttachBunWsTransportOptions {
|
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Structural view of the Bun `Bun.serve({ websocket })` handler object the
|
|
10
|
-
* crossws Bun adapter produces
|
|
10
|
+
* crossws Bun adapter produces, typed loosely so devframe carries no
|
|
11
11
|
* dependency on Bun's own types.
|
|
12
12
|
*/
|
|
13
13
|
interface BunWsTierWebSocket {
|
|
@@ -17,14 +17,14 @@ interface BunWsTierWebSocket {
|
|
|
17
17
|
drain?: (ws: unknown) => unknown;
|
|
18
18
|
}
|
|
19
19
|
interface BunWsTier {
|
|
20
|
-
/** Complete a WS upgrade request
|
|
20
|
+
/** Complete a WS upgrade request; `Bun.serve`'s server as 2nd argument. */
|
|
21
21
|
handleUpgrade: (request: Request, server: unknown) => Promise<Response | undefined>;
|
|
22
22
|
/** The handlers to spread into `Bun.serve({ websocket })`. */
|
|
23
23
|
websocket: BunWsTierWebSocket;
|
|
24
24
|
close: () => Promise<void>;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
* The Bun fetch-upgrade WebSocket tier for `initDevframe` / `initHub
|
|
27
|
+
* The Bun fetch-upgrade WebSocket tier for `initDevframe` / `initHub`: the
|
|
28
28
|
* same RPC peer wiring as `attachWsRpcTransport`, driven by crossws's Bun
|
|
29
29
|
* adapter so upgrades complete through `handler(request, server)` on the
|
|
30
30
|
* app's own origin, with no side-car server. Load it dynamically so the Bun
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as isAllowedOrigin } from "../../origin-DZit9g29.mjs";
|
|
2
|
+
import { createWsRpcPeerHooks } from "./ws-server.mjs";
|
|
2
3
|
//#region src/rpc/transports/ws-bun.ts
|
|
3
4
|
/**
|
|
4
|
-
* The Bun fetch-upgrade WebSocket tier for `initDevframe` / `initHub
|
|
5
|
+
* The Bun fetch-upgrade WebSocket tier for `initDevframe` / `initHub`: the
|
|
5
6
|
* same RPC peer wiring as `attachWsRpcTransport`, driven by crossws's Bun
|
|
6
7
|
* adapter so upgrades complete through `handler(request, server)` on the
|
|
7
8
|
* app's own origin, with no side-car server. Load it dynamically so the Bun
|
|
@@ -15,6 +16,11 @@ async function attachBunWsTransport(core, options = {}) {
|
|
|
15
16
|
onConnected: core.onConnected,
|
|
16
17
|
onDisconnected: core.onDisconnected
|
|
17
18
|
}),
|
|
19
|
+
/**
|
|
20
|
+
* The same origin policy `routeUpgrades` applies for the Node
|
|
21
|
+
* transport, enforced at the upgrade hook since Bun upgrades arrive
|
|
22
|
+
* as fetch requests rather than `upgrade` socket events.
|
|
23
|
+
*/
|
|
18
24
|
upgrade(request) {
|
|
19
25
|
const origin = request.headers.get("origin") ?? void 0;
|
|
20
26
|
const allowed = allowedOrigins && !Array.isArray(allowedOrigins) ? allowedOrigins.isAllowed(origin) : isAllowedOrigin(origin, allowedOrigins || []);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createWsRpcChannel, t as WsRpcChannelOptions } from "../../ws-client-
|
|
1
|
+
import { n as createWsRpcChannel, t as WsRpcChannelOptions } from "../../ws-client-Xpxt0oPA.mjs";
|
|
2
2
|
export { WsRpcChannelOptions, createWsRpcChannel };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DEVFRAME_AUTH_TOKEN_QUERY_PARAM } from "../../constants.mjs";
|
|
2
|
-
import { t as createRpcWireCodec } from "../../wire-codec-
|
|
2
|
+
import { t as createRpcWireCodec } from "../../wire-codec-dcCeXcSo.mjs";
|
|
3
3
|
//#region src/rpc/transports/ws-client.ts
|
|
4
4
|
function NOOP() {}
|
|
5
5
|
const EMPTY_DEFS = /* @__PURE__ */ new Map();
|
|
@@ -7,7 +7,7 @@ const EMPTY_DEFS = /* @__PURE__ */ new Map();
|
|
|
7
7
|
* Build a birpc `ChannelOptions` object backed by a browser `WebSocket`.
|
|
8
8
|
* Pass the result straight to `createRpcClient`'s `channel` option.
|
|
9
9
|
*
|
|
10
|
-
* Also returns `close()`, closing the underlying socket
|
|
10
|
+
* Also returns `close()`, closing the underlying socket, mirroring the server transport's
|
|
11
11
|
* existing `WsRpcTransport.close()`. `birpc`'s own `ChannelOptions` has no teardown of its own.
|
|
12
12
|
*/
|
|
13
13
|
function createWsRpcChannel(options) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as WsOriginRegistry } from "../../ws-server-
|
|
2
|
-
import { t as ContextRpcServer } from "../../rpc-core-
|
|
1
|
+
import { n as WsOriginRegistry } from "../../ws-server-D2nv68Hg.mjs";
|
|
2
|
+
import { t as ContextRpcServer } from "../../rpc-core-Ceu6AUz8.mjs";
|
|
3
3
|
//#region src/rpc/transports/ws-deno.d.ts
|
|
4
4
|
interface AttachDenoWsTransportOptions {
|
|
5
5
|
/** Same contract as `WsRpcTransportOptions.allowedOrigins`. */
|
|
@@ -7,7 +7,7 @@ interface AttachDenoWsTransportOptions {
|
|
|
7
7
|
}
|
|
8
8
|
interface DenoWsTier {
|
|
9
9
|
/**
|
|
10
|
-
* Complete a WS upgrade request
|
|
10
|
+
* Complete a WS upgrade request; `Deno.serve`'s handler info as the 2nd
|
|
11
11
|
* argument. Unlike Bun, Deno's adapter attaches the socket to the returned
|
|
12
12
|
* `Response` itself, so there is no `websocket` handler object to register.
|
|
13
13
|
*/
|
|
@@ -15,7 +15,7 @@ interface DenoWsTier {
|
|
|
15
15
|
close: () => Promise<void>;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* The Deno fetch-upgrade WebSocket tier for `initDevframe` / `initHub
|
|
18
|
+
* The Deno fetch-upgrade WebSocket tier for `initDevframe` / `initHub`: the
|
|
19
19
|
* same RPC peer wiring as `attachWsRpcTransport`, driven by crossws's Deno
|
|
20
20
|
* adapter so upgrades complete through `handleUpgrade(request, info)` on the
|
|
21
21
|
* app's own origin, with no side-car server. Load it dynamically so the Deno
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as isAllowedOrigin } from "../../origin-DZit9g29.mjs";
|
|
2
|
+
import { createWsRpcPeerHooks } from "./ws-server.mjs";
|
|
2
3
|
//#region src/rpc/transports/ws-deno.ts
|
|
3
4
|
/**
|
|
4
|
-
* The Deno fetch-upgrade WebSocket tier for `initDevframe` / `initHub
|
|
5
|
+
* The Deno fetch-upgrade WebSocket tier for `initDevframe` / `initHub`: the
|
|
5
6
|
* same RPC peer wiring as `attachWsRpcTransport`, driven by crossws's Deno
|
|
6
7
|
* adapter so upgrades complete through `handleUpgrade(request, info)` on the
|
|
7
8
|
* app's own origin, with no side-car server. Load it dynamically so the Deno
|
|
@@ -15,6 +16,11 @@ async function attachDenoWsTransport(core, options = {}) {
|
|
|
15
16
|
onConnected: core.onConnected,
|
|
16
17
|
onDisconnected: core.onDisconnected
|
|
17
18
|
}),
|
|
19
|
+
/**
|
|
20
|
+
* The same origin policy `routeUpgrades` applies for the Node
|
|
21
|
+
* transport, enforced at the upgrade hook since Deno upgrades arrive
|
|
22
|
+
* as fetch requests rather than `upgrade` socket events.
|
|
23
|
+
*/
|
|
18
24
|
upgrade(request) {
|
|
19
25
|
const origin = request.headers.get("origin") ?? void 0;
|
|
20
26
|
const allowed = allowedOrigins && !Array.isArray(allowedOrigins) ? allowedOrigins.isAllowed(origin) : isAllowedOrigin(origin, allowedOrigins || []);
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { a as attachWsRpcTransport, c as
|
|
1
|
+
import { a as attachWsRpcTransport, c as DevframeNodeRpcSessionMeta, d as DevframeRpcTransportKind, i as WsRpcTransportOptions, l as DevframeRpcConnection, n as WsOriginRegistry, o as createWsOriginRegistry, r as WsRpcTransport, s as createWsRpcPeerHooks, t as CreateWsOriginRegistryOptions, u as DevframeRpcConnectionRequest } from "../../ws-server-D2nv68Hg.mjs";
|
|
2
|
+
import { n as isLoopbackHostname, t as isAllowedOrigin } from "../../origin-DGDH8BI9.mjs";
|
|
2
3
|
export { CreateWsOriginRegistryOptions, type DevframeNodeRpcSessionMeta, type DevframeRpcConnection, type DevframeRpcConnectionRequest, type DevframeRpcTransportKind, WsOriginRegistry, WsRpcTransport, WsRpcTransportOptions, attachWsRpcTransport, createWsOriginRegistry, createWsRpcPeerHooks, isAllowedOrigin, isLoopbackHostname };
|
|
@@ -1,2 +1,233 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../../constants.mjs";
|
|
2
|
+
import { t as createRpcWireCodec } from "../../wire-codec-dcCeXcSo.mjs";
|
|
3
|
+
import { n as isLoopbackHostname, t as isAllowedOrigin } from "../../origin-DZit9g29.mjs";
|
|
4
|
+
import { t as createRpcSessionMeta } from "../../session-DPfj6zQG.mjs";
|
|
5
|
+
import { n as randomToken, r as timingSafeEqual } from "../../crypto-token-TVbGGFuj.mjs";
|
|
6
|
+
import { createServer } from "node:http";
|
|
7
|
+
import { createServer as createServer$1 } from "node:https";
|
|
8
|
+
import crossws from "crossws/adapters/node";
|
|
9
|
+
//#region src/rpc/transports/ws-server.ts
|
|
10
|
+
/**
|
|
11
|
+
* Create a live, token-protected origin allowlist for external browser
|
|
12
|
+
* viewers. Pass it to {@link WsRpcTransportOptions.allowedOrigins}, then use
|
|
13
|
+
* `registerFromUrl()` in the connection metadata handler to authorize a
|
|
14
|
+
* viewer without sharing a mutable array or disabling DNS-rebinding protection.
|
|
15
|
+
*/
|
|
16
|
+
function createWsOriginRegistry(options = {}) {
|
|
17
|
+
const token = randomToken();
|
|
18
|
+
const origins = new Set(options.allowedOrigins ?? []);
|
|
19
|
+
function normalizeOrigin(origin) {
|
|
20
|
+
if (!origin) return;
|
|
21
|
+
try {
|
|
22
|
+
const url = new URL(origin);
|
|
23
|
+
const normalized = url.origin === "null" ? `${url.protocol}//${url.host}` : url.origin;
|
|
24
|
+
return origin === normalized ? normalized : void 0;
|
|
25
|
+
} catch {}
|
|
26
|
+
}
|
|
27
|
+
function registerOrigin(origin, candidateToken) {
|
|
28
|
+
const normalized = normalizeOrigin(origin);
|
|
29
|
+
if (!normalized || !candidateToken || !timingSafeEqual(token, candidateToken)) return false;
|
|
30
|
+
if (options.validateOrigin && !options.validateOrigin(normalized)) return false;
|
|
31
|
+
origins.add(normalized);
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
token,
|
|
36
|
+
registerFromUrl(url) {
|
|
37
|
+
let parsed;
|
|
38
|
+
try {
|
|
39
|
+
parsed = new URL(url, "http://localhost");
|
|
40
|
+
} catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const origin = parsed.searchParams.get("devframe_viewer_origin") ?? void 0;
|
|
44
|
+
return registerOrigin(origin, parsed.searchParams.get("devframe_viewer_origin_token") ?? void 0) ? origin : void 0;
|
|
45
|
+
},
|
|
46
|
+
isAllowed(origin) {
|
|
47
|
+
return isAllowedOrigin(origin, [...origins]);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const EMPTY_DEFS = /* @__PURE__ */ new Map();
|
|
52
|
+
function NOOP() {}
|
|
53
|
+
function listen(server, port, host) {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
const onError = (error) => reject(error);
|
|
56
|
+
server.once("error", onError);
|
|
57
|
+
try {
|
|
58
|
+
server.listen(port, host, () => {
|
|
59
|
+
server.off("error", onError);
|
|
60
|
+
resolve();
|
|
61
|
+
});
|
|
62
|
+
} catch (error) {
|
|
63
|
+
server.off("error", onError);
|
|
64
|
+
reject(error);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Compare two URL paths ignoring a trailing slash. */
|
|
69
|
+
function pathMatches(a, b) {
|
|
70
|
+
const strip = (p) => p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
|
|
71
|
+
return strip(a) === strip(b);
|
|
72
|
+
}
|
|
73
|
+
function isWsOriginRegistry(value) {
|
|
74
|
+
return !!value && !Array.isArray(value);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build the `upgrade` listener that hands a request to the crossws adapter,
|
|
78
|
+
* optionally filtered to a single `path`. Non-matching requests are left
|
|
79
|
+
* untouched so other upgrade listeners (e.g. a Vite dev server's HMR socket)
|
|
80
|
+
* can claim them, unless `destroyUnmatched` is set.
|
|
81
|
+
*/
|
|
82
|
+
function createUpgradeListener(ws, path, destroyUnmatched, allowedOrigins) {
|
|
83
|
+
return (req, socket, head) => {
|
|
84
|
+
socket.on("error", () => {});
|
|
85
|
+
if (path) {
|
|
86
|
+
let pathname = req.url ?? "/";
|
|
87
|
+
try {
|
|
88
|
+
pathname = new URL(req.url ?? "/", "http://localhost").pathname;
|
|
89
|
+
} catch {}
|
|
90
|
+
if (!pathMatches(pathname, path)) {
|
|
91
|
+
if (destroyUnmatched) {
|
|
92
|
+
socket.write("HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n");
|
|
93
|
+
socket.destroy();
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const originAllowed = isWsOriginRegistry(allowedOrigins) ? allowedOrigins.isAllowed(req.headers.origin) : isAllowedOrigin(req.headers.origin, allowedOrigins || []);
|
|
99
|
+
if (allowedOrigins !== false && !originAllowed) {
|
|
100
|
+
socket.write("HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n");
|
|
101
|
+
socket.destroy();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
ws.handleUpgrade(req, socket, head);
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The per-peer lifecycle hooks driving a devframe RPC WebSocket, shaped for
|
|
109
|
+
* any [crossws](https://crossws.h3.dev) adapter. {@link attachWsRpcTransport}
|
|
110
|
+
* feeds them to the Node adapter; runtime-specific attachments (e.g. Bun's
|
|
111
|
+
* fetch-upgrade adapter) reuse the same hooks so every transport speaks the
|
|
112
|
+
* identical wire protocol: one birpc channel per peer, per-method
|
|
113
|
+
* `jsonSerializable` dispatch between strict JSON and structured-clone.
|
|
114
|
+
*/
|
|
115
|
+
function createWsRpcPeerHooks(rpcGroup, options = {}) {
|
|
116
|
+
const { onConnected = NOOP, onDisconnected = NOOP, definitions = EMPTY_DEFS, serialize: serializeOverride, deserialize: deserializeOverride } = options;
|
|
117
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
118
|
+
return {
|
|
119
|
+
open: (peer) => {
|
|
120
|
+
const meta = createRpcSessionMeta();
|
|
121
|
+
meta.peer = peer;
|
|
122
|
+
const connection = {
|
|
123
|
+
id: meta.id,
|
|
124
|
+
transport: "websocket",
|
|
125
|
+
request: peer.request,
|
|
126
|
+
send: (data) => peer.send(data),
|
|
127
|
+
close: (code, reason) => peer.close(code, reason),
|
|
128
|
+
peer
|
|
129
|
+
};
|
|
130
|
+
const codec = createRpcWireCodec(definitions);
|
|
131
|
+
const state = {
|
|
132
|
+
meta,
|
|
133
|
+
connection
|
|
134
|
+
};
|
|
135
|
+
const channel = {
|
|
136
|
+
post: (data) => {
|
|
137
|
+
peer.send(data);
|
|
138
|
+
},
|
|
139
|
+
on: (fn) => {
|
|
140
|
+
state.onMessage = fn;
|
|
141
|
+
},
|
|
142
|
+
serialize: serializeOverride ?? codec.serialize,
|
|
143
|
+
deserialize: deserializeOverride ?? codec.deserialize,
|
|
144
|
+
meta
|
|
145
|
+
};
|
|
146
|
+
state.channel = channel;
|
|
147
|
+
states.set(peer, state);
|
|
148
|
+
rpcGroup.updateChannels((channels) => {
|
|
149
|
+
channels.push(channel);
|
|
150
|
+
});
|
|
151
|
+
onConnected(connection, meta);
|
|
152
|
+
},
|
|
153
|
+
message: (peer, message) => {
|
|
154
|
+
states.get(peer)?.onMessage?.(message.text());
|
|
155
|
+
},
|
|
156
|
+
close: (peer) => {
|
|
157
|
+
const state = states.get(peer);
|
|
158
|
+
if (!state) return;
|
|
159
|
+
states.delete(peer);
|
|
160
|
+
rpcGroup.updateChannels((channels) => {
|
|
161
|
+
const index = state.channel ? channels.indexOf(state.channel) : -1;
|
|
162
|
+
if (index >= 0) channels.splice(index, 1);
|
|
163
|
+
});
|
|
164
|
+
onDisconnected(state.connection, state.meta);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Attach a WebSocket transport to an existing RPC group, powered by
|
|
170
|
+
* [crossws](https://crossws.h3.dev). Either attach to an existing HTTP(S)
|
|
171
|
+
* `server` (sharing its port, optionally scoped to a `path`), or let this
|
|
172
|
+
* helper create a standalone server from `port` / `host` / `https`.
|
|
173
|
+
*
|
|
174
|
+
* Returns the crossws node adapter, standalone-server readiness/address
|
|
175
|
+
* accessors, `detach` (remove the upgrade listener from a shared `server`),
|
|
176
|
+
* and `close` (full deterministic teardown).
|
|
177
|
+
*/
|
|
178
|
+
function attachWsRpcTransport(rpcGroup, options = {}) {
|
|
179
|
+
const { server, port, host = "localhost", path, destroyUnmatched = false, unbound, https, allowedOrigins } = options;
|
|
180
|
+
const ws = crossws({ hooks: createWsRpcPeerHooks(rpcGroup, options) });
|
|
181
|
+
const sharedUpgradeListener = createUpgradeListener(ws, path, destroyUnmatched, allowedOrigins);
|
|
182
|
+
const ownedUpgradeListener = createUpgradeListener(ws, path, true, allowedOrigins);
|
|
183
|
+
/** Bind a server's `upgrade` events, tracked so `close()` detaches them. */
|
|
184
|
+
const attachments = /* @__PURE__ */ new Set();
|
|
185
|
+
function attachTo(target, listener) {
|
|
186
|
+
target.on("upgrade", listener);
|
|
187
|
+
const detachOne = () => {
|
|
188
|
+
target.off("upgrade", listener);
|
|
189
|
+
attachments.delete(detachOne);
|
|
190
|
+
};
|
|
191
|
+
attachments.add(detachOne);
|
|
192
|
+
return detachOne;
|
|
193
|
+
}
|
|
194
|
+
let ready = Promise.resolve();
|
|
195
|
+
let ownedServer;
|
|
196
|
+
if (unbound) {} else if (server) attachTo(server, sharedUpgradeListener);
|
|
197
|
+
else if (https) {
|
|
198
|
+
ownedServer = createServer$1(https);
|
|
199
|
+
attachTo(ownedServer, ownedUpgradeListener);
|
|
200
|
+
ready = listen(ownedServer, port ?? 0, host);
|
|
201
|
+
} else {
|
|
202
|
+
ownedServer = createServer((_req, res) => {
|
|
203
|
+
res.writeHead(426, { "content-type": "text/plain" });
|
|
204
|
+
res.end("Upgrade Required");
|
|
205
|
+
});
|
|
206
|
+
attachTo(ownedServer, ownedUpgradeListener);
|
|
207
|
+
ready = listen(ownedServer, port ?? 0, host);
|
|
208
|
+
}
|
|
209
|
+
const activeServer = server ?? ownedServer;
|
|
210
|
+
function detachAll() {
|
|
211
|
+
for (const detachOne of [...attachments]) detachOne();
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
ws,
|
|
215
|
+
ready,
|
|
216
|
+
address: () => activeServer?.address() ?? null,
|
|
217
|
+
handleUpgrade: sharedUpgradeListener,
|
|
218
|
+
attach: (target) => attachTo(target, sharedUpgradeListener),
|
|
219
|
+
detach: detachAll,
|
|
220
|
+
async close() {
|
|
221
|
+
detachAll();
|
|
222
|
+
ws.closeAll(void 0, void 0, true);
|
|
223
|
+
if (ownedServer) {
|
|
224
|
+
const srv = ownedServer;
|
|
225
|
+
await ready.catch(() => {});
|
|
226
|
+
if (!srv.listening) return;
|
|
227
|
+
await new Promise((r) => srv.close(() => r()));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
2
233
|
export { attachWsRpcTransport, createWsOriginRegistry, createWsRpcPeerHooks, isAllowedOrigin, isLoopbackHostname };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import "./index-
|
|
1
|
+
import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection } from "./ws-server-D2nv68Hg.mjs";
|
|
2
|
+
import { _t as DevframeRpcClientFunctions, o as DevframeNodeContext, s as DevframeNodeRpcSession, vt as DevframeRpcServerFunctions, wt as DevframeAuthHandler } from "./context-4AIVRLYF.mjs";
|
|
3
|
+
import "./index-pKl67H6w.mjs";
|
|
4
4
|
import { BirpcGroup, EventOptions } from "birpc";
|
|
5
5
|
//#region src/node/rpc-core.d.ts
|
|
6
6
|
interface CreateContextRpcServerOptions {
|
|
@@ -33,7 +33,7 @@ interface ContextRpcServer {
|
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
35
|
* Bind a devframe context's registered RPC functions to a birpc group,
|
|
36
|
-
* transport-agnostically
|
|
36
|
+
* transport-agnostically: the shared core under the instance shell's own
|
|
37
37
|
* HTTP+WS binding (Node http + WS) and the Bun fetch-upgrade tier of
|
|
38
38
|
* `createHandler`.
|
|
39
39
|
*
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.mjs";
|
|
2
2
|
import { createRpcServer } from "./rpc/server.mjs";
|
|
3
|
-
import { t as diagnostics } from "./diagnostics-
|
|
3
|
+
import { t as diagnostics } from "./diagnostics-BMfN8mb1.mjs";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
5
|
//#region src/node/rpc-core.ts
|
|
6
6
|
var rpc_core_exports = /* @__PURE__ */ __exportAll({ createContextRpcServer: () => createContextRpcServer });
|
|
7
7
|
/**
|
|
8
8
|
* Bind a devframe context's registered RPC functions to a birpc group,
|
|
9
|
-
* transport-agnostically
|
|
9
|
+
* transport-agnostically: the shared core under the instance shell's own
|
|
10
10
|
* HTTP+WS binding (Node http + WS) and the Bun fetch-upgrade tier of
|
|
11
11
|
* `createHandler`.
|
|
12
12
|
*
|
|
@@ -26,8 +26,20 @@ function createContextRpcServer(options) {
|
|
|
26
26
|
for (const fn of authHandler.rpcFunctions) if (!rpcHost.definitions.has(fn.name)) rpcHost.register(fn);
|
|
27
27
|
}
|
|
28
28
|
const rpcGroup = createRpcServer(rpcHost.functions, { rpcOptions: {
|
|
29
|
+
/**
|
|
30
|
+
* Forwarded as-is so a host with its own structured diagnostics
|
|
31
|
+
* keeps seeing RPC failures.
|
|
32
|
+
*/
|
|
29
33
|
onFunctionError: options.rpcOptions?.onFunctionError,
|
|
30
34
|
onGeneralError: options.rpcOptions?.onGeneralError,
|
|
35
|
+
/**
|
|
36
|
+
* Wrap each RPC handler in an AsyncLocalStorage context so
|
|
37
|
+
* `ctx.rpc.getCurrentRpcSession()` works inside handlers (used
|
|
38
|
+
* by streaming subscribe/unsubscribe/cancel and shared-state
|
|
39
|
+
* sync), and (when an `authorize` gate is configured) reject
|
|
40
|
+
* the call before it ever reaches the handler. Mirrors
|
|
41
|
+
* `packages/core/src/node/ws.ts`'s resolver.
|
|
42
|
+
*/
|
|
31
43
|
resolver(name, fn) {
|
|
32
44
|
const rpc = this;
|
|
33
45
|
if (!fn) return void 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as diagnostics } from "./diagnostics-
|
|
1
|
+
import { t as diagnostics } from "./diagnostics-D0EVm5M6.mjs";
|
|
2
2
|
//#region src/rpc/serialization.ts
|
|
3
3
|
/**
|
|
4
4
|
* Wire format used by the live RPC transports (WebSocket and SSE).
|
|
@@ -14,7 +14,7 @@ import { t as diagnostics } from "./diagnostics-CD8nlgll.mjs";
|
|
|
14
14
|
*
|
|
15
15
|
* birpc envelopes always start with `{`, so a leading byte that is not
|
|
16
16
|
* `s` is unambiguously JSON. Each direction independently chooses its
|
|
17
|
-
* encoding from local definitions
|
|
17
|
+
* encoding from local definitions; request and response are not
|
|
18
18
|
* coupled by a mirror rule.
|
|
19
19
|
*/
|
|
20
20
|
const STRUCTURED_CLONE_PREFIX = "s:";
|
|
@@ -26,16 +26,16 @@ const STRUCTURED_CLONE_PREFIX = "s:";
|
|
|
26
26
|
* instances, or `undefined` inside an array (silently becomes `null`).
|
|
27
27
|
*
|
|
28
28
|
* Native pass-throughs (no extra work needed):
|
|
29
|
-
* - circular references
|
|
30
|
-
* - `BigInt` at top level
|
|
29
|
+
* - circular references: `JSON.stringify` raises `TypeError`.
|
|
30
|
+
* - `BigInt` at top level: caught here for a friendlier error path.
|
|
31
31
|
*
|
|
32
32
|
* Lenient cases (allowed without throwing):
|
|
33
|
-
* - `undefined` as an object property
|
|
33
|
+
* - `undefined` as an object property: legitimate optional field;
|
|
34
34
|
* JSON.stringify just omits it.
|
|
35
|
-
* - `undefined` at the root
|
|
36
|
-
* - `Symbol` / `Function` values
|
|
35
|
+
* - `undefined` at the root: legitimate "action returned nothing".
|
|
36
|
+
* - `Symbol` / `Function` values: semantically "drop me" in JSON.
|
|
37
37
|
*
|
|
38
|
-
* `fnName` is used only for the diagnostic message
|
|
38
|
+
* `fnName` is used only for the diagnostic message; pass the RPC
|
|
39
39
|
* function name when calling from a wire serializer / dump writer so
|
|
40
40
|
* the error points at the offending function.
|
|
41
41
|
*/
|
|
@@ -47,19 +47,21 @@ function strictJsonStringify(value, fnName = "") {
|
|
|
47
47
|
if (Array.isArray(holder)) throw nonJsonAt(fnName, "undefined", holder, key);
|
|
48
48
|
return val;
|
|
49
49
|
}
|
|
50
|
-
if (original
|
|
51
|
-
if (typeof original === "bigint") throw nonJsonAt(fnName, "BigInt", holder, key);
|
|
52
|
-
if (typeof original === "object") {
|
|
53
|
-
if (original instanceof Map) throw nonJsonAt(fnName, "Map", holder, key);
|
|
54
|
-
if (original instanceof Set) throw nonJsonAt(fnName, "Set", holder, key);
|
|
55
|
-
if (original instanceof Date) throw nonJsonAt(fnName, "Date", holder, key);
|
|
56
|
-
if (Array.isArray(original)) return val;
|
|
57
|
-
const proto = Object.getPrototypeOf(original);
|
|
58
|
-
if (proto !== null && proto !== Object.prototype) throw nonJsonAt(fnName, original.constructor?.name ?? "class instance", holder, key);
|
|
59
|
-
}
|
|
50
|
+
if (original !== null) assertJsonSafe(original, holder, key, fnName);
|
|
60
51
|
return val;
|
|
61
52
|
});
|
|
62
53
|
}
|
|
54
|
+
/** Throw `DF0020` when `original` is a type JSON can't round-trip losslessly. */
|
|
55
|
+
function assertJsonSafe(original, holder, key, fnName) {
|
|
56
|
+
if (typeof original === "bigint") throw nonJsonAt(fnName, "BigInt", holder, key);
|
|
57
|
+
if (typeof original !== "object") return;
|
|
58
|
+
if (original instanceof Map) throw nonJsonAt(fnName, "Map", holder, key);
|
|
59
|
+
if (original instanceof Set) throw nonJsonAt(fnName, "Set", holder, key);
|
|
60
|
+
if (original instanceof Date) throw nonJsonAt(fnName, "Date", holder, key);
|
|
61
|
+
if (Array.isArray(original)) return;
|
|
62
|
+
const proto = Object.getPrototypeOf(original);
|
|
63
|
+
if (proto !== null && proto !== Object.prototype) throw nonJsonAt(fnName, original.constructor?.name ?? "class instance", holder, key);
|
|
64
|
+
}
|
|
63
65
|
function nonJsonAt(fnName, type, parent, key) {
|
|
64
66
|
const path = formatPath(parent, key);
|
|
65
67
|
return diagnostics.DF0020({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as DEVFRAME_EVENTS } from "./events-
|
|
2
|
-
import { t as diagnostics } from "./diagnostics-
|
|
1
|
+
import { t as DEVFRAME_EVENTS } from "./events-BV4Dj59a.mjs";
|
|
2
|
+
import { t as diagnostics } from "./diagnostics-BMfN8mb1.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { isAbsolute, join } from "pathe";
|
|
@@ -219,6 +219,12 @@ var DevframeAgentHost = class {
|
|
|
219
219
|
description: input.description,
|
|
220
220
|
safety: input.safety ?? "action",
|
|
221
221
|
tags: input.tags,
|
|
222
|
+
/**
|
|
223
|
+
* Standard Schema `args` are carried raw (mirroring how an RPC-backed
|
|
224
|
+
* tool defers to `ctx.rpc.definitions`); consumers (the MCP adapter)
|
|
225
|
+
* convert to JSON Schema on demand. An explicit `inputSchema` override
|
|
226
|
+
* wins when given.
|
|
227
|
+
*/
|
|
222
228
|
args: input.args,
|
|
223
229
|
inputSchema: input.inputSchema,
|
|
224
230
|
outputSchema: input.outputSchema,
|
|
@@ -268,7 +274,7 @@ function inferSafety(type) {
|
|
|
268
274
|
//#region src/node/services-install.ts
|
|
269
275
|
/**
|
|
270
276
|
* Turn a `resolveFrom` value (a file path, a file URL like `import.meta.url`,
|
|
271
|
-
* or a directory) into something `createRequire` accepts
|
|
277
|
+
* or a directory) into something `createRequire` accepts; a directory gets a
|
|
272
278
|
* synthetic filename appended so resolution starts inside it.
|
|
273
279
|
*/
|
|
274
280
|
function toRequireBase(resolveFrom) {
|
|
@@ -341,6 +347,24 @@ function compareVersions(a, b) {
|
|
|
341
347
|
if (a.prerelease && b.prerelease) return a.prerelease < b.prerelease ? -1 : a.prerelease > b.prerelease ? 1 : 0;
|
|
342
348
|
return 0;
|
|
343
349
|
}
|
|
350
|
+
/** Whether `version` and `base` share their first `lockUpTo + 1` parts. */
|
|
351
|
+
function partsMatchUpTo(version, base, lockUpTo) {
|
|
352
|
+
for (let i = 0; i <= lockUpTo; i++) if ((version.parts[i] ?? 0) !== (base.parts[i] ?? 0)) return false;
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
function satisfiesCaret(version, base) {
|
|
356
|
+
if (compareVersions(version, base) < 0) return false;
|
|
357
|
+
const fixedIndex = base.parts.findIndex((part) => part !== 0);
|
|
358
|
+
return partsMatchUpTo(version, base, fixedIndex === -1 ? base.parts.length - 1 : fixedIndex);
|
|
359
|
+
}
|
|
360
|
+
function satisfiesTilde(version, base, segments) {
|
|
361
|
+
if (compareVersions(version, base) < 0) return false;
|
|
362
|
+
return partsMatchUpTo(version, base, segments.length >= 2 ? 1 : 0);
|
|
363
|
+
}
|
|
364
|
+
function satisfiesExactOrPrefix(version, base, segments) {
|
|
365
|
+
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;
|
|
366
|
+
return segments.length >= 3 ? compareVersions(version, base) === 0 : true;
|
|
367
|
+
}
|
|
344
368
|
function satisfiesComparator(version, comparator) {
|
|
345
369
|
const raw = comparator.trim();
|
|
346
370
|
if (!raw || raw === "*" || raw === "x") return true;
|
|
@@ -356,26 +380,13 @@ function satisfiesComparator(version, comparator) {
|
|
|
356
380
|
case ">=": return compareVersions(version, base) >= 0;
|
|
357
381
|
case "<": return compareVersions(version, base) < 0;
|
|
358
382
|
case "<=": return compareVersions(version, base) <= 0;
|
|
359
|
-
case "^":
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
const lockUpTo = fixedIndex === -1 ? base.parts.length - 1 : fixedIndex;
|
|
363
|
-
for (let i = 0; i <= lockUpTo; i++) if ((version.parts[i] ?? 0) !== (base.parts[i] ?? 0)) return false;
|
|
364
|
-
return true;
|
|
365
|
-
}
|
|
366
|
-
case "~": {
|
|
367
|
-
if (compareVersions(version, base) < 0) return false;
|
|
368
|
-
const lockUpTo = segments.length >= 2 ? 1 : 0;
|
|
369
|
-
for (let i = 0; i <= lockUpTo; i++) if ((version.parts[i] ?? 0) !== (base.parts[i] ?? 0)) return false;
|
|
370
|
-
return true;
|
|
371
|
-
}
|
|
372
|
-
default:
|
|
373
|
-
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;
|
|
374
|
-
return segments.length >= 3 ? compareVersions(version, base) === 0 : true;
|
|
383
|
+
case "^": return satisfiesCaret(version, base);
|
|
384
|
+
case "~": return satisfiesTilde(version, base, segments);
|
|
385
|
+
default: return satisfiesExactOrPrefix(version, base, segments);
|
|
375
386
|
}
|
|
376
387
|
}
|
|
377
388
|
/**
|
|
378
|
-
* Pragmatic semver range check for service version declarations
|
|
389
|
+
* Pragmatic semver range check for service version declarations; supports
|
|
379
390
|
* the common forms (`1.2.3`, `^1.2.3`, `~1.2`, `>=1 <3`, `1.x`, `*`, and
|
|
380
391
|
* `||`-joined alternatives) without pulling in a semver dependency. An
|
|
381
392
|
* unparseable version or range reads as **not satisfied**.
|
|
@@ -402,7 +413,7 @@ function deepMergeTwo(a, b) {
|
|
|
402
413
|
}
|
|
403
414
|
/**
|
|
404
415
|
* Default option-set merge when a service declares no `mergeOptions`:
|
|
405
|
-
* deep-merge in declaration order
|
|
416
|
+
* deep-merge in declaration order: objects recurse, arrays union-dedupe,
|
|
406
417
|
* scalars take the later value. Covers the built-in services (`roots` /
|
|
407
418
|
* `langs` union, `themes` per-key last-wins) without a custom hook.
|
|
408
419
|
*/
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/rpc/transports/session.ts
|
|
2
|
+
let sessionId = 0;
|
|
3
|
+
/**
|
|
4
|
+
* Mint the per-connection session meta every transport binding shares:
|
|
5
|
+
* one id space across transports, so session bookkeeping (streaming
|
|
6
|
+
* subscriptions, shared-state sync, auth trust) never collides between a
|
|
7
|
+
* WS peer and an SSE session on the same server.
|
|
8
|
+
*/
|
|
9
|
+
function createRpcSessionMeta() {
|
|
10
|
+
return {
|
|
11
|
+
id: sessionId++,
|
|
12
|
+
subscribedStates: /* @__PURE__ */ new Set()
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { createRpcSessionMeta as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createEventEmitter } from "./utils/events.mjs";
|
|
2
2
|
import { nanoid } from "./utils/nanoid.mjs";
|
|
3
|
-
//#region ../../node_modules/.pnpm/immer@11.1.
|
|
3
|
+
//#region ../../node_modules/.pnpm/immer@11.1.18/node_modules/immer/dist/immer.mjs
|
|
4
4
|
var NOTHING = Symbol.for("immer-nothing");
|
|
5
5
|
var DRAFTABLE = Symbol.for("immer-draftable");
|
|
6
6
|
var DRAFT_STATE = Symbol.for("immer-state");
|
|
@@ -891,6 +891,7 @@ function enablePatches() {
|
|
|
891
891
|
getPath
|
|
892
892
|
});
|
|
893
893
|
}
|
|
894
|
+
globalThis.Iterator?.from;
|
|
894
895
|
var immer = new Immer2();
|
|
895
896
|
var produce = immer.produce;
|
|
896
897
|
var produceWithPatches = /* @__PURE__ */ immer.produceWithPatches.bind(immer);
|
|
@@ -930,8 +931,8 @@ function createSharedState(options) {
|
|
|
930
931
|
if (syncIds.has(syncId)) return;
|
|
931
932
|
rememberSyncId(syncIds, syncId);
|
|
932
933
|
if (enablePatches$1) {
|
|
933
|
-
const [
|
|
934
|
-
state =
|
|
934
|
+
const [nextState, patches] = produceWithPatches(state, fn);
|
|
935
|
+
state = nextState;
|
|
935
936
|
events.emit("updated", state, patches, syncId);
|
|
936
937
|
} else {
|
|
937
938
|
state = produce(state, fn);
|
|
@@ -37,7 +37,7 @@ function number() {
|
|
|
37
37
|
function boolean() {
|
|
38
38
|
return make("boolean", (v) => typeof v === "boolean" ? ok(v) : fail("Expected a boolean"));
|
|
39
39
|
}
|
|
40
|
-
/** `undefined
|
|
40
|
+
/** `undefined`, mirroring valibot's `void`. */
|
|
41
41
|
function voidType() {
|
|
42
42
|
return make("void", (v) => v === void 0 ? ok(void 0) : fail("Expected undefined"));
|
|
43
43
|
}
|
|
@@ -130,7 +130,7 @@ function describe(schema, description) {
|
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
132
|
/**
|
|
133
|
-
* Grouped access to every builder
|
|
133
|
+
* Grouped access to every builder: `s.string()`, `s.object({ ... })`,
|
|
134
134
|
* `s.void()`, etc. Handy for a valibot-like `import { s } from
|
|
135
135
|
* 'devframe/utils/simple-schema'` call site.
|
|
136
136
|
*/
|