reroute-js 1.0.0-alpha.33 → 1.0.0-alpha.35

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 (219) hide show
  1. package/README.md +1 -0
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +202 -94
  4. package/cli/bin.js.map +12 -11
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +15 -7
  7. package/cli/index.js.map +7 -7
  8. package/cli/src/cli.d.ts +1 -1
  9. package/cli/src/commands/analyze.d.ts +1 -1
  10. package/cli/src/commands/build.d.ts +1 -1
  11. package/cli/src/commands/dev.d.ts +1 -1
  12. package/cli/src/commands/gen.d.ts +1 -1
  13. package/cli/src/commands/gen.d.ts.map +1 -1
  14. package/cli/src/commands/index.d.ts +1 -1
  15. package/cli/src/commands/init.d.ts +1 -1
  16. package/cli/src/commands/lib/assets.d.ts +1 -1
  17. package/cli/src/commands/lib/bundler.d.ts +8 -1
  18. package/cli/src/commands/lib/bundler.d.ts.map +1 -1
  19. package/cli/src/commands/lib/command.d.ts +1 -1
  20. package/cli/src/commands/lib/env.d.ts +1 -1
  21. package/cli/src/commands/lib/images.d.ts +1 -1
  22. package/cli/src/commands/lib/index.d.ts +1 -1
  23. package/cli/src/commands/lib/log.d.ts +1 -1
  24. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  25. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  26. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  27. package/cli/src/commands/lib/prerender.d.ts +1 -1
  28. package/cli/src/commands/lib/production.d.ts +1 -1
  29. package/cli/src/commands/lib/routes.d.ts +40 -0
  30. package/cli/src/commands/lib/routes.d.ts.map +1 -0
  31. package/cli/src/commands/lib/server.d.ts +1 -1
  32. package/cli/src/commands/lib/static.d.ts +1 -1
  33. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  34. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  35. package/cli/src/commands/lib/supervise.d.ts +1 -1
  36. package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
  37. package/cli/src/commands/lib/theme.d.ts +1 -1
  38. package/cli/src/commands/lib/version.d.ts +1 -1
  39. package/cli/src/commands/lib/watch.d.ts +1 -1
  40. package/cli/src/commands/og.d.ts +1 -1
  41. package/cli/src/commands/start.d.ts +1 -1
  42. package/cli/src/commands/static-render.d.ts +1 -1
  43. package/cli/src/index.d.ts +1 -1
  44. package/core/index.d.ts +1 -1
  45. package/core/index.js +55 -15
  46. package/core/index.js.map +8 -8
  47. package/core/src/app-paths.d.ts +1 -1
  48. package/core/src/bundler/hash.d.ts +1 -1
  49. package/core/src/bundler/index.d.ts +1 -1
  50. package/core/src/config.d.ts +1 -1
  51. package/core/src/content/discovery.d.ts +1 -1
  52. package/core/src/content/index.d.ts +1 -1
  53. package/core/src/content/metadata.d.ts +1 -1
  54. package/core/src/i18n/catalog.d.ts +1 -1
  55. package/core/src/i18n/discover.d.ts +1 -1
  56. package/core/src/i18n/index.d.ts +1 -1
  57. package/core/src/i18n/messages.d.ts +1 -1
  58. package/core/src/i18n/negotiate.d.ts +1 -1
  59. package/core/src/i18n/pathname.d.ts +1 -1
  60. package/core/src/i18n/resolve.d.ts +1 -1
  61. package/core/src/i18n/types.d.ts +1 -1
  62. package/core/src/image.d.ts +1 -1
  63. package/core/src/index.d.ts +1 -1
  64. package/core/src/llms/discovery.d.ts +1 -1
  65. package/core/src/llms/extractor.d.ts +1 -1
  66. package/core/src/llms/formatter.d.ts +1 -1
  67. package/core/src/llms/full-generator.d.ts +1 -1
  68. package/core/src/llms/index-generator.d.ts +1 -1
  69. package/core/src/llms/index.d.ts +1 -1
  70. package/core/src/og/discovery.d.ts +1 -1
  71. package/core/src/og/index.d.ts +1 -1
  72. package/core/src/og/meta.d.ts +1 -1
  73. package/core/src/og/render.d.ts +1 -1
  74. package/core/src/og/types.d.ts +1 -1
  75. package/core/src/robots/discovery.d.ts +1 -1
  76. package/core/src/robots/generator.d.ts +1 -1
  77. package/core/src/robots/index.d.ts +1 -1
  78. package/core/src/robots/policies.d.ts +1 -1
  79. package/core/src/rss/discovery.d.ts +1 -1
  80. package/core/src/rss/generator.d.ts +1 -1
  81. package/core/src/rss/index.d.ts +1 -1
  82. package/core/src/sitemap/discovery.d.ts +1 -1
  83. package/core/src/sitemap/generator.d.ts +1 -1
  84. package/core/src/sitemap/index.d.ts +1 -1
  85. package/core/src/ssr/index.d.ts +1 -1
  86. package/core/src/ssr/lib/cache.d.ts +1 -1
  87. package/core/src/ssr/lib/cleanup.d.ts +1 -1
  88. package/core/src/ssr/lib/collections.d.ts +1 -1
  89. package/core/src/ssr/lib/compression.d.ts +1 -1
  90. package/core/src/ssr/lib/compute/content.d.ts +1 -1
  91. package/core/src/ssr/lib/compute/index.d.ts +1 -1
  92. package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
  93. package/core/src/ssr/lib/compute/layouts.d.ts.map +1 -1
  94. package/core/src/ssr/lib/compute/routes.d.ts +1 -1
  95. package/core/src/ssr/lib/content-path.d.ts +1 -1
  96. package/core/src/ssr/lib/data.d.ts +1 -1
  97. package/core/src/ssr/lib/html.d.ts +1 -1
  98. package/core/src/ssr/lib/imports.d.ts +1 -1
  99. package/core/src/ssr/lib/index.d.ts +1 -1
  100. package/core/src/ssr/lib/layouts.d.ts +10 -2
  101. package/core/src/ssr/lib/layouts.d.ts.map +1 -1
  102. package/core/src/ssr/lib/metadata.d.ts +1 -1
  103. package/core/src/ssr/lib/mime.d.ts +1 -1
  104. package/core/src/ssr/lib/modules.d.ts +1 -1
  105. package/core/src/ssr/lib/path.d.ts +1 -1
  106. package/core/src/ssr/lib/preload.d.ts +16 -3
  107. package/core/src/ssr/lib/preload.d.ts.map +1 -1
  108. package/core/src/ssr/lib/route-match.d.ts +1 -1
  109. package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
  110. package/core/src/ssr/lib/scripts/data.d.ts +1 -1
  111. package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
  112. package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
  113. package/core/src/ssr/lib/scripts/index.d.ts +1 -1
  114. package/core/src/ssr/lib/seed.d.ts +1 -1
  115. package/core/src/ssr/lib/serialize.d.ts +1 -1
  116. package/core/src/ssr/lib/setup.d.ts +1 -1
  117. package/core/src/ssr/lib/setup.d.ts.map +1 -1
  118. package/core/src/ssr/lib/styles.d.ts +1 -1
  119. package/core/src/ssr/lib/template.d.ts +1 -1
  120. package/core/src/ssr/lib/types.d.ts +1 -1
  121. package/core/src/ssr/render.d.ts +1 -1
  122. package/core/src/ssr/stream.d.ts +1 -1
  123. package/elysia/index.d.ts +1 -1
  124. package/elysia/index.js +55 -15
  125. package/elysia/index.js.map +8 -8
  126. package/elysia/src/index.d.ts +1 -1
  127. package/elysia/src/libs/assets.d.ts +1 -1
  128. package/elysia/src/libs/cache.d.ts +1 -1
  129. package/elysia/src/libs/caching.d.ts +1 -1
  130. package/elysia/src/libs/devReload.d.ts +1 -1
  131. package/elysia/src/libs/http.d.ts +1 -1
  132. package/elysia/src/libs/i18n.d.ts +1 -1
  133. package/elysia/src/libs/image.d.ts +1 -1
  134. package/elysia/src/libs/index.d.ts +1 -1
  135. package/elysia/src/libs/llms.d.ts +1 -1
  136. package/elysia/src/libs/response.d.ts +1 -1
  137. package/elysia/src/libs/serving.d.ts +1 -1
  138. package/elysia/src/plugin.d.ts +1 -1
  139. package/elysia/src/routes/artifacts.d.ts +1 -1
  140. package/elysia/src/routes/content.d.ts +1 -1
  141. package/elysia/src/routes/image.d.ts +1 -1
  142. package/elysia/src/routes/index.d.ts +1 -1
  143. package/elysia/src/routes/internal.d.ts +1 -1
  144. package/elysia/src/routes/liveReloadClient.d.ts +1 -1
  145. package/elysia/src/routes/llms.d.ts +1 -1
  146. package/elysia/src/routes/og.d.ts +1 -1
  147. package/elysia/src/routes/redirects.d.ts +1 -1
  148. package/elysia/src/routes/robots.d.ts +1 -1
  149. package/elysia/src/routes/rss.d.ts +1 -1
  150. package/elysia/src/routes/search.d.ts +1 -1
  151. package/elysia/src/routes/sitemap.d.ts +1 -1
  152. package/elysia/src/routes/ssr.d.ts +1 -1
  153. package/elysia/src/routes/static.d.ts +1 -1
  154. package/elysia/src/routes/themeCssRefresh.d.ts +1 -1
  155. package/elysia/src/types.d.ts +1 -1
  156. package/package.json +1 -1
  157. package/react/index.d.ts +1 -1
  158. package/react/index.js +12 -4
  159. package/react/index.js.map +4 -4
  160. package/react/src/components/ClientOnly.d.ts +1 -1
  161. package/react/src/components/ContentRoute.d.ts +1 -1
  162. package/react/src/components/Image.d.ts +1 -1
  163. package/react/src/components/LazyRoute.d.ts +1 -1
  164. package/react/src/components/Link.d.ts +1 -1
  165. package/react/src/components/Markdown.d.ts +1 -1
  166. package/react/src/components/Outlet.d.ts +1 -1
  167. package/react/src/components/index.d.ts +1 -1
  168. package/react/src/hooks/index.d.ts +1 -1
  169. package/react/src/hooks/useContent.d.ts +1 -1
  170. package/react/src/hooks/useData.d.ts +1 -1
  171. package/react/src/hooks/useFeed.d.ts +1 -1
  172. package/react/src/hooks/useLayoutData.d.ts +1 -1
  173. package/react/src/hooks/useLlms.d.ts +1 -1
  174. package/react/src/hooks/useNavigate.d.ts +1 -1
  175. package/react/src/hooks/useParams.d.ts +1 -1
  176. package/react/src/hooks/useRouter.d.ts +1 -1
  177. package/react/src/hooks/useSearch.d.ts +1 -1
  178. package/react/src/hooks/useSearchParams.d.ts +1 -1
  179. package/react/src/hooks/useToc.d.ts +1 -1
  180. package/react/src/i18n/LocaleProvider.d.ts +1 -1
  181. package/react/src/i18n/helpers.d.ts +1 -1
  182. package/react/src/i18n/index.d.ts +1 -1
  183. package/react/src/index.d.ts +1 -1
  184. package/react/src/lib/bundle.d.ts +1 -1
  185. package/react/src/lib/collection.d.ts +1 -1
  186. package/react/src/lib/content.d.ts +1 -1
  187. package/react/src/lib/head.d.ts +1 -1
  188. package/react/src/lib/index.d.ts +2 -1
  189. package/react/src/lib/index.d.ts.map +1 -1
  190. package/react/src/lib/layouts.d.ts +11 -1
  191. package/react/src/lib/layouts.d.ts.map +1 -1
  192. package/react/src/lib/lazy-route.d.ts +1 -1
  193. package/react/src/lib/route-loader.d.ts +1 -1
  194. package/react/src/lib/static-data.d.ts +1 -1
  195. package/react/src/providers/ContentProvider.d.ts +1 -1
  196. package/react/src/providers/RerouteProvider.d.ts +1 -1
  197. package/react/src/providers/RouterProvider.d.ts +1 -1
  198. package/react/src/providers/index.d.ts +1 -1
  199. package/react/src/types/any.d.ts +1 -1
  200. package/react/src/types/index.d.ts +1 -1
  201. package/react/src/types/router.d.ts +1 -1
  202. package/telemetry/react.d.ts +1 -1
  203. package/telemetry/react.js +2 -2
  204. package/telemetry/react.js.map +1 -1
  205. package/telemetry/server.d.ts +1 -1
  206. package/telemetry/server.js +13 -5
  207. package/telemetry/server.js.map +7 -7
  208. package/telemetry/src/react/api.d.ts +1 -1
  209. package/telemetry/src/react/context.d.ts +1 -1
  210. package/telemetry/src/react/index.d.ts +1 -1
  211. package/telemetry/src/react/telemetry.d.ts +1 -1
  212. package/telemetry/src/server/context.d.ts +1 -1
  213. package/telemetry/src/server/headers/extractor.d.ts +1 -1
  214. package/telemetry/src/server/headers/index.d.ts +1 -1
  215. package/telemetry/src/server/headers/presets.d.ts +1 -1
  216. package/telemetry/src/server/index.d.ts +1 -1
  217. package/telemetry/src/server/instrumentation.d.ts +1 -1
  218. package/telemetry/src/server/plugin.d.ts +1 -1
  219. package/telemetry/src/server/sourcemap.d.ts +1 -1
package/README.md CHANGED
@@ -130,6 +130,7 @@ Reroute is a feature-rich file-based routing framework for building fullstack Re
130
130
  - `<Link>` - Client-side navigation with automatic prefetching (localizes content hrefs)
131
131
  - `<Image>` - Optimized images with automatic format negotiation and lazy loading
132
132
  - `<Outlet>` - Render nested route components
133
+ - Route groups - `routes/(app)/[layout].tsx` wraps the routes in `(app)/` with one layout, no URL segment
133
134
  - `<ContentRoute>` - Dynamic content rendering with metadata injection
134
135
  - `<ClientOnly>` - Client-side only rendering with optional layout preservation (className/style props)
135
136
  - 🎭 **Providers**:
package/cli/bin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v1.0.0-alpha.33
2
+ * reroute-js v1.0.0-alpha.35
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2026 stewones <hi@stewan.io>
package/cli/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
3
  /**
4
- * reroute-js v1.0.0-alpha.33
4
+ * reroute-js v1.0.0-alpha.35
5
5
  *
6
6
  * @license MIT
7
7
  * @copyright 2026 stewones <hi@stewan.io>
@@ -68,7 +68,7 @@ async function getVersionString() {
68
68
  }
69
69
  async function getVersion() {
70
70
  if (true) {
71
- return "1.0.0-alpha.33";
71
+ return "1.0.0-alpha.35";
72
72
  }
73
73
  const possiblePaths = [
74
74
  path.join(import.meta.dir, "../../../../package.json"),
@@ -86,7 +86,7 @@ async function getVersion() {
86
86
  }
87
87
  async function getCommit() {
88
88
  if (true) {
89
- return "04f6516";
89
+ return "bb512b2";
90
90
  }
91
91
  return "dev";
92
92
  }
@@ -1908,10 +1908,17 @@ function layoutCovers(pattern, pathname) {
1908
1908
  return true;
1909
1909
  return pathname === base || pathname.startsWith(`${base}/`);
1910
1910
  }
1911
- function getMatchingLayouts(pathname, layouts) {
1911
+ function layoutWraps(layout, pathname, routePattern) {
1912
+ if (Array.isArray(layout?.routes)) {
1913
+ return routePattern !== undefined && layout.routes.includes(routePattern);
1914
+ }
1915
+ return layoutCovers(String(layout?.pattern || "/"), pathname);
1916
+ }
1917
+ function getMatchingLayouts(pathname, layouts, routes) {
1912
1918
  if (!Array.isArray(layouts))
1913
1919
  return [];
1914
- return layouts.filter((layout) => layoutCovers(String(layout?.pattern || "/"), pathname)).sort((a, b) => {
1920
+ const routePattern = Array.isArray(routes) ? matchRoutes(routes, pathname)?.route.pattern : undefined;
1921
+ return layouts.filter((layout) => layoutWraps(layout, pathname, routePattern)).sort((a, b) => {
1915
1922
  const aDepth = getPatternDepth(a?.pattern);
1916
1923
  const bDepth = getPatternDepth(b?.pattern);
1917
1924
  return aDepth - bDepth;
@@ -1926,6 +1933,7 @@ function createLayoutCacheKey(pattern, pathname) {
1926
1933
  function createLayoutDataKey(pattern) {
1927
1934
  return `__layout:${pattern}`;
1928
1935
  }
1936
+ var init_layouts = () => {};
1929
1937
 
1930
1938
  // packages/core/src/ssr/lib/compute/layouts.ts
1931
1939
  async function loadLayoutSSRExport(layout, clientDir, isWatchMode) {
@@ -2025,7 +2033,8 @@ async function computeLayoutData(pathname, clientDir, _cwd, isWatchMode, options
2025
2033
  const maxAgeMs = maxAge * 1000;
2026
2034
  try {
2027
2035
  const layouts = routesModule?.layouts;
2028
- const matchingLayouts = getMatchingLayouts(pathname, layouts);
2036
+ const routes = routesModule?.routes;
2037
+ const matchingLayouts = getMatchingLayouts(pathname, layouts, routes);
2029
2038
  for (const layout of matchingLayouts) {
2030
2039
  try {
2031
2040
  const layoutStatus = await processLayout(layout, pathname, clientDir, isWatchMode, streaming, maxAgeMs, searchParams, ssrData, pendingTasks, options.headers);
@@ -2052,9 +2061,10 @@ function mergeLayoutData(ssrData, pathname) {
2052
2061
  ssrData[pathname] = layoutData;
2053
2062
  }
2054
2063
  }
2055
- var init_layouts = __esm(() => {
2064
+ var init_layouts2 = __esm(() => {
2056
2065
  init_cache();
2057
2066
  init_imports();
2067
+ init_layouts();
2058
2068
  });
2059
2069
 
2060
2070
  // packages/core/src/ssr/lib/compute/routes.ts
@@ -2346,10 +2356,10 @@ function setGlobalSSRData(data) {
2346
2356
  var init_compute = __esm(() => {
2347
2357
  init_imports();
2348
2358
  init_content2();
2349
- init_layouts();
2359
+ init_layouts2();
2350
2360
  init_routes();
2351
2361
  init_content2();
2352
- init_layouts();
2362
+ init_layouts2();
2353
2363
  init_routes();
2354
2364
  });
2355
2365
 
@@ -2661,12 +2671,14 @@ async function loadLayoutData(pathname, clientDir, cwd, isWatchMode, searchParam
2661
2671
  const allData = {};
2662
2672
  try {
2663
2673
  let layouts = globalThis.__REROUTE_LAYOUTS__;
2674
+ let routes = globalThis.__REROUTE_ROUTES__;
2664
2675
  if (!layouts) {
2665
2676
  const routesPath = join2(cwd, ".reroute", "routes.ts");
2666
2677
  const m = await dynamicImport(routesPath, isWatchMode);
2667
2678
  layouts = m?.layouts;
2679
+ routes = m?.routes;
2668
2680
  }
2669
- const matchingLayouts = getMatchingLayouts(pathname, layouts);
2681
+ const matchingLayouts = getMatchingLayouts(pathname, layouts, routes);
2670
2682
  for (const layout of matchingLayouts) {
2671
2683
  const result = await processLayout2(layout, pathname, clientDir, isWatchMode, searchParams);
2672
2684
  if (result) {
@@ -2688,6 +2700,7 @@ function createLazyMarker(pathname, key) {
2688
2700
  var init_data = __esm(() => {
2689
2701
  init_content_path();
2690
2702
  init_imports();
2703
+ init_layouts();
2691
2704
  init_seed();
2692
2705
  });
2693
2706
 
@@ -3153,7 +3166,7 @@ ${ssrHead}`);
3153
3166
  async function extractLayoutMetadata(pathname, clientDir, cwd, isWatchMode, addHead, setLang, ogConfig, titleSuffix) {
3154
3167
  try {
3155
3168
  const m = await loadRoutesModule(cwd, isWatchMode);
3156
- const matchingLayouts = getMatchingLayouts(pathname, m?.layouts);
3169
+ const matchingLayouts = getMatchingLayouts(pathname, m?.layouts, m?.routes);
3157
3170
  for (const layout of matchingLayouts) {
3158
3171
  await processLayoutForMetadata(layout, clientDir, isWatchMode, addHead, setLang, ogConfig, titleSuffix);
3159
3172
  }
@@ -3472,10 +3485,11 @@ var init_metadata2 = __esm(() => {
3472
3485
  init_compute();
3473
3486
  init_content_path();
3474
3487
  init_imports();
3488
+ init_layouts();
3475
3489
  });
3476
3490
 
3477
3491
  // packages/core/src/ssr/lib/preload.ts
3478
- import { readdir as readdir6, stat as stat5 } from "node:fs/promises";
3492
+ import { readdir as readdir6, readFile, stat as stat5 } from "node:fs/promises";
3479
3493
  async function preloadContentModule(pathname, clientDir, cwd, isWatchMode) {
3480
3494
  let extraHead = "";
3481
3495
  let hydrationScript = "";
@@ -3578,15 +3592,37 @@ function resetSSRAccessTracking() {
3578
3592
  globalThis.__REROUTE_SSR_ACCESSED__ = {};
3579
3593
  } catch {}
3580
3594
  }
3581
- function createBundlePreload(bundleUrl) {
3595
+ async function bundleImports(cwd, bundleUrl) {
3596
+ const key = `${cwd}:${bundleUrl}`;
3597
+ if (bundleImportsCache?.key === key)
3598
+ return bundleImportsCache.hrefs;
3599
+ const slash = bundleUrl.lastIndexOf("/");
3600
+ const base = bundleUrl.slice(0, slash + 1);
3601
+ const entry = bundleUrl.slice(slash + 1);
3602
+ let hrefs = [];
3603
+ try {
3604
+ const raw = await readFile(bundlePreloadPath(join2(cwd, ".reroute", "bundles")), "utf8");
3605
+ const manifest = JSON.parse(raw);
3606
+ if (manifest.entry === entry && Array.isArray(manifest.imports)) {
3607
+ hrefs = manifest.imports.filter((file) => typeof file === "string").map((file) => `${base}${file}`);
3608
+ }
3609
+ } catch {}
3610
+ bundleImportsCache = { key, hrefs };
3611
+ return hrefs;
3612
+ }
3613
+ function createBundlePreload(bundleUrl, imports = []) {
3582
3614
  try {
3583
3615
  if (typeof bundleUrl === "string" && bundleUrl.endsWith(".js")) {
3584
- return `
3585
- <link rel="modulepreload" href="${bundleUrl}" />`;
3616
+ return [bundleUrl, ...imports].map((href) => `
3617
+ <link rel="modulepreload" href="${href}" />`).join("");
3586
3618
  }
3587
3619
  } catch {}
3588
3620
  return "";
3589
3621
  }
3622
+ function bundlePreloadPath(bundlesDir) {
3623
+ return join2(bundlesDir, "preload.json");
3624
+ }
3625
+ var bundleImportsCache = null;
3590
3626
  var init_preload = __esm(() => {
3591
3627
  init_imports();
3592
3628
  });
@@ -4057,7 +4093,7 @@ async function performSSRSetupInternal(options, streaming, timeoutState) {
4057
4093
  assertNotTimedOut();
4058
4094
  resetSSRAccessTracking();
4059
4095
  resetSSRContentResults();
4060
- const bundlePreload = createBundlePreload(bundleUrl);
4096
+ const bundlePreload = createBundlePreload(bundleUrl, await bundleImports(cwd, bundleUrl));
4061
4097
  const preloadResult = await withSpan("ssr.preload", async (span) => {
4062
4098
  span.setAttribute("pathname", pathname);
4063
4099
  const result = await preloadContentModule(pathname, clientDir, cwd, isWatchMode);
@@ -4196,6 +4232,7 @@ var init_lib = __esm(() => {
4196
4232
  init_compute();
4197
4233
  init_html();
4198
4234
  init_imports();
4235
+ init_layouts();
4199
4236
  init_metadata2();
4200
4237
  init_modules();
4201
4238
  init_preload();
@@ -7035,6 +7072,8 @@ __export(exports_core, {
7035
7072
  buildLlmsDiscovery: () => buildLlmsDiscovery,
7036
7073
  buildLocaleCookie: () => buildLocaleCookie,
7037
7074
  buildSitemapLoc: () => buildSitemapLoc,
7075
+ bundleImports: () => bundleImports,
7076
+ bundlePreloadPath: () => bundlePreloadPath,
7038
7077
  cleanupPathScopedSSRData: () => cleanupPathScopedSSRData,
7039
7078
  clearSSRModuleStores: () => clearSSRModuleStores,
7040
7079
  clearWatchImportCache: () => clearWatchImportCache,
@@ -7113,6 +7152,7 @@ __export(exports_core, {
7113
7152
  isThenable: () => isThenable,
7114
7153
  join: () => join2,
7115
7154
  layoutCovers: () => layoutCovers,
7155
+ layoutWraps: () => layoutWraps,
7116
7156
  listContentFiles: () => listContentFiles,
7117
7157
  llmsAlternateLinkTag: () => llmsAlternateLinkTag,
7118
7158
  loadCollections: () => loadCollections,
@@ -7187,6 +7227,27 @@ function getNamingConfig(options) {
7187
7227
  function shouldRebuildClientBundle(filename) {
7188
7228
  return filename.endsWith(".ts") || filename.endsWith(".tsx") || filename.endsWith(".md") || filename.endsWith(".mdx");
7189
7229
  }
7230
+ function entryStaticImports(metafile, entryFile) {
7231
+ if (typeof metafile !== "object" || metafile === null || !("outputs" in metafile) || typeof metafile.outputs !== "object" || metafile.outputs === null) {
7232
+ return [];
7233
+ }
7234
+ const outputs = new Map(Object.entries(metafile.outputs).map(([path3, output]) => [fileNameOf(path3), output]));
7235
+ const found = [];
7236
+ const queue = [entryFile];
7237
+ for (let file = queue.shift();file !== undefined; file = queue.shift()) {
7238
+ for (const item of outputs.get(file)?.imports ?? []) {
7239
+ if (item.kind !== "import-statement" || typeof item.path !== "string")
7240
+ continue;
7241
+ const chunk = fileNameOf(item.path);
7242
+ if (chunk === entryFile || found.includes(chunk))
7243
+ continue;
7244
+ found.push(chunk);
7245
+ queue.push(chunk);
7246
+ }
7247
+ }
7248
+ return found;
7249
+ }
7250
+ var fileNameOf = (path3) => path3.split(/[\\/]/).pop() ?? path3;
7190
7251
 
7191
7252
  // packages/cli/src/commands/lib/env.ts
7192
7253
  import { existsSync as existsSync2, readFileSync } from "node:fs";
@@ -8070,6 +8131,109 @@ function isProductionMode(args = []) {
8070
8131
  return hasProdFlag(args);
8071
8132
  }
8072
8133
 
8134
+ // packages/cli/src/commands/lib/routes.ts
8135
+ function isRouteGroup(segment) {
8136
+ return groupSegment.test(segment);
8137
+ }
8138
+ function withoutGroups(routePath) {
8139
+ return routePath.split("/").filter((segment) => segment !== "" && !isRouteGroup(segment)).join("/");
8140
+ }
8141
+ function dirOf(filePath) {
8142
+ return filePath.split("/").slice(0, -1).join("/");
8143
+ }
8144
+ function inGroup(dir) {
8145
+ return dir.split("/").some(isRouteGroup);
8146
+ }
8147
+ function fileToRoute(filePath) {
8148
+ const isLayout = filePath.endsWith("[layout].tsx") || filePath.endsWith("[layout].ts") || filePath.endsWith("[layout].md") || filePath.endsWith("[layout].mdx");
8149
+ const dir = dirOf(filePath);
8150
+ let routePath = filePath.replace(/\.(tsx|ts|md|mdx)$/, "");
8151
+ if (isLayout) {
8152
+ const pattern2 = routePath.replace(/\[layout\]$/, "").replace(/\/$/, "");
8153
+ const normalizedPattern2 = pattern2 === "" ? "/" : `/${pattern2}`;
8154
+ return {
8155
+ path: routePath,
8156
+ pattern: normalizedPattern2,
8157
+ filePath,
8158
+ isLayout,
8159
+ isDynamic: false,
8160
+ params: [],
8161
+ isNotFound: false,
8162
+ dir
8163
+ };
8164
+ }
8165
+ routePath = routePath.replace(/\/index$/, "").replace(/^index$/, "");
8166
+ const params = [];
8167
+ const pattern = withoutGroups(routePath).replace(/\[([^\]]+)\]/g, (_, param) => {
8168
+ params.push(param);
8169
+ return `:${param}`;
8170
+ });
8171
+ const normalizedPattern = pattern === "" ? "/" : `/${pattern}`;
8172
+ const isNotFound = /(^|\/)\[404\]$/.test(routePath);
8173
+ let notFoundBasePattern;
8174
+ if (isNotFound) {
8175
+ const base = withoutGroups(routePath.replace(/(^|\/)\[404\]$/, ""));
8176
+ notFoundBasePattern = base ? `/${base}` : "/";
8177
+ }
8178
+ return {
8179
+ path: routePath,
8180
+ pattern: normalizedPattern,
8181
+ filePath,
8182
+ isLayout: false,
8183
+ isDynamic: params.length > 0,
8184
+ params,
8185
+ isNotFound,
8186
+ notFoundBasePattern,
8187
+ dir
8188
+ };
8189
+ }
8190
+ function sortRoutes(routes) {
8191
+ return routes.sort((a, b) => compareRouteSpecificity(a, b));
8192
+ }
8193
+ function assertUniquePatterns(routes) {
8194
+ const seen = new Map;
8195
+ for (const route of routes) {
8196
+ const other = seen.get(route.pattern);
8197
+ if (other) {
8198
+ throw new Error(`Routes ${other} and ${route.filePath} both serve ${route.pattern}`);
8199
+ }
8200
+ seen.set(route.pattern, route.filePath);
8201
+ }
8202
+ }
8203
+ function routesUnder(dir, routes) {
8204
+ return routes.filter((route) => route.dir === dir || route.dir.startsWith(`${dir}/`)).map((route) => route.pattern);
8205
+ }
8206
+ function generateRouteTree(files) {
8207
+ const routes = [];
8208
+ const layouts2 = [];
8209
+ const notFoundRoutes = [];
8210
+ for (const file of files) {
8211
+ const route = fileToRoute(file);
8212
+ if (route.isLayout) {
8213
+ layouts2.push(route);
8214
+ } else if (route.isNotFound) {
8215
+ notFoundRoutes.push(route);
8216
+ } else {
8217
+ routes.push(route);
8218
+ }
8219
+ }
8220
+ assertUniquePatterns(routes);
8221
+ for (const layout of layouts2) {
8222
+ if (inGroup(layout.dir))
8223
+ layout.routes = routesUnder(layout.dir, routes);
8224
+ }
8225
+ return {
8226
+ routes: sortRoutes(routes),
8227
+ layouts: layouts2,
8228
+ notFoundRoutes
8229
+ };
8230
+ }
8231
+ var groupSegment;
8232
+ var init_routes2 = __esm(() => {
8233
+ init_core();
8234
+ groupSegment = /^\(.+\)$/;
8235
+ });
8236
+
8073
8237
  // packages/cli/src/commands/lib/streaming/analyzer.ts
8074
8238
  import { dirname as dirname4, join as join10 } from "node:path";
8075
8239
  function hasSSRDataExport(source) {
@@ -8309,7 +8473,7 @@ var init_theme = __esm(() => {
8309
8473
 
8310
8474
  // packages/cli/src/commands/lib/watch.ts
8311
8475
  import { createHash as createHash3 } from "node:crypto";
8312
- import { readFile } from "node:fs/promises";
8476
+ import { readFile as readFile2 } from "node:fs/promises";
8313
8477
  import { dirname as dirname7, isAbsolute as isAbsolute2, join as join13, resolve as resolve4, sep } from "node:path";
8314
8478
  function isWatchNoise(name) {
8315
8479
  return name.split(/[/\\]/).some((part) => part.startsWith(".")) || /\.bust-[^/\\]+$/.test(name);
@@ -8332,7 +8496,7 @@ function createContentFingerprint(options) {
8332
8496
  async changed(absPath) {
8333
8497
  const settling = Date.now() - startedAt < settleMs;
8334
8498
  try {
8335
- const buf = await readFile(absPath);
8499
+ const buf = await readFile2(absPath);
8336
8500
  gone.delete(absPath);
8337
8501
  const hash2 = createHash3("sha1").update(buf).digest("hex");
8338
8502
  const prev = hashes.get(absPath);
@@ -8606,69 +8770,6 @@ async function scanOgFiles(dir, base = "") {
8606
8770
  }
8607
8771
  return files;
8608
8772
  }
8609
- function fileToRoute(filePath) {
8610
- const isLayout = filePath.endsWith("[layout].tsx") || filePath.endsWith("[layout].ts") || filePath.endsWith("[layout].md") || filePath.endsWith("[layout].mdx");
8611
- let routePath = filePath.replace(/\.(tsx|ts|md|mdx)$/, "");
8612
- if (isLayout) {
8613
- const pattern2 = routePath.replace(/\[layout\]$/, "").replace(/\/$/, "");
8614
- const normalizedPattern2 = pattern2 === "" ? "/" : `/${pattern2}`;
8615
- return {
8616
- path: routePath,
8617
- pattern: normalizedPattern2,
8618
- filePath,
8619
- isLayout,
8620
- isDynamic: false,
8621
- params: [],
8622
- isNotFound: false
8623
- };
8624
- }
8625
- routePath = routePath.replace(/\/index$/, "").replace(/^index$/, "");
8626
- const params = [];
8627
- const pattern = routePath.replace(/\[([^\]]+)\]/g, (_, param) => {
8628
- params.push(param);
8629
- return `:${param}`;
8630
- });
8631
- const normalizedPattern = pattern === "" ? "/" : `/${pattern}`;
8632
- const isNotFound = /(^|\/)\[404\]$/.test(routePath);
8633
- let notFoundBasePattern;
8634
- if (isNotFound) {
8635
- const base = routePath.replace(/(^|\/)\[404\]$/, "").replace(/\/$/, "");
8636
- notFoundBasePattern = base ? `/${base}` : "/";
8637
- }
8638
- return {
8639
- path: routePath,
8640
- pattern: normalizedPattern,
8641
- filePath,
8642
- isLayout: false,
8643
- isDynamic: params.length > 0,
8644
- params,
8645
- isNotFound,
8646
- notFoundBasePattern
8647
- };
8648
- }
8649
- function sortRoutes(routes) {
8650
- return routes.sort((a, b) => compareRouteSpecificity(a, b));
8651
- }
8652
- function generateRouteTree(files) {
8653
- const routes = [];
8654
- const layouts2 = [];
8655
- const notFoundRoutes = [];
8656
- for (const file of files) {
8657
- const route = fileToRoute(file);
8658
- if (route.isLayout) {
8659
- layouts2.push(route);
8660
- } else if (route.isNotFound) {
8661
- notFoundRoutes.push(route);
8662
- } else {
8663
- routes.push(route);
8664
- }
8665
- }
8666
- return {
8667
- routes: sortRoutes(routes),
8668
- layouts: layouts2,
8669
- notFoundRoutes
8670
- };
8671
- }
8672
8773
  function getImportPath(filePath, streamingMap, routesImportBase) {
8673
8774
  const isMarkdown = /\.(md|mdx)$/.test(filePath);
8674
8775
  if (isMarkdown) {
@@ -8746,9 +8847,11 @@ const Layout${i}Meta = _meta(Layout${i}Module);`)
8746
8847
  }).join(`
8747
8848
  `);
8748
8849
  const layoutsArray = tree.layouts.map((l, i) => {
8850
+ const scope = l.routes ? `
8851
+ routes: ${JSON.stringify(l.routes)},` : "";
8749
8852
  return ` {
8750
8853
  pattern: "${l.pattern}",
8751
- path: "${l.path}",
8854
+ path: "${l.path}",${scope}
8752
8855
  component: Layout${i},
8753
8856
  ssr: Layout${i}SSR,
8754
8857
  meta: Layout${i}Meta,
@@ -9527,6 +9630,10 @@ async function buildEntrypointBundle(cwd, args = []) {
9527
9630
  }
9528
9631
  }
9529
9632
  }));
9633
+ await Bun.write(bundlePreloadPath(bundlesDir), JSON.stringify({
9634
+ entry: entryFile,
9635
+ imports: entryStaticImports("metafile" in result ? result.metafile : undefined, entryFile)
9636
+ }));
9530
9637
  if (shouldPreCompress && compressionCount > 0) {
9531
9638
  const compressionDuration = performance.now() - compressionStartTime;
9532
9639
  const timeStr = compressionDuration < 1000 ? `${compressionDuration.toFixed(0)}ms` : `${(compressionDuration / 1000).toFixed(2)}s`;
@@ -10266,6 +10373,7 @@ var init_gen = __esm(() => {
10266
10373
  init_env();
10267
10374
  init_images();
10268
10375
  init_markdown();
10376
+ init_routes2();
10269
10377
  init_analyzer();
10270
10378
  init_suspense();
10271
10379
  init_theme();
@@ -105638,7 +105746,7 @@ __export(exports_analyze, {
105638
105746
  default: () => analyze
105639
105747
  });
105640
105748
  import { existsSync as existsSync14, statSync } from "node:fs";
105641
- import { readdir as readdir9, readFile as readFile2, stat as stat6, writeFile as writeFile2 } from "node:fs/promises";
105749
+ import { readdir as readdir9, readFile as readFile3, stat as stat6, writeFile as writeFile2 } from "node:fs/promises";
105642
105750
  import { basename as basename4, join as join20, relative as relative4 } from "node:path";
105643
105751
  import Table from "cli-table3";
105644
105752
  async function findChunkBundles(cwd) {
@@ -105900,7 +106008,7 @@ async function buildDependencyTree(entryPath, cwd) {
105900
106008
  }
105901
106009
  return node.size;
105902
106010
  };
105903
- const content2 = await readFile2(entryPath, "utf-8");
106011
+ const content2 = await readFile3(entryPath, "utf-8");
105904
106012
  const modulePattern = /\/\/\s*(.+?\.(?:ts|tsx|js|jsx|mjs|cjs))\s*$/gm;
105905
106013
  const nodeModulesNode = {
105906
106014
  name: "node_modules",
@@ -105981,8 +106089,8 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
105981
106089
  if (!existsSync14(mapPath))
105982
106090
  return null;
105983
106091
  const [bundle, mapJson] = await Promise.all([
105984
- readFile2(bundlePath, "utf-8"),
105985
- readFile2(mapPath, "utf-8")
106092
+ readFile3(bundlePath, "utf-8"),
106093
+ readFile3(mapPath, "utf-8")
105986
106094
  ]);
105987
106095
  const map = JSON.parse(mapJson);
105988
106096
  const sourceRoot = map.sourceRoot || "";
@@ -106141,7 +106249,7 @@ async function generateHTMLReport(stats, depTree, mainInfo, browserDepTree, brow
106141
106249
  const stats2 = statSync(filePath);
106142
106250
  if (stats2.isFile() && !file.includes(".")) {
106143
106251
  actualServerBinarySize = stats2.size;
106144
- const content2 = await readFile2(filePath);
106252
+ const content2 = await readFile3(filePath);
106145
106253
  actualServerBinaryGzipped = Bun.gzipSync(content2).length;
106146
106254
  break;
106147
106255
  }
@@ -107627,7 +107735,7 @@ async function printConsoleReport(stats, depTree, mainInfo, browserDepTree, brow
107627
107735
  const stats2 = statSync(filePath);
107628
107736
  if (stats2.isFile() && !file.includes(".")) {
107629
107737
  actualServerBinarySize = stats2.size;
107630
- const content2 = await readFile2(filePath);
107738
+ const content2 = await readFile3(filePath);
107631
107739
  actualServerBinaryGzipped = Bun.gzipSync(content2).length;
107632
107740
  break;
107633
107741
  }
@@ -107705,7 +107813,7 @@ async function analyze(args) {
107705
107813
  }
107706
107814
  try {
107707
107815
  const browserStat = await stat6(browserEntry);
107708
- const browserContent = await readFile2(browserEntry);
107816
+ const browserContent = await readFile3(browserEntry);
107709
107817
  const browserGzipped = Bun.gzipSync(browserContent).length;
107710
107818
  browserInfo = {
107711
107819
  name: basename4(browserEntry),
@@ -107759,7 +107867,7 @@ async function analyze(args) {
107759
107867
  const packageJsonPath = join20(cwd, "package.json");
107760
107868
  if (existsSync14(packageJsonPath)) {
107761
107869
  try {
107762
- const packageJson = JSON.parse(await readFile2(packageJsonPath, "utf-8"));
107870
+ const packageJson = JSON.parse(await readFile3(packageJsonPath, "utf-8"));
107763
107871
  const runtimeDeps = packageJson.dependencies || {};
107764
107872
  const nodeModulesNode = depTree.root.children?.find((c) => c.name === "node_modules");
107765
107873
  if (nodeModulesNode) {
@@ -107787,7 +107895,7 @@ async function analyze(args) {
107787
107895
  }
107788
107896
  try {
107789
107897
  const entryStat = await stat6(entry);
107790
- const entryContent = await readFile2(entry);
107898
+ const entryContent = await readFile3(entry);
107791
107899
  const entryGzipped = Bun.gzipSync(entryContent).length;
107792
107900
  mainInfo = {
107793
107901
  name: basename4(entry),
@@ -108620,7 +108728,7 @@ async function getVersionString2() {
108620
108728
  }
108621
108729
  async function getVersion2() {
108622
108730
  if (true) {
108623
- return "1.0.0-alpha.33";
108731
+ return "1.0.0-alpha.35";
108624
108732
  }
108625
108733
  const possiblePaths = [
108626
108734
  path3.join(import.meta.dir, "../../../package.json"),
@@ -108637,10 +108745,10 @@ async function getVersion2() {
108637
108745
  }
108638
108746
  async function getCommit2() {
108639
108747
  if (true) {
108640
- return "04f6516";
108748
+ return "bb512b2";
108641
108749
  }
108642
108750
  return "dev";
108643
108751
  }
108644
108752
  main();
108645
108753
 
108646
- //# debugId=24B3FF39BB270EF564756E2164756E21
108754
+ //# debugId=85223BABEE11283064756E2164756E21