@react-router/dev 7.0.0-pre.3 → 7.0.0-pre.5

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.
package/dist/cli/index.js CHANGED
@@ -1,5 +1,6 @@
1
+ #!/usr/bin/env node
1
2
  /**
2
- * @react-router/dev v7.0.0-pre.3
3
+ * @react-router/dev v7.0.0-pre.5
3
4
  *
4
5
  * Copyright (c) Remix Software Inc.
5
6
  *
@@ -18,9 +19,6 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
18
19
  var __esm = (fn, res) => function __init() {
19
20
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
20
21
  };
21
- var __commonJS = (cb, mod) => function __require() {
22
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
23
- };
24
22
  var __export = (target, all) => {
25
23
  for (var name in all)
26
24
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -86,6 +84,10 @@ var init_node_adapter = __esm({
86
84
  async function preloadViteEsm() {
87
85
  vite = await import("vite");
88
86
  }
87
+ function importViteEsmSync() {
88
+ invariant(vite, "importViteEsmSync() called before preloadViteEsm()");
89
+ return vite;
90
+ }
89
91
  var vite;
90
92
  var init_import_vite_esm_sync = __esm({
91
93
  "vite/import-vite-esm-sync.ts"() {
@@ -144,6 +146,44 @@ var init_remove_exports = __esm({
144
146
  });
145
147
 
146
148
  // config/routes.ts
149
+ function configRoutesToRouteManifest(routes2, rootId = "root") {
150
+ let routeManifest = {};
151
+ function walk(route, parentId) {
152
+ let id2 = route.id || createRouteId(route.file);
153
+ let manifestItem = {
154
+ id: id2,
155
+ parentId,
156
+ file: route.file,
157
+ path: route.path,
158
+ index: route.index,
159
+ caseSensitive: route.caseSensitive
160
+ };
161
+ if (routeManifest.hasOwnProperty(id2)) {
162
+ throw new Error(
163
+ `Unable to define routes with duplicate route id: "${id2}"`
164
+ );
165
+ }
166
+ routeManifest[id2] = manifestItem;
167
+ if (route.children) {
168
+ for (let child of route.children) {
169
+ walk(child, id2);
170
+ }
171
+ }
172
+ }
173
+ for (let route of routes2) {
174
+ walk(route, rootId);
175
+ }
176
+ return routeManifest;
177
+ }
178
+ function createRouteId(file) {
179
+ return normalizeSlashes(stripFileExtension(file));
180
+ }
181
+ function normalizeSlashes(file) {
182
+ return file.split(import_node_path.win32.sep).join("/");
183
+ }
184
+ function stripFileExtension(file) {
185
+ return file.replace(/\.[a-z0-9]+$/i, "");
186
+ }
147
187
  var import_node_path, v, import_pick, routeConfigEntrySchema, resolvedRouteConfigSchema;
148
188
  var init_routes = __esm({
149
189
  "config/routes.ts"() {
@@ -177,7 +217,14 @@ var init_detectPackageManager = __esm({
177
217
  });
178
218
 
179
219
  // vite/config.ts
180
- var import_node_child_process, import_node_path2, import_fs_extra, import_picocolors, import_pick2, import_omit, import_package_json, branchRouteProperties, configRouteToBranchRoute;
220
+ function findEntry(dir, basename2) {
221
+ for (let ext of entryExts) {
222
+ let file = import_node_path2.default.resolve(dir, basename2 + ext);
223
+ if (import_fs_extra.default.existsSync(file)) return import_node_path2.default.relative(dir, file);
224
+ }
225
+ return void 0;
226
+ }
227
+ var import_node_child_process, import_node_path2, import_fs_extra, import_picocolors, import_pick2, import_omit, import_package_json, branchRouteProperties, configRouteToBranchRoute, entryExts;
181
228
  var init_config = __esm({
182
229
  "vite/config.ts"() {
183
230
  "use strict";
@@ -198,6 +245,7 @@ var init_config = __esm({
198
245
  "index"
199
246
  ];
200
247
  configRouteToBranchRoute = (configRoute) => (0, import_pick2.default)(configRoute, branchRouteProperties);
248
+ entryExts = [".js", ".jsx", ".ts", ".tsx"];
201
249
  }
202
250
  });
203
251
 
@@ -214,6 +262,43 @@ var init_with_props = __esm({
214
262
  });
215
263
 
216
264
  // vite/vite-node.ts
265
+ async function createContext(viteConfig = {}) {
266
+ await preloadViteEsm();
267
+ const vite2 = importViteEsmSync();
268
+ const devServer = await vite2.createServer(
269
+ vite2.mergeConfig(
270
+ {
271
+ server: {
272
+ preTransformRequests: false,
273
+ hmr: false
274
+ },
275
+ optimizeDeps: {
276
+ noDiscovery: true
277
+ },
278
+ configFile: false,
279
+ envFile: false,
280
+ plugins: []
281
+ },
282
+ viteConfig
283
+ )
284
+ );
285
+ await devServer.pluginContainer.buildStart({});
286
+ const server = new import_server.ViteNodeServer(devServer);
287
+ (0, import_source_map.installSourcemapsSupport)({
288
+ getSourceMap: (source) => server.getSourceMap(source)
289
+ });
290
+ const runner = new import_client.ViteNodeRunner({
291
+ root: devServer.config.root,
292
+ base: devServer.config.base,
293
+ fetchModule(id2) {
294
+ return server.fetchModule(id2);
295
+ },
296
+ resolveId(id2, importer) {
297
+ return server.resolveId(id2, importer);
298
+ }
299
+ });
300
+ return { devServer, server, runner };
301
+ }
217
302
  var import_server, import_client, import_source_map;
218
303
  var init_vite_node = __esm({
219
304
  "vite/vite-node.ts"() {
@@ -385,7 +470,7 @@ var init_profiler = __esm({
385
470
  });
386
471
  };
387
472
  profileCount = 0;
388
- stop = (log) => {
473
+ stop = (log2) => {
389
474
  let session = getSession();
390
475
  if (!session) return;
391
476
  return new Promise((res, rej) => {
@@ -393,7 +478,7 @@ var init_profiler = __esm({
393
478
  if (err) return rej(err);
394
479
  let outPath = import_node_path3.default.resolve(`./react-router-${profileCount++}.cpuprofile`);
395
480
  import_node_fs.default.writeFileSync(outPath, JSON.stringify(profile));
396
- log(
481
+ log2(
397
482
  import_picocolors3.default.yellow(
398
483
  `CPU profile written to ${import_picocolors3.default.white(import_picocolors3.default.dim(outPath))}`
399
484
  )
@@ -565,7 +650,7 @@ async function build(root, {
565
650
  const ctx = await extractPluginContext(viteConfig);
566
651
  if (!ctx) {
567
652
  console.error(
568
- import_picocolors4.default.red("React Router Vite plugin not found in Vite config")
653
+ import_picocolors6.default.red("React Router Vite plugin not found in Vite config")
569
654
  );
570
655
  process.exit(1);
571
656
  }
@@ -617,13 +702,13 @@ async function build(root, {
617
702
  viteConfig
618
703
  });
619
704
  }
620
- var import_node_path4, import_fs_extra2, import_picocolors4;
705
+ var import_node_path4, import_fs_extra2, import_picocolors6;
621
706
  var init_build = __esm({
622
707
  "vite/build.ts"() {
623
708
  "use strict";
624
709
  import_node_path4 = __toESM(require("path"));
625
710
  import_fs_extra2 = __toESM(require("fs-extra"));
626
- import_picocolors4 = __toESM(require("picocolors"));
711
+ import_picocolors6 = __toESM(require("picocolors"));
627
712
  init_plugin();
628
713
  init_config();
629
714
  init_invariant();
@@ -661,7 +746,7 @@ async function dev(root, {
661
746
  });
662
747
  if (!server.config.plugins.find((plugin2) => plugin2.name === "react-router")) {
663
748
  console.error(
664
- import_picocolors5.default.red("React Router Vite plugin not found in Vite config")
749
+ import_picocolors7.default.red("React Router Vite plugin not found in Vite config")
665
750
  );
666
751
  process.exit(1);
667
752
  }
@@ -684,198 +769,27 @@ async function dev(root, {
684
769
  ];
685
770
  server.bindCLIShortcuts({ print: true, customShortcuts });
686
771
  }
687
- var import_picocolors5;
772
+ var import_picocolors7;
688
773
  var init_dev = __esm({
689
774
  "vite/dev.ts"() {
690
775
  "use strict";
691
- import_picocolors5 = __toESM(require("picocolors"));
776
+ import_picocolors7 = __toESM(require("picocolors"));
692
777
  init_import_vite_esm_sync();
693
778
  init_profiler();
694
779
  }
695
780
  });
696
781
 
697
- // package.json
698
- var require_package = __commonJS({
699
- "package.json"(exports2, module2) {
700
- module2.exports = {
701
- name: "@react-router/dev",
702
- version: "7.0.0-pre.3",
703
- description: "Dev tools and CLI for React Router",
704
- homepage: "https://reactrouter.com",
705
- bugs: {
706
- url: "https://github.com/remix-run/react-router/issues"
707
- },
708
- repository: {
709
- type: "git",
710
- url: "https://github.com/remix-run/react-router",
711
- directory: "packages/react-router-dev"
712
- },
713
- license: "MIT",
714
- main: "./dist/typescript/plugin.ts",
715
- exports: {
716
- "./routes": {
717
- types: "./dist/routes.d.ts",
718
- default: "./dist/routes.js"
719
- },
720
- "./vite": {
721
- types: "./dist/vite.d.ts",
722
- default: "./dist/vite.js"
723
- },
724
- "./vite/cloudflare": {
725
- types: "./dist/vite/cloudflare.d.ts",
726
- default: "./dist/vite/cloudflare.js"
727
- },
728
- "./package.json": "./package.json"
729
- },
730
- bin: {
731
- "react-router": "bin.js"
732
- },
733
- scripts: {
734
- build: "wireit"
735
- },
736
- wireit: {
737
- build: {
738
- command: "tsup",
739
- files: [
740
- "cli/**",
741
- "config/**",
742
- "typescript/**",
743
- "vite/**",
744
- "*.ts",
745
- "bin.js",
746
- "tsconfig.json",
747
- "package.json"
748
- ],
749
- output: [
750
- "dist/**"
751
- ]
752
- }
753
- },
754
- dependencies: {
755
- "@babel/core": "^7.21.8",
756
- "@babel/generator": "^7.21.5",
757
- "@babel/parser": "^7.21.8",
758
- "@babel/plugin-syntax-decorators": "^7.22.10",
759
- "@babel/plugin-syntax-jsx": "^7.21.4",
760
- "@babel/preset-typescript": "^7.21.5",
761
- "@babel/traverse": "^7.23.2",
762
- "@babel/types": "^7.22.5",
763
- "@npmcli/package-json": "^4.0.1",
764
- "@react-router/node": "workspace:*",
765
- arg: "^5.0.1",
766
- "babel-dead-code-elimination": "^1.0.6",
767
- chalk: "^4.1.2",
768
- chokidar: "^4.0.0",
769
- dedent: "^1.5.3",
770
- "es-module-lexer": "^1.3.1",
771
- "exit-hook": "2.2.1",
772
- "fs-extra": "^10.0.0",
773
- "gunzip-maybe": "^1.4.2",
774
- jsesc: "3.0.2",
775
- lodash: "^4.17.21",
776
- pathe: "^1.1.2",
777
- picocolors: "^1.0.0",
778
- picomatch: "^2.3.1",
779
- prettier: "^2.7.1",
780
- "react-refresh": "^0.14.0",
781
- semver: "^7.3.7",
782
- "set-cookie-parser": "^2.6.0",
783
- valibot: "^0.41.0",
784
- "vite-node": "^1.6.0"
785
- },
786
- devDependencies: {
787
- "@react-router/serve": "workspace:*",
788
- "@types/babel__core": "^7.20.5",
789
- "@types/babel__generator": "^7.6.8",
790
- "@types/babel__traverse": "^7.20.5",
791
- "@types/dedent": "^0.7.0",
792
- "@types/express": "^4.17.9",
793
- "@types/fs-extra": "^8.1.2",
794
- "@types/gunzip-maybe": "^1.4.0",
795
- "@types/jsesc": "^3.0.1",
796
- "@types/lodash": "^4.14.182",
797
- "@types/node": "^18.17.1",
798
- "@types/npmcli__package-json": "^4.0.0",
799
- "@types/picomatch": "^2.3.0",
800
- "@types/prettier": "^2.7.3",
801
- "@types/set-cookie-parser": "^2.4.1",
802
- dotenv: "^16.0.0",
803
- "esbuild-register": "^3.3.2",
804
- execa: "5.1.1",
805
- express: "^4.19.2",
806
- "fast-glob": "3.2.11",
807
- "react-router": "workspace:^",
808
- "strip-ansi": "^6.0.1",
809
- "tiny-invariant": "^1.2.0",
810
- tsup: "^8.3.0",
811
- typescript: "^5.1.6",
812
- vite: "^5.1.0",
813
- wireit: "0.14.9",
814
- wrangler: "^3.28.2"
815
- },
816
- peerDependencies: {
817
- "@react-router/serve": "workspace:^",
818
- "react-router": "workspace:^",
819
- typescript: "^5.1.0",
820
- vite: "^5.1.0",
821
- wrangler: "^3.28.2"
822
- },
823
- peerDependenciesMeta: {
824
- "@react-router/serve": {
825
- optional: true
826
- },
827
- typescript: {
828
- optional: true
829
- },
830
- wrangler: {
831
- optional: true
832
- }
833
- },
834
- engines: {
835
- node: ">=20.0.0"
836
- },
837
- files: [
838
- "dist/",
839
- "bin.js",
840
- "CHANGELOG.md",
841
- "LICENSE.md",
842
- "README.md"
843
- ]
844
- };
845
- }
846
- });
847
-
848
782
  // cli/run.ts
849
783
  var import_arg = __toESM(require("arg"));
850
784
  var import_semver = __toESM(require("semver"));
851
-
852
- // colors.ts
853
- var import_chalk = __toESM(require("chalk"));
854
- var useColor = import_chalk.default.supportsColor && !process.env.NO_COLOR;
855
- var identity = (x) => x;
856
- var safe = (style) => useColor ? style : identity;
857
- var heading = safe(import_chalk.default.underline);
858
- var arg = safe(import_chalk.default.yellowBright);
859
- var error = safe(import_chalk.default.red);
860
- var warning = safe(import_chalk.default.yellow);
861
- var hint = safe(import_chalk.default.blue);
862
- var logoBlue = safe(import_chalk.default.blueBright);
863
- var logoGreen = safe(import_chalk.default.greenBright);
864
- var logoYellow = safe(import_chalk.default.yellowBright);
865
- var logoPink = safe(import_chalk.default.magentaBright);
866
- var logoRed = safe(import_chalk.default.redBright);
867
- var bold = safe(import_chalk.default.bold);
868
- var blue = safe(import_chalk.default.blue);
869
- var cyan = safe(import_chalk.default.cyan);
870
- var gray = safe(import_chalk.default.gray);
871
- var red = safe(import_chalk.default.red);
872
- var yellow = safe(import_chalk.default.yellow);
785
+ var import_picocolors9 = __toESM(require("picocolors"));
873
786
 
874
787
  // cli/commands.ts
875
788
  var path7 = __toESM(require("path"));
876
789
  var import_fs_extra3 = __toESM(require("fs-extra"));
877
790
  var import_package_json2 = __toESM(require("@npmcli/package-json"));
878
791
  var import_exit_hook = __toESM(require("exit-hook"));
792
+ var import_picocolors8 = __toESM(require("picocolors"));
879
793
 
880
794
  // config/format.ts
881
795
  function formatRoutes(routeManifest, format) {
@@ -957,12 +871,53 @@ function transpile(tsx, options = {}) {
957
871
  // cli/commands.ts
958
872
  init_profiler();
959
873
 
960
- // typescript/typegen.ts
874
+ // typegen.ts
961
875
  var import_node_fs2 = __toESM(require("fs"));
962
876
  var import_chokidar = __toESM(require("chokidar"));
963
877
  var import_dedent2 = __toESM(require("dedent"));
964
878
  var Path = __toESM(require("pathe"));
965
879
  var Pathe = __toESM(require("pathe/utils"));
880
+ var import_picocolors5 = __toESM(require("picocolors"));
881
+
882
+ // logger.ts
883
+ var import_picocolors4 = __toESM(require("picocolors"));
884
+ var DATE_TIME_FORMAT = new Intl.DateTimeFormat([], {
885
+ hour: "2-digit",
886
+ minute: "2-digit",
887
+ second: "2-digit",
888
+ hour12: false
889
+ });
890
+ var log = (level) => (body, options = {}) => {
891
+ const dest = level === "error" ? process.stderr : process.stdout;
892
+ let message = getPrefix(level, options) + " " + body;
893
+ if (options.durationMs) {
894
+ const duration = options.durationMs < 1e3 ? `${Math.round(options.durationMs)}ms` : `${(options.durationMs / 1e3).toFixed(2)}s`;
895
+ message += " " + import_picocolors4.default.dim(duration);
896
+ }
897
+ dest.write(message + "\n");
898
+ };
899
+ function getPrefix(level, options) {
900
+ const timestamp = `${DATE_TIME_FORMAT.format(/* @__PURE__ */ new Date())}`;
901
+ const prefix = [];
902
+ if (level === "error" || level === "warn") {
903
+ prefix.push(import_picocolors4.default.bold(timestamp));
904
+ prefix.push(`[${level.toUpperCase()}]`);
905
+ } else {
906
+ prefix.push(timestamp);
907
+ }
908
+ if (options.label) {
909
+ prefix.push(`[${options.label}]`);
910
+ }
911
+ if (level === "error") return import_picocolors4.default.red(prefix.join(" "));
912
+ if (level === "warn") return import_picocolors4.default.yellow(prefix.join(" "));
913
+ if (prefix.length === 1) return import_picocolors4.default.dim(prefix[0]);
914
+ return import_picocolors4.default.dim(prefix[0]) + " " + import_picocolors4.default.blue(prefix.splice(1).join(" "));
915
+ }
916
+ var info = log("info");
917
+ var warn = log("warn");
918
+ var error = log("error");
919
+
920
+ // typegen.ts
966
921
  init_routes();
967
922
  init_vite_node();
968
923
  init_config();
@@ -970,19 +925,100 @@ init_plugin();
970
925
  function getDirectory(ctx) {
971
926
  return Path.join(ctx.rootDirectory, ".react-router/types");
972
927
  }
973
- function getPath(ctx, route) {
974
- return Path.join(
975
- getDirectory(ctx),
976
- "app",
977
- Path.dirname(route.file),
978
- "+types." + Pathe.filename(route.file) + ".d.ts"
928
+ async function watch(rootDirectory, options = {}) {
929
+ const watchStart = performance.now();
930
+ const vitePluginCtx = await loadPluginContext({
931
+ root: rootDirectory,
932
+ configFile: options.configFile
933
+ });
934
+ const routeConfigFile = findEntry(
935
+ vitePluginCtx.reactRouterConfig.appDirectory,
936
+ "routes"
937
+ );
938
+ if (!routeConfigFile) {
939
+ warn(
940
+ `Could not find route config within ${import_picocolors5.default.blue(
941
+ Path.relative(
942
+ vitePluginCtx.rootDirectory,
943
+ vitePluginCtx.reactRouterConfig.appDirectory
944
+ )
945
+ )}`
946
+ );
947
+ process.exit(1);
948
+ }
949
+ const routeConfigPath = Path.join(
950
+ vitePluginCtx.reactRouterConfig.appDirectory,
951
+ routeConfigFile
979
952
  );
953
+ const routesViteNodeContext = await createContext({
954
+ root: rootDirectory
955
+ });
956
+ async function getRoutes() {
957
+ const routes2 = {};
958
+ const rootRouteFile = findEntry(
959
+ vitePluginCtx.reactRouterConfig.appDirectory,
960
+ "root"
961
+ );
962
+ if (rootRouteFile) {
963
+ routes2.root = { path: "", id: "root", file: rootRouteFile };
964
+ } else {
965
+ warn(`Could not find \`root\` route`);
966
+ }
967
+ routesViteNodeContext.devServer.moduleGraph.invalidateAll();
968
+ routesViteNodeContext.runner.moduleCache.clear();
969
+ const routeConfig = (await routesViteNodeContext.runner.executeFile(routeConfigPath)).routes;
970
+ return {
971
+ ...routes2,
972
+ ...configRoutesToRouteManifest(await routeConfig)
973
+ };
974
+ }
975
+ const ctx = {
976
+ rootDirectory,
977
+ appDirectory: vitePluginCtx.reactRouterConfig.appDirectory,
978
+ routes: await getRoutes()
979
+ };
980
+ await writeAll(ctx);
981
+ info("generated initial types", {
982
+ durationMs: performance.now() - watchStart
983
+ });
984
+ const watcher = import_chokidar.default.watch(ctx.appDirectory, { ignoreInitial: true });
985
+ watcher.on("all", async (event, path8) => {
986
+ const eventStart = performance.now();
987
+ path8 = Path.normalize(path8);
988
+ ctx.routes = await getRoutes();
989
+ const routeConfigChanged = Boolean(
990
+ routesViteNodeContext.devServer.moduleGraph.getModuleById(path8)
991
+ );
992
+ if (routeConfigChanged) {
993
+ await writeAll(ctx);
994
+ info("changed route config", {
995
+ durationMs: performance.now() - eventStart
996
+ });
997
+ return;
998
+ }
999
+ const route = Object.values(ctx.routes).find(
1000
+ (route2) => path8 === Path.join(ctx.appDirectory, route2.file)
1001
+ );
1002
+ if (route && (event === "add" || event === "unlink")) {
1003
+ await writeAll(ctx);
1004
+ info(
1005
+ `${event === "add" ? "added" : "removed"} route ${import_picocolors5.default.blue(route.file)}`,
1006
+ { durationMs: performance.now() - eventStart }
1007
+ );
1008
+ return;
1009
+ }
1010
+ });
980
1011
  }
981
1012
  async function writeAll(ctx) {
982
1013
  import_node_fs2.default.rmSync(getDirectory(ctx), { recursive: true, force: true });
983
1014
  Object.values(ctx.routes).forEach((route) => {
984
1015
  if (!import_node_fs2.default.existsSync(Path.join(ctx.appDirectory, route.file))) return;
985
- const typesPath = getPath(ctx, route);
1016
+ const typesPath = Path.join(
1017
+ getDirectory(ctx),
1018
+ Path.relative(ctx.rootDirectory, ctx.appDirectory),
1019
+ Path.dirname(route.file),
1020
+ "+types." + Pathe.filename(route.file) + ".d.ts"
1021
+ );
986
1022
  const content = getModule(ctx.routes, route);
987
1023
  import_node_fs2.default.mkdirSync(Path.dirname(typesPath), { recursive: true });
988
1024
  import_node_fs2.default.writeFileSync(typesPath, content);
@@ -997,19 +1033,21 @@ function getModule(routes2, route) {
997
1033
 
998
1034
  export type Params = {${formattedParamsProperties(routes2, route)}}
999
1035
 
1000
- type Route = typeof import("./${Pathe.filename(route.file)}")
1036
+ type RouteModule = typeof import("./${Pathe.filename(route.file)}")
1001
1037
 
1002
- export type LoaderData = T.CreateLoaderData<Route>
1003
- export type ActionData = T.CreateActionData<Route>
1038
+ export namespace Route {
1039
+ export type LoaderData = T.CreateLoaderData<RouteModule>
1040
+ export type ActionData = T.CreateActionData<RouteModule>
1004
1041
 
1005
- export type LoaderArgs = T.CreateServerLoaderArgs<Params>
1006
- export type ClientLoaderArgs = T.CreateClientLoaderArgs<Params, Route>
1007
- export type ActionArgs = T.CreateServerActionArgs<Params>
1008
- export type ClientActionArgs = T.CreateClientActionArgs<Params, Route>
1042
+ export type LoaderArgs = T.CreateServerLoaderArgs<Params>
1043
+ export type ClientLoaderArgs = T.CreateClientLoaderArgs<Params, RouteModule>
1044
+ export type ActionArgs = T.CreateServerActionArgs<Params>
1045
+ export type ClientActionArgs = T.CreateClientActionArgs<Params, RouteModule>
1009
1046
 
1010
- export type HydrateFallbackProps = T.CreateHydrateFallbackProps<Params>
1011
- export type ComponentProps = T.CreateComponentProps<Params, LoaderData, ActionData>
1012
- export type ErrorBoundaryProps = T.CreateErrorBoundaryProps<Params, LoaderData, ActionData>
1047
+ export type HydrateFallbackProps = T.CreateHydrateFallbackProps<Params>
1048
+ export type ComponentProps = T.CreateComponentProps<Params, LoaderData, ActionData>
1049
+ export type ErrorBoundaryProps = T.CreateErrorBoundaryProps<Params, LoaderData, ActionData>
1050
+ }
1013
1051
  `;
1014
1052
  }
1015
1053
  function formattedParamsProperties(routes2, route) {
@@ -1019,12 +1057,12 @@ function formattedParamsProperties(routes2, route) {
1019
1057
  const properties = Object.entries(params).map(([name, values]) => {
1020
1058
  if (values.length === 1) {
1021
1059
  const isOptional = values[0];
1022
- return indent + (isOptional ? `${name}?: string` : `${name}: string`);
1060
+ return indent + (isOptional ? `"${name}"?: string` : `"${name}": string`);
1023
1061
  }
1024
1062
  const items = values.map(
1025
1063
  (isOptional) => isOptional ? "string | undefined" : "string"
1026
1064
  );
1027
- return indent + `${name}: [${items.join(", ")}]`;
1065
+ return indent + `"${name}": [${items.join(", ")}]`;
1028
1066
  });
1029
1067
  const body = properties.length === 0 ? "" : "\n" + properties.join("\n") + "\n";
1030
1068
  return body;
@@ -1052,6 +1090,8 @@ function parseParams(urlpath) {
1052
1090
  result[param].push(isOptional);
1053
1091
  return;
1054
1092
  });
1093
+ const hasSplat = segments.at(-1) === "*";
1094
+ if (hasSplat) result["*"] = [false];
1055
1095
  return result;
1056
1096
  }
1057
1097
 
@@ -1063,7 +1103,7 @@ async function routes(reactRouterRoot, flags = {}) {
1063
1103
  });
1064
1104
  if (!ctx) {
1065
1105
  console.error(
1066
- red("React Router Vite plugin not found in Vite config")
1106
+ import_picocolors8.default.red("React Router Vite plugin not found in Vite config")
1067
1107
  );
1068
1108
  process.exit(1);
1069
1109
  }
@@ -1117,14 +1157,14 @@ async function generateEntry(entry, reactRouterRoot, flags = {}) {
1117
1157
  let entriesArray = Array.from(entries);
1118
1158
  let list = conjunctionListFormat.format(entriesArray);
1119
1159
  console.error(
1120
- error(`Invalid entry file. Valid entry files are ${list}`)
1160
+ import_picocolors8.default.red(`Invalid entry file. Valid entry files are ${list}`)
1121
1161
  );
1122
1162
  return;
1123
1163
  }
1124
1164
  let pkgJson = await import_package_json2.default.load(rootDirectory);
1125
1165
  let deps = pkgJson.content.dependencies ?? {};
1126
1166
  if (!deps["@react-router/node"]) {
1127
- console.error(error(`No default server entry detected.`));
1167
+ console.error(import_picocolors8.default.red(`No default server entry detected.`));
1128
1168
  return;
1129
1169
  }
1130
1170
  let defaultsDirectory = path7.resolve(
@@ -1154,7 +1194,7 @@ async function generateEntry(entry, reactRouterRoot, flags = {}) {
1154
1194
  await import_fs_extra3.default.writeFile(outputFile2, contents, "utf-8");
1155
1195
  }
1156
1196
  console.log(
1157
- blue(
1197
+ import_picocolors8.default.blue(
1158
1198
  `Entry file ${entry} created at ${path7.relative(
1159
1199
  rootDirectory,
1160
1200
  outputFile2
@@ -1167,8 +1207,8 @@ async function checkForEntry(rootDirectory, appDirectory, entries2) {
1167
1207
  let entryPath = path7.resolve(appDirectory, entry);
1168
1208
  let exists = await import_fs_extra3.default.pathExists(entryPath);
1169
1209
  if (exists) {
1170
- let relative5 = path7.relative(rootDirectory, entryPath);
1171
- console.error(error(`Entry file ${relative5} already exists.`));
1210
+ let relative6 = path7.relative(rootDirectory, entryPath);
1211
+ console.error(import_picocolors8.default.red(`Entry file ${relative6} already exists.`));
1172
1212
  return process.exit(1);
1173
1213
  }
1174
1214
  }
@@ -1183,8 +1223,15 @@ async function createClientEntry(rootDirectory, appDirectory, inputFile) {
1183
1223
  let contents = await import_fs_extra3.default.readFile(inputFile, "utf-8");
1184
1224
  return contents;
1185
1225
  }
1186
- async function typegen(root) {
1187
- let ctx = await loadPluginContext({ root });
1226
+ async function typegen(root, flags) {
1227
+ root ??= process.cwd();
1228
+ if (flags.watch) {
1229
+ await watch(root, { configFile: flags.config });
1230
+ await new Promise(() => {
1231
+ });
1232
+ return;
1233
+ }
1234
+ let ctx = await loadPluginContext({ root, configFile: flags.config });
1188
1235
  await writeAll({
1189
1236
  rootDirectory: root,
1190
1237
  appDirectory: ctx.reactRouterConfig.appDirectory,
@@ -1194,14 +1241,14 @@ async function typegen(root) {
1194
1241
 
1195
1242
  // cli/run.ts
1196
1243
  var helpText = `
1197
- ${logoBlue("react-router")}
1244
+ ${import_picocolors9.default.blueBright("react-router")}
1198
1245
 
1199
- ${heading("Usage")}:
1200
- $ react-router build [${arg("projectDir")}]
1201
- $ react-router dev [${arg("projectDir")}]
1202
- $ react-router routes [${arg("projectDir")}]
1246
+ ${import_picocolors9.default.underline("Usage")}:
1247
+ $ react-router build [${import_picocolors9.default.yellowBright("projectDir")}]
1248
+ $ react-router dev [${import_picocolors9.default.yellowBright("projectDir")}]
1249
+ $ react-router routes [${import_picocolors9.default.yellowBright("projectDir")}]
1203
1250
 
1204
- ${heading("Options")}:
1251
+ ${import_picocolors9.default.underline("Options")}:
1205
1252
  --help, -h Print this help message and exit
1206
1253
  --version, -v Print the CLI version and exit
1207
1254
  --no-color Disable ANSI colors in console output
@@ -1234,23 +1281,26 @@ ${logoBlue("react-router")}
1234
1281
  \`reveal\` Options:
1235
1282
  --config, -c Use specified Vite config file (string)
1236
1283
  --no-typescript Generate plain JavaScript files
1284
+ \`typegen\` Options:
1285
+ --config, -c Use specified Vite config file (string)
1286
+ --watch Automatically regenerate types whenever route config (\`routes.ts\`) or route modules change
1237
1287
 
1238
- ${heading("Build your project")}:
1288
+ ${import_picocolors9.default.underline("Build your project")}:
1239
1289
 
1240
1290
  $ react-router build
1241
1291
 
1242
- ${heading("Run your project locally in development")}:
1292
+ ${import_picocolors9.default.underline("Run your project locally in development")}:
1243
1293
 
1244
1294
  $ react-router dev
1245
1295
 
1246
- ${heading("Show all routes in your app")}:
1296
+ ${import_picocolors9.default.underline("Show all routes in your app")}:
1247
1297
 
1248
1298
  $ react-router routes
1249
1299
  $ react-router routes my-app
1250
1300
  $ react-router routes --json
1251
1301
  $ react-router routes --config vite.react-router.config.ts
1252
1302
 
1253
- ${heading("Reveal the used entry point")}:
1303
+ ${import_picocolors9.default.underline("Reveal the used entry point")}:
1254
1304
 
1255
1305
  $ react-router reveal entry.client
1256
1306
  $ react-router reveal entry.server
@@ -1258,9 +1308,11 @@ ${logoBlue("react-router")}
1258
1308
  $ react-router reveal entry.server --no-typescript
1259
1309
  $ react-router reveal entry.server --config vite.react-router.config.ts
1260
1310
 
1261
- ${heading("Generate types for route modules")}:
1311
+ ${import_picocolors9.default.underline("Generate types for route modules")}:
1262
1312
 
1263
1313
  $ react-router typegen
1314
+ $ react-router typegen --watch
1315
+ $ react-router typegen --config vite.react-router.config.ts
1264
1316
  `;
1265
1317
  async function run(argv = process.argv.slice(2)) {
1266
1318
  let versions = process.versions;
@@ -1270,8 +1322,8 @@ async function run(argv = process.argv.slice(2)) {
1270
1322
  `\uFE0F\u{1F6A8} Oops, Node v${versions.node} detected. react-router requires a Node version greater than ${MINIMUM_NODE_VERSION}.`
1271
1323
  );
1272
1324
  }
1273
- let isBooleanFlag = (arg3) => {
1274
- let index = argv.indexOf(arg3);
1325
+ let isBooleanFlag = (arg2) => {
1326
+ let index = argv.indexOf(arg2);
1275
1327
  let nextArg = argv[index + 1];
1276
1328
  return !nextArg || nextArg.startsWith("-");
1277
1329
  };
@@ -1304,7 +1356,8 @@ async function run(argv = process.argv.slice(2)) {
1304
1356
  "--strictPort": Boolean,
1305
1357
  "--profile": Boolean,
1306
1358
  "--sourcemapClient": isBooleanFlag("--sourcemapClient") ? Boolean : String,
1307
- "--sourcemapServer": isBooleanFlag("--sourcemapServer") ? Boolean : String
1359
+ "--sourcemapServer": isBooleanFlag("--sourcemapServer") ? Boolean : String,
1360
+ "--watch": Boolean
1308
1361
  },
1309
1362
  {
1310
1363
  argv
@@ -1321,7 +1374,7 @@ async function run(argv = process.argv.slice(2)) {
1321
1374
  return;
1322
1375
  }
1323
1376
  if (flags.version) {
1324
- let version = require_package().version;
1377
+ let version = require("../package.json").version;
1325
1378
  console.log(version);
1326
1379
  return;
1327
1380
  }
@@ -1345,7 +1398,7 @@ async function run(argv = process.argv.slice(2)) {
1345
1398
  await dev2(input[1], flags);
1346
1399
  break;
1347
1400
  case "typegen":
1348
- await typegen(input[1]);
1401
+ await typegen(input[1], flags);
1349
1402
  break;
1350
1403
  default:
1351
1404
  await dev2(input[0], flags);