@timber-js/app 0.2.0-alpha.151 → 0.2.0-alpha.153

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 (58) hide show
  1. package/dist/_chunks/actions-8lJZYYGq.js +298 -0
  2. package/dist/_chunks/actions-8lJZYYGq.js.map +1 -0
  3. package/dist/_chunks/{cache-api-Co-yI-gP.js → cache-api-e1E4i3Vy.js} +3 -26
  4. package/dist/_chunks/cache-api-e1E4i3Vy.js.map +1 -0
  5. package/dist/_chunks/{cli-schema-sync-DJDdyEae.js → cli-schema-sync-ChsRzw8o.js} +2 -2
  6. package/dist/_chunks/{cli-schema-sync-DJDdyEae.js.map → cli-schema-sync-ChsRzw8o.js.map} +1 -1
  7. package/dist/_chunks/{cli-schema-sync-D_IhHEUW.js → cli-schema-sync-D4urWkeV.js} +1 -1
  8. package/dist/_chunks/{actions-a0RczDnB.js → logger-DvmCWhN9.js} +665 -274
  9. package/dist/_chunks/logger-DvmCWhN9.js.map +1 -0
  10. package/dist/_chunks/plugin-context-GfDWsdd2.js.map +1 -1
  11. package/dist/_chunks/{walkers-DvWDj453.js → walkers-DZuFKqFX.js} +2 -2
  12. package/dist/_chunks/{walkers-DvWDj453.js.map → walkers-DZuFKqFX.js.map} +1 -1
  13. package/dist/cache/index.js +1 -1
  14. package/dist/cli.js +1 -1
  15. package/dist/client/browser-dev.d.ts +3 -0
  16. package/dist/client/browser-dev.d.ts.map +1 -1
  17. package/dist/config-types.d.ts +8 -0
  18. package/dist/config-types.d.ts.map +1 -1
  19. package/dist/config-validation.d.ts.map +1 -1
  20. package/dist/index.js +193 -48
  21. package/dist/index.js.map +1 -1
  22. package/dist/plugin-context.d.ts +9 -0
  23. package/dist/plugin-context.d.ts.map +1 -1
  24. package/dist/plugins/build-report.d.ts +13 -0
  25. package/dist/plugins/build-report.d.ts.map +1 -1
  26. package/dist/plugins/chunks.d.ts +11 -4
  27. package/dist/plugins/chunks.d.ts.map +1 -1
  28. package/dist/plugins/client-chunks.d.ts +23 -22
  29. package/dist/plugins/client-chunks.d.ts.map +1 -1
  30. package/dist/routing/index.js +2 -2
  31. package/dist/server/index.js +2 -2
  32. package/dist/server/internal.js +65 -2
  33. package/dist/server/internal.js.map +1 -1
  34. package/dist/server/logger.d.ts.map +1 -1
  35. package/dist/server/pipeline.d.ts.map +1 -1
  36. package/dist/server/primitives.d.ts +8 -0
  37. package/dist/server/primitives.d.ts.map +1 -1
  38. package/dist/server/route-element-builder.d.ts.map +1 -1
  39. package/dist/server/stream-utils.d.ts +11 -0
  40. package/dist/server/stream-utils.d.ts.map +1 -1
  41. package/package.json +4 -4
  42. package/src/client/browser-dev.ts +3 -0
  43. package/src/config-types.ts +8 -0
  44. package/src/config-validation.ts +16 -0
  45. package/src/index.ts +2 -2
  46. package/src/plugin-context.ts +9 -0
  47. package/src/plugins/build-report.ts +105 -10
  48. package/src/plugins/chunks.ts +74 -5
  49. package/src/plugins/client-chunks.ts +73 -42
  50. package/src/server/logger.ts +5 -0
  51. package/src/server/pipeline.ts +13 -0
  52. package/src/server/primitives.ts +29 -0
  53. package/src/server/route-element-builder.ts +4 -1
  54. package/src/server/stream-utils.ts +73 -0
  55. package/dist/_chunks/actions-a0RczDnB.js.map +0 -1
  56. package/dist/_chunks/cache-api-Co-yI-gP.js.map +0 -1
  57. package/dist/_chunks/logger-CM0clugc.js +0 -645
  58. package/dist/_chunks/logger-CM0clugc.js.map +0 -1
@@ -1,9 +1,567 @@
1
- import { A as requestContextAls, D as withSpan, g as isDebug, j as revalidationAls } from "./logger-CM0clugc.js";
2
1
  import { t as _setGetSearchParamsFn } from "./define-CFmvb4Bt.js";
3
2
  import { t as _setGetSegmentParamsFn } from "./define-Bssfp6ot.js";
4
3
  import { n as assertValidCookieOptions, r as assertValidCookieValue, t as assertValidCookieName } from "./validation-taUkvA4Q.js";
5
- import { a as getWaitUntil, t as cache } from "./cache-api-Co-yI-gP.js";
6
4
  import { a as mergePreservedSearchParams, r as validateExternalRedirectUrl, t as assertRelativeRedirectPath } from "./href-validation-FiA_rToW.js";
5
+ import { randomUUID } from "node:crypto";
6
+ import { AsyncLocalStorage } from "node:async_hooks";
7
+ //#region src/server/als-registry.ts
8
+ /**
9
+ * Centralized AsyncLocalStorage registry for server-side per-request state.
10
+ *
11
+ * ALL ALS instances used by the server framework live here. Individual
12
+ * modules (request-context.ts, tracing.ts, actions.ts, etc.) import from
13
+ * this registry and re-export public accessor functions.
14
+ *
15
+ * Why: ALS instances require singleton semantics — if two copies of the
16
+ * same ALS exist (one from a relative import, one from a barrel import,
17
+ * or the same file re-evaluated by Vite after an HMR invalidation), one
18
+ * module writes to its copy and another reads from an empty copy.
19
+ * Centralizing ALS creation in a single module + anchoring each instance
20
+ * on `globalThis` under a `Symbol.for(...)` key eliminates this class of
21
+ * bug, including the Vite-dev case where module instance split would
22
+ * otherwise hand two copies of this file out of a single evaluation cycle.
23
+ *
24
+ * The `timber-shims` plugin remaps `@timber-js/app/server` to src/ in
25
+ * RSC and SSR environments so import-specifier paths converge here, and
26
+ * the `globalThis[SYMBOL_FOR]` anchor below closes the remaining gap: any
27
+ * second evaluation of this module picks up the ALS the first evaluation
28
+ * already stored rather than instantiating a fresh one. Same pattern the
29
+ * Cloudflare bindings ALS uses in `adapters/cloudflare.ts`.
30
+ *
31
+ * DO NOT create ALS instances outside this file. If you need a new ALS,
32
+ * add it here and import from `./als-registry.js` in the consuming module.
33
+ * Inside this file, always route through `getOrCreateAls(symbol)` — a raw
34
+ * `new AsyncLocalStorage()` reintroduces the instance-split hazard.
35
+ *
36
+ * See design/18-build-system.md §"Module Singleton Strategy" and
37
+ * §"Singleton State Registry". Regression test:
38
+ * `tests/als-registry-singleton.test.ts`.
39
+ */
40
+ /**
41
+ * Return a process-wide singleton `AsyncLocalStorage` keyed by `symbol`.
42
+ *
43
+ * `Symbol.for(...)` keys live in the cross-realm symbol registry, and
44
+ * `globalThis` is shared across every module evaluation inside the same
45
+ * Node.js process. Together they give a stable anchor that survives
46
+ * re-evaluation of this file — the second evaluation observes the
47
+ * `globalThis[symbol]` slot already populated by the first and hands
48
+ * back the identical ALS instance.
49
+ */
50
+ function getOrCreateAls(symbol) {
51
+ const g = globalThis;
52
+ const existing = g[symbol];
53
+ if (existing instanceof AsyncLocalStorage) return existing;
54
+ const created = new AsyncLocalStorage();
55
+ g[symbol] = created;
56
+ return created;
57
+ }
58
+ /** @internal — import via request-context.ts public API */
59
+ var requestContextAls = getOrCreateAls(Symbol.for("timber:request-context-als"));
60
+ /** @internal — import via tracing.ts public API */
61
+ var traceAls = getOrCreateAls(Symbol.for("timber:trace-als"));
62
+ /** @internal — import via server-timing.ts public API */
63
+ var timingAls = getOrCreateAls(Symbol.for("timber:timing-als"));
64
+ /** @internal — import via actions.ts public API */
65
+ var revalidationAls = getOrCreateAls(Symbol.for("timber:revalidation-als"));
66
+ /** @internal — import via form-flash.ts public API */
67
+ var formFlashAls = getOrCreateAls(Symbol.for("timber:form-flash-als"));
68
+ /** @internal — import via early-hints-sender.ts public API */
69
+ var earlyHintsSenderAls = getOrCreateAls(Symbol.for("timber:early-hints-sender-als"));
70
+ /** @internal — import via waituntil-bridge.ts public API */
71
+ var waitUntilAls = getOrCreateAls(Symbol.for("timber:wait-until-als"));
72
+ //#endregion
73
+ //#region src/server/tracing.ts
74
+ /**
75
+ * Tracing — per-request trace ID via AsyncLocalStorage, OTEL span helpers.
76
+ *
77
+ * getTraceId() is always available in server code (middleware, access, components, actions).
78
+ * Returns a 32-char lowercase hex string — the OTEL trace ID when an SDK is active,
79
+ * or a crypto.randomUUID()-derived fallback otherwise.
80
+ *
81
+ * See design/17-logging.md §"trace_id is Always Set"
82
+ */
83
+ /**
84
+ * Returns the current request's trace ID — always a 32-char lowercase hex string.
85
+ *
86
+ * With OTEL: the real OTEL trace ID (matches Jaeger/Honeycomb/Datadog).
87
+ * Without OTEL: crypto.randomUUID() with hyphens stripped.
88
+ *
89
+ * Throws if called outside a request context (no ALS store).
90
+ */
91
+ function getTraceId() {
92
+ const store = traceAls.getStore();
93
+ if (!store) throw new Error("[timber] getTraceId() called outside of a request context. It can only be used in middleware, access checks, server components, and server actions.");
94
+ return store.traceId;
95
+ }
96
+ /**
97
+ * Returns the current OTEL span ID if available, undefined otherwise.
98
+ */
99
+ function getSpanId() {
100
+ return traceAls.getStore()?.spanId;
101
+ }
102
+ /**
103
+ * Generate a 32-char lowercase hex ID from crypto.randomUUID().
104
+ * Same format as OTEL trace IDs — zero-friction upgrade path.
105
+ */
106
+ function generateTraceId() {
107
+ return randomUUID().replace(/-/g, "");
108
+ }
109
+ /**
110
+ * Run a callback within a trace context. Used by the pipeline to establish
111
+ * per-request ALS scope.
112
+ */
113
+ function runWithTraceId(id, fn) {
114
+ return traceAls.run({ traceId: id }, fn);
115
+ }
116
+ /**
117
+ * Replace the trace ID in the current ALS store. Used when OTEL creates
118
+ * a root span and we want to switch from the UUID fallback to the real
119
+ * OTEL trace ID.
120
+ */
121
+ function replaceTraceId(newTraceId, newSpanId) {
122
+ const store = traceAls.getStore();
123
+ if (store) {
124
+ store.traceId = newTraceId;
125
+ store.spanId = newSpanId;
126
+ }
127
+ }
128
+ /**
129
+ * Update the span ID in the current ALS store. Used when entering a new
130
+ * OTEL span to keep log–trace correlation accurate.
131
+ */
132
+ function updateSpanId(newSpanId) {
133
+ const store = traceAls.getStore();
134
+ if (store) store.spanId = newSpanId;
135
+ }
136
+ /**
137
+ * Get the current trace store, or undefined if outside a request context.
138
+ * Framework-internal — use getTraceId()/getSpanId() in user code.
139
+ */
140
+ function getTraceStore() {
141
+ return traceAls.getStore();
142
+ }
143
+ /**
144
+ * Attempt to get the @opentelemetry/api tracer. Returns undefined if the
145
+ * package is not installed or no SDK is registered.
146
+ *
147
+ * timber.js depends on @opentelemetry/api as the vendor-neutral interface.
148
+ * The API is a no-op by default — spans are only emitted when the developer
149
+ * initializes an SDK in register().
150
+ */
151
+ var _otelApi;
152
+ async function getOtelApi() {
153
+ if (_otelApi === void 0) try {
154
+ _otelApi = await import("@opentelemetry/api");
155
+ } catch {
156
+ _otelApi = null;
157
+ }
158
+ return _otelApi;
159
+ }
160
+ /** OTEL tracer instance, lazily created. */
161
+ var _tracer;
162
+ /**
163
+ * Get the timber.js OTEL tracer. Returns null if @opentelemetry/api is not available.
164
+ */
165
+ async function getTracer() {
166
+ if (_tracer === void 0) {
167
+ const api = await getOtelApi();
168
+ if (api) _tracer = api.trace.getTracer("timber.js");
169
+ else _tracer = null;
170
+ }
171
+ return _tracer;
172
+ }
173
+ /**
174
+ * Run a function within an OTEL span. If OTEL is not available, runs the function
175
+ * directly without any span overhead.
176
+ *
177
+ * Automatically:
178
+ * - Creates the span as a child of the current context
179
+ * - Updates the ALS span ID for log–trace correlation
180
+ * - Ends the span when the function completes
181
+ * - Records exceptions on error
182
+ */
183
+ async function withSpan(name, attributes, fn) {
184
+ const tracer = await getTracer();
185
+ if (!tracer) return fn();
186
+ const api = await getOtelApi();
187
+ return tracer.startActiveSpan(name, { attributes }, async (span) => {
188
+ const prevSpanId = getSpanId();
189
+ updateSpanId(span.spanContext().spanId);
190
+ try {
191
+ const result = await fn();
192
+ span.setStatus({ code: api.SpanStatusCode.OK });
193
+ return result;
194
+ } catch (error) {
195
+ span.setStatus({ code: api.SpanStatusCode.ERROR });
196
+ if (error instanceof Error) span.recordException(error);
197
+ throw error;
198
+ } finally {
199
+ span.end();
200
+ updateSpanId(prevSpanId);
201
+ }
202
+ });
203
+ }
204
+ /**
205
+ * Set an attribute on the current active span (if any).
206
+ * Used for setting span attributes after span creation (e.g. timber.result on access spans).
207
+ */
208
+ async function setSpanAttribute(key, value) {
209
+ const api = await getOtelApi();
210
+ if (!api) return;
211
+ const activeSpan = api.trace.getActiveSpan();
212
+ if (activeSpan) activeSpan.setAttribute(key, value);
213
+ }
214
+ /**
215
+ * Add a span event to the current active span (if any).
216
+ * Used for timber.cache HIT/MISS events — recorded as span events, not child spans.
217
+ */
218
+ async function addSpanEvent(name, attributes) {
219
+ const api = await getOtelApi();
220
+ if (!api) return;
221
+ const activeSpan = api.trace.getActiveSpan();
222
+ if (activeSpan) activeSpan.addEvent(name, attributes);
223
+ }
224
+ /**
225
+ * Fire-and-forget span event — no await, no microtask overhead.
226
+ *
227
+ * Used on the cache hot path where awaiting addSpanEvent creates an
228
+ * unnecessary microtask per cache operation. If OTEL is not loaded yet,
229
+ * the event is silently dropped (acceptable for diagnostics).
230
+ *
231
+ * See TIM-370 for perf motivation.
232
+ */
233
+ function addSpanEventSync(name, attributes) {
234
+ if (!_otelApi) return;
235
+ const activeSpan = _otelApi.trace.getActiveSpan();
236
+ if (activeSpan) activeSpan.addEvent(name, attributes);
237
+ }
238
+ /**
239
+ * Try to extract the OTEL trace ID from the current active span context.
240
+ * Returns undefined if OTEL is not active or no span exists.
241
+ */
242
+ async function getOtelTraceId() {
243
+ const api = await getOtelApi();
244
+ if (!api) return void 0;
245
+ const activeSpan = api.trace.getActiveSpan();
246
+ if (!activeSpan) return void 0;
247
+ const ctx = activeSpan.spanContext();
248
+ if (!ctx.traceId || ctx.traceId === "00000000000000000000000000000000") return;
249
+ return {
250
+ traceId: ctx.traceId,
251
+ spanId: ctx.spanId
252
+ };
253
+ }
254
+ //#endregion
255
+ //#region src/server/debug.ts
256
+ /**
257
+ * Runtime debug flag for timber.js.
258
+ *
259
+ * Two distinct functions for two distinct security levels:
260
+ *
261
+ * ## `isDebug()` — server-side logging only
262
+ *
263
+ * Returns true when timber's debug/warning messages should be written to
264
+ * stderr / the server console. This NEVER affects what is sent to the
265
+ * client (no error details, no timing headers, no stack traces).
266
+ *
267
+ * Active when any of:
268
+ * - `NODE_ENV !== 'production'` (standard dev mode)
269
+ * - `TIMBER_DEBUG` env var is set to a truthy value at runtime
270
+ * - `timber.config.ts` has `debug: true`
271
+ *
272
+ * ## `isDevMode()` — client-visible dev behavior
273
+ *
274
+ * Returns true ONLY when `NODE_ENV !== 'production'`. This gates anything
275
+ * that changes what clients can observe:
276
+ * - Dev error pages with stack traces (fallback-error.ts)
277
+ * - Detailed Server-Timing headers (pipeline.ts)
278
+ * - Error messages in action INTERNAL_ERROR payloads (action-client.ts)
279
+ * - Pipeline error handler wiring (Vite overlay)
280
+ *
281
+ * `isDevMode()` is statically replaced in production builds → the guarded
282
+ * code is tree-shaken to zero bytes. TIMBER_DEBUG cannot enable it.
283
+ *
284
+ * Usage:
285
+ * In Cloudflare Workers wrangler.toml:
286
+ * [vars]
287
+ * TIMBER_DEBUG = "1"
288
+ *
289
+ * In Node.js:
290
+ * TIMBER_DEBUG=1 node server.js
291
+ *
292
+ * In timber.config.ts:
293
+ * export default { debug: true }
294
+ *
295
+ * See design/13-security.md for the security taxonomy.
296
+ * See design/18-build-system.md for build pipeline details.
297
+ */
298
+ /**
299
+ * Check if the application is running in development mode.
300
+ *
301
+ * This is the ONLY function that should gate client-visible dev behavior:
302
+ * - Dev error pages with stack traces
303
+ * - Server-Timing mode default (`'detailed'` in dev, `'total'` in prod)
304
+ * - Error messages in action `INTERNAL_ERROR` payloads
305
+ * - Pipeline error handler wiring (Vite overlay)
306
+ *
307
+ * Returns `process.env.NODE_ENV !== 'production'`, which is statically
308
+ * replaced by the bundler in production builds. Code guarded by this
309
+ * function is tree-shaken to zero bytes in production.
310
+ *
311
+ * TIMBER_DEBUG does NOT enable this — that would leak server internals
312
+ * to clients. Use `isDebug()` for server-side-only logging.
313
+ */
314
+ function isDevMode() {
315
+ return process.env.NODE_ENV !== "production";
316
+ }
317
+ /**
318
+ * Config-level debug override. Set via `setDebugFromConfig()` during
319
+ * initialization when timber.config.ts has `debug: true`.
320
+ */
321
+ var _configDebug = false;
322
+ /**
323
+ * Check if timber debug logging is active (server-side only).
324
+ *
325
+ * Returns true if ANY of these conditions hold:
326
+ * - NODE_ENV is not 'production' (standard dev mode)
327
+ * - TIMBER_DEBUG environment variable is set to a truthy value at runtime
328
+ * - timber.config.ts has `debug: true`
329
+ *
330
+ * This function controls ONLY server-side logging — messages written to
331
+ * stderr or the server console. It NEVER affects client-visible behavior
332
+ * (error pages, response headers, action payloads). For client-visible
333
+ * behavior, use `isDevMode()`.
334
+ *
335
+ * The TIMBER_DEBUG check is deliberately written as a dynamic property
336
+ * access so bundlers cannot statically replace it.
337
+ */
338
+ function isDebug() {
339
+ if (process.env.NODE_ENV !== "production") return true;
340
+ if (_configDebug) return true;
341
+ return _readTimberDebugEnv();
342
+ }
343
+ /**
344
+ * Read TIMBER_DEBUG from the environment at runtime.
345
+ *
346
+ * Extracted to a separate function to:
347
+ * 1. Prevent bundler inlining (cross-module function calls are not inlined)
348
+ * 2. Handle platforms where `process` may not exist (Cloudflare Workers)
349
+ * 3. Support globalThis.__TIMBER_DEBUG for programmatic control
350
+ */
351
+ function _readTimberDebugEnv() {
352
+ if (globalThis.__TIMBER_DEBUG) return true;
353
+ try {
354
+ const val = typeof process !== "undefined" && process.env ? process.env["TIMBER_DEBUG"] : void 0;
355
+ if (val && val !== "0" && val !== "false") return true;
356
+ } catch {}
357
+ return false;
358
+ }
359
+ //#endregion
360
+ //#region src/server/error-formatter.ts
361
+ /**
362
+ * Error Formatter — rewrites SSR/RSC error messages to surface user code.
363
+ *
364
+ * When React or Vite throw errors during SSR, stack traces reference
365
+ * vendored dependency paths (e.g. `.vite/deps_ssr/@vitejs_plugin-rsc_vendor_...`)
366
+ * and mangled export names (`__vite_ssr_export_default__`). This module
367
+ * rewrites error messages and stack traces to point at user code instead.
368
+ *
369
+ * Dev-only — in production, errors go through the structured logger
370
+ * without formatting.
371
+ */
372
+ /**
373
+ * Patterns that identify internal Vite/RSC vendor paths in stack traces.
374
+ * These are replaced with human-readable labels.
375
+ */
376
+ var VENDOR_PATH_PATTERNS = [
377
+ {
378
+ pattern: /node_modules\/\.vite\/deps_ssr\/@vitejs_plugin-rsc_vendor_react-server-dom[^\s)]+/g,
379
+ replacement: "<react-server-dom>"
380
+ },
381
+ {
382
+ pattern: /node_modules\/\.vite\/deps_ssr\/@vitejs_plugin-rsc_vendor[^\s)]+/g,
383
+ replacement: "<rsc-vendor>"
384
+ },
385
+ {
386
+ pattern: /node_modules\/\.vite\/deps_ssr\/[^\s)]+/g,
387
+ replacement: "<vite-dep>"
388
+ },
389
+ {
390
+ pattern: /node_modules\/\.vite\/deps\/[^\s)]+/g,
391
+ replacement: "<vite-dep>"
392
+ }
393
+ ];
394
+ /**
395
+ * Patterns that identify Vite-mangled export names in error messages.
396
+ */
397
+ var MANGLED_NAME_PATTERNS = [{
398
+ pattern: /__vite_ssr_export_default__/g,
399
+ replacement: "<default export>"
400
+ }, {
401
+ pattern: /__vite_ssr_export_(\w+)__/g,
402
+ replacement: "<export $1>"
403
+ }];
404
+ /**
405
+ * Rewrite an error's message and stack to replace internal Vite paths
406
+ * and mangled names with human-readable labels.
407
+ */
408
+ function formatSsrError(error) {
409
+ if (!(error instanceof Error)) return String(error);
410
+ let message = error.message;
411
+ let stack = error.stack ?? "";
412
+ for (const { pattern, replacement } of MANGLED_NAME_PATTERNS) message = message.replace(pattern, replacement);
413
+ for (const { pattern, replacement } of VENDOR_PATH_PATTERNS) stack = stack.replace(pattern, replacement);
414
+ for (const { pattern, replacement } of MANGLED_NAME_PATTERNS) stack = stack.replace(pattern, replacement);
415
+ const hint = extractErrorHint(error.message);
416
+ const parts = [];
417
+ parts.push(message);
418
+ if (hint) parts.push(` → ${hint}`);
419
+ const userFrames = extractUserFrames(stack);
420
+ if (userFrames.length > 0) {
421
+ parts.push("");
422
+ parts.push(" User code in stack:");
423
+ for (const frame of userFrames) parts.push(` ${frame}`);
424
+ }
425
+ return parts.join("\n");
426
+ }
427
+ /**
428
+ * Extract a human-readable hint from common React/RSC error messages.
429
+ *
430
+ * React error messages contain useful information but the surrounding
431
+ * context (vendor paths, mangled names) obscures it. This extracts the
432
+ * actionable part as a one-line hint.
433
+ */
434
+ function extractErrorHint(message) {
435
+ if (message.match(/Functions cannot be passed directly to Client Components/)) {
436
+ const propMatch = message.match(/<[^>]*?\s(\w+)=\{function/);
437
+ if (propMatch) return `Prop "${propMatch[1]}" is a function — mark it "use server" or call it before passing`;
438
+ return "A function prop was passed to a Client Component — mark it \"use server\" or call it before passing";
439
+ }
440
+ if (message.includes("Objects are not valid as a React child")) return "An object was rendered as JSX children — convert to string or extract the value";
441
+ const nullRefMatch = message.match(/Cannot read propert(?:y|ies) of (undefined|null) \(reading '(\w+)'\)/);
442
+ if (nullRefMatch) return `Accessed .${nullRefMatch[2]} on ${nullRefMatch[1]} — check that the value exists`;
443
+ const notFnMatch = message.match(/(\w+) is not a function/);
444
+ if (notFnMatch) return `"${notFnMatch[1]}" is not a function — check imports and exports`;
445
+ if (message.includes("Element type is invalid")) return "A component resolved to undefined/null — check default exports and import paths";
446
+ if (message.includes("Invalid hook call")) return "A hook was called outside of a React component render. If this is a 'use client' component, ensure the directive is at the very top of the file (before any imports) and that @vitejs/plugin-rsc is loaded correctly. Barrel re-exports from non-'use client' files do not propagate the directive.";
447
+ return null;
448
+ }
449
+ /**
450
+ * Extract stack frames that reference user code (not node_modules,
451
+ * not framework internals).
452
+ *
453
+ * Returns at most 5 frames to keep output concise.
454
+ */
455
+ function extractUserFrames(stack) {
456
+ const lines = stack.split("\n");
457
+ const userFrames = [];
458
+ for (const line of lines) {
459
+ const trimmed = line.trim();
460
+ if (!trimmed.startsWith("at ")) continue;
461
+ if (trimmed.includes("node_modules") || trimmed.includes("<react-server-dom>") || trimmed.includes("<rsc-vendor>") || trimmed.includes("<vite-dep>") || trimmed.includes("node:internal")) continue;
462
+ userFrames.push(trimmed);
463
+ if (userFrames.length >= 5) break;
464
+ }
465
+ return userFrames;
466
+ }
467
+ //#endregion
468
+ //#region src/server/default-logger.ts
469
+ /**
470
+ * DefaultLogger — human-readable stderr logging when no custom logger is configured.
471
+ *
472
+ * Ships as the fallback so production deployments always have error visibility,
473
+ * even without an `instrumentation.ts` logger export. Output is one line per
474
+ * event, designed for `fly logs`, `kubectl logs`, Cloudflare dashboard tails, etc.
475
+ *
476
+ * Format:
477
+ * [timber] ERROR message key=value key=value trace_id=4bf92f35
478
+ * [timber] WARN message key=value key=value trace_id=4bf92f35
479
+ * [timber] INFO message method=GET path=/dashboard status=200 durationMs=43 trace_id=4bf92f35
480
+ *
481
+ * Behavior:
482
+ * - Suppressed entirely in dev mode (dev logging handles all output)
483
+ * - `debug` suppressed unless TIMBER_DEBUG is set
484
+ * - Replaced entirely when a custom logger is set via `setLogger()`
485
+ *
486
+ * See design/17-logging.md §"DefaultLogger"
487
+ */
488
+ /**
489
+ * Format data fields as `key=value` pairs for human-readable output.
490
+ * - `error` key is serialized via formatSsrError for stack trace cleanup
491
+ * - `trace_id` is truncated to 8 chars for readability (full ID in OTEL)
492
+ * - Other values are stringified inline
493
+ */
494
+ function formatDataFields(data) {
495
+ if (!data) return "";
496
+ const parts = [];
497
+ let traceId;
498
+ for (const [key, value] of Object.entries(data)) {
499
+ if (key === "trace_id") {
500
+ traceId = typeof value === "string" ? value : String(value);
501
+ continue;
502
+ }
503
+ if (key === "error") {
504
+ parts.push(`error=${formatSsrError(value)}`);
505
+ continue;
506
+ }
507
+ if (value === void 0 || value === null) continue;
508
+ parts.push(`${key}=${value}`);
509
+ }
510
+ if (traceId) parts.push(`trace_id=${traceId.slice(0, 8)}`);
511
+ return parts.length > 0 ? " " + parts.join(" ") : "";
512
+ }
513
+ /** Pad level string to fixed width for alignment. */
514
+ function padLevel(level) {
515
+ return level.padEnd(5);
516
+ }
517
+ function createDefaultLogger() {
518
+ return {
519
+ error(msg, data) {
520
+ const fields = formatDataFields(data);
521
+ process.stderr.write(`[timber] ${padLevel("ERROR")} ${msg}${fields}\n`);
522
+ },
523
+ warn(msg, data) {
524
+ const fields = formatDataFields(data);
525
+ process.stderr.write(`[timber] ${padLevel("WARN")} ${msg}${fields}\n`);
526
+ },
527
+ info(msg, data) {
528
+ if (isDevMode()) return;
529
+ if (!isDebug()) return;
530
+ const fields = formatDataFields(data);
531
+ process.stderr.write(`[timber] ${padLevel("INFO")} ${msg}${fields}\n`);
532
+ },
533
+ debug(msg, data) {
534
+ if (isDevMode()) return;
535
+ if (!isDebug()) return;
536
+ const fields = formatDataFields(data);
537
+ process.stderr.write(`[timber] ${padLevel("DEBUG")} ${msg}${fields}\n`);
538
+ }
539
+ };
540
+ }
541
+ //#endregion
542
+ //#region src/server/waituntil-bridge.ts
543
+ /**
544
+ * Per-request waitUntil bridge — ALS bridge for platform adapters.
545
+ *
546
+ * The generated entry point (Nitro, Cloudflare) wraps the handler with
547
+ * `runWithWaitUntil`, binding the platform's lifecycle extension function
548
+ * (e.g., h3's `event.waitUntil()` or CF's `ctx.waitUntil()`) for the
549
+ * request duration. The `waitUntil()` primitive reads from this ALS to
550
+ * dispatch background work to the correct platform API.
551
+ *
552
+ * Design doc: design/11-platform.md §"waitUntil()"
553
+ */
554
+ /**
555
+ * Get the current request's waitUntil function, if available.
556
+ *
557
+ * Returns undefined when no platform adapter has installed a waitUntil
558
+ * handler for the current request (e.g., on platforms that don't support
559
+ * lifecycle extension, or outside a request context).
560
+ */
561
+ function getWaitUntil() {
562
+ return waitUntilAls.getStore();
563
+ }
564
+ //#endregion
7
565
  //#region src/server/cookie-parsing.ts
8
566
  /**
9
567
  * Parse a Cookie header string into a Map of name → value pairs.
@@ -701,6 +1259,24 @@ var RedirectSignal = class extends Error {
701
1259
  }
702
1260
  };
703
1261
  /**
1262
+ * Returns true if the error is a framework control-flow signal (RedirectSignal
1263
+ * or DenySignal) rather than a genuine application error. Works both for direct
1264
+ * instances (RSC-side) and deserialized digest errors (SSR cross-boundary).
1265
+ *
1266
+ * See also: isFrameworkSignalError() in client/browser-dev.ts (client-only).
1267
+ */
1268
+ function isControlFlowSignal(error) {
1269
+ if (error instanceof DenySignal || error instanceof RedirectSignal) return true;
1270
+ if (error && typeof error === "object") {
1271
+ const digest = error.digest;
1272
+ if (typeof digest === "string") try {
1273
+ const parsed = JSON.parse(digest);
1274
+ if (parsed && typeof parsed === "object") return parsed.type === "redirect" || parsed.type === "deny";
1275
+ } catch {}
1276
+ }
1277
+ return false;
1278
+ }
1279
+ /**
704
1280
  * Redirect to a relative path. Rejects absolute and protocol-relative URLs.
705
1281
  * Use `redirectExternal()` for external redirects with an allow-list.
706
1282
  *
@@ -808,299 +1384,114 @@ function waitUntil(promise, adapter) {
808
1384
  }
809
1385
  }
810
1386
  //#endregion
811
- //#region src/server/form-data.ts
1387
+ //#region src/server/logger.ts
812
1388
  /**
813
- * FormData preprocessing — schema-agnostic conversion of FormData to typed objects.
814
- *
815
- * FormData is all strings. Schema validation expects typed values. This module
816
- * bridges the gap with intelligent coercion that runs *before* schema validation.
1389
+ * Logger — structured logging with environment-aware formatting.
817
1390
  *
818
- * Inspired by zod-form-data, but schema-agnostic — works with any Standard Schema
819
- * library (Zod, Valibot, ArkType).
1391
+ * timber.js ships a DefaultLogger that writes human-readable lines to stderr
1392
+ * in production. Users can export a custom logger from instrumentation.ts to
1393
+ * replace it with pino, winston, or any TimberLogger-compatible object.
820
1394
  *
821
- * See design/08-forms-and-actions.md §"parseFormData() and coerce helpers"
1395
+ * See design/17-logging.md §"Production Logging"
822
1396
  */
1397
+ var _logger = createDefaultLogger();
823
1398
  /**
824
- * Convert FormData into a plain object with intelligent coercion.
825
- *
826
- * Handles:
827
- * - **Duplicate keys → arrays**: `tags=js&tags=ts` → `{ tags: ["js", "ts"] }`
828
- * - **Nested dot-paths**: `user.name=Alice` → `{ user: { name: "Alice" } }`
829
- * - **Empty strings → undefined**: Enables `.optional()` semantics in schemas
830
- * - **Empty Files → undefined**: File inputs with no selection become `undefined`
831
- * - **Strips `$ACTION_*` fields**: React's internal hidden fields are excluded
1399
+ * Set the user-provided logger. Called by the instrumentation loader
1400
+ * when it finds a `logger` export in instrumentation.ts. Replaces
1401
+ * the DefaultLogger entirely.
832
1402
  */
833
- function parseFormData(formData) {
834
- const flat = {};
835
- for (const key of new Set(formData.keys())) {
836
- if (key.startsWith("$ACTION_")) continue;
837
- if (DANGEROUS_KEYS.has(key)) continue;
838
- const processed = formData.getAll(key).map(normalizeValue);
839
- if (processed.length === 1) flat[key] = processed[0];
840
- else flat[key] = processed.filter((v) => v !== void 0);
841
- }
842
- return expandDotPaths(flat);
1403
+ function setLogger(logger) {
1404
+ _logger = logger;
843
1405
  }
844
1406
  /**
845
- * Normalize a single FormData entry value.
846
- * - Empty strings → undefined (enables .optional() semantics)
847
- * - Empty File objects (no selection) → undefined
848
- * - Everything else passes through as-is
1407
+ * Get the current logger. Always non-null — returns DefaultLogger when
1408
+ * no custom logger is configured.
849
1409
  */
850
- function normalizeValue(value) {
851
- if (typeof value === "string") return value === "" ? void 0 : value;
852
- if (value instanceof File && value.size === 0 && value.name === "") return;
853
- return value;
1410
+ function getLogger() {
1411
+ return _logger;
854
1412
  }
855
1413
  /**
856
- * Expand dot-notation keys into nested objects.
857
- * `{ "user.name": "Alice", "user.age": "30" }` → `{ user: { name: "Alice", age: "30" } }`
858
- *
859
- * Keys without dots are left as-is. Bracket notation (e.g. `items[0]`) is NOT
860
- * supported — use dot notation (`items.0`) instead.
1414
+ * Inject trace_id and span_id into log data for log–trace correlation.
1415
+ * Always injects trace_id (never undefined). Injects span_id only when OTEL is active.
861
1416
  */
862
- function expandDotPaths(flat) {
863
- const result = {};
864
- let hasDotPaths = false;
865
- for (const key of Object.keys(flat)) if (key.includes(".")) {
866
- hasDotPaths = true;
867
- break;
1417
+ function withTraceContext(data) {
1418
+ const store = getTraceStore();
1419
+ const enriched = { ...data };
1420
+ if (store) {
1421
+ enriched.trace_id = store.traceId;
1422
+ if (store.spanId) enriched.span_id = store.spanId;
868
1423
  }
869
- if (!hasDotPaths) return flat;
870
- for (const [key, value] of Object.entries(flat)) {
871
- const parts = key.split(".");
872
- if (parts.some((p) => DANGEROUS_KEYS.has(p))) continue;
873
- if (parts.length === 1) {
874
- result[parts[0]] = value;
875
- continue;
876
- }
877
- let current = result;
878
- for (let i = 0; i < parts.length - 1; i++) {
879
- const part = parts[i];
880
- if (current[part] === void 0 || current[part] === null) current[part] = {};
881
- if (typeof current[part] !== "object" || current[part] instanceof File) current[part] = {};
882
- current = current[part];
883
- }
884
- current[parts[parts.length - 1]] = value;
885
- }
886
- return result;
1424
+ return enriched;
887
1425
  }
888
- var DANGEROUS_KEYS = new Set(["__proto__"]);
889
- /**
890
- * Schema-agnostic coercion primitives for common FormData patterns.
891
- *
892
- * These are plain transform functions — they compose with any schema library's
893
- * `transform`/`preprocess` pipeline:
894
- *
895
- * ```ts
896
- * // Zod
897
- * z.preprocess(coerce.number, z.number())
898
- * // Valibot
899
- * v.pipe(v.unknown(), v.transform(coerce.number), v.number())
900
- * ```
901
- */
902
- var coerce = {
903
- /**
904
- * Coerce a string to a number.
905
- * - `"42"` → `42`
906
- * - `"3.14"` → `3.14`
907
- * - `""` / `undefined` / `null` → `undefined`
908
- * - Non-numeric strings → `undefined` (schema validation will catch this)
909
- */
910
- number(value) {
911
- if (value === void 0 || value === null || value === "") return void 0;
912
- if (typeof value === "number") return value;
913
- if (typeof value !== "string") return void 0;
914
- const num = Number(value);
915
- if (Number.isNaN(num)) return void 0;
916
- return num;
917
- },
918
- /**
919
- * Coerce a checkbox value to a boolean.
920
- * HTML checkboxes submit "on" when checked and are absent when unchecked.
921
- * - `"on"` / any truthy string → `true`
922
- * - `undefined` / `null` / `""` → `false`
923
- */
924
- checkbox(value) {
925
- if (value === void 0 || value === null || value === "") return false;
926
- if (typeof value === "boolean") return value;
927
- return typeof value === "string" && value.length > 0;
928
- },
929
- /**
930
- * Parse a JSON string into an object.
931
- * - Valid JSON string → parsed object
932
- * - `""` / `undefined` / `null` → `undefined`
933
- * - Invalid JSON → `undefined` (schema validation will catch this)
934
- */
935
- json(value) {
936
- if (value === void 0 || value === null || value === "") return void 0;
937
- if (typeof value !== "string") return value;
938
- try {
939
- return JSON.parse(value);
940
- } catch {
941
- return;
942
- }
943
- },
944
- /**
945
- * Coerce a date string to a Date object.
946
- * Handles `<input type="date">` (`"2024-01-15"`), `<input type="datetime-local">`
947
- * (`"2024-01-15T10:30"`), and full ISO 8601 strings.
948
- * - Valid date string → `Date`
949
- * - `""` / `undefined` / `null` → `undefined`
950
- * - Invalid date strings → `undefined` (schema validation will catch this)
951
- * - Impossible dates that `new Date()` silently normalizes (e.g. Feb 31) → `undefined`
952
- */
953
- date(value) {
954
- if (value === void 0 || value === null || value === "") return void 0;
955
- if (value instanceof Date) return value;
956
- if (typeof value !== "string") return void 0;
957
- const date = new Date(value);
958
- if (Number.isNaN(date.getTime())) return void 0;
959
- const ymdMatch = value.match(/^(\d{4})-(\d{2})-(\d{2})/);
960
- if (ymdMatch) {
961
- const inputYear = Number(ymdMatch[1]);
962
- const inputMonth = Number(ymdMatch[2]);
963
- const inputDay = Number(ymdMatch[3]);
964
- const isUTC = value.length === 10 || value.endsWith("Z");
965
- const parsedYear = isUTC ? date.getUTCFullYear() : date.getFullYear();
966
- const parsedMonth = isUTC ? date.getUTCMonth() + 1 : date.getMonth() + 1;
967
- const parsedDay = isUTC ? date.getUTCDate() : date.getDate();
968
- if (inputYear !== parsedYear || inputMonth !== parsedMonth || inputDay !== parsedDay) return;
969
- }
970
- return date;
971
- },
972
- /**
973
- * Create a File coercion function with optional size and mime type validation.
974
- * Returns the File if valid, `undefined` otherwise.
975
- *
976
- * ```ts
977
- * // Basic — just checks it's a real File
978
- * z.preprocess(coerce.file(), z.instanceof(File))
979
- *
980
- * // With constraints
981
- * z.preprocess(
982
- * coerce.file({ maxSize: 5 * 1024 * 1024, accept: ['image/png', 'image/jpeg'] }),
983
- * z.instanceof(File)
984
- * )
985
- * ```
986
- */
987
- file(options) {
988
- return (value) => {
989
- if (value === void 0 || value === null || value === "") return void 0;
990
- if (!(value instanceof File)) return void 0;
991
- if (value.size === 0 && value.name === "") return void 0;
992
- if (options?.maxSize !== void 0 && value.size > options.maxSize) return;
993
- if (options?.accept !== void 0 && !options.accept.includes(value.type)) return;
994
- return value;
995
- };
996
- }
997
- };
998
- //#endregion
999
- //#region src/server/actions.ts
1000
- /**
1001
- * Server action primitives: revalidatePath, revalidateTag, and the action handler.
1002
- *
1003
- * - revalidatePath(path) re-renders the route at that path and returns the RSC
1004
- * flight payload for inline reconciliation.
1005
- * - revalidateTag(tag) invalidates timber.cache entries by tag.
1006
- *
1007
- * Both are callable from anywhere on the server — actions, API routes, handlers.
1008
- *
1009
- * The action handler processes incoming action requests, validates CSRF,
1010
- * enforces body limits, executes the action, and returns the response
1011
- * (with piggybacked RSC payload if revalidatePath was called).
1012
- *
1013
- * See design/08-forms-and-actions.md
1014
- */
1015
- /**
1016
- * Get the current revalidation state. Throws if called outside an action context.
1017
- * @internal
1018
- */
1019
- function getRevalidationState() {
1020
- const state = revalidationAls.getStore();
1021
- if (!state) throw new Error("revalidatePath/revalidateTag called outside of a server action context. These functions can only be called during action execution.");
1022
- return state;
1426
+ /** Log a completed request. Level: info. */
1427
+ function logRequestCompleted(data) {
1428
+ _logger.info("request completed", withTraceContext(data));
1023
1429
  }
1024
- /**
1025
- * Re-render the route at `path` and include the RSC flight payload in the
1026
- * action response. The client reconciles inline — no separate fetch needed.
1027
- *
1028
- * Can be called from server actions, API routes, or any server-side context.
1029
- *
1030
- * @param path - The path to re-render (e.g. '/dashboard', '/todos').
1031
- */
1032
- function revalidatePath(path) {
1033
- const state = getRevalidationState();
1034
- if (!state.paths.includes(path)) state.paths.push(path);
1430
+ /** Log request received. Level: debug. */
1431
+ function logRequestReceived(data) {
1432
+ _logger.debug("request received", withTraceContext(data));
1035
1433
  }
1036
- /**
1037
- * Invalidate all timber.cache entries tagged with `tag`.
1038
- * Does not return a payload — the next request for an invalidated entry re-executes.
1039
- *
1040
- * @param tag - The cache tag to invalidate (e.g. 'products', 'user:123').
1041
- */
1042
- function revalidateTag(tag) {
1043
- const state = getRevalidationState();
1044
- if (!state.tags.includes(tag)) state.tags.push(tag);
1434
+ /** Log a slow request warning. Level: warn. */
1435
+ function logSlowRequest(data) {
1436
+ _logger.warn("slow request exceeded threshold", withTraceContext(data));
1437
+ }
1438
+ /** Log middleware short-circuit. Level: debug. */
1439
+ function logMiddlewareShortCircuit(data) {
1440
+ _logger.debug("middleware short-circuited", withTraceContext(data));
1441
+ }
1442
+ /** Log unhandled error in middleware phase. Level: error. */
1443
+ function logMiddlewareError(data) {
1444
+ if (isControlFlowSignal(data.error)) return;
1445
+ _logger.error("unhandled error in middleware phase", withTraceContext(data));
1446
+ }
1447
+ /** Log unhandled render-phase error. Level: error. */
1448
+ function logRenderError(data) {
1449
+ if (isControlFlowSignal(data.error)) return;
1450
+ _logger.error("unhandled render-phase error", withTraceContext(data));
1451
+ }
1452
+ /** Log proxy.ts uncaught error. Level: error. */
1453
+ function logProxyError(data) {
1454
+ _logger.error("proxy.ts threw uncaught error", withTraceContext(data));
1455
+ }
1456
+ /** Log unhandled error in route handler. Level: error. */
1457
+ function logRouteError(data) {
1458
+ if (isControlFlowSignal(data.error)) return;
1459
+ _logger.error("unhandled route handler error", withTraceContext(data));
1460
+ }
1461
+ /** Log waitUntil() adapter missing (once at startup). Level: warn. */
1462
+ function logWaitUntilUnsupported() {
1463
+ _logger.warn("adapter does not support waitUntil()");
1464
+ }
1465
+ /** Log waitUntil() promise rejection. Level: warn. */
1466
+ function logWaitUntilRejected(data) {
1467
+ _logger.warn("waitUntil() promise rejected", withTraceContext(data));
1468
+ }
1469
+ /** Log staleWhileRevalidate refetch failure. Level: warn. */
1470
+ function logSwrRefetchFailed(data) {
1471
+ _logger.warn("staleWhileRevalidate refetch failed", withTraceContext(data));
1472
+ }
1473
+ /** Log cache miss. Level: debug. */
1474
+ function logCacheMiss(data) {
1475
+ _logger.debug("timber.cache MISS", withTraceContext(data));
1045
1476
  }
1046
1477
  /**
1047
- * Execute a server action and process revalidation.
1478
+ * Log an intentionally swallowed error. Provides observability into catch
1479
+ * blocks that are deliberately empty — the error is consumed, never rethrown.
1048
1480
  *
1049
- * 1. Sets up revalidation state
1050
- * 2. Calls the action function
1051
- * 3. Processes revalidateTag calls (invalidates cache entries)
1052
- * 4. Processes revalidatePath calls (re-renders and captures RSC payload)
1053
- * 5. Returns the action result + optional RSC payload
1481
+ * Default level: `warn` in dev (so the overlay surfaces patterns), `debug`
1482
+ * in production (low noise unless TIMBER_DEBUG is set). Pass `opts.level`
1483
+ * to override.
1054
1484
  *
1055
- * @param actionFn - The server action function to execute.
1056
- * @param args - Arguments to pass to the action.
1057
- * @param config - Handler configuration (cache handler, renderer).
1485
+ * **Infallible** — swallow() itself never throws, even if the logger is
1486
+ * broken. A thrown swallow would turn a benign catch into a crash.
1058
1487
  */
1059
- async function executeAction(actionFn, args, config = {}, spanMeta) {
1060
- const state = {
1061
- paths: [],
1062
- tags: []
1063
- };
1064
- let actionResult;
1065
- let redirectTo;
1066
- let redirectStatus;
1067
- await revalidationAls.run(state, async () => {
1068
- try {
1069
- actionResult = await withSpan("timber.action", {
1070
- ...spanMeta?.actionFile ? { "timber.action_file": spanMeta.actionFile } : {},
1071
- ...spanMeta?.actionName ? { "timber.action_name": spanMeta.actionName } : {}
1072
- }, () => actionFn(...args));
1073
- } catch (error) {
1074
- if (error instanceof RedirectSignal) {
1075
- redirectTo = error.location;
1076
- redirectStatus = error.status;
1077
- } else throw error;
1078
- }
1079
- });
1080
- if (state.tags.length > 0) await Promise.all(state.tags.map((tag) => cache.invalidate({ tag })));
1081
- let revalidation;
1082
- if (state.paths.length > 0 && config.renderer) {
1083
- const path = state.paths[0];
1084
- try {
1085
- revalidation = await config.renderer(path);
1086
- } catch (renderError) {
1087
- if (renderError instanceof RedirectSignal) {
1088
- redirectTo = renderError.location;
1089
- redirectStatus = renderError.status;
1090
- } else if (renderError instanceof DenySignal) console.error(`[timber] revalidatePath dropped — target middleware denied (status ${renderError.status})`);
1091
- else console.error("[timber] revalidatePath render failed:", renderError);
1092
- }
1093
- }
1094
- return {
1095
- actionResult,
1096
- revalidation,
1097
- ...redirectTo ? {
1098
- redirectTo,
1099
- redirectStatus
1100
- } : {}
1101
- };
1488
+ function swallow(err, reason, opts) {
1489
+ try {
1490
+ const level = opts?.level ?? (isDevMode() ? "warn" : "debug");
1491
+ _logger[level](`swallowed: ${reason}`, withTraceContext({ error: err }));
1492
+ } catch {}
1102
1493
  }
1103
1494
  //#endregion
1104
- export { setSegmentParams as C, getSetCookieHeaders as E, setMutableCookieContext as S, getCookieJar as T, getSearchParams as _, parseFormData as a, runWithRequestContext as b, RenderError as c, redirectExternal as d, waitUntil as f, getHeaders as g, getHeader as h, coerce as i, deny as l, applyRequestHeaderOverlay as m, revalidatePath as n, DenySignal as o, RedirectType as p, revalidateTag as r, RedirectSignal as s, executeAction as t, redirect as u, getSegmentParams as v, getCookie as w, setMatchedSegmentPath as x, markResponseFlushed as y };
1495
+ export { revalidationAls as $, runWithRequestContext as A, addSpanEvent as B, RedirectType as C, getSearchParams as D, getHeaders as E, getCookieJar as F, getTraceId as G, generateTraceId as H, getSetCookieHeaders as I, setSpanAttribute as J, replaceTraceId as K, getWaitUntil as L, setMutableCookieContext as M, setSegmentParams as N, getSegmentParams as O, getCookie as P, requestContextAls as Q, isDebug as R, waitUntil as S, getHeader as T, getOtelTraceId as U, addSpanEventSync as V, getSpanId as W, earlyHintsSenderAls as X, withSpan as Y, formFlashAls as Z, RedirectSignal as _, logProxyError as a, redirect as b, logRequestReceived as c, logSwrRefetchFailed as d, timingAls as et, logWaitUntilRejected as f, DenySignal as g, swallow as h, logMiddlewareShortCircuit as i, setMatchedSegmentPath as j, markResponseFlushed as k, logRouteError as l, setLogger as m, logCacheMiss as n, logRenderError as o, logWaitUntilUnsupported as p, runWithTraceId as q, logMiddlewareError as r, logRequestCompleted as s, getLogger as t, logSlowRequest as u, RenderError as v, applyRequestHeaderOverlay as w, redirectExternal as x, deny as y, isDevMode as z };
1105
1496
 
1106
- //# sourceMappingURL=actions-a0RczDnB.js.map
1497
+ //# sourceMappingURL=logger-DvmCWhN9.js.map