@mauroandre/velojs 0.0.57 → 0.0.58
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
CHANGED
|
@@ -467,6 +467,7 @@ A page value that must **track server state over time** — a total another
|
|
|
467
467
|
person's request changes, data a background scheduler mutates — declares the
|
|
468
468
|
channels that keep it fresh. No extra component, no manual subscription: the
|
|
469
469
|
module exports `channels` next to its `loader`.
|
|
470
|
+
The one-sentence model: the live loader keeps a page's state replica faithful to the server — the first payload arrives through the usual path (SSR, `__PAGE_DATA__`, the `?_data=1` refetch), and from then on every change is **addressed**, by the app's own rules, to the group of clients it concerns, **by duty or by interest**, each one receiving the state computed for its own scope.
|
|
470
471
|
|
|
471
472
|
```tsx
|
|
472
473
|
// app/expenses/Expenses.tsx
|
|
@@ -768,6 +769,8 @@ partitions is internal information, and it never ships in a production build.
|
|
|
768
769
|
|
|
769
770
|
### The partition contract
|
|
770
771
|
|
|
772
|
+
**Addressed, not broadcast.** A partition is not a filter applied after a broadcast. The `emit` is addressed: the runtime resolves the partition key and writes only to the connections of that group — a client outside the group never hears about the change, not even a byte. Two reasons make a partition matter, and they compose: **by duty** (authorization — the data belongs to that team, that family, that project; others must not see it) and **by interest** (relevance — the tab watching project 9 has nothing to wake up for when project 7 changes). The same `scope` serves both; the app decides which, or both at once.
|
|
773
|
+
|
|
771
774
|
On subscribe the `scope` receives `{ user, params }`. `user` is `c.get("user")`
|
|
772
775
|
— the house key, the same one the stream/socket channel resolvers use (a
|
|
773
776
|
middleware that materializes the principal elsewhere should set it in `"user"`
|
|
@@ -2025,7 +2028,7 @@ velojs build
|
|
|
2025
2028
|
|
|
2026
2029
|
Asset filenames include content hashes for long-term browser caching. The server build reads the Vite manifest to inject the correct filenames into `<Scripts>`.
|
|
2027
2030
|
|
|
2028
|
-
In production, `velojs start` sets `NODE_ENV=production` automatically and serves static files from `dist/client/`. HTML responses are served with `Cache-Control: no-cache` so browsers always fetch the latest HTML (which references the current hashed assets).
|
|
2031
|
+
In production, `velojs start` sets `NODE_ENV=production` automatically and serves static files from `dist/client/`. Assets carry content hashes and are **public by design**, so the server answers an existing file **before the app's route table** — a page route, an action endpoint or a route middleware (an auth guard redirecting to `/login`, for instance) never sees an asset path. Only the framework's own infra middlewares (trailing-slash normalization, the logger) run ahead of the asset lookup. Paths that are not files fall through to the app routes as usual (SSR pages, actions, streams, sockets, endpoints, the catch-all 404). HTML responses are served with `Cache-Control: no-cache` so browsers always fetch the latest HTML (which references the current hashed assets).
|
|
2029
2032
|
|
|
2030
2033
|
### Static assets on CDN
|
|
2031
2034
|
|
|
@@ -2035,7 +2038,7 @@ Set `STATIC_BASE_URL` to serve static assets from a CDN or S3 bucket:
|
|
|
2035
2038
|
STATIC_BASE_URL=https://cdn.example.com/assets node dist/server.js
|
|
2036
2039
|
```
|
|
2037
2040
|
|
|
2038
|
-
The `<Scripts />` component and CSS `url()` references will use this prefix automatically.
|
|
2041
|
+
The `<Scripts />` component and CSS `url()` references will use this prefix automatically. When `STATIC_BASE_URL` starts with `http`, the server mounts no local static at all — every path is an app path, and the assets' public-by-design semantics come from the bucket/CDN.
|
|
2039
2042
|
|
|
2040
2043
|
---
|
|
2041
2044
|
|
package/agent/AGENTS.md
CHANGED
|
@@ -108,6 +108,8 @@ import { emit } from "@mauroandre/velojs/server";
|
|
|
108
108
|
await emit("teamExpenses", { user: { teamId: 7 } });
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
An `emit` is addressed to the partition's group — clients outside the group never hear about it (not a broadcast the client filters); partitions exist by duty (authorization) or by interest (relevance).
|
|
112
|
+
|
|
111
113
|
Or, when the producer already holds the new value, it pushes it as a typed slice:
|
|
112
114
|
|
|
113
115
|
```ts
|
|
@@ -5,7 +5,7 @@ description: "Keep a loader value faithful to server state in real time: declare
|
|
|
5
5
|
|
|
6
6
|
# Live loader
|
|
7
7
|
|
|
8
|
-
A `loader` fetches a page's data once per request and re-fetches it on SPA navigation. That is everything a page needs when its data changes because of the user themselves — or not at all. A **value that must track server state over time** (a team total another person's request changes, data a background scheduler mutates) needs the loader to stay faithful. That is the live loader: the same `loader`, the same `useLoader()` read, plus a sibling `channels` export.
|
|
8
|
+
A `loader` fetches a page's data once per request and re-fetches it on SPA navigation. That is everything a page needs when its data changes because of the user themselves — or not at all. A **value that must track server state over time** (a team total another person's request changes, data a background scheduler mutates) needs the loader to stay faithful. That is the live loader: the same `loader`, the same `useLoader()` read, plus a sibling `channels` export. The one-sentence model: the live loader keeps a page's state replica faithful to the server — the first payload arrives through the usual path (SSR, `__PAGE_DATA__`, the `?_data=1` refetch), and from then on every change is **addressed**, by the app's own rules, to the group of clients it concerns, **by duty or by interest**, each one receiving the state computed for its own scope.
|
|
9
9
|
|
|
10
10
|
## The three declarations
|
|
11
11
|
|
|
@@ -284,6 +284,8 @@ On a page with no `channels` the fields exist, the record is empty and the aggre
|
|
|
284
284
|
|
|
285
285
|
## The partition contract
|
|
286
286
|
|
|
287
|
+
**Addressed, not broadcast.** A partition is not a filter applied after a broadcast. The `emit` is addressed: the runtime resolves the partition key and writes only to the connections of that group — a client outside the group never hears about the change, not even a byte. Two reasons make a partition matter, and they compose: **by duty** (authorization — the data belongs to that team, that family, that project; others must not see it) and **by interest** (relevance — the tab watching project 9 has nothing to wake up for when project 7 changes). The same `scope` serves both; the app decides which, or both at once.
|
|
288
|
+
|
|
287
289
|
On subscribe the `scope` receives `{ user, params }`. `user` is whatever a middleware materialized under the house key `"user"` — the same key the stream/socket channel resolvers use; a middleware that materializes the principal somewhere else should set it in `"user"` too:
|
|
288
290
|
|
|
289
291
|
```ts
|
|
@@ -25,6 +25,12 @@ npx velojs start
|
|
|
25
25
|
|
|
26
26
|
This automatically sets `NODE_ENV=production` and starts the server. In production mode, VeloJS serves static files from `dist/client/` and handles SSR for all page routes.
|
|
27
27
|
|
|
28
|
+
### Assets are served before the app routes
|
|
29
|
+
|
|
30
|
+
`dist/client` assets are **public by design**: their names carry content hashes and their URLs are fetched by the browser with no session and no route logic attached. The server answers an existing file from `dist/client` **before the app's route table** — so a page route, an action endpoint or a route middleware (an auth guard redirecting to `/login`, for instance) never sees an asset path. Only the framework's own infra middlewares (trailing-slash normalization and the logger) run ahead of the asset lookup.
|
|
31
|
+
|
|
32
|
+
Paths that are not files keep the normal flow: SSR pages, actions, streams, sockets, endpoints and the app's catch-all 404. A top-level dynamic route (`/:mes`) therefore means only app paths — `/client.<hash>.js` is served as a file, while `/2026-10` goes through the route's middlewares and loaders.
|
|
33
|
+
|
|
28
34
|
## Dockerfile
|
|
29
35
|
|
|
30
36
|
Here's a production-ready Dockerfile with multi-stage build:
|
|
@@ -124,7 +130,7 @@ If you want to serve static assets (JS, CSS, images) from a CDN or S3 bucket ins
|
|
|
124
130
|
STATIC_BASE_URL=https://cdn.example.com/assets npx velojs start
|
|
125
131
|
```
|
|
126
132
|
|
|
127
|
-
The `<Scripts />` component and CSS `url()` references will automatically use this prefix.
|
|
133
|
+
The `<Scripts />` component and CSS `url()` references will automatically use this prefix. When `STATIC_BASE_URL` starts with `http`, the server mounts no local static at all: every path is an app path, and the public-by-design semantics come from the bucket/CDN.
|
|
128
134
|
|
|
129
135
|
## Included dependencies
|
|
130
136
|
|
package/dist/server.js
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
import { jsx as w } from "preact/jsx-runtime";
|
|
2
|
-
import { Hono as
|
|
3
|
-
import { logger as
|
|
2
|
+
import { Hono as j } from "hono";
|
|
3
|
+
import { logger as q } from "hono/logger";
|
|
4
4
|
import { trimTrailingSlash as T } from "hono/trailing-slash";
|
|
5
5
|
import { render as A } from "preact-render-to-string";
|
|
6
6
|
import { Router as $ } from "wouter-preact";
|
|
7
7
|
import { AsyncLocalStorage as k } from "node:async_hooks";
|
|
8
8
|
import { getAppContext as _ } from "./app-context.js";
|
|
9
|
-
import { flushPendingStreamRoutes as D, registerStreamHandler as
|
|
10
|
-
import { registerSocketRoutes as
|
|
11
|
-
import { inspectChannels as
|
|
12
|
-
import { emit as
|
|
9
|
+
import { flushPendingStreamRoutes as D, registerStreamHandler as N } from "./events.js";
|
|
10
|
+
import { registerSocketRoutes as O, injectWebSocketServer as S } from "./sockets.js";
|
|
11
|
+
import { inspectChannels as I, registerChannelRoute as H } from "./channels.js";
|
|
12
|
+
import { emit as de, registerChannels as ue } from "./channels.js";
|
|
13
13
|
const P = new k();
|
|
14
14
|
globalThis.__veloServerData = P;
|
|
15
15
|
let g = null;
|
|
16
|
-
function
|
|
16
|
+
function se(e) {
|
|
17
17
|
if (g) {
|
|
18
18
|
e(g);
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
21
|
_().serverCallbacks.push(e);
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function C(e) {
|
|
24
24
|
g = e;
|
|
25
25
|
const t = _();
|
|
26
26
|
for (const a of t.serverCallbacks) a(e);
|
|
27
27
|
t.serverCallbacks.length = 0;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function V(e) {
|
|
30
30
|
g === e && (g = null);
|
|
31
31
|
}
|
|
32
|
-
function
|
|
32
|
+
function ae(e) {
|
|
33
33
|
_().pendingRoutes.push(e);
|
|
34
34
|
}
|
|
35
|
-
const
|
|
35
|
+
const x = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029"), G = (e, t, a, r) => {
|
|
36
36
|
if (r && r !== 200 && e.status(r), e.req.query("_data") === "1") {
|
|
37
37
|
const c = globalThis.__veloBuildHash || void 0, i = a ? { ...a, __buildHash: c } : { __buildHash: c };
|
|
38
38
|
return e.json(i);
|
|
@@ -43,14 +43,14 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
43
43
|
);
|
|
44
44
|
if (e.header("Cache-Control", "no-cache"), !a)
|
|
45
45
|
return e.html(n);
|
|
46
|
-
const s = `<script>window.__PAGE_DATA__=${
|
|
46
|
+
const s = `<script>window.__PAGE_DATA__=${x(a)}<\/script>`;
|
|
47
47
|
return e.html(n.replace("</head>", () => `${s}</head>`));
|
|
48
|
-
},
|
|
48
|
+
}, L = async (e, t) => {
|
|
49
49
|
const a = t.req.param(), r = t.req.query(), o = { params: a, query: r, c: t }, n = await Promise.all(
|
|
50
50
|
e.map(async (i) => {
|
|
51
51
|
if (!i.loader) return null;
|
|
52
|
-
const
|
|
53
|
-
return
|
|
52
|
+
const l = await i.loader(o), d = i.metadata?.moduleId;
|
|
53
|
+
return d ? { moduleId: d, loaderData: l } : null;
|
|
54
54
|
})
|
|
55
55
|
);
|
|
56
56
|
let s;
|
|
@@ -71,7 +71,7 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
71
71
|
data: c,
|
|
72
72
|
shortCircuit: s
|
|
73
73
|
};
|
|
74
|
-
},
|
|
74
|
+
}, M = (e) => {
|
|
75
75
|
if (e.length === 0) return null;
|
|
76
76
|
const t = e.filter(Boolean);
|
|
77
77
|
if (t.length === 0) return null;
|
|
@@ -104,27 +104,27 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
104
104
|
s
|
|
105
105
|
);
|
|
106
106
|
else if (o.module) {
|
|
107
|
-
const c = o.path === "*", i = o.statusCode ?? (c ? 404 : void 0),
|
|
108
|
-
if (!
|
|
107
|
+
const c = o.path === "*", i = o.statusCode ?? (c ? 404 : void 0), l = o.module.metadata?.fullPath;
|
|
108
|
+
if (!l && !c) {
|
|
109
109
|
console.warn(
|
|
110
110
|
`Module ${o.module.metadata?.moduleId} has no fullPath`
|
|
111
111
|
);
|
|
112
112
|
continue;
|
|
113
113
|
}
|
|
114
|
-
const
|
|
115
|
-
const { components: u, data:
|
|
116
|
-
if (
|
|
117
|
-
const v =
|
|
118
|
-
return
|
|
114
|
+
const d = async (f) => {
|
|
115
|
+
const { components: u, data: m, shortCircuit: h } = await L(n, f);
|
|
116
|
+
if (h) {
|
|
117
|
+
const v = h.headers.get("Location");
|
|
118
|
+
return f.req.query("_data") === "1" && v && h.status >= 300 && h.status < 400 ? f.json({ __redirect: v }) : h;
|
|
119
119
|
}
|
|
120
|
-
const p =
|
|
121
|
-
return
|
|
120
|
+
const p = M(u);
|
|
121
|
+
return G(f, p, m, i);
|
|
122
122
|
};
|
|
123
|
-
c ? e.notFound(
|
|
123
|
+
c ? e.notFound(d) : s.length > 0 ? e.on(["GET"], [l], ...s, d) : e.on(["GET"], [l], d);
|
|
124
124
|
} else
|
|
125
125
|
continue;
|
|
126
126
|
}
|
|
127
|
-
},
|
|
127
|
+
}, E = (e, t, a = []) => {
|
|
128
128
|
for (const r of t) {
|
|
129
129
|
const o = r.module?.metadata?.moduleId, n = [
|
|
130
130
|
...a,
|
|
@@ -135,22 +135,22 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
135
135
|
(c) => c.startsWith("action_")
|
|
136
136
|
);
|
|
137
137
|
for (const c of s) {
|
|
138
|
-
const i = c.replace("action_", ""),
|
|
139
|
-
if (typeof
|
|
140
|
-
const
|
|
141
|
-
let
|
|
138
|
+
const i = c.replace("action_", ""), l = r.module[c];
|
|
139
|
+
if (typeof l == "function") {
|
|
140
|
+
const d = `/_action/${o}/${i}`, f = async (u) => {
|
|
141
|
+
let m = {};
|
|
142
142
|
try {
|
|
143
|
-
|
|
143
|
+
m = await u.req.json();
|
|
144
144
|
} catch {
|
|
145
145
|
}
|
|
146
|
-
const
|
|
147
|
-
body:
|
|
146
|
+
const h = {
|
|
147
|
+
body: m,
|
|
148
148
|
params: u.req.param(),
|
|
149
149
|
query: u.req.query(),
|
|
150
150
|
c: u
|
|
151
151
|
};
|
|
152
152
|
try {
|
|
153
|
-
const p = await
|
|
153
|
+
const p = await l(h);
|
|
154
154
|
return u.json(p ?? { ok: !0 });
|
|
155
155
|
} catch (p) {
|
|
156
156
|
const v = p instanceof Error ? p.message : "Action failed";
|
|
@@ -159,16 +159,16 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
159
159
|
};
|
|
160
160
|
n.length > 0 ? e.on(
|
|
161
161
|
["POST"],
|
|
162
|
-
[
|
|
162
|
+
[d],
|
|
163
163
|
...n,
|
|
164
|
-
|
|
165
|
-
) : e.on(["POST"], [
|
|
164
|
+
f
|
|
165
|
+
) : e.on(["POST"], [d], f);
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
-
r.children &&
|
|
169
|
+
r.children && E(e, r.children, n);
|
|
170
170
|
}
|
|
171
|
-
},
|
|
171
|
+
}, W = async (e, t, a = []) => {
|
|
172
172
|
const r = (o, n) => {
|
|
173
173
|
for (const s of o) {
|
|
174
174
|
const c = s.module?.metadata?.moduleId, i = [
|
|
@@ -176,16 +176,16 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
176
176
|
...s.middlewares || []
|
|
177
177
|
];
|
|
178
178
|
if (s.module && c) {
|
|
179
|
-
const
|
|
180
|
-
(
|
|
179
|
+
const l = Object.keys(s.module).filter(
|
|
180
|
+
(d) => d.startsWith("stream_")
|
|
181
181
|
);
|
|
182
|
-
for (const
|
|
183
|
-
const
|
|
182
|
+
for (const d of l) {
|
|
183
|
+
const f = d.replace("stream_", ""), u = s.module[d];
|
|
184
184
|
if (u?.__isVeloEventStream) {
|
|
185
|
-
const
|
|
186
|
-
u.__path =
|
|
185
|
+
const m = `/_event/${c}/${f}`;
|
|
186
|
+
u.__path = m, N(
|
|
187
187
|
e,
|
|
188
|
-
|
|
188
|
+
m,
|
|
189
189
|
u,
|
|
190
190
|
i
|
|
191
191
|
);
|
|
@@ -196,7 +196,7 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
196
196
|
}
|
|
197
197
|
};
|
|
198
198
|
r(t, a);
|
|
199
|
-
},
|
|
199
|
+
}, b = (e, t, a = []) => {
|
|
200
200
|
for (const r of t) {
|
|
201
201
|
const o = r.module?.metadata?.moduleId, n = [
|
|
202
202
|
...a,
|
|
@@ -215,9 +215,9 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
215
215
|
n
|
|
216
216
|
);
|
|
217
217
|
}
|
|
218
|
-
r.children &&
|
|
218
|
+
r.children && b(e, r.children, n);
|
|
219
219
|
}
|
|
220
|
-
},
|
|
220
|
+
}, K = (e, t) => t ? t.startsWith("/") ? e + t : e ? e + "/" + t : "/" + t : e || "", B = (e) => {
|
|
221
221
|
const t = /* @__PURE__ */ new Set(), a = (r) => {
|
|
222
222
|
for (const o of r) {
|
|
223
223
|
if (o.module && !o.children) {
|
|
@@ -228,33 +228,33 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
228
228
|
}
|
|
229
229
|
};
|
|
230
230
|
return a(e), t;
|
|
231
|
-
},
|
|
231
|
+
}, R = (e, t, a, r = "", o = []) => {
|
|
232
232
|
for (const n of t) {
|
|
233
|
-
const s =
|
|
233
|
+
const s = K(r, n.path), c = [
|
|
234
234
|
...o,
|
|
235
235
|
...n.middlewares || []
|
|
236
|
-
], i = !!n.handler,
|
|
237
|
-
if (i && !
|
|
236
|
+
], i = !!n.handler, l = !!n.method;
|
|
237
|
+
if (i && !l ? console.warn(
|
|
238
238
|
`[velojs] invalid route at "${s || "/"}" — "handler" set without "method"; endpoint skipped`
|
|
239
|
-
) :
|
|
239
|
+
) : l && !i ? console.warn(
|
|
240
240
|
`[velojs] invalid route at "${s || "/"}" — "method" set without "handler"; endpoint skipped`
|
|
241
241
|
) : i && n.module ? console.warn(
|
|
242
242
|
`[velojs] ambiguous route at "${s || "/"}" — both "module" and "handler" set; endpoint ignored, page kept`
|
|
243
243
|
) : i && n.isRoot && console.warn(
|
|
244
244
|
`[velojs] "isRoot" has no effect on endpoint at "${s || "/"}"; ignored`
|
|
245
|
-
), i &&
|
|
246
|
-
const
|
|
247
|
-
|
|
245
|
+
), i && l && !n.module) {
|
|
246
|
+
const f = n.method;
|
|
247
|
+
f === "GET" && a.has(s) && console.warn(
|
|
248
248
|
`[velojs] path "${s}" has both a page GET and an endpoint GET; the page wins and the endpoint is unreachable. Consider renaming one.`
|
|
249
249
|
);
|
|
250
|
-
const u = n.handler,
|
|
251
|
-
c:
|
|
252
|
-
params:
|
|
253
|
-
query:
|
|
250
|
+
const u = n.handler, m = async (h) => await u({
|
|
251
|
+
c: h,
|
|
252
|
+
params: h.req.param(),
|
|
253
|
+
query: h.req.query()
|
|
254
254
|
});
|
|
255
|
-
c.length > 0 ? e.on([
|
|
255
|
+
c.length > 0 ? e.on([f], [s], ...c, m) : e.on([f], [s], m);
|
|
256
256
|
}
|
|
257
|
-
n.children &&
|
|
257
|
+
n.children && R(
|
|
258
258
|
e,
|
|
259
259
|
n.children,
|
|
260
260
|
a,
|
|
@@ -263,48 +263,50 @@ const G = (e) => JSON.stringify(e).replace(/</g, "\\u003c").replace(/>/g, "\\u00
|
|
|
263
263
|
);
|
|
264
264
|
}
|
|
265
265
|
}, F = async (e) => {
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
if (process.env.NODE_ENV !== "production" || process.env.VELO_STATIC || (process.env.STATIC_BASE_URL || "").startsWith("http")) return;
|
|
267
|
+
const { serveStatic: a } = await import("@hono/node-server/serve-static"), { join: r } = await import("node:path");
|
|
268
|
+
e.use("/*", a({ root: r(process.cwd(), "dist/client") }));
|
|
269
|
+
}, U = async (e) => {
|
|
270
|
+
const t = new j();
|
|
271
|
+
t.use(T()), process.env.NODE_ENV !== "production" && t.use("*", q()), await F(t);
|
|
268
272
|
const r = _().pendingRoutes.splice(0);
|
|
269
273
|
for (const n of r)
|
|
270
274
|
await n(t);
|
|
271
|
-
y(t, e),
|
|
275
|
+
y(t, e), E(t, e), await W(t, e), b(t, e), process.env.NODE_ENV !== "production" && t.get("/_channel-inspect", (n) => n.json(I()));
|
|
272
276
|
const o = B(e);
|
|
273
|
-
if (
|
|
277
|
+
if (R(t, e, o), await O(t, e), D(t), process.env.NODE_ENV !== "production" && !g) {
|
|
274
278
|
const n = globalThis.__veloDevServer;
|
|
275
|
-
n && (
|
|
279
|
+
n && (C(n), await S(t, n));
|
|
276
280
|
}
|
|
277
281
|
return t;
|
|
278
|
-
},
|
|
279
|
-
const { routes: t } = e, a = Number(process.env.PORT) || e.port || 3e3, r = process.env.HOST || e.hostname || void 0, o = await
|
|
282
|
+
}, ie = async (e) => {
|
|
283
|
+
const { routes: t } = e, a = Number(process.env.PORT) || e.port || 3e3, r = process.env.HOST || e.hostname || void 0, o = await U(t);
|
|
280
284
|
if (process.env.NODE_ENV === "production" && !process.env.VELO_STATIC) {
|
|
281
|
-
const { serve: n } = await import("@hono/node-server"), {
|
|
282
|
-
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const h = d.address === "::" || d.address === "0.0.0.0" ? "0.0.0.0 (all interfaces)" : d.address;
|
|
288
|
-
console.log(`Server running on ${h}:${d.port}`);
|
|
285
|
+
const { serve: n } = await import("@hono/node-server"), s = n({ fetch: o.fetch, port: a, ...r ? { hostname: r } : {} });
|
|
286
|
+
s.listening || await new Promise((i) => s.once("listening", i));
|
|
287
|
+
const c = s.address();
|
|
288
|
+
if (c && typeof c == "object") {
|
|
289
|
+
const l = c.address === "::" || c.address === "0.0.0.0" ? "0.0.0.0 (all interfaces)" : c.address;
|
|
290
|
+
console.log(`Server running on ${l}:${c.port}`);
|
|
289
291
|
} else
|
|
290
292
|
console.log(`Server running on port ${a}`);
|
|
291
|
-
await S(o,
|
|
292
|
-
|
|
293
|
+
await S(o, s), C(s), s.once("close", () => {
|
|
294
|
+
V(s);
|
|
293
295
|
});
|
|
294
296
|
}
|
|
295
297
|
return o;
|
|
296
298
|
};
|
|
297
299
|
export {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
300
|
+
ae as addRoutes,
|
|
301
|
+
V as clearActiveServer,
|
|
302
|
+
U as createApp,
|
|
303
|
+
U as default,
|
|
304
|
+
de as emit,
|
|
305
|
+
C as flushServerCallbacks,
|
|
306
|
+
I as inspectChannels,
|
|
307
|
+
x as jsonForScript,
|
|
308
|
+
se as onServer,
|
|
309
|
+
ue as registerChannels,
|
|
308
310
|
P as serverDataStorage,
|
|
309
|
-
|
|
311
|
+
ie as startServer
|
|
310
312
|
};
|