@timber-js/app 0.2.0-alpha.120 → 0.2.0-alpha.122

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 (157) hide show
  1. package/dist/_chunks/{actions-Cw-7NfJJ.js → actions-Dy8vOjFt.js} +6 -6
  2. package/dist/_chunks/actions-Dy8vOjFt.js.map +1 -0
  3. package/dist/_chunks/{build-output-helper-DhxiT18k.js → build-output-helper-DYOWsPjZ.js} +47 -6
  4. package/dist/_chunks/build-output-helper-DYOWsPjZ.js.map +1 -0
  5. package/dist/_chunks/cli-schema-sync-4HcQIziG.js +2 -0
  6. package/dist/_chunks/cli-schema-sync-VcCf1TFY.js +738 -0
  7. package/dist/_chunks/cli-schema-sync-VcCf1TFY.js.map +1 -0
  8. package/dist/_chunks/{codec-registry-V7ARyeLN.js → codec-registry-G9hD5LOq.js} +1 -1
  9. package/dist/_chunks/{codec-registry-V7ARyeLN.js.map → codec-registry-G9hD5LOq.js.map} +1 -1
  10. package/dist/_chunks/{define-zQX6e1tN.js → define-CPVQaWbx.js} +3 -3
  11. package/dist/_chunks/{define-zQX6e1tN.js.map → define-CPVQaWbx.js.map} +1 -1
  12. package/dist/_chunks/{define-8zQ8Vm7x.js → define-jeHDXZGq.js} +3 -3
  13. package/dist/_chunks/{define-8zQ8Vm7x.js.map → define-jeHDXZGq.js.map} +1 -1
  14. package/dist/_chunks/{format-CR6v1pWE.js → format-BjN9HLu9.js} +1 -1
  15. package/dist/_chunks/{format-CR6v1pWE.js.map → format-BjN9HLu9.js.map} +1 -1
  16. package/dist/_chunks/{handler-store-iqnt2ghN.js → handler-store-CcwNX-gk.js} +1 -1
  17. package/dist/_chunks/{handler-store-iqnt2ghN.js.map → handler-store-CcwNX-gk.js.map} +1 -1
  18. package/dist/_chunks/{merge-search-params-CwxJzBLS.js → merge-search-params-az6ZiBeU.js} +1 -1
  19. package/dist/_chunks/{merge-search-params-CwxJzBLS.js.map → merge-search-params-az6ZiBeU.js.map} +1 -1
  20. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DESG8uk5.js} +32 -19
  21. package/dist/_chunks/metadata-routes-DESG8uk5.js.map +1 -0
  22. package/dist/_chunks/{navigation-root-DKsJ5Di7.js → navigation-root-DoRTeBm5.js} +2 -2
  23. package/dist/_chunks/{navigation-root-DKsJ5Di7.js.map → navigation-root-DoRTeBm5.js.map} +1 -1
  24. package/dist/_chunks/{registry-Dp_hJL4s.js → registry-BI9cgCt7.js} +1 -1
  25. package/dist/_chunks/{registry-Dp_hJL4s.js.map → registry-BI9cgCt7.js.map} +1 -1
  26. package/dist/_chunks/{resolve-schema-23Mc8aLi.js → resolve-schema-cURaYvaD.js} +15 -3
  27. package/dist/_chunks/resolve-schema-cURaYvaD.js.map +1 -0
  28. package/dist/_chunks/{router-ref-sektkr-t.js → router-ref-CpvjBqdu.js} +2 -2
  29. package/dist/_chunks/{router-ref-sektkr-t.js.map → router-ref-CpvjBqdu.js.map} +1 -1
  30. package/dist/_chunks/{schema-bridge-eL5vQDSA.js → schema-bridge-o0SwFtXW.js} +1 -1
  31. package/dist/_chunks/{schema-bridge-eL5vQDSA.js.map → schema-bridge-o0SwFtXW.js.map} +1 -1
  32. package/dist/_chunks/{segment-classify-CnfLLvir.js → segment-classify-BjfuctV2.js} +1 -1
  33. package/dist/_chunks/{segment-classify-CnfLLvir.js.map → segment-classify-BjfuctV2.js.map} +1 -1
  34. package/dist/_chunks/{segment-context-Bg0pFbLT.js → segment-context-EsfQpS--.js} +1 -1
  35. package/dist/_chunks/{segment-context-Bg0pFbLT.js.map → segment-context-EsfQpS--.js.map} +1 -1
  36. package/dist/_chunks/{ssr-data-BO5OvEvg.js → ssr-data-m9-cNEIw.js} +1 -1
  37. package/dist/_chunks/{ssr-data-BO5OvEvg.js.map → ssr-data-m9-cNEIw.js.map} +1 -1
  38. package/dist/_chunks/{stale-reload-BCPRG0Cv.js → stale-reload-BN2kcE06.js} +1 -1
  39. package/dist/_chunks/{stale-reload-BCPRG0Cv.js.map → stale-reload-BN2kcE06.js.map} +1 -1
  40. package/dist/_chunks/{use-query-states-D9SBlAfp.js → use-query-states-C9G6LP0F.js} +2 -2
  41. package/dist/_chunks/{use-query-states-D9SBlAfp.js.map → use-query-states-C9G6LP0F.js.map} +1 -1
  42. package/dist/_chunks/{use-segment-params-CskiK-59.js → use-segment-params-CtIAjqK0.js} +2 -2
  43. package/dist/_chunks/{use-segment-params-CskiK-59.js.map → use-segment-params-CtIAjqK0.js.map} +1 -1
  44. package/dist/_chunks/{validation-Bm3Je-09.js → validation-BMU5MPzP.js} +1 -1
  45. package/dist/_chunks/{validation-Bm3Je-09.js.map → validation-BMU5MPzP.js.map} +1 -1
  46. package/dist/_chunks/{walkers-DgOXkTts.js → walkers-tkw7sDlj.js} +125 -12
  47. package/dist/_chunks/walkers-tkw7sDlj.js.map +1 -0
  48. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  49. package/dist/adapters/cloudflare.js +1 -1
  50. package/dist/adapters/nitro.js +1 -1
  51. package/dist/cache/index.js +1 -1
  52. package/dist/cli-schema-sync.d.ts.map +1 -1
  53. package/dist/cli.js +1 -1
  54. package/dist/client/error-boundary.js +2 -2
  55. package/dist/client/index.js +10 -10
  56. package/dist/client/index.js.map +1 -1
  57. package/dist/client/internal.js +7 -7
  58. package/dist/client/link.d.ts +9 -5
  59. package/dist/client/link.d.ts.map +1 -1
  60. package/dist/codec.d.ts +18 -0
  61. package/dist/codec.d.ts.map +1 -1
  62. package/dist/codec.js +30 -1
  63. package/dist/codec.js.map +1 -1
  64. package/dist/cookies/index.js +3 -3
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +127 -26
  67. package/dist/index.js.map +1 -1
  68. package/dist/params/define-schema.d.ts +32 -4
  69. package/dist/params/define-schema.d.ts.map +1 -1
  70. package/dist/params/index.d.ts +1 -1
  71. package/dist/params/index.d.ts.map +1 -1
  72. package/dist/params/index.js +2 -2
  73. package/dist/params/index.js.map +1 -1
  74. package/dist/params/resolve-schema.d.ts.map +1 -1
  75. package/dist/plugins/build-manifest.d.ts.map +1 -1
  76. package/dist/plugins/cloudflare-wasm.d.ts +18 -0
  77. package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
  78. package/dist/plugins/dev-server.d.ts.map +1 -1
  79. package/dist/plugins/routing.d.ts.map +1 -1
  80. package/dist/routing/codegen-shared.d.ts +5 -4
  81. package/dist/routing/codegen-shared.d.ts.map +1 -1
  82. package/dist/routing/index.d.ts +2 -0
  83. package/dist/routing/index.d.ts.map +1 -1
  84. package/dist/routing/index.js +4 -4
  85. package/dist/routing/scanner.d.ts.map +1 -1
  86. package/dist/routing/schema-validation.d.ts +35 -0
  87. package/dist/routing/schema-validation.d.ts.map +1 -0
  88. package/dist/search-params/index.js +3 -3
  89. package/dist/segment-params/index.js +1 -1
  90. package/dist/server/actions.d.ts +3 -8
  91. package/dist/server/actions.d.ts.map +1 -1
  92. package/dist/server/build-manifest.d.ts +6 -0
  93. package/dist/server/build-manifest.d.ts.map +1 -1
  94. package/dist/server/index.js +2 -2
  95. package/dist/server/internal.d.ts +1 -1
  96. package/dist/server/internal.d.ts.map +1 -1
  97. package/dist/server/internal.js +15 -6
  98. package/dist/server/internal.js.map +1 -1
  99. package/dist/server/metadata-routes.d.ts +23 -7
  100. package/dist/server/metadata-routes.d.ts.map +1 -1
  101. package/dist/server/pipeline-phases.d.ts.map +1 -1
  102. package/dist/server/request-context.d.ts.map +1 -1
  103. package/dist/server/route-element-builder.d.ts +1 -1
  104. package/dist/server/route-element-builder.d.ts.map +1 -1
  105. package/dist/server/route-matcher.d.ts +4 -2
  106. package/dist/server/route-matcher.d.ts.map +1 -1
  107. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  108. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  109. package/dist/server/ssr-entry.d.ts.map +1 -1
  110. package/dist/server/tree-match.d.ts +12 -4
  111. package/dist/server/tree-match.d.ts.map +1 -1
  112. package/dist/server/types.d.ts +2 -2
  113. package/package.json +7 -6
  114. package/src/adapters/build-output-helper.ts +67 -5
  115. package/src/cli-schema-sync.ts +25 -4
  116. package/src/cli.ts +0 -0
  117. package/src/client/browser-entry/index.ts +1 -1
  118. package/src/client/link.tsx +9 -9
  119. package/src/codec.ts +51 -1
  120. package/src/index.ts +2 -0
  121. package/src/params/define-schema.ts +46 -5
  122. package/src/params/index.ts +7 -1
  123. package/src/params/resolve-schema.ts +28 -0
  124. package/src/plugins/build-manifest.ts +57 -5
  125. package/src/plugins/cloudflare-wasm.ts +103 -0
  126. package/src/plugins/dev-server.ts +4 -2
  127. package/src/plugins/routing.ts +31 -34
  128. package/src/routing/codegen-shared.ts +8 -5
  129. package/src/routing/codegen.ts +59 -5
  130. package/src/routing/index.ts +5 -0
  131. package/src/routing/link-codegen.ts +1 -1
  132. package/src/routing/scanner.ts +58 -0
  133. package/src/routing/schema-validation.ts +149 -0
  134. package/src/server/actions.ts +4 -14
  135. package/src/server/build-manifest.ts +7 -0
  136. package/src/server/internal.ts +7 -1
  137. package/src/server/metadata-routes.ts +44 -19
  138. package/src/server/pipeline-phases.ts +8 -0
  139. package/src/server/request-context.ts +0 -4
  140. package/src/server/route-element-builder.ts +57 -11
  141. package/src/server/route-matcher.ts +81 -49
  142. package/src/server/rsc-entry/index.ts +7 -1
  143. package/src/server/rsc-entry/render-route.ts +7 -1
  144. package/src/server/ssr-entry.ts +6 -0
  145. package/src/server/tree-match.ts +23 -11
  146. package/src/server/types.ts +2 -2
  147. package/LICENSE +0 -8
  148. package/dist/_chunks/actions-Cw-7NfJJ.js.map +0 -1
  149. package/dist/_chunks/build-output-helper-DhxiT18k.js.map +0 -1
  150. package/dist/_chunks/cli-schema-sync-XV0I47Gj.js +0 -2
  151. package/dist/_chunks/cli-schema-sync-q2wB0DyJ.js +0 -358
  152. package/dist/_chunks/cli-schema-sync-q2wB0DyJ.js.map +0 -1
  153. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
  154. package/dist/_chunks/resolve-schema-23Mc8aLi.js.map +0 -1
  155. package/dist/_chunks/scanner-DmfoB7iK.js +0 -336
  156. package/dist/_chunks/scanner-DmfoB7iK.js.map +0 -1
  157. package/dist/_chunks/walkers-DgOXkTts.js.map +0 -1
@@ -18,7 +18,7 @@ export interface MetadataRouteInfo {
18
18
  /** Whether this route can appear in nested segments (not just app root). */
19
19
  nestable: boolean;
20
20
  }
21
- export type MetadataRouteType = 'sitemap' | 'robots' | 'manifest' | 'favicon' | 'icon' | 'opengraph-image' | 'twitter-image' | 'apple-icon';
21
+ export type MetadataRouteType = 'sitemap' | 'robots' | 'manifest' | 'favicon' | 'icon' | 'opengraph-image' | 'apple-icon';
22
22
  /**
23
23
  * All recognized metadata route file conventions.
24
24
  *
@@ -78,17 +78,33 @@ export declare function classifyMetadataRoute(fileName: string): MetadataRouteIn
78
78
  * @returns The URL path fragment this route serves at
79
79
  */
80
80
  export declare function getMetadataRouteServePath(type: MetadataRouteType): string;
81
+ export declare function isMetadataRouteServePath(pathname: string): boolean;
82
+ /** A <link> auto-link tag. */
83
+ export interface AutoLinkLink {
84
+ tag: 'link';
85
+ rel: string;
86
+ href: string;
87
+ type?: string;
88
+ }
89
+ /** A <meta> auto-link tag. */
90
+ export interface AutoLinkMeta {
91
+ tag: 'meta';
92
+ property?: string;
93
+ name?: string;
94
+ content: string;
95
+ }
96
+ export type AutoLinkTag = AutoLinkLink | AutoLinkMeta;
81
97
  /**
82
98
  * Get the auto-link tags to inject into <head> for metadata route files
83
99
  * discovered in a segment.
84
100
  *
101
+ * Returns link tags for icon/apple-icon/manifest, and meta tags for
102
+ * opengraph-image (emits both og:image and twitter:image). Returns null
103
+ * for types that don't auto-link (favicon, sitemap, robots).
104
+ *
85
105
  * @param type - The metadata route type
86
106
  * @param href - The resolved URL path to the metadata route
87
- * @returns An object with tag/attrs for the <head>, or null if no auto-link
107
+ * @returns Tag descriptor(s) for the <head>, or null if no auto-link
88
108
  */
89
- export declare function getMetadataRouteAutoLink(type: MetadataRouteType, href: string): {
90
- rel: string;
91
- href: string;
92
- type?: string;
93
- } | null;
109
+ export declare function getMetadataRouteAutoLink(type: MetadataRouteType, href: string): AutoLinkTag[];
94
110
  //# sourceMappingURL=metadata-routes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metadata-routes.d.ts","sourceRoot":"","sources":["../../src/server/metadata-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,IAAI,EAAE,iBAAiB,CAAC;IACxB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,QAAQ,GACR,UAAU,GACV,SAAS,GACT,MAAM,GACN,iBAAiB,GACjB,eAAe,GACf,YAAY,CAAC;AAIjB;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAC7C,MAAM,EACN;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CACnB,CAkEF,CAAC;AAoBF;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,qBAAqB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKjG;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAItF;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAIvF;AAID;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAoBhF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAKzE;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,MAAM,GACX;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAWrD"}
1
+ {"version":3,"file":"metadata-routes.d.ts","sourceRoot":"","sources":["../../src/server/metadata-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,IAAI,EAAE,iBAAiB,CAAC;IACxB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,QAAQ,GACR,UAAU,GACV,SAAS,GACT,MAAM,GACN,iBAAiB,GACjB,YAAY,CAAC;AAIjB;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAC7C,MAAM,EACN;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CACnB,CA2DF,CAAC;AAoBF;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,qBAAqB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKjG;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAItF;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAIvF;AAID;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAoBhF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAKzE;AAMD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED,8BAA8B;AAC9B,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,8BAA8B;AAC9B,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAgB7F"}
@@ -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,CAiQnB"}
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,CAyQnB"}
@@ -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,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
+ {"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;AAI7B;;;;;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"}
@@ -95,5 +95,5 @@ export declare class RouteSignalWithContext extends Error {
95
95
  * AccessPreRunner during renderToReadableStream so that access.ts and
96
96
  * render components share the same React.cache scope (TIM-662).
97
97
  */
98
- export declare function buildRouteElement(req: Request, match: RouteMatch, interception?: InterceptionContext, clientStateTree?: Set<string> | null): Promise<RouteElementResult>;
98
+ export declare function buildRouteElement(req: Request, match: RouteMatch, interception?: InterceptionContext, clientStateTree?: Set<string> | null, metadataRouteHashes?: Record<string, string>): Promise<RouteElementResult>;
99
99
  //# sourceMappingURL=route-element-builder.d.ts.map
@@ -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,CAqW7B"}
1
+ {"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAY9D,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,EACpC,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,kBAAkB,CAAC,CA0Y7B"}
@@ -57,12 +57,14 @@ export interface MetadataRouteMatch {
57
57
  * that should be served from disk rather than executed as a handler.
58
58
  */
59
59
  isStatic: boolean;
60
+ /** Extracted segment params from dynamic segments in the URL prefix. */
61
+ segmentParams: Record<string, string | string[]>;
60
62
  }
61
63
  /**
62
64
  * Create a metadata route matcher from a manifest.
63
65
  *
64
- * Walks the segment tree and builds a map from serve paths to handler modules.
65
- * Metadata routes are matched by exact pathname (e.g., /sitemap.xml, /blog/sitemap.xml).
66
+ * Uses dynamic tree matching to resolve metadata routes, supporting
67
+ * dynamic segments like /docs/[slug]/opengraph-image.
66
68
  *
67
69
  * See design/16-metadata.md §"Metadata Routes"
68
70
  */
@@ -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;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"}
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;IAClB,wEAAwE;IACxE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAClD;AAQD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,YAAY,GACrB,CAAC,QAAQ,EAAE,MAAM,KAAK,kBAAkB,GAAG,IAAI,CAEjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/index.ts"],"names":[],"mappings":"AAuBA,OAAO,uCAAuC,CAAC;AAqB/C,OAAO,KAAK,EAAuB,cAAc,EAAc,MAAM,gBAAgB,CAAC;AAqCtF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAE5E;AA8WD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAInE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,QAAA,MAAiB,QAAQ,qCAGxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,gBAAkB,CAAC;AAE9C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/index.ts"],"names":[],"mappings":"AAuBA,OAAO,uCAAuC,CAAC;AAqB/C,OAAO,KAAK,EAAuB,cAAc,EAAc,MAAM,gBAAgB,CAAC;AAqCtF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAE5E;AAoXD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAInE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,QAAA,MAAiB,QAAQ,qCAGxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,gBAAkB,CAAC;AAE9C,eAAe,QAAQ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"render-route.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/render-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAU1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAkB/D;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,qBAAqB,CAAC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,mBAAmB,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAClE;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,IAAI,EAAE,eAAe,EACrB,YAAY,CAAC,EAAE,mBAAmB,GACjC,OAAO,CAAC,QAAQ,CAAC,CAkOnB"}
1
+ {"version":3,"file":"render-route.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/render-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAU1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAkB/D;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,qBAAqB,CAAC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,mBAAmB,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAClE;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,IAAI,EAAE,eAAe,EACrB,YAAY,CAAC,EAAE,mBAAmB,GACjC,OAAO,CAAC,QAAQ,CAAC,CAwOnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-entry.d.ts","sourceRoot":"","sources":["../../src/server/ssr-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,uCAAuC,CAAC;AA2E/C;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,eAAe,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qEAAqE;IACrE,SAAS,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACvC;;;0DAGsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iFAE6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;4DACwD;IACxD,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE;QACZ,gFAAgF;QAChF,QAAQ,EAAE,MAAM,CAAC;QACjB,uDAAuD;QACvD,OAAO,EAAE,MAAM,CAAC;QAChB,gEAAgE;QAChE,MAAM,EAAE,MAAM,CAAC;QACf,wEAAwE;QACxE,UAAU,EAAE,MAAM,CAAC;QACnB,+CAA+C;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,sDAAsD;QACtD,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IAEF;;;;;OAKG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,QAAQ,CAAC,CA6LnB;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"ssr-entry.d.ts","sourceRoot":"","sources":["../../src/server/ssr-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,uCAAuC,CAAC;AAiF/C;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,eAAe,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qEAAqE;IACrE,SAAS,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACvC;;;0DAGsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iFAE6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;4DACwD;IACxD,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE;QACZ,gFAAgF;QAChF,QAAQ,EAAE,MAAM,CAAC;QACjB,uDAAuD;QACvD,OAAO,EAAE,MAAM,CAAC;QAChB,gEAAgE;QAChE,MAAM,EAAE,MAAM,CAAC;QACf,wEAAwE;QACxE,UAAU,EAAE,MAAM,CAAC;QACnB,+CAA+C;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,sDAAsD;QACtD,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IAEF;;;;;OAKG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,QAAQ,CAAC,CA6LnB;AAED,eAAe,SAAS,CAAC"}
@@ -22,6 +22,14 @@ export interface TreeMatchResult<TFile> {
22
22
  /** Collected params, keyed by param name. Catch-all params are string[]. */
23
23
  params: Record<string, string | string[]>;
24
24
  }
25
+ export interface TreeMatchOptions {
26
+ /**
27
+ * When true (default), only match if the leaf node has a page or route
28
+ * handler. Set to false for metadata route matching, where we just need
29
+ * to find the owning segment regardless of whether it has a page.
30
+ */
31
+ requireTerminal?: boolean;
32
+ }
25
33
  /**
26
34
  * Match URL path parts against a segment tree.
27
35
  *
@@ -29,13 +37,13 @@ export interface TreeMatchResult<TFile> {
29
37
  * ordering globally across group boundaries. Returns the matched
30
38
  * segment chain and collected params, or null if no route matches.
31
39
  *
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.
40
+ * By default, a match requires a terminal node (one with `page` or
41
+ * `route`) at the leaf. Pass `{ requireTerminal: false }` to match
42
+ * any segment (used by metadata route matching).
35
43
  *
36
44
  * @param root The root segment node to start matching from.
37
45
  * @param parts URL path parts (e.g. ['blog', 'hello-world']).
38
46
  * Empty array matches the root itself (if terminal).
39
47
  */
40
- export declare function matchUrlParts<TFile>(root: SegmentNode<TFile>, parts: string[]): TreeMatchResult<TFile> | null;
48
+ export declare function matchUrlParts<TFile>(root: SegmentNode<TFile>, parts: string[], options?: TreeMatchOptions): TreeMatchResult<TFile> | null;
41
49
  //# sourceMappingURL=tree-match.d.ts.map
@@ -1 +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"}
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,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EACjC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,EACxB,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE,gBAAgB,GACzB,eAAe,CAAC,KAAK,CAAC,GAAG,IAAI,CAS/B"}
@@ -250,7 +250,7 @@ export declare namespace MetadataRoute {
250
250
  * This is a structural union — the pipeline dispatches on the shape at
251
251
  * request time (see `pipeline-phases.ts`):
252
252
  * - `Response` → returned as-is (e.g. `ImageResponse`, `Response.redirect()`).
253
- * Used by `icon.tsx`, `opengraph-image.tsx`, `twitter-image.tsx`,
253
+ * Used by `icon.tsx`, `opengraph-image.tsx`,
254
254
  * `apple-icon.tsx`.
255
255
  * - `string` → written as the response body verbatim. Used by `robots.ts`
256
256
  * and by any handler that wants to emit a pre-serialized payload.
@@ -265,7 +265,7 @@ export type MetadataResult = Response | string | MetadataRoute.Sitemap | Metadat
265
265
  /**
266
266
  * Default export signature for a dynamic metadata route file
267
267
  * (`sitemap.ts`, `robots.ts`, `manifest.ts`, `icon.tsx`,
268
- * `opengraph-image.tsx`, `twitter-image.tsx`, `apple-icon.tsx`).
268
+ * `opengraph-image.tsx`, `apple-icon.tsx`).
269
269
  *
270
270
  * Parameterize `TResult` to narrow the return type for a specific route:
271
271
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timber-js/app",
3
- "version": "0.2.0-alpha.120",
3
+ "version": "0.2.0-alpha.122",
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",
@@ -114,6 +114,11 @@
114
114
  "publishConfig": {
115
115
  "access": "public"
116
116
  },
117
+ "scripts": {
118
+ "build": "vite build --config vite.lib.config.ts && tsc --emitDeclarationOnly --project tsconfig.json --outDir dist",
119
+ "typecheck": "tsgo --noEmit",
120
+ "prepublishOnly": "pnpm run build"
121
+ },
117
122
  "dependencies": {
118
123
  "@opentelemetry/api": "^1.9.1",
119
124
  "@opentelemetry/context-async-hooks": "^2.6.1",
@@ -157,9 +162,5 @@
157
162
  },
158
163
  "engines": {
159
164
  "node": ">=22.12.0"
160
- },
161
- "scripts": {
162
- "build": "vite build --config vite.lib.config.ts && tsc --emitDeclarationOnly --project tsconfig.json --outDir dist",
163
- "typecheck": "tsgo --noEmit"
164
165
  }
165
- }
166
+ }
@@ -11,8 +11,8 @@
11
11
  // IMPORTANT: This module must remain a leaf — no imports from ../server/,
12
12
  // ../client/, or Vite-dependent code. See adapters/shared.ts header.
13
13
 
14
- import { writeFile, mkdir, cp } from 'node:fs/promises';
15
- import { join } from 'node:path';
14
+ import { writeFile, mkdir, cp, readdir, readFile } from 'node:fs/promises';
15
+ import { join, basename } from 'node:path';
16
16
  import { generateHeadersFile } from './shared.js';
17
17
  import type { TimberConfig } from './types';
18
18
 
@@ -54,11 +54,23 @@ export async function runSharedBuildSteps(opts: BuildOutputBaseOptions): Promise
54
54
  const clientDir = join(buildDir, 'client');
55
55
  const publicDir = join(outDir, publicDirName);
56
56
  await mkdir(publicDir, { recursive: true });
57
+ // Find WASM files that are referenced by client JS (legitimate client WASM)
58
+ // vs orphaned server-only WASM (e.g. @takumi-rs for OG image generation).
59
+ // Only strip orphaned WASM to avoid breaking client-side WASM usage.
60
+ const referencedWasm = await findReferencedWasm(clientDir);
61
+
57
62
  await cp(clientDir, publicDir, {
58
63
  recursive: true,
59
- filter: config.clientJavascriptDisabled ? (src: string) => !src.endsWith('.js') : undefined,
60
- }).catch(() => {
64
+ filter: (src: string) => {
65
+ if (src.endsWith('.wasm') && !referencedWasm.has(basename(src))) {
66
+ return false;
67
+ }
68
+ if (config.clientJavascriptDisabled && src.endsWith('.js')) return false;
69
+ return true;
70
+ },
71
+ }).catch((e: NodeJS.ErrnoException) => {
61
72
  // Client dir may not exist when client JavaScript is disabled
73
+ if (e.code !== 'ENOENT') throw e;
62
74
  });
63
75
 
64
76
  // 3. Write _headers file for static asset cache control.
@@ -66,7 +78,12 @@ export async function runSharedBuildSteps(opts: BuildOutputBaseOptions): Promise
66
78
 
67
79
  // 4. Copy RSC + SSR server bundles into the output directory.
68
80
  await cp(join(buildDir, 'rsc'), join(outDir, 'rsc'), { recursive: true });
69
- await cp(join(buildDir, 'ssr'), join(outDir, 'ssr'), { recursive: true }).catch(() => {});
81
+ await cp(join(buildDir, 'ssr'), join(outDir, 'ssr'), { recursive: true }).catch(
82
+ (e: NodeJS.ErrnoException) => {
83
+ // SSR dir may not exist for static-only builds
84
+ if (e.code !== 'ENOENT') throw e;
85
+ }
86
+ );
70
87
 
71
88
  // 5. Write manifest-init module if present.
72
89
  if (config.manifestInit) {
@@ -75,3 +92,48 @@ export async function runSharedBuildSteps(opts: BuildOutputBaseOptions): Promise
75
92
 
76
93
  return publicDir;
77
94
  }
95
+
96
+ /**
97
+ * Scan client JS files for references to .wasm filenames.
98
+ * Returns the set of WASM basenames that are actually imported/referenced
99
+ * by client code and must be preserved in the static output.
100
+ */
101
+ async function findReferencedWasm(clientDir: string): Promise<Set<string>> {
102
+ const referenced = new Set<string>();
103
+
104
+ let files: string[];
105
+ try {
106
+ files = await collectFiles(clientDir);
107
+ } catch {
108
+ return referenced;
109
+ }
110
+
111
+ const jsFiles = files.filter((f) => f.endsWith('.js'));
112
+ const wasmFiles = files.filter((f) => f.endsWith('.wasm')).map((f) => basename(f));
113
+ if (wasmFiles.length === 0) return referenced;
114
+
115
+ for (const jsFile of jsFiles) {
116
+ const content = await readFile(jsFile, 'utf-8');
117
+ for (const wasmName of wasmFiles) {
118
+ if (content.includes(wasmName)) {
119
+ referenced.add(wasmName);
120
+ }
121
+ }
122
+ }
123
+
124
+ return referenced;
125
+ }
126
+
127
+ async function collectFiles(dir: string): Promise<string[]> {
128
+ const result: string[] = [];
129
+ const entries = await readdir(dir, { withFileTypes: true });
130
+ for (const entry of entries) {
131
+ const fullPath = join(dir, entry.name);
132
+ if (entry.isDirectory()) {
133
+ result.push(...(await collectFiles(fullPath)));
134
+ } else {
135
+ result.push(fullPath);
136
+ }
137
+ }
138
+ return result;
139
+ }
@@ -89,11 +89,32 @@ function generateNewSchema(segments: string[]): string {
89
89
  * Append missing segment entries to an existing schema file.
90
90
  * Inserts new entries before the closing `}` of segmentParams.
91
91
  */
92
+ const CODEC_IMPORT = "import { codec } from '@timber-js/app/codec';";
93
+
94
+ function hasCodecImport(content: string): boolean {
95
+ return /import\s+\{[^}]*\bcodec\b[^}]*\}\s+from\s+['"]@timber-js\/app\/codec['"]/.test(content);
96
+ }
97
+
98
+ function ensureCodecImport(content: string): string {
99
+ if (hasCodecImport(content)) return content;
100
+
101
+ // Insert after the last existing import statement
102
+ const lines = content.split('\n');
103
+ let lastImportIndex = -1;
104
+ for (let i = 0; i < lines.length; i++) {
105
+ if (/^\s*import\s/.test(lines[i])) lastImportIndex = i;
106
+ }
107
+
108
+ if (lastImportIndex === -1) {
109
+ return CODEC_IMPORT + '\n' + content;
110
+ }
111
+
112
+ lines.splice(lastImportIndex + 1, 0, CODEC_IMPORT);
113
+ return lines.join('\n');
114
+ }
115
+
92
116
  function appendToSchema(content: string, newSegments: string[]): string {
93
- // Find the closing brace of segmentParams object.
94
- // Strategy: find the last entry in segmentParams block, insert after it.
95
- // Look for the pattern: segmentParams: { ... }
96
- // We find the closing `},` or `}` that ends segmentParams.
117
+ content = ensureCodecImport(content);
97
118
 
98
119
  // Find "segmentParams" key position
99
120
  const spIndex = content.indexOf('segmentParams');
package/src/cli.ts CHANGED
File without changes
@@ -39,7 +39,7 @@ import 'virtual:timber-search-params-registry';
39
39
  // @ts-expect-error — virtual module provided by timber-routing plugin
40
40
  import schemaCodecs from 'virtual:timber-schema';
41
41
  import { setLinkCodecs } from '../../params/codec-registry.js';
42
- if (schemaCodecs) setLinkCodecs(schemaCodecs);
42
+ setLinkCodecs(schemaCodecs);
43
43
 
44
44
  import { setClientDeploymentId } from '../rsc-fetch.js';
45
45
  import {
@@ -143,6 +143,9 @@ export type LinkSegmentParams<T> = {
143
143
  // because there is no way to look up a definition from a computed string.
144
144
  //
145
145
  // `resolveHref` discriminates at runtime by presence of a `definition` key.
146
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
+ export type ParamValue = string | number | string[] | { toString(): string; [key: string]: any };
148
+
146
149
  type WrappedSearchParamsProp = {
147
150
  definition: SearchParamsDefinition<Record<string, unknown>>;
148
151
  values: Record<string, unknown>;
@@ -156,7 +159,7 @@ type LinkSearchParamsProp = WrappedSearchParamsProp | FlatSearchParamsProp;
156
159
  */
157
160
  interface LinkRuntimeProps extends LinkBaseProps {
158
161
  href: string;
159
- segmentParams?: Record<string, string | number | string[]>;
162
+ segmentParams?: Record<string, ParamValue>;
160
163
  searchParams?: LinkSearchParamsProp;
161
164
  }
162
165
 
@@ -167,7 +170,7 @@ export type LinkPropsWithHref = LinkBaseProps & {
167
170
  searchParams?: LinkSearchParamsProp;
168
171
  };
169
172
  export type LinkPropsWithParams = LinkRuntimeProps & {
170
- segmentParams: Record<string, string | number | string[]>;
173
+ segmentParams: Record<string, ParamValue>;
171
174
  };
172
175
  export type LinkProps = LinkRuntimeProps;
173
176
 
@@ -232,7 +235,7 @@ export function parseSegments(pattern: string): UrlSegment[] {
232
235
  */
233
236
  function resolveSegment(
234
237
  seg: UrlSegment,
235
- params: Record<string, string | number | string[]>,
238
+ params: Record<string, ParamValue>,
236
239
  pattern: string
237
240
  ): string | null {
238
241
  switch (seg.kind) {
@@ -313,10 +316,7 @@ function splitPatternSuffix(pattern: string): [path: string, suffix: string] {
313
316
  return [path, suffix];
314
317
  }
315
318
 
316
- export function interpolateParams(
317
- pattern: string,
318
- params: Record<string, string | number | string[]>
319
- ): string {
319
+ export function interpolateParams(pattern: string, params: Record<string, ParamValue>): string {
320
320
  const [pathPart, suffix] = splitPatternSuffix(pattern);
321
321
 
322
322
  const resolved = parseSegments(pathPart)
@@ -346,7 +346,7 @@ function isWrappedSearchParamsProp(sp: LinkSearchParamsProp): sp is WrappedSearc
346
346
 
347
347
  export function resolveHref(
348
348
  href: string,
349
- params?: Record<string, string | number | string[]>,
349
+ params?: Record<string, ParamValue>,
350
350
  searchParams?: LinkSearchParamsProp
351
351
  ): string {
352
352
  let resolvedPath = href;
@@ -416,7 +416,7 @@ interface LinkOutputProps {
416
416
  */
417
417
  export function buildLinkProps(
418
418
  props: Pick<LinkPropsWithHref, 'href'> & {
419
- params?: Record<string, string | number | string[]>;
419
+ params?: Record<string, ParamValue>;
420
420
  searchParams?: LinkSearchParamsProp;
421
421
  }
422
422
  ): LinkOutputProps {
package/src/codec.ts CHANGED
@@ -22,6 +22,23 @@ export interface Codec<T> {
22
22
  serialize(value: T): string | null;
23
23
  }
24
24
 
25
+ /**
26
+ * Marker interface for codecs designed for catch-all segments (`[...slug]`).
27
+ * These codecs expect `string[]` input from the router.
28
+ */
29
+ export interface CatchAllCodec<T> extends Codec<T> {
30
+ readonly __catchAll: true;
31
+ }
32
+
33
+ /**
34
+ * Marker interface for codecs designed for optional catch-all segments (`[[...slug]]`).
35
+ * These codecs expect `string[] | undefined` input from the router.
36
+ */
37
+ export interface OptionalCatchAllCodec<T> extends Codec<T> {
38
+ readonly __catchAll: true;
39
+ readonly __optional: true;
40
+ }
41
+
25
42
  /**
26
43
  * Recursive JSON-serializable type. The canonical definition for data that
27
44
  * can safely cross the RSC → client boundary.
@@ -86,6 +103,7 @@ export const codec = {
86
103
  } satisfies Codec<string>,
87
104
 
88
105
  stringArray: {
106
+ __catchAll: true as const,
89
107
  parse(value: string | string[] | undefined): string[] {
90
108
  if (Array.isArray(value)) return value;
91
109
  return value ? [value] : [];
@@ -93,5 +111,37 @@ export const codec = {
93
111
  serialize(value: string[]): string | null {
94
112
  return value.join('/');
95
113
  },
96
- } satisfies Codec<string[]>,
114
+ } satisfies CatchAllCodec<string[]>,
115
+
116
+ catchAll<T>(inner: Codec<T>): CatchAllCodec<T[]> {
117
+ return {
118
+ __catchAll: true as const,
119
+ parse(value: string | string[] | undefined): T[] {
120
+ const arr = Array.isArray(value) ? value : value !== undefined ? [value] : [];
121
+ if (arr.length === 0) {
122
+ throw new Error('Catch-all segment requires at least one value');
123
+ }
124
+ return arr.map((item) => inner.parse(item));
125
+ },
126
+ serialize(value: T[]): string | null {
127
+ return value.map((item) => inner.serialize(item)).join('/');
128
+ },
129
+ };
130
+ },
131
+
132
+ optionalCatchAll<T>(inner: Codec<T>): OptionalCatchAllCodec<T[] | undefined> {
133
+ return {
134
+ __catchAll: true as const,
135
+ __optional: true as const,
136
+ parse(value: string | string[] | undefined): T[] | undefined {
137
+ const arr = Array.isArray(value) ? value : value !== undefined ? [value] : [];
138
+ if (arr.length === 0) return undefined;
139
+ return arr.map((item) => inner.parse(item));
140
+ },
141
+ serialize(value: T[] | undefined): string | null {
142
+ if (!value || value.length === 0) return null;
143
+ return value.map((item) => inner.serialize(item)).join('/');
144
+ },
145
+ };
146
+ },
97
147
  } as const;
package/src/index.ts CHANGED
@@ -29,6 +29,7 @@ import { timberReactProd } from './plugins/react-prod';
29
29
  import { timberChunks } from './plugins/chunks';
30
30
  import { clientChunkGroup } from './plugins/client-chunks';
31
31
  import { timberServerBundle } from './plugins/server-bundle';
32
+ import { timberCloudflareWasm } from './plugins/cloudflare-wasm';
32
33
  import { timberAdapterBuild } from './plugins/adapter-build';
33
34
  import { timberBuildReport } from './plugins/build-report';
34
35
  import { createNoopTimer } from './utils/startup-timer';
@@ -531,6 +532,7 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
531
532
  timberMdx(ctx),
532
533
  timberContent(ctx),
533
534
  timberServerBundle(), // Bundle all deps in server environments for prod
535
+ timberCloudflareWasm(ctx), // Externalize WASM for Cloudflare Workers
534
536
  timberChunks(),
535
537
  timberBuildReport(ctx), // Post-build: route table with bundle sizes
536
538
  timberAdapterBuild(ctx), // Post-build: invoke adapter.buildOutput()
@@ -8,7 +8,7 @@
8
8
  * Design doc: design/41-global-params.md
9
9
  */
10
10
 
11
- import type { Codec } from '../codec.js';
11
+ import type { Codec, CatchAllCodec, OptionalCatchAllCodec } from '../codec.js';
12
12
  import type { StandardSchemaV1 } from '../schema-bridge.js';
13
13
 
14
14
  // ---------------------------------------------------------------------------
@@ -31,7 +31,42 @@ export type InferCodecType<V> =
31
31
  : string;
32
32
 
33
33
  /** Acceptable codec value for segment params: a Codec or Standard Schema. */
34
- type SegmentParamCodec = Codec<unknown> | StandardSchemaV1<unknown>;
34
+ export type SegmentParamCodec = Codec<unknown> | StandardSchemaV1<unknown>;
35
+
36
+ /** Codec constraint for catch-all segment keys (`[...name]`). */
37
+ export type CatchAllParamCodec = CatchAllCodec<unknown> | StandardSchemaV1<readonly unknown[]>;
38
+
39
+ /** Codec constraint for optional catch-all segment keys (`[[...name]]`). */
40
+ export type OptionalCatchAllParamCodec =
41
+ | OptionalCatchAllCodec<unknown>
42
+ | StandardSchemaV1<readonly unknown[] | undefined>;
43
+
44
+ /**
45
+ * Resolves the required codec type for a given bracket key pattern.
46
+ * - `[...name]` → requires a catch-all codec
47
+ * - `[[...name]]` → requires an optional catch-all codec
48
+ * - `[name]` → accepts any segment param codec
49
+ */
50
+ export type CodecForKey<K extends string> = K extends `[[...${string}]]`
51
+ ? OptionalCatchAllParamCodec
52
+ : K extends `[...${string}]`
53
+ ? CatchAllParamCodec
54
+ : SegmentParamCodec;
55
+
56
+ /**
57
+ * Registry interface augmented by codegen with known filesystem bracket keys.
58
+ * When empty (no codegen yet), ValidDynamicSegmentKeys falls back to string.
59
+ */
60
+ export interface ValidDynamicSegmentKeysRegistry {}
61
+
62
+ /**
63
+ * Union of valid bracket keys for defineSchema.
64
+ * After codegen runs, this is the set of filesystem segment names.
65
+ * Before codegen (fresh project), accepts any string.
66
+ */
67
+ export type ValidDynamicSegmentKeys = keyof ValidDynamicSegmentKeysRegistry extends never
68
+ ? string
69
+ : keyof ValidDynamicSegmentKeysRegistry & string;
35
70
 
36
71
  /** Configuration object for defineSchema. */
37
72
  export interface SchemaConfig<S extends Record<string, SegmentParamCodec>> {
@@ -66,8 +101,14 @@ export interface SchemaConfig<S extends Record<string, SegmentParamCodec>> {
66
101
  * });
67
102
  * ```
68
103
  */
69
- export function defineSchema<S extends Record<string, SegmentParamCodec>>(
70
- config: SchemaConfig<S>
71
- ): SchemaConfig<S> {
104
+ export function defineSchema<
105
+ S extends {
106
+ [K in keyof S]: K extends ValidDynamicSegmentKeys
107
+ ? K extends string
108
+ ? CodecForKey<K>
109
+ : SegmentParamCodec
110
+ : never;
111
+ },
112
+ >(config: { segmentParams: S }): { segmentParams: S } {
72
113
  return config;
73
114
  }
@@ -6,6 +6,12 @@
6
6
  // See design/41-global-params.md
7
7
 
8
8
  export { defineSchema } from './define-schema.js';
9
- export type { InferCodecType, SchemaConfig } from './define-schema.js';
9
+ export type {
10
+ InferCodecType,
11
+ SchemaConfig,
12
+ SegmentParamCodec,
13
+ ValidDynamicSegmentKeys,
14
+ ValidDynamicSegmentKeysRegistry,
15
+ } from './define-schema.js';
10
16
  export { resolveSchemaCodecs, toBracketKey } from './resolve-schema.js';
11
17
  export { setLinkCodecs, getLinkCodec } from './codec-registry.js';