@voltro/web 0.1.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/CHANGELOG.md +52 -0
- package/LICENSE +57 -0
- package/README.md +26 -0
- package/SECURITY.md +56 -0
- package/THIRD-PARTY-NOTICES.md +347 -0
- package/dist/defaultFallbacks-Bg_X-9Wv.js +541 -0
- package/dist/frameworkBoot-DBOFujAI.js +596 -0
- package/dist/frameworkBoot.d.ts +64 -0
- package/dist/frameworkBoot.js +2 -0
- package/dist/hooks.d.ts +28 -0
- package/dist/hooks.js +14 -0
- package/dist/index.d.ts +1077 -0
- package/dist/index.js +141 -0
- package/dist/mount-BuFzlw1e.js +74 -0
- package/dist/mount.d.ts +70 -0
- package/dist/mount.js +2 -0
- package/dist/serverContext-D5-Dmh8d.js +741 -0
- package/dist/ssr.d.ts +322 -0
- package/dist/ssr.js +76 -0
- package/package.json +68 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { AppClientsContext as e, useAppClient as t } from "./hooks.js";
|
|
2
|
+
import { a as n, c as r, i, l as a, o, r as s, s as c, u as l } from "./frameworkBoot-DBOFujAI.js";
|
|
3
|
+
import { a as u, c as d, i as f, l as p, o as m, s as h } from "./defaultFallbacks-Bg_X-9Wv.js";
|
|
4
|
+
import { i as g, n as _, r as ee, t as te } from "./mount-BuFzlw1e.js";
|
|
5
|
+
import { A as ne, B as re, C as ie, D as v, E as y, F as b, I as x, L as S, M as C, N as w, O as T, P as E, R as D, S as O, T as k, V as A, _ as j, a as M, b as N, c as P, d as F, f as I, g as L, h as R, i as z, j as B, k as V, l as ae, m as H, n as U, o as W, p as G, r as K, s as q, t as J, u as oe, v as se, w as ce, x as le, y as ue, z as de } from "./serverContext-D5-Dmh8d.js";
|
|
6
|
+
import { createContext as fe, createElement as Y, useContext as pe } from "react";
|
|
7
|
+
export * from "@voltro/client";
|
|
8
|
+
export * from "@voltro/ui";
|
|
9
|
+
//#region src/image.tsx
|
|
10
|
+
var X = ({ src: e }) => e, Z = fe({ loader: X }), me = ({ loader: e, children: t }) => Y(Z.Provider, { value: { loader: e } }, t), Q = [
|
|
11
|
+
640,
|
|
12
|
+
750,
|
|
13
|
+
828,
|
|
14
|
+
1080,
|
|
15
|
+
1200,
|
|
16
|
+
1920,
|
|
17
|
+
2048,
|
|
18
|
+
3840
|
|
19
|
+
], he = (e, t, n, r) => {
|
|
20
|
+
let i = n !== void 0 && !r ? Array.from(new Set(Q.filter((e) => e <= n * 2).concat(n))).sort((e, t) => e - t) : [...Q];
|
|
21
|
+
return {
|
|
22
|
+
srcSet: i.map((n) => `${e({
|
|
23
|
+
src: t,
|
|
24
|
+
width: n
|
|
25
|
+
})} ${n}w`).join(", "),
|
|
26
|
+
fallback: e({
|
|
27
|
+
src: t,
|
|
28
|
+
width: i[i.length - 1]
|
|
29
|
+
})
|
|
30
|
+
};
|
|
31
|
+
}, ge = ({ src: e, alt: t, width: n, height: r, fill: i = !1, sizes: a, priority: o = !1, loader: s, placeholder: c = "empty", blurDataURL: l, style: u, ...d }) => {
|
|
32
|
+
let f = pe(Z).loader, p = s ?? f;
|
|
33
|
+
!i && (n === void 0 || r === void 0) && typeof console < "u" && console.warn(`<Image src="${e}"> needs both width and height (or fill) to reserve layout space and avoid CLS.`);
|
|
34
|
+
let { srcSet: m, fallback: h } = he(p, e, n, i), g = c === "blur" && l ? {
|
|
35
|
+
backgroundImage: `url(${l})`,
|
|
36
|
+
backgroundSize: "cover",
|
|
37
|
+
backgroundPosition: "center"
|
|
38
|
+
} : {}, _ = i ? {
|
|
39
|
+
position: "absolute",
|
|
40
|
+
inset: 0,
|
|
41
|
+
height: "100%",
|
|
42
|
+
width: "100%",
|
|
43
|
+
objectFit: "cover"
|
|
44
|
+
} : {};
|
|
45
|
+
return Y("img", {
|
|
46
|
+
src: h,
|
|
47
|
+
srcSet: m,
|
|
48
|
+
sizes: a ?? (i ? "100vw" : void 0),
|
|
49
|
+
alt: t,
|
|
50
|
+
...i ? {} : {
|
|
51
|
+
width: n,
|
|
52
|
+
height: r
|
|
53
|
+
},
|
|
54
|
+
loading: o ? "eager" : "lazy",
|
|
55
|
+
decoding: "async",
|
|
56
|
+
...o ? { fetchPriority: "high" } : {},
|
|
57
|
+
style: {
|
|
58
|
+
...g,
|
|
59
|
+
..._,
|
|
60
|
+
...u
|
|
61
|
+
},
|
|
62
|
+
...d
|
|
63
|
+
});
|
|
64
|
+
}, $ = ({ to: e, children: t, className: n }) => Y("a", {
|
|
65
|
+
href: e,
|
|
66
|
+
className: n
|
|
67
|
+
}, t), _e = {
|
|
68
|
+
position: "sticky",
|
|
69
|
+
top: 0,
|
|
70
|
+
zIndex: 10,
|
|
71
|
+
display: "flex",
|
|
72
|
+
alignItems: "center",
|
|
73
|
+
justifyContent: "space-between",
|
|
74
|
+
gap: "1.5rem",
|
|
75
|
+
padding: "1rem 1.5rem",
|
|
76
|
+
borderBottom: "1px solid var(--voltro-blog-border, rgba(127,127,127,0.2))",
|
|
77
|
+
backdropFilter: "blur(8px)"
|
|
78
|
+
}, ve = {
|
|
79
|
+
maxWidth: "48rem",
|
|
80
|
+
margin: "0 auto",
|
|
81
|
+
padding: "2rem 1.5rem",
|
|
82
|
+
width: "100%"
|
|
83
|
+
}, ye = (e) => {
|
|
84
|
+
let { brand: t, topNav: n, children: r, pathname: i, footer: a, breadcrumbs: o, headerRight: s } = e, c = e.Link ?? $, l = Y("nav", {
|
|
85
|
+
className: "voltro-blog-nav",
|
|
86
|
+
style: {
|
|
87
|
+
display: "flex",
|
|
88
|
+
gap: "1rem",
|
|
89
|
+
alignItems: "center"
|
|
90
|
+
}
|
|
91
|
+
}, ...n.map((e) => {
|
|
92
|
+
let t = i === e.href;
|
|
93
|
+
return Y(c, {
|
|
94
|
+
key: e.href,
|
|
95
|
+
to: e.href,
|
|
96
|
+
className: t ? "voltro-blog-nav-link is-active" : "voltro-blog-nav-link",
|
|
97
|
+
children: e.label
|
|
98
|
+
});
|
|
99
|
+
})), u = Y("header", {
|
|
100
|
+
className: "voltro-blog-header",
|
|
101
|
+
style: _e
|
|
102
|
+
}, Y("div", { className: "voltro-blog-brand" }, t), s ? Y("div", { style: {
|
|
103
|
+
display: "flex",
|
|
104
|
+
gap: "1rem",
|
|
105
|
+
alignItems: "center"
|
|
106
|
+
} }, l, s) : l), d = o && o.length > 0 ? Y("nav", {
|
|
107
|
+
className: "voltro-blog-breadcrumbs",
|
|
108
|
+
"aria-label": "Breadcrumb",
|
|
109
|
+
style: {
|
|
110
|
+
fontSize: "0.85rem",
|
|
111
|
+
opacity: .75,
|
|
112
|
+
marginBottom: "1rem",
|
|
113
|
+
display: "flex",
|
|
114
|
+
gap: "0.5rem"
|
|
115
|
+
}
|
|
116
|
+
}, ...o.flatMap((e, t) => {
|
|
117
|
+
let n = t === o.length - 1, r = e.href && !n ? Y(c, {
|
|
118
|
+
key: `c${t}`,
|
|
119
|
+
to: e.href,
|
|
120
|
+
children: e.label
|
|
121
|
+
}) : Y("span", {
|
|
122
|
+
key: `c${t}`,
|
|
123
|
+
"aria-current": n ? "page" : void 0
|
|
124
|
+
}, e.label);
|
|
125
|
+
return n ? [r] : [r, Y("span", { key: `s${t}` }, "/")];
|
|
126
|
+
})) : null;
|
|
127
|
+
return Y("div", { className: "voltro-blog-layout" }, u, Y("main", {
|
|
128
|
+
className: "voltro-blog-main",
|
|
129
|
+
style: ve
|
|
130
|
+
}, d, r), a ? Y("footer", {
|
|
131
|
+
className: "voltro-blog-footer",
|
|
132
|
+
style: {
|
|
133
|
+
maxWidth: "48rem",
|
|
134
|
+
margin: "0 auto",
|
|
135
|
+
padding: "2rem 1.5rem",
|
|
136
|
+
borderTop: "1px solid var(--voltro-blog-border, rgba(127,127,127,0.2))"
|
|
137
|
+
}
|
|
138
|
+
}, a) : null);
|
|
139
|
+
}, be = "framework-web";
|
|
140
|
+
//#endregion
|
|
141
|
+
export { e as AppClientsContext, ye as BlogLayout, f as FallbackStringsProvider, ge as Image, me as ImageConfigProvider, W as Link, q as LoaderCache, P as LoaderDataContext, r as NavigationIndicator, w as NotFoundError, ae as PlainLink, a as ReconnectContext, E as RedirectError, oe as Router, F as RouterContext, J as ServerRequestContext, U as ServerRequestProvider, be as WEB_NAME, I as compileRoute, u as defaultFallbackStrings, G as externalUrl, H as findNotFound, s as formatPrintf, _ as getIslandComponent, de as getRouteSnapshot, h as getStatuses, ee as hydrateIslandsOnPage, i as installBrowserConsoleBridge, n as installServerLogRelay, b as isNotFound, x as isRedirect, g as island, R as lazyPageRoute, L as loaderCacheKey, j as matchRoute, te as mount, S as notFound, se as pageRoute, K as parseCookieHeader, X as passthroughImageLoader, ue as preloadRouteModule, d as pushStatus, D as redirect, o as registerClientTrace, N as resolveAnchorNavigation, le as resolveMeta, O as segmentLoaderKey, re as setRouteSnapshot, ie as sortRoutesByPriority, A as subscribeRouteSnapshot, p as subscribeStatuses, c as subscribeTraceErrors, t as useAppClient, ce as useBlocker, m as useFallbackStrings, k as useLoaderData, y as useLocation, v as useNavigate, T as useParams, V as usePrefetch, l as useReconnect, z as useSearchParams, M as useServerRequest, ne as useSetSearchParams, B as withHash, C as withQuery };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { t as e } from "./frameworkBoot-DBOFujAI.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 };
|
package/dist/mount.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
import { Rpc } from '@effect/rpc';
|
|
3
|
+
import { RpcGroup } from '@effect/rpc';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Boot the framework's React stack against the given app. Resolves the
|
|
7
|
+
* typed rpc client for each api in parallel, renders the user's component
|
|
8
|
+
* tree inside the framework runtime + clients providers, and in dev mode
|
|
9
|
+
* auto-recovers each client in-place when its dev server restarts.
|
|
10
|
+
*/
|
|
11
|
+
export declare const mount: (App: ComponentType, options: MountOptions) => void;
|
|
12
|
+
|
|
13
|
+
export declare interface MountApiSpec<Rpcs extends Rpc.Any = Rpc.Any> {
|
|
14
|
+
/** The RpcGroup this api speaks. */
|
|
15
|
+
readonly group: RpcGroup.RpcGroup<Rpcs>;
|
|
16
|
+
/** Per-rpc-tag descriptor metadata: `{ kind, source?, targets? }`. The
|
|
17
|
+
* framework's auto-optimistic flow reads this to know which mutation
|
|
18
|
+
* affects which cached query. The CLI's codegen emits it as
|
|
19
|
+
* `appDescriptors` next to `appGroup`. */
|
|
20
|
+
readonly descriptors?: Readonly<Record<string, {
|
|
21
|
+
readonly kind: 'query' | 'mutation' | 'action' | 'stream' | 'workflow';
|
|
22
|
+
readonly source?: string;
|
|
23
|
+
readonly targets?: ReadonlyArray<{
|
|
24
|
+
readonly table: string;
|
|
25
|
+
readonly op: 'insert' | 'update' | 'delete';
|
|
26
|
+
readonly order?: 'prepend' | 'append';
|
|
27
|
+
}>;
|
|
28
|
+
}>>;
|
|
29
|
+
/** Explicit WebSocket URL for this api. Required for external apis
|
|
30
|
+
* (where there's no Vite proxy). Defaults to same-origin `/ws/<name>`
|
|
31
|
+
* for workspace apis served via the framework's dev proxy. */
|
|
32
|
+
readonly wsUrl?: string;
|
|
33
|
+
/** Auth headers sent with EVERY rpc request over the socket — this is how
|
|
34
|
+
* a cross-origin api authenticates WS subscriptions. They ride in the
|
|
35
|
+
* @effect/rpc message frame, NOT the WS handshake (a browser can't set
|
|
36
|
+
* upgrade headers). Pass a thunk to fetch a rotating token fresh on every
|
|
37
|
+
* (re)connect, e.g. `headers: async () => ({ authorization: 'Bearer ' +
|
|
38
|
+
* (await supabase.auth.getSession()).data.session?.access_token })`; a
|
|
39
|
+
* static object is also accepted. Do NOT hardcode a secret literal — it
|
|
40
|
+
* ships to the client and is visible in source; resolve it at runtime. */
|
|
41
|
+
readonly headers?: ResolvableHeaders;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare interface MountOptions {
|
|
45
|
+
/** Map of api name → spec. The name is the lookup key for hooks
|
|
46
|
+
* (`useAppClient<T>(name)`, `useSubscription(name, ...)`, etc.). */
|
|
47
|
+
readonly apis: Record<string, MountApiSpec>;
|
|
48
|
+
/** Override the root element id. Defaults to 'root'. */
|
|
49
|
+
readonly rootId?: string;
|
|
50
|
+
/** Optional in-page devtools overlay component. Wired up by the
|
|
51
|
+
* CLI's generated `main.tsx` when `import.meta.env.DEV` is truthy
|
|
52
|
+
* and the app hasn't set `disableDevtools` in app.config.ts.
|
|
53
|
+
* Renders INSIDE the FrameworkBoot tree so its hooks
|
|
54
|
+
* (useFrameworkRuntimes, useLoaderData, …) resolve normally.
|
|
55
|
+
* PascalCase because it is a React component reference rendered
|
|
56
|
+
* as <Devtools/>. */
|
|
57
|
+
readonly Devtools?: ComponentType;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Auth headers for an api's WS rpc client. @effect/rpc sends these in the
|
|
62
|
+
* per-request MESSAGE frame (NOT the WS upgrade — a browser can't set upgrade
|
|
63
|
+
* headers), so the server's AuthMiddleware sees them on every call; this is
|
|
64
|
+
* what lets a cross-origin api authenticate WS subscriptions. A thunk is
|
|
65
|
+
* resolved fresh on every (re)connect, so a rotating token (e.g. a Supabase
|
|
66
|
+
* access token) is pulled anew per connect instead of freezing at first mount.
|
|
67
|
+
*/
|
|
68
|
+
declare type ResolvableHeaders = Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
|
|
69
|
+
|
|
70
|
+
export { }
|
package/dist/mount.js
ADDED