@react-router/dev 0.0.0-experimental-f887449bb → 0.0.0-experimental-e067e5e52
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 +57 -0
- package/dist/cli/index.js +71 -59
- package/dist/config.d.ts +50 -0
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/vite/cloudflare.js +10 -9
- package/dist/vite.js +772 -222
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
+
## 7.13.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Bump @remix-run/node-fetch-server dep ([#14704](https://github.com/remix-run/react-router/pull/14704))
|
|
8
|
+
- Updated dependencies:
|
|
9
|
+
- `react-router@7.13.0`
|
|
10
|
+
- `@react-router/node@7.13.0`
|
|
11
|
+
- `@react-router/serve@7.13.0`
|
|
12
|
+
|
|
13
|
+
## 7.12.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- 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))
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 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))
|
|
22
|
+
|
|
23
|
+
- fix(vite): Skip SSR middleware in preview server for SPA mode ([#14673](https://github.com/remix-run/react-router/pull/14673))
|
|
24
|
+
|
|
25
|
+
- \[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))
|
|
26
|
+
|
|
27
|
+
Currently, your HTTP and `request` pathnames would be as follows for `/a/b/c` and `/a/b/c/`
|
|
28
|
+
|
|
29
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
|
|
30
|
+
| ------------ | ----------------- | ------------------------ |
|
|
31
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
32
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
33
|
+
|
|
34
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
|
|
35
|
+
| ------------- | ----------------- | ------------------------ |
|
|
36
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
37
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ⚠️ |
|
|
38
|
+
|
|
39
|
+
With this flag enabled, these pathnames will be made consistent though a new `_.data` format for client-side `.data` requests:
|
|
40
|
+
|
|
41
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
|
|
42
|
+
| ------------ | ----------------- | ------------------------ |
|
|
43
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
44
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
45
|
+
|
|
46
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
|
|
47
|
+
| ------------- | ------------------ | ------------------------ |
|
|
48
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
49
|
+
| **Data** | `/a/b/c/_.data` ⬅️ | `/a/b/c/` ✅ |
|
|
50
|
+
|
|
51
|
+
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.
|
|
52
|
+
|
|
53
|
+
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.
|
|
54
|
+
|
|
55
|
+
- Updated dependencies:
|
|
56
|
+
- `react-router@7.12.0`
|
|
57
|
+
- `@react-router/node@7.12.0`
|
|
58
|
+
- `@react-router/serve@7.12.0`
|
|
59
|
+
|
|
3
60
|
## 7.11.0
|
|
4
61
|
|
|
5
62
|
### Minor 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-
|
|
3
|
+
* @react-router/dev v0.0.0-experimental-e067e5e52
|
|
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
|
-
([
|
|
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 (
|
|
393
|
+
if (prerender2) {
|
|
394
394
|
let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
|
|
395
|
-
let isValidPrerenderConfig = isValidPrerenderPathsConfig(
|
|
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
|
|
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."
|
|
@@ -507,23 +507,26 @@ async function resolveConfig({
|
|
|
507
507
|
unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
|
|
508
508
|
unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
|
|
509
509
|
unstable_trailingSlashAwareDataRequests: userAndPresetConfigs.future?.unstable_trailingSlashAwareDataRequests ?? false,
|
|
510
|
+
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
510
511
|
v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
|
|
511
512
|
v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
|
|
512
513
|
v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
|
|
513
514
|
};
|
|
515
|
+
let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;
|
|
514
516
|
let reactRouterConfig = deepFreeze({
|
|
515
517
|
appDirectory,
|
|
516
518
|
basename: basename3,
|
|
517
519
|
buildDirectory,
|
|
518
520
|
buildEnd,
|
|
519
521
|
future,
|
|
520
|
-
prerender,
|
|
522
|
+
prerender: prerender2,
|
|
521
523
|
routes: routes2,
|
|
522
524
|
routeDiscovery,
|
|
523
525
|
serverBuildFile,
|
|
524
526
|
serverBundles,
|
|
525
527
|
serverModuleFormat,
|
|
526
528
|
ssr,
|
|
529
|
+
allowedActionOrigins,
|
|
527
530
|
unstable_routeConfig: routeConfig
|
|
528
531
|
});
|
|
529
532
|
for (let preset of reactRouterUserConfig.presets ?? []) {
|
|
@@ -583,11 +586,11 @@ async function createConfigLoader({
|
|
|
583
586
|
if (!fsWatcher) {
|
|
584
587
|
fsWatcher = import_chokidar.default.watch([root, appDirectory], {
|
|
585
588
|
ignoreInitial: true,
|
|
586
|
-
ignored: (
|
|
587
|
-
let dirname5 = import_pathe3.default.dirname(
|
|
589
|
+
ignored: (path10) => {
|
|
590
|
+
let dirname5 = import_pathe3.default.dirname(path10);
|
|
588
591
|
return !dirname5.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
|
|
589
592
|
// that are at the root level, not nested in subdirectories
|
|
590
|
-
|
|
593
|
+
path10 !== root && // Watch the root directory itself
|
|
591
594
|
dirname5 !== root;
|
|
592
595
|
}
|
|
593
596
|
});
|
|
@@ -912,7 +915,7 @@ function fullpath(lineage2) {
|
|
|
912
915
|
if (lineage2.length === 1 && route?.id === "root") return "/";
|
|
913
916
|
const isLayout = route && route.index !== true && route.path === void 0;
|
|
914
917
|
if (isLayout) return void 0;
|
|
915
|
-
return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((
|
|
918
|
+
return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path10) => path10 !== void 0 && path10 !== "").join("/");
|
|
916
919
|
}
|
|
917
920
|
var init_route = __esm({
|
|
918
921
|
"typegen/route.ts"() {
|
|
@@ -957,6 +960,7 @@ function generateServerBuild(ctx) {
|
|
|
957
960
|
export const routeDiscovery: ServerBuild["routeDiscovery"];
|
|
958
961
|
export const routes: ServerBuild["routes"];
|
|
959
962
|
export const ssr: ServerBuild["ssr"];
|
|
963
|
+
export const allowedActionOrigins: ServerBuild["allowedActionOrigins"];
|
|
960
964
|
export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
|
|
961
965
|
}
|
|
962
966
|
`;
|
|
@@ -1095,8 +1099,8 @@ function routeModulesType(ctx) {
|
|
|
1095
1099
|
);
|
|
1096
1100
|
}
|
|
1097
1101
|
function isInAppDirectory(ctx, routeFile) {
|
|
1098
|
-
const
|
|
1099
|
-
return
|
|
1102
|
+
const path10 = Path3.resolve(ctx.config.appDirectory, routeFile);
|
|
1103
|
+
return path10.startsWith(ctx.config.appDirectory);
|
|
1100
1104
|
}
|
|
1101
1105
|
function getRouteAnnotations({
|
|
1102
1106
|
ctx,
|
|
@@ -1208,21 +1212,21 @@ function getRouteAnnotations({
|
|
|
1208
1212
|
return { filename: filename2, content };
|
|
1209
1213
|
}
|
|
1210
1214
|
function relativeImportSource(from, to) {
|
|
1211
|
-
let
|
|
1212
|
-
let extension = Path3.extname(
|
|
1213
|
-
|
|
1214
|
-
if (!
|
|
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;
|
|
1215
1219
|
if (!extension || /\.(js|ts)x?$/.test(extension)) {
|
|
1216
1220
|
extension = ".js";
|
|
1217
1221
|
}
|
|
1218
|
-
return
|
|
1222
|
+
return path10 + extension;
|
|
1219
1223
|
}
|
|
1220
1224
|
function rootDirsPath(ctx, typesPath) {
|
|
1221
1225
|
const rel = Path3.relative(typesDirectory(ctx), typesPath);
|
|
1222
1226
|
return Path3.join(ctx.rootDirectory, rel);
|
|
1223
1227
|
}
|
|
1224
|
-
function paramsType(
|
|
1225
|
-
const params = parse2(
|
|
1228
|
+
function paramsType(path10) {
|
|
1229
|
+
const params = parse2(path10);
|
|
1226
1230
|
return t2.tsTypeLiteral(
|
|
1227
1231
|
Object.entries(params).map(([param, isRequired]) => {
|
|
1228
1232
|
const property = t2.tsPropertySignature(
|
|
@@ -1374,11 +1378,9 @@ var init_has_rsc_plugin = __esm({
|
|
|
1374
1378
|
});
|
|
1375
1379
|
|
|
1376
1380
|
// vite/node-adapter.ts
|
|
1377
|
-
var import_node_fetch_server;
|
|
1378
1381
|
var init_node_adapter = __esm({
|
|
1379
1382
|
"vite/node-adapter.ts"() {
|
|
1380
1383
|
"use strict";
|
|
1381
|
-
import_node_fetch_server = require("@remix-run/node-fetch-server");
|
|
1382
1384
|
init_invariant();
|
|
1383
1385
|
}
|
|
1384
1386
|
});
|
|
@@ -1554,6 +1556,16 @@ var init_warn_on_client_source_maps = __esm({
|
|
|
1554
1556
|
}
|
|
1555
1557
|
});
|
|
1556
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
|
+
|
|
1557
1569
|
// vite/plugin.ts
|
|
1558
1570
|
async function resolveViteConfig({
|
|
1559
1571
|
configFile,
|
|
@@ -1596,11 +1608,11 @@ function getServerBundleIds(ctx) {
|
|
|
1596
1608
|
async function cleanBuildDirectory(viteConfig, ctx) {
|
|
1597
1609
|
let buildDirectory = ctx.reactRouterConfig.buildDirectory;
|
|
1598
1610
|
let isWithinRoot = () => {
|
|
1599
|
-
let relativePath =
|
|
1600
|
-
return !relativePath.startsWith("..") && !
|
|
1611
|
+
let relativePath = path8.relative(ctx.rootDirectory, buildDirectory);
|
|
1612
|
+
return !relativePath.startsWith("..") && !path8.isAbsolute(relativePath);
|
|
1601
1613
|
};
|
|
1602
1614
|
if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
|
|
1603
|
-
await (0,
|
|
1615
|
+
await (0, import_promises3.rm)(buildDirectory, { force: true, recursive: true });
|
|
1604
1616
|
}
|
|
1605
1617
|
}
|
|
1606
1618
|
async function cleanViteManifests(environmentsOptions, ctx) {
|
|
@@ -1608,7 +1620,7 @@ async function cleanViteManifests(environmentsOptions, ctx) {
|
|
|
1608
1620
|
([environmentName, options]) => {
|
|
1609
1621
|
let outDir = options.build?.outDir;
|
|
1610
1622
|
invariant(outDir, `Expected build.outDir for ${environmentName}`);
|
|
1611
|
-
return
|
|
1623
|
+
return path8.join(outDir, ".vite/manifest.json");
|
|
1612
1624
|
}
|
|
1613
1625
|
);
|
|
1614
1626
|
await Promise.all(
|
|
@@ -1616,12 +1628,12 @@ async function cleanViteManifests(environmentsOptions, ctx) {
|
|
|
1616
1628
|
let manifestExists = (0, import_node_fs3.existsSync)(viteManifestPath);
|
|
1617
1629
|
if (!manifestExists) return;
|
|
1618
1630
|
if (!ctx.viteManifestEnabled) {
|
|
1619
|
-
await (0,
|
|
1631
|
+
await (0, import_promises3.rm)(viteManifestPath, { force: true, recursive: true });
|
|
1620
1632
|
}
|
|
1621
|
-
let viteDir =
|
|
1622
|
-
let viteDirFiles = await (0,
|
|
1633
|
+
let viteDir = path8.dirname(viteManifestPath);
|
|
1634
|
+
let viteDirFiles = await (0, import_promises3.readdir)(viteDir, { recursive: true });
|
|
1623
1635
|
if (viteDirFiles.length === 0) {
|
|
1624
|
-
await (0,
|
|
1636
|
+
await (0, import_promises3.rm)(viteDir, { force: true, recursive: true });
|
|
1625
1637
|
}
|
|
1626
1638
|
})
|
|
1627
1639
|
);
|
|
@@ -1635,10 +1647,10 @@ function mergeEnvironmentOptions(base, ...overrides) {
|
|
|
1635
1647
|
}
|
|
1636
1648
|
async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
|
|
1637
1649
|
let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
|
|
1638
|
-
let packageRoot =
|
|
1650
|
+
let packageRoot = path8.dirname(
|
|
1639
1651
|
require.resolve("@react-router/dev/package.json")
|
|
1640
1652
|
);
|
|
1641
|
-
let { moduleSyncEnabled } = await import(`file:///${
|
|
1653
|
+
let { moduleSyncEnabled } = await import(`file:///${path8.join(packageRoot, "module-sync-enabled/index.mjs")}`);
|
|
1642
1654
|
let vite2 = getVite();
|
|
1643
1655
|
function getBaseOptions({
|
|
1644
1656
|
viteUserConfig
|
|
@@ -1717,7 +1729,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
|
|
|
1717
1729
|
ctx.entryClientFilePath,
|
|
1718
1730
|
...Object.values(ctx.reactRouterConfig.routes).flatMap(
|
|
1719
1731
|
(route) => {
|
|
1720
|
-
let routeFilePath =
|
|
1732
|
+
let routeFilePath = path8.resolve(
|
|
1721
1733
|
ctx.reactRouterConfig.appDirectory,
|
|
1722
1734
|
route.file
|
|
1723
1735
|
);
|
|
@@ -1741,7 +1753,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
|
|
|
1741
1753
|
) : null;
|
|
1742
1754
|
let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
|
|
1743
1755
|
let assetsDir = (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
|
|
1744
|
-
return
|
|
1756
|
+
return path8.posix.join(
|
|
1745
1757
|
assetsDir,
|
|
1746
1758
|
`[name]${routeChunkSuffix}-[hash].js`
|
|
1747
1759
|
);
|
|
@@ -1791,17 +1803,16 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
|
|
|
1791
1803
|
function isNonNullable(x) {
|
|
1792
1804
|
return x != null;
|
|
1793
1805
|
}
|
|
1794
|
-
var import_node_crypto, import_node_fs3,
|
|
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;
|
|
1795
1807
|
var init_plugin = __esm({
|
|
1796
1808
|
"vite/plugin.ts"() {
|
|
1797
1809
|
"use strict";
|
|
1798
1810
|
import_node_crypto = require("crypto");
|
|
1799
1811
|
import_node_fs3 = require("fs");
|
|
1800
|
-
|
|
1801
|
-
|
|
1812
|
+
import_promises3 = require("fs/promises");
|
|
1813
|
+
path8 = __toESM(require("path"));
|
|
1802
1814
|
url = __toESM(require("url"));
|
|
1803
1815
|
babel2 = __toESM(require("@babel/core"));
|
|
1804
|
-
import_node_fetch_server2 = require("@remix-run/node-fetch-server");
|
|
1805
1816
|
import_react_router2 = require("react-router");
|
|
1806
1817
|
import_es_module_lexer = require("es-module-lexer");
|
|
1807
1818
|
import_pick3 = __toESM(require("lodash/pick"));
|
|
@@ -1828,6 +1839,7 @@ var init_plugin = __esm({
|
|
|
1828
1839
|
init_load_dotenv();
|
|
1829
1840
|
init_validate_plugin_order();
|
|
1830
1841
|
init_warn_on_client_source_maps();
|
|
1842
|
+
init_prerender();
|
|
1831
1843
|
CLIENT_NON_COMPONENT_EXPORTS = [
|
|
1832
1844
|
"clientAction",
|
|
1833
1845
|
"clientLoader",
|
|
@@ -1853,20 +1865,20 @@ var init_plugin = __esm({
|
|
|
1853
1865
|
serverManifest: create("server-manifest"),
|
|
1854
1866
|
browserManifest: create("browser-manifest")
|
|
1855
1867
|
};
|
|
1856
|
-
getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) =>
|
|
1868
|
+
getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path8.join(
|
|
1857
1869
|
reactRouterConfig.buildDirectory,
|
|
1858
1870
|
"server",
|
|
1859
1871
|
...serverBundleId ? [serverBundleId] : []
|
|
1860
1872
|
);
|
|
1861
|
-
getClientBuildDirectory = (reactRouterConfig) =>
|
|
1862
|
-
defaultEntriesDir =
|
|
1863
|
-
|
|
1873
|
+
getClientBuildDirectory = (reactRouterConfig) => path8.join(reactRouterConfig.buildDirectory, "client");
|
|
1874
|
+
defaultEntriesDir = path8.resolve(
|
|
1875
|
+
path8.dirname(require.resolve("@react-router/dev/package.json")),
|
|
1864
1876
|
"dist",
|
|
1865
1877
|
"config",
|
|
1866
1878
|
"defaults"
|
|
1867
1879
|
);
|
|
1868
1880
|
defaultEntries = (0, import_node_fs3.readdirSync)(defaultEntriesDir).map(
|
|
1869
|
-
(filename2) =>
|
|
1881
|
+
(filename2) => path8.join(defaultEntriesDir, filename2)
|
|
1870
1882
|
);
|
|
1871
1883
|
invariant(defaultEntries.length > 0, "No default entries found");
|
|
1872
1884
|
REACT_REFRESH_HEADER = `
|
|
@@ -2151,8 +2163,8 @@ var import_picocolors9 = __toESM(require("picocolors"));
|
|
|
2151
2163
|
|
|
2152
2164
|
// cli/commands.ts
|
|
2153
2165
|
var import_node_fs4 = require("fs");
|
|
2154
|
-
var
|
|
2155
|
-
var
|
|
2166
|
+
var import_promises4 = require("fs/promises");
|
|
2167
|
+
var path9 = __toESM(require("path"));
|
|
2156
2168
|
var import_exit_hook = __toESM(require("exit-hook"));
|
|
2157
2169
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
2158
2170
|
var import_react_router3 = require("react-router");
|
|
@@ -2325,14 +2337,14 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2325
2337
|
console.error(import_picocolors8.default.red(`No default server entry detected.`));
|
|
2326
2338
|
return;
|
|
2327
2339
|
}
|
|
2328
|
-
let defaultsDirectory =
|
|
2329
|
-
|
|
2340
|
+
let defaultsDirectory = path9.resolve(
|
|
2341
|
+
path9.dirname(require.resolve("@react-router/dev/package.json")),
|
|
2330
2342
|
"dist",
|
|
2331
2343
|
"config",
|
|
2332
2344
|
"defaults"
|
|
2333
2345
|
);
|
|
2334
|
-
let defaultEntryClient =
|
|
2335
|
-
let defaultEntryServer =
|
|
2346
|
+
let defaultEntryClient = path9.resolve(defaultsDirectory, "entry.client.tsx");
|
|
2347
|
+
let defaultEntryServer = path9.resolve(
|
|
2336
2348
|
defaultsDirectory,
|
|
2337
2349
|
`entry.server.node.tsx`
|
|
2338
2350
|
);
|
|
@@ -2341,19 +2353,19 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2341
2353
|
let useTypeScript = flags.typescript ?? true;
|
|
2342
2354
|
let outputExtension = useTypeScript ? "tsx" : "jsx";
|
|
2343
2355
|
let outputEntry = `${entry}.${outputExtension}`;
|
|
2344
|
-
let outputFile =
|
|
2356
|
+
let outputFile = path9.resolve(appDirectory, outputEntry);
|
|
2345
2357
|
if (!useTypeScript) {
|
|
2346
2358
|
let javascript = await transpile(contents, {
|
|
2347
2359
|
cwd: rootDirectory,
|
|
2348
2360
|
filename: isServerEntry ? defaultEntryServer : defaultEntryClient
|
|
2349
2361
|
});
|
|
2350
|
-
await (0,
|
|
2362
|
+
await (0, import_promises4.writeFile)(outputFile, javascript, "utf-8");
|
|
2351
2363
|
} else {
|
|
2352
|
-
await (0,
|
|
2364
|
+
await (0, import_promises4.writeFile)(outputFile, contents, "utf-8");
|
|
2353
2365
|
}
|
|
2354
2366
|
console.log(
|
|
2355
2367
|
import_picocolors8.default.blue(
|
|
2356
|
-
`Entry file ${entry} created at ${
|
|
2368
|
+
`Entry file ${entry} created at ${path9.relative(
|
|
2357
2369
|
rootDirectory,
|
|
2358
2370
|
outputFile
|
|
2359
2371
|
)}.`
|
|
@@ -2362,16 +2374,16 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2362
2374
|
}
|
|
2363
2375
|
function resolveRootDirectory(root, flags) {
|
|
2364
2376
|
if (root) {
|
|
2365
|
-
return
|
|
2377
|
+
return path9.resolve(root);
|
|
2366
2378
|
}
|
|
2367
|
-
return process.env.REACT_ROUTER_ROOT || (flags?.config ?
|
|
2379
|
+
return process.env.REACT_ROUTER_ROOT || (flags?.config ? path9.dirname(path9.resolve(flags.config)) : process.cwd());
|
|
2368
2380
|
}
|
|
2369
2381
|
async function checkForEntry(rootDirectory, appDirectory, entries2) {
|
|
2370
2382
|
for (let entry of entries2) {
|
|
2371
|
-
let entryPath =
|
|
2383
|
+
let entryPath = path9.resolve(appDirectory, entry);
|
|
2372
2384
|
let exists = (0, import_node_fs4.existsSync)(entryPath);
|
|
2373
2385
|
if (exists) {
|
|
2374
|
-
let relative7 =
|
|
2386
|
+
let relative7 = path9.relative(rootDirectory, entryPath);
|
|
2375
2387
|
console.error(import_picocolors8.default.red(`Entry file ${relative7} already exists.`));
|
|
2376
2388
|
return process.exit(1);
|
|
2377
2389
|
}
|
|
@@ -2379,12 +2391,12 @@ async function checkForEntry(rootDirectory, appDirectory, entries2) {
|
|
|
2379
2391
|
}
|
|
2380
2392
|
async function createServerEntry(rootDirectory, appDirectory, inputFile) {
|
|
2381
2393
|
await checkForEntry(rootDirectory, appDirectory, serverEntries);
|
|
2382
|
-
let contents = await (0,
|
|
2394
|
+
let contents = await (0, import_promises4.readFile)(inputFile, "utf-8");
|
|
2383
2395
|
return contents;
|
|
2384
2396
|
}
|
|
2385
2397
|
async function createClientEntry(rootDirectory, appDirectory, inputFile) {
|
|
2386
2398
|
await checkForEntry(rootDirectory, appDirectory, clientEntries);
|
|
2387
|
-
let contents = await (0,
|
|
2399
|
+
let contents = await (0, import_promises4.readFile)(inputFile, "utf-8");
|
|
2388
2400
|
return contents;
|
|
2389
2401
|
}
|
|
2390
2402
|
async function typegen(root, flags) {
|
package/dist/config.d.ts
CHANGED
|
@@ -40,6 +40,10 @@ interface FutureConfig {
|
|
|
40
40
|
unstable_optimizeDeps: boolean;
|
|
41
41
|
unstable_subResourceIntegrity: boolean;
|
|
42
42
|
unstable_trailingSlashAwareDataRequests: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Prerender with Vite Preview server
|
|
45
|
+
*/
|
|
46
|
+
unstable_previewServerPrerendering?: boolean;
|
|
43
47
|
/**
|
|
44
48
|
* Enable route middleware
|
|
45
49
|
*/
|
|
@@ -148,6 +152,47 @@ type ReactRouterConfig = {
|
|
|
148
152
|
* SPA without server-rendering. Default's to `true`.
|
|
149
153
|
*/
|
|
150
154
|
ssr?: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* An array of allowed origin hosts for action submissions to UI routes (does not apply
|
|
157
|
+
* to resource routes). Supports micromatch glob patterns (`*` to match one segment,
|
|
158
|
+
* `**` to match multiple).
|
|
159
|
+
*
|
|
160
|
+
* ```tsx
|
|
161
|
+
* export default {
|
|
162
|
+
* allowedActionOrigins: [
|
|
163
|
+
* "example.com",
|
|
164
|
+
* "*.example.com", // sub.example.com
|
|
165
|
+
* "**.example.com", // sub.domain.example.com
|
|
166
|
+
* ],
|
|
167
|
+
* } satisfies Config;
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* If you need to set this value at runtime, you can do in by setting the value
|
|
171
|
+
* on the server build in your custom server. For example, when using `express`:
|
|
172
|
+
*
|
|
173
|
+
* ```ts
|
|
174
|
+
* import express from "express";
|
|
175
|
+
* import { createRequestHandler } from "@react-router/express";
|
|
176
|
+
* import type { ServerBuild } from "react-router";
|
|
177
|
+
*
|
|
178
|
+
* export const app = express();
|
|
179
|
+
*
|
|
180
|
+
* async function getBuild() {
|
|
181
|
+
* let build: ServerBuild = await import(
|
|
182
|
+
* "virtual:react-router/server-build"
|
|
183
|
+
* );
|
|
184
|
+
* return {
|
|
185
|
+
* ...build,
|
|
186
|
+
* allowedActionOrigins:
|
|
187
|
+
* process.env.NODE_ENV === "development"
|
|
188
|
+
* ? undefined
|
|
189
|
+
* : ["staging.example.com", "www.example.com"],
|
|
190
|
+
* };
|
|
191
|
+
* }
|
|
192
|
+
*
|
|
193
|
+
* app.use(createRequestHandler({ build: getBuild }));
|
|
194
|
+
*/
|
|
195
|
+
allowedActionOrigins?: string[];
|
|
151
196
|
};
|
|
152
197
|
type ResolvedReactRouterConfig = Readonly<{
|
|
153
198
|
/**
|
|
@@ -213,6 +258,11 @@ type ResolvedReactRouterConfig = Readonly<{
|
|
|
213
258
|
* SPA without server-rendering. Default's to `true`.
|
|
214
259
|
*/
|
|
215
260
|
ssr: boolean;
|
|
261
|
+
/**
|
|
262
|
+
* The allowed origins for actions / mutations. Does not apply to routes
|
|
263
|
+
* without a component. micromatch glob patterns are supported.
|
|
264
|
+
*/
|
|
265
|
+
allowedActionOrigins: string[] | false;
|
|
216
266
|
/**
|
|
217
267
|
* The resolved array of route config entries exported from `routes.ts`
|
|
218
268
|
*/
|
package/dist/config.js
CHANGED
package/dist/routes.js
CHANGED
package/dist/vite/cloudflare.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-e067e5e52
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -45,12 +45,8 @@ __export(cloudflare_exports, {
|
|
|
45
45
|
module.exports = __toCommonJS(cloudflare_exports);
|
|
46
46
|
|
|
47
47
|
// vite/cloudflare-dev-proxy.ts
|
|
48
|
-
var import_node_fetch_server2 = require("@remix-run/node-fetch-server");
|
|
49
48
|
var import_react_router = require("react-router");
|
|
50
49
|
|
|
51
|
-
// vite/node-adapter.ts
|
|
52
|
-
var import_node_fetch_server = require("@remix-run/node-fetch-server");
|
|
53
|
-
|
|
54
50
|
// invariant.ts
|
|
55
51
|
function invariant(value, message) {
|
|
56
52
|
if (value === false || value === null || typeof value === "undefined") {
|
|
@@ -62,13 +58,14 @@ function invariant(value, message) {
|
|
|
62
58
|
}
|
|
63
59
|
|
|
64
60
|
// vite/node-adapter.ts
|
|
65
|
-
function fromNodeRequest(nodeReq, nodeRes) {
|
|
61
|
+
async function fromNodeRequest(nodeReq, nodeRes) {
|
|
66
62
|
invariant(
|
|
67
63
|
nodeReq.originalUrl,
|
|
68
64
|
"Expected `nodeReq.originalUrl` to be defined"
|
|
69
65
|
);
|
|
70
66
|
nodeReq.url = nodeReq.originalUrl;
|
|
71
|
-
|
|
67
|
+
const { createRequest } = await import("@remix-run/node-fetch-server");
|
|
68
|
+
return createRequest(nodeReq, nodeRes);
|
|
72
69
|
}
|
|
73
70
|
|
|
74
71
|
// vite/vite.ts
|
|
@@ -536,10 +533,12 @@ async function resolveConfig({
|
|
|
536
533
|
unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
|
|
537
534
|
unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
|
|
538
535
|
unstable_trailingSlashAwareDataRequests: userAndPresetConfigs.future?.unstable_trailingSlashAwareDataRequests ?? false,
|
|
536
|
+
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
539
537
|
v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
|
|
540
538
|
v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
|
|
541
539
|
v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
|
|
542
540
|
};
|
|
541
|
+
let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;
|
|
543
542
|
let reactRouterConfig = deepFreeze({
|
|
544
543
|
appDirectory,
|
|
545
544
|
basename,
|
|
@@ -553,6 +552,7 @@ async function resolveConfig({
|
|
|
553
552
|
serverBundles,
|
|
554
553
|
serverModuleFormat,
|
|
555
554
|
ssr,
|
|
555
|
+
allowedActionOrigins,
|
|
556
556
|
unstable_routeConfig: routeConfig
|
|
557
557
|
});
|
|
558
558
|
for (let preset of reactRouterUserConfig.presets ?? []) {
|
|
@@ -818,6 +818,7 @@ var cloudflareDevProxyVitePlugin = (options = {}) => {
|
|
|
818
818
|
}
|
|
819
819
|
},
|
|
820
820
|
configureServer: async (viteDevServer) => {
|
|
821
|
+
const { sendResponse } = await import("@remix-run/node-fetch-server");
|
|
821
822
|
let context;
|
|
822
823
|
let getContext = async () => {
|
|
823
824
|
let { getPlatformProxy } = await importWrangler();
|
|
@@ -834,11 +835,11 @@ var cloudflareDevProxyVitePlugin = (options = {}) => {
|
|
|
834
835
|
serverBuildId
|
|
835
836
|
);
|
|
836
837
|
let handler = (0, import_react_router.createRequestHandler)(build, "development");
|
|
837
|
-
let req = fromNodeRequest(nodeReq, nodeRes);
|
|
838
|
+
let req = await fromNodeRequest(nodeReq, nodeRes);
|
|
838
839
|
context ??= await getContext();
|
|
839
840
|
let loadContext = getLoadContext ? await getLoadContext({ request: req, context }) : context;
|
|
840
841
|
let res = await handler(req, loadContext);
|
|
841
|
-
await
|
|
842
|
+
await sendResponse(nodeRes, res);
|
|
842
843
|
} catch (error) {
|
|
843
844
|
next(error);
|
|
844
845
|
}
|