@timber-js/app 0.2.0-alpha.61 → 0.2.0-alpha.62

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 (103) hide show
  1. package/dist/_chunks/{als-registry-Ba7URUIn.js → als-registry-BJARkOcu.js} +1 -1
  2. package/dist/_chunks/{als-registry-Ba7URUIn.js.map → als-registry-BJARkOcu.js.map} +1 -1
  3. package/dist/_chunks/{define-CT98cU9c.js → define-Djpqoe1K.js} +1 -1
  4. package/dist/_chunks/{define-CT98cU9c.js.map → define-Djpqoe1K.js.map} +1 -1
  5. package/dist/_chunks/{define-cookie-BWr_52kY.js → define-cookie-B2djY9w0.js} +4 -4
  6. package/dist/_chunks/{define-cookie-BWr_52kY.js.map → define-cookie-B2djY9w0.js.map} +1 -1
  7. package/dist/_chunks/{define-TK8C1M3x.js → define-hdajFTq7.js} +2 -2
  8. package/dist/_chunks/{define-TK8C1M3x.js.map → define-hdajFTq7.js.map} +1 -1
  9. package/dist/_chunks/{error-boundary-DpZJBCqh.js → error-boundary-A_sgyyUP.js} +1 -1
  10. package/dist/_chunks/{error-boundary-DpZJBCqh.js.map → error-boundary-A_sgyyUP.js.map} +1 -1
  11. package/dist/_chunks/{tracing-VYETCQsg.js → handler-store-CaE0ZgVG.js} +54 -3
  12. package/dist/_chunks/handler-store-CaE0ZgVG.js.map +1 -0
  13. package/dist/_chunks/{interception-Cey5DCGr.js → interception-BVm64Jr5.js} +7 -13
  14. package/dist/_chunks/interception-BVm64Jr5.js.map +1 -0
  15. package/dist/_chunks/{metadata-routes-BU684ls2.js → metadata-routes-DS3eKNmf.js} +1 -1
  16. package/dist/_chunks/{metadata-routes-BU684ls2.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  17. package/dist/_chunks/{request-context-rju2rbga.js → request-context-B_u9dyhZ.js} +4 -4
  18. package/dist/_chunks/{request-context-rju2rbga.js.map → request-context-B_u9dyhZ.js.map} +1 -1
  19. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  20. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  21. package/dist/_chunks/{segment-context-CyaM1mrD.js → segment-context-CVRHlkkQ.js} +1 -1
  22. package/dist/_chunks/{segment-context-CyaM1mrD.js.map → segment-context-CVRHlkkQ.js.map} +1 -1
  23. package/dist/_chunks/{stale-reload-BSSym1MJ.js → stale-reload-BeyHXZ5B.js} +1 -1
  24. package/dist/_chunks/{stale-reload-BSSym1MJ.js.map → stale-reload-BeyHXZ5B.js.map} +1 -1
  25. package/dist/_chunks/{use-query-states-wEXY2JQB.js → use-query-states-DAhgj8Gx.js} +1 -1
  26. package/dist/_chunks/{use-query-states-wEXY2JQB.js.map → use-query-states-DAhgj8Gx.js.map} +1 -1
  27. package/dist/_chunks/{wrappers-BaG1bnM3.js → wrappers-CJQ3KwVr.js} +1 -1
  28. package/dist/_chunks/{wrappers-BaG1bnM3.js.map → wrappers-CJQ3KwVr.js.map} +1 -1
  29. package/dist/cache/cache-api.d.ts +24 -0
  30. package/dist/cache/cache-api.d.ts.map +1 -0
  31. package/dist/cache/handler-store.d.ts +31 -0
  32. package/dist/cache/handler-store.d.ts.map +1 -0
  33. package/dist/cache/index.d.ts +2 -1
  34. package/dist/cache/index.d.ts.map +1 -1
  35. package/dist/cache/index.js +33 -2
  36. package/dist/cache/index.js.map +1 -1
  37. package/dist/client/error-boundary.js +1 -1
  38. package/dist/client/index.d.ts +1 -1
  39. package/dist/client/index.d.ts.map +1 -1
  40. package/dist/client/index.js +49 -20
  41. package/dist/client/index.js.map +1 -1
  42. package/dist/client/link.d.ts +6 -0
  43. package/dist/client/link.d.ts.map +1 -1
  44. package/dist/client/transition-root.d.ts +12 -0
  45. package/dist/client/transition-root.d.ts.map +1 -1
  46. package/dist/cookies/index.js +1 -1
  47. package/dist/index.js +52 -2
  48. package/dist/index.js.map +1 -1
  49. package/dist/params/index.js +3 -3
  50. package/dist/plugins/entries.d.ts.map +1 -1
  51. package/dist/routing/index.d.ts +2 -0
  52. package/dist/routing/index.d.ts.map +1 -1
  53. package/dist/routing/index.js +3 -2
  54. package/dist/routing/scanner.d.ts.map +1 -1
  55. package/dist/routing/segment-classify.d.ts +46 -0
  56. package/dist/routing/segment-classify.d.ts.map +1 -0
  57. package/dist/search-params/index.js +3 -3
  58. package/dist/server/actions.d.ts +0 -3
  59. package/dist/server/actions.d.ts.map +1 -1
  60. package/dist/server/deny-renderer.d.ts.map +1 -1
  61. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  62. package/dist/server/fallback-error.d.ts.map +1 -1
  63. package/dist/server/index.js +98 -17
  64. package/dist/server/index.js.map +1 -1
  65. package/dist/server/pipeline-interception.d.ts.map +1 -1
  66. package/dist/server/pipeline.d.ts.map +1 -1
  67. package/dist/server/route-element-builder.d.ts.map +1 -1
  68. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  69. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  70. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  71. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  72. package/dist/server/safe-load.d.ts +46 -0
  73. package/dist/server/safe-load.d.ts.map +1 -0
  74. package/dist/server/slot-resolver.d.ts.map +1 -1
  75. package/dist/server/tracing.d.ts.map +1 -1
  76. package/package.json +1 -1
  77. package/src/cache/cache-api.ts +38 -0
  78. package/src/cache/handler-store.ts +68 -0
  79. package/src/cache/index.ts +2 -1
  80. package/src/client/browser-entry.ts +89 -42
  81. package/src/client/index.ts +1 -1
  82. package/src/client/link.tsx +81 -46
  83. package/src/client/transition-root.tsx +27 -0
  84. package/src/plugins/entries.ts +61 -0
  85. package/src/routing/index.ts +2 -0
  86. package/src/routing/scanner.ts +7 -16
  87. package/src/routing/segment-classify.ts +89 -0
  88. package/src/server/actions.ts +7 -6
  89. package/src/server/deny-renderer.ts +4 -3
  90. package/src/server/error-boundary-wrapper.ts +9 -6
  91. package/src/server/fallback-error.ts +2 -1
  92. package/src/server/pipeline-interception.ts +16 -15
  93. package/src/server/pipeline.ts +11 -2
  94. package/src/server/route-element-builder.ts +5 -4
  95. package/src/server/rsc-entry/api-handler.ts +4 -3
  96. package/src/server/rsc-entry/error-renderer.ts +15 -9
  97. package/src/server/rsc-entry/index.ts +12 -0
  98. package/src/server/rsc-entry/ssr-bridge.ts +13 -4
  99. package/src/server/safe-load.ts +60 -0
  100. package/src/server/slot-resolver.ts +3 -1
  101. package/src/server/tracing.ts +14 -3
  102. package/dist/_chunks/interception-Cey5DCGr.js.map +0 -1
  103. package/dist/_chunks/tracing-VYETCQsg.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline-interception.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-interception.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,OAAO,4BAA4B,EAAE,mBAAmB,EAAE,GACnE,uBAAuB,GAAG,IAAI,CAYhC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CA0BjF"}
1
+ {"version":3,"file":"pipeline-interception.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-interception.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,OAAO,4BAA4B,EAAE,mBAAmB,EAAE,GACnE,uBAAuB,GAAG,IAAI,CAYhC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAyBjF"}
@@ -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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;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;AAM7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAKzD;;;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;;;GAGG;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;;;;;;;;;GASG;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,CA6R7B"}
1
+ {"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;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;AAM7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAMzD;;;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;;;GAGG;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;;;;;;;;;GASG;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,CA6R7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-handler.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/api-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAMjD,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,eAAe,EAAE,OAAO,GACvB,OAAO,CAAC,QAAQ,CAAC,CAyDnB"}
1
+ {"version":3,"file":"api-handler.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/api-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAMjD,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,eAAe,EAAE,OAAO,GACvB,OAAO,CAAC,QAAQ,CAAC,CAyDnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"error-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/error-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGlE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAkHD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,gBAAgB,EAAE,WAAW,EAAE,EAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,EACtC,WAAW,CAAC,EAAE,eAAe,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAoCnB;AAmID;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,mBAAmB,EAChC,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,GACrC,OAAO,CAAC,QAAQ,CAAC,CA6BnB"}
1
+ {"version":3,"file":"error-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/error-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGlE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAWvD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAqHD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,gBAAgB,EAAE,WAAW,EAAE,EAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,EACtC,WAAW,CAAC,EAAE,eAAe,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAoCnB;AAqID;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,mBAAmB,EAChC,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,GACrC,OAAO,CAAC,QAAQ,CAAC,CA6BnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/index.ts"],"names":[],"mappings":"AA4DA,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AAkCtB;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,mBAAmB,EAAE,KAAK,IAAI,GACtF,IAAI,CAEN;AAoeD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAInE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;8BA7TrC,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;AA+ThD,wBAAiE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/index.ts"],"names":[],"mappings":"AA8DA,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AAkCtB;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,mBAAmB,EAAE,KAAK,IAAI,GACtF,IAAI,CAEN;AA8eD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAInE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;8BA7TrC,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;AA+ThD,wBAAiE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-bridge.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/ssr-bridge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAsB,OAAO,CAC3B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,QAAQ,CAAC,CAMnB"}
1
+ {"version":3,"file":"ssr-bridge.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/ssr-bridge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAsB,OAAO,CAC3B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,QAAQ,CAAC,CAenB"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * loadModule — enriched error context for route manifest .load() failures.
3
+ *
4
+ * Wraps the lazy `load()` functions from the route manifest with a
5
+ * try/catch that re-throws with the file path and original cause.
6
+ *
7
+ * Callers that need fallthrough behavior (error renderers) can use
8
+ * `.catch(() => null)` or try/catch — the decision stays at the call site.
9
+ *
10
+ * See design/spike-TIM-551-dynamic-import-audit.md §"Proposed Wrapping Strategy"
11
+ */
12
+ /** A manifest file reference with a lazy import function and file path. */
13
+ export interface ManifestLoader {
14
+ load: () => Promise<unknown>;
15
+ filePath: string;
16
+ }
17
+ /**
18
+ * Custom error class for module load failures.
19
+ *
20
+ * Preserves the original error as `cause` while providing a
21
+ * human-readable message with the file path.
22
+ */
23
+ export declare class ModuleLoadError extends Error {
24
+ /** The file path that failed to load. */
25
+ readonly filePath: string;
26
+ constructor(filePath: string, cause: unknown);
27
+ }
28
+ /**
29
+ * Load a route manifest module with enriched error context.
30
+ *
31
+ * On success: returns the module object (same as `loader.load()`).
32
+ * On failure: throws `ModuleLoadError` with file path and original cause.
33
+ *
34
+ * For error rendering paths that need fallthrough instead of throwing,
35
+ * callers should catch at the call site:
36
+ *
37
+ * ```ts
38
+ * // Throwing (default) — route-element-builder, api-handler, etc.
39
+ * const mod = await loadModule(segment.page);
40
+ *
41
+ * // Fallthrough — error-renderer, error-boundary-wrapper
42
+ * const mod = await loadModule(segment.error).catch(() => null);
43
+ * ```
44
+ */
45
+ export declare function loadModule<T = Record<string, unknown>>(loader: ManifestLoader): Promise<T>;
46
+ //# sourceMappingURL=safe-load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-load.d.ts","sourceRoot":"","sources":["../../src/server/safe-load.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAM7C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAMhG"}
@@ -1 +1 @@
1
- {"version":3,"file":"slot-resolver.d.ts","sourceRoot":"","sources":["../../src/server/slot-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,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;AAkHlE;;;;;;;;;;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,CA+FpC"}
1
+ {"version":3,"file":"slot-resolver.d.ts","sourceRoot":"","sources":["../../src/server/slot-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,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,CA+FpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/server/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG9D,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD;;;;;;;GAOG;AACH,wBAAgB,OAAO,IAAI,MAAM,CAShC;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,MAAM,GAAG,SAAS,CAE3C;AAID;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAM3E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAKhE;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,UAAU,GAAG,SAAS,CAEtD;AAID;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,OAAO,iBAAiB,EAAE,eAAe,GAChD,OAAO,CAAC,IAAI,CAAC,CA4Bf;AA4BD;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC,CAUrF;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EACrD,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAC/B,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GACrD,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GACrD,IAAI,CASN;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAc/F"}
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/server/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG9D,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD;;;;;;;GAOG;AACH,wBAAgB,OAAO,IAAI,MAAM,CAShC;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,MAAM,GAAG,SAAS,CAE3C;AAID;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAM3E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAKhE;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,UAAU,GAAG,SAAS,CAEtD;AAID;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,OAAO,iBAAiB,EAAE,eAAe,GAChD,OAAO,CAAC,IAAI,CAAC,CAuCf;AA4BD;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC,CAUrF;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EACrD,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAC/B,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GACrD,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GACrD,IAAI,CASN;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAc/F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timber-js/app",
3
- "version": "0.2.0-alpha.61",
3
+ "version": "0.2.0-alpha.62",
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",
@@ -0,0 +1,38 @@
1
+ import type { CacheOptions } from './index';
2
+ import { createCache } from './timber-cache';
3
+ import { getCacheHandler } from './handler-store';
4
+
5
+ /**
6
+ * Public caching API: `cache(fn, opts)`.
7
+ *
8
+ * Wraps an async function with cross-request caching. Uses the configured
9
+ * cache handler (defaults to MemoryCacheHandler, overridable via timber.config.ts).
10
+ *
11
+ * ```ts
12
+ * import { cache } from '@timber-js/app/cache';
13
+ *
14
+ * const getUser = cache(
15
+ * async (id: string) => db.users.findUnique({ where: { id } }),
16
+ * { ttl: 60, tags: (id) => [`user:${id}`] }
17
+ * );
18
+ * ```
19
+ */
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ export function cache<Fn extends (...args: any[]) => Promise<any>>(
22
+ fn: Fn,
23
+ opts: CacheOptions<Fn>
24
+ ): Fn {
25
+ return createCache(fn, opts, getCacheHandler());
26
+ }
27
+
28
+ /**
29
+ * Invalidate cache entries by tag or key.
30
+ *
31
+ * ```ts
32
+ * cache.invalidate({ tag: 'products' });
33
+ * cache.invalidate({ key: 'user:abc' });
34
+ * ```
35
+ */
36
+ cache.invalidate = async function invalidate(opts: { key?: string; tag?: string }): Promise<void> {
37
+ await getCacheHandler().invalidate(opts);
38
+ };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Module-level cache handler singleton.
3
+ *
4
+ * Lazily initialized to MemoryCacheHandler on first access. The framework
5
+ * replaces this at boot from timber.config.ts via setCacheHandler().
6
+ *
7
+ * This module avoids importing from ./index to prevent circular dependencies.
8
+ */
9
+
10
+ // Inline the interface to avoid circular import with index.ts
11
+ interface CacheHandlerLike {
12
+ get(key: string): Promise<{ value: unknown; stale: boolean } | null>;
13
+ set(key: string, value: unknown, opts: { ttl: number; tags: string[] }): Promise<void>;
14
+ invalidate(opts: { key?: string; tag?: string }): Promise<void>;
15
+ }
16
+
17
+ let handler: CacheHandlerLike | null = null;
18
+
19
+ /** Replace the active cache handler. Called by the framework at boot. */
20
+ export function setCacheHandler(h: CacheHandlerLike): void {
21
+ handler = h;
22
+ }
23
+
24
+ /**
25
+ * Get the active cache handler. Creates a default MemoryCacheHandler on
26
+ * first access if none has been set via setCacheHandler().
27
+ */
28
+ export function getCacheHandler(): CacheHandlerLike {
29
+ if (!handler) {
30
+ // Inline a minimal LRU cache to avoid circular dep with index.ts.
31
+ // In production, the framework always calls setCacheHandler() at boot.
32
+ handler = createDefaultHandler();
33
+ }
34
+ return handler;
35
+ }
36
+
37
+ function createDefaultHandler(): CacheHandlerLike {
38
+ const store = new Map<string, { value: unknown; expiresAt: number; tags: string[] }>();
39
+ const maxSize = 1000;
40
+
41
+ return {
42
+ async get(key) {
43
+ const entry = store.get(key);
44
+ if (!entry) return null;
45
+ store.delete(key);
46
+ store.set(key, entry);
47
+ const stale = Date.now() > entry.expiresAt;
48
+ return { value: entry.value, stale };
49
+ },
50
+ async set(key, value, opts) {
51
+ if (store.has(key)) store.delete(key);
52
+ while (store.size >= maxSize) {
53
+ const oldest = store.keys().next().value;
54
+ if (oldest !== undefined) store.delete(oldest);
55
+ else break;
56
+ }
57
+ store.set(key, { value, expiresAt: Date.now() + opts.ttl * 1000, tags: opts.tags });
58
+ },
59
+ async invalidate(opts) {
60
+ if (opts.key) store.delete(opts.key);
61
+ if (opts.tag) {
62
+ for (const [key, entry] of store) {
63
+ if (entry.tags.includes(opts.tag)) store.delete(key);
64
+ }
65
+ }
66
+ },
67
+ };
68
+ }
@@ -86,7 +86,8 @@ export class MemoryCacheHandler implements CacheHandler {
86
86
 
87
87
  export { RedisCacheHandler } from './redis-handler';
88
88
  export type { RedisClient } from './redis-handler';
89
- export { createCache } from './timber-cache';
89
+ export { cache } from './cache-api';
90
+ export { setCacheHandler, getCacheHandler } from './handler-store';
90
91
  export { registerCachedFunction } from './register-cached-function';
91
92
  export type { RegisterCachedFunctionOptions } from './register-cached-function';
92
93
  export { stableStringify } from './stable-stringify';
@@ -35,7 +35,13 @@ import {
35
35
  // If we used relative imports (./router-ref.js), Vite would load separate src/
36
36
  // copies with separate module-level state — e.g., globalRouter set here but
37
37
  // read as null from the dist/ copy used by useRouter().
38
- import { createRouter, setGlobalRouter, getRouter, setCurrentParams } from '@timber-js/app/client';
38
+ import {
39
+ createRouter,
40
+ setGlobalRouter,
41
+ getRouter,
42
+ getRouterOrNull,
43
+ setCurrentParams,
44
+ } from '@timber-js/app/client';
39
45
  import type { RouterDeps, RouterInstance } from '@timber-js/app/client';
40
46
 
41
47
  // Internal-only modules (no shared mutable state with user code) use relative
@@ -52,7 +58,12 @@ import {
52
58
  import { setupServerLogReplay, setupClientErrorForwarding } from './browser-dev.js';
53
59
  // browser-links.ts removed — Link components own their click/hover handlers directly.
54
60
  // See LOCAL-340.
55
- import { TransitionRoot, transitionRender, navigateTransition } from './transition-root.js';
61
+ import {
62
+ TransitionRoot,
63
+ transitionRender,
64
+ navigateTransition,
65
+ installDeferredNavigation,
66
+ } from './transition-root.js';
56
67
  import {
57
68
  isStaleClientReference,
58
69
  isChunkLoadError,
@@ -365,33 +376,28 @@ function bootstrap(runtimeConfig: typeof config): void {
365
376
  const element = createFromReadableStream(rscPayload);
366
377
  initialElement = element;
367
378
 
368
- // ── Initialize the navigation router BEFORE hydration ──────────────
369
- // hydrateRoot() synchronously executes component render functions.
370
- // Components that call useRouter() during render need the global
371
- // router to be available, otherwise they get a stale no-op reference.
372
- // The router must be initialized before hydration so useRouter() works.
373
- // renderRoot uses transitionRender (no direct reactRoot dependency).
374
- initRouter();
375
-
376
- // ── Initialize navigation state BEFORE hydration ───────────────────
377
- // Read server-embedded params and set navigation state so that
378
- // useSegmentParams() and usePathname() return correct values during hydration.
379
- // This must happen before hydrateRoot so the NavigationProvider
380
- // wrapping the element has the right values on the initial render.
381
- const earlyParams = (self as unknown as Record<string, unknown>).__timber_params;
382
- if (earlyParams && typeof earlyParams === 'object') {
383
- setCurrentParams(earlyParams as Record<string, string | string[]>);
384
- setNavigationState({
385
- params: earlyParams as Record<string, string | string[]>,
386
- pathname: window.location.pathname,
387
- });
388
- delete (self as unknown as Record<string, unknown>).__timber_params;
389
- } else {
390
- setNavigationState({
391
- params: {},
392
- pathname: window.location.pathname,
393
- });
394
- }
379
+ // ── Pre-hydration bootstrap sequence ──────────────────────────────
380
+ //
381
+ // These steps MUST execute in this exact order before hydrateRoot():
382
+ //
383
+ // 1. initRouter() — creates the global router so useRouter()
384
+ // works during render (methods lazily resolve
385
+ // the router at invocation, not render time,
386
+ // but initRouter must still run first)
387
+ //
388
+ // 2. setCurrentParams() — populates module-level params snapshot so
389
+ // + setNavigationState() useSegmentParams() and usePathname()
390
+ // return correct values during hydration
391
+ //
392
+ // 3. hydrateRoot() — synchronously executes component render
393
+ // functions that depend on steps 1-2
394
+ //
395
+ // Implicit prerequisite: the __timber_f RSC stream (ReadableStream
396
+ // above) must be wired up before hydrateRoot, because React starts
397
+ // consuming it synchronously during hydration.
398
+ //
399
+ // See design/19-client-navigation.md §"NavigationContext"
400
+ runPreHydration(element);
395
401
 
396
402
  // Hydrate on document — the root layout renders the full <html> tree,
397
403
  // so React owns the entire document from the root.
@@ -413,6 +419,15 @@ function bootstrap(runtimeConfig: typeof config): void {
413
419
  initial: wrapped,
414
420
  topLoaderConfig: _config.topLoader,
415
421
  });
422
+
423
+ if (process.env.NODE_ENV !== 'production') {
424
+ if (!getRouterOrNull()) {
425
+ throw new Error(
426
+ '[timber] hydrateRoot called before initRouter() — bootstrap order violated'
427
+ );
428
+ }
429
+ }
430
+
416
431
  _reactRoot = hydrateRoot(document, rootElement, {
417
432
  // Suppress recoverable hydration errors from deny/error signals
418
433
  // inside Suspense boundaries. The server already handled these
@@ -436,20 +451,27 @@ function bootstrap(runtimeConfig: typeof config): void {
436
451
  // navigation can still render RSC payloads. The initial SSR HTML
437
452
  // remains as-is; the first client navigation will replace it with
438
453
  // a React-managed tree.
439
- initRouter();
440
- // Mount TransitionRoot so navigateTransition is wired up for client
441
- // navigation. Without this, navigation from SSR-only/shell-less pages
442
- // updates URL/history but leaves stale page content (TIM-580).
443
- const navState = getNavigationState();
444
- const placeholder = createElement('div') as unknown as React.ReactNode;
445
- const withNav = createElement(NavigationProvider, { value: navState }, placeholder);
446
- const wrapped = createElement(TimberNuqsAdapter, null, withNav);
447
- const rootElement = createElement(TransitionRoot, {
448
- initial: wrapped,
449
- topLoaderConfig: _config.topLoader,
454
+ runPreHydration(null);
455
+ // Defer React root creation until first client navigation (TIM-600).
456
+ //
457
+ // We must NOT call createRoot(document).render() here that would take
458
+ // React ownership of the entire document and blank the SSR HTML.
459
+ // Instead, installDeferredNavigation sets up one-shot callbacks so the
460
+ // first navigateTransition/transitionRender call creates the root on
461
+ // `document` with the navigated content. After that initial render,
462
+ // TransitionRoot's real startTransition-based callbacks take over.
463
+ //
464
+ // This also fixes TIM-580 (navigation from SSR-only pages) because the
465
+ // deferred callbacks ensure TransitionRoot is mounted before the first
466
+ // navigation completes.
467
+ installDeferredNavigation((initial) => {
468
+ const rootElement = createElement(TransitionRoot, {
469
+ initial,
470
+ topLoaderConfig: _config.topLoader,
471
+ });
472
+ _reactRoot = createRoot(document);
473
+ _reactRoot.render(rootElement);
450
474
  });
451
- _reactRoot = createRoot(document);
452
- _reactRoot.render(rootElement);
453
475
  }
454
476
 
455
477
  // ── Router initialization (hoisted above hydrateRoot) ────────────────
@@ -564,6 +586,31 @@ function bootstrap(runtimeConfig: typeof config): void {
564
586
  setGlobalRouter(router);
565
587
  }
566
588
 
589
+ // ── Pre-hydration sequence ──────────────────────────────────────────
590
+ // Concentrates the ordering contract: initRouter → setParams/navState.
591
+ // Called before hydrateRoot in the hydration path. The createRoot path
592
+ // calls initRouter() directly (no params to read from server embed).
593
+ function runPreHydration(_element: unknown): void {
594
+ // Step 1: Initialize the router
595
+ initRouter();
596
+
597
+ // Step 2: Read server-embedded params and set navigation state
598
+ const earlyParams = (self as unknown as Record<string, unknown>).__timber_params;
599
+ if (earlyParams && typeof earlyParams === 'object') {
600
+ setCurrentParams(earlyParams as Record<string, string | string[]>);
601
+ setNavigationState({
602
+ params: earlyParams as Record<string, string | string[]>,
603
+ pathname: window.location.pathname,
604
+ });
605
+ delete (self as unknown as Record<string, unknown>).__timber_params;
606
+ } else {
607
+ setNavigationState({
608
+ params: {},
609
+ pathname: window.location.pathname,
610
+ });
611
+ }
612
+ }
613
+
567
614
  // Store the initial page in the history stack so back-button works
568
615
  // after the first navigation. We store the decoded RSC element so
569
616
  // back navigation can replay it instantly without a server fetch.
@@ -20,7 +20,7 @@ export type {
20
20
  export { useNavigationPending } from './use-navigation-pending';
21
21
  export { useLinkStatus, LinkStatusContext } from './use-link-status';
22
22
  export type { LinkStatus } from './use-link-status';
23
- export { getRouter, setGlobalRouter } from './router-ref';
23
+ export { getRouter, getRouterOrNull, setGlobalRouter } from './router-ref';
24
24
  export { useRouter } from './use-router';
25
25
  export type { AppRouterInstance } from './use-router';
26
26
  export { usePathname } from './use-pathname';
@@ -27,6 +27,7 @@ import {
27
27
  type MouseEvent as ReactMouseEvent,
28
28
  } from 'react';
29
29
  import type { SearchParamsDefinition } from '../search-params/define.js';
30
+ import { classifyUrlSegment, type UrlSegment } from '../routing/segment-classify.js';
30
31
  import { LinkStatusContext } from './use-link-status.js';
31
32
  import { getRouterOrNull } from './router-ref.js';
32
33
  import { getSsrData } from './ssr-data.js';
@@ -187,57 +188,91 @@ export function isInternalHref(href: string): boolean {
187
188
  * - [...param] → catch-all (joined with /)
188
189
  * - [[...param]] → optional catch-all (omitted if undefined/empty)
189
190
  */
191
+ /**
192
+ * Parse a route pattern's path portion into classified segments.
193
+ * Exported for testing. Uses the shared character-based classifier.
194
+ */
195
+ export function parseSegments(pattern: string): UrlSegment[] {
196
+ return pattern.split('/').filter(Boolean).map(classifyUrlSegment);
197
+ }
198
+
199
+ /**
200
+ * Resolve a single classified segment into its string representation.
201
+ * Returns null for optional catch-all with no value (filtered out before join).
202
+ */
203
+ function resolveSegment(
204
+ seg: UrlSegment,
205
+ params: Record<string, string | number | string[]>,
206
+ pattern: string
207
+ ): string | null {
208
+ switch (seg.kind) {
209
+ case 'static':
210
+ return seg.value;
211
+
212
+ case 'optional-catch-all': {
213
+ const value = params[seg.name];
214
+ if (value === undefined || (Array.isArray(value) && value.length === 0)) {
215
+ return null;
216
+ }
217
+ const segments = Array.isArray(value) ? value : [value];
218
+ return segments.map(encodeURIComponent).join('/');
219
+ }
220
+
221
+ case 'catch-all': {
222
+ const value = params[seg.name];
223
+ if (value === undefined) {
224
+ throw new Error(
225
+ `<Link> missing required catch-all param "${seg.name}" for pattern "${pattern}".`
226
+ );
227
+ }
228
+ const segments = Array.isArray(value) ? value : [value];
229
+ if (segments.length === 0) {
230
+ throw new Error(
231
+ `<Link> catch-all param "${seg.name}" must have at least one segment for pattern "${pattern}".`
232
+ );
233
+ }
234
+ return segments.map(encodeURIComponent).join('/');
235
+ }
236
+
237
+ case 'dynamic': {
238
+ const value = params[seg.name];
239
+ if (value === undefined) {
240
+ throw new Error(`<Link> missing required param "${seg.name}" for pattern "${pattern}".`);
241
+ }
242
+ if (Array.isArray(value)) {
243
+ throw new Error(
244
+ `<Link> param "${seg.name}" expected a string but received an array for pattern "${pattern}".`
245
+ );
246
+ }
247
+ return encodeURIComponent(String(value));
248
+ }
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Split a URL pattern into the path portion and any trailing ?query/#hash suffix.
254
+ * Uses URL parsing for correctness rather than manual index arithmetic.
255
+ */
256
+ function splitPatternSuffix(pattern: string): [path: string, suffix: string] {
257
+ if (!pattern.includes('?') && !pattern.includes('#')) {
258
+ return [pattern, ''];
259
+ }
260
+ const url = new URL(pattern, 'http://x');
261
+ const suffix = url.search + url.hash;
262
+ const path = pattern.slice(0, pattern.length - suffix.length);
263
+ return [path, suffix];
264
+ }
265
+
190
266
  export function interpolateParams(
191
267
  pattern: string,
192
268
  params: Record<string, string | number | string[]>
193
269
  ): string {
194
- return (
195
- pattern
196
- .replace(
197
- /\[\[\.\.\.(\w+)\]\]|\[\.\.\.(\w+)\]|\[(\w+)\]/g,
198
- (_match, optionalCatchAll, catchAll, single) => {
199
- if (optionalCatchAll) {
200
- const value = params[optionalCatchAll];
201
- if (value === undefined || (Array.isArray(value) && value.length === 0)) {
202
- return '';
203
- }
204
- const segments = Array.isArray(value) ? value : [value];
205
- return segments.map(encodeURIComponent).join('/');
206
- }
207
-
208
- if (catchAll) {
209
- const value = params[catchAll];
210
- if (value === undefined) {
211
- throw new Error(
212
- `<Link> missing required catch-all param "${catchAll}" for pattern "${pattern}".`
213
- );
214
- }
215
- const segments = Array.isArray(value) ? value : [value];
216
- if (segments.length === 0) {
217
- throw new Error(
218
- `<Link> catch-all param "${catchAll}" must have at least one segment for pattern "${pattern}".`
219
- );
220
- }
221
- return segments.map(encodeURIComponent).join('/');
222
- }
270
+ const [pathPart, suffix] = splitPatternSuffix(pattern);
223
271
 
224
- // single dynamic segment
225
- const value = params[single];
226
- if (value === undefined) {
227
- throw new Error(`<Link> missing required param "${single}" for pattern "${pattern}".`);
228
- }
229
- if (Array.isArray(value)) {
230
- throw new Error(
231
- `<Link> param "${single}" expected a string but received an array for pattern "${pattern}".`
232
- );
233
- }
234
- // Accept numbers — coerce to string for URL interpolation
235
- return encodeURIComponent(String(value));
236
- }
237
- )
238
- // Clean up trailing slash from empty optional catch-all
239
- .replace(/\/+$/, '') || '/'
240
- );
272
+ const resolved = parseSegments(pathPart)
273
+ .map((seg) => resolveSegment(seg, params, pattern))
274
+ .filter((s): s is string => s !== null);
275
+ return ('/' + resolved.join('/') || '/') + suffix;
241
276
  }
242
277
 
243
278
  // ─── Resolve Href ───────────────────────────────────────────────
@@ -176,3 +176,30 @@ export function navigateTransition(
176
176
  export function isTransitionRootReady(): boolean {
177
177
  return _transitionRender !== null;
178
178
  }
179
+
180
+ /**
181
+ * Install one-shot deferred callbacks for the no-RSC bootstrap path (TIM-600).
182
+ *
183
+ * When there's no RSC payload, we can't create a React root immediately —
184
+ * `createRoot(document).render(...)` would blank the SSR HTML. Instead,
185
+ * this sets up `_transitionRender` and `_navigateTransition` so that the
186
+ * first client navigation triggers root creation via `createAndMount`.
187
+ *
188
+ * After `createAndMount` runs, TransitionRoot renders and overwrites these
189
+ * callbacks with its real `startTransition`-based implementations.
190
+ */
191
+ export function installDeferredNavigation(createAndMount: (initial: ReactNode) => void): void {
192
+ let mounted = false;
193
+ const mountOnce = (element: ReactNode) => {
194
+ if (mounted) return;
195
+ mounted = true;
196
+ createAndMount(element);
197
+ };
198
+ _transitionRender = (element: ReactNode) => {
199
+ mountOnce(element);
200
+ };
201
+ _navigateTransition = async (_pendingUrl: string, perform: () => Promise<ReactNode>) => {
202
+ const element = await perform();
203
+ mountOnce(element);
204
+ };
205
+ }