@react-router/dev 7.6.0 → 7.6.1-pre.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.
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v7.6.0
3
+ * @react-router/dev v7.6.1-pre.1
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -357,7 +357,7 @@ async function resolveConfig({
357
357
  );
358
358
  let {
359
359
  appDirectory: userAppDirectory,
360
- basename: basename2,
360
+ basename: basename3,
361
361
  buildDirectory: userBuildDirectory,
362
362
  buildEnd,
363
363
  prerender,
@@ -472,7 +472,7 @@ async function resolveConfig({
472
472
  };
473
473
  let reactRouterConfig = deepFreeze({
474
474
  appDirectory,
475
- basename: basename2,
475
+ basename: basename3,
476
476
  buildDirectory,
477
477
  buildEnd,
478
478
  future,
@@ -535,11 +535,11 @@ async function createConfigLoader({
535
535
  fsWatcher = import_chokidar.default.watch([root, appDirectory], {
536
536
  ignoreInitial: true,
537
537
  ignored: (path8) => {
538
- let dirname6 = import_pathe3.default.dirname(path8);
539
- return !dirname6.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
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
540
  // that are at the root level, not nested in subdirectories
541
541
  path8 !== root && // Watch the root directory itself
542
- dirname6 !== root;
542
+ dirname5 !== root;
543
543
  }
544
544
  });
545
545
  fsWatcher.on("all", async (...args) => {
@@ -634,15 +634,15 @@ function omitRoutes(config) {
634
634
  routes: {}
635
635
  };
636
636
  }
637
- function isEntryFile(entryBasename, filename3) {
638
- return entryExts.some((ext) => filename3 === `${entryBasename}${ext}`);
637
+ function isEntryFile(entryBasename, filename2) {
638
+ return entryExts.some((ext) => filename2 === `${entryBasename}${ext}`);
639
639
  }
640
- function findEntry(dir, basename2, options) {
640
+ function findEntry(dir, basename3, options) {
641
641
  let currentDir = import_pathe3.default.resolve(dir);
642
642
  let { root } = import_pathe3.default.parse(currentDir);
643
643
  while (true) {
644
644
  for (let ext of options?.extensions ?? entryExts) {
645
- let file = import_pathe3.default.resolve(currentDir, basename2 + ext);
645
+ let file = import_pathe3.default.resolve(currentDir, basename3 + ext);
646
646
  if (import_node_fs.default.existsSync(file)) {
647
647
  return options?.absolute ?? false ? file : import_pathe3.default.relative(dir, file);
648
648
  }
@@ -780,6 +780,31 @@ var init_profiler = __esm({
780
780
  }
781
781
  });
782
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
+
783
808
  // vite/babel.ts
784
809
  var babel_exports = {};
785
810
  __export(babel_exports, {
@@ -799,27 +824,6 @@ var init_babel = __esm({
799
824
  }
800
825
  });
801
826
 
802
- // typegen/paths.ts
803
- function getTypesDir(ctx) {
804
- return Path3.join(ctx.rootDirectory, ".react-router/types");
805
- }
806
- function getTypesPath(ctx, route) {
807
- return Path3.join(
808
- getTypesDir(ctx),
809
- Path3.relative(ctx.rootDirectory, ctx.config.appDirectory),
810
- Path3.dirname(route.file),
811
- "+types/" + Pathe.filename(route.file) + ".ts"
812
- );
813
- }
814
- var Path3, Pathe;
815
- var init_paths = __esm({
816
- "typegen/paths.ts"() {
817
- "use strict";
818
- Path3 = __toESM(require("pathe"));
819
- Pathe = __toESM(require("pathe/utils"));
820
- }
821
- });
822
-
823
827
  // typegen/params.ts
824
828
  function parse2(fullpath2) {
825
829
  const result = {};
@@ -854,8 +858,11 @@ function lineage(routes2, route) {
854
858
  return result;
855
859
  }
856
860
  function fullpath(lineage2) {
857
- if (lineage2.length === 1 && lineage2[0].id === "root") return "/";
858
- return "/" + lineage2.map((route) => route.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path8) => path8 !== void 0 && path8 !== "").join("/");
861
+ const route = lineage2.at(-1);
862
+ if (lineage2.length === 1 && route?.id === "root") return "/";
863
+ const isLayout = route && route.index !== true && route.path === void 0;
864
+ if (isLayout) return void 0;
865
+ return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path8) => path8 !== void 0 && path8 !== "").join("/");
859
866
  }
860
867
  var init_route = __esm({
861
868
  "typegen/route.ts"() {
@@ -864,108 +871,380 @@ var init_route = __esm({
864
871
  });
865
872
 
866
873
  // typegen/generate.ts
867
- function generate2(ctx, route) {
868
- const lineage2 = lineage(ctx.config.routes, route);
869
- const fullpath2 = fullpath(lineage2);
870
- const typesPath = getTypesPath(ctx, route);
871
- const parents = lineage2.slice(0, -1);
872
- const parentTypeImports = parents.map((parent, i) => {
873
- const rel = Path4.relative(
874
- Path4.dirname(typesPath),
875
- getTypesPath(ctx, parent)
876
- );
877
- const indent = i === 0 ? "" : " ".repeat(2);
878
- let source = noExtension(rel);
879
- if (!source.startsWith("../")) source = "./" + source;
880
- return `${indent}import type { Info as Parent${i} } from "${source}.js"`;
881
- }).join("\n");
882
- return import_dedent.default`
883
- // React Router generated types for route:
884
- // ${route.file}
885
-
886
- import type * as T from "react-router/route-module"
887
-
888
- ${parentTypeImports}
889
-
890
- type Module = typeof import("../${Pathe2.filename(route.file)}.js")
891
-
892
- export type Info = {
893
- parents: [${parents.map((_, i) => `Parent${i}`).join(", ")}],
894
- id: "${route.id}"
895
- file: "${route.file}"
896
- path: "${route.path}"
897
- params: {${formatParamProperties(
898
- fullpath2
899
- )}} & { [key: string]: string | undefined }
900
- module: Module
901
- loaderData: T.CreateLoaderData<Module>
902
- actionData: T.CreateActionData<Module>
874
+ function typesDirectory(ctx) {
875
+ return Path3.join(ctx.rootDirectory, ".react-router/types");
876
+ }
877
+ function generateFuture(ctx) {
878
+ const filename2 = Path3.join(typesDirectory(ctx), "+future.ts");
879
+ const content = import_dedent.default`
880
+ // Generated by React Router
881
+
882
+ import "react-router";
883
+
884
+ declare module "react-router" {
885
+ interface Future {
886
+ unstable_middleware: ${ctx.config.future.unstable_middleware}
887
+ }
903
888
  }
889
+ `;
890
+ return { filename: filename2, content };
891
+ }
892
+ function generateServerBuild(ctx) {
893
+ const filename2 = Path3.join(typesDirectory(ctx), "+server-build.d.ts");
894
+ const content = import_dedent.default`
895
+ // Generated by React Router
904
896
 
905
- export namespace Route {
906
- export type LinkDescriptors = T.LinkDescriptors
907
- export type LinksFunction = () => LinkDescriptors
897
+ declare module "virtual:react-router/server-build" {
898
+ import { ServerBuild } from "react-router";
899
+ export const assets: ServerBuild["assets"];
900
+ export const assetsBuildDirectory: ServerBuild["assetsBuildDirectory"];
901
+ export const basename: ServerBuild["basename"];
902
+ export const entry: ServerBuild["entry"];
903
+ export const future: ServerBuild["future"];
904
+ export const isSpaMode: ServerBuild["isSpaMode"];
905
+ export const prerender: ServerBuild["prerender"];
906
+ export const publicPath: ServerBuild["publicPath"];
907
+ export const routeDiscovery: ServerBuild["routeDiscovery"];
908
+ export const routes: ServerBuild["routes"];
909
+ export const ssr: ServerBuild["ssr"];
910
+ export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
911
+ }
912
+ `;
913
+ return { filename: filename2, content };
914
+ }
915
+ function generateRoutes(ctx) {
916
+ const fileToRoutes = /* @__PURE__ */ new Map();
917
+ const lineages = /* @__PURE__ */ new Map();
918
+ const allPages = /* @__PURE__ */ new Set();
919
+ const routeToPages = /* @__PURE__ */ new Map();
920
+ for (const route of Object.values(ctx.config.routes)) {
921
+ let routeIds = fileToRoutes.get(route.file);
922
+ if (!routeIds) {
923
+ routeIds = /* @__PURE__ */ new Set();
924
+ fileToRoutes.set(route.file, routeIds);
925
+ }
926
+ routeIds.add(route.id);
927
+ const lineage2 = lineage(ctx.config.routes, route);
928
+ lineages.set(route.id, lineage2);
929
+ const fullpath2 = fullpath(lineage2);
930
+ if (!fullpath2) continue;
931
+ const pages = explodeOptionalSegments(fullpath2);
932
+ pages.forEach((page) => allPages.add(page));
933
+ lineage2.forEach(({ id }) => {
934
+ let routePages = routeToPages.get(id);
935
+ if (!routePages) {
936
+ routePages = /* @__PURE__ */ new Set();
937
+ routeToPages.set(id, routePages);
938
+ }
939
+ pages.forEach((page) => routePages.add(page));
940
+ });
941
+ }
942
+ const routesTs = {
943
+ filename: Path3.join(typesDirectory(ctx), "+routes.ts"),
944
+ content: import_dedent.default`
945
+ // Generated by React Router
908
946
 
909
- export type MetaArgs = T.CreateMetaArgs<Info>
910
- export type MetaDescriptors = T.MetaDescriptors
911
- export type MetaFunction = (args: MetaArgs) => MetaDescriptors
947
+ import "react-router"
912
948
 
913
- export type HeadersArgs = T.HeadersArgs
914
- export type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit
949
+ declare module "react-router" {
950
+ interface Register {
951
+ pages: Pages
952
+ routeFiles: RouteFiles
953
+ }
954
+ }
955
+ ` + "\n\n" + generate(pagesType(allPages)).code + "\n\n" + generate(routeFilesType({ fileToRoutes, routeToPages })).code
956
+ };
957
+ const allAnnotations = Array.from(fileToRoutes.entries()).filter(([file]) => isInAppDirectory(ctx, file)).map(
958
+ ([file, routeIds]) => getRouteAnnotations({ ctx, file, routeIds, lineages })
959
+ );
960
+ return [routesTs, ...allAnnotations];
961
+ }
962
+ function pagesType(pages) {
963
+ return t2.tsTypeAliasDeclaration(
964
+ t2.identifier("Pages"),
965
+ null,
966
+ t2.tsTypeLiteral(
967
+ Array.from(pages).map((page) => {
968
+ return t2.tsPropertySignature(
969
+ t2.stringLiteral(page),
970
+ t2.tsTypeAnnotation(
971
+ t2.tsTypeLiteral([
972
+ t2.tsPropertySignature(
973
+ t2.identifier("params"),
974
+ t2.tsTypeAnnotation(paramsType(page))
975
+ )
976
+ ])
977
+ )
978
+ );
979
+ })
980
+ )
981
+ );
982
+ }
983
+ function routeFilesType({
984
+ fileToRoutes,
985
+ routeToPages
986
+ }) {
987
+ return t2.tsTypeAliasDeclaration(
988
+ t2.identifier("RouteFiles"),
989
+ null,
990
+ t2.tsTypeLiteral(
991
+ Array.from(fileToRoutes).map(
992
+ ([file, routeIds]) => t2.tsPropertySignature(
993
+ t2.stringLiteral(file),
994
+ t2.tsTypeAnnotation(
995
+ t2.tsUnionType(
996
+ Array.from(routeIds).map((routeId) => {
997
+ const pages = routeToPages.get(routeId) ?? /* @__PURE__ */ new Set();
998
+ return t2.tsTypeLiteral([
999
+ t2.tsPropertySignature(
1000
+ t2.identifier("id"),
1001
+ t2.tsTypeAnnotation(
1002
+ t2.tsLiteralType(t2.stringLiteral(routeId))
1003
+ )
1004
+ ),
1005
+ t2.tsPropertySignature(
1006
+ t2.identifier("page"),
1007
+ t2.tsTypeAnnotation(
1008
+ pages ? t2.tsUnionType(
1009
+ Array.from(pages).map(
1010
+ (page) => t2.tsLiteralType(t2.stringLiteral(page))
1011
+ )
1012
+ ) : t2.tsNeverKeyword()
1013
+ )
1014
+ )
1015
+ ]);
1016
+ })
1017
+ )
1018
+ )
1019
+ )
1020
+ )
1021
+ )
1022
+ );
1023
+ }
1024
+ function isInAppDirectory(ctx, routeFile) {
1025
+ const path8 = Path3.resolve(ctx.config.appDirectory, routeFile);
1026
+ return path8.startsWith(ctx.config.appDirectory);
1027
+ }
1028
+ function getRouteAnnotations({
1029
+ ctx,
1030
+ file,
1031
+ routeIds,
1032
+ lineages
1033
+ }) {
1034
+ const filename2 = Path3.join(
1035
+ typesDirectory(ctx),
1036
+ Path3.relative(ctx.rootDirectory, ctx.config.appDirectory),
1037
+ Path3.dirname(file),
1038
+ "+types",
1039
+ Pathe.filename(file) + ".ts"
1040
+ );
1041
+ const matchesType = t2.tsTypeAliasDeclaration(
1042
+ t2.identifier("Matches"),
1043
+ null,
1044
+ t2.tsUnionType(
1045
+ Array.from(routeIds).map((routeId) => {
1046
+ const lineage2 = lineages.get(routeId);
1047
+ return t2.tsTupleType(
1048
+ lineage2.map(
1049
+ (route) => t2.tsTypeLiteral([
1050
+ t2.tsPropertySignature(
1051
+ t2.identifier("id"),
1052
+ t2.tsTypeAnnotation(t2.tsLiteralType(t2.stringLiteral(route.id)))
1053
+ ),
1054
+ t2.tsPropertySignature(
1055
+ t2.identifier("module"),
1056
+ t2.tsTypeAnnotation(
1057
+ t2.tsTypeQuery(
1058
+ t2.tsImportType(
1059
+ t2.stringLiteral(
1060
+ relativeImportSource(
1061
+ rootDirsPath(ctx, filename2),
1062
+ Path3.resolve(ctx.config.appDirectory, route.file)
1063
+ )
1064
+ )
1065
+ )
1066
+ )
1067
+ )
1068
+ )
1069
+ ])
1070
+ )
1071
+ );
1072
+ })
1073
+ )
1074
+ );
1075
+ const routeImportSource = relativeImportSource(
1076
+ rootDirsPath(ctx, filename2),
1077
+ Path3.resolve(ctx.config.appDirectory, file)
1078
+ );
1079
+ const content = import_dedent.default`
1080
+ // Generated by React Router
915
1081
 
916
- export type unstable_MiddlewareFunction = T.CreateServerMiddlewareFunction<Info>
917
- export type unstable_ClientMiddlewareFunction = T.CreateClientMiddlewareFunction<Info>
918
- export type LoaderArgs = T.CreateServerLoaderArgs<Info>
919
- export type ClientLoaderArgs = T.CreateClientLoaderArgs<Info>
920
- export type ActionArgs = T.CreateServerActionArgs<Info>
921
- export type ClientActionArgs = T.CreateClientActionArgs<Info>
1082
+ import type { GetInfo, GetAnnotations } from "react-router/internal";
922
1083
 
923
- export type HydrateFallbackProps = T.CreateHydrateFallbackProps<Info>
924
- export type ComponentProps = T.CreateComponentProps<Info>
925
- export type ErrorBoundaryProps = T.CreateErrorBoundaryProps<Info>
926
- }
927
- `;
1084
+ type Module = typeof import("${routeImportSource}")
1085
+
1086
+ type Info = GetInfo<{
1087
+ file: "${file}",
1088
+ module: Module
1089
+ }>
1090
+ ` + "\n\n" + generate(matchesType).code + "\n\n" + import_dedent.default`
1091
+ type Annotations = GetAnnotations<Info & { module: Module, matches: Matches }>;
1092
+
1093
+ export namespace Route {
1094
+ // links
1095
+ export type LinkDescriptors = Annotations["LinkDescriptors"];
1096
+ export type LinksFunction = Annotations["LinksFunction"];
1097
+
1098
+ // meta
1099
+ export type MetaArgs = Annotations["MetaArgs"];
1100
+ export type MetaDescriptors = Annotations["MetaDescriptors"];
1101
+ export type MetaFunction = Annotations["MetaFunction"];
1102
+
1103
+ // headers
1104
+ export type HeadersArgs = Annotations["HeadersArgs"];
1105
+ export type HeadersFunction = Annotations["HeadersFunction"];
1106
+
1107
+ // unstable_middleware
1108
+ export type unstable_MiddlewareFunction = Annotations["unstable_MiddlewareFunction"];
1109
+
1110
+ // unstable_clientMiddleware
1111
+ export type unstable_ClientMiddlewareFunction = Annotations["unstable_ClientMiddlewareFunction"];
1112
+
1113
+ // loader
1114
+ export type LoaderArgs = Annotations["LoaderArgs"];
1115
+
1116
+ // clientLoader
1117
+ export type ClientLoaderArgs = Annotations["ClientLoaderArgs"];
1118
+
1119
+ // action
1120
+ export type ActionArgs = Annotations["ActionArgs"];
1121
+
1122
+ // clientAction
1123
+ export type ClientActionArgs = Annotations["ClientActionArgs"];
1124
+
1125
+ // HydrateFallback
1126
+ export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
1127
+
1128
+ // Component
1129
+ export type ComponentProps = Annotations["ComponentProps"];
1130
+
1131
+ // ErrorBoundary
1132
+ export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"];
1133
+ }
1134
+ `;
1135
+ return { filename: filename2, content };
1136
+ }
1137
+ function relativeImportSource(from, to) {
1138
+ let path8 = Path3.relative(Path3.dirname(from), to);
1139
+ path8 = Path3.join(Path3.dirname(path8), Pathe.filename(path8));
1140
+ if (!path8.startsWith("../")) path8 = "./" + path8;
1141
+ return path8 + ".js";
1142
+ }
1143
+ function rootDirsPath(ctx, typesPath) {
1144
+ const rel = Path3.relative(typesDirectory(ctx), typesPath);
1145
+ return Path3.join(ctx.rootDirectory, rel);
1146
+ }
1147
+ function paramsType(path8) {
1148
+ const params = parse2(path8);
1149
+ return t2.tsTypeLiteral(
1150
+ Object.entries(params).map(([param, isRequired]) => {
1151
+ const property = t2.tsPropertySignature(
1152
+ t2.stringLiteral(param),
1153
+ t2.tsTypeAnnotation(t2.tsStringKeyword())
1154
+ );
1155
+ property.optional = !isRequired;
1156
+ return property;
1157
+ })
1158
+ );
928
1159
  }
929
- function formatParamProperties(fullpath2) {
930
- const params = parse2(fullpath2);
931
- const properties = Object.entries(params).map(
932
- ([name, isRequired]) => isRequired ? `"${name}": string` : `"${name}"?: string`
1160
+ function explodeOptionalSegments(path8) {
1161
+ let segments = path8.split("/");
1162
+ if (segments.length === 0) return [];
1163
+ let [first, ...rest] = segments;
1164
+ let isOptional = first.endsWith("?");
1165
+ let required = first.replace(/\?$/, "");
1166
+ if (rest.length === 0) {
1167
+ return isOptional ? [required, ""] : [required];
1168
+ }
1169
+ let restExploded = explodeOptionalSegments(rest.join("/"));
1170
+ let result = [];
1171
+ result.push(
1172
+ ...restExploded.map(
1173
+ (subpath) => subpath === "" ? required : [required, subpath].join("/")
1174
+ )
1175
+ );
1176
+ if (isOptional) {
1177
+ result.push(...restExploded);
1178
+ }
1179
+ return result.map(
1180
+ (exploded) => path8.startsWith("/") && exploded === "" ? "/" : exploded
933
1181
  );
934
- return properties.join("; ");
935
1182
  }
936
- var import_dedent, Path4, Pathe2, noExtension;
1183
+ var import_dedent, Path3, Pathe, t2;
937
1184
  var init_generate = __esm({
938
1185
  "typegen/generate.ts"() {
939
1186
  "use strict";
940
1187
  import_dedent = __toESM(require("dedent"));
941
- Path4 = __toESM(require("pathe"));
942
- Pathe2 = __toESM(require("pathe/utils"));
943
- init_paths();
1188
+ Path3 = __toESM(require("pathe"));
1189
+ Pathe = __toESM(require("pathe/utils"));
1190
+ init_babel();
944
1191
  init_params();
945
1192
  init_route();
946
- noExtension = (path8) => Path4.join(Path4.dirname(path8), Pathe2.filename(path8));
1193
+ ({ t: t2 } = babel_exports);
947
1194
  }
948
1195
  });
949
1196
 
950
1197
  // typegen/index.ts
1198
+ async function clearRouteModuleAnnotations(ctx) {
1199
+ await import_promises.default.rm(
1200
+ Path4.join(typesDirectory(ctx), Path4.basename(ctx.config.appDirectory)),
1201
+ { recursive: true, force: true }
1202
+ );
1203
+ }
1204
+ async function write(...files) {
1205
+ return Promise.all(
1206
+ files.map(async ({ filename: filename2, content }) => {
1207
+ await import_promises.default.mkdir(Path4.dirname(filename2), { recursive: true });
1208
+ await import_promises.default.writeFile(filename2, content);
1209
+ })
1210
+ );
1211
+ }
951
1212
  async function run(rootDirectory, { mode }) {
952
1213
  const ctx = await createContext2({ rootDirectory, mode, watch: false });
953
- await writeAll(ctx);
1214
+ await import_promises.default.rm(typesDirectory(ctx), { recursive: true, force: true });
1215
+ await write(
1216
+ generateFuture(ctx),
1217
+ generateServerBuild(ctx),
1218
+ ...generateRoutes(ctx)
1219
+ );
954
1220
  }
955
1221
  async function watch(rootDirectory, { mode, logger }) {
956
1222
  const ctx = await createContext2({ rootDirectory, mode, watch: true });
957
- await writeAll(ctx);
958
- logger?.info(import_picocolors3.default.green("generated types"), { timestamp: true, clear: true });
1223
+ await import_promises.default.rm(typesDirectory(ctx), { recursive: true, force: true });
1224
+ await write(
1225
+ generateFuture(ctx),
1226
+ generateServerBuild(ctx),
1227
+ ...generateRoutes(ctx)
1228
+ );
1229
+ logger?.info((0, import_picocolors3.green)("generated types"), { timestamp: true, clear: true });
959
1230
  ctx.configLoader.onChange(
960
1231
  async ({ result, configChanged, routeConfigChanged }) => {
961
1232
  if (!result.ok) {
962
- logger?.error(import_picocolors3.default.red(result.error), { timestamp: true, clear: true });
1233
+ logger?.error((0, import_picocolors3.red)(result.error), { timestamp: true, clear: true });
963
1234
  return;
964
1235
  }
965
1236
  ctx.config = result.value;
966
- if (configChanged || routeConfigChanged) {
967
- await writeAll(ctx);
968
- logger?.info(import_picocolors3.default.green("regenerated types"), {
1237
+ if (configChanged) {
1238
+ await write(generateFuture(ctx));
1239
+ logger?.info((0, import_picocolors3.green)("regenerated types"), {
1240
+ timestamp: true,
1241
+ clear: true
1242
+ });
1243
+ }
1244
+ if (routeConfigChanged) {
1245
+ await clearRouteModuleAnnotations(ctx);
1246
+ await write(...generateRoutes(ctx));
1247
+ logger?.info((0, import_picocolors3.green)("regenerated types"), {
969
1248
  timestamp: true,
970
1249
  clear: true
971
1250
  });
@@ -976,116 +1255,15 @@ async function watch(rootDirectory, { mode, logger }) {
976
1255
  close: async () => await ctx.configLoader.close()
977
1256
  };
978
1257
  }
979
- async function createContext2({
980
- rootDirectory,
981
- watch: watch2,
982
- mode
983
- }) {
984
- const configLoader = await createConfigLoader({ rootDirectory, mode, watch: watch2 });
985
- const configResult = await configLoader.getConfig();
986
- if (!configResult.ok) {
987
- throw new Error(configResult.error);
988
- }
989
- const config = configResult.value;
990
- return {
991
- configLoader,
992
- rootDirectory,
993
- config
994
- };
995
- }
996
- async function writeAll(ctx) {
997
- const typegenDir = getTypesDir(ctx);
998
- import_node_fs3.default.rmSync(typegenDir, { recursive: true, force: true });
999
- Object.values(ctx.config.routes).forEach((route) => {
1000
- const typesPath = getTypesPath(ctx, route);
1001
- const content = generate2(ctx, route);
1002
- import_node_fs3.default.mkdirSync(Path5.dirname(typesPath), { recursive: true });
1003
- import_node_fs3.default.writeFileSync(typesPath, content);
1004
- });
1005
- const registerPath = Path5.join(typegenDir, "+register.ts");
1006
- import_node_fs3.default.writeFileSync(registerPath, register(ctx));
1007
- const virtualPath = Path5.join(typegenDir, "+virtual.d.ts");
1008
- import_node_fs3.default.writeFileSync(virtualPath, virtual);
1009
- }
1010
- function register(ctx) {
1011
- const register2 = import_dedent2.default`
1012
- import "react-router";
1013
-
1014
- declare module "react-router" {
1015
- interface Register {
1016
- params: Params;
1017
- }
1018
-
1019
- interface Future {
1020
- unstable_middleware: ${ctx.config.future.unstable_middleware}
1021
- }
1022
- }
1023
- `;
1024
- const { t: t2 } = babel_exports;
1025
- const fullpaths = /* @__PURE__ */ new Set();
1026
- Object.values(ctx.config.routes).forEach((route) => {
1027
- if (route.id !== "root" && !route.path) return;
1028
- const lineage2 = lineage(ctx.config.routes, route);
1029
- const fullpath2 = fullpath(lineage2);
1030
- fullpaths.add(fullpath2);
1031
- });
1032
- const typeParams = t2.tsTypeAliasDeclaration(
1033
- t2.identifier("Params"),
1034
- null,
1035
- t2.tsTypeLiteral(
1036
- Array.from(fullpaths).map((fullpath2) => {
1037
- const params = parse2(fullpath2);
1038
- return t2.tsPropertySignature(
1039
- t2.stringLiteral(fullpath2),
1040
- t2.tsTypeAnnotation(
1041
- t2.tsTypeLiteral(
1042
- Object.entries(params).map(([param, isRequired]) => {
1043
- const property = t2.tsPropertySignature(
1044
- t2.stringLiteral(param),
1045
- t2.tsTypeAnnotation(t2.tsStringKeyword())
1046
- );
1047
- property.optional = !isRequired;
1048
- return property;
1049
- })
1050
- )
1051
- )
1052
- );
1053
- })
1054
- )
1055
- );
1056
- return [register2, generate(typeParams).code].join("\n\n");
1057
- }
1058
- var import_node_fs3, import_dedent2, Path5, import_picocolors3, virtual;
1258
+ var import_promises, Path4, import_picocolors3;
1059
1259
  var init_typegen = __esm({
1060
1260
  "typegen/index.ts"() {
1061
1261
  "use strict";
1062
- import_node_fs3 = __toESM(require("fs"));
1063
- import_dedent2 = __toESM(require("dedent"));
1064
- Path5 = __toESM(require("pathe"));
1065
- import_picocolors3 = __toESM(require("picocolors"));
1066
- init_config();
1067
- init_babel();
1262
+ import_promises = __toESM(require("fs/promises"));
1263
+ Path4 = __toESM(require("pathe"));
1264
+ import_picocolors3 = require("picocolors");
1265
+ init_context();
1068
1266
  init_generate();
1069
- init_paths();
1070
- init_params();
1071
- init_route();
1072
- virtual = import_dedent2.default`
1073
- declare module "virtual:react-router/server-build" {
1074
- import { ServerBuild } from "react-router";
1075
- export const assets: ServerBuild["assets"];
1076
- export const assetsBuildDirectory: ServerBuild["assetsBuildDirectory"];
1077
- export const basename: ServerBuild["basename"];
1078
- export const entry: ServerBuild["entry"];
1079
- export const future: ServerBuild["future"];
1080
- export const isSpaMode: ServerBuild["isSpaMode"];
1081
- export const prerender: ServerBuild["prerender"];
1082
- export const publicPath: ServerBuild["publicPath"];
1083
- export const routeDiscovery: ServerBuild["routeDiscovery"];
1084
- export const routes: ServerBuild["routes"];
1085
- export const ssr: ServerBuild["ssr"];
1086
- export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
1087
- }
1088
- `;
1089
1267
  }
1090
1268
  });
1091
1269
 
@@ -1214,11 +1392,11 @@ var init_route_chunks = __esm({
1214
1392
  });
1215
1393
 
1216
1394
  // vite/with-props.ts
1217
- var import_dedent3, vmod;
1395
+ var import_dedent2, vmod;
1218
1396
  var init_with_props = __esm({
1219
1397
  "vite/with-props.ts"() {
1220
1398
  "use strict";
1221
- import_dedent3 = __toESM(require("dedent"));
1399
+ import_dedent2 = __toESM(require("dedent"));
1222
1400
  init_babel();
1223
1401
  init_virtual_module();
1224
1402
  vmod = create("with-props");
@@ -1366,7 +1544,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1366
1544
  copyPublicDir: false,
1367
1545
  // Assets in the public directory are only used by the client
1368
1546
  rollupOptions: {
1369
- input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual2.serverBuild.id,
1547
+ input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
1370
1548
  output: {
1371
1549
  entryFileNames: serverBuildFile,
1372
1550
  format: serverModuleFormat
@@ -1457,7 +1635,7 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
1457
1635
  function isNonNullable(x) {
1458
1636
  return x != null;
1459
1637
  }
1460
- var import_node_crypto, fs4, path6, 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, virtualHmrRuntime, virtualInjectHmrRuntime, virtual2, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1638
+ var import_node_crypto, fs4, path6, 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, virtualHmrRuntime, virtualInjectHmrRuntime, virtual, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1461
1639
  var init_plugin = __esm({
1462
1640
  "vite/plugin.ts"() {
1463
1641
  "use strict";
@@ -1507,7 +1685,7 @@ var init_plugin = __esm({
1507
1685
  SSR_BUNDLE_PREFIX = "ssrBundle_";
1508
1686
  virtualHmrRuntime = create("hmr-runtime");
1509
1687
  virtualInjectHmrRuntime = create("inject-hmr-runtime");
1510
- virtual2 = {
1688
+ virtual = {
1511
1689
  serverBuild: create("server-build"),
1512
1690
  serverManifest: create("server-manifest"),
1513
1691
  browserManifest: create("browser-manifest")
@@ -1524,7 +1702,7 @@ var init_plugin = __esm({
1524
1702
  "config",
1525
1703
  "defaults"
1526
1704
  );
1527
- defaultEntries = fse.readdirSync(defaultEntriesDir).map((filename3) => path6.join(defaultEntriesDir, filename3));
1705
+ defaultEntries = fse.readdirSync(defaultEntriesDir).map((filename2) => path6.join(defaultEntriesDir, filename2));
1528
1706
  invariant(defaultEntries.length > 0, "No default entries found");
1529
1707
  REACT_REFRESH_HEADER = `
1530
1708
  import RefreshRuntime from "${virtualHmrRuntime.id}";
@@ -2009,8 +2187,8 @@ async function checkForEntry(rootDirectory, appDirectory, entries2) {
2009
2187
  let entryPath = path7.resolve(appDirectory, entry);
2010
2188
  let exists = await import_fs_extra.default.pathExists(entryPath);
2011
2189
  if (exists) {
2012
- let relative8 = path7.relative(rootDirectory, entryPath);
2013
- console.error(import_picocolors7.default.red(`Entry file ${relative8} already exists.`));
2190
+ let relative7 = path7.relative(rootDirectory, entryPath);
2191
+ console.error(import_picocolors7.default.red(`Entry file ${relative7} already exists.`));
2014
2192
  return process.exit(1);
2015
2193
  }
2016
2194
  }