@c0va23/react-router-dev 7.10.1 → 7.13.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/CHANGELOG.md CHANGED
@@ -1,5 +1,89 @@
1
1
  # `@react-router/dev`
2
2
 
3
+ ## 7.13.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies:
8
+ - `react-router@7.13.1`
9
+ - `@react-router/node@7.13.1`
10
+ - `@react-router/serve@7.13.1`
11
+
12
+ ## 7.13.0
13
+
14
+ ### Patch Changes
15
+
16
+ - Bump @remix-run/node-fetch-server dep ([#14704](https://github.com/remix-run/react-router/pull/14704))
17
+ - Updated dependencies:
18
+ - `react-router@7.13.0`
19
+ - `@react-router/node@7.13.0`
20
+ - `@react-router/serve@7.13.0`
21
+
22
+ ## 7.12.0
23
+
24
+ ### Minor Changes
25
+
26
+ - Add additional layer of CSRF protection by rejecting submissions to UI routes from external origins. If you need to permit access to specific external origins, you can specify them in the `react-router.config.ts` config `allowedActionOrigins` field. ([#14708](https://github.com/remix-run/react-router/pull/14708))
27
+
28
+ ### Patch Changes
29
+
30
+ - Fix `Maximum call stack size exceeded` errors when HMR is triggered against code with cyclic imports ([#14522](https://github.com/remix-run/react-router/pull/14522))
31
+
32
+ - fix(vite): Skip SSR middleware in preview server for SPA mode ([#14673](https://github.com/remix-run/react-router/pull/14673))
33
+
34
+ - \[UNSTABLE] Add a new `future.unstable_trailingSlashAwareDataRequests` flag to provide consistent behavior of `request.pathname` inside `middleware`, `loader`, and `action` functions on document and data requests when a trailing slash is present in the browser URL. ([#14644](https://github.com/remix-run/react-router/pull/14644))
35
+
36
+ Currently, your HTTP and `request` pathnames would be as follows for `/a/b/c` and `/a/b/c/`
37
+
38
+ | URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
39
+ | ------------ | ----------------- | ------------------------ |
40
+ | **Document** | `/a/b/c` | `/a/b/c` ✅ |
41
+ | **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
42
+
43
+ | URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
44
+ | ------------- | ----------------- | ------------------------ |
45
+ | **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
46
+ | **Data** | `/a/b/c.data` | `/a/b/c` ⚠️ |
47
+
48
+ With this flag enabled, these pathnames will be made consistent though a new `_.data` format for client-side `.data` requests:
49
+
50
+ | URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
51
+ | ------------ | ----------------- | ------------------------ |
52
+ | **Document** | `/a/b/c` | `/a/b/c` ✅ |
53
+ | **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
54
+
55
+ | URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
56
+ | ------------- | ------------------ | ------------------------ |
57
+ | **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
58
+ | **Data** | `/a/b/c/_.data` ⬅️ | `/a/b/c/` ✅ |
59
+
60
+ This a bug fix but we are putting it behind an opt-in flag because it has the potential to be a "breaking bug fix" if you are relying on the URL format for any other application or caching logic.
61
+
62
+ Enabling this flag also changes the format of client side `.data` requests from `/_root.data` to `/_.data` when navigating to `/` to align with the new format. This does not impact the `request` pathname which is still `/` in all cases.
63
+
64
+ - Updated dependencies:
65
+ - `react-router@7.12.0`
66
+ - `@react-router/node@7.12.0`
67
+ - `@react-router/serve@7.12.0`
68
+
69
+ ## 7.11.0
70
+
71
+ ### Minor Changes
72
+
73
+ - feat: add `vite preview` support ([#14507](https://github.com/remix-run/react-router/pull/14507))
74
+
75
+ ### Patch Changes
76
+
77
+ - rsc framework mode manual chunking for react and react-router deps ([#14655](https://github.com/remix-run/react-router/pull/14655))
78
+ - add support for throwing redirect Response's at RSC render time ([#14596](https://github.com/remix-run/react-router/pull/14596))
79
+ - support custom entrypoints for RSC framework mode ([#14643](https://github.com/remix-run/react-router/pull/14643))
80
+ - `routeRSCServerRequest` replace `fetchServer` with `serverResponse` ([#14597](https://github.com/remix-run/react-router/pull/14597))
81
+ - rsc framewlrk mode - optimize react-server-dom-webpack if in project package.json ([#14656](https://github.com/remix-run/react-router/pull/14656))
82
+ - Updated dependencies:
83
+ - `react-router@7.11.0`
84
+ - `@react-router/serve@7.11.0`
85
+ - `@react-router/node@7.11.0`
86
+
3
87
  ## 7.10.1
4
88
 
5
89
  ### Patch Changes
@@ -229,7 +313,6 @@
229
313
  - Stabilize middleware and context APIs. ([#14215](https://github.com/remix-run/react-router/pull/14215))
230
314
 
231
315
  We have removed the `unstable_` prefix from the following APIs and they are now considered stable and ready for production use:
232
-
233
316
  - [`RouterContextProvider`](https://reactrouter.com/api/utils/RouterContextProvider)
234
317
  - [`createContext`](https://reactrouter.com/api/utils/createContext)
235
318
  - `createBrowserRouter` [`getContext`](https://reactrouter.com/api/data-routers/createBrowserRouter#optsgetcontext) option
@@ -972,7 +1055,6 @@
972
1055
  ```
973
1056
 
974
1057
  This initial implementation targets type inference for:
975
-
976
1058
  - `Params` : Path parameters from your routing config in `routes.ts` including file-based routing
977
1059
  - `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module
978
1060
  - `ActionData` : Action data from `action` and/or `clientAction` within your route module
@@ -987,7 +1069,6 @@
987
1069
  ```
988
1070
 
989
1071
  Check out our docs for more:
990
-
991
1072
  - [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety)
992
1073
  - [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety)
993
1074
 
@@ -1187,7 +1268,6 @@
1187
1268
  - Vite: Provide `Unstable_ServerBundlesFunction` and `Unstable_VitePluginConfig` types ([#8654](https://github.com/remix-run/remix/pull/8654))
1188
1269
 
1189
1270
  - Vite: add `--sourcemapClient` and `--sourcemapServer` flags to `remix vite:build` ([#8613](https://github.com/remix-run/remix/pull/8613))
1190
-
1191
1271
  - `--sourcemapClient`
1192
1272
 
1193
1273
  - `--sourcemapClient=inline`
@@ -1524,7 +1604,6 @@
1524
1604
  - Add support for `clientLoader`/`clientAction`/`HydrateFallback` route exports ([RFC](https://github.com/remix-run/remix/discussions/7634)) ([#8173](https://github.com/remix-run/remix/pull/8173))
1525
1605
 
1526
1606
  Remix now supports loaders/actions that run on the client (in addition to, or instead of the loader/action that runs on the server). While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as:
1527
-
1528
1607
  - Leveraging a data source local to the browser (i.e., `localStorage`)
1529
1608
  - Managing a client-side cache of server data (like `IndexedDB`)
1530
1609
  - Bypassing the Remix server in a BFF setup and hitting your API directly from the browser
@@ -1928,7 +2007,6 @@
1928
2007
  - Output esbuild metafiles for bundle analysis ([#6772](https://github.com/remix-run/remix/pull/6772))
1929
2008
 
1930
2009
  Written to server build directory (`build/` by default):
1931
-
1932
2010
  - `metafile.css.json`
1933
2011
  - `metafile.js.json` (browser JS)
1934
2012
  - `metafile.server.json` (server JS)
@@ -2026,7 +2104,6 @@
2026
2104
  - built-in tls support ([#6483](https://github.com/remix-run/remix/pull/6483))
2027
2105
 
2028
2106
  New options:
2029
-
2030
2107
  - `--tls-key` / `tlsKey`: TLS key
2031
2108
  - `--tls-cert` / `tlsCert`: TLS Certificate
2032
2109
 
@@ -2297,7 +2374,6 @@
2297
2374
  ```
2298
2375
 
2299
2376
  The dev server will:
2300
-
2301
2377
  - force `NODE_ENV=development` and warn you if it was previously set to something else
2302
2378
  - rebuild your app whenever your Remix app code changes
2303
2379
  - restart your app server whenever rebuilds succeed
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v7.10.1
3
+ * @react-router/dev v7.13.1
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -217,7 +217,7 @@ function validateRouteConfig({
217
217
  `Route config in "${routeConfigFile}" is invalid.`,
218
218
  root ? `${root}` : [],
219
219
  nested ? Object.entries(nested).map(
220
- ([path9, message]) => `Path: routes.${path9}
220
+ ([path10, message]) => `Path: routes.${path10}
221
221
  ${message}`
222
222
  ) : []
223
223
  ].flat().join("\n\n")
@@ -376,7 +376,7 @@ async function resolveConfig({
376
376
  basename: basename3,
377
377
  buildDirectory: userBuildDirectory,
378
378
  buildEnd,
379
- prerender,
379
+ prerender: prerender2,
380
380
  routeDiscovery: userRouteDiscovery,
381
381
  serverBuildFile,
382
382
  serverBundles,
@@ -390,15 +390,15 @@ async function resolveConfig({
390
390
  if (!ssr && serverBundles) {
391
391
  serverBundles = void 0;
392
392
  }
393
- if (prerender) {
393
+ if (prerender2) {
394
394
  let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
395
- let isValidPrerenderConfig = isValidPrerenderPathsConfig(prerender) || typeof prerender === "object" && "paths" in prerender && isValidPrerenderPathsConfig(prerender.paths);
395
+ let isValidPrerenderConfig = isValidPrerenderPathsConfig(prerender2) || typeof prerender2 === "object" && "paths" in prerender2 && isValidPrerenderPathsConfig(prerender2.paths);
396
396
  if (!isValidPrerenderConfig) {
397
397
  return err(
398
398
  "The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths."
399
399
  );
400
400
  }
401
- let isValidConcurrencyConfig = typeof prerender != "object" || !("unstable_concurrency" in prerender) || typeof prerender.unstable_concurrency === "number" && Number.isInteger(prerender.unstable_concurrency) && prerender.unstable_concurrency > 0;
401
+ let isValidConcurrencyConfig = typeof prerender2 != "object" || !("unstable_concurrency" in prerender2) || typeof prerender2.unstable_concurrency === "number" && Number.isInteger(prerender2.unstable_concurrency) && prerender2.unstable_concurrency > 0;
402
402
  if (!isValidConcurrencyConfig) {
403
403
  return err(
404
404
  "The `prerender.unstable_concurrency` config must be a positive integer if specified."
@@ -506,23 +506,27 @@ async function resolveConfig({
506
506
  let future = {
507
507
  unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
508
508
  unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
509
+ unstable_trailingSlashAwareDataRequests: userAndPresetConfigs.future?.unstable_trailingSlashAwareDataRequests ?? false,
510
+ unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
509
511
  v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
510
512
  v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
511
513
  v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
512
514
  };
515
+ let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;
513
516
  let reactRouterConfig = deepFreeze({
514
517
  appDirectory,
515
518
  basename: basename3,
516
519
  buildDirectory,
517
520
  buildEnd,
518
521
  future,
519
- prerender,
522
+ prerender: prerender2,
520
523
  routes: routes2,
521
524
  routeDiscovery,
522
525
  serverBuildFile,
523
526
  serverBundles,
524
527
  serverModuleFormat,
525
528
  ssr,
529
+ allowedActionOrigins,
526
530
  unstable_routeConfig: routeConfig
527
531
  });
528
532
  for (let preset of reactRouterUserConfig.presets ?? []) {
@@ -582,11 +586,11 @@ async function createConfigLoader({
582
586
  if (!fsWatcher) {
583
587
  fsWatcher = import_chokidar.default.watch([root, appDirectory], {
584
588
  ignoreInitial: true,
585
- ignored: (path9) => {
586
- let dirname5 = import_pathe3.default.dirname(path9);
589
+ ignored: (path10) => {
590
+ let dirname5 = import_pathe3.default.dirname(path10);
587
591
  return !dirname5.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
588
592
  // that are at the root level, not nested in subdirectories
589
- path9 !== root && // Watch the root directory itself
593
+ path10 !== root && // Watch the root directory itself
590
594
  dirname5 !== root;
591
595
  }
592
596
  });
@@ -911,7 +915,7 @@ function fullpath(lineage2) {
911
915
  if (lineage2.length === 1 && route?.id === "root") return "/";
912
916
  const isLayout = route && route.index !== true && route.path === void 0;
913
917
  if (isLayout) return void 0;
914
- return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path9) => path9 !== void 0 && path9 !== "").join("/");
918
+ return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path10) => path10 !== void 0 && path10 !== "").join("/");
915
919
  }
916
920
  var init_route = __esm({
917
921
  "typegen/route.ts"() {
@@ -956,6 +960,7 @@ function generateServerBuild(ctx) {
956
960
  export const routeDiscovery: ServerBuild["routeDiscovery"];
957
961
  export const routes: ServerBuild["routes"];
958
962
  export const ssr: ServerBuild["ssr"];
963
+ export const allowedActionOrigins: ServerBuild["allowedActionOrigins"];
959
964
  export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
960
965
  }
961
966
  `;
@@ -1094,8 +1099,8 @@ function routeModulesType(ctx) {
1094
1099
  );
1095
1100
  }
1096
1101
  function isInAppDirectory(ctx, routeFile) {
1097
- const path9 = Path3.resolve(ctx.config.appDirectory, routeFile);
1098
- return path9.startsWith(ctx.config.appDirectory);
1102
+ const path10 = Path3.resolve(ctx.config.appDirectory, routeFile);
1103
+ return path10.startsWith(ctx.config.appDirectory);
1099
1104
  }
1100
1105
  function getRouteAnnotations({
1101
1106
  ctx,
@@ -1207,21 +1212,21 @@ function getRouteAnnotations({
1207
1212
  return { filename: filename2, content };
1208
1213
  }
1209
1214
  function relativeImportSource(from, to) {
1210
- let path9 = Path3.relative(Path3.dirname(from), to);
1211
- let extension = Path3.extname(path9);
1212
- path9 = Path3.join(Path3.dirname(path9), Pathe.filename(path9));
1213
- if (!path9.startsWith("../")) path9 = "./" + path9;
1215
+ let path10 = Path3.relative(Path3.dirname(from), to);
1216
+ let extension = Path3.extname(path10);
1217
+ path10 = Path3.join(Path3.dirname(path10), Pathe.filename(path10));
1218
+ if (!path10.startsWith("../")) path10 = "./" + path10;
1214
1219
  if (!extension || /\.(js|ts)x?$/.test(extension)) {
1215
1220
  extension = ".js";
1216
1221
  }
1217
- return path9 + extension;
1222
+ return path10 + extension;
1218
1223
  }
1219
1224
  function rootDirsPath(ctx, typesPath) {
1220
1225
  const rel = Path3.relative(typesDirectory(ctx), typesPath);
1221
1226
  return Path3.join(ctx.rootDirectory, rel);
1222
1227
  }
1223
- function paramsType(path9) {
1224
- const params = parse2(path9);
1228
+ function paramsType(path10) {
1229
+ const params = parse2(path10);
1225
1230
  return t2.tsTypeLiteral(
1226
1231
  Object.entries(params).map(([param, isRequired]) => {
1227
1232
  const property = t2.tsPropertySignature(
@@ -1373,11 +1378,9 @@ var init_has_rsc_plugin = __esm({
1373
1378
  });
1374
1379
 
1375
1380
  // vite/node-adapter.ts
1376
- var import_node_fetch_server;
1377
1381
  var init_node_adapter = __esm({
1378
1382
  "vite/node-adapter.ts"() {
1379
1383
  "use strict";
1380
- import_node_fetch_server = require("@remix-run/node-fetch-server");
1381
1384
  init_invariant();
1382
1385
  }
1383
1386
  });
@@ -1553,6 +1556,16 @@ var init_warn_on_client_source_maps = __esm({
1553
1556
  }
1554
1557
  });
1555
1558
 
1559
+ // vite/plugins/prerender.ts
1560
+ var import_promises2, import_node_path2;
1561
+ var init_prerender = __esm({
1562
+ "vite/plugins/prerender.ts"() {
1563
+ "use strict";
1564
+ import_promises2 = require("fs/promises");
1565
+ import_node_path2 = __toESM(require("path"));
1566
+ }
1567
+ });
1568
+
1556
1569
  // vite/plugin.ts
1557
1570
  async function resolveViteConfig({
1558
1571
  configFile,
@@ -1595,11 +1608,11 @@ function getServerBundleIds(ctx) {
1595
1608
  async function cleanBuildDirectory(viteConfig, ctx) {
1596
1609
  let buildDirectory = ctx.reactRouterConfig.buildDirectory;
1597
1610
  let isWithinRoot = () => {
1598
- let relativePath = path7.relative(ctx.rootDirectory, buildDirectory);
1599
- return !relativePath.startsWith("..") && !path7.isAbsolute(relativePath);
1611
+ let relativePath = path8.relative(ctx.rootDirectory, buildDirectory);
1612
+ return !relativePath.startsWith("..") && !path8.isAbsolute(relativePath);
1600
1613
  };
1601
1614
  if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
1602
- await (0, import_promises2.rm)(buildDirectory, { force: true, recursive: true });
1615
+ await (0, import_promises3.rm)(buildDirectory, { force: true, recursive: true });
1603
1616
  }
1604
1617
  }
1605
1618
  async function cleanViteManifests(environmentsOptions, ctx) {
@@ -1607,7 +1620,7 @@ async function cleanViteManifests(environmentsOptions, ctx) {
1607
1620
  ([environmentName, options]) => {
1608
1621
  let outDir = options.build?.outDir;
1609
1622
  invariant(outDir, `Expected build.outDir for ${environmentName}`);
1610
- return path7.join(outDir, ".vite/manifest.json");
1623
+ return path8.join(outDir, ".vite/manifest.json");
1611
1624
  }
1612
1625
  );
1613
1626
  await Promise.all(
@@ -1615,12 +1628,12 @@ async function cleanViteManifests(environmentsOptions, ctx) {
1615
1628
  let manifestExists = (0, import_node_fs3.existsSync)(viteManifestPath);
1616
1629
  if (!manifestExists) return;
1617
1630
  if (!ctx.viteManifestEnabled) {
1618
- await (0, import_promises2.rm)(viteManifestPath, { force: true, recursive: true });
1631
+ await (0, import_promises3.rm)(viteManifestPath, { force: true, recursive: true });
1619
1632
  }
1620
- let viteDir = path7.dirname(viteManifestPath);
1621
- let viteDirFiles = await (0, import_promises2.readdir)(viteDir, { recursive: true });
1633
+ let viteDir = path8.dirname(viteManifestPath);
1634
+ let viteDirFiles = await (0, import_promises3.readdir)(viteDir, { recursive: true });
1622
1635
  if (viteDirFiles.length === 0) {
1623
- await (0, import_promises2.rm)(viteDir, { force: true, recursive: true });
1636
+ await (0, import_promises3.rm)(viteDir, { force: true, recursive: true });
1624
1637
  }
1625
1638
  })
1626
1639
  );
@@ -1634,10 +1647,10 @@ function mergeEnvironmentOptions(base, ...overrides) {
1634
1647
  }
1635
1648
  async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1636
1649
  let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
1637
- let packageRoot = path7.dirname(
1650
+ let packageRoot = path8.dirname(
1638
1651
  require.resolve("@react-router/dev/package.json")
1639
1652
  );
1640
- let { moduleSyncEnabled } = await import(`file:///${path7.join(packageRoot, "module-sync-enabled/index.mjs")}`);
1653
+ let { moduleSyncEnabled } = await import(`file:///${path8.join(packageRoot, "module-sync-enabled/index.mjs")}`);
1641
1654
  let vite2 = getVite();
1642
1655
  function getBaseOptions({
1643
1656
  viteUserConfig
@@ -1716,7 +1729,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1716
1729
  ctx.entryClientFilePath,
1717
1730
  ...Object.values(ctx.reactRouterConfig.routes).flatMap(
1718
1731
  (route) => {
1719
- let routeFilePath = path7.resolve(
1732
+ let routeFilePath = path8.resolve(
1720
1733
  ctx.reactRouterConfig.appDirectory,
1721
1734
  route.file
1722
1735
  );
@@ -1740,7 +1753,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1740
1753
  ) : null;
1741
1754
  let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
1742
1755
  let assetsDir = (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
1743
- return path7.posix.join(
1756
+ return path8.posix.join(
1744
1757
  assetsDir,
1745
1758
  `[name]${routeChunkSuffix}-[hash].js`
1746
1759
  );
@@ -1790,17 +1803,16 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
1790
1803
  function isNonNullable(x) {
1791
1804
  return x != null;
1792
1805
  }
1793
- var import_node_crypto, import_node_fs3, import_promises2, path7, url, babel2, import_node_fetch_server2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors5, 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;
1806
+ var import_node_crypto, import_node_fs3, import_promises3, path8, url, babel2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors5, 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;
1794
1807
  var init_plugin = __esm({
1795
1808
  "vite/plugin.ts"() {
1796
1809
  "use strict";
1797
1810
  import_node_crypto = require("crypto");
1798
1811
  import_node_fs3 = require("fs");
1799
- import_promises2 = require("fs/promises");
1800
- path7 = __toESM(require("path"));
1812
+ import_promises3 = require("fs/promises");
1813
+ path8 = __toESM(require("path"));
1801
1814
  url = __toESM(require("url"));
1802
1815
  babel2 = __toESM(require("@babel/core"));
1803
- import_node_fetch_server2 = require("@remix-run/node-fetch-server");
1804
1816
  import_react_router2 = require("react-router");
1805
1817
  import_es_module_lexer = require("es-module-lexer");
1806
1818
  import_pick3 = __toESM(require("lodash/pick"));
@@ -1827,6 +1839,7 @@ var init_plugin = __esm({
1827
1839
  init_load_dotenv();
1828
1840
  init_validate_plugin_order();
1829
1841
  init_warn_on_client_source_maps();
1842
+ init_prerender();
1830
1843
  CLIENT_NON_COMPONENT_EXPORTS = [
1831
1844
  "clientAction",
1832
1845
  "clientLoader",
@@ -1852,20 +1865,20 @@ var init_plugin = __esm({
1852
1865
  serverManifest: create("server-manifest"),
1853
1866
  browserManifest: create("browser-manifest")
1854
1867
  };
1855
- getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path7.join(
1868
+ getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path8.join(
1856
1869
  reactRouterConfig.buildDirectory,
1857
1870
  "server",
1858
1871
  ...serverBundleId ? [serverBundleId] : []
1859
1872
  );
1860
- getClientBuildDirectory = (reactRouterConfig) => path7.join(reactRouterConfig.buildDirectory, "client");
1861
- defaultEntriesDir = path7.resolve(
1862
- path7.dirname(require.resolve("@react-router/dev/package.json")),
1873
+ getClientBuildDirectory = (reactRouterConfig) => path8.join(reactRouterConfig.buildDirectory, "client");
1874
+ defaultEntriesDir = path8.resolve(
1875
+ path8.dirname(require.resolve("@react-router/dev/package.json")),
1863
1876
  "dist",
1864
1877
  "config",
1865
1878
  "defaults"
1866
1879
  );
1867
1880
  defaultEntries = (0, import_node_fs3.readdirSync)(defaultEntriesDir).map(
1868
- (filename2) => path7.join(defaultEntriesDir, filename2)
1881
+ (filename2) => path8.join(defaultEntriesDir, filename2)
1869
1882
  );
1870
1883
  invariant(defaultEntries.length > 0, "No default entries found");
1871
1884
  REACT_REFRESH_HEADER = `
@@ -2150,8 +2163,8 @@ var import_picocolors9 = __toESM(require("picocolors"));
2150
2163
 
2151
2164
  // cli/commands.ts
2152
2165
  var import_node_fs4 = require("fs");
2153
- var import_promises3 = require("fs/promises");
2154
- var path8 = __toESM(require("path"));
2166
+ var import_promises4 = require("fs/promises");
2167
+ var path9 = __toESM(require("path"));
2155
2168
  var import_exit_hook = __toESM(require("exit-hook"));
2156
2169
  var import_picocolors8 = __toESM(require("picocolors"));
2157
2170
  var import_react_router3 = require("react-router");
@@ -2324,14 +2337,14 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
2324
2337
  console.error(import_picocolors8.default.red(`No default server entry detected.`));
2325
2338
  return;
2326
2339
  }
2327
- let defaultsDirectory = path8.resolve(
2328
- path8.dirname(require.resolve("@react-router/dev/package.json")),
2340
+ let defaultsDirectory = path9.resolve(
2341
+ path9.dirname(require.resolve("@react-router/dev/package.json")),
2329
2342
  "dist",
2330
2343
  "config",
2331
2344
  "defaults"
2332
2345
  );
2333
- let defaultEntryClient = path8.resolve(defaultsDirectory, "entry.client.tsx");
2334
- let defaultEntryServer = path8.resolve(
2346
+ let defaultEntryClient = path9.resolve(defaultsDirectory, "entry.client.tsx");
2347
+ let defaultEntryServer = path9.resolve(
2335
2348
  defaultsDirectory,
2336
2349
  `entry.server.node.tsx`
2337
2350
  );
@@ -2340,19 +2353,19 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
2340
2353
  let useTypeScript = flags.typescript ?? true;
2341
2354
  let outputExtension = useTypeScript ? "tsx" : "jsx";
2342
2355
  let outputEntry = `${entry}.${outputExtension}`;
2343
- let outputFile = path8.resolve(appDirectory, outputEntry);
2356
+ let outputFile = path9.resolve(appDirectory, outputEntry);
2344
2357
  if (!useTypeScript) {
2345
2358
  let javascript = await transpile(contents, {
2346
2359
  cwd: rootDirectory,
2347
2360
  filename: isServerEntry ? defaultEntryServer : defaultEntryClient
2348
2361
  });
2349
- await (0, import_promises3.writeFile)(outputFile, javascript, "utf-8");
2362
+ await (0, import_promises4.writeFile)(outputFile, javascript, "utf-8");
2350
2363
  } else {
2351
- await (0, import_promises3.writeFile)(outputFile, contents, "utf-8");
2364
+ await (0, import_promises4.writeFile)(outputFile, contents, "utf-8");
2352
2365
  }
2353
2366
  console.log(
2354
2367
  import_picocolors8.default.blue(
2355
- `Entry file ${entry} created at ${path8.relative(
2368
+ `Entry file ${entry} created at ${path9.relative(
2356
2369
  rootDirectory,
2357
2370
  outputFile
2358
2371
  )}.`
@@ -2361,16 +2374,16 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
2361
2374
  }
2362
2375
  function resolveRootDirectory(root, flags) {
2363
2376
  if (root) {
2364
- return path8.resolve(root);
2377
+ return path9.resolve(root);
2365
2378
  }
2366
- return process.env.REACT_ROUTER_ROOT || (flags?.config ? path8.dirname(path8.resolve(flags.config)) : process.cwd());
2379
+ return process.env.REACT_ROUTER_ROOT || (flags?.config ? path9.dirname(path9.resolve(flags.config)) : process.cwd());
2367
2380
  }
2368
2381
  async function checkForEntry(rootDirectory, appDirectory, entries2) {
2369
2382
  for (let entry of entries2) {
2370
- let entryPath = path8.resolve(appDirectory, entry);
2383
+ let entryPath = path9.resolve(appDirectory, entry);
2371
2384
  let exists = (0, import_node_fs4.existsSync)(entryPath);
2372
2385
  if (exists) {
2373
- let relative7 = path8.relative(rootDirectory, entryPath);
2386
+ let relative7 = path9.relative(rootDirectory, entryPath);
2374
2387
  console.error(import_picocolors8.default.red(`Entry file ${relative7} already exists.`));
2375
2388
  return process.exit(1);
2376
2389
  }
@@ -2378,12 +2391,12 @@ async function checkForEntry(rootDirectory, appDirectory, entries2) {
2378
2391
  }
2379
2392
  async function createServerEntry(rootDirectory, appDirectory, inputFile) {
2380
2393
  await checkForEntry(rootDirectory, appDirectory, serverEntries);
2381
- let contents = await (0, import_promises3.readFile)(inputFile, "utf-8");
2394
+ let contents = await (0, import_promises4.readFile)(inputFile, "utf-8");
2382
2395
  return contents;
2383
2396
  }
2384
2397
  async function createClientEntry(rootDirectory, appDirectory, inputFile) {
2385
2398
  await checkForEntry(rootDirectory, appDirectory, clientEntries);
2386
- let contents = await (0, import_promises3.readFile)(inputFile, "utf-8");
2399
+ let contents = await (0, import_promises4.readFile)(inputFile, "utf-8");
2387
2400
  return contents;
2388
2401
  }
2389
2402
  async function typegen(root, flags) {
@@ -6,22 +6,36 @@ import {
6
6
  loadServerAction,
7
7
  renderToReadableStream,
8
8
  } from "@vitejs/plugin-rsc/rsc";
9
- import { unstable_matchRSCServerRequest as matchRSCServerRequest } from "react-router";
9
+ import {
10
+ RouterContextProvider,
11
+ unstable_matchRSCServerRequest as matchRSCServerRequest,
12
+ } from "react-router";
10
13
 
14
+ // Import the routes generated by routes.ts
11
15
  import routes from "virtual:react-router/unstable_rsc/routes";
12
16
  import basename from "virtual:react-router/unstable_rsc/basename";
13
17
  import unstable_reactRouterServeConfig from "virtual:react-router/unstable_rsc/react-router-serve-config";
14
18
 
15
- export async function fetchServer(request: Request) {
16
- return await matchRSCServerRequest({
19
+ export { unstable_reactRouterServeConfig };
20
+
21
+ export function fetchServer(
22
+ request: Request,
23
+ requestContext?: RouterContextProvider,
24
+ ) {
25
+ return matchRSCServerRequest({
26
+ basename,
27
+ // Provide the React Server touchpoints.
17
28
  createTemporaryReferenceSet,
18
29
  decodeAction,
19
30
  decodeFormState,
20
31
  decodeReply,
21
32
  loadServerAction,
33
+ // The incoming request.
22
34
  request,
35
+ requestContext,
36
+ // The app routes.
23
37
  routes,
24
- basename,
38
+ // Encode the match with the React Server implementation.
25
39
  generateResponse(match, options) {
26
40
  return new Response(renderToReadableStream(match.payload, options), {
27
41
  status: match.statusCode,
@@ -31,14 +45,22 @@ export async function fetchServer(request: Request) {
31
45
  });
32
46
  }
33
47
 
34
- export { unstable_reactRouterServeConfig };
48
+ export default {
49
+ async fetch(request: Request, requestContext?: RouterContextProvider) {
50
+ if (requestContext && !(requestContext instanceof RouterContextProvider)) {
51
+ requestContext = undefined;
52
+ }
35
53
 
36
- export default async function handler(request: Request) {
37
- const ssr = await import.meta.viteRsc.loadModule<
38
- typeof import("./entry.ssr")
39
- >("ssr", "index");
40
- return ssr.default(request, fetchServer);
41
- }
54
+ const ssr = await import.meta.viteRsc.loadModule<
55
+ typeof import("./entry.ssr.tsx")
56
+ >("ssr", "index");
57
+
58
+ return await ssr.generateHTML(
59
+ request,
60
+ await fetchServer(request, requestContext),
61
+ );
62
+ },
63
+ };
42
64
 
43
65
  if (import.meta.hot) {
44
66
  import.meta.hot.accept();
@@ -1,31 +1,38 @@
1
1
  import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
2
- // @ts-expect-error
3
- import * as ReactDomServer from "react-dom/server.edge";
2
+ // @ts-expect-error - no types for this, can import from root once on latest 19
3
+ import { renderToReadableStream } from "react-dom/server.edge";
4
4
  import {
5
- unstable_RSCStaticRouter as RSCStaticRouter,
6
5
  unstable_routeRSCServerRequest as routeRSCServerRequest,
6
+ unstable_RSCStaticRouter as RSCStaticRouter,
7
7
  } from "react-router";
8
8
 
9
- export default async function handler(
9
+ export async function generateHTML(
10
10
  request: Request,
11
- fetchServer: (request: Request) => Promise<Response>,
12
- ) {
13
- const bootstrapScriptContent =
14
- await import.meta.viteRsc.loadBootstrapScriptContent("index");
15
-
16
- return routeRSCServerRequest({
11
+ serverResponse: Response,
12
+ ): Promise<Response> {
13
+ return await routeRSCServerRequest({
14
+ // The incoming request.
17
15
  request,
18
- fetchServer,
16
+ // The response from the RSC server.
17
+ serverResponse,
18
+ // Provide the React Server touchpoints.
19
19
  createFromReadableStream,
20
- async renderHTML(getPayload) {
21
- const payload = getPayload();
20
+ // Render the router to HTML.
21
+ async renderHTML(getPayload, options) {
22
+ const payload = await getPayload();
23
+ const formState =
24
+ payload.type === "render" ? await payload.formState : undefined;
25
+
26
+ const bootstrapScriptContent =
27
+ await import.meta.viteRsc.loadBootstrapScriptContent("index");
22
28
 
23
- return ReactDomServer.renderToReadableStream(
29
+ return await renderToReadableStream(
24
30
  <RSCStaticRouter getPayload={getPayload} />,
25
31
  {
32
+ ...options,
26
33
  bootstrapScriptContent,
34
+ formState,
27
35
  signal: request.signal,
28
- formState: await payload.formState,
29
36
  },
30
37
  );
31
38
  },