@voltro/web 0.55.0 → 0.56.0

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.
@@ -1,20 +1,20 @@
1
1
  import { t as e } from "./globalContext-AuflFFmy.js";
2
2
  import { AppClientsContext as t } from "./hooks.js";
3
3
  import { c as n, l as r, r as i, s as a, u as o } from "./defaultFallbacks-SQ45vAhz.js";
4
- import { useCallback as s, useContext as c, useEffect as l, useRef as u, useState as d, useSyncExternalStore as f } from "react";
5
- import { FrameworkRuntimesProvider as p, buildApiRuntime as m, ssrClientProxy as h, ssrStubHandle as ee, startApiSupervisor as g, subscribeClientTraces as te, wireAuthRefresh as ne } from "@voltro/client";
6
- import { Fragment as re, jsx as _, jsxs as v } from "react/jsx-runtime";
4
+ import { useCallback as s, useContext as c, useEffect as l, useMemo as u, useRef as d, useState as f, useSyncExternalStore as p } from "react";
5
+ import { FrameworkRuntimesProvider as ee, buildApiRuntime as m, ssrClientProxy as te, ssrStubHandle as ne, startApiSupervisor as re, subscribeClientTraces as ie, wireAuthRefresh as ae } from "@voltro/client";
6
+ import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
7
7
  //#region src/reconnect.ts
8
- var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C = () => {
9
- let e = f(o, n, n).some((e) => e.kind === "loading" || e.kind === "reconnecting"), [t, r] = d(!1);
8
+ var v = e("reconnect", null), y = () => c(v) ?? (() => {}), b = 150, x = 220, S = () => {
9
+ let e = p(o, n, n).some((e) => e.kind === "loading" || e.kind === "reconnecting"), [t, r] = f(!1);
10
10
  return l(() => {
11
11
  if (!e) {
12
12
  r(!1);
13
13
  return;
14
14
  }
15
- let t = setTimeout(() => r(!0), x);
15
+ let t = setTimeout(() => r(!0), b);
16
16
  return () => clearTimeout(t);
17
- }, [e]), /* @__PURE__ */ v("div", {
17
+ }, [e]), /* @__PURE__ */ _("div", {
18
18
  "aria-hidden": "true",
19
19
  "data-voltro-nav-indicator": "",
20
20
  style: {
@@ -25,7 +25,7 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
25
25
  pointerEvents: "none",
26
26
  opacity: +!!t,
27
27
  transform: t ? "translateY(0) scale(1)" : "translateY(4px) scale(0.96)",
28
- transition: `opacity ${S}ms ease, transform ${S}ms ease`,
28
+ transition: `opacity ${x}ms ease, transform ${x}ms ease`,
29
29
  display: "grid",
30
30
  placeItems: "center",
31
31
  width: 34,
@@ -37,51 +37,51 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
37
37
  border: "1px solid color-mix(in oklch, canvastext 12%, transparent)",
38
38
  boxShadow: "0 4px 14px color-mix(in oklch, canvastext 16%, transparent)"
39
39
  },
40
- children: [/* @__PURE__ */ _("span", { "data-voltro-nav-spinner": "" }), /* @__PURE__ */ _("style", { children: w })]
40
+ children: [/* @__PURE__ */ g("span", { "data-voltro-nav-spinner": "" }), /* @__PURE__ */ g("style", { children: C })]
41
41
  });
42
- }, w = "\n@keyframes voltroNavSpin { to { transform: rotate(360deg); } }\n[data-voltro-nav-spinner] {\n width: 16px;\n height: 16px;\n border-radius: 50%;\n border: 2px solid color-mix(in oklch, canvastext 22%, transparent);\n border-top-color: color-mix(in oklch, canvastext 78%, transparent);\n animation: voltroNavSpin 0.7s linear infinite;\n}\n@media (prefers-reduced-motion: reduce) {\n [data-voltro-nav-spinner] { animation-duration: 1.6s; }\n}\n", T = 2e3, ie = () => typeof window < "u" && !1, ae = () => typeof window > "u" ? null : `${window.location.origin}/`, oe = 2e4, E = "voltro:wedge-reload-at", se = () => {
42
+ }, C = "\n@keyframes voltroNavSpin { to { transform: rotate(360deg); } }\n[data-voltro-nav-spinner] {\n width: 16px;\n height: 16px;\n border-radius: 50%;\n border: 2px solid color-mix(in oklch, canvastext 22%, transparent);\n border-top-color: color-mix(in oklch, canvastext 78%, transparent);\n animation: voltroNavSpin 0.7s linear infinite;\n}\n@media (prefers-reduced-motion: reduce) {\n [data-voltro-nav-spinner] { animation-duration: 1.6s; }\n}\n", w = 2e3, T = () => typeof window < "u" && !1, E = () => typeof window > "u" ? null : `${window.location.origin}/`, D = 2e4, O = "voltro:wedge-reload-at", k = () => {
43
43
  try {
44
- let e = Number(window.sessionStorage.getItem(E) ?? "0"), t = Date.now();
45
- if (t - e < oe) return;
46
- window.sessionStorage.setItem(E, String(t));
44
+ let e = Number(window.sessionStorage.getItem(O) ?? "0"), t = Date.now();
45
+ if (t - e < D) return;
46
+ window.sessionStorage.setItem(O, String(t));
47
47
  } catch {}
48
48
  window.location.reload();
49
- }, D = () => {
50
- if (ie()) return {
49
+ }, A = () => {
50
+ if (T()) return {
51
51
  afterFailures: 2,
52
52
  arm: () => {
53
- let e = ae();
53
+ let e = E();
54
54
  if (e === null) return () => {};
55
55
  let t = setInterval(() => {
56
56
  fetch(e, {
57
57
  method: "GET",
58
58
  cache: "no-store",
59
- signal: AbortSignal.timeout(T)
59
+ signal: AbortSignal.timeout(w)
60
60
  }).then((e) => {
61
- e.status < 500 && se();
61
+ e.status < 500 && k();
62
62
  }).catch(() => {});
63
- }, T);
63
+ }, w);
64
64
  return () => clearInterval(t);
65
65
  }
66
66
  };
67
- }, O = {
67
+ }, j = {
68
68
  log: console.log.bind(console),
69
69
  info: console.info.bind(console),
70
70
  warn: console.warn.bind(console),
71
71
  error: console.error.bind(console),
72
72
  debug: console.debug.bind(console)
73
- }, k = 200, A = 400, ce = 20, j = 1e3, M = (e) => {
73
+ }, M = 200, oe = 400, se = 20, N = 1e3, P = (e) => {
74
74
  if (typeof e == "string") return e;
75
75
  if (e === void 0) return "undefined";
76
76
  if (e === null) return "null";
77
77
  if (e instanceof Error) return e.stack ?? e.message;
78
78
  if (typeof e == "object") try {
79
- return JSON.stringify(e, le());
79
+ return JSON.stringify(e, ce());
80
80
  } catch {
81
81
  return Object.prototype.toString.call(e);
82
82
  }
83
83
  return String(e);
84
- }, le = () => {
84
+ }, ce = () => {
85
85
  let e = /* @__PURE__ */ new WeakSet();
86
86
  return (t, n) => {
87
87
  if (typeof n == "object" && n) {
@@ -90,20 +90,20 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
90
90
  }
91
91
  return n;
92
92
  };
93
- }, N = (e, t) => e.length > t ? `${e.slice(0, t)}…` : e, P = /%[sdifoOc]/g, F = (e) => {
93
+ }, F = (e, t) => e.length > t ? `${e.slice(0, t)}…` : e, I = /%[sdifoOc]/g, L = (e) => {
94
94
  if (e.length === 0) return {
95
95
  message: "",
96
96
  rest: []
97
97
  };
98
98
  let t = e[0];
99
- if (typeof t != "string" || !P.test(t)) return {
100
- message: M(t),
99
+ if (typeof t != "string" || !I.test(t)) return {
100
+ message: P(t),
101
101
  rest: e.slice(1)
102
102
  };
103
- P.lastIndex = 0;
103
+ I.lastIndex = 0;
104
104
  let n = 1;
105
105
  return {
106
- message: t.replace(P, (t) => {
106
+ message: t.replace(I, (t) => {
107
107
  if (t === "%c") return n++, "";
108
108
  if (n >= e.length) return t;
109
109
  let r = e[n++];
@@ -119,21 +119,21 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
119
119
  return Number.isFinite(e) ? String(e) : "NaN";
120
120
  }
121
121
  case "%o":
122
- case "%O": return M(r);
122
+ case "%O": return P(r);
123
123
  default: return t;
124
124
  }
125
125
  }),
126
126
  rest: e.slice(n)
127
127
  };
128
- }, I = (e) => {
129
- let t = e.flushAfterMs ?? A, n = `${e.baseUrl.replace(/\/+$/, "")}/_voltro/inspect/clientLog`, r = [], i = null, a = !1, o = () => {
128
+ }, R = (e) => {
129
+ let t = e.flushAfterMs ?? oe, n = `${e.baseUrl.replace(/\/+$/, "")}/_voltro/inspect/clientLog`, r = [], i = null, a = !1, o = () => {
130
130
  if (i !== null && (clearTimeout(i), i = null), r.length === 0) return;
131
131
  let t = r;
132
132
  r = [];
133
133
  let a = {
134
134
  app: e.appName,
135
135
  page: typeof window < "u" ? window.location.pathname : void 0,
136
- ua: typeof navigator < "u" ? N(navigator.userAgent, 200) : void 0,
136
+ ua: typeof navigator < "u" ? F(navigator.userAgent, 200) : void 0,
137
137
  entries: t
138
138
  };
139
139
  try {
@@ -149,11 +149,11 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
149
149
  i === null && (i = setTimeout(o, t));
150
150
  }, c = (e, t) => {
151
151
  if (a) return;
152
- r.length >= k && r.shift();
152
+ r.length >= M && r.shift();
153
153
  let n = t.find((e) => e instanceof Error), i = t.find((e) => typeof e == "object" && !!e && "componentStack" in e), c = typeof i?.componentStack == "string" ? i.componentStack : void 0, l = t[0] instanceof Error ? {
154
154
  message: t[0].message,
155
155
  rest: t.slice(1)
156
- } : F(t), u = N(l.message, j), d = l.rest.filter((e) => e !== n && e !== i).map((e) => N(M(e), j)), f;
156
+ } : L(t), u = F(l.message, N), d = l.rest.filter((e) => e !== n && e !== i).map((e) => F(P(e), N)), f;
157
157
  n ? (f = n.stack ?? n.message, c && (f += `\n\nComponent stack:${c}`)) : e === "error" && (f = (/* @__PURE__ */ Error()).stack);
158
158
  let p = {
159
159
  ts: Date.now(),
@@ -162,29 +162,29 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
162
162
  ...d.length > 0 ? { args: d } : {},
163
163
  ...f === void 0 ? {} : { stack: f }
164
164
  };
165
- r.push(p), r.length >= ce ? o() : s();
165
+ r.push(p), r.length >= se ? o() : s();
166
166
  }, l = (e) => (...t) => {
167
- O[e](...t), c(e, t);
167
+ j[e](...t), c(e, t);
168
168
  };
169
169
  console.log = l("log"), console.info = l("info"), console.warn = l("warn"), console.error = l("error"), console.debug = l("debug");
170
170
  let u = () => {
171
171
  o();
172
172
  };
173
173
  return typeof window < "u" && (window.addEventListener("beforeunload", u), window.addEventListener("pagehide", u)), { dispose: () => {
174
- a = !0, o(), i !== null && (clearTimeout(i), i = null), console.log = O.log, console.info = O.info, console.warn = O.warn, console.error = O.error, console.debug = O.debug, typeof window < "u" && (window.removeEventListener("beforeunload", u), window.removeEventListener("pagehide", u));
174
+ a = !0, o(), i !== null && (clearTimeout(i), i = null), console.log = j.log, console.info = j.info, console.warn = j.warn, console.error = j.error, console.debug = j.debug, typeof window < "u" && (window.removeEventListener("beforeunload", u), window.removeEventListener("pagehide", u));
175
175
  } };
176
- }, L = 500, R = /* @__PURE__ */ new Set(), z = (e) => {
177
- if (!R.has(e) && (R.add(e), R.size > L)) {
178
- let e = R.values().next().value;
179
- e !== void 0 && R.delete(e);
176
+ }, le = 500, z = /* @__PURE__ */ new Set(), B = (e) => {
177
+ if (!z.has(e) && (z.add(e), z.size > le)) {
178
+ let e = z.values().next().value;
179
+ e !== void 0 && z.delete(e);
180
180
  }
181
- }, B = /* @__PURE__ */ new Set(), V = (e) => (B.add(e), () => {
182
- B.delete(e);
183
- }), H = (e) => {
184
- for (let t of B) try {
181
+ }, V = /* @__PURE__ */ new Set(), H = (e) => (V.add(e), () => {
182
+ V.delete(e);
183
+ }), U = (e) => {
184
+ for (let t of V) try {
185
185
  t(e);
186
186
  } catch {}
187
- }, U = {
187
+ }, ue = {
188
188
  log: "log",
189
189
  info: "info",
190
190
  warn: "warn",
@@ -203,21 +203,21 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
203
203
  try {
204
204
  let n = JSON.parse(t.data).payload;
205
205
  if (!n || typeof n.message != "string" || n.scope === "client") return;
206
- let r = n.level === void 0 ? "log" : U[n.level], i = n.scope ? ` ${n.scope}` : "";
207
- O[r](`%c[server ${e.originLabel}${i}]%c ${n.message}`, W[r], "", ...n.fields ? [n.fields] : []);
206
+ let r = n.level === void 0 ? "log" : ue[n.level], i = n.scope ? ` ${n.scope}` : "";
207
+ j[r](`%c[server ${e.originLabel}${i}]%c ${n.message}`, W[r], "", ...n.fields ? [n.fields] : []);
208
208
  } catch {}
209
209
  }), n.addEventListener("trace", (t) => {
210
210
  try {
211
211
  let n = JSON.parse(t.data).payload;
212
- if (!n || n.status !== "error" || typeof n.traceId != "string" || !R.has(n.traceId)) return;
212
+ if (!n || n.status !== "error" || typeof n.traceId != "string" || !z.has(n.traceId)) return;
213
213
  let r = n.name ?? "span", i = n.statusMessage && n.statusMessage.length > 0 ? n.statusMessage : `${r} failed`;
214
- H({
214
+ U({
215
215
  traceId: n.traceId,
216
216
  spanName: r,
217
217
  api: e.originLabel,
218
218
  message: i,
219
219
  ts: Date.now()
220
- }), O.error(`%c[trace ${e.originLabel}]%c ${r} failed — ${i} (trace ${n.traceId})`, W.error, "");
220
+ }), j.error(`%c[trace ${e.originLabel}]%c ${r} failed — ${i} (trace ${n.traceId})`, W.error, "");
221
221
  } catch {}
222
222
  }), n.addEventListener("error", () => {
223
223
  n && n.readyState === EventSource.CLOSED && (n = null, !r && i === null && (i = setTimeout(() => {
@@ -236,20 +236,20 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
236
236
  muted: "oklch(0.65 0.012 285)",
237
237
  danger: "oklch(0.7 0.21 22)",
238
238
  dangerDim: "oklch(0.5 0.18 22 / 25%)"
239
- }, q = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace", ue = "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif", de = 0, fe = () => {
240
- let [e, t] = d([]);
241
- if (l(() => V((e) => {
239
+ }, q = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace", de = "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif", fe = 0, pe = () => {
240
+ let [e, t] = f([]);
241
+ if (l(() => H((e) => {
242
242
  t((t) => {
243
243
  if (t.some((t) => t.traceId === e.traceId && t.spanName === e.spanName)) return t;
244
244
  let n = [...t, {
245
245
  ...e,
246
- id: ++de
246
+ id: ++fe
247
247
  }];
248
248
  return n.length > 4 ? n.slice(n.length - 4) : n;
249
249
  });
250
250
  }), []), e.length === 0) return null;
251
251
  let n = (e) => t((t) => t.filter((t) => t.id !== e));
252
- return /* @__PURE__ */ _("div", {
252
+ return /* @__PURE__ */ g("div", {
253
253
  style: {
254
254
  position: "fixed",
255
255
  right: 16,
@@ -259,17 +259,17 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
259
259
  flexDirection: "column",
260
260
  gap: 10,
261
261
  maxWidth: 380,
262
- fontFamily: ue,
262
+ fontFamily: de,
263
263
  pointerEvents: "none"
264
264
  },
265
- children: e.map((e) => /* @__PURE__ */ _(pe, {
265
+ children: e.map((e) => /* @__PURE__ */ g(me, {
266
266
  toast: e,
267
267
  onDismiss: () => n(e.id)
268
268
  }, e.id))
269
269
  });
270
- }, pe = ({ toast: e, onDismiss: t }) => {
271
- let [n, r] = d(!1), a = `voltro logs --trace ${e.traceId}`;
272
- return /* @__PURE__ */ v("div", {
270
+ }, me = ({ toast: e, onDismiss: t }) => {
271
+ let [n, r] = f(!1), a = `voltro logs --trace ${e.traceId}`;
272
+ return /* @__PURE__ */ _("div", {
273
273
  style: {
274
274
  pointerEvents: "auto",
275
275
  background: K.card,
@@ -283,14 +283,14 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
283
283
  lineHeight: 1.45
284
284
  },
285
285
  children: [
286
- /* @__PURE__ */ v("div", {
286
+ /* @__PURE__ */ _("div", {
287
287
  style: {
288
288
  display: "flex",
289
289
  alignItems: "center",
290
290
  justifyContent: "space-between",
291
291
  gap: 8
292
292
  },
293
- children: [/* @__PURE__ */ _("span", {
293
+ children: [/* @__PURE__ */ g("span", {
294
294
  style: {
295
295
  color: K.danger,
296
296
  fontWeight: 600,
@@ -298,7 +298,7 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
298
298
  letterSpacing: .3
299
299
  },
300
300
  children: "⚠ Backend error"
301
- }), /* @__PURE__ */ _("button", {
301
+ }), /* @__PURE__ */ g("button", {
302
302
  onClick: t,
303
303
  "aria-label": "Dismiss",
304
304
  style: {
@@ -313,14 +313,14 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
313
313
  children: "×"
314
314
  })]
315
315
  }),
316
- /* @__PURE__ */ v("div", {
316
+ /* @__PURE__ */ _("div", {
317
317
  style: {
318
318
  marginTop: 6,
319
319
  color: K.muted,
320
320
  fontSize: 11.5
321
321
  },
322
322
  children: [
323
- /* @__PURE__ */ _("span", {
323
+ /* @__PURE__ */ g("span", {
324
324
  style: {
325
325
  fontFamily: q,
326
326
  color: K.fg
@@ -328,13 +328,13 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
328
328
  children: e.api
329
329
  }),
330
330
  " · ",
331
- /* @__PURE__ */ _("span", {
331
+ /* @__PURE__ */ g("span", {
332
332
  style: { fontFamily: q },
333
333
  children: e.spanName
334
334
  })
335
335
  ]
336
336
  }),
337
- /* @__PURE__ */ _("div", {
337
+ /* @__PURE__ */ g("div", {
338
338
  style: {
339
339
  marginTop: 4,
340
340
  color: K.fg,
@@ -342,7 +342,7 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
342
342
  },
343
343
  children: e.message
344
344
  }),
345
- /* @__PURE__ */ _("button", {
345
+ /* @__PURE__ */ g("button", {
346
346
  onClick: () => {
347
347
  i(a).then((e) => {
348
348
  e !== "failed" && (r(!0), setTimeout(() => r(!1), 1500));
@@ -367,14 +367,14 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
367
367
  })
368
368
  ]
369
369
  });
370
- }, J = (e) => {
370
+ }, he = (e) => {
371
371
  try {
372
372
  let t = new URL(e);
373
373
  return `${t.protocol === "wss:" ? "https:" : "http:"}//${t.host}`;
374
374
  } catch {
375
375
  return "";
376
376
  }
377
- }, Y = (e, t) => /^wss?:\/\//i.test(e) || /^https?:\/\//i.test(e) ? J(e) : `/_voltro/api/${t}`, me = typeof performance < "u" ? performance.now() : Date.now(), X = () => {
377
+ }, J = (e, t) => /^wss?:\/\//i.test(e) || /^https?:\/\//i.test(e) ? he(e) : `/_voltro/api/${t}`, ge = typeof performance < "u" ? performance.now() : Date.now(), Y = () => {
378
378
  if (typeof window > "u") return !1;
379
379
  try {
380
380
  if (window.localStorage?.getItem("framework_debug") === "1") return !0;
@@ -386,65 +386,84 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
386
386
  PROD: !0,
387
387
  SSR: !1
388
388
  }.DEV === !0;
389
- }, Z = (e, ...t) => {
390
- if (!X()) return;
391
- let n = ((typeof performance < "u" ? performance.now() : Date.now()) - me).toFixed(0).padStart(6, " ");
389
+ }, X = (e, ...t) => {
390
+ if (!Y()) return;
391
+ let n = ((typeof performance < "u" ? performance.now() : Date.now()) - ge).toFixed(0).padStart(6, " ");
392
392
  console.log(`[fw ${e} +${n}ms]`, ...t);
393
- }, Q = 3e3, he = 0, ge = (e, t, n, r) => (i, a) => {
394
- let o = ++he;
395
- Z(e, `ws#${o} create gen=${t} url=${i}`);
393
+ }, Z = 3e3, _e = 0, Q = (e, t, n, r) => (i, a) => {
394
+ let o = ++_e;
395
+ X(e, `ws#${o} create gen=${t} url=${i}`);
396
396
  let s = new globalThis.WebSocket(i, a), c = !1, l = !1, u = (e) => {
397
397
  l || (l = !0, r(e));
398
398
  }, d = (t) => (n) => {
399
399
  let r = t === "close" ? `code=${n.code}` : "type=error";
400
- Z(e, `ws#${o} ${t} opened=${c} issued=${l} ${r}`), u(t);
400
+ X(e, `ws#${o} ${t} opened=${c} issued=${l} ${r}`), u(t);
401
401
  };
402
402
  return s.addEventListener("open", () => {
403
- c = !0, Z(e, `ws#${o} open gen=${t}`), n();
403
+ c = !0, X(e, `ws#${o} open gen=${t}`), n();
404
404
  }), s.addEventListener("close", d("close")), s.addEventListener("error", d("error")), setTimeout(() => {
405
405
  if (!c && !l) {
406
- Z(e, `ws#${o} connect-timeout gen=${t} (no open within ${Q}ms)`), u("connect-timeout");
406
+ X(e, `ws#${o} connect-timeout gen=${t} (no open within ${Z}ms)`), u("connect-timeout");
407
407
  try {
408
408
  s.close();
409
409
  } catch {}
410
410
  }
411
- }, Q), s;
412
- }, _e = async (e, t, n, r) => {
413
- Z(e.name, `build gen=${t}: making runtime`);
411
+ }, Z), s;
412
+ }, ve = async (e, t, n, r) => {
413
+ X(e.name, `build gen=${t}: making runtime`);
414
414
  try {
415
415
  let i = await m({
416
416
  name: e.name,
417
417
  wsUrl: e.wsUrl,
418
418
  group: e.group,
419
419
  headers: e.headers,
420
- webSocketConstructor: ge(e.name, t, n, r)
420
+ webSocketConstructor: Q(e.name, t, n, r)
421
421
  });
422
- return Z(e.name, `build gen=${t}: runtime resolved`), i;
422
+ return X(e.name, `build gen=${t}: runtime resolved`), i;
423
423
  } catch (n) {
424
- throw Z(e.name, `build gen=${t}: runtime FAILED, disposing`, n.message ?? n), n;
424
+ throw X(e.name, `build gen=${t}: runtime FAILED, disposing`, n.message ?? n), n;
425
425
  }
426
- }, $ = ({ apis: e, children: n, chrome: i }) => {
427
- let [o, c] = d(() => ({
426
+ }, $ = ({ apis: e, children: n, chrome: i, connect: o = "eager" }) => {
427
+ let [c, p] = f(() => ({
428
428
  initialized: e.length === 0,
429
429
  clients: /* @__PURE__ */ new Map()
430
- })), f = u(null), m = s(() => {
431
- f.current?.reconnect();
432
- }, []), [b, x] = d(!1);
430
+ })), m = d(null), y = s(() => {
431
+ m.current?.reconnect();
432
+ }, []), [b, x] = f(!1);
433
433
  l(() => {
434
434
  x(!0);
435
435
  }, []), l(() => {
436
- let e = [...o.clients.values()].map((e) => ne(e.errorBus, () => {
437
- f.current?.refreshAuth();
436
+ let e = [...c.clients.values()].map((e) => ae(e.errorBus, () => {
437
+ m.current?.refreshAuth();
438
438
  }));
439
439
  return () => {
440
440
  for (let t of e) t.dispose();
441
441
  };
442
- }, [o.clients]), l(() => {
443
- let t = D(), n = g({
444
- apis: e,
445
- buildClient: _e,
442
+ }, [c.clients]);
443
+ let [C, w] = f(() => new Set(o === "eager" ? e.map((e) => e.name) : [])), T = s((e) => {
444
+ w((t) => t.has(e) ? t : /* @__PURE__ */ new Set([...t, e]));
445
+ }, []);
446
+ l(() => {
447
+ o === "eager" && w((t) => {
448
+ let n = new Set(t), r = !1;
449
+ for (let t of e) n.has(t.name) || (n.add(t.name), r = !0);
450
+ return r ? n : t;
451
+ });
452
+ }, [e, o]);
453
+ let E = u(() => e.filter((e) => C.has(e.name)), [e, C]);
454
+ l(() => {
455
+ if (E.length === 0) {
456
+ p({
457
+ clients: /* @__PURE__ */ new Map(),
458
+ initialized: !0
459
+ });
460
+ return;
461
+ }
462
+ let e = A(), t = re({
463
+ apis: E,
464
+ buildClient: ve,
446
465
  onChange: (e, t) => {
447
- c({
466
+ p({
448
467
  clients: e,
449
468
  initialized: t
450
469
  });
@@ -454,67 +473,69 @@ var y = e("reconnect", null), b = () => c(y) ?? (() => {}), x = 150, S = 220, C
454
473
  kind: "reconnecting",
455
474
  label: "Reconnecting…"
456
475
  }),
457
- ...t ? { wedgeBackstop: t } : {}
476
+ ...e ? { wedgeBackstop: e } : {}
458
477
  });
459
- return f.current = n, () => {
460
- n.dispose(), f.current === n && (f.current = null);
478
+ return m.current = t, () => {
479
+ t.dispose(), m.current === t && (m.current = null);
461
480
  };
462
- }, [e]), l(() => {
463
- if (!X() || typeof window > "u") return;
481
+ }, [E]), l(() => {
482
+ if (!Y() || typeof window > "u") return;
464
483
  let t = [], n = [], r = e[0]?.name ?? "web";
465
- t.push(I({
484
+ t.push(R({
466
485
  baseUrl: window.location.origin,
467
486
  appName: r
468
487
  }));
469
488
  for (let t of e) {
470
- let e = Y(t.wsUrl, t.name);
489
+ let e = J(t.wsUrl, t.name);
471
490
  e.length !== 0 && n.push(G({
472
491
  baseUrl: e,
473
492
  originLabel: t.name
474
493
  }));
475
494
  }
476
- let i = te((e) => z(e.traceId));
495
+ let i = ie((e) => B(e.traceId));
477
496
  return () => {
478
497
  for (let e of t) e.dispose();
479
498
  for (let e of n) e.dispose();
480
499
  i();
481
500
  };
482
501
  }, [e]);
483
- let S = new Map(e.map((e) => [e.name, o.clients.get(e.name)?.client ?? h])), w = new Map(e.map((e) => {
484
- let t = o.clients.get(e.name);
502
+ let D = new Map(e.map((e) => [e.name, c.clients.get(e.name)?.client ?? te])), O = new Map(e.map((e) => {
503
+ let t = c.clients.get(e.name);
485
504
  return t ? [e.name, {
486
505
  runtime: t.runtime,
487
506
  cache: t.cache,
488
507
  client: t.client,
489
508
  descriptors: e.descriptors,
490
- inspectBaseUrl: Y(e.wsUrl, e.name),
509
+ inspectBaseUrl: J(e.wsUrl, e.name),
491
510
  errorBus: t.errorBus
492
511
  }] : [e.name, {
493
- ...ee,
512
+ ...ne,
494
513
  descriptors: e.descriptors
495
514
  }];
496
515
  }));
497
- return /* @__PURE__ */ _(y.Provider, {
498
- value: m,
499
- children: /* @__PURE__ */ _(p, {
500
- apis: w,
501
- children: /* @__PURE__ */ _(t.Provider, {
502
- value: S,
503
- children: /* @__PURE__ */ _(a, {
504
- chrome: b ? /* @__PURE__ */ v(re, { children: [
505
- /* @__PURE__ */ _(C, {}),
516
+ return /* @__PURE__ */ g(v.Provider, {
517
+ value: y,
518
+ children: /* @__PURE__ */ g(ee, {
519
+ apis: O,
520
+ ...o === "lazy" ? { demand: T } : {},
521
+ children: /* @__PURE__ */ g(t.Provider, {
522
+ value: D,
523
+ children: /* @__PURE__ */ g(a, {
524
+ chrome: b ? /* @__PURE__ */ _(h, { children: [
525
+ /* @__PURE__ */ g(S, {}),
506
526
  i,
507
- X() ? /* @__PURE__ */ _(fe, {}) : null
527
+ Y() ? /* @__PURE__ */ g(pe, {}) : null
508
528
  ] }) : null,
509
529
  children: n
510
530
  })
511
531
  })
512
532
  })
513
533
  });
514
- }, ve = ({ App: e, apis: t, Devtools: n }) => /* @__PURE__ */ _($, {
534
+ }, ye = ({ App: e, apis: t, Devtools: n, connect: r }) => /* @__PURE__ */ g($, {
515
535
  apis: t,
516
- chrome: n ? /* @__PURE__ */ _(n, {}) : null,
517
- children: /* @__PURE__ */ _(e, {})
536
+ chrome: n ? /* @__PURE__ */ g(n, {}) : null,
537
+ ...r ? { connect: r } : {},
538
+ children: /* @__PURE__ */ g(e, {})
518
539
  });
519
540
  //#endregion
520
- export { G as a, C as c, I as i, y as l, $ as n, z as o, F as r, V as s, ve as t, b as u };
541
+ export { G as a, S as c, R as i, v as l, $ as n, B as o, L as r, H as s, ye as t, y as u };
@@ -5,7 +5,7 @@ import { ReactNode } from 'react';
5
5
 
6
6
  export { ClientDescriptorMap }
7
7
 
8
- export declare const FrameworkBoot: ({ App, apis, Devtools }: FrameworkBootProps) => ReactNode;
8
+ export declare const FrameworkBoot: ({ App, apis, Devtools, connect }: FrameworkBootProps) => ReactNode;
9
9
 
10
10
  export declare interface FrameworkBootProps {
11
11
  readonly App: ComponentType;
@@ -15,11 +15,13 @@ export declare interface FrameworkBootProps {
15
15
  * (useFrameworkRuntimes etc.) resolve. PascalCase because it is a
16
16
  * React component reference rendered as <Devtools/>. */
17
17
  readonly Devtools?: ComponentType;
18
+ /** Passed to `VoltroRuntimeProvider` — see its `connect` doc. */
19
+ readonly connect?: 'eager' | 'lazy';
18
20
  }
19
21
 
20
22
  export { MountedApi }
21
23
 
22
- export declare const VoltroRuntimeProvider: ({ apis, children, chrome }: VoltroRuntimeProviderProps) => ReactNode;
24
+ export declare const VoltroRuntimeProvider: ({ apis, children, chrome, connect }: VoltroRuntimeProviderProps) => ReactNode;
23
25
 
24
26
  export declare interface VoltroRuntimeProviderProps {
25
27
  /** The apis to mount (name, group, descriptors, wsUrl, headers). */
@@ -33,6 +35,29 @@ export declare interface VoltroRuntimeProviderProps {
33
35
  * unset. Gated behind the same post-mount flag as the rest of the
34
36
  * chrome so it never trips a hydration mismatch. */
35
37
  readonly chrome?: ReactNode;
38
+ /**
39
+ * When each api connects.
40
+ *
41
+ * 'eager' (default) — every declared api opens its socket at mount, as it
42
+ * always has.
43
+ * 'lazy' — an api connects on the FIRST hook that asks for it
44
+ * (`useFrameworkApi`, i.e. every data hook). A page
45
+ * that reads no data never opens a socket.
46
+ *
47
+ * `'lazy'` is not the default because it changes when a connection error
48
+ * surfaces, and an app that opens its socket for a side effect (a presence
49
+ * ping, an inspect stream) would notice. It is `web.api.connect` in
50
+ * `app.config.ts`.
51
+ *
52
+ * Why it exists, measured in a real browser against a `voltro start`:
53
+ * `interactive: 'full'` is the DEFAULT, and a pre-rendered documentation page
54
+ * with no subscription at all opened a WebSocket (`'none'` and `'islands'`
55
+ * opened none). And a connected socket keeps a dormancy-managed instance
56
+ * awake — `isIdleNow` is false while `connectedClients() > 0` — so a single
57
+ * open tab on a pricing page prevented scale-to-zero for as long as it stayed
58
+ * open.
59
+ */
60
+ readonly connect?: 'eager' | 'lazy';
36
61
  }
37
62
 
38
63
  export { }
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "./frameworkBoot-CnE9vzLQ.js";
1
+ import { n as e, t } from "./frameworkBoot-BfJpdpZp.js";
2
2
  export { t as FrameworkBoot, e as VoltroRuntimeProvider };
package/dist/index.d.ts CHANGED
@@ -760,6 +760,11 @@ export declare interface MountOptions {
760
760
  * PascalCase because it is a React component reference rendered
761
761
  * as <Devtools/>. */
762
762
  readonly Devtools?: ComponentType;
763
+ /** When each api connects — `'eager'` (default) or `'lazy'` (on the first
764
+ * hook that asks for it). Set from `app.config.ts`'s `web.api.connect` by
765
+ * the generated entry; see `VoltroRuntimeProvider`'s `connect` for the
766
+ * measurements behind it. */
767
+ readonly connect?: 'eager' | 'lazy';
763
768
  }
764
769
 
765
770
  /** Options for an imperative navigation. `replace` swaps the current
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./globalContext-AuflFFmy.js";
2
2
  import { AppClientsContext as t, useAppClient as n } from "./hooks.js";
3
- import { a as r, c as i, i as a, l as o, o as s, r as c, s as l, u } from "./frameworkBoot-CnE9vzLQ.js";
3
+ import { a as r, c as i, i as a, l as o, o as s, r as c, s as l, u } from "./frameworkBoot-BfJpdpZp.js";
4
4
  import { a as d, c as f, i as p, l as m, o as h, u as g } from "./defaultFallbacks-SQ45vAhz.js";
5
5
  import { getIslandComponent as _, hydrateIslandsOnPage as v, island as y } from "./islands.js";
6
6
  import { c as b, d as x, f as S, g as C, l as w, m as T } from "./routerState-Cr6fTbka.js";