vue-ssr-lite 0.1.13 → 0.2.2

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.
Files changed (42) hide show
  1. package/README.md +169 -159
  2. package/dist/SsrApplicationRuntime.d.ts.map +1 -1
  3. package/dist/SsrBrowserRuntime.d.ts +7 -6
  4. package/dist/SsrBrowserRuntime.d.ts.map +1 -1
  5. package/dist/SsrConfigCompileRuntime.d.ts +40 -0
  6. package/dist/SsrConfigCompileRuntime.d.ts.map +1 -0
  7. package/dist/SsrConfigRuntime.d.ts +4 -0
  8. package/dist/SsrConfigRuntime.d.ts.map +1 -0
  9. package/dist/SsrConfigTypes.d.ts +106 -0
  10. package/dist/SsrConfigTypes.d.ts.map +1 -0
  11. package/dist/SsrDomainRuntime.d.ts +38 -0
  12. package/dist/SsrDomainRuntime.d.ts.map +1 -0
  13. package/dist/SsrReactivityRuntime.d.ts +8 -1
  14. package/dist/SsrReactivityRuntime.d.ts.map +1 -1
  15. package/dist/SsrRenderRuntime.d.ts.map +1 -1
  16. package/dist/SsrRequestResolution.d.ts +3 -1
  17. package/dist/SsrRequestResolution.d.ts.map +1 -1
  18. package/dist/SsrRuntimeTypes.d.ts +6 -21
  19. package/dist/SsrRuntimeTypes.d.ts.map +1 -1
  20. package/dist/SsrTestFixtures.d.ts +8 -0
  21. package/dist/SsrTestFixtures.d.ts.map +1 -0
  22. package/dist/chunks/SsrApplicationRuntime-D4arUtsy.mjs +238 -0
  23. package/dist/chunks/SsrConfigRuntime-D0DkOrVQ.mjs +4 -0
  24. package/dist/chunks/SsrReactivityRuntime-CroM1WJG.mjs +28 -0
  25. package/dist/chunks/SsrServerRuntime-D7cDSFNm.mjs +1004 -0
  26. package/dist/cli.mjs +34 -34
  27. package/dist/client.d.ts +1 -0
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.mjs +79 -56
  30. package/dist/index.d.ts +4 -2
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.mjs +25 -19
  33. package/dist/server/SsrHostRuntime.d.ts +52 -2
  34. package/dist/server/SsrHostRuntime.d.ts.map +1 -1
  35. package/dist/server/SsrServerRuntime.d.ts.map +1 -1
  36. package/dist/server.d.ts +3 -0
  37. package/dist/server.d.ts.map +1 -1
  38. package/dist/server.mjs +73 -60
  39. package/package.json +1 -1
  40. package/dist/chunks/SsrApplicationRuntime-lMR_sMdk.mjs +0 -155
  41. package/dist/chunks/SsrReactivityRuntime-CUbPx7ew.mjs +0 -9
  42. package/dist/chunks/SsrServerRuntime-nBan8KxD.mjs +0 -731
@@ -0,0 +1,1004 @@
1
+ import { createServer as gt } from "node:http";
2
+ import { access as wt, stat as Y, readFile as lt } from "node:fs/promises";
3
+ import { resolve as j, sep as tt, extname as dt } from "node:path";
4
+ import { c as yt, h as vt, r as St } from "./SsrApplicationRuntime-D4arUtsy.mjs";
5
+ import { renderToString as bt } from "@vue/server-renderer";
6
+ import { c as xt } from "./SsrDiagnosticsRuntime-B5VbSgsA.mjs";
7
+ import { a as ut } from "./SsrSerialization-k-3aCFYt.mjs";
8
+ import { r as X, p as $t, i as Ct } from "./SsrHtmlRuntime-cTFsMSAZ.mjs";
9
+ const Z = (t) => String(Array.isArray(t) ? t[0] : t || "").split(",", 1)[0].trim(), Et = 1e6;
10
+ class C extends Error {
11
+ constructor(e) {
12
+ super(e), this.name = "SsrHostConfigurationError";
13
+ }
14
+ }
15
+ const V = (t) => {
16
+ const e = Z(t);
17
+ if (!e || e.length > 512 || /[\u0000-\u0020\u007f]/.test(e) || /[\\/@?#]/.test(e))
18
+ return "";
19
+ try {
20
+ const o = e.includes(":") && e.split(":").length > 2 && !e.startsWith("[") ? `[${e}]` : e, r = new URL(`http://${o}`);
21
+ if (r.username || r.password || r.pathname !== "/" || r.search || r.hash)
22
+ return "";
23
+ const n = r.hostname.toLowerCase().replace(/\.$/, "");
24
+ return n ? `${n.includes(":") && !n.startsWith("[") ? `[${n}]` : n}${r.port ? `:${r.port}` : ""}` : "";
25
+ } catch {
26
+ return "";
27
+ }
28
+ }, z = (t) => {
29
+ const e = V(t);
30
+ if (!e) return "";
31
+ if (e.startsWith("[")) {
32
+ const o = e.indexOf("]");
33
+ return o > 0 ? e.slice(1, o) : "";
34
+ }
35
+ return e.replace(/:\d+$/, "");
36
+ }, Q = (t) => {
37
+ const e = t.trim().toLowerCase();
38
+ if (e === "*") return "*";
39
+ if (e.startsWith("*.")) {
40
+ const o = z(e.slice(2));
41
+ return o && !o.includes(":") && !o.includes("*") ? `*.${o}` : "";
42
+ }
43
+ return V(e);
44
+ }, Rt = (t, e) => {
45
+ const o = z(t), r = Q(e);
46
+ return !o || !r ? !1 : r === "*" ? !0 : r.startsWith("*.") ? o.endsWith(`.${r.slice(2)}`) : V(t) === r || o === z(r);
47
+ }, Pt = (t, e) => {
48
+ const o = z(t), r = Q(e);
49
+ if (!o || !r || !Rt(t, r)) return null;
50
+ if (r === "*")
51
+ return { category: "catch-all", specificity: 0, pattern: r };
52
+ if (r.startsWith("*."))
53
+ return {
54
+ category: "wildcard",
55
+ specificity: r.slice(2).length,
56
+ pattern: r
57
+ };
58
+ const n = z(r);
59
+ return {
60
+ category: "exact",
61
+ specificity: Et + n.length,
62
+ pattern: r
63
+ };
64
+ }, At = (t) => {
65
+ const e = /* @__PURE__ */ new Map(), o = [];
66
+ for (const r of t) {
67
+ const n = r.hosts ?? [];
68
+ if (!n.length)
69
+ throw new C(
70
+ `SSR application "${r.id}" requires at least one host pattern.`
71
+ );
72
+ const c = /* @__PURE__ */ new Set();
73
+ for (const l of n) {
74
+ const h = String(l ?? "").trim();
75
+ if (!h)
76
+ throw new C(
77
+ `SSR application "${r.id}" contains an empty host pattern.`
78
+ );
79
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(h) || /[/?#]/.test(h))
80
+ throw new C(
81
+ `SSR application "${r.id}" host pattern "${l}" must not include a protocol, path, or query.`
82
+ );
83
+ const u = Q(h);
84
+ if (!u)
85
+ throw new C(
86
+ `SSR application "${r.id}" has an invalid host pattern "${l}". Use an exact hostname, *.example.com, or *.`
87
+ );
88
+ if (u !== "*" && (u.startsWith("[") ? /\]:\d+$/.test(u) : /:\d+$/.test(u)))
89
+ throw new C(
90
+ `SSR application "${r.id}" host pattern "${l}" must not include a port.`
91
+ );
92
+ if (c.has(u)) continue;
93
+ if (c.add(u), u === "*") {
94
+ o.push(r.id);
95
+ continue;
96
+ }
97
+ const m = e.get(u);
98
+ if (m && m !== r.id)
99
+ throw new C(
100
+ `Host pattern "${u}" is assigned to both "${m}" and "${r.id}".`
101
+ );
102
+ e.set(u, r.id);
103
+ }
104
+ }
105
+ if (o.length > 1)
106
+ throw new C(
107
+ `Multiple catch-all ("*") host applications are not allowed (applications: ${o.join(", ")}).`
108
+ );
109
+ }, It = (t, e, o) => {
110
+ const r = z(e);
111
+ if (!r) return null;
112
+ let n = null;
113
+ for (const l of t)
114
+ for (const h of l.hosts ?? []) {
115
+ const u = Pt(e, h);
116
+ if (!u) continue;
117
+ const a = {
118
+ entry: l,
119
+ matchedPattern: u.pattern,
120
+ normalizedHostname: r,
121
+ category: u.category,
122
+ specificity: u.specificity
123
+ };
124
+ if (!n || a.specificity > n.specificity) {
125
+ n = a;
126
+ continue;
127
+ }
128
+ a.specificity < n.specificity || a.entry.id < n.entry.id && (n = a);
129
+ }
130
+ if (n) return n;
131
+ if (!o) return null;
132
+ const c = t.find(
133
+ (l) => l.id === o
134
+ );
135
+ return c ? {
136
+ entry: c,
137
+ matchedPattern: null,
138
+ normalizedHostname: r,
139
+ category: "default",
140
+ specificity: -1
141
+ } : null;
142
+ }, Ht = (t, e, o = !1) => V(o && Z(t) || e), Mt = (t, e, o = !1) => {
143
+ if (!o) return e;
144
+ const r = Z(t).toLowerCase();
145
+ return r === "http" || r === "https" ? r : e;
146
+ }, et = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/, Dt = (t, e = [], o = []) => {
147
+ const r = new Set(e.filter((l) => et.test(l))), n = new Set(o.filter((l) => et.test(l)));
148
+ if (!t || r.size === 0) return;
149
+ const c = String(t).split(";").map((l) => l.trim()).filter(Boolean).filter((l) => {
150
+ const h = l.indexOf("=");
151
+ if (h <= 0) return !1;
152
+ const u = l.slice(0, h).trim();
153
+ return r.has(u) && !n.has(u);
154
+ });
155
+ return c.length ? c.join("; ") : void 0;
156
+ }, Tt = ["localhost", "127.0.0.1", "0.0.0.0", "::1"], rt = [
157
+ "ssr.config.ts",
158
+ "ssr.config.mts",
159
+ "ssr.config.js",
160
+ "ssr.config.mjs"
161
+ ], W = (t, e) => {
162
+ const o = z(V(t) || t);
163
+ if (!o || o.includes("/") || o.includes("?"))
164
+ throw new C(
165
+ `${e} must be a valid hostname without a protocol, path, or port.`
166
+ );
167
+ return o.replace(/^\[|\]$/g, "");
168
+ }, T = (t, e) => {
169
+ t.includes(e) || t.push(e);
170
+ }, kt = (t, e) => {
171
+ const o = t.mode ?? "root-and-subdomains", r = W(
172
+ e ? t.development : t.production,
173
+ e ? "domain.development" : "domain.production"
174
+ ), n = [];
175
+ if ((o === "root" || o === "root-and-subdomains") && T(n, r), (o === "subdomains" || o === "root-and-subdomains") && T(n, `*.${r}`), e) {
176
+ const c = W(
177
+ t.production,
178
+ "domain.production"
179
+ );
180
+ if (c !== r && ((o === "root" || o === "root-and-subdomains") && T(n, c), (o === "subdomains" || o === "root-and-subdomains") && T(n, `*.${c}`)), t.localAliases)
181
+ for (const l of Tt) T(n, l);
182
+ }
183
+ for (const c of t.additionalHosts ?? [])
184
+ T(n, W(c, "domain.additionalHosts"));
185
+ if (t.customDomains && T(n, "*"), !n.length)
186
+ throw new C(
187
+ "Application domain configuration produced an empty host list."
188
+ );
189
+ return n;
190
+ }, ot = (t) => t == null ? [] : Array.isArray(t) ? t.map((e) => String(e).trim()).filter(Boolean) : String(t).split(",").map((e) => e.trim()).filter(Boolean), jt = async (t, e, o) => {
191
+ if (!t) return;
192
+ const r = typeof t == "function" ? await t() : t;
193
+ if (!r?.id || !r.rootComponent)
194
+ throw new C(
195
+ `Application "${e}" ${o} loader must return a valid SsrApplicationDefinition.`
196
+ );
197
+ return r;
198
+ }, se = async (t, e) => {
199
+ if (e) return j(t, e);
200
+ for (const o of rt) {
201
+ const r = j(t, o);
202
+ try {
203
+ return await wt(r), r;
204
+ } catch {
205
+ }
206
+ }
207
+ throw new Error(
208
+ `vue-ssr-lite could not find an SSR config in ${t}. Expected one of: ${rt.join(", ")}`
209
+ );
210
+ }, zt = async (t, e = {}) => {
211
+ const r = t?.default ?? t, n = typeof r == "function" ? await r() : r;
212
+ if (!n?.name || !n.applications || typeof n.applications != "object")
213
+ throw new Error(
214
+ "The SSR config module must export defineSsrConfig({ name, applications })."
215
+ );
216
+ const c = e.development ?? (typeof process < "u" ? process.env.NODE_ENV !== "production" : !0), l = Object.keys(n.applications);
217
+ if (!l.length)
218
+ throw new Error("SSR config requires at least one application.");
219
+ const h = [];
220
+ for (const u of l) {
221
+ const a = n.applications[u];
222
+ if (!a?.template || !a.domain)
223
+ throw new C(
224
+ `Application "${u}" requires template and domain configuration.`
225
+ );
226
+ const m = a.spa !== void 0, v = a.ssr !== void 0;
227
+ if (!m && !v)
228
+ throw new C(
229
+ `Application "${u}" requires spa or ssr.`
230
+ );
231
+ if (m && v)
232
+ throw new C(
233
+ `Application "${u}" cannot declare both spa and ssr.`
234
+ );
235
+ const s = v ? "ssr" : "spa", i = a.ssr || (a.spa && a.spa !== !0 ? a.spa : void 0), y = await jt(i, u, s), d = {
236
+ ...a.publicConfig || {}
237
+ };
238
+ a.graphql && (d.graphql = {
239
+ endpoint: a.graphql.endpoint,
240
+ timeout: a.graphql.timeout ?? 8e3
241
+ }), h.push({
242
+ id: u,
243
+ kind: s,
244
+ template: a.template,
245
+ hosts: kt(a.domain, c),
246
+ roles: a.roles ? [...a.roles] : void 0,
247
+ application: y,
248
+ mountSelector: a.mountSelector,
249
+ cacheControl: a.cacheControl,
250
+ responseCache: a.responseCache,
251
+ endpoints: a.endpoints ? [...a.endpoints] : [],
252
+ cookieAllowlist: ot(a.cookies?.allow),
253
+ cookieDenylist: ot(a.cookies?.deny),
254
+ publicConfig: d,
255
+ domain: {
256
+ development: W(
257
+ a.domain.development,
258
+ `${u}.domain.development`
259
+ ),
260
+ production: W(
261
+ a.domain.production,
262
+ `${u}.domain.production`
263
+ ),
264
+ mode: a.domain.mode ?? "root-and-subdomains",
265
+ localAliases: !!a.domain.localAliases,
266
+ customDomains: !!a.domain.customDomains,
267
+ expose: a.domain.expose
268
+ }
269
+ });
270
+ }
271
+ if (At(h), n.defaultApplicationId && !h.some((u) => u.id === n.defaultApplicationId))
272
+ throw new Error(
273
+ `defaultApplicationId "${n.defaultApplicationId}" does not match an application.`
274
+ );
275
+ return {
276
+ name: n.name,
277
+ applications: h,
278
+ defaultApplicationId: n.defaultApplicationId,
279
+ development: c,
280
+ readiness: n.readiness,
281
+ server: {
282
+ root: n.server?.root,
283
+ host: n.server?.host,
284
+ port: n.server?.port,
285
+ role: n.runtime,
286
+ trustProxy: n.server?.trustProxy,
287
+ clientOutDir: n.server?.clientOutDir,
288
+ requestTimeoutMs: n.server?.requestTimeoutMs,
289
+ shutdownTimeoutMs: n.server?.shutdownTimeoutMs,
290
+ healthPath: n.server?.healthPath,
291
+ readinessPath: n.server?.readinessPath,
292
+ maxResolutionPasses: n.server?.maxResolutionPasses,
293
+ resolutionDeadlineMs: n.server?.resolutionDeadlineMs,
294
+ diagnostics: n.server?.diagnostics,
295
+ logger: n.server?.logger,
296
+ publicConfig: {}
297
+ }
298
+ };
299
+ }, _ = () => globalThis.performance?.now?.() ?? Date.now(), st = (t) => new TextEncoder().encode(t).byteLength, nt = (t, e, o, r) => {
300
+ for (const n of r) {
301
+ const c = { requestId: e, applicationId: o, code: n.code };
302
+ t?.warn ? t.warn(`ssr.diagnostic.${n.code}`, c) : console.warn(`[vue-ssr-lite] ${n.message}`, c);
303
+ }
304
+ }, Nt = async (t, e, o = {}) => {
305
+ const r = _(), n = Math.max(1, Math.floor(o.maxResolutionPasses ?? 4)), c = o.resolutionDeadlineMs ?? 0, l = o.diagnostics ?? process.env.NODE_ENV !== "production", h = vt(!0);
306
+ let u = r, a = r, m = r, v, s, i = "", y = "", d = 0, x;
307
+ const N = async () => {
308
+ if (!s) return;
309
+ const S = s;
310
+ s = void 0;
311
+ try {
312
+ await t.cleanup?.(S.context);
313
+ } catch (p) {
314
+ console.error("[vue-ssr-lite] application cleanup failed", p);
315
+ }
316
+ try {
317
+ S.hydration.dispose();
318
+ } catch (p) {
319
+ console.error("[vue-ssr-lite] hydration cleanup failed", p);
320
+ }
321
+ };
322
+ try {
323
+ let S = !1;
324
+ for (let b = 0; b < n && !S; b += 1) {
325
+ if (d = b + 1, h.beginPass(b), s = await yt(t, {
326
+ server: !0,
327
+ request: e,
328
+ resumeState: b === 0 ? void 0 : v,
329
+ resolution: h
330
+ }), b === 0 && (u = _()), s.router) {
331
+ const O = new URL(e.url);
332
+ await s.router.push(`${O.pathname}${O.search}${O.hash}`), await s.router.isReady(), s.router.currentRoute.value.matched.length === 0 && (s.context.response.statusCode = 404);
333
+ }
334
+ b === 0 && (a = _());
335
+ const H = {};
336
+ i = await bt(s.app, H), y = H.teleports?.body ?? "", m = _();
337
+ const A = h.pendingWork(), g = h.additionalPassRequested(), U = b === n - 1;
338
+ if (A.length === 0 && !g || U) {
339
+ S = !0, U && (A.length > 0 || g) && nt(o.logger, e.requestId, t.id, [
340
+ {
341
+ code: "resolution-pass-limit",
342
+ message: `Resolution did not settle within ${n} render passes; serializing the last render.`
343
+ }
344
+ ]);
345
+ break;
346
+ }
347
+ await h.drain(c, e.signal), v = s.hydration.collect(), await N();
348
+ }
349
+ if (!s) throw new Error("SSR render produced no application instance.");
350
+ const p = await t.resolveHead?.(s.context) ?? s.context.head.value;
351
+ l && nt(
352
+ o.logger,
353
+ e.requestId,
354
+ t.id,
355
+ xt({
356
+ html: i,
357
+ route: s.router?.currentRoute.value ?? null,
358
+ requestUrl: e.url,
359
+ applicationId: t.id
360
+ })
361
+ );
362
+ const f = {
363
+ version: 1,
364
+ applicationId: t.id,
365
+ publicConfig: e.publicConfig,
366
+ domain: e.domain,
367
+ application: s.context.state,
368
+ plugins: s.hydration.collect()
369
+ }, P = st(ut(f)), D = _();
370
+ return {
371
+ html: i,
372
+ teleports: y,
373
+ head: p,
374
+ response: s.context.response,
375
+ hydrationState: f,
376
+ metrics: {
377
+ requestId: e.requestId,
378
+ applicationId: t.id,
379
+ contextDurationMs: u - r,
380
+ routeDurationMs: a - u,
381
+ renderDurationMs: m - a,
382
+ totalDurationMs: D - r,
383
+ htmlBytes: st(i),
384
+ stateBytes: P,
385
+ renderPasses: d
386
+ }
387
+ };
388
+ } catch (S) {
389
+ throw x = S, S;
390
+ } finally {
391
+ let S;
392
+ if (s) {
393
+ try {
394
+ await t.cleanup?.(s.context);
395
+ } catch (p) {
396
+ S = p, console.error("[vue-ssr-lite] application cleanup failed", p);
397
+ }
398
+ try {
399
+ s.hydration.dispose();
400
+ } catch (p) {
401
+ console.error("[vue-ssr-lite] hydration cleanup failed", p), S || (S = p);
402
+ }
403
+ }
404
+ if (h.dispose(), !x && S) throw S;
405
+ }
406
+ }, Ot = {
407
+ ".css": "text/css; charset=utf-8",
408
+ ".gif": "image/gif",
409
+ ".html": "text/html; charset=utf-8",
410
+ ".ico": "image/x-icon",
411
+ ".jpeg": "image/jpeg",
412
+ ".jpg": "image/jpeg",
413
+ ".js": "text/javascript; charset=utf-8",
414
+ ".json": "application/json; charset=utf-8",
415
+ ".map": "application/json; charset=utf-8",
416
+ ".png": "image/png",
417
+ ".svg": "image/svg+xml",
418
+ ".txt": "text/plain; charset=utf-8",
419
+ ".webp": "image/webp",
420
+ ".woff": "font/woff",
421
+ ".woff2": "font/woff2",
422
+ ".xml": "application/xml; charset=utf-8"
423
+ }, Lt = async (t, e, o) => {
424
+ try {
425
+ const r = decodeURIComponent(e).replace(/^\/+/, "");
426
+ if (!r || o.includes(r)) return null;
427
+ const n = j(t, r), c = t.endsWith(tt) ? t : `${t}${tt}`;
428
+ return !n.startsWith(c) || !(await Y(n)).isFile() ? null : {
429
+ statusCode: 200,
430
+ body: await lt(n),
431
+ headers: {
432
+ "content-type": Ot[dt(n)] || "application/octet-stream",
433
+ "cache-control": e.startsWith("/assets/") ? "public, max-age=31536000, immutable" : "public, max-age=3600"
434
+ }
435
+ };
436
+ } catch {
437
+ return null;
438
+ }
439
+ }, Ft = (t) => typeof t == "string" ? new TextEncoder().encode(t).byteLength : t?.byteLength ?? 0, at = (t) => ({
440
+ statusCode: t.statusCode,
441
+ body: t.body instanceof Uint8Array ? t.body.slice() : t.body,
442
+ headers: t.headers ? { ...t.headers } : void 0
443
+ }), ne = (t = {}) => {
444
+ const e = Number(t.maxEntries ?? 500), o = Number(t.maxBytes ?? 32 * 1024 * 1024), r = Number.isFinite(e) ? Math.max(1, Math.floor(e)) : 500, n = Number.isFinite(o) ? Math.max(1, Math.floor(o)) : 32 * 1024 * 1024, c = /* @__PURE__ */ new Map();
445
+ let l = 0;
446
+ const h = (a) => {
447
+ const m = c.get(a);
448
+ return m ? (c.delete(a), l -= m.size, !0) : !1;
449
+ }, u = () => {
450
+ const a = Date.now();
451
+ for (const [m, v] of c)
452
+ v.expiresAt <= a && h(m);
453
+ for (; c.size > r || l > n; ) {
454
+ const m = c.keys().next().value;
455
+ if (!m) break;
456
+ h(m);
457
+ }
458
+ };
459
+ return {
460
+ get(a) {
461
+ const m = c.get(a);
462
+ return m ? m.expiresAt <= Date.now() ? (h(a), null) : (c.delete(a), c.set(a, m), at(m.response)) : null;
463
+ },
464
+ set(a, m, v) {
465
+ const s = Number(v.ttlMs);
466
+ if (!Number.isFinite(s) || s <= 0) return;
467
+ h(a);
468
+ const i = at(m), y = Ft(i.body);
469
+ y > n || (c.set(a, {
470
+ response: i,
471
+ expiresAt: Date.now() + s,
472
+ size: y,
473
+ tags: new Set(v.tags ?? [])
474
+ }), l += y, u());
475
+ },
476
+ invalidate(a = {}) {
477
+ const m = new Set(a.keys ?? []), v = new Set(a.tags ?? []);
478
+ let s = 0;
479
+ for (const [i, y] of c)
480
+ (!m.size && !v.size || m.has(i) || [...v].some((x) => y.tags.has(x))) && h(i) && (s += 1);
481
+ return s;
482
+ }
483
+ };
484
+ }, Ut = async (t, e, o) => {
485
+ if (!o || e.method !== "GET" || e.cookie || !Number.isFinite(o.ttlMs) || o.ttlMs <= 0)
486
+ return null;
487
+ const r = o.vary ? await o.vary(e) : "";
488
+ return r == null ? null : JSON.stringify([
489
+ "vue-ssr-lite:v1",
490
+ t,
491
+ e.host,
492
+ e.pathname,
493
+ e.search,
494
+ r
495
+ ]);
496
+ }, Bt = (t, e, o) => {
497
+ const r = Object.entries(t.headers ?? {}), n = String(
498
+ r.find(([l]) => l.toLowerCase() === "cache-control")?.[1] || ""
499
+ ).toLowerCase();
500
+ return t.statusCode === 200 && typeof t.body == "string" && !r.some(([l]) => l.toLowerCase() === "set-cookie") && !n.includes("private") && !n.includes("no-store") && (o.shouldCache?.(t, e) ?? !0);
501
+ };
502
+ class pt extends Error {
503
+ constructor() {
504
+ super("SSR request timed out."), this.name = "SsrRequestTimeoutError";
505
+ }
506
+ }
507
+ const _t = (t) => {
508
+ const e = t ?? 4173;
509
+ if (!Number.isInteger(e) || e < 0 || e > 65535)
510
+ throw new Error("SSR server port must be an integer between 0 and 65535.");
511
+ return e;
512
+ }, Wt = (t) => t === "0.0.0.0" || t === "::" || t === "::1" ? "localhost" : t, Vt = (t, e, o) => {
513
+ const r = `http://${Wt(t)}:${e}/`;
514
+ console.log(
515
+ [
516
+ "",
517
+ "✓ Server Ready",
518
+ "",
519
+ ` ➜ Local: ${r}`,
520
+ ` ➜ Role: ${o}`,
521
+ ""
522
+ ].join(`
523
+ `)
524
+ );
525
+ }, it = async (t) => {
526
+ const e = await zt(t, {
527
+ development: process.env.NODE_ENV !== "production"
528
+ });
529
+ for (const o of e.applications) {
530
+ const r = !o.roles?.length || !e.server.role || o.roles.includes(e.server.role);
531
+ if (o.kind === "ssr" && r && !o.application)
532
+ throw new Error(
533
+ `SSR application "${o.id}" requires an ssr application definition.`
534
+ );
535
+ }
536
+ return e;
537
+ }, Gt = (t, e, o, r) => {
538
+ const c = `<script type="application/json" id="vue-ssr-lite-domain">${ut({
539
+ version: 1,
540
+ applicationId: e,
541
+ domain: o,
542
+ publicConfig: r
543
+ })}<\/script>`;
544
+ return t.includes("</body>") ? t.replace(/<\/body>/i, ` ${c}
545
+ </body>`) : `${t}
546
+ ${c}`;
547
+ }, L = {
548
+ "referrer-policy": "strict-origin-when-cross-origin",
549
+ "x-content-type-options": "nosniff",
550
+ "x-frame-options": "SAMEORIGIN"
551
+ }, F = (t, e) => {
552
+ if (t.method !== "GET" && t.method !== "HEAD") return !1;
553
+ if (t.headers["sec-fetch-mode"] === "navigate") return !0;
554
+ const o = String(t.headers.accept || "");
555
+ return o.includes("text/html") ? !0 : (!o || o === "*/*") && !dt(e);
556
+ }, Jt = (t, e, o = "") => e.end(t.method === "HEAD" ? "" : o), R = (t, e, o) => {
557
+ e.writeHead(o.statusCode, o.headers ?? {}), Jt(t, e, o.body ?? "");
558
+ }, k = (t, e, o, r) => R(t, e, {
559
+ statusCode: o,
560
+ body: JSON.stringify(r),
561
+ headers: {
562
+ "content-type": "application/json; charset=utf-8",
563
+ "cache-control": "no-store"
564
+ }
565
+ }), ct = async (t, e, o) => {
566
+ if (!Number.isFinite(e) || e <= 0) return t;
567
+ let r;
568
+ const n = new Promise((c, l) => {
569
+ r = setTimeout(() => {
570
+ o.abort(), l(new pt());
571
+ }, e);
572
+ });
573
+ try {
574
+ return await Promise.race([t, n]);
575
+ } finally {
576
+ r && clearTimeout(r);
577
+ }
578
+ }, Kt = (t) => t.headers, Xt = (t, e, o) => new Promise((r, n) => {
579
+ t.middlewares(e, o, (c) => {
580
+ c ? n(c) : r();
581
+ });
582
+ }), ae = async (t) => {
583
+ let e = !1;
584
+ const o = await it(await t.loadRuntime()), r = o.server, n = r.host || "0.0.0.0", c = _t(r.port), l = j(
585
+ r.root || t.root,
586
+ r.clientOutDir || "dist/client"
587
+ ), h = async () => t.production ? o : it(await t.loadRuntime()), u = async (s, i, y) => {
588
+ const d = s.server.root || t.root, x = await lt(
589
+ j(t.production ? l : d, i),
590
+ "utf8"
591
+ );
592
+ if (t.production || !t.vite) return x;
593
+ const N = `/${i.replaceAll("\\", "/").replace(/^\/+/, "")}`;
594
+ return t.vite.transformIndexHtml(N, x, y);
595
+ }, a = async (s) => {
596
+ const i = s.server.root || t.root, y = s.applications.filter(
597
+ (d) => !d.roles?.length || !s.server.role || d.roles.includes(s.server.role)
598
+ );
599
+ await Promise.all(
600
+ y.map(async (d) => {
601
+ if (!(await Y(
602
+ j(
603
+ t.production ? l : i,
604
+ d.template
605
+ )
606
+ )).isFile())
607
+ throw new Error(`SSR client entry is missing: ${d.template}`);
608
+ })
609
+ ), await Promise.all((s.readiness ?? []).map((d) => d.run()));
610
+ }, m = o.applications.filter(
611
+ (s) => !s.roles?.length || !o.server.role || s.roles.includes(o.server.role)
612
+ );
613
+ await Promise.all(
614
+ m.map(async (s) => {
615
+ const i = o.server.root || t.root;
616
+ if (!(await Y(
617
+ j(
618
+ t.production ? l : i,
619
+ s.template
620
+ )
621
+ )).isFile())
622
+ throw new Error(`Missing client entry: ${s.template}`);
623
+ })
624
+ );
625
+ const v = gt(async (s, i) => {
626
+ const y = Date.now();
627
+ let d = "/", x = "unknown", N;
628
+ const S = new AbortController();
629
+ s.once("aborted", () => S.abort()), i.once("close", () => {
630
+ i.writableEnded || S.abort();
631
+ });
632
+ try {
633
+ const p = await h(), f = p.server, P = new URL(s.url || "/", "http://internal");
634
+ d = P.pathname;
635
+ const D = f.healthPath || "/healthz", b = f.readinessPath || "/readyz";
636
+ if (d === D)
637
+ return k(s, i, 200, {
638
+ status: "ok",
639
+ service: p.name,
640
+ role: f.role || "default",
641
+ timestamp: new Date(y).toISOString()
642
+ });
643
+ if (d === b) {
644
+ if (e)
645
+ return k(s, i, 503, {
646
+ status: "error",
647
+ service: p.name,
648
+ message: "Server is shutting down."
649
+ });
650
+ try {
651
+ return await a(p), k(s, i, 200, {
652
+ status: "ok",
653
+ service: p.name,
654
+ role: f.role || "default"
655
+ });
656
+ } catch {
657
+ return k(s, i, 503, {
658
+ status: "error",
659
+ service: p.name,
660
+ message: "A required dependency is unavailable."
661
+ });
662
+ }
663
+ }
664
+ const H = Ht(
665
+ s.headers["x-forwarded-host"],
666
+ s.headers.host,
667
+ f.trustProxy
668
+ );
669
+ if (!H)
670
+ return R(s, i, {
671
+ statusCode: 400,
672
+ body: F(s, d) ? X("Invalid request", "The Host header is invalid.") : JSON.stringify({ status: "error", message: "Invalid Host header." }),
673
+ headers: {
674
+ "content-type": F(s, d) ? "text/html; charset=utf-8" : "application/json; charset=utf-8",
675
+ "cache-control": "no-store",
676
+ ...L
677
+ }
678
+ });
679
+ const A = It(
680
+ p.applications,
681
+ H,
682
+ p.defaultApplicationId
683
+ );
684
+ if (!A)
685
+ return k(s, i, 421, {
686
+ status: "error",
687
+ service: p.name,
688
+ message: "No application serves this host."
689
+ });
690
+ const g = A.entry;
691
+ if (x = g.id, f.logger?.debug?.("ssr.host_resolved", {
692
+ entryId: g.id,
693
+ category: A.category,
694
+ specificity: A.specificity,
695
+ matchedPattern: A.matchedPattern,
696
+ hostname: A.normalizedHostname,
697
+ role: f.role || "default"
698
+ }), g.roles?.length && f.role && !g.roles.includes(f.role)) {
699
+ const w = `Runtime role does not serve application "${g.id}".`;
700
+ return R(s, i, {
701
+ statusCode: 421,
702
+ body: F(s, d) ? X("Misdirected request", w) : JSON.stringify({ status: "error", message: w }),
703
+ headers: {
704
+ "content-type": F(s, d) ? "text/html; charset=utf-8" : "application/json; charset=utf-8",
705
+ "cache-control": "no-store",
706
+ ...L
707
+ }
708
+ });
709
+ }
710
+ const U = Mt(
711
+ s.headers["x-forwarded-proto"],
712
+ s.socket.encrypted ? "https" : "http",
713
+ f.trustProxy
714
+ ), O = St(
715
+ H,
716
+ g,
717
+ p.development
718
+ ), ft = Dt(
719
+ s.headers.cookie,
720
+ g.cookieAllowlist,
721
+ g.cookieDenylist
722
+ ), E = {
723
+ requestId: String(s.headers["x-request-id"] || "").trim() || `${y.toString(36)}-${Math.random().toString(36).slice(2, 10)}`,
724
+ url: new URL(
725
+ `${P.pathname}${P.search}`,
726
+ `${U}://${H}`
727
+ ).href,
728
+ host: H,
729
+ protocol: U,
730
+ method: s.method || "GET",
731
+ headers: Kt(s),
732
+ cookie: ft,
733
+ publicConfig: g.publicConfig,
734
+ domain: O,
735
+ signal: S.signal,
736
+ pathname: d,
737
+ search: P.search,
738
+ entryId: g.id
739
+ };
740
+ N = E;
741
+ const ht = {
742
+ signal: S.signal,
743
+ logger: f.logger
744
+ };
745
+ for (const w of g.endpoints) {
746
+ if (!w.match(E)) continue;
747
+ const I = await ct(
748
+ Promise.resolve(w.handle(E, ht)),
749
+ f.requestTimeoutMs ?? 15e3,
750
+ S
751
+ );
752
+ if (I) return R(s, i, I);
753
+ }
754
+ if (t.production) {
755
+ const w = await Lt(
756
+ l,
757
+ d,
758
+ p.applications.map(({ template: I }) => I)
759
+ );
760
+ if (w) return R(s, i, w);
761
+ } else if (t.vite && (d.startsWith("/src/") || d.startsWith("/@") || d.includes(".") || d === "/__vite_ping") && (await Xt(t.vite, s, i), i.writableEnded))
762
+ return;
763
+ if (!F(s, d))
764
+ return k(s, i, 404, {
765
+ status: "error",
766
+ service: p.name,
767
+ message: "Resource not found."
768
+ });
769
+ const M = g.kind === "ssr" ? g.responseCache : void 0;
770
+ let B = null;
771
+ try {
772
+ B = await Ut(
773
+ g.id,
774
+ E,
775
+ M
776
+ );
777
+ } catch (w) {
778
+ f.logger?.warn?.("ssr.cache.key.failed", {
779
+ entryId: g.id,
780
+ requestId: E.requestId,
781
+ error: w instanceof Error ? w.message : "Unknown cache error"
782
+ });
783
+ }
784
+ if (M && B)
785
+ try {
786
+ const w = await M.store.get(B);
787
+ if (w)
788
+ return R(s, i, {
789
+ ...w,
790
+ headers: {
791
+ ...w.headers,
792
+ "server-timing": 'cache;desc="hit"'
793
+ }
794
+ });
795
+ } catch (w) {
796
+ f.logger?.warn?.("ssr.cache.read.failed", {
797
+ entryId: g.id,
798
+ requestId: E.requestId,
799
+ error: w instanceof Error ? w.message : "Unknown cache error"
800
+ });
801
+ }
802
+ let G = await u(p, g.template, s.url || "/");
803
+ if (g.kind === "spa")
804
+ return R(s, i, {
805
+ statusCode: 200,
806
+ body: Gt(
807
+ G,
808
+ g.id,
809
+ O,
810
+ g.publicConfig
811
+ ),
812
+ headers: {
813
+ "content-type": "text/html; charset=utf-8",
814
+ "cache-control": g.cacheControl || "private, no-store",
815
+ vary: "Host, X-Forwarded-Host",
816
+ ...L
817
+ }
818
+ });
819
+ const J = g.application;
820
+ G = $t(
821
+ G,
822
+ g.mountSelector || J.mountSelector || "#app"
823
+ );
824
+ const q = f.requestTimeoutMs ?? 15e3, $ = await ct(
825
+ Nt(J, E, {
826
+ maxResolutionPasses: f.maxResolutionPasses,
827
+ resolutionDeadlineMs: f.resolutionDeadlineMs ?? q,
828
+ diagnostics: f.diagnostics ?? !t.production,
829
+ logger: f.logger
830
+ }),
831
+ q,
832
+ S
833
+ );
834
+ if ($.response.redirect) {
835
+ const w = $.response.redirect, I = new URL(w.location, E.url);
836
+ if (I.protocol !== "http:" && I.protocol !== "https:")
837
+ throw new Error("SSR redirects must use HTTP or HTTPS.");
838
+ if (!w.allowExternal && I.origin !== new URL(E.url).origin)
839
+ throw new Error("Cross-origin redirect requires allowExternal: true.");
840
+ return R(s, i, {
841
+ statusCode: w.statusCode ?? 302,
842
+ headers: {
843
+ location: I.href,
844
+ "cache-control": "no-store"
845
+ }
846
+ });
847
+ }
848
+ const mt = Ct(G, {
849
+ applicationId: J.id,
850
+ html: $.html,
851
+ teleports: $.teleports,
852
+ head: $.head,
853
+ state: $.hydrationState
854
+ });
855
+ f.onMetrics?.($.metrics), f.logger?.info?.("ssr.render.complete", $.metrics);
856
+ const K = {
857
+ statusCode: $.response.statusCode,
858
+ body: mt,
859
+ headers: {
860
+ "content-type": "text/html; charset=utf-8",
861
+ "cache-control": g.cacheControl || "private, no-store",
862
+ vary: "Host, X-Forwarded-Host",
863
+ "server-timing": [
864
+ `context;dur=${$.metrics.contextDurationMs.toFixed(1)}`,
865
+ `route;dur=${$.metrics.routeDurationMs.toFixed(1)}`,
866
+ `render;dur=${$.metrics.renderDurationMs.toFixed(1)}`
867
+ ].join(", "),
868
+ ...$.response.headers,
869
+ ...L
870
+ }
871
+ };
872
+ if (M && B && Bt(K, E, M))
873
+ try {
874
+ await M.store.set(B, K, {
875
+ ttlMs: M.ttlMs,
876
+ tags: await M.tags?.(E)
877
+ });
878
+ } catch (w) {
879
+ f.logger?.warn?.("ssr.cache.write.failed", {
880
+ entryId: g.id,
881
+ requestId: E.requestId,
882
+ error: w instanceof Error ? w.message : "Unknown cache error"
883
+ });
884
+ }
885
+ return R(s, i, K);
886
+ } catch (p) {
887
+ t.vite?.ssrFixStacktrace(p);
888
+ const f = await h().catch(() => o);
889
+ if (f.server.logger?.error?.("ssr.request.failed", {
890
+ entryId: x,
891
+ pathname: d,
892
+ error: p instanceof Error ? p.message : "Unknown error"
893
+ }), i.writableEnded) return;
894
+ if (i.headersSent) return i.destroy();
895
+ const P = p instanceof pt, D = P ? 504 : 500;
896
+ if (f.server.renderError)
897
+ try {
898
+ const b = await f.server.renderError({
899
+ error: p,
900
+ kind: P ? "timeout" : "internal",
901
+ production: t.production,
902
+ request: N,
903
+ entryId: x === "unknown" ? void 0 : x
904
+ });
905
+ if (b)
906
+ return R(s, i, {
907
+ ...b,
908
+ statusCode: b.statusCode >= 400 ? b.statusCode : D,
909
+ headers: {
910
+ ...b.headers,
911
+ "cache-control": "no-store",
912
+ ...L
913
+ }
914
+ });
915
+ } catch (b) {
916
+ f.server.logger?.error?.("ssr.error-renderer.failed", {
917
+ entryId: x,
918
+ error: b instanceof Error ? b.message : "Unknown error renderer failure"
919
+ });
920
+ }
921
+ return F(s, d) ? R(s, i, {
922
+ statusCode: D,
923
+ body: X(
924
+ P ? "Request timed out" : "Application unavailable",
925
+ t.production ? "The application could not render this page. Please try again." : p instanceof Error ? p.message : "Unknown rendering failure."
926
+ ),
927
+ headers: {
928
+ "content-type": "text/html; charset=utf-8",
929
+ "cache-control": "no-store",
930
+ ...L
931
+ }
932
+ }) : k(s, i, D, {
933
+ status: "error",
934
+ service: f.name
935
+ });
936
+ }
937
+ });
938
+ return {
939
+ nodeServer: v,
940
+ address: () => {
941
+ const s = v.address();
942
+ return {
943
+ host: typeof s == "object" && s ? s.address : n,
944
+ port: typeof s == "object" && s ? s.port : c
945
+ };
946
+ },
947
+ listen: () => new Promise((s, i) => {
948
+ const y = (d) => i(d);
949
+ v.once("error", y), v.listen(c, n, () => {
950
+ v.off("error", y), Vt(
951
+ n,
952
+ c,
953
+ r.role || "default"
954
+ ), s();
955
+ });
956
+ }),
957
+ close: async () => {
958
+ if (e) return;
959
+ e = !0;
960
+ const s = r.shutdownTimeoutMs ?? 1e4;
961
+ let i;
962
+ try {
963
+ await Promise.race([
964
+ Promise.all([
965
+ new Promise((y, d) => {
966
+ v.close(
967
+ (x) => x ? d(x) : y()
968
+ );
969
+ }),
970
+ t.vite?.close()
971
+ ]),
972
+ new Promise((y, d) => {
973
+ i = setTimeout(() => {
974
+ v.closeAllConnections?.(), d(new Error("SSR server graceful shutdown timed out."));
975
+ }, s);
976
+ })
977
+ ]);
978
+ } finally {
979
+ i && clearTimeout(i);
980
+ }
981
+ }
982
+ };
983
+ };
984
+ export {
985
+ C as S,
986
+ zt as a,
987
+ ne as b,
988
+ ae as c,
989
+ Q as d,
990
+ Nt as e,
991
+ Dt as f,
992
+ Ht as g,
993
+ Mt as h,
994
+ Bt as i,
995
+ It as j,
996
+ Lt as k,
997
+ Ut as l,
998
+ Rt as m,
999
+ V as n,
1000
+ z as o,
1001
+ se as r,
1002
+ Pt as s,
1003
+ At as v
1004
+ };