devframe 0.6.0-beta.2 → 0.6.0-beta.3

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 (58) hide show
  1. package/dist/adapters/build.d.mts +1 -1
  2. package/dist/adapters/build.mjs +2 -2
  3. package/dist/adapters/cli.d.mts +1 -1
  4. package/dist/adapters/cli.mjs +1 -1
  5. package/dist/adapters/dev.d.mts +2 -2
  6. package/dist/adapters/dev.mjs +1 -1
  7. package/dist/adapters/embedded.d.mts +1 -1
  8. package/dist/adapters/mcp.d.mts +1 -1
  9. package/dist/adapters/mcp.mjs +3 -3
  10. package/dist/client/index.d.mts +2 -2
  11. package/dist/client/index.mjs +56 -22
  12. package/dist/constants.d.mts +24 -1
  13. package/dist/constants.mjs +26 -1
  14. package/dist/{context-BEVByy_Z.d.mts → context-B_I9fMBc.d.mts} +1 -1
  15. package/dist/{context-3x_bgBgZ.mjs → context-CKJheEtf.mjs} +2 -2
  16. package/dist/{dev-BaX8fLH2.mjs → dev-DSxKFn-v.mjs} +4 -4
  17. package/dist/{devframe-D-gr9sBx.d.mts → devframe-DgvncQy2.d.mts} +19 -3
  18. package/dist/{dump-DoXkj4ku.mjs → dump-D09PZb7T.mjs} +14 -4
  19. package/dist/{hash-DFc5WwhO.mjs → hash-PAfnyu2k.mjs} +1 -1
  20. package/dist/helpers/vite.d.mts +1 -1
  21. package/dist/helpers/vite.mjs +2 -2
  22. package/dist/{host-h3-C5SZlk03.mjs → host-h3-Dsf-Tgwx.mjs} +37 -11
  23. package/dist/index-B4lNDq5v.d.mts +107 -0
  24. package/dist/{index-CxaPKDXX.d.mts → index-Dy6GFDRf.d.mts} +1 -0
  25. package/dist/index.d.mts +2 -2
  26. package/dist/{launch-editor-DPfltGA4.mjs → launch-editor-DIzaS5EG.mjs} +58 -43
  27. package/dist/node/auth.d.mts +2 -64
  28. package/dist/node/auth.mjs +2 -100
  29. package/dist/node/hub-internals.d.mts +2 -2
  30. package/dist/node/hub-internals.mjs +1 -1
  31. package/dist/node/index.d.mts +3 -3
  32. package/dist/node/index.mjs +3 -3
  33. package/dist/recipes/interactive-auth.d.mts +53 -0
  34. package/dist/recipes/interactive-auth.mjs +132 -0
  35. package/dist/recipes/open-helpers.mjs +2 -2
  36. package/dist/{revoke-ENfxWkFK.mjs → revoke-BtQDKTp7.mjs} +1 -1
  37. package/dist/rpc/dump.mjs +1 -1
  38. package/dist/rpc/index.d.mts +2 -2
  39. package/dist/rpc/index.mjs +4 -1
  40. package/dist/rpc/transports/ws-client.mjs +21 -8
  41. package/dist/{server-Dl6TU5LE.mjs → server-BdN41ckC.mjs} +36 -4
  42. package/dist/{server-rX781kz-.d.mts → server-DXPq8q0K.d.mts} +40 -9
  43. package/dist/{shared-state-D4PPieA0.mjs → shared-state-QtMas0NG.mjs} +34 -4
  44. package/dist/state-WX3HT5a3.mjs +101 -0
  45. package/dist/{storage-l2ezeend.mjs → storage-yrUZaiib.mjs} +55 -6
  46. package/dist/types/index.d.mts +2 -2
  47. package/dist/utils/crypto-token.mjs +1 -1
  48. package/dist/utils/events.d.mts +1 -1
  49. package/dist/utils/hash.mjs +1 -1
  50. package/dist/utils/launch-editor.mjs +1 -1
  51. package/dist/utils/open.mjs +1 -1
  52. package/dist/utils/serve-static.mjs +2 -1
  53. package/dist/utils/shared-state.d.mts +1 -1
  54. package/dist/utils/shared-state.mjs +1 -1
  55. package/dist/utils/streaming-channel.d.mts +1 -1
  56. package/dist/utils/when.d.mts +1 -1
  57. package/package.json +10 -9
  58. package/dist/{open-Dusa2Zzd.mjs → open-Deb5xmIT.mjs} +1 -1
@@ -1,4 +1,4 @@
1
- import { r as DevframeDefinition } from "../devframe-D-gr9sBx.mjs";
1
+ import { r as DevframeDefinition } from "../devframe-DgvncQy2.mjs";
2
2
 
3
3
  //#region src/adapters/build.d.ts
4
4
  interface CreateBuildOptions {
@@ -1,9 +1,9 @@
1
- import { t as collectStaticRpcDump } from "../dump-DoXkj4ku.mjs";
1
+ import { t as collectStaticRpcDump } from "../dump-D09PZb7T.mjs";
2
2
  import { n as colors } from "../diagnostics-reporter-CsIG85Q5.mjs";
3
3
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME } from "../constants.mjs";
4
4
  import { n as strictJsonStringify } from "../serialization-DpLXCy13.mjs";
5
5
  import { n as structuredCloneStringify } from "../structured-clone-XpHLZ8nr.mjs";
6
- import { n as createHostContext, t as createH3DevframeHost } from "../host-h3-C5SZlk03.mjs";
6
+ import { n as createHostContext, t as createH3DevframeHost } from "../host-h3-Dsf-Tgwx.mjs";
7
7
  import { n as resolveBasePath } from "../_shared-bWRzeSa0.mjs";
8
8
  import { existsSync } from "node:fs";
9
9
  import { dirname, resolve } from "pathe";
@@ -1,4 +1,4 @@
1
- import { Ct as CliFlagsSchema, Et as parseCliFlags, Tt as defineCliFlags, r as DevframeDefinition, wt as InferCliFlags } from "../devframe-D-gr9sBx.mjs";
1
+ import { Ct as CliFlagsSchema, Et as parseCliFlags, Tt as defineCliFlags, r as DevframeDefinition, wt as InferCliFlags } from "../devframe-DgvncQy2.mjs";
2
2
  import { CAC } from "cac";
3
3
  import { H3 } from "h3";
4
4
 
@@ -1,6 +1,6 @@
1
1
  import { n as colors } from "../diagnostics-reporter-CsIG85Q5.mjs";
2
2
  import { createBuild } from "./build.mjs";
3
- import { n as resolveDevServerPort, t as createDevServer } from "../dev-BaX8fLH2.mjs";
3
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-DSxKFn-v.mjs";
4
4
  import process from "node:process";
5
5
  import cac from "cac";
6
6
  import { safeParse } from "valibot";
@@ -1,5 +1,5 @@
1
- import { l as DevframeWsOptions, r as DevframeDefinition } from "../devframe-D-gr9sBx.mjs";
2
- import { n as StartedServer } from "../server-rX781kz-.mjs";
1
+ import { l as DevframeWsOptions, r as DevframeDefinition } from "../devframe-DgvncQy2.mjs";
2
+ import { n as StartedServer } from "../server-DXPq8q0K.mjs";
3
3
  import { H3 } from "h3";
4
4
 
5
5
  //#region src/adapters/dev.d.ts
@@ -1,2 +1,2 @@
1
- import { n as resolveDevServerPort, t as createDevServer } from "../dev-BaX8fLH2.mjs";
1
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-DSxKFn-v.mjs";
2
2
  export { createDevServer, resolveDevServerPort };
@@ -1,4 +1,4 @@
1
- import { m as DevframeNodeContext, r as DevframeDefinition } from "../devframe-D-gr9sBx.mjs";
1
+ import { m as DevframeNodeContext, r as DevframeDefinition } from "../devframe-DgvncQy2.mjs";
2
2
 
3
3
  //#region src/adapters/embedded.d.ts
4
4
  interface CreateEmbeddedOptions {
@@ -1,4 +1,4 @@
1
- import { r as DevframeDefinition } from "../devframe-D-gr9sBx.mjs";
1
+ import { r as DevframeDefinition } from "../devframe-DgvncQy2.mjs";
2
2
  //#region src/adapters/mcp/build-server.d.ts
3
3
  interface CreateMcpServerOptions {
4
4
  /**
@@ -1,8 +1,8 @@
1
- import { a as diagnostics } from "../storage-l2ezeend.mjs";
2
- import { n as createHostContext } from "../host-h3-C5SZlk03.mjs";
1
+ import { a as diagnostics } from "../storage-yrUZaiib.mjs";
2
+ import { n as createHostContext } from "../host-h3-Dsf-Tgwx.mjs";
3
3
  import { join } from "pathe";
4
- import { homedir } from "node:os";
5
4
  import process from "node:process";
5
+ import { homedir } from "node:os";
6
6
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7
7
  import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
8
8
  import { toJsonSchema } from "@valibot/to-json-schema";
@@ -1,6 +1,6 @@
1
- import { $ as ScopedServerFunctions, D as StreamReader, J as DevframeSettings, L as SharedState, O as StreamSink, bt as EventEmitter, d as ConnectionMeta, et as ScopedSharedStates, it as DevframeRpcServerFunctions, rt as DevframeRpcClientFunctions, tt as SettingsForNamespace, v as RpcSharedStateGetOptions, y as RpcSharedStateHost } from "../devframe-D-gr9sBx.mjs";
1
+ import { $ as ScopedServerFunctions, D as StreamReader, J as DevframeSettings, L as SharedState, O as StreamSink, bt as EventEmitter, d as ConnectionMeta, et as ScopedSharedStates, it as DevframeRpcServerFunctions, rt as DevframeRpcClientFunctions, tt as SettingsForNamespace, v as RpcSharedStateGetOptions, y as RpcSharedStateHost } from "../devframe-DgvncQy2.mjs";
2
2
  import { _ as RpcFunctionDefinition, w as RpcFunctionsCollector } from "../types-DZEx4ffs.mjs";
3
- import { C as RpcCacheManager, w as RpcCacheOptions } from "../index-CxaPKDXX.mjs";
3
+ import { C as RpcCacheManager, w as RpcCacheOptions } from "../index-Dy6GFDRf.mjs";
4
4
  import { t as WsRpcChannelOptions } from "../ws-client-D0z0pOhn.mjs";
5
5
  import { BirpcOptions, BirpcReturn } from "birpc";
6
6
 
@@ -1,7 +1,7 @@
1
- import { t as hash } from "../hash-DFc5WwhO.mjs";
1
+ import { t as hash } from "../hash-PAfnyu2k.mjs";
2
2
  import { colors } from "../utils/colors.mjs";
3
3
  import { createEventEmitter } from "../utils/events.mjs";
4
- import { t as createSharedState } from "../shared-state-D4PPieA0.mjs";
4
+ import { t as createSharedState } from "../shared-state-QtMas0NG.mjs";
5
5
  import { i as structuredCloneStringify, n as structuredCloneParse, t as structuredCloneDeserialize } from "../structured-clone-CeZOHvkd.mjs";
6
6
  import { createStreamReader, createStreamSink } from "../utils/streaming-channel.mjs";
7
7
  import { promiseWithResolver } from "../utils/promise.mjs";
@@ -21,6 +21,14 @@ const DEVFRAME_RPC_DUMP_MANIFEST_FILENAME = "__rpc-dump/index.json";
21
21
  * `consumeOtpFromUrl` client utilities (or `connectDevframe`'s `otpParam`).
22
22
  */
23
23
  const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
24
+ /**
25
+ * WS upgrade-URL query parameter carrying a previously-issued bearer token.
26
+ * Set by `createWsRpcChannel` (browser transport) whenever `authToken` is
27
+ * passed; read at connect time by a host's connect-time trust hook (see
28
+ * `recipes/interactive-auth`'s `onConnect`) so a returning client can be
29
+ * trusted before its own `anonymous:devframe:auth` handshake call arrives.
30
+ */
31
+ const DEVFRAME_AUTH_TOKEN_QUERY_PARAM = "devframe_auth_token";
24
32
  //#endregion
25
33
  //#region src/utils/diagnostics-reporter.ts
26
34
  const formatAnsi = ansiFormatter(colors);
@@ -83,14 +91,24 @@ async function getRpcResolvedSetupResult(definition, context) {
83
91
  if (!definition.setup) return {};
84
92
  if (typeof context === "object" && context !== null) {
85
93
  definition.__cache ??= /* @__PURE__ */ new WeakMap();
86
- let promise = definition.__cache.get(context);
94
+ const cache = definition.__cache;
95
+ let promise = cache.get(context);
87
96
  if (!promise) {
88
97
  promise = Promise.resolve(definition.setup(context));
89
- definition.__cache.set(context, promise);
98
+ promise.catch(() => {
99
+ if (cache.get(context) === promise) cache.delete(context);
100
+ });
101
+ cache.set(context, promise);
90
102
  }
91
103
  return await promise;
92
104
  }
93
- definition.__promise ??= Promise.resolve(definition.setup(context));
105
+ if (!definition.__promise) {
106
+ const promise = Promise.resolve(definition.setup(context));
107
+ promise.catch(() => {
108
+ if (definition.__promise === promise) definition.__promise = void 0;
109
+ });
110
+ definition.__promise = promise;
111
+ }
94
112
  return await definition.__promise;
95
113
  }
96
114
  async function getRpcHandler(definition, context) {
@@ -122,6 +140,9 @@ var RpcCacheManager = class {
122
140
  const methodCache = this.cacheMap.get(m);
123
141
  if (methodCache) return methodCache.get(this.keySerializer(a));
124
142
  }
143
+ has(m, a) {
144
+ return this.cacheMap.get(m)?.has(this.keySerializer(a)) ?? false;
145
+ }
125
146
  apply(req, res) {
126
147
  const methodCache = this.cacheMap.get(req.m) || /* @__PURE__ */ new Map();
127
148
  methodCache.set(this.keySerializer(req.a), res);
@@ -398,8 +419,12 @@ function createRpcSharedStateClientHost(rpc) {
398
419
  return new Promise((resolve) => {
399
420
  if (!rpc.isTrusted) {
400
421
  resolve(state);
422
+ let initialized = false;
401
423
  rpc.events.on("rpc:is-trusted:updated", (isTrusted) => {
402
- if (isTrusted) initSharedState();
424
+ if (isTrusted && !initialized) {
425
+ initialized = true;
426
+ initSharedState();
427
+ }
403
428
  });
404
429
  } else initSharedState().then(resolve);
405
430
  });
@@ -611,14 +636,15 @@ const EMPTY_DEFS = /* @__PURE__ */ new Map();
611
636
  */
612
637
  function createWsRpcChannel(options) {
613
638
  let url = options.url;
614
- if (options.authToken) url = `${url}?devframe_auth_token=${encodeURIComponent(options.authToken)}`;
639
+ if (options.authToken) url = `${url}?${DEVFRAME_AUTH_TOKEN_QUERY_PARAM}=${encodeURIComponent(options.authToken)}`;
615
640
  const ws = new WebSocket(url);
616
641
  const { onConnected = NOOP, onError = NOOP, onDisconnected = NOOP, definitions = EMPTY_DEFS } = options;
617
642
  ws.addEventListener("open", (e) => {
618
643
  onConnected(e);
619
644
  });
620
645
  ws.addEventListener("error", (e) => {
621
- onError(e instanceof Error ? e : new Error(e.type));
646
+ const _e = e instanceof Error ? e : new Error(e.type);
647
+ onError(_e);
622
648
  });
623
649
  ws.addEventListener("close", (e) => {
624
650
  onDisconnected(e);
@@ -631,14 +657,25 @@ function createWsRpcChannel(options) {
631
657
  });
632
658
  },
633
659
  post: (data) => {
634
- if (ws.readyState === WebSocket.OPEN) ws.send(data);
635
- else {
636
- function handler() {
637
- ws.send(data);
638
- ws.removeEventListener("open", handler);
660
+ if (ws.readyState === WebSocket.OPEN) {
661
+ ws.send(data);
662
+ return;
663
+ }
664
+ if (ws.readyState === WebSocket.CONNECTING) {
665
+ const onOpen = () => {
666
+ cleanup();
667
+ if (ws.readyState === WebSocket.OPEN) ws.send(data);
668
+ };
669
+ const onClose = () => cleanup();
670
+ function cleanup() {
671
+ ws.removeEventListener("open", onOpen);
672
+ ws.removeEventListener("close", onClose);
639
673
  }
640
- ws.addEventListener("open", handler);
674
+ ws.addEventListener("open", onOpen);
675
+ ws.addEventListener("close", onClose);
676
+ return;
641
677
  }
678
+ onError(/* @__PURE__ */ new Error("Devframe WebSocket is not open; message dropped"));
642
679
  },
643
680
  serialize: (msg) => {
644
681
  let method;
@@ -1899,7 +1936,7 @@ function createWsRpcClientMode(options) {
1899
1936
  }
1900
1937
  async function requestTrustWithToken(token) {
1901
1938
  currentAuthToken = token;
1902
- const result = await serverRpc.$call("devframe:anonymous:auth", {
1939
+ const result = await serverRpc.$call("anonymous:devframe:auth", {
1903
1940
  authToken: token,
1904
1941
  ua: describeUA(),
1905
1942
  origin: location.origin
@@ -1910,7 +1947,7 @@ function createWsRpcClientMode(options) {
1910
1947
  return result.isTrusted;
1911
1948
  }
1912
1949
  async function requestTrustWithCode(code) {
1913
- const token = (await serverRpc.$call("devframe:auth:exchange", {
1950
+ const token = (await serverRpc.$call("anonymous:devframe:auth:exchange", {
1914
1951
  code,
1915
1952
  ua: describeUA(),
1916
1953
  origin: location.origin
@@ -2124,12 +2161,9 @@ async function getDevframeRpcClient(options = {}) {
2124
2161
  async onRequest(req, next, resolve) {
2125
2162
  await rpcOptions.onRequest?.call(this, req, next, resolve);
2126
2163
  if (cacheOptions && cacheManager?.validate(req.m)) {
2127
- const cached = cacheManager.cached(req.m, req.a);
2128
- if (cached) return resolve(cached);
2129
- else {
2130
- const res = await next(req);
2131
- cacheManager?.apply(req, res);
2132
- }
2164
+ if (cacheManager.has(req.m, req.a)) return resolve(cacheManager.cached(req.m, req.a));
2165
+ const res = await next(req);
2166
+ cacheManager.apply(req, res);
2133
2167
  } else await next(req);
2134
2168
  }
2135
2169
  },
@@ -29,5 +29,28 @@ declare const REMOTE_CONNECTION_KEY = "devframe-remote-connection";
29
29
  * `consumeOtpFromUrl` client utilities (or `connectDevframe`'s `otpParam`).
30
30
  */
31
31
  declare const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
32
+ /**
33
+ * WS upgrade-URL query parameter carrying a previously-issued bearer token.
34
+ * Set by `createWsRpcChannel` (browser transport) whenever `authToken` is
35
+ * passed; read at connect time by a host's connect-time trust hook (see
36
+ * `recipes/interactive-auth`'s `onConnect`) so a returning client can be
37
+ * trusted before its own `anonymous:devframe:auth` handshake call arrives.
38
+ */
39
+ declare const DEVFRAME_AUTH_TOKEN_QUERY_PARAM = "devframe_auth_token";
40
+ /**
41
+ * Prefix that marks an RPC method as callable before a connection is
42
+ * trusted. This is the *only* rule the pre-trust gate applies — there is no
43
+ * per-method allowlist. Any handshake method a host adapter needs to reach
44
+ * before authentication must be named `anonymous:<rest>` (e.g.
45
+ * `anonymous:devframe:auth`).
46
+ */
47
+ declare const ANONYMOUS_RPC_PREFIX = "anonymous:";
48
+ /**
49
+ * Whether `name` is callable before a connection is trusted, i.e. it starts
50
+ * with {@link ANONYMOUS_RPC_PREFIX}. Used by the resolver gate in
51
+ * `startHttpAndWs` (via an `authorize` function) and by host adapters that
52
+ * implement their own transport.
53
+ */
54
+ declare function isAnonymousRpcMethod(name: string): boolean;
32
55
  //#endregion
33
- export { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY };
56
+ export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
@@ -29,5 +29,30 @@ const REMOTE_CONNECTION_KEY = "devframe-remote-connection";
29
29
  * `consumeOtpFromUrl` client utilities (or `connectDevframe`'s `otpParam`).
30
30
  */
31
31
  const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
32
+ /**
33
+ * WS upgrade-URL query parameter carrying a previously-issued bearer token.
34
+ * Set by `createWsRpcChannel` (browser transport) whenever `authToken` is
35
+ * passed; read at connect time by a host's connect-time trust hook (see
36
+ * `recipes/interactive-auth`'s `onConnect`) so a returning client can be
37
+ * trusted before its own `anonymous:devframe:auth` handshake call arrives.
38
+ */
39
+ const DEVFRAME_AUTH_TOKEN_QUERY_PARAM = "devframe_auth_token";
40
+ /**
41
+ * Prefix that marks an RPC method as callable before a connection is
42
+ * trusted. This is the *only* rule the pre-trust gate applies — there is no
43
+ * per-method allowlist. Any handshake method a host adapter needs to reach
44
+ * before authentication must be named `anonymous:<rest>` (e.g.
45
+ * `anonymous:devframe:auth`).
46
+ */
47
+ const ANONYMOUS_RPC_PREFIX = "anonymous:";
48
+ /**
49
+ * Whether `name` is callable before a connection is trusted, i.e. it starts
50
+ * with {@link ANONYMOUS_RPC_PREFIX}. Used by the resolver gate in
51
+ * `startHttpAndWs` (via an `authorize` function) and by host adapters that
52
+ * implement their own transport.
53
+ */
54
+ function isAnonymousRpcMethod(name) {
55
+ return name.startsWith(ANONYMOUS_RPC_PREFIX);
56
+ }
32
57
  //#endregion
33
- export { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY };
58
+ export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
@@ -1,4 +1,4 @@
1
- import { L as SharedState, m as DevframeNodeContext } from "./devframe-D-gr9sBx.mjs";
1
+ import { L as SharedState, m as DevframeNodeContext } from "./devframe-DgvncQy2.mjs";
2
2
 
3
3
  //#region src/node/hub-internals/context.d.ts
4
4
  interface InternalAnonymousAuthStorage {
@@ -1,5 +1,5 @@
1
- import { t as createStorage } from "./storage-l2ezeend.mjs";
2
- import { i as randomToken, n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-ENfxWkFK.mjs";
1
+ import { t as createStorage } from "./storage-yrUZaiib.mjs";
2
+ import { i as randomToken, n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-BtQDKTp7.mjs";
3
3
  import { join } from "pathe";
4
4
  //#region src/node/hub-internals/context.ts
5
5
  const internalContextMap = /* @__PURE__ */ new WeakMap();
@@ -1,12 +1,12 @@
1
1
  import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
2
- import { n as createHostContext, t as createH3DevframeHost } from "./host-h3-C5SZlk03.mjs";
3
- import { t as startHttpAndWs } from "./server-Dl6TU5LE.mjs";
2
+ import { n as createHostContext, t as createH3DevframeHost } from "./host-h3-Dsf-Tgwx.mjs";
3
+ import { t as startHttpAndWs } from "./server-BdN41ckC.mjs";
4
4
  import { n as resolveBasePath, t as normalizeBasePath } from "./_shared-bWRzeSa0.mjs";
5
- import { t as open } from "./open-Dusa2Zzd.mjs";
5
+ import { t as open } from "./open-Deb5xmIT.mjs";
6
6
  import { mountStaticHandler } from "./utils/serve-static.mjs";
7
7
  import { resolve } from "pathe";
8
- import { networkInterfaces } from "node:os";
9
8
  import process$1 from "node:process";
9
+ import { networkInterfaces } from "node:os";
10
10
  import { H3 } from "h3";
11
11
  import { createServer } from "node:net";
12
12
  import { joinURL, withBase as withBase$1, withLeadingSlash, withoutLeadingSlash } from "ufo";
@@ -1,5 +1,5 @@
1
1
  import { _ as RpcFunctionDefinition } from "./types-DZEx4ffs.mjs";
2
- import { S as RpcFunctionsCollectorBase } from "./index-CxaPKDXX.mjs";
2
+ import { S as RpcFunctionsCollectorBase } from "./index-Dy6GFDRf.mjs";
3
3
  import { t as DevframeNodeRpcSessionMeta } from "./ws-server-Bc2wBHl-.mjs";
4
4
  import { CAC } from "cac";
5
5
  import { GenericSchema, InferOutput } from "valibot";
@@ -471,9 +471,13 @@ interface DevframeRpcServerFunctions {
471
471
  * by the host adapter (e.g. Vite DevTools); the standalone server registers
472
472
  * an auto-trust noop when `auth: false`.
473
473
  *
474
+ * Named with the `anonymous:` prefix (see `isAnonymousRpcMethod`) so it is
475
+ * reachable before the connection is trusted — this is the *only* rule the
476
+ * pre-trust gate applies, no per-method allowlist.
477
+ *
474
478
  * @internal
475
479
  */
476
- 'devframe:anonymous:auth': (params: {
480
+ 'anonymous:devframe:auth': (params: {
477
481
  authToken: string;
478
482
  ua: string;
479
483
  origin: string;
@@ -485,15 +489,27 @@ interface DevframeRpcServerFunctions {
485
489
  * node-issued bearer token, returning the token on success or `null`. The
486
490
  * handler is provided by the host adapter on top of `exchangeTempAuthCode`.
487
491
  *
492
+ * Named with the `anonymous:` prefix (see `isAnonymousRpcMethod`) so it is
493
+ * reachable before the connection is trusted.
494
+ *
488
495
  * @internal
489
496
  */
490
- 'devframe:auth:exchange': (params: {
497
+ 'anonymous:devframe:auth:exchange': (params: {
491
498
  code: string;
492
499
  ua: string;
493
500
  origin: string;
494
501
  }) => Promise<{
495
502
  authToken: string | null;
496
503
  }>;
504
+ /**
505
+ * Self-revoke: the caller asks the server to revoke its own bearer token
506
+ * (if any) and drop to untrusted. Requires an already-trusted caller, so
507
+ * unlike the two handshake methods above it does **not** carry the
508
+ * `anonymous:` prefix. Registered by `recipes/interactive-auth`.
509
+ *
510
+ * @internal
511
+ */
512
+ 'devframe:auth:revoke': () => Promise<void>;
497
513
  /**
498
514
  * Subscribe a client to a shared-state key. Wired by
499
515
  * `RpcSharedStateHost`; do not register manually.
@@ -5,7 +5,7 @@ import { createHash } from "node:crypto";
5
5
  function serialize(o) {
6
6
  return typeof o == "string" ? `'${o}'` : new c().serialize(o);
7
7
  }
8
- const c = /* @__PURE__ */ function() {
8
+ const c = /*@__PURE__*/ function() {
9
9
  class o {
10
10
  #t = /* @__PURE__ */ new Map();
11
11
  compare(t, r) {
@@ -501,14 +501,24 @@ async function getRpcResolvedSetupResult(definition, context) {
501
501
  if (!definition.setup) return {};
502
502
  if (typeof context === "object" && context !== null) {
503
503
  definition.__cache ??= /* @__PURE__ */ new WeakMap();
504
- let promise = definition.__cache.get(context);
504
+ const cache = definition.__cache;
505
+ let promise = cache.get(context);
505
506
  if (!promise) {
506
507
  promise = Promise.resolve(definition.setup(context));
507
- definition.__cache.set(context, promise);
508
+ promise.catch(() => {
509
+ if (cache.get(context) === promise) cache.delete(context);
510
+ });
511
+ cache.set(context, promise);
508
512
  }
509
513
  return await promise;
510
514
  }
511
- definition.__promise ??= Promise.resolve(definition.setup(context));
515
+ if (!definition.__promise) {
516
+ const promise = Promise.resolve(definition.setup(context));
517
+ promise.catch(() => {
518
+ if (definition.__promise === promise) definition.__promise = void 0;
519
+ });
520
+ definition.__promise = promise;
521
+ }
512
522
  return await definition.__promise;
513
523
  }
514
524
  async function getRpcHandler(definition, context) {
@@ -2,7 +2,7 @@
2
2
  function serialize(o) {
3
3
  return typeof o == "string" ? `'${o}'` : new c().serialize(o);
4
4
  }
5
- const c = /* @__PURE__ */ function() {
5
+ const c = /*@__PURE__*/ function() {
6
6
  class o {
7
7
  #t = /* @__PURE__ */ new Map();
8
8
  compare(t, r) {
@@ -1,4 +1,4 @@
1
- import { r as DevframeDefinition } from "../devframe-D-gr9sBx.mjs";
1
+ import { r as DevframeDefinition } from "../devframe-DgvncQy2.mjs";
2
2
 
3
3
  //#region src/helpers/vite.d.ts
4
4
  interface ViteDevBridgeOptions {
@@ -1,8 +1,8 @@
1
1
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_WS_ROUTE } from "../constants.mjs";
2
- import { a as diagnostics } from "../storage-l2ezeend.mjs";
2
+ import { a as diagnostics } from "../storage-yrUZaiib.mjs";
3
3
  import { n as resolveBasePath, t as normalizeBasePath } from "../_shared-bWRzeSa0.mjs";
4
4
  import { serveStaticNodeMiddleware } from "../utils/serve-static.mjs";
5
- import { n as resolveDevServerPort, t as createDevServer } from "../dev-BaX8fLH2.mjs";
5
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-DSxKFn-v.mjs";
6
6
  import { resolve } from "pathe";
7
7
  //#region src/helpers/vite.ts
8
8
  /**
@@ -2,14 +2,14 @@ import { t as devframeReporter } from "./diagnostics-reporter-CsIG85Q5.mjs";
2
2
  import { t as diagnostics } from "./diagnostics-BXwBQmoN.mjs";
3
3
  import { RpcFunctionsCollectorBase } from "./rpc/index.mjs";
4
4
  import { defineRpcFunction } from "./index.mjs";
5
- import { a as diagnostics$1, i as createEventEmitter, n as createSharedState, r as nanoid, t as createStorage } from "./storage-l2ezeend.mjs";
5
+ import { a as diagnostics$1, i as createEventEmitter, n as createSharedState, r as nanoid, t as createStorage } from "./storage-yrUZaiib.mjs";
6
6
  import { defineDiagnostics } from "nostics";
7
7
  import { isatty } from "node:tty";
8
8
  import { formatWithOptions, inspect } from "node:util";
9
9
  import { existsSync } from "node:fs";
10
10
  import { join } from "pathe";
11
- import { homedir } from "node:os";
12
11
  import process$1 from "node:process";
12
+ import { homedir } from "node:os";
13
13
  //#region src/node/host-agent.ts
14
14
  /**
15
15
  * Framework-neutral host aggregating the agent-exposed surface of a
@@ -203,11 +203,18 @@ var DevframeDiagnosticsHost = class {
203
203
  }
204
204
  };
205
205
  //#endregion
206
- //#region ../../node_modules/.pnpm/obug@2.1.1/node_modules/obug/dist/core.js
206
+ //#region ../../node_modules/.pnpm/obug@2.1.3/node_modules/obug/dist/core.js
207
+ /**
208
+ * Coerce `value`.
209
+ */
207
210
  function coerce(value) {
208
211
  if (value instanceof Error) return value.stack || value.message;
209
212
  return value;
210
213
  }
214
+ /**
215
+ * Selects a color for a debug namespace
216
+ * @return An ANSI color code for the given namespace
217
+ */
211
218
  function selectColor(colors, namespace) {
212
219
  let hash = 0;
213
220
  for (let i = 0; i < namespace.length; i++) {
@@ -216,6 +223,10 @@ function selectColor(colors, namespace) {
216
223
  }
217
224
  return colors[Math.abs(hash) % colors.length];
218
225
  }
226
+ /**
227
+ * Checks if the given string matches a namespace template, honoring
228
+ * asterisks as wildcards.
229
+ */
219
230
  function matchesTemplate(search, template) {
220
231
  let searchIndex = 0;
221
232
  let templateIndex = 0;
@@ -270,8 +281,8 @@ function createDebug$1(namespace, options) {
270
281
  options.formatArgs.call(debug, diff, args);
271
282
  debug.log(...args);
272
283
  };
273
- debug.extend = function(namespace$1, delimiter = ":") {
274
- return createDebug$1(this.namespace + delimiter + namespace$1, {
284
+ debug.extend = function(namespace, delimiter = ":") {
285
+ return createDebug$1(this.namespace + delimiter + namespace, {
275
286
  useColors: this.useColors,
276
287
  color: this.color,
277
288
  formatArgs: this.formatArgs,
@@ -302,21 +313,24 @@ function createDebug$1(namespace, options) {
302
313
  }
303
314
  let names = [];
304
315
  let skips = [];
305
- function enable(namespaces$1) {
306
- globalNamespaces = namespaces$1;
316
+ function enable(namespaces) {
317
+ globalNamespaces = namespaces;
307
318
  names = [];
308
319
  skips = [];
309
320
  const split = globalNamespaces.trim().replace(/\s+/g, ",").split(",").filter(Boolean);
310
321
  for (const ns of split) if (ns[0] === "-") skips.push(ns.slice(1));
311
322
  else names.push(ns);
312
323
  }
324
+ /**
325
+ * Returns true if the given mode name is enabled, false otherwise.
326
+ */
313
327
  function enabled(name) {
314
328
  for (const skip of skips) if (matchesTemplate(name, skip)) return false;
315
329
  for (const ns of names) if (matchesTemplate(name, ns)) return true;
316
330
  return false;
317
331
  }
318
332
  //#endregion
319
- //#region ../../node_modules/.pnpm/obug@2.1.1/node_modules/obug/dist/node.js
333
+ //#region ../../node_modules/.pnpm/obug@2.1.3/node_modules/obug/dist/node.js
320
334
  const colors = process.stderr.getColorDepth && process.stderr.getColorDepth() > 2 ? [
321
335
  20,
322
336
  21,
@@ -412,7 +426,10 @@ const inspectOpts = Object.keys(process.env).filter((key) => /^debug_/i.test(key
412
426
  else value = Number(value);
413
427
  obj[prop] = value;
414
428
  return obj;
415
- }, {});
429
+ }, Object.create(null));
430
+ /**
431
+ * Is stdout a TTY? Colored output is enabled when `true`.
432
+ */
416
433
  function useColors() {
417
434
  return "colors" in inspectOpts ? Boolean(inspectOpts.colors) : isatty(process.stderr.fd);
418
435
  }
@@ -420,9 +437,12 @@ function getDate() {
420
437
  if (inspectOpts.hideDate) return "";
421
438
  return `${(/* @__PURE__ */ new Date()).toISOString()} `;
422
439
  }
440
+ /**
441
+ * Adds ANSI color escape codes if enabled.
442
+ */
423
443
  function formatArgs(diff, args) {
424
- const { namespace: name, useColors: useColors$1 } = this;
425
- if (useColors$1) {
444
+ const { namespace: name, useColors } = this;
445
+ if (useColors) {
426
446
  const c = this.color;
427
447
  const colorCode = `\u001B[3${c < 8 ? c : `8;5;${c}`}`;
428
448
  const prefix = ` ${colorCode};1m${name} \u001B[0m`;
@@ -437,10 +457,16 @@ const defaultOptions = {
437
457
  useColors: useColors(),
438
458
  formatArgs,
439
459
  formatters: {
460
+ /**
461
+ * Map %o to `util.inspect()`, all on a single line.
462
+ */
440
463
  o(v) {
441
464
  this.inspectOpts.colors = this.useColors;
442
465
  return inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" ");
443
466
  },
467
+ /**
468
+ * Map %O to `util.inspect()`, allowing multiple lines if needed.
469
+ */
444
470
  O(v) {
445
471
  this.inspectOpts.colors = this.useColors;
446
472
  return inspect(v, this.inspectOpts);