reroute-js 0.25.2 → 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/README.md +150 -52
- package/cli/bin.d.ts +1 -1
- package/cli/bin.js +446 -150
- package/cli/bin.js.map +13 -9
- package/cli/index.d.ts +1 -1
- package/cli/index.js +4 -4
- package/cli/index.js.map +1 -1
- package/cli/src/cli.d.ts +1 -1
- package/cli/src/commands/analyze.d.ts +1 -1
- package/cli/src/commands/build.d.ts +1 -1
- package/cli/src/commands/dev.d.ts +1 -1
- package/cli/src/commands/gen.d.ts +1 -1
- package/cli/src/commands/gen.d.ts.map +1 -1
- package/cli/src/commands/index.d.ts +1 -1
- package/cli/src/commands/init.d.ts +1 -1
- package/cli/src/commands/lib/assets.d.ts +1 -1
- package/cli/src/commands/lib/bundler.d.ts +1 -1
- package/cli/src/commands/lib/command.d.ts +1 -1
- package/cli/src/commands/lib/env.d.ts +1 -1
- package/cli/src/commands/lib/index.d.ts +1 -1
- package/cli/src/commands/lib/log.d.ts +1 -1
- package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
- package/cli/src/commands/lib/markdown/index.d.ts +1 -1
- package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
- package/cli/src/commands/lib/production.d.ts +1 -1
- package/cli/src/commands/lib/server.d.ts +1 -1
- package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
- package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
- package/cli/src/commands/lib/tailwind.d.ts +1 -1
- package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
- package/cli/src/commands/lib/version.d.ts +1 -1
- package/cli/src/commands/og.d.ts +1 -1
- package/cli/src/commands/start.d.ts +1 -1
- package/cli/src/index.d.ts +1 -1
- package/core/index.d.ts +1 -1
- package/core/index.js +912 -589
- package/core/index.js.map +22 -14
- package/core/src/bundler/hash.d.ts +1 -1
- package/core/src/bundler/index.d.ts +1 -1
- package/core/src/config.d.ts +243 -2
- package/core/src/config.d.ts.map +1 -1
- package/core/src/content/discovery.d.ts +1 -1
- package/core/src/content/index.d.ts +1 -1
- package/core/src/content/metadata.d.ts +1 -1
- package/core/src/index.d.ts +1 -1
- package/core/src/llms/extractor.d.ts +1 -1
- package/core/src/llms/formatter.d.ts +1 -1
- package/core/src/llms/full-generator.d.ts +1 -1
- package/core/src/llms/index-generator.d.ts +1 -1
- package/core/src/llms/index.d.ts +1 -1
- package/core/src/og/discovery.d.ts +1 -1
- package/core/src/og/index.d.ts +1 -1
- package/core/src/og/meta.d.ts +1 -1
- package/core/src/og/render.d.ts +1 -1
- package/core/src/og/types.d.ts +1 -1
- package/core/src/robots/discovery.d.ts +1 -1
- package/core/src/robots/generator.d.ts +1 -1
- package/core/src/robots/index.d.ts +1 -1
- package/core/src/robots/policies.d.ts +1 -1
- package/core/src/rss/discovery.d.ts +1 -1
- package/core/src/rss/generator.d.ts +1 -1
- package/core/src/rss/index.d.ts +1 -1
- package/core/src/sitemap/discovery.d.ts +1 -1
- package/core/src/sitemap/generator.d.ts +1 -1
- package/core/src/sitemap/index.d.ts +1 -1
- package/core/src/ssr/index.d.ts +1 -1
- package/core/src/ssr/lib/cache.d.ts +1 -1
- package/core/src/ssr/lib/collections.d.ts +1 -1
- package/core/src/ssr/lib/compression.d.ts +1 -1
- package/core/src/ssr/lib/compute/content.d.ts +1 -1
- package/core/src/ssr/lib/compute/index.d.ts +1 -1
- package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
- package/core/src/ssr/lib/compute/routes.d.ts +1 -1
- package/core/src/ssr/lib/data.d.ts +1 -1
- package/core/src/ssr/lib/html.d.ts +1 -1
- package/core/src/ssr/lib/imports.d.ts +1 -1
- package/core/src/ssr/lib/index.d.ts +1 -1
- package/core/src/ssr/lib/layouts.d.ts +1 -1
- package/core/src/ssr/lib/metadata.d.ts +1 -1
- package/core/src/ssr/lib/mime.d.ts +1 -1
- package/core/src/ssr/lib/modules.d.ts +1 -1
- package/core/src/ssr/lib/path.d.ts +1 -1
- package/core/src/ssr/lib/preload.d.ts +1 -1
- package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
- package/core/src/ssr/lib/scripts/data.d.ts +2 -2
- package/core/src/ssr/lib/scripts/data.d.ts.map +1 -1
- package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
- package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
- package/core/src/ssr/lib/scripts/index.d.ts +1 -1
- package/core/src/ssr/lib/seed.d.ts +1 -1
- package/core/src/ssr/lib/setup.d.ts +4 -2
- package/core/src/ssr/lib/setup.d.ts.map +1 -1
- package/core/src/ssr/lib/styles.d.ts +1 -1
- package/core/src/ssr/lib/template.d.ts +1 -1
- package/core/src/ssr/lib/types.d.ts +1 -1
- package/core/src/ssr/render.d.ts +4 -2
- package/core/src/ssr/render.d.ts.map +1 -1
- package/core/src/ssr/stream.d.ts +4 -2
- package/core/src/ssr/stream.d.ts.map +1 -1
- package/elysia/index.d.ts +1 -1
- package/elysia/index.js +715 -468
- package/elysia/index.js.map +15 -11
- package/elysia/src/index.d.ts +1 -1
- package/elysia/src/libs/assets.d.ts +1 -1
- package/elysia/src/libs/cache.d.ts +1 -1
- package/elysia/src/libs/caching.d.ts +1 -1
- package/elysia/src/libs/http.d.ts +1 -1
- package/elysia/src/libs/image.d.ts +1 -1
- package/elysia/src/libs/index.d.ts +1 -1
- package/elysia/src/libs/llms.d.ts +1 -1
- package/elysia/src/libs/response.d.ts +1 -1
- package/elysia/src/libs/serving.d.ts +1 -1
- package/elysia/src/plugin.d.ts +1 -1
- package/elysia/src/routes/artifacts.d.ts +1 -1
- package/elysia/src/routes/content.d.ts +1 -1
- package/elysia/src/routes/content.d.ts.map +1 -1
- package/elysia/src/routes/image.d.ts +1 -1
- package/elysia/src/routes/index.d.ts +1 -1
- package/elysia/src/routes/internal.d.ts +1 -1
- package/elysia/src/routes/llms.d.ts +1 -1
- package/elysia/src/routes/og.d.ts +1 -1
- package/elysia/src/routes/redirects.d.ts +1 -1
- package/elysia/src/routes/robots.d.ts +1 -1
- package/elysia/src/routes/rss.d.ts +1 -1
- package/elysia/src/routes/search.d.ts +1 -1
- package/elysia/src/routes/sitemap.d.ts +1 -1
- package/elysia/src/routes/ssr.d.ts +1 -1
- package/elysia/src/routes/ssr.d.ts.map +1 -1
- package/elysia/src/routes/static.d.ts +1 -1
- package/elysia/src/routes/static.d.ts.map +1 -1
- package/elysia/src/types.d.ts +1 -1
- package/package.json +2 -9
- package/react/index.d.ts +1 -1
- package/react/index.js +2 -2
- package/react/index.js.map +1 -1
- package/react/src/components/ClientOnly.d.ts +1 -1
- package/react/src/components/ContentRoute.d.ts +1 -1
- package/react/src/components/Image.d.ts +1 -1
- package/react/src/components/LazyRoute.d.ts +1 -1
- package/react/src/components/Link.d.ts +1 -1
- package/react/src/components/Markdown.d.ts +1 -1
- package/react/src/components/Outlet.d.ts +1 -1
- package/react/src/components/index.d.ts +1 -1
- package/react/src/hooks/index.d.ts +1 -1
- package/react/src/hooks/useContent.d.ts +1 -1
- package/react/src/hooks/useData.d.ts +1 -1
- package/react/src/hooks/useFeed.d.ts +1 -1
- package/react/src/hooks/useLayoutData.d.ts +1 -1
- package/react/src/hooks/useLlms.d.ts +1 -1
- package/react/src/hooks/useNavigate.d.ts +1 -1
- package/react/src/hooks/useParams.d.ts +1 -1
- package/react/src/hooks/useRouter.d.ts +1 -1
- package/react/src/hooks/useSearch.d.ts +1 -1
- package/react/src/hooks/useSearchParams.d.ts +1 -1
- package/react/src/hooks/useToc.d.ts +1 -1
- package/react/src/index.d.ts +1 -1
- package/react/src/lib/collection.d.ts +1 -1
- package/react/src/lib/content.d.ts +1 -1
- package/react/src/lib/head.d.ts +1 -1
- package/react/src/lib/index.d.ts +1 -1
- package/react/src/lib/lazy-route.d.ts +1 -1
- package/react/src/lib/route-loader.d.ts +1 -1
- package/react/src/providers/ContentProvider.d.ts +1 -1
- package/react/src/providers/RerouteProvider.d.ts +1 -1
- package/react/src/providers/RouterProvider.d.ts +1 -1
- package/react/src/providers/index.d.ts +1 -1
- package/react/src/types/any.d.ts +1 -1
- package/react/src/types/index.d.ts +1 -1
- package/react/src/types/router.d.ts +1 -1
- package/telemetry/react.d.ts +2 -2
- package/telemetry/react.d.ts.map +1 -1
- package/telemetry/react.js +167 -185
- package/telemetry/react.js.map +7 -6
- package/telemetry/{index.d.ts → server.d.ts} +2 -2
- package/telemetry/server.d.ts.map +1 -0
- package/telemetry/server.js +1134 -0
- package/telemetry/server.js.map +44 -0
- package/telemetry/src/{browser/react.d.ts → react/api.d.ts} +4 -12
- package/telemetry/src/react/api.d.ts.map +1 -0
- package/telemetry/{browser.d.ts → src/react/index.d.ts} +4 -3
- package/telemetry/src/react/index.d.ts.map +1 -0
- package/telemetry/src/{browser/index.d.ts → react/telemetry.d.ts} +13 -13
- package/telemetry/src/react/telemetry.d.ts.map +1 -0
- package/telemetry/src/server/index.d.ts +3 -101
- package/telemetry/src/server/index.d.ts.map +1 -1
- package/telemetry/src/server/instrumentation.d.ts +62 -0
- package/telemetry/src/server/instrumentation.d.ts.map +1 -0
- package/telemetry/src/server/plugin.d.ts +72 -0
- package/telemetry/src/server/plugin.d.ts.map +1 -0
- package/telemetry/browser.d.ts.map +0 -1
- package/telemetry/browser.js +0 -382
- package/telemetry/browser.js.map +0 -10
- package/telemetry/index.d.ts.map +0 -1
- package/telemetry/index.js +0 -509
- package/telemetry/index.js.map +0 -10
- package/telemetry/src/browser/index.d.ts.map +0 -1
- package/telemetry/src/browser/react.d.ts.map +0 -1
package/core/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* reroute-js v0.
|
|
2
|
+
* reroute-js v0.26.0
|
|
3
3
|
*
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2025 stewones <hi@stewan.io>
|
|
@@ -36,6 +36,44 @@ var __export = (target, all) => {
|
|
|
36
36
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
37
37
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
38
38
|
|
|
39
|
+
// packages/core/src/bundler/hash.ts
|
|
40
|
+
async function generateContentHash(content) {
|
|
41
|
+
const data = new TextEncoder().encode(content);
|
|
42
|
+
const buf = await crypto.subtle.digest("SHA-256", data);
|
|
43
|
+
let hex = "";
|
|
44
|
+
for (const b of new Uint8Array(buf))
|
|
45
|
+
hex += b.toString(16).padStart(2, "0");
|
|
46
|
+
return hex.slice(0, 8);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// packages/core/src/bundler/index.ts
|
|
50
|
+
var init_bundler = () => {};
|
|
51
|
+
|
|
52
|
+
// packages/core/src/config.ts
|
|
53
|
+
import { pathToFileURL } from "node:url";
|
|
54
|
+
function defineConfig(config) {
|
|
55
|
+
return config;
|
|
56
|
+
}
|
|
57
|
+
async function loadConfig(cwd) {
|
|
58
|
+
const bundledConfig = globalThis.__REROUTE_CONFIG__;
|
|
59
|
+
if (bundledConfig) {
|
|
60
|
+
return bundledConfig;
|
|
61
|
+
}
|
|
62
|
+
const configPath = `${cwd}/reroute.config.ts`;
|
|
63
|
+
const configFile = Bun.file(configPath);
|
|
64
|
+
if (!await configFile.exists()) {
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const mod = await import(`${pathToFileURL(configPath).href}?t=${Date.now()}`);
|
|
69
|
+
return mod.default || mod;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.warn("[reroute] Failed to load reroute.config.ts:", error);
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
var init_config = () => {};
|
|
76
|
+
|
|
39
77
|
// packages/core/src/ssr/lib/path.ts
|
|
40
78
|
function join(...parts) {
|
|
41
79
|
return parts.join("/").replace(/\/+/g, "/");
|
|
@@ -55,6 +93,61 @@ function stripEnd(p, ch) {
|
|
|
55
93
|
return p.endsWith(ch) ? p.slice(0, -ch.length) : p;
|
|
56
94
|
}
|
|
57
95
|
|
|
96
|
+
// packages/core/src/content/discovery.ts
|
|
97
|
+
import { readdir, stat } from "node:fs/promises";
|
|
98
|
+
async function listContentFiles(dir, baseRel) {
|
|
99
|
+
const out = [];
|
|
100
|
+
try {
|
|
101
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
const full = join(dir, entry.name);
|
|
104
|
+
const rel = join(baseRel, entry.name);
|
|
105
|
+
if (entry.isDirectory()) {
|
|
106
|
+
const nested = await listContentFiles(full, rel);
|
|
107
|
+
out.push(...nested);
|
|
108
|
+
} else if (entry.isFile()) {
|
|
109
|
+
if (/\.(tsx|ts)$/.test(entry.name) && !entry.name.startsWith("_")) {
|
|
110
|
+
out.push(rel);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} catch {}
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
async function discoverCollections(clientDir) {
|
|
118
|
+
const collections = new Set;
|
|
119
|
+
const bundledCollectionsDir = join(clientDir, "collections");
|
|
120
|
+
try {
|
|
121
|
+
const bundledEntries = await readdir(bundledCollectionsDir, {
|
|
122
|
+
withFileTypes: true
|
|
123
|
+
});
|
|
124
|
+
for (const entry of bundledEntries) {
|
|
125
|
+
if (entry.isFile() && entry.name.endsWith(".js")) {
|
|
126
|
+
const collectionName = entry.name.replace(/\.js$/, "");
|
|
127
|
+
collections.add(collectionName);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (collections.size > 0) {
|
|
131
|
+
return Array.from(collections);
|
|
132
|
+
}
|
|
133
|
+
} catch {}
|
|
134
|
+
const root = join(clientDir, "routes");
|
|
135
|
+
try {
|
|
136
|
+
const entries = await readdir(root, { withFileTypes: true });
|
|
137
|
+
for (const entry of entries) {
|
|
138
|
+
if (entry.isDirectory()) {
|
|
139
|
+
const contentDir = join(root, entry.name, "content");
|
|
140
|
+
try {
|
|
141
|
+
await stat(contentDir);
|
|
142
|
+
collections.add(entry.name);
|
|
143
|
+
} catch {}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch {}
|
|
147
|
+
return Array.from(collections);
|
|
148
|
+
}
|
|
149
|
+
var init_discovery = () => {};
|
|
150
|
+
|
|
58
151
|
// packages/core/src/content/metadata.ts
|
|
59
152
|
import { stat as stat2 } from "node:fs/promises";
|
|
60
153
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
@@ -94,6 +187,159 @@ function escapeHtml(input) {
|
|
|
94
187
|
}
|
|
95
188
|
var init_metadata = () => {};
|
|
96
189
|
|
|
190
|
+
// packages/core/src/content/index.ts
|
|
191
|
+
var init_content = __esm(() => {
|
|
192
|
+
init_discovery();
|
|
193
|
+
init_metadata();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// packages/telemetry/src/server/instrumentation.ts
|
|
197
|
+
import { context, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
198
|
+
function isOtelAvailable() {
|
|
199
|
+
if (otelAvailable !== undefined)
|
|
200
|
+
return otelAvailable;
|
|
201
|
+
try {
|
|
202
|
+
__require("@opentelemetry/api");
|
|
203
|
+
otelAvailable = true;
|
|
204
|
+
return true;
|
|
205
|
+
} catch {
|
|
206
|
+
otelAvailable = false;
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
class NoopSpan {
|
|
212
|
+
spanContext() {
|
|
213
|
+
return {
|
|
214
|
+
traceId: "",
|
|
215
|
+
spanId: "",
|
|
216
|
+
traceFlags: 0
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
setAttribute() {
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
setAttributes() {
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
addEvent() {
|
|
226
|
+
return this;
|
|
227
|
+
}
|
|
228
|
+
addLink() {
|
|
229
|
+
return this;
|
|
230
|
+
}
|
|
231
|
+
addLinks() {
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
setStatus() {
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
updateName() {
|
|
238
|
+
return this;
|
|
239
|
+
}
|
|
240
|
+
end() {}
|
|
241
|
+
isRecording() {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
recordException() {}
|
|
245
|
+
}
|
|
246
|
+
async function withSpan(name, fn, attributes) {
|
|
247
|
+
if (!isOtelAvailable()) {
|
|
248
|
+
return fn(noopSpan);
|
|
249
|
+
}
|
|
250
|
+
const tracer = trace.getTracer("reroute");
|
|
251
|
+
return tracer.startActiveSpan(name, { attributes }, async (span) => {
|
|
252
|
+
try {
|
|
253
|
+
const result = await fn(span);
|
|
254
|
+
span.end();
|
|
255
|
+
return result;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
span.recordException(error);
|
|
258
|
+
span.setStatus({
|
|
259
|
+
code: SpanStatusCode.ERROR,
|
|
260
|
+
message: error instanceof Error ? error.message : String(error)
|
|
261
|
+
});
|
|
262
|
+
span.end();
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
function withSpanSync(name, fn, attributes) {
|
|
268
|
+
if (!isOtelAvailable()) {
|
|
269
|
+
return fn(noopSpan);
|
|
270
|
+
}
|
|
271
|
+
const tracer = trace.getTracer("reroute");
|
|
272
|
+
return tracer.startActiveSpan(name, { attributes }, (span) => {
|
|
273
|
+
try {
|
|
274
|
+
const result = fn(span);
|
|
275
|
+
span.end();
|
|
276
|
+
return result;
|
|
277
|
+
} catch (error) {
|
|
278
|
+
span.recordException(error);
|
|
279
|
+
span.setStatus({
|
|
280
|
+
code: SpanStatusCode.ERROR,
|
|
281
|
+
message: error instanceof Error ? error.message : String(error)
|
|
282
|
+
});
|
|
283
|
+
span.end();
|
|
284
|
+
throw error;
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
async function withParentSpan(parentSpan, fn) {
|
|
289
|
+
if (!(isOtelAvailable() && parentSpan)) {
|
|
290
|
+
return fn();
|
|
291
|
+
}
|
|
292
|
+
const ctx = trace.setSpan(context.active(), parentSpan);
|
|
293
|
+
return context.with(ctx, fn);
|
|
294
|
+
}
|
|
295
|
+
var otelAvailable, noopSpan;
|
|
296
|
+
var init_instrumentation = __esm(() => {
|
|
297
|
+
noopSpan = new NoopSpan;
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// packages/telemetry/src/server/plugin.ts
|
|
301
|
+
import {
|
|
302
|
+
metrics,
|
|
303
|
+
SpanStatusCode as SpanStatusCode2,
|
|
304
|
+
trace as trace2
|
|
305
|
+
} from "@opentelemetry/api";
|
|
306
|
+
import { logs, SeverityNumber } from "@opentelemetry/api-logs";
|
|
307
|
+
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-proto";
|
|
308
|
+
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-proto";
|
|
309
|
+
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
|
|
310
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
311
|
+
import {
|
|
312
|
+
BatchLogRecordProcessor,
|
|
313
|
+
LoggerProvider
|
|
314
|
+
} from "@opentelemetry/sdk-logs";
|
|
315
|
+
import {
|
|
316
|
+
MeterProvider,
|
|
317
|
+
PeriodicExportingMetricReader
|
|
318
|
+
} from "@opentelemetry/sdk-metrics";
|
|
319
|
+
import {
|
|
320
|
+
BatchSpanProcessor,
|
|
321
|
+
NodeTracerProvider
|
|
322
|
+
} from "@opentelemetry/sdk-trace-node";
|
|
323
|
+
import {
|
|
324
|
+
ATTR_SERVICE_NAME,
|
|
325
|
+
ATTR_SERVICE_VERSION
|
|
326
|
+
} from "@opentelemetry/semantic-conventions";
|
|
327
|
+
import { ATTR_HOST_NAME } from "@opentelemetry/semantic-conventions/incubating";
|
|
328
|
+
var init_plugin = __esm(() => {
|
|
329
|
+
init_core();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// packages/telemetry/src/server/index.ts
|
|
333
|
+
var init_server = __esm(() => {
|
|
334
|
+
init_instrumentation();
|
|
335
|
+
init_plugin();
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// packages/telemetry/server.ts
|
|
339
|
+
var init_server2 = __esm(() => {
|
|
340
|
+
init_server();
|
|
341
|
+
});
|
|
342
|
+
|
|
97
343
|
// packages/core/src/ssr/lib/cache.ts
|
|
98
344
|
class SSRDataCache {
|
|
99
345
|
cache = new Map;
|
|
@@ -403,7 +649,7 @@ async function computeContentData(pathname, options, searchParams, sharedSsrData
|
|
|
403
649
|
} catch {}
|
|
404
650
|
return { data: ssrData, error, statusOverride, pendingTasks };
|
|
405
651
|
}
|
|
406
|
-
var
|
|
652
|
+
var init_content2 = __esm(() => {
|
|
407
653
|
init_cache();
|
|
408
654
|
init_imports();
|
|
409
655
|
});
|
|
@@ -837,10 +1083,10 @@ function setGlobalSSRData(data) {
|
|
|
837
1083
|
}
|
|
838
1084
|
var init_compute = __esm(() => {
|
|
839
1085
|
init_imports();
|
|
840
|
-
|
|
1086
|
+
init_content2();
|
|
841
1087
|
init_layouts();
|
|
842
1088
|
init_routes();
|
|
843
|
-
|
|
1089
|
+
init_content2();
|
|
844
1090
|
init_layouts();
|
|
845
1091
|
init_routes();
|
|
846
1092
|
});
|
|
@@ -1400,7 +1646,7 @@ function extractParamsFromPath(pathname, ogPath, clientDir) {
|
|
|
1400
1646
|
}
|
|
1401
1647
|
return params;
|
|
1402
1648
|
}
|
|
1403
|
-
var
|
|
1649
|
+
var init_discovery2 = () => {};
|
|
1404
1650
|
|
|
1405
1651
|
// packages/core/src/og/meta.ts
|
|
1406
1652
|
async function generateOGImageMetaTags(pathname, clientDir, ogConfig) {
|
|
@@ -1436,7 +1682,7 @@ async function generateOGImageMetaTags(pathname, clientDir, ogConfig) {
|
|
|
1436
1682
|
<meta name="twitter:image" content="${ogImagePath}" />`;
|
|
1437
1683
|
}
|
|
1438
1684
|
var init_meta = __esm(() => {
|
|
1439
|
-
|
|
1685
|
+
init_discovery2();
|
|
1440
1686
|
});
|
|
1441
1687
|
|
|
1442
1688
|
// packages/core/src/ssr/lib/metadata.ts
|
|
@@ -1910,12 +2156,25 @@ function createSSRExportsScript(pathname) {
|
|
|
1910
2156
|
return "";
|
|
1911
2157
|
}
|
|
1912
2158
|
}
|
|
1913
|
-
function
|
|
2159
|
+
function createTelemetryConfigScript(browserTelemetryConfig) {
|
|
2160
|
+
if (!browserTelemetryConfig || Object.keys(browserTelemetryConfig).length === 0) {
|
|
2161
|
+
return "";
|
|
2162
|
+
}
|
|
2163
|
+
try {
|
|
2164
|
+
const configJson = escapeJsonForScript(JSON.stringify(browserTelemetryConfig));
|
|
2165
|
+
return `<script>(function(){try{var w=(typeof window!=='undefined'?window:globalThis);w.__REROUTE_TELEMETRY_BROWSER__=${configJson};}catch(e){}})();</script>`;
|
|
2166
|
+
} catch (error) {
|
|
2167
|
+
console.error("[reroute] Failed to serialize browser telemetry config:", error);
|
|
2168
|
+
return "";
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
function createDataScript(ssrData, errorMsg, pathname, browserTelemetryConfig) {
|
|
1914
2172
|
let script = "";
|
|
1915
2173
|
script += createContentCaptureScript();
|
|
1916
2174
|
if (pathname) {
|
|
1917
2175
|
script += createSSRExportsScript(pathname);
|
|
1918
2176
|
}
|
|
2177
|
+
script += createTelemetryConfigScript(browserTelemetryConfig);
|
|
1919
2178
|
if (ssrData && Object.keys(ssrData).length > 0) {
|
|
1920
2179
|
try {
|
|
1921
2180
|
const duplicatedData = duplicateQueryParamData(ssrData);
|
|
@@ -2016,7 +2275,7 @@ async function performSSRSetup(options, streaming = false) {
|
|
|
2016
2275
|
});
|
|
2017
2276
|
try {
|
|
2018
2277
|
return await Promise.race([
|
|
2019
|
-
performSSRSetupInternal(options, streaming),
|
|
2278
|
+
withParentSpan(options.parentSpan, () => performSSRSetupInternal(options, streaming)),
|
|
2020
2279
|
timeoutPromise
|
|
2021
2280
|
]);
|
|
2022
2281
|
} catch (error) {
|
|
@@ -2047,34 +2306,70 @@ async function performSSRSetupInternal(options, streaming) {
|
|
|
2047
2306
|
searchParams,
|
|
2048
2307
|
ogConfig
|
|
2049
2308
|
} = options;
|
|
2050
|
-
await
|
|
2051
|
-
|
|
2052
|
-
|
|
2309
|
+
await withSpan("ssr.seed", async (span) => {
|
|
2310
|
+
span.setAttribute("pathname", pathname);
|
|
2311
|
+
span.setAttribute("streaming", streaming);
|
|
2312
|
+
await seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode);
|
|
2313
|
+
if (debug)
|
|
2314
|
+
console.log(`[Setup] ${pathname} - seedModule: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
2315
|
+
});
|
|
2053
2316
|
resetSSRAccessTracking();
|
|
2054
2317
|
const bundlePreload = createBundlePreload(bundleUrl);
|
|
2055
|
-
const preloadResult = await
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2318
|
+
const preloadResult = await withSpan("ssr.preload", async (span) => {
|
|
2319
|
+
span.setAttribute("pathname", pathname);
|
|
2320
|
+
const result = await preloadContentModule(pathname, clientDir, cwd, isWatchMode);
|
|
2321
|
+
span.setAttribute("has_module", !!result.modulePath);
|
|
2322
|
+
if (debug)
|
|
2323
|
+
console.log(`[Setup] ${pathname} - preloadContent: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
2324
|
+
return result;
|
|
2325
|
+
});
|
|
2326
|
+
const computeResult = await withSpan("ssr.compute.data", async (span) => {
|
|
2327
|
+
span.setAttribute("pathname", pathname);
|
|
2328
|
+
span.setAttribute("streaming", streaming);
|
|
2329
|
+
const result = await computeSSRData(pathname, clientDir, cwd, isWatchMode, { streaming, maxAge }, searchParams);
|
|
2330
|
+
span.setAttribute("has_error", !!result.error);
|
|
2331
|
+
span.setAttribute("has_data", Object.keys(result.data).length > 0);
|
|
2332
|
+
if (debug)
|
|
2333
|
+
console.log(`[Setup] ${pathname} - computeSSRData: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
2334
|
+
return result;
|
|
2335
|
+
});
|
|
2061
2336
|
setGlobalSSRData(computeResult.data);
|
|
2062
2337
|
const usingCachedCollections = !!options.cachedCollections;
|
|
2063
|
-
const byCollectionForSSR =
|
|
2064
|
-
|
|
2065
|
-
|
|
2338
|
+
const byCollectionForSSR = await withSpan("ssr.load.collections", async (span) => {
|
|
2339
|
+
span.setAttribute("pathname", pathname);
|
|
2340
|
+
span.setAttribute("cached", usingCachedCollections);
|
|
2341
|
+
const collections = options.cachedCollections ? options.cachedCollections : await loadCollections(cwd, isWatchMode);
|
|
2342
|
+
span.setAttribute("collection_count", Object.keys(collections).length);
|
|
2343
|
+
if (debug)
|
|
2344
|
+
console.log(`[Setup] ${pathname} - loadCollections (cached: ${usingCachedCollections}): ${(performance.now() - t0).toFixed(2)}ms`);
|
|
2345
|
+
return collections;
|
|
2346
|
+
});
|
|
2066
2347
|
setGlobalCollections(byCollectionForSSR);
|
|
2067
2348
|
const usingCachedCSS = !!options.cachedTailwindCSS;
|
|
2068
|
-
const inlineStyleTag =
|
|
2069
|
-
|
|
2070
|
-
|
|
2349
|
+
const inlineStyleTag = await withSpan("ssr.inline.css", async (span) => {
|
|
2350
|
+
const css = options.cachedTailwindCSS ? options.cachedTailwindCSS : await inlineTailwindCSS(clientDir, !streaming, isWatchMode);
|
|
2351
|
+
span.setAttributes({
|
|
2352
|
+
"reroute.cached": usingCachedCSS,
|
|
2353
|
+
"reroute.css.size": css.length
|
|
2354
|
+
});
|
|
2355
|
+
if (debug)
|
|
2356
|
+
console.log(`[Setup] ${pathname} - inlineTailwindCSS (cached: ${usingCachedCSS}): ${(performance.now() - t0).toFixed(2)}ms`);
|
|
2357
|
+
return css;
|
|
2358
|
+
});
|
|
2071
2359
|
let statusOverride = preloadResult.statusOverride;
|
|
2072
2360
|
if (computeResult.statusContainer.value) {
|
|
2073
2361
|
statusOverride = computeResult.statusContainer.value;
|
|
2074
2362
|
}
|
|
2075
|
-
const metadataResult = await
|
|
2076
|
-
|
|
2077
|
-
|
|
2363
|
+
const metadataResult = await withSpan("ssr.extract.metadata", async (span) => {
|
|
2364
|
+
const result = await extractPageMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ogConfig);
|
|
2365
|
+
span.setAttributes({
|
|
2366
|
+
"reroute.pathname": pathname,
|
|
2367
|
+
"reroute.metadata.exists": !!result.perPageHead
|
|
2368
|
+
});
|
|
2369
|
+
if (debug)
|
|
2370
|
+
console.log(`[Setup] ${pathname} - extractMetadata: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
2371
|
+
return result;
|
|
2372
|
+
});
|
|
2078
2373
|
return {
|
|
2079
2374
|
ssrData: computeResult.data,
|
|
2080
2375
|
ssrError: computeResult.error,
|
|
@@ -2102,10 +2397,10 @@ function generateCollectionScripts(byCollectionForSSR) {
|
|
|
2102
2397
|
} catch {}
|
|
2103
2398
|
return "";
|
|
2104
2399
|
}
|
|
2105
|
-
function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScripts = "", preloadScript = "", bundleUrl = "", pathname = "") {
|
|
2400
|
+
function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScripts = "", preloadScript = "", bundleUrl = "", pathname = "", browserTelemetryConfig) {
|
|
2106
2401
|
let scripts = preloadScript;
|
|
2107
2402
|
scripts += collectionScripts;
|
|
2108
|
-
scripts += createDataScript(ssrData, isWatchMode ? ssrError : undefined, pathname);
|
|
2403
|
+
scripts += createDataScript(ssrData, isWatchMode ? ssrError : undefined, pathname, browserTelemetryConfig);
|
|
2109
2404
|
scripts += createFeedsScript();
|
|
2110
2405
|
scripts += createLlmsScript();
|
|
2111
2406
|
if (bundleUrl) {
|
|
@@ -2117,6 +2412,7 @@ function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScri
|
|
|
2117
2412
|
return scripts;
|
|
2118
2413
|
}
|
|
2119
2414
|
var init_setup = __esm(() => {
|
|
2415
|
+
init_server2();
|
|
2120
2416
|
init_collections();
|
|
2121
2417
|
init_compute();
|
|
2122
2418
|
init_metadata2();
|
|
@@ -2185,6 +2481,7 @@ async function renderSSRDocument(options) {
|
|
|
2185
2481
|
clientDir,
|
|
2186
2482
|
cwd,
|
|
2187
2483
|
isWatchMode,
|
|
2484
|
+
parentSpan: options.parentSpan,
|
|
2188
2485
|
bundleUrl,
|
|
2189
2486
|
maxAge,
|
|
2190
2487
|
searchParams,
|
|
@@ -2194,14 +2491,29 @@ async function renderSSRDocument(options) {
|
|
|
2194
2491
|
}, false);
|
|
2195
2492
|
const duplicatedData = duplicateQueryParamData(setup2.ssrData);
|
|
2196
2493
|
setGlobalSSRData(duplicatedData);
|
|
2197
|
-
const
|
|
2198
|
-
|
|
2199
|
-
|
|
2494
|
+
const appHtml = await withSpan("ssr.render.react", async (span) => {
|
|
2495
|
+
const componentWithPathname = cloneElement(rootComponent, {
|
|
2496
|
+
pathname,
|
|
2497
|
+
searchParams
|
|
2498
|
+
});
|
|
2499
|
+
span.setAttribute("reroute.pathname", pathname);
|
|
2500
|
+
const html3 = renderToString(componentWithPathname);
|
|
2501
|
+
span.setAttribute("reroute.html.final.size", html3.length);
|
|
2502
|
+
return html3;
|
|
2503
|
+
});
|
|
2504
|
+
const baseTemplate = await withSpan("ssr.load.template", async (span) => {
|
|
2505
|
+
const template2 = await loadIndexHtml(clientDir);
|
|
2506
|
+
span.setAttribute("reroute.template.size", template2.length);
|
|
2507
|
+
return template2;
|
|
2200
2508
|
});
|
|
2201
|
-
const appHtml = renderToString(componentWithPathname);
|
|
2202
|
-
const baseTemplate = await loadIndexHtml(clientDir);
|
|
2203
2509
|
const collectionScripts = generateCollectionScripts(setup2.byCollectionForSSR);
|
|
2204
|
-
const
|
|
2510
|
+
const config = await loadConfig(cwd);
|
|
2511
|
+
const browserTelemetryConfig = config.telemetry?.browser;
|
|
2512
|
+
const hydrationScript = await withSpan("ssr.generate.scripts", async (span) => {
|
|
2513
|
+
const script = generateHydrationScripts(setup2.ssrData, isWatchMode, setup2.ssrError, collectionScripts, setup2.preloadHydrationScript, bundleUrl, pathname, browserTelemetryConfig);
|
|
2514
|
+
span.setAttribute("reroute.scripts.size", script.length);
|
|
2515
|
+
return script;
|
|
2516
|
+
});
|
|
2205
2517
|
let statusOverride = setup2.preloadStatusOverride;
|
|
2206
2518
|
if (setup2.statusContainer.value) {
|
|
2207
2519
|
statusOverride = setup2.statusContainer.value;
|
|
@@ -2216,12 +2528,19 @@ async function renderSSRDocument(options) {
|
|
|
2216
2528
|
dedent(setup2.metadataResult.perPageHead)
|
|
2217
2529
|
].filter(Boolean).join(`
|
|
2218
2530
|
`));
|
|
2219
|
-
const html2 =
|
|
2220
|
-
|
|
2531
|
+
const html2 = withSpanSync("ssr.apply.template", (span) => {
|
|
2532
|
+
const result = applyIndexTemplate(baseTemplate, appHtml, {
|
|
2533
|
+
head: [setup2.inlineStyleTag, combinedHead].filter(Boolean).join(`
|
|
2221
2534
|
`),
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2535
|
+
hydrationScript,
|
|
2536
|
+
lang: setup2.metadataResult.pageLang || lang,
|
|
2537
|
+
appId
|
|
2538
|
+
});
|
|
2539
|
+
span.setAttributes({
|
|
2540
|
+
"reroute.html.final.size": result.length,
|
|
2541
|
+
"reroute.html.original.size": appHtml.length
|
|
2542
|
+
});
|
|
2543
|
+
return result;
|
|
2225
2544
|
});
|
|
2226
2545
|
return {
|
|
2227
2546
|
html: html2,
|
|
@@ -2229,6 +2548,8 @@ async function renderSSRDocument(options) {
|
|
|
2229
2548
|
};
|
|
2230
2549
|
}
|
|
2231
2550
|
var init_render = __esm(() => {
|
|
2551
|
+
init_server2();
|
|
2552
|
+
init_config();
|
|
2232
2553
|
init_lib();
|
|
2233
2554
|
init_html();
|
|
2234
2555
|
});
|
|
@@ -2857,366 +3178,44 @@ var init_index_generator = __esm(() => {
|
|
|
2857
3178
|
init_extractor();
|
|
2858
3179
|
});
|
|
2859
3180
|
|
|
2860
|
-
// packages/core/src/
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
discoverCollectionContent: () => discoverCollectionContent
|
|
2867
|
-
});
|
|
2868
|
-
async function loadRoutesModule2(cwd, isWatchMode) {
|
|
2869
|
-
let routes = globalThis.__REROUTE_ROUTES__;
|
|
2870
|
-
if (!routes) {
|
|
2871
|
-
const routesPath = join(cwd, ".reroute", "routes.ts");
|
|
2872
|
-
const url = Bun.pathToFileURL(routesPath).href;
|
|
2873
|
-
const mod = await import(`${url}${isWatchMode ? `?t=${Date.now()}` : ""}`);
|
|
2874
|
-
routes = mod?.routes;
|
|
3181
|
+
// packages/core/src/llms/full-generator.ts
|
|
3182
|
+
function buildHeader(baseUrl, llmsConfig) {
|
|
3183
|
+
const parts = [];
|
|
3184
|
+
if (llmsConfig?.siteName) {
|
|
3185
|
+
parts.push(`# ${llmsConfig.siteName}`);
|
|
3186
|
+
parts.push("");
|
|
2875
3187
|
}
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
return;
|
|
2886
|
-
const isDynamic = pattern.includes(":");
|
|
2887
|
-
const sitemapRoute = { path: path2, pattern, isDynamic };
|
|
2888
|
-
if (isDynamic) {
|
|
2889
|
-
dynamicRoutes.push(sitemapRoute);
|
|
2890
|
-
} else {
|
|
2891
|
-
staticRoutes.push(sitemapRoute);
|
|
3188
|
+
if (llmsConfig?.siteDescription) {
|
|
3189
|
+
parts.push(llmsConfig.siteDescription);
|
|
3190
|
+
parts.push("");
|
|
3191
|
+
}
|
|
3192
|
+
if (parts.length > 0) {
|
|
3193
|
+
parts.push(`${baseUrl}/index.txt`);
|
|
3194
|
+
parts.push("");
|
|
3195
|
+
parts.push("---");
|
|
3196
|
+
parts.push("");
|
|
2892
3197
|
}
|
|
3198
|
+
return parts;
|
|
2893
3199
|
}
|
|
2894
|
-
async function
|
|
2895
|
-
const
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
}
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
const exists = await Bun.file(collectionFile).exists();
|
|
2914
|
-
if (!exists) {
|
|
2915
|
-
return entries;
|
|
2916
|
-
}
|
|
2917
|
-
const url = `${Bun.pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ""}`;
|
|
2918
|
-
const mod = await import(url);
|
|
2919
|
-
const items = mod.items || [];
|
|
2920
|
-
for (const item of items) {
|
|
2921
|
-
const href = String(item.href || "");
|
|
2922
|
-
const meta = item.meta || {};
|
|
2923
|
-
if (href) {
|
|
2924
|
-
const entry = {
|
|
2925
|
-
loc: `${baseUrl}${href}`,
|
|
2926
|
-
lastmod: meta.date ? new Date(meta.date).toISOString() : undefined,
|
|
2927
|
-
changefreq: "weekly",
|
|
2928
|
-
priority: 0.7
|
|
2929
|
-
};
|
|
2930
|
-
entries.push(entry);
|
|
2931
|
-
}
|
|
2932
|
-
}
|
|
2933
|
-
} catch (error) {
|
|
2934
|
-
console.error(`[reroute] Failed to discover collection ${collection}:`, error);
|
|
2935
|
-
}
|
|
2936
|
-
return entries;
|
|
2937
|
-
}
|
|
2938
|
-
async function discoverSSRDataRoutes2(_cwd, clientDir, staticRoutes, isWatchMode, baseUrl, sitemapConfig) {
|
|
2939
|
-
const ssrDataRoutes = new Map;
|
|
2940
|
-
for (const route of staticRoutes) {
|
|
2941
|
-
if (sitemapConfig?.excludeDiscovery?.includes(route.pattern)) {
|
|
2942
|
-
continue;
|
|
2943
|
-
}
|
|
2944
|
-
try {
|
|
2945
|
-
const abs = join(clientDir, "routes", route.path);
|
|
2946
|
-
const mod = await import(Bun.pathToFileURL(abs).href + (isWatchMode ? `?t=${Date.now()}` : ""));
|
|
2947
|
-
const ssr = mod?.ssr;
|
|
2948
|
-
const dataFn = ssr?.data;
|
|
2949
|
-
if (typeof dataFn === "function") {
|
|
2950
|
-
const mockSet = { status: 200 };
|
|
2951
|
-
const result = await dataFn({
|
|
2952
|
-
pathname: route.pattern,
|
|
2953
|
-
params: {},
|
|
2954
|
-
set: mockSet
|
|
2955
|
-
});
|
|
2956
|
-
const entries = extractEntriesFromData(result, route.pattern, baseUrl, sitemapConfig);
|
|
2957
|
-
if (entries.length > 0) {
|
|
2958
|
-
ssrDataRoutes.set(route.pattern, entries);
|
|
2959
|
-
}
|
|
2960
|
-
}
|
|
2961
|
-
} catch {}
|
|
2962
|
-
}
|
|
2963
|
-
return ssrDataRoutes;
|
|
2964
|
-
}
|
|
2965
|
-
function findArraysInObject(obj) {
|
|
2966
|
-
const arrays = [];
|
|
2967
|
-
for (const value of Object.values(obj)) {
|
|
2968
|
-
if (Array.isArray(value)) {
|
|
2969
|
-
arrays.push(value);
|
|
2970
|
-
} else if (value && typeof value === "object") {
|
|
2971
|
-
arrays.push(...findArraysInObject(value));
|
|
2972
|
-
}
|
|
2973
|
-
}
|
|
2974
|
-
return arrays;
|
|
2975
|
-
}
|
|
2976
|
-
function processItemsToEntries(items, routePattern, baseUrl, sitemapConfig) {
|
|
2977
|
-
const entries = [];
|
|
2978
|
-
for (const item of items) {
|
|
2979
|
-
if (typeof item !== "object" || item === null)
|
|
2980
|
-
continue;
|
|
2981
|
-
const entry = createEntryFromItem(item, routePattern, baseUrl, sitemapConfig);
|
|
2982
|
-
if (entry) {
|
|
2983
|
-
entries.push(entry);
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
2986
|
-
return entries;
|
|
2987
|
-
}
|
|
2988
|
-
function extractWithCustomFunction(data, routePattern, baseUrl, sitemapConfig) {
|
|
2989
|
-
try {
|
|
2990
|
-
const items = sitemapConfig.extractUrls?.(data, routePattern);
|
|
2991
|
-
if (!Array.isArray(items))
|
|
2992
|
-
return [];
|
|
2993
|
-
return processItemsToEntries(items, routePattern, baseUrl, sitemapConfig);
|
|
2994
|
-
} catch (error) {
|
|
2995
|
-
console.warn("[reroute/sitemap] extractUrls failed:", error);
|
|
2996
|
-
return [];
|
|
2997
|
-
}
|
|
2998
|
-
}
|
|
2999
|
-
function extractWithAutoDiscovery(data, routePattern, baseUrl, sitemapConfig) {
|
|
3000
|
-
const entries = [];
|
|
3001
|
-
const arrays = findArraysInObject(data);
|
|
3002
|
-
for (const array of arrays) {
|
|
3003
|
-
if (array.length > 0) {
|
|
3004
|
-
const arrayEntries = processItemsToEntries(array, routePattern, baseUrl, sitemapConfig);
|
|
3005
|
-
entries.push(...arrayEntries);
|
|
3006
|
-
}
|
|
3007
|
-
}
|
|
3008
|
-
return entries;
|
|
3009
|
-
}
|
|
3010
|
-
function extractEntriesFromData(data, routePattern, baseUrl, sitemapConfig) {
|
|
3011
|
-
if (!data || typeof data !== "object") {
|
|
3012
|
-
return [];
|
|
3013
|
-
}
|
|
3014
|
-
if (sitemapConfig?.extractUrls) {
|
|
3015
|
-
return extractWithCustomFunction(data, routePattern, baseUrl, sitemapConfig);
|
|
3016
|
-
}
|
|
3017
|
-
return extractWithAutoDiscovery(data, routePattern, baseUrl, sitemapConfig);
|
|
3018
|
-
}
|
|
3019
|
-
function extractIdentifierFromItem(item, routePattern, sitemapConfig) {
|
|
3020
|
-
if (sitemapConfig?.extractUrl) {
|
|
3021
|
-
try {
|
|
3022
|
-
const identifier2 = sitemapConfig.extractUrl(item, routePattern);
|
|
3023
|
-
if (identifier2)
|
|
3024
|
-
return identifier2;
|
|
3025
|
-
} catch (error) {
|
|
3026
|
-
console.warn("[reroute/sitemap] extractUrl failed:", error);
|
|
3027
|
-
}
|
|
3028
|
-
}
|
|
3029
|
-
const identifier = item.version || item.slug || item.id || item.name || item.key;
|
|
3030
|
-
return identifier ? identifier : null;
|
|
3031
|
-
}
|
|
3032
|
-
function extractLastmodFromItem(item, sitemapConfig) {
|
|
3033
|
-
if (sitemapConfig?.extractLastmod) {
|
|
3034
|
-
try {
|
|
3035
|
-
const lastmod = sitemapConfig.extractLastmod(item);
|
|
3036
|
-
if (lastmod) {
|
|
3037
|
-
return new Date(lastmod).toISOString();
|
|
3038
|
-
}
|
|
3039
|
-
} catch (error) {
|
|
3040
|
-
console.warn("[reroute/sitemap] extractLastmod failed:", error);
|
|
3041
|
-
}
|
|
3042
|
-
}
|
|
3043
|
-
if (item.publishedAt && typeof item.publishedAt === "string") {
|
|
3044
|
-
return new Date(item.publishedAt).toISOString();
|
|
3045
|
-
}
|
|
3046
|
-
if (item.date && typeof item.date === "string") {
|
|
3047
|
-
return new Date(item.date).toISOString();
|
|
3048
|
-
}
|
|
3049
|
-
if (item.updatedAt && typeof item.updatedAt === "string") {
|
|
3050
|
-
return new Date(item.updatedAt).toISOString();
|
|
3051
|
-
}
|
|
3052
|
-
return;
|
|
3053
|
-
}
|
|
3054
|
-
function createEntryFromItem(item, routePattern, baseUrl, sitemapConfig) {
|
|
3055
|
-
const identifier = extractIdentifierFromItem(item, routePattern, sitemapConfig);
|
|
3056
|
-
if (!identifier) {
|
|
3057
|
-
return null;
|
|
3058
|
-
}
|
|
3059
|
-
const url = `${baseUrl}${routePattern}/${identifier}`;
|
|
3060
|
-
const entry = {
|
|
3061
|
-
loc: url,
|
|
3062
|
-
changefreq: sitemapConfig?.changefreq || "weekly",
|
|
3063
|
-
priority: sitemapConfig?.priority !== undefined ? sitemapConfig.priority : 0.6
|
|
3064
|
-
};
|
|
3065
|
-
const lastmod = extractLastmodFromItem(item, sitemapConfig);
|
|
3066
|
-
if (lastmod) {
|
|
3067
|
-
entry.lastmod = lastmod;
|
|
3068
|
-
}
|
|
3069
|
-
return entry;
|
|
3070
|
-
}
|
|
3071
|
-
async function discoverSitemapData(cwd, clientDir, collections2, baseUrl, isWatchMode, sitemapConfig) {
|
|
3072
|
-
const { staticRoutes, dynamicRoutes } = await discoverRoutes(cwd, isWatchMode);
|
|
3073
|
-
const collectionsMap = new Map;
|
|
3074
|
-
for (const collection of collections2) {
|
|
3075
|
-
const entries = await discoverCollectionContent(cwd, collection, isWatchMode, baseUrl);
|
|
3076
|
-
if (entries.length > 0) {
|
|
3077
|
-
collectionsMap.set(collection, entries);
|
|
3078
|
-
}
|
|
3079
|
-
}
|
|
3080
|
-
const ssrDataRoutes = await discoverSSRDataRoutes2(cwd, clientDir, staticRoutes, isWatchMode, baseUrl, sitemapConfig);
|
|
3081
|
-
return {
|
|
3082
|
-
staticRoutes,
|
|
3083
|
-
dynamicRoutes,
|
|
3084
|
-
collections: collectionsMap,
|
|
3085
|
-
ssrDataRoutes
|
|
3086
|
-
};
|
|
3087
|
-
}
|
|
3088
|
-
var init_discovery2 = () => {};
|
|
3089
|
-
|
|
3090
|
-
// packages/core/src/bundler/hash.ts
|
|
3091
|
-
async function generateContentHash(content) {
|
|
3092
|
-
const data = new TextEncoder().encode(content);
|
|
3093
|
-
const buf = await crypto.subtle.digest("SHA-256", data);
|
|
3094
|
-
let hex = "";
|
|
3095
|
-
for (const b of new Uint8Array(buf))
|
|
3096
|
-
hex += b.toString(16).padStart(2, "0");
|
|
3097
|
-
return hex.slice(0, 8);
|
|
3098
|
-
}
|
|
3099
|
-
// packages/core/src/config.ts
|
|
3100
|
-
import { pathToFileURL } from "node:url";
|
|
3101
|
-
function defineConfig(config) {
|
|
3102
|
-
return config;
|
|
3103
|
-
}
|
|
3104
|
-
async function loadConfig(cwd) {
|
|
3105
|
-
const bundledConfig = globalThis.__REROUTE_CONFIG__;
|
|
3106
|
-
if (bundledConfig) {
|
|
3107
|
-
return bundledConfig;
|
|
3108
|
-
}
|
|
3109
|
-
const configPath = `${cwd}/reroute.config.ts`;
|
|
3110
|
-
const configFile = Bun.file(configPath);
|
|
3111
|
-
if (!await configFile.exists()) {
|
|
3112
|
-
return {};
|
|
3113
|
-
}
|
|
3114
|
-
try {
|
|
3115
|
-
const mod = await import(`${pathToFileURL(configPath).href}?t=${Date.now()}`);
|
|
3116
|
-
return mod.default || mod;
|
|
3117
|
-
} catch (error) {
|
|
3118
|
-
console.warn("[reroute] Failed to load reroute.config.ts:", error);
|
|
3119
|
-
return {};
|
|
3120
|
-
}
|
|
3121
|
-
}
|
|
3122
|
-
// packages/core/src/content/discovery.ts
|
|
3123
|
-
import { readdir, stat } from "node:fs/promises";
|
|
3124
|
-
async function listContentFiles(dir, baseRel) {
|
|
3125
|
-
const out = [];
|
|
3126
|
-
try {
|
|
3127
|
-
const entries = await readdir(dir, { withFileTypes: true });
|
|
3128
|
-
for (const entry of entries) {
|
|
3129
|
-
const full = join(dir, entry.name);
|
|
3130
|
-
const rel = join(baseRel, entry.name);
|
|
3131
|
-
if (entry.isDirectory()) {
|
|
3132
|
-
const nested = await listContentFiles(full, rel);
|
|
3133
|
-
out.push(...nested);
|
|
3134
|
-
} else if (entry.isFile()) {
|
|
3135
|
-
if (/\.(tsx|ts)$/.test(entry.name) && !entry.name.startsWith("_")) {
|
|
3136
|
-
out.push(rel);
|
|
3137
|
-
}
|
|
3138
|
-
}
|
|
3139
|
-
}
|
|
3140
|
-
} catch {}
|
|
3141
|
-
return out;
|
|
3142
|
-
}
|
|
3143
|
-
async function discoverCollections(clientDir) {
|
|
3144
|
-
const collections = new Set;
|
|
3145
|
-
const bundledCollectionsDir = join(clientDir, "collections");
|
|
3146
|
-
try {
|
|
3147
|
-
const bundledEntries = await readdir(bundledCollectionsDir, {
|
|
3148
|
-
withFileTypes: true
|
|
3149
|
-
});
|
|
3150
|
-
for (const entry of bundledEntries) {
|
|
3151
|
-
if (entry.isFile() && entry.name.endsWith(".js")) {
|
|
3152
|
-
const collectionName = entry.name.replace(/\.js$/, "");
|
|
3153
|
-
collections.add(collectionName);
|
|
3154
|
-
}
|
|
3155
|
-
}
|
|
3156
|
-
if (collections.size > 0) {
|
|
3157
|
-
return Array.from(collections);
|
|
3158
|
-
}
|
|
3159
|
-
} catch {}
|
|
3160
|
-
const root = join(clientDir, "routes");
|
|
3161
|
-
try {
|
|
3162
|
-
const entries = await readdir(root, { withFileTypes: true });
|
|
3163
|
-
for (const entry of entries) {
|
|
3164
|
-
if (entry.isDirectory()) {
|
|
3165
|
-
const contentDir = join(root, entry.name, "content");
|
|
3166
|
-
try {
|
|
3167
|
-
await stat(contentDir);
|
|
3168
|
-
collections.add(entry.name);
|
|
3169
|
-
} catch {}
|
|
3170
|
-
}
|
|
3171
|
-
}
|
|
3172
|
-
} catch {}
|
|
3173
|
-
return Array.from(collections);
|
|
3174
|
-
}
|
|
3175
|
-
|
|
3176
|
-
// packages/core/src/content/index.ts
|
|
3177
|
-
init_metadata();
|
|
3178
|
-
// packages/core/src/llms/index.ts
|
|
3179
|
-
init_extractor();
|
|
3180
|
-
|
|
3181
|
-
// packages/core/src/llms/full-generator.ts
|
|
3182
|
-
init_extractor();
|
|
3183
|
-
function buildHeader(baseUrl, llmsConfig) {
|
|
3184
|
-
const parts = [];
|
|
3185
|
-
if (llmsConfig?.siteName) {
|
|
3186
|
-
parts.push(`# ${llmsConfig.siteName}`);
|
|
3187
|
-
parts.push("");
|
|
3188
|
-
}
|
|
3189
|
-
if (llmsConfig?.siteDescription) {
|
|
3190
|
-
parts.push(llmsConfig.siteDescription);
|
|
3191
|
-
parts.push("");
|
|
3192
|
-
}
|
|
3193
|
-
if (parts.length > 0) {
|
|
3194
|
-
parts.push(`${baseUrl}/index.txt`);
|
|
3195
|
-
parts.push("");
|
|
3196
|
-
parts.push("---");
|
|
3197
|
-
parts.push("");
|
|
3198
|
-
}
|
|
3199
|
-
return parts;
|
|
3200
|
-
}
|
|
3201
|
-
async function discoverAllRoutes(cwd, clientDir, collections2, isWatchMode, llmsConfig) {
|
|
3202
|
-
const {
|
|
3203
|
-
discoverStaticRoutes: discoverStaticRoutes2,
|
|
3204
|
-
discoverCollectionRoutes: discoverCollectionRoutes2,
|
|
3205
|
-
discoverSSRDataRoutes: discoverSSRDataRoutes2
|
|
3206
|
-
} = await Promise.resolve().then(() => (init_index_generator(), exports_index_generator));
|
|
3207
|
-
const staticRoutes = await discoverStaticRoutes2(cwd, isWatchMode);
|
|
3208
|
-
const collectionsMap = await discoverCollectionRoutes2(cwd, collections2, isWatchMode, llmsConfig);
|
|
3209
|
-
const ssrDataRoutes = await discoverSSRDataRoutes2(cwd, clientDir, staticRoutes, isWatchMode);
|
|
3210
|
-
const allRoutes = [];
|
|
3211
|
-
for (const route of staticRoutes) {
|
|
3212
|
-
if (!shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {
|
|
3213
|
-
allRoutes.push({ path: route.path });
|
|
3214
|
-
}
|
|
3215
|
-
}
|
|
3216
|
-
for (const [_collection, routes] of collectionsMap.entries()) {
|
|
3217
|
-
for (const route of routes) {
|
|
3218
|
-
if (!shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {
|
|
3219
|
-
allRoutes.push({ path: route.path });
|
|
3200
|
+
async function discoverAllRoutes(cwd, clientDir, collections2, isWatchMode, llmsConfig) {
|
|
3201
|
+
const {
|
|
3202
|
+
discoverStaticRoutes: discoverStaticRoutes2,
|
|
3203
|
+
discoverCollectionRoutes: discoverCollectionRoutes2,
|
|
3204
|
+
discoverSSRDataRoutes: discoverSSRDataRoutes2
|
|
3205
|
+
} = await Promise.resolve().then(() => (init_index_generator(), exports_index_generator));
|
|
3206
|
+
const staticRoutes = await discoverStaticRoutes2(cwd, isWatchMode);
|
|
3207
|
+
const collectionsMap = await discoverCollectionRoutes2(cwd, collections2, isWatchMode, llmsConfig);
|
|
3208
|
+
const ssrDataRoutes = await discoverSSRDataRoutes2(cwd, clientDir, staticRoutes, isWatchMode);
|
|
3209
|
+
const allRoutes = [];
|
|
3210
|
+
for (const route of staticRoutes) {
|
|
3211
|
+
if (!shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {
|
|
3212
|
+
allRoutes.push({ path: route.path });
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
for (const [_collection, routes] of collectionsMap.entries()) {
|
|
3216
|
+
for (const route of routes) {
|
|
3217
|
+
if (!shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {
|
|
3218
|
+
allRoutes.push({ path: route.path });
|
|
3220
3219
|
}
|
|
3221
3220
|
}
|
|
3222
3221
|
}
|
|
@@ -3312,12 +3311,16 @@ async function generateLLMsFullContent(options) {
|
|
|
3312
3311
|
stats: { itemCount: extracted.itemCount, byteSize }
|
|
3313
3312
|
};
|
|
3314
3313
|
}
|
|
3314
|
+
var init_full_generator = __esm(() => {
|
|
3315
|
+
init_extractor();
|
|
3316
|
+
});
|
|
3315
3317
|
|
|
3316
3318
|
// packages/core/src/llms/index.ts
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3319
|
+
var init_llms = __esm(() => {
|
|
3320
|
+
init_extractor();
|
|
3321
|
+
init_full_generator();
|
|
3322
|
+
init_index_generator();
|
|
3323
|
+
});
|
|
3321
3324
|
|
|
3322
3325
|
// packages/core/src/og/render.ts
|
|
3323
3326
|
import { createElement } from "react";
|
|
@@ -3417,6 +3420,15 @@ function DefaultOGTemplate({
|
|
|
3417
3420
|
}
|
|
3418
3421
|
}))));
|
|
3419
3422
|
}
|
|
3423
|
+
var init_render2 = () => {};
|
|
3424
|
+
|
|
3425
|
+
// packages/core/src/og/index.ts
|
|
3426
|
+
var init_og = __esm(() => {
|
|
3427
|
+
init_discovery2();
|
|
3428
|
+
init_meta();
|
|
3429
|
+
init_render2();
|
|
3430
|
+
});
|
|
3431
|
+
|
|
3420
3432
|
// packages/core/src/robots/discovery.ts
|
|
3421
3433
|
async function discoverRoutesForRobots(cwd, isWatchMode) {
|
|
3422
3434
|
const routes = [];
|
|
@@ -3467,6 +3479,8 @@ async function discoverRobotsData(cwd, isWatchMode, robotsConfig, sitemapConfig,
|
|
|
3467
3479
|
redirectSourcePaths
|
|
3468
3480
|
};
|
|
3469
3481
|
}
|
|
3482
|
+
var init_discovery3 = () => {};
|
|
3483
|
+
|
|
3470
3484
|
// packages/core/src/robots/generator.ts
|
|
3471
3485
|
function getEffectivePolicies(policies) {
|
|
3472
3486
|
if (policies.length > 0)
|
|
@@ -3491,125 +3505,366 @@ function addAllowDirectives(lines, policy) {
|
|
|
3491
3505
|
lines.push(`Allow: ${path2}`);
|
|
3492
3506
|
}
|
|
3493
3507
|
}
|
|
3494
|
-
function getDisallows(policy, autoDisallows) {
|
|
3495
|
-
const disallows = new Set(policy.disallow || []);
|
|
3496
|
-
if (policy.userAgent === "*") {
|
|
3497
|
-
for (const path2 of autoDisallows) {
|
|
3498
|
-
disallows.add(path2);
|
|
3508
|
+
function getDisallows(policy, autoDisallows) {
|
|
3509
|
+
const disallows = new Set(policy.disallow || []);
|
|
3510
|
+
if (policy.userAgent === "*") {
|
|
3511
|
+
for (const path2 of autoDisallows) {
|
|
3512
|
+
disallows.add(path2);
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
return disallows;
|
|
3516
|
+
}
|
|
3517
|
+
function addDisallowDirectives(lines, policy, autoDisallows) {
|
|
3518
|
+
const disallows = getDisallows(policy, autoDisallows);
|
|
3519
|
+
if (disallows.size > 0) {
|
|
3520
|
+
for (const path2 of Array.from(disallows).sort()) {
|
|
3521
|
+
lines.push(`Disallow: ${path2}`);
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
function addPolicyBlock(lines, policy, autoDisallows) {
|
|
3526
|
+
lines.push(`User-agent: ${policy.userAgent}`);
|
|
3527
|
+
addAllowDirectives(lines, policy);
|
|
3528
|
+
addDisallowDirectives(lines, policy, autoDisallows);
|
|
3529
|
+
if (policy.crawlDelay !== undefined) {
|
|
3530
|
+
lines.push(`Crawl-delay: ${policy.crawlDelay}`);
|
|
3531
|
+
}
|
|
3532
|
+
lines.push("");
|
|
3533
|
+
}
|
|
3534
|
+
function addGlobalCrawlDelay(lines, crawlDelay, effectivePolicies) {
|
|
3535
|
+
const hasWildcardCrawlDelay = effectivePolicies.some((p) => p.userAgent === "*" && p.crawlDelay !== undefined);
|
|
3536
|
+
if (crawlDelay !== undefined && !hasWildcardCrawlDelay) {
|
|
3537
|
+
lines.push(`Crawl-delay: ${crawlDelay}`);
|
|
3538
|
+
lines.push("");
|
|
3539
|
+
}
|
|
3540
|
+
}
|
|
3541
|
+
function addSitemapReference(lines, robotsConfig, sitemapEnabled) {
|
|
3542
|
+
if (robotsConfig.referenceSitemap !== false && sitemapEnabled && robotsConfig.baseUrl) {
|
|
3543
|
+
lines.push(`Sitemap: ${robotsConfig.baseUrl}/sitemap.xml`);
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
function generateRobots(discovery2, robotsConfig, sitemapEnabled) {
|
|
3547
|
+
const lines = [];
|
|
3548
|
+
const { policies = [], customRules, crawlDelay } = robotsConfig;
|
|
3549
|
+
const effectivePolicies = getEffectivePolicies(policies);
|
|
3550
|
+
const autoDisallows = getAutoDisallows(discovery2);
|
|
3551
|
+
for (const policy of effectivePolicies) {
|
|
3552
|
+
addPolicyBlock(lines, policy, autoDisallows);
|
|
3553
|
+
}
|
|
3554
|
+
addGlobalCrawlDelay(lines, crawlDelay, effectivePolicies);
|
|
3555
|
+
if (customRules) {
|
|
3556
|
+
lines.push(customRules.trim());
|
|
3557
|
+
lines.push("");
|
|
3558
|
+
}
|
|
3559
|
+
addSitemapReference(lines, robotsConfig, sitemapEnabled);
|
|
3560
|
+
return `${lines.join(`
|
|
3561
|
+
`).trim()}
|
|
3562
|
+
`;
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3565
|
+
// packages/core/src/robots/policies.ts
|
|
3566
|
+
function blockAICrawlers(crawlers) {
|
|
3567
|
+
const agents = crawlers || Object.values(AI_CRAWLERS);
|
|
3568
|
+
return agents.map((agent) => ({
|
|
3569
|
+
userAgent: agent,
|
|
3570
|
+
disallow: ["/"]
|
|
3571
|
+
}));
|
|
3572
|
+
}
|
|
3573
|
+
function allowAICrawlers(crawlers) {
|
|
3574
|
+
const agents = crawlers || Object.values(AI_CRAWLERS);
|
|
3575
|
+
return agents.map((agent) => ({
|
|
3576
|
+
userAgent: agent,
|
|
3577
|
+
allow: ["/"]
|
|
3578
|
+
}));
|
|
3579
|
+
}
|
|
3580
|
+
function blockAITrainingCrawlers() {
|
|
3581
|
+
const trainingCrawlers = [
|
|
3582
|
+
AI_CRAWLERS.GOOGLE_EXTENDED,
|
|
3583
|
+
AI_CRAWLERS.COMMON_CRAWL,
|
|
3584
|
+
AI_CRAWLERS.BYTEDANCE,
|
|
3585
|
+
AI_CRAWLERS.OMGILI
|
|
3586
|
+
];
|
|
3587
|
+
return trainingCrawlers.map((agent) => ({
|
|
3588
|
+
userAgent: agent,
|
|
3589
|
+
disallow: ["/"]
|
|
3590
|
+
}));
|
|
3591
|
+
}
|
|
3592
|
+
function allowSearchCrawlers(crawlers) {
|
|
3593
|
+
const agents = crawlers || Object.values(SEARCH_CRAWLERS);
|
|
3594
|
+
return agents.map((agent) => ({
|
|
3595
|
+
userAgent: agent,
|
|
3596
|
+
allow: ["/"]
|
|
3597
|
+
}));
|
|
3598
|
+
}
|
|
3599
|
+
function blockSearchCrawlers(crawlers) {
|
|
3600
|
+
const agents = crawlers || Object.values(SEARCH_CRAWLERS);
|
|
3601
|
+
return agents.map((agent) => ({
|
|
3602
|
+
userAgent: agent,
|
|
3603
|
+
disallow: ["/"]
|
|
3604
|
+
}));
|
|
3605
|
+
}
|
|
3606
|
+
var AI_CRAWLERS, SEARCH_CRAWLERS;
|
|
3607
|
+
var init_policies = __esm(() => {
|
|
3608
|
+
AI_CRAWLERS = {
|
|
3609
|
+
GPT: "GPTBot",
|
|
3610
|
+
CHATGPT: "ChatGPT-User",
|
|
3611
|
+
CLAUDE: "Claude-Web",
|
|
3612
|
+
ANTHROPIC: "anthropic-ai",
|
|
3613
|
+
COHERE: "cohere-ai",
|
|
3614
|
+
GOOGLE_EXTENDED: "Google-Extended",
|
|
3615
|
+
FACEBOOK: "FacebookBot",
|
|
3616
|
+
APPLE_EXTENDED: "Applebot-Extended",
|
|
3617
|
+
PERPLEXITY: "PerplexityBot",
|
|
3618
|
+
BYTEDANCE: "Bytespider",
|
|
3619
|
+
COMMON_CRAWL: "CCBot",
|
|
3620
|
+
OMGILI: "Omgilibot"
|
|
3621
|
+
};
|
|
3622
|
+
SEARCH_CRAWLERS = {
|
|
3623
|
+
GOOGLEBOT: "Googlebot",
|
|
3624
|
+
BINGBOT: "Bingbot",
|
|
3625
|
+
SLURP: "Slurp",
|
|
3626
|
+
DUCKDUCKBOT: "DuckDuckBot",
|
|
3627
|
+
BAIDUSPIDER: "Baiduspider",
|
|
3628
|
+
YANDEXBOT: "YandexBot"
|
|
3629
|
+
};
|
|
3630
|
+
});
|
|
3631
|
+
|
|
3632
|
+
// packages/core/src/robots/index.ts
|
|
3633
|
+
var init_robots = __esm(() => {
|
|
3634
|
+
init_discovery3();
|
|
3635
|
+
init_policies();
|
|
3636
|
+
});
|
|
3637
|
+
|
|
3638
|
+
// packages/core/src/sitemap/discovery.ts
|
|
3639
|
+
var exports_discovery = {};
|
|
3640
|
+
__export(exports_discovery, {
|
|
3641
|
+
discoverSitemapData: () => discoverSitemapData,
|
|
3642
|
+
discoverSSRDataRoutes: () => discoverSSRDataRoutes2,
|
|
3643
|
+
discoverRoutes: () => discoverRoutes,
|
|
3644
|
+
discoverCollectionContent: () => discoverCollectionContent
|
|
3645
|
+
});
|
|
3646
|
+
async function loadRoutesModule2(cwd, isWatchMode) {
|
|
3647
|
+
let routes = globalThis.__REROUTE_ROUTES__;
|
|
3648
|
+
if (!routes) {
|
|
3649
|
+
const routesPath = join(cwd, ".reroute", "routes.ts");
|
|
3650
|
+
const url = Bun.pathToFileURL(routesPath).href;
|
|
3651
|
+
const mod = await import(`${url}${isWatchMode ? `?t=${Date.now()}` : ""}`);
|
|
3652
|
+
routes = mod?.routes;
|
|
3653
|
+
}
|
|
3654
|
+
return routes;
|
|
3655
|
+
}
|
|
3656
|
+
function shouldSkipRoute(pattern) {
|
|
3657
|
+
return pattern.includes("[404]") || pattern.includes("[layout]") || pattern.includes("[skeleton]");
|
|
3658
|
+
}
|
|
3659
|
+
function categorizeRoute(route, staticRoutes, dynamicRoutes) {
|
|
3660
|
+
const pattern = String(route?.pattern || "");
|
|
3661
|
+
const path2 = String(route?.path || "");
|
|
3662
|
+
if (shouldSkipRoute(pattern))
|
|
3663
|
+
return;
|
|
3664
|
+
const isDynamic = pattern.includes(":");
|
|
3665
|
+
const sitemapRoute = { path: path2, pattern, isDynamic };
|
|
3666
|
+
if (isDynamic) {
|
|
3667
|
+
dynamicRoutes.push(sitemapRoute);
|
|
3668
|
+
} else {
|
|
3669
|
+
staticRoutes.push(sitemapRoute);
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
async function discoverRoutes(cwd, isWatchMode) {
|
|
3673
|
+
const staticRoutes = [];
|
|
3674
|
+
const dynamicRoutes = [];
|
|
3675
|
+
try {
|
|
3676
|
+
const routes = await loadRoutesModule2(cwd, isWatchMode);
|
|
3677
|
+
if (Array.isArray(routes)) {
|
|
3678
|
+
for (const route of routes) {
|
|
3679
|
+
categorizeRoute(route, staticRoutes, dynamicRoutes);
|
|
3680
|
+
}
|
|
3681
|
+
}
|
|
3682
|
+
} catch (error) {
|
|
3683
|
+
console.error("[reroute] Failed to discover routes for sitemap:", error);
|
|
3684
|
+
}
|
|
3685
|
+
return { staticRoutes, dynamicRoutes };
|
|
3686
|
+
}
|
|
3687
|
+
async function discoverCollectionContent(cwd, collection, isWatchMode, baseUrl) {
|
|
3688
|
+
const entries = [];
|
|
3689
|
+
try {
|
|
3690
|
+
const collectionFile = join(cwd, ".reroute", "collections", `${collection}.js`);
|
|
3691
|
+
const exists = await Bun.file(collectionFile).exists();
|
|
3692
|
+
if (!exists) {
|
|
3693
|
+
return entries;
|
|
3694
|
+
}
|
|
3695
|
+
const url = `${Bun.pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ""}`;
|
|
3696
|
+
const mod = await import(url);
|
|
3697
|
+
const items = mod.items || [];
|
|
3698
|
+
for (const item of items) {
|
|
3699
|
+
const href = String(item.href || "");
|
|
3700
|
+
const meta = item.meta || {};
|
|
3701
|
+
if (href) {
|
|
3702
|
+
const entry = {
|
|
3703
|
+
loc: `${baseUrl}${href}`,
|
|
3704
|
+
lastmod: meta.date ? new Date(meta.date).toISOString() : undefined,
|
|
3705
|
+
changefreq: "weekly",
|
|
3706
|
+
priority: 0.7
|
|
3707
|
+
};
|
|
3708
|
+
entries.push(entry);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
} catch (error) {
|
|
3712
|
+
console.error(`[reroute] Failed to discover collection ${collection}:`, error);
|
|
3713
|
+
}
|
|
3714
|
+
return entries;
|
|
3715
|
+
}
|
|
3716
|
+
async function discoverSSRDataRoutes2(_cwd, clientDir, staticRoutes, isWatchMode, baseUrl, sitemapConfig) {
|
|
3717
|
+
const ssrDataRoutes = new Map;
|
|
3718
|
+
for (const route of staticRoutes) {
|
|
3719
|
+
if (sitemapConfig?.excludeDiscovery?.includes(route.pattern)) {
|
|
3720
|
+
continue;
|
|
3721
|
+
}
|
|
3722
|
+
try {
|
|
3723
|
+
const abs = join(clientDir, "routes", route.path);
|
|
3724
|
+
const mod = await import(Bun.pathToFileURL(abs).href + (isWatchMode ? `?t=${Date.now()}` : ""));
|
|
3725
|
+
const ssr = mod?.ssr;
|
|
3726
|
+
const dataFn = ssr?.data;
|
|
3727
|
+
if (typeof dataFn === "function") {
|
|
3728
|
+
const mockSet = { status: 200 };
|
|
3729
|
+
const result = await dataFn({
|
|
3730
|
+
pathname: route.pattern,
|
|
3731
|
+
params: {},
|
|
3732
|
+
set: mockSet
|
|
3733
|
+
});
|
|
3734
|
+
const entries = extractEntriesFromData(result, route.pattern, baseUrl, sitemapConfig);
|
|
3735
|
+
if (entries.length > 0) {
|
|
3736
|
+
ssrDataRoutes.set(route.pattern, entries);
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
} catch {}
|
|
3740
|
+
}
|
|
3741
|
+
return ssrDataRoutes;
|
|
3742
|
+
}
|
|
3743
|
+
function findArraysInObject(obj) {
|
|
3744
|
+
const arrays = [];
|
|
3745
|
+
for (const value of Object.values(obj)) {
|
|
3746
|
+
if (Array.isArray(value)) {
|
|
3747
|
+
arrays.push(value);
|
|
3748
|
+
} else if (value && typeof value === "object") {
|
|
3749
|
+
arrays.push(...findArraysInObject(value));
|
|
3499
3750
|
}
|
|
3500
3751
|
}
|
|
3501
|
-
return
|
|
3752
|
+
return arrays;
|
|
3502
3753
|
}
|
|
3503
|
-
function
|
|
3504
|
-
const
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3754
|
+
function processItemsToEntries(items, routePattern, baseUrl, sitemapConfig) {
|
|
3755
|
+
const entries = [];
|
|
3756
|
+
for (const item of items) {
|
|
3757
|
+
if (typeof item !== "object" || item === null)
|
|
3758
|
+
continue;
|
|
3759
|
+
const entry = createEntryFromItem(item, routePattern, baseUrl, sitemapConfig);
|
|
3760
|
+
if (entry) {
|
|
3761
|
+
entries.push(entry);
|
|
3508
3762
|
}
|
|
3509
3763
|
}
|
|
3764
|
+
return entries;
|
|
3510
3765
|
}
|
|
3511
|
-
function
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
}
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
function addGlobalCrawlDelay(lines, crawlDelay, effectivePolicies) {
|
|
3521
|
-
const hasWildcardCrawlDelay = effectivePolicies.some((p) => p.userAgent === "*" && p.crawlDelay !== undefined);
|
|
3522
|
-
if (crawlDelay !== undefined && !hasWildcardCrawlDelay) {
|
|
3523
|
-
lines.push(`Crawl-delay: ${crawlDelay}`);
|
|
3524
|
-
lines.push("");
|
|
3766
|
+
function extractWithCustomFunction(data, routePattern, baseUrl, sitemapConfig) {
|
|
3767
|
+
try {
|
|
3768
|
+
const items = sitemapConfig.extractUrls?.(data, routePattern);
|
|
3769
|
+
if (!Array.isArray(items))
|
|
3770
|
+
return [];
|
|
3771
|
+
return processItemsToEntries(items, routePattern, baseUrl, sitemapConfig);
|
|
3772
|
+
} catch (error) {
|
|
3773
|
+
console.warn("[reroute/sitemap] extractUrls failed:", error);
|
|
3774
|
+
return [];
|
|
3525
3775
|
}
|
|
3526
3776
|
}
|
|
3527
|
-
function
|
|
3528
|
-
|
|
3529
|
-
|
|
3777
|
+
function extractWithAutoDiscovery(data, routePattern, baseUrl, sitemapConfig) {
|
|
3778
|
+
const entries = [];
|
|
3779
|
+
const arrays = findArraysInObject(data);
|
|
3780
|
+
for (const array of arrays) {
|
|
3781
|
+
if (array.length > 0) {
|
|
3782
|
+
const arrayEntries = processItemsToEntries(array, routePattern, baseUrl, sitemapConfig);
|
|
3783
|
+
entries.push(...arrayEntries);
|
|
3784
|
+
}
|
|
3530
3785
|
}
|
|
3786
|
+
return entries;
|
|
3531
3787
|
}
|
|
3532
|
-
function
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
const effectivePolicies = getEffectivePolicies(policies);
|
|
3536
|
-
const autoDisallows = getAutoDisallows(discovery2);
|
|
3537
|
-
for (const policy of effectivePolicies) {
|
|
3538
|
-
addPolicyBlock(lines, policy, autoDisallows);
|
|
3788
|
+
function extractEntriesFromData(data, routePattern, baseUrl, sitemapConfig) {
|
|
3789
|
+
if (!data || typeof data !== "object") {
|
|
3790
|
+
return [];
|
|
3539
3791
|
}
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
lines.push(customRules.trim());
|
|
3543
|
-
lines.push("");
|
|
3792
|
+
if (sitemapConfig?.extractUrls) {
|
|
3793
|
+
return extractWithCustomFunction(data, routePattern, baseUrl, sitemapConfig);
|
|
3544
3794
|
}
|
|
3545
|
-
|
|
3546
|
-
return `${lines.join(`
|
|
3547
|
-
`).trim()}
|
|
3548
|
-
`;
|
|
3549
|
-
}
|
|
3550
|
-
// packages/core/src/robots/policies.ts
|
|
3551
|
-
var AI_CRAWLERS = {
|
|
3552
|
-
GPT: "GPTBot",
|
|
3553
|
-
CHATGPT: "ChatGPT-User",
|
|
3554
|
-
CLAUDE: "Claude-Web",
|
|
3555
|
-
ANTHROPIC: "anthropic-ai",
|
|
3556
|
-
COHERE: "cohere-ai",
|
|
3557
|
-
GOOGLE_EXTENDED: "Google-Extended",
|
|
3558
|
-
FACEBOOK: "FacebookBot",
|
|
3559
|
-
APPLE_EXTENDED: "Applebot-Extended",
|
|
3560
|
-
PERPLEXITY: "PerplexityBot",
|
|
3561
|
-
BYTEDANCE: "Bytespider",
|
|
3562
|
-
COMMON_CRAWL: "CCBot",
|
|
3563
|
-
OMGILI: "Omgilibot"
|
|
3564
|
-
};
|
|
3565
|
-
var SEARCH_CRAWLERS = {
|
|
3566
|
-
GOOGLEBOT: "Googlebot",
|
|
3567
|
-
BINGBOT: "Bingbot",
|
|
3568
|
-
SLURP: "Slurp",
|
|
3569
|
-
DUCKDUCKBOT: "DuckDuckBot",
|
|
3570
|
-
BAIDUSPIDER: "Baiduspider",
|
|
3571
|
-
YANDEXBOT: "YandexBot"
|
|
3572
|
-
};
|
|
3573
|
-
function blockAICrawlers(crawlers) {
|
|
3574
|
-
const agents = crawlers || Object.values(AI_CRAWLERS);
|
|
3575
|
-
return agents.map((agent) => ({
|
|
3576
|
-
userAgent: agent,
|
|
3577
|
-
disallow: ["/"]
|
|
3578
|
-
}));
|
|
3795
|
+
return extractWithAutoDiscovery(data, routePattern, baseUrl, sitemapConfig);
|
|
3579
3796
|
}
|
|
3580
|
-
function
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3797
|
+
function extractIdentifierFromItem(item, routePattern, sitemapConfig) {
|
|
3798
|
+
if (sitemapConfig?.extractUrl) {
|
|
3799
|
+
try {
|
|
3800
|
+
const identifier2 = sitemapConfig.extractUrl(item, routePattern);
|
|
3801
|
+
if (identifier2)
|
|
3802
|
+
return identifier2;
|
|
3803
|
+
} catch (error) {
|
|
3804
|
+
console.warn("[reroute/sitemap] extractUrl failed:", error);
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
const identifier = item.version || item.slug || item.id || item.name || item.key;
|
|
3808
|
+
return identifier ? identifier : null;
|
|
3586
3809
|
}
|
|
3587
|
-
function
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
}
|
|
3810
|
+
function extractLastmodFromItem(item, sitemapConfig) {
|
|
3811
|
+
if (sitemapConfig?.extractLastmod) {
|
|
3812
|
+
try {
|
|
3813
|
+
const lastmod = sitemapConfig.extractLastmod(item);
|
|
3814
|
+
if (lastmod) {
|
|
3815
|
+
return new Date(lastmod).toISOString();
|
|
3816
|
+
}
|
|
3817
|
+
} catch (error) {
|
|
3818
|
+
console.warn("[reroute/sitemap] extractLastmod failed:", error);
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
if (item.publishedAt && typeof item.publishedAt === "string") {
|
|
3822
|
+
return new Date(item.publishedAt).toISOString();
|
|
3823
|
+
}
|
|
3824
|
+
if (item.date && typeof item.date === "string") {
|
|
3825
|
+
return new Date(item.date).toISOString();
|
|
3826
|
+
}
|
|
3827
|
+
if (item.updatedAt && typeof item.updatedAt === "string") {
|
|
3828
|
+
return new Date(item.updatedAt).toISOString();
|
|
3829
|
+
}
|
|
3830
|
+
return;
|
|
3598
3831
|
}
|
|
3599
|
-
function
|
|
3600
|
-
const
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
}
|
|
3832
|
+
function createEntryFromItem(item, routePattern, baseUrl, sitemapConfig) {
|
|
3833
|
+
const identifier = extractIdentifierFromItem(item, routePattern, sitemapConfig);
|
|
3834
|
+
if (!identifier) {
|
|
3835
|
+
return null;
|
|
3836
|
+
}
|
|
3837
|
+
const url = `${baseUrl}${routePattern}/${identifier}`;
|
|
3838
|
+
const entry = {
|
|
3839
|
+
loc: url,
|
|
3840
|
+
changefreq: sitemapConfig?.changefreq || "weekly",
|
|
3841
|
+
priority: sitemapConfig?.priority !== undefined ? sitemapConfig.priority : 0.6
|
|
3842
|
+
};
|
|
3843
|
+
const lastmod = extractLastmodFromItem(item, sitemapConfig);
|
|
3844
|
+
if (lastmod) {
|
|
3845
|
+
entry.lastmod = lastmod;
|
|
3846
|
+
}
|
|
3847
|
+
return entry;
|
|
3605
3848
|
}
|
|
3606
|
-
function
|
|
3607
|
-
const
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3849
|
+
async function discoverSitemapData(cwd, clientDir, collections2, baseUrl, isWatchMode, sitemapConfig) {
|
|
3850
|
+
const { staticRoutes, dynamicRoutes } = await discoverRoutes(cwd, isWatchMode);
|
|
3851
|
+
const collectionsMap = new Map;
|
|
3852
|
+
for (const collection of collections2) {
|
|
3853
|
+
const entries = await discoverCollectionContent(cwd, collection, isWatchMode, baseUrl);
|
|
3854
|
+
if (entries.length > 0) {
|
|
3855
|
+
collectionsMap.set(collection, entries);
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
const ssrDataRoutes = await discoverSSRDataRoutes2(cwd, clientDir, staticRoutes, isWatchMode, baseUrl, sitemapConfig);
|
|
3859
|
+
return {
|
|
3860
|
+
staticRoutes,
|
|
3861
|
+
dynamicRoutes,
|
|
3862
|
+
collections: collectionsMap,
|
|
3863
|
+
ssrDataRoutes
|
|
3864
|
+
};
|
|
3612
3865
|
}
|
|
3866
|
+
var init_discovery4 = () => {};
|
|
3867
|
+
|
|
3613
3868
|
// packages/core/src/rss/discovery.ts
|
|
3614
3869
|
import { pathToFileURL as pathToFileURL7 } from "node:url";
|
|
3615
3870
|
function extractDescription(meta, rssConfig) {
|
|
@@ -3863,7 +4118,7 @@ async function discoverRSSData(cwd, clientDir, collections2, baseUrl, isWatchMod
|
|
|
3863
4118
|
}
|
|
3864
4119
|
}
|
|
3865
4120
|
const ssrDataFeeds = new Map;
|
|
3866
|
-
const { discoverRoutes: discoverRoutes2 } = await Promise.resolve().then(() => (
|
|
4121
|
+
const { discoverRoutes: discoverRoutes2 } = await Promise.resolve().then(() => (init_discovery4(), exports_discovery));
|
|
3867
4122
|
const { staticRoutes } = await discoverRoutes2(cwd, isWatchMode);
|
|
3868
4123
|
for (const route of staticRoutes) {
|
|
3869
4124
|
if (rssConfig?.excludeDiscovery?.includes(route.pattern)) {
|
|
@@ -3937,6 +4192,8 @@ async function discoverLayoutFeedItems(cwd, clientDir, isWatchMode, baseUrl, rss
|
|
|
3937
4192
|
}
|
|
3938
4193
|
return layoutFeeds;
|
|
3939
4194
|
}
|
|
4195
|
+
var init_discovery5 = () => {};
|
|
4196
|
+
|
|
3940
4197
|
// packages/core/src/rss/generator.ts
|
|
3941
4198
|
function generateRSSXML(feed, options = {}) {
|
|
3942
4199
|
const { limit } = options;
|
|
@@ -4045,11 +4302,13 @@ function generateFeed(feed, options = {}) {
|
|
|
4045
4302
|
function escapeXml(unsafe) {
|
|
4046
4303
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4047
4304
|
}
|
|
4048
|
-
|
|
4049
|
-
|
|
4305
|
+
|
|
4306
|
+
// packages/core/src/rss/index.ts
|
|
4307
|
+
var init_rss = __esm(() => {
|
|
4308
|
+
init_discovery5();
|
|
4309
|
+
});
|
|
4050
4310
|
|
|
4051
4311
|
// packages/core/src/sitemap/generator.ts
|
|
4052
|
-
var DEFAULT_MAX_URLS = 50000;
|
|
4053
4312
|
function normalizeRouteLocation(loc) {
|
|
4054
4313
|
if (loc === "/index") {
|
|
4055
4314
|
return "/";
|
|
@@ -4182,14 +4441,16 @@ ${sitemapEntries}
|
|
|
4182
4441
|
function escapeXml2(unsafe) {
|
|
4183
4442
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4184
4443
|
}
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4444
|
+
var DEFAULT_MAX_URLS = 50000;
|
|
4445
|
+
var init_generator = () => {};
|
|
4446
|
+
|
|
4447
|
+
// packages/core/src/sitemap/index.ts
|
|
4448
|
+
var init_sitemap = __esm(() => {
|
|
4449
|
+
init_discovery4();
|
|
4450
|
+
init_generator();
|
|
4451
|
+
});
|
|
4188
4452
|
|
|
4189
4453
|
// packages/core/src/ssr/stream.ts
|
|
4190
|
-
init_lib();
|
|
4191
|
-
init_html();
|
|
4192
|
-
init_imports();
|
|
4193
4454
|
import { cloneElement as cloneElement2 } from "react";
|
|
4194
4455
|
import { renderToReadableStream } from "react-dom/server";
|
|
4195
4456
|
async function renderSSRDocumentStream(options) {
|
|
@@ -4216,6 +4477,7 @@ async function renderSSRDocumentStream(options) {
|
|
|
4216
4477
|
clientDir,
|
|
4217
4478
|
cwd,
|
|
4218
4479
|
isWatchMode,
|
|
4480
|
+
parentSpan: options.parentSpan,
|
|
4219
4481
|
bundleUrl,
|
|
4220
4482
|
maxAge,
|
|
4221
4483
|
searchParams,
|
|
@@ -4237,14 +4499,19 @@ async function renderSSRDocumentStream(options) {
|
|
|
4237
4499
|
const { readable, writable } = new TransformStream;
|
|
4238
4500
|
const writer = writable.getWriter();
|
|
4239
4501
|
const usingCache = !!options.cachedIndexHtml;
|
|
4240
|
-
const
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4502
|
+
const { htmlHead, rootStart, rootEnd, htmlTail } = await withSpan("ssr.load.template", async (span) => {
|
|
4503
|
+
const template2 = options.cachedIndexHtml ? options.cachedIndexHtml : await loadIndexHtml(clientDir);
|
|
4504
|
+
span.setAttribute("reroute.cached", usingCache);
|
|
4505
|
+
span.setAttribute("reroute.template.size", template2.length);
|
|
4506
|
+
if (debug)
|
|
4507
|
+
console.log(`[renderStream] ${pathname} - loadIndexHtml (cached: ${usingCache}): ${(performance.now() - t0).toFixed(2)}ms`);
|
|
4508
|
+
const parts = splitTemplate(template2, appId);
|
|
4509
|
+
if (debug)
|
|
4510
|
+
console.log(`[renderStream] ${pathname} - splitTemplate: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
4511
|
+
return {
|
|
4512
|
+
...parts
|
|
4513
|
+
};
|
|
4514
|
+
});
|
|
4248
4515
|
const pageLang = setup2.metadataResult.pageLang || lang;
|
|
4249
4516
|
let headWithLang = htmlHead.replace(/<html([^>]*)>/i, `<html$1 lang="${pageLang}">`);
|
|
4250
4517
|
const extraHead = setup2.bundlePreload + setup2.preloadExtraHead + setup2.metadataResult.perPageHead;
|
|
@@ -4254,6 +4521,8 @@ async function renderSSRDocumentStream(options) {
|
|
|
4254
4521
|
if (/<meta\s+name\s*=\s*['"]description['"][^>]*>/i.test(extraHead)) {
|
|
4255
4522
|
headWithLang = headWithLang.replace(/<meta\s+name\s*=\s*['"]description['"][^>]*>/i, "");
|
|
4256
4523
|
}
|
|
4524
|
+
const config = await loadConfig(cwd);
|
|
4525
|
+
const browserTelemetryConfig = config.telemetry?.browser;
|
|
4257
4526
|
streamSSRContent(writer, encoder, {
|
|
4258
4527
|
rootComponent,
|
|
4259
4528
|
pathname,
|
|
@@ -4272,82 +4541,102 @@ async function renderSSRDocumentStream(options) {
|
|
|
4272
4541
|
ssrData: setup2.ssrData,
|
|
4273
4542
|
ssrError: setup2.ssrError,
|
|
4274
4543
|
byCollectionForSSR: setup2.byCollectionForSSR,
|
|
4275
|
-
preloadHydrationScript: setup2.preloadHydrationScript
|
|
4544
|
+
preloadHydrationScript: setup2.preloadHydrationScript,
|
|
4545
|
+
browserTelemetryConfig,
|
|
4546
|
+
parentSpan: options.parentSpan
|
|
4276
4547
|
});
|
|
4277
4548
|
if (debug)
|
|
4278
4549
|
console.log(`[renderStream] ${pathname} - returning stream: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
4279
4550
|
return { stream: readable, status: statusOverride || 200 };
|
|
4280
4551
|
}
|
|
4281
4552
|
async function streamSSRContent(writer, encoder, ctx) {
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4553
|
+
return withParentSpan(ctx.parentSpan, async () => {
|
|
4554
|
+
const t0 = ctx.debug ? performance.now() : 0;
|
|
4555
|
+
const STREAM_TIMEOUT_MS = 60000;
|
|
4556
|
+
let streamTimedOut = false;
|
|
4557
|
+
let timeoutId = null;
|
|
4558
|
+
const cleanup = () => {
|
|
4559
|
+
if (timeoutId) {
|
|
4560
|
+
clearTimeout(timeoutId);
|
|
4561
|
+
timeoutId = null;
|
|
4562
|
+
}
|
|
4563
|
+
};
|
|
4564
|
+
try {
|
|
4565
|
+
const combinedHead = deduplicateMetaTags([ctx.inlineStyleTag, ctx.head, ctx.extraHead].filter(Boolean).join(`
|
|
4294
4566
|
`));
|
|
4295
|
-
|
|
4567
|
+
const headWithLangAndContent = ctx.headWithLang.replace(/<html([^>]*)>/i, `<html$1 lang="${ctx.pageLang}">`).replace(/<\/head>/i, `${combinedHead ? `${combinedHead}
|
|
4296
4568
|
` : ""}</head>`);
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4569
|
+
const headContent = `${headWithLangAndContent}<body>`;
|
|
4570
|
+
await writer.write(encoder.encode(headContent));
|
|
4571
|
+
if (ctx.debug)
|
|
4572
|
+
console.log(`[Stream] ${ctx.pathname} - first byte written: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
4573
|
+
await writer.write(encoder.encode(ctx.rootStart));
|
|
4574
|
+
await withSpan("ssr.document.stream", async (span) => {
|
|
4575
|
+
const componentWithPathname = cloneElement2(ctx.rootComponent, {
|
|
4576
|
+
pathname: ctx.pathname,
|
|
4577
|
+
searchParams: ctx.searchParams
|
|
4578
|
+
});
|
|
4579
|
+
span.setAttribute("reroute.pathname", ctx.pathname);
|
|
4580
|
+
let streamError = null;
|
|
4581
|
+
const streamPromise = renderToReadableStream(componentWithPathname, {
|
|
4582
|
+
onError(error) {
|
|
4583
|
+
console.error("[reroute] SSR stream error:", error);
|
|
4584
|
+
streamError = error instanceof Error ? error : new Error(String(error));
|
|
4585
|
+
}
|
|
4586
|
+
}).catch((err) => {
|
|
4587
|
+
streamError = err;
|
|
4588
|
+
throw err;
|
|
4589
|
+
});
|
|
4590
|
+
const reactStream = await streamPromise;
|
|
4591
|
+
if (streamError)
|
|
4592
|
+
throw streamError;
|
|
4593
|
+
const streamTimeoutPromise = new Promise((resolve) => {
|
|
4594
|
+
timeoutId = setTimeout(() => {
|
|
4595
|
+
console.warn(`[reroute] Stream timeout after ${STREAM_TIMEOUT_MS}ms for ${ctx.pathname}, forcing close`);
|
|
4596
|
+
streamTimedOut = true;
|
|
4597
|
+
resolve({ done: true, value: undefined });
|
|
4598
|
+
}, STREAM_TIMEOUT_MS);
|
|
4599
|
+
});
|
|
4600
|
+
const reader = reactStream.getReader();
|
|
4601
|
+
let chunkCount = 0;
|
|
4602
|
+
while (true) {
|
|
4603
|
+
const result = await Promise.race([
|
|
4604
|
+
reader.read(),
|
|
4605
|
+
streamTimeoutPromise
|
|
4606
|
+
]);
|
|
4607
|
+
if (result.done || streamTimedOut) {
|
|
4608
|
+
try {
|
|
4609
|
+
reader.releaseLock();
|
|
4610
|
+
} catch {}
|
|
4611
|
+
break;
|
|
4612
|
+
}
|
|
4613
|
+
if (result.value) {
|
|
4614
|
+
await writer.write(result.value);
|
|
4615
|
+
chunkCount++;
|
|
4616
|
+
}
|
|
4617
|
+
}
|
|
4618
|
+
cleanup();
|
|
4619
|
+
span.setAttributes({
|
|
4620
|
+
"reroute.stream.chunks": chunkCount,
|
|
4621
|
+
"reroute.stream.timedOut": streamTimedOut
|
|
4622
|
+
});
|
|
4623
|
+
});
|
|
4624
|
+
await writer.write(encoder.encode(ctx.rootEnd));
|
|
4625
|
+
const allScripts = await withSpan("ssr.generate.scripts", async (span) => {
|
|
4626
|
+
const scripts2 = buildStreamingScripts(ctx);
|
|
4627
|
+
span.setAttribute("reroute.script_size", scripts2.length);
|
|
4628
|
+
return scripts2;
|
|
4629
|
+
});
|
|
4630
|
+
await writer.write(encoder.encode(allScripts + ctx.htmlTail));
|
|
4631
|
+
await writer.close();
|
|
4632
|
+
} catch (error) {
|
|
4633
|
+
cleanup();
|
|
4634
|
+
console.error("[reroute] Stream error:", error);
|
|
4635
|
+
try {
|
|
4636
|
+
await writer.abort(error);
|
|
4637
|
+
} catch {}
|
|
4338
4638
|
}
|
|
4339
|
-
|
|
4340
|
-
await writer.write(encoder.encode(ctx.rootEnd));
|
|
4341
|
-
const allScripts = buildStreamingScripts(ctx);
|
|
4342
|
-
await writer.write(encoder.encode(allScripts + ctx.htmlTail));
|
|
4343
|
-
await writer.close();
|
|
4344
|
-
} catch (error) {
|
|
4345
|
-
cleanup();
|
|
4346
|
-
console.error("[reroute] Stream error:", error);
|
|
4347
|
-
try {
|
|
4348
|
-
await writer.abort(error);
|
|
4349
|
-
} catch {}
|
|
4350
|
-
}
|
|
4639
|
+
});
|
|
4351
4640
|
}
|
|
4352
4641
|
function buildStreamingScripts(ctx) {
|
|
4353
4642
|
const collectionScripts = generateCollectionScripts(ctx.byCollectionForSSR);
|
|
@@ -4358,7 +4647,7 @@ function buildStreamingScripts(ctx) {
|
|
|
4358
4647
|
ssrDataSnapshot[key] = value;
|
|
4359
4648
|
}
|
|
4360
4649
|
}
|
|
4361
|
-
const dataScript = createDataScript(ssrDataSnapshot, ctx.isWatchMode ? ctx.ssrError : undefined, ctx.pathname);
|
|
4650
|
+
const dataScript = createDataScript(ssrDataSnapshot, ctx.isWatchMode ? ctx.ssrError : undefined, ctx.pathname, ctx.browserTelemetryConfig);
|
|
4362
4651
|
const feedsScript = createFeedsScript();
|
|
4363
4652
|
const llmsScript = createLlmsScript();
|
|
4364
4653
|
let allScripts = dataScript + feedsScript + llmsScript + collectionScripts + ctx.preloadHydrationScript;
|
|
@@ -4368,6 +4657,40 @@ function buildStreamingScripts(ctx) {
|
|
|
4368
4657
|
}
|
|
4369
4658
|
return allScripts;
|
|
4370
4659
|
}
|
|
4660
|
+
var init_stream = __esm(() => {
|
|
4661
|
+
init_server2();
|
|
4662
|
+
init_config();
|
|
4663
|
+
init_lib();
|
|
4664
|
+
init_html();
|
|
4665
|
+
init_imports();
|
|
4666
|
+
});
|
|
4667
|
+
|
|
4668
|
+
// packages/core/src/ssr/index.ts
|
|
4669
|
+
var init_ssr = __esm(() => {
|
|
4670
|
+
init_lib();
|
|
4671
|
+
init_render();
|
|
4672
|
+
init_stream();
|
|
4673
|
+
});
|
|
4674
|
+
|
|
4675
|
+
// packages/core/src/index.ts
|
|
4676
|
+
var init_src = __esm(() => {
|
|
4677
|
+
init_bundler();
|
|
4678
|
+
init_config();
|
|
4679
|
+
init_content();
|
|
4680
|
+
init_llms();
|
|
4681
|
+
init_og();
|
|
4682
|
+
init_robots();
|
|
4683
|
+
init_rss();
|
|
4684
|
+
init_sitemap();
|
|
4685
|
+
init_ssr();
|
|
4686
|
+
});
|
|
4687
|
+
|
|
4688
|
+
// packages/core/index.ts
|
|
4689
|
+
var init_core = __esm(() => {
|
|
4690
|
+
init_src();
|
|
4691
|
+
});
|
|
4692
|
+
init_core();
|
|
4693
|
+
|
|
4371
4694
|
export {
|
|
4372
4695
|
toPromise,
|
|
4373
4696
|
toBytes,
|
|
@@ -4475,4 +4798,4 @@ export {
|
|
|
4475
4798
|
AI_CRAWLERS
|
|
4476
4799
|
};
|
|
4477
4800
|
|
|
4478
|
-
//# debugId=
|
|
4801
|
+
//# debugId=3D165410A6034F1E64756E2164756E21
|