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/elysia/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>
|
|
@@ -193,6 +193,153 @@ var init_content = __esm(() => {
|
|
|
193
193
|
init_metadata();
|
|
194
194
|
});
|
|
195
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
|
+
|
|
196
343
|
// packages/core/src/ssr/lib/cache.ts
|
|
197
344
|
class SSRDataCache {
|
|
198
345
|
cache = new Map;
|
|
@@ -2009,12 +2156,25 @@ function createSSRExportsScript(pathname) {
|
|
|
2009
2156
|
return "";
|
|
2010
2157
|
}
|
|
2011
2158
|
}
|
|
2012
|
-
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) {
|
|
2013
2172
|
let script = "";
|
|
2014
2173
|
script += createContentCaptureScript();
|
|
2015
2174
|
if (pathname) {
|
|
2016
2175
|
script += createSSRExportsScript(pathname);
|
|
2017
2176
|
}
|
|
2177
|
+
script += createTelemetryConfigScript(browserTelemetryConfig);
|
|
2018
2178
|
if (ssrData && Object.keys(ssrData).length > 0) {
|
|
2019
2179
|
try {
|
|
2020
2180
|
const duplicatedData = duplicateQueryParamData(ssrData);
|
|
@@ -2115,7 +2275,7 @@ async function performSSRSetup(options, streaming = false) {
|
|
|
2115
2275
|
});
|
|
2116
2276
|
try {
|
|
2117
2277
|
return await Promise.race([
|
|
2118
|
-
performSSRSetupInternal(options, streaming),
|
|
2278
|
+
withParentSpan(options.parentSpan, () => performSSRSetupInternal(options, streaming)),
|
|
2119
2279
|
timeoutPromise
|
|
2120
2280
|
]);
|
|
2121
2281
|
} catch (error) {
|
|
@@ -2146,34 +2306,70 @@ async function performSSRSetupInternal(options, streaming) {
|
|
|
2146
2306
|
searchParams,
|
|
2147
2307
|
ogConfig
|
|
2148
2308
|
} = options;
|
|
2149
|
-
await
|
|
2150
|
-
|
|
2151
|
-
|
|
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
|
+
});
|
|
2152
2316
|
resetSSRAccessTracking();
|
|
2153
2317
|
const bundlePreload = createBundlePreload(bundleUrl);
|
|
2154
|
-
const preloadResult = await
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
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
|
+
});
|
|
2160
2336
|
setGlobalSSRData(computeResult.data);
|
|
2161
2337
|
const usingCachedCollections = !!options.cachedCollections;
|
|
2162
|
-
const byCollectionForSSR =
|
|
2163
|
-
|
|
2164
|
-
|
|
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
|
+
});
|
|
2165
2347
|
setGlobalCollections(byCollectionForSSR);
|
|
2166
2348
|
const usingCachedCSS = !!options.cachedTailwindCSS;
|
|
2167
|
-
const inlineStyleTag =
|
|
2168
|
-
|
|
2169
|
-
|
|
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
|
+
});
|
|
2170
2359
|
let statusOverride = preloadResult.statusOverride;
|
|
2171
2360
|
if (computeResult.statusContainer.value) {
|
|
2172
2361
|
statusOverride = computeResult.statusContainer.value;
|
|
2173
2362
|
}
|
|
2174
|
-
const metadataResult = await
|
|
2175
|
-
|
|
2176
|
-
|
|
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
|
+
});
|
|
2177
2373
|
return {
|
|
2178
2374
|
ssrData: computeResult.data,
|
|
2179
2375
|
ssrError: computeResult.error,
|
|
@@ -2201,10 +2397,10 @@ function generateCollectionScripts(byCollectionForSSR) {
|
|
|
2201
2397
|
} catch {}
|
|
2202
2398
|
return "";
|
|
2203
2399
|
}
|
|
2204
|
-
function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScripts = "", preloadScript = "", bundleUrl = "", pathname = "") {
|
|
2400
|
+
function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScripts = "", preloadScript = "", bundleUrl = "", pathname = "", browserTelemetryConfig) {
|
|
2205
2401
|
let scripts = preloadScript;
|
|
2206
2402
|
scripts += collectionScripts;
|
|
2207
|
-
scripts += createDataScript(ssrData, isWatchMode ? ssrError : undefined, pathname);
|
|
2403
|
+
scripts += createDataScript(ssrData, isWatchMode ? ssrError : undefined, pathname, browserTelemetryConfig);
|
|
2208
2404
|
scripts += createFeedsScript();
|
|
2209
2405
|
scripts += createLlmsScript();
|
|
2210
2406
|
if (bundleUrl) {
|
|
@@ -2216,6 +2412,7 @@ function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScri
|
|
|
2216
2412
|
return scripts;
|
|
2217
2413
|
}
|
|
2218
2414
|
var init_setup = __esm(() => {
|
|
2415
|
+
init_server2();
|
|
2219
2416
|
init_collections();
|
|
2220
2417
|
init_compute();
|
|
2221
2418
|
init_metadata2();
|
|
@@ -2284,6 +2481,7 @@ async function renderSSRDocument(options) {
|
|
|
2284
2481
|
clientDir,
|
|
2285
2482
|
cwd,
|
|
2286
2483
|
isWatchMode,
|
|
2484
|
+
parentSpan: options.parentSpan,
|
|
2287
2485
|
bundleUrl,
|
|
2288
2486
|
maxAge,
|
|
2289
2487
|
searchParams,
|
|
@@ -2293,14 +2491,29 @@ async function renderSSRDocument(options) {
|
|
|
2293
2491
|
}, false);
|
|
2294
2492
|
const duplicatedData = duplicateQueryParamData(setup2.ssrData);
|
|
2295
2493
|
setGlobalSSRData(duplicatedData);
|
|
2296
|
-
const
|
|
2297
|
-
|
|
2298
|
-
|
|
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;
|
|
2299
2508
|
});
|
|
2300
|
-
const appHtml = renderToString(componentWithPathname);
|
|
2301
|
-
const baseTemplate = await loadIndexHtml(clientDir);
|
|
2302
2509
|
const collectionScripts = generateCollectionScripts(setup2.byCollectionForSSR);
|
|
2303
|
-
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
|
+
});
|
|
2304
2517
|
let statusOverride = setup2.preloadStatusOverride;
|
|
2305
2518
|
if (setup2.statusContainer.value) {
|
|
2306
2519
|
statusOverride = setup2.statusContainer.value;
|
|
@@ -2315,12 +2528,19 @@ async function renderSSRDocument(options) {
|
|
|
2315
2528
|
dedent(setup2.metadataResult.perPageHead)
|
|
2316
2529
|
].filter(Boolean).join(`
|
|
2317
2530
|
`));
|
|
2318
|
-
const html2 =
|
|
2319
|
-
|
|
2531
|
+
const html2 = withSpanSync("ssr.apply.template", (span) => {
|
|
2532
|
+
const result = applyIndexTemplate(baseTemplate, appHtml, {
|
|
2533
|
+
head: [setup2.inlineStyleTag, combinedHead].filter(Boolean).join(`
|
|
2320
2534
|
`),
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
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;
|
|
2324
2544
|
});
|
|
2325
2545
|
return {
|
|
2326
2546
|
html: html2,
|
|
@@ -2328,6 +2548,8 @@ async function renderSSRDocument(options) {
|
|
|
2328
2548
|
};
|
|
2329
2549
|
}
|
|
2330
2550
|
var init_render = __esm(() => {
|
|
2551
|
+
init_server2();
|
|
2552
|
+
init_config();
|
|
2331
2553
|
init_lib();
|
|
2332
2554
|
init_html();
|
|
2333
2555
|
});
|
|
@@ -4255,6 +4477,7 @@ async function renderSSRDocumentStream(options) {
|
|
|
4255
4477
|
clientDir,
|
|
4256
4478
|
cwd,
|
|
4257
4479
|
isWatchMode,
|
|
4480
|
+
parentSpan: options.parentSpan,
|
|
4258
4481
|
bundleUrl,
|
|
4259
4482
|
maxAge,
|
|
4260
4483
|
searchParams,
|
|
@@ -4276,14 +4499,19 @@ async function renderSSRDocumentStream(options) {
|
|
|
4276
4499
|
const { readable, writable } = new TransformStream;
|
|
4277
4500
|
const writer = writable.getWriter();
|
|
4278
4501
|
const usingCache = !!options.cachedIndexHtml;
|
|
4279
|
-
const
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
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
|
+
});
|
|
4287
4515
|
const pageLang = setup2.metadataResult.pageLang || lang;
|
|
4288
4516
|
let headWithLang = htmlHead.replace(/<html([^>]*)>/i, `<html$1 lang="${pageLang}">`);
|
|
4289
4517
|
const extraHead = setup2.bundlePreload + setup2.preloadExtraHead + setup2.metadataResult.perPageHead;
|
|
@@ -4293,6 +4521,8 @@ async function renderSSRDocumentStream(options) {
|
|
|
4293
4521
|
if (/<meta\s+name\s*=\s*['"]description['"][^>]*>/i.test(extraHead)) {
|
|
4294
4522
|
headWithLang = headWithLang.replace(/<meta\s+name\s*=\s*['"]description['"][^>]*>/i, "");
|
|
4295
4523
|
}
|
|
4524
|
+
const config = await loadConfig(cwd);
|
|
4525
|
+
const browserTelemetryConfig = config.telemetry?.browser;
|
|
4296
4526
|
streamSSRContent(writer, encoder, {
|
|
4297
4527
|
rootComponent,
|
|
4298
4528
|
pathname,
|
|
@@ -4311,82 +4541,102 @@ async function renderSSRDocumentStream(options) {
|
|
|
4311
4541
|
ssrData: setup2.ssrData,
|
|
4312
4542
|
ssrError: setup2.ssrError,
|
|
4313
4543
|
byCollectionForSSR: setup2.byCollectionForSSR,
|
|
4314
|
-
preloadHydrationScript: setup2.preloadHydrationScript
|
|
4544
|
+
preloadHydrationScript: setup2.preloadHydrationScript,
|
|
4545
|
+
browserTelemetryConfig,
|
|
4546
|
+
parentSpan: options.parentSpan
|
|
4315
4547
|
});
|
|
4316
4548
|
if (debug)
|
|
4317
4549
|
console.log(`[renderStream] ${pathname} - returning stream: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
4318
4550
|
return { stream: readable, status: statusOverride || 200 };
|
|
4319
4551
|
}
|
|
4320
4552
|
async function streamSSRContent(writer, encoder, ctx) {
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
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(`
|
|
4333
4566
|
`));
|
|
4334
|
-
|
|
4567
|
+
const headWithLangAndContent = ctx.headWithLang.replace(/<html([^>]*)>/i, `<html$1 lang="${ctx.pageLang}">`).replace(/<\/head>/i, `${combinedHead ? `${combinedHead}
|
|
4335
4568
|
` : ""}</head>`);
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
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 {}
|
|
4377
4638
|
}
|
|
4378
|
-
|
|
4379
|
-
await writer.write(encoder.encode(ctx.rootEnd));
|
|
4380
|
-
const allScripts = buildStreamingScripts(ctx);
|
|
4381
|
-
await writer.write(encoder.encode(allScripts + ctx.htmlTail));
|
|
4382
|
-
await writer.close();
|
|
4383
|
-
} catch (error) {
|
|
4384
|
-
cleanup();
|
|
4385
|
-
console.error("[reroute] Stream error:", error);
|
|
4386
|
-
try {
|
|
4387
|
-
await writer.abort(error);
|
|
4388
|
-
} catch {}
|
|
4389
|
-
}
|
|
4639
|
+
});
|
|
4390
4640
|
}
|
|
4391
4641
|
function buildStreamingScripts(ctx) {
|
|
4392
4642
|
const collectionScripts = generateCollectionScripts(ctx.byCollectionForSSR);
|
|
@@ -4397,7 +4647,7 @@ function buildStreamingScripts(ctx) {
|
|
|
4397
4647
|
ssrDataSnapshot[key] = value;
|
|
4398
4648
|
}
|
|
4399
4649
|
}
|
|
4400
|
-
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);
|
|
4401
4651
|
const feedsScript = createFeedsScript();
|
|
4402
4652
|
const llmsScript = createLlmsScript();
|
|
4403
4653
|
let allScripts = dataScript + feedsScript + llmsScript + collectionScripts + ctx.preloadHydrationScript;
|
|
@@ -4408,6 +4658,8 @@ function buildStreamingScripts(ctx) {
|
|
|
4408
4658
|
return allScripts;
|
|
4409
4659
|
}
|
|
4410
4660
|
var init_stream = __esm(() => {
|
|
4661
|
+
init_server2();
|
|
4662
|
+
init_config();
|
|
4411
4663
|
init_lib();
|
|
4412
4664
|
init_html();
|
|
4413
4665
|
init_imports();
|
|
@@ -4955,12 +5207,19 @@ function registerArtifactsRoutes(app, cwd, fileCache, options) {
|
|
|
4955
5207
|
|
|
4956
5208
|
// packages/elysia/src/routes/content.ts
|
|
4957
5209
|
init_core();
|
|
5210
|
+
import { trace as trace3 } from "@opentelemetry/api";
|
|
4958
5211
|
import { NotFoundError as NotFoundError3 } from "elysia";
|
|
4959
|
-
|
|
5212
|
+
var otelAvailable2;
|
|
5213
|
+
function isOtelAvailable2() {
|
|
5214
|
+
if (otelAvailable2 !== undefined)
|
|
5215
|
+
return otelAvailable2;
|
|
4960
5216
|
try {
|
|
4961
|
-
|
|
5217
|
+
__require("@opentelemetry/api");
|
|
5218
|
+
otelAvailable2 = true;
|
|
5219
|
+
return true;
|
|
4962
5220
|
} catch {
|
|
4963
|
-
|
|
5221
|
+
otelAvailable2 = false;
|
|
5222
|
+
return false;
|
|
4964
5223
|
}
|
|
4965
5224
|
}
|
|
4966
5225
|
function registerContentRoutes(app, cwd, collectionCache, directive, maxAge, isWatchMode) {
|
|
@@ -4971,14 +5230,13 @@ function registerContentRoutes(app, cwd, collectionCache, directive, maxAge, isW
|
|
|
4971
5230
|
const cacheKey = `content:${collectionPath}`;
|
|
4972
5231
|
const cached = collectionCache.get(cacheKey);
|
|
4973
5232
|
if (cached) {
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
});
|
|
5233
|
+
if (isOtelAvailable2()) {
|
|
5234
|
+
const currentSpan = trace3.getActiveSpan();
|
|
5235
|
+
currentSpan?.setAttributes({
|
|
5236
|
+
"reroute.cache.hit": true,
|
|
5237
|
+
"reroute.collection": collectionPath
|
|
5238
|
+
});
|
|
5239
|
+
}
|
|
4982
5240
|
const response = cached.clone();
|
|
4983
5241
|
response.headers.set("Reroute-Cache", "HIT");
|
|
4984
5242
|
return response;
|
|
@@ -4987,14 +5245,10 @@ function registerContentRoutes(app, cwd, collectionCache, directive, maxAge, isW
|
|
|
4987
5245
|
const collectionFile = join(cwd, ".reroute", "collections", `${collectionPath}.js`);
|
|
4988
5246
|
const file = Bun.file(collectionFile);
|
|
4989
5247
|
if (!await file.exists()) {
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
"http.response.status_code": 404,
|
|
4995
|
-
"reroute.content.not_found": true,
|
|
4996
|
-
"reroute.content.collection": collectionPath
|
|
4997
|
-
});
|
|
5248
|
+
if (isOtelAvailable2()) {
|
|
5249
|
+
const currentSpan = trace3.getActiveSpan();
|
|
5250
|
+
currentSpan?.setAttribute("reroute.collection", collectionPath);
|
|
5251
|
+
}
|
|
4998
5252
|
throw new NotFoundError3;
|
|
4999
5253
|
}
|
|
5000
5254
|
const url = `${Bun.pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ""}`;
|
|
@@ -5010,29 +5264,23 @@ function registerContentRoutes(app, cwd, collectionCache, directive, maxAge, isW
|
|
|
5010
5264
|
}
|
|
5011
5265
|
});
|
|
5012
5266
|
collectionCache.set(cacheKey, response);
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
"reroute.content.cache_hit": false
|
|
5022
|
-
});
|
|
5267
|
+
if (isOtelAvailable2()) {
|
|
5268
|
+
const currentSpan = trace3.getActiveSpan();
|
|
5269
|
+
currentSpan?.setAttributes({
|
|
5270
|
+
"reroute.collection": collectionPath,
|
|
5271
|
+
"reroute.collection.docs": items.length,
|
|
5272
|
+
"reroute.cache.hit": false
|
|
5273
|
+
});
|
|
5274
|
+
}
|
|
5023
5275
|
return response.clone();
|
|
5024
5276
|
} catch (e) {
|
|
5025
5277
|
if (e instanceof NotFoundError3)
|
|
5026
5278
|
throw e;
|
|
5027
5279
|
console.error(`[reroute] Failed to serve collection ${collectionPath}:`, e);
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
"http.response.status_code": 500,
|
|
5033
|
-
"reroute.content.error": true,
|
|
5034
|
-
"reroute.content.collection": collectionPath
|
|
5035
|
-
});
|
|
5280
|
+
if (isOtelAvailable2()) {
|
|
5281
|
+
const currentSpan = trace3.getActiveSpan();
|
|
5282
|
+
currentSpan?.setAttribute("reroute.collection", collectionPath);
|
|
5283
|
+
}
|
|
5036
5284
|
throw new NotFoundError3;
|
|
5037
5285
|
}
|
|
5038
5286
|
});
|
|
@@ -6681,7 +6929,9 @@ function registerSitemapRoutes(app, options) {
|
|
|
6681
6929
|
|
|
6682
6930
|
// packages/elysia/src/routes/ssr.ts
|
|
6683
6931
|
init_core();
|
|
6932
|
+
init_server2();
|
|
6684
6933
|
import { join as join4 } from "node:path";
|
|
6934
|
+
import { trace as trace4 } from "@opentelemetry/api";
|
|
6685
6935
|
import { NotFoundError as NotFoundError11 } from "elysia";
|
|
6686
6936
|
if (typeof process !== "undefined") {
|
|
6687
6937
|
process.on("unhandledRejection", (reason, _promise) => {
|
|
@@ -6691,16 +6941,17 @@ if (typeof process !== "undefined") {
|
|
|
6691
6941
|
console.error("[reroute] Uncaught Exception:", error);
|
|
6692
6942
|
});
|
|
6693
6943
|
}
|
|
6694
|
-
var
|
|
6695
|
-
function
|
|
6696
|
-
if (
|
|
6697
|
-
return
|
|
6944
|
+
var otelAvailable3;
|
|
6945
|
+
function isOtelAvailable3() {
|
|
6946
|
+
if (otelAvailable3 !== undefined)
|
|
6947
|
+
return otelAvailable3;
|
|
6698
6948
|
try {
|
|
6699
|
-
|
|
6700
|
-
|
|
6949
|
+
__require("@opentelemetry/api");
|
|
6950
|
+
otelAvailable3 = true;
|
|
6951
|
+
return true;
|
|
6701
6952
|
} catch {
|
|
6702
|
-
|
|
6703
|
-
return
|
|
6953
|
+
otelAvailable3 = false;
|
|
6954
|
+
return false;
|
|
6704
6955
|
}
|
|
6705
6956
|
}
|
|
6706
6957
|
function registerSSRRoutes(app, options) {
|
|
@@ -6742,7 +6993,8 @@ function registerSSRRoutes(app, options) {
|
|
|
6742
6993
|
}
|
|
6743
6994
|
const handleSSR = async ({
|
|
6744
6995
|
request,
|
|
6745
|
-
set
|
|
6996
|
+
set,
|
|
6997
|
+
store
|
|
6746
6998
|
}) => {
|
|
6747
6999
|
const t0 = performance.now();
|
|
6748
7000
|
const method = request.method || "GET";
|
|
@@ -6757,62 +7009,71 @@ function registerSSRRoutes(app, options) {
|
|
|
6757
7009
|
const fullPath = pathname;
|
|
6758
7010
|
const searchParams = url.searchParams;
|
|
6759
7011
|
const acceptEncoding = request.headers.get("accept-encoding") || "";
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
const
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
7012
|
+
const parentSpan = store.telemetrySpan;
|
|
7013
|
+
return withParentSpan(parentSpan, async () => {
|
|
7014
|
+
if (!isWatchMode && SSR_HTML_TTL_MS > 0) {
|
|
7015
|
+
try {
|
|
7016
|
+
const ck = makeKey(pathname, acceptEncoding);
|
|
7017
|
+
const cached = htmlCache.get(ck);
|
|
7018
|
+
if (cached && cached.exp > Date.now()) {
|
|
7019
|
+
if (isOtelAvailable3()) {
|
|
7020
|
+
const currentSpan = trace4.getActiveSpan();
|
|
7021
|
+
currentSpan?.setAttributes({
|
|
7022
|
+
"reroute.cache.hit": true,
|
|
7023
|
+
"reroute.cache.key": ck,
|
|
7024
|
+
"reroute.pathname": pathname
|
|
7025
|
+
});
|
|
7026
|
+
}
|
|
7027
|
+
set.status = cached.status;
|
|
7028
|
+
Object.assign(set.headers, cached.headers);
|
|
7029
|
+
set.headers["Reroute-Cache"] = "HIT";
|
|
7030
|
+
return new Response(cached.body);
|
|
7031
|
+
}
|
|
7032
|
+
} catch {}
|
|
7033
|
+
}
|
|
7034
|
+
const bundleUrl = await withSpan("ssr.get.bundle", async (span) => {
|
|
7035
|
+
span.setAttribute("reroute.pathname", pathname);
|
|
7036
|
+
const url2 = await getBundleUrl();
|
|
7037
|
+
if (debug)
|
|
7038
|
+
console.log(`[SSR] ${pathname} - bundleUrl: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7039
|
+
return url2;
|
|
7040
|
+
});
|
|
7041
|
+
const { cachedCollections, cachedTailwindCSS, cachedIndexHtml } = await withSpan("ssr.load.cache", async (span) => {
|
|
7042
|
+
const collections2 = await getCollections();
|
|
7043
|
+
const tailwindCSS = await getTailwindCSS();
|
|
7044
|
+
const indexHtml = await getIndexHtml();
|
|
7045
|
+
span.setAttributes({
|
|
7046
|
+
"reroute.pathname": pathname,
|
|
7047
|
+
"reroute.collections.exists": !!collections2,
|
|
7048
|
+
"reroute.collections.count": Object.keys(collections2).length
|
|
7049
|
+
});
|
|
7050
|
+
if (debug)
|
|
7051
|
+
console.log(`[SSR] ${pathname} - cached setup: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7052
|
+
return {
|
|
7053
|
+
cachedCollections: collections2,
|
|
7054
|
+
cachedTailwindCSS: tailwindCSS,
|
|
7055
|
+
cachedIndexHtml: indexHtml
|
|
7056
|
+
};
|
|
7057
|
+
});
|
|
6792
7058
|
try {
|
|
6793
|
-
const
|
|
6794
|
-
|
|
7059
|
+
const linkValue = `<${bundleUrl}>; rel=modulepreload; as=script`;
|
|
7060
|
+
try {
|
|
7061
|
+
const hints = new Headers({ Link: linkValue });
|
|
7062
|
+
request?.sendEarlyHints?.(hints);
|
|
7063
|
+
} catch {}
|
|
7064
|
+
set.headers.link = set.headers.link ? `${set.headers.link}, ${linkValue}` : linkValue;
|
|
6795
7065
|
} catch {}
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
try {
|
|
6806
|
-
const otel = getOtelUtilities2();
|
|
6807
|
-
const renderFn = async () => {
|
|
6808
|
-
otel?.setAttributes({
|
|
6809
|
-
"http.request.method": "GET",
|
|
6810
|
-
"reroute.ssr.enabled": true,
|
|
6811
|
-
"reroute.ssr.streaming": true,
|
|
6812
|
-
"reroute.cache.hit": false,
|
|
6813
|
-
"reroute.pathname": pathname
|
|
7066
|
+
const cacheControlHeader = isWatchMode ? "no-cache, no-store, must-revalidate" : `${directive}, max-age=${maxAge}`;
|
|
7067
|
+
let response;
|
|
7068
|
+
if (streamingEnabled) {
|
|
7069
|
+
if (debug)
|
|
7070
|
+
console.log(`[SSR] ${pathname} - starting stream: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7071
|
+
const { stream: stream2, status } = await withSpan("ssr.document.render", async (renderSpan) => {
|
|
7072
|
+
renderSpan?.setAttributes({
|
|
7073
|
+
"reroute.pathname": pathname,
|
|
7074
|
+
"reroute.cache.hit": false
|
|
6814
7075
|
});
|
|
6815
|
-
const
|
|
7076
|
+
const result = await renderSSRDocumentStream({
|
|
6816
7077
|
pathname: fullPath,
|
|
6817
7078
|
rootComponent,
|
|
6818
7079
|
clientDir,
|
|
@@ -6828,25 +7089,191 @@ function registerSSRRoutes(app, options) {
|
|
|
6828
7089
|
appId,
|
|
6829
7090
|
maxAge,
|
|
6830
7091
|
searchParams,
|
|
6831
|
-
ogConfig: options.ogConfig
|
|
7092
|
+
ogConfig: options.ogConfig,
|
|
7093
|
+
parentSpan: renderSpan
|
|
6832
7094
|
});
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
return
|
|
6837
|
-
};
|
|
6838
|
-
const tBeforeRecord = debug ? performance.now() : 0;
|
|
6839
|
-
const result = otel ? await otel.record("reroute.ssr.render_stream", renderFn) : await renderFn();
|
|
6840
|
-
if (debug)
|
|
6841
|
-
console.log(`[SSR] ${pathname} - otel.record completed: ${(performance.now() - t0).toFixed(2)}ms (record overhead: ${(performance.now() - tBeforeRecord - (performance.now() - t0)).toFixed(2)}ms)`);
|
|
6842
|
-
const tBeforeExtract = debug ? performance.now() : 0;
|
|
6843
|
-
stream2 = result.stream;
|
|
6844
|
-
status = result.status;
|
|
7095
|
+
renderSpan?.setAttribute("http.response.status_code", result.status);
|
|
7096
|
+
if (debug)
|
|
7097
|
+
console.log(`[SSR] ${pathname} - render completed: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7098
|
+
return result;
|
|
7099
|
+
});
|
|
6845
7100
|
if (debug)
|
|
6846
|
-
console.log(`[SSR] ${pathname} -
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
7101
|
+
console.log(`[SSR] ${pathname} - before compression check: ${(performance.now() - t0).toFixed(2)}ms, compression=${compression2}, acceptEncoding=${!!acceptEncoding}`);
|
|
7102
|
+
if (compression2 && acceptEncoding) {
|
|
7103
|
+
const fullHtml = await withSpan("ssr.buffer.stream", async (span) => {
|
|
7104
|
+
const chunks = [];
|
|
7105
|
+
const reader = stream2.getReader();
|
|
7106
|
+
try {
|
|
7107
|
+
while (true) {
|
|
7108
|
+
const { done, value } = await reader.read();
|
|
7109
|
+
if (done)
|
|
7110
|
+
break;
|
|
7111
|
+
chunks.push(new Uint8Array(value));
|
|
7112
|
+
}
|
|
7113
|
+
} finally {
|
|
7114
|
+
reader.releaseLock();
|
|
7115
|
+
}
|
|
7116
|
+
const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
7117
|
+
const buffer = new Uint8Array(totalLength);
|
|
7118
|
+
let offset = 0;
|
|
7119
|
+
for (const chunk of chunks) {
|
|
7120
|
+
buffer.set(chunk, offset);
|
|
7121
|
+
offset += chunk.length;
|
|
7122
|
+
}
|
|
7123
|
+
span.setAttributes({
|
|
7124
|
+
"reroute.stream.chunks": chunks.length,
|
|
7125
|
+
"reroute.stream.bytes": totalLength
|
|
7126
|
+
});
|
|
7127
|
+
return buffer;
|
|
7128
|
+
});
|
|
7129
|
+
const { body, extraHeaders } = await withSpan("ssr.compress", async (span) => {
|
|
7130
|
+
const result = gzipIfAccepted(fullHtml, "text/html; charset=utf-8", acceptEncoding);
|
|
7131
|
+
span.setAttributes({
|
|
7132
|
+
"reroute.size.original": fullHtml.length,
|
|
7133
|
+
"reroute.size.compressed": result.body.length,
|
|
7134
|
+
"reroute.encoding": extraHeaders["Content-Encoding"] || "none"
|
|
7135
|
+
});
|
|
7136
|
+
return result;
|
|
7137
|
+
});
|
|
7138
|
+
if (!isWatchMode && SSR_HTML_TTL_MS > 0 && status === 200) {
|
|
7139
|
+
try {
|
|
7140
|
+
const ck = makeKey(pathname, acceptEncoding);
|
|
7141
|
+
const cacheHeaders = {
|
|
7142
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
7143
|
+
"Cache-Control": cacheControlHeader,
|
|
7144
|
+
...extraHeaders
|
|
7145
|
+
};
|
|
7146
|
+
if (set.headers.link) {
|
|
7147
|
+
cacheHeaders.Link = set.headers.link;
|
|
7148
|
+
}
|
|
7149
|
+
htmlCache.set(ck, {
|
|
7150
|
+
status,
|
|
7151
|
+
headers: cacheHeaders,
|
|
7152
|
+
body,
|
|
7153
|
+
exp: Date.now() + SSR_HTML_TTL_MS
|
|
7154
|
+
});
|
|
7155
|
+
} catch {}
|
|
7156
|
+
}
|
|
7157
|
+
const resHeaders = {
|
|
7158
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
7159
|
+
"Cache-Control": cacheControlHeader,
|
|
7160
|
+
"Reroute-Cache": "MISS",
|
|
7161
|
+
...extraHeaders
|
|
7162
|
+
};
|
|
7163
|
+
if (set.headers.link) {
|
|
7164
|
+
resHeaders.Link = set.headers.link;
|
|
7165
|
+
}
|
|
7166
|
+
set.status = status;
|
|
7167
|
+
response = new Response(body, {
|
|
7168
|
+
status,
|
|
7169
|
+
headers: resHeaders
|
|
7170
|
+
});
|
|
7171
|
+
} else {
|
|
7172
|
+
const shouldCache = !isWatchMode && SSR_HTML_TTL_MS > 0 && status === 200;
|
|
7173
|
+
if (debug)
|
|
7174
|
+
console.log(`[SSR] ${pathname} - no compression path, shouldCache=${shouldCache}`);
|
|
7175
|
+
if (shouldCache) {
|
|
7176
|
+
response = await withSpan("ssr.create.response", async (span) => {
|
|
7177
|
+
if (debug)
|
|
7178
|
+
console.log(`[SSR] ${pathname} - creating caching stream: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7179
|
+
const chunks = [];
|
|
7180
|
+
const cachingStream = stream2.pipeThrough(new TransformStream({
|
|
7181
|
+
transform(chunk, controller) {
|
|
7182
|
+
chunks.push(new Uint8Array(chunk));
|
|
7183
|
+
controller.enqueue(chunk);
|
|
7184
|
+
},
|
|
7185
|
+
flush() {
|
|
7186
|
+
try {
|
|
7187
|
+
const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
7188
|
+
const fullHtml = new Uint8Array(totalLength);
|
|
7189
|
+
let offset = 0;
|
|
7190
|
+
for (const chunk of chunks) {
|
|
7191
|
+
fullHtml.set(chunk, offset);
|
|
7192
|
+
offset += chunk.length;
|
|
7193
|
+
}
|
|
7194
|
+
const ck = makeKey(pathname, acceptEncoding);
|
|
7195
|
+
const cacheHeaders = {
|
|
7196
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
7197
|
+
"Cache-Control": cacheControlHeader
|
|
7198
|
+
};
|
|
7199
|
+
if (set.headers.link) {
|
|
7200
|
+
cacheHeaders.Link = set.headers.link;
|
|
7201
|
+
}
|
|
7202
|
+
htmlCache.set(ck, {
|
|
7203
|
+
status,
|
|
7204
|
+
headers: cacheHeaders,
|
|
7205
|
+
body: fullHtml,
|
|
7206
|
+
exp: Date.now() + SSR_HTML_TTL_MS
|
|
7207
|
+
});
|
|
7208
|
+
} catch (e) {
|
|
7209
|
+
console.error("[reroute] Failed to cache stream:", e);
|
|
7210
|
+
}
|
|
7211
|
+
}
|
|
7212
|
+
}));
|
|
7213
|
+
set.status = status;
|
|
7214
|
+
const tBeforeResponse = debug ? performance.now() : 0;
|
|
7215
|
+
const res = new Response(cachingStream, {
|
|
7216
|
+
status,
|
|
7217
|
+
headers: {
|
|
7218
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
7219
|
+
"Cache-Control": cacheControlHeader,
|
|
7220
|
+
"Reroute-Cache": "MISS"
|
|
7221
|
+
}
|
|
7222
|
+
});
|
|
7223
|
+
if (debug)
|
|
7224
|
+
console.log(`[SSR] ${pathname} - Response created (cached stream): ${(performance.now() - t0).toFixed(2)}ms (creation: ${(performance.now() - tBeforeResponse).toFixed(2)}ms)`);
|
|
7225
|
+
span.setAttribute("reroute.cached", true);
|
|
7226
|
+
return res;
|
|
7227
|
+
});
|
|
7228
|
+
} else {
|
|
7229
|
+
if (debug)
|
|
7230
|
+
console.log(`[SSR] ${pathname} - creating direct stream response: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7231
|
+
set.status = status;
|
|
7232
|
+
response = new Response(stream2, {
|
|
7233
|
+
status,
|
|
7234
|
+
headers: {
|
|
7235
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
7236
|
+
"Cache-Control": cacheControlHeader,
|
|
7237
|
+
"Reroute-Cache": "MISS"
|
|
7238
|
+
}
|
|
7239
|
+
});
|
|
7240
|
+
if (debug)
|
|
7241
|
+
console.log(`[SSR] ${pathname} - Response created (direct stream): ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7242
|
+
}
|
|
7243
|
+
}
|
|
7244
|
+
} else {
|
|
7245
|
+
let html2;
|
|
7246
|
+
let status;
|
|
7247
|
+
try {
|
|
7248
|
+
const result = await withSpan("ssr.render.sync", async (renderSpan) => {
|
|
7249
|
+
renderSpan?.setAttributes({
|
|
7250
|
+
"reroute.pathname": pathname,
|
|
7251
|
+
"reroute.cache.hit": false
|
|
7252
|
+
});
|
|
7253
|
+
const renderResult = await renderSSRDocument({
|
|
7254
|
+
pathname: fullPath,
|
|
7255
|
+
rootComponent,
|
|
7256
|
+
clientDir,
|
|
7257
|
+
cwd,
|
|
7258
|
+
isWatchMode,
|
|
7259
|
+
bundleUrl,
|
|
7260
|
+
head,
|
|
7261
|
+
lang,
|
|
7262
|
+
appId,
|
|
7263
|
+
maxAge,
|
|
7264
|
+
searchParams,
|
|
7265
|
+
ogConfig: options.ogConfig,
|
|
7266
|
+
parentSpan: renderSpan
|
|
7267
|
+
});
|
|
7268
|
+
renderSpan?.setAttribute("http.response.status_code", renderResult.status);
|
|
7269
|
+
return renderResult;
|
|
7270
|
+
});
|
|
7271
|
+
html2 = result.html;
|
|
7272
|
+
status = result.status;
|
|
7273
|
+
} catch (ssrError) {
|
|
7274
|
+
console.error("[reroute] SSR rendering failed, returning error page:", ssrError);
|
|
7275
|
+
set.status = 500;
|
|
7276
|
+
const errorHtml = `<!DOCTYPE html>
|
|
6850
7277
|
<html lang="en">
|
|
6851
7278
|
<head>
|
|
6852
7279
|
<meta charset="UTF-8">
|
|
@@ -6865,53 +7292,20 @@ function registerSSRRoutes(app, options) {
|
|
|
6865
7292
|
<script type="module" src="${bundleUrl}"></script>
|
|
6866
7293
|
</body>
|
|
6867
7294
|
</html>`;
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
}
|
|
6873
|
-
if (debug)
|
|
6874
|
-
console.log(`[SSR] ${pathname} - before compression check: ${(performance.now() - t0).toFixed(2)}ms, compression=${compression2}, acceptEncoding=${!!acceptEncoding}`);
|
|
6875
|
-
if (compression2 && acceptEncoding) {
|
|
6876
|
-
const chunks = [];
|
|
6877
|
-
const reader = stream2.getReader();
|
|
6878
|
-
try {
|
|
6879
|
-
while (true) {
|
|
6880
|
-
const { done, value } = await reader.read();
|
|
6881
|
-
if (done)
|
|
6882
|
-
break;
|
|
6883
|
-
chunks.push(new Uint8Array(value));
|
|
6884
|
-
}
|
|
6885
|
-
} finally {
|
|
6886
|
-
reader.releaseLock();
|
|
6887
|
-
}
|
|
6888
|
-
const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
6889
|
-
const fullHtml = new Uint8Array(totalLength);
|
|
6890
|
-
let offset = 0;
|
|
6891
|
-
for (const chunk of chunks) {
|
|
6892
|
-
fullHtml.set(chunk, offset);
|
|
6893
|
-
offset += chunk.length;
|
|
6894
|
-
}
|
|
6895
|
-
const { body, extraHeaders } = gzipIfAccepted(fullHtml, "text/html; charset=utf-8", acceptEncoding);
|
|
6896
|
-
if (!isWatchMode && SSR_HTML_TTL_MS > 0 && status === 200) {
|
|
6897
|
-
try {
|
|
6898
|
-
const ck = makeKey(pathname, acceptEncoding);
|
|
6899
|
-
const cacheHeaders = {
|
|
6900
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
6901
|
-
"Cache-Control": cacheControlHeader,
|
|
6902
|
-
...extraHeaders
|
|
6903
|
-
};
|
|
6904
|
-
if (set.headers.link) {
|
|
6905
|
-
cacheHeaders.Link = set.headers.link;
|
|
6906
|
-
}
|
|
6907
|
-
htmlCache.set(ck, {
|
|
6908
|
-
status,
|
|
6909
|
-
headers: cacheHeaders,
|
|
6910
|
-
body,
|
|
6911
|
-
exp: Date.now() + SSR_HTML_TTL_MS
|
|
6912
|
-
});
|
|
6913
|
-
} catch {}
|
|
7295
|
+
return new Response(errorHtml, {
|
|
7296
|
+
status: 500,
|
|
7297
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
7298
|
+
});
|
|
6914
7299
|
}
|
|
7300
|
+
const { body, extraHeaders } = compression2 ? await withSpan("ssr.compress", async (span) => {
|
|
7301
|
+
const result = gzipIfAccepted(html2, "text/html; charset=utf-8", acceptEncoding);
|
|
7302
|
+
span.setAttributes({
|
|
7303
|
+
"reroute.size.original": html2.length,
|
|
7304
|
+
"reroute.size.compressed": typeof result.body === "string" ? result.body.length : result.body.length,
|
|
7305
|
+
"reroute.encoding": result.extraHeaders["Content-Encoding"] || "none"
|
|
7306
|
+
});
|
|
7307
|
+
return result;
|
|
7308
|
+
}) : { body: html2, extraHeaders: {} };
|
|
6915
7309
|
const resHeaders = {
|
|
6916
7310
|
"Content-Type": "text/html; charset=utf-8",
|
|
6917
7311
|
"Cache-Control": cacheControlHeader,
|
|
@@ -6926,171 +7320,26 @@ function registerSSRRoutes(app, options) {
|
|
|
6926
7320
|
status,
|
|
6927
7321
|
headers: resHeaders
|
|
6928
7322
|
});
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
chunks.push(new Uint8Array(chunk));
|
|
6940
|
-
controller.enqueue(chunk);
|
|
6941
|
-
},
|
|
6942
|
-
flush() {
|
|
6943
|
-
try {
|
|
6944
|
-
const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
6945
|
-
const fullHtml = new Uint8Array(totalLength);
|
|
6946
|
-
let offset = 0;
|
|
6947
|
-
for (const chunk of chunks) {
|
|
6948
|
-
fullHtml.set(chunk, offset);
|
|
6949
|
-
offset += chunk.length;
|
|
6950
|
-
}
|
|
6951
|
-
const ck = makeKey(pathname, acceptEncoding);
|
|
6952
|
-
const cacheHeaders = {
|
|
6953
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
6954
|
-
"Cache-Control": cacheControlHeader
|
|
6955
|
-
};
|
|
6956
|
-
if (set.headers.link) {
|
|
6957
|
-
cacheHeaders.Link = set.headers.link;
|
|
6958
|
-
}
|
|
6959
|
-
htmlCache.set(ck, {
|
|
6960
|
-
status,
|
|
6961
|
-
headers: cacheHeaders,
|
|
6962
|
-
body: fullHtml,
|
|
6963
|
-
exp: Date.now() + SSR_HTML_TTL_MS
|
|
6964
|
-
});
|
|
6965
|
-
} catch (e) {
|
|
6966
|
-
console.error("[reroute] Failed to cache stream:", e);
|
|
6967
|
-
}
|
|
6968
|
-
}
|
|
6969
|
-
}));
|
|
6970
|
-
set.status = status;
|
|
6971
|
-
const tBeforeResponse = debug ? performance.now() : 0;
|
|
6972
|
-
response = new Response(cachingStream, {
|
|
6973
|
-
status,
|
|
6974
|
-
headers: {
|
|
6975
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
6976
|
-
"Cache-Control": cacheControlHeader,
|
|
6977
|
-
"Reroute-Cache": "MISS"
|
|
6978
|
-
}
|
|
6979
|
-
});
|
|
6980
|
-
if (debug)
|
|
6981
|
-
console.log(`[SSR] ${pathname} - Response created (cached stream): ${(performance.now() - t0).toFixed(2)}ms (creation: ${(performance.now() - tBeforeResponse).toFixed(2)}ms)`);
|
|
6982
|
-
} else {
|
|
6983
|
-
if (debug)
|
|
6984
|
-
console.log(`[SSR] ${pathname} - creating direct stream response: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
6985
|
-
set.status = status;
|
|
6986
|
-
const tBeforeResponse = debug ? performance.now() : 0;
|
|
6987
|
-
response = new Response(stream2, {
|
|
6988
|
-
status,
|
|
6989
|
-
headers: {
|
|
6990
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
6991
|
-
"Cache-Control": cacheControlHeader,
|
|
6992
|
-
"Reroute-Cache": "MISS"
|
|
6993
|
-
}
|
|
6994
|
-
});
|
|
6995
|
-
if (debug)
|
|
6996
|
-
console.log(`[SSR] ${pathname} - Response created (direct stream): ${(performance.now() - t0).toFixed(2)}ms (creation: ${(performance.now() - tBeforeResponse).toFixed(2)}ms)`);
|
|
7323
|
+
if (!isWatchMode && SSR_HTML_TTL_MS > 0 && status >= 200 && status < 300) {
|
|
7324
|
+
try {
|
|
7325
|
+
const ck = makeKey(pathname, acceptEncoding);
|
|
7326
|
+
htmlCache.set(ck, {
|
|
7327
|
+
status,
|
|
7328
|
+
headers: resHeaders,
|
|
7329
|
+
body,
|
|
7330
|
+
exp: Date.now() + SSR_HTML_TTL_MS
|
|
7331
|
+
});
|
|
7332
|
+
} catch {}
|
|
6997
7333
|
}
|
|
6998
7334
|
}
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
"reroute.ssr.enabled": true,
|
|
7008
|
-
"reroute.ssr.streaming": false,
|
|
7009
|
-
"reroute.cache.hit": false,
|
|
7010
|
-
"reroute.pathname": pathname
|
|
7011
|
-
});
|
|
7012
|
-
const result2 = await renderSSRDocument({
|
|
7013
|
-
pathname: fullPath,
|
|
7014
|
-
rootComponent,
|
|
7015
|
-
clientDir,
|
|
7016
|
-
cwd,
|
|
7017
|
-
isWatchMode,
|
|
7018
|
-
bundleUrl,
|
|
7019
|
-
head,
|
|
7020
|
-
lang,
|
|
7021
|
-
appId,
|
|
7022
|
-
maxAge,
|
|
7023
|
-
searchParams,
|
|
7024
|
-
ogConfig: options.ogConfig
|
|
7025
|
-
});
|
|
7026
|
-
otel?.setAttributes({
|
|
7027
|
-
"http.response.status_code": result2.status
|
|
7028
|
-
});
|
|
7029
|
-
return result2;
|
|
7030
|
-
};
|
|
7031
|
-
const result = otel ? await otel.record("reroute.ssr.render_sync", renderFn) : await renderFn();
|
|
7032
|
-
html2 = result.html;
|
|
7033
|
-
status = result.status;
|
|
7034
|
-
} catch (ssrError) {
|
|
7035
|
-
console.error("[reroute] SSR rendering failed, returning error page:", ssrError);
|
|
7036
|
-
const errorHtml = `<!DOCTYPE html>
|
|
7037
|
-
<html lang="en">
|
|
7038
|
-
<head>
|
|
7039
|
-
<meta charset="UTF-8">
|
|
7040
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7041
|
-
<title>Error</title>
|
|
7042
|
-
<style>
|
|
7043
|
-
body { font-family: system-ui, sans-serif; padding: 2rem; background: #111; color: #fff; }
|
|
7044
|
-
h1 { color: #f87171; }
|
|
7045
|
-
pre { background: #222; padding: 1rem; border-radius: 0.5rem; overflow: auto; }
|
|
7046
|
-
</style>
|
|
7047
|
-
</head>
|
|
7048
|
-
<body>
|
|
7049
|
-
<h1>Server Error</h1>
|
|
7050
|
-
<p>An error occurred while rendering this page.</p>
|
|
7051
|
-
${isWatchMode ? `<pre>${ssrError instanceof Error ? ssrError.stack : String(ssrError)}</pre>` : ""}
|
|
7052
|
-
<script type="module" src="${bundleUrl}"></script>
|
|
7053
|
-
</body>
|
|
7054
|
-
</html>`;
|
|
7055
|
-
return new Response(errorHtml, {
|
|
7056
|
-
status: 500,
|
|
7057
|
-
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
7058
|
-
});
|
|
7059
|
-
}
|
|
7060
|
-
const { body, extraHeaders } = compression2 ? gzipIfAccepted(html2, "text/html; charset=utf-8", acceptEncoding) : { body: html2, extraHeaders: {} };
|
|
7061
|
-
const resHeaders = {
|
|
7062
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
7063
|
-
"Cache-Control": cacheControlHeader,
|
|
7064
|
-
"Reroute-Cache": "MISS",
|
|
7065
|
-
...extraHeaders
|
|
7066
|
-
};
|
|
7067
|
-
if (set.headers.link) {
|
|
7068
|
-
resHeaders.Link = set.headers.link;
|
|
7069
|
-
}
|
|
7070
|
-
set.status = status;
|
|
7071
|
-
response = new Response(body, {
|
|
7072
|
-
status,
|
|
7073
|
-
headers: resHeaders
|
|
7074
|
-
});
|
|
7075
|
-
if (!isWatchMode && SSR_HTML_TTL_MS > 0 && status >= 200 && status < 300) {
|
|
7076
|
-
try {
|
|
7077
|
-
const ck = makeKey(pathname, acceptEncoding);
|
|
7078
|
-
htmlCache.set(ck, {
|
|
7079
|
-
status,
|
|
7080
|
-
headers: resHeaders,
|
|
7081
|
-
body,
|
|
7082
|
-
exp: Date.now() + SSR_HTML_TTL_MS
|
|
7083
|
-
});
|
|
7084
|
-
} catch {}
|
|
7085
|
-
}
|
|
7086
|
-
}
|
|
7087
|
-
const tBeforeReturn = debug ? performance.now() : 0;
|
|
7088
|
-
if (debug)
|
|
7089
|
-
console.log(`[SSR] ${pathname} - about to return response: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7090
|
-
const returnValue = response;
|
|
7091
|
-
if (debug)
|
|
7092
|
-
console.log(`[SSR] ${pathname} - response returned: ${(performance.now() - t0).toFixed(2)}ms (return overhead: ${(performance.now() - tBeforeReturn).toFixed(2)}ms)`);
|
|
7093
|
-
return returnValue;
|
|
7335
|
+
const tBeforeReturn = debug ? performance.now() : 0;
|
|
7336
|
+
if (debug)
|
|
7337
|
+
console.log(`[SSR] ${pathname} - about to return response: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
7338
|
+
const returnValue = response;
|
|
7339
|
+
if (debug)
|
|
7340
|
+
console.log(`[SSR] ${pathname} - response returned: ${(performance.now() - t0).toFixed(2)}ms (return overhead: ${(performance.now() - tBeforeReturn).toFixed(2)}ms)`);
|
|
7341
|
+
return returnValue;
|
|
7342
|
+
});
|
|
7094
7343
|
};
|
|
7095
7344
|
const allRoutes = [...staticRoutes, ...contentRoutes, ...dynamicRoutes];
|
|
7096
7345
|
for (const path2 of allRoutes) {
|
|
@@ -7101,12 +7350,19 @@ function registerSSRRoutes(app, options) {
|
|
|
7101
7350
|
|
|
7102
7351
|
// packages/elysia/src/routes/static.ts
|
|
7103
7352
|
init_core();
|
|
7353
|
+
import { trace as trace5 } from "@opentelemetry/api";
|
|
7104
7354
|
import { NotFoundError as NotFoundError12 } from "elysia";
|
|
7105
|
-
|
|
7355
|
+
var otelAvailable4;
|
|
7356
|
+
function isOtelAvailable4() {
|
|
7357
|
+
if (otelAvailable4 !== undefined)
|
|
7358
|
+
return otelAvailable4;
|
|
7106
7359
|
try {
|
|
7107
|
-
|
|
7360
|
+
__require("@opentelemetry/api");
|
|
7361
|
+
otelAvailable4 = true;
|
|
7362
|
+
return true;
|
|
7108
7363
|
} catch {
|
|
7109
|
-
|
|
7364
|
+
otelAvailable4 = false;
|
|
7365
|
+
return false;
|
|
7110
7366
|
}
|
|
7111
7367
|
}
|
|
7112
7368
|
function registerStaticRoutes(app, options) {
|
|
@@ -7123,21 +7379,18 @@ function registerStaticRoutes(app, options) {
|
|
|
7123
7379
|
compression: compression2 = true
|
|
7124
7380
|
} = options;
|
|
7125
7381
|
function setOtelAttributes(statusCode, cachHit, requestPath, encoding, reason) {
|
|
7126
|
-
|
|
7127
|
-
|
|
7382
|
+
if (!isOtelAvailable4())
|
|
7383
|
+
return;
|
|
7384
|
+
const currentSpan = trace5.getActiveSpan();
|
|
7128
7385
|
const attrs = {
|
|
7129
|
-
"http.request.method": "GET",
|
|
7130
|
-
"http.response.status_code": statusCode,
|
|
7131
7386
|
"reroute.static.path": requestPath
|
|
7132
7387
|
};
|
|
7133
7388
|
if (statusCode === 200) {
|
|
7134
|
-
attrs["reroute.
|
|
7389
|
+
attrs["reroute.cache.hit"] = cachHit;
|
|
7135
7390
|
if (encoding)
|
|
7136
|
-
attrs["reroute.
|
|
7137
|
-
} else if (
|
|
7138
|
-
attrs["reroute.
|
|
7139
|
-
if (reason)
|
|
7140
|
-
attrs["reroute.static.reason"] = reason;
|
|
7391
|
+
attrs["reroute.encoding"] = encoding;
|
|
7392
|
+
} else if (reason) {
|
|
7393
|
+
attrs["reroute.error.reason"] = reason;
|
|
7141
7394
|
}
|
|
7142
7395
|
currentSpan?.setAttributes(attrs);
|
|
7143
7396
|
}
|
|
@@ -7188,31 +7441,25 @@ function registerStaticRoutes(app, options) {
|
|
|
7188
7441
|
}
|
|
7189
7442
|
});
|
|
7190
7443
|
fileCache.set(cacheKey, response);
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
"reroute.static.compressed": !!extraHeaders["Content-Encoding"]
|
|
7201
|
-
});
|
|
7444
|
+
if (isOtelAvailable4()) {
|
|
7445
|
+
const currentSpan = trace5.getActiveSpan();
|
|
7446
|
+
currentSpan?.setAttributes({
|
|
7447
|
+
"reroute.static.path": requestPath,
|
|
7448
|
+
"reroute.content.type": contentType,
|
|
7449
|
+
"reroute.cache.hit": false,
|
|
7450
|
+
"reroute.compressed": !!extraHeaders["Content-Encoding"]
|
|
7451
|
+
});
|
|
7452
|
+
}
|
|
7202
7453
|
return response.clone();
|
|
7203
7454
|
} catch (error) {
|
|
7204
7455
|
if (error instanceof NotFoundError12) {
|
|
7205
7456
|
throw error;
|
|
7206
7457
|
}
|
|
7207
7458
|
console.error(`[reroute] Error serving ${filePath}:`, error);
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
"http.response.status_code": 500,
|
|
7213
|
-
"reroute.static.error": true,
|
|
7214
|
-
"reroute.static.path": requestPath
|
|
7215
|
-
});
|
|
7459
|
+
if (isOtelAvailable4()) {
|
|
7460
|
+
const currentSpan = trace5.getActiveSpan();
|
|
7461
|
+
currentSpan?.setAttribute("reroute.static.path", requestPath);
|
|
7462
|
+
}
|
|
7216
7463
|
throw new NotFoundError12;
|
|
7217
7464
|
}
|
|
7218
7465
|
});
|
|
@@ -7567,4 +7814,4 @@ export {
|
|
|
7567
7814
|
reroute
|
|
7568
7815
|
};
|
|
7569
7816
|
|
|
7570
|
-
//# debugId=
|
|
7817
|
+
//# debugId=2F8AA864C3640F9564756E2164756E21
|