@timber-js/app 0.2.0-alpha.146 → 0.2.0-alpha.148

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 (297) hide show
  1. package/dist/_chunks/{actions-OIZ8siQu.js → actions-a0RczDnB.js} +8 -34
  2. package/dist/_chunks/{actions-OIZ8siQu.js.map → actions-a0RczDnB.js.map} +1 -1
  3. package/dist/_chunks/cache-api-Co-yI-gP.js +424 -0
  4. package/dist/_chunks/cache-api-Co-yI-gP.js.map +1 -0
  5. package/dist/_chunks/{metadata-routes-BjepjefT.js → canonicalize-P41GR6tY.js} +65 -2
  6. package/dist/_chunks/canonicalize-P41GR6tY.js.map +1 -0
  7. package/dist/_chunks/{cli-schema-sync-D2IpXicg.js → cli-schema-sync-DJDdyEae.js} +157 -313
  8. package/dist/_chunks/cli-schema-sync-DJDdyEae.js.map +1 -0
  9. package/dist/_chunks/cli-schema-sync-D_IhHEUW.js +2 -0
  10. package/dist/_chunks/{define-DMVhsipD.js → define-Bssfp6ot.js} +3 -33
  11. package/dist/_chunks/define-Bssfp6ot.js.map +1 -0
  12. package/dist/_chunks/{define-C3RvHQPK.js → define-CFmvb4Bt.js} +15 -7
  13. package/dist/_chunks/define-CFmvb4Bt.js.map +1 -0
  14. package/dist/_chunks/{href-validation-DyZIzfMJ.js → href-validation-FiA_rToW.js} +2 -1
  15. package/dist/_chunks/{href-validation-DyZIzfMJ.js.map → href-validation-FiA_rToW.js.map} +1 -1
  16. package/dist/_chunks/{tracing-M_zKubhk.js → logger-CM0clugc.js} +394 -107
  17. package/dist/_chunks/logger-CM0clugc.js.map +1 -0
  18. package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -1
  19. package/dist/_chunks/plugin-context-DurqFBuY.js +2 -0
  20. package/dist/_chunks/plugin-context-GfDWsdd2.js +268 -0
  21. package/dist/_chunks/plugin-context-GfDWsdd2.js.map +1 -0
  22. package/dist/_chunks/{resolve-schema-Dj8tQloi.js → resolve-schema-3iUvBV5T.js} +3 -30
  23. package/dist/_chunks/resolve-schema-3iUvBV5T.js.map +1 -0
  24. package/dist/_chunks/{schema-bridge-DK_89h8O.js → schema-bridge-BY3QLBL7.js} +35 -2
  25. package/dist/_chunks/schema-bridge-BY3QLBL7.js.map +1 -0
  26. package/dist/_chunks/tree-match-D2l830j2.js +102 -0
  27. package/dist/_chunks/tree-match-D2l830j2.js.map +1 -0
  28. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -1
  29. package/dist/_chunks/{walkers-7FBPM-hX.js → walkers-DvWDj453.js} +154 -88
  30. package/dist/_chunks/walkers-DvWDj453.js.map +1 -0
  31. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -1
  32. package/dist/adapters/cloudflare-kv-cache.js +36 -14
  33. package/dist/adapters/cloudflare-kv-cache.js.map +1 -1
  34. package/dist/adapters/compress-module.d.ts +5 -4
  35. package/dist/adapters/compress-module.d.ts.map +1 -1
  36. package/dist/adapters/nitro.d.ts +1 -3
  37. package/dist/adapters/nitro.d.ts.map +1 -1
  38. package/dist/adapters/nitro.js +14 -134
  39. package/dist/adapters/nitro.js.map +1 -1
  40. package/dist/cache/cache-api.d.ts.map +1 -1
  41. package/dist/cache/index.d.ts +3 -1
  42. package/dist/cache/index.d.ts.map +1 -1
  43. package/dist/cache/index.js +20 -235
  44. package/dist/cache/index.js.map +1 -1
  45. package/dist/cache/invalidation-epoch.d.ts +43 -0
  46. package/dist/cache/invalidation-epoch.d.ts.map +1 -0
  47. package/dist/cache/redis-handler.d.ts +13 -0
  48. package/dist/cache/redis-handler.d.ts.map +1 -1
  49. package/dist/cache/timber-cache.d.ts +17 -9
  50. package/dist/cache/timber-cache.d.ts.map +1 -1
  51. package/dist/cli-schema-sync.d.ts +21 -1
  52. package/dist/cli-schema-sync.d.ts.map +1 -1
  53. package/dist/cli.d.ts +12 -0
  54. package/dist/cli.d.ts.map +1 -1
  55. package/dist/cli.js +26 -31
  56. package/dist/cli.js.map +1 -1
  57. package/dist/client/browser-entry/hmr.d.ts.map +1 -1
  58. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  59. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  60. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  61. package/dist/client/error-boundary.d.ts.map +1 -1
  62. package/dist/client/error-boundary.js +13 -4
  63. package/dist/client/error-boundary.js.map +1 -1
  64. package/dist/client/error-reconstituter.d.ts +8 -1
  65. package/dist/client/error-reconstituter.d.ts.map +1 -1
  66. package/dist/client/history.d.ts +10 -17
  67. package/dist/client/history.d.ts.map +1 -1
  68. package/dist/client/index.js +1 -1
  69. package/dist/client/index.js.map +1 -1
  70. package/dist/client/internal.js +30 -33
  71. package/dist/client/internal.js.map +1 -1
  72. package/dist/client/navigation-api.d.ts +9 -2
  73. package/dist/client/navigation-api.d.ts.map +1 -1
  74. package/dist/client/navigation-context.d.ts +0 -11
  75. package/dist/client/navigation-context.d.ts.map +1 -1
  76. package/dist/client/navigation-root.d.ts +0 -5
  77. package/dist/client/navigation-root.d.ts.map +1 -1
  78. package/dist/client/router.d.ts.map +1 -1
  79. package/dist/client/rsc-fetch.d.ts.map +1 -1
  80. package/dist/client/use-search-params.d.ts +10 -5
  81. package/dist/client/use-search-params.d.ts.map +1 -1
  82. package/dist/codec.js +1 -1
  83. package/dist/config-validation.d.ts.map +1 -1
  84. package/dist/cookies/define-cookie.d.ts.map +1 -1
  85. package/dist/cookies/index.js +2 -4
  86. package/dist/cookies/index.js.map +1 -1
  87. package/dist/dev-tools/dev-page-shell.d.ts +1 -0
  88. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
  89. package/dist/dev-tools/hydration-overlay.d.ts +11 -0
  90. package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
  91. package/dist/dev-tools/index.d.ts +1 -2
  92. package/dist/dev-tools/index.d.ts.map +1 -1
  93. package/dist/fonts/ast-walk.d.ts +68 -0
  94. package/dist/fonts/ast-walk.d.ts.map +1 -0
  95. package/dist/fonts/ast.d.ts +23 -11
  96. package/dist/fonts/ast.d.ts.map +1 -1
  97. package/dist/fonts/bundle.d.ts +3 -1
  98. package/dist/fonts/bundle.d.ts.map +1 -1
  99. package/dist/fonts/dev-middleware.d.ts +1 -1
  100. package/dist/fonts/dev-middleware.d.ts.map +1 -1
  101. package/dist/fonts/fallbacks.d.ts +0 -7
  102. package/dist/fonts/fallbacks.d.ts.map +1 -1
  103. package/dist/fonts/google.d.ts +4 -2
  104. package/dist/fonts/google.d.ts.map +1 -1
  105. package/dist/fonts/local.d.ts +3 -3
  106. package/dist/fonts/local.d.ts.map +1 -1
  107. package/dist/fonts/paths.d.ts +43 -0
  108. package/dist/fonts/paths.d.ts.map +1 -0
  109. package/dist/fonts/pipeline.d.ts +7 -21
  110. package/dist/fonts/pipeline.d.ts.map +1 -1
  111. package/dist/fonts/transform.d.ts.map +1 -1
  112. package/dist/fonts/virtual-modules.d.ts +1 -18
  113. package/dist/fonts/virtual-modules.d.ts.map +1 -1
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +609 -406
  116. package/dist/index.js.map +1 -1
  117. package/dist/params/index.js +1 -1
  118. package/dist/params/resolve-schema.d.ts.map +1 -1
  119. package/dist/plugin-context.d.ts +28 -5
  120. package/dist/plugin-context.d.ts.map +1 -1
  121. package/dist/plugins/cache.d.ts +13 -5
  122. package/dist/plugins/cache.d.ts.map +1 -1
  123. package/dist/plugins/dev-server.d.ts.map +1 -1
  124. package/dist/plugins/fonts.d.ts +1 -2
  125. package/dist/plugins/fonts.d.ts.map +1 -1
  126. package/dist/plugins/routing.d.ts.map +1 -1
  127. package/dist/routing/codegen-types.d.ts +4 -0
  128. package/dist/routing/codegen-types.d.ts.map +1 -1
  129. package/dist/routing/codegen.d.ts.map +1 -1
  130. package/dist/routing/convention-lint.d.ts.map +1 -1
  131. package/dist/routing/file-cache.d.ts +8 -0
  132. package/dist/routing/file-cache.d.ts.map +1 -0
  133. package/dist/routing/index.js +2 -2
  134. package/dist/routing/interception.d.ts +0 -5
  135. package/dist/routing/interception.d.ts.map +1 -1
  136. package/dist/routing/manifest-codegen.d.ts +32 -0
  137. package/dist/routing/manifest-codegen.d.ts.map +1 -0
  138. package/dist/routing/scanner.d.ts.map +1 -1
  139. package/dist/schema-bridge.d.ts +15 -0
  140. package/dist/schema-bridge.d.ts.map +1 -1
  141. package/dist/search-params/define.d.ts.map +1 -1
  142. package/dist/search-params/index.js +7 -3
  143. package/dist/search-params/index.js.map +1 -1
  144. package/dist/search-params/wrappers.d.ts.map +1 -1
  145. package/dist/segment-params/define.d.ts.map +1 -1
  146. package/dist/segment-params/index.js +1 -1
  147. package/dist/server/access-gate.d.ts.map +1 -1
  148. package/dist/server/actions.d.ts +0 -14
  149. package/dist/server/actions.d.ts.map +1 -1
  150. package/dist/server/build-manifest.d.ts +0 -29
  151. package/dist/server/build-manifest.d.ts.map +1 -1
  152. package/dist/server/canonicalize.d.ts +10 -0
  153. package/dist/server/canonicalize.d.ts.map +1 -1
  154. package/dist/server/deny-boundary.d.ts +27 -2
  155. package/dist/server/deny-boundary.d.ts.map +1 -1
  156. package/dist/server/deny-renderer.d.ts +1 -1
  157. package/dist/server/deny-renderer.d.ts.map +1 -1
  158. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  159. package/dist/server/html-injector-core.d.ts +8 -0
  160. package/dist/server/html-injector-core.d.ts.map +1 -1
  161. package/dist/server/html-injectors.d.ts.map +1 -1
  162. package/dist/server/index.js +2 -2
  163. package/dist/server/internal.d.ts +1 -5
  164. package/dist/server/internal.d.ts.map +1 -1
  165. package/dist/server/internal.js +238 -349
  166. package/dist/server/internal.js.map +1 -1
  167. package/dist/server/node-stream-transforms.d.ts +0 -11
  168. package/dist/server/node-stream-transforms.d.ts.map +1 -1
  169. package/dist/server/render-utils.d.ts +25 -0
  170. package/dist/server/render-utils.d.ts.map +1 -0
  171. package/dist/server/route-element-builder.d.ts +11 -25
  172. package/dist/server/route-element-builder.d.ts.map +1 -1
  173. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  174. package/dist/server/rsc-entry/helpers.d.ts +2 -18
  175. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  176. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  177. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  178. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  179. package/dist/server/ssr-render.d.ts.map +1 -1
  180. package/dist/server/status-code-resolver.d.ts +6 -0
  181. package/dist/server/status-code-resolver.d.ts.map +1 -1
  182. package/dist/server/utils/mdx-file.d.ts +15 -0
  183. package/dist/server/utils/mdx-file.d.ts.map +1 -0
  184. package/dist/shared/href-validation.d.ts.map +1 -1
  185. package/dist/shims/image.d.ts +15 -15
  186. package/package.json +3 -3
  187. package/src/adapters/cloudflare-kv-cache.ts +56 -19
  188. package/src/adapters/compress-module.ts +27 -118
  189. package/src/adapters/nitro.ts +3 -41
  190. package/src/adapters/raw-imports.d.ts +5 -0
  191. package/src/cache/cache-api.ts +9 -1
  192. package/src/cache/index.ts +5 -2
  193. package/src/cache/invalidation-epoch.ts +93 -0
  194. package/src/cache/redis-handler.ts +33 -2
  195. package/src/cache/timber-cache.ts +109 -53
  196. package/src/cli-schema-sync.ts +123 -30
  197. package/src/cli.ts +33 -37
  198. package/src/client/browser-entry/hmr.ts +0 -11
  199. package/src/client/browser-entry/hydrate.ts +39 -5
  200. package/src/client/browser-entry/post-hydration.ts +6 -15
  201. package/src/client/browser-entry/router-init.ts +98 -3
  202. package/src/client/error-boundary.tsx +14 -0
  203. package/src/client/error-reconstituter.tsx +15 -1
  204. package/src/client/history.ts +10 -24
  205. package/src/client/navigation-api.ts +14 -9
  206. package/src/client/navigation-context.ts +1 -21
  207. package/src/client/navigation-root.tsx +0 -8
  208. package/src/client/router.ts +18 -8
  209. package/src/client/rsc-fetch.ts +7 -2
  210. package/src/client/use-search-params.ts +10 -5
  211. package/src/config-validation.ts +33 -25
  212. package/src/cookies/define-cookie.ts +2 -18
  213. package/src/dev-tools/dev-page-shell.ts +6 -2
  214. package/src/dev-tools/hydration-overlay.ts +158 -0
  215. package/src/dev-tools/index.ts +3 -16
  216. package/src/fonts/ast-walk.ts +235 -0
  217. package/src/fonts/ast.ts +91 -249
  218. package/src/fonts/bundle.ts +16 -9
  219. package/src/fonts/dev-middleware.ts +16 -5
  220. package/src/fonts/fallbacks.ts +0 -23
  221. package/src/fonts/google.ts +7 -3
  222. package/src/fonts/local.ts +7 -6
  223. package/src/fonts/paths.ts +58 -0
  224. package/src/fonts/pipeline.ts +27 -48
  225. package/src/fonts/transform.ts +27 -0
  226. package/src/fonts/virtual-modules.ts +1 -57
  227. package/src/index.ts +5 -11
  228. package/src/params/resolve-schema.ts +2 -34
  229. package/src/plugin-context.ts +95 -17
  230. package/src/plugins/cache.ts +64 -17
  231. package/src/plugins/dev-server.ts +61 -9
  232. package/src/plugins/fonts.ts +21 -6
  233. package/src/plugins/routing.ts +5 -348
  234. package/src/routing/codegen-types.ts +4 -0
  235. package/src/routing/codegen.ts +66 -8
  236. package/src/routing/convention-lint.ts +4 -3
  237. package/src/routing/file-cache.ts +23 -0
  238. package/src/routing/interception.ts +2 -21
  239. package/src/routing/manifest-codegen.ts +290 -0
  240. package/src/routing/scanner.ts +85 -80
  241. package/src/routing/schema-validation.ts +2 -2
  242. package/src/schema-bridge.ts +63 -2
  243. package/src/search-params/define.ts +34 -2
  244. package/src/search-params/wrappers.ts +21 -3
  245. package/src/segment-params/define.ts +2 -62
  246. package/src/server/access-gate.tsx +8 -0
  247. package/src/server/actions.ts +8 -31
  248. package/src/server/build-manifest.ts +0 -56
  249. package/src/server/canonicalize.ts +6 -3
  250. package/src/server/deny-boundary.ts +106 -13
  251. package/src/server/deny-renderer.ts +46 -10
  252. package/src/server/error-boundary-wrapper.ts +1 -14
  253. package/src/server/html-injector-core.ts +19 -0
  254. package/src/server/html-injectors.ts +14 -4
  255. package/src/server/internal.ts +1 -18
  256. package/src/server/node-stream-transforms.ts +5 -72
  257. package/src/server/render-utils.ts +31 -0
  258. package/src/server/route-element-builder.ts +77 -47
  259. package/src/server/route-matcher.ts +22 -6
  260. package/src/server/rsc-entry/error-renderer.ts +2 -12
  261. package/src/server/rsc-entry/helpers.ts +6 -34
  262. package/src/server/rsc-entry/index.ts +11 -0
  263. package/src/server/rsc-entry/render-route.ts +7 -9
  264. package/src/server/rsc-entry/rsc-payload.ts +2 -1
  265. package/src/server/rsc-entry/ssr-renderer.ts +2 -2
  266. package/src/server/ssr-render.ts +1 -11
  267. package/src/server/status-code-resolver.ts +3 -2
  268. package/src/server/tree-match.ts +15 -5
  269. package/src/server/utils/mdx-file.ts +22 -0
  270. package/src/shared/href-validation.ts +8 -0
  271. package/dist/_chunks/cli-schema-sync-D2IpXicg.js.map +0 -1
  272. package/dist/_chunks/cli-schema-sync-DH-M8Poy.js +0 -2
  273. package/dist/_chunks/define-C3RvHQPK.js.map +0 -1
  274. package/dist/_chunks/define-DMVhsipD.js.map +0 -1
  275. package/dist/_chunks/handler-store-BVDgyTh7.js +0 -78
  276. package/dist/_chunks/handler-store-BVDgyTh7.js.map +0 -1
  277. package/dist/_chunks/logger-Dt-jQaBO.js +0 -291
  278. package/dist/_chunks/logger-Dt-jQaBO.js.map +0 -1
  279. package/dist/_chunks/metadata-routes-BjepjefT.js.map +0 -1
  280. package/dist/_chunks/resolve-schema-Dj8tQloi.js.map +0 -1
  281. package/dist/_chunks/schema-bridge-DK_89h8O.js.map +0 -1
  282. package/dist/_chunks/tracing-M_zKubhk.js.map +0 -1
  283. package/dist/_chunks/walkers-7FBPM-hX.js.map +0 -1
  284. package/dist/_chunks/warnings-CNPXaypM.js +0 -125
  285. package/dist/_chunks/warnings-CNPXaypM.js.map +0 -1
  286. package/dist/client/link-pending-store.d.ts +0 -65
  287. package/dist/client/link-pending-store.d.ts.map +0 -1
  288. package/dist/client/nav-link-store.d.ts +0 -27
  289. package/dist/client/nav-link-store.d.ts.map +0 -1
  290. package/dist/dev-tools/warnings.d.ts +0 -109
  291. package/dist/dev-tools/warnings.d.ts.map +0 -1
  292. package/dist/server/flush.d.ts +0 -74
  293. package/dist/server/flush.d.ts.map +0 -1
  294. package/src/client/link-pending-store.ts +0 -116
  295. package/src/client/nav-link-store.ts +0 -37
  296. package/src/dev-tools/warnings.ts +0 -238
  297. package/src/server/flush.ts +0 -183
@@ -1,10 +1,9 @@
1
- import { a as isDynamicMetadataExtension, n as classifyMetadataRoute } from "./metadata-routes-BjepjefT.js";
1
+ import { a as classifyMetadataRoute, c as isDynamicMetadataExtension, n as NULL_BYTE_RE, t as ENCODED_SEPARATOR_RE } from "./canonicalize-P41GR6tY.js";
2
2
  import { r as DEFAULT_PAGE_EXTENSIONS, t as classifySegment } from "./segment-classify-CDDRVKs7.js";
3
- import { h as swallow } from "./logger-Dt-jQaBO.js";
3
+ import { h as swallow } from "./logger-CM0clugc.js";
4
+ import { o as resolveAppDir } from "./plugin-context-GfDWsdd2.js";
4
5
  import { basename, extname, join } from "node:path";
5
- import { createRequire } from "node:module";
6
6
  import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
7
- import { performance } from "node:perf_hooks";
8
7
  //#region src/routing/scanner.ts
9
8
  /**
10
9
  * Route discovery scanner.
@@ -16,17 +15,6 @@ import { performance } from "node:perf_hooks";
16
15
  * is discovery only.
17
16
  */
18
17
  /**
19
- * Pattern matching encoded path delimiters that must be rejected during route discovery.
20
- * %2F / %2f (forward slash) and %5C / %5c (backslash) can cause route collisions
21
- * when decoded. See design/13-security.md §"Encoded separators rejected".
22
- */
23
- var ENCODED_SEPARATOR_PATTERN = /%(?:2[fF]|5[cC])/;
24
- /**
25
- * Pattern matching encoded null bytes (%00) that must be rejected.
26
- * See design/13-security.md §"Null bytes rejected".
27
- */
28
- var ENCODED_NULL_PATTERN = /%00/;
29
- /**
30
18
  * File convention names that use pageExtensions (can be .tsx, .ts, .jsx, .js, .mdx, etc.)
31
19
  */
32
20
  var PAGE_EXT_CONVENTIONS = new Set([
@@ -127,48 +115,23 @@ function scanSegmentFiles(dirPath, node, extSet) {
127
115
  const ext = extname(entry).slice(1);
128
116
  const name = basename(entry, `.${ext}`);
129
117
  if (PAGE_EXT_CONVENTIONS.has(name) && extSet.has(ext)) {
130
- const file = {
118
+ const key = name;
119
+ const existing = node[key];
120
+ if (existing) throwDuplicateConvention(name, existing.filePath, fullPath);
121
+ node[key] = {
131
122
  filePath: fullPath,
132
123
  extension: ext
133
124
  };
134
- switch (name) {
135
- case "page":
136
- node.page = file;
137
- break;
138
- case "layout":
139
- node.layout = file;
140
- break;
141
- case "error":
142
- node.error = file;
143
- break;
144
- case "default":
145
- node.default = file;
146
- break;
147
- case "denied":
148
- node.denied = file;
149
- break;
150
- }
151
125
  continue;
152
126
  }
153
- if (FIXED_CONVENTIONS.has(name) && /\.?[jt]sx?$/.test(ext)) {
154
- const file = {
127
+ if (FIXED_CONVENTIONS.has(name) && /^[jt]sx?$/.test(ext)) {
128
+ const key = name;
129
+ const existing = node[key];
130
+ if (existing) throwDuplicateConvention(name, existing.filePath, fullPath);
131
+ node[key] = {
155
132
  filePath: fullPath,
156
133
  extension: ext
157
134
  };
158
- switch (name) {
159
- case "middleware":
160
- node.middleware = file;
161
- break;
162
- case "access":
163
- node.access = file;
164
- break;
165
- case "route":
166
- node.route = file;
167
- break;
168
- case "params":
169
- node.params = file;
170
- break;
171
- }
172
135
  continue;
173
136
  }
174
137
  if (STATUS_CODE_PATTERN.test(name) && ext === "json") {
@@ -181,6 +144,8 @@ function scanSegmentFiles(dirPath, node, extSet) {
181
144
  }
182
145
  if (STATUS_CODE_PATTERN.test(name) && extSet.has(ext)) {
183
146
  if (!node.statusFiles) node.statusFiles = {};
147
+ const existing = node.statusFiles[name];
148
+ if (existing) throwDuplicateConvention(name, existing.filePath, fullPath);
184
149
  node.statusFiles[name] = {
185
150
  filePath: fullPath,
186
151
  extension: ext
@@ -189,6 +154,8 @@ function scanSegmentFiles(dirPath, node, extSet) {
189
154
  }
190
155
  if (name in LEGACY_STATUS_FILES && extSet.has(ext)) {
191
156
  if (!node.legacyStatusFiles) node.legacyStatusFiles = {};
157
+ const existing = node.legacyStatusFiles[name];
158
+ if (existing) throwDuplicateConvention(name, existing.filePath, fullPath);
192
159
  node.legacyStatusFiles[name] = {
193
160
  filePath: fullPath,
194
161
  extension: ext
@@ -200,7 +167,9 @@ function scanSegmentFiles(dirPath, node, extSet) {
200
167
  const existing = node.metadataRoutes[name];
201
168
  if (existing) {
202
169
  const existingIsDynamic = isDynamicMetadataExtension(name, existing.extension);
203
- if (isDynamicMetadataExtension(name, ext) || !existingIsDynamic) node.metadataRoutes[name] = {
170
+ const newIsDynamic = isDynamicMetadataExtension(name, ext);
171
+ if (existingIsDynamic === newIsDynamic) throwDuplicateConvention(name, existing.filePath, fullPath);
172
+ if (newIsDynamic) node.metadataRoutes[name] = {
204
173
  filePath: fullPath,
205
174
  extension: ext
206
175
  };
@@ -213,6 +182,16 @@ function scanSegmentFiles(dirPath, node, extSet) {
213
182
  if (node.route && node.page) throw new Error(`Build error: route.ts and page.* cannot coexist in the same segment.\n route.ts: ${node.route.filePath}\n page: ${node.page.filePath}\nA URL is either an API endpoint or a rendered page, not both.`);
214
183
  }
215
184
  /**
185
+ * Throw a build error for two files claiming the same convention slot in
186
+ * one segment (e.g. page.tsx + page.jsx). Which file readdir returns first
187
+ * is platform-dependent (APFS sorts entries, ext4 does not) — silently
188
+ * picking one would let macOS dev and Linux CI serve different
189
+ * implementations of the same route.
190
+ */
191
+ function throwDuplicateConvention(convention, firstPath, secondPath) {
192
+ throw new Error(`Build error: duplicate '${convention}' files in the same route segment.\n File 1: ${firstPath}\n File 2: ${secondPath}\nEach segment may define '${convention}' at most once. Remove one of the files.`);
193
+ }
194
+ /**
216
195
  * Recursively scan child directories and build the segment tree.
217
196
  */
218
197
  function scanChildren(dirPath, parentNode, extSet) {
@@ -230,8 +209,8 @@ function scanChildren(dirPath, parentNode, extSet) {
230
209
  } catch {
231
210
  continue;
232
211
  }
233
- if (ENCODED_SEPARATOR_PATTERN.test(entry)) throw new Error(`Build error: directory name contains an encoded path delimiter (%%2F or %%5C).\n Directory: ${fullPath}\nEncoded separators in directory names cause route collisions when decoded. Rename the directory to remove the encoded delimiter.`);
234
- if (ENCODED_NULL_PATTERN.test(entry)) throw new Error(`Build error: directory name contains an encoded null byte (%%00).\n Directory: ${fullPath}\nEncoded null bytes in directory names are not allowed. Rename the directory to remove the null byte encoding.`);
212
+ if (ENCODED_SEPARATOR_RE.test(entry)) throw new Error(`Build error: directory name contains an encoded path delimiter (%2F or %5C).\n Directory: ${fullPath}\nEncoded separators in directory names cause route collisions when decoded. Rename the directory to remove the encoded delimiter.`);
213
+ if (NULL_BYTE_RE.test(entry)) throw new Error(`Build error: directory name contains an encoded null byte (%00).\n Directory: ${fullPath}\nEncoded null bytes in directory names are not allowed. Rename the directory to remove the null byte encoding.`);
235
214
  const { type, paramName, interceptionMarker, interceptedSegmentName } = classifySegment(entry);
236
215
  if (type === "private") continue;
237
216
  const childNode = createSegmentNode(entry, type, computeUrlPath(parentNode.urlPath, entry, type), paramName, interceptionMarker, interceptedSegmentName);
@@ -249,32 +228,34 @@ function scanChildren(dirPath, parentNode, extSet) {
249
228
  * Two route groups like (auth)/login/page.tsx and (marketing)/login/page.tsx both claim
250
229
  * /login — the scanner must detect and reject this at build time.
251
230
  *
252
- * Parallel slots are excluded from collision detection — they intentionally coexist at
253
- * the same URL path as their parent (that's the whole point of parallel routes).
231
+ * Each parallel slot is validated as its OWN collision space: a slot's pages
232
+ * intentionally share URL paths with the parent tree (that's the point of
233
+ * parallel routes), but two route groups INSIDE one slot claiming the same
234
+ * URL — e.g. @side/(a)/x/page.tsx + @side/(b)/x/page.tsx — still collide.
254
235
  */
255
236
  function validateRouteGroupCollisions(root) {
256
- collectRoutableLeaves(root, /* @__PURE__ */ new Map(), "", false);
237
+ collectRoutableLeaves(root, /* @__PURE__ */ new Map(), "");
257
238
  }
258
239
  /**
259
240
  * Walk the segment tree and collect all routable leaves (page or route files),
260
- * throwing on collision. Slots are tracked in their own collision space since
261
- * they are parallel routes that intentionally share URL paths with their parent.
241
+ * throwing on collision. Each slot recurses with a FRESH collision map —
242
+ * slots are parallel routes that intentionally share URL paths with their
243
+ * parent tree, but collisions within a single slot are real errors.
262
244
  */
263
- function collectRoutableLeaves(node, seen, segmentPath, insideSlot) {
245
+ function collectRoutableLeaves(node, seen, segmentPath) {
246
+ if (node.segmentType === "intercepting") return;
264
247
  const currentPath = segmentPath ? `${segmentPath}/${node.segmentName}` : node.segmentName || "(root)";
265
- if (!insideSlot) {
266
- const routableFile = node.page ?? node.route;
267
- if (routableFile) {
268
- const existing = seen.get(node.urlPath);
269
- if (existing) throw new Error(`Build error: route collision — multiple route groups produce a page/route at the same URL path.\n URL path: ${node.urlPath}\n File 1: ${existing.filePath} (via ${existing.segmentPath})\n File 2: ${routableFile.filePath} (via ${currentPath})\nEach URL path must map to exactly one page or route handler. Rename or move one of the conflicting files.`);
270
- seen.set(node.urlPath, {
271
- filePath: routableFile.filePath,
272
- segmentPath: currentPath
273
- });
274
- }
248
+ const routableFile = node.page ?? node.route;
249
+ if (routableFile) {
250
+ const existing = seen.get(node.urlPath);
251
+ if (existing) throw new Error(`Build error: route collision — multiple route groups produce a page/route at the same URL path.\n URL path: ${node.urlPath}\n File 1: ${existing.filePath} (via ${existing.segmentPath})\n File 2: ${routableFile.filePath} (via ${currentPath})\nEach URL path must map to exactly one page or route handler. Rename or move one of the conflicting files.`);
252
+ seen.set(node.urlPath, {
253
+ filePath: routableFile.filePath,
254
+ segmentPath: currentPath
255
+ });
275
256
  }
276
- for (const child of node.children) collectRoutableLeaves(child, seen, currentPath, insideSlot);
277
- for (const slotNode of Object.values(node.slots)) collectRoutableLeaves(slotNode, seen, currentPath, true);
257
+ for (const child of node.children) collectRoutableLeaves(child, seen, currentPath);
258
+ for (const slotNode of Object.values(node.slots)) collectRoutableLeaves(slotNode, /* @__PURE__ */ new Map(), currentPath);
278
259
  }
279
260
  /**
280
261
  * Validate that no route chain contains duplicate dynamic param names.
@@ -369,225 +350,6 @@ function findPageExtFile(dirPath, name, extSet) {
369
350
  }
370
351
  }
371
352
  //#endregion
372
- //#region src/utils/startup-timer.ts
373
- /**
374
- * Startup timer — records named phases with their durations.
375
- *
376
- * Used by the plugin system to instrument cold start and report a
377
- * timing breakdown in dev mode. Zero overhead in production (disabled).
378
- *
379
- * See design/18-build-system.md, TIM-155.
380
- */
381
- /**
382
- * Create a startup timer that records phase durations.
383
- */
384
- function createStartupTimer() {
385
- const pending = /* @__PURE__ */ new Map();
386
- const phases = [];
387
- return {
388
- start(phase) {
389
- pending.set(phase, performance.now());
390
- },
391
- end(phase) {
392
- const startMs = pending.get(phase);
393
- if (startMs === void 0) return 0;
394
- pending.delete(phase);
395
- const durationMs = performance.now() - startMs;
396
- phases.push({
397
- name: phase,
398
- startMs,
399
- durationMs
400
- });
401
- return durationMs;
402
- },
403
- getPhases() {
404
- return [...phases].sort((a, b) => a.startMs - b.startMs);
405
- },
406
- totalMs() {
407
- if (phases.length === 0) return 0;
408
- const sorted = this.getPhases();
409
- const first = sorted[0];
410
- const last = sorted[sorted.length - 1];
411
- return last.startMs + last.durationMs - first.startMs;
412
- },
413
- formatSummary() {
414
- const sorted = this.getPhases();
415
- if (sorted.length === 0) return "No phases recorded.";
416
- const lines = sorted.map((p) => {
417
- const ms = p.durationMs.toFixed(1);
418
- return ` ${p.name.padEnd(30)} ${ms.padStart(8)}ms`;
419
- });
420
- const total = this.totalMs().toFixed(1);
421
- lines.push(` ${"total".padEnd(30)} ${total.padStart(8)}ms`);
422
- return ["[timber] startup timing:", ...lines].join("\n");
423
- }
424
- };
425
- }
426
- /**
427
- * No-op timer for production builds — all methods are empty.
428
- */
429
- function createNoopTimer() {
430
- return {
431
- start() {},
432
- end() {
433
- return 0;
434
- },
435
- getPhases() {
436
- return [];
437
- },
438
- totalMs() {
439
- return 0;
440
- },
441
- formatSummary() {
442
- return "";
443
- }
444
- };
445
- }
446
- //#endregion
447
- //#region src/plugin-context.ts
448
- /**
449
- * Plugin context — internal types and helpers for timber sub-plugins.
450
- *
451
- * These are NOT part of the user-facing API. They are consumed by
452
- * sub-plugins (routing, entries, shims, etc.) via relative imports.
453
- * The root entry point (index.ts) does not re-export them.
454
- *
455
- * Design doc: 18-build-system.md §"Shared Plugin Context"
456
- */
457
- /**
458
- * Resolve `clientJavascript` into a fully resolved config.
459
- */
460
- function resolveClientJavascript(config) {
461
- if (config.clientJavascript !== void 0) {
462
- if (typeof config.clientJavascript === "boolean") return {
463
- disabled: !config.clientJavascript,
464
- enableHMRInDev: !config.clientJavascript
465
- };
466
- return {
467
- disabled: config.clientJavascript.disabled,
468
- enableHMRInDev: config.clientJavascript.enableHMRInDev ?? config.clientJavascript.disabled
469
- };
470
- }
471
- return {
472
- disabled: false,
473
- enableHMRInDev: false
474
- };
475
- }
476
- /**
477
- * Resolve the app directory. Checks (in order):
478
- * 1. Explicit `configAppDir` from timber.config.ts
479
- * 2. `<root>/app`
480
- * 3. `<root>/src/app`
481
- *
482
- * Throws if none exist.
483
- */
484
- function resolveAppDir(root, configAppDir) {
485
- if (configAppDir) {
486
- const explicit = join(root, configAppDir);
487
- if (!existsSync(explicit)) throw new Error(`[timber] Configured appDir "${configAppDir}" does not exist at ${explicit}`);
488
- return explicit;
489
- }
490
- const rootApp = join(root, "app");
491
- if (existsSync(rootApp)) return rootApp;
492
- const srcApp = join(root, "src", "app");
493
- if (existsSync(srcApp)) return srcApp;
494
- throw new Error(`[timber] Could not find app directory. Expected "app/" or "src/app/" in ${root}. You can set appDir in timber.config.ts to specify a custom location.`);
495
- }
496
- function createPluginContext(config, root) {
497
- const projectRoot = root ?? process.cwd();
498
- const resolvedConfig = { ...config };
499
- return {
500
- config: resolvedConfig,
501
- clientJavascript: resolveClientJavascript(resolvedConfig),
502
- routeTree: null,
503
- appDir: join(projectRoot, "app"),
504
- root: projectRoot,
505
- dev: false,
506
- buildManifest: null,
507
- deploymentId: null,
508
- timer: createStartupTimer(),
509
- holdingServer: null,
510
- buildDir: resolveBuildDir(projectRoot, resolvedConfig.buildDir)
511
- };
512
- }
513
- /** Default build output directory (relative to root). */
514
- var DEFAULT_BUILD_DIR = join(".timber", "dist");
515
- /**
516
- * Resolve the build output directory.
517
- *
518
- * Priority:
519
- * 1. Explicit `timberBuildDir` from timber.config.ts
520
- * 2. Explicit `viteBuildOutDir` from Vite's build.outDir (if not the default 'dist')
521
- * 3. Default: `.timber/dist`
522
- *
523
- * Returns an absolute path.
524
- */
525
- function resolveBuildDir(root, timberBuildDir, viteBuildOutDir) {
526
- if (timberBuildDir) return join(root, timberBuildDir);
527
- if (viteBuildOutDir && viteBuildOutDir !== "dist") return join(root, viteBuildOutDir);
528
- return join(root, DEFAULT_BUILD_DIR);
529
- }
530
- /**
531
- * Load timber.config.ts (or .js, .mjs) from the project root.
532
- * Returns the config object or null if no config file is found.
533
- *
534
- * Uses require() which works for ESM modules on Node 22.12+.
535
- * This keeps timber() synchronous — no async config loading needed.
536
- */
537
- function loadTimberConfigFile(root) {
538
- const configNames = [
539
- "timber.config.ts",
540
- "timber.config.js",
541
- "timber.config.mjs"
542
- ];
543
- const req = createRequire(join(root, "package.json"));
544
- for (const name of configNames) {
545
- const configPath = join(root, name);
546
- if (existsSync(configPath)) {
547
- const mod = req(configPath);
548
- return mod.default ?? mod;
549
- }
550
- }
551
- return null;
552
- }
553
- /**
554
- * Detect config keys set in both inline (vite.config.ts) and file (timber.config.ts)
555
- * and warn the user. The `output` key is excluded because it defaults to 'server'
556
- * in createPluginContext and would always appear as an inline key.
557
- *
558
- * Returns the list of conflicting key names (for testing).
559
- */
560
- function warnConfigConflicts(inline, fileConfig) {
561
- const conflicts = [];
562
- for (const key of Object.keys(fileConfig)) if (key in inline && inline[key] !== void 0) conflicts.push(key);
563
- if (conflicts.length > 0) console.warn(`[timber] Config conflict: ${conflicts.map((k) => `"${k}"`).join(", ")} set in both vite.config.ts (inline) and timber.config.ts. Move all config to timber.config.ts to avoid confusion. The inline value from vite.config.ts will be used.`);
564
- return conflicts;
565
- }
566
- /**
567
- * Merge file-based config into ctx.config. Inline config (already in ctx.config)
568
- * takes precedence — file config only fills in missing fields.
569
- */
570
- function mergeFileConfig(ctx, fileConfig) {
571
- const inline = ctx.config;
572
- warnConfigConflicts(inline, fileConfig);
573
- ctx.config = {
574
- ...fileConfig,
575
- ...inline,
576
- ...fileConfig.limits && inline.limits ? { limits: {
577
- ...fileConfig.limits,
578
- ...inline.limits
579
- } } : {},
580
- ...fileConfig.dev && inline.dev ? { dev: {
581
- ...fileConfig.dev,
582
- ...inline.dev
583
- } } : {},
584
- ...fileConfig.mdx && inline.mdx ? { mdx: {
585
- ...fileConfig.mdx,
586
- ...inline.mdx
587
- } } : {}
588
- };
589
- }
590
- //#endregion
591
353
  //#region src/cli-schema-sync.ts
592
354
  /**
593
355
  * `timber schema sync` — scan filesystem for dynamic segments, append
@@ -612,14 +374,98 @@ function walkSegments(node, segments) {
612
374
  for (const slot of Object.values(node.slots)) walkSegments(slot, segments);
613
375
  }
614
376
  /**
377
+ * Replace comment bodies (and optionally string contents) with spaces,
378
+ * preserving length and newlines so every index maps 1:1 to the original.
379
+ * Lets the structural scanning below ignore `segmentParams` mentions and
380
+ * braces inside comments/strings without a TS parser (fine pre-alpha,
381
+ * see TIM-1066).
382
+ *
383
+ * With `maskStrings`, string contents are blanked too — except literal
384
+ * 'segmentParams' strings, kept so a quoted property key stays findable.
385
+ */
386
+ function maskSource(content, maskStrings) {
387
+ const out = content.split("");
388
+ const n = content.length;
389
+ let i = 0;
390
+ const blank = (from, to) => {
391
+ for (let j = from; j < to; j++) if (content[j] !== "\n") out[j] = " ";
392
+ };
393
+ while (i < n) {
394
+ const ch = content[i];
395
+ const next = content[i + 1];
396
+ if (ch === "/" && next === "/") {
397
+ const start = i;
398
+ while (i < n && content[i] !== "\n") i++;
399
+ blank(start, i);
400
+ } else if (ch === "/" && next === "*") {
401
+ const start = i;
402
+ i += 2;
403
+ while (i < n && !(content[i] === "*" && content[i + 1] === "/")) i++;
404
+ i = Math.min(i + 2, n);
405
+ blank(start, i);
406
+ } else if (ch === "\"" || ch === "'" || ch === "`") {
407
+ const start = i;
408
+ i++;
409
+ while (i < n && content[i] !== ch) {
410
+ if (content[i] === "\\") i++;
411
+ i++;
412
+ }
413
+ const end = i;
414
+ if (maskStrings && content.slice(start + 1, end) !== "segmentParams") blank(start + 1, end);
415
+ i++;
416
+ } else i++;
417
+ }
418
+ return out.join("");
419
+ }
420
+ /**
421
+ * Locate the `segmentParams: { ... }` block in a schema file.
422
+ * Returns the indices of the opening and matching closing brace, or null
423
+ * if no segmentParams property is found. Comments and strings are masked
424
+ * first, so a JSDoc example mentioning `segmentParams: { ... }` above the
425
+ * real defineSchema call is not mistaken for the block, and braces inside
426
+ * comments/strings don't skew the depth count. The search is anchored to
427
+ * the `defineSchema(` call when present, so helper objects with their own
428
+ * segmentParams property earlier in the file are skipped.
429
+ */
430
+ function findSegmentParamsBlock(content) {
431
+ const masked = maskSource(content, true);
432
+ const defineCall = /\bdefineSchema\s*\(/.exec(masked);
433
+ const keyRe = /(['"]?)segmentParams\1\s*:\s*\{/g;
434
+ keyRe.lastIndex = defineCall ? defineCall.index + defineCall[0].length : 0;
435
+ const keyMatch = keyRe.exec(masked);
436
+ if (!keyMatch) return null;
437
+ const openBrace = keyMatch.index + keyMatch[0].length - 1;
438
+ let depth = 1;
439
+ let i = openBrace + 1;
440
+ while (i < masked.length && depth > 0) {
441
+ if (masked[i] === "{") depth++;
442
+ else if (masked[i] === "}") depth--;
443
+ i++;
444
+ }
445
+ if (depth > 0) return null;
446
+ return {
447
+ openBrace,
448
+ closeBrace: i - 1
449
+ };
450
+ }
451
+ /**
615
452
  * Parse existing bracket keys from an app/schema.ts file.
616
- * Uses regex to find keys in segmentParams: { '[key]': ... } blocks.
453
+ * Scoped to the segmentParams: { ... } block — bracket keys elsewhere in
454
+ * the file (unrelated objects, comments above defineSchema) are ignored.
455
+ * Comments inside the block are masked, so a commented-out entry does not
456
+ * count as registered.
457
+ *
458
+ * The key charset matches the route classifier (segment-classify.ts):
459
+ * any character except `]`, so hyphenated params like '[my-param]' parse.
617
460
  */
618
461
  function parseExistingSchemaKeys(content) {
462
+ const block = findSegmentParamsBlock(content);
463
+ if (!block) return [];
464
+ const blockContent = maskSource(content, false).slice(block.openBrace, block.closeBrace);
619
465
  const keys = [];
620
- const re = /['"](\[{1,2}(?:\.{3})?\w+\]{1,2})['"]\s*:/g;
466
+ const re = /['"](\[{1,2}(?:\.{3})?[^\]]+\]{1,2})['"]\s*:/g;
621
467
  let m;
622
- while ((m = re.exec(content)) !== null) keys.push(m[1]);
468
+ while ((m = re.exec(blockContent)) !== null) keys.push(m[1]);
623
469
  return keys;
624
470
  }
625
471
  /** Schema file extensions to check. */
@@ -678,18 +524,9 @@ function ensureCodecImport(content) {
678
524
  }
679
525
  function appendToSchema(content, newSegments) {
680
526
  content = ensureCodecImport(content);
681
- const spIndex = content.indexOf("segmentParams");
682
- if (spIndex === -1) throw new Error("[timber] Could not find segmentParams in schema file. Expected a defineSchema({ segmentParams: { ... } }) call.");
683
- const openBrace = content.indexOf("{", spIndex + 13);
684
- if (openBrace === -1) throw new Error("[timber] Could not find opening brace for segmentParams.");
685
- let depth = 1;
686
- let i = openBrace + 1;
687
- while (i < content.length && depth > 0) {
688
- if (content[i] === "{") depth++;
689
- else if (content[i] === "}") depth--;
690
- i++;
691
- }
692
- const closeBrace = i - 1;
527
+ const block = findSegmentParamsBlock(content);
528
+ if (!block) throw new Error("[timber] Could not find segmentParams in schema file. Expected a defineSchema({ segmentParams: { ... } }) call.");
529
+ const { openBrace, closeBrace } = block;
693
530
  const existingLine = content.slice(openBrace, closeBrace).match(/^(\s+)['"]\[/m);
694
531
  const indent = existingLine ? existingLine[1] : " ";
695
532
  const insertion = newSegments.map((seg) => `${indent}'${seg}': ${defaultCodecForSegment(seg)},`).join("\n");
@@ -699,20 +536,26 @@ function appendToSchema(content, newSegments) {
699
536
  }
700
537
  /**
701
538
  * Remove entries from the segmentParams block whose keys match `staleSegments`.
702
- * Removes the entire line including trailing comma/whitespace.
539
+ * Removes the entire entry including trailing comma/whitespace. Scoped to
540
+ * the segmentParams block — identical keys in unrelated objects elsewhere
541
+ * in the file are left untouched.
703
542
  */
704
543
  function removeFromSchema(content, staleSegments) {
544
+ const block = findSegmentParamsBlock(content);
545
+ if (!block) return content;
546
+ let blockContent = content.slice(block.openBrace, block.closeBrace);
547
+ let blockMasked = maskSource(blockContent, false);
705
548
  for (const seg of staleSegments) {
706
549
  const escaped = seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
707
550
  const keyRe = new RegExp(`^[ \t]*['"]${escaped}['"][ \t]*:`, "gm");
708
551
  let m;
709
- while ((m = keyRe.exec(content)) !== null) {
552
+ while ((m = keyRe.exec(blockMasked)) !== null) {
710
553
  const start = m.index;
711
554
  let i = m.index + m[0].length;
712
555
  let depth = 0;
713
556
  let inString = null;
714
- while (i < content.length) {
715
- const ch = content[i];
557
+ while (i < blockMasked.length) {
558
+ const ch = blockMasked[i];
716
559
  if (inString) {
717
560
  if (ch === "\\") i++;
718
561
  else if (ch === inString) inString = null;
@@ -725,12 +568,13 @@ function removeFromSchema(content, staleSegments) {
725
568
  } else if (depth === 0 && (ch === "\n" || ch === "}")) break;
726
569
  i++;
727
570
  }
728
- if (i < content.length && content[i] === "\n") i++;
729
- content = content.slice(0, start) + content.slice(i);
571
+ if (i < blockMasked.length && blockMasked[i] === "\n") i++;
572
+ blockContent = blockContent.slice(0, start) + blockContent.slice(i);
573
+ blockMasked = blockMasked.slice(0, start) + blockMasked.slice(i);
730
574
  keyRe.lastIndex = start;
731
575
  }
732
576
  }
733
- return content;
577
+ return content.slice(0, block.openBrace) + blockContent + content.slice(block.closeBrace);
734
578
  }
735
579
  /**
736
580
  * Run the schema sync: scan filesystem, diff against schema, append missing.
@@ -780,6 +624,6 @@ function runSchemaSync(projectRoot) {
780
624
  };
781
625
  }
782
626
  //#endregion
783
- export { runSchemaSync as a, loadTimberConfigFile as c, resolveBuildDir as d, resolveClientJavascript as f, parseExistingSchemaKeys as i, mergeFileConfig as l, scanRoutes as m, defaultCodecForSegment as n, DEFAULT_BUILD_DIR as o, createNoopTimer as p, findSchemaFile as r, createPluginContext as s, collectDynamicSegments as t, resolveAppDir as u };
627
+ export { parseExistingSchemaKeys as a, findSegmentParamsBlock as i, defaultCodecForSegment as n, runSchemaSync as o, findSchemaFile as r, scanRoutes as s, collectDynamicSegments as t };
784
628
 
785
- //# sourceMappingURL=cli-schema-sync-D2IpXicg.js.map
629
+ //# sourceMappingURL=cli-schema-sync-DJDdyEae.js.map