@timber-js/app 0.2.0-alpha.115 → 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 (58) hide show
  1. package/dist/_chunks/{actions-ILhDUzES.js → actions-Cw-7NfJJ.js} +24 -17
  2. package/dist/_chunks/actions-Cw-7NfJJ.js.map +1 -0
  3. package/dist/_chunks/{define-a0CCE6Nx.js → define-zQX6e1tN.js} +2 -2
  4. package/dist/_chunks/{define-a0CCE6Nx.js.map → define-zQX6e1tN.js.map} +1 -1
  5. package/dist/_chunks/{navigation-root-CY3pRMxF.js → navigation-root-DKsJ5Di7.js} +2 -2
  6. package/dist/_chunks/{navigation-root-CY3pRMxF.js.map → navigation-root-DKsJ5Di7.js.map} +1 -1
  7. package/dist/_chunks/{resolve-schema-DO8B0mO9.js → resolve-schema-23Mc8aLi.js} +1 -1
  8. package/dist/_chunks/{resolve-schema-DO8B0mO9.js.map → resolve-schema-23Mc8aLi.js.map} +1 -1
  9. package/dist/_chunks/{segment-context-EsfQpS--.js → segment-context-Bg0pFbLT.js} +1 -1
  10. package/dist/_chunks/{segment-context-EsfQpS--.js.map → segment-context-Bg0pFbLT.js.map} +1 -1
  11. package/dist/_chunks/tracing-DvKLzCFa.js.map +1 -1
  12. package/dist/_chunks/{use-segment-params-BSt_O2cb.js → use-segment-params-CskiK-59.js} +2 -2
  13. package/dist/_chunks/{use-segment-params-BSt_O2cb.js.map → use-segment-params-CskiK-59.js.map} +1 -1
  14. package/dist/_chunks/{walkers-DGV9dQRq.js → walkers-DgOXkTts.js} +12 -10
  15. package/dist/_chunks/walkers-DgOXkTts.js.map +1 -0
  16. package/dist/client/index.js +4 -4
  17. package/dist/client/internal.js +3 -3
  18. package/dist/client/use-segment-params.d.ts +3 -3
  19. package/dist/client/use-segment-params.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/params/index.js +1 -1
  22. package/dist/routing/codegen-types.d.ts +3 -0
  23. package/dist/routing/codegen-types.d.ts.map +1 -1
  24. package/dist/routing/index.js +1 -1
  25. package/dist/segment-params/index.js +1 -1
  26. package/dist/server/als-registry.d.ts +17 -4
  27. package/dist/server/als-registry.d.ts.map +1 -1
  28. package/dist/server/index.js +1 -1
  29. package/dist/server/internal.js +70 -69
  30. package/dist/server/internal.js.map +1 -1
  31. package/dist/server/param-coercion.d.ts +18 -0
  32. package/dist/server/param-coercion.d.ts.map +1 -1
  33. package/dist/server/pipeline-phases.d.ts.map +1 -1
  34. package/dist/server/pipeline.d.ts +7 -0
  35. package/dist/server/pipeline.d.ts.map +1 -1
  36. package/dist/server/request-context.d.ts +18 -9
  37. package/dist/server/request-context.d.ts.map +1 -1
  38. package/dist/server/route-element-builder.d.ts.map +1 -1
  39. package/dist/server/route-matcher.d.ts.map +1 -1
  40. package/dist/server/slot-resolver.d.ts +1 -1
  41. package/dist/server/slot-resolver.d.ts.map +1 -1
  42. package/dist/server/tree-match.d.ts +41 -0
  43. package/dist/server/tree-match.d.ts.map +1 -0
  44. package/package.json +1 -1
  45. package/src/client/use-segment-params.ts +4 -4
  46. package/src/routing/codegen-types.ts +3 -0
  47. package/src/routing/codegen.ts +18 -9
  48. package/src/server/als-registry.ts +17 -4
  49. package/src/server/param-coercion.ts +58 -0
  50. package/src/server/pipeline-phases.ts +14 -7
  51. package/src/server/pipeline.ts +7 -0
  52. package/src/server/request-context.ts +48 -17
  53. package/src/server/route-element-builder.ts +12 -2
  54. package/src/server/route-matcher.ts +8 -168
  55. package/src/server/slot-resolver.ts +79 -112
  56. package/src/server/tree-match.ts +198 -0
  57. package/dist/_chunks/actions-ILhDUzES.js.map +0 -1
  58. package/dist/_chunks/walkers-DGV9dQRq.js.map +0 -1
@@ -19,6 +19,24 @@ import type { RouteMatch } from './pipeline.js';
19
19
  * @internal
20
20
  */
21
21
  export declare function setGlobalSchemaCodecs(codecs: Record<string, Codec<unknown>> | null): void;
22
+ /**
23
+ * Coerce raw slot params through global schema codecs.
24
+ *
25
+ * Each slot segment that has a paramName is looked up in the global codec
26
+ * map by its bracket key (e.g. '[...year]' for catch-all). If a codec
27
+ * exists, the raw value is parsed through it. If no codec exists or no
28
+ * global codecs are registered, the raw value passes through unchanged.
29
+ *
30
+ * Unlike main route coercion, this does NOT throw ParamCoercionError on
31
+ * failure — slots degrade gracefully. A failed coercion logs a warning
32
+ * in dev mode and keeps the raw value.
33
+ *
34
+ * @internal — framework use only
35
+ */
36
+ export declare function coerceSlotParams(slotChain: Array<{
37
+ segmentType: string;
38
+ paramName?: string;
39
+ }>, rawParams: Record<string, string | string[]>): Record<string, string | string[]>;
22
40
  /**
23
41
  * Run segment param coercion on the matched route's segments.
24
42
  *
@@ -1 +1 @@
1
- {"version":3,"file":"param-coercion.d.ts","sourceRoot":"","sources":["../../src/server/param-coercion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAahD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAEzF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgG1E"}
1
+ {"version":3,"file":"param-coercion.d.ts","sourceRoot":"","sources":["../../src/server/param-coercion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAahD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAEzF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAC3C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAuCnC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgG1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline-phases.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEpG,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKrF,UAAU,aAAa;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAID;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAavB;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,YAAY,CAAC,CA6DvB;AAID;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE,aAAa,GACjD,OAAO,CAAC,YAAY,CAAC,CAkBvB;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,QAAQ,CAAC,CA0PnB"}
1
+ {"version":3,"file":"pipeline-phases.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEpG,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKrF,UAAU,aAAa;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAID;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAavB;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,YAAY,CAAC,CA6DvB;AAID;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE,aAAa,GACjD,OAAO,CAAC,YAAY,CAAC,CAkBvB;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,QAAQ,CAAC,CAiQnB"}
@@ -32,6 +32,13 @@ export interface RouteMatch {
32
32
  segments: ManifestSegmentNode[];
33
33
  /** Extracted segment params (catch-all segments produce string[]). */
34
34
  segmentParams: Record<string, string | string[]>;
35
+ /**
36
+ * Raw segment params before codec coercion. Always string or string[].
37
+ * Used by slot resolution to reconstruct URL parts — coerced params may
38
+ * have been transformed by codecs and are unsuitable for URL matching.
39
+ * Set by the pipeline before coercion runs.
40
+ */
41
+ rawSegmentParams?: Record<string, string | string[]>;
35
42
  /** Middleware chain from the segment tree, ordered root-to-leaf. */
36
43
  middlewareChain: MiddlewareFn[];
37
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"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"}
@@ -40,16 +40,16 @@ export declare function getSearchParams(): URLSearchParams;
40
40
  /**
41
41
  * Returns the current request's coerced segment params.
42
42
  *
43
- * The optional `_route` argument exists only for TypeScript narrowing —
44
- * it does not affect the runtime return value. Pass a route pattern
45
- * (e.g. `'/[artistSlug]/[year]'`) to narrow the return type to the
46
- * exact params shape for that route.
43
+ * The optional `segmentPath` argument exists only for TypeScript narrowing —
44
+ * it does not affect the runtime return value. Pass a segment path
45
+ * (e.g. `'/(browse)/[artistSlug]/[year]'`) to narrow the return type to the
46
+ * exact params shape for that segment.
47
47
  *
48
- * Without a route argument, returns all coerced params with optional types.
48
+ * Without an argument, returns all coerced params with optional types.
49
49
  *
50
50
  * See design/41-global-params.md §Function Signatures
51
51
  */
52
- export declare function getSegmentParams(route?: string): Record<string, string | string[]>;
52
+ export declare function getSegmentParams(segmentPath?: string): Record<string, string | string[]>;
53
53
  /**
54
54
  * Set the segment params on the current request context.
55
55
  * Called by the pipeline after route matching and param coercion.
@@ -58,12 +58,21 @@ export declare function getSegmentParams(route?: string): Record<string, string
58
58
  */
59
59
  export declare function setSegmentParams(params: Record<string, string | string[]>): void;
60
60
  /**
61
- * Store the matched route pattern (e.g. '/[artistSlug]/[year]') for
62
- * dev-mode route mismatch validation in getSegmentParams().
61
+ * Store per-slot coerced segment params in the current request context.
62
+ * Called by the route element builder when resolving parallel slots.
63
63
  *
64
+ * @param segmentPath — The slot's full tree path (e.g. '/(browse)/@shows/[artistSlug]/[...year]')
65
+ * @param params — The slot's coerced segment params
64
66
  * @internal — framework use only
65
67
  */
66
- export declare function setMatchedRoutePattern(pattern: string): void;
68
+ export declare function setSlotParams(segmentPath: string, params: Record<string, string | string[]>): void;
69
+ /**
70
+ * Store the matched segment path (e.g. '/(browse)/[artistSlug]/[year]') for
71
+ * dev-mode validation in getSegmentParams().
72
+ *
73
+ * @internal — framework use only
74
+ */
75
+ export declare function setMatchedSegmentPath(segmentPath: string): void;
67
76
  /**
68
77
  * Returns the raw search string from the current request URL (e.g. "?foo=bar").
69
78
  * Synchronous — safe for use in `redirect()` which throws synchronously.
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,iBAAiB,EAA4B,MAAM,mBAAmB,CAAC;AAOhF,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAQ7B;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,eAAe,CAS5C;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,eAAe,CASjD;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAkClF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,IAAI,CAMhF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI5D;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAG/C;AAID;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,OAAO,EACP,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,MAAM,CAAC,QAAQ,CACnF,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAmBrE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmBhE"}
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,iBAAiB,EAA4B,MAAM,mBAAmB,CAAC;AAOhF,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAQ7B;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,eAAe,CAS5C;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,eAAe,CASjD;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CA+CxF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,IAAI,CAMhF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GACxC,IAAI,CAKN;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAI/D;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAG/C;AAID;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,OAAO,EACP,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,MAAM,CAAC,QAAQ,CACnF,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAmBrE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmBhE"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAK9D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAa7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAezD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAM7D;AAID;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAID,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAED,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,2CAA2C;IAC3C,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,wDAAwD;IACxD,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,qCAAqC;IACrC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,MAAM,EAAE,UAAU,GAAG,cAAc;aACnC,gBAAgB,EAAE,oBAAoB,EAAE;aACxC,QAAQ,EAAE,mBAAmB,EAAE;gBAF/B,MAAM,EAAE,UAAU,GAAG,cAAc,EACnC,gBAAgB,EAAE,oBAAoB,EAAE,EACxC,QAAQ,EAAE,mBAAmB,EAAE;CAIlD;AA8DD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,YAAY,CAAC,EAAE,mBAAmB,EAClC,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GACnC,OAAO,CAAC,kBAAkB,CAAC,CA2V7B"}
1
+ {"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAK9D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAa7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAezD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAM7D;AAID;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAID,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAED,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,2CAA2C;IAC3C,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,wDAAwD;IACxD,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,qCAAqC;IACrC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,MAAM,EAAE,UAAU,GAAG,cAAc;aACnC,gBAAgB,EAAE,oBAAoB,EAAE;aACxC,QAAQ,EAAE,mBAAmB,EAAE;gBAF/B,MAAM,EAAE,UAAU,GAAG,cAAc,EACnC,gBAAgB,EAAE,oBAAoB,EAAE,EACxC,QAAQ,EAAE,mBAAmB,EAAE;CAIlD;AA8DD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,YAAY,CAAC,EAAE,mBAAmB,EAClC,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAqW7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-matcher.d.ts","sourceRoot":"","sources":["../../src/server/route-matcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAW9B,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,YAAY,CAAC;IAC3D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,YAAY,GACrB,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAEzC;AAuMD,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,IAAI,EAAE,iBAAiB,CAAC;IACxB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,IAAI,EAAE,YAAY,CAAC;IACnB,0DAA0D;IAC1D,OAAO,EAAE,mBAAmB,CAAC;IAC7B;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,YAAY,GACrB,CAAC,QAAQ,EAAE,MAAM,KAAK,kBAAkB,GAAG,IAAI,CAMjD"}
1
+ {"version":3,"file":"route-matcher.d.ts","sourceRoot":"","sources":["../../src/server/route-matcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAY9B,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,YAAY,CAAC;IAC3D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,YAAY,GACrB,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAEzC;AAsCD,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,IAAI,EAAE,iBAAiB,CAAC;IACxB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,IAAI,EAAE,YAAY,CAAC;IACnB,0DAA0D;IAC1D,OAAO,EAAE,mBAAmB,CAAC;IAC7B;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,YAAY,GACrB,CAAC,QAAQ,EAAE,MAAM,KAAK,kBAAkB,GAAG,IAAI,CAMjD"}
@@ -29,6 +29,6 @@ type CreateElementFn = (...args: unknown[]) => React.ReactElement;
29
29
  * 2. Layouts from each segment in the slot's matched chain
30
30
  * 3. SlotAccessGate if the slot root has access.ts
31
31
  */
32
- export declare function resolveSlotElement(slotNode: ManifestSegmentNode, match: RouteMatch, h: CreateElementFn, interception?: InterceptionContext): Promise<React.ReactElement | null>;
32
+ export declare function resolveSlotElement(slotNode: ManifestSegmentNode, match: RouteMatch, h: CreateElementFn, interception?: InterceptionContext, parentTreePath?: string): Promise<React.ReactElement | null>;
33
33
  export {};
34
34
  //# sourceMappingURL=slot-resolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slot-resolver.d.ts","sourceRoot":"","sources":["../../src/server/slot-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,KAAK,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,YAAY,CAAC;AAmHlE;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,eAAe,EAClB,YAAY,CAAC,EAAE,mBAAmB,GACjC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAgGpC"}
1
+ {"version":3,"file":"slot-resolver.d.ts","sourceRoot":"","sources":["../../src/server/slot-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAK9D,KAAK,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,YAAY,CAAC;AAgClE;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,eAAe,EAClB,YAAY,CAAC,EAAE,mBAAmB,EAClC,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAgHpC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared URL-matching tree walker for segment trees.
3
+ *
4
+ * Both the main route matcher (`route-matcher.ts`) and slot resolver
5
+ * (`slot-resolver.ts`) need to walk a SegmentNode tree, matching URL
6
+ * parts against children with the same priority semantics:
7
+ *
8
+ * static > dynamic > catch-all > optional-catch-all
9
+ *
10
+ * Before this module, each had its own walker with subtle divergences
11
+ * (different group handling, missing backtracking, incomplete
12
+ * optional-catch-all support). This shared walker is the single
13
+ * source of truth for URL-to-segment matching.
14
+ *
15
+ * See design/07-routing.md §"Request Lifecycle" and TIM-940.
16
+ */
17
+ import type { SegmentNode } from '../routing/types.js';
18
+ /** Result of matching URL parts against a segment tree. */
19
+ export interface TreeMatchResult<TFile> {
20
+ /** Matched segment chain from root to leaf, inclusive. */
21
+ chain: SegmentNode<TFile>[];
22
+ /** Collected params, keyed by param name. Catch-all params are string[]. */
23
+ params: Record<string, string | string[]>;
24
+ }
25
+ /**
26
+ * Match URL path parts against a segment tree.
27
+ *
28
+ * Walks the tree depth-first with backtracking, applying priority
29
+ * ordering globally across group boundaries. Returns the matched
30
+ * segment chain and collected params, or null if no route matches.
31
+ *
32
+ * A match requires a terminal node (one with `page` or `route`) at
33
+ * the leaf. Catch-all and optional-catch-all segments only match if
34
+ * they are terminal.
35
+ *
36
+ * @param root The root segment node to start matching from.
37
+ * @param parts URL path parts (e.g. ['blog', 'hello-world']).
38
+ * Empty array matches the root itself (if terminal).
39
+ */
40
+ export declare function matchUrlParts<TFile>(root: SegmentNode<TFile>, parts: string[]): TreeMatchResult<TFile> | null;
41
+ //# sourceMappingURL=tree-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-match.d.ts","sourceRoot":"","sources":["../../src/server/tree-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,2DAA2D;AAC3D,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,0DAA0D;IAC1D,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;IAC5B,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EACjC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,EACxB,KAAK,EAAE,MAAM,EAAE,GACd,eAAe,CAAC,KAAK,CAAC,GAAG,IAAI,CAQ/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timber-js/app",
3
- "version": "0.2.0-alpha.115",
3
+ "version": "0.2.0-alpha.117",
4
4
  "description": "Vite-native React framework built for Servers and Serverless Platforms — correct HTTP semantics, real status codes, pages that work without JavaScript",
5
5
  "keywords": [
6
6
  "cloudflare-workers",
@@ -115,15 +115,15 @@ export function notifyParamsListeners(): void {
115
115
  * When called outside a React component (e.g., in test assertions),
116
116
  * falls back to the module-level snapshot.
117
117
  *
118
- * @overload Typed — when a known route path is passed, returns the
118
+ * @overload Typed — when a known segment path is passed, returns the
119
119
  * exact params shape from the generated Routes interface.
120
120
  * @overload Fallback — returns the generic params record.
121
121
  */
122
122
  export function useSegmentParams<R extends keyof Routes>(
123
- route: R
123
+ segmentPath: R
124
124
  ): Routes[R] extends { segmentParams: infer P } ? P : Record<string, string | string[]>;
125
- export function useSegmentParams(route?: string): Record<string, string | string[]>;
126
- export function useSegmentParams(_route?: string): Record<string, string | string[]> {
125
+ export function useSegmentParams(segmentPath?: string): Record<string, string | string[]>;
126
+ export function useSegmentParams(_segmentPath?: string): Record<string, string | string[]> {
127
127
  // Try reading from NavigationContext (client-side, inside React tree).
128
128
  // During SSR, no NavigationProvider is mounted, so this returns null.
129
129
  // When called outside a React component, useContext throws — caught below.
@@ -10,6 +10,9 @@
10
10
  export interface RouteEntry {
11
11
  /** URL path pattern (e.g. "/products/[id]") */
12
12
  urlPath: string;
13
+ /** Full tree path including groups and slots (e.g. "/(browse)/[artistSlug]/@shows/[year]").
14
+ * Uniquely identifies a segment — unlike urlPath which strips groups/slots. */
15
+ segmentPath: string;
13
16
  /** Accumulated params from all ancestor dynamic segments */
14
17
  params: ParamEntry[];
15
18
  /** Whether the page.tsx exports searchParams */
@@ -48,7 +48,7 @@ export function generateRouteMap(tree: RouteTree, options: CodegenOptions = {}):
48
48
  const hasSchema = options.hasSchema ?? detectSchema(options.appDir);
49
49
 
50
50
  const routes: RouteEntry[] = [];
51
- collectRoutes(tree.root, [], [], routes, hasSchema);
51
+ collectRoutes(tree.root, [], [], '', routes, hasSchema);
52
52
 
53
53
  // Sort routes alphabetically for deterministic output
54
54
  routes.sort((a, b) => a.urlPath.localeCompare(b.urlPath));
@@ -80,9 +80,13 @@ function collectRoutes(
80
80
  node: SegmentNode,
81
81
  ancestorParams: ParamEntry[],
82
82
  ancestorParamsFiles: string[],
83
+ parentTreePath: string,
83
84
  routes: RouteEntry[],
84
85
  hasSchema: boolean
85
86
  ): void {
87
+ // Build the tree path (includes groups, slots — uniquely identifies this segment).
88
+ // Root node has empty segmentName, producing treePath = ''.
89
+ const treePath = node.segmentName ? `${parentTreePath}/${node.segmentName}` : parentTreePath;
86
90
  // TIM-834: Identify this segment's own params.ts (if it has a
87
91
  // segmentParams export). The full chain of params.ts files in the
88
92
  // route ancestry is threaded down via `ancestorParamsFiles`; codec
@@ -148,6 +152,7 @@ function collectRoutes(
148
152
 
149
153
  const entry: RouteEntry = {
150
154
  urlPath: node.urlPath,
155
+ segmentPath: treePath || '/',
151
156
  params: resolvedParams,
152
157
  hasSearchParams: false,
153
158
  isApiRoute,
@@ -170,12 +175,12 @@ function collectRoutes(
170
175
 
171
176
  // Recurse into children
172
177
  for (const child of node.children) {
173
- collectRoutes(child, params, nextAncestorFiles, routes, hasSchema);
178
+ collectRoutes(child, params, nextAncestorFiles, treePath, routes, hasSchema);
174
179
  }
175
180
 
176
181
  // Recurse into slots (they share the parent's URL path, but may have their own pages)
177
182
  for (const slot of Object.values(node.slots)) {
178
- collectRoutes(slot, params, nextAncestorFiles, routes, hasSchema);
183
+ collectRoutes(slot, params, nextAncestorFiles, treePath, routes, hasSchema);
179
184
  }
180
185
  }
181
186
 
@@ -245,14 +250,14 @@ function formatSchemaTypes(routes: RouteEntry[]): string[] {
245
250
  lines.push('/** Union of all valid route patterns. */');
246
251
  lines.push('export type TimberRoute = keyof TimberSegmentParams;');
247
252
  lines.push('');
248
- lines.push('/** Maps each route pattern to its accumulated segment params. */');
253
+ lines.push('/** Maps each segment path to its accumulated segment params. */');
249
254
  lines.push('export interface TimberSegmentParams {');
250
255
 
251
256
  for (const route of routes) {
252
257
  if (route.params.length === 0) {
253
- lines.push(` '${route.urlPath}': {};`);
258
+ lines.push(` '${route.segmentPath}': {};`);
254
259
  } else {
255
- lines.push(` '${route.urlPath}': {`);
260
+ lines.push(` '${route.segmentPath}': {`);
256
261
  for (const p of route.params) {
257
262
  lines.push(` ${p.name}: ${buildSchemaParamType(p)};`);
258
263
  }
@@ -356,7 +361,9 @@ function formatDeclarationFile(
356
361
  lines.push("declare module '@timber-js/app/server' {");
357
362
  for (const route of dynamicRoutes) {
358
363
  const paramsType = formatParamsType(route.params, importBase, hasSchema);
359
- lines.push(` export function getSegmentParams(route: '${route.urlPath}'): ${paramsType}`);
364
+ lines.push(
365
+ ` export function getSegmentParams(segmentPath: '${route.segmentPath}'): ${paramsType}`
366
+ );
360
367
  }
361
368
  lines.push(' export function getSegmentParams(): Record<string, string | string[]>');
362
369
  lines.push('}');
@@ -372,11 +379,13 @@ function formatDeclarationFile(
372
379
  );
373
380
  lines.push('');
374
381
 
375
- // useParams overloads
382
+ // useSegmentParams overloads
376
383
  if (dynamicRoutes.length > 0) {
377
384
  for (const route of dynamicRoutes) {
378
385
  const paramsType = formatParamsType(route.params, importBase, hasSchema);
379
- lines.push(` export function useSegmentParams(route: '${route.urlPath}'): ${paramsType}`);
386
+ lines.push(
387
+ ` export function useSegmentParams(segmentPath: '${route.segmentPath}'): ${paramsType}`
388
+ );
380
389
  }
381
390
  lines.push(' export function useSegmentParams(): Record<string, string | string[]>');
382
391
  lines.push('');
@@ -60,12 +60,25 @@ export interface RequestContextStore {
60
60
  */
61
61
  segmentParams?: Record<string, string | string[]>;
62
62
  /**
63
- * The matched route pattern (e.g. '/[artistSlug]/[year]').
64
- * Set by the pipeline alongside segmentParams. Used by
65
- * getSegmentParams() for dev-mode route mismatch validation.
63
+ * The matched segment path (e.g. '/(browse)/[artistSlug]/[year]').
64
+ * Includes route groups and parallel slots — uniquely identifies the
65
+ * segment in the route tree. Set by the pipeline alongside segmentParams.
66
+ * Used by getSegmentParams() for dev-mode validation.
66
67
  * See design/41-global-params.md §Runtime Validation
67
68
  */
68
- matchedRoutePattern?: string;
69
+ matchedSegmentPath?: string;
70
+ /**
71
+ * Per-slot coerced segment params, keyed by the slot's full tree path
72
+ * (e.g. '/(browse)/@shows/[artistSlug]/[...year]').
73
+ *
74
+ * Each slot walks its own segment tree and may interpret URL parts
75
+ * differently from the main route (e.g. catch-all vs dynamic). This
76
+ * map stores slot-specific params so getSegmentParams(segmentPath)
77
+ * returns the correct types for slot pages.
78
+ *
79
+ * See design/07-routing.md §"Parallel Slot Params"
80
+ */
81
+ slotParamsMap?: Map<string, Record<string, string | string[]>>;
69
82
  /** Outgoing Set-Cookie entries (name → serialized value + options). Last write wins. */
70
83
  cookieJar: Map<string, CookieEntry>;
71
84
  /** Whether the response has flushed (headers committed). */
@@ -36,6 +36,64 @@ export function setGlobalSchemaCodecs(codecs: Record<string, Codec<unknown>> | n
36
36
  _globalCodecs = codecs;
37
37
  }
38
38
 
39
+ /**
40
+ * Coerce raw slot params through global schema codecs.
41
+ *
42
+ * Each slot segment that has a paramName is looked up in the global codec
43
+ * map by its bracket key (e.g. '[...year]' for catch-all). If a codec
44
+ * exists, the raw value is parsed through it. If no codec exists or no
45
+ * global codecs are registered, the raw value passes through unchanged.
46
+ *
47
+ * Unlike main route coercion, this does NOT throw ParamCoercionError on
48
+ * failure — slots degrade gracefully. A failed coercion logs a warning
49
+ * in dev mode and keeps the raw value.
50
+ *
51
+ * @internal — framework use only
52
+ */
53
+ export function coerceSlotParams(
54
+ slotChain: Array<{ segmentType: string; paramName?: string }>,
55
+ rawParams: Record<string, string | string[]>
56
+ ): Record<string, string | string[]> {
57
+ const globalCodecs = _globalCodecs;
58
+ if (!globalCodecs) return rawParams;
59
+
60
+ const result: Record<string, string | string[]> = Object.create(null);
61
+ for (const key of Object.keys(rawParams)) {
62
+ result[key] = rawParams[key];
63
+ }
64
+
65
+ for (const segment of slotChain) {
66
+ if (!segment.paramName) continue;
67
+ const bracketKey = toBracketKey(segment.segmentType, segment.paramName);
68
+ const codec = globalCodecs[bracketKey];
69
+ if (!codec) continue;
70
+
71
+ const key = segment.paramName;
72
+ if (!(key in result)) continue;
73
+
74
+ try {
75
+ result[key] = sanitizeParamValue(codec.parse(result[key] as string | string[])) as
76
+ | string
77
+ | string[];
78
+ } catch (err) {
79
+ // Slot param coercion failures are non-fatal — keep the raw value.
80
+ // The main route already validated the URL; the slot just interprets
81
+ // the same parts differently.
82
+ if (isDebug()) {
83
+ const message = err instanceof Error ? err.message : String(err);
84
+ console.warn(
85
+ `[timber] Slot param coercion failed for "${key}" (codec: ${bracketKey})\n` +
86
+ ` Error: ${message}\n` +
87
+ ` Raw value: ${JSON.stringify(result[key])}\n` +
88
+ ` Keeping raw value.`
89
+ );
90
+ }
91
+ }
92
+ }
93
+
94
+ return result as Record<string, string | string[]>;
95
+ }
96
+
39
97
  /**
40
98
  * Run segment param coercion on the matched route's segments.
41
99
  *
@@ -20,7 +20,7 @@ import {
20
20
  applyRequestHeaderOverlay,
21
21
  setMutableCookieContext,
22
22
  setSegmentParams,
23
- setMatchedRoutePattern,
23
+ setMatchedSegmentPath,
24
24
  } from './request-context.js';
25
25
  import { withSpan } from './tracing.js';
26
26
  import { logRenderError } from './logger.js';
@@ -380,6 +380,11 @@ export async function handleRequest(
380
380
  // Load params.ts modules from matched segments and coerce raw string
381
381
  // params through defineSegmentParams codecs. Coercion failure → 404
382
382
  // (middleware never runs). See design/07-routing.md §"Where Coercion Runs"
383
+ //
384
+ // Snapshot raw params before coercion — slot resolution needs the
385
+ // original string values to reconstruct URL parts for tree matching.
386
+ // Coerced params may have been transformed by codecs.
387
+ match.rawSegmentParams = { ...match.segmentParams };
383
388
  try {
384
389
  await coerceSegmentParams(match);
385
390
  } catch (error) {
@@ -419,12 +424,14 @@ export async function handleRequest(
419
424
  // See design/07-routing.md §"params.ts — Convention File for Typed Params"
420
425
  setSegmentParams(match.segmentParams);
421
426
 
422
- // Store the matched route pattern for dev-mode validation in getSegmentParams().
423
- // The leaf segment's urlPath is the accumulated route pattern.
424
- const leaf = match.segments[match.segments.length - 1];
425
- if (leaf) {
426
- setMatchedRoutePattern(leaf.urlPath);
427
- }
427
+ // Store the matched segment path for dev-mode validation in getSegmentParams().
428
+ // Build the tree path from the segment chain (includes groups and slots).
429
+ const segmentPath =
430
+ match.segments
431
+ .map((s) => s.segmentName)
432
+ .filter(Boolean)
433
+ .join('/') || '/';
434
+ setMatchedSegmentPath(segmentPath.startsWith('/') ? segmentPath : `/${segmentPath}`);
428
435
 
429
436
  // Bypass middleware for synthetic re-render requests built by the
430
437
  // action-dispatch wrapper after a no-JS form validation failure.
@@ -50,6 +50,13 @@ export interface RouteMatch {
50
50
  segments: ManifestSegmentNode[];
51
51
  /** Extracted segment params (catch-all segments produce string[]). */
52
52
  segmentParams: Record<string, string | string[]>;
53
+ /**
54
+ * Raw segment params before codec coercion. Always string or string[].
55
+ * Used by slot resolution to reconstruct URL parts — coerced params may
56
+ * have been transformed by codecs and are unsuitable for URL matching.
57
+ * Set by the pipeline before coercion runs.
58
+ */
59
+ rawSegmentParams?: Record<string, string | string[]>;
53
60
  /** Middleware chain from the segment tree, ordered root-to-leaf. */
54
61
  middlewareChain: MiddlewareFn[];
55
62
  }
@@ -89,16 +89,16 @@ _setGetSegmentParamsFn(getSegmentParams);
89
89
  /**
90
90
  * Returns the current request's coerced segment params.
91
91
  *
92
- * The optional `_route` argument exists only for TypeScript narrowing —
93
- * it does not affect the runtime return value. Pass a route pattern
94
- * (e.g. `'/[artistSlug]/[year]'`) to narrow the return type to the
95
- * exact params shape for that route.
92
+ * The optional `segmentPath` argument exists only for TypeScript narrowing —
93
+ * it does not affect the runtime return value. Pass a segment path
94
+ * (e.g. `'/(browse)/[artistSlug]/[year]'`) to narrow the return type to the
95
+ * exact params shape for that segment.
96
96
  *
97
- * Without a route argument, returns all coerced params with optional types.
97
+ * Without an argument, returns all coerced params with optional types.
98
98
  *
99
99
  * See design/41-global-params.md §Function Signatures
100
100
  */
101
- export function getSegmentParams(route?: string): Record<string, string | string[]> {
101
+ export function getSegmentParams(segmentPath?: string): Record<string, string | string[]> {
102
102
  const store = requestContextAls.getStore();
103
103
  if (!store) {
104
104
  throw new Error(
@@ -113,18 +113,31 @@ export function getSegmentParams(route?: string): Record<string, string | string
113
113
  );
114
114
  }
115
115
 
116
- // Dev-mode validation: warn when the route argument expects dynamic
117
- // segments that don't exist on the actual matched route. This catches
118
- // bugs like passing a child route's $segment to a parent layout.
116
+ // Check slot params map first — parallel slots may have different param
117
+ // types than the main route (e.g. catch-all [..year] → string[] vs
118
+ // dynamic [year] → string). If the requested segment path matches a
119
+ // stored slot, return its params merged with the main route's.
120
+ if (segmentPath && store.slotParamsMap?.has(segmentPath)) {
121
+ const slotParams = store.slotParamsMap.get(segmentPath)!;
122
+ // Merge: main params as base, slot-specific params override.
123
+ // This ensures params from segments above the slot (that the slot
124
+ // doesn't re-derive) are still available.
125
+ return { ...store.segmentParams, ...slotParams };
126
+ }
127
+
128
+ // Dev-mode validation: warn when the segment path expects dynamic
129
+ // segments that don't exist on the actual matched segment. This catches
130
+ // bugs like passing a child segment's $segment to a parent layout.
131
+ // Skip for slot paths — they're validated against their own chain.
119
132
  // See design/41-global-params.md §Runtime Validation
120
- if (route && isDebug() && store.matchedRoutePattern) {
121
- const expected = extractDynamicSegments(route);
122
- const actual = extractDynamicSegments(store.matchedRoutePattern);
133
+ if (segmentPath && isDebug() && store.matchedSegmentPath) {
134
+ const expected = extractDynamicSegments(segmentPath);
135
+ const actual = extractDynamicSegments(store.matchedSegmentPath);
123
136
  const missing = expected.filter((s) => !actual.includes(s));
124
137
 
125
138
  if (missing.length > 0) {
126
139
  console.warn(
127
- `[timber] getSegmentParams('${route}') called but current route is '${store.matchedRoutePattern}'\n` +
140
+ `[timber] getSegmentParams('${segmentPath}') called but current segment is '${store.matchedSegmentPath}'\n` +
128
141
  ` Missing params: ${missing.join(', ')}\n` +
129
142
  ` These will be undefined at runtime despite the type annotation.`
130
143
  );
@@ -149,15 +162,33 @@ export function setSegmentParams(params: Record<string, string | string[]>): voi
149
162
  }
150
163
 
151
164
  /**
152
- * Store the matched route pattern (e.g. '/[artistSlug]/[year]') for
153
- * dev-mode route mismatch validation in getSegmentParams().
165
+ * Store per-slot coerced segment params in the current request context.
166
+ * Called by the route element builder when resolving parallel slots.
167
+ *
168
+ * @param segmentPath — The slot's full tree path (e.g. '/(browse)/@shows/[artistSlug]/[...year]')
169
+ * @param params — The slot's coerced segment params
170
+ * @internal — framework use only
171
+ */
172
+ export function setSlotParams(
173
+ segmentPath: string,
174
+ params: Record<string, string | string[]>
175
+ ): void {
176
+ const store = requestContextAls.getStore();
177
+ if (!store) return; // non-throwing — optional diagnostic
178
+ if (!store.slotParamsMap) store.slotParamsMap = new Map();
179
+ store.slotParamsMap.set(segmentPath, params);
180
+ }
181
+
182
+ /**
183
+ * Store the matched segment path (e.g. '/(browse)/[artistSlug]/[year]') for
184
+ * dev-mode validation in getSegmentParams().
154
185
  *
155
186
  * @internal — framework use only
156
187
  */
157
- export function setMatchedRoutePattern(pattern: string): void {
188
+ export function setMatchedSegmentPath(segmentPath: string): void {
158
189
  const store = requestContextAls.getStore();
159
190
  if (!store) return; // non-throwing — optional diagnostic
160
- store.matchedRoutePattern = pattern;
191
+ store.matchedSegmentPath = segmentPath;
161
192
  }
162
193
 
163
194
  /**
@@ -465,7 +465,16 @@ export async function buildRouteElement(
465
465
  // This prevents leaking layout UI (sidebars, nav) on denied pages.
466
466
  // See design/04-authorization.md §"Access Failure".
467
467
  if (layoutComponent) {
468
- // Resolve parallel slots for this layout
468
+ // Resolve parallel slots for this layout.
469
+ // Compute the parent tree path so slots can build their full
470
+ // segment path for per-slot param storage in ALS.
471
+ const parentTreePath =
472
+ '/' +
473
+ segments
474
+ .slice(0, i + 1)
475
+ .map((s) => s.segmentName)
476
+ .filter(Boolean)
477
+ .join('/');
469
478
  const slotProps: Record<string, unknown> = {};
470
479
  const slotEntries = Object.entries(segment.slots ?? {});
471
480
  for (const [slotName, slotNode] of slotEntries) {
@@ -473,7 +482,8 @@ export async function buildRouteElement(
473
482
  slotNode as ManifestSegmentNode,
474
483
  match,
475
484
  h,
476
- interception
485
+ interception,
486
+ parentTreePath
477
487
  );
478
488
  }
479
489