reroute-js 0.8.0 → 0.9.1

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 (124) hide show
  1. package/_/basic/package.json +1 -0
  2. package/_/basic/src/client/index.html +0 -1
  3. package/_/blog/package.json +1 -0
  4. package/_/store/package.json +1 -0
  5. package/cli/bin.d.ts +1 -1
  6. package/cli/bin.js +589 -615
  7. package/cli/bin.js.map +19 -24
  8. package/cli/index.d.ts +1 -1
  9. package/cli/index.js +48 -25
  10. package/cli/index.js.map +5 -5
  11. package/cli/src/cli.d.ts +1 -1
  12. package/cli/src/commands/analyze.d.ts +1 -1
  13. package/cli/src/commands/build.d.ts +3 -4
  14. package/cli/src/commands/build.d.ts.map +1 -1
  15. package/cli/src/commands/dev.d.ts +2 -3
  16. package/cli/src/commands/dev.d.ts.map +1 -1
  17. package/cli/src/commands/gen.d.ts +1 -1
  18. package/cli/src/commands/gen.d.ts.map +1 -1
  19. package/cli/src/commands/init.d.ts +1 -1
  20. package/cli/src/commands/start.d.ts +3 -4
  21. package/cli/src/commands/start.d.ts.map +1 -1
  22. package/cli/src/libs/command.d.ts +1 -1
  23. package/cli/src/libs/index.d.ts +1 -1
  24. package/cli/src/libs/log.d.ts +1 -1
  25. package/cli/src/libs/log.d.ts.map +1 -1
  26. package/cli/src/libs/markdown-processor.d.ts +2 -1
  27. package/cli/src/libs/markdown-processor.d.ts.map +1 -1
  28. package/cli/src/libs/markdown.d.ts +1 -1
  29. package/cli/src/libs/production.d.ts +1 -1
  30. package/cli/src/libs/server.d.ts +18 -0
  31. package/cli/src/libs/server.d.ts.map +1 -0
  32. package/cli/src/libs/tailwind.d.ts +2 -2
  33. package/cli/src/libs/tailwind.d.ts.map +1 -1
  34. package/cli/src/libs/version.d.ts +1 -1
  35. package/core/index.d.ts +1 -1
  36. package/core/index.js +130 -351
  37. package/core/index.js.map +8 -11
  38. package/core/src/bundler/hash.d.ts +1 -1
  39. package/core/src/bundler/index.d.ts +1 -2
  40. package/core/src/bundler/index.d.ts.map +1 -1
  41. package/core/src/content/discovery.d.ts +1 -3
  42. package/core/src/content/discovery.d.ts.map +1 -1
  43. package/core/src/content/index.d.ts +1 -2
  44. package/core/src/content/index.d.ts.map +1 -1
  45. package/core/src/content/metadata.d.ts +1 -1
  46. package/core/src/index.d.ts +1 -1
  47. package/core/src/ssr/data.d.ts +1 -1
  48. package/core/src/ssr/index.d.ts +1 -1
  49. package/core/src/ssr/modules.d.ts +1 -1
  50. package/core/src/ssr/render.d.ts +1 -1
  51. package/core/src/ssr/render.d.ts.map +1 -1
  52. package/core/src/ssr/seed.d.ts +1 -1
  53. package/core/src/template/html.d.ts +1 -1
  54. package/core/src/template/index.d.ts +1 -1
  55. package/core/src/types.d.ts +7 -19
  56. package/core/src/types.d.ts.map +1 -1
  57. package/core/src/utils/cache.d.ts +1 -1
  58. package/core/src/utils/compression.d.ts +2 -1
  59. package/core/src/utils/compression.d.ts.map +1 -1
  60. package/core/src/utils/index.d.ts +1 -1
  61. package/core/src/utils/mime.d.ts +1 -1
  62. package/core/src/utils/path.d.ts +1 -1
  63. package/elysia/index.d.ts +1 -1
  64. package/elysia/index.js +391 -665
  65. package/elysia/index.js.map +14 -17
  66. package/elysia/src/index.d.ts +1 -1
  67. package/elysia/src/libs/cache.d.ts +14 -0
  68. package/elysia/src/libs/cache.d.ts.map +1 -0
  69. package/elysia/src/libs/http.d.ts +1 -1
  70. package/elysia/src/libs/image.d.ts +1 -1
  71. package/elysia/src/libs/image.d.ts.map +1 -1
  72. package/elysia/src/plugin.d.ts +1 -1
  73. package/elysia/src/plugin.d.ts.map +1 -1
  74. package/elysia/src/routes/artifacts.d.ts +9 -2
  75. package/elysia/src/routes/artifacts.d.ts.map +1 -1
  76. package/elysia/src/routes/content.d.ts +3 -2
  77. package/elysia/src/routes/content.d.ts.map +1 -1
  78. package/elysia/src/routes/dev.d.ts +1 -1
  79. package/elysia/src/routes/dev.d.ts.map +1 -1
  80. package/elysia/src/routes/image.d.ts +1 -1
  81. package/elysia/src/routes/ssr.d.ts +2 -2
  82. package/elysia/src/routes/ssr.d.ts.map +1 -1
  83. package/elysia/src/routes/static.d.ts +2 -5
  84. package/elysia/src/routes/static.d.ts.map +1 -1
  85. package/elysia/src/types.d.ts +10 -3
  86. package/elysia/src/types.d.ts.map +1 -1
  87. package/package.json +4 -4
  88. package/react/index.d.ts +1 -1
  89. package/react/index.js +80 -65
  90. package/react/index.js.map +5 -4
  91. package/react/src/components/ClientOnly.d.ts +1 -1
  92. package/react/src/components/ContentRoute.d.ts +1 -1
  93. package/react/src/components/Image.d.ts +1 -1
  94. package/react/src/components/Link.d.ts +1 -1
  95. package/react/src/components/Markdown.d.ts +1 -1
  96. package/react/src/components/Outlet.d.ts +1 -1
  97. package/react/src/components/index.d.ts +1 -1
  98. package/react/src/hooks/index.d.ts +1 -1
  99. package/react/src/hooks/useContent.d.ts +1 -1
  100. package/react/src/hooks/useData.d.ts +1 -1
  101. package/react/src/hooks/useNavigate.d.ts +1 -1
  102. package/react/src/hooks/useParams.d.ts +1 -1
  103. package/react/src/hooks/useRouter.d.ts +1 -1
  104. package/react/src/hooks/useSearchParams.d.ts +1 -1
  105. package/react/src/index.d.ts +1 -1
  106. package/react/src/providers/ContentProvider.d.ts +1 -1
  107. package/react/src/providers/RerouteProvider.d.ts +1 -1
  108. package/react/src/providers/RouterProvider.d.ts +1 -1
  109. package/react/src/providers/index.d.ts +1 -1
  110. package/react/src/types/any.d.ts +1 -1
  111. package/react/src/types/index.d.ts +1 -1
  112. package/react/src/types/router.d.ts +1 -1
  113. package/react/src/utils/content.d.ts +1 -1
  114. package/react/src/utils/head.d.ts +1 -1
  115. package/react/src/utils/index.d.ts +2 -1
  116. package/react/src/utils/index.d.ts.map +1 -1
  117. package/react/src/utils/lazy-route.d.ts +41 -0
  118. package/react/src/utils/lazy-route.d.ts.map +1 -0
  119. package/cli/src/commands/boot.d.ts +0 -18
  120. package/cli/src/commands/boot.d.ts.map +0 -1
  121. package/core/src/bundler/transpile.d.ts +0 -13
  122. package/core/src/bundler/transpile.d.ts.map +0 -1
  123. package/core/src/content/registry.d.ts +0 -11
  124. package/core/src/content/registry.d.ts.map +0 -1
package/cli/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
3
  /**
4
- * reroute-js v0.8.0
4
+ * reroute-js v0.9.1
5
5
  *
6
6
  * @license MIT
7
7
  * @copyright 2025 stewones <hi@stewan.io>
@@ -47,7 +47,7 @@ async function getVersionString() {
47
47
  }
48
48
  async function getVersion() {
49
49
  if (true) {
50
- return "0.8.0";
50
+ return "0.9.1";
51
51
  }
52
52
  const possiblePaths = [
53
53
  path.join(import.meta.dir, "../../../../package.json"),
@@ -65,7 +65,7 @@ async function getVersion() {
65
65
  }
66
66
  async function getCommit() {
67
67
  if (true) {
68
- return "b31f8e3";
68
+ return "75cc9e9";
69
69
  }
70
70
  return "dev";
71
71
  }
@@ -77,7 +77,7 @@ __export(exports_init, {
77
77
  default: () => init
78
78
  });
79
79
  import { existsSync } from "node:fs";
80
- import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
80
+ import { mkdir, readdir } from "node:fs/promises";
81
81
  import { join } from "node:path";
82
82
  async function init(args) {
83
83
  const options = parseArgs(args);
@@ -199,13 +199,13 @@ async function copyTemplateFiles(templatePath, targetPath, variables) {
199
199
  await mkdir(destPath, { recursive: true });
200
200
  await copyTemplateFiles(sourcePath, destPath, variables);
201
201
  } else if (entry.isFile()) {
202
- const content = await readFile(sourcePath, "utf-8");
202
+ const content = await Bun.file(sourcePath).text();
203
203
  let processedContent = content;
204
204
  for (const [key, value] of Object.entries(variables)) {
205
205
  const placeholder = `{{${key}}}`;
206
206
  processedContent = processedContent.split(placeholder).join(value);
207
207
  }
208
- await writeFile(destPath, processedContent);
208
+ await Bun.write(destPath, processedContent);
209
209
  }
210
210
  }
211
211
  }
@@ -231,9 +231,9 @@ async function copySourceFiles(sourcePath, targetPath, variables) {
231
231
  if (entry.isDirectory()) {
232
232
  await copySourceFiles(sourceEntryPath, targetEntryPath, variables);
233
233
  } else if (entry.isFile()) {
234
- const content = await readFile(sourceEntryPath, "utf-8");
234
+ const content = await Bun.file(sourceEntryPath).text();
235
235
  const processedContent = variables ? applyVariableReplacements(content, entry.name, variables) : content;
236
- await writeFile(targetEntryPath, processedContent);
236
+ await Bun.write(targetEntryPath, processedContent);
237
237
  }
238
238
  }
239
239
  }
@@ -532,14 +532,27 @@ async function compileMdx(content, cwd, options = {}) {
532
532
  });
533
533
  return String(result);
534
534
  } catch (error) {
535
- console.error("[reroute/mdx] Compilation failed:", error);
535
+ const errorMessage = error instanceof Error ? error.message : String(error);
536
+ const errorLocation = error && typeof error === "object" && "place" in error && error.place && typeof error.place === "object" ? `at line ${error.place.line || "?"}, column ${error.place.column || "?"}` : "";
537
+ const fileInfo = options.filename ? ` in ${options.filename}` : "";
538
+ console.warn(`[reroute/mdx] Compilation failed${fileInfo}${errorLocation ? ` ${errorLocation}` : ""}: ${errorMessage}`);
539
+ console.warn("[reroute/mdx] Falling back to react-markdown");
536
540
  return null;
537
541
  }
538
542
  }
539
543
  async function generateMarkdownModule(processed, cwd, options = {}) {
540
544
  const { frontmatter, content } = processed;
541
- const { enableGfm = true, theme = "github-dark", isMdx = false } = options;
542
- const compiledMdx = await compileMdx(content, cwd, { enableGfm, theme });
545
+ const {
546
+ enableGfm = true,
547
+ theme = "github-dark",
548
+ isMdx = false,
549
+ filename
550
+ } = options;
551
+ const compiledMdx = await compileMdx(content, cwd, {
552
+ enableGfm,
553
+ theme,
554
+ filename
555
+ });
543
556
  if (compiledMdx) {
544
557
  return `// Generated from ${isMdx ? "MDX" : "Markdown"} file with @mdx-js/mdx
545
558
 
@@ -557,7 +570,6 @@ export const ssr = {
557
570
  };
558
571
  `;
559
572
  }
560
- console.warn("[reroute/mdx] MDX compile unavailable; falling back to react-markdown");
561
573
  const escapedContent = content.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
562
574
  const pluginImports = [];
563
575
  const remarkPluginsList = [];
@@ -651,7 +663,7 @@ var init_markdown_processor = () => {};
651
663
 
652
664
  // packages/cli/src/libs/production.ts
653
665
  function isProductionMode(args = []) {
654
- return true;
666
+ return Bun.env.NODE_ENV === "production" || args.includes("--prod");
655
667
  }
656
668
 
657
669
  // packages/cli/src/libs/tailwind.ts
@@ -659,20 +671,28 @@ import { spawn } from "node:child_process";
659
671
  import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
660
672
  import { join as join4 } from "node:path";
661
673
  function isTailwindAvailable(cwd) {
662
- const packageJsonPath = join4(cwd, "package.json");
663
- if (!existsSync4(packageJsonPath)) {
664
- return false;
665
- }
666
- try {
667
- const packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
668
- const deps = {
669
- ...packageJson.dependencies,
670
- ...packageJson.devDependencies
671
- };
672
- return "@tailwindcss/cli" in deps;
673
- } catch {
674
- return false;
674
+ const pathsToTry = [
675
+ join4(cwd, "package.json"),
676
+ join4(cwd, "../package.json"),
677
+ join4(cwd, "../../package.json"),
678
+ join4(cwd, "../../../package.json")
679
+ ];
680
+ for (const packageJsonPath of pathsToTry) {
681
+ if (!existsSync4(packageJsonPath)) {
682
+ continue;
683
+ }
684
+ try {
685
+ const packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
686
+ const deps = {
687
+ ...packageJson.dependencies,
688
+ ...packageJson.devDependencies
689
+ };
690
+ if ("@tailwindcss/cli" in deps) {
691
+ return true;
692
+ }
693
+ } catch {}
675
694
  }
695
+ return false;
676
696
  }
677
697
  function getTailwindPaths(cwd) {
678
698
  const input = join4(cwd, "src/client/theme.css");
@@ -704,12 +724,16 @@ function resolveTailwindBin(cwd) {
704
724
  }
705
725
  return join4(cwd, "node_modules/.bin/tailwindcss");
706
726
  }
707
- async function buildTailwind(cwd) {
727
+ async function buildTailwind(cwd, minify = false) {
708
728
  const { input, output } = getTailwindPaths(cwd);
709
729
  return new Promise((resolve, reject) => {
710
730
  const tailwindBin = resolveTailwindBin(cwd);
711
731
  const args = ["-i", input, "-o", output];
712
- console.log(`[reroute/tailwind] build start: -i ${input} -o ${output}`);
732
+ if (minify) {
733
+ args.push("--minify");
734
+ }
735
+ const argsStr = args.join(" ");
736
+ console.log(`[reroute/tailwind] build start: ${argsStr}`);
713
737
  const tailwind = spawn(tailwindBin, args, {
714
738
  cwd,
715
739
  stdio: "pipe"
@@ -739,10 +763,10 @@ async function buildTailwind(cwd) {
739
763
  });
740
764
  });
741
765
  }
742
- async function buildTailwindIfConfigured(cwd) {
766
+ async function buildTailwindIfConfigured(cwd, minify = false) {
743
767
  try {
744
768
  if (isTailwindAvailable(cwd) && hasTailwindInput(cwd)) {
745
- await buildTailwind(cwd);
769
+ await buildTailwind(cwd, minify);
746
770
  return true;
747
771
  }
748
772
  return false;
@@ -759,16 +783,69 @@ __export(exports_gen, {
759
783
  default: () => gen
760
784
  });
761
785
  import { watch } from "node:fs";
762
- import { mkdir as mkdir2, readdir as readdir2, rm, writeFile as writeFile2 } from "node:fs/promises";
786
+ import { mkdir as mkdir2, readdir as readdir2, rm } from "node:fs/promises";
763
787
  import { join as join5 } from "node:path";
764
788
  import { pathToFileURL } from "node:url";
765
- async function cleanupOutputDir(cwd) {
789
+ async function ensureOutputDir(cwd) {
766
790
  try {
767
- await rm(join5(cwd, OUTPUT_DIR), { force: true });
768
- await mkdir2(join5(cwd, OUTPUT_DIR), { recursive: true });
769
- console.log("[reroute/gen] Cleaned up generated artifacts in .reroute");
791
+ const outputPath = join5(cwd, OUTPUT_DIR);
792
+ let needsCleanup = false;
793
+ try {
794
+ const entries = await readdir2(outputPath);
795
+ needsCleanup = entries.length > 0;
796
+ } catch {}
797
+ if (needsCleanup) {
798
+ await rm(outputPath, { force: true, recursive: true });
799
+ console.log("[reroute/gen] Cleaned up generated artifacts in .reroute");
800
+ }
801
+ await mkdir2(outputPath, { recursive: true });
802
+ await mkdir2(join5(cwd, OUTPUT_COLLECTIONS_DIR), { recursive: true });
803
+ await mkdir2(join5(cwd, ".reroute/bundles"), { recursive: true });
770
804
  } catch {}
771
805
  }
806
+ async function writeStubFiles(cwd) {
807
+ const STUB_ROUTES = `// \uD83D\uDEA8 Auto-generated stub by Reroute - DO NOT EDIT \uD83D\uDEA8
808
+ // This will be replaced by actual routes
809
+ /* eslint-disable */
810
+ // @ts-nocheck
811
+
812
+ export const layouts: any[] = [];
813
+ export const notFoundRoutes: any[] = [];
814
+
815
+ export function matchRoute(pathname: string): any {
816
+ return null;
817
+ }
818
+
819
+ export type RouteParams = Record<string, never>;
820
+ `;
821
+ const STUB_CONTENT = `// \uD83D\uDEA8 Auto-generated stub by Reroute - DO NOT EDIT \uD83D\uDEA8
822
+ // This will be replaced by actual content
823
+ /* eslint-disable */
824
+ // @ts-nocheck
825
+
826
+ export const contentRegistry: Record<string, any> = {};
827
+ `;
828
+ const STUB_INDEX = `// \uD83D\uDEA8 Auto-generated stub by Reroute - DO NOT EDIT \uD83D\uDEA8
829
+ // This will be replaced by actual artifacts
830
+ /* eslint-disable */
831
+ // @ts-nocheck
832
+
833
+ import { layouts, matchRoute, notFoundRoutes } from './routes';
834
+
835
+ export const artifacts = {
836
+ layouts,
837
+ matchRoute,
838
+ notFoundRoutes,
839
+ contentBaseUrl: '/.reroute/collections'
840
+ } as const;
841
+
842
+ export type RerouteArtifacts = typeof artifacts;
843
+ `;
844
+ await Bun.write(join5(cwd, OUTPUT_ROUTES), STUB_ROUTES);
845
+ await Bun.write(join5(cwd, OUTPUT_CONTENT_TS), STUB_CONTENT);
846
+ await Bun.write(join5(cwd, OUTPUT_INDEX), STUB_INDEX);
847
+ console.log("[reroute/gen] Initialized stub files");
848
+ }
772
849
  async function scanDirectory(dir, base = "") {
773
850
  const files = [];
774
851
  const entries = await readdir2(dir, { withFileTypes: true });
@@ -880,10 +957,26 @@ function getImportPath(filePath) {
880
957
  return `../src/client/routes/${pathWithoutExt}`;
881
958
  }
882
959
  function generateTypeScript(tree) {
883
- const imports = [
884
- ...tree.routes.map((r, i) => `import Route${i} from '${getImportPath(r.filePath)}';`),
885
- ...tree.layouts.map((l, i) => `import Layout${i} from '${getImportPath(l.filePath)}';`),
886
- ...tree.notFoundRoutes.map((nf, i) => `import NotFound${i} from '${getImportPath(nf.filePath)}';`)
960
+ const helperImport = "import { createLazyRoute } from 'reroute-js/react';";
961
+ const eagerImports = [
962
+ ...tree.routes.map((r, i) => `import Route${i}Eager from '${getImportPath(r.filePath)}';`),
963
+ ...tree.layouts.map((l, i) => `import Layout${i}Eager from '${getImportPath(l.filePath)}';`),
964
+ ...tree.notFoundRoutes.map((nf, i) => `import NotFound${i}Eager from '${getImportPath(nf.filePath)}';`)
965
+ ].join(`
966
+ `);
967
+ const lazyWrappers = [
968
+ ...tree.routes.map((r, i) => {
969
+ const importPath = getImportPath(r.filePath);
970
+ return `const Route${i} = createLazyRoute(Route${i}Eager, () => import('${importPath}'), "${r.pattern}");`;
971
+ }),
972
+ ...tree.layouts.map((l, i) => {
973
+ const importPath = getImportPath(l.filePath);
974
+ return `const Layout${i} = createLazyRoute(Layout${i}Eager, () => import('${importPath}'), "${l.pattern}");`;
975
+ }),
976
+ ...tree.notFoundRoutes.map((nf, i) => {
977
+ const importPath = getImportPath(nf.filePath);
978
+ return `const NotFound${i} = createLazyRoute(NotFound${i}Eager, () => import('${importPath}'), "${nf.notFoundBasePattern || "/"}");`;
979
+ })
887
980
  ].join(`
888
981
  `);
889
982
  const routesArray = tree.routes.map((r, i) => {
@@ -923,7 +1016,11 @@ function generateTypeScript(tree) {
923
1016
  /* eslint-disable */
924
1017
  // @ts-nocheck
925
1018
 
926
- ${imports}
1019
+ ${helperImport}
1020
+
1021
+ ${eagerImports}
1022
+
1023
+ ${lazyWrappers}
927
1024
 
928
1025
  export const routes: RouteInfo = [
929
1026
  ${routesArray}
@@ -1003,7 +1100,7 @@ async function sha8(text) {
1003
1100
  hex += b.toString(16).padStart(2, "0");
1004
1101
  return hex.slice(0, 8);
1005
1102
  }
1006
- async function buildContentChunks(cwd) {
1103
+ async function buildContentChunks(cwd, args = []) {
1007
1104
  const routesRoot = join5(cwd, ROUTES_DIR);
1008
1105
  console.log(`[reroute/content] scan ${routesRoot}`);
1009
1106
  const collections = await readdir2(routesRoot, { withFileTypes: true });
@@ -1015,7 +1112,7 @@ async function buildContentChunks(cwd) {
1015
1112
  const contentDir = join5(routesRoot, collection, "content");
1016
1113
  console.log(`[reroute/content] collection ${collection} dir ${contentDir}`);
1017
1114
  const files = await listContentFiles(contentDir);
1018
- console.log(`[reroute/content] files ${files.join(",")}`);
1115
+ console.log(`[reroute/content] files ${files.length}`);
1019
1116
  if (!files.length)
1020
1117
  continue;
1021
1118
  for (const file of files) {
@@ -1034,8 +1131,7 @@ async function buildContentChunks(cwd) {
1034
1131
  }
1035
1132
  let code = "";
1036
1133
  try {
1037
- console.log(`[reroute/content] build ${buildSrc}`);
1038
- const isProd = isProductionMode();
1134
+ const isProd = isProductionMode(args);
1039
1135
  const result = await Bun.build({
1040
1136
  entrypoints: [buildSrc],
1041
1137
  target: "browser",
@@ -1055,19 +1151,17 @@ async function buildContentChunks(cwd) {
1055
1151
  continue;
1056
1152
  }
1057
1153
  const hash = await sha8(code);
1058
- const chunkRelDir = join5(".reroute", "chunks", collection);
1154
+ const chunkRelDir = join5(".reroute", "bundles");
1059
1155
  const chunkAbsDir = join5(cwd, chunkRelDir);
1060
- const outFile = `${name}.${hash}.js`;
1156
+ const outFile = `${collection}-${name}.${hash}.js`;
1061
1157
  const absOut = join5(chunkAbsDir, outFile);
1062
- await mkdir2(chunkAbsDir, { recursive: true });
1063
1158
  try {
1064
1159
  const exists = await Bun.file(absOut).exists();
1065
1160
  if (!exists)
1066
- await writeFile2(absOut, code, "utf-8");
1161
+ await Bun.write(absOut, code);
1067
1162
  } catch {}
1068
1163
  let meta = {};
1069
1164
  try {
1070
- console.log(`[reroute/content] meta ${buildSrc}`);
1071
1165
  const url = `${pathToFileURL(buildSrc).href}?t=${Date.now()}`;
1072
1166
  const m = await import(url);
1073
1167
  meta = m.meta || {};
@@ -1077,7 +1171,7 @@ async function buildContentChunks(cwd) {
1077
1171
  name,
1078
1172
  slug: name,
1079
1173
  href: `/${collection}/${name}`,
1080
- moduleUrl: ("/" + chunkRelDir.replace(/\\/g, "/") + "/" + outFile).replace(/\\+/g, "/"),
1174
+ moduleUrl: `/bundles/${outFile}`,
1081
1175
  meta
1082
1176
  });
1083
1177
  }
@@ -1108,12 +1202,10 @@ async function buildContentChunks(cwd) {
1108
1202
  lines.push(" return m ? (m as Record<string, any>)[name] : undefined;");
1109
1203
  lines.push("}");
1110
1204
  lines.push("");
1111
- await mkdir2(join5(cwd, ".reroute"), { recursive: true });
1112
- await writeFile2(join5(cwd, OUTPUT_CONTENT_TS), lines.join(`
1113
- `), "utf-8");
1205
+ await Bun.write(join5(cwd, OUTPUT_CONTENT_TS), lines.join(`
1206
+ `));
1114
1207
  console.log(`[reroute/content] wrote ${join5(cwd, OUTPUT_CONTENT_TS)}`);
1115
1208
  const collectionsSet = new Set(results.map((r) => r.collection));
1116
- await mkdir2(join5(cwd, OUTPUT_COLLECTIONS_DIR), { recursive: true });
1117
1209
  for (const collection of collectionsSet) {
1118
1210
  const items = results.filter((r) => r.collection === collection);
1119
1211
  const js = [];
@@ -1133,8 +1225,8 @@ async function buildContentChunks(cwd) {
1133
1225
  js.push(" return byName[name];");
1134
1226
  js.push("}");
1135
1227
  js.push("");
1136
- await writeFile2(join5(cwd, OUTPUT_COLLECTIONS_DIR, `${collection}.js`), js.join(`
1137
- `), "utf-8");
1228
+ await Bun.write(join5(cwd, OUTPUT_COLLECTIONS_DIR, `${collection}.js`), js.join(`
1229
+ `));
1138
1230
  console.log(`[reroute/content] wrote ${join5(cwd, OUTPUT_COLLECTIONS_DIR, `${collection}.js`)}`);
1139
1231
  }
1140
1232
  }
@@ -1147,9 +1239,6 @@ async function preprocessMarkdownFiles(cwd) {
1147
1239
  } catch {}
1148
1240
  const markdownConfig = getMarkdownConfig(cwd);
1149
1241
  console.log("[reroute/markdown] Config:", markdownConfig);
1150
- try {
1151
- await mkdir2(markdownDir, { recursive: true });
1152
- } catch {}
1153
1242
  async function scanMarkdown(dir, base = "") {
1154
1243
  const files = [];
1155
1244
  try {
@@ -1161,7 +1250,6 @@ async function preprocessMarkdownFiles(cwd) {
1161
1250
  const nested = await scanMarkdown(fullPath, relativePath);
1162
1251
  files.push(...nested);
1163
1252
  } else if (entry.isFile() && isMarkdownFile(entry.name)) {
1164
- console.log(`[reroute/markdown] Found markdown file: ${relativePath}`);
1165
1253
  files.push(relativePath);
1166
1254
  }
1167
1255
  }
@@ -1172,13 +1260,12 @@ async function preprocessMarkdownFiles(cwd) {
1172
1260
  }
1173
1261
  console.log(`[reroute/markdown] Scanning ${routesPath} for markdown files...`);
1174
1262
  const markdownFiles = await scanMarkdown(routesPath);
1175
- console.log(`[reroute/markdown] Scan complete. Found files:`, markdownFiles);
1263
+ console.log(`[reroute/markdown] Scan complete. Found files:`, markdownFiles.length);
1176
1264
  if (markdownFiles.length === 0) {
1177
1265
  console.log("[reroute/markdown] No markdown files found, skipping preprocessing");
1178
1266
  return;
1179
1267
  }
1180
1268
  console.log(`[reroute/markdown] Found ${markdownFiles.length} markdown file(s)`);
1181
- await mkdir2(markdownDir, { recursive: true });
1182
1269
  for (const file of markdownFiles) {
1183
1270
  const sourcePath = join5(routesPath, file);
1184
1271
  const targetPath = join5(markdownDir, file.replace(/\.mdx?$/, ".tsx"));
@@ -1190,25 +1277,94 @@ async function preprocessMarkdownFiles(cwd) {
1190
1277
  moduleCode = await generateMarkdownModule(processed, cwd, {
1191
1278
  enableGfm: markdownConfig.hasRemarkGfm,
1192
1279
  theme: "github-dark",
1193
- isMdx
1280
+ isMdx,
1281
+ filename: file
1194
1282
  });
1195
1283
  } else {
1196
1284
  moduleCode = generatePlainMarkdownModule(processed);
1197
1285
  }
1198
- const targetDir = join5(markdownDir, file.split("/").slice(0, -1).join("/"));
1199
- if (targetDir !== markdownDir) {
1200
- await mkdir2(targetDir, { recursive: true });
1201
- }
1202
- await writeFile2(targetPath, moduleCode, "utf-8");
1203
- console.log(`[reroute/markdown] Processed ${file} -> ${targetPath}`);
1286
+ await Bun.write(targetPath, moduleCode);
1204
1287
  } catch (error) {
1205
1288
  console.error(`[reroute/markdown] Failed to process ${file}:`, error);
1206
1289
  }
1207
1290
  }
1208
1291
  }
1209
- async function generate(cwd) {
1292
+ async function buildEntrypointBundle(cwd, args = []) {
1293
+ const clientDir = join5(cwd, "src", "client");
1294
+ const entrypoint = join5(clientDir, "index.tsx");
1295
+ const exists = await Bun.file(entrypoint).exists();
1296
+ if (!exists) {
1297
+ console.log("[reroute/gen] No index.tsx found, skipping bundle build");
1298
+ return;
1299
+ }
1300
+ console.log("[reroute/gen] Building entrypoint bundle with code splitting...");
1301
+ const isProd = isProductionMode(args);
1302
+ const result = await Bun.build({
1303
+ entrypoints: [entrypoint],
1304
+ target: "browser",
1305
+ format: "esm",
1306
+ splitting: true,
1307
+ sourcemap: isProd ? "linked" : "external",
1308
+ minify: isProd,
1309
+ naming: {
1310
+ entry: "[name].[hash].[ext]",
1311
+ chunk: "chunk.[hash].[ext]",
1312
+ asset: "[name].[hash].[ext]"
1313
+ },
1314
+ jsx: {
1315
+ runtime: "automatic",
1316
+ importSource: "react",
1317
+ development: !isProd
1318
+ },
1319
+ define: {
1320
+ "process.env.NODE_ENV": isProd ? '"production"' : '"development"',
1321
+ __DEV__: isProd ? "false" : "true",
1322
+ "import.meta.env.MODE": isProd ? '"production"' : '"development"'
1323
+ },
1324
+ ...isProd ? { drop: ["console", "debugger"] } : {}
1325
+ });
1326
+ if (!result.success) {
1327
+ console.error("[reroute/gen] Entrypoint build failed:");
1328
+ for (const log of result.logs)
1329
+ console.error(log);
1330
+ throw new Error("Failed to build entrypoint");
1331
+ }
1332
+ const bundlesDir = join5(cwd, ".reroute", "bundles");
1333
+ try {
1334
+ const existingFiles = await readdir2(bundlesDir);
1335
+ for (const file of existingFiles) {
1336
+ if (/^(index|chunk)\.[a-z0-9]+\.(js|js\.map)$/i.test(file)) {
1337
+ await rm(join5(bundlesDir, file), { force: true });
1338
+ }
1339
+ }
1340
+ } catch {}
1341
+ const outputs = [];
1342
+ let entryFile = "";
1343
+ for (const output of result.outputs) {
1344
+ const content = await output.text();
1345
+ const fileName = output.path.split("/").pop() || output.path.split("\\").pop() || "unknown";
1346
+ const destPath = join5(bundlesDir, fileName);
1347
+ await Bun.write(destPath, content);
1348
+ const isEntry = fileName.startsWith("index.") && fileName.endsWith(".js") && !fileName.endsWith(".map");
1349
+ if (isEntry)
1350
+ entryFile = fileName;
1351
+ outputs.push({
1352
+ fileName,
1353
+ size: content.length,
1354
+ isEntry
1355
+ });
1356
+ }
1357
+ const totalSize = outputs.reduce((sum, o) => sum + o.size, 0);
1358
+ const gzipped = Bun.gzipSync(new TextEncoder().encode(outputs.find((o) => o.isEntry)?.fileName ? await Bun.file(join5(bundlesDir, entryFile)).text() : "")).length;
1359
+ console.log(`[reroute/gen] Built ${outputs.length} files (${(totalSize / 1024).toFixed(2)}KB, ${(gzipped / 1024).toFixed(2)}KB gzipped)`);
1360
+ console.log(`[reroute/gen] Entry: ${entryFile}`);
1361
+ console.log(`[reroute/gen] Chunks: ${outputs.filter((o) => !o.isEntry && o.fileName.endsWith(".js")).length}`);
1362
+ }
1363
+ async function generate(cwd, args = []) {
1364
+ const startTime = performance.now();
1210
1365
  console.log("[reroute/gen] Starting generation...");
1211
- await cleanupOutputDir(cwd);
1366
+ await ensureOutputDir(cwd);
1367
+ await writeStubFiles(cwd);
1212
1368
  await preprocessMarkdownFiles(cwd);
1213
1369
  const routesPath = join5(cwd, ROUTES_DIR);
1214
1370
  try {
@@ -1217,15 +1373,14 @@ async function generate(cwd) {
1217
1373
  const all = Array.from(new Set([...files, ...nfFiles]));
1218
1374
  const tree = generateRouteTree(all.map((f) => f.replace(/\\/g, "/")));
1219
1375
  const ts = generateTypeScript(tree);
1220
- await mkdir2(join5(cwd, ".reroute"), { recursive: true });
1221
- await writeFile2(join5(cwd, OUTPUT_ROUTES), ts, "utf-8");
1376
+ await Bun.write(join5(cwd, OUTPUT_ROUTES), ts);
1222
1377
  console.log(`[reroute/gen] Generated routes: ${join5(cwd, OUTPUT_ROUTES)}`);
1223
1378
  } catch (error) {
1224
1379
  console.error("[reroute/gen] Failed to generate routes:", error);
1225
1380
  throw error;
1226
1381
  }
1227
1382
  try {
1228
- await buildContentChunks(cwd);
1383
+ await buildContentChunks(cwd, args);
1229
1384
  console.log(`[reroute/gen] Generated content: ${join5(cwd, OUTPUT_CONTENT_TS)} + collections/*.js`);
1230
1385
  } catch (error) {
1231
1386
  console.error("[reroute/gen] Failed to generate content:", error);
@@ -1246,25 +1401,34 @@ async function generate(cwd) {
1246
1401
  indexLines.push("} as const;");
1247
1402
  indexLines.push("");
1248
1403
  indexLines.push("export type RerouteArtifacts = typeof artifacts;");
1249
- await writeFile2(join5(cwd, OUTPUT_INDEX), indexLines.join(`
1250
- `), "utf-8");
1404
+ await Bun.write(join5(cwd, OUTPUT_INDEX), indexLines.join(`
1405
+ `));
1251
1406
  console.log(`[reroute/gen] Generated index: ${join5(cwd, OUTPUT_INDEX)}`);
1252
- console.log("[reroute/gen] Generation complete");
1407
+ try {
1408
+ await buildEntrypointBundle(cwd, args);
1409
+ } catch (error) {
1410
+ console.error("[reroute/gen] Failed to build entrypoint:", error);
1411
+ throw error;
1412
+ }
1413
+ const endTime = performance.now();
1414
+ const duration = ((endTime - startTime) / 1000).toFixed(2);
1415
+ console.log(`[reroute/gen] Generation complete in ${duration}s`);
1253
1416
  }
1254
1417
  async function gen(args) {
1255
1418
  const cwd = process.cwd();
1256
1419
  const watchMode = args.includes("--watch") || args.includes("-w");
1420
+ const isProd = isProductionMode(args);
1257
1421
  if (!watchMode) {
1258
- await generate(cwd);
1259
- await buildTailwindIfConfigured(cwd);
1422
+ await generate(cwd, args);
1423
+ await buildTailwindIfConfigured(cwd, isProd);
1260
1424
  checkMarkdownIfConfigured(cwd);
1261
1425
  return;
1262
1426
  }
1263
1427
  console.log("[reroute/gen] Watch mode enabled");
1264
1428
  console.log("[reroute/gen] Initial generation...");
1265
- await generate(cwd);
1429
+ await generate(cwd, args);
1266
1430
  try {
1267
- await buildTailwindIfConfigured(cwd);
1431
+ await buildTailwindIfConfigured(cwd, isProd);
1268
1432
  checkMarkdownIfConfigured(cwd);
1269
1433
  } catch {}
1270
1434
  const notifyReload = async (reason) => {
@@ -1284,6 +1448,7 @@ async function gen(args) {
1284
1448
  } catch {}
1285
1449
  }
1286
1450
  };
1451
+ await notifyReload("initial generation");
1287
1452
  const routesPath = join5(cwd, ROUTES_DIR);
1288
1453
  console.log(`[reroute/gen] Watching ${routesPath} for changes...`);
1289
1454
  let debounce = null;
@@ -1295,16 +1460,16 @@ async function gen(args) {
1295
1460
  debounce = setTimeout(async () => {
1296
1461
  console.log("[reroute/gen] Change detected, regenerating...");
1297
1462
  try {
1298
- await generate(cwd);
1299
- await buildTailwindIfConfigured(cwd);
1463
+ await generate(cwd, args);
1464
+ await buildTailwindIfConfigured(cwd, isProd);
1300
1465
  await notifyReload("routes change");
1301
1466
  } catch (e) {
1302
1467
  console.error("[reroute/gen] Error during regeneration:", e);
1303
1468
  }
1304
- }, 120);
1469
+ }, 50);
1305
1470
  });
1306
1471
  const clientPath = join5(cwd, "src", "client");
1307
- console.log(`[reroute/gen] Watching ${clientPath} for Tailwind class changes...`);
1472
+ console.log(`[reroute/gen] Watching ${clientPath} for changes...`);
1308
1473
  let twDebounce = null;
1309
1474
  const twWatcher = watch(clientPath, { recursive: true }, (_ev, filename) => {
1310
1475
  if (!filename)
@@ -1320,10 +1485,14 @@ async function gen(args) {
1320
1485
  clearTimeout(twDebounce);
1321
1486
  twDebounce = setTimeout(async () => {
1322
1487
  try {
1323
- await buildTailwindIfConfigured(cwd);
1488
+ if (name === "index.tsx" || name.includes("components/") || name.includes("hooks/") || name.includes("providers/")) {
1489
+ console.log("[reroute/gen] Client code changed, rebuilding bundle...");
1490
+ await buildEntrypointBundle(cwd, args);
1491
+ }
1492
+ await buildTailwindIfConfigured(cwd, isProd);
1324
1493
  await notifyReload("client change");
1325
1494
  } catch {}
1326
- }, 150);
1495
+ }, 100);
1327
1496
  });
1328
1497
  process.on("SIGINT", () => {
1329
1498
  console.log(`
@@ -1344,69 +1513,6 @@ var init_gen = __esm(() => {
1344
1513
  init_tailwind();
1345
1514
  });
1346
1515
 
1347
- // packages/cli/src/commands/boot.ts
1348
- var exports_boot = {};
1349
- __export(exports_boot, {
1350
- default: () => boot
1351
- });
1352
- import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
1353
- import { join as join6 } from "node:path";
1354
- async function boot(_) {
1355
- const cwd = process.cwd();
1356
- try {
1357
- console.log("[reroute/boot] Initializing .reroute directory...");
1358
- await mkdir3(join6(cwd, OUTPUT_DIR2), { recursive: true });
1359
- await mkdir3(join6(cwd, OUTPUT_COLLECTIONS_DIR2), { recursive: true });
1360
- await writeFile3(join6(cwd, OUTPUT_ROUTES2), STUB_ROUTES, "utf-8");
1361
- console.log(`[reroute/boot] Created stub: ${OUTPUT_ROUTES2}`);
1362
- await writeFile3(join6(cwd, OUTPUT_CONTENT_TS2), STUB_CONTENT, "utf-8");
1363
- console.log(`[reroute/boot] Created stub: ${OUTPUT_CONTENT_TS2}`);
1364
- await writeFile3(join6(cwd, OUTPUT_INDEX2), STUB_INDEX, "utf-8");
1365
- console.log(`[reroute/boot] Created stub: ${OUTPUT_INDEX2}`);
1366
- console.log("[reroute/boot] Initialization complete");
1367
- console.log('[reroute/boot] Run "reroute gen" to generate actual routes and content.');
1368
- } catch (error) {
1369
- console.error("[reroute/boot] Failed to initialize:", error);
1370
- throw error;
1371
- }
1372
- }
1373
- var OUTPUT_DIR2 = ".reroute", OUTPUT_ROUTES2 = ".reroute/routes.ts", OUTPUT_CONTENT_TS2 = ".reroute/content.ts", OUTPUT_COLLECTIONS_DIR2 = ".reroute/collections", OUTPUT_INDEX2 = ".reroute/index.ts", STUB_ROUTES = `// \uD83D\uDEA8 Auto-generated stub by Reroute - DO NOT EDIT \uD83D\uDEA8
1374
- // Run 'reroute gen' to generate actual routes
1375
- /* eslint-disable */
1376
- // @ts-nocheck
1377
-
1378
- export const layouts: any[] = [];
1379
- export const notFoundRoutes: any[] = [];
1380
-
1381
- export function matchRoute(pathname: string): any {
1382
- return null;
1383
- }
1384
-
1385
- export type RouteParams = Record<string, never>;
1386
- `, STUB_CONTENT = `// \uD83D\uDEA8 Auto-generated stub by Reroute - DO NOT EDIT \uD83D\uDEA8
1387
- // Run 'reroute gen' to generate actual content
1388
- /* eslint-disable */
1389
- // @ts-nocheck
1390
-
1391
- export const contentRegistry: Record<string, any> = {};
1392
- `, STUB_INDEX = `// \uD83D\uDEA8 Auto-generated stub by Reroute - DO NOT EDIT \uD83D\uDEA8
1393
- // Run 'reroute gen' to generate actual artifacts
1394
- /* eslint-disable */
1395
- // @ts-nocheck
1396
-
1397
- import { layouts, matchRoute, notFoundRoutes } from './routes';
1398
-
1399
- export const artifacts = {
1400
- layouts,
1401
- matchRoute,
1402
- notFoundRoutes,
1403
- contentBaseUrl: '/.reroute/collections'
1404
- } as const;
1405
-
1406
- export type RerouteArtifacts = typeof artifacts;
1407
- `;
1408
- var init_boot = () => {};
1409
-
1410
1516
  // packages/cli/src/libs/log.ts
1411
1517
  function colorizeLogPrefix(text) {
1412
1518
  let colored = text;
@@ -1447,7 +1553,6 @@ var init_log = __esm(() => {
1447
1553
  "[reroute/markdown]": "{yellow-fg}",
1448
1554
  "[reroute/tailwind]": "{red-fg}",
1449
1555
  "[reroute/mdx]": "{bright-red-fg}",
1450
- "[reroute/boot]": "{bright-yellow-fg}",
1451
1556
  "[reroute/dev]": "{green-fg}",
1452
1557
  "[reroute/start]": "{bright-cyan-fg}",
1453
1558
  "[reroute/build]": "{bright-magenta-fg}",
@@ -1457,6 +1562,24 @@ var init_log = __esm(() => {
1457
1562
  };
1458
1563
  });
1459
1564
 
1565
+ // packages/cli/src/libs/server.ts
1566
+ async function waitForServerReady(port = 3000, timeout = 1e4) {
1567
+ const startTime = Date.now();
1568
+ const checkInterval = 200;
1569
+ while (Date.now() - startTime < timeout) {
1570
+ try {
1571
+ const response = await fetch(`http://localhost:${port}/`, {
1572
+ method: "GET"
1573
+ });
1574
+ if (response.status < 500) {
1575
+ return;
1576
+ }
1577
+ } catch {}
1578
+ await new Promise((resolve) => setTimeout(resolve, checkInterval));
1579
+ }
1580
+ throw new Error(`Timeout waiting for server to respond after ${timeout}ms`);
1581
+ }
1582
+
1460
1583
  // packages/cli/src/commands/dev.ts
1461
1584
  var exports_dev = {};
1462
1585
  __export(exports_dev, {
@@ -1464,19 +1587,65 @@ __export(exports_dev, {
1464
1587
  });
1465
1588
  import { spawn as spawn2 } from "node:child_process";
1466
1589
  import { existsSync as existsSync5 } from "node:fs";
1467
- import { join as join7 } from "node:path";
1590
+ import { join as join6 } from "node:path";
1591
+ async function waitForRequiredFiles(cwd, timeout = 30000) {
1592
+ const requiredFiles = [
1593
+ join6(cwd, ".reroute/routes.ts"),
1594
+ join6(cwd, ".reroute/content.ts"),
1595
+ join6(cwd, ".reroute/index.ts")
1596
+ ];
1597
+ const bundlesDir = join6(cwd, ".reroute/bundles");
1598
+ const startTime = Date.now();
1599
+ const checkInterval = 100;
1600
+ while (Date.now() - startTime < timeout) {
1601
+ const allFilesExist = requiredFiles.every((file) => existsSync5(file));
1602
+ if (!allFilesExist) {
1603
+ await new Promise((resolve) => setTimeout(resolve, checkInterval));
1604
+ continue;
1605
+ }
1606
+ if (existsSync5(bundlesDir)) {
1607
+ const { readdirSync, statSync } = __require("node:fs");
1608
+ try {
1609
+ const files = readdirSync(bundlesDir);
1610
+ const indexBundleFile = files.find((f) => {
1611
+ if (!f.startsWith("index.") || !f.endsWith(".js") || f.endsWith(".map")) {
1612
+ return false;
1613
+ }
1614
+ try {
1615
+ const filePath = join6(bundlesDir, f);
1616
+ const stats = statSync(filePath);
1617
+ return stats.size > 100;
1618
+ } catch {
1619
+ return false;
1620
+ }
1621
+ });
1622
+ if (indexBundleFile) {
1623
+ const filePath = join6(bundlesDir, indexBundleFile);
1624
+ const size1 = statSync(filePath).size;
1625
+ await new Promise((resolve) => setTimeout(resolve, 200));
1626
+ const size2 = statSync(filePath).size;
1627
+ if (size1 === size2 && size2 > 100) {
1628
+ return;
1629
+ }
1630
+ }
1631
+ } catch {}
1632
+ }
1633
+ await new Promise((resolve) => setTimeout(resolve, checkInterval));
1634
+ }
1635
+ throw new Error(`Timeout waiting for required files to be created after ${timeout}ms`);
1636
+ }
1468
1637
  function getRerouteCommand() {
1469
- const binPath = join7(import.meta.dir, "..", "..", "bin.ts");
1638
+ const binPath = join6(import.meta.dir, "..", "..", "bin.ts");
1470
1639
  const isBunDev = existsSync5(binPath);
1471
1640
  if (isBunDev) {
1472
1641
  return `bun ${binPath}`;
1473
1642
  }
1474
1643
  const cwd = process.cwd();
1475
1644
  const nodeModulesPaths = [
1476
- join7(cwd, "node_modules", ".bin", "reroute"),
1477
- join7(cwd, "..", "node_modules", ".bin", "reroute"),
1478
- join7(cwd, "..", "..", "node_modules", ".bin", "reroute"),
1479
- join7(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
1645
+ join6(cwd, "node_modules", ".bin", "reroute"),
1646
+ join6(cwd, "..", "node_modules", ".bin", "reroute"),
1647
+ join6(cwd, "..", "..", "node_modules", ".bin", "reroute"),
1648
+ join6(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
1480
1649
  ];
1481
1650
  for (const binPath2 of nodeModulesPaths) {
1482
1651
  if (existsSync5(binPath2)) {
@@ -1488,10 +1657,6 @@ function getRerouteCommand() {
1488
1657
  async function dev(args) {
1489
1658
  const singleColumn = args.includes("--single") || args.includes("-s");
1490
1659
  try {
1491
- console.log("[reroute/dev] Running boot...");
1492
- await boot([]);
1493
- console.log(`[reroute/dev] Boot complete
1494
- `);
1495
1660
  console.log("[reroute/dev] Starting development servers...");
1496
1661
  console.log(`[reroute/dev] Press Ctrl+C to stop
1497
1662
  `);
@@ -1503,9 +1668,27 @@ async function dev(args) {
1503
1668
  stdio: ["ignore", "pipe", "pipe"],
1504
1669
  shell: useShell
1505
1670
  });
1671
+ console.log("[reroute/dev] Generating bundle...");
1672
+ try {
1673
+ await waitForRequiredFiles(process.cwd());
1674
+ } catch (error) {
1675
+ console.error("[reroute/dev] Failed to initialize:", error);
1676
+ genProcess.kill();
1677
+ process.exit(1);
1678
+ }
1506
1679
  const serverProcess = spawn2("bun", ["--watch", "src/index.ts"], {
1507
1680
  stdio: ["ignore", "pipe", "pipe"]
1508
1681
  });
1682
+ console.log("[reroute/dev] Bundle complete, waiting for server...");
1683
+ const port = Number(process.env.PORT || "3000");
1684
+ try {
1685
+ await waitForServerReady(port);
1686
+ } catch (error) {
1687
+ console.error("[reroute/dev] Server failed to start:", error);
1688
+ genProcess.kill();
1689
+ serverProcess.kill();
1690
+ process.exit(1);
1691
+ }
1509
1692
  if (singleColumn) {
1510
1693
  const genBuffer = { current: "" };
1511
1694
  const serverBuffer = { current: "" };
@@ -1751,7 +1934,6 @@ async function dev(args) {
1751
1934
  }
1752
1935
  var init_dev = __esm(() => {
1753
1936
  init_log();
1754
- init_boot();
1755
1937
  });
1756
1938
 
1757
1939
  // packages/cli/src/commands/start.ts
@@ -1761,19 +1943,19 @@ __export(exports_start, {
1761
1943
  });
1762
1944
  import { spawn as spawn3 } from "node:child_process";
1763
1945
  import { existsSync as existsSync6 } from "node:fs";
1764
- import { join as join8 } from "node:path";
1946
+ import { join as join7 } from "node:path";
1765
1947
  function getRerouteCommand2() {
1766
- const binPath = join8(import.meta.dir, "..", "..", "bin.ts");
1948
+ const binPath = join7(import.meta.dir, "..", "..", "bin.ts");
1767
1949
  const isBunDev = existsSync6(binPath);
1768
1950
  if (isBunDev) {
1769
1951
  return `bun ${binPath}`;
1770
1952
  }
1771
1953
  const cwd = process.cwd();
1772
1954
  const nodeModulesPaths = [
1773
- join8(cwd, "node_modules", ".bin", "reroute"),
1774
- join8(cwd, "..", "node_modules", ".bin", "reroute"),
1775
- join8(cwd, "..", "..", "node_modules", ".bin", "reroute"),
1776
- join8(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
1955
+ join7(cwd, "node_modules", ".bin", "reroute"),
1956
+ join7(cwd, "..", "node_modules", ".bin", "reroute"),
1957
+ join7(cwd, "..", "..", "node_modules", ".bin", "reroute"),
1958
+ join7(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
1777
1959
  ];
1778
1960
  for (const binPath2 of nodeModulesPaths) {
1779
1961
  if (existsSync6(binPath2)) {
@@ -1786,21 +1968,7 @@ async function start(_args) {
1786
1968
  try {
1787
1969
  const rerouteCmd = getRerouteCommand2();
1788
1970
  const useShell = rerouteCmd.includes(" ");
1789
- const bootBuffer = { current: "" };
1790
1971
  const genBuffer = { current: "" };
1791
- const handleBootOutput = (data) => {
1792
- const text = bootBuffer.current + data.toString();
1793
- const lines = text.split(`
1794
- `);
1795
- bootBuffer.current = lines.pop() || "";
1796
- for (const line of lines) {
1797
- if (!line.trim()) {
1798
- continue;
1799
- }
1800
- const ansiColored = colorizeLogPrefixAnsi(line);
1801
- console.log(ansiColored);
1802
- }
1803
- };
1804
1972
  const handleGenOutput = (data) => {
1805
1973
  const text = genBuffer.current + data.toString();
1806
1974
  const lines = text.split(`
@@ -1814,34 +1982,10 @@ async function start(_args) {
1814
1982
  console.log(ansiColored);
1815
1983
  }
1816
1984
  };
1817
- process.stdout.write(`${colorizeLogPrefixAnsi("[reroute/start] Running boot...")}
1818
- `);
1819
- const bootCommand = useShell ? `${rerouteCmd} boot` : rerouteCmd;
1820
- const bootArgs = useShell ? [] : ["boot"];
1821
- await new Promise((resolve, reject) => {
1822
- const bootProcess = spawn3(bootCommand, bootArgs, {
1823
- stdio: ["ignore", "pipe", "pipe"],
1824
- shell: useShell
1825
- });
1826
- bootProcess.stdout?.on("data", handleBootOutput);
1827
- bootProcess.stderr?.on("data", handleBootOutput);
1828
- bootProcess.on("exit", (code) => {
1829
- if (code !== null && code !== 0) {
1830
- reject(new Error(`Boot exited with code ${code}`));
1831
- } else {
1832
- resolve();
1833
- }
1834
- });
1835
- bootProcess.on("error", (error) => {
1836
- reject(error);
1837
- });
1838
- });
1839
- process.stdout.write(colorizeLogPrefixAnsi(`[reroute/start] Boot complete
1840
- `));
1841
1985
  process.stdout.write(`${colorizeLogPrefixAnsi("[reroute/start] Running gen...")}
1842
1986
  `);
1843
- const genCommand = useShell ? `${rerouteCmd} gen` : rerouteCmd;
1844
- const genArgs = useShell ? [] : ["gen"];
1987
+ const genCommand = useShell ? `${rerouteCmd} gen --prod` : rerouteCmd;
1988
+ const genArgs = useShell ? [] : ["gen", "--prod"];
1845
1989
  await new Promise((resolve, reject) => {
1846
1990
  const genProcess = spawn3(genCommand, genArgs, {
1847
1991
  stdio: ["ignore", "pipe", "pipe"],
@@ -1864,8 +2008,6 @@ async function start(_args) {
1864
2008
  `));
1865
2009
  process.stdout.write(`${colorizeLogPrefixAnsi("[reroute/start] Starting server...")}
1866
2010
  `);
1867
- process.stdout.write(colorizeLogPrefixAnsi(`[reroute/start] Press Ctrl+C to stop
1868
- `));
1869
2011
  const serverProcess = spawn3("bun", ["src/index.ts"], {
1870
2012
  stdio: ["ignore", "pipe", "pipe"]
1871
2013
  });
@@ -1873,6 +2015,19 @@ async function start(_args) {
1873
2015
  const handleServerOutput = createServerOutputHandler(serverBuffer);
1874
2016
  serverProcess.stdout?.on("data", handleServerOutput);
1875
2017
  serverProcess.stderr?.on("data", handleServerOutput);
2018
+ process.stdout.write(colorizeLogPrefixAnsi(`[reroute/start] Waiting for server to be ready...
2019
+ `));
2020
+ const port = Number(process.env.PORT || "3000");
2021
+ try {
2022
+ await waitForServerReady(port, 1e4);
2023
+ process.stdout.write(colorizeLogPrefixAnsi(`[reroute/start] Server is ready!
2024
+ `));
2025
+ } catch {
2026
+ process.stdout.write(colorizeLogPrefixAnsi(`[reroute/start] \uD83D\uDEA8Warning: Server may not be fully ready yet
2027
+ `));
2028
+ }
2029
+ process.stdout.write(colorizeLogPrefixAnsi(`[reroute/start] Press Ctrl+C to stop
2030
+ `));
1876
2031
  process.on("SIGINT", () => {
1877
2032
  process.stdout.write(`${colorizeLogPrefixAnsi(`
1878
2033
  [reroute/start] Shutting down...`)}
@@ -1916,19 +2071,19 @@ __export(exports_build, {
1916
2071
  });
1917
2072
  import { spawn as spawn4 } from "node:child_process";
1918
2073
  import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
1919
- import { join as join9 } from "node:path";
2074
+ import { join as join8 } from "node:path";
1920
2075
  function getRerouteCommand3() {
1921
- const binPath = join9(import.meta.dir, "..", "..", "bin.ts");
2076
+ const binPath = join8(import.meta.dir, "..", "..", "bin.ts");
1922
2077
  const isBunDev = existsSync7(binPath);
1923
2078
  if (isBunDev) {
1924
2079
  return `bun ${binPath}`;
1925
2080
  }
1926
2081
  const cwd = process.cwd();
1927
2082
  const nodeModulesPaths = [
1928
- join9(cwd, "node_modules", ".bin", "reroute"),
1929
- join9(cwd, "..", "node_modules", ".bin", "reroute"),
1930
- join9(cwd, "..", "..", "node_modules", ".bin", "reroute"),
1931
- join9(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
2083
+ join8(cwd, "node_modules", ".bin", "reroute"),
2084
+ join8(cwd, "..", "node_modules", ".bin", "reroute"),
2085
+ join8(cwd, "..", "..", "node_modules", ".bin", "reroute"),
2086
+ join8(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
1932
2087
  ];
1933
2088
  for (const binPath2 of nodeModulesPaths) {
1934
2089
  if (existsSync7(binPath2)) {
@@ -1939,7 +2094,7 @@ function getRerouteCommand3() {
1939
2094
  }
1940
2095
  function getOutputName() {
1941
2096
  const cwd = process.cwd();
1942
- const packageJsonPath = join9(cwd, "package.json");
2097
+ const packageJsonPath = join8(cwd, "package.json");
1943
2098
  if (existsSync7(packageJsonPath)) {
1944
2099
  try {
1945
2100
  const packageJson = JSON.parse(readFileSync4(packageJsonPath, "utf-8"));
@@ -1966,21 +2121,7 @@ async function build(args) {
1966
2121
  if (outfileArgIndex !== -1 && args[outfileArgIndex + 1]) {
1967
2122
  outputPath = args[outfileArgIndex + 1];
1968
2123
  }
1969
- const bootBuffer = { current: "" };
1970
2124
  const genBuffer = { current: "" };
1971
- const handleBootOutput = (data) => {
1972
- const text = bootBuffer.current + data.toString();
1973
- const lines = text.split(`
1974
- `);
1975
- bootBuffer.current = lines.pop() || "";
1976
- for (const line of lines) {
1977
- if (!line.trim()) {
1978
- continue;
1979
- }
1980
- const ansiColored = colorizeLogPrefixAnsi(line);
1981
- console.log(ansiColored);
1982
- }
1983
- };
1984
2125
  const handleGenOutput = (data) => {
1985
2126
  const text = genBuffer.current + data.toString();
1986
2127
  const lines = text.split(`
@@ -1994,34 +2135,10 @@ async function build(args) {
1994
2135
  console.log(ansiColored);
1995
2136
  }
1996
2137
  };
1997
- process.stdout.write(`${colorizeLogPrefixAnsi("[reroute/build] Running boot...")}
1998
- `);
1999
- const bootCommand = useShell ? `${rerouteCmd} boot` : rerouteCmd;
2000
- const bootArgs = useShell ? [] : ["boot"];
2001
- await new Promise((resolve, reject) => {
2002
- const bootProcess = spawn4(bootCommand, bootArgs, {
2003
- stdio: ["ignore", "pipe", "pipe"],
2004
- shell: useShell
2005
- });
2006
- bootProcess.stdout?.on("data", handleBootOutput);
2007
- bootProcess.stderr?.on("data", handleBootOutput);
2008
- bootProcess.on("exit", (code) => {
2009
- if (code !== null && code !== 0) {
2010
- reject(new Error(`Boot exited with code ${code}`));
2011
- } else {
2012
- resolve();
2013
- }
2014
- });
2015
- bootProcess.on("error", (error) => {
2016
- reject(error);
2017
- });
2018
- });
2019
- process.stdout.write(colorizeLogPrefixAnsi(`[reroute/build] Boot complete
2020
- `));
2021
- process.stdout.write(`${colorizeLogPrefixAnsi("[reroute/build] Running gen...")}
2138
+ process.stdout.write(`${colorizeLogPrefixAnsi("[reroute/build] Running gen --prod...")}
2022
2139
  `);
2023
- const genCommand = useShell ? `${rerouteCmd} gen` : rerouteCmd;
2024
- const genArgs = useShell ? [] : ["gen"];
2140
+ const genCommand = useShell ? `${rerouteCmd} gen --prod` : rerouteCmd;
2141
+ const genArgs = useShell ? [] : ["gen", "--prod"];
2025
2142
  await new Promise((resolve, reject) => {
2026
2143
  const genProcess = spawn4(genCommand, genArgs, {
2027
2144
  stdio: ["ignore", "pipe", "pipe"],
@@ -2095,59 +2212,11 @@ async function generateContentHash(content) {
2095
2212
  return hex.slice(0, 8);
2096
2213
  }
2097
2214
 
2098
- // packages/cli/src/libs/command.ts
2099
- var exports_command = {};
2100
- __export(exports_command, {
2101
- getRerouteCommand: () => getRerouteCommand4
2102
- });
2103
- import { existsSync as existsSync8 } from "node:fs";
2104
- import { join as join10 } from "node:path";
2105
- function getRerouteCommand4() {
2106
- const binPath = join10(import.meta.dir, "..", "..", "bin.ts");
2107
- const isBunDev = existsSync8(binPath);
2108
- if (isBunDev) {
2109
- return `bun ${binPath}`;
2110
- }
2111
- const cwd = process.cwd();
2112
- const nodeModulesPaths = [
2113
- join10(cwd, "node_modules", ".bin", "reroute"),
2114
- join10(cwd, "..", "node_modules", ".bin", "reroute"),
2115
- join10(cwd, "..", "..", "node_modules", ".bin", "reroute"),
2116
- join10(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
2117
- ];
2118
- for (const binPath2 of nodeModulesPaths) {
2119
- if (existsSync8(binPath2)) {
2120
- return binPath2;
2121
- }
2122
- }
2123
- return "reroute";
2124
- }
2125
- var init_command = () => {};
2126
-
2127
- // packages/cli/src/libs/index.ts
2128
- var init_libs = __esm(() => {
2129
- init_command();
2130
- init_log();
2131
- init_markdown();
2132
- init_markdown_processor();
2133
- init_tailwind();
2134
- });
2135
-
2136
- // packages/cli/index.ts
2137
- var init_cli = __esm(() => {
2138
- init_libs();
2139
- });
2215
+ // packages/core/src/bundler/index.ts
2216
+ var init_bundler = () => {};
2140
2217
 
2141
2218
  // packages/core/src/utils/path.ts
2142
- var exports_path = {};
2143
- __export(exports_path, {
2144
- stripStart: () => stripStart,
2145
- stripEnd: () => stripEnd,
2146
- join: () => join11,
2147
- extname: () => extname2,
2148
- basename: () => basename2
2149
- });
2150
- function join11(...parts) {
2219
+ function join9(...parts) {
2151
2220
  return parts.join("/").replace(/\/+/g, "/");
2152
2221
  }
2153
2222
  function extname2(p) {
@@ -2165,120 +2234,60 @@ function stripEnd(p, ch) {
2165
2234
  return p.endsWith(ch) ? p.slice(0, -ch.length) : p;
2166
2235
  }
2167
2236
 
2168
- // packages/core/src/bundler/transpile.ts
2169
- function isWatchMode() {
2170
- try {
2171
- return Array.isArray(process.execArgv) && process.execArgv.includes("--watch") || Array.isArray(process.argv) && process.argv.includes("--watch");
2172
- } catch {
2173
- return false;
2174
- }
2175
- }
2176
- async function transpileFile(filePath, originalPath, options, bundleCache) {
2177
- const src = await Bun.file(filePath).text();
2178
- const cacheKey = `${filePath}-${await generateContentHash(src)}`;
2179
- if (bundleCache.has(cacheKey)) {
2180
- return bundleCache.get(cacheKey);
2181
- }
2182
- console.log(`[reroute] Building ${originalPath}${options.minify ? " (minified)" : ""}...`);
2237
+ // packages/core/src/content/discovery.ts
2238
+ import { readdir as readdir3, stat } from "node:fs/promises";
2239
+ async function listContentFiles2(dir, baseRel) {
2240
+ const out = [];
2183
2241
  try {
2184
- if (isWatchMode()) {
2185
- const cwd = typeof process !== "undefined" && process.cwd ? process.cwd() : "";
2186
- if (cwd) {
2187
- await buildTailwindIfConfigured(cwd);
2188
- }
2189
- }
2190
- } catch (e) {
2191
- console.warn("[reroute/tailwind] rebuild failed:", e);
2192
- }
2193
- async function doBuild(sm) {
2194
- return await Bun.build({
2195
- entrypoints: [filePath],
2196
- target: "browser",
2197
- format: "esm",
2198
- minify: options.minify,
2199
- splitting: false,
2200
- sourcemap: sm,
2201
- define: {
2202
- "process.env.NODE_ENV": options.minify ? '"production"' : '"development"'
2242
+ const entries = await readdir3(dir, { withFileTypes: true });
2243
+ for (const entry of entries) {
2244
+ const full = join9(dir, entry.name);
2245
+ const rel = join9(baseRel, entry.name);
2246
+ if (entry.isDirectory()) {
2247
+ const nested = await listContentFiles2(full, rel);
2248
+ out.push(...nested);
2249
+ } else if (entry.isFile()) {
2250
+ if (/\.(tsx|ts)$/.test(entry.name) && !entry.name.startsWith("_")) {
2251
+ out.push(rel);
2252
+ }
2203
2253
  }
2204
- });
2205
- }
2206
- let result;
2207
- try {
2208
- result = await doBuild(options.sourcemap ? "external" : "none");
2209
- } catch (error) {
2210
- console.warn(`[reroute] Build errored for ${originalPath} (sourcemap external). Retrying without sourcemap...`, error);
2211
- result = await doBuild("none");
2212
- }
2213
- if (!result.success) {
2214
- console.error(`[reroute] Failed to build ${filePath}`);
2215
- for (const log2 of result.logs)
2216
- console.error(log2);
2217
- throw new Error(`Failed to transpile ${filePath}`);
2218
- }
2219
- const output = result.outputs[0];
2220
- const code = await output.text();
2221
- let sourceMap;
2222
- if (options.sourcemap && result.outputs.length > 1) {
2223
- const mapOutput = result.outputs.find((o) => o.path.endsWith(".map"));
2224
- if (mapOutput) {
2225
- sourceMap = await mapOutput.text();
2226
2254
  }
2227
- }
2228
- const contentHash = await generateContentHash(code);
2229
- const bundleInfo = {
2230
- hash: contentHash,
2231
- code,
2232
- sourceMap
2233
- };
2234
- bundleCache.set(cacheKey, bundleInfo);
2235
- const sizeKB = (code.length / 1024).toFixed(2);
2236
- const gzippedSize = Bun.gzipSync(new TextEncoder().encode(code)).length;
2237
- const gzippedKB = (gzippedSize / 1024).toFixed(2);
2238
- console.log(`[reroute] Built ${originalPath} -> ${sizeKB} KB (${gzippedKB} KB gzipped)`);
2239
- return bundleInfo;
2255
+ } catch {}
2256
+ return out;
2240
2257
  }
2241
- async function getBundleUrlsFor(modules, clientDir, prefix, options, bundleCache) {
2242
- const mods = Array.isArray(modules) ? modules : [modules];
2243
- const urls = [];
2244
- const { join: join12 } = await Promise.resolve().then(() => exports_path);
2245
- for (const mod of mods) {
2246
- const rel = mod.replace(/^\.\//, "");
2247
- const fullPath = join12(clientDir, rel);
2248
- try {
2249
- const bundleInfo = await transpileFile(fullPath, rel, options, bundleCache);
2250
- const base = basename2(rel, extname2(rel));
2251
- urls.push(`${prefix}/${base}.${bundleInfo.hash}.js`);
2252
- } catch (error) {
2253
- console.error(`[reroute] Error getting bundle URL for ${rel}:`, error);
2254
- urls.push(`${prefix}/${rel}`);
2258
+ async function discoverCollections(clientDir) {
2259
+ const root = join9(clientDir, "routes");
2260
+ const collections = new Set;
2261
+ try {
2262
+ const entries = await readdir3(root, { withFileTypes: true });
2263
+ for (const entry of entries) {
2264
+ if (entry.isDirectory()) {
2265
+ const contentDir = join9(root, entry.name, "content");
2266
+ try {
2267
+ await stat(contentDir);
2268
+ collections.add(entry.name);
2269
+ } catch {}
2270
+ }
2255
2271
  }
2256
- }
2257
- return urls;
2272
+ } catch {}
2273
+ return Array.from(collections);
2258
2274
  }
2259
- var init_transpile = __esm(() => {
2260
- init_cli();
2261
- });
2262
-
2263
- // packages/core/src/bundler/index.ts
2264
- var init_bundler = __esm(() => {
2265
- init_transpile();
2266
- });
2275
+ var init_discovery = () => {};
2267
2276
 
2268
2277
  // packages/core/src/content/metadata.ts
2269
- import { stat } from "node:fs/promises";
2278
+ import { stat as stat2 } from "node:fs/promises";
2270
2279
  import { pathToFileURL as pathToFileURL2 } from "node:url";
2271
- async function getContentMeta(absPath, isWatchMode2) {
2280
+ async function getContentMeta(absPath, isWatchMode) {
2272
2281
  try {
2273
2282
  const url = pathToFileURL2(absPath).href;
2274
- const mod = await import(`${url}${isWatchMode2 ? `?t=${Date.now()}` : ""}`);
2283
+ const mod = await import(`${url}${isWatchMode ? `?t=${Date.now()}` : ""}`);
2275
2284
  const meta = mod.meta || mod.frontmatter || {};
2276
2285
  if (meta && typeof meta === "object")
2277
2286
  return meta;
2278
2287
  return {};
2279
2288
  } catch {
2280
2289
  try {
2281
- const s = await stat(absPath);
2290
+ const s = await stat2(absPath);
2282
2291
  return { date: new Date(s.mtimeMs).toISOString() };
2283
2292
  } catch {
2284
2293
  return {};
@@ -2304,94 +2313,16 @@ function escapeHtml(input) {
2304
2313
  }
2305
2314
  var init_metadata = () => {};
2306
2315
 
2307
- // packages/core/src/content/discovery.ts
2308
- import { readdir as readdir3, stat as stat2 } from "node:fs/promises";
2309
- async function listContentFiles2(dir, baseRel) {
2310
- const out = [];
2311
- try {
2312
- const entries = await readdir3(dir, { withFileTypes: true });
2313
- for (const entry of entries) {
2314
- const full = join11(dir, entry.name);
2315
- const rel = join11(baseRel, entry.name);
2316
- if (entry.isDirectory()) {
2317
- const nested = await listContentFiles2(full, rel);
2318
- out.push(...nested);
2319
- } else if (entry.isFile()) {
2320
- if (/\.(tsx|ts)$/.test(entry.name) && !entry.name.startsWith("_")) {
2321
- out.push(rel);
2322
- }
2323
- }
2324
- }
2325
- } catch {}
2326
- return out;
2327
- }
2328
- async function buildContentDTOs(collectionPath, clientDir, prefix, isWatchMode2) {
2329
- const normalized = stripStart(stripEnd(collectionPath, "/"), "/");
2330
- const contentRelDir = join11("routes", normalized, "content");
2331
- const contentAbsDir = join11(clientDir, contentRelDir);
2332
- const files = await listContentFiles2(contentAbsDir, "");
2333
- const items = [];
2334
- for (const rel of files) {
2335
- const fullRelPath = join11(contentRelDir, rel);
2336
- const absPath = join11(clientDir, fullRelPath);
2337
- const noExt = rel.replace(/\.(tsx|ts)$/, "");
2338
- const name = basename2(noExt);
2339
- const moduleUrl = `${prefix}/${fullRelPath}`.replace(/\/+/g, "/");
2340
- const meta = await getContentMeta(absPath, isWatchMode2);
2341
- const href = `/${normalized}/${name}`.replace(/\\+/g, "/");
2342
- items.push({
2343
- slug: noExt,
2344
- name,
2345
- path: fullRelPath,
2346
- module: moduleUrl,
2347
- meta,
2348
- href
2349
- });
2350
- }
2351
- return items;
2352
- }
2353
- async function discoverCollections(clientDir) {
2354
- const root = join11(clientDir, "routes");
2355
- const collections = new Set;
2356
- try {
2357
- const entries = await readdir3(root, { withFileTypes: true });
2358
- for (const entry of entries) {
2359
- if (entry.isDirectory()) {
2360
- const contentDir = join11(root, entry.name, "content");
2361
- try {
2362
- await stat2(contentDir);
2363
- collections.add(entry.name);
2364
- } catch {}
2365
- }
2366
- }
2367
- } catch {}
2368
- return Array.from(collections);
2369
- }
2370
- var init_discovery = __esm(() => {
2371
- init_metadata();
2372
- });
2373
-
2374
- // packages/core/src/content/registry.ts
2375
- async function generateContentRegistry(cwd) {
2376
- try {
2377
- const p = join11(cwd, ".reroute", "content.ts");
2378
- const exists = await Bun.file(p).exists();
2379
- console.log(exists ? "[reroute] Content registry up-to-date" : "[reroute] Warning: .reroute/content.ts not found");
2380
- } catch {}
2381
- }
2382
- var init_registry = () => {};
2383
-
2384
2316
  // packages/core/src/content/index.ts
2385
2317
  var init_content = __esm(() => {
2386
2318
  init_discovery();
2387
2319
  init_metadata();
2388
- init_registry();
2389
2320
  });
2390
2321
 
2391
2322
  // packages/core/src/ssr/modules.ts
2392
2323
  import { readdir as readdir4, stat as stat3 } from "node:fs/promises";
2393
2324
  import { pathToFileURL as pathToFileURL3 } from "node:url";
2394
- async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode2) {
2325
+ async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode) {
2395
2326
  try {
2396
2327
  const parts = pathname.split("/").filter(Boolean);
2397
2328
  if (parts.length < 2)
@@ -2399,20 +2330,20 @@ async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode2
2399
2330
  const collection = parts[0];
2400
2331
  const name = parts[1];
2401
2332
  try {
2402
- const registryPath = join11(cwd, ".reroute", "content.ts");
2403
- const reg = await import(pathToFileURL3(registryPath).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2333
+ const registryPath = join9(cwd, ".reroute", "content.ts");
2334
+ const reg = await import(pathToFileURL3(registryPath).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2404
2335
  const get = reg?.getContentEntry;
2405
2336
  const entry = typeof get === "function" ? get(collection, name) : undefined;
2406
2337
  const moduleUrl = entry?.module;
2407
2338
  if (moduleUrl?.endsWith(".js")) {
2408
- const abs = join11(cwd, moduleUrl.replace(/^\//, ""));
2409
- const href = pathToFileURL3(abs).href + (isWatchMode2 ? `?t=${Date.now()}` : "");
2339
+ const abs = join9(cwd, moduleUrl.replace(/^\//, ""));
2340
+ const href = pathToFileURL3(abs).href + (isWatchMode ? `?t=${Date.now()}` : "");
2410
2341
  const mod = await import(href);
2411
2342
  return mod;
2412
2343
  }
2413
2344
  } catch {}
2414
2345
  try {
2415
- const chunkDir = join11(cwd, ".reroute", "chunks", collection);
2346
+ const chunkDir = join9(cwd, ".reroute", "chunks", collection);
2416
2347
  const files = await readdir4(chunkDir);
2417
2348
  const matches = files.filter((n) => n.startsWith(`${name}.`) && n.endsWith(".js"));
2418
2349
  if (matches.length) {
@@ -2420,22 +2351,22 @@ async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode2
2420
2351
  let latestM = 0;
2421
2352
  for (const f of matches) {
2422
2353
  try {
2423
- const s = await stat3(join11(chunkDir, f));
2354
+ const s = await stat3(join9(chunkDir, f));
2424
2355
  if (s.mtimeMs >= latestM) {
2425
2356
  latestM = s.mtimeMs;
2426
2357
  latest = f;
2427
2358
  }
2428
2359
  } catch {}
2429
2360
  }
2430
- const absChunk = join11(chunkDir, latest);
2431
- const href = pathToFileURL3(absChunk).href + (isWatchMode2 ? `?t=${Date.now()}` : "");
2361
+ const absChunk = join9(chunkDir, latest);
2362
+ const href = pathToFileURL3(absChunk).href + (isWatchMode ? `?t=${Date.now()}` : "");
2432
2363
  const mod = await import(href);
2433
2364
  return mod;
2434
2365
  }
2435
2366
  } catch {}
2436
2367
  try {
2437
- const srcTsx = join11(clientDir, "routes", collection, "content", `${name}.tsx`);
2438
- const srcTs = join11(clientDir, "routes", collection, "content", `${name}.ts`);
2368
+ const srcTsx = join9(clientDir, "routes", collection, "content", `${name}.tsx`);
2369
+ const srcTs = join9(clientDir, "routes", collection, "content", `${name}.ts`);
2439
2370
  let absSrc = null;
2440
2371
  if (await Bun.file(srcTsx).exists())
2441
2372
  absSrc = srcTsx;
@@ -2443,7 +2374,7 @@ async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode2
2443
2374
  absSrc = srcTs;
2444
2375
  if (absSrc) {
2445
2376
  const href = pathToFileURL3(absSrc).href;
2446
- const mod = await (isWatchMode2 ? import(`${href}?t=${Date.now()}`) : import(href));
2377
+ const mod = await (isWatchMode ? import(`${href}?t=${Date.now()}`) : import(href));
2447
2378
  return mod;
2448
2379
  }
2449
2380
  } catch {}
@@ -2453,7 +2384,7 @@ async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode2
2453
2384
  var init_modules = () => {};
2454
2385
 
2455
2386
  // packages/core/src/ssr/seed.ts
2456
- async function seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode2) {
2387
+ async function seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode) {
2457
2388
  try {
2458
2389
  const parts = pathname.split("/").filter(Boolean);
2459
2390
  if (parts.length < 2)
@@ -2461,7 +2392,7 @@ async function seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode2) {
2461
2392
  const collection = parts[0];
2462
2393
  const name = parts[1];
2463
2394
  const key = `${collection}:${name}`;
2464
- const mod = await importContentModuleForPath(pathname, clientDir, cwd, isWatchMode2);
2395
+ const mod = await importContentModuleForPath(pathname, clientDir, cwd, isWatchMode);
2465
2396
  if (!mod)
2466
2397
  return;
2467
2398
  const C = mod.default || mod;
@@ -2485,9 +2416,9 @@ var init_seed = __esm(() => {
2485
2416
  // packages/core/src/ssr/data.ts
2486
2417
  import { pathToFileURL as pathToFileURL4 } from "node:url";
2487
2418
  async function computeSSRDataForPath(params) {
2488
- const { pathname, clientDir, cwd, isWatchMode: isWatchMode2 } = params;
2419
+ const { pathname, clientDir, cwd, isWatchMode } = params;
2489
2420
  try {
2490
- await seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode2);
2421
+ await seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode);
2491
2422
  } catch {}
2492
2423
  try {
2493
2424
  const parts = pathname.split("/").filter(Boolean);
@@ -2502,15 +2433,15 @@ async function computeSSRDataForPath(params) {
2502
2433
  }
2503
2434
  } catch {}
2504
2435
  try {
2505
- const routesPath = join11(cwd, ".reroute", "routes.ts");
2506
- const m = await import(pathToFileURL4(routesPath).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2436
+ const routesPath = join9(cwd, ".reroute", "routes.ts");
2437
+ const m = await import(pathToFileURL4(routesPath).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2507
2438
  const match = typeof m.matchRoute === "function" ? m.matchRoute(pathname) : null;
2508
2439
  const r = match?.route;
2509
2440
  const paramsValue = match?.params || {};
2510
2441
  if (r && typeof r.path === "string") {
2511
2442
  try {
2512
- const abs = join11(clientDir, "routes", String(r.path));
2513
- const mod = await import(pathToFileURL4(abs).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2443
+ const abs = join9(clientDir, "routes", String(r.path));
2444
+ const mod = await import(pathToFileURL4(abs).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2514
2445
  const ssr = mod?.ssr;
2515
2446
  const dataFn = ssr?.data;
2516
2447
  if (typeof dataFn === "function") {
@@ -2525,7 +2456,7 @@ var init_data = __esm(() => {
2525
2456
  init_seed();
2526
2457
  });
2527
2458
 
2528
- // node_modules/dedent/dist/dedent.mjs
2459
+ // node_modules/.bun/dedent@1.7.0/node_modules/dedent/dist/dedent.mjs
2529
2460
  function ownKeys(object, enumerableOnly) {
2530
2461
  var keys = Object.keys(object);
2531
2462
  if (Object.getOwnPropertySymbols) {
@@ -2646,7 +2577,7 @@ var init_dedent = __esm(() => {
2646
2577
 
2647
2578
  // packages/core/src/template/html.ts
2648
2579
  async function loadIndexHtml(clientDir) {
2649
- const templatePath = join11(clientDir, "index.html");
2580
+ const templatePath = join9(clientDir, "index.html");
2650
2581
  try {
2651
2582
  const content = await Bun.file(templatePath).text();
2652
2583
  return content;
@@ -2734,7 +2665,7 @@ async function renderSSRDocument(options) {
2734
2665
  rootComponent,
2735
2666
  clientDir,
2736
2667
  cwd,
2737
- isWatchMode: isWatchMode2,
2668
+ isWatchMode,
2738
2669
  bundleUrl,
2739
2670
  head = "",
2740
2671
  lang = "en",
@@ -2744,6 +2675,12 @@ async function renderSSRDocument(options) {
2744
2675
  const scripts = [bundleUrl];
2745
2676
  let hydrationScript = "";
2746
2677
  let extraHead = "";
2678
+ try {
2679
+ if (typeof bundleUrl === "string" && bundleUrl.endsWith(".js")) {
2680
+ extraHead += `
2681
+ <link rel="modulepreload" href="${bundleUrl}" />`;
2682
+ }
2683
+ } catch {}
2747
2684
  let statusOverride;
2748
2685
  try {
2749
2686
  globalThis.__REROUTE_SSR_ACCESSED__ = {};
@@ -2756,7 +2693,7 @@ async function renderSSRDocument(options) {
2756
2693
  let modulePath = "";
2757
2694
  let isContentCollection = false;
2758
2695
  try {
2759
- const maybeDir = join11(clientDir, "routes", collection, "content");
2696
+ const maybeDir = join9(clientDir, "routes", collection, "content");
2760
2697
  const s = await stat4(maybeDir);
2761
2698
  isContentCollection = typeof s?.isDirectory === "function" ? s.isDirectory() : true;
2762
2699
  } catch {
@@ -2766,8 +2703,8 @@ async function renderSSRDocument(options) {
2766
2703
  throw new Error("skip-content-preload");
2767
2704
  }
2768
2705
  try {
2769
- const registryPath = join11(cwd, ".reroute", "content.ts");
2770
- const reg = await import(pathToFileURL5(registryPath).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2706
+ const registryPath = join9(cwd, ".reroute", "content.ts");
2707
+ const reg = await import(pathToFileURL5(registryPath).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2771
2708
  const get = reg?.getContentEntry;
2772
2709
  const entry = typeof get === "function" ? get(collection, name) : undefined;
2773
2710
  const moduleUrl = entry?.module;
@@ -2777,7 +2714,7 @@ async function renderSSRDocument(options) {
2777
2714
  } catch {}
2778
2715
  if (!modulePath) {
2779
2716
  try {
2780
- const chunkDir = join11(cwd, ".reroute", "chunks", collection);
2717
+ const chunkDir = join9(cwd, ".reroute", "chunks", collection);
2781
2718
  const files = await readdir5(chunkDir);
2782
2719
  const candidates = files.filter((n) => n.startsWith(`${name}.`) && n.endsWith(".js"));
2783
2720
  if (candidates.length) {
@@ -2785,25 +2722,25 @@ async function renderSSRDocument(options) {
2785
2722
  let latestM = 0;
2786
2723
  for (const candidateName of candidates) {
2787
2724
  try {
2788
- const s = await stat4(join11(chunkDir, candidateName));
2725
+ const s = await stat4(join9(chunkDir, candidateName));
2789
2726
  if (s.mtimeMs >= latestM) {
2790
2727
  latestM = s.mtimeMs;
2791
2728
  latest = candidateName;
2792
2729
  }
2793
2730
  } catch {}
2794
2731
  }
2795
- modulePath = `/${join11(".reroute", "chunks", collection, latest).replace(/\\+/g, "/")}`;
2732
+ modulePath = `/${join9(".reroute", "chunks", collection, latest).replace(/\\+/g, "/")}`;
2796
2733
  }
2797
2734
  } catch {}
2798
2735
  }
2799
2736
  if (!modulePath) {
2800
- const tsx = join11(clientDir, "routes", collection, "content", `${name}.tsx`);
2801
- const ts = join11(clientDir, "routes", collection, "content", `${name}.ts`);
2737
+ const tsx = join9(clientDir, "routes", collection, "content", `${name}.tsx`);
2738
+ const ts = join9(clientDir, "routes", collection, "content", `${name}.ts`);
2802
2739
  let srcUrl = "";
2803
2740
  if (await Bun.file(tsx).exists()) {
2804
- srcUrl = `/${join11("routes", collection, "content", `${name}.tsx`).replace(/\\+/g, "/")}`;
2741
+ srcUrl = `/${join9("routes", collection, "content", `${name}.tsx`).replace(/\\+/g, "/")}`;
2805
2742
  } else if (await Bun.file(ts).exists()) {
2806
- srcUrl = `/${join11("routes", collection, "content", `${name}.ts`).replace(/\\+/g, "/")}`;
2743
+ srcUrl = `/${join9("routes", collection, "content", `${name}.ts`).replace(/\\+/g, "/")}`;
2807
2744
  }
2808
2745
  if (srcUrl) {
2809
2746
  modulePath = srcUrl;
@@ -2821,7 +2758,7 @@ async function renderSSRDocument(options) {
2821
2758
  }
2822
2759
  }
2823
2760
  } catch {}
2824
- await seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode2);
2761
+ await seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode);
2825
2762
  const __SSR_DATA__ = {};
2826
2763
  try {
2827
2764
  try {
@@ -2841,15 +2778,15 @@ async function renderSSRDocument(options) {
2841
2778
  }
2842
2779
  } catch {}
2843
2780
  try {
2844
- const routesPath = join11(cwd, ".reroute", "routes.ts");
2845
- const m = await import(pathToFileURL5(routesPath).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2781
+ const routesPath = join9(cwd, ".reroute", "routes.ts");
2782
+ const m = await import(pathToFileURL5(routesPath).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2846
2783
  const match = typeof m.matchRoute === "function" ? m.matchRoute(pathname) : null;
2847
2784
  const r = match?.route;
2848
2785
  const params = match?.params || {};
2849
2786
  if (r && typeof r.path === "string") {
2850
2787
  try {
2851
- const abs = join11(clientDir, "routes", String(r.path));
2852
- const mod = await import(pathToFileURL5(abs).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2788
+ const abs = join9(clientDir, "routes", String(r.path));
2789
+ const mod = await import(pathToFileURL5(abs).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2853
2790
  const ssr = mod?.ssr;
2854
2791
  const dataFn = ssr?.data;
2855
2792
  if (typeof dataFn === "function") {
@@ -2865,8 +2802,8 @@ async function renderSSRDocument(options) {
2865
2802
  } catch {}
2866
2803
  let __byCollectionForSSR = {};
2867
2804
  try {
2868
- const p = join11(cwd, ".reroute", "content.ts");
2869
- const mod = await import(pathToFileURL5(p).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2805
+ const p = join9(cwd, ".reroute", "content.ts");
2806
+ const mod = await import(pathToFileURL5(p).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2870
2807
  __byCollectionForSSR = mod?.byCollection || {};
2871
2808
  try {
2872
2809
  globalThis.__REROUTE_COLLECTIONS__ = __byCollectionForSSR;
@@ -2880,10 +2817,10 @@ async function renderSSRDocument(options) {
2880
2817
  let inlineStyleTag = "";
2881
2818
  try {
2882
2819
  const candidates = [
2883
- join11(clientDir, "..", ".reroute", "theme.css"),
2884
- join11(clientDir, "..", "..", ".reroute", "theme.css"),
2885
- join11(clientDir, "..", "..", "..", ".reroute", "theme.css"),
2886
- join11(clientDir, "..", "..", "..", "..", ".reroute", "theme.css")
2820
+ join9(clientDir, "..", ".reroute", "theme.css"),
2821
+ join9(clientDir, "..", "..", ".reroute", "theme.css"),
2822
+ join9(clientDir, "..", "..", "..", ".reroute", "theme.css"),
2823
+ join9(clientDir, "..", "..", "..", "..", ".reroute", "theme.css")
2887
2824
  ];
2888
2825
  let cssPath = "";
2889
2826
  for (const p of candidates) {
@@ -2966,7 +2903,7 @@ async function renderSSRDocument(options) {
2966
2903
  </script>`;
2967
2904
  } catch {}
2968
2905
  hydrationScript += scripts.map((src) => `<script type="module" src="${src}"></script>`).join("");
2969
- if (isWatchMode2) {
2906
+ if (isWatchMode) {
2970
2907
  hydrationScript += `<script type="module" src="/__reroute_watch.js"></script>`;
2971
2908
  }
2972
2909
  let perPageHead = "";
@@ -2991,8 +2928,8 @@ ${ssrHead}`;
2991
2928
  }
2992
2929
  } catch {}
2993
2930
  try {
2994
- const routesPath = join11(cwd, ".reroute", "routes.ts");
2995
- const m = await import(pathToFileURL5(routesPath).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2931
+ const routesPath = join9(cwd, ".reroute", "routes.ts");
2932
+ const m = await import(pathToFileURL5(routesPath).href + (isWatchMode ? `?t=${Date.now()}` : ""));
2996
2933
  const match = typeof m.matchRoute === "function" ? m.matchRoute(pathname) : null;
2997
2934
  const r = match?.route;
2998
2935
  if (!r) {
@@ -3000,8 +2937,8 @@ ${ssrHead}`;
3000
2937
  }
3001
2938
  if (r && typeof r.path === "string") {
3002
2939
  try {
3003
- const abs = join11(clientDir, "routes", String(r.path));
3004
- const mod = await import(pathToFileURL5(abs).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2940
+ const abs = join9(clientDir, "routes", String(r.path));
2941
+ const mod = await import(pathToFileURL5(abs).href + (isWatchMode ? `?t=${Date.now()}` : ""));
3005
2942
  const meta = mod?.meta;
3006
2943
  const ssr = mod?.ssr;
3007
2944
  if (meta)
@@ -3035,8 +2972,8 @@ ${ssrHead}`;
3035
2972
  }
3036
2973
  if (chosen && typeof chosen.path === "string") {
3037
2974
  try {
3038
- const abs = join11(clientDir, "routes", String(chosen.path));
3039
- const mod = await import(pathToFileURL5(abs).href + (isWatchMode2 ? `?t=${Date.now()}` : ""));
2975
+ const abs = join9(clientDir, "routes", String(chosen.path));
2976
+ const mod = await import(pathToFileURL5(abs).href + (isWatchMode ? `?t=${Date.now()}` : ""));
3040
2977
  const meta = mod?.meta;
3041
2978
  const ssr = mod?.ssr;
3042
2979
  if (meta)
@@ -3150,21 +3087,35 @@ function isCompressible(contentType) {
3150
3087
  }
3151
3088
 
3152
3089
  // packages/core/src/utils/compression.ts
3090
+ import { brotliCompressSync } from "node:zlib";
3153
3091
  function acceptsGzip(acceptEncoding) {
3154
3092
  return Boolean(acceptEncoding && /gzip/i.test(acceptEncoding));
3155
3093
  }
3094
+ function acceptsBrotli(acceptEncoding) {
3095
+ return Boolean(acceptEncoding && /\bbr\b/i.test(acceptEncoding));
3096
+ }
3156
3097
  function toBytes(input) {
3157
3098
  return typeof input === "string" ? new TextEncoder().encode(input) : input;
3158
3099
  }
3159
3100
  function gzipIfAccepted(body, contentType, acceptEncoding) {
3160
3101
  const extraHeaders = {};
3161
- if (acceptsGzip(acceptEncoding) && isCompressible(contentType)) {
3162
- try {
3163
- const compressed = Bun.gzipSync(toBytes(body));
3164
- extraHeaders["Content-Encoding"] = "gzip";
3165
- extraHeaders.Vary = "Accept-Encoding";
3166
- return { body: compressed, extraHeaders };
3167
- } catch {}
3102
+ if (isCompressible(contentType)) {
3103
+ if (acceptsBrotli(acceptEncoding)) {
3104
+ try {
3105
+ const compressed = brotliCompressSync(toBytes(body));
3106
+ extraHeaders["Content-Encoding"] = "br";
3107
+ extraHeaders.Vary = "Accept-Encoding";
3108
+ return { body: compressed, extraHeaders };
3109
+ } catch {}
3110
+ }
3111
+ if (acceptsGzip(acceptEncoding)) {
3112
+ try {
3113
+ const compressed = Bun.gzipSync(toBytes(body));
3114
+ extraHeaders["Content-Encoding"] = "gzip";
3115
+ extraHeaders.Vary = "Accept-Encoding";
3116
+ return { body: compressed, extraHeaders };
3117
+ } catch {}
3118
+ }
3168
3119
  }
3169
3120
  return { body, extraHeaders };
3170
3121
  }
@@ -3188,7 +3139,6 @@ var init_src = __esm(() => {
3188
3139
  // packages/core/index.ts
3189
3140
  var exports_core = {};
3190
3141
  __export(exports_core, {
3191
- transpileFile: () => transpileFile,
3192
3142
  toBytes: () => toBytes,
3193
3143
  stripStart: () => stripStart,
3194
3144
  stripEnd: () => stripEnd,
@@ -3196,54 +3146,81 @@ __export(exports_core, {
3196
3146
  renderSSRDocument: () => renderSSRDocument,
3197
3147
  loadIndexHtml: () => loadIndexHtml,
3198
3148
  listContentFiles: () => listContentFiles2,
3199
- join: () => join11,
3149
+ join: () => join9,
3200
3150
  isCompressible: () => isCompressible,
3201
3151
  gzipIfAccepted: () => gzipIfAccepted,
3202
3152
  getMimeType: () => getMimeType,
3203
3153
  getContentMeta: () => getContentMeta,
3204
- getBundleUrlsFor: () => getBundleUrlsFor,
3205
- generateContentRegistry: () => generateContentRegistry,
3206
3154
  generateContentHash: () => generateContentHash,
3207
3155
  extname: () => extname2,
3208
3156
  discoverCollections: () => discoverCollections,
3209
3157
  computeSSRDataForPath: () => computeSSRDataForPath,
3210
3158
  buildHeadFromMeta: () => buildHeadFromMeta,
3211
- buildContentDTOs: () => buildContentDTOs,
3212
3159
  basename: () => basename2,
3213
3160
  applyIndexTemplate: () => applyIndexTemplate,
3214
3161
  acceptsGzip: () => acceptsGzip,
3162
+ acceptsBrotli: () => acceptsBrotli,
3215
3163
  LRUCache: () => LRUCache
3216
3164
  });
3217
3165
  var init_core = __esm(() => {
3218
3166
  init_src();
3219
3167
  });
3220
3168
 
3169
+ // packages/cli/src/libs/command.ts
3170
+ var exports_command = {};
3171
+ __export(exports_command, {
3172
+ getRerouteCommand: () => getRerouteCommand4
3173
+ });
3174
+ import { existsSync as existsSync8 } from "node:fs";
3175
+ import { join as join10 } from "node:path";
3176
+ function getRerouteCommand4() {
3177
+ const binPath = join10(import.meta.dir, "..", "..", "bin.ts");
3178
+ const isBunDev = existsSync8(binPath);
3179
+ if (isBunDev) {
3180
+ return `bun ${binPath}`;
3181
+ }
3182
+ const cwd = process.cwd();
3183
+ const nodeModulesPaths = [
3184
+ join10(cwd, "node_modules", ".bin", "reroute"),
3185
+ join10(cwd, "..", "node_modules", ".bin", "reroute"),
3186
+ join10(cwd, "..", "..", "node_modules", ".bin", "reroute"),
3187
+ join10(cwd, "..", "..", "..", "node_modules", ".bin", "reroute")
3188
+ ];
3189
+ for (const binPath2 of nodeModulesPaths) {
3190
+ if (existsSync8(binPath2)) {
3191
+ return binPath2;
3192
+ }
3193
+ }
3194
+ return "reroute";
3195
+ }
3196
+ var init_command = () => {};
3197
+
3221
3198
  // packages/cli/src/commands/analyze.ts
3222
3199
  var exports_analyze = {};
3223
3200
  __export(exports_analyze, {
3224
3201
  default: () => analyze
3225
3202
  });
3226
3203
  import { existsSync as existsSync9, statSync } from "node:fs";
3227
- import { readdir as readdir6, readFile as readFile2, stat as stat5, writeFile as writeFile4 } from "node:fs/promises";
3228
- import { basename as basename3, join as join12, relative } from "node:path";
3204
+ import { readdir as readdir6, readFile, stat as stat5, writeFile } from "node:fs/promises";
3205
+ import { basename as basename3, join as join11, relative } from "node:path";
3229
3206
  import Table from "cli-table3";
3230
3207
  async function findBundles(cwd) {
3231
3208
  const bundles = [];
3232
- const chunksDir = join12(cwd, ".reroute", "chunks");
3209
+ const chunksDir = join11(cwd, ".reroute", "chunks");
3233
3210
  if (existsSync9(chunksDir)) {
3234
3211
  const collections = await readdir6(chunksDir, { withFileTypes: true });
3235
3212
  for (const collection of collections) {
3236
3213
  if (!collection.isDirectory())
3237
3214
  continue;
3238
- const collectionDir = join12(chunksDir, collection.name);
3215
+ const collectionDir = join11(chunksDir, collection.name);
3239
3216
  const files = await readdir6(collectionDir);
3240
3217
  for (const file of files) {
3241
3218
  if (!file.endsWith(".js"))
3242
3219
  continue;
3243
- const filePath = join12(collectionDir, file);
3220
+ const filePath = join11(collectionDir, file);
3244
3221
  const stats = await stat5(filePath);
3245
- const content2 = await readFile2(filePath);
3246
- const gzippedSize = Bun.gzipSync(content2).length;
3222
+ const content2 = await Bun.file(filePath).arrayBuffer();
3223
+ const gzippedSize = Bun.gzipSync(new Uint8Array(content2)).length;
3247
3224
  bundles.push({
3248
3225
  path: filePath,
3249
3226
  name: file,
@@ -3255,15 +3232,15 @@ async function findBundles(cwd) {
3255
3232
  }
3256
3233
  }
3257
3234
  }
3258
- const distDir = join12(cwd, "dist");
3235
+ const distDir = join11(cwd, "dist");
3259
3236
  if (existsSync9(distDir)) {
3260
3237
  const files = await readdir6(distDir);
3261
3238
  for (const file of files) {
3262
- const filePath = join12(distDir, file);
3239
+ const filePath = join11(distDir, file);
3263
3240
  const stats = statSync(filePath);
3264
3241
  if (stats.isFile() && !file.endsWith(".map") && !file.endsWith(".d.ts")) {
3265
- const content2 = await readFile2(filePath);
3266
- const gzippedSize = Bun.gzipSync(content2).length;
3242
+ const content2 = await Bun.file(filePath).arrayBuffer();
3243
+ const gzippedSize = Bun.gzipSync(new Uint8Array(content2)).length;
3267
3244
  bundles.push({
3268
3245
  path: filePath,
3269
3246
  name: file,
@@ -3279,9 +3256,9 @@ async function findBundles(cwd) {
3279
3256
  }
3280
3257
  async function findBrowserEntry(cwd) {
3281
3258
  try {
3282
- const clientDir = join12(cwd, "src", "client");
3283
- const tsxEntry = join12(clientDir, "index.tsx");
3284
- const tsEntry = join12(clientDir, "index.ts");
3259
+ const clientDir = join11(cwd, "src", "client");
3260
+ const tsxEntry = join11(clientDir, "index.tsx");
3261
+ const tsEntry = join11(clientDir, "index.ts");
3285
3262
  let sourceEntry = null;
3286
3263
  if (existsSync9(tsxEntry)) {
3287
3264
  sourceEntry = tsxEntry;
@@ -3305,7 +3282,7 @@ async function findBrowserEntry(cwd) {
3305
3282
  });
3306
3283
  if (!result.success) {
3307
3284
  if (result.logs && result.logs.length > 0) {
3308
- console.warn("[reroute/analyze] Browser build errors:", result.logs.map((log2) => log2.message).join(`
3285
+ console.warn("[reroute/analyze] Browser build errors:", result.logs.map((log) => log.message).join(`
3309
3286
  `));
3310
3287
  }
3311
3288
  return null;
@@ -3314,17 +3291,17 @@ async function findBrowserEntry(cwd) {
3314
3291
  console.warn("[reroute/analyze] Browser build produced no outputs");
3315
3292
  return null;
3316
3293
  }
3317
- const tempDir = join12(cwd, ".reroute", "browser");
3294
+ const tempDir = join11(cwd, ".reroute", "browser");
3318
3295
  await import("node:fs/promises").then((fs) => fs.mkdir(tempDir, { recursive: true }));
3319
3296
  const output = result.outputs[0];
3320
3297
  const code = await output.text();
3321
3298
  const actualHash = await generateContentHash2(code);
3322
- const bundlePath = join12(tempDir, `index.${actualHash}.js`);
3323
- await writeFile4(bundlePath, code, "utf-8");
3299
+ const bundlePath = join11(tempDir, `index.${actualHash}.js`);
3300
+ await writeFile(bundlePath, code, "utf-8");
3324
3301
  const mapOutput = result.outputs.find((o) => o.path.endsWith(".map"));
3325
3302
  if (mapOutput) {
3326
3303
  const mapContent = await mapOutput.text();
3327
- await writeFile4(`${bundlePath}.map`, mapContent, "utf-8");
3304
+ await writeFile(`${bundlePath}.map`, mapContent, "utf-8");
3328
3305
  }
3329
3306
  return bundlePath;
3330
3307
  } catch (error) {
@@ -3371,7 +3348,7 @@ function calculateStats(bundles) {
3371
3348
  }
3372
3349
  async function getInstalledPackageSizes(cwd) {
3373
3350
  const packageSizes = new Map;
3374
- const nodeModulesDir = join12(cwd, "node_modules");
3351
+ const nodeModulesDir = join11(cwd, "node_modules");
3375
3352
  if (!existsSync9(nodeModulesDir))
3376
3353
  return packageSizes;
3377
3354
  try {
@@ -3430,7 +3407,7 @@ async function buildDependencyTree(entryPath, cwd) {
3430
3407
  if (!pkgNode) {
3431
3408
  pkgNode = {
3432
3409
  name: pkgName || "unknown",
3433
- path: join12(cwd, "node_modules", pkgName || ""),
3410
+ path: join11(cwd, "node_modules", pkgName || ""),
3434
3411
  size: 0,
3435
3412
  children: []
3436
3413
  };
@@ -3451,7 +3428,7 @@ async function buildDependencyTree(entryPath, cwd) {
3451
3428
  if (!child) {
3452
3429
  child = {
3453
3430
  name: part,
3454
- path: join12(cwd, ...parts.slice(0, i + 1)),
3431
+ path: join11(cwd, ...parts.slice(0, i + 1)),
3455
3432
  size: 0,
3456
3433
  children: []
3457
3434
  };
@@ -3471,11 +3448,11 @@ async function buildDependencyTree(entryPath, cwd) {
3471
3448
  }
3472
3449
  return node.size;
3473
3450
  };
3474
- const content2 = await readFile2(entryPath, "utf-8");
3451
+ const content2 = await readFile(entryPath, "utf-8");
3475
3452
  const modulePattern = /\/\/\s*(.+?\.(?:ts|tsx|js|jsx|mjs|cjs))\s*$/gm;
3476
3453
  const nodeModulesNode = {
3477
3454
  name: "node_modules",
3478
- path: join12(cwd, "node_modules"),
3455
+ path: join11(cwd, "node_modules"),
3479
3456
  size: 0,
3480
3457
  children: []
3481
3458
  };
@@ -3541,7 +3518,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
3541
3518
  if (sourcePath.startsWith("/") || sourcePath.match(/^[A-Za-z]:\\/))
3542
3519
  return sourcePath;
3543
3520
  const bundleDir = bundlePath.substring(0, bundlePath.lastIndexOf("/"));
3544
- return join12(bundleDir, sourceRoot || "", sourcePath);
3521
+ return join11(bundleDir, sourceRoot || "", sourcePath);
3545
3522
  }, computeSizes = function(node) {
3546
3523
  if (node.children && node.children.length > 0) {
3547
3524
  node.size = node.children.reduce((s, c) => s + computeSizes(c), 0);
@@ -3552,8 +3529,8 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
3552
3529
  if (!existsSync9(mapPath))
3553
3530
  return null;
3554
3531
  const [bundle, mapJson] = await Promise.all([
3555
- readFile2(bundlePath, "utf-8"),
3556
- readFile2(mapPath, "utf-8")
3532
+ readFile(bundlePath, "utf-8"),
3533
+ readFile(mapPath, "utf-8")
3557
3534
  ]);
3558
3535
  const map = JSON.parse(mapJson);
3559
3536
  const sourceRoot = map.sourceRoot || "";
@@ -3613,7 +3590,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
3613
3590
  };
3614
3591
  const nodeModulesNode = {
3615
3592
  name: "node_modules",
3616
- path: join12(cwd, "node_modules"),
3593
+ path: join11(cwd, "node_modules"),
3617
3594
  size: 0,
3618
3595
  children: []
3619
3596
  };
@@ -3653,7 +3630,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
3653
3630
  if (!pkgNode) {
3654
3631
  pkgNode = {
3655
3632
  name: pkgName || "unknown",
3656
- path: join12(cwd, "node_modules", pkgName || ""),
3633
+ path: join11(cwd, "node_modules", pkgName || ""),
3657
3634
  size: 0,
3658
3635
  children: []
3659
3636
  };
@@ -3674,7 +3651,7 @@ async function buildTreeFromSourceMap(bundlePath, cwd) {
3674
3651
  if (!child) {
3675
3652
  child = {
3676
3653
  name: part,
3677
- path: join12(cwd, ...parts.slice(0, i2 + 1)),
3654
+ path: join11(cwd, ...parts.slice(0, i2 + 1)),
3678
3655
  size: 0,
3679
3656
  children: []
3680
3657
  };
@@ -3704,15 +3681,15 @@ async function generateHTMLReport(stats, depTree, mainInfo, browserDepTree, brow
3704
3681
  let actualServerBinarySize = null;
3705
3682
  let actualServerBinaryGzipped = null;
3706
3683
  try {
3707
- const distDir = join12(process.cwd(), "dist");
3684
+ const distDir = join11(process.cwd(), "dist");
3708
3685
  if (existsSync9(distDir)) {
3709
3686
  const files = await readdir6(distDir);
3710
3687
  for (const file of files) {
3711
- const filePath = join12(distDir, file);
3688
+ const filePath = join11(distDir, file);
3712
3689
  const stats2 = statSync(filePath);
3713
3690
  if (stats2.isFile() && !file.includes(".")) {
3714
3691
  actualServerBinarySize = stats2.size;
3715
- const content2 = await readFile2(filePath);
3692
+ const content2 = await readFile(filePath);
3716
3693
  actualServerBinaryGzipped = Bun.gzipSync(content2).length;
3717
3694
  break;
3718
3695
  }
@@ -5190,15 +5167,15 @@ async function printConsoleReport(stats, depTree, mainInfo, browserDepTree, brow
5190
5167
  let actualServerBinarySize = null;
5191
5168
  let actualServerBinaryGzipped = null;
5192
5169
  try {
5193
- const distDir = join12(process.cwd(), "dist");
5170
+ const distDir = join11(process.cwd(), "dist");
5194
5171
  if (existsSync9(distDir)) {
5195
5172
  const files = await readdir6(distDir);
5196
5173
  for (const file of files) {
5197
- const filePath = join12(distDir, file);
5174
+ const filePath = join11(distDir, file);
5198
5175
  const stats2 = statSync(filePath);
5199
5176
  if (stats2.isFile() && !file.includes(".")) {
5200
5177
  actualServerBinarySize = stats2.size;
5201
- const content2 = await readFile2(filePath);
5178
+ const content2 = await readFile(filePath);
5202
5179
  actualServerBinaryGzipped = Bun.gzipSync(content2).length;
5203
5180
  break;
5204
5181
  }
@@ -5228,7 +5205,7 @@ async function analyze(args) {
5228
5205
  const isProd = isProductionMode(args);
5229
5206
  const searchIndex = args.indexOf("--search");
5230
5207
  const initialSearch = searchIndex !== -1 && args[searchIndex + 1] ? args[searchIndex + 1] : "";
5231
- const rerouteIndexPath = join12(cwd, ".reroute", "index.ts");
5208
+ const rerouteIndexPath = join11(cwd, ".reroute", "index.ts");
5232
5209
  if (!existsSync9(rerouteIndexPath)) {
5233
5210
  console.log(colorizeLogPrefixAnsi(`[reroute/analyze] .reroute artifacts not found, running build...
5234
5211
  `));
@@ -5276,7 +5253,7 @@ async function analyze(args) {
5276
5253
  }
5277
5254
  try {
5278
5255
  const browserStat = await stat5(browserEntry);
5279
- const browserContent = await readFile2(browserEntry);
5256
+ const browserContent = await readFile(browserEntry);
5280
5257
  const browserGzipped = Bun.gzipSync(browserContent).length;
5281
5258
  browserInfo = {
5282
5259
  name: basename3(browserEntry),
@@ -5291,13 +5268,13 @@ async function analyze(args) {
5291
5268
  let entry = null;
5292
5269
  let depTree = null;
5293
5270
  let mainInfo = null;
5294
- const srcEntry = join12(cwd, "src", "index.ts");
5271
+ const srcEntry = join11(cwd, "src", "index.ts");
5295
5272
  if (existsSync9(srcEntry)) {
5296
5273
  console.log(colorizeLogPrefixAnsi(`[reroute/analyze] Building server binary for analysis...
5297
5274
  `));
5298
- const { mkdir: mkdir4 } = await import("node:fs/promises");
5299
- const serverAnalysisDir = join12(cwd, ".reroute", "server");
5300
- await mkdir4(serverAnalysisDir, { recursive: true });
5275
+ const { mkdir: mkdir3 } = await import("node:fs/promises");
5276
+ const serverAnalysisDir = join11(cwd, ".reroute", "server");
5277
+ await mkdir3(serverAnalysisDir, { recursive: true });
5301
5278
  const result = await Bun.build({
5302
5279
  entrypoints: [srcEntry],
5303
5280
  target: "bun",
@@ -5309,12 +5286,12 @@ async function analyze(args) {
5309
5286
  if (result.success && result.outputs.length > 0) {
5310
5287
  const output = result.outputs[0];
5311
5288
  const code = await output.text();
5312
- const analysisEntry = join12(serverAnalysisDir, "index.js");
5313
- await writeFile4(analysisEntry, code, "utf-8");
5289
+ const analysisEntry = join11(serverAnalysisDir, "index.js");
5290
+ await writeFile(analysisEntry, code, "utf-8");
5314
5291
  const mapOutput = result.outputs.find((o) => o.path.endsWith(".map"));
5315
5292
  if (mapOutput) {
5316
5293
  const mapContent = await mapOutput.text();
5317
- await writeFile4(`${analysisEntry}.map`, mapContent, "utf-8");
5294
+ await writeFile(`${analysisEntry}.map`, mapContent, "utf-8");
5318
5295
  }
5319
5296
  entry = analysisEntry;
5320
5297
  }
@@ -5327,10 +5304,10 @@ async function analyze(args) {
5327
5304
  `));
5328
5305
  const installedSizes = await getInstalledPackageSizes(cwd);
5329
5306
  if (depTree) {
5330
- const packageJsonPath = join12(cwd, "package.json");
5307
+ const packageJsonPath = join11(cwd, "package.json");
5331
5308
  if (existsSync9(packageJsonPath)) {
5332
5309
  try {
5333
- const packageJson = JSON.parse(await readFile2(packageJsonPath, "utf-8"));
5310
+ const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
5334
5311
  const runtimeDeps = packageJson.dependencies || {};
5335
5312
  const nodeModulesNode = depTree.root.children?.find((c) => c.name === "node_modules");
5336
5313
  if (nodeModulesNode) {
@@ -5339,7 +5316,7 @@ async function analyze(args) {
5339
5316
  if (!trackedPkgs.has(pkgName) && installedSizes.has(pkgName)) {
5340
5317
  nodeModulesNode.children?.push({
5341
5318
  name: pkgName,
5342
- path: join12(cwd, "node_modules", pkgName),
5319
+ path: join11(cwd, "node_modules", pkgName),
5343
5320
  size: installedSizes.get(pkgName) || 0
5344
5321
  });
5345
5322
  }
@@ -5358,7 +5335,7 @@ async function analyze(args) {
5358
5335
  }
5359
5336
  try {
5360
5337
  const entryStat = await stat5(entry);
5361
- const entryContent = await readFile2(entry);
5338
+ const entryContent = await readFile(entry);
5362
5339
  const entryGzipped = Bun.gzipSync(entryContent).length;
5363
5340
  mainInfo = {
5364
5341
  name: basename3(entry),
@@ -5370,30 +5347,30 @@ async function analyze(args) {
5370
5347
  const fullOutput = args.includes("--full");
5371
5348
  await printConsoleReport(stats, depTree, mainInfo, browserDepTree, browserInfo, fullOutput);
5372
5349
  if (outputHtml || openBrowser) {
5373
- const htmlPath = join12(cwd, ".reroute", "analysis.html");
5350
+ const htmlPath = join11(cwd, ".reroute", "analysis.html");
5374
5351
  const html2 = await generateHTMLReport(stats, depTree, mainInfo, browserDepTree, browserInfo, initialSearch);
5375
- const { mkdir: mkdir4 } = await import("node:fs/promises");
5376
- await mkdir4(join12(cwd, ".reroute"), { recursive: true });
5377
- await writeFile4(htmlPath, html2, "utf-8");
5352
+ const { mkdir: mkdir3 } = await import("node:fs/promises");
5353
+ await mkdir3(join11(cwd, ".reroute"), { recursive: true });
5354
+ await writeFile(htmlPath, html2, "utf-8");
5378
5355
  console.log(colorizeLogPrefixAnsi(`[reroute/analyze] HTML report generated: ${relative(cwd, htmlPath)}
5379
5356
  `));
5380
5357
  if (openBrowser) {
5381
5358
  try {
5382
5359
  const { spawn: spawn5 } = await import("node:child_process");
5383
5360
  const platform = process.platform;
5384
- let command2;
5361
+ let command;
5385
5362
  let commandArgs;
5386
5363
  if (platform === "darwin") {
5387
- command2 = "open";
5364
+ command = "open";
5388
5365
  commandArgs = [htmlPath];
5389
5366
  } else if (platform === "win32") {
5390
- command2 = "cmd";
5367
+ command = "cmd";
5391
5368
  commandArgs = ["/c", "start", "", htmlPath];
5392
5369
  } else {
5393
- command2 = "xdg-open";
5370
+ command = "xdg-open";
5394
5371
  commandArgs = [htmlPath];
5395
5372
  }
5396
- spawn5(command2, commandArgs, { detached: true, stdio: "ignore" });
5373
+ spawn5(command, commandArgs, { detached: true, stdio: "ignore" });
5397
5374
  console.log(colorizeLogPrefixAnsi(`[reroute/analyze] Opened report in browser
5398
5375
  `));
5399
5376
  } catch {
@@ -5435,7 +5412,6 @@ import path3 from "node:path";
5435
5412
  var commands = {
5436
5413
  init: () => Promise.resolve().then(() => (init_init(), exports_init)),
5437
5414
  gen: () => Promise.resolve().then(() => (init_gen(), exports_gen)),
5438
- boot: () => Promise.resolve().then(() => (init_boot(), exports_boot)),
5439
5415
  dev: () => Promise.resolve().then(() => (init_dev(), exports_dev)),
5440
5416
  start: () => Promise.resolve().then(() => (init_start(), exports_start)),
5441
5417
  build: () => Promise.resolve().then(() => (init_build(), exports_build)),
@@ -5452,9 +5428,9 @@ async function main() {
5452
5428
  await printHelp2();
5453
5429
  process.exit(0);
5454
5430
  }
5455
- const command2 = args[0];
5456
- if (!commands[command2]) {
5457
- console.error(`Unknown command: ${command2}`);
5431
+ const command = args[0];
5432
+ if (!commands[command]) {
5433
+ console.error(`Unknown command: ${command}`);
5458
5434
  console.error("");
5459
5435
  await printHelp2();
5460
5436
  process.exit(1);
@@ -5467,7 +5443,7 @@ async function main() {
5467
5443
  Bun.env.NODE_ENV = "production";
5468
5444
  }
5469
5445
  }
5470
- const module = await commands[command2]();
5446
+ const module = await commands[command]();
5471
5447
  await module.default(commandArgs);
5472
5448
  } catch (error) {
5473
5449
  console.error("Error executing command:", error);
@@ -5487,7 +5463,6 @@ async function printHelp2() {
5487
5463
  console.log("Commands:");
5488
5464
  console.log("");
5489
5465
  console.log(" init Scaffold a new Reroute project");
5490
- console.log(" boot Initialize .reroute directory with stub files");
5491
5466
  console.log(" gen Generate content registry and static assets");
5492
5467
  console.log(" dev Start development environment");
5493
5468
  console.log(" start Run production-like server locally");
@@ -5505,7 +5480,6 @@ async function printHelp2() {
5505
5480
  console.log("Examples:");
5506
5481
  console.log("");
5507
5482
  console.log(" reroute init my-app");
5508
- console.log(" reroute boot");
5509
5483
  console.log("");
5510
5484
  console.log(" reroute gen");
5511
5485
  console.log(" reroute gen -w");
@@ -5535,7 +5509,7 @@ async function getVersionString2() {
5535
5509
  }
5536
5510
  async function getVersion2() {
5537
5511
  if (true) {
5538
- return "0.8.0";
5512
+ return "0.9.1";
5539
5513
  }
5540
5514
  const possiblePaths = [
5541
5515
  path3.join(import.meta.dir, "../../../package.json"),
@@ -5552,10 +5526,10 @@ async function getVersion2() {
5552
5526
  }
5553
5527
  async function getCommit2() {
5554
5528
  if (true) {
5555
- return "b31f8e3";
5529
+ return "75cc9e9";
5556
5530
  }
5557
5531
  return "dev";
5558
5532
  }
5559
5533
  main();
5560
5534
 
5561
- //# debugId=8F50A077EDCF534864756E2164756E21
5535
+ //# debugId=2FE626A79390776364756E2164756E21