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
package/dist/node/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../index-
|
|
2
|
-
import { v as RpcFunctionDefinitionAny } from "../types-
|
|
3
|
-
import { k as SharedState, l as RpcFunctionsHost, o as DevframeNodeContext
|
|
1
|
+
import "../index-pIVt92jP.mjs";
|
|
2
|
+
import { v as RpcFunctionDefinitionAny } from "../types-Dq4i156u.mjs";
|
|
3
|
+
import { bt as DevframeHost, k as SharedState, l as RpcFunctionsHost, o as DevframeNodeContext } from "../context-4AIVRLYF.mjs";
|
|
4
4
|
import { BirpcGroup } from "birpc";
|
|
5
5
|
//#region src/node/context.d.ts
|
|
6
6
|
interface CreateHostContextOptions {
|
|
@@ -13,7 +13,7 @@ interface CreateHostContextOptions {
|
|
|
13
13
|
* serves (from `DevframeDefinition.importMetaUrl`). Supplies the default
|
|
14
14
|
* `resolveFrom` base for remote {@link DevframeViewHost.hostStatic} sources
|
|
15
15
|
* that don't set one, so a locally installed copy of an assets package is
|
|
16
|
-
* served with zero network. An internal plumbing detail
|
|
16
|
+
* served with zero network. An internal plumbing detail; it isn't part of
|
|
17
17
|
* the public {@link DevframeNodeContext} surface.
|
|
18
18
|
*/
|
|
19
19
|
importMetaUrl?: string;
|
|
@@ -28,7 +28,7 @@ interface CreateHostContextOptions {
|
|
|
28
28
|
* Framework- and build-tool-agnostic core of the Devframe node context.
|
|
29
29
|
* Wires the RPC host, view (HTTP file-serving) host, diagnostics, and
|
|
30
30
|
* agent subsystems. Host adapters can wrap this to augment `ctx` with
|
|
31
|
-
* extra surfaces
|
|
31
|
+
* extra surfaces; for example, `@vitejs/devtools-kit`'s
|
|
32
32
|
* `createKitContext` attaches `docks`, `terminals`, `messages`, and
|
|
33
33
|
* `commands` when mounted into Vite DevTools.
|
|
34
34
|
*/
|
package/dist/node/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as createHostContext } from "../context-
|
|
2
|
-
import { t as createStorage } from "../storage-
|
|
1
|
+
import { t as createHostContext } from "../context-CwPUinjn.mjs";
|
|
2
|
+
import { t as createStorage } from "../storage-Dccf_IyD.mjs";
|
|
3
3
|
export { createHostContext, createStorage };
|
|
@@ -10,7 +10,7 @@ declare function devframeReporter(d: Diagnostic, { method }?: {
|
|
|
10
10
|
method?: 'log' | 'warn' | 'error';
|
|
11
11
|
}): void;
|
|
12
12
|
/**
|
|
13
|
-
* Options accepted by {@link defineDiagnostics}
|
|
13
|
+
* Options accepted by {@link defineDiagnostics}, identical to `nostics`'s
|
|
14
14
|
* own `DefineDiagnosticsOptions`, minus the reporter devframe already
|
|
15
15
|
* prepends.
|
|
16
16
|
*/
|
|
@@ -20,7 +20,7 @@ type DevframeDefineDiagnosticsOptions<Codes extends Record<string, DiagnosticDef
|
|
|
20
20
|
* ANSI console reporter pre-wired ahead of any `reporters` passed in. Every
|
|
21
21
|
* `diagnostics.ts` in devframe core, `@devframes/hub`, `@devframes/json-render`,
|
|
22
22
|
* and the built-in plugins defines its codes through this instead of
|
|
23
|
-
* `nostics`'s own `defineDiagnostics
|
|
23
|
+
* `nostics`'s own `defineDiagnostics`; the reporter registration lives
|
|
24
24
|
* here, once, so none of them need to build their own reporter (`colors`,
|
|
25
25
|
* `ansiFormatter`) or take a direct dependency on `nostics` themselves.
|
|
26
26
|
*/
|
|
@@ -45,7 +45,7 @@ function devframeReporter(d, { method = "warn" } = {}) {
|
|
|
45
45
|
* ANSI console reporter pre-wired ahead of any `reporters` passed in. Every
|
|
46
46
|
* `diagnostics.ts` in devframe core, `@devframes/hub`, `@devframes/json-render`,
|
|
47
47
|
* and the built-in plugins defines its codes through this instead of
|
|
48
|
-
* `nostics`'s own `defineDiagnostics
|
|
48
|
+
* `nostics`'s own `defineDiagnostics`; the reporter registration lives
|
|
49
49
|
* here, once, so none of them need to build their own reporter (`colors`,
|
|
50
50
|
* `ansiFormatter`) or take a direct dependency on `nostics` themselves.
|
|
51
51
|
*/
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/utils/origin.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Origin and hostname predicates shared by the RPC transports (the WS upgrade,
|
|
4
|
+
* SSE, and MCP origin gates) and the instance shell's authentication-link
|
|
5
|
+
* origin validation. Kept dependency-free and runtime-agnostic so any consumer
|
|
6
|
+
* can pull in a single check without dragging in a transport's `crossws`
|
|
7
|
+
* import.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Whether `hostname` names a loopback host: `localhost` (or any `*.localhost`
|
|
11
|
+
* subdomain), the IPv6 loopback `::1`, or an IPv4 literal inside the
|
|
12
|
+
* `127.0.0.0/8` loopback block.
|
|
13
|
+
*
|
|
14
|
+
* The IPv4 case is matched **structurally**: the whole hostname must be a
|
|
15
|
+
* canonical dotted-decimal IPv4 literal whose first octet is `127`. A bare
|
|
16
|
+
* `startsWith('127.')` prefix check would also accept an attacker-controlled
|
|
17
|
+
* DNS name that merely *begins* with `127.` (`127.attacker.example`,
|
|
18
|
+
* `127.0.0.1.attacker.example`), letting a cross-origin browser page defeat
|
|
19
|
+
* the loopback origin gate that guards the RPC/MCP surface (a DNS-rebinding /
|
|
20
|
+
* cross-site WebSocket-hijacking bypass). Requiring a real IPv4 literal keeps
|
|
21
|
+
* genuine loopback addresses (`127.0.0.1`, `127.5.5.5`) allowed while rejecting
|
|
22
|
+
* those DNS names.
|
|
23
|
+
*/
|
|
24
|
+
declare function isLoopbackHostname(hostname: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Default origin policy for a localhost dev tool: allow requests with no
|
|
27
|
+
* `Origin` header (native, non-browser clients), allow any loopback origin
|
|
28
|
+
* (so cross-port localhost dev setups keep working), and allow explicitly
|
|
29
|
+
* configured origins. Everything else, such as a real remote page in the dev's
|
|
30
|
+
* browser, is rejected.
|
|
31
|
+
*/
|
|
32
|
+
declare function isAllowedOrigin(origin: string | undefined, allowedOrigins: readonly string[]): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Decide whether a request-derived origin candidate may back a devframe's
|
|
35
|
+
* advertised public origin, the destination of the OTP magic link. Stricter
|
|
36
|
+
* than {@link isAllowedOrigin}: it rejects credentials, a path, a query, a
|
|
37
|
+
* fragment, a malformed port, and non-HTTP(S) schemes, and adopts a candidate
|
|
38
|
+
* only when its hostname is loopback or its canonical origin exactly matches
|
|
39
|
+
* an `allowedOrigins` entry (a caller with no static list passes none, so only
|
|
40
|
+
* loopback qualifies). Returns the canonical origin to adopt, or `undefined`
|
|
41
|
+
* to reject. Forwarded headers are never consulted.
|
|
42
|
+
*/
|
|
43
|
+
declare function validateOriginCandidate(candidate: string, allowedOrigins?: readonly string[]): string | undefined;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { isLoopbackHostname as n, validateOriginCandidate as r, isAllowedOrigin as t };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
//#region src/utils/origin.ts
|
|
2
|
+
/**
|
|
3
|
+
* Origin and hostname predicates shared by the RPC transports (the WS upgrade,
|
|
4
|
+
* SSE, and MCP origin gates) and the instance shell's authentication-link
|
|
5
|
+
* origin validation. Kept dependency-free and runtime-agnostic so any consumer
|
|
6
|
+
* can pull in a single check without dragging in a transport's `crossws`
|
|
7
|
+
* import.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Whether `hostname` names a loopback host: `localhost` (or any `*.localhost`
|
|
11
|
+
* subdomain), the IPv6 loopback `::1`, or an IPv4 literal inside the
|
|
12
|
+
* `127.0.0.0/8` loopback block.
|
|
13
|
+
*
|
|
14
|
+
* The IPv4 case is matched **structurally**: the whole hostname must be a
|
|
15
|
+
* canonical dotted-decimal IPv4 literal whose first octet is `127`. A bare
|
|
16
|
+
* `startsWith('127.')` prefix check would also accept an attacker-controlled
|
|
17
|
+
* DNS name that merely *begins* with `127.` (`127.attacker.example`,
|
|
18
|
+
* `127.0.0.1.attacker.example`), letting a cross-origin browser page defeat
|
|
19
|
+
* the loopback origin gate that guards the RPC/MCP surface (a DNS-rebinding /
|
|
20
|
+
* cross-site WebSocket-hijacking bypass). Requiring a real IPv4 literal keeps
|
|
21
|
+
* genuine loopback addresses (`127.0.0.1`, `127.5.5.5`) allowed while rejecting
|
|
22
|
+
* those DNS names.
|
|
23
|
+
*/
|
|
24
|
+
function isLoopbackHostname(hostname) {
|
|
25
|
+
const h = hostname.replace(/^\[|\]$/g, "");
|
|
26
|
+
if (h === "localhost" || h.endsWith(".localhost") || h === "::1") return true;
|
|
27
|
+
return isLoopbackIPv4(h);
|
|
28
|
+
}
|
|
29
|
+
/** A canonical dotted-decimal IPv4 literal in `127.0.0.0/8`. */
|
|
30
|
+
function isLoopbackIPv4(hostname) {
|
|
31
|
+
const octets = hostname.split(".");
|
|
32
|
+
if (octets.length !== 4 || !octets.every(isDecimalOctet)) return false;
|
|
33
|
+
return Number(octets[0]) === 127;
|
|
34
|
+
}
|
|
35
|
+
/** A single canonical IPv4 octet: 1–3 digits, no leading zero, value 0–255. */
|
|
36
|
+
function isDecimalOctet(part) {
|
|
37
|
+
if (!/^\d{1,3}$/.test(part) || part.length > 1 && part[0] === "0") return false;
|
|
38
|
+
return Number(part) <= 255;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Default origin policy for a localhost dev tool: allow requests with no
|
|
42
|
+
* `Origin` header (native, non-browser clients), allow any loopback origin
|
|
43
|
+
* (so cross-port localhost dev setups keep working), and allow explicitly
|
|
44
|
+
* configured origins. Everything else, such as a real remote page in the dev's
|
|
45
|
+
* browser, is rejected.
|
|
46
|
+
*/
|
|
47
|
+
function isAllowedOrigin(origin, allowedOrigins) {
|
|
48
|
+
if (!origin) return true;
|
|
49
|
+
if (allowedOrigins.includes(origin)) return true;
|
|
50
|
+
try {
|
|
51
|
+
return isLoopbackHostname(new URL(origin).hostname);
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Decide whether a request-derived origin candidate may back a devframe's
|
|
58
|
+
* advertised public origin, the destination of the OTP magic link. Stricter
|
|
59
|
+
* than {@link isAllowedOrigin}: it rejects credentials, a path, a query, a
|
|
60
|
+
* fragment, a malformed port, and non-HTTP(S) schemes, and adopts a candidate
|
|
61
|
+
* only when its hostname is loopback or its canonical origin exactly matches
|
|
62
|
+
* an `allowedOrigins` entry (a caller with no static list passes none, so only
|
|
63
|
+
* loopback qualifies). Returns the canonical origin to adopt, or `undefined`
|
|
64
|
+
* to reject. Forwarded headers are never consulted.
|
|
65
|
+
*/
|
|
66
|
+
function validateOriginCandidate(candidate, allowedOrigins) {
|
|
67
|
+
let url;
|
|
68
|
+
try {
|
|
69
|
+
url = new URL(candidate);
|
|
70
|
+
} catch {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return void 0;
|
|
74
|
+
if (url.username || url.password || url.search || url.hash || url.pathname !== "/" && url.pathname !== "") return void 0;
|
|
75
|
+
const canonical = url.origin;
|
|
76
|
+
if (canonical === "null") return void 0;
|
|
77
|
+
if (isLoopbackHostname(url.hostname) || allowedOrigins?.includes(canonical)) return canonical;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { isLoopbackHostname as n, validateOriginCandidate as r, isAllowedOrigin as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../index-
|
|
2
|
-
import { E as Thenable, S as RpcFunctionSetupResult, c as RpcDump, g as RpcFunctionAgentOptions } from "../types-
|
|
3
|
-
import "../context-
|
|
1
|
+
import "../index-pIVt92jP.mjs";
|
|
2
|
+
import { E as Thenable, S as RpcFunctionSetupResult, c as RpcDump, g as RpcFunctionAgentOptions } from "../types-Dq4i156u.mjs";
|
|
3
|
+
import "../context-4AIVRLYF.mjs";
|
|
4
4
|
import { SimpleSchema } from "../utils/simple-schema.mjs";
|
|
5
5
|
//#region src/recipes/common-rpc-functions.d.ts
|
|
6
6
|
/**
|
|
@@ -34,7 +34,7 @@ declare const KNOWN_EDITORS: KnownEditor[];
|
|
|
34
34
|
* })
|
|
35
35
|
* ```
|
|
36
36
|
*
|
|
37
|
-
* @deprecated Use the `@devframes/service-open` wire service instead
|
|
37
|
+
* @deprecated Use the `@devframes/service-open` wire service instead: one
|
|
38
38
|
* host-level installation shared by every plugin and feature-detectable from
|
|
39
39
|
* clients, with workspace-root path containment on top of the editor gating.
|
|
40
40
|
*/
|
|
@@ -64,7 +64,7 @@ declare const openInEditor: {
|
|
|
64
64
|
* ctx.rpc.register(openInFinder)
|
|
65
65
|
* ```
|
|
66
66
|
*
|
|
67
|
-
* @deprecated Use the `@devframes/service-open` wire service instead
|
|
67
|
+
* @deprecated Use the `@devframes/service-open` wire service instead: one
|
|
68
68
|
* host-level installation shared by every plugin and feature-detectable from
|
|
69
69
|
* clients, with workspace-root path containment.
|
|
70
70
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as defineRpcFunction } from "../define-BLWPsH6y.mjs";
|
|
2
|
-
import { t as s } from "../simple-schema-
|
|
2
|
+
import { t as s } from "../simple-schema-Bi40l-P6.mjs";
|
|
3
3
|
//#region src/recipes/common-rpc-functions.ts
|
|
4
4
|
/** Runtime list of every {@link KnownEditor}. */
|
|
5
5
|
const KNOWN_EDITORS = [
|
|
@@ -57,7 +57,7 @@ const KNOWN_EDITORS = [
|
|
|
57
57
|
* })
|
|
58
58
|
* ```
|
|
59
59
|
*
|
|
60
|
-
* @deprecated Use the `@devframes/service-open` wire service instead
|
|
60
|
+
* @deprecated Use the `@devframes/service-open` wire service instead: one
|
|
61
61
|
* host-level installation shared by every plugin and feature-detectable from
|
|
62
62
|
* clients, with workspace-root path containment on top of the editor gating.
|
|
63
63
|
*/
|
|
@@ -83,7 +83,7 @@ const openInEditor = defineRpcFunction({
|
|
|
83
83
|
* ctx.rpc.register(openInFinder)
|
|
84
84
|
* ```
|
|
85
85
|
*
|
|
86
|
-
* @deprecated Use the `@devframes/service-open` wire service instead
|
|
86
|
+
* @deprecated Use the `@devframes/service-open` wire service instead: one
|
|
87
87
|
* host-level installation shared by every plugin and feature-detectable from
|
|
88
88
|
* clients, with workspace-root path containment.
|
|
89
89
|
*/
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "../index-
|
|
1
|
+
import { o as DevframeNodeContext, s as DevframeNodeRpcSession, wt as DevframeAuthHandler } from "../context-4AIVRLYF.mjs";
|
|
2
|
+
import "../index-pKl67H6w.mjs";
|
|
3
3
|
//#region src/recipes/interactive-auth.d.ts
|
|
4
4
|
interface CreateInteractiveAuthOptions {
|
|
5
5
|
/**
|
|
6
|
-
* Static, pre-shared bearer tokens that are always trusted
|
|
6
|
+
* Static, pre-shared bearer tokens that are always trusted, for CI runs
|
|
7
7
|
* or shared machines where the interactive code prompt would only get in
|
|
8
8
|
* the way. Checked in both the handshake handler and the connect-time
|
|
9
9
|
* hook, alongside tokens minted by a real code exchange.
|
|
@@ -11,7 +11,7 @@ interface CreateInteractiveAuthOptions {
|
|
|
11
11
|
clientAuthTokens?: string[];
|
|
12
12
|
/**
|
|
13
13
|
* Print the current code + magic-link URL. Devframe stays headless, so
|
|
14
|
-
* there is no default banner printed automatically
|
|
14
|
+
* there is no default banner printed automatically; call
|
|
15
15
|
* `auth.printBanner()` yourself once the server is listening. Override
|
|
16
16
|
* this to customize the format; defaults to a small boxed message on
|
|
17
17
|
* stdout.
|
|
@@ -41,10 +41,10 @@ interface CreateInteractiveAuthOptions {
|
|
|
41
41
|
* Package the interactive OTP auth protocol devframe's primitives
|
|
42
42
|
* (`exchangeTempAuthCode`, `verifyAuthToken`, `revokeAuthToken`,
|
|
43
43
|
* `getTempAuthCode`, `buildOtpAuthUrl`) implement into a ready-made
|
|
44
|
-
* {@link DevframeAuthHandler}
|
|
44
|
+
* {@link DevframeAuthHandler}: the handshake RPC functions, the resolver
|
|
45
45
|
* gate, the connect-time trust hook, and the startup banner.
|
|
46
46
|
*
|
|
47
|
-
* The auth storage stays internal to this handler
|
|
47
|
+
* The auth storage stays internal to this handler; callers never reach into
|
|
48
48
|
* `devframe/node/hub-internals` themselves.
|
|
49
49
|
*
|
|
50
50
|
* ```ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { s as colors } from "../nostics-
|
|
1
|
+
import { s as colors } from "../nostics-D0PvLZsn.mjs";
|
|
2
2
|
import { n as defineRpcFunction } from "../define-BLWPsH6y.mjs";
|
|
3
3
|
import { isAnonymousRpcMethod } from "../constants.mjs";
|
|
4
|
-
import { a as verifyAuthToken, n as exchangeTempAuthCode, r as getTempAuthCode, t as buildOtpAuthUrl } from "../state-
|
|
5
|
-
import { t as getInternalContext } from "../context-
|
|
6
|
-
import { t as s } from "../simple-schema-
|
|
4
|
+
import { a as verifyAuthToken, n as exchangeTempAuthCode, r as getTempAuthCode, t as buildOtpAuthUrl } from "../state-CeQQWzM-.mjs";
|
|
5
|
+
import { t as getInternalContext } from "../context-DIUvJW4D.mjs";
|
|
6
|
+
import { t as s } from "../simple-schema-Bi40l-P6.mjs";
|
|
7
7
|
//#region src/recipes/interactive-auth.ts
|
|
8
8
|
function defaultBanner(info) {
|
|
9
9
|
console.log(`\n ${colors.dim("devframe auth code")} ${colors.bold(info.code)}\n ${colors.dim("or open")} ${colors.cyan(info.url)}\n`);
|
|
@@ -12,10 +12,10 @@ function defaultBanner(info) {
|
|
|
12
12
|
* Package the interactive OTP auth protocol devframe's primitives
|
|
13
13
|
* (`exchangeTempAuthCode`, `verifyAuthToken`, `revokeAuthToken`,
|
|
14
14
|
* `getTempAuthCode`, `buildOtpAuthUrl`) implement into a ready-made
|
|
15
|
-
* {@link DevframeAuthHandler}
|
|
15
|
+
* {@link DevframeAuthHandler}: the handshake RPC functions, the resolver
|
|
16
16
|
* gate, the connect-time trust hook, and the startup banner.
|
|
17
17
|
*
|
|
18
|
-
* The auth storage stays internal to this handler
|
|
18
|
+
* The auth storage stays internal to this handler; callers never reach into
|
|
19
19
|
* `devframe/node/hub-internals` themselves.
|
|
20
20
|
*
|
|
21
21
|
* ```ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as diagnostics } from "./diagnostics-
|
|
1
|
+
import { t as diagnostics } from "./diagnostics-BMfN8mb1.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { isatty } from "node:tty";
|
|
4
4
|
import { formatWithOptions, inspect } from "node:util";
|
|
5
|
-
import { dirname, extname, join, normalize, sep } from "pathe";
|
|
5
|
+
import { dirname, extname, isAbsolute, join, normalize, resolve, sep } from "pathe";
|
|
6
6
|
import { createReadStream, existsSync } from "node:fs";
|
|
7
7
|
import { Buffer } from "node:buffer";
|
|
8
8
|
import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -302,7 +302,7 @@ const MANIFEST_FILENAME = ".manifest.json";
|
|
|
302
302
|
* list is dropped, because it describes the *provider's* transfer rather than
|
|
303
303
|
* the file: hop-by-hop and encoding headers no longer match the body `fetch`
|
|
304
304
|
* already decoded, and a CDN's policy headers (`set-cookie`, `cache-control`,
|
|
305
|
-
* framing/CSP) belong to its origin
|
|
305
|
+
* framing/CSP) belong to its origin, so replaying them under the dev server's
|
|
306
306
|
* origin could just as well break the iframe these assets render in.
|
|
307
307
|
*/
|
|
308
308
|
const PROXIED_HEADERS = [
|
|
@@ -436,6 +436,24 @@ function candidatePaths(prefix, cleaned) {
|
|
|
436
436
|
if (!/\.[a-z0-9]+$/i.test(cleaned) && !candidates.includes(`${prefix}index.html`)) candidates.push(`${prefix}index.html`);
|
|
437
437
|
return candidates;
|
|
438
438
|
}
|
|
439
|
+
/**
|
|
440
|
+
* Resolve the safe destination for a provider-listed `filePath` beneath
|
|
441
|
+
* `prefix`, materializing into the already-resolved `root`, or `null` when
|
|
442
|
+
* the entry is unsafe or lies outside the selected `prefix`. A compromised
|
|
443
|
+
* provider is an untrusted boundary even though the built-in jsDelivr/unpkg
|
|
444
|
+
* listings never emit any of this: reject an absolute path, a backslash
|
|
445
|
+
* (never normalized into a separator; Windows-style traversal stays rejected
|
|
446
|
+
* on every platform), and any suffix whose resolved destination would land
|
|
447
|
+
* outside `root`. `target === root` is deliberately unsafe too: it names the
|
|
448
|
+
* directory itself, never a writable file.
|
|
449
|
+
*/
|
|
450
|
+
function materializeTarget(filePath, prefix, root) {
|
|
451
|
+
if (filePath.includes("\\") || isAbsolute(filePath) || !filePath.startsWith(prefix)) return null;
|
|
452
|
+
const suffix = filePath.slice(prefix.length);
|
|
453
|
+
if (!suffix || isAbsolute(suffix)) return null;
|
|
454
|
+
const target = resolve(root, suffix);
|
|
455
|
+
return target === root || !target.startsWith(root + sep) ? null : target;
|
|
456
|
+
}
|
|
439
457
|
function createStore(assets, cacheDir) {
|
|
440
458
|
const normalized = {
|
|
441
459
|
...assets,
|
|
@@ -582,8 +600,10 @@ function createStore(assets, cacheDir) {
|
|
|
582
600
|
} catch (error) {
|
|
583
601
|
return fail(errText(error), error);
|
|
584
602
|
}
|
|
585
|
-
|
|
586
|
-
|
|
603
|
+
const root = resolve(targetDir);
|
|
604
|
+
for (const filePath of files) {
|
|
605
|
+
const target = materializeTarget(filePath, prefix, root);
|
|
606
|
+
if (target == null) continue;
|
|
587
607
|
const url = provider.fileUrl(normalized.package, normalized.version, filePath);
|
|
588
608
|
let res;
|
|
589
609
|
try {
|
|
@@ -625,7 +645,7 @@ function assertValidRemoteAssets(assets) {
|
|
|
625
645
|
* {@link RemoteAssetsStore} back-proxy. Remote caches live under
|
|
626
646
|
* `<projectStorageDir>/.remote-assets/<package>@<version>/`.
|
|
627
647
|
*
|
|
628
|
-
* A remote source's `package`/`version` are validated first (`DF0065`)
|
|
648
|
+
* A remote source's `package`/`version` are validated first (`DF0065`); both
|
|
629
649
|
* are interpolated into CDN URLs and the cache path.
|
|
630
650
|
*
|
|
631
651
|
* `defaultResolveFrom` (typically the declaring devframe's `importMetaUrl`)
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Resolution order at serve time:
|
|
8
8
|
*
|
|
9
|
-
* 1. The package installed locally (resolved from {@link resolveFrom})
|
|
10
|
-
*
|
|
9
|
+
* 1. The package installed locally (resolved from {@link resolveFrom}),
|
|
10
|
+
* the zero-network / air-gap path. Version skew warns; a major
|
|
11
11
|
* version mismatch throws.
|
|
12
12
|
* 2. The per-file cache under
|
|
13
13
|
* `<storageDir project>/.remote-assets/<package>@<version>/`.
|
|
14
|
-
* 3. The CDN {@link provider}
|
|
14
|
+
* 3. The CDN {@link provider}: each requested file streams through to
|
|
15
15
|
* the browser while being written into the cache.
|
|
16
16
|
*
|
|
17
17
|
* Anywhere a static mount accepts a dist directory (`clientAssets`,
|
|
18
|
-
* `hostStatic`, `mountStatic`) it also accepts this object
|
|
18
|
+
* `hostStatic`, `mountStatic`) it also accepts this object; see
|
|
19
19
|
* {@link StaticAssetsSource}.
|
|
20
20
|
*/
|
|
21
21
|
interface RemoteAssets {
|
|
@@ -39,7 +39,7 @@ interface RemoteAssets {
|
|
|
39
39
|
* `import.meta.url` of the declaring module. When set, a locally
|
|
40
40
|
* installed copy of {@link package} is resolved from this module's own
|
|
41
41
|
* dependency graph first (works under pnpm's strict layout) and served
|
|
42
|
-
* with zero network. Omitting it skips the installed-package step
|
|
42
|
+
* with zero network. Omitting it skips the installed-package step;
|
|
43
43
|
* cache + CDN still work.
|
|
44
44
|
*/
|
|
45
45
|
resolveFrom?: string | null;
|
|
@@ -54,7 +54,7 @@ interface RemoteAssets {
|
|
|
54
54
|
offline?: boolean;
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
|
-
* Built-in CDN providers (`'jsdelivr'
|
|
57
|
+
* Built-in CDN providers (`'jsdelivr'`, the default, or `'unpkg'`) or a custom
|
|
58
58
|
* provider for corp mirrors.
|
|
59
59
|
*/
|
|
60
60
|
type RemoteAssetsProvider = 'jsdelivr' | 'unpkg' | RemoteAssetsProviderCustom;
|
|
@@ -97,7 +97,7 @@ interface RemoteAssetsErrorMessage {
|
|
|
97
97
|
reason: string;
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
|
-
* A resolved, servable handle over a {@link RemoteAssets} declaration
|
|
100
|
+
* A resolved, servable handle over a {@link RemoteAssets} declaration,
|
|
101
101
|
* produced by `resolveStaticAssetsSource()` (`devframe/utils/remote-assets`)
|
|
102
102
|
* and consumed by the static-serving engine (`devframe/utils/serve-static`).
|
|
103
103
|
*/
|
package/dist/rpc/dump.d.mts
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import { h as RpcDumpStore, l as RpcDumpClientOptions, m as RpcDumpRecordError, n as BirpcReturn, o as RpcDefinitionsToFunctions, u as RpcDumpCollectionOptions, v as RpcFunctionDefinitionAny } from "../types-
|
|
1
|
+
import { h as RpcDumpStore, l as RpcDumpClientOptions, m as RpcDumpRecordError, n as BirpcReturn, o as RpcDefinitionsToFunctions, u as RpcDumpCollectionOptions, v as RpcFunctionDefinitionAny } from "../types-Dq4i156u.mjs";
|
|
2
2
|
//#region src/rpc/dump/collect.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* Collects pre-computed dumps by executing functions with their defined input combinations.
|
|
5
|
-
* Static functions without dump config automatically get `{ inputs: [[]] }`.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* const store = await dumpFunctions([greet], context, { concurrency: 10 })
|
|
10
|
-
* ```
|
|
11
|
-
*/
|
|
12
3
|
declare function dumpFunctions<T extends readonly RpcFunctionDefinitionAny[]>(definitions: T, context?: any, options?: RpcDumpCollectionOptions): Promise<RpcDumpStore<RpcDefinitionsToFunctions<T>>>;
|
|
13
4
|
/**
|
|
14
5
|
* Creates a client that serves pre-computed results from a dump store.
|
|
@@ -64,7 +55,7 @@ type StaticRpcDumpManifest = Record<string, StaticRpcDumpManifestValue>;
|
|
|
64
55
|
interface StaticRpcDumpFile {
|
|
65
56
|
/** Whether this file was written via `JSON.stringify` or `structured-clone-es.stringify`. */
|
|
66
57
|
serialization: StaticRpcDumpSerialization;
|
|
67
|
-
/** Function name the file belongs to
|
|
58
|
+
/** Function name the file belongs to, used to scope `DF0019` errors during write. */
|
|
68
59
|
fnName: string;
|
|
69
60
|
/** Payload to encode. */
|
|
70
61
|
data: unknown;
|
package/dist/rpc/dump.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as reviveDumpError, i as getDefinitionsWithDumps, n as createClientFromDump, o as serializeDumpError, r as dumpFunctions, t as collectStaticRpcDump } from "../static-
|
|
1
|
+
import { a as reviveDumpError, i as getDefinitionsWithDumps, n as createClientFromDump, o as serializeDumpError, r as dumpFunctions, t as collectStaticRpcDump } from "../static-DZ8P2Kn7.mjs";
|
|
2
2
|
export { collectStaticRpcDump, createClientFromDump, dumpFunctions, getDefinitionsWithDumps, reviveDumpError, serializeDumpError };
|
package/dist/rpc/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as STRUCTURED_CLONE_PREFIX, c as getRpcResolvedSetupResult, d as RpcFunctionsCollectorBase, f as RpcCacheManager, i as validateRpcReturn, l as createDefineWrapperWithContext, n as validateDefinitions, o as strictJsonStringify, p as RpcCacheOptions, r as validateRpcArgs, s as getRpcHandler, t as validateDefinition, u as defineRpcFunction } from "../index-
|
|
2
|
-
import { C as RpcFunctionType, E as Thenable, S as RpcFunctionSetupResult, T as RpcReturnSchema, _ as RpcFunctionDefinition, a as RpcDefinitionsFilter, b as RpcFunctionDefinitionBase, c as RpcDump, d as RpcDumpDefinition, f as RpcDumpGetter, g as RpcFunctionAgentOptions, h as RpcDumpStore, i as RpcArgsSchema, l as RpcDumpClientOptions, m as RpcDumpRecordError, n as BirpcReturn, o as RpcDefinitionsToFunctions, p as RpcDumpRecord, r as EntriesToObject, s as RpcDefinitionsToFunctionsWithNamespace, t as BirpcFn, u as RpcDumpCollectionOptions, v as RpcFunctionDefinitionAny, w as RpcFunctionsCollector, x as RpcFunctionDefinitionToFunction, y as RpcFunctionDefinitionAnyWithContext } from "../types-
|
|
1
|
+
import { a as STRUCTURED_CLONE_PREFIX, c as getRpcResolvedSetupResult, d as RpcFunctionsCollectorBase, f as RpcCacheManager, i as validateRpcReturn, l as createDefineWrapperWithContext, n as validateDefinitions, o as strictJsonStringify, p as RpcCacheOptions, r as validateRpcArgs, s as getRpcHandler, t as validateDefinition, u as defineRpcFunction } from "../index-pIVt92jP.mjs";
|
|
2
|
+
import { C as RpcFunctionType, E as Thenable, S as RpcFunctionSetupResult, T as RpcReturnSchema, _ as RpcFunctionDefinition, a as RpcDefinitionsFilter, b as RpcFunctionDefinitionBase, c as RpcDump, d as RpcDumpDefinition, f as RpcDumpGetter, g as RpcFunctionAgentOptions, h as RpcDumpStore, i as RpcArgsSchema, l as RpcDumpClientOptions, m as RpcDumpRecordError, n as BirpcReturn, o as RpcDefinitionsToFunctions, p as RpcDumpRecord, r as EntriesToObject, s as RpcDefinitionsToFunctionsWithNamespace, t as BirpcFn, u as RpcDumpCollectionOptions, v as RpcFunctionDefinitionAny, w as RpcFunctionsCollector, x as RpcFunctionDefinitionToFunction, y as RpcFunctionDefinitionAnyWithContext } from "../types-Dq4i156u.mjs";
|
|
3
3
|
export { type BirpcFn, type BirpcReturn, EntriesToObject, RpcArgsSchema, RpcCacheManager, RpcCacheOptions, RpcDefinitionsFilter, RpcDefinitionsToFunctions, RpcDefinitionsToFunctionsWithNamespace, RpcDump, RpcDumpClientOptions, RpcDumpCollectionOptions, RpcDumpDefinition, RpcDumpGetter, RpcDumpRecord, RpcDumpRecordError, RpcDumpStore, RpcFunctionAgentOptions, RpcFunctionDefinition, RpcFunctionDefinitionAny, RpcFunctionDefinitionAnyWithContext, RpcFunctionDefinitionBase, RpcFunctionDefinitionToFunction, RpcFunctionSetupResult, RpcFunctionType, RpcFunctionsCollector, RpcFunctionsCollectorBase, RpcReturnSchema, STRUCTURED_CLONE_PREFIX, Thenable, createDefineWrapperWithContext, defineRpcFunction, getRpcHandler, getRpcResolvedSetupResult, strictJsonStringify, validateDefinition, validateDefinitions, validateRpcArgs, validateRpcReturn };
|
package/dist/rpc/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as validateRpcArgs, i as getRpcResolvedSetupResult, n as validateDefinitions, o as validateRpcReturn, r as getRpcHandler, s as hash, t as validateDefinition } from "../validation-
|
|
2
|
-
import { t as diagnostics } from "../diagnostics-
|
|
1
|
+
import { a as validateRpcArgs, i as getRpcResolvedSetupResult, n as validateDefinitions, o as validateRpcReturn, r as getRpcHandler, s as hash, t as validateDefinition } from "../validation-BOy8IoFZ.mjs";
|
|
2
|
+
import { t as diagnostics } from "../diagnostics-D0EVm5M6.mjs";
|
|
3
3
|
import { n as defineRpcFunction, t as createDefineWrapperWithContext } from "../define-BLWPsH6y.mjs";
|
|
4
|
-
import { n as strictJsonStringify, t as STRUCTURED_CLONE_PREFIX } from "../serialization-
|
|
4
|
+
import { n as strictJsonStringify, t as STRUCTURED_CLONE_PREFIX } from "../serialization-DTZnPQ1-.mjs";
|
|
5
5
|
//#region src/rpc/cache.ts
|
|
6
6
|
/**
|
|
7
7
|
* @experimental API is expected to change.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createSseRpcChannel, t as SseRpcChannelOptions } from "../../sse-client-
|
|
1
|
+
import { n as createSseRpcChannel, t as SseRpcChannelOptions } from "../../sse-client-BQ4jS3eO.mjs";
|
|
2
2
|
export { SseRpcChannelOptions, createSseRpcChannel };
|
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import { DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_SSE_SESSION_HEADER } 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/sse-client.ts
|
|
4
4
|
function NOOP() {}
|
|
5
|
+
/** Split the next complete SSE frame (up to a blank line) off the buffer. */
|
|
6
|
+
function takeFrame(buffer) {
|
|
7
|
+
const boundary = buffer.search(/\n\n|\r\n\r\n/);
|
|
8
|
+
if (boundary < 0) return void 0;
|
|
9
|
+
return {
|
|
10
|
+
frame: buffer.slice(0, boundary),
|
|
11
|
+
rest: buffer.slice(boundary + (buffer[boundary] === "\r" ? 4 : 2))
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/** Parse one SSE frame's lines into its event name and data lines. */
|
|
15
|
+
function parseFrame(frame) {
|
|
16
|
+
let event = "message";
|
|
17
|
+
const data = [];
|
|
18
|
+
for (const rawLine of frame.split(/\r?\n/)) {
|
|
19
|
+
if (rawLine.startsWith(":")) continue;
|
|
20
|
+
if (rawLine.startsWith("event:")) event = rawLine.slice(6).trimStart();
|
|
21
|
+
else if (rawLine.startsWith("data:")) data.push(rawLine.slice(5).replace(/^ /, ""));
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
event,
|
|
25
|
+
data
|
|
26
|
+
};
|
|
27
|
+
}
|
|
5
28
|
/**
|
|
6
29
|
* Build a birpc `ChannelOptions` object backed by an SSE stream (server →
|
|
7
|
-
* client) and HTTP `POST` (client → server)
|
|
30
|
+
* client) and HTTP `POST` (client → server): the WebSocket-free counterpart
|
|
8
31
|
* to `createWsRpcChannel`, wire-compatible with `attachSseRpcTransport`.
|
|
9
32
|
*
|
|
10
33
|
* The stream is consumed via `fetch` streaming (not `EventSource`), so it
|
|
@@ -12,7 +35,7 @@ function NOOP() {}
|
|
|
12
35
|
* (`event: session`) carries the session id; every `POST` echoes it in the
|
|
13
36
|
* `x-birpc-session` header. A response to a client-initiated request comes
|
|
14
37
|
* back in the `POST`'s own body and is re-injected into the channel; a
|
|
15
|
-
* dropped stream terminates the channel
|
|
38
|
+
* dropped stream terminates the channel; there is no reconnect, matching
|
|
16
39
|
* the WS channel's closed-is-done semantics.
|
|
17
40
|
*/
|
|
18
41
|
function createSseRpcChannel(options) {
|
|
@@ -63,17 +86,10 @@ function createSseRpcChannel(options) {
|
|
|
63
86
|
if (done) break;
|
|
64
87
|
buffer += decoder.decode(value, { stream: true });
|
|
65
88
|
for (;;) {
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
let event = "message";
|
|
71
|
-
const data = [];
|
|
72
|
-
for (const rawLine of frame.split(/\r?\n/)) {
|
|
73
|
-
if (rawLine.startsWith(":")) continue;
|
|
74
|
-
if (rawLine.startsWith("event:")) event = rawLine.slice(6).trimStart();
|
|
75
|
-
else if (rawLine.startsWith("data:")) data.push(rawLine.slice(5).replace(/^ /, ""));
|
|
76
|
-
}
|
|
89
|
+
const taken = takeFrame(buffer);
|
|
90
|
+
if (!taken) break;
|
|
91
|
+
buffer = taken.rest;
|
|
92
|
+
const { event, data } = parseFrame(taken.frame);
|
|
77
93
|
if (data.length > 0) dispatch(event, data.join("\n"));
|
|
78
94
|
}
|
|
79
95
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { v as RpcFunctionDefinitionAny } from "../../types-
|
|
2
|
-
import {
|
|
1
|
+
import { v as RpcFunctionDefinitionAny } from "../../types-Dq4i156u.mjs";
|
|
2
|
+
import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "../../ws-server-D2nv68Hg.mjs";
|
|
3
3
|
import { BirpcGroup } from "birpc";
|
|
4
4
|
//#region src/rpc/transports/sse-server.d.ts
|
|
5
5
|
interface SseRpcTransportOptions {
|
|
@@ -14,7 +14,7 @@ interface SseRpcTransportOptions {
|
|
|
14
14
|
* RPC function definitions, used by the per-call wire serializer to
|
|
15
15
|
* dispatch between strict-JSON and structured-clone encoding based on
|
|
16
16
|
* each function's `jsonSerializable` flag. When omitted, all messages
|
|
17
|
-
* fall back to structured-clone
|
|
17
|
+
* fall back to structured-clone, the same contract as the WS transport.
|
|
18
18
|
*/
|
|
19
19
|
definitions?: ReadonlyMap<string, Pick<RpcFunctionDefinitionAny, 'jsonSerializable'>>;
|
|
20
20
|
onConnected?: (connection: DevframeRpcConnection, meta: DevframeNodeRpcSessionMeta) => void;
|
|
@@ -42,7 +42,7 @@ interface SseRpcTransport {
|
|
|
42
42
|
close: () => void;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
|
-
* Attach an SSE + HTTP POST transport to an existing RPC group
|
|
45
|
+
* Attach an SSE + HTTP POST transport to an existing RPC group: the
|
|
46
46
|
* WebSocket-free counterpart to `attachWsRpcTransport`, for hosts and
|
|
47
47
|
* proxies where the upgrade isn't available. Speaks the same birpc wire
|
|
48
48
|
* protocol (one channel per session, per-method `jsonSerializable`
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { DEVFRAME_SSE_SESSION_HEADER } from "../../constants.mjs";
|
|
2
|
-
import { n as peekRpcWireFrame, t as createRpcWireCodec } from "../../wire-codec-
|
|
3
|
-
import {
|
|
2
|
+
import { n as peekRpcWireFrame, t as createRpcWireCodec } from "../../wire-codec-dcCeXcSo.mjs";
|
|
3
|
+
import { t as isAllowedOrigin } from "../../origin-DZit9g29.mjs";
|
|
4
|
+
import { t as createRpcSessionMeta } from "../../session-DPfj6zQG.mjs";
|
|
4
5
|
//#region src/rpc/transports/sse-server.ts
|
|
5
6
|
const SSE_STREAM_HEADERS = {
|
|
6
7
|
"content-type": "text/event-stream",
|
|
7
8
|
"cache-control": "no-cache, no-transform",
|
|
9
|
+
/** Tell buffering reverse proxies (nginx) to pass frames through as-is. */
|
|
8
10
|
"x-accel-buffering": "no"
|
|
9
11
|
};
|
|
10
12
|
function NOOP() {}
|
|
11
13
|
/**
|
|
12
|
-
* Attach an SSE + HTTP POST transport to an existing RPC group
|
|
14
|
+
* Attach an SSE + HTTP POST transport to an existing RPC group: the
|
|
13
15
|
* WebSocket-free counterpart to `attachWsRpcTransport`, for hosts and
|
|
14
16
|
* proxies where the upgrade isn't available. Speaks the same birpc wire
|
|
15
17
|
* protocol (one channel per session, per-method `jsonSerializable`
|
|
@@ -33,7 +35,7 @@ function attachSseRpcTransport(rpcGroup, options = {}) {
|
|
|
33
35
|
return allowedOrigins && !Array.isArray(allowedOrigins) ? allowedOrigins.isAllowed(origin) : isAllowedOrigin(origin, allowedOrigins ?? []);
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
|
-
* CORS headers for a browser on another (allowed) origin
|
|
38
|
+
* CORS headers for a browser on another (allowed) origin: the side-car /
|
|
37
39
|
* registered-viewer case. Same-origin requests carry no `Origin` (or their
|
|
38
40
|
* own), where these headers are inert.
|
|
39
41
|
*/
|
|
@@ -65,8 +67,6 @@ function attachSseRpcTransport(rpcGroup, options = {}) {
|
|
|
65
67
|
const session = {
|
|
66
68
|
id,
|
|
67
69
|
meta,
|
|
68
|
-
connection: void 0,
|
|
69
|
-
channel: void 0,
|
|
70
70
|
parked: /* @__PURE__ */ new Map(),
|
|
71
71
|
closed: false,
|
|
72
72
|
close: () => {
|
|
@@ -80,7 +80,7 @@ function attachSseRpcTransport(rpcGroup, options = {}) {
|
|
|
80
80
|
controller?.close();
|
|
81
81
|
} catch {}
|
|
82
82
|
rpcGroup.updateChannels((channels) => {
|
|
83
|
-
const index = channels.indexOf(session.channel);
|
|
83
|
+
const index = session.channel ? channels.indexOf(session.channel) : -1;
|
|
84
84
|
if (index >= 0) channels.splice(index, 1);
|
|
85
85
|
});
|
|
86
86
|
onDisconnected(session.connection, meta);
|