reroute-js 1.0.0-alpha.20 → 1.0.0-alpha.22

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 (214) hide show
  1. package/README.md +1 -0
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +631 -238
  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 +29 -5
  157. package/react/index.js.map +3 -3
  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 +1 -1
  189. package/react/src/lib/route-loader.d.ts +1 -1
  190. package/react/src/providers/ContentProvider.d.ts +1 -1
  191. package/react/src/providers/RerouteProvider.d.ts +1 -1
  192. package/react/src/providers/RouterProvider.d.ts +1 -1
  193. package/react/src/providers/index.d.ts +1 -1
  194. package/react/src/types/any.d.ts +1 -1
  195. package/react/src/types/index.d.ts +1 -1
  196. package/react/src/types/router.d.ts +1 -1
  197. package/telemetry/react.d.ts +1 -1
  198. package/telemetry/react.js +2 -2
  199. package/telemetry/react.js.map +1 -1
  200. package/telemetry/server.d.ts +1 -1
  201. package/telemetry/server.js +6 -2
  202. package/telemetry/server.js.map +4 -4
  203. package/telemetry/src/react/api.d.ts +1 -1
  204. package/telemetry/src/react/context.d.ts +1 -1
  205. package/telemetry/src/react/index.d.ts +1 -1
  206. package/telemetry/src/react/telemetry.d.ts +1 -1
  207. package/telemetry/src/server/context.d.ts +1 -1
  208. package/telemetry/src/server/headers/extractor.d.ts +1 -1
  209. package/telemetry/src/server/headers/index.d.ts +1 -1
  210. package/telemetry/src/server/headers/presets.d.ts +1 -1
  211. package/telemetry/src/server/index.d.ts +1 -1
  212. package/telemetry/src/server/instrumentation.d.ts +1 -1
  213. package/telemetry/src/server/plugin.d.ts +1 -1
  214. package/telemetry/src/server/sourcemap.d.ts +1 -1
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.20
4
+ * reroute-js v1.0.0-alpha.22
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.20";
71
+ return "1.0.0-alpha.22";
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 "1bc8849";
89
+ return "53ae62b";
90
90
  }
91
91
  return "dev";
92
92
  }
@@ -962,6 +962,58 @@ var init_i18n = __esm(() => {
962
962
  init_resolve();
963
963
  });
964
964
 
965
+ // packages/core/src/image.ts
966
+ function uniquePositiveWidths(widths) {
967
+ return [...new Set(widths.filter((width) => width > 0))].sort((a, b) => a - b);
968
+ }
969
+ function resolveImagePreprocess(image) {
970
+ const preprocess = image?.preprocess;
971
+ if (!preprocess) {
972
+ return {
973
+ enabled: false,
974
+ widths: [...DEFAULT_IMAGE_DEVICE_SIZES],
975
+ formats: [...DEFAULT_PREPROCESS_FORMATS],
976
+ quality: DEFAULT_IMAGE_QUALITY,
977
+ qualities: [DEFAULT_IMAGE_QUALITY]
978
+ };
979
+ }
980
+ const options = preprocess === true ? {} : preprocess;
981
+ const quality = options.quality ?? DEFAULT_IMAGE_QUALITY;
982
+ return {
983
+ enabled: true,
984
+ widths: uniquePositiveWidths([
985
+ options.mobile ?? DEFAULT_PREPROCESS_SIZES.mobile,
986
+ options.tablet ?? DEFAULT_PREPROCESS_SIZES.tablet,
987
+ options.desktop ?? DEFAULT_PREPROCESS_SIZES.desktop
988
+ ]),
989
+ formats: options.formats?.length ? options.formats : [...DEFAULT_PREPROCESS_FORMATS],
990
+ quality,
991
+ qualities: uniquePositiveWidths(options.qualities ?? [quality])
992
+ };
993
+ }
994
+ function resolveImageDeviceSizes(image) {
995
+ return resolveImagePreprocess(image).widths;
996
+ }
997
+ var DEFAULT_IMAGE_DEVICE_SIZES, DEFAULT_PREPROCESS_SIZES, DEFAULT_PREPROCESS_FORMATS, DEFAULT_IMAGE_QUALITY = 75;
998
+ var init_image = __esm(() => {
999
+ DEFAULT_IMAGE_DEVICE_SIZES = [
1000
+ 640,
1001
+ 750,
1002
+ 828,
1003
+ 1080,
1004
+ 1200,
1005
+ 1920,
1006
+ 2048,
1007
+ 3840
1008
+ ];
1009
+ DEFAULT_PREPROCESS_SIZES = {
1010
+ mobile: 640,
1011
+ tablet: 1024,
1012
+ desktop: 1920
1013
+ };
1014
+ DEFAULT_PREPROCESS_FORMATS = ["webp", "avif"];
1015
+ });
1016
+
965
1017
  // packages/telemetry/src/server/context.ts
966
1018
  import { AsyncLocalStorage } from "node:async_hooks";
967
1019
  var contextStorage;
@@ -6931,6 +6983,7 @@ var init_src = __esm(() => {
6931
6983
  init_config();
6932
6984
  init_content();
6933
6985
  init_i18n();
6986
+ init_image();
6934
6987
  init_llms();
6935
6988
  init_og();
6936
6989
  init_robots();
@@ -6946,8 +6999,12 @@ __export(exports_core, {
6946
6999
  DEFAULT_APP_SERVER: () => DEFAULT_APP_SERVER,
6947
7000
  DEFAULT_APP_SRC: () => DEFAULT_APP_SRC,
6948
7001
  DEFAULT_COOKIE: () => DEFAULT_COOKIE,
7002
+ DEFAULT_IMAGE_DEVICE_SIZES: () => DEFAULT_IMAGE_DEVICE_SIZES,
7003
+ DEFAULT_IMAGE_QUALITY: () => DEFAULT_IMAGE_QUALITY,
6949
7004
  DEFAULT_LOCALE: () => DEFAULT_LOCALE,
6950
7005
  DEFAULT_LOCALES_DIR: () => DEFAULT_LOCALES_DIR,
7006
+ DEFAULT_PREPROCESS_FORMATS: () => DEFAULT_PREPROCESS_FORMATS,
7007
+ DEFAULT_PREPROCESS_SIZES: () => DEFAULT_PREPROCESS_SIZES,
6951
7008
  DefaultOGTemplate: () => DefaultOGTemplate,
6952
7009
  LRUCache: () => LRUCache,
6953
7010
  SEARCH_CRAWLERS: () => SEARCH_CRAWLERS,
@@ -7075,6 +7132,8 @@ __export(exports_core, {
7075
7132
  resetSSRAccessTracking: () => resetSSRAccessTracking,
7076
7133
  resetSSRContentResults: () => resetSSRContentResults,
7077
7134
  resolveAppPaths: () => resolveAppPaths,
7135
+ resolveImageDeviceSizes: () => resolveImageDeviceSizes,
7136
+ resolveImagePreprocess: () => resolveImagePreprocess,
7078
7137
  resolveLocale: () => resolveLocale,
7079
7138
  seedSSRModuleForPath: () => seedSSRModuleForPath,
7080
7139
  setGlobalCollections: () => setGlobalCollections,
@@ -7188,14 +7247,318 @@ function envToDefineObject(env) {
7188
7247
  var envLoadedLog = false;
7189
7248
  var init_env = () => {};
7190
7249
 
7250
+ // packages/elysia/src/libs/image.ts
7251
+ import { existsSync as existsSync3, readdirSync as readdirSync2 } from "node:fs";
7252
+ import { cpus } from "node:os";
7253
+ import { join as join6 } from "node:path";
7254
+ import sharp from "sharp";
7255
+ function initImageCache(cacheDir) {
7256
+ diskCacheDir = cacheDir;
7257
+ }
7258
+ function imageCacheIdentity(imagePath) {
7259
+ const normalized = imagePath.replace(/\\/g, "/");
7260
+ const marker = "/assets/";
7261
+ const index = normalized.lastIndexOf(marker);
7262
+ if (index !== -1) {
7263
+ return normalized.slice(index);
7264
+ }
7265
+ return normalized;
7266
+ }
7267
+ function getCacheKey(imagePath, options) {
7268
+ const optionsString = JSON.stringify(options);
7269
+ const hasher = new Bun.CryptoHasher("sha256");
7270
+ hasher.update(`${imageCacheIdentity(imagePath)}:${optionsString}`);
7271
+ const hash2 = hasher.digest("hex");
7272
+ return hash2;
7273
+ }
7274
+ function getContentType(format) {
7275
+ const contentTypes = {
7276
+ webp: "image/webp",
7277
+ avif: "image/avif",
7278
+ jpeg: "image/jpeg",
7279
+ jpg: "image/jpeg",
7280
+ png: "image/png",
7281
+ gif: "image/gif"
7282
+ };
7283
+ return contentTypes[format] || "image/jpeg";
7284
+ }
7285
+ function negotiateFormat(acceptHeader, requestedFormat) {
7286
+ if (requestedFormat && ["webp", "avif", "jpeg", "png"].includes(requestedFormat)) {
7287
+ return requestedFormat;
7288
+ }
7289
+ const accept = acceptHeader?.toLowerCase() || "";
7290
+ if (accept.includes("image/avif")) {
7291
+ return "avif";
7292
+ }
7293
+ if (accept.includes("image/webp")) {
7294
+ return "webp";
7295
+ }
7296
+ return "jpeg";
7297
+ }
7298
+ async function loadFromDiskCache(cacheKey) {
7299
+ if (!diskCacheDir)
7300
+ return null;
7301
+ try {
7302
+ const cachePath = join6(diskCacheDir, `${cacheKey}.json`);
7303
+ const imagePath = join6(diskCacheDir, `${cacheKey}.img`);
7304
+ if (!(existsSync3(cachePath) && existsSync3(imagePath))) {
7305
+ return null;
7306
+ }
7307
+ const metadata3 = JSON.parse(await Bun.file(cachePath).text());
7308
+ const buffer = Buffer.from(await Bun.file(imagePath).arrayBuffer());
7309
+ return {
7310
+ buffer,
7311
+ contentType: metadata3.contentType,
7312
+ format: metadata3.format,
7313
+ width: metadata3.width,
7314
+ height: metadata3.height,
7315
+ size: metadata3.size
7316
+ };
7317
+ } catch {
7318
+ return null;
7319
+ }
7320
+ }
7321
+ async function saveToDiskCache(cacheKey, result) {
7322
+ if (!diskCacheDir)
7323
+ return;
7324
+ try {
7325
+ const cachePath = join6(diskCacheDir, `${cacheKey}.json`);
7326
+ const imagePath = join6(diskCacheDir, `${cacheKey}.img`);
7327
+ await Bun.write(cachePath, JSON.stringify({
7328
+ contentType: result.contentType,
7329
+ format: result.format,
7330
+ width: result.width,
7331
+ height: result.height,
7332
+ size: result.size
7333
+ }));
7334
+ await Bun.write(imagePath, result.buffer);
7335
+ } catch (error) {
7336
+ console.error("Failed to save image to disk cache:", error);
7337
+ }
7338
+ }
7339
+ async function fetchImageBuffer(imagePath) {
7340
+ if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
7341
+ const response = await fetch(imagePath);
7342
+ if (!response.ok) {
7343
+ throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);
7344
+ }
7345
+ const arrayBuffer = await response.arrayBuffer();
7346
+ return Buffer.from(arrayBuffer);
7347
+ }
7348
+ return Buffer.from(await Bun.file(imagePath).arrayBuffer());
7349
+ }
7350
+ function applyFormatTransform(transformer, format, quality) {
7351
+ switch (format) {
7352
+ case "webp":
7353
+ return transformer.webp({ quality, effort: 4 });
7354
+ case "avif":
7355
+ return transformer.avif({ quality, effort: 4 });
7356
+ case "png":
7357
+ return transformer.png({
7358
+ quality,
7359
+ compressionLevel: 9,
7360
+ adaptiveFiltering: true
7361
+ });
7362
+ default:
7363
+ return transformer.jpeg({ quality, mozjpeg: true });
7364
+ }
7365
+ }
7366
+ function addToMemoryCache(cacheKey, result) {
7367
+ if (imageCache.size >= MAX_CACHE_SIZE) {
7368
+ const firstKey = imageCache.keys().next().value;
7369
+ if (firstKey) {
7370
+ imageCache.delete(firstKey);
7371
+ }
7372
+ }
7373
+ imageCache.set(cacheKey, result);
7374
+ }
7375
+ async function optimizeImage(imagePath, options, acceptHeader) {
7376
+ const cacheKey = getCacheKey(imagePath, options);
7377
+ const memCached = imageCache.get(cacheKey);
7378
+ if (memCached) {
7379
+ return memCached;
7380
+ }
7381
+ const diskCached = await loadFromDiskCache(cacheKey);
7382
+ if (diskCached) {
7383
+ addToMemoryCache(cacheKey, diskCached);
7384
+ return diskCached;
7385
+ }
7386
+ const sourceBuffer = await fetchImageBuffer(imagePath);
7387
+ const format = options.format === "auto" || !options.format ? negotiateFormat(acceptHeader, undefined) : options.format;
7388
+ let transformer = sharp(sourceBuffer);
7389
+ const metadata3 = await transformer.metadata();
7390
+ if (options.width || options.height) {
7391
+ const resizeOptions = {
7392
+ width: options.width,
7393
+ height: options.height,
7394
+ fit: options.fit || "cover",
7395
+ withoutEnlargement: true
7396
+ };
7397
+ transformer = transformer.resize(resizeOptions);
7398
+ }
7399
+ const quality = options.quality ?? 75;
7400
+ transformer = applyFormatTransform(transformer, format, quality);
7401
+ const buffer = await transformer.toBuffer();
7402
+ const info = await sharp(buffer).metadata();
7403
+ const result = {
7404
+ buffer,
7405
+ contentType: getContentType(format),
7406
+ format,
7407
+ width: info.width || metadata3.width || options.width || 0,
7408
+ height: info.height || metadata3.height || options.height || 0,
7409
+ size: buffer.length
7410
+ };
7411
+ await saveToDiskCache(cacheKey, result);
7412
+ if (imageCache.size >= MAX_CACHE_SIZE) {
7413
+ const firstKey = imageCache.keys().next().value;
7414
+ if (firstKey) {
7415
+ imageCache.delete(firstKey);
7416
+ }
7417
+ }
7418
+ imageCache.set(cacheKey, result);
7419
+ return result;
7420
+ }
7421
+ function isImageFile(path3) {
7422
+ const imageExtensions = [".jpg", ".jpeg", ".png", ".webp", ".avif", ".gif"];
7423
+ const ext = path3.toLowerCase().split(".").pop();
7424
+ return ext ? imageExtensions.includes(`.${ext}`) : false;
7425
+ }
7426
+ function isPreprocessSource(path3) {
7427
+ return isImageFile(path3) && !path3.toLowerCase().endsWith(".gif");
7428
+ }
7429
+ function walkImageFiles(dir) {
7430
+ if (!existsSync3(dir)) {
7431
+ return [];
7432
+ }
7433
+ const files = [];
7434
+ const entries = readdirSync2(dir, { withFileTypes: true });
7435
+ for (const entry of entries) {
7436
+ const fullPath = join6(dir, entry.name);
7437
+ if (entry.isDirectory()) {
7438
+ files.push(...walkImageFiles(fullPath));
7439
+ } else if (isPreprocessSource(fullPath)) {
7440
+ files.push(fullPath);
7441
+ }
7442
+ }
7443
+ return files;
7444
+ }
7445
+ async function bakeVariant(cacheDir, imagePath, width, quality, format) {
7446
+ const transform = {
7447
+ width,
7448
+ quality,
7449
+ format,
7450
+ fit: "cover"
7451
+ };
7452
+ const cacheKey = getCacheKey(imagePath, transform);
7453
+ const existed = existsSync3(join6(cacheDir, `${cacheKey}.img`)) && existsSync3(join6(cacheDir, `${cacheKey}.json`));
7454
+ await optimizeImage(imagePath, transform, format === "auto" ? "image/webp" : undefined);
7455
+ return existed ? "cached" : "generated";
7456
+ }
7457
+ function preprocessJobs(options) {
7458
+ const sources = walkImageFiles(options.assetsDir);
7459
+ const formats = [
7460
+ ...options.formats,
7461
+ "auto"
7462
+ ];
7463
+ const qualities = options.qualities?.length ? options.qualities : [options.quality];
7464
+ return sources.flatMap((imagePath) => options.widths.flatMap((width) => qualities.flatMap((quality) => formats.map((format) => ({ imagePath, width, quality, format })))));
7465
+ }
7466
+ async function mapPool(items, concurrency, fn) {
7467
+ if (items.length === 0) {
7468
+ return [];
7469
+ }
7470
+ const results = new Array(items.length);
7471
+ let next = 0;
7472
+ const workers = Math.min(Math.max(1, concurrency), items.length);
7473
+ await Promise.all(Array.from({ length: workers }, async () => {
7474
+ while (next < items.length) {
7475
+ const index = next;
7476
+ next += 1;
7477
+ results[index] = await fn(items[index]);
7478
+ }
7479
+ }));
7480
+ return results;
7481
+ }
7482
+ function preprocessConcurrency(override) {
7483
+ if (override && override > 0) {
7484
+ return override;
7485
+ }
7486
+ return Math.max(1, cpus().length);
7487
+ }
7488
+ async function preprocessImages(options) {
7489
+ initImageCache(options.cacheDir);
7490
+ const jobs = preprocessJobs(options);
7491
+ const concurrency = preprocessConcurrency(options.concurrency);
7492
+ if (jobs.length > 0) {
7493
+ console.log(`[reroute] Preprocessing ${jobs.length} image variants (${concurrency} at a time)...`);
7494
+ }
7495
+ const previousSharpThreads = sharp.concurrency();
7496
+ sharp.concurrency(1);
7497
+ const results = await mapPool(jobs, concurrency, (job) => bakeVariant(options.cacheDir, job.imagePath, job.width, job.quality, job.format)).finally(() => {
7498
+ sharp.concurrency(previousSharpThreads);
7499
+ });
7500
+ let generated = 0;
7501
+ let cached = 0;
7502
+ for (const result of results) {
7503
+ if (result === "cached") {
7504
+ cached++;
7505
+ } else {
7506
+ generated++;
7507
+ }
7508
+ }
7509
+ const sources = new Set(jobs.map((job) => job.imagePath)).size;
7510
+ return { sources, generated, cached, jobs: jobs.length, concurrency };
7511
+ }
7512
+ var imageCache, MAX_CACHE_SIZE = 100, diskCacheDir = null;
7513
+ var init_image2 = __esm(() => {
7514
+ imageCache = new Map;
7515
+ });
7516
+
7517
+ // packages/cli/src/commands/lib/images.ts
7518
+ import { existsSync as existsSync4 } from "node:fs";
7519
+ import { join as join7 } from "node:path";
7520
+ function resolvePreprocessAssetsDir(cwd, config2) {
7521
+ const builtAssets = join7(cwd, ".reroute", "assets");
7522
+ if (existsSync4(builtAssets)) {
7523
+ return builtAssets;
7524
+ }
7525
+ return join7(cwd, resolveAppPaths(config2).assetsDir);
7526
+ }
7527
+ async function runImagePreprocess(cwd, config2) {
7528
+ const preprocess = resolveImagePreprocess(config2.image);
7529
+ if (!preprocess.enabled) {
7530
+ return;
7531
+ }
7532
+ const assetsDir = resolvePreprocessAssetsDir(cwd, config2);
7533
+ if (!existsSync4(assetsDir)) {
7534
+ console.log("[reroute] Image preprocess skipped (no assets directory)");
7535
+ return;
7536
+ }
7537
+ const started = performance.now();
7538
+ const result = await preprocessImages({
7539
+ assetsDir,
7540
+ cacheDir: join7(cwd, ".reroute", "image-cache"),
7541
+ widths: preprocess.widths,
7542
+ formats: preprocess.formats,
7543
+ quality: preprocess.quality,
7544
+ qualities: preprocess.qualities
7545
+ });
7546
+ const elapsed = ((performance.now() - started) / 1000).toFixed(2);
7547
+ console.log(`[reroute] Preprocessed ${result.sources} images → ${result.jobs} variants (${result.concurrency} at a time): ${result.generated} new, ${result.cached} cached (${elapsed}s)`);
7548
+ }
7549
+ var init_images = __esm(() => {
7550
+ init_core();
7551
+ init_image2();
7552
+ });
7553
+
7191
7554
  // packages/cli/src/commands/lib/markdown/availability.ts
7192
- import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
7193
- import { dirname as dirname2, join as join6 } from "node:path";
7555
+ import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
7556
+ import { dirname as dirname2, join as join8 } from "node:path";
7194
7557
  function isPackageAvailable(cwd, packageName) {
7195
7558
  let currentDir = cwd;
7196
7559
  for (let i = 0;i < 5; i++) {
7197
- const packageJsonPath = join6(currentDir, "package.json");
7198
- if (existsSync3(packageJsonPath)) {
7560
+ const packageJsonPath = join8(currentDir, "package.json");
7561
+ if (existsSync5(packageJsonPath)) {
7199
7562
  try {
7200
7563
  const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
7201
7564
  const deps = {
@@ -7265,8 +7628,8 @@ function checkMarkdownIfConfigured(cwd) {
7265
7628
  var init_availability = () => {};
7266
7629
 
7267
7630
  // packages/cli/src/commands/lib/markdown/processor.ts
7268
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
7269
- import { basename as basename3, dirname as dirname3, extname as extname3, join as join7, relative, resolve } from "node:path";
7631
+ import { existsSync as existsSync6, readFileSync as readFileSync3 } from "node:fs";
7632
+ import { basename as basename3, dirname as dirname3, extname as extname3, join as join9, relative, resolve } from "node:path";
7270
7633
  import matter from "gray-matter";
7271
7634
  function convertPropertiesToJsx(properties) {
7272
7635
  const newProperties = {};
@@ -7325,8 +7688,8 @@ function processMarkdownFile(filePath) {
7325
7688
  function isMdxAvailable2(cwd) {
7326
7689
  let currentDir = cwd;
7327
7690
  for (let i = 0;i < 5; i++) {
7328
- const packageJsonPath = join7(currentDir, "package.json");
7329
- if (existsSync4(packageJsonPath)) {
7691
+ const packageJsonPath = join9(currentDir, "package.json");
7692
+ if (existsSync6(packageJsonPath)) {
7330
7693
  try {
7331
7694
  const packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
7332
7695
  const deps = {
@@ -7349,10 +7712,10 @@ function isMdxAvailable2(cwd) {
7349
7712
  }
7350
7713
  function tryLoadModule(cwd, moduleName) {
7351
7714
  const pathsToTry = [
7352
- join7(cwd, `node_modules/${moduleName}`),
7353
- join7(cwd, `../node_modules/${moduleName}`),
7354
- join7(cwd, `../../node_modules/${moduleName}`),
7355
- join7(cwd, `../../../node_modules/${moduleName}`)
7715
+ join9(cwd, `node_modules/${moduleName}`),
7716
+ join9(cwd, `../node_modules/${moduleName}`),
7717
+ join9(cwd, `../../node_modules/${moduleName}`),
7718
+ join9(cwd, `../../../node_modules/${moduleName}`)
7356
7719
  ];
7357
7720
  for (const modulePath of pathsToTry) {
7358
7721
  try {
@@ -7677,12 +8040,15 @@ var init_markdown = __esm(() => {
7677
8040
  });
7678
8041
 
7679
8042
  // packages/cli/src/commands/lib/production.ts
8043
+ function hasProdFlag(args = []) {
8044
+ return args.includes("--prod") || args.includes("--production");
8045
+ }
7680
8046
  function isProductionMode(args = []) {
7681
- return args.includes("--prod");
8047
+ return hasProdFlag(args);
7682
8048
  }
7683
8049
 
7684
8050
  // packages/cli/src/commands/lib/streaming/analyzer.ts
7685
- import { dirname as dirname4, join as join8 } from "node:path";
8051
+ import { dirname as dirname4, join as join10 } from "node:path";
7686
8052
  function hasSSRDataExport(source) {
7687
8053
  if (SSR_DATA_INLINE_EXPORT_REGEX.test(source)) {
7688
8054
  return true;
@@ -7710,10 +8076,10 @@ async function analyzeRouteForStreaming(options) {
7710
8076
  }
7711
8077
  async function findSkeletonForTarget(routesDir, relativePath, type) {
7712
8078
  const dirName = normalizeRelativePath(dirname4(relativePath));
7713
- const baseDir = dirName === "." ? routesDir : join8(routesDir, dirName).replace(/\\/g, "/");
8079
+ const baseDir = dirName === "." ? routesDir : join10(routesDir, dirName).replace(/\\/g, "/");
7714
8080
  const candidates = type === "layout" ? ["[layout+skeleton].tsx", "[layout+skeleton].ts"] : ["[skeleton].tsx", "[skeleton].ts"];
7715
8081
  for (const candidate of candidates) {
7716
- const candidatePath = join8(baseDir, candidate);
8082
+ const candidatePath = join10(baseDir, candidate);
7717
8083
  try {
7718
8084
  const file = Bun.file(candidatePath);
7719
8085
  if (await file.exists()) {
@@ -7734,12 +8100,12 @@ var init_analyzer = __esm(() => {
7734
8100
  });
7735
8101
 
7736
8102
  // packages/cli/src/commands/lib/streaming/suspense.ts
7737
- import { dirname as dirname5, join as join9, relative as relative2 } from "node:path";
8103
+ import { dirname as dirname5, join as join11, relative as relative2 } from "node:path";
7738
8104
  async function generateStreamingWrapper(options) {
7739
8105
  const { cwd, relativeFilePath, analysis, config: config2 } = options;
7740
- const streamingModulePath = join9(cwd, ".reroute", "streaming", relativeFilePath).replace(/\.(tsx|ts)$/, ".tsx");
8106
+ const streamingModulePath = join11(cwd, ".reroute", "streaming", relativeFilePath).replace(/\.(tsx|ts)$/, ".tsx");
7741
8107
  const wrapperDir = dirname5(streamingModulePath);
7742
- const originalModuleWithoutExt = removeExtension(join9(cwd, resolveAppPaths(config2).routesDir, relativeFilePath));
8108
+ const originalModuleWithoutExt = removeExtension(join11(cwd, resolveAppPaths(config2).routesDir, relativeFilePath));
7743
8109
  const originalImportPath = toImportPath(wrapperDir, originalModuleWithoutExt);
7744
8110
  const skeletonImportBlock = await resolveSkeletonBlock({
7745
8111
  analysis,
@@ -7781,7 +8147,7 @@ async function resolveSkeletonBlock(args) {
7781
8147
  }
7782
8148
  function resolveConfiguredSkeletonPath(value, cwd) {
7783
8149
  if (typeof value === "string" && value.trim().length > 0) {
7784
- return value.startsWith("/") ? value : join9(cwd, value);
8150
+ return value.startsWith("/") ? value : join11(cwd, value);
7785
8151
  }
7786
8152
  if (value && !warnedSkeletonType) {
7787
8153
  console.warn("[reroute/streaming] default skeletons must be provided as string module paths in reroute.config.ts");
@@ -7819,13 +8185,13 @@ var init_suspense = __esm(() => {
7819
8185
 
7820
8186
  // packages/cli/src/commands/lib/theme.ts
7821
8187
  import { createHash as createHash2 } from "node:crypto";
7822
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
8188
+ import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
7823
8189
  import { mkdir as mkdir2, readdir as readdir7, unlink as unlink2, writeFile } from "node:fs/promises";
7824
- import { dirname as dirname6, isAbsolute, join as join10, resolve as resolve2 } from "node:path";
8190
+ import { dirname as dirname6, isAbsolute, join as join12, resolve as resolve2 } from "node:path";
7825
8191
  async function getCssPaths(cwd) {
7826
8192
  const paths = resolveAppPaths(await loadConfig(cwd));
7827
- const input = join10(cwd, paths.cssEntry);
7828
- const bundlesDir = join10(cwd, ".reroute/bundles");
8193
+ const input = join12(cwd, paths.cssEntry);
8194
+ const bundlesDir = join12(cwd, ".reroute/bundles");
7829
8195
  return { input, bundlesDir };
7830
8196
  }
7831
8197
  function themeCssFileName2(css) {
@@ -7850,7 +8216,7 @@ function bundleCssEntrypoint(entryPath) {
7850
8216
  if (stack.has(absPath)) {
7851
8217
  throw new Error(`[reroute/theme] Circular @import detected: ${absPath}`);
7852
8218
  }
7853
- if (!existsSync5(absPath)) {
8219
+ if (!existsSync7(absPath)) {
7854
8220
  throw new Error(`[reroute/theme] Missing CSS import: ${absPath}`);
7855
8221
  }
7856
8222
  stack.add(absPath);
@@ -7877,21 +8243,21 @@ async function pruneStaleThemeCss(bundlesDir, keep) {
7877
8243
  const files = await readdir7(bundlesDir);
7878
8244
  for (const file of files) {
7879
8245
  if (HASHED_THEME_RE2.test(file) && file !== keep) {
7880
- await unlink2(join10(bundlesDir, file));
8246
+ await unlink2(join12(bundlesDir, file));
7881
8247
  }
7882
8248
  }
7883
8249
  }
7884
8250
  async function syncThemeCss(cwd) {
7885
8251
  const { input, bundlesDir } = await getCssPaths(cwd);
7886
- if (!existsSync5(input)) {
8252
+ if (!existsSync7(input)) {
7887
8253
  return false;
7888
8254
  }
7889
8255
  await mkdir2(bundlesDir, { recursive: true });
7890
8256
  try {
7891
8257
  const css = bundleCssEntrypoint(input);
7892
8258
  const hashedName = themeCssFileName2(css);
7893
- await writeFile(join10(bundlesDir, "index.css"), css, "utf-8");
7894
- await writeFile(join10(bundlesDir, hashedName), css, "utf-8");
8259
+ await writeFile(join12(bundlesDir, "index.css"), css, "utf-8");
8260
+ await writeFile(join12(bundlesDir, hashedName), css, "utf-8");
7895
8261
  await pruneStaleThemeCss(bundlesDir, hashedName);
7896
8262
  } catch (err) {
7897
8263
  const message = err instanceof Error ? err.message : String(err);
@@ -7914,7 +8280,7 @@ var init_theme = __esm(() => {
7914
8280
  // packages/cli/src/commands/lib/watch.ts
7915
8281
  import { createHash as createHash3 } from "node:crypto";
7916
8282
  import { readFile } from "node:fs/promises";
7917
- import { join as join11 } from "node:path";
8283
+ import { join as join13 } from "node:path";
7918
8284
  function isWatchNoise(name) {
7919
8285
  return name.split(/[/\\]/).some((part) => part.startsWith(".")) || /\.bust-[^/\\]+$/.test(name);
7920
8286
  }
@@ -7948,7 +8314,7 @@ function createContentFingerprint(options) {
7948
8314
  async function retainChangedFiles(root, names, fingerprint) {
7949
8315
  const changed = [];
7950
8316
  for (const name of names) {
7951
- if (await fingerprint.changed(join11(root, name))) {
8317
+ if (await fingerprint.changed(join13(root, name))) {
7952
8318
  changed.push(name);
7953
8319
  }
7954
8320
  }
@@ -7964,11 +8330,11 @@ __export(exports_gen, {
7964
8330
  });
7965
8331
  import { watch } from "node:fs";
7966
8332
  import { copyFile as copyFile2, mkdir as mkdir3, readdir as readdir8, rm, unlink as unlink3 } from "node:fs/promises";
7967
- import { dirname as dirname7, extname as extname4, join as join12 } from "node:path";
8333
+ import { dirname as dirname7, extname as extname4, join as join14 } from "node:path";
7968
8334
  import { pathToFileURL as pathToFileURL8 } from "node:url";
7969
8335
  async function bundleThemeCssIntoArtifacts(cwd) {
7970
- const cssPath = join12(cwd, ".reroute", "bundles", "index.css");
7971
- const artifactsPath = join12(cwd, OUTPUT_ARTIFACTS);
8336
+ const cssPath = join14(cwd, ".reroute", "bundles", "index.css");
8337
+ const artifactsPath = join14(cwd, OUTPUT_ARTIFACTS);
7972
8338
  try {
7973
8339
  const cssContent = await Bun.file(cssPath).text();
7974
8340
  if (!cssContent)
@@ -7994,7 +8360,7 @@ async function bundleThemeCssIntoArtifacts(cwd) {
7994
8360
  async function ensureOutputDir(cwd, options = {}) {
7995
8361
  const { clean = true } = options;
7996
8362
  try {
7997
- const outputPath = join12(cwd, OUTPUT_DIR);
8363
+ const outputPath = join14(cwd, OUTPUT_DIR);
7998
8364
  if (clean) {
7999
8365
  let needsCleanup = false;
8000
8366
  try {
@@ -8007,9 +8373,9 @@ async function ensureOutputDir(cwd, options = {}) {
8007
8373
  }
8008
8374
  }
8009
8375
  await mkdir3(outputPath, { recursive: true });
8010
- await mkdir3(join12(cwd, OUTPUT_COLLECTIONS_DIR), { recursive: true });
8011
- await mkdir3(join12(cwd, ".reroute/bundles"), { recursive: true });
8012
- await mkdir3(join12(cwd, ".reroute/streaming"), { recursive: true });
8376
+ await mkdir3(join14(cwd, OUTPUT_COLLECTIONS_DIR), { recursive: true });
8377
+ await mkdir3(join14(cwd, ".reroute/bundles"), { recursive: true });
8378
+ await mkdir3(join14(cwd, ".reroute/streaming"), { recursive: true });
8013
8379
  } catch {}
8014
8380
  }
8015
8381
  async function writeStubFiles(cwd, serverImport) {
@@ -8087,14 +8453,14 @@ import './artifacts';
8087
8453
  import './routes'; // Import routes (bundles all route components)
8088
8454
  import '${serverImport}';
8089
8455
  `;
8090
- await Bun.write(join12(cwd, OUTPUT_ROUTES), STUB_ROUTES);
8091
- await Bun.write(join12(cwd, OUTPUT_ROUTES_CLIENT), STUB_ROUTES);
8092
- await Bun.write(join12(cwd, OUTPUT_CONTENT_TS), STUB_CONTENT);
8093
- await Bun.write(join12(cwd, OUTPUT_ARTIFACTS), STUB_ARTIFACTS);
8094
- await Bun.write(join12(cwd, OUTPUT_ARTIFACTS_CLIENT), STUB_ARTIFACTS_CLIENT);
8095
- await Bun.write(join12(cwd, OUTPUT_ARTIFACTS_SERVER), STUB_ARTIFACTS_SERVER);
8096
- await Bun.write(join12(cwd, OUTPUT_INDEX), STUB_INDEX);
8097
- await Bun.write(join12(cwd, ".reroute/entry.ts"), stubEntry);
8456
+ await Bun.write(join14(cwd, OUTPUT_ROUTES), STUB_ROUTES);
8457
+ await Bun.write(join14(cwd, OUTPUT_ROUTES_CLIENT), STUB_ROUTES);
8458
+ await Bun.write(join14(cwd, OUTPUT_CONTENT_TS), STUB_CONTENT);
8459
+ await Bun.write(join14(cwd, OUTPUT_ARTIFACTS), STUB_ARTIFACTS);
8460
+ await Bun.write(join14(cwd, OUTPUT_ARTIFACTS_CLIENT), STUB_ARTIFACTS_CLIENT);
8461
+ await Bun.write(join14(cwd, OUTPUT_ARTIFACTS_SERVER), STUB_ARTIFACTS_SERVER);
8462
+ await Bun.write(join14(cwd, OUTPUT_INDEX), STUB_INDEX);
8463
+ await Bun.write(join14(cwd, ".reroute/entry.ts"), stubEntry);
8098
8464
  console.log("[reroute/gen] Initialized stub files");
8099
8465
  }
8100
8466
  function shouldSkipFile(relativePath, entryName) {
@@ -8116,8 +8482,8 @@ async function scanDirectory(dir, base = "") {
8116
8482
  const files = [];
8117
8483
  const entries = await readdir8(dir, { withFileTypes: true });
8118
8484
  for (const entry of entries) {
8119
- const fullPath = join12(dir, entry.name);
8120
- const relativePath = join12(base, entry.name);
8485
+ const fullPath = join14(dir, entry.name);
8486
+ const relativePath = join14(base, entry.name);
8121
8487
  if (entry.isDirectory()) {
8122
8488
  if (entry.name === "content")
8123
8489
  continue;
@@ -8135,8 +8501,8 @@ async function scan404Files(dir, base = "") {
8135
8501
  const files = [];
8136
8502
  const entries = await readdir8(dir, { withFileTypes: true });
8137
8503
  for (const entry of entries) {
8138
- const fullPath = join12(dir, entry.name);
8139
- const relativePath = join12(base, entry.name);
8504
+ const fullPath = join14(dir, entry.name);
8505
+ const relativePath = join14(base, entry.name);
8140
8506
  if (entry.isDirectory()) {
8141
8507
  const nested = await scan404Files(fullPath, relativePath);
8142
8508
  files.push(...nested);
@@ -8151,8 +8517,8 @@ async function scanOgFiles(dir, base = "") {
8151
8517
  const files = [];
8152
8518
  const entries = await readdir8(dir, { withFileTypes: true });
8153
8519
  for (const entry of entries) {
8154
- const fullPath = join12(dir, entry.name);
8155
- const relativePath = join12(base, entry.name);
8520
+ const fullPath = join14(dir, entry.name);
8521
+ const relativePath = join14(base, entry.name);
8156
8522
  if (entry.isDirectory()) {
8157
8523
  if (entry.name === "content")
8158
8524
  continue;
@@ -8420,7 +8786,7 @@ ${client ? "" : `// Set globals for compiled binary support (sitemap/RSS/robots
8420
8786
  `;
8421
8787
  }
8422
8788
  async function buildStreamingWrappersForTree(cwd, routesPath, tree, config2) {
8423
- const streamingDir = join12(cwd, ".reroute", "streaming");
8789
+ const streamingDir = join14(cwd, ".reroute", "streaming");
8424
8790
  const analyses = new Map;
8425
8791
  const candidates = [
8426
8792
  ...tree.routes.map((route) => ({
@@ -8439,7 +8805,7 @@ async function buildStreamingWrappersForTree(cwd, routesPath, tree, config2) {
8439
8805
  for (const candidate of candidates) {
8440
8806
  if (!/\.(tsx|ts)$/.test(candidate.filePath))
8441
8807
  continue;
8442
- const absolutePath = join12(routesPath, candidate.filePath);
8808
+ const absolutePath = join14(routesPath, candidate.filePath);
8443
8809
  const analysis = await analyzeRouteForStreaming({
8444
8810
  absolutePath,
8445
8811
  relativePath: candidate.filePath,
@@ -8448,7 +8814,7 @@ async function buildStreamingWrappersForTree(cwd, routesPath, tree, config2) {
8448
8814
  });
8449
8815
  if (!analysis.needsStreaming)
8450
8816
  continue;
8451
- const wrapperPath = join12(streamingDir, candidate.filePath).replace(/\.(tsx|ts)$/, ".tsx");
8817
+ const wrapperPath = join14(streamingDir, candidate.filePath).replace(/\.(tsx|ts)$/, ".tsx");
8452
8818
  await mkdir3(dirname7(wrapperPath), { recursive: true });
8453
8819
  const code = await generateStreamingWrapper({
8454
8820
  cwd,
@@ -8473,13 +8839,13 @@ function isContentFileName(name) {
8473
8839
  }
8474
8840
  async function listLocaleContentFiles(collectionDir, locale) {
8475
8841
  try {
8476
- const nested = await readdir8(join12(collectionDir, locale), {
8842
+ const nested = await readdir8(join14(collectionDir, locale), {
8477
8843
  withFileTypes: true
8478
8844
  });
8479
8845
  const files = [];
8480
8846
  for (const n of nested) {
8481
8847
  if (n.isFile() && isContentFileName(n.name)) {
8482
- files.push({ relativePath: join12(locale, n.name), locale });
8848
+ files.push({ relativePath: join14(locale, n.name), locale });
8483
8849
  }
8484
8850
  }
8485
8851
  return files;
@@ -8517,7 +8883,7 @@ async function loadContentMeta(absSrc, buildSrc, isMarkdown) {
8517
8883
  if (isMarkdown) {
8518
8884
  return processMarkdownFile(absSrc).frontmatter || {};
8519
8885
  }
8520
- const tmp = join12(dirname7(buildSrc), `.meta-${Date.now()}-${Math.random().toString(36).slice(2)}${extname4(buildSrc)}`);
8886
+ const tmp = join14(dirname7(buildSrc), `.meta-${Date.now()}-${Math.random().toString(36).slice(2)}${extname4(buildSrc)}`);
8521
8887
  try {
8522
8888
  await copyFile2(buildSrc, tmp);
8523
8889
  const m = await import(pathToFileURL8(tmp).href);
@@ -8570,14 +8936,24 @@ ${spaces}}`;
8570
8936
  }
8571
8937
  return serializeValue(config2);
8572
8938
  }
8939
+ function imageRuntimeSnippet(config2) {
8940
+ const preprocess = resolveImagePreprocess(config2.image);
8941
+ if (!preprocess.enabled) {
8942
+ return null;
8943
+ }
8944
+ return `(globalThis as any).__REROUTE_IMAGE__ = ${JSON.stringify({
8945
+ sizes: preprocess.widths,
8946
+ quality: preprocess.quality
8947
+ })};`;
8948
+ }
8573
8949
  async function buildSingleContentChunk(cwd, collection, fileRef, contentDir, args, defaultLocale) {
8574
8950
  const file = fileRef.relativePath;
8575
8951
  const locale = fileRef.locale || defaultLocale;
8576
8952
  const baseName = file.split("/").pop() || file;
8577
8953
  const name = baseName.replace(/\.(tsx|ts|md|mdx)$/, "");
8578
- const absSrc = join12(contentDir, file);
8954
+ const absSrc = join14(contentDir, file);
8579
8955
  const isMarkdown = /\.(md|mdx)$/.test(file);
8580
- const buildSrc = isMarkdown ? join12(cwd, ".reroute", "markdown", collection, "content", file.replace(/\.(md|mdx)$/, ".tsx")) : absSrc;
8956
+ const buildSrc = isMarkdown ? join14(cwd, ".reroute", "markdown", collection, "content", file.replace(/\.(md|mdx)$/, ".tsx")) : absSrc;
8581
8957
  if (isMarkdown) {
8582
8958
  try {
8583
8959
  const exists = await Bun.file(buildSrc).exists();
@@ -8623,11 +8999,11 @@ async function buildSingleContentChunk(cwd, collection, fileRef, contentDir, arg
8623
8999
  return null;
8624
9000
  }
8625
9001
  const hash2 = await sha8(code);
8626
- const chunkRelDir = join12(".reroute", "bundles");
8627
- const chunkAbsDir = join12(cwd, chunkRelDir);
9002
+ const chunkRelDir = join14(".reroute", "bundles");
9003
+ const chunkAbsDir = join14(cwd, chunkRelDir);
8628
9004
  const localeSuffix = locale !== defaultLocale ? `${locale}-` : "";
8629
9005
  const outFile = `${collection}-${localeSuffix}${name}.${hash2}.js`;
8630
- const absOut = join12(chunkAbsDir, outFile);
9006
+ const absOut = join14(chunkAbsDir, outFile);
8631
9007
  if (sourcemapContent) {
8632
9008
  code = code.replace(/\/\/# sourceMappingURL=.*\.js\.map/, `//# sourceMappingURL=${outFile}.map`);
8633
9009
  }
@@ -8660,7 +9036,7 @@ async function buildSingleContentChunk(cwd, collection, fileRef, contentDir, arg
8660
9036
  };
8661
9037
  }
8662
9038
  async function buildContentChunks(cwd, args = [], defaultLocale = "en-US", routesDir) {
8663
- const routesRoot = join12(cwd, routesDir);
9039
+ const routesRoot = join14(cwd, routesDir);
8664
9040
  console.log(`[reroute/content] scan ${routesRoot}`);
8665
9041
  const collections2 = await readdir8(routesRoot, { withFileTypes: true });
8666
9042
  const results = [];
@@ -8668,7 +9044,7 @@ async function buildContentChunks(cwd, args = [], defaultLocale = "en-US", route
8668
9044
  if (!c.isDirectory())
8669
9045
  continue;
8670
9046
  const collection = c.name;
8671
- const contentDir = join12(routesRoot, collection, "content");
9047
+ const contentDir = join14(routesRoot, collection, "content");
8672
9048
  console.log(`[reroute/content] collection ${collection} dir ${contentDir}`);
8673
9049
  const files = await listContentFiles2(contentDir);
8674
9050
  console.log(`[reroute/content] files ${files.length}`);
@@ -8720,7 +9096,7 @@ async function buildContentChunks(cwd, args = [], defaultLocale = "en-US", route
8720
9096
  lines.push("");
8721
9097
  const writes = [];
8722
9098
  writes.push({
8723
- path: join12(cwd, OUTPUT_CONTENT_TS),
9099
+ path: join14(cwd, OUTPUT_CONTENT_TS),
8724
9100
  content: lines.join(`
8725
9101
  `)
8726
9102
  });
@@ -8754,7 +9130,7 @@ async function buildContentChunks(cwd, args = [], defaultLocale = "en-US", route
8754
9130
  js.push("}");
8755
9131
  js.push("");
8756
9132
  writes.push({
8757
- path: join12(cwd, OUTPUT_COLLECTIONS_DIR, `${collection}.js`),
9133
+ path: join14(cwd, OUTPUT_COLLECTIONS_DIR, `${collection}.js`),
8758
9134
  content: js.join(`
8759
9135
  `)
8760
9136
  });
@@ -8778,7 +9154,7 @@ async function buildSearchIndex(cwd, config2, args = []) {
8778
9154
  minHeadingLevel = 1,
8779
9155
  maxHeadingLevel = 6
8780
9156
  } = searchConfig;
8781
- const routesRoot = join12(cwd, resolveAppPaths(config2).routesDir);
9157
+ const routesRoot = join14(cwd, resolveAppPaths(config2).routesDir);
8782
9158
  const collections2 = await readdir8(routesRoot, { withFileTypes: true });
8783
9159
  const i18n2 = await discoverI18n(cwd, config2.i18n);
8784
9160
  const defaultLocale = i18n2.defaultLocale;
@@ -8790,7 +9166,7 @@ async function buildSearchIndex(cwd, config2, args = []) {
8790
9166
  if (targetCollections.length > 0 && !targetCollections.includes(collection)) {
8791
9167
  continue;
8792
9168
  }
8793
- const contentDir = join12(routesRoot, collection, "content");
9169
+ const contentDir = join14(routesRoot, collection, "content");
8794
9170
  try {
8795
9171
  const files = await listContentFiles2(contentDir);
8796
9172
  for (const fileRef of files) {
@@ -8800,7 +9176,7 @@ async function buildSearchIndex(cwd, config2, args = []) {
8800
9176
  const baseName = file.split("/").pop() || file;
8801
9177
  const name = baseName.replace(/\.(md|mdx)$/, "");
8802
9178
  const locale = fileRef.locale || defaultLocale;
8803
- const filePath = join12(contentDir, file);
9179
+ const filePath = join14(contentDir, file);
8804
9180
  try {
8805
9181
  const processed = processMarkdownFile(filePath);
8806
9182
  const { frontmatter, content: content2 } = processed;
@@ -8848,13 +9224,13 @@ async function buildSearchIndex(cwd, config2, args = []) {
8848
9224
  generated: new Date().toISOString(),
8849
9225
  entries: searchIndex
8850
9226
  };
8851
- await Bun.write(join12(cwd, OUTPUT_SEARCH_INDEX), JSON.stringify(indexData, null, 2));
8852
- console.log(`[reroute/search] Generated search index with ${searchIndex.length} entries: ${join12(cwd, OUTPUT_SEARCH_INDEX)}`);
9227
+ await Bun.write(join14(cwd, OUTPUT_SEARCH_INDEX), JSON.stringify(indexData, null, 2));
9228
+ console.log(`[reroute/search] Generated search index with ${searchIndex.length} entries: ${join14(cwd, OUTPUT_SEARCH_INDEX)}`);
8853
9229
  }
8854
9230
  async function preprocessMarkdownFiles(cwd, config2) {
8855
9231
  console.log("[reroute/markdown] Starting markdown preprocessing...");
8856
- const routesPath = join12(cwd, resolveAppPaths(config2).routesDir);
8857
- const markdownDir = join12(cwd, ".reroute", "markdown");
9232
+ const routesPath = join14(cwd, resolveAppPaths(config2).routesDir);
9233
+ const markdownDir = join14(cwd, ".reroute", "markdown");
8858
9234
  try {
8859
9235
  await rm(markdownDir, { force: true, recursive: true });
8860
9236
  } catch {}
@@ -8864,8 +9240,8 @@ async function preprocessMarkdownFiles(cwd, config2) {
8864
9240
  try {
8865
9241
  const entries = await readdir8(dir, { withFileTypes: true });
8866
9242
  for (const entry of entries) {
8867
- const fullPath = join12(dir, entry.name);
8868
- const relativePath = join12(base, entry.name);
9243
+ const fullPath = join14(dir, entry.name);
9244
+ const relativePath = join14(base, entry.name);
8869
9245
  if (entry.isDirectory()) {
8870
9246
  const nested = await scanMarkdown(fullPath, relativePath);
8871
9247
  files.push(...nested);
@@ -8887,8 +9263,8 @@ async function preprocessMarkdownFiles(cwd, config2) {
8887
9263
  }
8888
9264
  console.log(`[reroute/markdown] Found ${markdownFiles.length} markdown file(s)`);
8889
9265
  for (const file of markdownFiles) {
8890
- const sourcePath = join12(routesPath, file);
8891
- const targetPath = join12(markdownDir, file.replace(/\.mdx?$/, ".tsx"));
9266
+ const sourcePath = join14(routesPath, file);
9267
+ const targetPath = join14(markdownDir, file.replace(/\.mdx?$/, ".tsx"));
8892
9268
  try {
8893
9269
  const processed = processMarkdownFile(sourcePath);
8894
9270
  const isMdx = file.endsWith(".mdx");
@@ -8915,9 +9291,9 @@ async function preprocessMarkdownFiles(cwd, config2) {
8915
9291
  async function buildEntrypointBundle(cwd, args = []) {
8916
9292
  const buildStartTime = performance.now();
8917
9293
  const paths = resolveAppPaths(await loadConfig(cwd));
8918
- const clientDir = join12(cwd, paths.clientDir);
8919
- const userEntrypoint = join12(clientDir, "index.tsx");
8920
- const entrypoint = join12(cwd, OUTPUT_CLIENT_ENTRY);
9294
+ const clientDir = join14(cwd, paths.clientDir);
9295
+ const userEntrypoint = join14(clientDir, "index.tsx");
9296
+ const entrypoint = join14(cwd, OUTPUT_CLIENT_ENTRY);
8921
9297
  const exists = await Bun.file(userEntrypoint).exists();
8922
9298
  if (!exists) {
8923
9299
  console.log("[reroute/gen] No index.tsx found, skipping bundle build");
@@ -8929,8 +9305,8 @@ async function buildEntrypointBundle(cwd, args = []) {
8929
9305
  return;
8930
9306
  }
8931
9307
  console.log("[reroute/gen] Building entrypoint bundle...");
8932
- const isProd = args.includes("--prod");
8933
- const bundlesDir = join12(cwd, ".reroute", "bundles");
9308
+ const isProd = isProductionMode(args);
9309
+ const bundlesDir = join14(cwd, ".reroute", "bundles");
8934
9310
  await mkdir3(bundlesDir, { recursive: true });
8935
9311
  const mode = isProd ? "production" : "development";
8936
9312
  const publicEnv = getPublicEnvVars(cwd, mode);
@@ -9032,7 +9408,7 @@ async function buildEntrypointBundle(cwd, args = []) {
9032
9408
  const existingFiles = await readdir8(bundlesDir);
9033
9409
  for (const file of existingFiles) {
9034
9410
  if (/^(index|chunk|asset)\.[a-z0-9]+\.(js|css|js\.map|css\.map)(\.gz|\.br)?$/i.test(file) && !newFiles.has(file.replace(/\.(gz|br)$/, ""))) {
9035
- await rm(join12(bundlesDir, file), { force: true });
9411
+ await rm(join14(bundlesDir, file), { force: true });
9036
9412
  }
9037
9413
  }
9038
9414
  } catch (_error) {}
@@ -9048,7 +9424,7 @@ async function buildEntrypointBundle(cwd, args = []) {
9048
9424
  }
9049
9425
  }
9050
9426
  await Promise.all(outputs.map(async (output) => {
9051
- const destPath = join12(bundlesDir, output.fileName);
9427
+ const destPath = join14(bundlesDir, output.fileName);
9052
9428
  await Bun.write(destPath, output.content);
9053
9429
  if (shouldPreCompress) {
9054
9430
  const shouldCompress = /\.(js|css)$/i.test(output.fileName) && !output.fileName.endsWith(".map");
@@ -9119,7 +9495,7 @@ async function generate(cwd, args = [], options = {}) {
9119
9495
  await writeStubFiles(cwd, importFromReroute(paths.server));
9120
9496
  }
9121
9497
  await perfTrack("Markdown preprocessing", () => preprocessMarkdownFiles(cwd, config2));
9122
- const routesPath = join12(cwd, paths.routesDir);
9498
+ const routesPath = join14(cwd, paths.routesDir);
9123
9499
  try {
9124
9500
  await perfTrack("Routes generation", async () => {
9125
9501
  const files = await scanDirectory(routesPath);
@@ -9129,11 +9505,11 @@ async function generate(cwd, args = [], options = {}) {
9129
9505
  const streamingAnalyses = streamingEnabled ? await buildStreamingWrappersForTree(cwd, routesPath, tree, config2) : new Map;
9130
9506
  const serverRoutes = generateTypeScript(tree, streamingAnalyses, false, routesImportBase);
9131
9507
  const clientRoutes = generateTypeScript(tree, streamingAnalyses, true, routesImportBase);
9132
- await Bun.write(join12(cwd, OUTPUT_ROUTES), serverRoutes);
9133
- await Bun.write(join12(cwd, OUTPUT_ROUTES_CLIENT), clientRoutes);
9508
+ await Bun.write(join14(cwd, OUTPUT_ROUTES), serverRoutes);
9509
+ await Bun.write(join14(cwd, OUTPUT_ROUTES_CLIENT), clientRoutes);
9134
9510
  });
9135
9511
  if (!showPerformance) {
9136
- console.log(`[reroute/gen] Generated routes: ${join12(cwd, OUTPUT_ROUTES)} + ${OUTPUT_ROUTES_CLIENT}`);
9512
+ console.log(`[reroute/gen] Generated routes: ${join14(cwd, OUTPUT_ROUTES)} + ${OUTPUT_ROUTES_CLIENT}`);
9137
9513
  }
9138
9514
  } catch (error) {
9139
9515
  console.error("[reroute/gen] Failed to generate routes:", error);
@@ -9142,7 +9518,7 @@ async function generate(cwd, args = [], options = {}) {
9142
9518
  const i18n2 = await discoverI18n(cwd, config2.i18n);
9143
9519
  const defaultLocale = i18n2.defaultLocale;
9144
9520
  try {
9145
- await Bun.write(join12(cwd, ".reroute", "i18n.json"), JSON.stringify({
9521
+ await Bun.write(join14(cwd, ".reroute", "i18n.json"), JSON.stringify({
9146
9522
  enabled: i18n2.enabled,
9147
9523
  defaultLocale: i18n2.defaultLocale,
9148
9524
  locales: i18n2.locales,
@@ -9159,7 +9535,7 @@ async function generate(cwd, args = [], options = {}) {
9159
9535
  try {
9160
9536
  await perfTrack("Content building", () => buildContentChunks(cwd, args, defaultLocale, paths.routesDir));
9161
9537
  if (!showPerformance) {
9162
- console.log(`[reroute/gen] Generated content: ${join12(cwd, OUTPUT_CONTENT_TS)} + collections/*.js`);
9538
+ console.log(`[reroute/gen] Generated content: ${join14(cwd, OUTPUT_CONTENT_TS)} + collections/*.js`);
9163
9539
  }
9164
9540
  } catch (error) {
9165
9541
  console.error("[reroute/gen] Failed to generate content:", error);
@@ -9167,17 +9543,17 @@ async function generate(cwd, args = [], options = {}) {
9167
9543
  }
9168
9544
  try {
9169
9545
  await perfTrack("Manifest generation", async () => {
9170
- const routesPath2 = join12(cwd, OUTPUT_ROUTES);
9546
+ const routesPath2 = join14(cwd, OUTPUT_ROUTES);
9171
9547
  const routesModule = await import(`file://${routesPath2}?t=${Date.now()}`);
9172
9548
  const routes = routesModule.routes || [];
9173
9549
  const staticRoutes = routes.filter((r) => !r.params || r.params.length === 0).map((r) => r.pattern);
9174
9550
  const contentRoutes = [];
9175
- const collectionsDir = join12(cwd, ".reroute", "collections");
9551
+ const collectionsDir = join14(cwd, ".reroute", "collections");
9176
9552
  try {
9177
9553
  const collectionFiles = await readdir8(collectionsDir);
9178
9554
  for (const file of collectionFiles) {
9179
9555
  if (file.endsWith(".js")) {
9180
- const collectionPath = join12(collectionsDir, file);
9556
+ const collectionPath = join14(collectionsDir, file);
9181
9557
  const collectionModule = await import(`file://${collectionPath}?t=${Date.now()}`);
9182
9558
  const items = collectionModule.items || [];
9183
9559
  for (const item of items) {
@@ -9202,7 +9578,7 @@ async function generate(cwd, args = [], options = {}) {
9202
9578
  dynamicRoutes,
9203
9579
  version: 1
9204
9580
  };
9205
- await Bun.write(join12(cwd, ".reroute", "manifest.json"), JSON.stringify(manifest, null, 2));
9581
+ await Bun.write(join14(cwd, ".reroute", "manifest.json"), JSON.stringify(manifest, null, 2));
9206
9582
  });
9207
9583
  } catch (error) {
9208
9584
  console.error("[reroute/gen] Failed to generate manifest:", error);
@@ -9223,7 +9599,7 @@ async function generate(cwd, args = [], options = {}) {
9223
9599
  mdComponentsLines.push("");
9224
9600
  mdComponentsLines.push(`import markdownComponents from '${componentsPath}';`);
9225
9601
  mdComponentsLines.push("export { markdownComponents };");
9226
- await Bun.write(join12(cwd, ".reroute/markdown-components.ts"), mdComponentsLines.join(`
9602
+ await Bun.write(join14(cwd, ".reroute/markdown-components.ts"), mdComponentsLines.join(`
9227
9603
  `));
9228
9604
  }
9229
9605
  const buildArtifactsLines = (routesModule) => {
@@ -9249,7 +9625,7 @@ async function generate(cwd, args = [], options = {}) {
9249
9625
  const ogTemplatePath = config2.ogImage.defaultTemplate.startsWith(".") ? `../${config2.ogImage.defaultTemplate}` : config2.ogImage.defaultTemplate;
9250
9626
  indexLines.push(`import OGTemplate from '${ogTemplatePath}';`);
9251
9627
  }
9252
- const ogFiles = await scanOgFiles(join12(cwd, paths.routesDir));
9628
+ const ogFiles = await scanOgFiles(join14(cwd, paths.routesDir));
9253
9629
  const ogImports = [];
9254
9630
  for (let i = 0;i < ogFiles.length; i++) {
9255
9631
  const ogFile = ogFiles[i];
@@ -9295,7 +9671,7 @@ async function generate(cwd, args = [], options = {}) {
9295
9671
  }
9296
9672
  indexLines.push("};");
9297
9673
  }
9298
- const templatePath = join12(cwd, paths.clientDir, "index.html");
9674
+ const templatePath = join14(cwd, paths.clientDir, "index.html");
9299
9675
  try {
9300
9676
  const templateContent = await Bun.file(templatePath).text();
9301
9677
  indexLines.push("");
@@ -9305,6 +9681,10 @@ async function generate(cwd, args = [], options = {}) {
9305
9681
  indexLines.push("");
9306
9682
  indexLines.push("// Bundled config for compiled binary support");
9307
9683
  indexLines.push(`(globalThis as any).__REROUTE_CONFIG__ = ${serializeConfig(config2)};`);
9684
+ const imageRuntime = imageRuntimeSnippet(config2);
9685
+ if (imageRuntime) {
9686
+ indexLines.push(imageRuntime);
9687
+ }
9308
9688
  indexLines.push("");
9309
9689
  indexLines.push("export type RerouteBundle = typeof bundle;");
9310
9690
  indexLines.push("");
@@ -9326,6 +9706,9 @@ async function generate(cwd, args = [], options = {}) {
9326
9706
  clientLines.push("export type RerouteBundle = typeof bundle;");
9327
9707
  clientLines.push("");
9328
9708
  clientLines.push("(globalThis as any).__REROUTE_CLIENT_BUNDLE__ = bundle;");
9709
+ if (imageRuntime) {
9710
+ clientLines.push(imageRuntime);
9711
+ }
9329
9712
  const barrelArtifacts = [
9330
9713
  "// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8",
9331
9714
  "// Client bundle entry — lazy routes only",
@@ -9335,11 +9718,11 @@ async function generate(cwd, args = [], options = {}) {
9335
9718
  "export * from './artifacts.client';"
9336
9719
  ].join(`
9337
9720
  `);
9338
- await Bun.write(join12(cwd, OUTPUT_ARTIFACTS_SERVER), indexLines.join(`
9721
+ await Bun.write(join14(cwd, OUTPUT_ARTIFACTS_SERVER), indexLines.join(`
9339
9722
  `));
9340
- await Bun.write(join12(cwd, OUTPUT_ARTIFACTS_CLIENT), clientLines.join(`
9723
+ await Bun.write(join14(cwd, OUTPUT_ARTIFACTS_CLIENT), clientLines.join(`
9341
9724
  `));
9342
- await Bun.write(join12(cwd, OUTPUT_ARTIFACTS), barrelArtifacts);
9725
+ await Bun.write(join14(cwd, OUTPUT_ARTIFACTS), barrelArtifacts);
9343
9726
  const barrelLines = [
9344
9727
  "// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8",
9345
9728
  "// Barrel export for client imports",
@@ -9348,7 +9731,7 @@ async function generate(cwd, args = [], options = {}) {
9348
9731
  "",
9349
9732
  "export * from './artifacts';"
9350
9733
  ];
9351
- await Bun.write(join12(cwd, OUTPUT_INDEX), barrelLines.join(`
9734
+ await Bun.write(join14(cwd, OUTPUT_INDEX), barrelLines.join(`
9352
9735
  `));
9353
9736
  const entryLines = [
9354
9737
  "// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8",
@@ -9364,7 +9747,7 @@ async function generate(cwd, args = [], options = {}) {
9364
9747
  "import './routes'; // Route metadata for compiled binary discovery",
9365
9748
  `import '${importFromReroute(paths.server)}'; // Import user's server entry`
9366
9749
  ];
9367
- await Bun.write(join12(cwd, ".reroute/entry.ts"), entryLines.join(`
9750
+ await Bun.write(join14(cwd, ".reroute/entry.ts"), entryLines.join(`
9368
9751
  `));
9369
9752
  const clientEntryLines = [
9370
9753
  "// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8",
@@ -9373,14 +9756,17 @@ async function generate(cwd, args = [], options = {}) {
9373
9756
  "// @ts-nocheck",
9374
9757
  "",
9375
9758
  "import './artifacts.client'; // Client bundle (lazy routes)",
9376
- `import '${importFromReroute(join12(paths.clientDir, "index.tsx"))}'; // User hydration entry`
9759
+ `import '${importFromReroute(join14(paths.clientDir, "index.tsx"))}'; // User hydration entry`
9377
9760
  ];
9378
- await Bun.write(join12(cwd, OUTPUT_CLIENT_ENTRY), clientEntryLines.join(`
9761
+ await Bun.write(join14(cwd, OUTPUT_CLIENT_ENTRY), clientEntryLines.join(`
9379
9762
  `));
9380
9763
  if (!showPerformance) {
9381
- console.log(`[reroute/gen] Generated artifacts: ${join12(cwd, OUTPUT_ARTIFACTS)}`);
9764
+ console.log(`[reroute/gen] Generated artifacts: ${join14(cwd, OUTPUT_ARTIFACTS)}`);
9382
9765
  }
9383
9766
  await perfTrack("Bundle building", () => buildEntrypointBundle(cwd, args));
9767
+ if (isProductionMode(args)) {
9768
+ await perfTrack("Image preprocessing", () => runImagePreprocess(cwd, config2));
9769
+ }
9384
9770
  const endTime = performance.now();
9385
9771
  const duration = ((endTime - startTime) / 1000).toFixed(2);
9386
9772
  if (showPerformance) {
@@ -9500,7 +9886,7 @@ async function startGenWatch(cwd, args) {
9500
9886
  const slowDebounce = createDebouncer(300);
9501
9887
  const fingerprint = createContentFingerprint();
9502
9888
  const loadedConfig = await loadConfig(cwd);
9503
- const configPath = join12(cwd, "reroute.config.ts");
9889
+ const configPath = join14(cwd, "reroute.config.ts");
9504
9890
  let configWatcher = null;
9505
9891
  try {
9506
9892
  configWatcher = watch(configPath, () => {
@@ -9526,7 +9912,7 @@ async function startGenWatch(cwd, args) {
9526
9912
  ];
9527
9913
  const envWatchers = [];
9528
9914
  for (const envFile of envFiles) {
9529
- const envPath = join12(cwd, envFile);
9915
+ const envPath = join14(cwd, envFile);
9530
9916
  try {
9531
9917
  const envWatcher = watch(envPath, () => {
9532
9918
  mediumDebounce(() => {
@@ -9549,15 +9935,15 @@ async function startGenWatch(cwd, args) {
9549
9935
  let packagesWatcher = null;
9550
9936
  const isRerouteWorkspace = async () => {
9551
9937
  try {
9552
- const packagesPath = join12(cwd, "..", "..", "packages");
9553
- const exists = await Bun.file(join12(packagesPath, "core", "index.ts")).exists();
9938
+ const packagesPath = join14(cwd, "..", "..", "packages");
9939
+ const exists = await Bun.file(join14(packagesPath, "core", "index.ts")).exists();
9554
9940
  return exists;
9555
9941
  } catch {
9556
9942
  return false;
9557
9943
  }
9558
9944
  };
9559
9945
  if (await isRerouteWorkspace()) {
9560
- const packagesPath = join12(cwd, "..", "..", "packages");
9946
+ const packagesPath = join14(cwd, "..", "..", "packages");
9561
9947
  console.log("[reroute/watch] \uD83D\uDD27 Workspace development mode enabled");
9562
9948
  console.log(`[reroute/watch] \uD83D\uDD27 Watching ${packagesPath}...`);
9563
9949
  packagesWatcher = watch(packagesPath, { recursive: true }, (_ev, filename) => {
@@ -9571,7 +9957,7 @@ async function startGenWatch(cwd, args) {
9571
9957
  if (!/\.(tsx|ts|jsx|js)$/.test(name))
9572
9958
  return;
9573
9959
  slowDebounce(() => {
9574
- fingerprint.changed(join12(packagesPath, name)).then((changed) => {
9960
+ fingerprint.changed(join14(packagesPath, name)).then((changed) => {
9575
9961
  if (!changed)
9576
9962
  return;
9577
9963
  scheduleBuild(async () => {
@@ -9587,7 +9973,7 @@ async function startGenWatch(cwd, args) {
9587
9973
  });
9588
9974
  }
9589
9975
  const watchPaths = resolveAppPaths(loadedConfig);
9590
- const routesPath = join12(cwd, watchPaths.routesDir);
9976
+ const routesPath = join14(cwd, watchPaths.routesDir);
9591
9977
  console.log(`[reroute/watch] \uD83D\uDCC1 Watching ${routesPath}...`);
9592
9978
  const routesWatcher = watch(routesPath, { recursive: true }, (_ev, filename) => {
9593
9979
  if (!filename)
@@ -9596,7 +9982,7 @@ async function startGenWatch(cwd, args) {
9596
9982
  if (isWatchNoise(name))
9597
9983
  return;
9598
9984
  quickDebounce(() => {
9599
- fingerprint.changed(join12(routesPath, name)).then((changed) => {
9985
+ fingerprint.changed(join14(routesPath, name)).then((changed) => {
9600
9986
  if (!changed)
9601
9987
  return;
9602
9988
  scheduleBuild(async () => {
@@ -9615,7 +10001,7 @@ async function startGenWatch(cwd, args) {
9615
10001
  console.log("[reroute/watch] ├─ Building content chunks...");
9616
10002
  const contentStart = performance.now();
9617
10003
  const watchI18n = await discoverI18n(cwd, loadedConfig.i18n);
9618
- await Bun.write(join12(cwd, ".reroute", "i18n.json"), JSON.stringify({
10004
+ await Bun.write(join14(cwd, ".reroute", "i18n.json"), JSON.stringify({
9619
10005
  enabled: watchI18n.enabled,
9620
10006
  defaultLocale: watchI18n.defaultLocale,
9621
10007
  locales: watchI18n.locales,
@@ -9653,7 +10039,7 @@ async function startGenWatch(cwd, args) {
9653
10039
  });
9654
10040
  });
9655
10041
  });
9656
- const clientPath = join12(cwd, watchPaths.clientDir);
10042
+ const clientPath = join14(cwd, watchPaths.clientDir);
9657
10043
  console.log(`[reroute/watch] \uD83D\uDCE6 Watching ${clientPath}...`);
9658
10044
  async function rebuildWatchedClient(changed) {
9659
10045
  const label = changed.length === 1 ? changed[0] : `${changed.length} files`;
@@ -9750,6 +10136,7 @@ var OUTPUT_DIR = ".reroute", OUTPUT_ROUTES = ".reroute/routes.ts", OUTPUT_ROUTES
9750
10136
  var init_gen = __esm(() => {
9751
10137
  init_core();
9752
10138
  init_env();
10139
+ init_images();
9753
10140
  init_markdown();
9754
10141
  init_analyzer();
9755
10142
  init_suspense();
@@ -9762,23 +10149,23 @@ var exports_command = {};
9762
10149
  __export(exports_command, {
9763
10150
  getRerouteCommand: () => getRerouteCommand
9764
10151
  });
9765
- import { existsSync as existsSync6 } from "node:fs";
9766
- import { join as join13 } from "node:path";
10152
+ import { existsSync as existsSync8 } from "node:fs";
10153
+ import { join as join15 } from "node:path";
9767
10154
  function getRerouteCommand() {
9768
- const binPath = join13(import.meta.dir, "..", "..", "bin.ts");
9769
- const isBunDev = existsSync6(binPath);
10155
+ const binPath = join15(import.meta.dir, "..", "..", "bin.ts");
10156
+ const isBunDev = existsSync8(binPath);
9770
10157
  if (isBunDev) {
9771
10158
  return `bun ${binPath}`;
9772
10159
  }
9773
10160
  const cwd = process.cwd();
9774
10161
  const nodeModulesPaths = [
9775
- join13(cwd, "node_modules", ".bin", "reroute"),
9776
- join13(cwd, "..", "node_modules", ".bin", "reroute"),
9777
- join13(cwd, "..", "..", "node_modules", ".bin", "reroute"),
9778
- join13(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
10162
+ join15(cwd, "node_modules", ".bin", "reroute"),
10163
+ join15(cwd, "..", "node_modules", ".bin", "reroute"),
10164
+ join15(cwd, "..", "..", "node_modules", ".bin", "reroute"),
10165
+ join15(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
9779
10166
  ];
9780
10167
  for (const binPath2 of nodeModulesPaths) {
9781
- if (existsSync6(binPath2)) {
10168
+ if (existsSync8(binPath2)) {
9782
10169
  return binPath2;
9783
10170
  }
9784
10171
  }
@@ -88671,7 +89058,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
88671
89058
  out += ">" + text + "</a>";
88672
89059
  return out;
88673
89060
  };
88674
- _proto.image = function image(href, title, text) {
89061
+ _proto.image = function image2(href, title, text) {
88675
89062
  href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
88676
89063
  if (href === null) {
88677
89064
  return text;
@@ -88712,7 +89099,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
88712
89099
  _proto.link = function link(href, title, text) {
88713
89100
  return "" + text;
88714
89101
  };
88715
- _proto.image = function image(href, title, text) {
89102
+ _proto.image = function image2(href, title, text) {
88716
89103
  return "" + text;
88717
89104
  };
88718
89105
  _proto.br = function br() {
@@ -101853,7 +102240,7 @@ var require_lodash = __commonJS(function(exports, module) {
101853
102240
  }
101854
102241
  return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined2, comparator) : [];
101855
102242
  });
101856
- function join14(array, separator) {
102243
+ function join16(array, separator) {
101857
102244
  return array == null ? "" : nativeJoin.call(array, separator);
101858
102245
  }
101859
102246
  function last(array) {
@@ -103785,7 +104172,7 @@ __p += '`;
103785
104172
  lodash.isUndefined = isUndefined;
103786
104173
  lodash.isWeakMap = isWeakMap;
103787
104174
  lodash.isWeakSet = isWeakSet;
103788
- lodash.join = join14;
104175
+ lodash.join = join16;
103789
104176
  lodash.kebabCase = kebabCase;
103790
104177
  lodash.last = last;
103791
104178
  lodash.lastIndexOf = lastIndexOf;
@@ -104466,8 +104853,8 @@ __export(exports_dev, {
104466
104853
  default: () => dev
104467
104854
  });
104468
104855
  import { spawn } from "node:child_process";
104469
- import { existsSync as existsSync7 } from "node:fs";
104470
- import { join as join14 } from "node:path";
104856
+ import { existsSync as existsSync9 } from "node:fs";
104857
+ import { join as join16 } from "node:path";
104471
104858
  import { pathToFileURL as pathToFileURL9 } from "node:url";
104472
104859
  function parsePort(args) {
104473
104860
  const portIndex = args.findIndex((arg) => arg === "--port" || arg === "-p");
@@ -104499,11 +104886,12 @@ async function waitForInitialBuild(genProcess) {
104499
104886
  console.log("[reroute/dev] Initial build complete!");
104500
104887
  return outputBuffer;
104501
104888
  }
104502
- async function startTui(port) {
104889
+ async function startTui(port, args) {
104503
104890
  const rerouteCmd = getRerouteCommand();
104504
104891
  const useShell = rerouteCmd.includes(" ");
104505
- const genCommand = useShell ? `${rerouteCmd} gen --watch` : rerouteCmd;
104506
- const genArgs = useShell ? [] : ["gen", "--watch"];
104892
+ const prodArgs = isProductionMode(args) ? ["--prod"] : [];
104893
+ const genCommand = useShell ? `${rerouteCmd} gen --watch ${prodArgs.join(" ")}`.trim() : rerouteCmd;
104894
+ const genArgs = useShell ? [] : ["gen", "--watch", ...prodArgs];
104507
104895
  const genProcess = spawn(genCommand, genArgs, {
104508
104896
  stdio: ["ignore", "pipe", "pipe"],
104509
104897
  shell: useShell,
@@ -104552,13 +104940,13 @@ async function startTui(port) {
104552
104940
  const { setupTerminalUIHandlers: setupTerminalUIHandlers2 } = await Promise.resolve().then(() => exports_terminal_ui);
104553
104941
  setupTerminalUIHandlers2(screen, grid, genProcess, serverProcess, outputBuffer, blessed, colorizeLogPrefix, server2);
104554
104942
  }
104555
- async function startDefault(port) {
104943
+ async function startDefault(port, args) {
104556
104944
  process.env.PORT = String(port);
104557
104945
  process.env.REROUTE_DEV = "1";
104558
- const session = await startGenWatch(process.cwd(), ["--watch"]);
104946
+ const session = await startGenWatch(process.cwd(), genWatchArgs(args));
104559
104947
  const { server: server2 } = resolveAppPaths(await loadConfig(process.cwd()));
104560
- const entry = join14(process.cwd(), server2);
104561
- if (!existsSync7(entry)) {
104948
+ const entry = join16(process.cwd(), server2);
104949
+ if (!existsSync9(entry)) {
104562
104950
  session.close();
104563
104951
  throw new Error(`[reroute/dev] Missing ${entry}`);
104564
104952
  }
@@ -104582,6 +104970,9 @@ async function startDefault(port) {
104582
104970
  process.on("SIGINT", shutdown);
104583
104971
  process.on("SIGTERM", shutdown);
104584
104972
  }
104973
+ function genWatchArgs(args) {
104974
+ return isProductionMode(args) ? ["--watch", "--prod"] : ["--watch"];
104975
+ }
104585
104976
  async function dev(args) {
104586
104977
  const terminalUI = args.includes("--tui") || args.includes("-t");
104587
104978
  const port = parsePort(args);
@@ -104596,10 +104987,10 @@ async function dev(args) {
104596
104987
  console.log(`[reroute/dev] Press Ctrl+C to stop
104597
104988
  `);
104598
104989
  if (terminalUI) {
104599
- await startTui(port);
104990
+ await startTui(port, args);
104600
104991
  return;
104601
104992
  }
104602
- await startDefault(port);
104993
+ await startDefault(port, args);
104603
104994
  } catch (error) {
104604
104995
  if (error.code === "SIGINT") {
104605
104996
  console.log(`
@@ -104623,23 +105014,23 @@ __export(exports_start, {
104623
105014
  default: () => start
104624
105015
  });
104625
105016
  import { spawn as spawn2 } from "node:child_process";
104626
- import { existsSync as existsSync8 } from "node:fs";
104627
- import { join as join15 } from "node:path";
105017
+ import { existsSync as existsSync10 } from "node:fs";
105018
+ import { join as join17 } from "node:path";
104628
105019
  function getRerouteCommand2() {
104629
- const binPath = join15(import.meta.dir, "..", "..", "bin.ts");
104630
- const isBunDev = existsSync8(binPath);
105020
+ const binPath = join17(import.meta.dir, "..", "..", "bin.ts");
105021
+ const isBunDev = existsSync10(binPath);
104631
105022
  if (isBunDev) {
104632
105023
  return `bun ${binPath}`;
104633
105024
  }
104634
105025
  const cwd = process.cwd();
104635
105026
  const nodeModulesPaths = [
104636
- join15(cwd, "node_modules", ".bin", "reroute"),
104637
- join15(cwd, "..", "node_modules", ".bin", "reroute"),
104638
- join15(cwd, "..", "..", "node_modules", ".bin", "reroute"),
104639
- join15(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
105027
+ join17(cwd, "node_modules", ".bin", "reroute"),
105028
+ join17(cwd, "..", "node_modules", ".bin", "reroute"),
105029
+ join17(cwd, "..", "..", "node_modules", ".bin", "reroute"),
105030
+ join17(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
104640
105031
  ];
104641
105032
  for (const binPath2 of nodeModulesPaths) {
104642
- if (existsSync8(binPath2)) {
105033
+ if (existsSync10(binPath2)) {
104643
105034
  return binPath2;
104644
105035
  }
104645
105036
  }
@@ -104762,17 +105153,17 @@ var init_start = __esm(() => {
104762
105153
  // packages/cli/src/commands/lib/assets.ts
104763
105154
  import {
104764
105155
  cpSync,
104765
- existsSync as existsSync9,
105156
+ existsSync as existsSync11,
104766
105157
  mkdirSync,
104767
- readdirSync as readdirSync2
105158
+ readdirSync as readdirSync3
104768
105159
  } from "node:fs";
104769
- import { join as join16 } from "node:path";
105160
+ import { join as join18 } from "node:path";
104770
105161
  function copyAssetsToReroute(cwd, sourceAssetsDir, rerouteAssetsDir) {
104771
- if (!existsSync9(sourceAssetsDir)) {
105162
+ if (!existsSync11(sourceAssetsDir)) {
104772
105163
  return 0;
104773
105164
  }
104774
- const rerouteDir = join16(cwd, ".reroute");
104775
- if (!existsSync9(rerouteDir)) {
105165
+ const rerouteDir = join18(cwd, ".reroute");
105166
+ if (!existsSync11(rerouteDir)) {
104776
105167
  mkdirSync(rerouteDir, { recursive: true });
104777
105168
  }
104778
105169
  cpSync(sourceAssetsDir, rerouteAssetsDir, { recursive: true });
@@ -104780,10 +105171,10 @@ function copyAssetsToReroute(cwd, sourceAssetsDir, rerouteAssetsDir) {
104780
105171
  }
104781
105172
  function countFiles(dir) {
104782
105173
  let count = 0;
104783
- const entries = readdirSync2(dir, { withFileTypes: true });
105174
+ const entries = readdirSync3(dir, { withFileTypes: true });
104784
105175
  for (const entry of entries) {
104785
105176
  if (entry.isDirectory()) {
104786
- count += countFiles(join16(dir, entry.name));
105177
+ count += countFiles(join18(dir, entry.name));
104787
105178
  } else {
104788
105179
  count++;
104789
105180
  }
@@ -104798,23 +105189,23 @@ __export(exports_build, {
104798
105189
  default: () => build
104799
105190
  });
104800
105191
  import { spawn as spawn3 } from "node:child_process";
104801
- import { existsSync as existsSync10, readFileSync as readFileSync5, rmSync, unlinkSync } from "node:fs";
104802
- import { join as join17 } from "node:path";
105192
+ import { existsSync as existsSync12, readFileSync as readFileSync5, rmSync, unlinkSync } from "node:fs";
105193
+ import { join as join19 } from "node:path";
104803
105194
  function getRerouteCommand3() {
104804
- const binPath = join17(import.meta.dir, "..", "..", "bin.ts");
104805
- const isBunDev = existsSync10(binPath);
105195
+ const binPath = join19(import.meta.dir, "..", "..", "bin.ts");
105196
+ const isBunDev = existsSync12(binPath);
104806
105197
  if (isBunDev) {
104807
105198
  return `bun ${binPath}`;
104808
105199
  }
104809
105200
  const cwd = process.cwd();
104810
105201
  const nodeModulesPaths = [
104811
- join17(cwd, "node_modules", ".bin", "reroute"),
104812
- join17(cwd, "..", "node_modules", ".bin", "reroute"),
104813
- join17(cwd, "..", "..", "node_modules", ".bin", "reroute"),
104814
- join17(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
105202
+ join19(cwd, "node_modules", ".bin", "reroute"),
105203
+ join19(cwd, "..", "node_modules", ".bin", "reroute"),
105204
+ join19(cwd, "..", "..", "node_modules", ".bin", "reroute"),
105205
+ join19(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
104815
105206
  ];
104816
105207
  for (const binPath2 of nodeModulesPaths) {
104817
- if (existsSync10(binPath2)) {
105208
+ if (existsSync12(binPath2)) {
104818
105209
  return binPath2;
104819
105210
  }
104820
105211
  }
@@ -104822,8 +105213,8 @@ function getRerouteCommand3() {
104822
105213
  }
104823
105214
  function getOutputName() {
104824
105215
  const cwd = process.cwd();
104825
- const packageJsonPath = join17(cwd, "package.json");
104826
- if (existsSync10(packageJsonPath)) {
105216
+ const packageJsonPath = join19(cwd, "package.json");
105217
+ if (existsSync12(packageJsonPath)) {
104827
105218
  try {
104828
105219
  const packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
104829
105220
  const name = packageJson.name;
@@ -104854,16 +105245,16 @@ function parseBuildArgs(args) {
104854
105245
  return { outfile, compileBinary, noCompression, externalArgs };
104855
105246
  }
104856
105247
  function cleanDistFolder(cwd) {
104857
- const distDir = join17(cwd, "dist");
104858
- if (existsSync10(distDir)) {
105248
+ const distDir = join19(cwd, "dist");
105249
+ if (existsSync12(distDir)) {
104859
105250
  process.stdout.write(colorizeLogPrefixAnsi(`[reroute/build] Cleaning dist folder...
104860
105251
  `));
104861
105252
  rmSync(distDir, { recursive: true });
104862
105253
  }
104863
105254
  }
104864
105255
  async function cleanRerouteFolder(cwd) {
104865
- const rerouteDir = join17(cwd, ".reroute");
104866
- if (existsSync10(rerouteDir)) {
105256
+ const rerouteDir = join19(cwd, ".reroute");
105257
+ if (existsSync12(rerouteDir)) {
104867
105258
  process.stdout.write(colorizeLogPrefixAnsi(`[reroute/build] Cleaning .reroute folder...
104868
105259
  `));
104869
105260
  rmSync(rerouteDir, { recursive: true, force: true });
@@ -104917,8 +105308,8 @@ async function runGenCommand(rerouteCmd, useShell, noCompression) {
104917
105308
  async function copyAssets(cwd) {
104918
105309
  const config2 = await loadConfig(cwd);
104919
105310
  const { assetsDir } = resolveAppPaths(config2);
104920
- const sourceAssetsDir = join17(cwd, assetsDir);
104921
- const rerouteAssetsDir = join17(cwd, ".reroute", "assets");
105311
+ const sourceAssetsDir = join19(cwd, assetsDir);
105312
+ const rerouteAssetsDir = join19(cwd, ".reroute", "assets");
104922
105313
  process.stdout.write(colorizeLogPrefixAnsi(`[reroute/build] Copying assets...
104923
105314
  `));
104924
105315
  const fileCount = copyAssetsToReroute(cwd, sourceAssetsDir, rerouteAssetsDir);
@@ -104933,9 +105324,9 @@ async function copyAssets(cwd) {
104933
105324
  async function buildBundle(cwd, buildArgs) {
104934
105325
  const external = [...buildArgs.externalArgs, "sharp", "@vercel/og"];
104935
105326
  const buildResult = await Bun.build({
104936
- entrypoints: [join17(cwd, ".reroute/entry.ts")],
105327
+ entrypoints: [join19(cwd, ".reroute/entry.ts")],
104937
105328
  target: "bun",
104938
- outdir: join17(cwd, "dist"),
105329
+ outdir: join19(cwd, "dist"),
104939
105330
  sourcemap: "external",
104940
105331
  ...getCommonBuildOptions(),
104941
105332
  external,
@@ -104982,8 +105373,8 @@ function cleanupBundledFiles(rerouteDir) {
104982
105373
  "markdown-components.ts"
104983
105374
  ];
104984
105375
  for (const file of tsFilesToRemove) {
104985
- const filePath = join17(rerouteDir, file);
104986
- if (existsSync10(filePath)) {
105376
+ const filePath = join19(rerouteDir, file);
105377
+ if (existsSync12(filePath)) {
104987
105378
  try {
104988
105379
  unlinkSync(filePath);
104989
105380
  cleanupCount++;
@@ -104992,8 +105383,8 @@ function cleanupBundledFiles(rerouteDir) {
104992
105383
  }
104993
105384
  const dirsToRemove = ["markdown", "streaming"];
104994
105385
  for (const dir of dirsToRemove) {
104995
- const dirPath = join17(rerouteDir, dir);
104996
- if (existsSync10(dirPath)) {
105386
+ const dirPath = join19(rerouteDir, dir);
105387
+ if (existsSync12(dirPath)) {
104997
105388
  try {
104998
105389
  rmSync(dirPath, { recursive: true });
104999
105390
  cleanupCount++;
@@ -105025,8 +105416,9 @@ async function build(args) {
105025
105416
  const useShell = rerouteCmd.includes(" ");
105026
105417
  await runGenCommand(rerouteCmd, useShell, buildArgs.noCompression);
105027
105418
  await copyAssets(cwd);
105419
+ await runImagePreprocess(cwd, await loadConfig(cwd));
105028
105420
  await buildBundle(cwd, buildArgs);
105029
- const rerouteDir = join17(cwd, ".reroute");
105421
+ const rerouteDir = join19(cwd, ".reroute");
105030
105422
  cleanupBundledFiles(rerouteDir);
105031
105423
  logBuildComplete(buildStartTime, buildArgs);
105032
105424
  process.exit(0);
@@ -105039,6 +105431,7 @@ async function build(args) {
105039
105431
  var init_build = __esm(() => {
105040
105432
  init_core();
105041
105433
  init_assets();
105434
+ init_images();
105042
105435
  init_log();
105043
105436
  });
105044
105437
 
@@ -105047,25 +105440,25 @@ var exports_analyze = {};
105047
105440
  __export(exports_analyze, {
105048
105441
  default: () => analyze
105049
105442
  });
105050
- import { existsSync as existsSync11, statSync } from "node:fs";
105443
+ import { existsSync as existsSync13, statSync } from "node:fs";
105051
105444
  import { readdir as readdir9, readFile as readFile2, stat as stat6, writeFile as writeFile2 } from "node:fs/promises";
105052
- import { basename as basename4, join as join18, relative as relative3 } from "node:path";
105445
+ import { basename as basename4, join as join20, relative as relative3 } from "node:path";
105053
105446
  import Table from "cli-table3";
105054
105447
  async function findChunkBundles(cwd) {
105055
105448
  const bundles = [];
105056
- const chunksDir = join18(cwd, ".reroute", "chunks");
105057
- if (!existsSync11(chunksDir))
105449
+ const chunksDir = join20(cwd, ".reroute", "chunks");
105450
+ if (!existsSync13(chunksDir))
105058
105451
  return bundles;
105059
105452
  const collections2 = await readdir9(chunksDir, { withFileTypes: true });
105060
105453
  for (const collection of collections2) {
105061
105454
  if (!collection.isDirectory())
105062
105455
  continue;
105063
- const collectionDir = join18(chunksDir, collection.name);
105456
+ const collectionDir = join20(chunksDir, collection.name);
105064
105457
  const files = await readdir9(collectionDir);
105065
105458
  for (const file of files) {
105066
105459
  if (!file.endsWith(".js"))
105067
105460
  continue;
105068
- const filePath = join18(collectionDir, file);
105461
+ const filePath = join20(collectionDir, file);
105069
105462
  const stats = await stat6(filePath);
105070
105463
  const content2 = await Bun.file(filePath).arrayBuffer();
105071
105464
  const gzippedSize = Bun.gzipSync(new Uint8Array(content2)).length;
@@ -105083,12 +105476,12 @@ async function findChunkBundles(cwd) {
105083
105476
  }
105084
105477
  async function findDistBundles(cwd) {
105085
105478
  const bundles = [];
105086
- const distDir = join18(cwd, "dist");
105087
- if (!existsSync11(distDir))
105479
+ const distDir = join20(cwd, "dist");
105480
+ if (!existsSync13(distDir))
105088
105481
  return bundles;
105089
105482
  const files = await readdir9(distDir);
105090
105483
  for (const file of files) {
105091
- const filePath = join18(distDir, file);
105484
+ const filePath = join20(distDir, file);
105092
105485
  const stats = statSync(filePath);
105093
105486
  if (stats.isFile() && !file.endsWith(".map") && !file.endsWith(".d.ts")) {
105094
105487
  const content2 = await Bun.file(filePath).arrayBuffer();
@@ -105114,13 +105507,13 @@ async function findBundles(cwd) {
105114
105507
  }
105115
105508
  async function findBrowserEntry(cwd) {
105116
105509
  try {
105117
- const clientDir = join18(cwd, resolveAppPaths(await loadConfig(cwd)).clientDir);
105118
- const tsxEntry = join18(clientDir, "index.tsx");
105119
- const tsEntry = join18(clientDir, "index.ts");
105510
+ const clientDir = join20(cwd, resolveAppPaths(await loadConfig(cwd)).clientDir);
105511
+ const tsxEntry = join20(clientDir, "index.tsx");
105512
+ const tsEntry = join20(clientDir, "index.ts");
105120
105513
  let sourceEntry = null;
105121
- if (existsSync11(tsxEntry)) {
105514
+ if (existsSync13(tsxEntry)) {
105122
105515
  sourceEntry = tsxEntry;
105123
- } else if (existsSync11(tsEntry)) {
105516
+ } else if (existsSync13(tsEntry)) {
105124
105517
  sourceEntry = tsEntry;
105125
105518
  }
105126
105519
  if (!sourceEntry)
@@ -105149,12 +105542,12 @@ async function findBrowserEntry(cwd) {
105149
105542
  console.warn("[reroute/analyze] Browser build produced no outputs");
105150
105543
  return null;
105151
105544
  }
105152
- const tempDir = join18(cwd, ".reroute", "browser");
105545
+ const tempDir = join20(cwd, ".reroute", "browser");
105153
105546
  await import("node:fs/promises").then((fs) => fs.mkdir(tempDir, { recursive: true }));
105154
105547
  const output = result.outputs[0];
105155
105548
  const code = await output.text();
105156
105549
  const actualHash = await generateContentHash2(code);
105157
- const bundlePath = join18(tempDir, `index.${actualHash}.js`);
105550
+ const bundlePath = join20(tempDir, `index.${actualHash}.js`);
105158
105551
  await writeFile2(bundlePath, code, "utf-8");
105159
105552
  const mapOutput = result.outputs.find((o) => o.path.endsWith(".map"));
105160
105553
  if (mapOutput) {
@@ -105206,8 +105599,8 @@ function calculateStats(bundles) {
105206
105599
  }
105207
105600
  async function getInstalledPackageSizes(cwd) {
105208
105601
  const packageSizes = new Map;
105209
- const nodeModulesDir = join18(cwd, "node_modules");
105210
- if (!existsSync11(nodeModulesDir))
105602
+ const nodeModulesDir = join20(cwd, "node_modules");
105603
+ if (!existsSync13(nodeModulesDir))
105211
105604
  return packageSizes;
105212
105605
  try {
105213
105606
  const { execSync } = await import("node:child_process");
@@ -105245,7 +105638,7 @@ async function getInstalledPackageSizes(cwd) {
105245
105638
  }
105246
105639
  async function buildDependencyTree(entryPath, cwd) {
105247
105640
  try {
105248
- if (!existsSync11(entryPath))
105641
+ if (!existsSync13(entryPath))
105249
105642
  return null;
105250
105643
  const root = {
105251
105644
  name: basename4(entryPath),
@@ -105262,7 +105655,7 @@ async function buildDependencyTree(entryPath, cwd) {
105262
105655
  if (!pkgNode) {
105263
105656
  pkgNode = {
105264
105657
  name: pkgName || "unknown",
105265
- path: join18(cwd, "node_modules", pkgName || ""),
105658
+ path: join20(cwd, "node_modules", pkgName || ""),
105266
105659
  size: 0,
105267
105660
  children: []
105268
105661
  };
@@ -105283,7 +105676,7 @@ async function buildDependencyTree(entryPath, cwd) {
105283
105676
  if (!child) {
105284
105677
  child = {
105285
105678
  name: part,
105286
- path: join18(cwd, ...parts.slice(0, i + 1)),
105679
+ path: join20(cwd, ...parts.slice(0, i + 1)),
105287
105680
  size: 0,
105288
105681
  children: []
105289
105682
  };
@@ -105314,7 +105707,7 @@ async function buildDependencyTree(entryPath, cwd) {
105314
105707
  const modulePattern = /\/\/\s*(.+?\.(?:ts|tsx|js|jsx|mjs|cjs))\s*$/gm;
105315
105708
  const nodeModulesNode = {
105316
105709
  name: "node_modules",
105317
- path: join18(cwd, "node_modules"),
105710
+ path: join20(cwd, "node_modules"),
105318
105711
  size: 0,
105319
105712
  children: []
105320
105713
  };
@@ -105380,7 +105773,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
105380
105773
  if (sourcePath.startsWith("/") || sourcePath.match(/^[A-Za-z]:\\/))
105381
105774
  return sourcePath;
105382
105775
  const bundleDir = bundlePath.substring(0, bundlePath.lastIndexOf("/"));
105383
- return join18(bundleDir, sourceRoot || "", sourcePath);
105776
+ return join20(bundleDir, sourceRoot || "", sourcePath);
105384
105777
  }, computeSizes = function(node) {
105385
105778
  if (node.children && node.children.length > 0) {
105386
105779
  node.size = node.children.reduce((s, c) => s + computeSizes(c), 0);
@@ -105388,7 +105781,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
105388
105781
  return node.size;
105389
105782
  };
105390
105783
  const mapPath = `${bundlePath}.map`;
105391
- if (!existsSync11(mapPath))
105784
+ if (!existsSync13(mapPath))
105392
105785
  return null;
105393
105786
  const [bundle, mapJson] = await Promise.all([
105394
105787
  readFile2(bundlePath, "utf-8"),
@@ -105452,7 +105845,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
105452
105845
  };
105453
105846
  const nodeModulesNode = {
105454
105847
  name: "node_modules",
105455
- path: join18(cwd, "node_modules"),
105848
+ path: join20(cwd, "node_modules"),
105456
105849
  size: 0,
105457
105850
  children: []
105458
105851
  };
@@ -105492,7 +105885,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
105492
105885
  if (!pkgNode) {
105493
105886
  pkgNode = {
105494
105887
  name: pkgName || "unknown",
105495
- path: join18(cwd, "node_modules", pkgName || ""),
105888
+ path: join20(cwd, "node_modules", pkgName || ""),
105496
105889
  size: 0,
105497
105890
  children: []
105498
105891
  };
@@ -105513,7 +105906,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
105513
105906
  if (!child) {
105514
105907
  child = {
105515
105908
  name: part,
105516
- path: join18(cwd, ...parts.slice(0, i2 + 1)),
105909
+ path: join20(cwd, ...parts.slice(0, i2 + 1)),
105517
105910
  size: 0,
105518
105911
  children: []
105519
105912
  };
@@ -105543,11 +105936,11 @@ async function generateHTMLReport(stats, depTree, mainInfo, browserDepTree, brow
105543
105936
  let actualServerBinarySize = null;
105544
105937
  let actualServerBinaryGzipped = null;
105545
105938
  try {
105546
- const distDir = join18(process.cwd(), "dist");
105547
- if (existsSync11(distDir)) {
105939
+ const distDir = join20(process.cwd(), "dist");
105940
+ if (existsSync13(distDir)) {
105548
105941
  const files = await readdir9(distDir);
105549
105942
  for (const file of files) {
105550
- const filePath = join18(distDir, file);
105943
+ const filePath = join20(distDir, file);
105551
105944
  const stats2 = statSync(filePath);
105552
105945
  if (stats2.isFile() && !file.includes(".")) {
105553
105946
  actualServerBinarySize = stats2.size;
@@ -107029,11 +107422,11 @@ async function printConsoleReport(stats, depTree, mainInfo, browserDepTree, brow
107029
107422
  let actualServerBinarySize = null;
107030
107423
  let actualServerBinaryGzipped = null;
107031
107424
  try {
107032
- const distDir = join18(process.cwd(), "dist");
107033
- if (existsSync11(distDir)) {
107425
+ const distDir = join20(process.cwd(), "dist");
107426
+ if (existsSync13(distDir)) {
107034
107427
  const files = await readdir9(distDir);
107035
107428
  for (const file of files) {
107036
- const filePath = join18(distDir, file);
107429
+ const filePath = join20(distDir, file);
107037
107430
  const stats2 = statSync(filePath);
107038
107431
  if (stats2.isFile() && !file.includes(".")) {
107039
107432
  actualServerBinarySize = stats2.size;
@@ -107067,8 +107460,8 @@ async function analyze(args) {
107067
107460
  const isProd = isProductionMode(args);
107068
107461
  const searchIndex = args.indexOf("--search");
107069
107462
  const initialSearch = searchIndex !== -1 && args[searchIndex + 1] ? args[searchIndex + 1] : "";
107070
- const rerouteIndexPath = join18(cwd, ".reroute", "index.ts");
107071
- if (!existsSync11(rerouteIndexPath)) {
107463
+ const rerouteIndexPath = join20(cwd, ".reroute", "index.ts");
107464
+ if (!existsSync13(rerouteIndexPath)) {
107072
107465
  console.log(colorizeLogPrefixAnsi(`[reroute/analyze] .reroute artifacts not found, running build...
107073
107466
  `));
107074
107467
  const { spawn: spawn4 } = await import("node:child_process");
@@ -107130,12 +107523,12 @@ async function analyze(args) {
107130
107523
  let entry = null;
107131
107524
  let depTree = null;
107132
107525
  let mainInfo = null;
107133
- const srcEntry = join18(cwd, resolveAppPaths(await loadConfig(cwd)).server);
107134
- if (existsSync11(srcEntry)) {
107526
+ const srcEntry = join20(cwd, resolveAppPaths(await loadConfig(cwd)).server);
107527
+ if (existsSync13(srcEntry)) {
107135
107528
  console.log(colorizeLogPrefixAnsi(`[reroute/analyze] Building server binary for analysis...
107136
107529
  `));
107137
107530
  const { mkdir: mkdir4 } = await import("node:fs/promises");
107138
- const serverAnalysisDir = join18(cwd, ".reroute", "server");
107531
+ const serverAnalysisDir = join20(cwd, ".reroute", "server");
107139
107532
  await mkdir4(serverAnalysisDir, { recursive: true });
107140
107533
  const result = await Bun.build({
107141
107534
  entrypoints: [srcEntry],
@@ -107148,7 +107541,7 @@ async function analyze(args) {
107148
107541
  if (result.success && result.outputs.length > 0) {
107149
107542
  const output = result.outputs[0];
107150
107543
  const code = await output.text();
107151
- const analysisEntry = join18(serverAnalysisDir, "index.js");
107544
+ const analysisEntry = join20(serverAnalysisDir, "index.js");
107152
107545
  await writeFile2(analysisEntry, code, "utf-8");
107153
107546
  const mapOutput = result.outputs.find((o) => o.path.endsWith(".map"));
107154
107547
  if (mapOutput) {
@@ -107166,8 +107559,8 @@ async function analyze(args) {
107166
107559
  `));
107167
107560
  const installedSizes = await getInstalledPackageSizes(cwd);
107168
107561
  if (depTree) {
107169
- const packageJsonPath = join18(cwd, "package.json");
107170
- if (existsSync11(packageJsonPath)) {
107562
+ const packageJsonPath = join20(cwd, "package.json");
107563
+ if (existsSync13(packageJsonPath)) {
107171
107564
  try {
107172
107565
  const packageJson = JSON.parse(await readFile2(packageJsonPath, "utf-8"));
107173
107566
  const runtimeDeps = packageJson.dependencies || {};
@@ -107178,7 +107571,7 @@ async function analyze(args) {
107178
107571
  if (!trackedPkgs.has(pkgName) && installedSizes.has(pkgName)) {
107179
107572
  nodeModulesNode.children?.push({
107180
107573
  name: pkgName,
107181
- path: join18(cwd, "node_modules", pkgName),
107574
+ path: join20(cwd, "node_modules", pkgName),
107182
107575
  size: installedSizes.get(pkgName) || 0
107183
107576
  });
107184
107577
  }
@@ -107209,10 +107602,10 @@ async function analyze(args) {
107209
107602
  const fullOutput = args.includes("--full");
107210
107603
  await printConsoleReport(stats, depTree, mainInfo, browserDepTree, browserInfo, fullOutput);
107211
107604
  if (outputHtml || openBrowser) {
107212
- const htmlPath = join18(cwd, ".reroute", "analysis.html");
107605
+ const htmlPath = join20(cwd, ".reroute", "analysis.html");
107213
107606
  const html2 = await generateHTMLReport(stats, depTree, mainInfo, browserDepTree, browserInfo, initialSearch);
107214
107607
  const { mkdir: mkdir4 } = await import("node:fs/promises");
107215
- await mkdir4(join18(cwd, ".reroute"), { recursive: true });
107608
+ await mkdir4(join20(cwd, ".reroute"), { recursive: true });
107216
107609
  await writeFile2(htmlPath, html2, "utf-8");
107217
107610
  console.log(colorizeLogPrefixAnsi(`[reroute/analyze] HTML report generated: ${relative3(cwd, htmlPath)}
107218
107611
  `));
@@ -107277,7 +107670,7 @@ __export(exports_og, {
107277
107670
  });
107278
107671
  import { spawn as spawn4 } from "node:child_process";
107279
107672
  import { readdir as readdir10 } from "node:fs/promises";
107280
- import { join as join19 } from "node:path";
107673
+ import { join as join21 } from "node:path";
107281
107674
  function getPortFromConfig(baseUrl) {
107282
107675
  if (!baseUrl)
107283
107676
  return 3000;
@@ -107356,8 +107749,8 @@ async function scanForOgTemplates(dir, base, routes) {
107356
107749
  try {
107357
107750
  const entries = await readdir10(dir, { withFileTypes: true });
107358
107751
  for (const entry of entries) {
107359
- const fullPath = join19(dir, entry.name);
107360
- const relativePath = join19(base, entry.name);
107752
+ const fullPath = join21(dir, entry.name);
107753
+ const relativePath = join21(base, entry.name);
107361
107754
  if (entry.isDirectory()) {
107362
107755
  if (entry.name === "content")
107363
107756
  continue;
@@ -107378,7 +107771,7 @@ async function addContentRoutes(routesPath, routes) {
107378
107771
  for (const entry of entries) {
107379
107772
  if (!entry.isDirectory())
107380
107773
  continue;
107381
- const contentDir = join19(routesPath, entry.name, "content");
107774
+ const contentDir = join21(routesPath, entry.name, "content");
107382
107775
  try {
107383
107776
  const contentFiles = await readdir10(contentDir);
107384
107777
  if (contentFiles.length === 0)
@@ -107395,7 +107788,7 @@ async function addContentRoutes(routesPath, routes) {
107395
107788
  async function findRoutesWithOG(cwd) {
107396
107789
  const routes = [];
107397
107790
  try {
107398
- const manifestPath = join19(cwd, ".reroute", "manifest.json");
107791
+ const manifestPath = join21(cwd, ".reroute", "manifest.json");
107399
107792
  const manifestFile = Bun.file(manifestPath);
107400
107793
  const manifest = await manifestFile.json();
107401
107794
  if (manifest.staticRoutes && Array.isArray(manifest.staticRoutes)) {
@@ -107406,7 +107799,7 @@ async function findRoutesWithOG(cwd) {
107406
107799
  }
107407
107800
  } catch {
107408
107801
  console.warn("⚠️ .reroute/manifest.json not found, scanning routes directory...");
107409
- const routesPath = join19(cwd, resolveAppPaths(await loadConfig(cwd)).routesDir);
107802
+ const routesPath = join21(cwd, resolveAppPaths(await loadConfig(cwd)).routesDir);
107410
107803
  await scanForOgTemplates(routesPath, "", routes);
107411
107804
  await addContentRoutes(routesPath, routes);
107412
107805
  }
@@ -107584,7 +107977,7 @@ async function main() {
107584
107977
  }
107585
107978
  try {
107586
107979
  const commandArgs = args.slice(1);
107587
- if (commandArgs.includes("--prod")) {
107980
+ if (commandArgs.includes("--prod") || commandArgs.includes("--production")) {
107588
107981
  process.env.NODE_ENV = "production";
107589
107982
  if (typeof Bun !== "undefined") {
107590
107983
  Bun.env.NODE_ENV = "production";
@@ -107657,7 +108050,7 @@ async function getVersionString2() {
107657
108050
  }
107658
108051
  async function getVersion2() {
107659
108052
  if (true) {
107660
- return "1.0.0-alpha.20";
108053
+ return "1.0.0-alpha.22";
107661
108054
  }
107662
108055
  const possiblePaths = [
107663
108056
  path3.join(import.meta.dir, "../../../package.json"),
@@ -107674,10 +108067,10 @@ async function getVersion2() {
107674
108067
  }
107675
108068
  async function getCommit2() {
107676
108069
  if (true) {
107677
- return "1bc8849";
108070
+ return "53ae62b";
107678
108071
  }
107679
108072
  return "dev";
107680
108073
  }
107681
108074
  main();
107682
108075
 
107683
- //# debugId=13D7F37E6413989364756E2164756E21
108076
+ //# debugId=6EFAB19C7B4DAA9864756E2164756E21