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.
Files changed (197) hide show
  1. package/README.md +150 -52
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +446 -150
  4. package/cli/bin.js.map +13 -9
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +4 -4
  7. package/cli/index.js.map +1 -1
  8. package/cli/src/cli.d.ts +1 -1
  9. package/cli/src/commands/analyze.d.ts +1 -1
  10. package/cli/src/commands/build.d.ts +1 -1
  11. package/cli/src/commands/dev.d.ts +1 -1
  12. package/cli/src/commands/gen.d.ts +1 -1
  13. package/cli/src/commands/gen.d.ts.map +1 -1
  14. package/cli/src/commands/index.d.ts +1 -1
  15. package/cli/src/commands/init.d.ts +1 -1
  16. package/cli/src/commands/lib/assets.d.ts +1 -1
  17. package/cli/src/commands/lib/bundler.d.ts +1 -1
  18. package/cli/src/commands/lib/command.d.ts +1 -1
  19. package/cli/src/commands/lib/env.d.ts +1 -1
  20. package/cli/src/commands/lib/index.d.ts +1 -1
  21. package/cli/src/commands/lib/log.d.ts +1 -1
  22. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  23. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  24. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  25. package/cli/src/commands/lib/production.d.ts +1 -1
  26. package/cli/src/commands/lib/server.d.ts +1 -1
  27. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  28. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  29. package/cli/src/commands/lib/tailwind.d.ts +1 -1
  30. package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
  31. package/cli/src/commands/lib/version.d.ts +1 -1
  32. package/cli/src/commands/og.d.ts +1 -1
  33. package/cli/src/commands/start.d.ts +1 -1
  34. package/cli/src/index.d.ts +1 -1
  35. package/core/index.d.ts +1 -1
  36. package/core/index.js +912 -589
  37. package/core/index.js.map +22 -14
  38. package/core/src/bundler/hash.d.ts +1 -1
  39. package/core/src/bundler/index.d.ts +1 -1
  40. package/core/src/config.d.ts +243 -2
  41. package/core/src/config.d.ts.map +1 -1
  42. package/core/src/content/discovery.d.ts +1 -1
  43. package/core/src/content/index.d.ts +1 -1
  44. package/core/src/content/metadata.d.ts +1 -1
  45. package/core/src/index.d.ts +1 -1
  46. package/core/src/llms/extractor.d.ts +1 -1
  47. package/core/src/llms/formatter.d.ts +1 -1
  48. package/core/src/llms/full-generator.d.ts +1 -1
  49. package/core/src/llms/index-generator.d.ts +1 -1
  50. package/core/src/llms/index.d.ts +1 -1
  51. package/core/src/og/discovery.d.ts +1 -1
  52. package/core/src/og/index.d.ts +1 -1
  53. package/core/src/og/meta.d.ts +1 -1
  54. package/core/src/og/render.d.ts +1 -1
  55. package/core/src/og/types.d.ts +1 -1
  56. package/core/src/robots/discovery.d.ts +1 -1
  57. package/core/src/robots/generator.d.ts +1 -1
  58. package/core/src/robots/index.d.ts +1 -1
  59. package/core/src/robots/policies.d.ts +1 -1
  60. package/core/src/rss/discovery.d.ts +1 -1
  61. package/core/src/rss/generator.d.ts +1 -1
  62. package/core/src/rss/index.d.ts +1 -1
  63. package/core/src/sitemap/discovery.d.ts +1 -1
  64. package/core/src/sitemap/generator.d.ts +1 -1
  65. package/core/src/sitemap/index.d.ts +1 -1
  66. package/core/src/ssr/index.d.ts +1 -1
  67. package/core/src/ssr/lib/cache.d.ts +1 -1
  68. package/core/src/ssr/lib/collections.d.ts +1 -1
  69. package/core/src/ssr/lib/compression.d.ts +1 -1
  70. package/core/src/ssr/lib/compute/content.d.ts +1 -1
  71. package/core/src/ssr/lib/compute/index.d.ts +1 -1
  72. package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
  73. package/core/src/ssr/lib/compute/routes.d.ts +1 -1
  74. package/core/src/ssr/lib/data.d.ts +1 -1
  75. package/core/src/ssr/lib/html.d.ts +1 -1
  76. package/core/src/ssr/lib/imports.d.ts +1 -1
  77. package/core/src/ssr/lib/index.d.ts +1 -1
  78. package/core/src/ssr/lib/layouts.d.ts +1 -1
  79. package/core/src/ssr/lib/metadata.d.ts +1 -1
  80. package/core/src/ssr/lib/mime.d.ts +1 -1
  81. package/core/src/ssr/lib/modules.d.ts +1 -1
  82. package/core/src/ssr/lib/path.d.ts +1 -1
  83. package/core/src/ssr/lib/preload.d.ts +1 -1
  84. package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
  85. package/core/src/ssr/lib/scripts/data.d.ts +2 -2
  86. package/core/src/ssr/lib/scripts/data.d.ts.map +1 -1
  87. package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
  88. package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
  89. package/core/src/ssr/lib/scripts/index.d.ts +1 -1
  90. package/core/src/ssr/lib/seed.d.ts +1 -1
  91. package/core/src/ssr/lib/setup.d.ts +4 -2
  92. package/core/src/ssr/lib/setup.d.ts.map +1 -1
  93. package/core/src/ssr/lib/styles.d.ts +1 -1
  94. package/core/src/ssr/lib/template.d.ts +1 -1
  95. package/core/src/ssr/lib/types.d.ts +1 -1
  96. package/core/src/ssr/render.d.ts +4 -2
  97. package/core/src/ssr/render.d.ts.map +1 -1
  98. package/core/src/ssr/stream.d.ts +4 -2
  99. package/core/src/ssr/stream.d.ts.map +1 -1
  100. package/elysia/index.d.ts +1 -1
  101. package/elysia/index.js +715 -468
  102. package/elysia/index.js.map +15 -11
  103. package/elysia/src/index.d.ts +1 -1
  104. package/elysia/src/libs/assets.d.ts +1 -1
  105. package/elysia/src/libs/cache.d.ts +1 -1
  106. package/elysia/src/libs/caching.d.ts +1 -1
  107. package/elysia/src/libs/http.d.ts +1 -1
  108. package/elysia/src/libs/image.d.ts +1 -1
  109. package/elysia/src/libs/index.d.ts +1 -1
  110. package/elysia/src/libs/llms.d.ts +1 -1
  111. package/elysia/src/libs/response.d.ts +1 -1
  112. package/elysia/src/libs/serving.d.ts +1 -1
  113. package/elysia/src/plugin.d.ts +1 -1
  114. package/elysia/src/routes/artifacts.d.ts +1 -1
  115. package/elysia/src/routes/content.d.ts +1 -1
  116. package/elysia/src/routes/content.d.ts.map +1 -1
  117. package/elysia/src/routes/image.d.ts +1 -1
  118. package/elysia/src/routes/index.d.ts +1 -1
  119. package/elysia/src/routes/internal.d.ts +1 -1
  120. package/elysia/src/routes/llms.d.ts +1 -1
  121. package/elysia/src/routes/og.d.ts +1 -1
  122. package/elysia/src/routes/redirects.d.ts +1 -1
  123. package/elysia/src/routes/robots.d.ts +1 -1
  124. package/elysia/src/routes/rss.d.ts +1 -1
  125. package/elysia/src/routes/search.d.ts +1 -1
  126. package/elysia/src/routes/sitemap.d.ts +1 -1
  127. package/elysia/src/routes/ssr.d.ts +1 -1
  128. package/elysia/src/routes/ssr.d.ts.map +1 -1
  129. package/elysia/src/routes/static.d.ts +1 -1
  130. package/elysia/src/routes/static.d.ts.map +1 -1
  131. package/elysia/src/types.d.ts +1 -1
  132. package/package.json +2 -9
  133. package/react/index.d.ts +1 -1
  134. package/react/index.js +2 -2
  135. package/react/index.js.map +1 -1
  136. package/react/src/components/ClientOnly.d.ts +1 -1
  137. package/react/src/components/ContentRoute.d.ts +1 -1
  138. package/react/src/components/Image.d.ts +1 -1
  139. package/react/src/components/LazyRoute.d.ts +1 -1
  140. package/react/src/components/Link.d.ts +1 -1
  141. package/react/src/components/Markdown.d.ts +1 -1
  142. package/react/src/components/Outlet.d.ts +1 -1
  143. package/react/src/components/index.d.ts +1 -1
  144. package/react/src/hooks/index.d.ts +1 -1
  145. package/react/src/hooks/useContent.d.ts +1 -1
  146. package/react/src/hooks/useData.d.ts +1 -1
  147. package/react/src/hooks/useFeed.d.ts +1 -1
  148. package/react/src/hooks/useLayoutData.d.ts +1 -1
  149. package/react/src/hooks/useLlms.d.ts +1 -1
  150. package/react/src/hooks/useNavigate.d.ts +1 -1
  151. package/react/src/hooks/useParams.d.ts +1 -1
  152. package/react/src/hooks/useRouter.d.ts +1 -1
  153. package/react/src/hooks/useSearch.d.ts +1 -1
  154. package/react/src/hooks/useSearchParams.d.ts +1 -1
  155. package/react/src/hooks/useToc.d.ts +1 -1
  156. package/react/src/index.d.ts +1 -1
  157. package/react/src/lib/collection.d.ts +1 -1
  158. package/react/src/lib/content.d.ts +1 -1
  159. package/react/src/lib/head.d.ts +1 -1
  160. package/react/src/lib/index.d.ts +1 -1
  161. package/react/src/lib/lazy-route.d.ts +1 -1
  162. package/react/src/lib/route-loader.d.ts +1 -1
  163. package/react/src/providers/ContentProvider.d.ts +1 -1
  164. package/react/src/providers/RerouteProvider.d.ts +1 -1
  165. package/react/src/providers/RouterProvider.d.ts +1 -1
  166. package/react/src/providers/index.d.ts +1 -1
  167. package/react/src/types/any.d.ts +1 -1
  168. package/react/src/types/index.d.ts +1 -1
  169. package/react/src/types/router.d.ts +1 -1
  170. package/telemetry/react.d.ts +2 -2
  171. package/telemetry/react.d.ts.map +1 -1
  172. package/telemetry/react.js +167 -185
  173. package/telemetry/react.js.map +7 -6
  174. package/telemetry/{index.d.ts → server.d.ts} +2 -2
  175. package/telemetry/server.d.ts.map +1 -0
  176. package/telemetry/server.js +1134 -0
  177. package/telemetry/server.js.map +44 -0
  178. package/telemetry/src/{browser/react.d.ts → react/api.d.ts} +4 -12
  179. package/telemetry/src/react/api.d.ts.map +1 -0
  180. package/telemetry/{browser.d.ts → src/react/index.d.ts} +4 -3
  181. package/telemetry/src/react/index.d.ts.map +1 -0
  182. package/telemetry/src/{browser/index.d.ts → react/telemetry.d.ts} +13 -13
  183. package/telemetry/src/react/telemetry.d.ts.map +1 -0
  184. package/telemetry/src/server/index.d.ts +3 -101
  185. package/telemetry/src/server/index.d.ts.map +1 -1
  186. package/telemetry/src/server/instrumentation.d.ts +62 -0
  187. package/telemetry/src/server/instrumentation.d.ts.map +1 -0
  188. package/telemetry/src/server/plugin.d.ts +72 -0
  189. package/telemetry/src/server/plugin.d.ts.map +1 -0
  190. package/telemetry/browser.d.ts.map +0 -1
  191. package/telemetry/browser.js +0 -382
  192. package/telemetry/browser.js.map +0 -10
  193. package/telemetry/index.d.ts.map +0 -1
  194. package/telemetry/index.js +0 -509
  195. package/telemetry/index.js.map +0 -10
  196. package/telemetry/src/browser/index.d.ts.map +0 -1
  197. 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.25.2
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 init_content = __esm(() => {
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
- init_content();
1086
+ init_content2();
841
1087
  init_layouts();
842
1088
  init_routes();
843
- init_content();
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 init_discovery = () => {};
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
- init_discovery();
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 createDataScript(ssrData, errorMsg, pathname) {
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 seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode);
2051
- if (debug)
2052
- console.log(`[Setup] ${pathname} - seedModule: ${(performance.now() - t0).toFixed(2)}ms`);
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 preloadContentModule(pathname, clientDir, cwd, isWatchMode);
2056
- if (debug)
2057
- console.log(`[Setup] ${pathname} - preloadContent: ${(performance.now() - t0).toFixed(2)}ms`);
2058
- const computeResult = await computeSSRData(pathname, clientDir, cwd, isWatchMode, { streaming, maxAge }, searchParams);
2059
- if (debug)
2060
- console.log(`[Setup] ${pathname} - computeSSRData: ${(performance.now() - t0).toFixed(2)}ms`);
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 = options.cachedCollections ? options.cachedCollections : await loadCollections(cwd, isWatchMode);
2064
- if (debug)
2065
- console.log(`[Setup] ${pathname} - loadCollections (cached: ${usingCachedCollections}): ${(performance.now() - t0).toFixed(2)}ms`);
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 = options.cachedTailwindCSS ? options.cachedTailwindCSS : await inlineTailwindCSS(clientDir, !streaming, isWatchMode);
2069
- if (debug)
2070
- console.log(`[Setup] ${pathname} - inlineTailwindCSS (cached: ${usingCachedCSS}): ${(performance.now() - t0).toFixed(2)}ms`);
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 extractPageMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ogConfig);
2076
- if (debug)
2077
- console.log(`[Setup] ${pathname} - extractMetadata: ${(performance.now() - t0).toFixed(2)}ms`);
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 componentWithPathname = cloneElement(rootComponent, {
2198
- pathname,
2199
- searchParams
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 hydrationScript = generateHydrationScripts(setup2.ssrData, isWatchMode, setup2.ssrError, collectionScripts, setup2.preloadHydrationScript, bundleUrl, pathname);
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 = applyIndexTemplate(baseTemplate, appHtml, {
2220
- head: [setup2.inlineStyleTag, combinedHead].filter(Boolean).join(`
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
- hydrationScript,
2223
- lang: setup2.metadataResult.pageLang || lang,
2224
- appId
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/sitemap/discovery.ts
2861
- var exports_discovery = {};
2862
- __export(exports_discovery, {
2863
- discoverSitemapData: () => discoverSitemapData,
2864
- discoverSSRDataRoutes: () => discoverSSRDataRoutes2,
2865
- discoverRoutes: () => discoverRoutes,
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
- return routes;
2877
- }
2878
- function shouldSkipRoute(pattern) {
2879
- return pattern.includes("[404]") || pattern.includes("[layout]") || pattern.includes("[skeleton]");
2880
- }
2881
- function categorizeRoute(route, staticRoutes, dynamicRoutes) {
2882
- const pattern = String(route?.pattern || "");
2883
- const path2 = String(route?.path || "");
2884
- if (shouldSkipRoute(pattern))
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 discoverRoutes(cwd, isWatchMode) {
2895
- const staticRoutes = [];
2896
- const dynamicRoutes = [];
2897
- try {
2898
- const routes = await loadRoutesModule2(cwd, isWatchMode);
2899
- if (Array.isArray(routes)) {
2900
- for (const route of routes) {
2901
- categorizeRoute(route, staticRoutes, dynamicRoutes);
2902
- }
2903
- }
2904
- } catch (error) {
2905
- console.error("[reroute] Failed to discover routes for sitemap:", error);
2906
- }
2907
- return { staticRoutes, dynamicRoutes };
2908
- }
2909
- async function discoverCollectionContent(cwd, collection, isWatchMode, baseUrl) {
2910
- const entries = [];
2911
- try {
2912
- const collectionFile = join(cwd, ".reroute", "collections", `${collection}.js`);
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
- init_index_generator();
3318
- // packages/core/src/og/index.ts
3319
- init_discovery();
3320
- init_meta();
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 disallows;
3752
+ return arrays;
3502
3753
  }
3503
- function addDisallowDirectives(lines, policy, autoDisallows) {
3504
- const disallows = getDisallows(policy, autoDisallows);
3505
- if (disallows.size > 0) {
3506
- for (const path2 of Array.from(disallows).sort()) {
3507
- lines.push(`Disallow: ${path2}`);
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 addPolicyBlock(lines, policy, autoDisallows) {
3512
- lines.push(`User-agent: ${policy.userAgent}`);
3513
- addAllowDirectives(lines, policy);
3514
- addDisallowDirectives(lines, policy, autoDisallows);
3515
- if (policy.crawlDelay !== undefined) {
3516
- lines.push(`Crawl-delay: ${policy.crawlDelay}`);
3517
- }
3518
- lines.push("");
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 addSitemapReference(lines, robotsConfig, sitemapEnabled) {
3528
- if (robotsConfig.referenceSitemap !== false && sitemapEnabled && robotsConfig.baseUrl) {
3529
- lines.push(`Sitemap: ${robotsConfig.baseUrl}/sitemap.xml`);
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 generateRobots(discovery2, robotsConfig, sitemapEnabled) {
3533
- const lines = [];
3534
- const { policies = [], customRules, crawlDelay } = robotsConfig;
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
- addGlobalCrawlDelay(lines, crawlDelay, effectivePolicies);
3541
- if (customRules) {
3542
- lines.push(customRules.trim());
3543
- lines.push("");
3792
+ if (sitemapConfig?.extractUrls) {
3793
+ return extractWithCustomFunction(data, routePattern, baseUrl, sitemapConfig);
3544
3794
  }
3545
- addSitemapReference(lines, robotsConfig, sitemapEnabled);
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 allowAICrawlers(crawlers) {
3581
- const agents = crawlers || Object.values(AI_CRAWLERS);
3582
- return agents.map((agent) => ({
3583
- userAgent: agent,
3584
- allow: ["/"]
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 blockAITrainingCrawlers() {
3588
- const trainingCrawlers = [
3589
- AI_CRAWLERS.GOOGLE_EXTENDED,
3590
- AI_CRAWLERS.COMMON_CRAWL,
3591
- AI_CRAWLERS.BYTEDANCE,
3592
- AI_CRAWLERS.OMGILI
3593
- ];
3594
- return trainingCrawlers.map((agent) => ({
3595
- userAgent: agent,
3596
- disallow: ["/"]
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 allowSearchCrawlers(crawlers) {
3600
- const agents = crawlers || Object.values(SEARCH_CRAWLERS);
3601
- return agents.map((agent) => ({
3602
- userAgent: agent,
3603
- allow: ["/"]
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 blockSearchCrawlers(crawlers) {
3607
- const agents = crawlers || Object.values(SEARCH_CRAWLERS);
3608
- return agents.map((agent) => ({
3609
- userAgent: agent,
3610
- disallow: ["/"]
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(() => (init_discovery2(), exports_discovery));
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
4047
4304
  }
4048
- // packages/core/src/sitemap/index.ts
4049
- init_discovery2();
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
4184
4443
  }
4185
- // packages/core/src/ssr/index.ts
4186
- init_lib();
4187
- init_render();
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 tBeforeLoad = debug ? performance.now() : 0;
4241
- const baseTemplate = options.cachedIndexHtml ? options.cachedIndexHtml : await loadIndexHtml(clientDir);
4242
- if (debug)
4243
- console.log(`[renderStream] ${pathname} - loadIndexHtml (cached: ${usingCache}): ${(performance.now() - t0).toFixed(2)}ms (actual load: ${(performance.now() - tBeforeLoad).toFixed(2)}ms)`);
4244
- const tBeforeSplit = debug ? performance.now() : 0;
4245
- const { htmlHead, rootStart, rootEnd, htmlTail } = splitTemplate(baseTemplate, appId);
4246
- if (debug)
4247
- console.log(`[renderStream] ${pathname} - splitTemplate: ${(performance.now() - t0).toFixed(2)}ms (split took: ${(performance.now() - tBeforeSplit).toFixed(2)}ms)`);
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
- const t0 = ctx.debug ? performance.now() : 0;
4283
- const STREAM_TIMEOUT_MS = 60000;
4284
- let streamTimedOut = false;
4285
- let timeoutId = null;
4286
- const cleanup = () => {
4287
- if (timeoutId) {
4288
- clearTimeout(timeoutId);
4289
- timeoutId = null;
4290
- }
4291
- };
4292
- try {
4293
- const combinedHead = deduplicateMetaTags([ctx.inlineStyleTag, ctx.head, ctx.extraHead].filter(Boolean).join(`
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
- const headWithLangAndContent = ctx.headWithLang.replace(/<html([^>]*)>/i, `<html$1 lang="${ctx.pageLang}">`).replace(/<\/head>/i, `${combinedHead ? `${combinedHead}
4567
+ const headWithLangAndContent = ctx.headWithLang.replace(/<html([^>]*)>/i, `<html$1 lang="${ctx.pageLang}">`).replace(/<\/head>/i, `${combinedHead ? `${combinedHead}
4296
4568
  ` : ""}</head>`);
4297
- const headContent = `${headWithLangAndContent}<body>`;
4298
- await writer.write(encoder.encode(headContent));
4299
- if (ctx.debug)
4300
- console.log(`[Stream] ${ctx.pathname} - first byte written: ${(performance.now() - t0).toFixed(2)}ms`);
4301
- await writer.write(encoder.encode(ctx.rootStart));
4302
- const componentWithPathname = cloneElement2(ctx.rootComponent, {
4303
- pathname: ctx.pathname,
4304
- searchParams: ctx.searchParams
4305
- });
4306
- let streamError = null;
4307
- const streamPromise = renderToReadableStream(componentWithPathname, {
4308
- onError(error) {
4309
- console.error("[reroute] SSR stream error:", error);
4310
- streamError = error instanceof Error ? error : new Error(String(error));
4311
- }
4312
- }).catch((err) => {
4313
- streamError = err;
4314
- throw err;
4315
- });
4316
- const reactStream = await streamPromise;
4317
- if (streamError)
4318
- throw streamError;
4319
- const streamTimeoutPromise = new Promise((resolve) => {
4320
- timeoutId = setTimeout(() => {
4321
- console.warn(`[reroute] Stream timeout after ${STREAM_TIMEOUT_MS}ms for ${ctx.pathname}, forcing close`);
4322
- streamTimedOut = true;
4323
- resolve({ done: true, value: undefined });
4324
- }, STREAM_TIMEOUT_MS);
4325
- });
4326
- const reader = reactStream.getReader();
4327
- while (true) {
4328
- const result = await Promise.race([reader.read(), streamTimeoutPromise]);
4329
- if (result.done || streamTimedOut) {
4330
- try {
4331
- reader.releaseLock();
4332
- } catch {}
4333
- break;
4334
- }
4335
- if (result.value) {
4336
- await writer.write(result.value);
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
- cleanup();
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=32CE37F51F53B15F64756E2164756E21
4801
+ //# debugId=3D165410A6034F1E64756E2164756E21