@mauroandre/velojs 0.0.51 → 0.0.52
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/agent/skills/velojs-boot-state/SKILL.md +82 -0
- package/dist/components.d.ts +39 -0
- package/dist/components.js +44 -33
- package/dist/hooks.d.ts +24 -0
- package/dist/hooks.js +49 -45
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -8
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: velojs-boot-state
|
|
3
|
+
description: "Load localStorage/cookies BEFORE the first paint with `<Boot>` in client-root and read them with `useBoot()` — flicker-free themes, sidebars, and layout preferences. Use when UI state from the browser flashes on reload or when persisting layout preferences."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Boot state (pre-paint loading)
|
|
7
|
+
|
|
8
|
+
State stored in the browser (theme, collapsed sidebar, panel sizes) causes a flash on reload: the SSR HTML paints with defaults, then client JS corrects it — one visible frame of the wrong layout. The only code that runs between the `<head>` being parsed and the `<body>` being painted is a **synchronous inline script in the head**. `<Boot>` generates that script for you.
|
|
9
|
+
|
|
10
|
+
## Declaring what to load
|
|
11
|
+
|
|
12
|
+
In `client-root.tsx`, declare each storage separately with the exact key names your app uses:
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { Boot, Scripts } from "@mauroandre/velojs";
|
|
16
|
+
|
|
17
|
+
export const Component = ({ children }) => (
|
|
18
|
+
<html>
|
|
19
|
+
<head>
|
|
20
|
+
<Boot localStorage={["theme", "sidebarHidden"]} />
|
|
21
|
+
<Boot cookies={["org"]} />
|
|
22
|
+
</head>
|
|
23
|
+
<body>
|
|
24
|
+
{children}
|
|
25
|
+
<Scripts />
|
|
26
|
+
</body>
|
|
27
|
+
</html>
|
|
28
|
+
);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The generated script runs before the first paint and does two things:
|
|
32
|
+
|
|
33
|
+
1. Populates `window.__VELO_BOOT__ = { theme: "dark", sidebarHidden: "true" }` — only keys that exist; absent keys stay out.
|
|
34
|
+
2. Mirrors each found key as a sanitized `data-*` attribute on `<html>`: `data-theme="dark"`, `data-sidebar-hidden`... Key sanitization: anything outside `[a-zA-Z0-9-]` becomes `-` — `"bc:terminal-colapsado"` → `data-bc-terminal-colapsado`.
|
|
35
|
+
|
|
36
|
+
## Reading
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { useBoot } from "@mauroandre/velojs/hooks";
|
|
40
|
+
|
|
41
|
+
const { theme, sidebarHidden } = useBoot();
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Values are **raw strings**, immutable by definition — the boot happened once. Seed your own signal with them for reactivity (`signal(boot.sidebarHidden === "true")`); parse numbers/JSON yourself.
|
|
45
|
+
|
|
46
|
+
On the server `useBoot()` returns `{}` — SSR always renders defaults, never touches `window`.
|
|
47
|
+
|
|
48
|
+
## The anti-flicker contract (the part that matters)
|
|
49
|
+
|
|
50
|
+
**Visual state must be CSS reacting to the mirrored data-attribute — never conditional JSX.**
|
|
51
|
+
|
|
52
|
+
```css
|
|
53
|
+
html[data-theme="dark"] { --color-surface: #11151f; }
|
|
54
|
+
html[data-sidebar-hidden="true"] .sidebar { display: none; }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- ✅ Always render the sidebar in the vdom; hide it with CSS on the attribute. The attribute is correct **before the first paint** → single correct paint, no flash, no hydration mismatch.
|
|
58
|
+
- ❌ `{!sidebarHidden && <Sidebar />}` — the client's first render diverges from the SSR DOM (hydration mismatch) and only corrects **after** paint: the flash is back.
|
|
59
|
+
|
|
60
|
+
A CSS `transition` on the mirrored property does not fire on load (the attribute is set before the first style computation) — transitions only run on interactive toggles, which is what you want.
|
|
61
|
+
|
|
62
|
+
## Writing is the app's business
|
|
63
|
+
|
|
64
|
+
`<Boot>` only loads. Persisting on change is a signal + storage write in your gestures:
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
const sidebarHidden = signal(/* seeded from useBoot */);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
document.documentElement.dataset.sidebarHidden = String(sidebarHidden.value);
|
|
70
|
+
localStorage.setItem("sidebarHidden", String(sidebarHidden.value));
|
|
71
|
+
}, [sidebarHidden.value]);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Reference
|
|
75
|
+
|
|
76
|
+
| Piece | Behavior |
|
|
77
|
+
|-------|----------|
|
|
78
|
+
| `<Boot localStorage={[...]} />` | Inline pre-paint script; one `<Boot>` per storage |
|
|
79
|
+
| `<Boot cookies={[...]} />` | Same, from `document.cookie` |
|
|
80
|
+
| `useBoot()` | `Record<string, string>` — `{}` on the server, boot values on the client |
|
|
81
|
+
| Key `a:b` in storage | Attribute `data-a-b`; object key stays `"a:b"` |
|
|
82
|
+
| Storage throws (private mode) | Script is a no-op — app renders defaults |
|
package/dist/components.d.ts
CHANGED
|
@@ -29,6 +29,45 @@ interface ScriptsProps {
|
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
31
|
export declare function Scripts({ basePath, favicon }?: ScriptsProps): import("preact").JSX.Element;
|
|
32
|
+
interface BootProps {
|
|
33
|
+
/**
|
|
34
|
+
* localStorage keys to load before the first paint. The value of each
|
|
35
|
+
* key found is exposed on `window.__VELO_BOOT__` and mirrored as a
|
|
36
|
+
* sanitized `data-*` attribute on `<html>` — CSS reacting to the
|
|
37
|
+
* attribute is what makes the first paint flicker-free.
|
|
38
|
+
*/
|
|
39
|
+
localStorage?: string[];
|
|
40
|
+
/**
|
|
41
|
+
* Cookie names to load before the first paint (same exposure/mirroring
|
|
42
|
+
* as localStorage keys). Declare storages separately: one Boot per
|
|
43
|
+
* storage keeps each script minimal.
|
|
44
|
+
*/
|
|
45
|
+
cookies?: string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Generates the pre-paint boot script. Pure and isomorphic — Boot must
|
|
49
|
+
* render the SAME string on server and client so hydration matches.
|
|
50
|
+
* Exported for tests.
|
|
51
|
+
*/
|
|
52
|
+
export declare function bootScript({ localStorage: lsKeys, cookies: ckKeys }?: BootProps): string;
|
|
53
|
+
/**
|
|
54
|
+
* Declares client state to load BEFORE the first paint. Place it in the
|
|
55
|
+
* `<head>` of client-root — a synchronous inline script is the only code
|
|
56
|
+
* that runs between the head being parsed and the body being painted, so
|
|
57
|
+
* values it mirrors as data-attributes produce a single, correct paint.
|
|
58
|
+
*
|
|
59
|
+
* Reading: `useBoot()` destructures by the declared names.
|
|
60
|
+
* Writing/persisting stays with the app (signals + storage in its gestures).
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <head>
|
|
65
|
+
* <Boot localStorage={["theme", "sidebarHidden"]} />
|
|
66
|
+
* <Boot cookies={["org"]} />
|
|
67
|
+
* </head>
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function Boot(props: BootProps): import("preact").JSX.Element | null;
|
|
32
71
|
import type { ComponentProps } from "preact";
|
|
33
72
|
import type { RouteModule } from "./types.js";
|
|
34
73
|
type WouterLinkProps = ComponentProps<typeof WouterLink>;
|
package/dist/components.js
CHANGED
|
@@ -1,58 +1,69 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useRouter as
|
|
1
|
+
import { jsx as r, jsxs as p, Fragment as g } from "preact/jsx-runtime";
|
|
2
|
+
import { useRouter as L, Link as $ } from "wouter-preact";
|
|
3
3
|
import "@preact/signals";
|
|
4
4
|
import "preact/hooks";
|
|
5
5
|
import { __veloUpdatePending as C } from "./loader-store.js";
|
|
6
|
-
function
|
|
6
|
+
function w({ basePath: t, favicon: e = "/favicon.ico" } = {}) {
|
|
7
7
|
const n = process.env.NODE_ENV !== "production";
|
|
8
|
-
|
|
9
|
-
const
|
|
8
|
+
t = t || process.env.STATIC_BASE_URL || (process.env.VELO_STATIC ? "/client" : "");
|
|
9
|
+
const s = e === !1 ? void 0 : e.endsWith(".svg") ? "image/svg+xml" : e.endsWith(".png") ? "image/png" : "image/x-icon", i = e !== !1 && /* @__PURE__ */ r("link", { rel: "icon", href: `${t}${e}`, type: s });
|
|
10
10
|
if (n)
|
|
11
|
-
return /* @__PURE__ */
|
|
11
|
+
return /* @__PURE__ */ p(g, { children: [
|
|
12
12
|
i,
|
|
13
|
-
/* @__PURE__ */
|
|
14
|
-
/* @__PURE__ */
|
|
13
|
+
/* @__PURE__ */ r("script", { type: "module", src: "/@vite/client" }),
|
|
14
|
+
/* @__PURE__ */ r("script", { type: "module", src: "/__velo_client.js" })
|
|
15
15
|
] });
|
|
16
|
-
const
|
|
17
|
-
return /* @__PURE__ */
|
|
16
|
+
const c = globalThis.__veloClientJs || (typeof __VELO_CLIENT_JS__ < "u" ? __VELO_CLIENT_JS__ : "client.js"), l = globalThis.__veloClientCss || (typeof __VELO_CLIENT_CSS__ < "u" ? __VELO_CLIENT_CSS__ : "client.css");
|
|
17
|
+
return /* @__PURE__ */ p(g, { children: [
|
|
18
18
|
i,
|
|
19
|
-
/* @__PURE__ */
|
|
20
|
-
/* @__PURE__ */
|
|
19
|
+
/* @__PURE__ */ r("link", { rel: "stylesheet", href: `${t}/${l}` }),
|
|
20
|
+
/* @__PURE__ */ r("script", { type: "module", src: `${t}/${c}` })
|
|
21
21
|
] });
|
|
22
22
|
}
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
for (
|
|
26
|
-
|
|
23
|
+
function S({ localStorage: t, cookies: e } = {}) {
|
|
24
|
+
if ((!t || t.length === 0) && (!e || e.length === 0)) return "";
|
|
25
|
+
const n = (c) => JSON.stringify(c).replace(/</g, "\\u003c"), s = t && t.length > 0 ? `var L=${n(t)};for(var i=0;i<L.length;i++){var v=localStorage.getItem(L[i]);if(v!==null)b[L[i]]=v;}` : "", i = e && e.length > 0 ? `var C=${n(e)};var s=document.cookie?document.cookie.split("; "):[];var m={};for(var j=0;j<s.length;j++){var p=s[j].indexOf("=");if(p>0){m[s[j].slice(0,p)]=decodeURIComponent(s[j].slice(p+1));}}for(var k=0;k<C.length;k++){if(C[k]in m)b[C[k]]=m[C[k]];}` : "";
|
|
26
|
+
return `(function(){var b={};try{${s}}catch(e){}try{${i}}catch(e){}if(Object.keys(b).length){window.__VELO_BOOT__=Object.assign(window.__VELO_BOOT__||{},b);var d=document.documentElement;for(var q in b){d.setAttribute("data-"+String(q).replace(/[^a-zA-Z0-9-]/g,"-"),b[q]);}}})();`;
|
|
27
|
+
}
|
|
28
|
+
function y(t) {
|
|
29
|
+
const e = S(t);
|
|
30
|
+
return e ? /* @__PURE__ */ r("script", { dangerouslySetInnerHTML: { __html: e } }) : null;
|
|
31
|
+
}
|
|
32
|
+
function m(t, e) {
|
|
33
|
+
let n = t;
|
|
34
|
+
for (const [s, i] of Object.entries(e))
|
|
35
|
+
n = n.replace(`:${s}`, i);
|
|
27
36
|
return n;
|
|
28
37
|
}
|
|
29
|
-
function I({ to:
|
|
30
|
-
const
|
|
38
|
+
function I({ to: t, params: e, search: n, absolute: s, ...i }) {
|
|
39
|
+
const c = typeof t != "string", l = L(), _ = c ? t.metadata?.fullPath ?? "/" : t, f = e ? m(_, e) : _, u = n ? `?${new URLSearchParams(n).toString()}` : "", v = `${f}${u}`;
|
|
31
40
|
if (typeof window < "u" && C.value) {
|
|
32
|
-
let
|
|
33
|
-
if (
|
|
34
|
-
const
|
|
35
|
-
|
|
41
|
+
let a;
|
|
42
|
+
if (c) {
|
|
43
|
+
const o = t.metadata?.fullPath ?? _;
|
|
44
|
+
a = `${e ? m(o, e) : o}${u}`;
|
|
36
45
|
} else {
|
|
37
|
-
const
|
|
38
|
-
|
|
46
|
+
const o = f.replace(/^~/, "");
|
|
47
|
+
a = `${!f.startsWith("~") && l.base ? l.base : ""}${o}${u}`;
|
|
39
48
|
}
|
|
40
|
-
const { onClick:
|
|
41
|
-
return /* @__PURE__ */
|
|
49
|
+
const { onClick: d, ...h } = i;
|
|
50
|
+
return /* @__PURE__ */ r(
|
|
42
51
|
"a",
|
|
43
52
|
{
|
|
44
|
-
href:
|
|
45
|
-
onClick: (
|
|
46
|
-
|
|
53
|
+
href: a,
|
|
54
|
+
onClick: (o) => {
|
|
55
|
+
d && d(o), o.defaultPrevented || (o.preventDefault(), window.location.href = a);
|
|
47
56
|
},
|
|
48
|
-
...
|
|
57
|
+
...h
|
|
49
58
|
}
|
|
50
59
|
);
|
|
51
60
|
}
|
|
52
|
-
return /* @__PURE__ */
|
|
61
|
+
return /* @__PURE__ */ r($, { to: v, ...i });
|
|
53
62
|
}
|
|
54
63
|
export {
|
|
64
|
+
y as Boot,
|
|
55
65
|
I as Link,
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
w as Scripts,
|
|
67
|
+
S as bootScript,
|
|
68
|
+
m as substituteParams
|
|
58
69
|
};
|
package/dist/hooks.d.ts
CHANGED
|
@@ -3,6 +3,30 @@ import type { EventStream } from "./events.js";
|
|
|
3
3
|
import type { SocketHandler, SocketStub } from "./sockets.js";
|
|
4
4
|
import { __veloUpdatePending } from "./loader-store.js";
|
|
5
5
|
export { __veloUpdatePending };
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
/** Populated by <Boot>'s pre-paint script — see components.tsx. */
|
|
9
|
+
__VELO_BOOT__?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Reads the boot state loaded before the first paint by `<Boot>`.
|
|
14
|
+
*
|
|
15
|
+
* Values are raw strings, immutable by definition (the boot happened once —
|
|
16
|
+
* state evolves through the app's own signals, seeded with these values).
|
|
17
|
+
* On the server it returns an empty object: there is no window to read.
|
|
18
|
+
*
|
|
19
|
+
* The anti-flicker contract: visual state derived from these values must be
|
|
20
|
+
* CSS reacting to the mirrored data-attributes on `<html>`, not conditional
|
|
21
|
+
* JSX — the attribute is correct before the first paint, a conditional
|
|
22
|
+
* render only corrects after hydration.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* const { theme, sidebarHidden } = useBoot();
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function useBoot(): Record<string, string>;
|
|
6
30
|
/**
|
|
7
31
|
* Força o signal a notificar mudanças após mutação de propriedades aninhadas
|
|
8
32
|
*
|
package/dist/hooks.js
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
|
-
import { signal as
|
|
2
|
-
import { useEffect as E, useRef as
|
|
3
|
-
import { useLocation as
|
|
4
|
-
import { refetchModule as
|
|
1
|
+
import { signal as w, useSignal as u } from "@preact/signals";
|
|
2
|
+
import { useEffect as E, useRef as S } from "preact/hooks";
|
|
3
|
+
import { useLocation as b, useParams as O, useSearch as $ } from "wouter-preact";
|
|
4
|
+
import { refetchModule as D, loaderLoading as m, loaderEntry as N } from "./loader-store.js";
|
|
5
5
|
import { __veloUpdatePending as z } from "./loader-store.js";
|
|
6
|
-
function U(
|
|
6
|
+
function U() {
|
|
7
|
+
return typeof window > "u" ? {} : window.__VELO_BOOT__ ?? {};
|
|
8
|
+
}
|
|
9
|
+
function W(e) {
|
|
7
10
|
const n = e.value;
|
|
8
11
|
n === null || typeof n != "object" || (e.value = Array.isArray(n) ? [...n] : { ...n });
|
|
9
12
|
}
|
|
10
|
-
function
|
|
13
|
+
function j(e) {
|
|
11
14
|
return typeof window > "u" ? {
|
|
12
15
|
data: {
|
|
13
16
|
get value() {
|
|
14
17
|
return e ? globalThis.__veloServerData?.getStore?.()?.[e] ?? null : null;
|
|
15
18
|
}
|
|
16
19
|
},
|
|
17
|
-
loading:
|
|
20
|
+
loading: w(!1),
|
|
18
21
|
refetch: () => {
|
|
19
22
|
}
|
|
20
23
|
} : e ? {
|
|
21
24
|
data: N(e),
|
|
22
25
|
loading: m(e),
|
|
23
|
-
refetch: () =>
|
|
24
|
-
} : { data:
|
|
26
|
+
refetch: () => D(e)
|
|
27
|
+
} : { data: w(null), loading: w(!1), refetch: () => {
|
|
25
28
|
} };
|
|
26
29
|
}
|
|
27
|
-
function
|
|
30
|
+
function B(e, n) {
|
|
28
31
|
let t, r;
|
|
29
32
|
if (Array.isArray(e) ? r = e : (t = e, r = n), typeof window > "u") {
|
|
30
33
|
let g = null;
|
|
@@ -33,40 +36,40 @@ function j(e, n) {
|
|
|
33
36
|
h?.[t] && (g = h[t]);
|
|
34
37
|
}
|
|
35
38
|
return {
|
|
36
|
-
data:
|
|
37
|
-
loading:
|
|
39
|
+
data: u(g),
|
|
40
|
+
loading: u(!1),
|
|
38
41
|
refetch: () => {
|
|
39
42
|
}
|
|
40
43
|
};
|
|
41
44
|
}
|
|
42
45
|
if (!t)
|
|
43
|
-
return { data:
|
|
46
|
+
return { data: u(null), loading: u(!1), refetch: () => {
|
|
44
47
|
} };
|
|
45
|
-
const o = N(t), a = m(t),
|
|
48
|
+
const o = N(t), a = m(t), c = () => D(t), d = S(!0);
|
|
46
49
|
return E(() => {
|
|
47
|
-
d.current && (d.current = !1, o.value !== null) ||
|
|
48
|
-
}, r ?? []), { data: o, loading: a, refetch:
|
|
50
|
+
d.current && (d.current = !1, o.value !== null) || c();
|
|
51
|
+
}, r ?? []), { data: o, loading: a, refetch: c };
|
|
49
52
|
}
|
|
50
53
|
function J() {
|
|
51
|
-
const [, e] =
|
|
54
|
+
const [, e] = b();
|
|
52
55
|
return e;
|
|
53
56
|
}
|
|
54
57
|
function M() {
|
|
55
|
-
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__params ?? {} :
|
|
58
|
+
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__params ?? {} : O();
|
|
56
59
|
}
|
|
57
60
|
function q() {
|
|
58
61
|
if (typeof window > "u")
|
|
59
62
|
return globalThis.__veloServerData?.getStore?.()?.__query ?? {};
|
|
60
|
-
const e =
|
|
63
|
+
const e = $(), n = {};
|
|
61
64
|
return new URLSearchParams(e).forEach((t, r) => {
|
|
62
65
|
n[r] = t;
|
|
63
66
|
}), n;
|
|
64
67
|
}
|
|
65
68
|
function x() {
|
|
66
|
-
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__pathname ?? "/" : (
|
|
69
|
+
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__pathname ?? "/" : (b(), window.location.pathname);
|
|
67
70
|
}
|
|
68
71
|
function G(e, n = {}) {
|
|
69
|
-
const t =
|
|
72
|
+
const t = u(null), r = u(null), o = u(!1), a = u(null), { channel: c, enabled: d = !0 } = n;
|
|
70
73
|
return E(() => {
|
|
71
74
|
if (typeof window > "u" || !d) return;
|
|
72
75
|
if (!e.__path) {
|
|
@@ -74,18 +77,18 @@ function G(e, n = {}) {
|
|
|
74
77
|
return;
|
|
75
78
|
}
|
|
76
79
|
t.value = null, r.value = null, o.value = !1, a.value = null;
|
|
77
|
-
const g =
|
|
80
|
+
const g = c ? `${e.__path}?channel=${encodeURIComponent(c)}` : e.__path, s = new EventSource(g);
|
|
78
81
|
return s.addEventListener("snapshot", (h) => {
|
|
79
82
|
try {
|
|
80
83
|
r.value = JSON.parse(h.data);
|
|
81
|
-
} catch (
|
|
82
|
-
a.value =
|
|
84
|
+
} catch (y) {
|
|
85
|
+
a.value = y;
|
|
83
86
|
}
|
|
84
87
|
}), s.addEventListener("message", (h) => {
|
|
85
88
|
try {
|
|
86
89
|
t.value = JSON.parse(h.data);
|
|
87
|
-
} catch (
|
|
88
|
-
a.value =
|
|
90
|
+
} catch (y) {
|
|
91
|
+
a.value = y;
|
|
89
92
|
}
|
|
90
93
|
}), s.addEventListener("heartbeat", () => {
|
|
91
94
|
}), s.addEventListener("close", () => {
|
|
@@ -95,12 +98,12 @@ function G(e, n = {}) {
|
|
|
95
98
|
}), () => {
|
|
96
99
|
s.close();
|
|
97
100
|
};
|
|
98
|
-
}, [e,
|
|
101
|
+
}, [e, c, d]), { data: t, snapshot: r, closed: o, error: a };
|
|
99
102
|
}
|
|
100
|
-
function
|
|
101
|
-
const t =
|
|
103
|
+
function F(e, n = {}) {
|
|
104
|
+
const t = u("connecting"), r = u(null), o = u(null), a = S(null), c = S([]), { channel: d, onMessage: g, onOpen: s, onClose: h, onError: y, enabled: L = !0 } = n;
|
|
102
105
|
return E(() => {
|
|
103
|
-
if (typeof window > "u" || !
|
|
106
|
+
if (typeof window > "u" || !L) return;
|
|
104
107
|
if (!e.__path) {
|
|
105
108
|
console.warn("[velojs] useSocket: stub has no __path");
|
|
106
109
|
return;
|
|
@@ -109,27 +112,27 @@ function B(e, n = {}) {
|
|
|
109
112
|
const v = `${window.location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}`, i = d ? `${v}${e.__path}?channel=${encodeURIComponent(d)}` : `${v}${e.__path}`, f = new WebSocket(i);
|
|
110
113
|
return f.binaryType = "arraybuffer", a.current = f, f.addEventListener("open", () => {
|
|
111
114
|
t.value = "open";
|
|
112
|
-
const l =
|
|
113
|
-
|
|
114
|
-
for (const
|
|
115
|
+
const l = c.current;
|
|
116
|
+
c.current = [];
|
|
117
|
+
for (const _ of l)
|
|
115
118
|
try {
|
|
116
|
-
f.send(
|
|
119
|
+
f.send(_);
|
|
117
120
|
} catch {
|
|
118
121
|
}
|
|
119
122
|
s?.();
|
|
120
123
|
}), f.addEventListener("message", (l) => {
|
|
121
|
-
let
|
|
124
|
+
let _;
|
|
122
125
|
if (typeof l.data == "string")
|
|
123
|
-
|
|
126
|
+
_ = l.data;
|
|
124
127
|
else if (l.data instanceof ArrayBuffer)
|
|
125
|
-
|
|
128
|
+
_ = new Uint8Array(l.data);
|
|
126
129
|
else
|
|
127
130
|
return;
|
|
128
|
-
r.value =
|
|
131
|
+
r.value = _, g?.(_);
|
|
129
132
|
}), f.addEventListener("close", (l) => {
|
|
130
133
|
t.value = "closed", a.current = null, h?.(l);
|
|
131
134
|
}), f.addEventListener("error", (l) => {
|
|
132
|
-
o.value = l,
|
|
135
|
+
o.value = l, y?.(l);
|
|
133
136
|
}), () => {
|
|
134
137
|
a.current = null;
|
|
135
138
|
try {
|
|
@@ -137,7 +140,7 @@ function B(e, n = {}) {
|
|
|
137
140
|
} catch {
|
|
138
141
|
}
|
|
139
142
|
};
|
|
140
|
-
}, [e.__path, d,
|
|
143
|
+
}, [e.__path, d, L]), { send: (p) => {
|
|
141
144
|
let v;
|
|
142
145
|
typeof p == "string" || p instanceof Uint8Array ? v = p : v = JSON.stringify(p);
|
|
143
146
|
const i = a.current;
|
|
@@ -146,7 +149,7 @@ function B(e, n = {}) {
|
|
|
146
149
|
i.send(v);
|
|
147
150
|
} catch {
|
|
148
151
|
}
|
|
149
|
-
else i && i.readyState === WebSocket.CONNECTING &&
|
|
152
|
+
else i && i.readyState === WebSocket.CONNECTING && c.current.push(v);
|
|
150
153
|
}, close: (p, v) => {
|
|
151
154
|
const i = a.current;
|
|
152
155
|
if (i)
|
|
@@ -157,14 +160,15 @@ function B(e, n = {}) {
|
|
|
157
160
|
}, status: t, lastMessage: r, error: o };
|
|
158
161
|
}
|
|
159
162
|
export {
|
|
160
|
-
|
|
163
|
+
j as Loader,
|
|
161
164
|
z as __veloUpdatePending,
|
|
162
|
-
|
|
165
|
+
W as touch,
|
|
166
|
+
U as useBoot,
|
|
163
167
|
G as useEventStream,
|
|
164
|
-
|
|
168
|
+
B as useLoader,
|
|
165
169
|
J as useNavigate,
|
|
166
170
|
M as useParams,
|
|
167
171
|
x as usePathname,
|
|
168
172
|
q as useQuery,
|
|
169
|
-
|
|
173
|
+
F as useSocket
|
|
170
174
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { AppRoutes, RouteNode, RouteModule, LoaderArgs, ActionArgs, Metadata, HTTPMethod, EndpointHandler, EndpointHandlerArgs, } from "./types.js";
|
|
2
2
|
export type { VeloConfig } from "./config.js";
|
|
3
3
|
export { defineConfig } from "./config.js";
|
|
4
|
-
export { Scripts, Link } from "./components.js";
|
|
4
|
+
export { Scripts, Link, Boot } from "./components.js";
|
|
5
5
|
export { createEventStream, poll } from "./events.js";
|
|
6
6
|
export type { EventStream, EventStreamConfig, EmitFn, EmitOptions, SourceFn, PerChannelSourceFn, StreamPipeFn, StreamPipeArgs, ChannelResolver, } from "./events.js";
|
|
7
7
|
export type { SocketHandler, SocketHandlerArgs, SocketStub, } from "./sockets.js";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { defineConfig as
|
|
2
|
-
import {
|
|
3
|
-
import { createEventStream as
|
|
1
|
+
import { defineConfig as r } from "./config.js";
|
|
2
|
+
import { Boot as f, Link as p, Scripts as i } from "./components.js";
|
|
3
|
+
import { createEventStream as n, poll as x } from "./events.js";
|
|
4
4
|
export {
|
|
5
|
-
f as
|
|
6
|
-
p as
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
f as Boot,
|
|
6
|
+
p as Link,
|
|
7
|
+
i as Scripts,
|
|
8
|
+
n as createEventStream,
|
|
9
|
+
r as defineConfig,
|
|
10
|
+
x as poll
|
|
10
11
|
};
|