@react-router/dev 0.0.0-experimental-e988dc602 → 0.0.0-experimental-00e730ed0

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,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v0.0.0-experimental-e988dc602
3
+ * @react-router/dev v0.0.0-experimental-00e730ed0
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -125,13 +125,15 @@ var init_ssr_externals = __esm({
125
125
  // vite/vite-node.ts
126
126
  async function createContext({
127
127
  root,
128
- mode
128
+ mode,
129
+ customLogger
129
130
  }) {
130
131
  await preloadVite();
131
132
  const vite2 = getVite();
132
133
  const devServer = await vite2.createServer({
133
134
  root,
134
135
  mode,
136
+ customLogger,
135
137
  server: {
136
138
  preTransformRequests: false,
137
139
  hmr: false,
@@ -143,6 +145,15 @@ async function createContext({
143
145
  optimizeDeps: {
144
146
  noDiscovery: true
145
147
  },
148
+ css: {
149
+ // This empty PostCSS config object prevents the PostCSS config file from
150
+ // being loaded. We don't need it in a React Router config context, and
151
+ // there's also an issue in Vite 5 when using a .ts PostCSS config file in
152
+ // an ESM project: https://github.com/vitejs/vite/issues/15869. Consumers
153
+ // can work around this in their own Vite config file, but they can't
154
+ // configure this internal usage of vite-node.
155
+ postcss: {}
156
+ },
146
157
  configFile: false,
147
158
  envFile: false,
148
159
  plugins: []
@@ -205,7 +216,7 @@ function validateRouteConfig({
205
216
  `Route config in "${routeConfigFile}" is invalid.`,
206
217
  root ? `${root}` : [],
207
218
  nested ? Object.entries(nested).map(
208
- ([path9, message]) => `Path: routes.${path9}
219
+ ([path8, message]) => `Path: routes.${path8}
209
220
  ${message}`
210
221
  ) : []
211
222
  ].flat().join("\n\n")
@@ -290,7 +301,8 @@ function err(error) {
290
301
  async function resolveConfig({
291
302
  root,
292
303
  viteNodeContext,
293
- reactRouterConfigFile
304
+ reactRouterConfigFile,
305
+ skipRoutes
294
306
  }) {
295
307
  let reactRouterUserConfig = {};
296
308
  if (reactRouterConfigFile) {
@@ -339,12 +351,17 @@ async function resolveConfig({
339
351
  serverModuleFormat: "esm",
340
352
  ssr: true
341
353
  };
354
+ let userAndPresetConfigs = mergeReactRouterConfig(
355
+ ...presets,
356
+ reactRouterUserConfig
357
+ );
342
358
  let {
343
359
  appDirectory: userAppDirectory,
344
- basename: basename2,
360
+ basename: basename3,
345
361
  buildDirectory: userBuildDirectory,
346
362
  buildEnd,
347
363
  prerender,
364
+ routeDiscovery: userRouteDiscovery,
348
365
  serverBuildFile,
349
366
  serverBundles,
350
367
  serverModuleFormat,
@@ -352,7 +369,7 @@ async function resolveConfig({
352
369
  } = {
353
370
  ...defaults,
354
371
  // Default values should be completely overridden by user/preset config, not merged
355
- ...mergeReactRouterConfig(...presets, reactRouterUserConfig)
372
+ ...userAndPresetConfigs
356
373
  };
357
374
  if (!ssr && serverBundles) {
358
375
  serverBundles = void 0;
@@ -363,6 +380,32 @@ async function resolveConfig({
363
380
  "The `prerender` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths"
364
381
  );
365
382
  }
383
+ let routeDiscovery;
384
+ if (userRouteDiscovery == null) {
385
+ if (ssr) {
386
+ routeDiscovery = {
387
+ mode: "lazy",
388
+ manifestPath: "/__manifest"
389
+ };
390
+ } else {
391
+ routeDiscovery = { mode: "initial" };
392
+ }
393
+ } else if (userRouteDiscovery.mode === "initial") {
394
+ routeDiscovery = userRouteDiscovery;
395
+ } else if (userRouteDiscovery.mode === "lazy") {
396
+ if (!ssr) {
397
+ return err(
398
+ 'The `routeDiscovery.mode` config cannot be set to "lazy" when setting `ssr:false`'
399
+ );
400
+ }
401
+ let { manifestPath } = userRouteDiscovery;
402
+ if (manifestPath != null && !manifestPath.startsWith("/")) {
403
+ return err(
404
+ 'The `routeDiscovery.manifestPath` config must be a root-relative pathname beginning with a slash (i.e., "/__manifest")'
405
+ );
406
+ }
407
+ routeDiscovery = userRouteDiscovery;
408
+ }
366
409
  let appDirectory = import_pathe3.default.resolve(root, userAppDirectory || "app");
367
410
  let buildDirectory = import_pathe3.default.resolve(root, userBuildDirectory);
368
411
  let rootRouteFile = findEntry(appDirectory, "root");
@@ -375,45 +418,50 @@ async function resolveConfig({
375
418
  `Could not find a root route module in the app directory as "${rootRouteDisplayPath}"`
376
419
  );
377
420
  }
378
- let routes2 = {
379
- root: { path: "", id: "root", file: rootRouteFile }
380
- };
381
- let routeConfigFile = findEntry(appDirectory, "routes");
382
- try {
383
- if (!routeConfigFile) {
384
- let routeConfigDisplayPath = import_pathe3.default.relative(
385
- root,
386
- import_pathe3.default.join(appDirectory, "routes.ts")
387
- );
388
- return err(`Route config file not found at "${routeConfigDisplayPath}".`);
389
- }
390
- setAppDirectory(appDirectory);
391
- let routeConfigExport = (await viteNodeContext.runner.executeFile(
392
- import_pathe3.default.join(appDirectory, routeConfigFile)
393
- )).default;
394
- let routeConfig = await routeConfigExport;
395
- let result = validateRouteConfig({
396
- routeConfigFile,
397
- routeConfig
398
- });
399
- if (!result.valid) {
400
- return err(result.message);
401
- }
421
+ let routes2 = {};
422
+ if (!skipRoutes) {
402
423
  routes2 = {
403
- ...routes2,
404
- ...configRoutesToRouteManifest(appDirectory, routeConfig)
424
+ root: { path: "", id: "root", file: rootRouteFile }
405
425
  };
406
- } catch (error) {
407
- return err(
408
- [
409
- import_picocolors.default.red(`Route config in "${routeConfigFile}" is invalid.`),
410
- "",
411
- error.loc?.file && error.loc?.column && error.frame ? [
412
- import_pathe3.default.relative(appDirectory, error.loc.file) + ":" + error.loc.line + ":" + error.loc.column,
413
- error.frame.trim?.()
414
- ] : error.stack
415
- ].flat().join("\n")
416
- );
426
+ let routeConfigFile = findEntry(appDirectory, "routes");
427
+ try {
428
+ if (!routeConfigFile) {
429
+ let routeConfigDisplayPath = import_pathe3.default.relative(
430
+ root,
431
+ import_pathe3.default.join(appDirectory, "routes.ts")
432
+ );
433
+ return err(
434
+ `Route config file not found at "${routeConfigDisplayPath}".`
435
+ );
436
+ }
437
+ setAppDirectory(appDirectory);
438
+ let routeConfigExport = (await viteNodeContext.runner.executeFile(
439
+ import_pathe3.default.join(appDirectory, routeConfigFile)
440
+ )).default;
441
+ let routeConfig = await routeConfigExport;
442
+ let result = validateRouteConfig({
443
+ routeConfigFile,
444
+ routeConfig
445
+ });
446
+ if (!result.valid) {
447
+ return err(result.message);
448
+ }
449
+ routes2 = {
450
+ ...routes2,
451
+ ...configRoutesToRouteManifest(appDirectory, routeConfig)
452
+ };
453
+ } catch (error) {
454
+ return err(
455
+ [
456
+ import_picocolors.default.red(`Route config in "${routeConfigFile}" is invalid.`),
457
+ "",
458
+ error.loc?.file && error.loc?.column && error.frame ? [
459
+ import_pathe3.default.relative(appDirectory, error.loc.file) + ":" + error.loc.line + ":" + error.loc.column,
460
+ error.frame.trim?.()
461
+ ] : error.stack
462
+ ].flat().join("\n")
463
+ );
464
+ }
417
465
  }
418
466
  let future = {
419
467
  unstable_middleware: reactRouterUserConfig.future?.unstable_middleware ?? false,
@@ -424,12 +472,13 @@ async function resolveConfig({
424
472
  };
425
473
  let reactRouterConfig = deepFreeze({
426
474
  appDirectory,
427
- basename: basename2,
475
+ basename: basename3,
428
476
  buildDirectory,
429
477
  buildEnd,
430
478
  future,
431
479
  prerender,
432
480
  routes: routes2,
481
+ routeDiscovery,
433
482
  serverBuildFile,
434
483
  serverBundles,
435
484
  serverModuleFormat,
@@ -442,24 +491,35 @@ async function resolveConfig({
442
491
  }
443
492
  async function createConfigLoader({
444
493
  rootDirectory: root,
445
- watch: watch2
494
+ watch: watch2,
495
+ mode,
496
+ skipRoutes
446
497
  }) {
447
- root = root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
498
+ root = import_pathe3.default.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
499
+ let vite2 = await import("vite");
448
500
  let viteNodeContext = await createContext({
449
501
  root,
450
- mode: watch2 ? "development" : "production"
451
- });
452
- let reactRouterConfigFile = findEntry(root, "react-router.config", {
453
- absolute: true
502
+ mode,
503
+ // Filter out any info level logs from vite-node
504
+ customLogger: vite2.createLogger("warn", {
505
+ prefix: "[react-router]"
506
+ })
454
507
  });
455
- let getConfig = () => resolveConfig({ root, viteNodeContext, reactRouterConfigFile });
508
+ let reactRouterConfigFile;
509
+ let updateReactRouterConfigFile = () => {
510
+ reactRouterConfigFile = findEntry(root, "react-router.config", {
511
+ absolute: true
512
+ });
513
+ };
514
+ updateReactRouterConfigFile();
515
+ let getConfig = () => resolveConfig({ root, viteNodeContext, reactRouterConfigFile, skipRoutes });
456
516
  let appDirectory;
457
517
  let initialConfigResult = await getConfig();
458
518
  if (!initialConfigResult.ok) {
459
519
  throw new Error(initialConfigResult.error);
460
520
  }
461
- appDirectory = initialConfigResult.value.appDirectory;
462
- let lastConfig = initialConfigResult.value;
521
+ appDirectory = import_pathe3.default.normalize(initialConfigResult.value.appDirectory);
522
+ let currentConfig = initialConfigResult.value;
463
523
  let fsWatcher;
464
524
  let changeHandlers = [];
465
525
  return {
@@ -472,41 +532,71 @@ async function createConfigLoader({
472
532
  }
473
533
  changeHandlers.push(handler);
474
534
  if (!fsWatcher) {
475
- fsWatcher = import_chokidar.default.watch(
476
- [
477
- ...reactRouterConfigFile ? [reactRouterConfigFile] : [],
478
- appDirectory
479
- ],
480
- { ignoreInitial: true }
481
- );
535
+ fsWatcher = import_chokidar.default.watch([root, appDirectory], {
536
+ ignoreInitial: true,
537
+ ignored: (path8) => {
538
+ let dirname5 = import_pathe3.default.dirname(path8);
539
+ return !dirname5.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
540
+ // that are at the root level, not nested in subdirectories
541
+ path8 !== root && // Watch the root directory itself
542
+ dirname5 !== root;
543
+ }
544
+ });
482
545
  fsWatcher.on("all", async (...args) => {
483
546
  let [event, rawFilepath] = args;
484
547
  let filepath = import_pathe3.default.normalize(rawFilepath);
485
- let appFileAddedOrRemoved = appDirectory && (event === "add" || event === "unlink") && filepath.startsWith(import_pathe3.default.normalize(appDirectory));
486
- let configCodeUpdated = Boolean(
548
+ let fileAddedOrRemoved = event === "add" || event === "unlink";
549
+ let appFileAddedOrRemoved = fileAddedOrRemoved && filepath.startsWith(import_pathe3.default.normalize(appDirectory));
550
+ let rootRelativeFilepath = import_pathe3.default.relative(root, filepath);
551
+ let configFileAddedOrRemoved = fileAddedOrRemoved && isEntryFile("react-router.config", rootRelativeFilepath);
552
+ if (configFileAddedOrRemoved) {
553
+ updateReactRouterConfigFile();
554
+ }
555
+ let moduleGraphChanged = configFileAddedOrRemoved || Boolean(
487
556
  viteNodeContext.devServer?.moduleGraph.getModuleById(filepath)
488
557
  );
489
- if (configCodeUpdated || appFileAddedOrRemoved) {
490
- viteNodeContext.devServer?.moduleGraph.invalidateAll();
491
- viteNodeContext.runner?.moduleCache.clear();
558
+ if (!moduleGraphChanged && !appFileAddedOrRemoved) {
559
+ return;
492
560
  }
493
- if (appFileAddedOrRemoved || configCodeUpdated) {
494
- let result = await getConfig();
495
- let configChanged = result.ok && !(0, import_isEqual.default)(lastConfig, result.value);
496
- let routeConfigChanged = result.ok && !(0, import_isEqual.default)(lastConfig?.routes, result.value.routes);
497
- for (let handler2 of changeHandlers) {
498
- handler2({
499
- result,
500
- configCodeUpdated,
501
- configChanged,
502
- routeConfigChanged,
503
- path: filepath,
504
- event
505
- });
506
- }
507
- if (result.ok) {
508
- lastConfig = result.value;
509
- }
561
+ viteNodeContext.devServer?.moduleGraph.invalidateAll();
562
+ viteNodeContext.runner?.moduleCache.clear();
563
+ let result = await getConfig();
564
+ let prevAppDirectory = appDirectory;
565
+ appDirectory = import_pathe3.default.normalize(
566
+ (result.value ?? currentConfig).appDirectory
567
+ );
568
+ if (appDirectory !== prevAppDirectory) {
569
+ fsWatcher.unwatch(prevAppDirectory);
570
+ fsWatcher.add(appDirectory);
571
+ }
572
+ let configCodeChanged = configFileAddedOrRemoved || reactRouterConfigFile !== void 0 && isEntryFileDependency(
573
+ viteNodeContext.devServer.moduleGraph,
574
+ reactRouterConfigFile,
575
+ filepath
576
+ );
577
+ let routeConfigFile = !skipRoutes ? findEntry(appDirectory, "routes", {
578
+ absolute: true
579
+ }) : void 0;
580
+ let routeConfigCodeChanged = routeConfigFile !== void 0 && isEntryFileDependency(
581
+ viteNodeContext.devServer.moduleGraph,
582
+ routeConfigFile,
583
+ filepath
584
+ );
585
+ let configChanged = result.ok && !(0, import_isEqual.default)(omitRoutes(currentConfig), omitRoutes(result.value));
586
+ let routeConfigChanged = result.ok && !(0, import_isEqual.default)(currentConfig?.routes, result.value.routes);
587
+ for (let handler2 of changeHandlers) {
588
+ handler2({
589
+ result,
590
+ configCodeChanged,
591
+ routeConfigCodeChanged,
592
+ configChanged,
593
+ routeConfigChanged,
594
+ path: filepath,
595
+ event
596
+ });
597
+ }
598
+ if (result.ok) {
599
+ currentConfig = result.value;
510
600
  }
511
601
  });
512
602
  }
@@ -523,23 +613,73 @@ async function createConfigLoader({
523
613
  }
524
614
  };
525
615
  }
526
- async function loadConfig({ rootDirectory }) {
616
+ async function loadConfig({
617
+ rootDirectory,
618
+ mode,
619
+ skipRoutes
620
+ }) {
527
621
  let configLoader = await createConfigLoader({
528
622
  rootDirectory,
623
+ mode,
624
+ skipRoutes,
529
625
  watch: false
530
626
  });
531
627
  let config = await configLoader.getConfig();
532
628
  await configLoader.close();
533
629
  return config;
534
630
  }
535
- function findEntry(dir, basename2, options) {
536
- for (let ext of entryExts) {
537
- let file = import_pathe3.default.resolve(dir, basename2 + ext);
538
- if (import_node_fs.default.existsSync(file)) {
539
- return options?.absolute ?? false ? file : import_pathe3.default.relative(dir, file);
631
+ function omitRoutes(config) {
632
+ return {
633
+ ...config,
634
+ routes: {}
635
+ };
636
+ }
637
+ function isEntryFile(entryBasename, filename2) {
638
+ return entryExts.some((ext) => filename2 === `${entryBasename}${ext}`);
639
+ }
640
+ function findEntry(dir, basename3, options) {
641
+ let currentDir = import_pathe3.default.resolve(dir);
642
+ let { root } = import_pathe3.default.parse(currentDir);
643
+ while (true) {
644
+ for (let ext of options?.extensions ?? entryExts) {
645
+ let file = import_pathe3.default.resolve(currentDir, basename3 + ext);
646
+ if (import_node_fs.default.existsSync(file)) {
647
+ return options?.absolute ?? false ? file : import_pathe3.default.relative(dir, file);
648
+ }
540
649
  }
650
+ if (!options?.walkParents) {
651
+ return void 0;
652
+ }
653
+ let parentDir = import_pathe3.default.dirname(currentDir);
654
+ if (currentDir === root || parentDir === currentDir) {
655
+ return void 0;
656
+ }
657
+ currentDir = parentDir;
541
658
  }
542
- return void 0;
659
+ }
660
+ function isEntryFileDependency(moduleGraph, entryFilepath, filepath, visited = /* @__PURE__ */ new Set()) {
661
+ entryFilepath = import_pathe3.default.normalize(entryFilepath);
662
+ filepath = import_pathe3.default.normalize(filepath);
663
+ if (visited.has(filepath)) {
664
+ return false;
665
+ }
666
+ visited.add(filepath);
667
+ if (filepath === entryFilepath) {
668
+ return true;
669
+ }
670
+ let mod = moduleGraph.getModuleById(filepath);
671
+ if (!mod) {
672
+ return false;
673
+ }
674
+ for (let importer of mod.importers) {
675
+ if (!importer.id) {
676
+ continue;
677
+ }
678
+ if (importer.id === entryFilepath || isEntryFileDependency(moduleGraph, entryFilepath, importer.id, visited)) {
679
+ return true;
680
+ }
681
+ }
682
+ return false;
543
683
  }
544
684
  var import_node_fs, import_node_child_process, import_package_json, import_pathe3, import_chokidar, import_picocolors, import_pick2, import_omit, import_cloneDeep, import_isEqual, excludedConfigPresetKeys, mergeReactRouterConfig, deepFreeze, entryExts;
545
685
  var init_config = __esm({
@@ -640,6 +780,31 @@ var init_profiler = __esm({
640
780
  }
641
781
  });
642
782
 
783
+ // typegen/context.ts
784
+ async function createContext2({
785
+ rootDirectory,
786
+ watch: watch2,
787
+ mode
788
+ }) {
789
+ const configLoader = await createConfigLoader({ rootDirectory, mode, watch: watch2 });
790
+ const configResult = await configLoader.getConfig();
791
+ if (!configResult.ok) {
792
+ throw new Error(configResult.error);
793
+ }
794
+ const config = configResult.value;
795
+ return {
796
+ configLoader,
797
+ rootDirectory,
798
+ config
799
+ };
800
+ }
801
+ var init_context = __esm({
802
+ "typegen/context.ts"() {
803
+ "use strict";
804
+ init_config();
805
+ }
806
+ });
807
+
643
808
  // vite/babel.ts
644
809
  var babel_exports = {};
645
810
  __export(babel_exports, {
@@ -659,27 +824,6 @@ var init_babel = __esm({
659
824
  }
660
825
  });
661
826
 
662
- // typegen/paths.ts
663
- function getTypesDir(ctx) {
664
- return Path2.join(ctx.rootDirectory, ".react-router/types");
665
- }
666
- function getTypesPath(ctx, route) {
667
- return Path2.join(
668
- getTypesDir(ctx),
669
- Path2.relative(ctx.rootDirectory, ctx.config.appDirectory),
670
- Path2.dirname(route.file),
671
- "+types/" + Pathe.filename(route.file) + ".ts"
672
- );
673
- }
674
- var Path2, Pathe;
675
- var init_paths = __esm({
676
- "typegen/paths.ts"() {
677
- "use strict";
678
- Path2 = __toESM(require("pathe"));
679
- Pathe = __toESM(require("pathe/utils"));
680
- }
681
- });
682
-
683
827
  // typegen/params.ts
684
828
  function parse2(fullpath2) {
685
829
  const result = {};
@@ -715,7 +859,7 @@ function lineage(routes2, route) {
715
859
  }
716
860
  function fullpath(lineage2) {
717
861
  if (lineage2.length === 1 && lineage2[0].id === "root") return "/";
718
- return "/" + lineage2.map((route) => route.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path9) => path9 !== void 0 && path9 !== "").join("/");
862
+ return "/" + lineage2.map((route) => route.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path8) => path8 !== void 0 && path8 !== "").join("/");
719
863
  }
720
864
  var init_route = __esm({
721
865
  "typegen/route.ts"() {
@@ -724,220 +868,358 @@ var init_route = __esm({
724
868
  });
725
869
 
726
870
  // typegen/generate.ts
727
- function generate2(ctx, route) {
871
+ function typesDirectory(ctx) {
872
+ return Path3.join(ctx.rootDirectory, ".react-router/types");
873
+ }
874
+ function generateFuture(ctx) {
875
+ const filename2 = Path3.join(typesDirectory(ctx), "+future.ts");
876
+ const content = import_dedent.default`
877
+ // Generated by React Router
878
+
879
+ import "react-router";
880
+
881
+ declare module "react-router" {
882
+ interface Future {
883
+ unstable_middleware: ${ctx.config.future.unstable_middleware}
884
+ }
885
+ }
886
+ `;
887
+ return { filename: filename2, content };
888
+ }
889
+ function generateServerBuild(ctx) {
890
+ const filename2 = Path3.join(typesDirectory(ctx), "+server-build.d.ts");
891
+ const content = import_dedent.default`
892
+ // Generated by React Router
893
+
894
+ declare module "virtual:react-router/server-build" {
895
+ import { ServerBuild } from "react-router";
896
+ export const assets: ServerBuild["assets"];
897
+ export const assetsBuildDirectory: ServerBuild["assetsBuildDirectory"];
898
+ export const basename: ServerBuild["basename"];
899
+ export const entry: ServerBuild["entry"];
900
+ export const future: ServerBuild["future"];
901
+ export const isSpaMode: ServerBuild["isSpaMode"];
902
+ export const prerender: ServerBuild["prerender"];
903
+ export const publicPath: ServerBuild["publicPath"];
904
+ export const routeDiscovery: ServerBuild["routeDiscovery"];
905
+ export const routes: ServerBuild["routes"];
906
+ export const ssr: ServerBuild["ssr"];
907
+ export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
908
+ }
909
+ `;
910
+ return { filename: filename2, content };
911
+ }
912
+ function generatePages(ctx) {
913
+ const filename2 = Path3.join(typesDirectory(ctx), "+pages.ts");
914
+ const fullpaths = /* @__PURE__ */ new Set();
915
+ Object.values(ctx.config.routes).forEach((route) => {
916
+ if (route.id !== "root" && !route.path) return;
917
+ const lineage2 = lineage(ctx.config.routes, route);
918
+ const fullpath2 = fullpath(lineage2);
919
+ fullpaths.add(fullpath2);
920
+ });
921
+ const pagesType = t2.tsTypeAliasDeclaration(
922
+ t2.identifier("Pages"),
923
+ null,
924
+ t2.tsTypeLiteral(
925
+ Array.from(fullpaths).map((fullpath2) => {
926
+ return t2.tsPropertySignature(
927
+ t2.stringLiteral(fullpath2),
928
+ t2.tsTypeAnnotation(
929
+ t2.tsTypeLiteral([
930
+ t2.tsPropertySignature(
931
+ t2.identifier("params"),
932
+ t2.tsTypeAnnotation(paramsType(fullpath2))
933
+ )
934
+ ])
935
+ )
936
+ );
937
+ })
938
+ )
939
+ );
940
+ const content = import_dedent.default`
941
+ // Generated by React Router
942
+
943
+ import "react-router"
944
+
945
+ declare module "react-router" {
946
+ interface Register {
947
+ pages: Pages
948
+ }
949
+ }
950
+ ` + "\n\n" + generate(pagesType).code;
951
+ return { filename: filename2, content };
952
+ }
953
+ function generateRoutes(ctx) {
954
+ const filename2 = Path3.join(typesDirectory(ctx), "+routes-pre.ts");
955
+ const routesType = t2.tsTypeAliasDeclaration(
956
+ t2.identifier("routesPre"),
957
+ null,
958
+ t2.tsTypeLiteral(
959
+ Object.values(ctx.config.routes).map((route) => {
960
+ return t2.tsPropertySignature(
961
+ t2.stringLiteral(route.id),
962
+ t2.tsTypeAnnotation(
963
+ t2.tsTypeLiteral([
964
+ t2.tsPropertySignature(
965
+ t2.identifier("parentId"),
966
+ t2.tsTypeAnnotation(
967
+ route.parentId ? t2.tsLiteralType(t2.stringLiteral(route.parentId)) : t2.tsUndefinedKeyword()
968
+ )
969
+ ),
970
+ t2.tsPropertySignature(
971
+ t2.identifier("path"),
972
+ t2.tsTypeAnnotation(
973
+ route.path ? t2.tsLiteralType(t2.stringLiteral(route.path)) : t2.tsUndefinedKeyword()
974
+ )
975
+ ),
976
+ t2.tsPropertySignature(
977
+ t2.identifier("params"),
978
+ t2.tsTypeAnnotation(paramsType(route.path ?? ""))
979
+ ),
980
+ t2.tsPropertySignature(
981
+ t2.identifier("index"),
982
+ t2.tsTypeAnnotation(
983
+ t2.tsLiteralType(t2.booleanLiteral(route.index ?? false))
984
+ )
985
+ ),
986
+ t2.tsPropertySignature(
987
+ t2.identifier("file"),
988
+ t2.tsTypeAnnotation(t2.tsLiteralType(t2.stringLiteral(route.file)))
989
+ )
990
+ ])
991
+ )
992
+ );
993
+ })
994
+ )
995
+ );
996
+ const content = import_dedent.default`
997
+ // Generated by React Router
998
+
999
+ import "react-router"
1000
+
1001
+ declare module "react-router" {
1002
+ interface Register {
1003
+ routesPre: routesPre
1004
+ }
1005
+ }
1006
+ ` + "\n\n" + generate(routesType).code;
1007
+ return { filename: filename2, content };
1008
+ }
1009
+ function generateRouteModuleAnnotations(ctx) {
1010
+ return Object.values(ctx.config.routes).filter((route) => isRouteInAppDirectory(ctx, route)).map((route) => {
1011
+ const filename2 = getRouteModuleAnnotationsFilepath(ctx, route);
1012
+ const parents = getParents(ctx, route);
1013
+ const content = import_dedent.default`
1014
+ // Generated by React Router
1015
+
1016
+ import type {
1017
+ Params,
1018
+ RouteModuleAnnotations,
1019
+ CreateLoaderData,
1020
+ CreateActionData,
1021
+ } from "react-router/internal";
1022
+
1023
+ ${parents.map((parent) => parent.import).join("\n" + " ".repeat(3))}
1024
+ type Parents = [${parents.map((parent) => parent.name).join(", ")}]
1025
+
1026
+ type Id = "${route.id}"
1027
+ type Module = typeof import("../${Pathe.filename(route.file)}.js")
1028
+
1029
+ export type unstable_Props = {
1030
+ params: Params[Id]
1031
+ loaderData: CreateLoaderData<Module>
1032
+ actionData: CreateActionData<Module>
1033
+ }
1034
+
1035
+ type Annotations = RouteModuleAnnotations<unstable_Props & {
1036
+ parents: Parents,
1037
+ module: Module,
1038
+ }>;
1039
+
1040
+ export namespace Route {
1041
+ // links
1042
+ export type LinkDescriptors = Annotations["LinkDescriptors"];
1043
+ export type LinksFunction = Annotations["LinksFunction"];
1044
+
1045
+ // meta
1046
+ export type MetaArgs = Annotations["MetaArgs"];
1047
+ export type MetaDescriptors = Annotations["MetaDescriptors"];
1048
+ export type MetaFunction = Annotations["MetaFunction"];
1049
+
1050
+ // headers
1051
+ export type HeadersArgs = Annotations["HeadersArgs"];
1052
+ export type HeadersFunction = Annotations["HeadersFunction"];
1053
+
1054
+ // unstable_middleware
1055
+ export type unstable_MiddlewareFunction = Annotations["unstable_MiddlewareFunction"];
1056
+
1057
+ // unstable_clientMiddleware
1058
+ export type unstable_ClientMiddlewareFunction = Annotations["unstable_ClientMiddlewareFunction"];
1059
+
1060
+ // loader
1061
+ export type LoaderArgs = Annotations["LoaderArgs"];
1062
+
1063
+ // clientLoader
1064
+ export type ClientLoaderArgs = Annotations["ClientLoaderArgs"];
1065
+
1066
+ // action
1067
+ export type ActionArgs = Annotations["ActionArgs"];
1068
+
1069
+ // clientAction
1070
+ export type ClientActionArgs = Annotations["ClientActionArgs"];
1071
+
1072
+ // HydrateFallback
1073
+ export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
1074
+
1075
+ // Component
1076
+ export type ComponentProps = Annotations["ComponentProps"];
1077
+
1078
+ // ErrorBoundary
1079
+ export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"];
1080
+ }
1081
+ `;
1082
+ return { filename: filename2, content };
1083
+ });
1084
+ }
1085
+ function isRouteInAppDirectory(ctx, route) {
1086
+ const absoluteRoutePath = Path3.resolve(ctx.config.appDirectory, route.file);
1087
+ return absoluteRoutePath.startsWith(ctx.config.appDirectory);
1088
+ }
1089
+ function getRouteModuleAnnotationsFilepath(ctx, route) {
1090
+ return Path3.join(
1091
+ typesDirectory(ctx),
1092
+ Path3.relative(ctx.rootDirectory, ctx.config.appDirectory),
1093
+ Path3.dirname(route.file),
1094
+ "+types/" + Pathe.filename(route.file) + ".ts"
1095
+ );
1096
+ }
1097
+ function getParents(ctx, route) {
1098
+ const typesPath = getRouteModuleAnnotationsFilepath(ctx, route);
728
1099
  const lineage2 = lineage(ctx.config.routes, route);
729
- const fullpath2 = fullpath(lineage2);
730
- const typesPath = getTypesPath(ctx, route);
731
1100
  const parents = lineage2.slice(0, -1);
732
- const parentTypeImports = parents.map((parent, i) => {
1101
+ return parents.map((parent, i) => {
733
1102
  const rel = Path3.relative(
734
1103
  Path3.dirname(typesPath),
735
- getTypesPath(ctx, parent)
1104
+ getRouteModuleAnnotationsFilepath(ctx, parent)
736
1105
  );
737
- const indent = i === 0 ? "" : " ".repeat(2);
738
1106
  let source = noExtension(rel);
739
1107
  if (!source.startsWith("../")) source = "./" + source;
740
- return `${indent}import type { Info as Parent${i} } from "${source}.js"`;
741
- }).join("\n");
742
- return import_dedent.default`
743
- // React Router generated types for route:
744
- // ${route.file}
745
-
746
- import type * as T from "react-router/route-module"
747
-
748
- ${parentTypeImports}
749
-
750
- type Module = typeof import("../${Pathe2.filename(route.file)}.js")
751
-
752
- export type Info = {
753
- parents: [${parents.map((_, i) => `Parent${i}`).join(", ")}],
754
- id: "${route.id}"
755
- file: "${route.file}"
756
- path: "${route.path}"
757
- params: {${formatParamProperties(
758
- fullpath2
759
- )}} & { [key: string]: string | undefined }
760
- module: Module
761
- loaderData: T.CreateLoaderData<Module>
762
- actionData: T.CreateActionData<Module>
763
- }
764
-
765
- export namespace Route {
766
- export type LinkDescriptors = T.LinkDescriptors
767
- export type LinksFunction = () => LinkDescriptors
768
-
769
- export type MetaArgs = T.CreateMetaArgs<Info>
770
- export type MetaDescriptors = T.MetaDescriptors
771
- export type MetaFunction = (args: MetaArgs) => MetaDescriptors
772
-
773
- export type HeadersArgs = T.HeadersArgs
774
- export type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit
775
-
776
- export type unstable_MiddlewareFunction = T.CreateServerMiddlewareFunction<Info>
777
- export type unstable_ClientMiddlewareFunction = T.CreateClientMiddlewareFunction<Info>
778
- export type LoaderArgs = T.CreateServerLoaderArgs<Info>
779
- export type ClientLoaderArgs = T.CreateClientLoaderArgs<Info>
780
- export type ActionArgs = T.CreateServerActionArgs<Info>
781
- export type ClientActionArgs = T.CreateClientActionArgs<Info>
782
-
783
- export type HydrateFallbackProps = T.CreateHydrateFallbackProps<Info>
784
- export type ComponentProps = T.CreateComponentProps<Info>
785
- export type ErrorBoundaryProps = T.CreateErrorBoundaryProps<Info>
786
- }
787
- `;
1108
+ const name = `Parent${i}`;
1109
+ return {
1110
+ name,
1111
+ import: `import type { unstable_Props as ${name} } from "${source}.js"`
1112
+ };
1113
+ });
788
1114
  }
789
- function formatParamProperties(fullpath2) {
790
- const params = parse2(fullpath2);
791
- const properties = Object.entries(params).map(
792
- ([name, isRequired]) => isRequired ? `"${name}": string` : `"${name}"?: string`
1115
+ function noExtension(path8) {
1116
+ return Path3.join(Path3.dirname(path8), Pathe.filename(path8));
1117
+ }
1118
+ function paramsType(path8) {
1119
+ const params = parse2(path8);
1120
+ return t2.tsTypeLiteral(
1121
+ Object.entries(params).map(([param, isRequired]) => {
1122
+ const property = t2.tsPropertySignature(
1123
+ t2.stringLiteral(param),
1124
+ t2.tsTypeAnnotation(t2.tsStringKeyword())
1125
+ );
1126
+ property.optional = !isRequired;
1127
+ return property;
1128
+ })
793
1129
  );
794
- return properties.join("; ");
795
1130
  }
796
- var import_dedent, Path3, Pathe2, noExtension;
1131
+ var import_dedent, Path3, Pathe, t2;
797
1132
  var init_generate = __esm({
798
1133
  "typegen/generate.ts"() {
799
1134
  "use strict";
800
1135
  import_dedent = __toESM(require("dedent"));
801
1136
  Path3 = __toESM(require("pathe"));
802
- Pathe2 = __toESM(require("pathe/utils"));
803
- init_paths();
1137
+ Pathe = __toESM(require("pathe/utils"));
1138
+ init_babel();
804
1139
  init_params();
805
1140
  init_route();
806
- noExtension = (path9) => Path3.join(Path3.dirname(path9), Pathe2.filename(path9));
1141
+ ({ t: t2 } = babel_exports);
807
1142
  }
808
1143
  });
809
1144
 
810
1145
  // typegen/index.ts
811
- async function run(rootDirectory) {
812
- const ctx = await createContext2({ rootDirectory, watch: false });
813
- await writeAll(ctx);
814
- }
815
- async function watch(rootDirectory, { logger } = {}) {
816
- const ctx = await createContext2({ rootDirectory, watch: true });
817
- await writeAll(ctx);
818
- logger?.info(import_picocolors3.default.green("generated types"), { timestamp: true, clear: true });
819
- ctx.configLoader.onChange(async ({ result, routeConfigChanged }) => {
820
- if (!result.ok) {
821
- logger?.error(import_picocolors3.default.red(result.error), { timestamp: true, clear: true });
822
- return;
823
- }
824
- ctx.config = result.value;
825
- if (routeConfigChanged) {
826
- await writeAll(ctx);
827
- logger?.info(import_picocolors3.default.green("regenerated types"), {
828
- timestamp: true,
829
- clear: true
830
- });
831
- }
832
- });
833
- return {
834
- close: async () => await ctx.configLoader.close()
835
- };
1146
+ async function clearRouteModuleAnnotations(ctx) {
1147
+ await import_promises.default.rm(
1148
+ Path4.join(typesDirectory(ctx), Path4.basename(ctx.config.appDirectory)),
1149
+ { recursive: true, force: true }
1150
+ );
836
1151
  }
837
- async function createContext2({
838
- rootDirectory,
839
- watch: watch2
840
- }) {
841
- const configLoader = await createConfigLoader({ rootDirectory, watch: watch2 });
842
- const configResult = await configLoader.getConfig();
843
- if (!configResult.ok) {
844
- throw new Error(configResult.error);
845
- }
846
- const config = configResult.value;
847
- return {
848
- configLoader,
849
- rootDirectory,
850
- config
851
- };
1152
+ async function write(...files) {
1153
+ return Promise.all(
1154
+ files.map(async ({ filename: filename2, content }) => {
1155
+ await import_promises.default.mkdir(Path4.dirname(filename2), { recursive: true });
1156
+ await import_promises.default.writeFile(filename2, content);
1157
+ })
1158
+ );
852
1159
  }
853
- async function writeAll(ctx) {
854
- const typegenDir = getTypesDir(ctx);
855
- import_node_fs3.default.rmSync(typegenDir, { recursive: true, force: true });
856
- Object.values(ctx.config.routes).forEach((route) => {
857
- const typesPath = getTypesPath(ctx, route);
858
- const content = generate2(ctx, route);
859
- import_node_fs3.default.mkdirSync(Path4.dirname(typesPath), { recursive: true });
860
- import_node_fs3.default.writeFileSync(typesPath, content);
861
- });
862
- const registerPath = Path4.join(typegenDir, "+register.ts");
863
- import_node_fs3.default.writeFileSync(registerPath, register(ctx));
864
- const virtualPath = Path4.join(typegenDir, "+virtual.d.ts");
865
- import_node_fs3.default.writeFileSync(virtualPath, virtual);
1160
+ async function run(rootDirectory, { mode }) {
1161
+ const ctx = await createContext2({ rootDirectory, mode, watch: false });
1162
+ await import_promises.default.rm(typesDirectory(ctx), { recursive: true, force: true });
1163
+ await write(
1164
+ generateFuture(ctx),
1165
+ generatePages(ctx),
1166
+ generateRoutes(ctx),
1167
+ generateServerBuild(ctx),
1168
+ ...generateRouteModuleAnnotations(ctx)
1169
+ );
866
1170
  }
867
- function register(ctx) {
868
- const register2 = import_dedent2.default`
869
- import "react-router";
870
-
871
- declare module "react-router" {
872
- interface Register {
873
- params: Params;
874
- }
875
- }
876
- `;
877
- const { t: t2 } = babel_exports;
878
- const indexPaths = new Set(
879
- Object.values(ctx.config.routes).filter((route) => route.index).map((route) => route.path)
1171
+ async function watch(rootDirectory, { mode, logger }) {
1172
+ const ctx = await createContext2({ rootDirectory, mode, watch: true });
1173
+ await import_promises.default.rm(typesDirectory(ctx), { recursive: true, force: true });
1174
+ await write(
1175
+ generateFuture(ctx),
1176
+ generatePages(ctx),
1177
+ generateRoutes(ctx),
1178
+ generateServerBuild(ctx),
1179
+ ...generateRouteModuleAnnotations(ctx)
880
1180
  );
881
- const typeParams = t2.tsTypeAliasDeclaration(
882
- t2.identifier("Params"),
883
- null,
884
- t2.tsTypeLiteral(
885
- Object.values(ctx.config.routes).map((route) => {
886
- if (route.id !== "root" && !route.path) return void 0;
887
- if (!route.index && indexPaths.has(route.path)) return void 0;
888
- const lineage2 = lineage(ctx.config.routes, route);
889
- const fullpath2 = fullpath(lineage2);
890
- const params = parse2(fullpath2);
891
- return t2.tsPropertySignature(
892
- t2.stringLiteral(fullpath2),
893
- t2.tsTypeAnnotation(
894
- t2.tsTypeLiteral(
895
- Object.entries(params).map(([param, isRequired]) => {
896
- const property = t2.tsPropertySignature(
897
- t2.stringLiteral(param),
898
- t2.tsTypeAnnotation(t2.tsStringKeyword())
899
- );
900
- property.optional = !isRequired;
901
- return property;
902
- })
903
- )
904
- )
1181
+ logger?.info((0, import_picocolors3.green)("generated types"), { timestamp: true, clear: true });
1182
+ ctx.configLoader.onChange(
1183
+ async ({ result, configChanged, routeConfigChanged }) => {
1184
+ if (!result.ok) {
1185
+ logger?.error((0, import_picocolors3.red)(result.error), { timestamp: true, clear: true });
1186
+ return;
1187
+ }
1188
+ ctx.config = result.value;
1189
+ if (configChanged) {
1190
+ await write(generateFuture(ctx));
1191
+ logger?.info((0, import_picocolors3.green)("regenerated types"), {
1192
+ timestamp: true,
1193
+ clear: true
1194
+ });
1195
+ }
1196
+ if (routeConfigChanged) {
1197
+ await clearRouteModuleAnnotations(ctx);
1198
+ await write(
1199
+ generatePages(ctx),
1200
+ generateRoutes(ctx),
1201
+ ...generateRouteModuleAnnotations(ctx)
905
1202
  );
906
- }).filter((x) => x !== void 0)
907
- )
1203
+ logger?.info((0, import_picocolors3.green)("regenerated types"), {
1204
+ timestamp: true,
1205
+ clear: true
1206
+ });
1207
+ }
1208
+ }
908
1209
  );
909
- return [register2, generate(typeParams).code].join("\n\n");
1210
+ return {
1211
+ close: async () => await ctx.configLoader.close()
1212
+ };
910
1213
  }
911
- var import_node_fs3, import_dedent2, Path4, import_picocolors3, virtual;
1214
+ var import_promises, Path4, import_picocolors3;
912
1215
  var init_typegen = __esm({
913
1216
  "typegen/index.ts"() {
914
1217
  "use strict";
915
- import_node_fs3 = __toESM(require("fs"));
916
- import_dedent2 = __toESM(require("dedent"));
1218
+ import_promises = __toESM(require("fs/promises"));
917
1219
  Path4 = __toESM(require("pathe"));
918
- import_picocolors3 = __toESM(require("picocolors"));
919
- init_config();
920
- init_babel();
1220
+ import_picocolors3 = require("picocolors");
1221
+ init_context();
921
1222
  init_generate();
922
- init_paths();
923
- init_params();
924
- init_route();
925
- virtual = import_dedent2.default`
926
- declare module "virtual:react-router/server-build" {
927
- import { ServerBuild } from "react-router";
928
- export const assets: ServerBuild["assets"];
929
- export const assetsBuildDirectory: ServerBuild["assetsBuildDirectory"];
930
- export const basename: ServerBuild["basename"];
931
- export const entry: ServerBuild["entry"];
932
- export const future: ServerBuild["future"];
933
- export const isSpaMode: ServerBuild["isSpaMode"];
934
- export const prerender: ServerBuild["prerender"];
935
- export const publicPath: ServerBuild["publicPath"];
936
- export const routes: ServerBuild["routes"];
937
- export const ssr: ServerBuild["ssr"];
938
- export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
939
- }
940
- `;
941
1223
  }
942
1224
  });
943
1225
 
@@ -955,23 +1237,24 @@ var init_node_adapter = __esm({
955
1237
  });
956
1238
 
957
1239
  // vite/resolve-file-url.ts
958
- var path5;
1240
+ var path4;
959
1241
  var init_resolve_file_url = __esm({
960
1242
  "vite/resolve-file-url.ts"() {
961
1243
  "use strict";
962
- path5 = __toESM(require("path"));
1244
+ path4 = __toESM(require("path"));
963
1245
  init_vite();
964
1246
  }
965
1247
  });
966
1248
 
967
1249
  // vite/styles.ts
968
- var path6, import_react_router, cssFileRegExp, cssModulesRegExp;
1250
+ var path5, import_react_router, cssFileRegExp, cssModulesRegExp;
969
1251
  var init_styles = __esm({
970
1252
  "vite/styles.ts"() {
971
1253
  "use strict";
972
- path6 = __toESM(require("path"));
1254
+ path5 = __toESM(require("path"));
973
1255
  import_react_router = require("react-router");
974
1256
  init_resolve_file_url();
1257
+ init_babel();
975
1258
  cssFileRegExp = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
976
1259
  cssModulesRegExp = new RegExp(`\\.module${cssFileRegExp.source}`);
977
1260
  }
@@ -1065,11 +1348,11 @@ var init_route_chunks = __esm({
1065
1348
  });
1066
1349
 
1067
1350
  // vite/with-props.ts
1068
- var import_dedent3, vmod;
1351
+ var import_dedent2, vmod;
1069
1352
  var init_with_props = __esm({
1070
1353
  "vite/with-props.ts"() {
1071
1354
  "use strict";
1072
- import_dedent3 = __toESM(require("dedent"));
1355
+ import_dedent2 = __toESM(require("dedent"));
1073
1356
  init_babel();
1074
1357
  init_virtual_module();
1075
1358
  vmod = create("with-props");
@@ -1118,8 +1401,8 @@ function getServerBundleIds(ctx) {
1118
1401
  async function cleanBuildDirectory(viteConfig, ctx) {
1119
1402
  let buildDirectory = ctx.reactRouterConfig.buildDirectory;
1120
1403
  let isWithinRoot = () => {
1121
- let relativePath = path7.relative(ctx.rootDirectory, buildDirectory);
1122
- return !relativePath.startsWith("..") && !path7.isAbsolute(relativePath);
1404
+ let relativePath = path6.relative(ctx.rootDirectory, buildDirectory);
1405
+ return !relativePath.startsWith("..") && !path6.isAbsolute(relativePath);
1123
1406
  };
1124
1407
  if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
1125
1408
  await fse.remove(buildDirectory);
@@ -1130,7 +1413,7 @@ async function cleanViteManifests(environmentsOptions, ctx) {
1130
1413
  ([environmentName, options]) => {
1131
1414
  let outDir = options.build?.outDir;
1132
1415
  invariant(outDir, `Expected build.outDir for ${environmentName}`);
1133
- return path7.join(outDir, ".vite/manifest.json");
1416
+ return path6.join(outDir, ".vite/manifest.json");
1134
1417
  }
1135
1418
  );
1136
1419
  await Promise.all(
@@ -1140,7 +1423,7 @@ async function cleanViteManifests(environmentsOptions, ctx) {
1140
1423
  if (!ctx.viteManifestEnabled) {
1141
1424
  await fse.remove(viteManifestPath);
1142
1425
  }
1143
- let viteDir = path7.dirname(viteManifestPath);
1426
+ let viteDir = path6.dirname(viteManifestPath);
1144
1427
  let viteDirFiles = await fse.readdir(viteDir);
1145
1428
  if (viteDirFiles.length === 0) {
1146
1429
  await fse.remove(viteDir);
@@ -1157,10 +1440,10 @@ function mergeEnvironmentOptions(base, ...overrides) {
1157
1440
  }
1158
1441
  async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1159
1442
  let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
1160
- let packageRoot = path7.dirname(
1443
+ let packageRoot = path6.dirname(
1161
1444
  require.resolve("@react-router/dev/package.json")
1162
1445
  );
1163
- let { moduleSyncEnabled } = await import(`file:///${path7.join(packageRoot, "module-sync-enabled/index.mjs")}`);
1446
+ let { moduleSyncEnabled } = await import(`file:///${path6.join(packageRoot, "module-sync-enabled/index.mjs")}`);
1164
1447
  let vite2 = getVite();
1165
1448
  let viteServerConditions = [
1166
1449
  ...vite2.defaultServerConditions ?? [],
@@ -1217,7 +1500,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1217
1500
  copyPublicDir: false,
1218
1501
  // Assets in the public directory are only used by the client
1219
1502
  rollupOptions: {
1220
- input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual2.serverBuild.id,
1503
+ input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
1221
1504
  output: {
1222
1505
  entryFileNames: serverBuildFile,
1223
1506
  format: serverModuleFormat
@@ -1234,7 +1517,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1234
1517
  ctx.entryClientFilePath,
1235
1518
  ...Object.values(ctx.reactRouterConfig.routes).flatMap(
1236
1519
  (route) => {
1237
- let routeFilePath = path7.resolve(
1520
+ let routeFilePath = path6.resolve(
1238
1521
  ctx.reactRouterConfig.appDirectory,
1239
1522
  route.file
1240
1523
  );
@@ -1257,8 +1540,9 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1257
1540
  ""
1258
1541
  ) : null;
1259
1542
  let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
1260
- return path7.posix.join(
1261
- (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : viteUserConfig?.build?.assetsDir) ?? "assets",
1543
+ let assetsDir = (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
1544
+ return path6.posix.join(
1545
+ assetsDir,
1262
1546
  `[name]${routeChunkSuffix}-[hash].js`
1263
1547
  );
1264
1548
  }
@@ -1293,9 +1577,6 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1293
1577
  }
1294
1578
  });
1295
1579
  }
1296
- if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteCommand === "serve") {
1297
- environmentOptionsResolvers[CSS_DEV_HELPER_ENVIRONMENT_NAME] = () => ({});
1298
- }
1299
1580
  return environmentOptionsResolvers;
1300
1581
  }
1301
1582
  function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
@@ -1310,13 +1591,13 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
1310
1591
  function isNonNullable(x) {
1311
1592
  return x != null;
1312
1593
  }
1313
- var import_node_crypto, fs4, path7, url, fse, babel2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors4, import_kebabCase, CLIENT_NON_COMPONENT_EXPORTS, CLIENT_ROUTE_EXPORTS, BUILD_CLIENT_ROUTE_QUERY_STRING, SSR_BUNDLE_PREFIX, CSS_DEV_HELPER_ENVIRONMENT_NAME, virtualHmrRuntime, virtualInjectHmrRuntime, virtual2, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1594
+ var import_node_crypto, fs4, path6, url, fse, babel2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors4, import_kebabCase, import_tinyglobby, CLIENT_NON_COMPONENT_EXPORTS, CLIENT_ROUTE_EXPORTS, BUILD_CLIENT_ROUTE_QUERY_STRING, SSR_BUNDLE_PREFIX, virtualHmrRuntime, virtualInjectHmrRuntime, virtual, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1314
1595
  var init_plugin = __esm({
1315
1596
  "vite/plugin.ts"() {
1316
1597
  "use strict";
1317
1598
  import_node_crypto = require("crypto");
1318
1599
  fs4 = __toESM(require("fs"));
1319
- path7 = __toESM(require("path"));
1600
+ path6 = __toESM(require("path"));
1320
1601
  url = __toESM(require("url"));
1321
1602
  fse = __toESM(require("fs-extra"));
1322
1603
  babel2 = __toESM(require("@babel/core"));
@@ -1326,6 +1607,7 @@ var init_plugin = __esm({
1326
1607
  import_jsesc = __toESM(require("jsesc"));
1327
1608
  import_picocolors4 = __toESM(require("picocolors"));
1328
1609
  import_kebabCase = __toESM(require("lodash/kebabCase"));
1610
+ import_tinyglobby = require("tinyglobby");
1329
1611
  init_typegen();
1330
1612
  init_invariant();
1331
1613
  init_babel();
@@ -1358,27 +1640,26 @@ var init_plugin = __esm({
1358
1640
  ];
1359
1641
  BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
1360
1642
  SSR_BUNDLE_PREFIX = "ssrBundle_";
1361
- CSS_DEV_HELPER_ENVIRONMENT_NAME = "__react_router_css_dev_helper__";
1362
1643
  virtualHmrRuntime = create("hmr-runtime");
1363
1644
  virtualInjectHmrRuntime = create("inject-hmr-runtime");
1364
- virtual2 = {
1645
+ virtual = {
1365
1646
  serverBuild: create("server-build"),
1366
1647
  serverManifest: create("server-manifest"),
1367
1648
  browserManifest: create("browser-manifest")
1368
1649
  };
1369
- getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path7.join(
1650
+ getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path6.join(
1370
1651
  reactRouterConfig.buildDirectory,
1371
1652
  "server",
1372
1653
  ...serverBundleId ? [serverBundleId] : []
1373
1654
  );
1374
- getClientBuildDirectory = (reactRouterConfig) => path7.join(reactRouterConfig.buildDirectory, "client");
1375
- defaultEntriesDir = path7.resolve(
1376
- path7.dirname(require.resolve("@react-router/dev/package.json")),
1655
+ getClientBuildDirectory = (reactRouterConfig) => path6.join(reactRouterConfig.buildDirectory, "client");
1656
+ defaultEntriesDir = path6.resolve(
1657
+ path6.dirname(require.resolve("@react-router/dev/package.json")),
1377
1658
  "dist",
1378
1659
  "config",
1379
1660
  "defaults"
1380
1661
  );
1381
- defaultEntries = fse.readdirSync(defaultEntriesDir).map((filename3) => path7.join(defaultEntriesDir, filename3));
1662
+ defaultEntries = fse.readdirSync(defaultEntriesDir).map((filename2) => path6.join(defaultEntriesDir, filename2));
1382
1663
  invariant(defaultEntries.length > 0, "No default entries found");
1383
1664
  REACT_REFRESH_HEADER = `
1384
1665
  import RefreshRuntime from "${virtualHmrRuntime.id}";
@@ -1412,7 +1693,13 @@ __export(build_exports, {
1412
1693
  async function build(root, viteBuildOptions) {
1413
1694
  await preloadVite();
1414
1695
  let vite2 = getVite();
1415
- let configResult = await loadConfig({ rootDirectory: root });
1696
+ let configResult = await loadConfig({
1697
+ rootDirectory: root,
1698
+ mode: viteBuildOptions.mode ?? "production",
1699
+ // In this scope we only need future flags, so we can skip evaluating
1700
+ // routes.ts until we're within the Vite build context
1701
+ skipRoutes: true
1702
+ });
1416
1703
  if (!configResult.ok) {
1417
1704
  throw new Error(configResult.error);
1418
1705
  }
@@ -1652,7 +1939,7 @@ var import_semver = __toESM(require("semver"));
1652
1939
  var import_picocolors8 = __toESM(require("picocolors"));
1653
1940
 
1654
1941
  // cli/commands.ts
1655
- var path8 = __toESM(require("path"));
1942
+ var path7 = __toESM(require("path"));
1656
1943
  var import_fs_extra = __toESM(require("fs-extra"));
1657
1944
  var import_package_json2 = __toESM(require("@npmcli/package-json"));
1658
1945
  var import_exit_hook = __toESM(require("exit-hook"));
@@ -1738,9 +2025,12 @@ function transpile(tsx, options = {}) {
1738
2025
  init_profiler();
1739
2026
  init_typegen();
1740
2027
  init_vite();
1741
- async function routes(reactRouterRoot, flags = {}) {
1742
- let rootDirectory = reactRouterRoot ?? process.cwd();
1743
- let configResult = await loadConfig({ rootDirectory });
2028
+ async function routes(rootDirectory, flags = {}) {
2029
+ rootDirectory = resolveRootDirectory(rootDirectory, flags);
2030
+ let configResult = await loadConfig({
2031
+ rootDirectory,
2032
+ mode: flags.mode ?? "production"
2033
+ });
1744
2034
  if (!configResult.ok) {
1745
2035
  console.error(import_picocolors7.default.red(configResult.error));
1746
2036
  process.exit(1);
@@ -1749,9 +2039,7 @@ async function routes(reactRouterRoot, flags = {}) {
1749
2039
  console.log(formatRoutes(configResult.value.routes, format));
1750
2040
  }
1751
2041
  async function build2(root, options = {}) {
1752
- if (!root) {
1753
- root = process.env.REACT_ROUTER_ROOT || process.cwd();
1754
- }
2042
+ root = resolveRootDirectory(root, options);
1755
2043
  let { build: build3 } = await Promise.resolve().then(() => (init_build(), build_exports));
1756
2044
  if (options.profile) {
1757
2045
  await start();
@@ -1768,6 +2056,7 @@ async function dev2(root, options = {}) {
1768
2056
  await start();
1769
2057
  }
1770
2058
  (0, import_exit_hook.default)(() => stop(console.info));
2059
+ root = resolveRootDirectory(root, options);
1771
2060
  await dev3(root, options);
1772
2061
  await new Promise(() => {
1773
2062
  });
@@ -1779,14 +2068,17 @@ var conjunctionListFormat = new Intl.ListFormat("en", {
1779
2068
  style: "long",
1780
2069
  type: "conjunction"
1781
2070
  });
1782
- async function generateEntry(entry, reactRouterRoot, flags = {}) {
2071
+ async function generateEntry(entry, rootDirectory, flags = {}) {
1783
2072
  if (!entry) {
1784
- await generateEntry("entry.client", reactRouterRoot, flags);
1785
- await generateEntry("entry.server", reactRouterRoot, flags);
2073
+ await generateEntry("entry.client", rootDirectory, flags);
2074
+ await generateEntry("entry.server", rootDirectory, flags);
1786
2075
  return;
1787
2076
  }
1788
- let rootDirectory = reactRouterRoot ?? process.cwd();
1789
- let configResult = await loadConfig({ rootDirectory });
2077
+ rootDirectory = resolveRootDirectory(rootDirectory, flags);
2078
+ let configResult = await loadConfig({
2079
+ rootDirectory,
2080
+ mode: flags.mode ?? "production"
2081
+ });
1790
2082
  if (!configResult.ok) {
1791
2083
  console.error(import_picocolors7.default.red(configResult.error));
1792
2084
  return;
@@ -1806,14 +2098,14 @@ async function generateEntry(entry, reactRouterRoot, flags = {}) {
1806
2098
  console.error(import_picocolors7.default.red(`No default server entry detected.`));
1807
2099
  return;
1808
2100
  }
1809
- let defaultsDirectory = path8.resolve(
1810
- path8.dirname(require.resolve("@react-router/dev/package.json")),
2101
+ let defaultsDirectory = path7.resolve(
2102
+ path7.dirname(require.resolve("@react-router/dev/package.json")),
1811
2103
  "dist",
1812
2104
  "config",
1813
2105
  "defaults"
1814
2106
  );
1815
- let defaultEntryClient = path8.resolve(defaultsDirectory, "entry.client.tsx");
1816
- let defaultEntryServer = path8.resolve(
2107
+ let defaultEntryClient = path7.resolve(defaultsDirectory, "entry.client.tsx");
2108
+ let defaultEntryServer = path7.resolve(
1817
2109
  defaultsDirectory,
1818
2110
  `entry.server.node.tsx`
1819
2111
  );
@@ -1822,7 +2114,7 @@ async function generateEntry(entry, reactRouterRoot, flags = {}) {
1822
2114
  let useTypeScript = flags.typescript ?? true;
1823
2115
  let outputExtension = useTypeScript ? "tsx" : "jsx";
1824
2116
  let outputEntry = `${entry}.${outputExtension}`;
1825
- let outputFile2 = path8.resolve(appDirectory, outputEntry);
2117
+ let outputFile2 = path7.resolve(appDirectory, outputEntry);
1826
2118
  if (!useTypeScript) {
1827
2119
  let javascript = transpile(contents, {
1828
2120
  cwd: rootDirectory,
@@ -1834,20 +2126,26 @@ async function generateEntry(entry, reactRouterRoot, flags = {}) {
1834
2126
  }
1835
2127
  console.log(
1836
2128
  import_picocolors7.default.blue(
1837
- `Entry file ${entry} created at ${path8.relative(
2129
+ `Entry file ${entry} created at ${path7.relative(
1838
2130
  rootDirectory,
1839
2131
  outputFile2
1840
2132
  )}.`
1841
2133
  )
1842
2134
  );
1843
2135
  }
2136
+ function resolveRootDirectory(root, flags) {
2137
+ if (root) {
2138
+ return path7.resolve(root);
2139
+ }
2140
+ return process.env.REACT_ROUTER_ROOT || (flags?.config ? path7.dirname(path7.resolve(flags.config)) : process.cwd());
2141
+ }
1844
2142
  async function checkForEntry(rootDirectory, appDirectory, entries2) {
1845
2143
  for (let entry of entries2) {
1846
- let entryPath = path8.resolve(appDirectory, entry);
2144
+ let entryPath = path7.resolve(appDirectory, entry);
1847
2145
  let exists = await import_fs_extra.default.pathExists(entryPath);
1848
2146
  if (exists) {
1849
- let relative8 = path8.relative(rootDirectory, entryPath);
1850
- console.error(import_picocolors7.default.red(`Entry file ${relative8} already exists.`));
2147
+ let relative7 = path7.relative(rootDirectory, entryPath);
2148
+ console.error(import_picocolors7.default.red(`Entry file ${relative7} already exists.`));
1851
2149
  return process.exit(1);
1852
2150
  }
1853
2151
  }
@@ -1863,17 +2161,22 @@ async function createClientEntry(rootDirectory, appDirectory, inputFile) {
1863
2161
  return contents;
1864
2162
  }
1865
2163
  async function typegen(root, flags) {
1866
- root ??= process.cwd();
2164
+ root = resolveRootDirectory(root, flags);
1867
2165
  if (flags.watch) {
1868
2166
  await preloadVite();
1869
2167
  const vite2 = getVite();
1870
2168
  const logger = vite2.createLogger("info", { prefix: "[react-router]" });
1871
- await watch(root, { logger });
2169
+ await watch(root, {
2170
+ mode: flags.mode ?? "development",
2171
+ logger
2172
+ });
1872
2173
  await new Promise(() => {
1873
2174
  });
1874
2175
  return;
1875
2176
  }
1876
- await run(root);
2177
+ await run(root, {
2178
+ mode: flags.mode ?? "production"
2179
+ });
1877
2180
  }
1878
2181
 
1879
2182
  // cli/run.ts