@timber-js/app 0.2.0-alpha.116 → 0.2.0-alpha.117

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 (39) hide show
  1. package/dist/_chunks/{actions-DAVm0FQe.js → actions-Cw-7NfJJ.js} +8 -1
  2. package/dist/_chunks/actions-Cw-7NfJJ.js.map +1 -0
  3. package/dist/_chunks/{resolve-schema-DO8B0mO9.js → resolve-schema-23Mc8aLi.js} +1 -1
  4. package/dist/_chunks/{resolve-schema-DO8B0mO9.js.map → resolve-schema-23Mc8aLi.js.map} +1 -1
  5. package/dist/_chunks/{segment-context-EsfQpS--.js → segment-context-Bg0pFbLT.js} +1 -1
  6. package/dist/_chunks/{segment-context-EsfQpS--.js.map → segment-context-Bg0pFbLT.js.map} +1 -1
  7. package/dist/_chunks/tracing-DvKLzCFa.js.map +1 -1
  8. package/dist/client/index.js +1 -1
  9. package/dist/client/internal.js +1 -1
  10. package/dist/params/index.js +1 -1
  11. package/dist/server/als-registry.d.ts +12 -0
  12. package/dist/server/als-registry.d.ts.map +1 -1
  13. package/dist/server/index.js +1 -1
  14. package/dist/server/internal.js +68 -67
  15. package/dist/server/internal.js.map +1 -1
  16. package/dist/server/param-coercion.d.ts +18 -0
  17. package/dist/server/param-coercion.d.ts.map +1 -1
  18. package/dist/server/pipeline-phases.d.ts.map +1 -1
  19. package/dist/server/pipeline.d.ts +7 -0
  20. package/dist/server/pipeline.d.ts.map +1 -1
  21. package/dist/server/request-context.d.ts +9 -0
  22. package/dist/server/request-context.d.ts.map +1 -1
  23. package/dist/server/route-element-builder.d.ts.map +1 -1
  24. package/dist/server/route-matcher.d.ts.map +1 -1
  25. package/dist/server/slot-resolver.d.ts +1 -1
  26. package/dist/server/slot-resolver.d.ts.map +1 -1
  27. package/dist/server/tree-match.d.ts +41 -0
  28. package/dist/server/tree-match.d.ts.map +1 -0
  29. package/package.json +1 -1
  30. package/src/server/als-registry.ts +12 -0
  31. package/src/server/param-coercion.ts +58 -0
  32. package/src/server/pipeline-phases.ts +5 -0
  33. package/src/server/pipeline.ts +7 -0
  34. package/src/server/request-context.ts +31 -0
  35. package/src/server/route-element-builder.ts +12 -2
  36. package/src/server/route-matcher.ts +8 -168
  37. package/src/server/slot-resolver.ts +79 -112
  38. package/src/server/tree-match.ts +198 -0
  39. package/dist/_chunks/actions-DAVm0FQe.js.map +0 -1
@@ -3,10 +3,10 @@ import { a as warnRedirectInSuspense, c as warnSuspenseWrappingChildren, i as wa
3
3
  import { n as classifyUrlSegment } from "../_chunks/segment-classify-CnfLLvir.js";
4
4
  import { i as getMetadataRouteServePath, n as classifyMetadataRoute, r as getMetadataRouteAutoLink, t as METADATA_ROUTE_CONVENTIONS } from "../_chunks/metadata-routes-Cjmvi3rQ.js";
5
5
  import { a as logProxyError, c as logRequestReceived, d as logSwrRefetchFailed, f as logWaitUntilRejected, h as swallow, i as logMiddlewareShortCircuit, l as logRouteError, m as setLogger, n as logCacheMiss, o as logRenderError, p as logWaitUntilUnsupported, r as logMiddlewareError, s as logRequestCompleted, t as getLogger, u as logSlowRequest } from "../_chunks/logger-DDmK5skc.js";
6
- import { C as setMatchedSegmentPath, E as getCookie, O as getSetCookieHeaders, S as runWithRequestContext, T as setSegmentParams, _ as getHeader, b as getSegmentParams, c as DenySignal, d as RenderError, g as applyRequestHeaderOverlay, l as RedirectSignal, n as executeAction, o as coerce, r as isRscActionRequest, t as buildNoJsResponse, w as setMutableCookieContext, x as markResponseFlushed, y as getSearchParams } from "../_chunks/actions-DAVm0FQe.js";
6
+ import { C as setMatchedSegmentPath, E as getCookie, O as getSetCookieHeaders, S as runWithRequestContext, T as setSegmentParams, _ as getHeader, b as getSegmentParams, c as DenySignal, d as RenderError, g as applyRequestHeaderOverlay, l as RedirectSignal, n as executeAction, o as coerce, r as isRscActionRequest, t as buildNoJsResponse, w as setMutableCookieContext, x as markResponseFlushed, y as getSearchParams } from "../_chunks/actions-Cw-7NfJJ.js";
7
7
  import "../client/error-boundary.js";
8
- import "../_chunks/segment-context-EsfQpS--.js";
9
- import { n as toBracketKey } from "../_chunks/resolve-schema-DO8B0mO9.js";
8
+ import { n as toBracketKey } from "../_chunks/resolve-schema-23Mc8aLi.js";
9
+ import "../_chunks/segment-context-Bg0pFbLT.js";
10
10
  import { readFile } from "node:fs/promises";
11
11
  import { createElement } from "react";
12
12
  //#region src/server/server-timing.ts
@@ -1336,6 +1336,70 @@ function buildDeniedFallback(DeniedComponent, slotName, data, createElement) {
1336
1336
  });
1337
1337
  }
1338
1338
  //#endregion
1339
+ //#region src/server/param-coercion.ts
1340
+ /** Global schema codecs, set once at startup from virtual:timber-schema. */
1341
+ var _globalCodecs = null;
1342
+ /**
1343
+ * Run segment param coercion on the matched route's segments.
1344
+ *
1345
+ * When `globalCodecs` is provided (from app/schema.ts), uses the global
1346
+ * codec map keyed by bare param name. Otherwise falls back to loading
1347
+ * per-segment params.ts modules.
1348
+ *
1349
+ * Throws ParamCoercionError if any codec fails (→ 404).
1350
+ *
1351
+ * This runs BEFORE middleware, so ctx.segmentParams is already typed.
1352
+ * See design/07-routing.md §"Where Coercion Runs"
1353
+ * See design/41-global-params.md §"Pipeline Integration"
1354
+ */
1355
+ async function coerceSegmentParams(match) {
1356
+ const globalCodecs = _globalCodecs;
1357
+ const mergeTarget = Object.create(null);
1358
+ for (const key of Object.keys(match.segmentParams)) if (key !== "__proto__") mergeTarget[key] = match.segmentParams[key];
1359
+ match.segmentParams = mergeTarget;
1360
+ if (globalCodecs) {
1361
+ for (const segment of match.segments) {
1362
+ if (!segment.paramName) continue;
1363
+ const bracketKey = toBracketKey(segment.segmentType, segment.paramName);
1364
+ const codec = globalCodecs[bracketKey];
1365
+ if (!codec) continue;
1366
+ const key = segment.paramName;
1367
+ try {
1368
+ mergeTarget[key] = sanitizeParamValue(codec.parse(mergeTarget[key]));
1369
+ } catch (err) {
1370
+ const message = err instanceof Error ? err.message : String(err);
1371
+ if (isDebug()) console.warn(`[timber] Global schema codec rejected value for param "${key}"\n Error: ${message}\n Raw value: ${JSON.stringify(mergeTarget[key])}\n Hint: check the codec in app/schema.ts for key '${bracketKey}'.`);
1372
+ throw new ParamCoercionError(message);
1373
+ }
1374
+ }
1375
+ return;
1376
+ }
1377
+ for (const segment of match.segments) {
1378
+ if (!segment.params) continue;
1379
+ let mod;
1380
+ try {
1381
+ mod = await loadModule(segment.params);
1382
+ } catch (err) {
1383
+ const message = `Failed to load params module for segment "${segment.segmentName}": ${err instanceof Error ? err.message : String(err)}`;
1384
+ if (isDebug()) console.warn(`[timber] Param coercion error: ${message}\n Segment: ${segment.segmentName}\n Params file: ${segment.params}`);
1385
+ throw new ParamCoercionError(message);
1386
+ }
1387
+ const segmentParamsDef = mod.segmentParams;
1388
+ if (!segmentParamsDef || typeof segmentParamsDef.parse !== "function") continue;
1389
+ try {
1390
+ const coerced = segmentParamsDef.parse(match.segmentParams);
1391
+ for (const key of Object.keys(coerced)) if (key !== "__proto__") mergeTarget[key] = sanitizeParamValue(coerced[key]);
1392
+ } catch (err) {
1393
+ const message = err instanceof Error ? err.message : String(err);
1394
+ if (isDebug()) {
1395
+ const rawKeys = Object.keys(match.segmentParams).join(", ");
1396
+ console.warn(`[timber] Param codec rejected values for segment "${segment.segmentName}"\n Error: ${message}\n Available raw params: { ${rawKeys} }\n Params file: ${segment.params}\n Hint: this usually means a codec threw for the raw URL value.\n Check that the regex/schema accepts the actual path segment string.`);
1397
+ }
1398
+ throw new ParamCoercionError(message);
1399
+ }
1400
+ }
1401
+ }
1402
+ //#endregion
1339
1403
  //#region src/server/route-element-builder.ts
1340
1404
  /**
1341
1405
  * Thrown when a defineSegmentParams codec's parse() fails.
@@ -1536,70 +1600,6 @@ function pathnameMatchesPattern(pathname, pattern) {
1536
1600
  return pi === pathParts.length;
1537
1601
  }
1538
1602
  //#endregion
1539
- //#region src/server/param-coercion.ts
1540
- /** Global schema codecs, set once at startup from virtual:timber-schema. */
1541
- var _globalCodecs = null;
1542
- /**
1543
- * Run segment param coercion on the matched route's segments.
1544
- *
1545
- * When `globalCodecs` is provided (from app/schema.ts), uses the global
1546
- * codec map keyed by bare param name. Otherwise falls back to loading
1547
- * per-segment params.ts modules.
1548
- *
1549
- * Throws ParamCoercionError if any codec fails (→ 404).
1550
- *
1551
- * This runs BEFORE middleware, so ctx.segmentParams is already typed.
1552
- * See design/07-routing.md §"Where Coercion Runs"
1553
- * See design/41-global-params.md §"Pipeline Integration"
1554
- */
1555
- async function coerceSegmentParams(match) {
1556
- const globalCodecs = _globalCodecs;
1557
- const mergeTarget = Object.create(null);
1558
- for (const key of Object.keys(match.segmentParams)) if (key !== "__proto__") mergeTarget[key] = match.segmentParams[key];
1559
- match.segmentParams = mergeTarget;
1560
- if (globalCodecs) {
1561
- for (const segment of match.segments) {
1562
- if (!segment.paramName) continue;
1563
- const bracketKey = toBracketKey(segment.segmentType, segment.paramName);
1564
- const codec = globalCodecs[bracketKey];
1565
- if (!codec) continue;
1566
- const key = segment.paramName;
1567
- try {
1568
- mergeTarget[key] = sanitizeParamValue(codec.parse(mergeTarget[key]));
1569
- } catch (err) {
1570
- const message = err instanceof Error ? err.message : String(err);
1571
- if (isDebug()) console.warn(`[timber] Global schema codec rejected value for param "${key}"\n Error: ${message}\n Raw value: ${JSON.stringify(mergeTarget[key])}\n Hint: check the codec in app/schema.ts for key '${bracketKey}'.`);
1572
- throw new ParamCoercionError(message);
1573
- }
1574
- }
1575
- return;
1576
- }
1577
- for (const segment of match.segments) {
1578
- if (!segment.params) continue;
1579
- let mod;
1580
- try {
1581
- mod = await loadModule(segment.params);
1582
- } catch (err) {
1583
- const message = `Failed to load params module for segment "${segment.segmentName}": ${err instanceof Error ? err.message : String(err)}`;
1584
- if (isDebug()) console.warn(`[timber] Param coercion error: ${message}\n Segment: ${segment.segmentName}\n Params file: ${segment.params}`);
1585
- throw new ParamCoercionError(message);
1586
- }
1587
- const segmentParamsDef = mod.segmentParams;
1588
- if (!segmentParamsDef || typeof segmentParamsDef.parse !== "function") continue;
1589
- try {
1590
- const coerced = segmentParamsDef.parse(match.segmentParams);
1591
- for (const key of Object.keys(coerced)) if (key !== "__proto__") mergeTarget[key] = sanitizeParamValue(coerced[key]);
1592
- } catch (err) {
1593
- const message = err instanceof Error ? err.message : String(err);
1594
- if (isDebug()) {
1595
- const rawKeys = Object.keys(match.segmentParams).join(", ");
1596
- console.warn(`[timber] Param codec rejected values for segment "${segment.segmentName}"\n Error: ${message}\n Available raw params: { ${rawKeys} }\n Params file: ${segment.params}\n Hint: this usually means a codec threw for the raw URL value.\n Check that the regex/schema accepts the actual path segment string.`);
1597
- }
1598
- throw new ParamCoercionError(message);
1599
- }
1600
- }
1601
- }
1602
- //#endregion
1603
1603
  //#region src/server/pipeline-outcome.ts
1604
1604
  /**
1605
1605
  * Pipeline outcome translator — converts a `PhaseOutcome` (the value
@@ -1935,6 +1935,7 @@ async function handleRequest(config, req, method, path) {
1935
1935
  } catch (err) {
1936
1936
  swallow(err, "early hints hook threw");
1937
1937
  }
1938
+ match.rawSegmentParams = { ...match.segmentParams };
1938
1939
  try {
1939
1940
  await coerceSegmentParams(match);
1940
1941
  } catch (error) {