@react-router/dev 0.0.0-experimental-dc5ea5867 → 0.0.0-experimental-1ea0577

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/CHANGELOG.md CHANGED
@@ -1,67 +1,5 @@
1
1
  # `@react-router/dev`
2
2
 
3
- ## 7.6.2
4
-
5
- ### Patch Changes
6
-
7
- - Avoid additional `with-props` chunk in Framework Mode by moving route module component prop logic from the Vite plugin to `react-router` ([#13650](https://github.com/remix-run/react-router/pull/13650))
8
-
9
- - When `future.unstable_viteEnvironmentApi` is enabled and an absolute Vite `base` has been configured, ensure critical CSS is handled correctly during development ([#13598](https://github.com/remix-run/react-router/pull/13598))
10
-
11
- - Update `vite-node` ([#13673](https://github.com/remix-run/react-router/pull/13673))
12
-
13
- - Fix typegen for non-{.js,.jsx,.ts,.tsx} routes like .mdx ([#12453](https://github.com/remix-run/react-router/pull/12453))
14
-
15
- - Fix href types for optional dynamic params ([#13725](https://github.com/remix-run/react-router/pull/13725))
16
-
17
- 7.6.1 introduced fixes for `href` when using optional static segments,
18
- but those fixes caused regressions with how optional dynamic params worked in 7.6.0:
19
-
20
- ```ts
21
- // 7.6.0
22
- href("/users/:id?"); // ✅
23
- href("/users/:id?", { id: 1 }); // ✅
24
-
25
- // 7.6.1
26
- href("/users/:id?"); // ❌
27
- href("/users/:id?", { id: 1 }); // ❌
28
- ```
29
-
30
- Now, optional static segments are expanded into different paths for `href`, but optional dynamic params are not.
31
- This way `href` can unambiguously refer to an exact URL path, all while keeping the number of path options to a minimum.
32
-
33
- ```ts
34
- // 7.6.2
35
-
36
- // path: /users/:id?/edit?
37
- href("
38
- // ^ suggestions when cursor is here:
39
- //
40
- // /users/:id?
41
- // /users/:id?/edit
42
- ```
43
-
44
- Additionally, you can pass `params` from component props without needing to narrow them manually:
45
-
46
- ```ts
47
- declare const params: { id?: number };
48
-
49
- // 7.6.0
50
- href("/users/:id?", params);
51
-
52
- // 7.6.1
53
- href("/users/:id?", params); // ❌
54
- "id" in params ? href("/users/:id", params) : href("/users"); // works... but is annoying
55
-
56
- // 7.6.2
57
- href("/users/:id?", params); // restores behavior of 7.6.0
58
- ```
59
-
60
- - Updated dependencies:
61
- - `react-router@7.6.2`
62
- - `@react-router/node@7.6.2`
63
- - `@react-router/serve@7.6.2`
64
-
65
3
  ## 7.6.1
66
4
 
67
5
  ### Patch Changes
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-dc5ea5867
3
+ * @react-router/dev v0.0.0-experimental-1ea0577
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -130,11 +130,6 @@ async function createContext({
130
130
  }) {
131
131
  await preloadVite();
132
132
  const vite2 = getVite();
133
- const [{ ViteNodeServer }, { ViteNodeRunner }, { installSourcemapsSupport }] = await Promise.all([
134
- import("vite-node/server"),
135
- import("vite-node/client"),
136
- import("vite-node/source-map")
137
- ]);
138
133
  const devServer = await vite2.createServer({
139
134
  root,
140
135
  mode,
@@ -164,11 +159,11 @@ async function createContext({
164
159
  plugins: []
165
160
  });
166
161
  await devServer.pluginContainer.buildStart({});
167
- const server = new ViteNodeServer(devServer);
168
- installSourcemapsSupport({
162
+ const server = new import_server.ViteNodeServer(devServer);
163
+ (0, import_source_map.installSourcemapsSupport)({
169
164
  getSourceMap: (source) => server.getSourceMap(source)
170
165
  });
171
- const runner = new ViteNodeRunner({
166
+ const runner = new import_client.ViteNodeRunner({
172
167
  root: devServer.config.root,
173
168
  base: devServer.config.base,
174
169
  fetchModule(id) {
@@ -180,9 +175,13 @@ async function createContext({
180
175
  });
181
176
  return { devServer, server, runner };
182
177
  }
178
+ var import_server, import_client, import_source_map;
183
179
  var init_vite_node = __esm({
184
180
  "vite/vite-node.ts"() {
185
181
  "use strict";
182
+ import_server = require("vite-node/server");
183
+ import_client = require("vite-node/client");
184
+ import_source_map = require("vite-node/source-map");
186
185
  init_vite();
187
186
  init_ssr_externals();
188
187
  }
@@ -929,7 +928,7 @@ function generateRoutes(ctx) {
929
928
  lineages.set(route.id, lineage2);
930
929
  const fullpath2 = fullpath(lineage2);
931
930
  if (!fullpath2) continue;
932
- const pages = expand(fullpath2);
931
+ const pages = explodeOptionalSegments(fullpath2);
933
932
  pages.forEach((page) => allPages.add(page));
934
933
  lineage2.forEach(({ id }) => {
935
934
  let routePages = routeToPages.get(id);
@@ -1137,13 +1136,9 @@ function getRouteAnnotations({
1137
1136
  }
1138
1137
  function relativeImportSource(from, to) {
1139
1138
  let path8 = Path3.relative(Path3.dirname(from), to);
1140
- let extension = Path3.extname(path8);
1141
1139
  path8 = Path3.join(Path3.dirname(path8), Pathe.filename(path8));
1142
1140
  if (!path8.startsWith("../")) path8 = "./" + path8;
1143
- if (!extension || /\.(js|ts)x?$/.test(extension)) {
1144
- extension = ".js";
1145
- }
1146
- return path8 + extension;
1141
+ return path8 + ".js";
1147
1142
  }
1148
1143
  function rootDirsPath(ctx, typesPath) {
1149
1144
  const rel = Path3.relative(typesDirectory(ctx), typesPath);
@@ -1162,27 +1157,28 @@ function paramsType(path8) {
1162
1157
  })
1163
1158
  );
1164
1159
  }
1165
- function expand(fullpath2) {
1166
- function recurse(segments2, index) {
1167
- if (index === segments2.length) return [""];
1168
- const segment = segments2[index];
1169
- const isOptional = segment.endsWith("?");
1170
- const isDynamic = segment.startsWith(":");
1171
- const required = segment.replace(/\?$/, "");
1172
- const keep = !isOptional || isDynamic;
1173
- const kept = isDynamic ? segment : required;
1174
- const withoutSegment = recurse(segments2, index + 1);
1175
- const withSegment = withoutSegment.map((rest) => [kept, rest].join("/"));
1176
- if (keep) return withSegment;
1177
- return [...withoutSegment, ...withSegment];
1178
- }
1179
- const segments = fullpath2.split("/");
1180
- const expanded = /* @__PURE__ */ new Set();
1181
- for (let result of recurse(segments, 0)) {
1182
- if (result !== "/") result = result.replace(/\/$/, "");
1183
- expanded.add(result);
1184
- }
1185
- return expanded;
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
1181
+ );
1186
1182
  }
1187
1183
  var import_dedent, Path3, Pathe, t2;
1188
1184
  var init_generate = __esm({
@@ -1449,7 +1445,7 @@ async function cleanBuildDirectory(viteConfig, ctx) {
1449
1445
  return !relativePath.startsWith("..") && !path6.isAbsolute(relativePath);
1450
1446
  };
1451
1447
  if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
1452
- await (0, import_promises2.rm)(buildDirectory, { force: true, recursive: true });
1448
+ await fse.remove(buildDirectory);
1453
1449
  }
1454
1450
  }
1455
1451
  async function cleanViteManifests(environmentsOptions, ctx) {
@@ -1462,15 +1458,15 @@ async function cleanViteManifests(environmentsOptions, ctx) {
1462
1458
  );
1463
1459
  await Promise.all(
1464
1460
  viteManifestPaths.map(async (viteManifestPath) => {
1465
- let manifestExists = (0, import_node_fs3.existsSync)(viteManifestPath);
1461
+ let manifestExists = await fse.pathExists(viteManifestPath);
1466
1462
  if (!manifestExists) return;
1467
1463
  if (!ctx.viteManifestEnabled) {
1468
- await (0, import_promises2.rm)(viteManifestPath, { force: true, recursive: true });
1464
+ await fse.remove(viteManifestPath);
1469
1465
  }
1470
1466
  let viteDir = path6.dirname(viteManifestPath);
1471
- let viteDirFiles = await (0, import_promises2.readdir)(viteDir, { recursive: true });
1467
+ let viteDirFiles = await fse.readdir(viteDir);
1472
1468
  if (viteDirFiles.length === 0) {
1473
- await (0, import_promises2.rm)(viteDir, { force: true, recursive: true });
1469
+ await fse.remove(viteDir);
1474
1470
  }
1475
1471
  })
1476
1472
  );
@@ -1536,13 +1532,13 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1536
1532
  },
1537
1533
  build: {
1538
1534
  // We move SSR-only assets to client assets. Note that the
1539
- // SSR build can also emit code-split JS files (e.g., by
1535
+ // SSR build can also emit code-split JS files (e.g. by
1540
1536
  // dynamic import) under the same assets directory
1541
1537
  // regardless of "ssrEmitAssets" option, so we also need to
1542
- // keep these JS files to be kept as-is.
1538
+ // keep these JS files have to be kept as-is.
1543
1539
  ssrEmitAssets: true,
1544
1540
  copyPublicDir: false,
1545
- // The client only uses assets in the public directory
1541
+ // Assets in the public directory are only used by the client
1546
1542
  rollupOptions: {
1547
1543
  input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
1548
1544
  output: {
@@ -1566,7 +1562,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1566
1562
  route.file
1567
1563
  );
1568
1564
  let isRootRoute = route.file === ctx.reactRouterConfig.routes.root.file;
1569
- let code = (0, import_node_fs3.readFileSync)(routeFilePath, "utf-8");
1565
+ let code = fse.readFileSync(routeFilePath, "utf-8");
1570
1566
  return [
1571
1567
  `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
1572
1568
  ...ctx.reactRouterConfig.future.unstable_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
@@ -1635,19 +1631,18 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
1635
1631
  function isNonNullable(x) {
1636
1632
  return x != null;
1637
1633
  }
1638
- var import_node_crypto, import_node_fs3, import_promises2, path6, url, babel2, import_react_router2, import_es_module_lexer, import_tinyglobby, 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;
1634
+ 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;
1639
1635
  var init_plugin = __esm({
1640
1636
  "vite/plugin.ts"() {
1641
1637
  "use strict";
1642
1638
  import_node_crypto = require("crypto");
1643
- import_node_fs3 = require("fs");
1644
- import_promises2 = require("fs/promises");
1639
+ fs4 = __toESM(require("fs"));
1645
1640
  path6 = __toESM(require("path"));
1646
1641
  url = __toESM(require("url"));
1642
+ fse = __toESM(require("fs-extra"));
1647
1643
  babel2 = __toESM(require("@babel/core"));
1648
1644
  import_react_router2 = require("react-router");
1649
1645
  import_es_module_lexer = require("es-module-lexer");
1650
- import_tinyglobby = require("tinyglobby");
1651
1646
  import_pick3 = __toESM(require("lodash/pick"));
1652
1647
  import_jsesc = __toESM(require("jsesc"));
1653
1648
  import_picocolors4 = __toESM(require("picocolors"));
@@ -1703,9 +1698,7 @@ var init_plugin = __esm({
1703
1698
  "config",
1704
1699
  "defaults"
1705
1700
  );
1706
- defaultEntries = (0, import_node_fs3.readdirSync)(defaultEntriesDir).map(
1707
- (filename2) => path6.join(defaultEntriesDir, filename2)
1708
- );
1701
+ defaultEntries = fse.readdirSync(defaultEntriesDir).map((filename2) => path6.join(defaultEntriesDir, filename2));
1709
1702
  invariant(defaultEntries.length > 0, "No default entries found");
1710
1703
  REACT_REFRESH_HEADER = `
1711
1704
  import RefreshRuntime from "${virtualHmrRuntime.id}";
@@ -1985,9 +1978,8 @@ var import_semver = __toESM(require("semver"));
1985
1978
  var import_picocolors8 = __toESM(require("picocolors"));
1986
1979
 
1987
1980
  // cli/commands.ts
1988
- var import_node_fs4 = require("fs");
1989
- var import_promises3 = require("fs/promises");
1990
1981
  var path7 = __toESM(require("path"));
1982
+ var import_fs_extra = __toESM(require("fs-extra"));
1991
1983
  var import_package_json2 = __toESM(require("@npmcli/package-json"));
1992
1984
  var import_exit_hook = __toESM(require("exit-hook"));
1993
1985
  var import_picocolors7 = __toESM(require("picocolors"));
@@ -2161,21 +2153,21 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
2161
2153
  let useTypeScript = flags.typescript ?? true;
2162
2154
  let outputExtension = useTypeScript ? "tsx" : "jsx";
2163
2155
  let outputEntry = `${entry}.${outputExtension}`;
2164
- let outputFile = path7.resolve(appDirectory, outputEntry);
2156
+ let outputFile2 = path7.resolve(appDirectory, outputEntry);
2165
2157
  if (!useTypeScript) {
2166
2158
  let javascript = transpile(contents, {
2167
2159
  cwd: rootDirectory,
2168
2160
  filename: isServerEntry ? defaultEntryServer : defaultEntryClient
2169
2161
  });
2170
- await (0, import_promises3.writeFile)(outputFile, javascript, "utf-8");
2162
+ await import_fs_extra.default.writeFile(outputFile2, javascript, "utf-8");
2171
2163
  } else {
2172
- await (0, import_promises3.writeFile)(outputFile, contents, "utf-8");
2164
+ await import_fs_extra.default.writeFile(outputFile2, contents, "utf-8");
2173
2165
  }
2174
2166
  console.log(
2175
2167
  import_picocolors7.default.blue(
2176
2168
  `Entry file ${entry} created at ${path7.relative(
2177
2169
  rootDirectory,
2178
- outputFile
2170
+ outputFile2
2179
2171
  )}.`
2180
2172
  )
2181
2173
  );
@@ -2189,7 +2181,7 @@ function resolveRootDirectory(root, flags) {
2189
2181
  async function checkForEntry(rootDirectory, appDirectory, entries2) {
2190
2182
  for (let entry of entries2) {
2191
2183
  let entryPath = path7.resolve(appDirectory, entry);
2192
- let exists = (0, import_node_fs4.existsSync)(entryPath);
2184
+ let exists = await import_fs_extra.default.pathExists(entryPath);
2193
2185
  if (exists) {
2194
2186
  let relative7 = path7.relative(rootDirectory, entryPath);
2195
2187
  console.error(import_picocolors7.default.red(`Entry file ${relative7} already exists.`));
@@ -2199,12 +2191,12 @@ async function checkForEntry(rootDirectory, appDirectory, entries2) {
2199
2191
  }
2200
2192
  async function createServerEntry(rootDirectory, appDirectory, inputFile) {
2201
2193
  await checkForEntry(rootDirectory, appDirectory, serverEntries);
2202
- let contents = await (0, import_promises3.readFile)(inputFile, "utf-8");
2194
+ let contents = await import_fs_extra.default.readFile(inputFile, "utf-8");
2203
2195
  return contents;
2204
2196
  }
2205
2197
  async function createClientEntry(rootDirectory, appDirectory, inputFile) {
2206
2198
  await checkForEntry(rootDirectory, appDirectory, clientEntries);
2207
- let contents = await (0, import_promises3.readFile)(inputFile, "utf-8");
2199
+ let contents = await import_fs_extra.default.readFile(inputFile, "utf-8");
2208
2200
  return contents;
2209
2201
  }
2210
2202
  async function typegen(root, flags) {
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-dc5ea5867
2
+ * @react-router/dev v0.0.0-experimental-1ea0577
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-dc5ea5867
2
+ * @react-router/dev v0.0.0-experimental-1ea0577
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,6 +1,6 @@
1
1
  import { UNSAFE_MiddlewareEnabled, unstable_InitialContext, AppLoadContext } from 'react-router';
2
2
  import { Plugin } from 'vite';
3
- import { PlatformProxy, GetPlatformProxyOptions } from 'wrangler';
3
+ import { GetPlatformProxyOptions, PlatformProxy } from 'wrangler';
4
4
 
5
5
  type MaybePromise<T> = T | Promise<T>;
6
6
  type CfProperties = Record<string, unknown>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-dc5ea5867
2
+ * @react-router/dev v0.0.0-experimental-1ea0577
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -174,6 +174,11 @@ var import_node_fs = __toESM(require("fs"));
174
174
  var import_node_child_process = require("child_process");
175
175
  var import_package_json = __toESM(require("@npmcli/package-json"));
176
176
 
177
+ // vite/vite-node.ts
178
+ var import_server = require("vite-node/server");
179
+ var import_client = require("vite-node/client");
180
+ var import_source_map = require("vite-node/source-map");
181
+
177
182
  // vite/ssr-externals.ts
178
183
  var ssrExternals = isReactRouterRepo() ? [
179
184
  // This is only needed within this repo because these packages
@@ -197,11 +202,6 @@ async function createContext({
197
202
  }) {
198
203
  await preloadVite();
199
204
  const vite2 = getVite();
200
- const [{ ViteNodeServer }, { ViteNodeRunner }, { installSourcemapsSupport }] = await Promise.all([
201
- import("vite-node/server"),
202
- import("vite-node/client"),
203
- import("vite-node/source-map")
204
- ]);
205
205
  const devServer = await vite2.createServer({
206
206
  root,
207
207
  mode,
@@ -231,11 +231,11 @@ async function createContext({
231
231
  plugins: []
232
232
  });
233
233
  await devServer.pluginContainer.buildStart({});
234
- const server = new ViteNodeServer(devServer);
235
- installSourcemapsSupport({
234
+ const server = new import_server.ViteNodeServer(devServer);
235
+ (0, import_source_map.installSourcemapsSupport)({
236
236
  getSourceMap: (source) => server.getSourceMap(source)
237
237
  });
238
- const runner = new ViteNodeRunner({
238
+ const runner = new import_client.ViteNodeRunner({
239
239
  root: devServer.config.root,
240
240
  base: devServer.config.base,
241
241
  fetchModule(id) {
package/dist/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-dc5ea5867
2
+ * @react-router/dev v0.0.0-experimental-1ea0577
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -46,14 +46,13 @@ module.exports = __toCommonJS(vite_exports);
46
46
 
47
47
  // vite/plugin.ts
48
48
  var import_node_crypto = require("crypto");
49
- var import_node_fs2 = require("fs");
50
- var import_promises2 = require("fs/promises");
49
+ var fs3 = __toESM(require("fs"));
51
50
  var path5 = __toESM(require("path"));
52
51
  var url = __toESM(require("url"));
52
+ var fse = __toESM(require("fs-extra"));
53
53
  var babel = __toESM(require("@babel/core"));
54
54
  var import_react_router2 = require("react-router");
55
55
  var import_es_module_lexer = require("es-module-lexer");
56
- var import_tinyglobby = require("tinyglobby");
57
56
  var import_pick3 = __toESM(require("lodash/pick"));
58
57
  var import_jsesc = __toESM(require("jsesc"));
59
58
  var import_picocolors3 = __toESM(require("picocolors"));
@@ -69,6 +68,11 @@ var import_node_fs = __toESM(require("fs"));
69
68
  var import_node_child_process = require("child_process");
70
69
  var import_package_json = __toESM(require("@npmcli/package-json"));
71
70
 
71
+ // vite/vite-node.ts
72
+ var import_server = require("vite-node/server");
73
+ var import_client = require("vite-node/client");
74
+ var import_source_map = require("vite-node/source-map");
75
+
72
76
  // vite/vite.ts
73
77
  var import_pathe2 = __toESM(require("pathe"));
74
78
 
@@ -136,11 +140,6 @@ async function createContext({
136
140
  }) {
137
141
  await preloadVite();
138
142
  const vite2 = getVite();
139
- const [{ ViteNodeServer }, { ViteNodeRunner }, { installSourcemapsSupport }] = await Promise.all([
140
- import("vite-node/server"),
141
- import("vite-node/client"),
142
- import("vite-node/source-map")
143
- ]);
144
143
  const devServer = await vite2.createServer({
145
144
  root,
146
145
  mode,
@@ -170,11 +169,11 @@ async function createContext({
170
169
  plugins: []
171
170
  });
172
171
  await devServer.pluginContainer.buildStart({});
173
- const server = new ViteNodeServer(devServer);
174
- installSourcemapsSupport({
172
+ const server = new import_server.ViteNodeServer(devServer);
173
+ (0, import_source_map.installSourcemapsSupport)({
175
174
  getSourceMap: (source) => server.getSourceMap(source)
176
175
  });
177
- const runner = new ViteNodeRunner({
176
+ const runner = new import_client.ViteNodeRunner({
178
177
  root: devServer.config.root,
179
178
  base: devServer.config.base,
180
179
  fetchModule(id) {
@@ -916,7 +915,7 @@ function generateRoutes(ctx) {
916
915
  lineages.set(route.id, lineage2);
917
916
  const fullpath2 = fullpath(lineage2);
918
917
  if (!fullpath2) continue;
919
- const pages = expand(fullpath2);
918
+ const pages = explodeOptionalSegments(fullpath2);
920
919
  pages.forEach((page) => allPages.add(page));
921
920
  lineage2.forEach(({ id }) => {
922
921
  let routePages = routeToPages.get(id);
@@ -1124,13 +1123,9 @@ function getRouteAnnotations({
1124
1123
  }
1125
1124
  function relativeImportSource(from, to) {
1126
1125
  let path6 = Path3.relative(Path3.dirname(from), to);
1127
- let extension = Path3.extname(path6);
1128
1126
  path6 = Path3.join(Path3.dirname(path6), Pathe.filename(path6));
1129
1127
  if (!path6.startsWith("../")) path6 = "./" + path6;
1130
- if (!extension || /\.(js|ts)x?$/.test(extension)) {
1131
- extension = ".js";
1132
- }
1133
- return path6 + extension;
1128
+ return path6 + ".js";
1134
1129
  }
1135
1130
  function rootDirsPath(ctx, typesPath) {
1136
1131
  const rel = Path3.relative(typesDirectory(ctx), typesPath);
@@ -1149,27 +1144,28 @@ function paramsType(path6) {
1149
1144
  })
1150
1145
  );
1151
1146
  }
1152
- function expand(fullpath2) {
1153
- function recurse(segments2, index) {
1154
- if (index === segments2.length) return [""];
1155
- const segment = segments2[index];
1156
- const isOptional = segment.endsWith("?");
1157
- const isDynamic = segment.startsWith(":");
1158
- const required = segment.replace(/\?$/, "");
1159
- const keep = !isOptional || isDynamic;
1160
- const kept = isDynamic ? segment : required;
1161
- const withoutSegment = recurse(segments2, index + 1);
1162
- const withSegment = withoutSegment.map((rest) => [kept, rest].join("/"));
1163
- if (keep) return withSegment;
1164
- return [...withoutSegment, ...withSegment];
1147
+ function explodeOptionalSegments(path6) {
1148
+ let segments = path6.split("/");
1149
+ if (segments.length === 0) return [];
1150
+ let [first, ...rest] = segments;
1151
+ let isOptional = first.endsWith("?");
1152
+ let required = first.replace(/\?$/, "");
1153
+ if (rest.length === 0) {
1154
+ return isOptional ? [required, ""] : [required];
1165
1155
  }
1166
- const segments = fullpath2.split("/");
1167
- const expanded = /* @__PURE__ */ new Set();
1168
- for (let result of recurse(segments, 0)) {
1169
- if (result !== "/") result = result.replace(/\/$/, "");
1170
- expanded.add(result);
1156
+ let restExploded = explodeOptionalSegments(rest.join("/"));
1157
+ let result = [];
1158
+ result.push(
1159
+ ...restExploded.map(
1160
+ (subpath) => subpath === "" ? required : [required, subpath].join("/")
1161
+ )
1162
+ );
1163
+ if (isOptional) {
1164
+ result.push(...restExploded);
1171
1165
  }
1172
- return expanded;
1166
+ return result.map(
1167
+ (exploded) => path6.startsWith("/") && exploded === "" ? "/" : exploded
1168
+ );
1173
1169
  }
1174
1170
 
1175
1171
  // typegen/index.ts
@@ -2448,8 +2444,8 @@ function dedupe(array2) {
2448
2444
  return [...new Set(array2)];
2449
2445
  }
2450
2446
  var writeFileSafe = async (file, contents) => {
2451
- await (0, import_promises2.mkdir)(path5.dirname(file), { recursive: true });
2452
- await (0, import_promises2.writeFile)(file, contents);
2447
+ await fse.ensureDir(path5.dirname(file));
2448
+ await fse.writeFile(file, contents);
2453
2449
  };
2454
2450
  var getExportNames = (code) => {
2455
2451
  let [, exportSpecifiers] = (0, import_es_module_lexer.parse)(code);
@@ -2483,7 +2479,7 @@ var compileRouteFile = async (viteChildCompiler, ctx, routeFile, readRouteFile)
2483
2479
  };
2484
2480
  let [id, code] = await Promise.all([
2485
2481
  resolveId(),
2486
- readRouteFile?.() ?? (0, import_promises2.readFile)(routePath, "utf-8"),
2482
+ readRouteFile?.() ?? fse.readFile(routePath, "utf-8"),
2487
2483
  // pluginContainer.transform(...) fails if we don't do this first:
2488
2484
  moduleGraph.ensureEntryFromUrl(url2, ssr)
2489
2485
  ]);
@@ -2545,9 +2541,7 @@ var defaultEntriesDir = path5.resolve(
2545
2541
  "config",
2546
2542
  "defaults"
2547
2543
  );
2548
- var defaultEntries = (0, import_node_fs2.readdirSync)(defaultEntriesDir).map(
2549
- (filename2) => path5.join(defaultEntriesDir, filename2)
2550
- );
2544
+ var defaultEntries = fse.readdirSync(defaultEntriesDir).map((filename2) => path5.join(defaultEntriesDir, filename2));
2551
2545
  invariant(defaultEntries.length > 0, "No default entries found");
2552
2546
  var reactRouterDevLoadContext = () => void 0;
2553
2547
  var reactRouterVitePlugin = () => {
@@ -2684,7 +2678,7 @@ var reactRouterVitePlugin = () => {
2684
2678
  ` : ""}`;
2685
2679
  };
2686
2680
  let loadViteManifest = async (directory) => {
2687
- let manifestContents = await (0, import_promises2.readFile)(
2681
+ let manifestContents = await fse.readFile(
2688
2682
  path5.resolve(directory, ".vite", "manifest.json"),
2689
2683
  "utf-8"
2690
2684
  );
@@ -2706,7 +2700,7 @@ var reactRouterVitePlugin = () => {
2706
2700
  };
2707
2701
  let generateSriManifest = async (ctx2) => {
2708
2702
  let clientBuildDirectory = getClientBuildDirectory(ctx2.reactRouterConfig);
2709
- let entries = (0, import_node_fs2.readdirSync)(clientBuildDirectory, {
2703
+ let entries = fs3.readdirSync(clientBuildDirectory, {
2710
2704
  withFileTypes: true,
2711
2705
  recursive: true
2712
2706
  });
@@ -2716,7 +2710,7 @@ var reactRouterVitePlugin = () => {
2716
2710
  const entryNormalizedPath = "parentPath" in entry && typeof entry.parentPath === "string" ? entry.parentPath : entry.path;
2717
2711
  let contents;
2718
2712
  try {
2719
- contents = await (0, import_promises2.readFile)(
2713
+ contents = await fse.readFile(
2720
2714
  path5.join(entryNormalizedPath, entry.name),
2721
2715
  "utf-8"
2722
2716
  );
@@ -2972,7 +2966,6 @@ var reactRouterVitePlugin = () => {
2972
2966
  config: async (_viteUserConfig, _viteConfigEnv) => {
2973
2967
  await preloadVite();
2974
2968
  let vite2 = getVite();
2975
- let viteMajorVersion = parseInt(vite2.version.split(".")[0], 10);
2976
2969
  viteUserConfig = _viteUserConfig;
2977
2970
  viteConfigEnv = _viteConfigEnv;
2978
2971
  viteCommand = viteConfigEnv.command;
@@ -3002,7 +2995,7 @@ var reactRouterVitePlugin = () => {
3002
2995
  vite2.loadEnv(
3003
2996
  viteConfigEnv.mode,
3004
2997
  viteUserConfig.envDir ?? ctx.rootDirectory,
3005
- // We override the default prefix of "VITE_" with a blank string since
2998
+ // We override default prefix of "VITE_" with a blank string since
3006
2999
  // we're targeting the server, so we want to load all environment
3007
3000
  // variables, not just those explicitly marked for the client
3008
3001
  ""
@@ -3031,13 +3024,7 @@ var reactRouterVitePlugin = () => {
3031
3024
  ...Object.values(ctx.reactRouterConfig.routes).map(
3032
3025
  (route) => resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
3033
3026
  )
3034
- ].map(
3035
- (entry) => (
3036
- // In Vite 7, the `optimizeDeps.entries` option only accepts glob patterns.
3037
- // In prior versions, absolute file paths were treated differently.
3038
- viteMajorVersion >= 7 ? (0, import_tinyglobby.escapePath)(entry) : entry
3039
- )
3040
- ) : [],
3027
+ ] : [],
3041
3028
  include: [
3042
3029
  // Pre-bundle React dependencies to avoid React duplicates,
3043
3030
  // even if React dependencies are not direct dependencies.
@@ -3072,7 +3059,7 @@ var reactRouterVitePlugin = () => {
3072
3059
  conditions: viteCommand === "build" ? viteClientConditions : ["development", ...viteClientConditions]
3073
3060
  },
3074
3061
  base: viteUserConfig.base,
3075
- // When consumer provides an allowlist for files that can be read by
3062
+ // When consumer provides an allow list for files that can be read by
3076
3063
  // the server, ensure that the default entry files are included.
3077
3064
  // If we don't do this and a default entry file is used, the server
3078
3065
  // will throw an error that the file is not allowed to be read.
@@ -3364,15 +3351,15 @@ var reactRouterVitePlugin = () => {
3364
3351
  let src = path5.join(serverBuildDirectory, ssrAssetPath);
3365
3352
  let dest = path5.join(clientBuildDirectory, ssrAssetPath);
3366
3353
  if (!userSsrEmitAssets) {
3367
- if (!(0, import_node_fs2.existsSync)(dest)) {
3368
- await (0, import_promises2.rename)(src, dest);
3354
+ if (!fse.existsSync(dest)) {
3355
+ await fse.move(src, dest);
3369
3356
  movedAssetPaths.push(dest);
3370
3357
  } else {
3371
- await (0, import_promises2.rm)(src, { force: true, recursive: true });
3358
+ await fse.remove(src);
3372
3359
  removedAssetPaths.push(dest);
3373
3360
  }
3374
- } else if (!(0, import_node_fs2.existsSync)(dest)) {
3375
- await (0, import_promises2.cp)(src, dest, { recursive: true });
3361
+ } else if (!fse.existsSync(dest)) {
3362
+ await fse.copy(src, dest);
3376
3363
  copiedAssetPaths.push(dest);
3377
3364
  }
3378
3365
  }
@@ -3383,7 +3370,7 @@ var reactRouterVitePlugin = () => {
3383
3370
  await Promise.all(
3384
3371
  ssrCssPaths.map(async (cssPath) => {
3385
3372
  let src = path5.join(serverBuildDirectory, cssPath);
3386
- await (0, import_promises2.rm)(src, { force: true, recursive: true });
3373
+ await fse.remove(src);
3387
3374
  removedAssetPaths.push(src);
3388
3375
  })
3389
3376
  );
@@ -3394,9 +3381,9 @@ var reactRouterVitePlugin = () => {
3394
3381
  await Promise.all(
3395
3382
  Array.from(cleanedAssetDirs).map(async (dir) => {
3396
3383
  try {
3397
- const files = await (0, import_promises2.readdir)(dir, { recursive: true });
3384
+ const files = await fse.readdir(dir);
3398
3385
  if (files.length === 0) {
3399
- await (0, import_promises2.rm)(dir, { force: true, recursive: true });
3386
+ await fse.remove(dir);
3400
3387
  }
3401
3388
  } catch {
3402
3389
  }
@@ -3460,7 +3447,7 @@ var reactRouterVitePlugin = () => {
3460
3447
  "due to ssr:false"
3461
3448
  ].join(" ")
3462
3449
  );
3463
- (0, import_node_fs2.rmSync)(serverBuildDirectory, { force: true, recursive: true });
3450
+ fse.removeSync(serverBuildDirectory);
3464
3451
  }
3465
3452
  }
3466
3453
  },
@@ -3478,7 +3465,7 @@ var reactRouterVitePlugin = () => {
3478
3465
  // primarily ensures code is never duplicated across a route module and
3479
3466
  // its chunks. If we didn't have this plugin, any app that explicitly
3480
3467
  // imports a route module would result in duplicate code since the app
3481
- // would contain code for both the unprocessed route module and its
3468
+ // would contain code for both the unprocessed route module as well as its
3482
3469
  // individual chunks. This is because, since they have different module
3483
3470
  // IDs, they are treated as completely separate modules even though they
3484
3471
  // all reference the same underlying file. This plugin addresses this by
@@ -3784,8 +3771,11 @@ var reactRouterVitePlugin = () => {
3784
3771
  );
3785
3772
  return [
3786
3773
  "const exports = {}",
3787
- await (0, import_promises2.readFile)(reactRefreshRuntimePath, "utf8"),
3788
- await (0, import_promises2.readFile)(require.resolve("./static/refresh-utils.cjs"), "utf8"),
3774
+ await fse.readFile(reactRefreshRuntimePath, "utf8"),
3775
+ await fse.readFile(
3776
+ require.resolve("./static/refresh-utils.cjs"),
3777
+ "utf8"
3778
+ ),
3789
3779
  "export default exports"
3790
3780
  ].join("\n");
3791
3781
  }
@@ -3868,10 +3858,10 @@ var reactRouterVitePlugin = () => {
3868
3858
  {
3869
3859
  name: "react-router-server-change-trigger-client-hmr",
3870
3860
  // This hook is only available in Vite v6+ so this is a no-op in v5.
3871
- // Previously, the server and client modules were shared in a single module
3861
+ // Previously the server and client modules were shared in a single module
3872
3862
  // graph. This meant that changes to server code automatically resulted in
3873
- // client HMR updates. In Vite v6+, these module graphs are separate from
3874
- // each other, so we need to manually trigger client HMR updates if server
3863
+ // client HMR updates. In Vite v6+ these module graphs are separate from
3864
+ // each other so we need to manually trigger client HMR updates if server
3875
3865
  // code has changed.
3876
3866
  hotUpdate({ server, modules }) {
3877
3867
  if (this.environment.name !== "ssr" && modules.length <= 0) {
@@ -4065,7 +4055,7 @@ async function handleSpaMode(viteConfig, reactRouterConfig, serverBuildDirectory
4065
4055
  "SPA Mode: Did you forget to include `<Scripts/>` in your root route? Your pre-rendered HTML cannot hydrate without `<Scripts />`."
4066
4056
  );
4067
4057
  }
4068
- await (0, import_promises2.writeFile)(path5.join(clientBuildDirectory, filename2), html);
4058
+ await fse.writeFile(path5.join(clientBuildDirectory, filename2), html);
4069
4059
  let prettyDir = path5.relative(process.cwd(), clientBuildDirectory);
4070
4060
  let prettyPath = path5.join(prettyDir, filename2);
4071
4061
  if (build.prerender.length > 0) {
@@ -4196,8 +4186,8 @@ ${normalizedPath}`
4196
4186
  }
4197
4187
  let outdir = path5.relative(process.cwd(), clientBuildDirectory);
4198
4188
  let outfile = path5.join(outdir, ...normalizedPath.split("/"));
4199
- await (0, import_promises2.mkdir)(path5.dirname(outfile), { recursive: true });
4200
- await (0, import_promises2.writeFile)(outfile, data);
4189
+ await fse.ensureDir(path5.dirname(outfile));
4190
+ await fse.outputFile(outfile, data);
4201
4191
  viteConfig.logger.info(
4202
4192
  `Prerender (data): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
4203
4193
  );
@@ -4235,8 +4225,8 @@ ${html}`
4235
4225
  }
4236
4226
  let outdir = path5.relative(process.cwd(), clientBuildDirectory);
4237
4227
  let outfile = path5.join(outdir, ...normalizedPath.split("/"), "index.html");
4238
- await (0, import_promises2.mkdir)(path5.dirname(outfile), { recursive: true });
4239
- await (0, import_promises2.writeFile)(outfile, html);
4228
+ await fse.ensureDir(path5.dirname(outfile));
4229
+ await fse.outputFile(outfile, html);
4240
4230
  viteConfig.logger.info(
4241
4231
  `Prerender (html): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
4242
4232
  );
@@ -4254,8 +4244,8 @@ ${content.toString("utf8")}`
4254
4244
  }
4255
4245
  let outdir = path5.relative(process.cwd(), clientBuildDirectory);
4256
4246
  let outfile = path5.join(outdir, ...normalizedPath.split("/"));
4257
- await (0, import_promises2.mkdir)(path5.dirname(outfile), { recursive: true });
4258
- await (0, import_promises2.writeFile)(outfile, content);
4247
+ await fse.ensureDir(path5.dirname(outfile));
4248
+ await fse.outputFile(outfile, content);
4259
4249
  viteConfig.logger.info(
4260
4250
  `Prerender (resource): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
4261
4251
  );
@@ -4508,7 +4498,7 @@ async function cleanBuildDirectory(viteConfig, ctx) {
4508
4498
  return !relativePath.startsWith("..") && !path5.isAbsolute(relativePath);
4509
4499
  };
4510
4500
  if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
4511
- await (0, import_promises2.rm)(buildDirectory, { force: true, recursive: true });
4501
+ await fse.remove(buildDirectory);
4512
4502
  }
4513
4503
  }
4514
4504
  async function cleanViteManifests(environmentsOptions, ctx) {
@@ -4521,15 +4511,15 @@ async function cleanViteManifests(environmentsOptions, ctx) {
4521
4511
  );
4522
4512
  await Promise.all(
4523
4513
  viteManifestPaths.map(async (viteManifestPath) => {
4524
- let manifestExists = (0, import_node_fs2.existsSync)(viteManifestPath);
4514
+ let manifestExists = await fse.pathExists(viteManifestPath);
4525
4515
  if (!manifestExists) return;
4526
4516
  if (!ctx.viteManifestEnabled) {
4527
- await (0, import_promises2.rm)(viteManifestPath, { force: true, recursive: true });
4517
+ await fse.remove(viteManifestPath);
4528
4518
  }
4529
4519
  let viteDir = path5.dirname(viteManifestPath);
4530
- let viteDirFiles = await (0, import_promises2.readdir)(viteDir, { recursive: true });
4520
+ let viteDirFiles = await fse.readdir(viteDir);
4531
4521
  if (viteDirFiles.length === 0) {
4532
- await (0, import_promises2.rm)(viteDir, { force: true, recursive: true });
4522
+ await fse.remove(viteDir);
4533
4523
  }
4534
4524
  })
4535
4525
  );
@@ -4665,13 +4655,13 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
4665
4655
  },
4666
4656
  build: {
4667
4657
  // We move SSR-only assets to client assets. Note that the
4668
- // SSR build can also emit code-split JS files (e.g., by
4658
+ // SSR build can also emit code-split JS files (e.g. by
4669
4659
  // dynamic import) under the same assets directory
4670
4660
  // regardless of "ssrEmitAssets" option, so we also need to
4671
- // keep these JS files to be kept as-is.
4661
+ // keep these JS files have to be kept as-is.
4672
4662
  ssrEmitAssets: true,
4673
4663
  copyPublicDir: false,
4674
- // The client only uses assets in the public directory
4664
+ // Assets in the public directory are only used by the client
4675
4665
  rollupOptions: {
4676
4666
  input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
4677
4667
  output: {
@@ -4695,7 +4685,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
4695
4685
  route.file
4696
4686
  );
4697
4687
  let isRootRoute = route.file === ctx.reactRouterConfig.routes.root.file;
4698
- let code = (0, import_node_fs2.readFileSync)(routeFilePath, "utf-8");
4688
+ let code = fse.readFileSync(routeFilePath, "utf-8");
4699
4689
  return [
4700
4690
  `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
4701
4691
  ...ctx.reactRouterConfig.future.unstable_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
- "version": "0.0.0-experimental-dc5ea5867",
3
+ "version": "0.0.0-experimental-1ea0577",
4
4
  "description": "Dev tools and CLI for React Router",
5
5
  "homepage": "https://reactrouter.com",
6
6
  "bugs": {
@@ -75,6 +75,7 @@
75
75
  "dedent": "^1.5.3",
76
76
  "es-module-lexer": "^1.3.1",
77
77
  "exit-hook": "2.2.1",
78
+ "fs-extra": "^10.0.0",
78
79
  "jsesc": "3.0.2",
79
80
  "lodash": "^4.17.21",
80
81
  "pathe": "^1.1.2",
@@ -83,10 +84,9 @@
83
84
  "react-refresh": "^0.14.0",
84
85
  "semver": "^7.3.7",
85
86
  "set-cookie-parser": "^2.6.0",
86
- "tinyglobby": "^0.2.14",
87
87
  "valibot": "^0.41.0",
88
88
  "vite-node": "^3.1.4",
89
- "@react-router/node": "0.0.0-experimental-dc5ea5867"
89
+ "@react-router/node": "0.0.0-experimental-1ea0577"
90
90
  },
91
91
  "devDependencies": {
92
92
  "@types/babel__core": "^7.20.5",
@@ -94,6 +94,7 @@
94
94
  "@types/babel__traverse": "^7.20.5",
95
95
  "@types/dedent": "^0.7.0",
96
96
  "@types/express": "^4.17.9",
97
+ "@types/fs-extra": "^8.1.2",
97
98
  "@types/jsesc": "^3.0.1",
98
99
  "@types/lodash": "^4.14.182",
99
100
  "@types/node": "^20.0.0",
@@ -109,15 +110,15 @@
109
110
  "vite": "^6.1.0",
110
111
  "wireit": "0.14.9",
111
112
  "wrangler": "^4.2.0",
112
- "react-router": "^0.0.0-experimental-dc5ea5867",
113
- "@react-router/serve": "0.0.0-experimental-dc5ea5867"
113
+ "@react-router/serve": "0.0.0-experimental-1ea0577",
114
+ "react-router": "^0.0.0-experimental-1ea0577"
114
115
  },
115
116
  "peerDependencies": {
116
117
  "typescript": "^5.1.0",
117
- "vite": "^5.1.0 || ^6.0.0 || ^7.0.0",
118
+ "vite": "^5.1.0 || ^6.0.0",
118
119
  "wrangler": "^3.28.2 || ^4.0.0",
119
- "@react-router/serve": "^0.0.0-experimental-dc5ea5867",
120
- "react-router": "^0.0.0-experimental-dc5ea5867"
120
+ "@react-router/serve": "^0.0.0-experimental-1ea0577",
121
+ "react-router": "^0.0.0-experimental-1ea0577"
121
122
  },
122
123
  "peerDependenciesMeta": {
123
124
  "@react-router/serve": {