@mauroandre/velojs 0.0.26 → 0.0.27
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 +81 -2
- package/dist/events.d.ts +58 -3
- package/dist/events.js +174 -135
- package/dist/hooks.d.ts +56 -0
- package/dist/hooks.js +128 -68
- package/dist/index.d.ts +2 -1
- package/dist/server.js +51 -50
- package/dist/sockets.d.ts +94 -0
- package/dist/sockets.js +182 -0
- package/dist/testing/index.js +454 -291
- package/dist/testing/socketSession.d.ts +13 -0
- package/dist/testing/types.d.ts +36 -0
- package/dist/vite.d.ts +8 -0
- package/dist/vite.js +267 -236
- package/package.json +6 -1
package/dist/hooks.js
CHANGED
|
@@ -1,116 +1,176 @@
|
|
|
1
|
-
import { signal as
|
|
2
|
-
import { useEffect as
|
|
3
|
-
import { useLocation as
|
|
4
|
-
const
|
|
5
|
-
function
|
|
1
|
+
import { signal as g, useSignal as h } from "@preact/signals";
|
|
2
|
+
import { useEffect as D, useRef as E } from "preact/hooks";
|
|
3
|
+
import { useLocation as L, useParams as A } from "wouter-preact";
|
|
4
|
+
const b = g(!1);
|
|
5
|
+
function O(e) {
|
|
6
6
|
e.value !== null && typeof e.value == "object" && (e.value = { ...e.value });
|
|
7
7
|
}
|
|
8
|
-
function
|
|
9
|
-
const
|
|
8
|
+
function C(e) {
|
|
9
|
+
const c = g(!1);
|
|
10
10
|
if (typeof window > "u")
|
|
11
11
|
return { data: {
|
|
12
12
|
get value() {
|
|
13
13
|
return e ? globalThis.__veloServerData?.getStore?.()?.[e] ?? null : null;
|
|
14
14
|
}
|
|
15
|
-
}, loading:
|
|
15
|
+
}, loading: c };
|
|
16
16
|
const t = window.__PAGE_DATA__, r = e && t?.[e] ? t[e] : null;
|
|
17
|
-
return { data:
|
|
17
|
+
return { data: g(r), loading: c };
|
|
18
18
|
}
|
|
19
|
-
function
|
|
19
|
+
function U(e, c) {
|
|
20
20
|
let t, r;
|
|
21
|
-
Array.isArray(e) ? r = e : (t = e, r =
|
|
22
|
-
let
|
|
21
|
+
Array.isArray(e) ? r = e : (t = e, r = c);
|
|
22
|
+
let a = null;
|
|
23
23
|
if (typeof window > "u" && t) {
|
|
24
|
-
const
|
|
25
|
-
|
|
24
|
+
const _ = globalThis.__veloServerData?.getStore?.();
|
|
25
|
+
_?.[t] && (a = _[t]);
|
|
26
26
|
}
|
|
27
27
|
if (typeof window < "u" && t) {
|
|
28
|
-
const
|
|
29
|
-
|
|
28
|
+
const n = window.__PAGE_DATA__;
|
|
29
|
+
n?.[t] && (a = n[t], delete n[t]);
|
|
30
30
|
}
|
|
31
|
-
const
|
|
31
|
+
const o = h(a), s = h(!1), f = () => {
|
|
32
32
|
if (typeof window > "u" || !t) return;
|
|
33
|
-
const
|
|
33
|
+
const n = window.location.pathname;
|
|
34
34
|
s.value = !0;
|
|
35
|
-
const
|
|
35
|
+
const p = typeof __VELO_STATIC__ < "u" && __VELO_STATIC__ ? `${n === "/" ? "" : n}/index.json` : (() => {
|
|
36
36
|
const l = new URLSearchParams(window.location.search);
|
|
37
|
-
return l.set("_data", "1"), `${
|
|
37
|
+
return l.set("_data", "1"), `${n}?${l.toString()}`;
|
|
38
38
|
})();
|
|
39
|
-
fetch(
|
|
40
|
-
typeof __VELO_BUILD_HASH__ < "u" && l.__buildHash && l.__buildHash !== __VELO_BUILD_HASH__ && (
|
|
39
|
+
fetch(p, { cache: "no-cache" }).then((l) => l.json()).then((l) => {
|
|
40
|
+
typeof __VELO_BUILD_HASH__ < "u" && l.__buildHash && l.__buildHash !== __VELO_BUILD_HASH__ && (b.value = !0), o.value = l[t], s.value = !1;
|
|
41
41
|
}).catch(() => {
|
|
42
42
|
s.value = !1;
|
|
43
43
|
});
|
|
44
|
-
},
|
|
45
|
-
return
|
|
46
|
-
if (
|
|
47
|
-
|
|
44
|
+
}, y = E(a !== null);
|
|
45
|
+
return D(() => {
|
|
46
|
+
if (y.current) {
|
|
47
|
+
y.current = !1;
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
}, r ?? []), { data:
|
|
50
|
+
f();
|
|
51
|
+
}, r ?? []), { data: o, loading: s, refetch: f };
|
|
52
52
|
}
|
|
53
|
-
function
|
|
54
|
-
const [, e] =
|
|
53
|
+
function k() {
|
|
54
|
+
const [, e] = L();
|
|
55
55
|
return e;
|
|
56
56
|
}
|
|
57
|
-
function
|
|
58
|
-
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__params ?? {} :
|
|
57
|
+
function H() {
|
|
58
|
+
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__params ?? {} : A();
|
|
59
59
|
}
|
|
60
|
-
function
|
|
60
|
+
function R() {
|
|
61
61
|
if (typeof window > "u")
|
|
62
62
|
return globalThis.__veloServerData?.getStore?.()?.__query ?? {};
|
|
63
63
|
const e = window.__PAGE_DATA__;
|
|
64
64
|
if (e?.__query)
|
|
65
65
|
return e.__query;
|
|
66
|
-
const
|
|
67
|
-
return
|
|
68
|
-
t[
|
|
66
|
+
const c = new URLSearchParams(window.location.search), t = {};
|
|
67
|
+
return c.forEach((r, a) => {
|
|
68
|
+
t[a] = r;
|
|
69
69
|
}), t;
|
|
70
70
|
}
|
|
71
|
-
function
|
|
72
|
-
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__pathname ?? "/" : (
|
|
71
|
+
function G() {
|
|
72
|
+
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__pathname ?? "/" : (L(), window.location.pathname);
|
|
73
73
|
}
|
|
74
|
-
function
|
|
75
|
-
const t =
|
|
76
|
-
return
|
|
77
|
-
if (typeof window > "u" || !
|
|
74
|
+
function W(e, c = {}) {
|
|
75
|
+
const t = h(null), r = h(null), a = h(!1), o = h(null), { channel: s, enabled: f = !0 } = c;
|
|
76
|
+
return D(() => {
|
|
77
|
+
if (typeof window > "u" || !f) return;
|
|
78
78
|
if (!e.__path) {
|
|
79
79
|
console.warn("[velojs] useEventStream: stream has no __path");
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
|
-
t.value = null, r.value = null,
|
|
83
|
-
const
|
|
84
|
-
return
|
|
82
|
+
t.value = null, r.value = null, a.value = !1, o.value = null;
|
|
83
|
+
const y = s ? `${e.__path}?channel=${encodeURIComponent(s)}` : e.__path, n = new EventSource(y);
|
|
84
|
+
return n.addEventListener("snapshot", (_) => {
|
|
85
85
|
try {
|
|
86
|
-
r.value = JSON.parse(
|
|
87
|
-
} catch (
|
|
88
|
-
|
|
86
|
+
r.value = JSON.parse(_.data);
|
|
87
|
+
} catch (p) {
|
|
88
|
+
o.value = p;
|
|
89
89
|
}
|
|
90
|
-
}),
|
|
90
|
+
}), n.addEventListener("message", (_) => {
|
|
91
91
|
try {
|
|
92
|
-
t.value = JSON.parse(
|
|
93
|
-
} catch (
|
|
94
|
-
|
|
92
|
+
t.value = JSON.parse(_.data);
|
|
93
|
+
} catch (p) {
|
|
94
|
+
o.value = p;
|
|
95
95
|
}
|
|
96
|
-
}),
|
|
97
|
-
}),
|
|
98
|
-
|
|
99
|
-
}),
|
|
100
|
-
|
|
96
|
+
}), n.addEventListener("heartbeat", () => {
|
|
97
|
+
}), n.addEventListener("close", () => {
|
|
98
|
+
a.value = !0, n.close();
|
|
99
|
+
}), n.addEventListener("error", () => {
|
|
100
|
+
n.readyState === EventSource.CLOSED && (a.value = !0);
|
|
101
|
+
}), () => {
|
|
102
|
+
n.close();
|
|
103
|
+
};
|
|
104
|
+
}, [e, s, f]), { data: t, snapshot: r, closed: a, error: o };
|
|
105
|
+
}
|
|
106
|
+
function q(e, c = {}) {
|
|
107
|
+
const t = h("connecting"), r = h(null), a = h(null), o = E(null), s = E([]), { channel: f, onMessage: y, onOpen: n, onClose: _, onError: p, enabled: l = !0 } = c;
|
|
108
|
+
return D(() => {
|
|
109
|
+
if (typeof window > "u" || !l) return;
|
|
110
|
+
if (!e.__path) {
|
|
111
|
+
console.warn("[velojs] useSocket: stub has no __path");
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
t.value = "connecting", r.value = null, a.value = null;
|
|
115
|
+
const v = `${window.location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}`, i = f ? `${v}${e.__path}?channel=${encodeURIComponent(f)}` : `${v}${e.__path}`, d = new WebSocket(i);
|
|
116
|
+
return d.binaryType = "arraybuffer", o.current = d, d.addEventListener("open", () => {
|
|
117
|
+
t.value = "open";
|
|
118
|
+
const u = s.current;
|
|
119
|
+
s.current = [];
|
|
120
|
+
for (const S of u)
|
|
121
|
+
try {
|
|
122
|
+
d.send(S);
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
n?.();
|
|
126
|
+
}), d.addEventListener("message", (u) => {
|
|
127
|
+
let S;
|
|
128
|
+
if (typeof u.data == "string")
|
|
129
|
+
S = u.data;
|
|
130
|
+
else if (u.data instanceof ArrayBuffer)
|
|
131
|
+
S = new Uint8Array(u.data);
|
|
132
|
+
else
|
|
133
|
+
return;
|
|
134
|
+
r.value = S, y?.(S);
|
|
135
|
+
}), d.addEventListener("close", (u) => {
|
|
136
|
+
t.value = "closed", o.current = null, _?.(u);
|
|
137
|
+
}), d.addEventListener("error", (u) => {
|
|
138
|
+
a.value = u, p?.(u);
|
|
101
139
|
}), () => {
|
|
102
|
-
|
|
140
|
+
o.current = null;
|
|
141
|
+
try {
|
|
142
|
+
(d.readyState === WebSocket.OPEN || d.readyState === WebSocket.CONNECTING) && d.close();
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
103
145
|
};
|
|
104
|
-
}, [e,
|
|
146
|
+
}, [e.__path, f, l]), { send: (w) => {
|
|
147
|
+
let v;
|
|
148
|
+
typeof w == "string" || w instanceof Uint8Array ? v = w : v = JSON.stringify(w);
|
|
149
|
+
const i = o.current;
|
|
150
|
+
if (i && i.readyState === WebSocket.OPEN)
|
|
151
|
+
try {
|
|
152
|
+
i.send(v);
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
else i && i.readyState === WebSocket.CONNECTING && s.current.push(v);
|
|
156
|
+
}, close: (w, v) => {
|
|
157
|
+
const i = o.current;
|
|
158
|
+
if (i)
|
|
159
|
+
try {
|
|
160
|
+
i.close(w, v);
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
}, status: t, lastMessage: r, error: a };
|
|
105
164
|
}
|
|
106
165
|
export {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
166
|
+
C as Loader,
|
|
167
|
+
b as __veloUpdatePending,
|
|
168
|
+
O as touch,
|
|
169
|
+
W as useEventStream,
|
|
170
|
+
U as useLoader,
|
|
171
|
+
k as useNavigate,
|
|
172
|
+
H as useParams,
|
|
173
|
+
G as usePathname,
|
|
174
|
+
R as useQuery,
|
|
175
|
+
q as useSocket
|
|
116
176
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,6 @@ export type { VeloConfig } from "./config.js";
|
|
|
3
3
|
export { defineConfig } from "./config.js";
|
|
4
4
|
export { Scripts, Link } from "./components.js";
|
|
5
5
|
export { createEventStream, poll } from "./events.js";
|
|
6
|
-
export type { EventStream, EventStreamConfig, EmitFn, EmitOptions, SourceFn, PerChannelSourceFn, ChannelResolver, } from "./events.js";
|
|
6
|
+
export type { EventStream, EventStreamConfig, EmitFn, EmitOptions, SourceFn, PerChannelSourceFn, StreamPipeFn, StreamPipeArgs, ChannelResolver, } from "./events.js";
|
|
7
|
+
export type { SocketHandler, SocketHandlerArgs, SocketStub, } from "./sockets.js";
|
|
7
8
|
export type { Context, MiddlewareHandler, Next } from "hono";
|
package/dist/server.js
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
import { jsx as g } from "preact/jsx-runtime";
|
|
2
|
-
import { Hono as
|
|
3
|
-
import { logger as
|
|
4
|
-
import { trimTrailingSlash as
|
|
5
|
-
import { render as
|
|
2
|
+
import { Hono as q } from "hono";
|
|
3
|
+
import { logger as T } from "hono/logger";
|
|
4
|
+
import { trimTrailingSlash as j } from "hono/trailing-slash";
|
|
5
|
+
import { render as k } from "preact-render-to-string";
|
|
6
6
|
import { Router as A } from "wouter-preact";
|
|
7
7
|
import { AsyncLocalStorage as C } from "node:async_hooks";
|
|
8
8
|
import { getAppContext as v } from "./app-context.js";
|
|
9
|
-
import { flushPendingStreamRoutes as $, registerStreamHandler as
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
import { flushPendingStreamRoutes as $, registerStreamHandler as D } from "./events.js";
|
|
10
|
+
import { registerSocketRoutes as I, injectWebSocketServer as y } from "./sockets.js";
|
|
11
|
+
const S = new C();
|
|
12
|
+
globalThis.__veloServerData = S;
|
|
13
|
+
let w = null;
|
|
14
|
+
function Y(e) {
|
|
15
|
+
if (w) {
|
|
16
|
+
e(w);
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
19
|
v().serverCallbacks.push(e);
|
|
19
20
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
21
|
+
function P(e) {
|
|
22
|
+
w = e;
|
|
22
23
|
const t = v();
|
|
23
24
|
for (const s of t.serverCallbacks) s(e);
|
|
24
25
|
t.serverCallbacks.length = 0;
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
+
function Z(e) {
|
|
27
28
|
v().pendingRoutes.push(e);
|
|
28
29
|
}
|
|
29
|
-
const
|
|
30
|
+
const N = (e, t, s) => {
|
|
30
31
|
if (e.req.query("_data") === "1") {
|
|
31
32
|
const r = globalThis.__veloBuildHash || void 0, i = s ? { ...s, __buildHash: r } : { __buildHash: r };
|
|
32
33
|
return e.json(i);
|
|
33
34
|
}
|
|
34
|
-
const a = e.req.path, o =
|
|
35
|
+
const a = e.req.path, o = S.run(
|
|
35
36
|
s ?? {},
|
|
36
|
-
() =>
|
|
37
|
+
() => k(/* @__PURE__ */ g(A, { ssrPath: a, children: t }))
|
|
37
38
|
);
|
|
38
39
|
if (e.header("Cache-Control", "no-cache"), !s)
|
|
39
40
|
return e.html(o);
|
|
@@ -41,7 +42,7 @@ const D = (e, t, s) => {
|
|
|
41
42
|
s
|
|
42
43
|
)}<\/script>`;
|
|
43
44
|
return e.html(o.replace("</head>", `${n}</head>`));
|
|
44
|
-
},
|
|
45
|
+
}, O = async (e, t) => {
|
|
45
46
|
const s = t.req.param(), a = t.req.query(), o = { params: s, query: a, c: t }, n = await Promise.all(
|
|
46
47
|
e.map(async (i) => {
|
|
47
48
|
if (!i.loader) return null;
|
|
@@ -59,7 +60,7 @@ const D = (e, t, s) => {
|
|
|
59
60
|
components: e.map((i) => i.Component),
|
|
60
61
|
data: r
|
|
61
62
|
};
|
|
62
|
-
},
|
|
63
|
+
}, G = (e) => {
|
|
63
64
|
if (e.length === 0) return null;
|
|
64
65
|
const t = e.filter(Boolean);
|
|
65
66
|
if (t.length === 0) return null;
|
|
@@ -69,10 +70,10 @@ const D = (e, t, s) => {
|
|
|
69
70
|
}
|
|
70
71
|
const s = t[t.length - 1];
|
|
71
72
|
return t.slice(0, -1).reduceRight((o, n) => /* @__PURE__ */ g(n, { children: o }), /* @__PURE__ */ g(s, {}));
|
|
72
|
-
},
|
|
73
|
+
}, _ = (e, t, s = [], a = []) => {
|
|
73
74
|
for (const o of t) {
|
|
74
75
|
if (o.handler && !o.module) {
|
|
75
|
-
o.children &&
|
|
76
|
+
o.children && _(
|
|
76
77
|
e,
|
|
77
78
|
o.children,
|
|
78
79
|
s,
|
|
@@ -85,7 +86,7 @@ const D = (e, t, s) => {
|
|
|
85
86
|
...o.middlewares || []
|
|
86
87
|
];
|
|
87
88
|
if (o.children)
|
|
88
|
-
|
|
89
|
+
_(
|
|
89
90
|
e,
|
|
90
91
|
o.children,
|
|
91
92
|
n,
|
|
@@ -100,14 +101,14 @@ const D = (e, t, s) => {
|
|
|
100
101
|
continue;
|
|
101
102
|
}
|
|
102
103
|
const l = async (c) => {
|
|
103
|
-
const { components: u, data: h } = await
|
|
104
|
-
return
|
|
104
|
+
const { components: u, data: h } = await O(n, c), d = G(u);
|
|
105
|
+
return N(c, d, h);
|
|
105
106
|
};
|
|
106
107
|
r.length > 0 ? e.on(["GET"], [i], ...r, l) : e.on(["GET"], [i], l);
|
|
107
108
|
} else
|
|
108
109
|
continue;
|
|
109
110
|
}
|
|
110
|
-
},
|
|
111
|
+
}, E = (e, t, s = []) => {
|
|
111
112
|
for (const a of t) {
|
|
112
113
|
const o = a.module?.metadata?.moduleId, n = [
|
|
113
114
|
...s,
|
|
@@ -136,8 +137,8 @@ const D = (e, t, s) => {
|
|
|
136
137
|
const p = await c(f);
|
|
137
138
|
return d.json(p ?? { ok: !0 });
|
|
138
139
|
} catch (p) {
|
|
139
|
-
const
|
|
140
|
-
return d.json({ error:
|
|
140
|
+
const b = p instanceof Error ? p.message : "Action failed";
|
|
141
|
+
return d.json({ error: b }, 500);
|
|
141
142
|
}
|
|
142
143
|
};
|
|
143
144
|
n.length > 0 ? e.on(
|
|
@@ -149,9 +150,9 @@ const D = (e, t, s) => {
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
|
-
a.children &&
|
|
153
|
+
a.children && E(e, a.children, n);
|
|
153
154
|
}
|
|
154
|
-
},
|
|
155
|
+
}, H = async (e, t, s = []) => {
|
|
155
156
|
const a = (o, n) => {
|
|
156
157
|
for (const r of o) {
|
|
157
158
|
const i = r.module?.metadata?.moduleId, l = [
|
|
@@ -166,7 +167,7 @@ const D = (e, t, s) => {
|
|
|
166
167
|
const h = u.replace("stream_", ""), d = r.module[u];
|
|
167
168
|
if (d?.__isVeloEventStream) {
|
|
168
169
|
const m = `/_event/${i}/${h}`;
|
|
169
|
-
d.__path = m,
|
|
170
|
+
d.__path = m, D(
|
|
170
171
|
e,
|
|
171
172
|
m,
|
|
172
173
|
d,
|
|
@@ -179,7 +180,7 @@ const D = (e, t, s) => {
|
|
|
179
180
|
}
|
|
180
181
|
};
|
|
181
182
|
a(t, s);
|
|
182
|
-
},
|
|
183
|
+
}, x = (e, t) => t ? t.startsWith("/") ? e + t : e ? e + "/" + t : "/" + t : e || "", V = (e) => {
|
|
183
184
|
const t = /* @__PURE__ */ new Set(), s = (a) => {
|
|
184
185
|
for (const o of a) {
|
|
185
186
|
if (o.module && !o.children) {
|
|
@@ -190,9 +191,9 @@ const D = (e, t, s) => {
|
|
|
190
191
|
}
|
|
191
192
|
};
|
|
192
193
|
return s(e), t;
|
|
193
|
-
},
|
|
194
|
+
}, R = (e, t, s, a = "", o = []) => {
|
|
194
195
|
for (const n of t) {
|
|
195
|
-
const r =
|
|
196
|
+
const r = x(a, n.path), i = [
|
|
196
197
|
...o,
|
|
197
198
|
...n.middlewares || []
|
|
198
199
|
], l = !!n.handler, c = !!n.method;
|
|
@@ -216,7 +217,7 @@ const D = (e, t, s) => {
|
|
|
216
217
|
});
|
|
217
218
|
i.length > 0 ? e.on([h], [r], ...i, m) : e.on([h], [r], m);
|
|
218
219
|
}
|
|
219
|
-
n.children &&
|
|
220
|
+
n.children && R(
|
|
220
221
|
e,
|
|
221
222
|
n.children,
|
|
222
223
|
s,
|
|
@@ -224,34 +225,34 @@ const D = (e, t, s) => {
|
|
|
224
225
|
i
|
|
225
226
|
);
|
|
226
227
|
}
|
|
227
|
-
},
|
|
228
|
-
const t = new
|
|
229
|
-
t.use(
|
|
228
|
+
}, W = async (e) => {
|
|
229
|
+
const t = new q();
|
|
230
|
+
t.use(j()), process.env.NODE_ENV !== "production" && t.use("*", T());
|
|
230
231
|
const a = v().pendingRoutes.splice(0);
|
|
231
232
|
for (const n of a)
|
|
232
233
|
await n(t);
|
|
233
|
-
|
|
234
|
-
const o =
|
|
235
|
-
if (
|
|
234
|
+
_(t, e), E(t, e), await H(t, e);
|
|
235
|
+
const o = V(e);
|
|
236
|
+
if (R(t, e, o), await I(t, e), $(t), process.env.NODE_ENV !== "production" && !w) {
|
|
236
237
|
const n = globalThis.__veloDevServer;
|
|
237
|
-
n &&
|
|
238
|
+
n && (P(n), await y(t, n));
|
|
238
239
|
}
|
|
239
240
|
return t;
|
|
240
|
-
},
|
|
241
|
-
const { routes: t, port: s = Number(process.env.SERVER_PORT) || 3e3 } = e, a = await
|
|
241
|
+
}, ee = async (e) => {
|
|
242
|
+
const { routes: t, port: s = Number(process.env.SERVER_PORT) || 3e3 } = e, a = await W(t);
|
|
242
243
|
if (process.env.NODE_ENV === "production" && !process.env.VELO_STATIC) {
|
|
243
244
|
const { serve: o } = await import("@hono/node-server"), { serveStatic: n } = await import("@hono/node-server/serve-static"), { join: r } = await import("node:path"), i = r(process.cwd(), "dist/client");
|
|
244
245
|
(process.env.STATIC_BASE_URL || "").startsWith("http") || a.use("/*", n({ root: i })), console.log(`Server running on http://localhost:${s}`);
|
|
245
246
|
const c = o({ fetch: a.fetch, port: s });
|
|
246
|
-
|
|
247
|
+
await y(a, c), P(c);
|
|
247
248
|
}
|
|
248
249
|
return a;
|
|
249
250
|
};
|
|
250
251
|
export {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
252
|
+
Z as addRoutes,
|
|
253
|
+
W as createApp,
|
|
254
|
+
W as default,
|
|
255
|
+
Y as onServer,
|
|
256
|
+
S as serverDataStorage,
|
|
257
|
+
ee as startServer
|
|
257
258
|
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VeloJS Sockets — declarative WebSocket convention.
|
|
3
|
+
*
|
|
4
|
+
* Dev pattern: export `socket_<name>` from a page/layout module.
|
|
5
|
+
*
|
|
6
|
+
* ```typescript
|
|
7
|
+
* // app/workers/WorkerTerminal.tsx
|
|
8
|
+
* export const socket_terminal = async ({
|
|
9
|
+
* incoming, send, keepOpen, close, abortSignal, c, params, query,
|
|
10
|
+
* }) => {
|
|
11
|
+
* const user = c.get("user");
|
|
12
|
+
* const session = await createTerminal(params.workerId);
|
|
13
|
+
* session.on("data", (d) => send({ type: "data", data: d.toString() }));
|
|
14
|
+
* abortSignal.addEventListener("abort", () => session.destroy());
|
|
15
|
+
* keepOpen();
|
|
16
|
+
* for await (const raw of incoming) {
|
|
17
|
+
* const msg = JSON.parse(typeof raw === "string" ? raw : "");
|
|
18
|
+
* if (msg.type === "resize") session.resize(msg.cols, msg.rows);
|
|
19
|
+
* else if (msg.type === "data") session.write(msg.data);
|
|
20
|
+
* }
|
|
21
|
+
* };
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* The plugin strips `socket_*` bodies from the client bundle and replaces them
|
|
25
|
+
* with a stub carrying `__path`. On the client, use `useSocket(socket_terminal)`.
|
|
26
|
+
*/
|
|
27
|
+
import type { Context, Hono, MiddlewareHandler } from "hono";
|
|
28
|
+
import type { RouteNode } from "./types.js";
|
|
29
|
+
export interface SocketHandlerArgs {
|
|
30
|
+
/** Raw message frames from the client. Text frames → `string`, binary → `Uint8Array`. */
|
|
31
|
+
incoming: AsyncIterable<string | Uint8Array>;
|
|
32
|
+
/** Send a message. Objects are auto-serialized with `JSON.stringify`. */
|
|
33
|
+
send: (msg: string | Uint8Array | object) => void;
|
|
34
|
+
/** Close the socket imperatively. Accepts an optional WS close code + reason. */
|
|
35
|
+
close: (code?: number, reason?: string) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Mark the socket as long-running. If the handler returns without calling
|
|
38
|
+
* `keepOpen()`, the framework closes the socket. When `keepOpen()` is set,
|
|
39
|
+
* the socket stays open until the abort signal fires.
|
|
40
|
+
*
|
|
41
|
+
* `for await (const msg of incoming)` naturally keeps the handler alive
|
|
42
|
+
* while messages flow — `keepOpen()` is redundant in that case but not
|
|
43
|
+
* harmful.
|
|
44
|
+
*/
|
|
45
|
+
keepOpen: () => void;
|
|
46
|
+
/** Fires when the client disconnects, the server aborts, or `app.close()` is called. */
|
|
47
|
+
abortSignal: AbortSignal;
|
|
48
|
+
/** Hono Context — use `c.get("user")` etc. for middleware-provided values. */
|
|
49
|
+
c: Context;
|
|
50
|
+
/** URL params (e.g. `/:workerId`). */
|
|
51
|
+
params: Record<string, string>;
|
|
52
|
+
/** Query-string values. */
|
|
53
|
+
query: Record<string, string>;
|
|
54
|
+
}
|
|
55
|
+
export type SocketHandler = (args: SocketHandlerArgs) => void | Promise<void>;
|
|
56
|
+
/** Client-side stub shape — what the Vite plugin replaces `socket_*` with on the client bundle. */
|
|
57
|
+
export interface SocketStub {
|
|
58
|
+
readonly __isVeloSocket: true;
|
|
59
|
+
readonly __path: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Wraps a raw `incoming` iterable so each frame is JSON-parsed. Invalid JSON
|
|
63
|
+
* frames are skipped with a console warning (not thrown). Use when all client
|
|
64
|
+
* messages are JSON objects.
|
|
65
|
+
*
|
|
66
|
+
* ```typescript
|
|
67
|
+
* for await (const msg of parseJson<TerminalMsg>(incoming)) {
|
|
68
|
+
* if (msg.type === "resize") session.resize(msg.cols, msg.rows);
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseJson<T = unknown>(incoming: AsyncIterable<string | Uint8Array>): AsyncIterable<T>;
|
|
73
|
+
interface RegisteredSocket {
|
|
74
|
+
path: string;
|
|
75
|
+
handler: SocketHandler;
|
|
76
|
+
middlewares: MiddlewareHandler[];
|
|
77
|
+
}
|
|
78
|
+
/** @internal Used by the testing toolkit so `app.close()` aborts in-memory sessions too. */
|
|
79
|
+
export declare function trackSocketSession(app: Hono, ctrl: AbortController): () => void;
|
|
80
|
+
/** @internal Abort every open socket session on `app`. Called by testing toolkit + disposers. */
|
|
81
|
+
export declare function abortAllSocketSessions(app: Hono): void;
|
|
82
|
+
/** @internal Returns registered sockets for `app` (used by the testing toolkit). */
|
|
83
|
+
export declare function getAppSockets(app: Hono): ReadonlyMap<string, RegisteredSocket>;
|
|
84
|
+
export declare function registerSocketHandler(app: Hono, path: string, handler: SocketHandler, middlewares?: MiddlewareHandler[]): Promise<void>;
|
|
85
|
+
/** Walks the route tree and registers every `socket_*` export. */
|
|
86
|
+
export declare function registerSocketRoutes(app: Hono, nodes: RouteNode[], parentMiddlewares?: MiddlewareHandler[]): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Inject the WebSocket adapter into an HTTP server. Call after `serve()`
|
|
89
|
+
* returns (prod) or with Vite's dev http server (dev).
|
|
90
|
+
*
|
|
91
|
+
* No-op when no sockets are registered on `app`.
|
|
92
|
+
*/
|
|
93
|
+
export declare function injectWebSocketServer(app: Hono, server: any): Promise<void>;
|
|
94
|
+
export {};
|