@voltro/web 0.7.0 → 0.8.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.
package/dist/ssr.d.ts CHANGED
@@ -2,11 +2,92 @@ import { ComponentType } from 'react';
2
2
  import { PipeableStream } from 'react-dom/server';
3
3
  import { ReactNode } from 'react';
4
4
 
5
+ /**
6
+ * Throw unless this page can actually stream. Verified against React 19.2.7
7
+ * rather than assumed — each rejected combination FAILS SILENTLY otherwise,
8
+ * which is worse than not shipping the feature:
9
+ *
10
+ * - `renderMode: 'static'` — the prerender uses `renderToString`, which does
11
+ * not support Suspense: it emits an ERRORED boundary (`<!--$!-->`) plus a
12
+ * `<template data-msg="Switched to client rendering...">` and no warning.
13
+ * The artefact would ship a permanent client-rendered fallback.
14
+ * - `renderMode: 'isr'` — ISR caches a completed HTML STRING. Awaiting the
15
+ * deferred values to fill that string would make `defer()` a silent no-op
16
+ * that still reads like it streams; caching a stream is different
17
+ * machinery entirely.
18
+ * - `interactive: 'none'` — revealing a boundary needs React's inline
19
+ * `$RC`/`$RV` scripts, and this mode ships zero JS. The fallback would be
20
+ * permanent.
21
+ * - `interactive: 'islands'` — `mount()` returns after `hydrateIslandsOnPage()`
22
+ * and never hydrates the root, so nothing ever consumes the registry
23
+ * promises. Islands take their props from their own serialised payload, not
24
+ * from loader data, so there is no value in wiring them in.
25
+ */
26
+ export declare const assertDeferralSupported: (target: DeferralTarget) => void;
27
+
28
+ /** Render modes / interactive modes a page may combine with `defer()`. */
29
+ export declare interface DeferralTarget {
30
+ /** Route pattern or source file — named in the error so it is actionable. */
31
+ readonly page: string;
32
+ readonly renderMode: string;
33
+ readonly interactive: string;
34
+ }
35
+
36
+ /** Brand key on the object `defer()` returns. A single explicit container
37
+ * check — NOT a scan of arbitrary loader results for markers by shape. */
38
+ declare const DEFERRED_RESULT_TAG: "__voltroDeferredLoaderResult";
39
+
40
+ /** What a loader returns when it defers part of its data. Opaque to user
41
+ * code: build it with {@link defer}, read it with `useLoaderData()`. */
42
+ declare interface DeferredLoaderResult<TEager extends object = object, TDeferred extends Record<string, Promise<unknown>> = Record<string, Promise<unknown>>> {
43
+ readonly [DEFERRED_RESULT_TAG]: true;
44
+ /** Awaited before the shell renders — present in the SSR markup AND in the
45
+ * inlined `__voltro_state__` payload. */
46
+ readonly eager: TEager;
47
+ /** Streamed after the shell — each key becomes a promise on
48
+ * `useLoaderData()`, to be rendered through `<Await>`. */
49
+ readonly deferred: TDeferred;
50
+ }
51
+
52
+ /** Build the wire payload from what the server render was given. */
53
+ export declare const encodeRouterState: (input: RouterStateInput) => InlinedRouterState;
54
+
5
55
  declare interface ErrorBoundaryProps {
6
56
  readonly error: unknown;
7
57
  readonly reset: () => void;
8
58
  }
9
59
 
60
+ /**
61
+ * The wire shape. JSON cannot express `undefined`, which is why `ran` exists
62
+ * as a separate presence record: a loader that returned `undefined` is
63
+ * otherwise indistinguishable from one that never ran, and the client would
64
+ * re-run it on hydration (the flash this whole payload exists to remove).
65
+ */
66
+ export declare interface InlinedRouterState {
67
+ /** The page (leaf) loader's result — exactly the value the server render
68
+ * provided to the page's `LoaderDataContext`. */
69
+ readonly page?: unknown;
70
+ /** Per-layout loader results keyed by CHAIN INDEX (as a JSON string key).
71
+ * The index is the same one `descriptor.chain[i]` uses on both sides —
72
+ * see `wrapInChain` in ssr.tsx and in router.tsx. */
73
+ readonly segments?: Readonly<Record<string, unknown>>;
74
+ /** Which loaders actually RAN server-side. Drives cache seeding (i.e.
75
+ * "don't re-run this on hydration"); the values above drive the render. */
76
+ readonly ran?: {
77
+ readonly page?: boolean;
78
+ readonly segments?: ReadonlyArray<number>;
79
+ };
80
+ /** Deferred (streamed) loader fields: field name -> client-registry id, for
81
+ * the page loader and per chain index. The VALUES are not here — they
82
+ * arrive later, published by the settle `<script>` each `<Await>` boundary
83
+ * emits as its promise resolves. Absent entirely when nothing deferred, so
84
+ * a non-deferring page's payload is byte-identical to what it always was. */
85
+ readonly deferred?: {
86
+ readonly page?: Readonly<Record<string, string>>;
87
+ readonly segments?: Readonly<Record<string, Readonly<Record<string, string>>>>;
88
+ };
89
+ }
90
+
10
91
  /**
11
92
  * How the client-side JS hydrates a server-rendered page.
12
93
  *
@@ -25,6 +106,9 @@ declare interface ErrorBoundaryProps {
25
106
  */
26
107
  declare type InteractiveMode = 'full' | 'islands' | 'none';
27
108
 
109
+ /** True for exactly the object {@link defer} returns. */
110
+ export declare const isDeferredLoaderResult: (value: unknown) => value is DeferredLoaderResult;
111
+
28
112
  declare interface LoaderContext {
29
113
  readonly params: Readonly<Record<string, string>>;
30
114
  readonly pathname: string;
@@ -139,6 +223,33 @@ declare interface PageMeta {
139
223
 
140
224
  export declare const parseCookieHeader: (raw: string | undefined) => Record<string, string>;
141
225
 
226
+ /**
227
+ * Split one loader result for a streaming render. `scope` is `'page'` for the
228
+ * page loader or the layout's chain index, and only feeds the registry id.
229
+ */
230
+ export declare const prepareDeferredLoaderData: (result: unknown, scope: "page" | number) => PreparedLoaderData;
231
+
232
+ /** One loader's result, prepared for a streaming SSR render. */
233
+ export declare interface PreparedLoaderData {
234
+ /** What the RENDERER gets: eager fields plus one tagged promise per
235
+ * deferred field. Identical to the plain result when nothing deferred. */
236
+ readonly renderData: unknown;
237
+ /** What the `__voltro_state__` payload gets: eager fields only. A promise
238
+ * serialises to `{}`, so the deferred half must never reach it. */
239
+ readonly stateData: unknown;
240
+ /** Deferred field name -> registry id, for the state payload. `undefined`
241
+ * when the loader did not defer — the wire shape is then byte-identical
242
+ * to what a non-deferring page has always emitted. */
243
+ readonly deferredIds: Readonly<Record<string, string>> | undefined;
244
+ }
245
+
246
+ /**
247
+ * The `<script>` every streaming SSR emitter puts in `<head>`, before the
248
+ * shell. Must precede any settle script — which is automatic, since settle
249
+ * scripts ride in the body.
250
+ */
251
+ export declare const renderDeferredRegistryScript: () => string;
252
+
142
253
  /**
143
254
  * Helper for the build pipeline: stringify the resolved meta into a
144
255
  * `<head>`-ready HTML fragment. Returns an empty string when no meta
@@ -249,26 +360,69 @@ export declare interface RenderPageStreamResult {
249
360
  /**
250
361
  * Render a page to an HTML string using its layout chain + loader data. The
251
362
  * returned `html` is the body fragment — the caller composes the surrounding
252
- * document. Renders synchronously via `renderToString`; for the streaming
253
- * path (flush the shell before the whole tree is ready) use
363
+ * document. Renders synchronously via `renderToString`.
364
+ *
365
+ * This is the ARTEFACT renderer: static prerender and ISR, both of which need
366
+ * the whole document. See the doctrine note above before switching a caller to
254
367
  * {@link renderPageToStream}.
255
368
  */
256
369
  export declare const renderPageToHtml: (options: RenderPageOptions) => RenderPageResult;
257
370
 
258
371
  /**
259
- * Streaming SSR — the richer path alongside {@link renderPageToHtml}. Renders
260
- * the page via React's `renderToPipeableStream` so the server can flush the
261
- * shell (and each Suspense boundary as it resolves) instead of buffering the
262
- * whole document into one string. Same tree, same providers, same meta as the
263
- * sync path; the difference is time-to-first-byte and native Suspense
264
- * streaming.
372
+ * Streaming SSR — the RESPONSE renderer, for `renderMode: 'ssr'`. Renders via
373
+ * React's `renderToPipeableStream` so the server can flush the shell (and each
374
+ * Suspense boundary as it resolves) instead of buffering the whole document
375
+ * into one string. Same tree, same providers, same meta as the sync path.
265
376
  *
266
377
  * The caller drives the response: write the doctype + `<head>` (using the
267
378
  * synchronously-returned `meta`) + opening `<body><div id="root">` in
268
- * `onShellReady`, `stream.pipe(res)`, then close the document in `onAllReady`.
379
+ * `onShellReady`, pipe the stream, then close the document once it ends.
380
+ * Both boot paths do that through ONE shared helper —
381
+ * `streamSsrResponse` in `@voltro/cli`'s `ssrShell.ts` — rather than
382
+ * hand-mirroring the sequence, which is the drift class that previously cost
383
+ * this pipeline its layout-loader data in dev.
384
+ *
385
+ * Two details the caller MUST get right, both learned the hard way:
386
+ *
387
+ * - **Pass `bootstrapModules`, don't leave the entry `<script type="module">`
388
+ * in the shell.** A plain module script is deferred until the document is
389
+ * fully parsed — on a streamed response that is AFTER the last deferred
390
+ * boundary, which deletes the entire benefit. React emits `bootstrapModules`
391
+ * as `async` at the end of the shell instead.
392
+ * - **Pipe through a `PassThrough`.** React's `pipe()` calls `end()` on the
393
+ * destination itself, so writing the closing `</div>` + shell tail straight
394
+ * to the response would land after it was already closed.
269
395
  */
270
396
  export declare const renderPageToStream: (options: RenderPageStreamOptions) => RenderPageStreamResult;
271
397
 
398
+ /**
399
+ * The full `<script>` tag every SSR emitter injects into `<head>`. Emitters
400
+ * call THIS, never the pieces — that is what keeps the dev / serve / prerender
401
+ * paths on one payload shape.
402
+ */
403
+ export declare const renderRouterStateScript: (input: RouterStateInput) => string;
404
+
405
+ /** id of the `<script type="application/json">` tag carrying the payload. */
406
+ export declare const ROUTER_STATE_SCRIPT_ID = "__voltro_state__";
407
+
408
+ export declare interface RouterStateInput {
409
+ /** Page loader result passed to `renderPageToHtml` / `renderPageToStream`. */
410
+ readonly loaderData: unknown;
411
+ /** Layout loader results, keyed by chain index — the same object passed to
412
+ * the renderer, so the inlined payload cannot disagree with the markup. */
413
+ readonly segmentLoaderData?: Readonly<Record<number, unknown>> | undefined;
414
+ /** Whether the page module actually exported a `loader`. Not derivable from
415
+ * `loaderData` (a loader may legitimately resolve to `undefined`/`null`,
416
+ * and the SSR paths default the field to `null` when there is no loader). */
417
+ readonly pageLoaderRan: boolean;
418
+ /** Page-loader deferred fields: name -> registry id. Produced by
419
+ * `prepareDeferredLoaderData` in the SSR pipeline; omit when nothing
420
+ * deferred (which is every non-streaming emitter). */
421
+ readonly deferredPageIds?: Readonly<Record<string, string>> | undefined;
422
+ /** Layout-loader deferred fields, keyed by chain index. */
423
+ readonly deferredSegmentIds?: Readonly<Record<number, Readonly<Record<string, string>>>> | undefined;
424
+ }
425
+
272
426
  /**
273
427
  * One layer in a page's nesting chain. Each represents a directory level
274
428
  * in the file-convention layout (or a route group).
@@ -301,11 +455,11 @@ declare interface RouteSegment {
301
455
  }
302
456
 
303
457
  /**
304
- * Serialise loader data into a `<script>` payload safe to embed in
305
- * HTML. The result is wrapped in `<script type="application/json"
306
- * id="__voltro_state__">` by the caller; here we just produce the
307
- * JSON body with `</` sequences escaped (the well-known SSR XSS
308
- * vector).
458
+ * Serialise arbitrary data for inlining into an HTML `<script>` body.
459
+ *
460
+ * Escaping `<` is the well-known SSR XSS fix: it makes a `</script>` inside a
461
+ * string value un-parseable as a closing tag while staying valid JSON (`\u003c`
462
+ * decodes back to `<`), so no consumer has to un-escape anything.
309
463
  */
310
464
  export declare const serialiseStateForInlining: (state: unknown) => string;
311
465
 
package/dist/ssr.js CHANGED
@@ -1,47 +1,48 @@
1
- import { c as e, d as t, r as n, t as r, x as i } from "./serverContext-DSValgbm.js";
2
- import { createElement as a } from "react";
3
- import { renderToPipeableStream as o, renderToString as s } from "react-dom/server";
1
+ import { _ as e, a as t, g as n, m as r, n as i, p as a, s as o, t as s } from "./routerState-ga64vk2B.js";
2
+ import { c, d as l, r as u, t as d, x as f } from "./serverContext-BW0GF8fv.js";
3
+ import { createElement as p } from "react";
4
+ import { renderToPipeableStream as m, renderToString as h } from "react-dom/server";
4
5
  //#region src/ssr.tsx
5
- var c = (t, n, r, i) => {
6
- let o = a(e.Provider, { value: r }, a(t));
7
- if (!n) return o;
8
- for (let t = n.length - 1; t >= 0; t--) {
9
- let r = n[t];
10
- if (r.Layout) {
11
- let n = r.Layout;
12
- o = a(e.Provider, { value: i(t) }, a(n, { children: o }));
6
+ var g = (e, t, n, r) => {
7
+ let i = p(c.Provider, { value: n }, p(e));
8
+ if (!t) return i;
9
+ for (let e = t.length - 1; e >= 0; e--) {
10
+ let n = t[e];
11
+ if (n.Layout) {
12
+ let t = n.Layout;
13
+ i = p(c.Provider, { value: r(e) }, p(t, { children: i }));
13
14
  }
14
15
  }
15
- return o;
16
- }, l = (e) => {
17
- let { descriptor: n, params: o, pathname: s, loaderData: l, segmentLoaderData: u, requestContext: d, outerWrap: f, locale: p } = e, m = i(n.meta, o, l, p), h = {
18
- pathname: s,
16
+ return i;
17
+ }, _ = (e) => {
18
+ let { descriptor: t, params: n, pathname: r, loaderData: i, segmentLoaderData: a, requestContext: o, outerWrap: s, locale: c } = e, u = f(t.meta, n, i, c), m = {
19
+ pathname: r,
19
20
  search: "",
20
- params: o,
21
- loaderData: l,
21
+ params: n,
22
+ loaderData: i,
22
23
  navigate: () => {
23
24
  throw Error("navigate() is not supported during server-side rendering. Trigger navigations on the client only.");
24
25
  },
25
26
  prefetch: () => {},
26
27
  registerBlocker: () => () => {},
27
28
  blocked: null
28
- }, g = n.Component;
29
- if (!g) throw Error(`SSR received a descriptor with no Component for "${s}". Lazy page routes are a client-only optimization and must not be used on the server.`);
30
- let _ = a(t.Provider, { value: h }, c(g, n.chain, l, (e) => u?.[e]));
31
- return d && (_ = a(r.Provider, { value: d }, _)), f && (_ = f(_)), {
29
+ }, h = t.Component;
30
+ if (!h) throw Error(`SSR received a descriptor with no Component for "${r}". Lazy page routes are a client-only optimization and must not be used on the server.`);
31
+ let _ = p(l.Provider, { value: m }, g(h, t.chain, i, (e) => a?.[e]));
32
+ return o && (_ = p(d.Provider, { value: o }, _)), s && (_ = s(_)), {
32
33
  tree: _,
33
- meta: m
34
+ meta: u
34
35
  };
35
- }, u = (e) => {
36
- let { tree: t, meta: n } = l(e);
36
+ }, v = (e) => {
37
+ let { tree: t, meta: n } = _(e);
37
38
  return {
38
- html: s(t),
39
+ html: h(t),
39
40
  meta: n
40
41
  };
41
- }, d = (e) => {
42
- let { tree: t, meta: n } = l(e);
42
+ }, y = (e) => {
43
+ let { tree: t, meta: n } = _(e);
43
44
  return {
44
- stream: o(t, {
45
+ stream: m(t, {
45
46
  ...e.bootstrapModules ? { bootstrapModules: [...e.bootstrapModules] } : {},
46
47
  ...e.onShellReady ? { onShellReady: e.onShellReady } : {},
47
48
  ...e.onShellError ? { onShellError: e.onShellError } : {},
@@ -49,20 +50,20 @@ var c = (t, n, r, i) => {
49
50
  }),
50
51
  meta: n
51
52
  };
52
- }, f = (e) => {
53
+ }, b = (e) => {
53
54
  if (!e) return "";
54
55
  let t = [];
55
- if (typeof e.title == "string" && t.push(`<title>${m(e.title)}</title>`), e.description && t.push(`<meta name="description" content="${h(e.description)}" />`), e.canonical && t.push(`<link rel="canonical" href="${h(e.canonical)}" />`), e.tags) for (let n of e.tags) {
56
- let e = n.name ? `name="${h(n.name)}"` : n.property ? `property="${h(n.property)}"` : "";
57
- e && t.push(`<meta ${e} content="${h(n.content)}" />`);
56
+ if (typeof e.title == "string" && t.push(`<title>${x(e.title)}</title>`), e.description && t.push(`<meta name="description" content="${S(e.description)}" />`), e.canonical && t.push(`<link rel="canonical" href="${S(e.canonical)}" />`), e.tags) for (let n of e.tags) {
57
+ let e = n.name ? `name="${S(n.name)}"` : n.property ? `property="${S(n.property)}"` : "";
58
+ e && t.push(`<meta ${e} content="${S(n.content)}" />`);
58
59
  }
59
60
  if (e.links) for (let n of e.links) {
60
61
  let e = [
61
- `rel="${h(n.rel)}"`,
62
- `href="${h(n.href)}"`,
63
- n.hreflang ? `hreflang="${h(n.hreflang)}"` : "",
64
- n.type ? `type="${h(n.type)}"` : "",
65
- n.title ? `title="${h(n.title)}"` : ""
62
+ `rel="${S(n.rel)}"`,
63
+ `href="${S(n.href)}"`,
64
+ n.hreflang ? `hreflang="${S(n.hreflang)}"` : "",
65
+ n.type ? `type="${S(n.type)}"` : "",
66
+ n.title ? `title="${S(n.title)}"` : ""
66
67
  ].filter(Boolean).join(" ");
67
68
  t.push(`<link ${e} />`);
68
69
  }
@@ -71,6 +72,6 @@ var c = (t, n, r, i) => {
71
72
  t.push(`<script type="application/ld+json" data-voltro-page-jsonld>${e}<\/script>`);
72
73
  }
73
74
  return t.join("\n ");
74
- }, p = (e) => JSON.stringify(e ?? null).replace(/</g, "\\u003c"), m = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"), h = (e) => e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
75
+ }, x = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"), S = (e) => e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
75
76
  //#endregion
76
- export { n as parseCookieHeader, f as renderMetaToHtml, u as renderPageToHtml, d as renderPageToStream, p as serialiseStateForInlining };
77
+ export { s as ROUTER_STATE_SCRIPT_ID, o as assertDeferralSupported, i as encodeRouterState, a as isDeferredLoaderResult, u as parseCookieHeader, r as prepareDeferredLoaderData, n as renderDeferredRegistryScript, b as renderMetaToHtml, v as renderPageToHtml, y as renderPageToStream, t as renderRouterStateScript, e as serialiseStateForInlining };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/web",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "The Voltro web framework — file-based routing, render modes (SSR / SSG / islands), the page-export contract, data hooks, and the browser mount.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -52,8 +52,8 @@
52
52
  "node": ">=24.0.0"
53
53
  },
54
54
  "dependencies": {
55
- "@voltro/client": "0.7.0",
56
- "@voltro/ui": "0.7.0"
55
+ "@voltro/client": "0.8.0",
56
+ "@voltro/ui": "0.8.0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "@effect/platform": "^0.96.2",
@@ -1,74 +0,0 @@
1
- import { t as e } from "./frameworkBoot-C_d7E8Fj.js";
2
- import { StrictMode as t, createElement as n } from "react";
3
- import { createRoot as r, hydrateRoot as i } from "react-dom/client";
4
- import { jsx as a } from "react/jsx-runtime";
5
- //#region src/islands.tsx
6
- var o = /* @__PURE__ */ new Map(), s = (e, t) => {
7
- o.set(t.name, e);
8
- let r = t.hydrate ?? "visible", i = (i) => n("div", {
9
- "data-voltro-island": "",
10
- "data-island-name": t.name,
11
- "data-island-hydrate": r,
12
- "data-island-props": l(i)
13
- }, n(e, i));
14
- return i.displayName = `Island(${t.name})`, i;
15
- }, c = (e) => o.get(e), l = (e) => JSON.stringify(e ?? {}).replace(/</g, "\\u003c"), u = (e) => {
16
- if (!e) return {};
17
- try {
18
- return JSON.parse(e);
19
- } catch {
20
- return {};
21
- }
22
- }, d = () => {
23
- let e = document.querySelectorAll("[data-voltro-island]:not([data-voltro-hydrated])");
24
- for (let t of e) {
25
- let e = t.dataset.islandName ?? "", r = o.get(e);
26
- if (!r) {
27
- console.warn(`[voltro] island "${e}" referenced in DOM but not registered. Did the island file get imported in this bundle?`);
28
- continue;
29
- }
30
- let a = u(t.dataset.islandProps ?? null), s = t.dataset.islandHydrate ?? "visible";
31
- t.setAttribute("data-voltro-hydrated", "pending");
32
- let c = () => {
33
- t.getAttribute("data-voltro-hydrated") !== "done" && (t.setAttribute("data-voltro-hydrated", "done"), i(t, n(r, a)));
34
- };
35
- if (s === "load") c();
36
- else if (s === "idle") {
37
- let e = globalThis.requestIdleCallback;
38
- e ? e(c) : setTimeout(c, 0);
39
- } else if (s === "visible") {
40
- let e = new IntersectionObserver((t) => {
41
- t.some((e) => e.isIntersecting) && (e.disconnect(), c());
42
- }, { rootMargin: "64px" });
43
- e.observe(t);
44
- } else if (s === "interaction") {
45
- let e = () => {
46
- t.removeEventListener("pointerdown", e), t.removeEventListener("keydown", e), c();
47
- };
48
- t.addEventListener("pointerdown", e, { passive: !0 }), t.addEventListener("keydown", e);
49
- }
50
- }
51
- }, f = (e) => `${window.location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}/ws/${e}`, p = (n, o) => {
52
- let s = document.getElementById(o.rootId ?? "root");
53
- if (!s) throw Error(`@voltro/web: no #${o.rootId ?? "root"} element in the document`);
54
- let c = Object.entries(o.apis).map(([e, t]) => ({
55
- name: e,
56
- group: t.group,
57
- descriptors: t.descriptors ?? {},
58
- wsUrl: t.wsUrl ?? f(e),
59
- headers: t.headers
60
- })), l = document.getElementById("__voltro_state__") !== null && s.children.length > 0, u = document.querySelector("meta[name=\"voltro-interactive\"]")?.getAttribute("content") ?? "full";
61
- if (u === "none") return;
62
- if (u === "islands") {
63
- d();
64
- return;
65
- }
66
- let p = /* @__PURE__ */ a(t, { children: /* @__PURE__ */ a(e, {
67
- App: n,
68
- apis: c,
69
- ...o.Devtools ? { Devtools: o.Devtools } : {}
70
- }) });
71
- l ? i(s, p) : r(s).render(p);
72
- };
73
- //#endregion
74
- export { s as i, c as n, d as r, p as t };