@react-router/dev 0.0.0-experimental-00e730ed0 → 0.0.0-experimental-93ddf3985

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-00e730ed0
3
+ * @react-router/dev v0.0.0-experimental-93ddf3985
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -858,8 +858,11 @@ function lineage(routes2, route) {
858
858
  return result;
859
859
  }
860
860
  function fullpath(lineage2) {
861
- if (lineage2.length === 1 && lineage2[0].id === "root") return "/";
862
- 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("/");
863
866
  }
864
867
  var init_route = __esm({
865
868
  "typegen/route.ts"() {
@@ -909,27 +912,65 @@ function generateServerBuild(ctx) {
909
912
  `;
910
913
  return { filename: filename2, content };
911
914
  }
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;
915
+ function generateRoutes(ctx) {
916
+ const fileToRoutes = /* @__PURE__ */ new Map();
917
+ const lineages = /* @__PURE__ */ new Map();
918
+ const pages = /* @__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);
917
927
  const lineage2 = lineage(ctx.config.routes, route);
918
- const fullpath2 = fullpath(lineage2);
919
- fullpaths.add(fullpath2);
920
- });
921
- const pagesType = t2.tsTypeAliasDeclaration(
928
+ lineages.set(route.id, lineage2);
929
+ const page = fullpath(lineage2);
930
+ if (!page) continue;
931
+ pages.add(page);
932
+ lineage2.forEach(({ id }) => {
933
+ let routePages = routeToPages.get(id);
934
+ if (!routePages) {
935
+ routePages = /* @__PURE__ */ new Set();
936
+ routeToPages.set(id, routePages);
937
+ }
938
+ routePages.add(page);
939
+ });
940
+ }
941
+ const routesTs = {
942
+ filename: Path3.join(typesDirectory(ctx), "+routes.ts"),
943
+ content: import_dedent.default`
944
+ // Generated by React Router
945
+
946
+ import "react-router"
947
+
948
+ declare module "react-router" {
949
+ interface Register {
950
+ pages: Pages
951
+ routeFiles: RouteFiles
952
+ }
953
+ }
954
+ ` + "\n\n" + generate(pagesType(pages)).code + "\n\n" + generate(routeFilesType({ fileToRoutes, routeToPages })).code
955
+ };
956
+ const allAnnotations = Array.from(fileToRoutes.entries()).filter(([file]) => isInAppDirectory(ctx, file)).map(
957
+ ([file, routeIds]) => getRouteAnnotations({ ctx, file, routeIds, lineages })
958
+ );
959
+ return [routesTs, ...allAnnotations];
960
+ }
961
+ function pagesType(pages) {
962
+ return t2.tsTypeAliasDeclaration(
922
963
  t2.identifier("Pages"),
923
964
  null,
924
965
  t2.tsTypeLiteral(
925
- Array.from(fullpaths).map((fullpath2) => {
966
+ Array.from(pages).map((page) => {
926
967
  return t2.tsPropertySignature(
927
- t2.stringLiteral(fullpath2),
968
+ t2.stringLiteral(page),
928
969
  t2.tsTypeAnnotation(
929
970
  t2.tsTypeLiteral([
930
971
  t2.tsPropertySignature(
931
972
  t2.identifier("params"),
932
- t2.tsTypeAnnotation(paramsType(fullpath2))
973
+ t2.tsTypeAnnotation(paramsType(page))
933
974
  )
934
975
  ])
935
976
  )
@@ -937,55 +978,92 @@ function generatePages(ctx) {
937
978
  })
938
979
  )
939
980
  );
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
981
  }
953
- function generateRoutes(ctx) {
954
- const filename2 = Path3.join(typesDirectory(ctx), "+routes-pre.ts");
955
- const routesType = t2.tsTypeAliasDeclaration(
956
- t2.identifier("routesPre"),
982
+ function routeFilesType({
983
+ fileToRoutes,
984
+ routeToPages
985
+ }) {
986
+ return t2.tsTypeAliasDeclaration(
987
+ t2.identifier("RouteFiles"),
957
988
  null,
958
989
  t2.tsTypeLiteral(
959
- Object.values(ctx.config.routes).map((route) => {
960
- return t2.tsPropertySignature(
961
- t2.stringLiteral(route.id),
990
+ Array.from(fileToRoutes).map(
991
+ ([file, routeIds]) => t2.tsPropertySignature(
992
+ t2.stringLiteral(file),
962
993
  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
- ),
994
+ t2.tsUnionType(
995
+ Array.from(routeIds).map((routeId) => {
996
+ const pages = routeToPages.get(routeId) ?? /* @__PURE__ */ new Set();
997
+ return t2.tsTypeLiteral([
998
+ t2.tsPropertySignature(
999
+ t2.identifier("id"),
1000
+ t2.tsTypeAnnotation(
1001
+ t2.tsLiteralType(t2.stringLiteral(routeId))
1002
+ )
1003
+ ),
1004
+ t2.tsPropertySignature(
1005
+ t2.identifier("page"),
1006
+ t2.tsTypeAnnotation(
1007
+ pages ? t2.tsUnionType(
1008
+ Array.from(pages).map(
1009
+ (page) => t2.tsLiteralType(t2.stringLiteral(page))
1010
+ )
1011
+ ) : t2.tsNeverKeyword()
1012
+ )
1013
+ )
1014
+ ]);
1015
+ })
1016
+ )
1017
+ )
1018
+ )
1019
+ )
1020
+ )
1021
+ );
1022
+ }
1023
+ function isInAppDirectory(ctx, routeFile) {
1024
+ const path8 = Path3.resolve(ctx.config.appDirectory, routeFile);
1025
+ return path8.startsWith(ctx.config.appDirectory);
1026
+ }
1027
+ function getRouteAnnotations({
1028
+ ctx,
1029
+ file,
1030
+ routeIds,
1031
+ lineages
1032
+ }) {
1033
+ const filename2 = Path3.join(
1034
+ typesDirectory(ctx),
1035
+ Path3.relative(ctx.rootDirectory, ctx.config.appDirectory),
1036
+ Path3.dirname(file),
1037
+ "+types",
1038
+ Pathe.filename(file) + ".ts"
1039
+ );
1040
+ const matchesType = t2.tsTypeAliasDeclaration(
1041
+ t2.identifier("Matches"),
1042
+ null,
1043
+ t2.tsUnionType(
1044
+ Array.from(routeIds).map((routeId) => {
1045
+ const lineage2 = lineages.get(routeId);
1046
+ return t2.tsTupleType(
1047
+ lineage2.map(
1048
+ (route) => t2.tsTypeLiteral([
976
1049
  t2.tsPropertySignature(
977
- t2.identifier("params"),
978
- t2.tsTypeAnnotation(paramsType(route.path ?? ""))
1050
+ t2.identifier("id"),
1051
+ t2.tsTypeAnnotation(t2.tsLiteralType(t2.stringLiteral(route.id)))
979
1052
  ),
980
1053
  t2.tsPropertySignature(
981
- t2.identifier("index"),
1054
+ t2.identifier("module"),
982
1055
  t2.tsTypeAnnotation(
983
- t2.tsLiteralType(t2.booleanLiteral(route.index ?? false))
1056
+ t2.tsTypeQuery(
1057
+ t2.tsImportType(
1058
+ t2.stringLiteral(
1059
+ relativeImportSource(
1060
+ rootDirsPath(ctx, filename2),
1061
+ Path3.resolve(ctx.config.appDirectory, route.file)
1062
+ )
1063
+ )
1064
+ )
1065
+ )
984
1066
  )
985
- ),
986
- t2.tsPropertySignature(
987
- t2.identifier("file"),
988
- t2.tsTypeAnnotation(t2.tsLiteralType(t2.stringLiteral(route.file)))
989
1067
  )
990
1068
  ])
991
1069
  )
@@ -993,127 +1071,77 @@ function generateRoutes(ctx) {
993
1071
  })
994
1072
  )
995
1073
  );
1074
+ const routeImportSource = relativeImportSource(
1075
+ rootDirsPath(ctx, filename2),
1076
+ Path3.resolve(ctx.config.appDirectory, file)
1077
+ );
996
1078
  const content = import_dedent.default`
997
1079
  // Generated by React Router
998
1080
 
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(", ")}]
1081
+ import type { GetInfo, GetAnnotations } from "react-router/internal";
1025
1082
 
1026
- type Id = "${route.id}"
1027
- type Module = typeof import("../${Pathe.filename(route.file)}.js")
1083
+ type Module = typeof import("${routeImportSource}")
1028
1084
 
1029
- export type unstable_Props = {
1030
- params: Params[Id]
1031
- loaderData: CreateLoaderData<Module>
1032
- actionData: CreateActionData<Module>
1033
- }
1085
+ type Info = GetInfo<{
1086
+ file: "${file}",
1087
+ module: Module
1088
+ }>
1089
+ ` + "\n\n" + generate(matchesType).code + "\n\n" + import_dedent.default`
1090
+ type Annotations = GetAnnotations<Info & { module: Module, matches: Matches }>;
1034
1091
 
1035
- type Annotations = RouteModuleAnnotations<unstable_Props & {
1036
- parents: Parents,
1037
- module: Module,
1038
- }>;
1092
+ export namespace Route {
1093
+ // links
1094
+ export type LinkDescriptors = Annotations["LinkDescriptors"];
1095
+ export type LinksFunction = Annotations["LinksFunction"];
1039
1096
 
1040
- export namespace Route {
1041
- // links
1042
- export type LinkDescriptors = Annotations["LinkDescriptors"];
1043
- export type LinksFunction = Annotations["LinksFunction"];
1097
+ // meta
1098
+ export type MetaArgs = Annotations["MetaArgs"];
1099
+ export type MetaDescriptors = Annotations["MetaDescriptors"];
1100
+ export type MetaFunction = Annotations["MetaFunction"];
1044
1101
 
1045
- // meta
1046
- export type MetaArgs = Annotations["MetaArgs"];
1047
- export type MetaDescriptors = Annotations["MetaDescriptors"];
1048
- export type MetaFunction = Annotations["MetaFunction"];
1102
+ // headers
1103
+ export type HeadersArgs = Annotations["HeadersArgs"];
1104
+ export type HeadersFunction = Annotations["HeadersFunction"];
1049
1105
 
1050
- // headers
1051
- export type HeadersArgs = Annotations["HeadersArgs"];
1052
- export type HeadersFunction = Annotations["HeadersFunction"];
1106
+ // unstable_middleware
1107
+ export type unstable_MiddlewareFunction = Annotations["unstable_MiddlewareFunction"];
1053
1108
 
1054
- // unstable_middleware
1055
- export type unstable_MiddlewareFunction = Annotations["unstable_MiddlewareFunction"];
1109
+ // unstable_clientMiddleware
1110
+ export type unstable_ClientMiddlewareFunction = Annotations["unstable_ClientMiddlewareFunction"];
1056
1111
 
1057
- // unstable_clientMiddleware
1058
- export type unstable_ClientMiddlewareFunction = Annotations["unstable_ClientMiddlewareFunction"];
1112
+ // loader
1113
+ export type LoaderArgs = Annotations["LoaderArgs"];
1059
1114
 
1060
- // loader
1061
- export type LoaderArgs = Annotations["LoaderArgs"];
1115
+ // clientLoader
1116
+ export type ClientLoaderArgs = Annotations["ClientLoaderArgs"];
1062
1117
 
1063
- // clientLoader
1064
- export type ClientLoaderArgs = Annotations["ClientLoaderArgs"];
1118
+ // action
1119
+ export type ActionArgs = Annotations["ActionArgs"];
1065
1120
 
1066
- // action
1067
- export type ActionArgs = Annotations["ActionArgs"];
1121
+ // clientAction
1122
+ export type ClientActionArgs = Annotations["ClientActionArgs"];
1068
1123
 
1069
- // clientAction
1070
- export type ClientActionArgs = Annotations["ClientActionArgs"];
1124
+ // HydrateFallback
1125
+ export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
1071
1126
 
1072
- // HydrateFallback
1073
- export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
1127
+ // Component
1128
+ export type ComponentProps = Annotations["ComponentProps"];
1074
1129
 
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
- );
1130
+ // ErrorBoundary
1131
+ export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"];
1132
+ }
1133
+ `;
1134
+ return { filename: filename2, content };
1096
1135
  }
1097
- function getParents(ctx, route) {
1098
- const typesPath = getRouteModuleAnnotationsFilepath(ctx, route);
1099
- const lineage2 = lineage(ctx.config.routes, route);
1100
- const parents = lineage2.slice(0, -1);
1101
- return parents.map((parent, i) => {
1102
- const rel = Path3.relative(
1103
- Path3.dirname(typesPath),
1104
- getRouteModuleAnnotationsFilepath(ctx, parent)
1105
- );
1106
- let source = noExtension(rel);
1107
- if (!source.startsWith("../")) source = "./" + source;
1108
- const name = `Parent${i}`;
1109
- return {
1110
- name,
1111
- import: `import type { unstable_Props as ${name} } from "${source}.js"`
1112
- };
1113
- });
1136
+ function relativeImportSource(from, to) {
1137
+ let path8 = Path3.relative(Path3.dirname(from), to);
1138
+ path8 = Path3.join(Path3.dirname(path8), Pathe.filename(path8));
1139
+ if (!path8.startsWith("../")) path8 = "./" + path8;
1140
+ return path8 + ".js";
1114
1141
  }
1115
- function noExtension(path8) {
1116
- return Path3.join(Path3.dirname(path8), Pathe.filename(path8));
1142
+ function rootDirsPath(ctx, typesPath) {
1143
+ const rel = Path3.relative(typesDirectory(ctx), typesPath);
1144
+ return Path3.join(ctx.rootDirectory, rel);
1117
1145
  }
1118
1146
  function paramsType(path8) {
1119
1147
  const params = parse2(path8);
@@ -1162,10 +1190,8 @@ async function run(rootDirectory, { mode }) {
1162
1190
  await import_promises.default.rm(typesDirectory(ctx), { recursive: true, force: true });
1163
1191
  await write(
1164
1192
  generateFuture(ctx),
1165
- generatePages(ctx),
1166
- generateRoutes(ctx),
1167
1193
  generateServerBuild(ctx),
1168
- ...generateRouteModuleAnnotations(ctx)
1194
+ ...generateRoutes(ctx)
1169
1195
  );
1170
1196
  }
1171
1197
  async function watch(rootDirectory, { mode, logger }) {
@@ -1173,10 +1199,8 @@ async function watch(rootDirectory, { mode, logger }) {
1173
1199
  await import_promises.default.rm(typesDirectory(ctx), { recursive: true, force: true });
1174
1200
  await write(
1175
1201
  generateFuture(ctx),
1176
- generatePages(ctx),
1177
- generateRoutes(ctx),
1178
1202
  generateServerBuild(ctx),
1179
- ...generateRouteModuleAnnotations(ctx)
1203
+ ...generateRoutes(ctx)
1180
1204
  );
1181
1205
  logger?.info((0, import_picocolors3.green)("generated types"), { timestamp: true, clear: true });
1182
1206
  ctx.configLoader.onChange(
@@ -1195,11 +1219,7 @@ async function watch(rootDirectory, { mode, logger }) {
1195
1219
  }
1196
1220
  if (routeConfigChanged) {
1197
1221
  await clearRouteModuleAnnotations(ctx);
1198
- await write(
1199
- generatePages(ctx),
1200
- generateRoutes(ctx),
1201
- ...generateRouteModuleAnnotations(ctx)
1202
- );
1222
+ await write(...generateRoutes(ctx));
1203
1223
  logger?.info((0, import_picocolors3.green)("regenerated types"), {
1204
1224
  timestamp: true,
1205
1225
  clear: true
@@ -1591,7 +1611,7 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
1591
1611
  function isNonNullable(x) {
1592
1612
  return x != null;
1593
1613
  }
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;
1614
+ 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;
1595
1615
  var init_plugin = __esm({
1596
1616
  "vite/plugin.ts"() {
1597
1617
  "use strict";
@@ -1607,7 +1627,6 @@ var init_plugin = __esm({
1607
1627
  import_jsesc = __toESM(require("jsesc"));
1608
1628
  import_picocolors4 = __toESM(require("picocolors"));
1609
1629
  import_kebabCase = __toESM(require("lodash/kebabCase"));
1610
- import_tinyglobby = require("tinyglobby");
1611
1630
  init_typegen();
1612
1631
  init_invariant();
1613
1632
  init_babel();
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-00e730ed0
2
+ * @react-router/dev v0.0.0-experimental-93ddf3985
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
package/dist/routes.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-00e730ed0
2
+ * @react-router/dev v0.0.0-experimental-93ddf3985
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-00e730ed0
2
+ * @react-router/dev v0.0.0-experimental-93ddf3985
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
package/dist/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-00e730ed0
2
+ * @react-router/dev v0.0.0-experimental-93ddf3985
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -57,7 +57,6 @@ var import_pick3 = __toESM(require("lodash/pick"));
57
57
  var import_jsesc = __toESM(require("jsesc"));
58
58
  var import_picocolors3 = __toESM(require("picocolors"));
59
59
  var import_kebabCase = __toESM(require("lodash/kebabCase"));
60
- var import_tinyglobby = require("tinyglobby");
61
60
 
62
61
  // typegen/index.ts
63
62
  var import_promises = __toESM(require("fs/promises"));
@@ -850,8 +849,11 @@ function lineage(routes, route) {
850
849
  return result;
851
850
  }
852
851
  function fullpath(lineage2) {
853
- if (lineage2.length === 1 && lineage2[0].id === "root") return "/";
854
- return "/" + lineage2.map((route) => route.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path6) => path6 !== void 0 && path6 !== "").join("/");
852
+ const route = lineage2.at(-1);
853
+ if (lineage2.length === 1 && route?.id === "root") return "/";
854
+ const isLayout = route && route.index !== true && route.path === void 0;
855
+ if (isLayout) return void 0;
856
+ return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path6) => path6 !== void 0 && path6 !== "").join("/");
855
857
  }
856
858
 
857
859
  // typegen/generate.ts
@@ -897,27 +899,65 @@ function generateServerBuild(ctx) {
897
899
  return { filename: filename2, content };
898
900
  }
899
901
  var { t: t2 } = babel_exports;
900
- function generatePages(ctx) {
901
- const filename2 = Path3.join(typesDirectory(ctx), "+pages.ts");
902
- const fullpaths = /* @__PURE__ */ new Set();
903
- Object.values(ctx.config.routes).forEach((route) => {
904
- if (route.id !== "root" && !route.path) return;
902
+ function generateRoutes(ctx) {
903
+ const fileToRoutes = /* @__PURE__ */ new Map();
904
+ const lineages = /* @__PURE__ */ new Map();
905
+ const pages = /* @__PURE__ */ new Set();
906
+ const routeToPages = /* @__PURE__ */ new Map();
907
+ for (const route of Object.values(ctx.config.routes)) {
908
+ let routeIds = fileToRoutes.get(route.file);
909
+ if (!routeIds) {
910
+ routeIds = /* @__PURE__ */ new Set();
911
+ fileToRoutes.set(route.file, routeIds);
912
+ }
913
+ routeIds.add(route.id);
905
914
  const lineage2 = lineage(ctx.config.routes, route);
906
- const fullpath2 = fullpath(lineage2);
907
- fullpaths.add(fullpath2);
908
- });
909
- const pagesType = t2.tsTypeAliasDeclaration(
915
+ lineages.set(route.id, lineage2);
916
+ const page = fullpath(lineage2);
917
+ if (!page) continue;
918
+ pages.add(page);
919
+ lineage2.forEach(({ id }) => {
920
+ let routePages = routeToPages.get(id);
921
+ if (!routePages) {
922
+ routePages = /* @__PURE__ */ new Set();
923
+ routeToPages.set(id, routePages);
924
+ }
925
+ routePages.add(page);
926
+ });
927
+ }
928
+ const routesTs = {
929
+ filename: Path3.join(typesDirectory(ctx), "+routes.ts"),
930
+ content: import_dedent.default`
931
+ // Generated by React Router
932
+
933
+ import "react-router"
934
+
935
+ declare module "react-router" {
936
+ interface Register {
937
+ pages: Pages
938
+ routeFiles: RouteFiles
939
+ }
940
+ }
941
+ ` + "\n\n" + generate(pagesType(pages)).code + "\n\n" + generate(routeFilesType({ fileToRoutes, routeToPages })).code
942
+ };
943
+ const allAnnotations = Array.from(fileToRoutes.entries()).filter(([file]) => isInAppDirectory(ctx, file)).map(
944
+ ([file, routeIds]) => getRouteAnnotations({ ctx, file, routeIds, lineages })
945
+ );
946
+ return [routesTs, ...allAnnotations];
947
+ }
948
+ function pagesType(pages) {
949
+ return t2.tsTypeAliasDeclaration(
910
950
  t2.identifier("Pages"),
911
951
  null,
912
952
  t2.tsTypeLiteral(
913
- Array.from(fullpaths).map((fullpath2) => {
953
+ Array.from(pages).map((page) => {
914
954
  return t2.tsPropertySignature(
915
- t2.stringLiteral(fullpath2),
955
+ t2.stringLiteral(page),
916
956
  t2.tsTypeAnnotation(
917
957
  t2.tsTypeLiteral([
918
958
  t2.tsPropertySignature(
919
959
  t2.identifier("params"),
920
- t2.tsTypeAnnotation(paramsType(fullpath2))
960
+ t2.tsTypeAnnotation(paramsType(page))
921
961
  )
922
962
  ])
923
963
  )
@@ -925,55 +965,92 @@ function generatePages(ctx) {
925
965
  })
926
966
  )
927
967
  );
928
- const content = import_dedent.default`
929
- // Generated by React Router
930
-
931
- import "react-router"
932
-
933
- declare module "react-router" {
934
- interface Register {
935
- pages: Pages
936
- }
937
- }
938
- ` + "\n\n" + generate(pagesType).code;
939
- return { filename: filename2, content };
940
968
  }
941
- function generateRoutes(ctx) {
942
- const filename2 = Path3.join(typesDirectory(ctx), "+routes-pre.ts");
943
- const routesType = t2.tsTypeAliasDeclaration(
944
- t2.identifier("routesPre"),
969
+ function routeFilesType({
970
+ fileToRoutes,
971
+ routeToPages
972
+ }) {
973
+ return t2.tsTypeAliasDeclaration(
974
+ t2.identifier("RouteFiles"),
945
975
  null,
946
976
  t2.tsTypeLiteral(
947
- Object.values(ctx.config.routes).map((route) => {
948
- return t2.tsPropertySignature(
949
- t2.stringLiteral(route.id),
977
+ Array.from(fileToRoutes).map(
978
+ ([file, routeIds]) => t2.tsPropertySignature(
979
+ t2.stringLiteral(file),
950
980
  t2.tsTypeAnnotation(
951
- t2.tsTypeLiteral([
952
- t2.tsPropertySignature(
953
- t2.identifier("parentId"),
954
- t2.tsTypeAnnotation(
955
- route.parentId ? t2.tsLiteralType(t2.stringLiteral(route.parentId)) : t2.tsUndefinedKeyword()
956
- )
957
- ),
958
- t2.tsPropertySignature(
959
- t2.identifier("path"),
960
- t2.tsTypeAnnotation(
961
- route.path ? t2.tsLiteralType(t2.stringLiteral(route.path)) : t2.tsUndefinedKeyword()
962
- )
963
- ),
981
+ t2.tsUnionType(
982
+ Array.from(routeIds).map((routeId) => {
983
+ const pages = routeToPages.get(routeId) ?? /* @__PURE__ */ new Set();
984
+ return t2.tsTypeLiteral([
985
+ t2.tsPropertySignature(
986
+ t2.identifier("id"),
987
+ t2.tsTypeAnnotation(
988
+ t2.tsLiteralType(t2.stringLiteral(routeId))
989
+ )
990
+ ),
991
+ t2.tsPropertySignature(
992
+ t2.identifier("page"),
993
+ t2.tsTypeAnnotation(
994
+ pages ? t2.tsUnionType(
995
+ Array.from(pages).map(
996
+ (page) => t2.tsLiteralType(t2.stringLiteral(page))
997
+ )
998
+ ) : t2.tsNeverKeyword()
999
+ )
1000
+ )
1001
+ ]);
1002
+ })
1003
+ )
1004
+ )
1005
+ )
1006
+ )
1007
+ )
1008
+ );
1009
+ }
1010
+ function isInAppDirectory(ctx, routeFile) {
1011
+ const path6 = Path3.resolve(ctx.config.appDirectory, routeFile);
1012
+ return path6.startsWith(ctx.config.appDirectory);
1013
+ }
1014
+ function getRouteAnnotations({
1015
+ ctx,
1016
+ file,
1017
+ routeIds,
1018
+ lineages
1019
+ }) {
1020
+ const filename2 = Path3.join(
1021
+ typesDirectory(ctx),
1022
+ Path3.relative(ctx.rootDirectory, ctx.config.appDirectory),
1023
+ Path3.dirname(file),
1024
+ "+types",
1025
+ Pathe.filename(file) + ".ts"
1026
+ );
1027
+ const matchesType = t2.tsTypeAliasDeclaration(
1028
+ t2.identifier("Matches"),
1029
+ null,
1030
+ t2.tsUnionType(
1031
+ Array.from(routeIds).map((routeId) => {
1032
+ const lineage2 = lineages.get(routeId);
1033
+ return t2.tsTupleType(
1034
+ lineage2.map(
1035
+ (route) => t2.tsTypeLiteral([
964
1036
  t2.tsPropertySignature(
965
- t2.identifier("params"),
966
- t2.tsTypeAnnotation(paramsType(route.path ?? ""))
1037
+ t2.identifier("id"),
1038
+ t2.tsTypeAnnotation(t2.tsLiteralType(t2.stringLiteral(route.id)))
967
1039
  ),
968
1040
  t2.tsPropertySignature(
969
- t2.identifier("index"),
1041
+ t2.identifier("module"),
970
1042
  t2.tsTypeAnnotation(
971
- t2.tsLiteralType(t2.booleanLiteral(route.index ?? false))
1043
+ t2.tsTypeQuery(
1044
+ t2.tsImportType(
1045
+ t2.stringLiteral(
1046
+ relativeImportSource(
1047
+ rootDirsPath(ctx, filename2),
1048
+ Path3.resolve(ctx.config.appDirectory, route.file)
1049
+ )
1050
+ )
1051
+ )
1052
+ )
972
1053
  )
973
- ),
974
- t2.tsPropertySignature(
975
- t2.identifier("file"),
976
- t2.tsTypeAnnotation(t2.tsLiteralType(t2.stringLiteral(route.file)))
977
1054
  )
978
1055
  ])
979
1056
  )
@@ -981,127 +1058,77 @@ function generateRoutes(ctx) {
981
1058
  })
982
1059
  )
983
1060
  );
1061
+ const routeImportSource = relativeImportSource(
1062
+ rootDirsPath(ctx, filename2),
1063
+ Path3.resolve(ctx.config.appDirectory, file)
1064
+ );
984
1065
  const content = import_dedent.default`
985
1066
  // Generated by React Router
986
1067
 
987
- import "react-router"
1068
+ import type { GetInfo, GetAnnotations } from "react-router/internal";
988
1069
 
989
- declare module "react-router" {
990
- interface Register {
991
- routesPre: routesPre
992
- }
993
- }
994
- ` + "\n\n" + generate(routesType).code;
995
- return { filename: filename2, content };
996
- }
997
- function generateRouteModuleAnnotations(ctx) {
998
- return Object.values(ctx.config.routes).filter((route) => isRouteInAppDirectory(ctx, route)).map((route) => {
999
- const filename2 = getRouteModuleAnnotationsFilepath(ctx, route);
1000
- const parents = getParents(ctx, route);
1001
- const content = import_dedent.default`
1002
- // Generated by React Router
1070
+ type Module = typeof import("${routeImportSource}")
1003
1071
 
1004
- import type {
1005
- Params,
1006
- RouteModuleAnnotations,
1007
- CreateLoaderData,
1008
- CreateActionData,
1009
- } from "react-router/internal";
1072
+ type Info = GetInfo<{
1073
+ file: "${file}",
1074
+ module: Module
1075
+ }>
1076
+ ` + "\n\n" + generate(matchesType).code + "\n\n" + import_dedent.default`
1077
+ type Annotations = GetAnnotations<Info & { module: Module, matches: Matches }>;
1010
1078
 
1011
- ${parents.map((parent) => parent.import).join("\n" + " ".repeat(3))}
1012
- type Parents = [${parents.map((parent) => parent.name).join(", ")}]
1079
+ export namespace Route {
1080
+ // links
1081
+ export type LinkDescriptors = Annotations["LinkDescriptors"];
1082
+ export type LinksFunction = Annotations["LinksFunction"];
1013
1083
 
1014
- type Id = "${route.id}"
1015
- type Module = typeof import("../${Pathe.filename(route.file)}.js")
1084
+ // meta
1085
+ export type MetaArgs = Annotations["MetaArgs"];
1086
+ export type MetaDescriptors = Annotations["MetaDescriptors"];
1087
+ export type MetaFunction = Annotations["MetaFunction"];
1016
1088
 
1017
- export type unstable_Props = {
1018
- params: Params[Id]
1019
- loaderData: CreateLoaderData<Module>
1020
- actionData: CreateActionData<Module>
1021
- }
1089
+ // headers
1090
+ export type HeadersArgs = Annotations["HeadersArgs"];
1091
+ export type HeadersFunction = Annotations["HeadersFunction"];
1022
1092
 
1023
- type Annotations = RouteModuleAnnotations<unstable_Props & {
1024
- parents: Parents,
1025
- module: Module,
1026
- }>;
1093
+ // unstable_middleware
1094
+ export type unstable_MiddlewareFunction = Annotations["unstable_MiddlewareFunction"];
1027
1095
 
1028
- export namespace Route {
1029
- // links
1030
- export type LinkDescriptors = Annotations["LinkDescriptors"];
1031
- export type LinksFunction = Annotations["LinksFunction"];
1096
+ // unstable_clientMiddleware
1097
+ export type unstable_ClientMiddlewareFunction = Annotations["unstable_ClientMiddlewareFunction"];
1032
1098
 
1033
- // meta
1034
- export type MetaArgs = Annotations["MetaArgs"];
1035
- export type MetaDescriptors = Annotations["MetaDescriptors"];
1036
- export type MetaFunction = Annotations["MetaFunction"];
1099
+ // loader
1100
+ export type LoaderArgs = Annotations["LoaderArgs"];
1037
1101
 
1038
- // headers
1039
- export type HeadersArgs = Annotations["HeadersArgs"];
1040
- export type HeadersFunction = Annotations["HeadersFunction"];
1102
+ // clientLoader
1103
+ export type ClientLoaderArgs = Annotations["ClientLoaderArgs"];
1041
1104
 
1042
- // unstable_middleware
1043
- export type unstable_MiddlewareFunction = Annotations["unstable_MiddlewareFunction"];
1105
+ // action
1106
+ export type ActionArgs = Annotations["ActionArgs"];
1044
1107
 
1045
- // unstable_clientMiddleware
1046
- export type unstable_ClientMiddlewareFunction = Annotations["unstable_ClientMiddlewareFunction"];
1108
+ // clientAction
1109
+ export type ClientActionArgs = Annotations["ClientActionArgs"];
1047
1110
 
1048
- // loader
1049
- export type LoaderArgs = Annotations["LoaderArgs"];
1111
+ // HydrateFallback
1112
+ export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
1050
1113
 
1051
- // clientLoader
1052
- export type ClientLoaderArgs = Annotations["ClientLoaderArgs"];
1114
+ // Component
1115
+ export type ComponentProps = Annotations["ComponentProps"];
1053
1116
 
1054
- // action
1055
- export type ActionArgs = Annotations["ActionArgs"];
1056
-
1057
- // clientAction
1058
- export type ClientActionArgs = Annotations["ClientActionArgs"];
1059
-
1060
- // HydrateFallback
1061
- export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
1062
-
1063
- // Component
1064
- export type ComponentProps = Annotations["ComponentProps"];
1065
-
1066
- // ErrorBoundary
1067
- export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"];
1068
- }
1069
- `;
1070
- return { filename: filename2, content };
1071
- });
1072
- }
1073
- function isRouteInAppDirectory(ctx, route) {
1074
- const absoluteRoutePath = Path3.resolve(ctx.config.appDirectory, route.file);
1075
- return absoluteRoutePath.startsWith(ctx.config.appDirectory);
1076
- }
1077
- function getRouteModuleAnnotationsFilepath(ctx, route) {
1078
- return Path3.join(
1079
- typesDirectory(ctx),
1080
- Path3.relative(ctx.rootDirectory, ctx.config.appDirectory),
1081
- Path3.dirname(route.file),
1082
- "+types/" + Pathe.filename(route.file) + ".ts"
1083
- );
1117
+ // ErrorBoundary
1118
+ export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"];
1119
+ }
1120
+ `;
1121
+ return { filename: filename2, content };
1084
1122
  }
1085
- function getParents(ctx, route) {
1086
- const typesPath = getRouteModuleAnnotationsFilepath(ctx, route);
1087
- const lineage2 = lineage(ctx.config.routes, route);
1088
- const parents = lineage2.slice(0, -1);
1089
- return parents.map((parent, i) => {
1090
- const rel = Path3.relative(
1091
- Path3.dirname(typesPath),
1092
- getRouteModuleAnnotationsFilepath(ctx, parent)
1093
- );
1094
- let source = noExtension(rel);
1095
- if (!source.startsWith("../")) source = "./" + source;
1096
- const name = `Parent${i}`;
1097
- return {
1098
- name,
1099
- import: `import type { unstable_Props as ${name} } from "${source}.js"`
1100
- };
1101
- });
1123
+ function relativeImportSource(from, to) {
1124
+ let path6 = Path3.relative(Path3.dirname(from), to);
1125
+ path6 = Path3.join(Path3.dirname(path6), Pathe.filename(path6));
1126
+ if (!path6.startsWith("../")) path6 = "./" + path6;
1127
+ return path6 + ".js";
1102
1128
  }
1103
- function noExtension(path6) {
1104
- return Path3.join(Path3.dirname(path6), Pathe.filename(path6));
1129
+ function rootDirsPath(ctx, typesPath) {
1130
+ const rel = Path3.relative(typesDirectory(ctx), typesPath);
1131
+ return Path3.join(ctx.rootDirectory, rel);
1105
1132
  }
1106
1133
  function paramsType(path6) {
1107
1134
  const params = parse2(path6);
@@ -1137,10 +1164,8 @@ async function watch(rootDirectory, { mode, logger }) {
1137
1164
  await import_promises.default.rm(typesDirectory(ctx), { recursive: true, force: true });
1138
1165
  await write(
1139
1166
  generateFuture(ctx),
1140
- generatePages(ctx),
1141
- generateRoutes(ctx),
1142
1167
  generateServerBuild(ctx),
1143
- ...generateRouteModuleAnnotations(ctx)
1168
+ ...generateRoutes(ctx)
1144
1169
  );
1145
1170
  logger?.info((0, import_picocolors2.green)("generated types"), { timestamp: true, clear: true });
1146
1171
  ctx.configLoader.onChange(
@@ -1159,11 +1184,7 @@ async function watch(rootDirectory, { mode, logger }) {
1159
1184
  }
1160
1185
  if (routeConfigChanged) {
1161
1186
  await clearRouteModuleAnnotations(ctx);
1162
- await write(
1163
- generatePages(ctx),
1164
- generateRoutes(ctx),
1165
- ...generateRouteModuleAnnotations(ctx)
1166
- );
1187
+ await write(...generateRoutes(ctx));
1167
1188
  logger?.info((0, import_picocolors2.green)("regenerated types"), {
1168
1189
  timestamp: true,
1169
1190
  clear: true
@@ -3023,7 +3044,7 @@ var reactRouterVitePlugin = () => {
3023
3044
  ...Object.values(ctx.reactRouterConfig.routes).map(
3024
3045
  (route) => resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
3025
3046
  )
3026
- ].map(import_tinyglobby.convertPathToPattern) : [],
3047
+ ] : [],
3027
3048
  include: [
3028
3049
  // Pre-bundle React dependencies to avoid React duplicates,
3029
3050
  // even if React dependencies are not direct dependencies.
@@ -3126,7 +3147,7 @@ var reactRouterVitePlugin = () => {
3126
3147
  ctx.reactRouterConfig
3127
3148
  )
3128
3149
  )
3129
- ].map(import_tinyglobby.convertPathToPattern),
3150
+ ],
3130
3151
  include: [
3131
3152
  "react",
3132
3153
  "react/jsx-dev-runtime",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
- "version": "0.0.0-experimental-00e730ed0",
3
+ "version": "0.0.0-experimental-93ddf3985",
4
4
  "description": "Dev tools and CLI for React Router",
5
5
  "homepage": "https://reactrouter.com",
6
6
  "bugs": {
@@ -84,10 +84,9 @@
84
84
  "react-refresh": "^0.14.0",
85
85
  "semver": "^7.3.7",
86
86
  "set-cookie-parser": "^2.6.0",
87
- "tinyglobby": "^0.2.13",
88
87
  "valibot": "^0.41.0",
89
88
  "vite-node": "3.0.0-beta.2",
90
- "@react-router/node": "0.0.0-experimental-00e730ed0"
89
+ "@react-router/node": "0.0.0-experimental-93ddf3985"
91
90
  },
92
91
  "devDependencies": {
93
92
  "@types/babel__core": "^7.20.5",
@@ -111,15 +110,15 @@
111
110
  "vite": "^6.1.0",
112
111
  "wireit": "0.14.9",
113
112
  "wrangler": "^4.2.0",
114
- "@react-router/serve": "0.0.0-experimental-00e730ed0",
115
- "react-router": "^0.0.0-experimental-00e730ed0"
113
+ "@react-router/serve": "0.0.0-experimental-93ddf3985",
114
+ "react-router": "^0.0.0-experimental-93ddf3985"
116
115
  },
117
116
  "peerDependencies": {
118
117
  "typescript": "^5.1.0",
119
118
  "vite": "^5.1.0 || ^6.0.0",
120
119
  "wrangler": "^3.28.2 || ^4.0.0",
121
- "@react-router/serve": "^0.0.0-experimental-00e730ed0",
122
- "react-router": "^0.0.0-experimental-00e730ed0"
120
+ "@react-router/serve": "^0.0.0-experimental-93ddf3985",
121
+ "react-router": "^0.0.0-experimental-93ddf3985"
123
122
  },
124
123
  "peerDependenciesMeta": {
125
124
  "@react-router/serve": {