@jay-framework/production-server 0.25.5 → 0.26.0
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/dist/index.d.ts +8 -4
- package/dist/index.js +96 -239
- package/dist/init-services-CItlWIEg.js +1448 -0
- package/dist/serve-index-D5MDxOoW.d.ts +559 -0
- package/dist/serve-index.d.ts +1 -1
- package/dist/serve-index.js +18 -5
- package/package.json +8 -8
- package/dist/init-services-CG_wDJmY.js +0 -761
- package/dist/serve-index-C28bP6tW.d.ts +0 -260
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { R as RouteManifest,
|
|
2
|
-
export { b as ActionEntry, B as BuildMetadata, c as BuildOptions, C as CacheEntry, E as ErrorPageEntry, F as FilesystemArtifactStore, I as InstanceEntry, M as MatchResult, P as PageModule,
|
|
1
|
+
import { R as RouteManifest, A as ArtifactStore, a as RouteEntry } from './serve-index-D5MDxOoW.js';
|
|
2
|
+
export { b as ActionEntry, B as BuildMetadata, c as BuildOptions, C as CacheEntry, d as CacheNotFoundError, D as DEFAULT_LIST_TTL_MS, E as ErrorPageEntry, F as FilesystemArtifactStore, I as InstanceEntry, e as InstanceRef, f as InstanceRenderer, g as InstanceRendererOptions, L as ListInstancesOptions, M as MatchResult, h as MissOutcome, P as PageModule, i as PluginEntry, j as PreImportedPlugin, k as RefreshStart, l as ResolveResult, m as RouteMatch, n as RouteSegment, S as ServerElementModule, o as SwrCache, p as canonicalParams, q as deriveCachePath, r as fetchActionRequest, s as fetchPageRequest, t as fetchStaticFile, u as initializeServices, v as initializeServicesFromModules, w as instanceKey, x as isActionRequest, y as loadPagePartsFromConfig, z as matchRoutes, G as parseCacheEntry, H as registerActionsFromManifest, J as registerActionsFromModules, K as resolveRequest, N as routeInstanceDir, O as serializeCacheEntry, Q as synthesizeInstance, T as toInstanceRef } from './serve-index-D5MDxOoW.js';
|
|
3
3
|
import { HeadTag } from '@jay-framework/fullstack-component';
|
|
4
4
|
import { ErrorInfo } from '@jay-framework/stack-server-runtime';
|
|
5
5
|
import '@jay-framework/ssr-runtime';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Write `sitemap.xml` from the manifest routes × the store's instance listing (Design Log #227).
|
|
9
|
+
* The listing may be served from the store's TTL cache, so new items appear within the list TTL.
|
|
10
|
+
*/
|
|
11
|
+
declare function generateSitemap(manifest: RouteManifest, store: Pick<ArtifactStore, 'listInstances'>, baseUrl: string, outputPath: string): Promise<number>;
|
|
8
12
|
declare function buildUrlFromManifest(pattern: string, params: Record<string, string>): string;
|
|
9
13
|
|
|
10
14
|
/**
|
|
@@ -44,7 +48,7 @@ interface LlmsTxtSiteConfig {
|
|
|
44
48
|
* Returns the number of page links written. Requires `site.name` (the H1); callers skip the
|
|
45
49
|
* emission when it is absent (parallel to the sitemap requiring `baseUrl`).
|
|
46
50
|
*/
|
|
47
|
-
declare function generateLlmsTxt(manifest: RouteManifest,
|
|
51
|
+
declare function generateLlmsTxt(manifest: RouteManifest, store: Pick<ArtifactStore, 'listInstances' | 'readCacheData'>, site: LlmsTxtSiteConfig, outputPath: string): Promise<number>;
|
|
48
52
|
|
|
49
53
|
/**
|
|
50
54
|
* Generate a default `robots.txt` (DL#214) — **only when the author has not provided one**
|
package/dist/index.js
CHANGED
|
@@ -1,54 +1,12 @@
|
|
|
1
|
+
import { o as buildUrlFromManifest, F as FilesystemArtifactStore, I as InstanceRenderer, i as initializeServices, r as registerActionsFromManifest, h as isActionRequest, f as fetchActionRequest, b as fetchStaticFile, k as resolveRequest, q as renderErrorPage, a as fetchPageRequest, u as renderInstance, n as synthesizeInstance, v as generateSitemap, m as matchRoutes } from "./init-services-CItlWIEg.js";
|
|
2
|
+
import { C, D, S, c, d, e, g, w, p, j, l, s, t } from "./init-services-CItlWIEg.js";
|
|
1
3
|
import fs from "node:fs/promises";
|
|
2
|
-
import
|
|
3
|
-
import { headMetaToHeadTags, parseCookies, scanPlugins, DevSlowlyChangingPhase, slowRenderInstances } from "@jay-framework/stack-server-runtime";
|
|
4
|
+
import { headMetaToHeadTags, parseCookies, scanPlugins } from "@jay-framework/stack-server-runtime";
|
|
4
5
|
import http from "node:http";
|
|
5
6
|
import { Readable } from "node:stream";
|
|
7
|
+
import path from "node:path";
|
|
6
8
|
import { getLogger } from "@jay-framework/logger";
|
|
7
|
-
import { F as FilesystemArtifactStore, i as initializeServices, r as registerActionsFromManifest, d as isActionRequest, f as fetchActionRequest, b as fetchStaticFile, m as matchRequest, g as renderErrorPage, a as fetchPageRequest, l as loadPagePartsFromConfig } from "./init-services-CG_wDJmY.js";
|
|
8
|
-
import { c, e } from "./init-services-CG_wDJmY.js";
|
|
9
9
|
import { isJayWebhook } from "@jay-framework/fullstack-component";
|
|
10
|
-
import crypto from "node:crypto";
|
|
11
|
-
async function generateSitemap(manifest, baseUrl, outputPath) {
|
|
12
|
-
const base = baseUrl.replace(/\/$/, "");
|
|
13
|
-
const urls = [];
|
|
14
|
-
for (const route of manifest.routes) {
|
|
15
|
-
if (route.devOnly) continue;
|
|
16
|
-
if (route.noIndex) continue;
|
|
17
|
-
if (route.instances.length === 0) {
|
|
18
|
-
const hasDynamic = route.segments.some((s) => s.type !== "static");
|
|
19
|
-
if (!hasDynamic) {
|
|
20
|
-
const urlPath = route.pattern === "/" ? "/" : route.pattern;
|
|
21
|
-
urls.push(`${base}${urlPath}`);
|
|
22
|
-
}
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
for (const instance of route.instances) {
|
|
26
|
-
const urlPath = buildUrlFromManifest(route.pattern, instance.params);
|
|
27
|
-
urls.push(`${base}${urlPath}`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const tmpPath = outputPath + ".tmp";
|
|
31
|
-
const handle = await fs.open(tmpPath, "w");
|
|
32
|
-
try {
|
|
33
|
-
await handle.write('<?xml version="1.0" encoding="UTF-8"?>\n');
|
|
34
|
-
await handle.write('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n');
|
|
35
|
-
for (const url of urls) {
|
|
36
|
-
await handle.write(` <url><loc>${escapeXml(url)}</loc></url>
|
|
37
|
-
`);
|
|
38
|
-
}
|
|
39
|
-
await handle.write("</urlset>\n");
|
|
40
|
-
} finally {
|
|
41
|
-
await handle.close();
|
|
42
|
-
}
|
|
43
|
-
await fs.rename(tmpPath, outputPath);
|
|
44
|
-
return urls.length;
|
|
45
|
-
}
|
|
46
|
-
function buildUrlFromManifest(pattern, params) {
|
|
47
|
-
return pattern.replace(/\[\[(\w+)\]\]/g, (_, name) => params[name] || "").replace(/\[\.\.\.(\w+)\]/g, (_, name) => params[name] || "").replace(/\[(\w+)\]/g, (_, name) => params[name] || "").replace(/\/\/+/g, "/").replace(/\/$/, "") || "/";
|
|
48
|
-
}
|
|
49
|
-
function escapeXml(str) {
|
|
50
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
51
|
-
}
|
|
52
10
|
function resolveUrl(baseUrl, value) {
|
|
53
11
|
if (/^https?:\/\//i.test(value)) return value;
|
|
54
12
|
if (!baseUrl) return value;
|
|
@@ -91,41 +49,41 @@ const UNRESOLVED_BINDING = /\{[A-Za-z_$][\w$]*(?:\.[\w$]+)*\}/;
|
|
|
91
49
|
function hasUnresolved(value) {
|
|
92
50
|
return !!value && UNRESOLVED_BINDING.test(value);
|
|
93
51
|
}
|
|
94
|
-
async function loadSlowViewState(
|
|
52
|
+
async function loadSlowViewState(store, cachePath) {
|
|
95
53
|
try {
|
|
96
|
-
|
|
97
|
-
return JSON.parse(raw).slowViewState ?? {};
|
|
54
|
+
return (await store.readCacheData(cachePath)).slowViewState ?? {};
|
|
98
55
|
} catch {
|
|
99
56
|
return {};
|
|
100
57
|
}
|
|
101
58
|
}
|
|
102
59
|
function resolveTitleAndDescription(route, viewState) {
|
|
103
60
|
const tags = headMetaToHeadTags(route.headMeta, viewState);
|
|
104
|
-
const titleTag = tags.find((
|
|
61
|
+
const titleTag = tags.find((t2) => t2.tag.toLowerCase() === "title");
|
|
105
62
|
const descTag = tags.find(
|
|
106
|
-
(
|
|
63
|
+
(t2) => t2.tag.toLowerCase() === "meta" && t2.attrs?.name === "description"
|
|
107
64
|
);
|
|
108
65
|
const title = hasUnresolved(titleTag?.children) ? void 0 : titleTag?.children;
|
|
109
66
|
const description = hasUnresolved(descTag?.attrs?.content) ? void 0 : descTag?.attrs?.content;
|
|
110
67
|
return { title, description };
|
|
111
68
|
}
|
|
112
|
-
async function collectPageLinks(manifest, base,
|
|
69
|
+
async function collectPageLinks(manifest, base, store) {
|
|
113
70
|
const links = [];
|
|
114
71
|
for (const route of manifest.routes) {
|
|
115
72
|
if (route.devOnly || route.noIndex) continue;
|
|
116
|
-
|
|
117
|
-
|
|
73
|
+
let count = 0;
|
|
74
|
+
for await (const instance of store.listInstances(route)) {
|
|
75
|
+
count++;
|
|
76
|
+
const urlPath = buildUrlFromManifest(route.pattern, instance.params);
|
|
77
|
+
const viewState = await loadSlowViewState(store, instance.cachePath);
|
|
78
|
+
const { title, description } = resolveTitleAndDescription(route, viewState);
|
|
79
|
+
links.push({ title: title ?? urlPath, url: `${base}${urlPath}`, description });
|
|
80
|
+
}
|
|
81
|
+
if (count === 0) {
|
|
82
|
+
const hasDynamic = route.segments.some((s2) => s2.type !== "static");
|
|
118
83
|
if (hasDynamic) continue;
|
|
119
84
|
const urlPath = route.pattern === "/" ? "/" : route.pattern;
|
|
120
85
|
const { title, description } = resolveTitleAndDescription(route, {});
|
|
121
86
|
links.push({ title: title ?? urlPath, url: `${base}${urlPath}`, description });
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
for (const instance of route.instances) {
|
|
125
|
-
const urlPath = buildUrlFromManifest(route.pattern, instance.params);
|
|
126
|
-
const viewState = await loadSlowViewState(backendDir, instance.cachePath);
|
|
127
|
-
const { title, description } = resolveTitleAndDescription(route, viewState);
|
|
128
|
-
links.push({ title: title ?? urlPath, url: `${base}${urlPath}`, description });
|
|
129
87
|
}
|
|
130
88
|
}
|
|
131
89
|
return links;
|
|
@@ -135,9 +93,9 @@ function sectionOf(url, base) {
|
|
|
135
93
|
const seg = pathOnly.replace(/^\//, "").split("/")[0];
|
|
136
94
|
return seg || "Home";
|
|
137
95
|
}
|
|
138
|
-
async function generateLlmsTxt(manifest,
|
|
96
|
+
async function generateLlmsTxt(manifest, store, site, outputPath) {
|
|
139
97
|
const base = (site.baseUrl ?? "").replace(/\/$/, "");
|
|
140
|
-
const links = await collectPageLinks(manifest, base,
|
|
98
|
+
const links = await collectPageLinks(manifest, base, store);
|
|
141
99
|
const lines = [`# ${site.name}`, ""];
|
|
142
100
|
if (site.description) {
|
|
143
101
|
lines.push(`> ${site.description}`, "");
|
|
@@ -192,8 +150,10 @@ function toFetchRequest(req) {
|
|
|
192
150
|
async function pipeFetchResponse(response, res) {
|
|
193
151
|
const headers = {};
|
|
194
152
|
response.headers.forEach((value, key) => {
|
|
195
|
-
headers[key] = value;
|
|
153
|
+
if (key !== "set-cookie") headers[key] = value;
|
|
196
154
|
});
|
|
155
|
+
const setCookies = response.headers.getSetCookie();
|
|
156
|
+
if (setCookies.length > 0) headers["set-cookie"] = setCookies;
|
|
197
157
|
res.writeHead(response.status, headers);
|
|
198
158
|
if (response.body) {
|
|
199
159
|
const reader = response.body.getReader();
|
|
@@ -215,6 +175,7 @@ async function startMainServer(options) {
|
|
|
215
175
|
const backendDir = path.join(buildDir, "backend");
|
|
216
176
|
const frontendDir = path.join(buildDir, "frontend");
|
|
217
177
|
const artifacts = new FilesystemArtifactStore(backendDir);
|
|
178
|
+
const renderer = new InstanceRenderer(artifacts);
|
|
218
179
|
const manifest = await artifacts.readManifest();
|
|
219
180
|
logger.important(
|
|
220
181
|
`[Server] Loaded manifest: ${manifest.routes.length} routes, v${manifest.version}`
|
|
@@ -262,8 +223,27 @@ async function startMainServer(options) {
|
|
|
262
223
|
}
|
|
263
224
|
}
|
|
264
225
|
const currentManifest = await artifacts.readManifest();
|
|
265
|
-
const
|
|
266
|
-
|
|
226
|
+
const resolved = await resolveRequest(
|
|
227
|
+
currentManifest,
|
|
228
|
+
url.pathname,
|
|
229
|
+
artifacts,
|
|
230
|
+
renderer
|
|
231
|
+
);
|
|
232
|
+
if (resolved.kind === "redirect") {
|
|
233
|
+
res.writeHead(resolved.status, { Location: resolved.location });
|
|
234
|
+
res.end();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (resolved.kind === "unavailable") {
|
|
238
|
+
res.writeHead(503, {
|
|
239
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
240
|
+
"Retry-After": String(resolved.retryAfterSeconds),
|
|
241
|
+
"Cache-Control": "no-store"
|
|
242
|
+
});
|
|
243
|
+
res.end("Service Unavailable");
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (resolved.kind === "notFound") {
|
|
267
247
|
const response2 = await renderErrorPage(currentManifest, artifacts, staticBaseUrl, {
|
|
268
248
|
status: 404,
|
|
269
249
|
url: url.pathname
|
|
@@ -273,12 +253,13 @@ async function startMainServer(options) {
|
|
|
273
253
|
}
|
|
274
254
|
const cookies = parseCookies(req.headers.cookie);
|
|
275
255
|
const response = await fetchPageRequest(
|
|
276
|
-
match,
|
|
256
|
+
resolved.match,
|
|
277
257
|
currentManifest,
|
|
278
258
|
url,
|
|
279
259
|
artifacts,
|
|
280
260
|
staticBaseUrl,
|
|
281
|
-
cookies
|
|
261
|
+
cookies,
|
|
262
|
+
renderer
|
|
282
263
|
);
|
|
283
264
|
await pipeFetchResponse(response, res);
|
|
284
265
|
} catch (err) {
|
|
@@ -408,107 +389,23 @@ async function discoverWebhooks(projectRoot, serverBuildDir) {
|
|
|
408
389
|
}
|
|
409
390
|
return webhooks;
|
|
410
391
|
}
|
|
411
|
-
function
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
acc[key] = params[key];
|
|
415
|
-
return acc;
|
|
416
|
-
},
|
|
417
|
-
{}
|
|
418
|
-
);
|
|
419
|
-
const json = JSON.stringify(sorted);
|
|
420
|
-
if (json === "{}" && !suffix) return "";
|
|
421
|
-
const input = suffix ? json + ":" + suffix : json;
|
|
422
|
-
return "_" + crypto.createHash("md5").update(input).digest("hex").substring(0, 8);
|
|
423
|
-
}
|
|
424
|
-
async function rebuildInstance(route, params, backendDir, rebuildSuffix) {
|
|
425
|
-
const logger = getLogger();
|
|
426
|
-
const routeDir = route.pattern.replace(/^\//, "") || "index";
|
|
427
|
-
const paramHash = hashParams(params, rebuildSuffix);
|
|
428
|
-
const instanceId = `page${paramHash}`;
|
|
429
|
-
const backendInstanceDir = path.join(backendDir, "pre-rendered", routeDir);
|
|
430
|
-
await fs.mkdir(backendInstanceDir, { recursive: true });
|
|
431
|
-
const pagePartsConfigPath = path.join(backendInstanceDir, "page-parts.json");
|
|
432
|
-
const artifacts = new FilesystemArtifactStore(backendDir);
|
|
433
|
-
let pageParts;
|
|
434
|
-
try {
|
|
435
|
-
pageParts = await loadPagePartsFromConfig(
|
|
436
|
-
path.relative(backendDir, pagePartsConfigPath),
|
|
437
|
-
artifacts
|
|
438
|
-
);
|
|
439
|
-
} catch (err) {
|
|
440
|
-
return { status: "skipped", reason: `Failed to load page-parts.json: ${err.message}` };
|
|
392
|
+
async function rebuildInstance(route, params, store) {
|
|
393
|
+
if (!store.writeCacheData) {
|
|
394
|
+
return { status: "skipped", reason: "Artifact store is read-only" };
|
|
441
395
|
}
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
params,
|
|
446
|
-
{ language: "en", url: pageUrl },
|
|
447
|
-
pageParts.parts,
|
|
448
|
-
pageParts.discoveredInstances,
|
|
449
|
-
pageParts.headlessInstanceComponents
|
|
450
|
-
);
|
|
451
|
-
if (slowResult.kind !== "PhaseOutput") {
|
|
452
|
-
if (slowResult.kind === "ClientError" || slowResult.kind === "Redirect") {
|
|
453
|
-
return {
|
|
454
|
-
status: "skipped",
|
|
455
|
-
reason: `${slowResult.kind} ${slowResult.status ?? ""} ${slowResult.message ?? ""}`.trim()
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
return { status: "skipped", reason: `Slow render returned: ${slowResult.kind}` };
|
|
396
|
+
const outcome = await renderInstance(route, params, store, Date.now());
|
|
397
|
+
if (outcome.kind === "notFound") {
|
|
398
|
+
return { status: "skipped", reason: "ClientError 404" };
|
|
459
399
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
if (pageParts.discoveredInstances && pageParts.discoveredInstances.length > 0 && pageParts.headlessInstanceComponents.length > 0) {
|
|
463
|
-
const instanceSlowResult = await slowRenderInstances(
|
|
464
|
-
pageParts.discoveredInstances,
|
|
465
|
-
pageParts.headlessInstanceComponents,
|
|
466
|
-
{
|
|
467
|
-
pageViewState: slowViewState,
|
|
468
|
-
pageParams: params,
|
|
469
|
-
pageProps: { language: "en", url: pageUrl }
|
|
470
|
-
}
|
|
471
|
-
);
|
|
472
|
-
if (instanceSlowResult) {
|
|
473
|
-
const existingInstances = carryForward.__instances || {
|
|
474
|
-
discovered: [],
|
|
475
|
-
carryForwards: {}
|
|
476
|
-
};
|
|
477
|
-
carryForward.__instances = {
|
|
478
|
-
discovered: [
|
|
479
|
-
...existingInstances.discovered,
|
|
480
|
-
...instanceSlowResult.instancePhaseData.discovered
|
|
481
|
-
],
|
|
482
|
-
carryForwards: {
|
|
483
|
-
...existingInstances.carryForwards,
|
|
484
|
-
...instanceSlowResult.instancePhaseData.carryForwards
|
|
485
|
-
},
|
|
486
|
-
slowViewStates: {
|
|
487
|
-
...existingInstances.slowViewStates || {},
|
|
488
|
-
...instanceSlowResult.instancePhaseData.slowViewStates
|
|
489
|
-
}
|
|
490
|
-
};
|
|
491
|
-
}
|
|
400
|
+
if (outcome.kind === "redirect") {
|
|
401
|
+
return { status: "skipped", reason: `Redirect ${outcome.status} ${outcome.location}` };
|
|
492
402
|
}
|
|
493
|
-
if (
|
|
494
|
-
|
|
495
|
-
discovered: [],
|
|
496
|
-
carryForwards: {}
|
|
497
|
-
};
|
|
498
|
-
existingInstances.forEachInstances = pageParts.forEachInstances;
|
|
499
|
-
carryForward.__instances = existingInstances;
|
|
403
|
+
if (outcome.kind === "error") {
|
|
404
|
+
return { status: "skipped", reason: outcome.reason };
|
|
500
405
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const instanceEntry = {
|
|
505
|
-
params,
|
|
506
|
-
cachePath: path.relative(backendDir, cachePath),
|
|
507
|
-
serverElementPath: route.serverElementPath || "",
|
|
508
|
-
clientBundlePath: route.routeClientBundlePath || "",
|
|
509
|
-
clientCssPath: route.routeCssPath
|
|
510
|
-
};
|
|
511
|
-
return { status: "success", instanceEntry };
|
|
406
|
+
await store.writeCacheData(route, params, outcome.entry);
|
|
407
|
+
getLogger().info(`[Rebuild] Instance data: ${route.pattern} ${JSON.stringify(params)}`);
|
|
408
|
+
return { status: "success", instanceEntry: synthesizeInstance(route, params) };
|
|
512
409
|
}
|
|
513
410
|
function resolveContractToRoutes(manifest, contractName) {
|
|
514
411
|
return manifest.routes.filter((r) => r.contracts && r.contracts.includes(contractName));
|
|
@@ -534,20 +431,18 @@ async function rebuild(options) {
|
|
|
534
431
|
const backendDir = path.join(buildDir, "backend");
|
|
535
432
|
const frontendDir = path.join(buildDir, "frontend");
|
|
536
433
|
await initializeServices(backendDir, options.projectRoot, "Rebuild");
|
|
537
|
-
const
|
|
434
|
+
const store = new FilesystemArtifactStore(backendDir);
|
|
538
435
|
const result = { affected: 0, rebuilt: 0, errors: [] };
|
|
539
|
-
const orphanedFiles = [];
|
|
540
436
|
for (const route of affectedRoutes) {
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
|
|
437
|
+
const known = [];
|
|
438
|
+
for await (const ref of store.listInstances(route, { fresh: true })) {
|
|
439
|
+
if (!targetParams || paramsMatch(ref.params, targetParams)) known.push(ref.params);
|
|
544
440
|
}
|
|
545
|
-
|
|
441
|
+
const toRebuild = known.length === 0 && targetParams ? [targetParams] : known;
|
|
442
|
+
for (const params of toRebuild) {
|
|
546
443
|
result.affected++;
|
|
547
|
-
const params = instance.params;
|
|
548
|
-
const oldFiles = collectInstanceFiles(instance);
|
|
549
444
|
try {
|
|
550
|
-
const buildResult = await rebuildInstance(route, params,
|
|
445
|
+
const buildResult = await rebuildInstance(route, params, store);
|
|
551
446
|
if (buildResult.status !== "success") {
|
|
552
447
|
result.errors.push({
|
|
553
448
|
route: route.pattern,
|
|
@@ -556,13 +451,6 @@ async function rebuild(options) {
|
|
|
556
451
|
});
|
|
557
452
|
continue;
|
|
558
453
|
}
|
|
559
|
-
const existingIdx = route.instances.findIndex((i) => paramsMatch(i.params, params));
|
|
560
|
-
if (existingIdx >= 0) {
|
|
561
|
-
route.instances[existingIdx] = buildResult.instanceEntry;
|
|
562
|
-
orphanedFiles.push(...oldFiles);
|
|
563
|
-
} else {
|
|
564
|
-
route.instances.push(buildResult.instanceEntry);
|
|
565
|
-
}
|
|
566
454
|
result.rebuilt++;
|
|
567
455
|
logger.important(`[Rebuild] ${route.pattern} (${JSON.stringify(params)}): rebuilt`);
|
|
568
456
|
} catch (err) {
|
|
@@ -575,47 +463,22 @@ async function rebuild(options) {
|
|
|
575
463
|
}
|
|
576
464
|
}
|
|
577
465
|
if (result.rebuilt > 0) {
|
|
578
|
-
const tempPath = manifestPath + ".tmp";
|
|
579
|
-
await fs.writeFile(tempPath, JSON.stringify(manifest, null, 2));
|
|
580
|
-
await fs.rename(tempPath, manifestPath);
|
|
581
|
-
const metadataPath = path.join(buildDir, "backend", "build-metadata.json");
|
|
582
|
-
try {
|
|
583
|
-
const metadata = JSON.parse(await fs.readFile(metadataPath, "utf-8"));
|
|
584
|
-
metadata.buildTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
585
|
-
metadata.instanceCount = manifest.routes.reduce((n, r) => n + r.instances.length, 0);
|
|
586
|
-
await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
587
|
-
} catch {
|
|
588
|
-
await fs.writeFile(
|
|
589
|
-
metadataPath,
|
|
590
|
-
JSON.stringify(
|
|
591
|
-
{
|
|
592
|
-
version: options.version,
|
|
593
|
-
sourceHash: "",
|
|
594
|
-
buildTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
595
|
-
nodeVersion: process.version,
|
|
596
|
-
instanceCount: manifest.routes.reduce((n, r) => n + r.instances.length, 0)
|
|
597
|
-
},
|
|
598
|
-
null,
|
|
599
|
-
2
|
|
600
|
-
)
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
logger.important(`[Rebuild] Manifest and metadata updated`);
|
|
604
466
|
if (options.siteBaseUrl) {
|
|
605
467
|
const sitemapPath = path.join(frontendDir, "sitemap.xml");
|
|
606
|
-
const urlCount = await generateSitemap(
|
|
468
|
+
const urlCount = await generateSitemap(
|
|
469
|
+
manifest,
|
|
470
|
+
store,
|
|
471
|
+
options.siteBaseUrl,
|
|
472
|
+
sitemapPath
|
|
473
|
+
);
|
|
607
474
|
logger.info(`[Rebuild] Sitemap regenerated: ${urlCount} URLs`);
|
|
608
475
|
}
|
|
609
476
|
const site = options.site ?? (options.siteBaseUrl ? { baseUrl: options.siteBaseUrl } : {});
|
|
610
477
|
if (site.name) {
|
|
611
478
|
const llmsPath = path.join(frontendDir, "llms.txt");
|
|
612
|
-
const count = await generateLlmsTxt(manifest,
|
|
479
|
+
const count = await generateLlmsTxt(manifest, store, site, llmsPath);
|
|
613
480
|
logger.info(`[Rebuild] llms.txt regenerated: ${count} pages`);
|
|
614
481
|
}
|
|
615
|
-
if (orphanedFiles.length > 0) {
|
|
616
|
-
await appendCleanupManifest(buildDir, orphanedFiles);
|
|
617
|
-
logger.info(`[Rebuild] ${orphanedFiles.length} orphaned file(s) queued for cleanup`);
|
|
618
|
-
}
|
|
619
482
|
}
|
|
620
483
|
logger.important(
|
|
621
484
|
`[Rebuild] Done: ${result.affected} affected, ${result.rebuilt} rebuilt, ${result.errors.length} errors`
|
|
@@ -641,7 +504,7 @@ function resolveTarget(manifest, target) {
|
|
|
641
504
|
};
|
|
642
505
|
}
|
|
643
506
|
case "url": {
|
|
644
|
-
const match =
|
|
507
|
+
const match = matchRoutes(manifest, target.url).next().value;
|
|
645
508
|
if (!match) {
|
|
646
509
|
return { routes: [], label: `url "${target.url}"` };
|
|
647
510
|
}
|
|
@@ -662,22 +525,6 @@ async function rebuildContract(options) {
|
|
|
662
525
|
function paramsMatch(instanceParams, targetParams) {
|
|
663
526
|
return Object.entries(targetParams).every(([key, value]) => instanceParams[key] === value);
|
|
664
527
|
}
|
|
665
|
-
function collectInstanceFiles(instance) {
|
|
666
|
-
if (!instance.cachePath) return [];
|
|
667
|
-
const files = [instance.cachePath, instance.serverElementPath, instance.clientBundlePath];
|
|
668
|
-
if (instance.clientCssPath) files.push(instance.clientCssPath);
|
|
669
|
-
return files.filter(Boolean);
|
|
670
|
-
}
|
|
671
|
-
async function appendCleanupManifest(buildDir, files) {
|
|
672
|
-
const cleanupPath = path.join(buildDir, "cleanup-manifest.json");
|
|
673
|
-
let existing = [];
|
|
674
|
-
try {
|
|
675
|
-
existing = JSON.parse(await fs.readFile(cleanupPath, "utf-8"));
|
|
676
|
-
} catch {
|
|
677
|
-
}
|
|
678
|
-
existing.push(...files);
|
|
679
|
-
await fs.writeFile(cleanupPath, JSON.stringify(existing, null, 2));
|
|
680
|
-
}
|
|
681
528
|
async function cleanupOrphanedFiles(buildRoot, version) {
|
|
682
529
|
const logger = getLogger();
|
|
683
530
|
const buildDir = path.join(buildRoot, `v${version}`);
|
|
@@ -793,16 +640,13 @@ async function startRendererServer(options) {
|
|
|
793
640
|
return;
|
|
794
641
|
}
|
|
795
642
|
if (url.pathname === "/_jay/status" && req.method === "GET") {
|
|
796
|
-
const manifest = JSON.parse(
|
|
797
|
-
await fs.readFile(path.join(buildDir, "route-manifest.json"), "utf-8")
|
|
798
|
-
);
|
|
799
643
|
const metadata = JSON.parse(
|
|
800
644
|
await fs.readFile(path.join(buildDir, "build-metadata.json"), "utf-8")
|
|
801
645
|
);
|
|
802
646
|
const status = {
|
|
803
647
|
version: options.version,
|
|
804
648
|
buildTimestamp: metadata.buildTimestamp,
|
|
805
|
-
instanceCount:
|
|
649
|
+
instanceCount: metadata.instanceCount,
|
|
806
650
|
uptime: Math.floor((Date.now() - startTime) / 1e3),
|
|
807
651
|
webhooks: [...webhookMap.keys()],
|
|
808
652
|
lastWebhook
|
|
@@ -836,9 +680,15 @@ function readBody(req) {
|
|
|
836
680
|
});
|
|
837
681
|
}
|
|
838
682
|
export {
|
|
683
|
+
C as CacheNotFoundError,
|
|
684
|
+
D as DEFAULT_LIST_TTL_MS,
|
|
839
685
|
FilesystemArtifactStore,
|
|
686
|
+
InstanceRenderer,
|
|
687
|
+
S as SwrCache,
|
|
840
688
|
buildUrlFromManifest,
|
|
689
|
+
c as canonicalParams,
|
|
841
690
|
cleanupOrphanedFiles,
|
|
691
|
+
d as deriveCachePath,
|
|
842
692
|
fetchActionRequest,
|
|
843
693
|
fetchPageRequest,
|
|
844
694
|
fetchStaticFile,
|
|
@@ -847,16 +697,23 @@ export {
|
|
|
847
697
|
generateSiteJsonLd,
|
|
848
698
|
generateSitemap,
|
|
849
699
|
initializeServices,
|
|
850
|
-
|
|
700
|
+
e as initializeServicesFromModules,
|
|
701
|
+
g as instanceKey,
|
|
851
702
|
isActionRequest,
|
|
852
|
-
loadPagePartsFromConfig,
|
|
853
|
-
|
|
703
|
+
w as loadPagePartsFromConfig,
|
|
704
|
+
matchRoutes,
|
|
705
|
+
p as parseCacheEntry,
|
|
854
706
|
rebuild,
|
|
855
707
|
rebuildContract,
|
|
856
708
|
registerActionsFromManifest,
|
|
857
|
-
|
|
709
|
+
j as registerActionsFromModules,
|
|
858
710
|
renderErrorPage,
|
|
859
711
|
resolveContractToRoutes,
|
|
712
|
+
resolveRequest,
|
|
713
|
+
l as routeInstanceDir,
|
|
714
|
+
s as serializeCacheEntry,
|
|
860
715
|
startMainServer,
|
|
861
|
-
startRendererServer
|
|
716
|
+
startRendererServer,
|
|
717
|
+
synthesizeInstance,
|
|
718
|
+
t as toInstanceRef
|
|
862
719
|
};
|