reroute-js 1.0.0-alpha.21 → 1.0.0-alpha.23

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 (215) hide show
  1. package/README.md +1 -0
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +651 -248
  4. package/cli/bin.js.map +13 -10
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +14 -7
  7. package/cli/index.js.map +5 -5
  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/build.d.ts.map +1 -1
  12. package/cli/src/commands/dev.d.ts +1 -1
  13. package/cli/src/commands/dev.d.ts.map +1 -1
  14. package/cli/src/commands/gen.d.ts +1 -1
  15. package/cli/src/commands/gen.d.ts.map +1 -1
  16. package/cli/src/commands/index.d.ts +1 -1
  17. package/cli/src/commands/init.d.ts +1 -1
  18. package/cli/src/commands/lib/assets.d.ts +1 -1
  19. package/cli/src/commands/lib/bundler.d.ts +1 -1
  20. package/cli/src/commands/lib/command.d.ts +1 -1
  21. package/cli/src/commands/lib/env.d.ts +1 -1
  22. package/cli/src/commands/lib/images.d.ts +12 -0
  23. package/cli/src/commands/lib/images.d.ts.map +1 -0
  24. package/cli/src/commands/lib/index.d.ts +1 -1
  25. package/cli/src/commands/lib/log.d.ts +1 -1
  26. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  27. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  28. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  29. package/cli/src/commands/lib/production.d.ts +3 -3
  30. package/cli/src/commands/lib/production.d.ts.map +1 -1
  31. package/cli/src/commands/lib/server.d.ts +1 -1
  32. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  33. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  34. package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
  35. package/cli/src/commands/lib/theme.d.ts +1 -1
  36. package/cli/src/commands/lib/version.d.ts +1 -1
  37. package/cli/src/commands/lib/watch.d.ts +1 -1
  38. package/cli/src/commands/og.d.ts +1 -1
  39. package/cli/src/commands/start.d.ts +1 -1
  40. package/cli/src/index.d.ts +1 -1
  41. package/core/index.d.ts +1 -1
  42. package/core/index.js +61 -2
  43. package/core/index.js.map +6 -5
  44. package/core/src/app-paths.d.ts +1 -1
  45. package/core/src/bundler/hash.d.ts +1 -1
  46. package/core/src/bundler/index.d.ts +1 -1
  47. package/core/src/config.d.ts +41 -2
  48. package/core/src/config.d.ts.map +1 -1
  49. package/core/src/content/discovery.d.ts +1 -1
  50. package/core/src/content/index.d.ts +1 -1
  51. package/core/src/content/metadata.d.ts +1 -1
  52. package/core/src/i18n/catalog.d.ts +1 -1
  53. package/core/src/i18n/discover.d.ts +1 -1
  54. package/core/src/i18n/index.d.ts +1 -1
  55. package/core/src/i18n/messages.d.ts +1 -1
  56. package/core/src/i18n/negotiate.d.ts +1 -1
  57. package/core/src/i18n/pathname.d.ts +1 -1
  58. package/core/src/i18n/resolve.d.ts +1 -1
  59. package/core/src/i18n/types.d.ts +1 -1
  60. package/core/src/image.d.ts +29 -0
  61. package/core/src/image.d.ts.map +1 -0
  62. package/core/src/index.d.ts +2 -1
  63. package/core/src/index.d.ts.map +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/routes.d.ts +1 -1
  94. package/core/src/ssr/lib/content-path.d.ts +1 -1
  95. package/core/src/ssr/lib/data.d.ts +1 -1
  96. package/core/src/ssr/lib/html.d.ts +1 -1
  97. package/core/src/ssr/lib/imports.d.ts +1 -1
  98. package/core/src/ssr/lib/index.d.ts +1 -1
  99. package/core/src/ssr/lib/layouts.d.ts +1 -1
  100. package/core/src/ssr/lib/metadata.d.ts +1 -1
  101. package/core/src/ssr/lib/mime.d.ts +1 -1
  102. package/core/src/ssr/lib/modules.d.ts +1 -1
  103. package/core/src/ssr/lib/path.d.ts +1 -1
  104. package/core/src/ssr/lib/preload.d.ts +1 -1
  105. package/core/src/ssr/lib/route-match.d.ts +1 -1
  106. package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
  107. package/core/src/ssr/lib/scripts/data.d.ts +1 -1
  108. package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
  109. package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
  110. package/core/src/ssr/lib/scripts/index.d.ts +1 -1
  111. package/core/src/ssr/lib/seed.d.ts +1 -1
  112. package/core/src/ssr/lib/serialize.d.ts +1 -1
  113. package/core/src/ssr/lib/setup.d.ts +1 -1
  114. package/core/src/ssr/lib/styles.d.ts +1 -1
  115. package/core/src/ssr/lib/template.d.ts +1 -1
  116. package/core/src/ssr/lib/types.d.ts +1 -1
  117. package/core/src/ssr/render.d.ts +1 -1
  118. package/core/src/ssr/stream.d.ts +1 -1
  119. package/elysia/index.d.ts +1 -1
  120. package/elysia/index.js +295 -135
  121. package/elysia/index.js.map +7 -6
  122. package/elysia/src/index.d.ts +2 -1
  123. package/elysia/src/index.d.ts.map +1 -1
  124. package/elysia/src/libs/assets.d.ts +1 -1
  125. package/elysia/src/libs/cache.d.ts +1 -1
  126. package/elysia/src/libs/caching.d.ts +1 -1
  127. package/elysia/src/libs/http.d.ts +1 -1
  128. package/elysia/src/libs/i18n.d.ts +1 -1
  129. package/elysia/src/libs/image.d.ts +30 -1
  130. package/elysia/src/libs/image.d.ts.map +1 -1
  131. package/elysia/src/libs/index.d.ts +2 -2
  132. package/elysia/src/libs/index.d.ts.map +1 -1
  133. package/elysia/src/libs/llms.d.ts +1 -1
  134. package/elysia/src/libs/response.d.ts +1 -1
  135. package/elysia/src/libs/serving.d.ts +1 -1
  136. package/elysia/src/plugin.d.ts +1 -1
  137. package/elysia/src/routes/artifacts.d.ts +1 -1
  138. package/elysia/src/routes/content.d.ts +1 -1
  139. package/elysia/src/routes/image.d.ts +1 -1
  140. package/elysia/src/routes/index.d.ts +1 -1
  141. package/elysia/src/routes/internal.d.ts +1 -1
  142. package/elysia/src/routes/liveReloadClient.d.ts +1 -1
  143. package/elysia/src/routes/llms.d.ts +1 -1
  144. package/elysia/src/routes/og.d.ts +1 -1
  145. package/elysia/src/routes/redirects.d.ts +1 -1
  146. package/elysia/src/routes/robots.d.ts +1 -1
  147. package/elysia/src/routes/rss.d.ts +1 -1
  148. package/elysia/src/routes/search.d.ts +1 -1
  149. package/elysia/src/routes/sitemap.d.ts +1 -1
  150. package/elysia/src/routes/ssr.d.ts +1 -1
  151. package/elysia/src/routes/static.d.ts +1 -1
  152. package/elysia/src/routes/themeCssRefresh.d.ts +1 -1
  153. package/elysia/src/types.d.ts +1 -1
  154. package/package.json +1 -1
  155. package/react/index.d.ts +1 -1
  156. package/react/index.js +54 -17
  157. package/react/index.js.map +4 -4
  158. package/react/src/components/ClientOnly.d.ts +1 -1
  159. package/react/src/components/ContentRoute.d.ts +1 -1
  160. package/react/src/components/Image.d.ts +5 -1
  161. package/react/src/components/Image.d.ts.map +1 -1
  162. package/react/src/components/LazyRoute.d.ts +1 -1
  163. package/react/src/components/Link.d.ts +1 -1
  164. package/react/src/components/Markdown.d.ts +1 -1
  165. package/react/src/components/Outlet.d.ts +1 -1
  166. package/react/src/components/index.d.ts +1 -1
  167. package/react/src/hooks/index.d.ts +1 -1
  168. package/react/src/hooks/useContent.d.ts +1 -1
  169. package/react/src/hooks/useData.d.ts +1 -1
  170. package/react/src/hooks/useFeed.d.ts +1 -1
  171. package/react/src/hooks/useLayoutData.d.ts +1 -1
  172. package/react/src/hooks/useLlms.d.ts +1 -1
  173. package/react/src/hooks/useNavigate.d.ts +1 -1
  174. package/react/src/hooks/useParams.d.ts +1 -1
  175. package/react/src/hooks/useRouter.d.ts +1 -1
  176. package/react/src/hooks/useSearch.d.ts +1 -1
  177. package/react/src/hooks/useSearchParams.d.ts +1 -1
  178. package/react/src/hooks/useToc.d.ts +1 -1
  179. package/react/src/i18n/LocaleProvider.d.ts +1 -1
  180. package/react/src/i18n/helpers.d.ts +1 -1
  181. package/react/src/i18n/index.d.ts +1 -1
  182. package/react/src/index.d.ts +1 -1
  183. package/react/src/lib/bundle.d.ts +1 -1
  184. package/react/src/lib/collection.d.ts +1 -1
  185. package/react/src/lib/content.d.ts +1 -1
  186. package/react/src/lib/head.d.ts +1 -1
  187. package/react/src/lib/index.d.ts +1 -1
  188. package/react/src/lib/lazy-route.d.ts +9 -2
  189. package/react/src/lib/lazy-route.d.ts.map +1 -1
  190. package/react/src/lib/route-loader.d.ts +1 -1
  191. package/react/src/providers/ContentProvider.d.ts +1 -1
  192. package/react/src/providers/RerouteProvider.d.ts +1 -1
  193. package/react/src/providers/RouterProvider.d.ts +1 -1
  194. package/react/src/providers/index.d.ts +1 -1
  195. package/react/src/types/any.d.ts +1 -1
  196. package/react/src/types/index.d.ts +1 -1
  197. package/react/src/types/router.d.ts +1 -1
  198. package/telemetry/react.d.ts +1 -1
  199. package/telemetry/react.js +2 -2
  200. package/telemetry/react.js.map +1 -1
  201. package/telemetry/server.d.ts +1 -1
  202. package/telemetry/server.js +6 -2
  203. package/telemetry/server.js.map +4 -4
  204. package/telemetry/src/react/api.d.ts +1 -1
  205. package/telemetry/src/react/context.d.ts +1 -1
  206. package/telemetry/src/react/index.d.ts +1 -1
  207. package/telemetry/src/react/telemetry.d.ts +1 -1
  208. package/telemetry/src/server/context.d.ts +1 -1
  209. package/telemetry/src/server/headers/extractor.d.ts +1 -1
  210. package/telemetry/src/server/headers/index.d.ts +1 -1
  211. package/telemetry/src/server/headers/presets.d.ts +1 -1
  212. package/telemetry/src/server/index.d.ts +1 -1
  213. package/telemetry/src/server/instrumentation.d.ts +1 -1
  214. package/telemetry/src/server/plugin.d.ts +1 -1
  215. package/telemetry/src/server/sourcemap.d.ts +1 -1
package/elysia/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v1.0.0-alpha.21
2
+ * reroute-js v1.0.0-alpha.23
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2026 stewones <hi@stewan.io>
@@ -89,7 +89,7 @@ async function loadConfig(cwd) {
89
89
  var init_config = () => {};
90
90
 
91
91
  // packages/core/src/ssr/lib/path.ts
92
- function join(...parts) {
92
+ function join2(...parts) {
93
93
  return parts.join("/").replace(/\/+/g, "/");
94
94
  }
95
95
  function extname(p) {
@@ -114,8 +114,8 @@ async function listContentFiles(dir, baseRel) {
114
114
  try {
115
115
  const entries = await readdir(dir, { withFileTypes: true });
116
116
  for (const entry of entries) {
117
- const full = join(dir, entry.name);
118
- const rel = join(baseRel, entry.name);
117
+ const full = join2(dir, entry.name);
118
+ const rel = join2(baseRel, entry.name);
119
119
  if (entry.isDirectory()) {
120
120
  const nested = await listContentFiles(full, rel);
121
121
  out.push(...nested);
@@ -130,7 +130,7 @@ async function listContentFiles(dir, baseRel) {
130
130
  }
131
131
  async function discoverCollections(clientDir) {
132
132
  const collections = new Set;
133
- const bundledCollectionsDir = join(clientDir, "collections");
133
+ const bundledCollectionsDir = join2(clientDir, "collections");
134
134
  try {
135
135
  const bundledEntries = await readdir(bundledCollectionsDir, {
136
136
  withFileTypes: true
@@ -145,12 +145,12 @@ async function discoverCollections(clientDir) {
145
145
  return Array.from(collections);
146
146
  }
147
147
  } catch {}
148
- const root = join(clientDir, "routes");
148
+ const root = join2(clientDir, "routes");
149
149
  try {
150
150
  const entries = await readdir(root, { withFileTypes: true });
151
151
  for (const entry of entries) {
152
152
  if (entry.isDirectory()) {
153
- const contentDir = join(root, entry.name, "content");
153
+ const contentDir = join2(root, entry.name, "content");
154
154
  try {
155
155
  await stat(contentDir);
156
156
  collections.add(entry.name);
@@ -245,7 +245,7 @@ var init_catalog = () => {};
245
245
 
246
246
  // packages/core/src/i18n/discover.ts
247
247
  import { readdir as readdir2 } from "node:fs/promises";
248
- import { join as join2 } from "node:path";
248
+ import { join as join3 } from "node:path";
249
249
  async function loadCatalog(filePath) {
250
250
  try {
251
251
  const text = await Bun.file(filePath).text();
@@ -264,7 +264,7 @@ async function loadLocaleCatalogs(absDir) {
264
264
  const locale = entry.name.slice(0, -".json".length);
265
265
  if (!locale)
266
266
  continue;
267
- const catalog = await loadCatalog(join2(absDir, entry.name));
267
+ const catalog = await loadCatalog(join3(absDir, entry.name));
268
268
  if (!catalog)
269
269
  continue;
270
270
  catalogs[locale] = catalog;
@@ -286,7 +286,7 @@ async function discoverI18n(cwd, options = {}) {
286
286
  const defaultLocale = options.defaultLocale ?? DEFAULT_LOCALE;
287
287
  const cookie = options.cookie ?? DEFAULT_COOKIE;
288
288
  const redirectContentOnNegotiate = options.redirectContentOnNegotiate ?? true;
289
- const absDir = join2(cwd, localesDir);
289
+ const absDir = join3(cwd, localesDir);
290
290
  const disabled = {
291
291
  enabled: false,
292
292
  defaultLocale,
@@ -624,6 +624,58 @@ var init_i18n = __esm(() => {
624
624
  init_resolve();
625
625
  });
626
626
 
627
+ // packages/core/src/image.ts
628
+ function uniquePositiveWidths(widths) {
629
+ return [...new Set(widths.filter((width) => width > 0))].sort((a, b) => a - b);
630
+ }
631
+ function resolveImagePreprocess(image) {
632
+ const preprocess = image?.preprocess;
633
+ if (!preprocess) {
634
+ return {
635
+ enabled: false,
636
+ widths: [...DEFAULT_IMAGE_DEVICE_SIZES],
637
+ formats: [...DEFAULT_PREPROCESS_FORMATS],
638
+ quality: DEFAULT_IMAGE_QUALITY,
639
+ qualities: [DEFAULT_IMAGE_QUALITY]
640
+ };
641
+ }
642
+ const options = preprocess === true ? {} : preprocess;
643
+ const quality = options.quality ?? DEFAULT_IMAGE_QUALITY;
644
+ return {
645
+ enabled: true,
646
+ widths: uniquePositiveWidths([
647
+ options.mobile ?? DEFAULT_PREPROCESS_SIZES.mobile,
648
+ options.tablet ?? DEFAULT_PREPROCESS_SIZES.tablet,
649
+ options.desktop ?? DEFAULT_PREPROCESS_SIZES.desktop
650
+ ]),
651
+ formats: options.formats?.length ? options.formats : [...DEFAULT_PREPROCESS_FORMATS],
652
+ quality,
653
+ qualities: uniquePositiveWidths(options.qualities ?? [quality])
654
+ };
655
+ }
656
+ function resolveImageDeviceSizes(image) {
657
+ return resolveImagePreprocess(image).widths;
658
+ }
659
+ var DEFAULT_IMAGE_DEVICE_SIZES, DEFAULT_PREPROCESS_SIZES, DEFAULT_PREPROCESS_FORMATS, DEFAULT_IMAGE_QUALITY = 75;
660
+ var init_image = __esm(() => {
661
+ DEFAULT_IMAGE_DEVICE_SIZES = [
662
+ 640,
663
+ 750,
664
+ 828,
665
+ 1080,
666
+ 1200,
667
+ 1920,
668
+ 2048,
669
+ 3840
670
+ ];
671
+ DEFAULT_PREPROCESS_SIZES = {
672
+ mobile: 640,
673
+ tablet: 1024,
674
+ desktop: 1920
675
+ };
676
+ DEFAULT_PREPROCESS_FORMATS = ["webp", "avif"];
677
+ });
678
+
627
679
  // packages/telemetry/src/server/context.ts
628
680
  import { AsyncLocalStorage } from "node:async_hooks";
629
681
  var contextStorage;
@@ -1116,7 +1168,7 @@ function cleanupPathScopedSSRData(pathname) {
1116
1168
 
1117
1169
  // packages/core/src/ssr/lib/imports.ts
1118
1170
  import { copyFile, realpath, stat as stat3, unlink } from "node:fs/promises";
1119
- import { basename as basename2, dirname, extname as extname2, join as join3 } from "node:path";
1171
+ import { basename as basename2, dirname, extname as extname2, join as join4 } from "node:path";
1120
1172
  import { pathToFileURL as pathToFileURL3 } from "node:url";
1121
1173
  function clearWatchImportCache() {
1122
1174
  watchImportCache.clear();
@@ -1126,7 +1178,7 @@ function bustCopyPath(absolutePath) {
1126
1178
  const ext = extname2(absolutePath);
1127
1179
  const base = basename2(absolutePath, ext);
1128
1180
  const token = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
1129
- return join3(dir, `${base}.bust-${token}${ext}`);
1181
+ return join4(dir, `${base}.bust-${token}${ext}`);
1130
1182
  }
1131
1183
  async function dynamicImport(absolutePath, isWatchMode) {
1132
1184
  const href = pathToFileURL3(absolutePath).href;
@@ -1163,7 +1215,7 @@ var init_imports = __esm(() => {
1163
1215
  // packages/core/src/ssr/lib/collections.ts
1164
1216
  async function loadCollections(cwd, isWatchMode) {
1165
1217
  try {
1166
- const p = join(cwd, ".reroute", "content.ts");
1218
+ const p = join2(cwd, ".reroute", "content.ts");
1167
1219
  const mod = await dynamicImport(p, isWatchMode);
1168
1220
  return mod?.byCollection || {};
1169
1221
  } catch {
@@ -1540,7 +1592,7 @@ function createLayoutDataKey(pattern) {
1540
1592
  async function loadLayoutSSRExport(layout, clientDir, isWatchMode) {
1541
1593
  let ssrExport = layout?.ssr;
1542
1594
  if (!ssrExport) {
1543
- const abs = join(clientDir, "routes", String(layout.path));
1595
+ const abs = join2(clientDir, "routes", String(layout.path));
1544
1596
  const mod = await dynamicImport(abs, isWatchMode);
1545
1597
  ssrExport = mod?.ssr;
1546
1598
  }
@@ -1681,11 +1733,11 @@ async function loadRouteSSRExport(route, clientDir, isWatchMode) {
1681
1733
  let ssrExport = route?.ssr;
1682
1734
  if (!ssrExport) {
1683
1735
  const routePath = String(route.path);
1684
- const cwd = join(clientDir, "..");
1685
- let abs = join(cwd, ".reroute", "streaming", routePath);
1736
+ const cwd = join2(clientDir, "..");
1737
+ let abs = join2(cwd, ".reroute", "streaming", routePath);
1686
1738
  let mod = await dynamicImport(abs, isWatchMode).catch(() => null);
1687
1739
  if (!mod) {
1688
- abs = join(clientDir, "routes", routePath);
1740
+ abs = join2(clientDir, "routes", routePath);
1689
1741
  mod = await dynamicImport(abs, isWatchMode);
1690
1742
  }
1691
1743
  ssrExport = mod?.ssr;
@@ -1891,7 +1943,7 @@ async function loadRoutesModule(cwd, isWatchMode) {
1891
1943
  if (bundledRoutes && bundledLayouts) {
1892
1944
  return createBundledRoutesModule(bundledRoutes, bundledLayouts);
1893
1945
  }
1894
- const routesPath = join(cwd, ".reroute", "routes.ts");
1946
+ const routesPath = join2(cwd, ".reroute", "routes.ts");
1895
1947
  return await dynamicImport(routesPath, isWatchMode);
1896
1948
  } catch {
1897
1949
  return null;
@@ -1984,7 +2036,7 @@ async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode)
1984
2036
  }
1985
2037
  async function tryRegistryImport(collection, name, cwd, isWatchMode, locale) {
1986
2038
  try {
1987
- const registryPath = join(cwd, ".reroute", "content.ts");
2039
+ const registryPath = join2(cwd, ".reroute", "content.ts");
1988
2040
  const reg = await dynamicImport(registryPath, isWatchMode);
1989
2041
  const get = reg?.getContentEntry;
1990
2042
  const entry = typeof get === "function" ? get(collection, name, locale) : undefined;
@@ -1995,9 +2047,9 @@ async function tryRegistryImport(collection, name, cwd, isWatchMode, locale) {
1995
2047
  const normalized = raw.replace(/^\/+/, "");
1996
2048
  const candidates = [];
1997
2049
  if (normalized) {
1998
- candidates.push(join(cwd, normalized));
2050
+ candidates.push(join2(cwd, normalized));
1999
2051
  if (!normalized.startsWith(".reroute/")) {
2000
- candidates.push(join(cwd, ".reroute", normalized));
2052
+ candidates.push(join2(cwd, ".reroute", normalized));
2001
2053
  }
2002
2054
  }
2003
2055
  for (const abs of candidates) {
@@ -2012,7 +2064,7 @@ async function tryRegistryImport(collection, name, cwd, isWatchMode, locale) {
2012
2064
  }
2013
2065
  async function tryChunkImport(collection, name, cwd, isWatchMode) {
2014
2066
  try {
2015
- const chunkDir = join(cwd, ".reroute", "chunks", collection);
2067
+ const chunkDir = join2(cwd, ".reroute", "chunks", collection);
2016
2068
  const files = await readdir3(chunkDir);
2017
2069
  const matches = files.filter((n) => n.startsWith(`${name}.`) && n.endsWith(".js"));
2018
2070
  if (!matches.length)
@@ -2021,14 +2073,14 @@ async function tryChunkImport(collection, name, cwd, isWatchMode) {
2021
2073
  let latestM = 0;
2022
2074
  for (const f of matches) {
2023
2075
  try {
2024
- const s = await stat4(join(chunkDir, f));
2076
+ const s = await stat4(join2(chunkDir, f));
2025
2077
  if (s.mtimeMs >= latestM) {
2026
2078
  latestM = s.mtimeMs;
2027
2079
  latest = f;
2028
2080
  }
2029
2081
  } catch {}
2030
2082
  }
2031
- const absChunk = join(chunkDir, latest);
2083
+ const absChunk = join2(chunkDir, latest);
2032
2084
  return await dynamicImport(absChunk, isWatchMode);
2033
2085
  } catch {}
2034
2086
  return null;
@@ -2037,9 +2089,9 @@ async function trySourceImport(collection, name, clientDir, isWatchMode, locale)
2037
2089
  try {
2038
2090
  const candidates = [];
2039
2091
  if (locale) {
2040
- candidates.push(join(clientDir, "routes", collection, "content", locale, `${name}.tsx`), join(clientDir, "routes", collection, "content", locale, `${name}.ts`));
2092
+ candidates.push(join2(clientDir, "routes", collection, "content", locale, `${name}.tsx`), join2(clientDir, "routes", collection, "content", locale, `${name}.ts`));
2041
2093
  }
2042
- candidates.push(join(clientDir, "routes", collection, "content", `${name}.tsx`), join(clientDir, "routes", collection, "content", `${name}.ts`));
2094
+ candidates.push(join2(clientDir, "routes", collection, "content", `${name}.tsx`), join2(clientDir, "routes", collection, "content", `${name}.ts`));
2043
2095
  for (const absSrc of candidates) {
2044
2096
  if (await Bun.file(absSrc).exists()) {
2045
2097
  return await dynamicImport(absSrc, isWatchMode);
@@ -2149,7 +2201,7 @@ async function loadRouteDataInternal(pathname, clientDir, cwd, isWatchMode, sear
2149
2201
  let routes = globalThis.__REROUTE_ROUTES__;
2150
2202
  let matchRouteFn;
2151
2203
  if (!routes) {
2152
- const routesPath = join(cwd, ".reroute", "routes.ts");
2204
+ const routesPath = join2(cwd, ".reroute", "routes.ts");
2153
2205
  const m = await dynamicImport(routesPath, isWatchMode);
2154
2206
  routes = m?.routes;
2155
2207
  matchRouteFn = m?.matchRoute;
@@ -2164,10 +2216,10 @@ async function loadRouteDataInternal(pathname, clientDir, cwd, isWatchMode, sear
2164
2216
  let ssrExport = r?.ssr;
2165
2217
  if (!ssrExport) {
2166
2218
  const routePath = String(r.path);
2167
- let abs = join(cwd, ".reroute", "streaming", routePath);
2219
+ let abs = join2(cwd, ".reroute", "streaming", routePath);
2168
2220
  let mod = await dynamicImport(abs, isWatchMode).catch(() => null);
2169
2221
  if (!mod) {
2170
- abs = join(clientDir, "routes", routePath);
2222
+ abs = join2(clientDir, "routes", routePath);
2171
2223
  mod = await dynamicImport(abs, isWatchMode);
2172
2224
  }
2173
2225
  ssrExport = mod?.ssr;
@@ -2246,7 +2298,7 @@ async function processLayout2(layout, pathname, clientDir, isWatchMode, searchPa
2246
2298
  try {
2247
2299
  let ssrExport = layout?.ssr;
2248
2300
  if (!ssrExport) {
2249
- const abs = join(clientDir, "routes", String(layout.path));
2301
+ const abs = join2(clientDir, "routes", String(layout.path));
2250
2302
  const mod = await dynamicImport(abs, isWatchMode);
2251
2303
  ssrExport = mod?.ssr;
2252
2304
  }
@@ -2271,7 +2323,7 @@ async function loadLayoutData(pathname, clientDir, cwd, isWatchMode, searchParam
2271
2323
  try {
2272
2324
  let layouts = globalThis.__REROUTE_LAYOUTS__;
2273
2325
  if (!layouts) {
2274
- const routesPath = join(cwd, ".reroute", "routes.ts");
2326
+ const routesPath = join2(cwd, ".reroute", "routes.ts");
2275
2327
  const m = await dynamicImport(routesPath, isWatchMode);
2276
2328
  layouts = m?.layouts;
2277
2329
  }
@@ -2306,7 +2358,7 @@ async function loadIndexHtml(clientDir) {
2306
2358
  if (bundledTemplate) {
2307
2359
  return bundledTemplate;
2308
2360
  }
2309
- const templatePath = join(clientDir, "index.html");
2361
+ const templatePath = join2(clientDir, "index.html");
2310
2362
  try {
2311
2363
  const content = await Bun.file(templatePath).text();
2312
2364
  return content;
@@ -2518,10 +2570,10 @@ async function listDynamicRouteDirectories(baseDir) {
2518
2570
  }
2519
2571
  async function collectOGCandidatePaths(currentDir, parts, depth, pathsToTry, allowPartialFallback) {
2520
2572
  if (depth === parts.length) {
2521
- pathsToTry.push(join(currentDir, "[og].tsx"));
2573
+ pathsToTry.push(join2(currentDir, "[og].tsx"));
2522
2574
  return;
2523
2575
  }
2524
- const literalDir = join(currentDir, parts[depth]);
2576
+ const literalDir = join2(currentDir, parts[depth]);
2525
2577
  try {
2526
2578
  await readdir4(literalDir);
2527
2579
  await collectOGCandidatePaths(literalDir, parts, depth + 1, pathsToTry, true);
@@ -2529,18 +2581,18 @@ async function collectOGCandidatePaths(currentDir, parts, depth, pathsToTry, all
2529
2581
  const dynamicDirs = await listDynamicRouteDirectories(currentDir);
2530
2582
  for (const dynamicDir of dynamicDirs) {
2531
2583
  if (isCatchAllRouteDirectory(dynamicDir)) {
2532
- pathsToTry.push(join(currentDir, dynamicDir, "[og].tsx"));
2584
+ pathsToTry.push(join2(currentDir, dynamicDir, "[og].tsx"));
2533
2585
  continue;
2534
2586
  }
2535
- await collectOGCandidatePaths(join(currentDir, dynamicDir), parts, depth + 1, pathsToTry, false);
2587
+ await collectOGCandidatePaths(join2(currentDir, dynamicDir), parts, depth + 1, pathsToTry, false);
2536
2588
  }
2537
2589
  if (allowPartialFallback) {
2538
- pathsToTry.push(join(currentDir, "[og].tsx"));
2590
+ pathsToTry.push(join2(currentDir, "[og].tsx"));
2539
2591
  }
2540
2592
  }
2541
2593
  async function findOGImageForPath(pathname, clientDir) {
2542
2594
  const parts = pathname.split("/").filter(Boolean).filter((p) => !p.startsWith("__reroute"));
2543
- const routesDir = join(clientDir, "routes");
2595
+ const routesDir = join2(clientDir, "routes");
2544
2596
  const pathsToTry = [];
2545
2597
  await collectOGCandidatePaths(routesDir, parts, 0, pathsToTry, true);
2546
2598
  const uniquePaths = [...new Set(pathsToTry)];
@@ -2566,7 +2618,7 @@ async function loadOGImageComponent(ogPath, isWatchMode) {
2566
2618
  function extractParamsFromPath(pathname, ogPath, clientDir) {
2567
2619
  const params = {};
2568
2620
  const ogDir = ogPath.replace(/\/\[og\]\.tsx$/, "");
2569
- const routesDir = join(clientDir, "routes");
2621
+ const routesDir = join2(clientDir, "routes");
2570
2622
  const relativePath = ogDir.replace(routesDir, "").split("/").filter(Boolean);
2571
2623
  const pathnameParts = pathname.split("/").filter(Boolean);
2572
2624
  for (let i = 0;i < relativePath.length && i < pathnameParts.length; i++) {
@@ -2732,7 +2784,7 @@ async function processLayoutForMetadata(layout, clientDir, isWatchMode, addHead,
2732
2784
  if (typeof layout?.path !== "string")
2733
2785
  return;
2734
2786
  try {
2735
- const abs = join(clientDir, "routes", String(layout.path));
2787
+ const abs = join2(clientDir, "routes", String(layout.path));
2736
2788
  const { meta, ssr } = await loadModuleMetaAndSSR(layout, abs, isWatchMode);
2737
2789
  if (meta)
2738
2790
  addHead(buildHeadFromMeta(meta, ogConfig, titleSuffix));
@@ -2839,7 +2891,7 @@ async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode,
2839
2891
  }
2840
2892
  if (r && typeof r.path === "string") {
2841
2893
  try {
2842
- const abs = join(clientDir, "routes", String(r.path));
2894
+ const abs = join2(clientDir, "routes", String(r.path));
2843
2895
  const { meta, ssr } = await loadModuleMetaAndSSR(r, abs, isWatchMode);
2844
2896
  let head = "";
2845
2897
  if (meta)
@@ -2925,7 +2977,7 @@ async function extractNotFoundMetadata(pathname, clientDir, routesModule, isWatc
2925
2977
  return head;
2926
2978
  const chosen = findBestNotFoundRoute(list, pathname);
2927
2979
  if (chosen && typeof chosen.path === "string") {
2928
- const abs = join(clientDir, "routes", String(chosen.path));
2980
+ const abs = join2(clientDir, "routes", String(chosen.path));
2929
2981
  const { meta, ssr } = await loadModuleMetaAndSSR(chosen, abs, isWatchMode);
2930
2982
  if (meta)
2931
2983
  head += buildHeadFromMeta(meta, ogConfig, titleSuffix);
@@ -3104,7 +3156,7 @@ async function isContentCollection(clientDir, collection) {
3104
3156
  try {
3105
3157
  const isProduction = clientDir.endsWith(".reroute");
3106
3158
  if (isProduction) {
3107
- const collectionFile = join(clientDir, "collections", `${collection}.js`);
3159
+ const collectionFile = join2(clientDir, "collections", `${collection}.js`);
3108
3160
  try {
3109
3161
  const s2 = await stat5(collectionFile);
3110
3162
  return s2?.isFile() ?? false;
@@ -3112,7 +3164,7 @@ async function isContentCollection(clientDir, collection) {
3112
3164
  return false;
3113
3165
  }
3114
3166
  }
3115
- const maybeDir = join(clientDir, "routes", collection, "content");
3167
+ const maybeDir = join2(clientDir, "routes", collection, "content");
3116
3168
  const s = await stat5(maybeDir);
3117
3169
  return typeof s?.isDirectory === "function" ? s.isDirectory() : true;
3118
3170
  } catch {
@@ -3124,7 +3176,7 @@ async function findLatestCandidate(chunkDir, candidates) {
3124
3176
  let latestM = 0;
3125
3177
  for (const candidateName of candidates) {
3126
3178
  try {
3127
- const s = await stat5(join(chunkDir, candidateName));
3179
+ const s = await stat5(join2(chunkDir, candidateName));
3128
3180
  if (s.mtimeMs >= latestM) {
3129
3181
  latestM = s.mtimeMs;
3130
3182
  latest = candidateName;
@@ -3135,7 +3187,7 @@ async function findLatestCandidate(chunkDir, candidates) {
3135
3187
  }
3136
3188
  async function findContentModulePath(collection, name, clientDir, cwd, isWatchMode, locale) {
3137
3189
  try {
3138
- const registryPath = join(cwd, ".reroute", "content.ts");
3190
+ const registryPath = join2(cwd, ".reroute", "content.ts");
3139
3191
  const reg = await dynamicImport(registryPath, isWatchMode);
3140
3192
  const get = reg?.getContentEntry;
3141
3193
  const entry = typeof get === "function" ? get(collection, name, locale) : undefined;
@@ -3145,25 +3197,25 @@ async function findContentModulePath(collection, name, clientDir, cwd, isWatchMo
3145
3197
  }
3146
3198
  } catch {}
3147
3199
  try {
3148
- const chunkDir = join(cwd, ".reroute", "chunks", collection);
3200
+ const chunkDir = join2(cwd, ".reroute", "chunks", collection);
3149
3201
  const files = await readdir5(chunkDir);
3150
3202
  const candidates = files.filter((n) => n.startsWith(`${name}.`) && n.endsWith(".js"));
3151
3203
  if (candidates.length) {
3152
3204
  const latest = await findLatestCandidate(chunkDir, candidates);
3153
- return `/${join(".reroute", "chunks", collection, latest).replace(/\\+/g, "/")}`;
3205
+ return `/${join2(".reroute", "chunks", collection, latest).replace(/\\+/g, "/")}`;
3154
3206
  }
3155
3207
  } catch {}
3156
3208
  try {
3157
- const contentRoot = join(clientDir, "routes", collection, "content");
3209
+ const contentRoot = join2(clientDir, "routes", collection, "content");
3158
3210
  const candidates = locale ? [
3159
- join(contentRoot, locale, `${name}.tsx`),
3160
- join(contentRoot, locale, `${name}.ts`),
3161
- join(contentRoot, `${name}.tsx`),
3162
- join(contentRoot, `${name}.ts`)
3163
- ] : [join(contentRoot, `${name}.tsx`), join(contentRoot, `${name}.ts`)];
3211
+ join2(contentRoot, locale, `${name}.tsx`),
3212
+ join2(contentRoot, locale, `${name}.ts`),
3213
+ join2(contentRoot, `${name}.tsx`),
3214
+ join2(contentRoot, `${name}.ts`)
3215
+ ] : [join2(contentRoot, `${name}.tsx`), join2(contentRoot, `${name}.ts`)];
3164
3216
  for (const abs of candidates) {
3165
3217
  if (await Bun.file(abs).exists()) {
3166
- const rel = abs.startsWith(clientDir) ? abs.slice(clientDir.length).replace(/^[/\\]/, "") : join("routes", collection, "content", `${name}.tsx`);
3218
+ const rel = abs.startsWith(clientDir) ? abs.slice(clientDir.length).replace(/^[/\\]/, "") : join2("routes", collection, "content", `${name}.tsx`);
3167
3219
  return `/${rel.replace(/\\+/g, "/")}`;
3168
3220
  }
3169
3221
  }
@@ -3522,7 +3574,7 @@ var init_scripts = __esm(() => {
3522
3574
 
3523
3575
  // packages/core/src/ssr/lib/styles.ts
3524
3576
  import { createHash } from "node:crypto";
3525
- import { readdirSync } from "node:fs";
3577
+ import { readdirSync as readdirSync2 } from "node:fs";
3526
3578
  function themeCssHash(css) {
3527
3579
  return createHash("sha1").update(css).digest("hex").slice(0, 8);
3528
3580
  }
@@ -3534,10 +3586,10 @@ function themeLink(href) {
3534
3586
  }
3535
3587
  function bundlesDirs(clientDir) {
3536
3588
  return [
3537
- join(clientDir, "..", ".reroute", "bundles"),
3538
- join(clientDir, "..", "..", ".reroute", "bundles"),
3539
- join(clientDir, "..", "..", "..", ".reroute", "bundles"),
3540
- join(clientDir, "..", "..", "..", "..", ".reroute", "bundles")
3589
+ join2(clientDir, "..", ".reroute", "bundles"),
3590
+ join2(clientDir, "..", "..", ".reroute", "bundles"),
3591
+ join2(clientDir, "..", "..", "..", ".reroute", "bundles"),
3592
+ join2(clientDir, "..", "..", "..", "..", ".reroute", "bundles")
3541
3593
  ];
3542
3594
  }
3543
3595
  async function readFileIfExists(path) {
@@ -3549,13 +3601,13 @@ async function readFileIfExists(path) {
3549
3601
  async function readThemeFromBundles(clientDir) {
3550
3602
  for (const dir of bundlesDirs(clientDir)) {
3551
3603
  try {
3552
- const hashed = readdirSync(dir).find((name) => HASHED_THEME_RE.test(name));
3604
+ const hashed = readdirSync2(dir).find((name) => HASHED_THEME_RE.test(name));
3553
3605
  if (hashed) {
3554
- const css2 = await readFileIfExists(join(dir, hashed));
3606
+ const css2 = await readFileIfExists(join2(dir, hashed));
3555
3607
  if (css2)
3556
3608
  return { css: css2, href: `/bundles/${hashed}` };
3557
3609
  }
3558
- const css = await readFileIfExists(join(dir, "index.css"));
3610
+ const css = await readFileIfExists(join2(dir, "index.css"));
3559
3611
  if (css)
3560
3612
  return { css, href: `/bundles/${themeCssFileName(css)}` };
3561
3613
  } catch {}
@@ -4136,7 +4188,7 @@ async function loadCollectionItem(cwd, pathname, isWatchMode) {
4136
4188
  if (parts.length < 2)
4137
4189
  return null;
4138
4190
  const collection = parts[0];
4139
- const collectionFile = join(cwd, ".reroute", "collections", `${collection}.js`);
4191
+ const collectionFile = join2(cwd, ".reroute", "collections", `${collection}.js`);
4140
4192
  const exists = await Bun.file(collectionFile).exists();
4141
4193
  if (!exists)
4142
4194
  return null;
@@ -4151,7 +4203,7 @@ async function loadCollectionItem(cwd, pathname, isWatchMode) {
4151
4203
  async function findComponentPath(clientDir, collection, slug) {
4152
4204
  const extensions = [".mdx", ".md", ".tsx", ".jsx"];
4153
4205
  for (const ext of extensions) {
4154
- const testPath = join(clientDir, "routes", collection, "content", `${slug}${ext}`);
4206
+ const testPath = join2(clientDir, "routes", collection, "content", `${slug}${ext}`);
4155
4207
  const file = Bun.file(testPath);
4156
4208
  if (await file.exists()) {
4157
4209
  return testPath;
@@ -4422,7 +4474,7 @@ async function discoverStaticRoutes(cwd, isWatchMode) {
4422
4474
  try {
4423
4475
  let routesList = globalThis.__REROUTE_ROUTES__;
4424
4476
  if (!routesList) {
4425
- const routesPath = join(cwd, ".reroute", "routes.ts");
4477
+ const routesPath = join2(cwd, ".reroute", "routes.ts");
4426
4478
  const url = pathToFileURL6(routesPath).href;
4427
4479
  const mod = await import(`${url}${isWatchMode ? `?t=${Date.now()}` : ""}`);
4428
4480
  routesList = mod?.routes;
@@ -4447,7 +4499,7 @@ async function discoverStaticRoutes(cwd, isWatchMode) {
4447
4499
  return routes;
4448
4500
  }
4449
4501
  async function loadCollectionModule(cwd, collection, isWatchMode) {
4450
- const collectionFile = join(cwd, ".reroute", "collections", `${collection}.js`);
4502
+ const collectionFile = join2(cwd, ".reroute", "collections", `${collection}.js`);
4451
4503
  const exists = await Bun.file(collectionFile).exists();
4452
4504
  if (!exists)
4453
4505
  return null;
@@ -4507,7 +4559,7 @@ async function discoverCollectionRoutes(cwd, collections2, isWatchMode, llmsConf
4507
4559
  }
4508
4560
  async function loadRouteModule(cwd, routePath, isWatchMode) {
4509
4561
  try {
4510
- const abs = join(cwd, resolveAppPaths(await loadConfig(cwd)).routesDir, routePath);
4562
+ const abs = join2(cwd, resolveAppPaths(await loadConfig(cwd)).routesDir, routePath);
4511
4563
  const modUrl = `${pathToFileURL6(abs).href}${isWatchMode ? `?t=${Date.now()}` : ""}`;
4512
4564
  return await import(modUrl);
4513
4565
  } catch {
@@ -5013,7 +5065,7 @@ async function discoverRoutesForRobots(cwd, isWatchMode) {
5013
5065
  try {
5014
5066
  let routesArray = globalThis.__REROUTE_ROUTES__;
5015
5067
  if (!routesArray) {
5016
- const routesPath = join(cwd, ".reroute", "routes.ts");
5068
+ const routesPath = join2(cwd, ".reroute", "routes.ts");
5017
5069
  const url = Bun.pathToFileURL(routesPath).href;
5018
5070
  const mod = await import(`${url}${isWatchMode ? `?t=${Date.now()}` : ""}`);
5019
5071
  routesArray = mod?.routes;
@@ -5244,7 +5296,7 @@ __export(exports_discovery, {
5244
5296
  async function loadRoutesModule2(cwd, isWatchMode) {
5245
5297
  let routes = globalThis.__REROUTE_ROUTES__;
5246
5298
  if (!routes) {
5247
- const routesPath = join(cwd, ".reroute", "routes.ts");
5299
+ const routesPath = join2(cwd, ".reroute", "routes.ts");
5248
5300
  const url = Bun.pathToFileURL(routesPath).href;
5249
5301
  const mod = await import(`${url}${isWatchMode ? `?t=${Date.now()}` : ""}`);
5250
5302
  routes = mod?.routes;
@@ -5334,7 +5386,7 @@ function buildNamedCollectionSitemapEntries(collection, name, variants, defaultL
5334
5386
  async function discoverCollectionContent(cwd, collection, isWatchMode, baseUrl) {
5335
5387
  const entries = [];
5336
5388
  try {
5337
- const collectionFile = join(cwd, ".reroute", "collections", `${collection}.js`);
5389
+ const collectionFile = join2(cwd, ".reroute", "collections", `${collection}.js`);
5338
5390
  const exists = await Bun.file(collectionFile).exists();
5339
5391
  if (!exists) {
5340
5392
  return entries;
@@ -5409,7 +5461,7 @@ async function discoverSSRDataRoutes2(cwd, staticRoutes, isWatchMode, baseUrl, s
5409
5461
  return null;
5410
5462
  }
5411
5463
  try {
5412
- const routeModulePath = join(cwd, "src", "client", "routes", route.path);
5464
+ const routeModulePath = join2(cwd, "src", "client", "routes", route.path);
5413
5465
  const mod = await import(Bun.pathToFileURL(routeModulePath).href + (isWatchMode ? `?t=${Date.now()}` : ""));
5414
5466
  const ssr = mod?.ssr;
5415
5467
  const dataFn = ssr?.data;
@@ -5580,7 +5632,7 @@ async function loadRouteSitemapFn(cwd, route, isWatchMode) {
5580
5632
  return typeof sitemapFn === "function" ? sitemapFn : null;
5581
5633
  }
5582
5634
  try {
5583
- const routeModulePath = join(cwd, "src", "client", "routes", route.path);
5635
+ const routeModulePath = join2(cwd, "src", "client", "routes", route.path);
5584
5636
  const mod = await import(Bun.pathToFileURL(routeModulePath).href + (isWatchMode ? `?t=${Date.now()}` : ""));
5585
5637
  const sitemapFn = mod?.ssr?.sitemap;
5586
5638
  return typeof sitemapFn === "function" ? sitemapFn : null;
@@ -5723,7 +5775,7 @@ function createRSSItemFromMetaAndHref(href, meta, baseUrl, item, rssConfig) {
5723
5775
  async function discoverCollectionFeedItems(cwd, collection, isWatchMode, baseUrl, rssConfig) {
5724
5776
  const items = [];
5725
5777
  try {
5726
- const collectionFile = join(cwd, ".reroute", "collections", `${collection}.js`);
5778
+ const collectionFile = join2(cwd, ".reroute", "collections", `${collection}.js`);
5727
5779
  const exists = await Bun.file(collectionFile).exists();
5728
5780
  if (!exists) {
5729
5781
  return items;
@@ -5753,7 +5805,7 @@ async function discoverCollectionFeedItems(cwd, collection, isWatchMode, baseUrl
5753
5805
  async function discoverSSRDataFeedItems(cwd, routePattern, routePath, isWatchMode, baseUrl, rssConfig) {
5754
5806
  const items = [];
5755
5807
  try {
5756
- const abs = join(cwd, resolveAppPaths(await loadConfig(cwd)).routesDir, routePath);
5808
+ const abs = join2(cwd, resolveAppPaths(await loadConfig(cwd)).routesDir, routePath);
5757
5809
  const mod = await import(pathToFileURL7(abs).href + (isWatchMode ? `?t=${Date.now()}` : ""));
5758
5810
  const ssr = mod?.ssr;
5759
5811
  const dataFn = ssr?.data;
@@ -6593,6 +6645,7 @@ var init_src = __esm(() => {
6593
6645
  init_config();
6594
6646
  init_content();
6595
6647
  init_i18n();
6648
+ init_image();
6596
6649
  init_llms();
6597
6650
  init_og();
6598
6651
  init_robots();
@@ -6608,8 +6661,12 @@ __export(exports_core, {
6608
6661
  DEFAULT_APP_SERVER: () => DEFAULT_APP_SERVER,
6609
6662
  DEFAULT_APP_SRC: () => DEFAULT_APP_SRC,
6610
6663
  DEFAULT_COOKIE: () => DEFAULT_COOKIE,
6664
+ DEFAULT_IMAGE_DEVICE_SIZES: () => DEFAULT_IMAGE_DEVICE_SIZES,
6665
+ DEFAULT_IMAGE_QUALITY: () => DEFAULT_IMAGE_QUALITY,
6611
6666
  DEFAULT_LOCALE: () => DEFAULT_LOCALE,
6612
6667
  DEFAULT_LOCALES_DIR: () => DEFAULT_LOCALES_DIR,
6668
+ DEFAULT_PREPROCESS_FORMATS: () => DEFAULT_PREPROCESS_FORMATS,
6669
+ DEFAULT_PREPROCESS_SIZES: () => DEFAULT_PREPROCESS_SIZES,
6613
6670
  DefaultOGTemplate: () => DefaultOGTemplate,
6614
6671
  LRUCache: () => LRUCache,
6615
6672
  SEARCH_CRAWLERS: () => SEARCH_CRAWLERS,
@@ -6706,7 +6763,7 @@ __export(exports_core, {
6706
6763
  inlineThemeCSS: () => inlineThemeCSS,
6707
6764
  isCompressible: () => isCompressible,
6708
6765
  isThenable: () => isThenable,
6709
- join: () => join,
6766
+ join: () => join2,
6710
6767
  listContentFiles: () => listContentFiles,
6711
6768
  llmsAlternateLinkTag: () => llmsAlternateLinkTag,
6712
6769
  loadCollections: () => loadCollections,
@@ -6737,6 +6794,8 @@ __export(exports_core, {
6737
6794
  resetSSRAccessTracking: () => resetSSRAccessTracking,
6738
6795
  resetSSRContentResults: () => resetSSRContentResults,
6739
6796
  resolveAppPaths: () => resolveAppPaths,
6797
+ resolveImageDeviceSizes: () => resolveImageDeviceSizes,
6798
+ resolveImagePreprocess: () => resolveImagePreprocess,
6740
6799
  resolveLocale: () => resolveLocale,
6741
6800
  seedSSRModuleForPath: () => seedSSRModuleForPath,
6742
6801
  setGlobalCollections: () => setGlobalCollections,
@@ -6759,40 +6818,10 @@ var init_core = __esm(() => {
6759
6818
  init_src();
6760
6819
  });
6761
6820
 
6762
- // packages/elysia/src/plugin.ts
6763
- init_core();
6764
- import { existsSync as existsSync4 } from "node:fs";
6765
- import { join as join8 } from "node:path";
6766
- import { pathToFileURL as pathToFileURL8 } from "node:url";
6767
- import { createElement as createElement2 } from "react";
6768
-
6769
- // packages/elysia/src/libs/assets.ts
6770
- import { existsSync } from "node:fs";
6771
- function resolveClientDir(cwd, assets) {
6772
- if (assets.startsWith("/")) {
6773
- return assets;
6774
- }
6775
- const rerouteAssetsPath = `${cwd}/.reroute/assets`;
6776
- if (existsSync(rerouteAssetsPath)) {
6777
- return `${cwd}/.reroute`;
6778
- }
6779
- const devPath = `${cwd.replace(/\/$/, "")}/${assets.replace(/^\.\//, "")}`;
6780
- return devPath;
6781
- }
6782
-
6783
- // packages/elysia/src/libs/cache.ts
6784
- function resolveServerDataMaxAge(cacheEnabled, maxAgeSeconds) {
6785
- if (!cacheEnabled || maxAgeSeconds <= 0)
6786
- return 0;
6787
- return maxAgeSeconds;
6788
- }
6789
- function getEncoding(acceptEncoding) {
6790
- return /\bbr\b/i.test(acceptEncoding) ? "br" : /gzip/i.test(acceptEncoding) ? "gz" : "raw";
6791
- }
6792
-
6793
6821
  // packages/elysia/src/libs/image.ts
6794
- import { existsSync as existsSync2 } from "node:fs";
6795
- import { join as join4 } from "node:path";
6822
+ import { existsSync, readdirSync } from "node:fs";
6823
+ import { cpus } from "node:os";
6824
+ import { join } from "node:path";
6796
6825
  import sharp from "sharp";
6797
6826
  var imageCache = new Map;
6798
6827
  var MAX_CACHE_SIZE = 100;
@@ -6800,12 +6829,21 @@ var diskCacheDir = null;
6800
6829
  function initImageCache(cacheDir) {
6801
6830
  diskCacheDir = cacheDir;
6802
6831
  }
6832
+ function imageCacheIdentity(imagePath) {
6833
+ const normalized = imagePath.replace(/\\/g, "/");
6834
+ const marker = "/assets/";
6835
+ const index = normalized.lastIndexOf(marker);
6836
+ if (index !== -1) {
6837
+ return normalized.slice(index);
6838
+ }
6839
+ return normalized;
6840
+ }
6803
6841
  function getCacheKey(imagePath, options) {
6804
6842
  const optionsString = JSON.stringify(options);
6805
6843
  const hasher = new Bun.CryptoHasher("sha256");
6806
- hasher.update(`${imagePath}:${optionsString}`);
6807
- const hash2 = hasher.digest("hex");
6808
- return hash2;
6844
+ hasher.update(`${imageCacheIdentity(imagePath)}:${optionsString}`);
6845
+ const hash = hasher.digest("hex");
6846
+ return hash;
6809
6847
  }
6810
6848
  function getContentType(format) {
6811
6849
  const contentTypes = {
@@ -6835,20 +6873,20 @@ async function loadFromDiskCache(cacheKey) {
6835
6873
  if (!diskCacheDir)
6836
6874
  return null;
6837
6875
  try {
6838
- const cachePath = join4(diskCacheDir, `${cacheKey}.json`);
6839
- const imagePath = join4(diskCacheDir, `${cacheKey}.img`);
6840
- if (!(existsSync2(cachePath) && existsSync2(imagePath))) {
6876
+ const cachePath = join(diskCacheDir, `${cacheKey}.json`);
6877
+ const imagePath = join(diskCacheDir, `${cacheKey}.img`);
6878
+ if (!(existsSync(cachePath) && existsSync(imagePath))) {
6841
6879
  return null;
6842
6880
  }
6843
- const metadata3 = JSON.parse(await Bun.file(cachePath).text());
6881
+ const metadata = JSON.parse(await Bun.file(cachePath).text());
6844
6882
  const buffer = Buffer.from(await Bun.file(imagePath).arrayBuffer());
6845
6883
  return {
6846
6884
  buffer,
6847
- contentType: metadata3.contentType,
6848
- format: metadata3.format,
6849
- width: metadata3.width,
6850
- height: metadata3.height,
6851
- size: metadata3.size
6885
+ contentType: metadata.contentType,
6886
+ format: metadata.format,
6887
+ width: metadata.width,
6888
+ height: metadata.height,
6889
+ size: metadata.size
6852
6890
  };
6853
6891
  } catch {
6854
6892
  return null;
@@ -6858,8 +6896,8 @@ async function saveToDiskCache(cacheKey, result) {
6858
6896
  if (!diskCacheDir)
6859
6897
  return;
6860
6898
  try {
6861
- const cachePath = join4(diskCacheDir, `${cacheKey}.json`);
6862
- const imagePath = join4(diskCacheDir, `${cacheKey}.img`);
6899
+ const cachePath = join(diskCacheDir, `${cacheKey}.json`);
6900
+ const imagePath = join(diskCacheDir, `${cacheKey}.img`);
6863
6901
  await Bun.write(cachePath, JSON.stringify({
6864
6902
  contentType: result.contentType,
6865
6903
  format: result.format,
@@ -6922,7 +6960,7 @@ async function optimizeImage(imagePath, options, acceptHeader) {
6922
6960
  const sourceBuffer = await fetchImageBuffer(imagePath);
6923
6961
  const format = options.format === "auto" || !options.format ? negotiateFormat(acceptHeader, undefined) : options.format;
6924
6962
  let transformer = sharp(sourceBuffer);
6925
- const metadata3 = await transformer.metadata();
6963
+ const metadata = await transformer.metadata();
6926
6964
  if (options.width || options.height) {
6927
6965
  const resizeOptions = {
6928
6966
  width: options.width,
@@ -6940,8 +6978,8 @@ async function optimizeImage(imagePath, options, acceptHeader) {
6940
6978
  buffer,
6941
6979
  contentType: getContentType(format),
6942
6980
  format,
6943
- width: info.width || metadata3.width || options.width || 0,
6944
- height: info.height || metadata3.height || options.height || 0,
6981
+ width: info.width || metadata.width || options.width || 0,
6982
+ height: info.height || metadata.height || options.height || 0,
6945
6983
  size: buffer.length
6946
6984
  };
6947
6985
  await saveToDiskCache(cacheKey, result);
@@ -6954,11 +6992,127 @@ async function optimizeImage(imagePath, options, acceptHeader) {
6954
6992
  imageCache.set(cacheKey, result);
6955
6993
  return result;
6956
6994
  }
6957
- function isImageFile(path2) {
6995
+ function isImageFile(path) {
6958
6996
  const imageExtensions = [".jpg", ".jpeg", ".png", ".webp", ".avif", ".gif"];
6959
- const ext = path2.toLowerCase().split(".").pop();
6997
+ const ext = path.toLowerCase().split(".").pop();
6960
6998
  return ext ? imageExtensions.includes(`.${ext}`) : false;
6961
6999
  }
7000
+ function isPreprocessSource(path) {
7001
+ return isImageFile(path) && !path.toLowerCase().endsWith(".gif");
7002
+ }
7003
+ function walkImageFiles(dir) {
7004
+ if (!existsSync(dir)) {
7005
+ return [];
7006
+ }
7007
+ const files = [];
7008
+ const entries = readdirSync(dir, { withFileTypes: true });
7009
+ for (const entry of entries) {
7010
+ const fullPath = join(dir, entry.name);
7011
+ if (entry.isDirectory()) {
7012
+ files.push(...walkImageFiles(fullPath));
7013
+ } else if (isPreprocessSource(fullPath)) {
7014
+ files.push(fullPath);
7015
+ }
7016
+ }
7017
+ return files;
7018
+ }
7019
+ async function bakeVariant(cacheDir, imagePath, width, quality, format) {
7020
+ const transform = {
7021
+ width,
7022
+ quality,
7023
+ format,
7024
+ fit: "cover"
7025
+ };
7026
+ const cacheKey = getCacheKey(imagePath, transform);
7027
+ const existed = existsSync(join(cacheDir, `${cacheKey}.img`)) && existsSync(join(cacheDir, `${cacheKey}.json`));
7028
+ await optimizeImage(imagePath, transform, format === "auto" ? "image/webp" : undefined);
7029
+ return existed ? "cached" : "generated";
7030
+ }
7031
+ function preprocessJobs(options) {
7032
+ const sources = walkImageFiles(options.assetsDir);
7033
+ const formats = [
7034
+ ...options.formats,
7035
+ "auto"
7036
+ ];
7037
+ const qualities = options.qualities?.length ? options.qualities : [options.quality];
7038
+ return sources.flatMap((imagePath) => options.widths.flatMap((width) => qualities.flatMap((quality) => formats.map((format) => ({ imagePath, width, quality, format })))));
7039
+ }
7040
+ async function mapPool(items, concurrency, fn) {
7041
+ if (items.length === 0) {
7042
+ return [];
7043
+ }
7044
+ const results = new Array(items.length);
7045
+ let next = 0;
7046
+ const workers = Math.min(Math.max(1, concurrency), items.length);
7047
+ await Promise.all(Array.from({ length: workers }, async () => {
7048
+ while (next < items.length) {
7049
+ const index = next;
7050
+ next += 1;
7051
+ results[index] = await fn(items[index]);
7052
+ }
7053
+ }));
7054
+ return results;
7055
+ }
7056
+ function preprocessConcurrency(override) {
7057
+ if (override && override > 0) {
7058
+ return override;
7059
+ }
7060
+ return Math.max(1, cpus().length);
7061
+ }
7062
+ async function preprocessImages(options) {
7063
+ initImageCache(options.cacheDir);
7064
+ const jobs = preprocessJobs(options);
7065
+ const concurrency = preprocessConcurrency(options.concurrency);
7066
+ if (jobs.length > 0) {
7067
+ console.log(`[reroute] Preprocessing ${jobs.length} image variants (${concurrency} at a time)...`);
7068
+ }
7069
+ const previousSharpThreads = sharp.concurrency();
7070
+ sharp.concurrency(1);
7071
+ const results = await mapPool(jobs, concurrency, (job) => bakeVariant(options.cacheDir, job.imagePath, job.width, job.quality, job.format)).finally(() => {
7072
+ sharp.concurrency(previousSharpThreads);
7073
+ });
7074
+ let generated = 0;
7075
+ let cached = 0;
7076
+ for (const result of results) {
7077
+ if (result === "cached") {
7078
+ cached++;
7079
+ } else {
7080
+ generated++;
7081
+ }
7082
+ }
7083
+ const sources = new Set(jobs.map((job) => job.imagePath)).size;
7084
+ return { sources, generated, cached, jobs: jobs.length, concurrency };
7085
+ }
7086
+ // packages/elysia/src/plugin.ts
7087
+ init_core();
7088
+ import { existsSync as existsSync4 } from "node:fs";
7089
+ import { join as join8 } from "node:path";
7090
+ import { pathToFileURL as pathToFileURL8 } from "node:url";
7091
+ import { createElement as createElement2 } from "react";
7092
+
7093
+ // packages/elysia/src/libs/assets.ts
7094
+ import { existsSync as existsSync2 } from "node:fs";
7095
+ function resolveClientDir(cwd, assets) {
7096
+ if (assets.startsWith("/")) {
7097
+ return assets;
7098
+ }
7099
+ const rerouteAssetsPath = `${cwd}/.reroute/assets`;
7100
+ if (existsSync2(rerouteAssetsPath)) {
7101
+ return `${cwd}/.reroute`;
7102
+ }
7103
+ const devPath = `${cwd.replace(/\/$/, "")}/${assets.replace(/^\.\//, "")}`;
7104
+ return devPath;
7105
+ }
7106
+
7107
+ // packages/elysia/src/libs/cache.ts
7108
+ function resolveServerDataMaxAge(cacheEnabled, maxAgeSeconds) {
7109
+ if (!cacheEnabled || maxAgeSeconds <= 0)
7110
+ return 0;
7111
+ return maxAgeSeconds;
7112
+ }
7113
+ function getEncoding(acceptEncoding) {
7114
+ return /\bbr\b/i.test(acceptEncoding) ? "br" : /gzip/i.test(acceptEncoding) ? "gz" : "raw";
7115
+ }
6962
7116
 
6963
7117
  // packages/elysia/src/routes/artifacts.ts
6964
7118
  init_core();
@@ -7149,7 +7303,7 @@ function registerArtifactsRoutes(app, cwd, fileCache, options) {
7149
7303
  const fileName = String(params["*"] ?? "").replace(/^\/+/, "");
7150
7304
  if (!fileName)
7151
7305
  throw new NotFoundError2;
7152
- const filePath = join(cwd, ".reroute", "bundles", fileName);
7306
+ const filePath = join2(cwd, ".reroute", "bundles", fileName);
7153
7307
  const acceptEncoding = headers2["accept-encoding"] ?? "";
7154
7308
  const cacheControl = getHashedFileCacheControl(fileName, bundleMaxAge, directive, isWatchMode);
7155
7309
  try {
@@ -7170,7 +7324,7 @@ function registerArtifactsRoutes(app, cwd, fileCache, options) {
7170
7324
  const fileName = String(params["*"] ?? "").replace(/^\/+/, "");
7171
7325
  if (!fileName)
7172
7326
  throw new NotFoundError2;
7173
- const filePath = join(cwd, ".reroute", "collections", fileName);
7327
+ const filePath = join2(cwd, ".reroute", "collections", fileName);
7174
7328
  const acceptEncoding = headers2["accept-encoding"] ?? "";
7175
7329
  try {
7176
7330
  const cacheControl = isWatchMode ? "no-cache, no-store, must-revalidate" : "public, max-age=60, must-revalidate";
@@ -7224,7 +7378,7 @@ function registerContentRoutes(app, cwd, collectionCache, directive, maxAge, isW
7224
7378
  return response;
7225
7379
  }
7226
7380
  try {
7227
- const collectionFile = join(cwd, ".reroute", "collections", `${collectionPath}.js`);
7381
+ const collectionFile = join2(cwd, ".reroute", "collections", `${collectionPath}.js`);
7228
7382
  const file = Bun.file(collectionFile);
7229
7383
  if (!await file.exists()) {
7230
7384
  if (isOtelAvailable2()) {
@@ -8852,7 +9006,7 @@ async function discoverSSRRoutes(cwd, isWatchMode) {
8852
9006
  const { discoverSitemapData: discoverSitemapData2 } = await Promise.resolve().then(() => (init_core(), exports_core));
8853
9007
  const sitemapData = await discoverSitemapData2(cwd, [], "", isWatchMode);
8854
9008
  const staticRoutes = sitemapData.staticRoutes.filter((r) => !r.pattern.includes(":")).map((r) => ({ pattern: r.pattern, path: r.path }));
8855
- const routesPath = join(cwd, ".reroute", "routes.ts");
9009
+ const routesPath = join2(cwd, ".reroute", "routes.ts");
8856
9010
  const routesMod = await import(`${Bun.pathToFileURL(routesPath).href}${isWatchMode ? `?t=${Date.now()}` : ""}`);
8857
9011
  const layouts2 = routesMod.layouts ?? [];
8858
9012
  for (const layout of layouts2) {
@@ -9150,7 +9304,7 @@ function registerSearchRoute(app, cwd, directive, maxAge, searchConfig) {
9150
9304
  let lastModified = null;
9151
9305
  async function loadSearchIndex() {
9152
9306
  try {
9153
- const indexPath = join(cwd, ".reroute", "search.json");
9307
+ const indexPath = join2(cwd, ".reroute", "search.json");
9154
9308
  const file = Bun.file(indexPath);
9155
9309
  if (!await file.exists())
9156
9310
  return null;
@@ -9939,7 +10093,7 @@ function registerStaticRoutes(app, options) {
9939
10093
  }
9940
10094
  app.get("/assets/*", async function serveStaticFile({ params, headers: headers2 }) {
9941
10095
  const requestPath = params["*"];
9942
- const filePath = join(staticAssetsDir, requestPath);
10096
+ const filePath = join2(staticAssetsDir, requestPath);
9943
10097
  try {
9944
10098
  const acceptEncoding = headers2["accept-encoding"] ?? "";
9945
10099
  const encoding = getEncoding(acceptEncoding);
@@ -10420,7 +10574,13 @@ var reroute = () => async (app) => {
10420
10574
  return app;
10421
10575
  };
10422
10576
  export {
10577
+ imageCacheIdentity,
10578
+ initImageCache,
10579
+ isImageFile,
10580
+ optimizeImage,
10581
+ preprocessConcurrency,
10582
+ preprocessImages,
10423
10583
  reroute
10424
10584
  };
10425
10585
 
10426
- //# debugId=239BA0745203D99F64756E2164756E21
10586
+ //# debugId=9B670082489E5DF064756E2164756E21