@mauroandre/velojs 0.0.53 → 0.0.55
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 +27 -1
- package/agent/skills/velojs-event-streams/SKILL.md +28 -0
- package/agent/skills/velojs-getting-started/SKILL.md +2 -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-sockets/SKILL.md +16 -0
- package/agent/skills/velojs-type-reference/SKILL.md +1 -0
- package/dist/config.d.ts +5 -3
- package/dist/hooks.d.ts +12 -0
- package/dist/hooks.js +22 -22
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +273 -265
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -159,6 +159,8 @@ export const Component = () => {
|
|
|
159
159
|
npm run dev # http://localhost:3000
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
+
To expose the dev server beyond loopback — a VPS behind a reverse proxy, an app reached by hostname — set `HOST=0.0.0.0`, in the shell or in the project's `.env`; no `--host` flag by hand. The security trade-off: a broad bind in dev (`0.0.0.0`, `::`, or `--host` with no value) turns Vite's Host check off, so a request whose `Host` header carries that domain is served instead of 403'd — the DNS-rebinding protection you get on loopback is consciously given up. Stay on localhost unless you are behind a proxy; a `server.allowedHosts` declared in `vite.config.ts` still pins the allowed list.
|
|
163
|
+
|
|
162
164
|
### Configuration
|
|
163
165
|
|
|
164
166
|
```typescript
|
|
@@ -167,6 +169,7 @@ veloPlugin({
|
|
|
167
169
|
routesFile: "routes.tsx", // default
|
|
168
170
|
serverInit: "server.tsx", // default
|
|
169
171
|
clientInit: "client.tsx", // default
|
|
172
|
+
hostname: "127.0.0.1", // bind interface, dev and production (the HOST env wins)
|
|
170
173
|
});
|
|
171
174
|
```
|
|
172
175
|
|
|
@@ -731,7 +734,24 @@ const { data, snapshot, closed, error } = useEventStream(stream, {
|
|
|
731
734
|
| `closed` | `true` when server closed the stream |
|
|
732
735
|
| `error` | Parse or connection error, if any |
|
|
733
736
|
|
|
734
|
-
Lifecycle is automatic: opens on mount, closes on unmount, re-opens
|
|
737
|
+
Lifecycle is automatic: opens on mount, closes on unmount, re-opens when `channel` changes.
|
|
738
|
+
|
|
739
|
+
**Reconnect is stale-while-revalidate.** When the connection re-opens — `channel`, `stream` or `enabled` changed — `data` and `snapshot` keep their previous values until the first event of the new connection overwrites them, the same choice the loader store makes (a refresh must not blank the screen). A channel switch therefore never paints an empty state; only `closed` and `error` reset, because a re-open is a fresh attempt. First mount still starts at `null` and fills in when the snapshot arrives. An app that wants to blank the view on a new channel can clear the signals itself when the channel changes.
|
|
740
|
+
|
|
741
|
+
**Channel coming from loader data?** Pass `enabled` so the hook does not connect before the channel exists — the first render of a SPA navigation has `data = null`, and connecting with `channel: undefined` reaches the server without `?channel=`, which a resolver answers with `null` → 403 → a flash of `closed`:
|
|
742
|
+
|
|
743
|
+
```tsx
|
|
744
|
+
const { data } = useLoader<{ id: string }>();
|
|
745
|
+
const channel = data.value?.id;
|
|
746
|
+
|
|
747
|
+
// no connection until the loader resolves the channel
|
|
748
|
+
const { snapshot, closed } = useEventStream(stream_logs, {
|
|
749
|
+
// spread only when it exists — `exactOptionalPropertyTypes` (the repo's own
|
|
750
|
+
// tsconfig) rejects an explicit `undefined` in an optional property
|
|
751
|
+
...(channel != null && { channel }),
|
|
752
|
+
enabled: channel != null,
|
|
753
|
+
});
|
|
754
|
+
```
|
|
735
755
|
|
|
736
756
|
### `poll` helper
|
|
737
757
|
|
|
@@ -853,6 +873,9 @@ const { send, status, lastMessage, close } = useSocket(socket_terminal, {
|
|
|
853
873
|
```
|
|
854
874
|
|
|
855
875
|
- `status: Signal<"connecting" | "open" | "closed">` — reactive.
|
|
876
|
+
- `lastMessage: Signal<string | Uint8Array | null>` — last frame received.
|
|
877
|
+
- **Reconnect preserves `lastMessage`** — changing `stub.__path`, `channel` or `enabled` opens a new socket, but the previous frame stays until the first frame of the new one arrives (stale-while-revalidate, same as `useEventStream`); `status` restarts at `"connecting"` and `error` resets. Swapping the stub object with the same `__path` does not reconnect. Clear `lastMessage` yourself in `onOpen` if a channel switch must blank the view.
|
|
878
|
+
- **Channel coming from loader data?** Pass `enabled: channel != null` so the socket only opens once the channel resolves — same reason as `useEventStream`.
|
|
856
879
|
- **No auto-reconnect** — sockets are usually stateful (pty sessions, collaborative state); blind reconnect loses state silently. Re-mount or toggle `enabled` to reconnect.
|
|
857
880
|
|
|
858
881
|
### Testing
|
|
@@ -1252,6 +1275,7 @@ Callbacks queue until the server starts. If called after startup, executes immed
|
|
|
1252
1275
|
| Variable | Default | Description |
|
|
1253
1276
|
|----------|---------|-------------|
|
|
1254
1277
|
| `PORT` | `3000` | Server port. Overrides the `port` set in `defineConfig` |
|
|
1278
|
+
| `HOST` | — | Bind interface, in dev and production. Overrides `defineConfig`'s `hostname`; in dev an explicit `--host`/`server.host` still wins |
|
|
1255
1279
|
| `NODE_ENV` | — | Set automatically by `velojs start`. Enables static file serving |
|
|
1256
1280
|
| `STATIC_BASE_URL` | `""` | CDN/bucket prefix for static assets |
|
|
1257
1281
|
|
|
@@ -1455,6 +1479,8 @@ interface VeloConfig {
|
|
|
1455
1479
|
routesFile?: string; // default: "routes.tsx"
|
|
1456
1480
|
serverInit?: string; // default: "server.tsx"
|
|
1457
1481
|
clientInit?: string; // default: "client.tsx"
|
|
1482
|
+
port?: number; // default: 3000; the PORT env wins
|
|
1483
|
+
hostname?: string; // bind interface, dev and production; the HOST env wins
|
|
1458
1484
|
}
|
|
1459
1485
|
```
|
|
1460
1486
|
|
|
@@ -389,6 +389,34 @@ useEventStream(stream, {
|
|
|
389
389
|
|
|
390
390
|
The hook handles `EventSource` lifecycle automatically: opens on mount, closes on unmount, re-opens with a fresh connection when `channel` changes.
|
|
391
391
|
|
|
392
|
+
### Reconnect keeps the last value (stale-while-revalidate)
|
|
393
|
+
|
|
394
|
+
When the connection re-opens — `channel`, `stream` or `enabled` changed — `data` and `snapshot` keep their previous values until the first event of the new connection overwrites them. It is the same choice the loader store makes: a refresh must not blank the screen. Without it, a channel switch (navigating from `/deploys/1` to `/deploys/2` with the stream in a layout that survives the navigation) would paint an empty state for a full round-trip before the new snapshot arrives.
|
|
395
|
+
|
|
396
|
+
`closed` and `error` do reset on a re-open: a reconnect is a fresh attempt, not a closed stream. First mount still starts at `null` and fills in when the snapshot arrives — seed it from loader data if that first frame matters to your UI.
|
|
397
|
+
|
|
398
|
+
If a channel switch must blank the view, clear the signals yourself in an effect keyed on the channel.
|
|
399
|
+
|
|
400
|
+
### Don't connect before the channel exists
|
|
401
|
+
|
|
402
|
+
When `channel` derives from loader data, the first render of a SPA navigation has it `undefined` (the loader fetch is post-mount). The hook would then connect **without** `?channel=`, and a resolver that returns `null`/`undefined` for a missing channel answers **403** — the client sees `closed = true` and paints a broken state for the milliseconds until the loader resolves and the effect reconnects.
|
|
403
|
+
|
|
404
|
+
Pass `enabled` to gate the connection on the channel:
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
const { data } = useLoader<{ id: string }>();
|
|
408
|
+
const channel = data.value?.id;
|
|
409
|
+
|
|
410
|
+
const { snapshot, closed } = useEventStream(stream_logs, {
|
|
411
|
+
// spread only when it exists — `exactOptionalPropertyTypes` (the repo's own
|
|
412
|
+
// tsconfig) rejects an explicit `undefined` in an optional property
|
|
413
|
+
...(channel != null && { channel }),
|
|
414
|
+
enabled: channel != null, // no connection until the loader resolves the id
|
|
415
|
+
});
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
That flash is a documentation-level concern, not a hook one: the hook cannot distinguish "channel still loading" from "stream has no channel". `enabled` is the switch that expresses the difference.
|
|
419
|
+
|
|
392
420
|
## Heartbeat
|
|
393
421
|
|
|
394
422
|
VeloJS sends a `:heartbeat` SSE comment every 20 seconds by default. Without this, idle connections are closed by Cloudflare (~100s), Nginx (~60s), and AWS ALB (~60s) — and the client doesn't even notice.
|
|
@@ -175,6 +175,8 @@ npm run dev
|
|
|
175
175
|
|
|
176
176
|
Open `http://localhost:3000` in your browser. Changes to your code will hot-reload instantly.
|
|
177
177
|
|
|
178
|
+
The dev server binds loopback by default. To expose it beyond that — a VPS behind a reverse proxy, an app reached by a real hostname — set `HOST=0.0.0.0`, in the shell or in the project's `.env`; no `--host` flag by hand. A broad bind in dev (`0.0.0.0`, `::`, or `--host` with no value) also turns Vite's Host check off, so a request whose `Host` header carries that domain is served instead of 403'd — the DNS-rebinding protection you get on loopback is consciously traded away. A `server.allowedHosts` declared in `vite.config.ts` still pins the allowed list.
|
|
179
|
+
|
|
178
180
|
## Configuration
|
|
179
181
|
|
|
180
182
|
The `veloPlugin()` accepts optional configuration:
|
|
@@ -79,6 +79,12 @@ By default `velojs start` binds to **all interfaces** (`::`) — the norm for No
|
|
|
79
79
|
2. The `hostname` field in `defineConfig`.
|
|
80
80
|
3. The Node default (all interfaces).
|
|
81
81
|
|
|
82
|
+
The same declaration covers the dev server, with one extra step at the top: `velojs dev --host <value>` (or a `server.host` in `vite.config.ts`) wins, then `HOST`, then `hostname`, then Vite's default (loopback). `HOST=0.0.0.0` in the shell or in the project's `.env` therefore lifts `velojs dev` beyond loopback with no flag by hand.
|
|
83
|
+
|
|
84
|
+
### Dev behind a reverse proxy: the Host check
|
|
85
|
+
|
|
86
|
+
When a dev server binds broad it sits behind the proxy (or is reached by hostname), and requests arrive carrying the proxy's domain in the `Host` header. Vite's DNS-rebinding protection answers `403 Blocked request. This host is not allowed.` for any host outside its allow list — so the framework opens it whenever the declared bind is broad (`0.0.0.0`, `::`, or `--host` with no value): any `Host` is served. That is a conscious trade-off — the guard exists for loopback development, and leaving loopback means giving it up. If the project declared `server.allowedHosts`, that list wins and stays restrictive even on a broad bind.
|
|
87
|
+
|
|
82
88
|
### Secure bind for local/sensitive apps
|
|
83
89
|
|
|
84
90
|
If your app is **local and single-user** — a cockpit with a terminal, file access, real user data — it must listen on loopback only. An all-interfaces bind exposes that surface to the whole network without any error: the developer finds out by scanning, not by the app telling them.
|
|
@@ -151,5 +151,6 @@ Callbacks registered with `onServer` queue until the server starts. If called af
|
|
|
151
151
|
| Variable | Default | Description |
|
|
152
152
|
|----------|---------|-------------|
|
|
153
153
|
| `PORT` | `3000` | The port the server listens on. Overrides `defineConfig`'s `port`. |
|
|
154
|
+
| `HOST` | — | The bind interface, in dev and production. Overrides `defineConfig`'s `hostname`; in dev an explicit `--host`/`server.host` still wins. |
|
|
154
155
|
| `NODE_ENV` | — | Set automatically by `velojs start` to `production` |
|
|
155
156
|
| `STATIC_BASE_URL` | `""` | CDN/bucket prefix for static assets |
|
|
@@ -206,6 +206,22 @@ const { send, status, lastMessage, error, close } = useSocket(stub, {
|
|
|
206
206
|
- `send(msg)` — queues messages sent while `connecting`; drops messages sent while `closed`.
|
|
207
207
|
- `close(code?, reason?)` — client-initiated disconnect.
|
|
208
208
|
|
|
209
|
+
**Reconnect keeps `lastMessage` (stale-while-revalidate).** Changing `stub.__path`, `channel` or `enabled` opens a fresh socket, but the previous frame stays in `lastMessage` until the first frame of the new socket arrives — switching from a worker terminal to another one does not paint a blank view for a round-trip. It is the same choice the loader store and `useEventStream` make. `status` restarts at `"connecting"` and `error` resets, because a reconnect is a fresh attempt; a new stub object with the same `__path` is not a reconnect at all. If a channel switch must blank the view, clear `lastMessage` in `onOpen`.
|
|
210
|
+
|
|
211
|
+
**Channel coming from loader data?** The first render of a SPA navigation has no channel yet (the loader fetch is post-mount), and connecting then reaches the server without `?channel=` — for a guarded socket that is an error, not a connection. Pass `enabled: channel != null` to wait for the loader:
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
const { data } = useLoader<{ workerId: string }>();
|
|
215
|
+
const channel = data.value?.workerId;
|
|
216
|
+
|
|
217
|
+
const { send, status, lastMessage } = useSocket(socket_terminal, {
|
|
218
|
+
// spread only when it exists — `exactOptionalPropertyTypes` (the repo's own
|
|
219
|
+
// tsconfig) rejects an explicit `undefined` in an optional property
|
|
220
|
+
...(channel != null && { channel }),
|
|
221
|
+
enabled: channel != null, // no socket until the loader resolves the id
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
209
225
|
**No auto-reconnect.** If the server closes the socket (network drop, server restart), `status` goes to `"closed"` and stays there. The caller decides whether/when to reconnect — typically by toggling `enabled` or re-mounting the component. This is intentional: sockets are usually stateful (pty session, collaborative cursor) and a blind reconnect would silently lose state.
|
|
210
226
|
|
|
211
227
|
## Testing
|
|
@@ -138,5 +138,6 @@ interface VeloConfig {
|
|
|
138
138
|
serverInit?: string; // default: "server.tsx"
|
|
139
139
|
clientInit?: string; // default: "client.tsx"
|
|
140
140
|
port?: number; // default: 3000 (the PORT env always wins)
|
|
141
|
+
hostname?: string; // bind interface, dev and production; the HOST env wins
|
|
141
142
|
}
|
|
142
143
|
```
|
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/hooks.d.ts
CHANGED
|
@@ -166,6 +166,13 @@ export declare function usePathname(): string;
|
|
|
166
166
|
*
|
|
167
167
|
* The connection closes automatically when the component unmounts or when
|
|
168
168
|
* the channel changes (re-opens with new channel).
|
|
169
|
+
*
|
|
170
|
+
* Stale-while-revalidate: on a re-open (new `channel`/`stream`/`enabled`) the
|
|
171
|
+
* previous `data`/`snapshot` stay in place until the first event of the new
|
|
172
|
+
* connection overwrites them — the same choice the loader store makes. Only
|
|
173
|
+
* `closed`/`error` reset, because a re-open is a fresh attempt. To connect
|
|
174
|
+
* only once a channel derived from loader data has resolved, pass
|
|
175
|
+
* `enabled: channel != null`.
|
|
169
176
|
*/
|
|
170
177
|
export declare function useEventStream<TEvent, TSnapshot = TEvent>(stream: EventStream<TEvent, TSnapshot>, options?: {
|
|
171
178
|
channel?: string;
|
|
@@ -218,6 +225,11 @@ export interface UseSocketApi {
|
|
|
218
225
|
* becomes `"closed"` and stays that way — user flow decides whether to
|
|
219
226
|
* reconnect (typically by re-mounting or toggling `enabled`).
|
|
220
227
|
*
|
|
228
|
+
* Stale-while-revalidate: on reconnect (new `stub.__path`/`channel`/`enabled`)
|
|
229
|
+
* `lastMessage` keeps its previous value until the first frame of the new
|
|
230
|
+
* socket arrives; `status`/`error` restart as a fresh attempt
|
|
231
|
+
* (`"connecting"` → `"open"`).
|
|
232
|
+
*
|
|
221
233
|
* ```tsx
|
|
222
234
|
* const { send, status, lastMessage } = useSocket(socket_terminal, {
|
|
223
235
|
* channel: workerId,
|
package/dist/hooks.js
CHANGED
|
@@ -45,10 +45,10 @@ function B(e, n) {
|
|
|
45
45
|
if (!t)
|
|
46
46
|
return { data: u(null), loading: u(!1), refetch: () => {
|
|
47
47
|
} };
|
|
48
|
-
const o = N(t), a = m(t),
|
|
48
|
+
const o = N(t), a = m(t), l = () => D(t), d = S(!0);
|
|
49
49
|
return E(() => {
|
|
50
|
-
d.current && (d.current = !1, o.value !== null) ||
|
|
51
|
-
}, r ?? []), { data: o, loading: a, refetch:
|
|
50
|
+
d.current && (d.current = !1, o.value !== null) || l();
|
|
51
|
+
}, r ?? []), { data: o, loading: a, refetch: l };
|
|
52
52
|
}
|
|
53
53
|
function J() {
|
|
54
54
|
const [, e] = b();
|
|
@@ -69,15 +69,15 @@ function x() {
|
|
|
69
69
|
return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__pathname ?? "/" : (b(), window.location.pathname);
|
|
70
70
|
}
|
|
71
71
|
function G(e, n = {}) {
|
|
72
|
-
const t = u(null), r = u(null), o = u(!1), a = u(null), { channel:
|
|
72
|
+
const t = u(null), r = u(null), o = u(!1), a = u(null), { channel: l, enabled: d = !0 } = n;
|
|
73
73
|
return E(() => {
|
|
74
74
|
if (typeof window > "u" || !d) return;
|
|
75
75
|
if (!e.__path) {
|
|
76
76
|
console.warn("[velojs] useEventStream: stream has no __path");
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
const g =
|
|
79
|
+
o.value = !1, a.value = null;
|
|
80
|
+
const g = l ? `${e.__path}?channel=${encodeURIComponent(l)}` : e.__path, s = new EventSource(g);
|
|
81
81
|
return s.addEventListener("snapshot", (h) => {
|
|
82
82
|
try {
|
|
83
83
|
r.value = JSON.parse(h.data);
|
|
@@ -98,41 +98,41 @@ function G(e, n = {}) {
|
|
|
98
98
|
}), () => {
|
|
99
99
|
s.close();
|
|
100
100
|
};
|
|
101
|
-
}, [e,
|
|
101
|
+
}, [e, l, d]), { data: t, snapshot: r, closed: o, error: a };
|
|
102
102
|
}
|
|
103
103
|
function F(e, n = {}) {
|
|
104
|
-
const t = u("connecting"), r = u(null), o = u(null), a = S(null),
|
|
104
|
+
const t = u("connecting"), r = u(null), o = u(null), a = S(null), l = S([]), { channel: d, onMessage: g, onOpen: s, onClose: h, onError: y, enabled: L = !0 } = n;
|
|
105
105
|
return E(() => {
|
|
106
106
|
if (typeof window > "u" || !L) return;
|
|
107
107
|
if (!e.__path) {
|
|
108
108
|
console.warn("[velojs] useSocket: stub has no __path");
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
|
-
t.value = "connecting",
|
|
111
|
+
t.value = "connecting", o.value = null;
|
|
112
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);
|
|
113
113
|
return f.binaryType = "arraybuffer", a.current = f, f.addEventListener("open", () => {
|
|
114
114
|
t.value = "open";
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
for (const _ of
|
|
115
|
+
const c = l.current;
|
|
116
|
+
l.current = [];
|
|
117
|
+
for (const _ of c)
|
|
118
118
|
try {
|
|
119
119
|
f.send(_);
|
|
120
120
|
} catch {
|
|
121
121
|
}
|
|
122
122
|
s?.();
|
|
123
|
-
}), f.addEventListener("message", (
|
|
123
|
+
}), f.addEventListener("message", (c) => {
|
|
124
124
|
let _;
|
|
125
|
-
if (typeof
|
|
126
|
-
_ =
|
|
127
|
-
else if (
|
|
128
|
-
_ = new Uint8Array(
|
|
125
|
+
if (typeof c.data == "string")
|
|
126
|
+
_ = c.data;
|
|
127
|
+
else if (c.data instanceof ArrayBuffer)
|
|
128
|
+
_ = new Uint8Array(c.data);
|
|
129
129
|
else
|
|
130
130
|
return;
|
|
131
131
|
r.value = _, g?.(_);
|
|
132
|
-
}), f.addEventListener("close", (
|
|
133
|
-
t.value = "closed", a.current = null, h?.(
|
|
134
|
-
}), f.addEventListener("error", (
|
|
135
|
-
o.value =
|
|
132
|
+
}), f.addEventListener("close", (c) => {
|
|
133
|
+
t.value = "closed", a.current = null, h?.(c);
|
|
134
|
+
}), f.addEventListener("error", (c) => {
|
|
135
|
+
o.value = c, y?.(c);
|
|
136
136
|
}), () => {
|
|
137
137
|
a.current = null;
|
|
138
138
|
try {
|
|
@@ -149,7 +149,7 @@ function F(e, n = {}) {
|
|
|
149
149
|
i.send(v);
|
|
150
150
|
} catch {
|
|
151
151
|
}
|
|
152
|
-
else i && i.readyState === WebSocket.CONNECTING &&
|
|
152
|
+
else i && i.readyState === WebSocket.CONNECTING && l.current.push(v);
|
|
153
153
|
}, close: (p, v) => {
|
|
154
154
|
const i = a.current;
|
|
155
155
|
if (i)
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type PluginOption } from "vite";
|
|
2
2
|
import type { VeloConfig } from "./config.js";
|
|
3
3
|
import * as t from "@babel/types";
|
|
4
4
|
export declare function injectMetadata(code: string, moduleId: string, fullPath?: string, path?: string): string;
|
package/dist/vite.js
CHANGED
|
@@ -1,60 +1,61 @@
|
|
|
1
|
+
import { loadEnv as R } from "vite";
|
|
1
2
|
import d from "node:path";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { parse as
|
|
6
|
-
import
|
|
7
|
-
import
|
|
3
|
+
import S from "node:fs";
|
|
4
|
+
import $ from "@preact/preset-vite";
|
|
5
|
+
import H, { defaultOptions as J } from "@hono/vite-dev-server";
|
|
6
|
+
import { parse as v } from "@babel/parser";
|
|
7
|
+
import A from "@babel/traverse";
|
|
8
|
+
import N from "@babel/generator";
|
|
8
9
|
import * as e from "@babel/types";
|
|
9
10
|
import { buildGraph as U } from "./graph.js";
|
|
10
|
-
const m = typeof
|
|
11
|
-
function W(
|
|
12
|
-
const l =
|
|
11
|
+
const m = typeof A == "function" ? A : A.default, _ = typeof N == "function" ? N : N.default;
|
|
12
|
+
function W(p, s, r, i) {
|
|
13
|
+
const l = v(p, {
|
|
13
14
|
sourceType: "module",
|
|
14
15
|
plugins: ["typescript", "jsx"]
|
|
15
16
|
});
|
|
16
17
|
let t = !1;
|
|
17
18
|
if (m(l, {
|
|
18
19
|
// Procura: export const metadata = { ... }
|
|
19
|
-
ExportNamedDeclaration(
|
|
20
|
-
const c =
|
|
20
|
+
ExportNamedDeclaration(o) {
|
|
21
|
+
const c = o.node.declaration;
|
|
21
22
|
if (e.isVariableDeclaration(c) && c.declarations.length === 1) {
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
23
|
+
const n = c.declarations[0];
|
|
24
|
+
if (n && e.isIdentifier(n.id, { name: "metadata" }) && e.isObjectExpression(n.init)) {
|
|
24
25
|
t = !0;
|
|
25
|
-
const f =
|
|
26
|
+
const f = n.init.properties.filter((y) => e.isObjectProperty(y) && e.isIdentifier(y.key) ? y.key.name !== "moduleId" && y.key.name !== "fullPath" && y.key.name !== "path" : !0), h = [
|
|
26
27
|
e.objectProperty(
|
|
27
28
|
e.identifier("moduleId"),
|
|
28
|
-
e.stringLiteral(
|
|
29
|
+
e.stringLiteral(s)
|
|
29
30
|
)
|
|
30
31
|
];
|
|
31
|
-
|
|
32
|
+
r !== void 0 && h.push(
|
|
32
33
|
e.objectProperty(
|
|
33
34
|
e.identifier("fullPath"),
|
|
34
|
-
e.stringLiteral(
|
|
35
|
+
e.stringLiteral(r)
|
|
35
36
|
)
|
|
36
|
-
), i !== void 0 &&
|
|
37
|
+
), i !== void 0 && h.push(
|
|
37
38
|
e.objectProperty(
|
|
38
39
|
e.identifier("path"),
|
|
39
40
|
e.stringLiteral(i)
|
|
40
41
|
)
|
|
41
|
-
),
|
|
42
|
+
), n.init.properties = [...h, ...f];
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
}), !t) {
|
|
46
|
-
const
|
|
47
|
+
const o = [
|
|
47
48
|
e.objectProperty(
|
|
48
49
|
e.identifier("moduleId"),
|
|
49
|
-
e.stringLiteral(
|
|
50
|
+
e.stringLiteral(s)
|
|
50
51
|
)
|
|
51
52
|
];
|
|
52
|
-
|
|
53
|
+
r !== void 0 && o.push(
|
|
53
54
|
e.objectProperty(
|
|
54
55
|
e.identifier("fullPath"),
|
|
55
|
-
e.stringLiteral(
|
|
56
|
+
e.stringLiteral(r)
|
|
56
57
|
)
|
|
57
|
-
), i !== void 0 &&
|
|
58
|
+
), i !== void 0 && o.push(
|
|
58
59
|
e.objectProperty(
|
|
59
60
|
e.identifier("path"),
|
|
60
61
|
e.stringLiteral(i)
|
|
@@ -64,51 +65,51 @@ function W(u, o, n, i) {
|
|
|
64
65
|
e.variableDeclaration("const", [
|
|
65
66
|
e.variableDeclarator(
|
|
66
67
|
e.identifier("metadata"),
|
|
67
|
-
e.objectExpression(
|
|
68
|
+
e.objectExpression(o)
|
|
68
69
|
)
|
|
69
70
|
])
|
|
70
71
|
);
|
|
71
72
|
l.program.body.unshift(c);
|
|
72
73
|
}
|
|
73
|
-
return
|
|
74
|
+
return _(l, { retainLines: !0 }).code;
|
|
74
75
|
}
|
|
75
|
-
function
|
|
76
|
-
const
|
|
76
|
+
function B(p, s) {
|
|
77
|
+
const r = v(p, {
|
|
77
78
|
sourceType: "module",
|
|
78
79
|
plugins: ["typescript", "jsx"]
|
|
79
80
|
});
|
|
80
|
-
return m(
|
|
81
|
+
return m(r, {
|
|
81
82
|
CallExpression(l) {
|
|
82
|
-
const t = l.node.callee, a = e.isIdentifier(t, { name: "Loader" }) || e.isTSInstantiationExpression(t) && e.isIdentifier(t.expression, { name: "Loader" }),
|
|
83
|
-
if (!a && !
|
|
84
|
-
const c = l.node.arguments,
|
|
85
|
-
e.isStringLiteral(
|
|
83
|
+
const t = l.node.callee, a = e.isIdentifier(t, { name: "Loader" }) || e.isTSInstantiationExpression(t) && e.isIdentifier(t.expression, { name: "Loader" }), o = e.isIdentifier(t, { name: "useLoader" }) || e.isTSInstantiationExpression(t) && e.isIdentifier(t.expression, { name: "useLoader" });
|
|
84
|
+
if (!a && !o) return;
|
|
85
|
+
const c = l.node.arguments, n = e.stringLiteral(s), u = c[0];
|
|
86
|
+
e.isStringLiteral(u) && u.value.includes("/") || (l.node.arguments = [n, ...c]);
|
|
86
87
|
}
|
|
87
|
-
}),
|
|
88
|
+
}), _(r, { retainLines: !0 }).code;
|
|
88
89
|
}
|
|
89
|
-
function
|
|
90
|
-
const
|
|
90
|
+
function M(p, s) {
|
|
91
|
+
const r = v(p, {
|
|
91
92
|
sourceType: "module",
|
|
92
93
|
plugins: ["typescript", "jsx"]
|
|
93
94
|
});
|
|
94
|
-
return m(
|
|
95
|
+
return m(r, {
|
|
95
96
|
ExportNamedDeclaration(l) {
|
|
96
97
|
const t = l.node.declaration;
|
|
97
98
|
if (!e.isVariableDeclaration(t)) return;
|
|
98
99
|
const a = t.declarations[0];
|
|
99
100
|
if (!a || !e.isIdentifier(a.id)) return;
|
|
100
|
-
const
|
|
101
|
-
if (!
|
|
102
|
-
const c =
|
|
103
|
-
if (!e.isArrowFunctionExpression(
|
|
104
|
-
const
|
|
105
|
-
|
|
101
|
+
const o = a.id.name;
|
|
102
|
+
if (!o.startsWith("action_")) return;
|
|
103
|
+
const c = o.replace("action_", ""), n = a.init;
|
|
104
|
+
if (!e.isArrowFunctionExpression(n) || !n.async) return;
|
|
105
|
+
const u = n.params, f = G(s, c, u);
|
|
106
|
+
n.body = e.blockStatement([e.returnStatement(f)]), z(n, u);
|
|
106
107
|
}
|
|
107
|
-
}),
|
|
108
|
+
}), _(r, { retainLines: !0 }).code;
|
|
108
109
|
}
|
|
109
|
-
function
|
|
110
|
-
const i = `/_action/${
|
|
111
|
-
return
|
|
110
|
+
function G(p, s, r) {
|
|
111
|
+
const i = `/_action/${p}/${s}`;
|
|
112
|
+
return r.length === 0 ? e.callExpression(
|
|
112
113
|
e.memberExpression(
|
|
113
114
|
e.callExpression(e.identifier("fetch"), [
|
|
114
115
|
e.stringLiteral(i),
|
|
@@ -176,13 +177,13 @@ function H(u, o, n) {
|
|
|
176
177
|
]
|
|
177
178
|
);
|
|
178
179
|
}
|
|
179
|
-
function
|
|
180
|
-
if (
|
|
181
|
-
const
|
|
182
|
-
if (e.isObjectPattern(
|
|
180
|
+
function z(p, s) {
|
|
181
|
+
if (s.length === 0) return;
|
|
182
|
+
const r = s[0];
|
|
183
|
+
if (e.isObjectPattern(r)) {
|
|
183
184
|
let i = null;
|
|
184
|
-
if (e.isTSTypeAnnotation(
|
|
185
|
-
const a =
|
|
185
|
+
if (e.isTSTypeAnnotation(r.typeAnnotation) && e.isTSTypeReference(r.typeAnnotation.typeAnnotation)) {
|
|
186
|
+
const a = r.typeAnnotation.typeAnnotation;
|
|
186
187
|
e.isIdentifier(a.typeName, { name: "ActionArgs" }) && a.typeParameters?.params[0] && (i = a.typeParameters.params[0]);
|
|
187
188
|
}
|
|
188
189
|
const l = e.objectProperty(
|
|
@@ -199,23 +200,23 @@ function G(u, o) {
|
|
|
199
200
|
e.tsTypeAnnotation(i)
|
|
200
201
|
)
|
|
201
202
|
])
|
|
202
|
-
)),
|
|
203
|
+
)), p.params = [t];
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
|
-
function
|
|
206
|
-
const
|
|
206
|
+
function Y(p, s) {
|
|
207
|
+
const r = v(p, {
|
|
207
208
|
sourceType: "module",
|
|
208
209
|
plugins: ["typescript", "jsx"]
|
|
209
210
|
});
|
|
210
|
-
return m(
|
|
211
|
+
return m(r, {
|
|
211
212
|
ExportNamedDeclaration(l) {
|
|
212
213
|
const t = l.node.declaration;
|
|
213
214
|
if (!e.isVariableDeclaration(t)) return;
|
|
214
215
|
const a = t.declarations[0];
|
|
215
216
|
if (!a || !e.isIdentifier(a.id)) return;
|
|
216
|
-
const
|
|
217
|
-
if (!
|
|
218
|
-
const c =
|
|
217
|
+
const o = a.id.name;
|
|
218
|
+
if (!o.startsWith("stream_")) return;
|
|
219
|
+
const c = o.replace("stream_", ""), n = `/_event/${s}/${c}`;
|
|
219
220
|
a.init = e.objectExpression([
|
|
220
221
|
e.objectProperty(
|
|
221
222
|
e.identifier("__isVeloEventStream"),
|
|
@@ -223,26 +224,26 @@ function z(u, o) {
|
|
|
223
224
|
),
|
|
224
225
|
e.objectProperty(
|
|
225
226
|
e.identifier("__path"),
|
|
226
|
-
e.stringLiteral(
|
|
227
|
+
e.stringLiteral(n)
|
|
227
228
|
)
|
|
228
229
|
]), a.id.typeAnnotation = null;
|
|
229
230
|
}
|
|
230
|
-
}),
|
|
231
|
+
}), _(r, { retainLines: !0 }).code;
|
|
231
232
|
}
|
|
232
|
-
function
|
|
233
|
-
const
|
|
233
|
+
function X(p, s) {
|
|
234
|
+
const r = v(p, {
|
|
234
235
|
sourceType: "module",
|
|
235
236
|
plugins: ["typescript", "jsx"]
|
|
236
237
|
});
|
|
237
|
-
return m(
|
|
238
|
+
return m(r, {
|
|
238
239
|
ExportNamedDeclaration(l) {
|
|
239
240
|
const t = l.node.declaration;
|
|
240
241
|
if (!e.isVariableDeclaration(t)) return;
|
|
241
242
|
const a = t.declarations[0];
|
|
242
243
|
if (!a || !e.isIdentifier(a.id)) return;
|
|
243
|
-
const
|
|
244
|
-
if (!
|
|
245
|
-
const c =
|
|
244
|
+
const o = a.id.name;
|
|
245
|
+
if (!o.startsWith("socket_")) return;
|
|
246
|
+
const c = o.replace("socket_", ""), n = `/_socket/${s}/${c}`;
|
|
246
247
|
a.init = e.objectExpression([
|
|
247
248
|
e.objectProperty(
|
|
248
249
|
e.identifier("__isVeloSocket"),
|
|
@@ -250,300 +251,303 @@ function Y(u, o) {
|
|
|
250
251
|
),
|
|
251
252
|
e.objectProperty(
|
|
252
253
|
e.identifier("__path"),
|
|
253
|
-
e.stringLiteral(
|
|
254
|
+
e.stringLiteral(n)
|
|
254
255
|
)
|
|
255
256
|
]), a.id.typeAnnotation = null;
|
|
256
257
|
}
|
|
257
|
-
}),
|
|
258
|
+
}), _(r, { retainLines: !0 }).code;
|
|
258
259
|
}
|
|
259
|
-
function
|
|
260
|
-
const
|
|
260
|
+
function q(p) {
|
|
261
|
+
const s = v(p, {
|
|
261
262
|
sourceType: "module",
|
|
262
263
|
plugins: ["typescript", "jsx"]
|
|
263
264
|
});
|
|
264
|
-
return m(
|
|
265
|
+
return m(s, {
|
|
265
266
|
ExportNamedDeclaration(i) {
|
|
266
267
|
const l = i.node.declaration;
|
|
267
268
|
if (!e.isVariableDeclaration(l)) return;
|
|
268
269
|
const t = l.declarations[0];
|
|
269
270
|
!t || !e.isIdentifier(t.id) || t.id.name === "loader" && i.remove();
|
|
270
271
|
}
|
|
271
|
-
}),
|
|
272
|
+
}), _(s, { retainLines: !0 }).code;
|
|
272
273
|
}
|
|
273
|
-
function
|
|
274
|
-
const
|
|
274
|
+
function K(p) {
|
|
275
|
+
const s = v(p, {
|
|
275
276
|
sourceType: "module",
|
|
276
277
|
plugins: ["typescript", "jsx"]
|
|
277
|
-
}),
|
|
278
|
-
|
|
278
|
+
}), r = /* @__PURE__ */ new Set();
|
|
279
|
+
I(s.program, r);
|
|
279
280
|
let i = !1;
|
|
280
|
-
return m(
|
|
281
|
+
return m(s, {
|
|
281
282
|
ImportDeclaration(t) {
|
|
282
283
|
const a = t.node.specifiers;
|
|
283
284
|
if (a.length === 0) return;
|
|
284
|
-
const
|
|
285
|
-
|
|
285
|
+
const o = a.filter((c) => r.has(c.local.name));
|
|
286
|
+
o.length !== a.length && (i = !0, o.length === 0 ? t.remove() : t.node.specifiers = o);
|
|
286
287
|
}
|
|
287
|
-
}), i ?
|
|
288
|
+
}), i ? _(s, { retainLines: !0 }).code : p;
|
|
288
289
|
}
|
|
289
|
-
function
|
|
290
|
-
const
|
|
290
|
+
function Q(p) {
|
|
291
|
+
const s = v(p, {
|
|
291
292
|
sourceType: "module",
|
|
292
293
|
plugins: ["typescript", "jsx"]
|
|
293
|
-
}),
|
|
294
|
-
if (m(
|
|
295
|
-
ObjectProperty(
|
|
296
|
-
e.isIdentifier(
|
|
294
|
+
}), r = [];
|
|
295
|
+
if (m(s, {
|
|
296
|
+
ObjectProperty(o) {
|
|
297
|
+
e.isIdentifier(o.node.key, { name: "middlewares" }) && (r.push(o.node.value), o.remove());
|
|
297
298
|
}
|
|
298
|
-
}),
|
|
299
|
+
}), r.length === 0) return p;
|
|
299
300
|
const i = /* @__PURE__ */ new Set();
|
|
300
|
-
for (const
|
|
301
|
-
|
|
301
|
+
for (const o of r)
|
|
302
|
+
I(o, i);
|
|
302
303
|
const l = /* @__PURE__ */ new Set();
|
|
303
|
-
|
|
304
|
+
I(s.program, l);
|
|
304
305
|
const t = /* @__PURE__ */ new Set();
|
|
305
|
-
for (const
|
|
306
|
-
l.has(
|
|
307
|
-
return t.size > 0 && m(
|
|
308
|
-
ImportDeclaration(
|
|
309
|
-
const c =
|
|
310
|
-
|
|
306
|
+
for (const o of i)
|
|
307
|
+
l.has(o) || t.add(o);
|
|
308
|
+
return t.size > 0 && m(s, {
|
|
309
|
+
ImportDeclaration(o) {
|
|
310
|
+
const c = o.node.specifiers, n = c.filter((u) => !t.has(u.local.name));
|
|
311
|
+
n.length === 0 ? o.remove() : n.length !== c.length && (o.node.specifiers = n);
|
|
311
312
|
}
|
|
312
|
-
}),
|
|
313
|
+
}), _(s, { retainLines: !0 }).code;
|
|
313
314
|
}
|
|
314
|
-
function
|
|
315
|
-
const
|
|
315
|
+
function I(p, s) {
|
|
316
|
+
const r = (i) => {
|
|
316
317
|
if (!(!i || typeof i != "object")) {
|
|
317
318
|
if (Array.isArray(i)) {
|
|
318
|
-
for (const l of i)
|
|
319
|
+
for (const l of i) r(l);
|
|
319
320
|
return;
|
|
320
321
|
}
|
|
321
322
|
if (i.type === "Identifier") {
|
|
322
|
-
|
|
323
|
+
s.add(i.name), i.typeAnnotation && r(i.typeAnnotation);
|
|
323
324
|
return;
|
|
324
325
|
}
|
|
325
326
|
if (i.type === "JSXIdentifier") {
|
|
326
|
-
|
|
327
|
+
s.add(i.name);
|
|
327
328
|
return;
|
|
328
329
|
}
|
|
329
330
|
if (i.type === "MemberExpression") {
|
|
330
|
-
|
|
331
|
+
r(i.object), i.computed && r(i.property);
|
|
331
332
|
return;
|
|
332
333
|
}
|
|
333
334
|
if ((i.type === "ObjectProperty" || i.type === "ObjectMethod") && !i.computed) {
|
|
334
|
-
i.type === "ObjectProperty" ?
|
|
335
|
+
i.type === "ObjectProperty" ? r(i.value) : r(i.body);
|
|
335
336
|
return;
|
|
336
337
|
}
|
|
337
338
|
if (!(i.type === "ImportSpecifier" || i.type === "ImportDefaultSpecifier" || i.type === "ImportNamespaceSpecifier"))
|
|
338
339
|
for (const l of Object.keys(i))
|
|
339
|
-
l === "loc" || l === "start" || l === "end" || l === "leadingComments" || l === "trailingComments" || l === "innerComments" ||
|
|
340
|
+
l === "loc" || l === "start" || l === "end" || l === "leadingComments" || l === "trailingComments" || l === "innerComments" || r(i[l]);
|
|
340
341
|
}
|
|
341
342
|
};
|
|
342
|
-
|
|
343
|
+
r(p);
|
|
343
344
|
}
|
|
344
|
-
function
|
|
345
|
-
for (const
|
|
346
|
-
if (e.isObjectProperty(
|
|
345
|
+
function Z(p) {
|
|
346
|
+
for (const s of p.properties)
|
|
347
|
+
if (e.isObjectProperty(s) && e.isIdentifier(s.key) && s.key.name === "handler")
|
|
347
348
|
return !0;
|
|
348
349
|
return !1;
|
|
349
350
|
}
|
|
350
|
-
function
|
|
351
|
-
for (const
|
|
352
|
-
if (e.isObjectProperty(
|
|
353
|
-
return
|
|
351
|
+
function ee(p) {
|
|
352
|
+
for (const s of p.properties)
|
|
353
|
+
if (e.isObjectProperty(s) && e.isIdentifier(s.key) && s.key.name === "children" && e.isArrayExpression(s.value))
|
|
354
|
+
return s.value;
|
|
354
355
|
return null;
|
|
355
356
|
}
|
|
356
|
-
function
|
|
357
|
-
const
|
|
357
|
+
function te(p) {
|
|
358
|
+
const s = v(p, {
|
|
358
359
|
sourceType: "module",
|
|
359
360
|
plugins: ["typescript", "jsx"]
|
|
360
|
-
}),
|
|
361
|
-
for (let
|
|
362
|
-
const
|
|
363
|
-
if (!e.isObjectExpression(
|
|
364
|
-
if (
|
|
365
|
-
|
|
361
|
+
}), r = [], i = (c) => {
|
|
362
|
+
for (let n = c.elements.length - 1; n >= 0; n--) {
|
|
363
|
+
const u = c.elements[n];
|
|
364
|
+
if (!e.isObjectExpression(u)) continue;
|
|
365
|
+
if (Z(u)) {
|
|
366
|
+
r.push(u), c.elements.splice(n, 1);
|
|
366
367
|
continue;
|
|
367
368
|
}
|
|
368
|
-
const f =
|
|
369
|
+
const f = ee(u);
|
|
369
370
|
f && i(f);
|
|
370
371
|
}
|
|
371
372
|
};
|
|
372
|
-
if (m(
|
|
373
|
+
if (m(s, {
|
|
373
374
|
ExportDefaultDeclaration(c) {
|
|
374
|
-
const
|
|
375
|
-
let
|
|
376
|
-
e.isArrayExpression(
|
|
375
|
+
const n = c.node.declaration;
|
|
376
|
+
let u = null;
|
|
377
|
+
e.isArrayExpression(n) ? u = n : (e.isTSSatisfiesExpression(n) && e.isArrayExpression(n.expression) || e.isTSAsExpression(n) && e.isArrayExpression(n.expression)) && (u = n.expression), u && i(u);
|
|
377
378
|
}
|
|
378
|
-
}),
|
|
379
|
+
}), r.length === 0) return p;
|
|
379
380
|
const l = /* @__PURE__ */ new Set();
|
|
380
|
-
for (const c of
|
|
381
|
-
|
|
381
|
+
for (const c of r)
|
|
382
|
+
I(c, l);
|
|
382
383
|
const t = /* @__PURE__ */ new Set();
|
|
383
|
-
|
|
384
|
+
I(s.program, t);
|
|
384
385
|
const a = /* @__PURE__ */ new Set();
|
|
385
386
|
for (const c of l)
|
|
386
387
|
t.has(c) || a.add(c);
|
|
387
|
-
return a.size > 0 && m(
|
|
388
|
+
return a.size > 0 && m(s, {
|
|
388
389
|
ImportDeclaration(c) {
|
|
389
|
-
const
|
|
390
|
-
|
|
390
|
+
const n = c.node.specifiers, u = n.filter((f) => !a.has(f.local.name));
|
|
391
|
+
u.length === 0 ? c.remove() : u.length !== n.length && (c.node.specifiers = u);
|
|
391
392
|
}
|
|
392
|
-
}),
|
|
393
|
+
}), _(s, { retainLines: !0 }).code;
|
|
393
394
|
}
|
|
394
|
-
function
|
|
395
|
-
const
|
|
395
|
+
function w(p) {
|
|
396
|
+
const s = v(p, {
|
|
396
397
|
sourceType: "module",
|
|
397
398
|
plugins: ["typescript", "jsx"]
|
|
398
|
-
}),
|
|
399
|
-
m(
|
|
399
|
+
}), r = /* @__PURE__ */ new Map();
|
|
400
|
+
m(s, {
|
|
400
401
|
ImportDeclaration(t) {
|
|
401
402
|
const a = t.node.source.value;
|
|
402
|
-
for (const
|
|
403
|
-
e.isImportNamespaceSpecifier(
|
|
403
|
+
for (const o of t.node.specifiers)
|
|
404
|
+
e.isImportNamespaceSpecifier(o) && r.set(o.local.name, a);
|
|
404
405
|
}
|
|
405
406
|
});
|
|
406
407
|
const i = /* @__PURE__ */ new Map();
|
|
407
|
-
m(
|
|
408
|
+
m(s, {
|
|
408
409
|
ExportDefaultDeclaration(t) {
|
|
409
410
|
const a = t.node.declaration;
|
|
410
|
-
let
|
|
411
|
-
e.isArrayExpression(a) ?
|
|
411
|
+
let o = null;
|
|
412
|
+
e.isArrayExpression(a) ? o = a : (e.isTSSatisfiesExpression(a) || e.isTSAsExpression(a)) && e.isArrayExpression(a.expression) && (o = a.expression), o && k(o.elements, "", i);
|
|
412
413
|
}
|
|
413
414
|
});
|
|
414
415
|
const l = /* @__PURE__ */ new Map();
|
|
415
416
|
for (const [t, a] of i) {
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
418
|
-
const c =
|
|
417
|
+
const o = r.get(t);
|
|
418
|
+
if (o) {
|
|
419
|
+
const c = o.replace(/^\.\//, "").replace(/\.(tsx?|jsx?|js)$/, "");
|
|
419
420
|
l.set(c, a);
|
|
420
421
|
}
|
|
421
422
|
}
|
|
422
423
|
return l;
|
|
423
424
|
}
|
|
424
|
-
function
|
|
425
|
-
for (const i of
|
|
425
|
+
function k(p, s, r) {
|
|
426
|
+
for (const i of p) {
|
|
426
427
|
if (!e.isObjectExpression(i)) continue;
|
|
427
|
-
let l = "", t =
|
|
428
|
+
let l = "", t = s, a = null, o = null;
|
|
428
429
|
for (const c of i.properties) {
|
|
429
430
|
if (!e.isObjectProperty(c)) continue;
|
|
430
|
-
const
|
|
431
|
-
|
|
431
|
+
const n = c.key, u = e.isIdentifier(n) ? n.name : null;
|
|
432
|
+
u === "path" && e.isStringLiteral(c.value) && (l = c.value.value, l && !l.startsWith("/") ? t = s + "/" + l : t = s + l), u === "module" && e.isIdentifier(c.value) && (a = c.value.name), u === "children" && e.isArrayExpression(c.value) && (o = c.value);
|
|
432
433
|
}
|
|
433
434
|
if (a) {
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
fullPath:
|
|
435
|
+
const n = !o && l === "/" ? s || "/" : t;
|
|
436
|
+
r.set(a, {
|
|
437
|
+
fullPath: n,
|
|
437
438
|
path: l
|
|
438
439
|
});
|
|
439
440
|
}
|
|
440
|
-
|
|
441
|
+
o && k(o.elements, t, r);
|
|
441
442
|
}
|
|
442
443
|
}
|
|
443
|
-
const
|
|
444
|
-
function
|
|
445
|
-
let
|
|
446
|
-
const i =
|
|
444
|
+
const T = "virtual:velo/server-entry", O = "virtual:velo/client-entry", C = "\0" + T, F = "\0" + O;
|
|
445
|
+
function re(p, s) {
|
|
446
|
+
let r = d.resolve(process.cwd(), s);
|
|
447
|
+
const i = p.routesFile ?? "routes.tsx", l = /* @__PURE__ */ new Map();
|
|
447
448
|
return {
|
|
448
449
|
name: "velo:transform",
|
|
449
450
|
enforce: "pre",
|
|
450
451
|
configResolved(t) {
|
|
451
|
-
|
|
452
|
+
r = d.resolve(t.root, s);
|
|
452
453
|
},
|
|
453
454
|
buildStart() {
|
|
454
|
-
const t = d.join(
|
|
455
|
-
if (
|
|
456
|
-
const a =
|
|
455
|
+
const t = d.join(r, i);
|
|
456
|
+
if (S.existsSync(t)) {
|
|
457
|
+
const a = S.readFileSync(t, "utf-8"), o = w(a);
|
|
457
458
|
l.clear();
|
|
458
|
-
for (const [c,
|
|
459
|
-
l.set(c,
|
|
459
|
+
for (const [c, n] of o)
|
|
460
|
+
l.set(c, n);
|
|
460
461
|
}
|
|
461
462
|
},
|
|
462
463
|
handleHotUpdate({ file: t, server: a }) {
|
|
463
|
-
const
|
|
464
|
-
if (t ===
|
|
465
|
-
const c =
|
|
464
|
+
const o = d.join(r, i);
|
|
465
|
+
if (t === o) {
|
|
466
|
+
const c = S.readFileSync(o, "utf-8"), n = w(c);
|
|
466
467
|
l.clear();
|
|
467
|
-
for (const [
|
|
468
|
-
l.set(
|
|
468
|
+
for (const [u, f] of n)
|
|
469
|
+
l.set(u, f);
|
|
469
470
|
return a.ws.send({ type: "full-reload" }), [];
|
|
470
471
|
}
|
|
471
472
|
},
|
|
472
473
|
resolveId(t) {
|
|
473
|
-
return t ===
|
|
474
|
+
return t === T || t.endsWith(T) ? C : t === O || t.endsWith(O) || t === "/__velo_client.js" ? F : null;
|
|
474
475
|
},
|
|
475
476
|
load(t) {
|
|
476
|
-
const a =
|
|
477
|
-
return t ===
|
|
477
|
+
const a = p.routesFile ?? "routes.tsx", o = p.serverInit ?? "server.tsx", c = p.clientInit ?? "client.tsx", n = d.join(r, a).replace(/\.tsx?$/, ".js"), u = d.join(r, o).replace(/\.tsx?$/, ".js"), f = d.join(r, c).replace(/\.tsx?$/, ".js");
|
|
478
|
+
return t === C ? `
|
|
478
479
|
globalThis.__veloBuildHash = __VELO_BUILD_HASH__;
|
|
479
480
|
globalThis.__veloClientJs = __VELO_CLIENT_JS__;
|
|
480
481
|
globalThis.__veloClientCss = __VELO_CLIENT_CSS__;
|
|
481
|
-
import "${
|
|
482
|
-
import routes from "${
|
|
482
|
+
import "${u}";
|
|
483
|
+
import routes from "${n}";
|
|
483
484
|
import { startServer } from "@mauroandre/velojs/server";
|
|
484
485
|
|
|
485
486
|
export { routes };
|
|
486
487
|
export default await startServer({ routes, port: __VELO_CONFIG_PORT__, hostname: __VELO_CONFIG_HOSTNAME__ });
|
|
487
|
-
` : t ===
|
|
488
|
+
` : t === F ? `
|
|
488
489
|
import "${f}";
|
|
489
|
-
import routes from "${
|
|
490
|
+
import routes from "${n}";
|
|
490
491
|
import { startClient } from "@mauroandre/velojs/client";
|
|
491
492
|
|
|
492
493
|
startClient({ routes });
|
|
493
494
|
` : null;
|
|
494
495
|
},
|
|
495
|
-
transform(t, a,
|
|
496
|
-
const c =
|
|
497
|
-
if (a.startsWith("\0") || a.includes("/.velojs/") || !a.endsWith(".tsx") && !a.endsWith(".ts") || !a.startsWith(
|
|
498
|
-
let
|
|
499
|
-
const f = /middlewares:\s*\[/.test(t),
|
|
496
|
+
transform(t, a, o) {
|
|
497
|
+
const c = o?.ssr === !0;
|
|
498
|
+
if (a.startsWith("\0") || a.includes("/.velojs/") || !a.endsWith(".tsx") && !a.endsWith(".ts") || !a.startsWith(r)) return null;
|
|
499
|
+
let n = t, u = !1;
|
|
500
|
+
const f = /middlewares:\s*\[/.test(t), h = /export\s+(const|function)\s+Component/.test(
|
|
500
501
|
t
|
|
501
|
-
),
|
|
502
|
-
if (!c && f && (
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
)), !c &&
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
)), !c &&
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
)), c || (
|
|
502
|
+
), y = /export\s+(const|function)\s+loader/.test(t), b = /export\s+const\s+action_\w+/.test(t), j = /export\s+const\s+stream_\w+/.test(t), x = /export\s+const\s+socket_\w+/.test(t), L = /\bLoader\s*</.test(t) || /\bLoader\s*\(/.test(t), P = /\buseLoader\s*</.test(t) || /\buseLoader\s*\(/.test(t), E = /\bhandler\s*:/.test(t), V = d.join(r, i);
|
|
503
|
+
if (!c && f && (n = Q(n), u = !0), !c && E && a === V && (n = te(n), u = !0), h || y || b || j || x || L || P) {
|
|
504
|
+
const g = d.relative(r, a).replace(/\.(tsx?|jsx?)$/, "").replace(/\\/g, "/"), D = l.get(g);
|
|
505
|
+
n = W(n, g, D?.fullPath, D?.path), n = B(n, g), c || (n = M(
|
|
506
|
+
n,
|
|
507
|
+
g
|
|
508
|
+
)), !c && j && (n = Y(
|
|
509
|
+
n,
|
|
510
|
+
g
|
|
511
|
+
)), !c && x && (n = X(
|
|
512
|
+
n,
|
|
513
|
+
g
|
|
514
|
+
)), c || (n = q(n)), c || (n = K(n)), u = !0;
|
|
514
515
|
}
|
|
515
|
-
return
|
|
516
|
-
code:
|
|
516
|
+
return u ? {
|
|
517
|
+
code: n,
|
|
517
518
|
map: null
|
|
518
519
|
} : null;
|
|
519
520
|
}
|
|
520
521
|
};
|
|
521
522
|
}
|
|
522
|
-
function
|
|
523
|
+
function ne(p) {
|
|
523
524
|
return {
|
|
524
525
|
name: "velo:config",
|
|
525
|
-
config(
|
|
526
|
-
const i =
|
|
527
|
-
|
|
526
|
+
config(s, { mode: r }) {
|
|
527
|
+
const i = r === "server", l = r === "development", t = !!process.env.VELO_STATIC, a = s.server?.port ?? (Number(process.env.PORT) || p.port || 3e3), o = d.resolve(
|
|
528
|
+
process.cwd(),
|
|
529
|
+
s.root ?? "."
|
|
530
|
+
), c = s.envDir ? d.resolve(o, s.envDir) : o, n = R(r, c, ""), u = process.env.HOST?.trim() || n.HOST?.trim() || void 0, f = s.server?.host ?? u ?? p.hostname, h = f === !0 || f === "0.0.0.0" || f === "::", y = s.server?.allowedHosts ?? (h ? !0 : void 0);
|
|
531
|
+
let b = "client.js", j = "client.css";
|
|
528
532
|
if (i)
|
|
529
533
|
try {
|
|
530
|
-
const
|
|
531
|
-
|
|
534
|
+
const L = d.resolve(process.cwd(), "dist/client/.vite/manifest.json"), E = JSON.parse(S.readFileSync(L, "utf-8"))[O];
|
|
535
|
+
E && (b = E.file || b, E.css?.[0] && (j = E.css[0]));
|
|
532
536
|
} catch {
|
|
533
537
|
}
|
|
534
|
-
const
|
|
538
|
+
const x = {
|
|
535
539
|
define: {
|
|
536
540
|
"process.env.NODE_ENV": JSON.stringify(l ? "development" : "production"),
|
|
537
541
|
"process.env.STATIC_BASE_URL": JSON.stringify(process.env.STATIC_BASE_URL || (t ? "/client" : "")),
|
|
538
542
|
__VELO_STATIC__: JSON.stringify(t),
|
|
539
543
|
__VELO_BUILD_HASH__: JSON.stringify(process.env.VELO_BUILD_HASH || Date.now().toString(36)),
|
|
540
|
-
__VELO_CLIENT_JS__: JSON.stringify(
|
|
541
|
-
__VELO_CLIENT_CSS__: JSON.stringify(
|
|
544
|
+
__VELO_CLIENT_JS__: JSON.stringify(b),
|
|
545
|
+
__VELO_CLIENT_CSS__: JSON.stringify(j),
|
|
542
546
|
// Baked into the server bundle as startServer's port fallback.
|
|
543
547
|
// null when unset → startServer falls back to PORT env / 3000.
|
|
544
|
-
__VELO_CONFIG_PORT__: JSON.stringify(
|
|
548
|
+
__VELO_CONFIG_PORT__: JSON.stringify(p.port ?? null),
|
|
545
549
|
// Same for the bind interface: null → HOST env / Node default.
|
|
546
|
-
__VELO_CONFIG_HOSTNAME__: JSON.stringify(
|
|
550
|
+
__VELO_CONFIG_HOSTNAME__: JSON.stringify(p.hostname ?? null)
|
|
547
551
|
},
|
|
548
552
|
resolve: {
|
|
549
553
|
alias: {
|
|
@@ -552,11 +556,15 @@ function re(u) {
|
|
|
552
556
|
}
|
|
553
557
|
},
|
|
554
558
|
server: {
|
|
555
|
-
port: a
|
|
559
|
+
port: a,
|
|
560
|
+
// Host and allowedHosts only shape the dev server; in build
|
|
561
|
+
// they are inert, so we keep them out of the build config.
|
|
562
|
+
...l && f !== void 0 ? { host: f } : {},
|
|
563
|
+
...l && y !== void 0 ? { allowedHosts: y } : {}
|
|
556
564
|
}
|
|
557
565
|
};
|
|
558
|
-
return i ?
|
|
559
|
-
ssr:
|
|
566
|
+
return i ? x.build = {
|
|
567
|
+
ssr: T,
|
|
560
568
|
outDir: "dist",
|
|
561
569
|
emptyOutDir: !1,
|
|
562
570
|
copyPublicDir: !1,
|
|
@@ -565,107 +573,107 @@ function re(u) {
|
|
|
565
573
|
entryFileNames: "server.js"
|
|
566
574
|
}
|
|
567
575
|
}
|
|
568
|
-
} : l || (
|
|
576
|
+
} : l || (x.build = {
|
|
569
577
|
manifest: !0,
|
|
570
578
|
outDir: "dist/client",
|
|
571
579
|
rollupOptions: {
|
|
572
|
-
input:
|
|
580
|
+
input: O,
|
|
573
581
|
output: {
|
|
574
582
|
entryFileNames: "client.[hash].js",
|
|
575
|
-
assetFileNames: (
|
|
583
|
+
assetFileNames: (L) => L.names?.[0]?.endsWith(".css") ? "client.[hash].css" : "[name].[hash][extname]"
|
|
576
584
|
}
|
|
577
585
|
}
|
|
578
|
-
}),
|
|
586
|
+
}), x;
|
|
579
587
|
}
|
|
580
588
|
};
|
|
581
589
|
}
|
|
582
|
-
function
|
|
590
|
+
function ie() {
|
|
583
591
|
return {
|
|
584
592
|
name: "velo:static-url",
|
|
585
593
|
apply: "build",
|
|
586
594
|
enforce: "post",
|
|
587
|
-
generateBundle(
|
|
588
|
-
const
|
|
589
|
-
if (
|
|
590
|
-
for (const i of Object.values(
|
|
595
|
+
generateBundle(p, s) {
|
|
596
|
+
const r = process.env.STATIC_BASE_URL || "";
|
|
597
|
+
if (r)
|
|
598
|
+
for (const i of Object.values(s))
|
|
591
599
|
i.type === "asset" && typeof i.source == "string" && i.fileName.endsWith(".css") && (i.source = i.source.replace(
|
|
592
600
|
/url\(\s*(['"]?)\/(?!\/)/g,
|
|
593
|
-
`url($1${
|
|
601
|
+
`url($1${r}/`
|
|
594
602
|
));
|
|
595
603
|
}
|
|
596
604
|
};
|
|
597
605
|
}
|
|
598
|
-
function
|
|
599
|
-
let
|
|
606
|
+
function se(p, s) {
|
|
607
|
+
let r = "", i = "", l = !1, t = null;
|
|
600
608
|
function a() {
|
|
601
|
-
if (!
|
|
602
|
-
const
|
|
603
|
-
if (!
|
|
604
|
-
const c = U(
|
|
605
|
-
|
|
606
|
-
d.join(
|
|
609
|
+
if (!r) return;
|
|
610
|
+
const o = d.resolve(r, s);
|
|
611
|
+
if (!S.existsSync(o)) return;
|
|
612
|
+
const c = U(o), n = d.join(r, ".velojs");
|
|
613
|
+
S.mkdirSync(n, { recursive: !0 }), S.writeFileSync(
|
|
614
|
+
d.join(n, "graph.json"),
|
|
607
615
|
JSON.stringify(c)
|
|
608
616
|
);
|
|
609
617
|
}
|
|
610
618
|
return {
|
|
611
619
|
name: "velo:graph",
|
|
612
|
-
configResolved(
|
|
613
|
-
|
|
620
|
+
configResolved(o) {
|
|
621
|
+
r = o.root, i = o.mode;
|
|
614
622
|
},
|
|
615
623
|
writeBundle() {
|
|
616
624
|
i !== "server" && a();
|
|
617
625
|
},
|
|
618
|
-
configureServer(
|
|
626
|
+
configureServer(o) {
|
|
619
627
|
a(), l = !0;
|
|
620
|
-
const c = d.resolve(
|
|
621
|
-
|
|
622
|
-
l &&
|
|
628
|
+
const c = d.resolve(r, s);
|
|
629
|
+
o.watcher.on("all", (n, u) => {
|
|
630
|
+
l && u.startsWith(c) && (t && clearTimeout(t), t = setTimeout(() => a(), 500));
|
|
623
631
|
});
|
|
624
632
|
}
|
|
625
633
|
};
|
|
626
634
|
}
|
|
627
|
-
function
|
|
635
|
+
function oe(p) {
|
|
628
636
|
return [
|
|
629
637
|
...J.exclude,
|
|
630
638
|
/.*\.mjs$/,
|
|
631
|
-
...
|
|
639
|
+
...p.devServerExclude ?? []
|
|
632
640
|
];
|
|
633
641
|
}
|
|
634
|
-
function
|
|
635
|
-
const
|
|
642
|
+
function _e(p) {
|
|
643
|
+
const s = p ?? {}, r = s.appDirectory ?? "./app";
|
|
636
644
|
return [
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
entry:
|
|
644
|
-
exclude:
|
|
645
|
+
ne(s),
|
|
646
|
+
re(s, r),
|
|
647
|
+
ie(),
|
|
648
|
+
se(s, r),
|
|
649
|
+
$(),
|
|
650
|
+
H({
|
|
651
|
+
entry: T,
|
|
652
|
+
exclude: oe(s)
|
|
645
653
|
}),
|
|
646
|
-
|
|
654
|
+
ae()
|
|
647
655
|
];
|
|
648
656
|
}
|
|
649
|
-
function
|
|
657
|
+
function ae() {
|
|
650
658
|
return {
|
|
651
659
|
name: "velo:ws-bridge",
|
|
652
|
-
configureServer(
|
|
653
|
-
globalThis.__veloDevServer =
|
|
660
|
+
configureServer(p) {
|
|
661
|
+
globalThis.__veloDevServer = p.httpServer;
|
|
654
662
|
}
|
|
655
663
|
};
|
|
656
664
|
}
|
|
657
665
|
export {
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
666
|
+
w as buildFullPathMap,
|
|
667
|
+
k as collectFullPaths,
|
|
668
|
+
oe as devServerExcludeFor,
|
|
661
669
|
W as injectMetadata,
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
670
|
+
K as pruneClientOnlyImports,
|
|
671
|
+
te as removeEndpointRoutes,
|
|
672
|
+
q as removeLoaders,
|
|
673
|
+
Q as removeMiddlewares,
|
|
674
|
+
M as transformActionsForClient,
|
|
675
|
+
B as transformLoaderFunctions,
|
|
676
|
+
X as transformSocketsForClient,
|
|
677
|
+
Y as transformStreamsForClient,
|
|
678
|
+
_e as veloPlugin
|
|
671
679
|
};
|