@mauroandre/velojs 0.0.54 → 0.0.56
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/README.md +332 -3
- package/agent/AGENTS.md +149 -0
- package/agent/skills/velojs-getting-started/SKILL.md +2 -0
- package/agent/skills/velojs-live-loader/SKILL.md +329 -0
- package/agent/skills/velojs-production-deploy/SKILL.md +6 -0
- package/agent/skills/velojs-server-api/SKILL.md +1 -0
- package/agent/skills/velojs-type-reference/SKILL.md +1 -0
- package/dist/channels.d.ts +289 -0
- package/dist/channels.js +283 -0
- package/dist/client.js +55 -45
- package/dist/components.js +7 -6
- package/dist/config.d.ts +5 -3
- package/dist/events.d.ts +6 -0
- package/dist/events.js +1 -0
- package/dist/hooks.d.ts +26 -21
- package/dist/hooks.js +117 -98
- package/dist/live-loader.d.ts +87 -0
- package/dist/live-loader.js +131 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +144 -118
- package/dist/testing/index.d.ts +5 -1
- package/dist/testing/index.js +507 -427
- package/dist/testing/subscription.d.ts +18 -2
- package/dist/testing/types.d.ts +68 -0
- package/dist/types.d.ts +9 -0
- package/dist/vite.d.ts +16 -1
- package/dist/vite.js +458 -359
- package/package.json +1 -1
package/dist/channels.js
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { DEFAULT_HEARTBEAT_MS as L } from "./events.js";
|
|
2
|
+
const O = "snapshot", R = "slice", U = "error", B = "close", k = 50, q = 3e5;
|
|
3
|
+
let m = {}, C = k, b = q, j = L, x = !0;
|
|
4
|
+
function ie(e, t) {
|
|
5
|
+
m = e ? { ...e } : {}, C = t?.coalesceMs ?? k, b = t?.idleMs ?? q, j = t?.heartbeatMs ?? L, x = t?.logEmits ?? !0, V();
|
|
6
|
+
}
|
|
7
|
+
function se() {
|
|
8
|
+
return m;
|
|
9
|
+
}
|
|
10
|
+
function ae() {
|
|
11
|
+
return Object.keys(m);
|
|
12
|
+
}
|
|
13
|
+
const d = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map();
|
|
14
|
+
function K(e, t) {
|
|
15
|
+
return `${e}\0${t}`;
|
|
16
|
+
}
|
|
17
|
+
function Q(e, t) {
|
|
18
|
+
const n = K(e, t);
|
|
19
|
+
if (v.has(n)) return;
|
|
20
|
+
const o = setTimeout(() => {
|
|
21
|
+
v.delete(n), G(e, t);
|
|
22
|
+
}, C), r = o.unref;
|
|
23
|
+
typeof r == "function" && r.call(o), v.set(n, { timer: o, channel: e, partition: t });
|
|
24
|
+
}
|
|
25
|
+
function V() {
|
|
26
|
+
for (const e of v.values()) clearTimeout(e.timer);
|
|
27
|
+
v.clear();
|
|
28
|
+
}
|
|
29
|
+
function le() {
|
|
30
|
+
const e = [];
|
|
31
|
+
let t = 0;
|
|
32
|
+
for (const [o, r] of d) {
|
|
33
|
+
const l = [];
|
|
34
|
+
for (const [f, u] of r) {
|
|
35
|
+
const a = /* @__PURE__ */ new Map();
|
|
36
|
+
for (const c of u) {
|
|
37
|
+
const s = a.get(c.moduleId) ?? { count: 0, last: void 0 };
|
|
38
|
+
s.count += 1, c.lastDeliveryAt !== void 0 && (s.last === void 0 || c.lastDeliveryAt > s.last) && (s.last = c.lastDeliveryAt), a.set(c.moduleId, s);
|
|
39
|
+
}
|
|
40
|
+
for (const [c, s] of a)
|
|
41
|
+
l.push({
|
|
42
|
+
moduleId: c,
|
|
43
|
+
partition: f,
|
|
44
|
+
connections: s.count,
|
|
45
|
+
lastDeliveryAt: s.last === void 0 ? null : new Date(s.last).toISOString()
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
e.push({
|
|
49
|
+
channel: o,
|
|
50
|
+
groups: l,
|
|
51
|
+
connections: z(r)
|
|
52
|
+
}), t += z(r);
|
|
53
|
+
}
|
|
54
|
+
const n = [];
|
|
55
|
+
for (const o of v.values())
|
|
56
|
+
n.push({ channel: o.channel, partition: o.partition });
|
|
57
|
+
return { channels: e, openCoalesceWindows: n, totalConnections: t };
|
|
58
|
+
}
|
|
59
|
+
function z(e) {
|
|
60
|
+
let t = 0;
|
|
61
|
+
for (const n of e.values()) t += n.size;
|
|
62
|
+
return t;
|
|
63
|
+
}
|
|
64
|
+
function X(e) {
|
|
65
|
+
let t = d.get(e.channel);
|
|
66
|
+
t || (t = /* @__PURE__ */ new Map(), d.set(e.channel, t));
|
|
67
|
+
let n = t.get(e.partition);
|
|
68
|
+
n || (n = /* @__PURE__ */ new Set(), t.set(e.partition, n)), n.add(e);
|
|
69
|
+
}
|
|
70
|
+
function Y(e) {
|
|
71
|
+
const t = d.get(e.channel), n = t?.get(e.partition);
|
|
72
|
+
!t || !n || (n.delete(e), n.size === 0 && t.delete(e.partition), t.size === 0 && d.delete(e.channel));
|
|
73
|
+
}
|
|
74
|
+
function ue() {
|
|
75
|
+
d.clear(), V();
|
|
76
|
+
}
|
|
77
|
+
async function $(e, t) {
|
|
78
|
+
const n = e.scope;
|
|
79
|
+
return typeof n != "function" ? "all" : await n(t);
|
|
80
|
+
}
|
|
81
|
+
function Z(e, t) {
|
|
82
|
+
return e.get(t);
|
|
83
|
+
}
|
|
84
|
+
async function H(e, t) {
|
|
85
|
+
const n = d.get(e)?.get(t);
|
|
86
|
+
if (!n || n.size === 0) return null;
|
|
87
|
+
const o = m[e], r = [];
|
|
88
|
+
for (const l of [...n]) {
|
|
89
|
+
let f;
|
|
90
|
+
try {
|
|
91
|
+
f = await $(o, l.principal);
|
|
92
|
+
} catch (u) {
|
|
93
|
+
console.error(`[velojs] channel "${e}" scope threw on emit:`, u), f = null;
|
|
94
|
+
}
|
|
95
|
+
if (f == null || f !== t) {
|
|
96
|
+
await l.terminate();
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
r.push(l);
|
|
100
|
+
}
|
|
101
|
+
return r.length > 0 ? r : null;
|
|
102
|
+
}
|
|
103
|
+
async function G(e, t) {
|
|
104
|
+
const n = await H(e, t);
|
|
105
|
+
n && await Promise.all(n.map((o) => J(o)));
|
|
106
|
+
}
|
|
107
|
+
async function J(e) {
|
|
108
|
+
let t;
|
|
109
|
+
try {
|
|
110
|
+
t = await e.loader({
|
|
111
|
+
params: e.params,
|
|
112
|
+
query: e.query,
|
|
113
|
+
c: e.c
|
|
114
|
+
});
|
|
115
|
+
} catch (n) {
|
|
116
|
+
await e.send(
|
|
117
|
+
U,
|
|
118
|
+
JSON.stringify({
|
|
119
|
+
message: n instanceof Error ? n.message : String(n)
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
t instanceof Response || await e.send(O, JSON.stringify(t ?? null));
|
|
125
|
+
}
|
|
126
|
+
function ce(e, t, n, o) {
|
|
127
|
+
return typeof e == "string" ? ee(e, t) : te(e, t, n, o);
|
|
128
|
+
}
|
|
129
|
+
async function ee(e, t) {
|
|
130
|
+
const n = m[e];
|
|
131
|
+
if (!n)
|
|
132
|
+
throw new Error(
|
|
133
|
+
`[velojs] emit("${e}"): this channel has no entry in app/channels.ts. Add one — a typo or a renamed channel would otherwise be a silent no-op.`
|
|
134
|
+
);
|
|
135
|
+
const o = await $(n, t), r = o == null ? 0 : d.get(e)?.get(o)?.size ?? 0;
|
|
136
|
+
if (W(e, o, "invalidate", r), o != null && r !== 0) {
|
|
137
|
+
if (C <= 0) {
|
|
138
|
+
await G(e, o);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
Q(e, o);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function te(e, t, n, o) {
|
|
145
|
+
const r = e?.metadata?.moduleId;
|
|
146
|
+
if (!r)
|
|
147
|
+
throw new Error(
|
|
148
|
+
`[velojs] emit(module, "${t}", …): the module has no metadata.moduleId — pass the imported route module (the Vite plugin injects its metadata), the same object the route tree uses.`
|
|
149
|
+
);
|
|
150
|
+
const l = e.channels;
|
|
151
|
+
if (!Array.isArray(l) || !l.includes(t))
|
|
152
|
+
throw new Error(
|
|
153
|
+
`[velojs] emit(module, "${t}", …): module "${r}" does not declare channel "${t}" — add it to the module's \`channels\` export, or use emit("${t}", ctx) for the invalidation mode.`
|
|
154
|
+
);
|
|
155
|
+
if (typeof e.loader != "function")
|
|
156
|
+
throw new Error(
|
|
157
|
+
`[velojs] emit(module, "${t}", …): module "${r}" has no \`loader\` — there is no data shape to slice.`
|
|
158
|
+
);
|
|
159
|
+
const f = m[t];
|
|
160
|
+
if (!f)
|
|
161
|
+
throw new Error(
|
|
162
|
+
`[velojs] emit(module, "${t}", …): this channel has no entry in app/channels.ts. Add one — a typo or a renamed channel would otherwise be a silent no-op.`
|
|
163
|
+
);
|
|
164
|
+
if (o === null || typeof o != "object" || Array.isArray(o))
|
|
165
|
+
throw new Error(
|
|
166
|
+
`[velojs] emit(module, "${t}", …): the slice must be the object of changed keys — got ${o === null ? "null" : Array.isArray(o) ? "an array" : typeof o}.`
|
|
167
|
+
);
|
|
168
|
+
const u = await $(f, n), a = u == null ? void 0 : d.get(t)?.get(u), c = a?.size ?? 0;
|
|
169
|
+
if (W(t, u, "slice", c), u == null || !a || c === 0) return;
|
|
170
|
+
const s = await H(t, u);
|
|
171
|
+
if (!s) return;
|
|
172
|
+
const y = s.filter((p) => p.moduleId === r);
|
|
173
|
+
if (y.length === 0) return;
|
|
174
|
+
const A = JSON.stringify(o);
|
|
175
|
+
await Promise.all(y.map((p) => p.send(R, A)));
|
|
176
|
+
}
|
|
177
|
+
function W(e, t, n, o) {
|
|
178
|
+
if (!x) return;
|
|
179
|
+
const r = typeof t == "string" ? `"${t}"` : "null";
|
|
180
|
+
console.log(
|
|
181
|
+
`[velojs] emit kind=${n} channel="${e}" partition=${r} connections=${o} at=${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
function ne(e, t) {
|
|
185
|
+
let n = Promise.resolve();
|
|
186
|
+
return (o) => (n = n.then(() => t(o)).then(() => {
|
|
187
|
+
}).catch((r) => {
|
|
188
|
+
console.warn(
|
|
189
|
+
`[velojs] channel "${e}": SSE write failed — the snapshot did not reach the client:`,
|
|
190
|
+
r
|
|
191
|
+
);
|
|
192
|
+
}), n);
|
|
193
|
+
}
|
|
194
|
+
function fe(e, t, n, o, r, l) {
|
|
195
|
+
if (typeof o.loader != "function")
|
|
196
|
+
throw new Error(
|
|
197
|
+
`[velojs] module "${r}" declares \`channels\` without a \`loader\` — there is nothing to synchronize. Add a loader or remove the export.`
|
|
198
|
+
);
|
|
199
|
+
if (!m[n])
|
|
200
|
+
throw new Error(
|
|
201
|
+
`[velojs] module "${r}" declares channel "${n}" with no entry in app/channels.ts — add the partition resolver for "${n}".`
|
|
202
|
+
);
|
|
203
|
+
const f = o.loader, u = async (a) => {
|
|
204
|
+
const c = m[n], s = Z(a, "user");
|
|
205
|
+
let y;
|
|
206
|
+
try {
|
|
207
|
+
y = await $(c, s);
|
|
208
|
+
} catch (E) {
|
|
209
|
+
return console.error(`[velojs] channel "${n}" scope threw:`, E), a.json({ error: "internal" }, 500);
|
|
210
|
+
}
|
|
211
|
+
if (y == null)
|
|
212
|
+
return a.json({ error: "forbidden" }, 403);
|
|
213
|
+
const { streamSSE: A } = await import("hono/streaming"), p = await A(a, async (E) => {
|
|
214
|
+
let w = !1, I = () => {
|
|
215
|
+
};
|
|
216
|
+
const F = new Promise((i) => {
|
|
217
|
+
I = i;
|
|
218
|
+
}), T = ne(
|
|
219
|
+
n,
|
|
220
|
+
(i) => typeof i == "string" ? E.write(i) : E.writeSSE(i)
|
|
221
|
+
), S = {
|
|
222
|
+
channel: n,
|
|
223
|
+
partition: y,
|
|
224
|
+
moduleId: r,
|
|
225
|
+
principal: s,
|
|
226
|
+
loader: f,
|
|
227
|
+
c: a,
|
|
228
|
+
params: a.req.param(),
|
|
229
|
+
query: a.req.query(),
|
|
230
|
+
send: (i, P) => w ? Promise.resolve() : i === O || i === R ? T({ event: i, data: P }).then(() => {
|
|
231
|
+
w || (S.lastDeliveryAt = Date.now(), _());
|
|
232
|
+
}) : T({ event: i, data: P }),
|
|
233
|
+
terminate: (i) => N(i)
|
|
234
|
+
}, M = () => {
|
|
235
|
+
w || (w = !0, h !== null && clearTimeout(h), g !== null && clearInterval(g), Y(S), I());
|
|
236
|
+
}, N = async (i = "partition") => {
|
|
237
|
+
w || (await S.send(B, JSON.stringify({ reason: i })), M());
|
|
238
|
+
};
|
|
239
|
+
let h = null;
|
|
240
|
+
const _ = () => {
|
|
241
|
+
if (b <= 0 || w) return;
|
|
242
|
+
h !== null && clearTimeout(h), h = setTimeout(() => {
|
|
243
|
+
h = null, N("idle");
|
|
244
|
+
}, b);
|
|
245
|
+
const i = h.unref;
|
|
246
|
+
typeof i == "function" && i.call(h);
|
|
247
|
+
};
|
|
248
|
+
let g = null;
|
|
249
|
+
if (j > 0 && (g = setInterval(() => {
|
|
250
|
+
w || T(`: ping
|
|
251
|
+
|
|
252
|
+
`);
|
|
253
|
+
}, j)), X(S), E.onAbort(M), _(), g !== null) {
|
|
254
|
+
const i = g.unref;
|
|
255
|
+
typeof i == "function" && i.call(g);
|
|
256
|
+
}
|
|
257
|
+
await J(S), await F;
|
|
258
|
+
}), D = new Headers(p.headers);
|
|
259
|
+
return D.set("Cache-Control", "no-store"), new Response(p.body, {
|
|
260
|
+
status: p.status,
|
|
261
|
+
statusText: p.statusText,
|
|
262
|
+
headers: D
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
l.length > 0 ? e.on(["GET"], [t], ...l, u) : e.on(["GET"], [t], u);
|
|
266
|
+
}
|
|
267
|
+
export {
|
|
268
|
+
B as CHANNEL_CLOSE_EVENT,
|
|
269
|
+
U as CHANNEL_ERROR_EVENT,
|
|
270
|
+
k as DEFAULT_COALESCE_MS,
|
|
271
|
+
q as DEFAULT_IDLE_MS,
|
|
272
|
+
R as SLICE_EVENT,
|
|
273
|
+
O as SNAPSHOT_EVENT,
|
|
274
|
+
ue as __resetChannels,
|
|
275
|
+
ae as channelNames,
|
|
276
|
+
ne as createChannelWriteChain,
|
|
277
|
+
ce as emit,
|
|
278
|
+
se as getChannelMap,
|
|
279
|
+
le as inspectChannels,
|
|
280
|
+
J as pushSnapshot,
|
|
281
|
+
fe as registerChannelRoute,
|
|
282
|
+
ie as registerChannels
|
|
283
|
+
};
|
package/dist/client.js
CHANGED
|
@@ -1,92 +1,102 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { hydrate as
|
|
3
|
-
import { Router as
|
|
4
|
-
import { useEffect as
|
|
1
|
+
import { jsxs as w, jsx as r } from "preact/jsx-runtime";
|
|
2
|
+
import { hydrate as x } from "preact";
|
|
3
|
+
import { Router as S, Route as f, Switch as y, useLocation as b } from "wouter-preact";
|
|
4
|
+
import { useEffect as B } from "preact/hooks";
|
|
5
5
|
import { registerRoutePatterns as L, syncLocation as W } from "./loader-store.js";
|
|
6
|
-
|
|
6
|
+
import { ChannelBoundary as v } from "./live-loader.js";
|
|
7
|
+
const l = (t, n, e) => n ? e && n === "/" ? t || "/" : n.startsWith("/") ? t + n : t + "/" + n : t, E = (t) => t === "" ? "*" : `${t}/*?`, I = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), M = (t) => {
|
|
7
8
|
let n = !1;
|
|
8
9
|
t.endsWith("/*?") && (t = t.slice(0, -3), n = !0);
|
|
9
|
-
const e = t.split("/").map((c) => c.startsWith(":") ? "[^/]+" :
|
|
10
|
+
const e = t.split("/").map((c) => c.startsWith(":") ? "[^/]+" : I(c)).join("/");
|
|
10
11
|
return n ? `${e}(?:/.*)?` : e;
|
|
11
|
-
},
|
|
12
|
+
}, d = (t, n) => {
|
|
12
13
|
if (t.path === "*") return [];
|
|
13
14
|
if (!t.module) {
|
|
14
|
-
const c =
|
|
15
|
-
return (t.children ?? []).flatMap((i) =>
|
|
15
|
+
const c = l(n, t.path, !1);
|
|
16
|
+
return (t.children ?? []).flatMap((i) => d(i, c));
|
|
16
17
|
}
|
|
17
18
|
if (!t.children)
|
|
18
|
-
return [
|
|
19
|
+
return [l(n, t.path, !0) || "/"];
|
|
19
20
|
if (t.path)
|
|
20
|
-
return [`${
|
|
21
|
-
const e =
|
|
22
|
-
return (t.children ?? []).flatMap((c) =>
|
|
21
|
+
return [`${l(n, t.path, !1)}/*?`];
|
|
22
|
+
const e = l(n, t.path, !1);
|
|
23
|
+
return (t.children ?? []).flatMap((c) => d(c, e));
|
|
23
24
|
}, _ = (t, n) => {
|
|
24
|
-
const e =
|
|
25
|
+
const e = d(t, n);
|
|
25
26
|
return new RegExp(`^(?:${e.map(M).join("|")})$`);
|
|
26
|
-
},
|
|
27
|
+
}, C = (t) => {
|
|
27
28
|
for (const n of t) {
|
|
28
29
|
if (n.path === "*" && n.module) return n.module.Component;
|
|
29
30
|
if (n.children) {
|
|
30
|
-
const e =
|
|
31
|
+
const e = C(n.children);
|
|
31
32
|
if (e) return e;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
return null;
|
|
35
|
-
},
|
|
36
|
+
}, R = (t, n) => n ? [...t, /* @__PURE__ */ r(f, { children: /* @__PURE__ */ r(n, {}) }, "__notfound")] : t, a = (t, n, e, c) => {
|
|
36
37
|
const i = [];
|
|
37
|
-
for (let
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
if (!
|
|
41
|
-
if (
|
|
42
|
-
const
|
|
43
|
-
i.push(...
|
|
38
|
+
for (let h = 0; h < t.length; h++) {
|
|
39
|
+
const o = t[h], s = `${c}${h}`;
|
|
40
|
+
if (o.path === "*") continue;
|
|
41
|
+
if (!o.module) {
|
|
42
|
+
if (o.children) {
|
|
43
|
+
const u = l(n, o.path, !1);
|
|
44
|
+
i.push(...a(o.children, u, e, `${s}-`));
|
|
44
45
|
}
|
|
45
46
|
continue;
|
|
46
47
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const p = o.module.Component, m = (u) => /* @__PURE__ */ r(
|
|
49
|
+
v,
|
|
50
|
+
{
|
|
51
|
+
moduleId: o.module?.metadata?.moduleId,
|
|
52
|
+
channels: o.module?.channels,
|
|
53
|
+
children: u
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
if (!o.children) {
|
|
57
|
+
const u = l(n, o.path, !0) || "/";
|
|
50
58
|
i.push(
|
|
51
|
-
/* @__PURE__ */
|
|
59
|
+
/* @__PURE__ */ r(f, { path: u, children: m(/* @__PURE__ */ r(p, {})) }, s)
|
|
52
60
|
);
|
|
53
61
|
continue;
|
|
54
62
|
}
|
|
55
|
-
if (
|
|
63
|
+
if (o.isRoot) {
|
|
56
64
|
i.push(
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
-
|
|
65
|
+
/* @__PURE__ */ r(y, { children: R(
|
|
66
|
+
a(o.children, "", e, `${s}-`),
|
|
59
67
|
e
|
|
60
|
-
) },
|
|
68
|
+
) }, s)
|
|
61
69
|
);
|
|
62
70
|
continue;
|
|
63
71
|
}
|
|
64
|
-
const
|
|
72
|
+
const $ = l(n, o.path, !1), j = o.path ? E($) : _(o, n);
|
|
65
73
|
i.push(
|
|
66
|
-
/* @__PURE__ */
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
/* @__PURE__ */ r(f, { path: j, children: m(
|
|
75
|
+
/* @__PURE__ */ r(p, { children: /* @__PURE__ */ r(y, { children: R(
|
|
76
|
+
a(o.children, $, e, `${s}-`),
|
|
77
|
+
e
|
|
78
|
+
) }) })
|
|
79
|
+
) }, s)
|
|
70
80
|
);
|
|
71
81
|
}
|
|
72
82
|
return i;
|
|
73
83
|
}, g = () => {
|
|
74
|
-
const [t] =
|
|
75
|
-
return
|
|
84
|
+
const [t] = b();
|
|
85
|
+
return B(() => {
|
|
76
86
|
W(window.location.pathname);
|
|
77
87
|
}, [t]), null;
|
|
78
88
|
}, k = ({ routes: t }) => {
|
|
79
89
|
L(t);
|
|
80
|
-
const n =
|
|
81
|
-
return /* @__PURE__ */
|
|
82
|
-
/* @__PURE__ */
|
|
90
|
+
const n = C(t), e = a(t, "", n, "");
|
|
91
|
+
return /* @__PURE__ */ w(S, { children: [
|
|
92
|
+
/* @__PURE__ */ r(g, {}),
|
|
83
93
|
e
|
|
84
94
|
] });
|
|
85
|
-
},
|
|
95
|
+
}, H = (t) => {
|
|
86
96
|
const { routes: n } = t, e = document.querySelector("body");
|
|
87
|
-
e &&
|
|
97
|
+
e && x(/* @__PURE__ */ r(k, { routes: n }), e);
|
|
88
98
|
};
|
|
89
99
|
export {
|
|
90
100
|
k as ClientRoutes,
|
|
91
|
-
|
|
101
|
+
H as startClient
|
|
92
102
|
};
|
package/dist/components.js
CHANGED
|
@@ -3,7 +3,8 @@ 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
|
-
|
|
6
|
+
import "./live-loader.js";
|
|
7
|
+
function y({ basePath: t, favicon: e = "/favicon.ico" } = {}) {
|
|
7
8
|
const n = process.env.NODE_ENV !== "production";
|
|
8
9
|
t = t || process.env.STATIC_BASE_URL || (process.env.VELO_STATIC ? "/client" : "");
|
|
9
10
|
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 });
|
|
@@ -25,7 +26,7 @@ function S({ localStorage: t, cookies: e } = {}) {
|
|
|
25
26
|
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
27
|
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
|
}
|
|
28
|
-
function
|
|
29
|
+
function I(t) {
|
|
29
30
|
const e = S(t);
|
|
30
31
|
return e ? /* @__PURE__ */ r("script", { dangerouslySetInnerHTML: { __html: e } }) : null;
|
|
31
32
|
}
|
|
@@ -35,7 +36,7 @@ function m(t, e) {
|
|
|
35
36
|
n = n.replace(`:${s}`, i);
|
|
36
37
|
return n;
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
+
function V({ to: t, params: e, search: n, absolute: s, ...i }) {
|
|
39
40
|
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}`;
|
|
40
41
|
if (typeof window < "u" && C.value) {
|
|
41
42
|
let a;
|
|
@@ -61,9 +62,9 @@ function I({ to: t, params: e, search: n, absolute: s, ...i }) {
|
|
|
61
62
|
return /* @__PURE__ */ r($, { to: v, ...i });
|
|
62
63
|
}
|
|
63
64
|
export {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
I as Boot,
|
|
66
|
+
V as Link,
|
|
67
|
+
y as Scripts,
|
|
67
68
|
S as bootScript,
|
|
68
69
|
m as substituteParams
|
|
69
70
|
};
|
package/dist/config.d.ts
CHANGED
|
@@ -26,9 +26,11 @@ export interface VeloConfig {
|
|
|
26
26
|
*/
|
|
27
27
|
port?: number;
|
|
28
28
|
/**
|
|
29
|
-
* Interface de bind do servidor
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* Interface de bind do servidor, em dev e em produção. A env `HOST` tem
|
|
30
|
+
* precedência nos dois modos; em dev a ordem é: `server.host` do Vite
|
|
31
|
+
* (`--host`/vite.config) > env `HOST` > este campo. Default do Node:
|
|
32
|
+
* todas as interfaces (o que Docker/cloud esperam). Apps
|
|
33
|
+
* locais/sensíveis devem declarar "127.0.0.1".
|
|
32
34
|
*/
|
|
33
35
|
hostname?: string;
|
|
34
36
|
/**
|
package/dist/events.d.ts
CHANGED
|
@@ -284,6 +284,12 @@ interface StreamListener<TEvent> {
|
|
|
284
284
|
(event: TEvent): void;
|
|
285
285
|
close(): void;
|
|
286
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* The house's single SSE transport heartbeat, in milliseconds — the same
|
|
289
|
+
* default the live-loader channels use. Exported so the two surfaces never
|
|
290
|
+
* diverge in operational expectation.
|
|
291
|
+
*/
|
|
292
|
+
export declare const DEFAULT_HEARTBEAT_MS = 20000;
|
|
287
293
|
export declare function flushPendingStreamRoutes(app: Hono): void;
|
|
288
294
|
/** @internal Used by `@mauroandre/velojs/testing` to reset all streams. */
|
|
289
295
|
export declare function getRegisteredStreams(): ReadonlySet<EventStream<unknown, unknown>>;
|
package/dist/events.js
CHANGED
package/dist/hooks.d.ts
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
|
-
import { type Signal } from "@preact/signals";
|
|
1
|
+
import { type ReadonlySignal, type Signal } from "@preact/signals";
|
|
2
2
|
import type { EventStream } from "./events.js";
|
|
3
3
|
import type { SocketHandler, SocketStub } from "./sockets.js";
|
|
4
4
|
import { __veloUpdatePending } from "./loader-store.js";
|
|
5
|
+
import { type Freshness } from "./live-loader.js";
|
|
6
|
+
export type { Freshness } from "./live-loader.js";
|
|
7
|
+
/**
|
|
8
|
+
* What `Loader()`/`useLoader()` return. `freshness` is the page-level state of
|
|
9
|
+
* the live loader: `"live"` (connected), `"stale"` (connection closed,
|
|
10
|
+
* reconnecting or silent) and `"error"` (the last loader re-execution failed).
|
|
11
|
+
* On a page with no `channels` it exists and stays `"live"`. The framework
|
|
12
|
+
* exposes it as data for CSS to react to — it renders no JSX of its own.
|
|
13
|
+
*
|
|
14
|
+
* `freshnessByChannel` is the same state with per-channel granularity, keyed
|
|
15
|
+
* by the channel names the module declares — a page with two channels, one
|
|
16
|
+
* fallen and one following, shows both states at once. Empty record when the
|
|
17
|
+
* module declares no channels.
|
|
18
|
+
*/
|
|
19
|
+
export interface LoaderHandle<T> {
|
|
20
|
+
data: Signal<T | null>;
|
|
21
|
+
loading: Signal<boolean>;
|
|
22
|
+
refetch: () => void;
|
|
23
|
+
freshness: Signal<Freshness>;
|
|
24
|
+
freshnessByChannel: ReadonlySignal<Record<string, Freshness>>;
|
|
25
|
+
}
|
|
5
26
|
export { __veloUpdatePending };
|
|
6
27
|
declare global {
|
|
7
28
|
interface Window {
|
|
@@ -58,11 +79,7 @@ export declare function touch<T>(sig: Signal<T | null>): void;
|
|
|
58
79
|
*
|
|
59
80
|
* @param moduleId - Injetado automaticamente pelo veloPlugin
|
|
60
81
|
*/
|
|
61
|
-
export declare function Loader<T>(moduleId?: string):
|
|
62
|
-
data: Signal<T | null>;
|
|
63
|
-
loading: Signal<boolean>;
|
|
64
|
-
refetch: () => void;
|
|
65
|
-
};
|
|
82
|
+
export declare function Loader<T>(moduleId?: string): LoaderHandle<T>;
|
|
66
83
|
/**
|
|
67
84
|
* Hook para acessar dados do loader dentro de componentes
|
|
68
85
|
* Suporta SSR hydration e navegação SPA (faz fetch se necessário)
|
|
@@ -82,21 +99,9 @@ export declare function Loader<T>(moduleId?: string): {
|
|
|
82
99
|
* @param moduleId - Injetado automaticamente pelo veloPlugin
|
|
83
100
|
* @param deps - Array de dependências (triggers re-fetch quando mudam)
|
|
84
101
|
*/
|
|
85
|
-
export declare function useLoader<T>():
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
refetch: () => void;
|
|
89
|
-
};
|
|
90
|
-
export declare function useLoader<T>(deps: any[]): {
|
|
91
|
-
data: Signal<T | null>;
|
|
92
|
-
loading: Signal<boolean>;
|
|
93
|
-
refetch: () => void;
|
|
94
|
-
};
|
|
95
|
-
export declare function useLoader<T>(moduleId: string, deps?: any[]): {
|
|
96
|
-
data: Signal<T | null>;
|
|
97
|
-
loading: Signal<boolean>;
|
|
98
|
-
refetch: () => void;
|
|
99
|
-
};
|
|
102
|
+
export declare function useLoader<T>(): LoaderHandle<T>;
|
|
103
|
+
export declare function useLoader<T>(deps: any[]): LoaderHandle<T>;
|
|
104
|
+
export declare function useLoader<T>(moduleId: string, deps?: any[]): LoaderHandle<T>;
|
|
100
105
|
/**
|
|
101
106
|
* Hook para navegação programática
|
|
102
107
|
*
|