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.
Files changed (116) hide show
  1. package/dist/{_shared-BM3PdYli.mjs → _shared-C08SdQRl.mjs} +15 -4
  2. package/dist/{_shared-BJ6AmwTu.d.mts → _shared-CK3czkH4.d.mts} +25 -2
  3. package/dist/adapters/build.d.mts +6 -6
  4. package/dist/adapters/build.mjs +32 -22
  5. package/dist/adapters/cac.d.mts +16 -1
  6. package/dist/adapters/cac.mjs +8 -7
  7. package/dist/adapters/dev.d.mts +13 -13
  8. package/dist/adapters/dev.mjs +2 -2
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/initiate.d.mts +28 -26
  11. package/dist/adapters/initiate.mjs +1 -1
  12. package/dist/adapters/mcp.d.mts +28 -14
  13. package/dist/adapters/mcp.mjs +75 -39
  14. package/dist/{agent-tool-name-EgfoFO8C.mjs → agent-tool-name-DGzeuWcO.mjs} +2 -2
  15. package/dist/cli/main.d.mts +1 -1
  16. package/dist/cli/main.mjs +41 -17
  17. package/dist/client/index.d.mts +36 -36
  18. package/dist/client/index.mjs +83 -51
  19. package/dist/client-assets-DNdhagGm.mjs +16 -0
  20. package/dist/constants.d.mts +8 -7
  21. package/dist/constants.mjs +7 -6
  22. package/dist/{context-BhBzOXVa.d.mts → context-4AIVRLYF.d.mts} +173 -122
  23. package/dist/{context-omlma_1n.mjs → context-CwPUinjn.mjs} +126 -88
  24. package/dist/{context-KUqAfawQ.mjs → context-DIUvJW4D.mjs} +3 -3
  25. package/dist/{context-HOnG-WvG.d.mts → context-rgBSPFHS.d.mts} +5 -5
  26. package/dist/{crypto-token-XCqTSMg9.mjs → crypto-token-TVbGGFuj.mjs} +1 -1
  27. package/dist/{dev-Czit5IP4.mjs → dev-Eqq5PX0k.mjs} +37 -18
  28. package/dist/{diagnostics-BXWW3VK-.mjs → diagnostics-BMfN8mb1.mjs} +30 -17
  29. package/dist/{diagnostics-CD8nlgll.mjs → diagnostics-D0EVm5M6.mjs} +2 -2
  30. package/dist/{events-4daw0uK9.mjs → events-BV4Dj59a.mjs} +2 -2
  31. package/dist/{host-h3-fRbF9yor.mjs → host-h3-BJ4siyz7.mjs} +1 -1
  32. package/dist/in-page-channel/index.d.mts +59 -22
  33. package/dist/in-page-channel/index.mjs +71 -56
  34. package/dist/{index-BzyopqxV.d.mts → index-pIVt92jP.d.mts} +9 -9
  35. package/dist/{index-DcKxIMoI.d.mts → index-pKl67H6w.d.mts} +4 -4
  36. package/dist/index.d.mts +11 -13
  37. package/dist/index.mjs +6 -7
  38. package/dist/{instance-registry-BjlMQbFB.mjs → instance-registry-C7-41RSp.mjs} +8 -8
  39. package/dist/{instance-shell-Bh4l9Vz_.d.mts → instance-shell-7Z52PE4_.d.mts} +18 -18
  40. package/dist/{instance-shell-CpVW4zG0.mjs → instance-shell-cdVETpfz.mjs} +227 -58
  41. package/dist/internal/index.d.mts +51 -21
  42. package/dist/internal/index.mjs +10 -9
  43. package/dist/node/auth.d.mts +2 -2
  44. package/dist/node/auth.mjs +2 -2
  45. package/dist/node/hub-internals.d.mts +2 -2
  46. package/dist/node/hub-internals.mjs +2 -2
  47. package/dist/node/index.d.mts +5 -5
  48. package/dist/node/index.mjs +2 -2
  49. package/dist/{nostics-SPGDgHEP.d.mts → nostics-0sKe5HIj.d.mts} +2 -2
  50. package/dist/{nostics-CzECRXpE.mjs → nostics-D0PvLZsn.mjs} +1 -1
  51. package/dist/origin-DGDH8BI9.d.mts +45 -0
  52. package/dist/origin-DZit9g29.mjs +80 -0
  53. package/dist/recipes/common-rpc-functions.d.mts +5 -5
  54. package/dist/recipes/common-rpc-functions.mjs +3 -3
  55. package/dist/recipes/interactive-auth.d.mts +6 -6
  56. package/dist/recipes/interactive-auth.mjs +6 -6
  57. package/dist/{remote-assets-DezQmPQU.mjs → remote-assets-BIFWOlBW.mjs} +26 -6
  58. package/dist/{remote-assets-B13_vRkJ.d.mts → remote-assets-eBvSKZMS.d.mts} +7 -7
  59. package/dist/{revoke-COLW0cOi.mjs → revoke-cqztiCX4.mjs} +1 -1
  60. package/dist/rpc/dump.d.mts +2 -11
  61. package/dist/rpc/dump.mjs +1 -1
  62. package/dist/rpc/index.d.mts +2 -2
  63. package/dist/rpc/index.mjs +3 -3
  64. package/dist/rpc/transports/sse-client.d.mts +1 -1
  65. package/dist/rpc/transports/sse-client.mjs +30 -14
  66. package/dist/rpc/transports/sse-server.d.mts +4 -4
  67. package/dist/rpc/transports/sse-server.mjs +7 -7
  68. package/dist/rpc/transports/ws-bun.d.mts +5 -5
  69. package/dist/rpc/transports/ws-bun.mjs +8 -2
  70. package/dist/rpc/transports/ws-client.d.mts +1 -1
  71. package/dist/rpc/transports/ws-client.mjs +2 -2
  72. package/dist/rpc/transports/ws-deno.d.mts +4 -4
  73. package/dist/rpc/transports/ws-deno.mjs +8 -2
  74. package/dist/rpc/transports/ws-server.d.mts +2 -1
  75. package/dist/rpc/transports/ws-server.mjs +232 -1
  76. package/dist/{rpc-core-BHUsDl7s.d.mts → rpc-core-Ceu6AUz8.d.mts} +4 -4
  77. package/dist/{rpc-core-DlHd276T.mjs → rpc-core-DVQ7xi89.mjs} +14 -2
  78. package/dist/{serialization-BGzEwAdr.mjs → serialization-DTZnPQ1-.mjs} +20 -18
  79. package/dist/{services-install-CqqQVls5.mjs → services-install-P_DV7VYL.mjs} +32 -21
  80. package/dist/session-DPfj6zQG.mjs +16 -0
  81. package/dist/{shared-state-DoXutg_U.mjs → shared-state-CaxB1q0h.mjs} +4 -3
  82. package/dist/{simple-schema-DQPZrAaZ.mjs → simple-schema-Bi40l-P6.mjs} +2 -2
  83. package/dist/{sse-client-DwX021ST.d.mts → sse-client-BQ4jS3eO.d.mts} +4 -4
  84. package/dist/{state-CK9LjrnT.mjs → state-CeQQWzM-.mjs} +4 -4
  85. package/dist/{static-DV_qUSRS.mjs → static-DZ8P2Kn7.mjs} +130 -135
  86. package/dist/{storage-BXNVhKyR.mjs → storage-Dccf_IyD.mjs} +1 -1
  87. package/dist/types/index.d.mts +6 -6
  88. package/dist/{types-CMdPYhOx.d.mts → types-Dq4i156u.d.mts} +17 -17
  89. package/dist/utils/agent-tool-name.d.mts +2 -2
  90. package/dist/utils/agent-tool-name.mjs +2 -2
  91. package/dist/utils/colors.d.mts +1 -1
  92. package/dist/utils/crypto-token.d.mts +1 -1
  93. package/dist/utils/crypto-token.mjs +1 -1
  94. package/dist/utils/events.d.mts +1 -1
  95. package/dist/utils/nostics.d.mts +1 -1
  96. package/dist/utils/nostics.mjs +1 -1
  97. package/dist/utils/open.mjs +1 -1
  98. package/dist/utils/origin.d.mts +2 -0
  99. package/dist/utils/origin.mjs +80 -0
  100. package/dist/utils/remote-assets.d.mts +2 -2
  101. package/dist/utils/remote-assets.mjs +1 -1
  102. package/dist/utils/serve-static.d.mts +4 -4
  103. package/dist/utils/serve-static.mjs +56 -19
  104. package/dist/utils/shared-state.d.mts +1 -1
  105. package/dist/utils/shared-state.mjs +1 -1
  106. package/dist/utils/simple-schema.d.mts +5 -5
  107. package/dist/utils/simple-schema.mjs +2 -2
  108. package/dist/utils/streaming-channel.d.mts +1 -1
  109. package/dist/utils/streaming-channel.mjs +2 -2
  110. package/dist/utils/when.d.mts +5 -5
  111. package/dist/{validation-YrZH6atx.mjs → validation-BOy8IoFZ.mjs} +2 -2
  112. package/dist/{wire-codec-0K-o5MYW.mjs → wire-codec-dcCeXcSo.mjs} +3 -3
  113. package/dist/{ws-client-7_lZi-B9.d.mts → ws-client-Xpxt0oPA.d.mts} +3 -3
  114. package/dist/{ws-server-Di2oqr4q.d.mts → ws-server-D2nv68Hg.d.mts} +13 -22
  115. package/package.json +6 -5
  116. package/dist/ws-server-BdSLrhxE.mjs +0 -267
@@ -1,8 +1,8 @@
1
1
  //#region src/events.ts
2
2
  /**
3
- * Centralized registry of the core devframe event names — the node-side host
3
+ * Centralized registry of the core devframe event names: the node-side host
4
4
  * bus events, the client RPC connection events, and the server→client
5
- * broadcast notifications — so these names live in one place instead of
5
+ * broadcast notifications, so these names live in one place instead of
6
6
  * scattered string literals.
7
7
  *
8
8
  * **Keep this in sync with [`docs/content/8.references/3.events.md`](../../../docs/content/8.references/3.events.md)**
@@ -3,7 +3,7 @@ import { join } from "pathe";
3
3
  import { homedir } from "node:os";
4
4
  //#region src/node/host-h3.ts
5
5
  /**
6
- * h3-backed {@link DevframeHost} — used by the standalone CLI adapter.
6
+ * h3-backed {@link DevframeHost}, used by the standalone CLI adapter.
7
7
  */
8
8
  function createH3DevframeHost(options) {
9
9
  const workspaceRoot = options.workspaceRoot ?? process.cwd();
@@ -1,11 +1,11 @@
1
- import { D as InferArgsType, E as Thenable, O as InferReturnType, T as RpcReturnSchema, i as RpcArgsSchema } from "../types-CMdPYhOx.mjs";
2
- import { k as SharedState, zt as EventEmitter } from "../context-BhBzOXVa.mjs";
1
+ import { D as InferArgsType, E as Thenable, O as InferReturnType, T as RpcReturnSchema, i as RpcArgsSchema } from "../types-Dq4i156u.mjs";
2
+ import { Bt as EventEmitter, k as SharedState } from "../context-4AIVRLYF.mjs";
3
3
  import { BirpcReturn } from "birpc";
4
4
  //#region src/in-page-channel/types.d.ts
5
5
  /**
6
6
  * The shared contract of one in-page channel, declared once (usually in a
7
7
  * `shared/protocol.ts` both sides import) and passed to both endpoints as a
8
- * type parameter. Purely a type — the only runtime companion is the
8
+ * type parameter. Purely a type; the only runtime companion is the
9
9
  * channel-name constant declared next to it.
10
10
  */
11
11
  interface InPageChannelProtocol {
@@ -27,13 +27,19 @@ type SharedStates<P extends InPageChannelProtocol> = P['sharedStates'] extends R
27
27
  type FnArgs<F> = F extends ((...args: infer A) => any) ? A : never;
28
28
  type FnReturn<F> = F extends ((...args: any[]) => infer R) ? Awaited<R> : never;
29
29
  /**
30
- * Types of an in-page channel function — `RpcFunctionType` minus the
30
+ * Converts a protocol function to its accepted endpoint handler.
31
+ *
32
+ * @internal
33
+ */
34
+ type ProtocolHandler<F> = F extends ((...args: any[]) => any) ? (...args: FnArgs<F>) => Thenable<FnReturn<F>> : never;
35
+ /**
36
+ * Types of an in-page channel function: `RpcFunctionType` minus the
31
37
  * server-only `static`: `event` is fire-and-forget (the only type valid for
32
38
  * fan-out), `action` performs, `query` requests data (the default).
33
39
  */
34
40
  type InPageFunctionType = 'action' | 'event' | 'query';
35
41
  /**
36
- * An in-page channel function definition — the `defineRpcFunction` authoring
42
+ * An in-page channel function definition: the `defineRpcFunction` authoring
37
43
  * shape (`name`, `type`, Standard-Schema `args`/`returns`,
38
44
  * `jsonSerializable`, `handler`) narrowed to the browser: there is no
39
45
  * `dump`/`snapshot`/`cacheable`/`agent`. When `jsonSerializable` is `true`,
@@ -58,22 +64,49 @@ type InPageFunctionDefinition<NAME extends string, TYPE extends InPageFunctionTy
58
64
  jsonSerializable?: boolean;
59
65
  handler: (...args: InferArgsType<AS>) => Thenable<InferReturnType<RS>>;
60
66
  };
61
- /** Loosely-typed definition — the registration unit both endpoints accept. */
62
- type InPageFunctionDefinitionAny = InPageFunctionDefinition<string, any, any, any, any, any>;
67
+ /**
68
+ * Function metadata with its handler constrained by a protocol function.
69
+ *
70
+ * @internal
71
+ */
72
+ interface InPageFunctionOption<F> {
73
+ type?: InPageFunctionType;
74
+ /** Optional Standard Schema array validating the arguments. */
75
+ args?: RpcArgsSchema;
76
+ /** Optional Standard Schema validating the resolved return value. */
77
+ returns?: RpcReturnSchema;
78
+ jsonSerializable?: boolean;
79
+ handler: ProtocolHandler<F>;
80
+ }
81
+ /**
82
+ * Functions implemented by {@link createPageScriptChannel}.
83
+ *
84
+ * @internal
85
+ */
86
+ type CreatePageScriptChannelOptionsFunctions<P extends InPageChannelProtocol> = { [NAME in keyof PageScriptFunctions<P> & string]: InPageFunctionOption<PageScriptFunctions<P>[NAME]>; };
87
+ /**
88
+ * Functions implemented by {@link connectPanelChannel}.
89
+ *
90
+ * @internal
91
+ */
92
+ type ConnectPanelChannelOptionsFunctions<P extends InPageChannelProtocol> = { [NAME in keyof PanelFunctions<P> & string]: InPageFunctionOption<PanelFunctions<P>[NAME]>; };
63
93
  /**
64
94
  * Connection lifecycle of a panel endpoint: `connecting` (handshake retry
65
95
  * loop running, outgoing traffic buffered) → `connected` → back to
66
96
  * `connecting` on port loss, or `closed` after `close()` (permanent).
67
97
  */
68
98
  type InPageChannelStatus = 'connecting' | 'connected' | 'closed';
99
+ /**
100
+ * Options shared by both in-page channel endpoints.
101
+ *
102
+ * @internal
103
+ */
69
104
  interface InPageChannelCommonOptions {
70
105
  /**
71
106
  * Channel name, namespaced with the devframe id by convention
72
107
  * (e.g. `devframes:plugin:a11y`). Both endpoints must use the same name.
73
108
  */
74
109
  name: string;
75
- /** Implementations of this endpoint's side of the protocol. */
76
- functions?: readonly InPageFunctionDefinitionAny[];
77
110
  /**
78
111
  * Origins accepted during the handshake (and used as `targetOrigin` when
79
112
  * posting handshake messages). The in-page channel is same-origin by
@@ -89,7 +122,7 @@ interface InPageChannelCommonOptions {
89
122
  callTimeoutMs?: number;
90
123
  /**
91
124
  * Liveness heartbeat guarding against silently dead ports. Defaults to a
92
- * 5s ping / 12s silence window; pass `false` to disable — on both
125
+ * 5s ping / 12s silence window; pass `false` to disable, on both
93
126
  * endpoints together.
94
127
  */
95
128
  heartbeat?: {
@@ -97,7 +130,7 @@ interface InPageChannelCommonOptions {
97
130
  timeoutMs?: number;
98
131
  } | false;
99
132
  /**
100
- * Applied to each outgoing argument and handler result before posting —
133
+ * Applied to each outgoing argument and handler result before posting;
101
134
  * the place to unwrap framework reactivity (Vue `toRaw`, Solid `unwrap`)
102
135
  * into plain structured-cloneable values.
103
136
  */
@@ -106,7 +139,9 @@ interface InPageChannelCommonOptions {
106
139
  deserialize?: (value: unknown) => unknown;
107
140
  }
108
141
  /** Options for {@link createPageScriptChannel}. */
109
- interface CreatePageScriptChannelOptions extends InPageChannelCommonOptions {
142
+ interface CreatePageScriptChannelOptions<Protocol extends InPageChannelProtocol = InPageChannelProtocol> extends InPageChannelCommonOptions {
143
+ /** Implementations of the protocol's page-script functions. */
144
+ functions: CreatePageScriptChannelOptionsFunctions<Protocol>;
110
145
  /**
111
146
  * Window whose `message` events carry panel hellos. Defaults to the
112
147
  * global `window`; pass `false` to skip the handshake listener entirely
@@ -115,7 +150,9 @@ interface CreatePageScriptChannelOptions extends InPageChannelCommonOptions {
115
150
  window?: Window | false;
116
151
  }
117
152
  /** Options for {@link connectPanelChannel}. */
118
- interface ConnectPanelChannelOptions extends InPageChannelCommonOptions {
153
+ interface ConnectPanelChannelOptions<Protocol extends InPageChannelProtocol = InPageChannelProtocol> extends InPageChannelCommonOptions {
154
+ /** Implementations of the protocol's panel functions. */
155
+ functions: ConnectPanelChannelOptionsFunctions<Protocol>;
119
156
  /**
120
157
  * The panel's own window (listens for the handshake grant). Defaults to
121
158
  * the global `window`; pass `false` with `transport` to skip the handshake.
@@ -123,7 +160,7 @@ interface ConnectPanelChannelOptions extends InPageChannelCommonOptions {
123
160
  window?: Window | false;
124
161
  /**
125
162
  * Windows the hello is posted to. Defaults to the panel's ancestor chain
126
- * plus its `opener` — the places a same-tab page script can live. When
163
+ * plus its `opener`, the places a same-tab page script can live. When
127
164
  * empty and no `transport` is given, the endpoint stays `connecting` and
128
165
  * warns once.
129
166
  */
@@ -132,7 +169,7 @@ interface ConnectPanelChannelOptions extends InPageChannelCommonOptions {
132
169
  transport?: MessagePort;
133
170
  /**
134
171
  * Pin this panel to one page-script instance id. By default the panel
135
- * auto-pairs with the most recent page script that answers — almost
172
+ * auto-pairs with the most recent page script that answers, almost
136
173
  * always "my own tab's page script".
137
174
  */
138
175
  instanceId?: string;
@@ -151,7 +188,7 @@ interface ConnectPanelChannelOptions extends InPageChannelCommonOptions {
151
188
  eventBufferLimit?: number;
152
189
  }
153
190
  /**
154
- * The channel shared-state accessor — mirrors `rpc.sharedState`, with the
191
+ * The channel shared-state accessor, mirroring `rpc.sharedState`, with the
155
192
  * page script playing the server's role as rendezvous and authority. The
156
193
  * page script's first `get` of a key must provide `initialValue`; a panel's
157
194
  * `get` without one resolves once the authority's first replay arrives.
@@ -223,7 +260,7 @@ interface PanelChannel<P extends InPageChannelProtocol> {
223
260
  /**
224
261
  * Resolves once connected. With `timeoutMs`, rejects with an
225
262
  * `InPageChannelError` (code `timeout`) when no page script answered in
226
- * time — the hook for a "no page script found" fallback UI.
263
+ * time; the hook for a "no page script found" fallback UI.
227
264
  */
228
265
  whenConnected: (timeoutMs?: number) => Promise<void>;
229
266
  /**
@@ -271,11 +308,11 @@ declare class InPageChannelError extends Error {
271
308
  *
272
309
  * It listens for panel hellos on the host page's window and answers each
273
310
  * with a dedicated `MessageChannel` port (same-origin enforced both ways),
274
- * keeping one live peer per panel — dock iframe, popup, and Document-PiP
311
+ * keeping one live peer per panel: dock iframe, popup, and Document-PiP
275
312
  * panels all handshake the same way, and a panel reload is simply a new
276
313
  * handshake. No server is involved at any point.
277
314
  */
278
- declare function createPageScriptChannel<P extends InPageChannelProtocol>(options: CreatePageScriptChannelOptions): PageScriptChannel<P>;
315
+ declare function createPageScriptChannel<P extends InPageChannelProtocol>(options: CreatePageScriptChannelOptions<P>): PageScriptChannel<P>;
279
316
  //#endregion
280
317
  //#region src/in-page-channel/panel.d.ts
281
318
  /**
@@ -283,18 +320,18 @@ declare function createPageScriptChannel<P extends InPageChannelProtocol>(option
283
320
  *
284
321
  * The panel initiates: it posts a versioned hello to every window a
285
322
  * same-tab page script can live in (its ancestor chain and its `opener`),
286
- * retrying with backoff until one answers with a dedicated port — so boot
323
+ * retrying with backoff until one answers with a dedicated port, so boot
287
324
  * order never matters, and a reload of either side is just a re-handshake
288
325
  * (`WindowProxy` references survive navigations). While `connecting`,
289
326
  * outgoing calls and events are buffered; when no page script exists at all
290
327
  * (e.g. the panel opened standalone), the endpoint stays `connecting` and
291
328
  * the UI can key a fallback state off `status` / `whenConnected()`.
292
329
  */
293
- declare function connectPanelChannel<P extends InPageChannelProtocol>(options: ConnectPanelChannelOptions): PanelChannel<P>;
330
+ declare function connectPanelChannel<P extends InPageChannelProtocol>(options: ConnectPanelChannelOptions<P>): PanelChannel<P>;
294
331
  //#endregion
295
332
  //#region src/in-page-channel/index.d.ts
296
333
  /**
297
- * Define one in-page channel function — the `defineRpcFunction` authoring
334
+ * Define one in-page channel function, the `defineRpcFunction` authoring
298
335
  * shape narrowed to the browser (see {@link InPageFunctionDefinition}).
299
336
  * Pure identity: it only types the definition. Functions live in
300
337
  * side-specific files and are passed to their endpoint via `functions`; the
@@ -1,14 +1,14 @@
1
- import { t as DEVFRAME_EVENTS } from "../events-4daw0uK9.mjs";
1
+ import { t as DEVFRAME_EVENTS } from "../events-BV4Dj59a.mjs";
2
2
  import { createEventEmitter } from "../utils/events.mjs";
3
- import { t as createSharedState } from "../shared-state-DoXutg_U.mjs";
3
+ import { t as createSharedState } from "../shared-state-CaxB1q0h.mjs";
4
4
  import { nanoid } from "../utils/nanoid.mjs";
5
5
  import { createBirpc } from "birpc";
6
6
  //#region src/in-page-channel/protocol.ts
7
7
  /**
8
8
  * Wire protocol of the in-page channel handshake and its port-level control
9
- * frames. The envelope is transport-neutral by design — it identifies the
9
+ * frames. The envelope is transport-neutral by design: it identifies the
10
10
  * protocol (`channel` tag + `v`), the user channel (`name`), and the peers
11
- * (`panelId`, `instanceId`) — so a future cross-tab transport (e.g. a
11
+ * (`panelId`, `instanceId`), so a future cross-tab transport (e.g. a
12
12
  * `BroadcastChannel`) can reuse it unchanged.
13
13
  */
14
14
  /** `postMessage` tag every handshake message carries. */
@@ -26,7 +26,7 @@ let memoryInstanceId;
26
26
  /**
27
27
  * The page context's instance id: one nanoid per browser tab, persisted in
28
28
  * `sessionStorage` so it survives page-script reloads. It scopes handshakes
29
- * when the same app is open in several tabs — a panel pinned to an instance
29
+ * when the same app is open in several tabs, since a panel pinned to an instance
30
30
  * id ignores grants from every other tab's page script.
31
31
  */
32
32
  function resolveInstanceId(win) {
@@ -52,7 +52,7 @@ function resolveAllowedOrigins(allowedOrigins, win) {
52
52
  }
53
53
  /**
54
54
  * Default handshake targets of a panel: its ancestor chain plus its
55
- * `opener` — every same-tab window a page script can live in. `WindowProxy`
55
+ * `opener`, every same-tab window a page script can live in. `WindowProxy`
56
56
  * references stay valid across navigations, so hellos posted to these reach
57
57
  * a page script even after the host page reloads.
58
58
  */
@@ -93,7 +93,7 @@ var InPageChannelError = class extends Error {
93
93
  };
94
94
  const warned = /* @__PURE__ */ new Set();
95
95
  /**
96
- * `console.warn` once per distinct message — handshake noise (foreign
96
+ * `console.warn` once per distinct message, since handshake noise (foreign
97
97
  * origins, version mismatches, missing targets) repeats on every retry tick.
98
98
  */
99
99
  function warnOnce(message) {
@@ -102,19 +102,13 @@ function warnOnce(message) {
102
102
  console.warn(`[devframe] ${message}`);
103
103
  }
104
104
  }
105
- function jsonViolation(value, path, seen) {
106
- if (value === null || typeof value === "boolean" || typeof value === "string") return void 0;
107
- if (typeof value === "number") return Number.isFinite(value) ? void 0 : `${path} is ${value}`;
108
- if (typeof value !== "object") return `${path} is ${value === void 0 ? "`undefined`" : `a ${typeof value}`}`;
109
- if (seen.has(value)) return `${path} is circular`;
110
- seen.add(value);
111
- if (Array.isArray(value)) {
112
- for (let i = 0; i < value.length; i++) {
113
- const violation = jsonViolation(value[i], `${path}[${i}]`, seen);
114
- if (violation) return violation;
115
- }
116
- return;
105
+ function jsonArrayViolation(value, path, seen) {
106
+ for (let i = 0; i < value.length; i++) {
107
+ const violation = jsonViolation(value[i], `${path}[${i}]`, seen);
108
+ if (violation) return violation;
117
109
  }
110
+ }
111
+ function jsonObjectViolation(value, path, seen) {
118
112
  const proto = Object.getPrototypeOf(value);
119
113
  if (proto !== Object.prototype && proto !== null) return `${path} is an instance of ${value.constructor?.name ?? "an exotic class"}`;
120
114
  for (const [key, entry] of Object.entries(value)) {
@@ -122,10 +116,18 @@ function jsonViolation(value, path, seen) {
122
116
  if (violation) return violation;
123
117
  }
124
118
  }
119
+ function jsonViolation(value, path, seen) {
120
+ if (value === null || typeof value === "boolean" || typeof value === "string") return void 0;
121
+ if (typeof value === "number") return Number.isFinite(value) ? void 0 : `${path} is ${value}`;
122
+ if (typeof value !== "object") return `${path} is ${value === void 0 ? "`undefined`" : `a ${typeof value}`}`;
123
+ if (seen.has(value)) return `${path} is circular`;
124
+ seen.add(value);
125
+ return Array.isArray(value) ? jsonArrayViolation(value, path, seen) : jsonObjectViolation(value, path, seen);
126
+ }
125
127
  /**
126
128
  * Enforce a `jsonSerializable: true` contract: throws code
127
129
  * `not-serializable` naming the offending path when the value contains
128
- * anything strict JSON can't represent — surfacing the bug at the offending
130
+ * anything strict JSON can't represent, surfacing the bug at the offending
129
131
  * call instead of a silent coercion later.
130
132
  */
131
133
  function assertJsonSerializable(value, what, functionName) {
@@ -181,14 +183,35 @@ function createLocalFunctionRegistry(codec) {
181
183
  };
182
184
  }
183
185
  function wrapPostError(error) {
184
- if (error instanceof DOMException && error.name === "DataCloneError") return new InPageChannelError("not-cloneable", `a payload could not be structured-cloned across the in-page channel: ${error.message}. Strip non-cloneable values (functions, DOM nodes, framework reactivity proxies) before sending — declare the function \`jsonSerializable: true\` for a precise error, or provide a \`serialize\` hook.`, { cause: error });
186
+ if (error instanceof DOMException && error.name === "DataCloneError") return new InPageChannelError("not-cloneable", `a payload could not be structured-cloned across the in-page channel: ${error.message}. Strip non-cloneable values (functions, DOM nodes, framework reactivity proxies) before sending: declare the function \`jsonSerializable: true\` for a precise error, or provide a \`serialize\` hook.`, { cause: error });
185
187
  return error;
186
188
  }
187
189
  function attachChannelPort(port, options) {
188
190
  let birpcHandler;
189
191
  let disposed = false;
190
192
  const attached = {
191
- rpc: void 0,
193
+ rpc: createBirpc({}, {
194
+ post: (data) => {
195
+ try {
196
+ port.postMessage(data);
197
+ } catch (error) {
198
+ throw wrapPostError(error);
199
+ }
200
+ },
201
+ on: (fn) => {
202
+ birpcHandler = fn;
203
+ },
204
+ off: () => {
205
+ birpcHandler = void 0;
206
+ },
207
+ /**
208
+ * Deadlines live at the endpoint layer (`withCallDeadline`) with
209
+ * status-aware errors; birpc's own timer stays off.
210
+ */
211
+ timeout: -1,
212
+ proxify: false,
213
+ resolver: (name, resolved) => resolved ?? options.resolveLocal(name)
214
+ }),
192
215
  lastActivity: Date.now(),
193
216
  postControl(kind) {
194
217
  try {
@@ -222,24 +245,6 @@ function attachChannelPort(port, options) {
222
245
  function onClose() {
223
246
  options.onPeerClosed();
224
247
  }
225
- attached.rpc = createBirpc({}, {
226
- post: (data) => {
227
- try {
228
- port.postMessage(data);
229
- } catch (error) {
230
- throw wrapPostError(error);
231
- }
232
- },
233
- on: (fn) => {
234
- birpcHandler = fn;
235
- },
236
- off: () => {
237
- birpcHandler = void 0;
238
- },
239
- timeout: -1,
240
- proxify: false,
241
- resolver: (name, resolved) => resolved ?? options.resolveLocal(name)
242
- });
243
248
  port.addEventListener("message", onMessage);
244
249
  port.addEventListener("close", onClose);
245
250
  port.start?.();
@@ -265,7 +270,7 @@ function withCallDeadline(promise, ms, describeTimeout) {
265
270
  //#endregion
266
271
  //#region src/in-page-channel/state.ts
267
272
  /**
268
- * The channel shared-state layer — `createSharedState` pumped over the
273
+ * The channel shared-state layer: `createSharedState` pumped over the
269
274
  * in-page channel, mirroring the RPC shared-state wire design with the page
270
275
  * script playing the server's role: it owns the canonical value, replays a
271
276
  * snapshot to every (re)subscribing panel, and fans syncId-deduplicated
@@ -290,7 +295,7 @@ function createPageScriptStateHost(peers) {
290
295
  get: async (key, options) => {
291
296
  const existing = states.get(key);
292
297
  if (existing) return existing;
293
- if (options?.initialValue === void 0) throw new InPageChannelError("state-uninitialized", `in-page shared state "${key}" was accessed before initialization — the page script is the authority, so its first \`sharedState.get("${key}")\` must provide \`initialValue\``);
298
+ if (options?.initialValue === void 0) throw new InPageChannelError("state-uninitialized", `in-page shared state "${key}" was accessed before initialization; the page script is the authority, so its first \`sharedState.get("${key}")\` must provide \`initialValue\``);
294
299
  const state = createSharedState({
295
300
  initialValue: options.initialValue,
296
301
  enablePatches: true
@@ -337,7 +342,7 @@ function createPanelStateHost(options) {
337
342
  const seedWaiters = /* @__PURE__ */ new Map();
338
343
  /**
339
344
  * SyncIds of snapshot adoptions. Adopting the authority's replay must not
340
- * echo straight back up as a `set` — the authority already has the value.
345
+ * echo straight back up as a `set`; the authority already has the value.
341
346
  */
342
347
  const adoptedSyncIds = /* @__PURE__ */ new Set();
343
348
  function markSeeded(key) {
@@ -381,6 +386,10 @@ function createPanelStateHost(options) {
381
386
  const existing = states.get(key);
382
387
  if (existing) return Promise.resolve(existing);
383
388
  const state = createSharedState({
389
+ /**
390
+ * Without an initial value the state stays empty until the
391
+ * authority's first replay resolves the returned promise.
392
+ */
384
393
  initialValue: getOptions?.initialValue,
385
394
  enablePatches: true
386
395
  });
@@ -420,7 +429,7 @@ function createPanelStateHost(options) {
420
429
  *
421
430
  * It listens for panel hellos on the host page's window and answers each
422
431
  * with a dedicated `MessageChannel` port (same-origin enforced both ways),
423
- * keeping one live peer per panel — dock iframe, popup, and Document-PiP
432
+ * keeping one live peer per panel: dock iframe, popup, and Document-PiP
424
433
  * panels all handshake the same way, and a panel reload is simply a new
425
434
  * handshake. No server is involved at any point.
426
435
  */
@@ -440,7 +449,10 @@ function createPageScriptChannel(options) {
440
449
  let closed = false;
441
450
  let heartbeatTimer;
442
451
  const registry = createLocalFunctionRegistry(codec);
443
- for (const definition of options.functions ?? []) registry.register(definition);
452
+ for (const [fnName, definition] of Object.entries(options.functions ?? {})) registry.register({
453
+ ...definition,
454
+ name: fnName
455
+ });
444
456
  const stateHost = createPageScriptStateHost(function* () {
445
457
  for (const peer of peers.values()) yield {
446
458
  subscribedStates: peer.subscribedStates,
@@ -510,7 +522,7 @@ function createPageScriptChannel(options) {
510
522
  const data = event.data;
511
523
  if (!isHandshakeMessage(data) || data.kind !== "hello" || data.name !== name) return;
512
524
  if (data.v !== 1) {
513
- warnOnce(`in-page channel "${name}": ignoring a hello with protocol version ${data.v} (this side speaks 1) — align the devframe versions of the page script and the panel`);
525
+ warnOnce(`in-page channel "${name}": ignoring a hello with protocol version ${data.v} (this side speaks 1); align the devframe versions of the page script and the panel`);
514
526
  return;
515
527
  }
516
528
  if (!allowedOrigins.includes("*") && !allowedOrigins.includes(event.origin)) {
@@ -580,7 +592,7 @@ const DEFAULT_EVENT_BUFFER_LIMIT = 64;
580
592
  *
581
593
  * The panel initiates: it posts a versioned hello to every window a
582
594
  * same-tab page script can live in (its ancestor chain and its `opener`),
583
- * retrying with backoff until one answers with a dedicated port — so boot
595
+ * retrying with backoff until one answers with a dedicated port, so boot
584
596
  * order never matters, and a reload of either side is just a re-handshake
585
597
  * (`WindowProxy` references survive navigations). While `connecting`,
586
598
  * outgoing calls and events are buffered; when no page script exists at all
@@ -603,7 +615,10 @@ function connectPanelChannel(options) {
603
615
  const canHandshake = !!win && targets.length > 0;
604
616
  const events = createEventEmitter();
605
617
  const registry = createLocalFunctionRegistry(codec);
606
- for (const definition of options.functions ?? []) registry.register(definition);
618
+ for (const [fnName, definition] of Object.entries(options.functions ?? {})) registry.register({
619
+ ...definition,
620
+ name: fnName
621
+ });
607
622
  let status = "connecting";
608
623
  let attached;
609
624
  let pageScriptInfo;
@@ -642,7 +657,7 @@ function connectPanelChannel(options) {
642
657
  eventBuffer.shift();
643
658
  if (!droppedEventsWarned) {
644
659
  droppedEventsWarned = true;
645
- console.warn(`[devframe] in-page channel "${name}": event buffer overflowed while connecting — oldest events are being dropped (limit ${eventBufferLimit})`);
660
+ console.warn(`[devframe] in-page channel "${name}": event buffer overflowed while connecting, so the oldest events are being dropped (limit ${eventBufferLimit})`);
646
661
  }
647
662
  }
648
663
  eventBuffer.push({
@@ -651,7 +666,7 @@ function connectPanelChannel(options) {
651
666
  });
652
667
  }
653
668
  function enqueueCall(method, args) {
654
- if (status === "closed") return Promise.reject(new InPageChannelError("closed", `in-page channel "${name}": call "${method}" rejected — the channel is closed`));
669
+ if (status === "closed") return Promise.reject(new InPageChannelError("closed", `in-page channel "${name}": call "${method}" rejected because the channel is closed`));
655
670
  return withCallDeadline(new Promise((resolve, reject) => {
656
671
  const run = () => {
657
672
  attached.rpc.$call(method, ...args).then((result) => resolve(deserializeResult(codec, result)), reject);
@@ -661,7 +676,7 @@ function connectPanelChannel(options) {
661
676
  run,
662
677
  reject
663
678
  });
664
- }), callTimeoutMs, () => `in-page channel "${name}": call "${method}" timed out after ${callTimeoutMs}ms (status: ${status}${status === "connecting" ? " — is the page script loaded?" : ""})`);
679
+ }), callTimeoutMs, () => `in-page channel "${name}": call "${method}" timed out after ${callTimeoutMs}ms (status: ${status}${status === "connecting" ? "; is the page script loaded?" : ""})`);
665
680
  }
666
681
  function adoptPort(port, info) {
667
682
  attached?.dispose({
@@ -706,7 +721,7 @@ function connectPanelChannel(options) {
706
721
  stopTimers();
707
722
  setStatus("connecting");
708
723
  if (canHandshake) startHelloLoop();
709
- else warnOnce(`in-page channel "${name}": transport lost (${reason}) and the panel has no handshake targets — staying disconnected`);
724
+ else warnOnce(`in-page channel "${name}": transport lost (${reason}) and the panel has no handshake targets, so it stays disconnected`);
710
725
  }
711
726
  function startHelloLoop() {
712
727
  if (helloTimer || !canHandshake || status !== "connecting") return;
@@ -733,7 +748,7 @@ function connectPanelChannel(options) {
733
748
  const data = event.data;
734
749
  if (!isHandshakeMessage(data) || data.kind !== "grant" || data.name !== name || data.panelId !== panelId) return;
735
750
  if (data.v !== 1) {
736
- warnOnce(`in-page channel "${name}": ignoring a grant with protocol version ${data.v} (this side speaks 1) — align the devframe versions of the page script and the panel`);
751
+ warnOnce(`in-page channel "${name}": ignoring a grant with protocol version ${data.v} (this side speaks 1); align the devframe versions of the page script and the panel`);
737
752
  return;
738
753
  }
739
754
  if (!allowedOrigins.includes("*") && !allowedOrigins.includes(event.origin)) {
@@ -747,7 +762,7 @@ function connectPanelChannel(options) {
747
762
  win?.addEventListener("message", onWindowMessage);
748
763
  if (options.transport) adoptPort(options.transport);
749
764
  else if (canHandshake) startHelloLoop();
750
- else warnOnce(`in-page channel "${name}": the panel has no handshake targets (not embedded, no opener) and no transport — calls will buffer until a transport appears or the channel is closed`);
765
+ else warnOnce(`in-page channel "${name}": the panel has no handshake targets (not embedded, no opener) and no transport, so calls will buffer until a transport appears or the channel is closed`);
751
766
  return {
752
767
  name,
753
768
  get status() {
@@ -773,7 +788,7 @@ function connectPanelChannel(options) {
773
788
  const index = connectedWaiters.indexOf(waiter);
774
789
  if (index >= 0) {
775
790
  connectedWaiters.splice(index, 1);
776
- reject(new InPageChannelError("timeout", `in-page channel "${name}": no page script answered within ${timeoutMs}ms — it may not be loaded in this context (render a fallback state)`));
791
+ reject(new InPageChannelError("timeout", `in-page channel "${name}": no page script answered within ${timeoutMs}ms; it may not be loaded in this context (render a fallback state)`));
777
792
  }
778
793
  }, timeoutMs);
779
794
  });
@@ -802,7 +817,7 @@ function connectPanelChannel(options) {
802
817
  //#endregion
803
818
  //#region src/in-page-channel/index.ts
804
819
  /**
805
- * Define one in-page channel function — the `defineRpcFunction` authoring
820
+ * Define one in-page channel function, the `defineRpcFunction` authoring
806
821
  * shape narrowed to the browser (see {@link InPageFunctionDefinition}).
807
822
  * Pure identity: it only types the definition. Functions live in
808
823
  * side-specific files and are passed to their endpoint via `functions`; the
@@ -1,4 +1,4 @@
1
- import { C as RpcFunctionType, S as RpcFunctionSetupResult, T as RpcReturnSchema, _ as RpcFunctionDefinition, i as RpcArgsSchema, v as RpcFunctionDefinitionAny, w as RpcFunctionsCollector } from "./types-CMdPYhOx.mjs";
1
+ import { C as RpcFunctionType, S as RpcFunctionSetupResult, T as RpcReturnSchema, _ as RpcFunctionDefinition, i as RpcArgsSchema, v as RpcFunctionDefinitionAny, w as RpcFunctionsCollector } from "./types-Dq4i156u.mjs";
2
2
  //#region src/rpc/cache.d.ts
3
3
  interface RpcCacheOptions {
4
4
  functions: string[];
@@ -66,7 +66,7 @@ declare function getRpcHandler<NAME extends string, TYPE extends RpcFunctionType
66
66
  *
67
67
  * birpc envelopes always start with `{`, so a leading byte that is not
68
68
  * `s` is unambiguously JSON. Each direction independently chooses its
69
- * encoding from local definitions — request and response are not
69
+ * encoding from local definitions; request and response are not
70
70
  * coupled by a mirror rule.
71
71
  */
72
72
  declare const STRUCTURED_CLONE_PREFIX = "s:";
@@ -78,16 +78,16 @@ declare const STRUCTURED_CLONE_PREFIX = "s:";
78
78
  * instances, or `undefined` inside an array (silently becomes `null`).
79
79
  *
80
80
  * Native pass-throughs (no extra work needed):
81
- * - circular references — `JSON.stringify` raises `TypeError`.
82
- * - `BigInt` at top level — caught here for a friendlier error path.
81
+ * - circular references: `JSON.stringify` raises `TypeError`.
82
+ * - `BigInt` at top level: caught here for a friendlier error path.
83
83
  *
84
84
  * Lenient cases (allowed without throwing):
85
- * - `undefined` as an object property — legitimate optional field;
85
+ * - `undefined` as an object property: legitimate optional field;
86
86
  * JSON.stringify just omits it.
87
- * - `undefined` at the root — legitimate "action returned nothing".
88
- * - `Symbol` / `Function` values — semantically "drop me" in JSON.
87
+ * - `undefined` at the root: legitimate "action returned nothing".
88
+ * - `Symbol` / `Function` values: semantically "drop me" in JSON.
89
89
  *
90
- * `fnName` is used only for the diagnostic message — pass the RPC
90
+ * `fnName` is used only for the diagnostic message; pass the RPC
91
91
  * function name when calling from a wire serializer / dump writer so
92
92
  * the error points at the offending function.
93
93
  */
@@ -110,7 +110,7 @@ declare function validateRpcArgs(name: string, argsSchema: RpcArgsSchema | undef
110
110
  /**
111
111
  * Validate a handler's resolved return value against its declared schema.
112
112
  * Throws `DF0039` when the value fails the schema, otherwise returns the
113
- * original value unchanged (guard-only, never rewriting the payload — see
113
+ * original value unchanged (guard-only, never rewriting the payload; see
114
114
  * {@link validateRpcArgs}). Passes through when no return schema is set.
115
115
  *
116
116
  * @internal
@@ -1,5 +1,5 @@
1
- import { k as SharedState, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "./context-BhBzOXVa.mjs";
2
- import { n as InternalAnonymousAuthStorage } from "./context-HOnG-WvG.mjs";
1
+ import { k as SharedState, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "./context-4AIVRLYF.mjs";
2
+ import { n as InternalAnonymousAuthStorage } from "./context-rgBSPFHS.mjs";
3
3
  //#region src/node/auth/revoke.d.ts
4
4
  /**
5
5
  * Flip `isTrusted` to false on any live WS clients connected with `token`
@@ -29,13 +29,13 @@ declare function getTempAuthCode(): string;
29
29
  declare function refreshTempAuthCode(): string;
30
30
  /**
31
31
  * Build a "magic link" authentication URL that embeds a one-time code (OTP) in
32
- * the URL **fragment**. Opening it authenticates the client without typing —
32
+ * the URL **fragment**. Opening it authenticates the client without typing;
33
33
  * print it on startup (devframe stays headless, so the host prints its own
34
34
  * banner). Defaults to the current code; the link is subject to the same TTL.
35
35
  *
36
36
  * The code rides the fragment (`#devframe_otp=…`), not the query string, so it
37
37
  * is never sent to the server, written to an access log, or leaked in a
38
- * `Referer` header — the browser client reads it locally (see
38
+ * `Referer` header; the browser client reads it locally (see
39
39
  * `consumeOtpFromUrl`). Any existing fragment parameters are preserved.
40
40
  */
41
41
  declare function buildOtpAuthUrl(baseUrl: string, code?: string): string;