devframe 0.7.16 → 0.8.1

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 (80) hide show
  1. package/bin/devframe.mjs +8 -0
  2. package/dist/adapters/build.d.mts +1 -1
  3. package/dist/adapters/build.mjs +4 -4
  4. package/dist/adapters/cac.d.mts +1 -1
  5. package/dist/adapters/cac.mjs +1 -1
  6. package/dist/adapters/cli.d.mts +1 -1
  7. package/dist/adapters/cli.mjs +1 -1
  8. package/dist/adapters/dev.d.mts +2 -2
  9. package/dist/adapters/dev.mjs +1 -1
  10. package/dist/adapters/embedded.d.mts +1 -1
  11. package/dist/adapters/mcp.d.mts +51 -3
  12. package/dist/adapters/mcp.mjs +2 -2
  13. package/dist/agent-tool-name-C3b5vEwJ.mjs +34 -0
  14. package/dist/{cac-CPaOy3LD.mjs → cac-B1LM3zit.mjs} +18 -13
  15. package/dist/cli/main.d.mts +11 -0
  16. package/dist/cli/main.mjs +284 -0
  17. package/dist/client/index.d.mts +40 -11
  18. package/dist/client/index.mjs +129 -19
  19. package/dist/constants.d.mts +13 -6
  20. package/dist/constants.mjs +13 -6
  21. package/dist/{context-DY72brRI.mjs → context-CQefP2jR.mjs} +3 -2
  22. package/dist/{context-CzqPrJSz.d.mts → context-DFzmxCLa.d.mts} +1 -1
  23. package/dist/{revoke-BtQDKTp7.mjs → crypto-token-XCqTSMg9.mjs} +1 -35
  24. package/dist/{dev-BCeaQuGE.mjs → dev-BSHFZGZr.mjs} +22 -11
  25. package/dist/{devframe-Ckhf3kFw.d.mts → devframe-qgCKL683.d.mts} +77 -15
  26. package/dist/diagnostics-B5-qHeqD.mjs +94 -0
  27. package/dist/{diagnostics-BXwBQmoN.mjs → diagnostics-hwjXp_UV.mjs} +8 -0
  28. package/dist/{dump-Cz7yVvsB.mjs → dump-CgZShDRB.mjs} +82 -6
  29. package/dist/fetch-CK0S253E.mjs +534 -0
  30. package/dist/helpers/vite.d.mts +15 -14
  31. package/dist/helpers/vite.mjs +8 -8
  32. package/dist/{host-h3-CgOetlNE.mjs → host-h3-Kz7t5Xab.mjs} +83 -28
  33. package/dist/http-Dvgxujcu.mjs +38 -0
  34. package/dist/{index-8dndvIxR.d.mts → index-B7RgLw--.d.mts} +11 -6
  35. package/dist/{index-DgsLFhZg.d.mts → index-Dbw1p5ch.d.mts} +27 -3
  36. package/dist/{index-YDSJgsyG.d.mts → index-vAX6bYuc.d.mts} +1 -1
  37. package/dist/index.d.mts +5 -5
  38. package/dist/instance-registry-D6fxYu36.mjs +190 -0
  39. package/dist/node/auth.d.mts +2 -2
  40. package/dist/node/auth.mjs +2 -2
  41. package/dist/node/hub-internals.d.mts +2 -2
  42. package/dist/node/hub-internals.mjs +1 -1
  43. package/dist/node/index.d.mts +124 -6
  44. package/dist/node/index.mjs +5 -4
  45. package/dist/recipes/common-rpc-functions.d.mts +33 -33
  46. package/dist/recipes/common-rpc-functions.mjs +6 -6
  47. package/dist/recipes/interactive-auth.d.mts +2 -2
  48. package/dist/recipes/interactive-auth.mjs +23 -15
  49. package/dist/revoke-DZbJ7Cl0.mjs +35 -0
  50. package/dist/rpc/dump.d.mts +1 -1
  51. package/dist/rpc/dump.mjs +1 -1
  52. package/dist/rpc/index.d.mts +3 -3
  53. package/dist/rpc/index.mjs +4 -4
  54. package/dist/rpc/transports/ws-client.d.mts +1 -1
  55. package/dist/rpc/transports/ws-client.mjs +1 -1
  56. package/dist/rpc/transports/ws-server.d.mts +2 -2
  57. package/dist/rpc/transports/ws-server.mjs +50 -3
  58. package/dist/{serialization-DpLXCy13.mjs → serialization-C8Mnw9hK.mjs} +1 -1
  59. package/dist/{server-DykHCza_.mjs → server-CXaDDUl0.mjs} +2 -2
  60. package/dist/{server-B0wiP_Oi.d.mts → server-E9z4ZWbd.d.mts} +4 -3
  61. package/dist/simple-schema-BDzLeJDk.d.mts +102 -0
  62. package/dist/simple-schema-DQPZrAaZ.mjs +154 -0
  63. package/dist/{state-WX3HT5a3.mjs → state-BeUHDDjk.mjs} +13 -6
  64. package/dist/{storage-gEnj9ASQ.mjs → storage-Dzoc3NVC.mjs} +2 -66
  65. package/dist/{transports-BmDVn4SF.mjs → transports-vhizgqXM.mjs} +1 -1
  66. package/dist/types/index.d.mts +4 -4
  67. package/dist/{types-CrzNxXKq.d.mts → types-CnJSgRVa.d.mts} +33 -19
  68. package/dist/utils/agent-tool-name.d.mts +27 -0
  69. package/dist/utils/agent-tool-name.mjs +34 -0
  70. package/dist/utils/events.d.mts +1 -1
  71. package/dist/utils/shared-state.d.mts +1 -1
  72. package/dist/utils/simple-schema.d.mts +2 -0
  73. package/dist/utils/simple-schema.mjs +154 -0
  74. package/dist/utils/streaming-channel.d.mts +1 -1
  75. package/dist/{ws-client-DSXiI2h7.d.mts → ws-client-B6Tnr0ic.d.mts} +1 -1
  76. package/dist/{ws-server-9-wn7MNQ.d.mts → ws-server-J-zkiOyp.d.mts} +24 -3
  77. package/package.json +18 -7
  78. package/skills/devframe/SKILL.md +4 -3
  79. package/dist/build-server-C7vTKjiQ.mjs +0 -359
  80. package/dist/http-_pPbryTQ.mjs +0 -114
@@ -1,8 +1,38 @@
1
- import { C as DevframeServicesHost, Ct as AgentResourceContent, Dt as DevframeAgentHost$1, Et as AgentToolInput, H as DevframeDiagnosticsHost$1, J as RpcSharedStateHost, K as RpcFunctionsHost, L as DevframeViewHost$1, O as DevframeSettings, Ot as DevframeAgentHostEvents, R as DevframeHost, S as DevframeServiceOf, St as AgentResource, T as DevframeScopedNodeContext, Tt as AgentTool, U as DevframeDiagnosticsLogger, Z as RpcStreamingHost, b as DevframeNodeContext, bt as AgentHandle, ht as SharedState, kt as EventEmitter, wt as AgentResourceInput, x as DevframeServiceId, xt as AgentManifest } from "../devframe-Ckhf3kFw.mjs";
2
- import { v as RpcFunctionDefinitionAny } from "../types-CrzNxXKq.mjs";
3
- import "../index-DgsLFhZg.mjs";
4
- import { n as StartedServer, r as startHttpAndWs, t as StartHttpAndWsOptions } from "../server-B0wiP_Oi.mjs";
1
+ import { At as DevframeAgentHostEvents, C as DevframeServicesHost, Ct as AgentResourceContent, Dt as AgentToolProvider, Et as AgentToolInput, H as DevframeDiagnosticsHost$1, J as RpcSharedStateHost, K as RpcFunctionsHost, L as DevframeViewHost$1, O as DevframeSettings, Ot as AgentToolProviderHandle, R as DevframeHost, S as DevframeServiceOf, St as AgentResource, T as DevframeScopedNodeContext, Tt as AgentTool, U as DevframeDiagnosticsLogger, Z as RpcStreamingHost, b as DevframeNodeContext, bt as AgentHandle, ht as SharedState, jt as EventEmitter, kt as DevframeAgentHost$1, wt as AgentResourceInput, x as DevframeServiceId, xt as AgentManifest } from "../devframe-qgCKL683.mjs";
2
+ import { v as RpcFunctionDefinitionAny } from "../types-CnJSgRVa.mjs";
3
+ import "../index-Dbw1p5ch.mjs";
4
+ import { n as StartedServer, r as startHttpAndWs, t as StartHttpAndWsOptions } from "../server-E9z4ZWbd.mjs";
5
5
  import { BirpcGroup } from "birpc";
6
+ //#region src/node/agent-args.d.ts
7
+ /**
8
+ * How {@link coerceAgentPositionalArgs} treats an args object that carries
9
+ * neither declared schemas nor `arg0`/`arg1`/… keys:
10
+ *
11
+ * - `'wrap'` — pass the object itself as the single positional argument.
12
+ * RPC-backed tools use this: an untyped RPC may take one raw object.
13
+ * - `'drop'` — call with zero arguments. Command-backed tools use this:
14
+ * a handler's positional parameters come solely from its declared
15
+ * `agent.args` schemas, so undeclared payload is ignored.
16
+ */
17
+ type AgentArgsFallback = 'wrap' | 'drop';
18
+ /**
19
+ * Map the args payload an agent surface receives (MCP sends an object
20
+ * keyed `arg0`/`arg1`/…, matching the schema the adapter advertises) onto
21
+ * a handler's positional parameters. Shared by the agent host's RPC
22
+ * bridge and the hub's command-derived tools so the coercion cannot
23
+ * drift between them.
24
+ *
25
+ * - an array passes through as-is
26
+ * - `null`/`undefined` become a zero-argument call
27
+ * - with declared schemas, each schema reads its own `argN` key, in order
28
+ * - without schemas, `arg0`/`arg1`/… keys are collected when present
29
+ * - an empty object becomes a zero-argument call
30
+ * - anything else follows the {@link AgentArgsFallback}
31
+ *
32
+ * @experimental
33
+ */
34
+ declare function coerceAgentPositionalArgs(args: unknown, schemas: readonly unknown[] | undefined, fallback?: AgentArgsFallback): unknown[];
35
+ //#endregion
6
36
  //#region src/node/context.d.ts
7
37
  interface CreateHostContextOptions {
8
38
  cwd: string;
@@ -40,10 +70,12 @@ declare class DevframeAgentHost implements DevframeAgentHost$1 {
40
70
  readonly events: EventEmitter<DevframeAgentHostEvents>;
41
71
  private readonly tools;
42
72
  private readonly resources;
73
+ private readonly providers;
43
74
  private _rpcUnsubscribe;
44
75
  constructor(context: DevframeNodeContext);
45
76
  registerTool(input: AgentToolInput): AgentHandle;
46
77
  unregisterTool(id: string): boolean;
78
+ registerToolProvider(provider: AgentToolProvider): AgentToolProviderHandle;
47
79
  registerResource(input: AgentResourceInput): AgentHandle;
48
80
  unregisterResource(id: string): boolean;
49
81
  list(): AgentManifest;
@@ -55,9 +87,10 @@ declare class DevframeAgentHost implements DevframeAgentHost$1 {
55
87
  _dispose(): void;
56
88
  private _validateToolId;
57
89
  private _projectTool;
90
+ /** Query every registered provider, projecting inputs to serializable tools. */
91
+ private _collectProviderTools;
58
92
  private _collectRpcTools;
59
93
  private _findRpcDefinition;
60
- private _coercePositionalArgs;
61
94
  }
62
95
  //#endregion
63
96
  //#region src/node/host-diagnostics.d.ts
@@ -135,6 +168,91 @@ declare class DevframeViewHost implements DevframeViewHost$1 {
135
168
  hostStatic(baseUrl: string, distDir: string): void;
136
169
  }
137
170
  //#endregion
171
+ //#region src/node/instance-registry.d.ts
172
+ /**
173
+ * One running devframe instance, as recorded in the instance registry.
174
+ * Records are self-describing JSON — additive fields are safe.
175
+ *
176
+ * @experimental The agent-native surface is experimental and may change
177
+ * without a major version bump until it stabilizes.
178
+ */
179
+ interface DevframeInstanceRecord {
180
+ /** Process id of the dev server. */
181
+ pid: number;
182
+ /** Listening port. */
183
+ port: number;
184
+ /** Dialable HTTP origin, e.g. `http://127.0.0.1:9876`. */
185
+ origin: string;
186
+ /** Base path the devframe is mounted at (trailing slash). */
187
+ basePath: string;
188
+ /** Definition id. */
189
+ id: string;
190
+ /** Definition display name. */
191
+ name?: string;
192
+ /** Working directory the instance was started from. */
193
+ rootDir: string;
194
+ /**
195
+ * Absolute URL path of the MCP Streamable-HTTP endpoint on `origin`, or
196
+ * `null` when the instance runs without an MCP route.
197
+ */
198
+ mcp: {
199
+ path: string;
200
+ } | null;
201
+ /** Epoch-ms timestamp of registration. */
202
+ startedAt: number;
203
+ }
204
+ /**
205
+ * Handle returned by {@link registerDevframeInstance}.
206
+ *
207
+ * @experimental
208
+ */
209
+ interface DevframeInstanceRegistration {
210
+ /** The registry file backing this registration. */
211
+ readonly file: string;
212
+ /** Remove the record (idempotent). Call on server close. */
213
+ unregister: () => void;
214
+ }
215
+ /**
216
+ * Record a running devframe instance in the global instance registry so
217
+ * discovery tooling (`devframe connect`, editor integrations) can find it
218
+ * without port guessing.
219
+ *
220
+ * `createDevServer` registers automatically; custom hosts that serve a
221
+ * devframe in-process (e.g. `@devframes/next`'s host inside a Next dev
222
+ * server) call this explicitly with the origin they are reachable at.
223
+ *
224
+ * The record is written atomically to `<dir>/<pid>-<port>.json` and removed
225
+ * by {@link DevframeInstanceRegistration.unregister}. Records surviving a
226
+ * crash are pruned by readers whose liveness probe fails. Registration never
227
+ * throws — a write failure degrades to a coded warning (`DF0045`), since a
228
+ * dev server must not die over discovery metadata.
229
+ *
230
+ * @experimental
231
+ */
232
+ declare function registerDevframeInstance(record: DevframeInstanceRecord, options?: {
233
+ instancesDir?: string;
234
+ }): DevframeInstanceRegistration;
235
+ /**
236
+ * Read the registry and split records into live and dead by probing each
237
+ * one's `__connection.json`, deleting dead records (prune-on-read). Live
238
+ * records carry the dialable origin the probe confirmed (a `localhost`
239
+ * record may come back as `127.0.0.1` / `[::1]`).
240
+ *
241
+ * A liveness probe only proves *something* answers on the record's port, so
242
+ * records left behind by killed processes shadow the server currently bound
243
+ * there: per `(port, basePath)` only the newest record survives, older
244
+ * ghosts are pruned with the dead.
245
+ *
246
+ * @experimental
247
+ */
248
+ declare function listLiveDevframeInstances(options?: {
249
+ instancesDir?: string;
250
+ timeoutMs?: number;
251
+ }): Promise<{
252
+ live: DevframeInstanceRecord[];
253
+ pruned: DevframeInstanceRecord[];
254
+ }>;
255
+ //#endregion
138
256
  //#region src/node/rpc-shared-state.d.ts
139
257
  declare function createRpcSharedStateServerHost(rpc: RpcFunctionsHost): RpcSharedStateHost;
140
258
  //#endregion
@@ -180,4 +298,4 @@ declare function toDialableHost(host: string): string;
180
298
  declare function formatHostForUrl(host: string): string;
181
299
  declare function normalizeHttpServerUrl(host: string, port: number | string): string;
182
300
  //#endregion
183
- export { CreateH3DevframeHostOptions, CreateHostContextOptions, CreateStorageOptions, DevframeAgentHost, DevframeDiagnosticsHost, DevframeServicesHostImpl, DevframeViewHost, type RpcFunctionsHost, StartHttpAndWsOptions, StartedServer, createH3DevframeHost, createHostContext, createNodeSettings, createRpcSharedStateServerHost, createRpcStreamingServerHost, createScopedNodeContext, createStorage, formatHostForUrl, isObject, normalizeHttpServerUrl, startHttpAndWs, toDialableHost };
301
+ export { AgentArgsFallback, CreateH3DevframeHostOptions, CreateHostContextOptions, CreateStorageOptions, DevframeAgentHost, DevframeDiagnosticsHost, type DevframeInstanceRecord, type DevframeInstanceRegistration, DevframeServicesHostImpl, DevframeViewHost, type RpcFunctionsHost, StartHttpAndWsOptions, StartedServer, coerceAgentPositionalArgs, createH3DevframeHost, createHostContext, createNodeSettings, createRpcSharedStateServerHost, createRpcStreamingServerHost, createScopedNodeContext, createStorage, formatHostForUrl, isObject, listLiveDevframeInstances, normalizeHttpServerUrl, registerDevframeInstance, startHttpAndWs, toDialableHost };
@@ -1,4 +1,5 @@
1
- import { t as createStorage } from "../storage-gEnj9ASQ.mjs";
2
- import { a as DevframeViewHost, c as createRpcSharedStateServerHost, i as createNodeSettings, l as DevframeDiagnosticsHost, n as createHostContext, o as DevframeServicesHostImpl, r as createScopedNodeContext, s as createRpcStreamingServerHost, t as createH3DevframeHost, u as DevframeAgentHost } from "../host-h3-CgOetlNE.mjs";
3
- import { a as toDialableHost, i as normalizeHttpServerUrl, n as formatHostForUrl, r as isObject, t as startHttpAndWs } from "../server-DykHCza_.mjs";
4
- export { DevframeAgentHost, DevframeDiagnosticsHost, DevframeServicesHostImpl, DevframeViewHost, createH3DevframeHost, createHostContext, createNodeSettings, createRpcSharedStateServerHost, createRpcStreamingServerHost, createScopedNodeContext, createStorage, formatHostForUrl, isObject, normalizeHttpServerUrl, startHttpAndWs, toDialableHost };
1
+ import { a as DevframeViewHost, c as createRpcSharedStateServerHost, d as coerceAgentPositionalArgs, i as createNodeSettings, l as DevframeDiagnosticsHost, n as createHostContext, o as DevframeServicesHostImpl, r as createScopedNodeContext, s as createRpcStreamingServerHost, t as createH3DevframeHost, u as DevframeAgentHost } from "../host-h3-Kz7t5Xab.mjs";
2
+ import { t as createStorage } from "../storage-Dzoc3NVC.mjs";
3
+ import { r as registerDevframeInstance, t as listLiveDevframeInstances } from "../instance-registry-D6fxYu36.mjs";
4
+ import { a as toDialableHost, i as normalizeHttpServerUrl, n as formatHostForUrl, r as isObject, t as startHttpAndWs } from "../server-CXaDDUl0.mjs";
5
+ export { DevframeAgentHost, DevframeDiagnosticsHost, DevframeServicesHostImpl, DevframeViewHost, coerceAgentPositionalArgs, createH3DevframeHost, createHostContext, createNodeSettings, createRpcSharedStateServerHost, createRpcStreamingServerHost, createScopedNodeContext, createStorage, formatHostForUrl, isObject, listLiveDevframeInstances, normalizeHttpServerUrl, registerDevframeInstance, startHttpAndWs, toDialableHost };
@@ -1,7 +1,7 @@
1
- import "../devframe-Ckhf3kFw.mjs";
2
- import { E as Thenable, S as RpcFunctionSetupResult, c as RpcDump, g as RpcFunctionAgentOptions } from "../types-CrzNxXKq.mjs";
3
- import "../index-DgsLFhZg.mjs";
4
- import * as v from "valibot";
1
+ import "../devframe-qgCKL683.mjs";
2
+ import { E as Thenable, S as RpcFunctionSetupResult, c as RpcDump, g as RpcFunctionAgentOptions } from "../types-CnJSgRVa.mjs";
3
+ import "../index-Dbw1p5ch.mjs";
4
+ import { t as SimpleSchema } from "../simple-schema-BDzLeJDk.mjs";
5
5
  //#region src/recipes/common-rpc-functions.d.ts
6
6
  /**
7
7
  * Editor commands that `launch-editor` (the library behind
@@ -11,7 +11,7 @@ import * as v from "valibot";
11
11
  * arbitrary command.
12
12
  */
13
13
  type KnownEditor = 'atom' | 'subl' | 'sublime' | 'sublime_text' | 'wstorm' | 'charm' | 'zed' | 'notepad++' | 'vim' | 'mvim' | 'joe' | 'gvim' | 'emacs' | 'emacsclient' | 'rmate' | 'mate' | 'code' | 'code-insiders' | 'codium' | 'vscodium' | 'trae' | 'antigravity' | 'cursor' | 'appcode' | 'clion' | 'idea' | 'phpstorm' | 'pycharm' | 'rubymine' | 'webstorm' | 'goland' | 'rider';
14
- /** Runtime list of every {@link KnownEditor}, in the order `v.picklist` reports them. */
14
+ /** Runtime list of every {@link KnownEditor}. */
15
15
  declare const KNOWN_EDITORS: KnownEditor[];
16
16
  /**
17
17
  * Prebuilt RPC action that opens a file in the user's configured editor.
@@ -38,16 +38,16 @@ declare const openInEditor: {
38
38
  name: "devframe:open-in-editor";
39
39
  type?: "action" | undefined;
40
40
  cacheable?: boolean;
41
- args: readonly [v.StringSchema<undefined>, v.OptionalSchema<v.PicklistSchema<KnownEditor[], undefined>, undefined>];
42
- returns: v.VoidSchema<undefined>;
41
+ args: readonly [SimpleSchema<string, string>, SimpleSchema<KnownEditor | undefined, KnownEditor | undefined>];
42
+ returns: SimpleSchema<void, void>;
43
43
  jsonSerializable?: boolean;
44
44
  agent?: RpcFunctionAgentOptions;
45
- setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], void>>) | undefined;
46
- handler?: ((args_0: string, args_1: KnownEditor | undefined) => void) | undefined;
47
- dump?: RpcDump<[string, KnownEditor | undefined], void, undefined> | undefined;
45
+ setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], Thenable<void>>>) | undefined;
46
+ handler?: ((args_0: string, args_1: KnownEditor | undefined) => Thenable<void>) | undefined;
47
+ dump?: RpcDump<[string, KnownEditor | undefined], Thenable<void>, undefined> | undefined;
48
48
  snapshot?: boolean;
49
- __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], void>>> | undefined;
50
- __promise?: Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], void>> | undefined;
49
+ __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], Thenable<void>>>> | undefined;
50
+ __promise?: Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], Thenable<void>>> | undefined;
51
51
  };
52
52
  /**
53
53
  * Prebuilt RPC action that reveals a path in the OS file explorer.
@@ -64,16 +64,16 @@ declare const openInFinder: {
64
64
  name: "devframe:open-in-finder";
65
65
  type?: "action" | undefined;
66
66
  cacheable?: boolean;
67
- args: readonly [v.StringSchema<undefined>];
68
- returns: v.VoidSchema<undefined>;
67
+ args: readonly [SimpleSchema<string, string>];
68
+ returns: SimpleSchema<void, void>;
69
69
  jsonSerializable?: boolean;
70
70
  agent?: RpcFunctionAgentOptions;
71
- setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string], void>>) | undefined;
72
- handler?: ((args_0: string) => void) | undefined;
73
- dump?: RpcDump<[string], void, undefined> | undefined;
71
+ setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string], Thenable<void>>>) | undefined;
72
+ handler?: ((args_0: string) => Thenable<void>) | undefined;
73
+ dump?: RpcDump<[string], Thenable<void>, undefined> | undefined;
74
74
  snapshot?: boolean;
75
- __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string], void>>> | undefined;
76
- __promise?: Thenable<RpcFunctionSetupResult<[string], void>> | undefined;
75
+ __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string], Thenable<void>>>> | undefined;
76
+ __promise?: Thenable<RpcFunctionSetupResult<[string], Thenable<void>>> | undefined;
77
77
  };
78
78
  /**
79
79
  * Convenience array bundling both helpers so callers can register them
@@ -89,30 +89,30 @@ declare const commonRpcFunctions: readonly [{
89
89
  name: "devframe:open-in-editor";
90
90
  type?: "action" | undefined;
91
91
  cacheable?: boolean;
92
- args: readonly [v.StringSchema<undefined>, v.OptionalSchema<v.PicklistSchema<KnownEditor[], undefined>, undefined>];
93
- returns: v.VoidSchema<undefined>;
92
+ args: readonly [SimpleSchema<string, string>, SimpleSchema<KnownEditor | undefined, KnownEditor | undefined>];
93
+ returns: SimpleSchema<void, void>;
94
94
  jsonSerializable?: boolean;
95
95
  agent?: RpcFunctionAgentOptions;
96
- setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], void>>) | undefined;
97
- handler?: ((args_0: string, args_1: KnownEditor | undefined) => void) | undefined;
98
- dump?: RpcDump<[string, KnownEditor | undefined], void, undefined> | undefined;
96
+ setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], Thenable<void>>>) | undefined;
97
+ handler?: ((args_0: string, args_1: KnownEditor | undefined) => Thenable<void>) | undefined;
98
+ dump?: RpcDump<[string, KnownEditor | undefined], Thenable<void>, undefined> | undefined;
99
99
  snapshot?: boolean;
100
- __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], void>>> | undefined;
101
- __promise?: Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], void>> | undefined;
100
+ __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], Thenable<void>>>> | undefined;
101
+ __promise?: Thenable<RpcFunctionSetupResult<[string, KnownEditor | undefined], Thenable<void>>> | undefined;
102
102
  }, {
103
103
  name: "devframe:open-in-finder";
104
104
  type?: "action" | undefined;
105
105
  cacheable?: boolean;
106
- args: readonly [v.StringSchema<undefined>];
107
- returns: v.VoidSchema<undefined>;
106
+ args: readonly [SimpleSchema<string, string>];
107
+ returns: SimpleSchema<void, void>;
108
108
  jsonSerializable?: boolean;
109
109
  agent?: RpcFunctionAgentOptions;
110
- setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string], void>>) | undefined;
111
- handler?: ((args_0: string) => void) | undefined;
112
- dump?: RpcDump<[string], void, undefined> | undefined;
110
+ setup?: ((context: undefined) => Thenable<RpcFunctionSetupResult<[string], Thenable<void>>>) | undefined;
111
+ handler?: ((args_0: string) => Thenable<void>) | undefined;
112
+ dump?: RpcDump<[string], Thenable<void>, undefined> | undefined;
113
113
  snapshot?: boolean;
114
- __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string], void>>> | undefined;
115
- __promise?: Thenable<RpcFunctionSetupResult<[string], void>> | undefined;
114
+ __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<[string], Thenable<void>>>> | undefined;
115
+ __promise?: Thenable<RpcFunctionSetupResult<[string], Thenable<void>>> | undefined;
116
116
  }];
117
117
  //#endregion
118
118
  export { KNOWN_EDITORS, KnownEditor, commonRpcFunctions, openInEditor, openInFinder };
@@ -1,7 +1,7 @@
1
1
  import { n as defineRpcFunction } from "../define-BLWPsH6y.mjs";
2
- import * as v from "valibot";
2
+ import { t as s } from "../simple-schema-DQPZrAaZ.mjs";
3
3
  //#region src/recipes/common-rpc-functions.ts
4
- /** Runtime list of every {@link KnownEditor}, in the order `v.picklist` reports them. */
4
+ /** Runtime list of every {@link KnownEditor}. */
5
5
  const KNOWN_EDITORS = [
6
6
  "atom",
7
7
  "subl",
@@ -61,8 +61,8 @@ const openInEditor = defineRpcFunction({
61
61
  name: "devframe:open-in-editor",
62
62
  type: "action",
63
63
  jsonSerializable: true,
64
- args: [v.string(), v.optional(v.picklist(KNOWN_EDITORS))],
65
- returns: v.void(),
64
+ args: [s.string(), s.optional(s.picklist(KNOWN_EDITORS))],
65
+ returns: s.void(),
66
66
  async handler(filename, editor) {
67
67
  const { launchEditor } = await import("../utils/launch-editor.mjs");
68
68
  launchEditor(filename, editor);
@@ -83,8 +83,8 @@ const openInFinder = defineRpcFunction({
83
83
  name: "devframe:open-in-finder",
84
84
  type: "action",
85
85
  jsonSerializable: true,
86
- args: [v.string()],
87
- returns: v.void(),
86
+ args: [s.string()],
87
+ returns: s.void(),
88
88
  async handler(path) {
89
89
  const { open } = await import("../utils/open.mjs");
90
90
  await open(path);
@@ -1,5 +1,5 @@
1
- import { b as DevframeNodeContext, p as DevframeAuthHandler } from "../devframe-Ckhf3kFw.mjs";
2
- import "../index-8dndvIxR.mjs";
1
+ import { b as DevframeNodeContext, p as DevframeAuthHandler } from "../devframe-qgCKL683.mjs";
2
+ import "../index-B7RgLw--.mjs";
3
3
  //#region src/recipes/interactive-auth.d.ts
4
4
  interface CreateInteractiveAuthOptions {
5
5
  /**
@@ -1,9 +1,9 @@
1
1
  import { n as colors } from "../diagnostics-reporter-CsIG85Q5.mjs";
2
2
  import { isAnonymousRpcMethod } from "../constants.mjs";
3
3
  import { n as defineRpcFunction } from "../define-BLWPsH6y.mjs";
4
- import { t as getInternalContext } from "../context-DY72brRI.mjs";
5
- import { a as verifyAuthToken, n as exchangeTempAuthCode, r as getTempAuthCode, t as buildOtpAuthUrl } from "../state-WX3HT5a3.mjs";
6
- import * as v from "valibot";
4
+ import { t as getInternalContext } from "../context-CQefP2jR.mjs";
5
+ import { a as verifyAuthToken, n as exchangeTempAuthCode, r as getTempAuthCode, t as buildOtpAuthUrl } from "../state-BeUHDDjk.mjs";
6
+ import { t as s } from "../simple-schema-DQPZrAaZ.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`);
@@ -54,12 +54,12 @@ function createInteractiveAuth(context, options = {}) {
54
54
  name: "anonymous:devframe:auth",
55
55
  type: "action",
56
56
  jsonSerializable: true,
57
- args: [v.object({
58
- authToken: v.string(),
59
- ua: v.string(),
60
- origin: v.string()
57
+ args: [s.object({
58
+ authToken: s.string(),
59
+ ua: s.string(),
60
+ origin: s.string()
61
61
  })],
62
- returns: v.object({ isTrusted: v.boolean() }),
62
+ returns: s.object({ isTrusted: s.boolean() }),
63
63
  handler(params) {
64
64
  const session = context.rpc.getCurrentRpcSession();
65
65
  if (!session) return { isTrusted: false };
@@ -76,12 +76,12 @@ function createInteractiveAuth(context, options = {}) {
76
76
  name: "anonymous:devframe:auth:exchange",
77
77
  type: "action",
78
78
  jsonSerializable: true,
79
- args: [v.object({
80
- code: v.string(),
81
- ua: v.string(),
82
- origin: v.string()
79
+ args: [s.object({
80
+ code: s.string(),
81
+ ua: s.string(),
82
+ origin: s.string()
83
83
  })],
84
- returns: v.object({ authToken: v.nullable(v.string()) }),
84
+ returns: s.object({ authToken: s.nullable(s.string()) }),
85
85
  handler(params) {
86
86
  const session = context.rpc.getCurrentRpcSession();
87
87
  if (!session) return { authToken: null };
@@ -95,7 +95,7 @@ function createInteractiveAuth(context, options = {}) {
95
95
  type: "action",
96
96
  jsonSerializable: true,
97
97
  args: [],
98
- returns: v.void(),
98
+ returns: s.void(),
99
99
  async handler() {
100
100
  const token = context.rpc.getCurrentRpcSession()?.meta.clientAuthToken;
101
101
  if (token) await internal.revokeAuthToken(token);
@@ -107,16 +107,24 @@ function createInteractiveAuth(context, options = {}) {
107
107
  }
108
108
  function onConnect(peer, session) {
109
109
  let token;
110
+ let requestOrigin;
110
111
  try {
111
112
  token = new URL(peer.request?.url ?? "", "http://localhost").searchParams.get("devframe_auth_token") ?? void 0;
112
113
  } catch {}
114
+ try {
115
+ requestOrigin = peer.request?.headers?.get?.("origin") ?? void 0;
116
+ } catch {}
113
117
  if (!token) return;
114
118
  if (isStaticToken(token)) {
115
119
  session.meta.clientAuthToken = token;
116
120
  session.meta.isTrusted = true;
117
121
  return;
118
122
  }
119
- verifyAuthToken(token, session, storage);
123
+ if (verifyAuthToken(token, session, storage)) return;
124
+ if (internal.isRemoteTokenTrusted(token, requestOrigin)) {
125
+ session.meta.clientAuthToken = token;
126
+ session.meta.isTrusted = true;
127
+ }
120
128
  }
121
129
  function buildOpenUrl(url) {
122
130
  return buildOtpAuthUrl(url);
@@ -0,0 +1,35 @@
1
+ //#region src/node/auth/revoke.ts
2
+ /**
3
+ * Flip `isTrusted` to false on any live WS clients connected with `token`
4
+ * and broadcast the `auth:revoked` event so they can react.
5
+ *
6
+ * Shared between persisted-auth revocation and remote-dock token revocation.
7
+ */
8
+ async function revokeActiveConnectionsForToken(context, token) {
9
+ const rpcHost = context.rpc;
10
+ if (!rpcHost?._rpcGroup) return;
11
+ const affectedSessionIds = /* @__PURE__ */ new Set();
12
+ for (const client of rpcHost._rpcGroup.clients) if (client.$meta.clientAuthToken === token) {
13
+ affectedSessionIds.add(client.$meta.id);
14
+ client.$meta.isTrusted = false;
15
+ client.$meta.clientAuthToken = void 0;
16
+ }
17
+ if (affectedSessionIds.size === 0) return;
18
+ await rpcHost.broadcast({
19
+ method: "devframe:auth:revoked",
20
+ args: [],
21
+ filter: (client) => affectedSessionIds.has(client.$meta.id)
22
+ });
23
+ }
24
+ /**
25
+ * Revoke an auth token: remove from storage and notify all connected clients
26
+ * using this token that they are no longer trusted.
27
+ */
28
+ async function revokeAuthToken(context, storage, token) {
29
+ storage.mutate((state) => {
30
+ delete state.trusted[token];
31
+ });
32
+ await revokeActiveConnectionsForToken(context, token);
33
+ }
34
+ //#endregion
35
+ export { revokeAuthToken as n, revokeActiveConnectionsForToken as t };
@@ -1,2 +1,2 @@
1
- import { a as getDefinitionsWithDumps, c as StaticRpcDumpManifest, d as StaticRpcDumpManifestValue, f as StaticRpcDumpSerialization, i as dumpFunctions, l as StaticRpcDumpManifestQueryEntry, n as serializeDumpError, o as StaticRpcDumpCollection, p as collectStaticRpcDump, r as createClientFromDump, s as StaticRpcDumpFile, t as reviveDumpError, u as StaticRpcDumpManifestStaticEntry } from "../index-YDSJgsyG.mjs";
1
+ import { a as getDefinitionsWithDumps, c as StaticRpcDumpManifest, d as StaticRpcDumpManifestValue, f as StaticRpcDumpSerialization, i as dumpFunctions, l as StaticRpcDumpManifestQueryEntry, n as serializeDumpError, o as StaticRpcDumpCollection, p as collectStaticRpcDump, r as createClientFromDump, s as StaticRpcDumpFile, t as reviveDumpError, u as StaticRpcDumpManifestStaticEntry } from "../index-vAX6bYuc.mjs";
2
2
  export { StaticRpcDumpCollection, StaticRpcDumpFile, StaticRpcDumpManifest, StaticRpcDumpManifestQueryEntry, StaticRpcDumpManifestStaticEntry, StaticRpcDumpManifestValue, StaticRpcDumpSerialization, collectStaticRpcDump, createClientFromDump, dumpFunctions, getDefinitionsWithDumps, reviveDumpError, serializeDumpError };
package/dist/rpc/dump.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as dumpFunctions, c as serializeDumpError, i as createClientFromDump, o as getDefinitionsWithDumps, s as reviveDumpError, t as collectStaticRpcDump } from "../dump-Cz7yVvsB.mjs";
1
+ import { c as getDefinitionsWithDumps, l as reviveDumpError, o as createClientFromDump, s as dumpFunctions, t as collectStaticRpcDump, u as serializeDumpError } from "../dump-CgZShDRB.mjs";
2
2
  export { collectStaticRpcDump, createClientFromDump, dumpFunctions, getDefinitionsWithDumps, reviveDumpError, serializeDumpError };
@@ -1,3 +1,3 @@
1
- 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-CrzNxXKq.mjs";
2
- import { C as RpcCacheManager, S as RpcFunctionsCollectorBase, _ as strictJsonStringify, a as StaticRpcDumpManifestStaticEntry, b as createDefineWrapperWithContext, c as collectStaticRpcDump, d as getDefinitionsWithDumps, f as reviveDumpError, g as STRUCTURED_CLONE_PREFIX, h as validateDefinitions, i as StaticRpcDumpManifestQueryEntry, l as createClientFromDump, m as validateDefinition, n as StaticRpcDumpFile, o as StaticRpcDumpManifestValue, p as serializeDumpError, r as StaticRpcDumpManifest, s as StaticRpcDumpSerialization, t as StaticRpcDumpCollection, u as dumpFunctions, v as getRpcHandler, w as RpcCacheOptions, x as defineRpcFunction, y as getRpcResolvedSetupResult } from "../index-DgsLFhZg.mjs";
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, StaticRpcDumpCollection, StaticRpcDumpFile, StaticRpcDumpManifest, StaticRpcDumpManifestQueryEntry, StaticRpcDumpManifestStaticEntry, StaticRpcDumpManifestValue, StaticRpcDumpSerialization, Thenable, collectStaticRpcDump, createClientFromDump, createDefineWrapperWithContext, defineRpcFunction, dumpFunctions, getDefinitionsWithDumps, getRpcHandler, getRpcResolvedSetupResult, reviveDumpError, serializeDumpError, strictJsonStringify, validateDefinition, validateDefinitions };
1
+ 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-CnJSgRVa.mjs";
2
+ import { C as defineRpcFunction, E as RpcCacheOptions, S as createDefineWrapperWithContext, T as RpcCacheManager, _ as validateRpcReturn, a as StaticRpcDumpManifestStaticEntry, b as getRpcHandler, c as collectStaticRpcDump, d as getDefinitionsWithDumps, f as reviveDumpError, g as validateRpcArgs, h as validateDefinitions, i as StaticRpcDumpManifestQueryEntry, l as createClientFromDump, m as validateDefinition, n as StaticRpcDumpFile, o as StaticRpcDumpManifestValue, p as serializeDumpError, r as StaticRpcDumpManifest, s as StaticRpcDumpSerialization, t as StaticRpcDumpCollection, u as dumpFunctions, v as STRUCTURED_CLONE_PREFIX, w as RpcFunctionsCollectorBase, x as getRpcResolvedSetupResult, y as strictJsonStringify } from "../index-Dbw1p5ch.mjs";
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, StaticRpcDumpCollection, StaticRpcDumpFile, StaticRpcDumpManifest, StaticRpcDumpManifestQueryEntry, StaticRpcDumpManifestStaticEntry, StaticRpcDumpManifestValue, StaticRpcDumpSerialization, Thenable, collectStaticRpcDump, createClientFromDump, createDefineWrapperWithContext, defineRpcFunction, dumpFunctions, getDefinitionsWithDumps, getRpcHandler, getRpcResolvedSetupResult, reviveDumpError, serializeDumpError, strictJsonStringify, validateDefinition, validateDefinitions, validateRpcArgs, validateRpcReturn };
@@ -1,7 +1,7 @@
1
- import { a as dumpFunctions$1, c as serializeDumpError$1, d as hash, i as createClientFromDump$1, l as validateDefinition, n as getRpcHandler, o as getDefinitionsWithDumps$1, r as getRpcResolvedSetupResult, s as reviveDumpError$1, t as collectStaticRpcDump$1, u as validateDefinitions } from "../dump-Cz7yVvsB.mjs";
2
- import { t as diagnostics } from "../diagnostics-BXwBQmoN.mjs";
1
+ import { a as validateRpcReturn, c as getDefinitionsWithDumps$1, d as validateDefinition, f as validateDefinitions, i as validateRpcArgs, l as reviveDumpError$1, n as getRpcHandler, o as createClientFromDump$1, p as hash, r as getRpcResolvedSetupResult, s as dumpFunctions$1, t as collectStaticRpcDump$1, u as serializeDumpError$1 } from "../dump-CgZShDRB.mjs";
2
+ import { t as diagnostics } from "../diagnostics-hwjXp_UV.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-DpLXCy13.mjs";
4
+ import { n as strictJsonStringify, t as STRUCTURED_CLONE_PREFIX } from "../serialization-C8Mnw9hK.mjs";
5
5
  //#region src/rpc/cache.ts
6
6
  /**
7
7
  * @experimental API is expected to change.
@@ -130,4 +130,4 @@ const reviveDumpError = reviveDumpError$1;
130
130
  /** @deprecated Import from `devframe/rpc/dump` instead. */
131
131
  const serializeDumpError = serializeDumpError$1;
132
132
  //#endregion
133
- export { RpcCacheManager, RpcFunctionsCollectorBase, STRUCTURED_CLONE_PREFIX, collectStaticRpcDump, createClientFromDump, createDefineWrapperWithContext, defineRpcFunction, dumpFunctions, getDefinitionsWithDumps, getRpcHandler, getRpcResolvedSetupResult, reviveDumpError, serializeDumpError, strictJsonStringify, validateDefinition, validateDefinitions };
133
+ export { RpcCacheManager, RpcFunctionsCollectorBase, STRUCTURED_CLONE_PREFIX, collectStaticRpcDump, createClientFromDump, createDefineWrapperWithContext, defineRpcFunction, dumpFunctions, getDefinitionsWithDumps, getRpcHandler, getRpcResolvedSetupResult, reviveDumpError, serializeDumpError, strictJsonStringify, validateDefinition, validateDefinitions, validateRpcArgs, validateRpcReturn };
@@ -1,2 +1,2 @@
1
- import { n as createWsRpcChannel, t as WsRpcChannelOptions } from "../../ws-client-DSXiI2h7.mjs";
1
+ import { n as createWsRpcChannel, t as WsRpcChannelOptions } from "../../ws-client-B6Tnr0ic.mjs";
2
2
  export { WsRpcChannelOptions, createWsRpcChannel };
@@ -1,5 +1,5 @@
1
1
  import { DEVFRAME_AUTH_TOKEN_QUERY_PARAM } from "../../constants.mjs";
2
- import { n as strictJsonStringify } from "../../serialization-DpLXCy13.mjs";
2
+ import { n as strictJsonStringify } from "../../serialization-C8Mnw9hK.mjs";
3
3
  import { n as structuredCloneStringify, t as structuredCloneParse } from "../../structured-clone-CbAV5rFI.mjs";
4
4
  //#region src/rpc/transports/ws-client.ts
5
5
  function NOOP() {}
@@ -1,2 +1,2 @@
1
- import { a as isAllowedOrigin, i as attachWsRpcTransport, n as WsRpcTransport, o as isLoopbackHostname, r as WsRpcTransportOptions, t as DevframeNodeRpcSessionMeta } from "../../ws-server-9-wn7MNQ.mjs";
2
- export { DevframeNodeRpcSessionMeta, WsRpcTransport, WsRpcTransportOptions, attachWsRpcTransport, isAllowedOrigin, isLoopbackHostname };
1
+ import { a as WsRpcTransportOptions, c as isAllowedOrigin, i as WsRpcTransport, l as isLoopbackHostname, n as DevframeNodeRpcSessionMeta, o as attachWsRpcTransport, r as WsOriginRegistry, s as createWsOriginRegistry, t as CreateWsOriginRegistryOptions } from "../../ws-server-J-zkiOyp.mjs";
2
+ export { CreateWsOriginRegistryOptions, DevframeNodeRpcSessionMeta, WsOriginRegistry, WsRpcTransport, WsRpcTransportOptions, attachWsRpcTransport, createWsOriginRegistry, isAllowedOrigin, isLoopbackHostname };
@@ -1,9 +1,52 @@
1
- import { n as strictJsonStringify } from "../../serialization-DpLXCy13.mjs";
1
+ import "../../constants.mjs";
2
+ import { n as strictJsonStringify } from "../../serialization-C8Mnw9hK.mjs";
2
3
  import { n as structuredCloneStringify, t as structuredCloneParse } from "../../structured-clone-CbAV5rFI.mjs";
4
+ import { n as randomToken, r as timingSafeEqual } from "../../crypto-token-XCqTSMg9.mjs";
3
5
  import { createServer } from "node:http";
4
6
  import { createServer as createServer$1 } from "node:https";
5
7
  import crossws from "crossws/adapters/node";
6
8
  //#region src/rpc/transports/ws-server.ts
9
+ /**
10
+ * Create a live, token-protected origin allowlist for external browser
11
+ * viewers. Pass it to {@link WsRpcTransportOptions.allowedOrigins}, then use
12
+ * `registerFromUrl()` in the connection metadata handler to authorize a
13
+ * viewer without sharing a mutable array or disabling DNS-rebinding protection.
14
+ */
15
+ function createWsOriginRegistry(options = {}) {
16
+ const token = randomToken();
17
+ const origins = new Set(options.allowedOrigins ?? []);
18
+ function normalizeOrigin(origin) {
19
+ if (!origin) return;
20
+ try {
21
+ const url = new URL(origin);
22
+ const normalized = url.origin === "null" ? `${url.protocol}//${url.host}` : url.origin;
23
+ return origin === normalized ? normalized : void 0;
24
+ } catch {}
25
+ }
26
+ function registerOrigin(origin, candidateToken) {
27
+ const normalized = normalizeOrigin(origin);
28
+ if (!normalized || !candidateToken || !timingSafeEqual(token, candidateToken)) return false;
29
+ if (options.validateOrigin && !options.validateOrigin(normalized)) return false;
30
+ origins.add(normalized);
31
+ return true;
32
+ }
33
+ return {
34
+ token,
35
+ registerFromUrl(url) {
36
+ let parsed;
37
+ try {
38
+ parsed = new URL(url, "http://localhost");
39
+ } catch {
40
+ return;
41
+ }
42
+ const origin = parsed.searchParams.get("devframe_viewer_origin") ?? void 0;
43
+ return registerOrigin(origin, parsed.searchParams.get("devframe_viewer_origin_token") ?? void 0) ? origin : void 0;
44
+ },
45
+ isAllowed(origin) {
46
+ return isAllowedOrigin(origin, [...origins]);
47
+ }
48
+ };
49
+ }
7
50
  let sessionId = 0;
8
51
  const EMPTY_DEFS = /* @__PURE__ */ new Map();
9
52
  function NOOP() {}
@@ -32,6 +75,9 @@ function isAllowedOrigin(origin, allowedOrigins) {
32
75
  return false;
33
76
  }
34
77
  }
78
+ function isWsOriginRegistry(value) {
79
+ return !!value && !Array.isArray(value);
80
+ }
35
81
  /**
36
82
  * Route `upgrade` events on a server to the crossws adapter, optionally
37
83
  * filtered to a single `path`. Non-matching requests are left untouched so
@@ -55,7 +101,8 @@ function routeUpgrades(server, ws, path, destroyUnmatched, allowedOrigins) {
55
101
  return;
56
102
  }
57
103
  }
58
- if (allowedOrigins !== false && !isAllowedOrigin(req.headers.origin, allowedOrigins ?? [])) {
104
+ const originAllowed = isWsOriginRegistry(allowedOrigins) ? allowedOrigins.isAllowed(req.headers.origin) : isAllowedOrigin(req.headers.origin, allowedOrigins || []);
105
+ if (allowedOrigins !== false && !originAllowed) {
59
106
  socket.write("HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n");
60
107
  socket.destroy();
61
108
  return;
@@ -164,4 +211,4 @@ function attachWsRpcTransport(rpcGroup, options = {}) {
164
211
  };
165
212
  }
166
213
  //#endregion
167
- export { attachWsRpcTransport, isAllowedOrigin, isLoopbackHostname };
214
+ export { attachWsRpcTransport, createWsOriginRegistry, isAllowedOrigin, isLoopbackHostname };
@@ -1,4 +1,4 @@
1
- import { t as diagnostics } from "./diagnostics-BXwBQmoN.mjs";
1
+ import { t as diagnostics } from "./diagnostics-hwjXp_UV.mjs";
2
2
  //#region src/rpc/serialization.ts
3
3
  /**
4
4
  * Wire format used by the WS RPC transport.
@@ -1,7 +1,7 @@
1
1
  import { createRpcServer } from "./rpc/server.mjs";
2
2
  import { attachWsRpcTransport } from "./rpc/transports/ws-server.mjs";
3
- import { a as diagnostics } from "./storage-gEnj9ASQ.mjs";
4
- import { t as getInternalContext } from "./context-DY72brRI.mjs";
3
+ import { t as diagnostics } from "./diagnostics-B5-qHeqD.mjs";
4
+ import { t as getInternalContext } from "./context-CQefP2jR.mjs";
5
5
  import { createServer } from "node:http";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  import { H3, toNodeHandler } from "h3";