react-router 7.11.0 → 7.12.0-pre.0
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 +46 -13
- package/dist/development/{browser-Cv4JZyZ5.d.mts → browser-BEPxnEBW.d.mts} +4 -2
- package/dist/{production/browser-Cv4JZyZ5.d.mts → development/browser-CJ9_du-U.d.ts} +4 -2
- package/dist/development/{chunk-YNUBSHFH.mjs → chunk-2RQJSHF5.mjs} +111 -11
- package/dist/development/{chunk-2JY4UAJA.js → chunk-AUGQXA25.js} +98 -108
- package/dist/{production/chunk-BEXOWXJO.js → development/chunk-JBLDGBX7.js} +7 -7
- package/dist/development/{chunk-JMJ3UQ3L.mjs → chunk-KYKH2NCS.mjs} +122 -50
- package/dist/development/{chunk-SZQUWNVJ.js → chunk-MNTWZBMV.js} +117 -35
- package/dist/development/dom-export.d.mts +2 -2
- package/dist/development/dom-export.d.ts +2 -2
- package/dist/development/dom-export.js +35 -30
- package/dist/development/dom-export.mjs +12 -7
- package/dist/development/{index-react-server-client-P7VgYu6T.d.mts → index-react-server-client-IoJGLOqV.d.mts} +3 -1
- package/dist/{production/index-react-server-client-Cv5Q9lf0.d.ts → development/index-react-server-client-gGyf-7Xp.d.ts} +3 -1
- package/dist/development/index-react-server-client.d.mts +2 -2
- package/dist/development/index-react-server-client.d.ts +2 -2
- package/dist/development/index-react-server-client.js +4 -4
- package/dist/development/index-react-server-client.mjs +2 -2
- package/dist/development/index-react-server.d.mts +3 -1
- package/dist/development/index-react-server.d.ts +3 -1
- package/dist/development/index-react-server.js +92 -7
- package/dist/development/index-react-server.mjs +92 -7
- package/dist/development/index.d.mts +9 -9
- package/dist/development/index.d.ts +9 -9
- package/dist/development/index.js +205 -101
- package/dist/development/index.mjs +7 -3
- package/dist/{production/instrumentation-BlrVzjbg.d.ts → development/instrumentation-DvHY1sgY.d.ts} +45 -1
- package/dist/development/lib/types/internal.d.mts +2 -2
- package/dist/development/lib/types/internal.d.ts +2 -2
- package/dist/development/lib/types/internal.js +1 -1
- package/dist/development/lib/types/internal.mjs +1 -1
- package/dist/development/{register-BGQUMCK4.d.ts → register-Bm80E9qL.d.ts} +1 -1
- package/dist/development/{register-DTJJbt1o.d.mts → register-CS_tiXsm.d.mts} +1 -1
- package/dist/development/{router-5fbeEIMQ.d.mts → router-5iOvts3c.d.mts} +45 -1
- package/dist/{development/browser-o-qhcuhA.d.ts → production/browser-BEPxnEBW.d.mts} +4 -2
- package/dist/production/{browser-o-qhcuhA.d.ts → browser-CJ9_du-U.d.ts} +4 -2
- package/dist/production/{chunk-TINMVEA2.mjs → chunk-HFQUWXEK.mjs} +122 -50
- package/dist/production/{chunk-E6GYEQUT.mjs → chunk-ILRYJQTC.mjs} +111 -11
- package/dist/{development/chunk-GNDLROV6.js → production/chunk-O6YLM5NB.js} +7 -7
- package/dist/production/{chunk-ZMYPVUNZ.js → chunk-QWJQISZK.js} +98 -108
- package/dist/production/{chunk-2HFJAX7U.js → chunk-ZR2NIBH2.js} +117 -35
- package/dist/production/dom-export.d.mts +2 -2
- package/dist/production/dom-export.d.ts +2 -2
- package/dist/production/dom-export.js +35 -30
- package/dist/production/dom-export.mjs +12 -7
- package/dist/production/{index-react-server-client-P7VgYu6T.d.mts → index-react-server-client-IoJGLOqV.d.mts} +3 -1
- package/dist/{development/index-react-server-client-Cv5Q9lf0.d.ts → production/index-react-server-client-gGyf-7Xp.d.ts} +3 -1
- package/dist/production/index-react-server-client.d.mts +2 -2
- package/dist/production/index-react-server-client.d.ts +2 -2
- package/dist/production/index-react-server-client.js +4 -4
- package/dist/production/index-react-server-client.mjs +2 -2
- package/dist/production/index-react-server.d.mts +3 -1
- package/dist/production/index-react-server.d.ts +3 -1
- package/dist/production/index-react-server.js +92 -7
- package/dist/production/index-react-server.mjs +92 -7
- package/dist/production/index.d.mts +9 -9
- package/dist/production/index.d.ts +9 -9
- package/dist/production/index.js +205 -101
- package/dist/production/index.mjs +7 -3
- package/dist/{development/instrumentation-BlrVzjbg.d.ts → production/instrumentation-DvHY1sgY.d.ts} +45 -1
- package/dist/production/lib/types/internal.d.mts +2 -2
- package/dist/production/lib/types/internal.d.ts +2 -2
- package/dist/production/lib/types/internal.js +1 -1
- package/dist/production/lib/types/internal.mjs +1 -1
- package/dist/production/{register-BGQUMCK4.d.ts → register-Bm80E9qL.d.ts} +1 -1
- package/dist/production/{register-DTJJbt1o.d.mts → register-CS_tiXsm.d.mts} +1 -1
- package/dist/production/{router-5fbeEIMQ.d.mts → router-5iOvts3c.d.mts} +45 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# `react-router`
|
|
2
2
|
|
|
3
|
+
## 7.12.0-pre.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 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))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Fix `generatePath` when used with suffixed params (i.e., "/books/:id.json") ([#14269](https://github.com/remix-run/react-router/pull/14269))
|
|
12
|
+
- Export `UNSAFE_createMemoryHistory` and `UNSAFE_createHashHistory` alongside `UNSAFE_createBrowserHistory` for consistency. These are not intended to be used for new apps but intended to help apps usiong `unstable_HistoryRouter` migrate from v6->v7 so they can adopt the newer APIs. ([#14663](https://github.com/remix-run/react-router/pull/14663))
|
|
13
|
+
- Escape HTML in scroll restoration keys ([#14705](https://github.com/remix-run/react-router/pull/14705))
|
|
14
|
+
- Validate redirect locations ([#14706](https://github.com/remix-run/react-router/pull/14706))
|
|
15
|
+
- [UNSTABLE] Pass `<Scripts nonce>` value through to the underlying `importmap` `script` tag when using `future.unstable_subResourceIntegrity` ([#14675](https://github.com/remix-run/react-router/pull/14675))
|
|
16
|
+
- [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))
|
|
17
|
+
|
|
18
|
+
Currently, your HTTP and `request` pathnames would be as follows for `/a/b/c` and `/a/b/c/`
|
|
19
|
+
|
|
20
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname`** |
|
|
21
|
+
| ------------ | ----------------- | ----------------------- |
|
|
22
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
23
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
24
|
+
|
|
25
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname`** |
|
|
26
|
+
| ------------- | ----------------- | ----------------------- |
|
|
27
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
28
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ⚠️ |
|
|
29
|
+
|
|
30
|
+
With this flag enabled, these pathnames will be made consistent though a new `_.data` format for client-side `.data` requests:
|
|
31
|
+
|
|
32
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname`** |
|
|
33
|
+
| ------------ | ----------------- | ----------------------- |
|
|
34
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
35
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
36
|
+
|
|
37
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname`** |
|
|
38
|
+
| ------------- | ------------------ | ----------------------- |
|
|
39
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
40
|
+
| **Data** | `/a/b/c/_.data` ⬅️ | `/a/b/c/` ✅ |
|
|
41
|
+
|
|
42
|
+
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.
|
|
43
|
+
|
|
44
|
+
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.
|
|
45
|
+
|
|
46
|
+
- Preserve `clientLoader.hydrate=true` when using `<HydratedRouter unstable_instrumentations>` ([#14674](https://github.com/remix-run/react-router/pull/14674))
|
|
47
|
+
|
|
3
48
|
## 7.11.0
|
|
4
49
|
|
|
5
50
|
### Minor Changes
|
|
@@ -19,14 +64,12 @@
|
|
|
19
64
|
- \[UNSTABLE] Add a new `unstable_defaultShouldRevalidate` flag to various APIs to allow opt-ing out of standard revalidation behaviors. ([#14542](https://github.com/remix-run/react-router/pull/14542))
|
|
20
65
|
|
|
21
66
|
If active routes include a `shouldRevalidate` function, then your value will be passed as `defaultShouldRevalidate` in those function so that the route always has the final revalidation determination.
|
|
22
|
-
|
|
23
67
|
- `<Form method="post" unstable_defaultShouldRevalidate={false}>`
|
|
24
68
|
- `submit(data, { method: "post", unstable_defaultShouldRevalidate: false })`
|
|
25
69
|
- `<fetcher.Form method="post" unstable_defaultShouldRevalidate={false}>`
|
|
26
70
|
- `fetcher.submit(data, { method: "post", unstable_defaultShouldRevalidate: false })`
|
|
27
71
|
|
|
28
72
|
This is also available on non-submission APIs that may trigger revalidations due to changing search params:
|
|
29
|
-
|
|
30
73
|
- `<Link to="/" unstable_defaultShouldRevalidate={false}>`
|
|
31
74
|
- `navigate("/?foo=bar", { unstable_defaultShouldRevalidate: false })`
|
|
32
75
|
- `setSearchParams(params, { unstable_defaultShouldRevalidate: false })`
|
|
@@ -49,7 +92,6 @@
|
|
|
49
92
|
- ⚠️ This is a breaking change if you have begun using `fetcher.unstable_reset()`
|
|
50
93
|
|
|
51
94
|
- Stabilize the `dataStrategy` `match.shouldRevalidateArgs`/`match.shouldCallHandler()` APIs. ([#14592](https://github.com/remix-run/react-router/pull/14592))
|
|
52
|
-
|
|
53
95
|
- The `match.shouldLoad` API is now marked deprecated in favor of these more powerful alternatives
|
|
54
96
|
|
|
55
97
|
- If you're using this API in a custom `dataStrategy` today, you can swap to the new API at your convenience:
|
|
@@ -178,7 +220,6 @@
|
|
|
178
220
|
- Ensure action handlers run for routes with middleware even if no loader is present ([#14443](https://github.com/remix-run/react-router/pull/14443))
|
|
179
221
|
|
|
180
222
|
- Add `unstable_instrumentations` API to allow users to add observablity to their apps by instrumenting route loaders, actions, middlewares, lazy, as well as server-side request handlers and client side navigations/fetches ([#14412](https://github.com/remix-run/react-router/pull/14412))
|
|
181
|
-
|
|
182
223
|
- Framework Mode:
|
|
183
224
|
- `entry.server.tsx`: `export const unstable_instrumentations = [...]`
|
|
184
225
|
- `entry.client.tsx`: `<HydratedRouter unstable_instrumentations={[...]} />`
|
|
@@ -340,7 +381,6 @@
|
|
|
340
381
|
- Stabilize middleware and context APIs. ([#14215](https://github.com/remix-run/react-router/pull/14215))
|
|
341
382
|
|
|
342
383
|
We have removed the `unstable_` prefix from the following APIs and they are now considered stable and ready for production use:
|
|
343
|
-
|
|
344
384
|
- [`RouterContextProvider`](https://reactrouter.com/api/utils/RouterContextProvider)
|
|
345
385
|
- [`createContext`](https://reactrouter.com/api/utils/createContext)
|
|
346
386
|
- `createBrowserRouter` [`getContext`](https://reactrouter.com/api/data-routers/createBrowserRouter#optsgetcontext) option
|
|
@@ -367,7 +407,7 @@
|
|
|
367
407
|
|
|
368
408
|
- \[UNSTABLE] Add `<RouterProvider unstable_onError>`/`<HydratedRouter unstable_onError>` prop for client side error reporting ([#14162](https://github.com/remix-run/react-router/pull/14162))
|
|
369
409
|
|
|
370
|
-
- server action revalidation opt out via $
|
|
410
|
+
- server action revalidation opt out via $SKIP_REVALIDATION field ([#14154](https://github.com/remix-run/react-router/pull/14154))
|
|
371
411
|
|
|
372
412
|
- Properly escape interpolated param values in `generatePath()` ([#13530](https://github.com/remix-run/react-router/pull/13530))
|
|
373
413
|
|
|
@@ -416,7 +456,6 @@
|
|
|
416
456
|
- Remove dependency on `@types/node` in TypeScript declaration files ([#14059](https://github.com/remix-run/react-router/pull/14059))
|
|
417
457
|
|
|
418
458
|
- Fix types for `UIMatch` to reflect that the `loaderData`/`data` properties may be `undefined` ([#12206](https://github.com/remix-run/react-router/pull/12206))
|
|
419
|
-
|
|
420
459
|
- When an `ErrorBoundary` is being rendered, not all active matches will have loader data available, since it may have been their `loader` that threw to trigger the boundary
|
|
421
460
|
- The `UIMatch.data` type was not correctly handing this and would always reflect the presence of data, leading to the unexpected runtime errors when an `ErrorBoundary` was rendered
|
|
422
461
|
- ⚠️ This may cause some type errors to show up in your code for unguarded `match.data` accesses - you should properly guard for `undefined` values in those scenarios.
|
|
@@ -450,7 +489,6 @@
|
|
|
450
489
|
- \[UNSTABLE] When middleware is enabled, make the `context` parameter read-only (via `Readonly<unstable_RouterContextProvider>`) so that TypeScript will not allow you to write arbitrary fields to it in loaders, actions, or middleware. ([#14097](https://github.com/remix-run/react-router/pull/14097))
|
|
451
490
|
|
|
452
491
|
- \[UNSTABLE] Rename and alter the signature/functionality of the `unstable_respond` API in `staticHandler.query`/`staticHandler.queryRoute` ([#14103](https://github.com/remix-run/react-router/pull/14103))
|
|
453
|
-
|
|
454
492
|
- The API has been renamed to `unstable_generateMiddlewareResponse` for clarity
|
|
455
493
|
- The main functional change is that instead of running the loaders/actions before calling `unstable_respond` and handing you the result, we now pass a `query`/`queryRoute` function as a parameter and you execute the loaders/actions inside your callback, giving you full access to pre-processing and error handling
|
|
456
494
|
- The `query` version of the API now has a signature of `(query: (r: Request) => Promise<StaticHandlerContext | Response>) => Promise<Response>`
|
|
@@ -1096,7 +1134,6 @@
|
|
|
1096
1134
|
```
|
|
1097
1135
|
|
|
1098
1136
|
Similar to server-side requests, a fresh `context` will be created per navigation (or `fetcher` call). If you have initial data you'd like to populate in the context for every request, you can provide an `unstable_getContext` function at the root of your app:
|
|
1099
|
-
|
|
1100
1137
|
- Library mode - `createBrowserRouter(routes, { unstable_getContext })`
|
|
1101
1138
|
- Framework mode - `<HydratedRouter unstable_getContext>`
|
|
1102
1139
|
|
|
@@ -1284,7 +1321,6 @@ _No changes_
|
|
|
1284
1321
|
- Remove `future.v7_normalizeFormMethod` future flag ([#11697](https://github.com/remix-run/react-router/pull/11697))
|
|
1285
1322
|
|
|
1286
1323
|
- For Remix consumers migrating to React Router, the `crypto` global from the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is now required when using cookie and session APIs. This means that the following APIs are provided from `react-router` rather than platform-specific packages: ([#11837](https://github.com/remix-run/react-router/pull/11837))
|
|
1287
|
-
|
|
1288
1324
|
- `createCookie`
|
|
1289
1325
|
- `createCookieSessionStorage`
|
|
1290
1326
|
- `createMemorySessionStorage`
|
|
@@ -1293,7 +1329,6 @@ _No changes_
|
|
|
1293
1329
|
For consumers running older versions of Node, the `installGlobals` function from `@remix-run/node` has been updated to define `globalThis.crypto`, using [Node's `require('node:crypto').webcrypto` implementation.](https://nodejs.org/api/webcrypto.html)
|
|
1294
1330
|
|
|
1295
1331
|
Since platform-specific packages no longer need to implement this API, the following low-level APIs have been removed:
|
|
1296
|
-
|
|
1297
1332
|
- `createCookieFactory`
|
|
1298
1333
|
- `createSessionStorageFactory`
|
|
1299
1334
|
- `createCookieSessionStorageFactory`
|
|
@@ -1449,7 +1484,6 @@ _No changes_
|
|
|
1449
1484
|
```
|
|
1450
1485
|
|
|
1451
1486
|
This initial implementation targets type inference for:
|
|
1452
|
-
|
|
1453
1487
|
- `Params` : Path parameters from your routing config in `routes.ts` including file-based routing
|
|
1454
1488
|
- `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module
|
|
1455
1489
|
- `ActionData` : Action data from `action` and/or `clientAction` within your route module
|
|
@@ -1464,7 +1498,6 @@ _No changes_
|
|
|
1464
1498
|
```
|
|
1465
1499
|
|
|
1466
1500
|
Check out our docs for more:
|
|
1467
|
-
|
|
1468
1501
|
- [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety)
|
|
1469
1502
|
- [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety)
|
|
1470
1503
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './router-
|
|
2
|
+
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './router-5iOvts3c.mjs';
|
|
3
3
|
|
|
4
4
|
type RSCRouteConfigEntryBase = {
|
|
5
5
|
action?: ActionFunction;
|
|
@@ -138,6 +138,7 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
138
138
|
* @category RSC
|
|
139
139
|
* @mode data
|
|
140
140
|
* @param opts Options
|
|
141
|
+
* @param opts.allowedActionOrigins Origin patterns that are allowed to execute actions.
|
|
141
142
|
* @param opts.basename The basename to use when matching the request.
|
|
142
143
|
* @param opts.createTemporaryReferenceSet A function that returns a temporary
|
|
143
144
|
* reference set for the request, used to track temporary references in the [RSC](https://react.dev/reference/rsc/server-components)
|
|
@@ -167,7 +168,8 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
167
168
|
* that contains the [RSC](https://react.dev/reference/rsc/server-components)
|
|
168
169
|
* data for hydration.
|
|
169
170
|
*/
|
|
170
|
-
declare function matchRSCServerRequest({ createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
171
|
+
declare function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
172
|
+
allowedActionOrigins?: string[];
|
|
171
173
|
createTemporaryReferenceSet: () => unknown;
|
|
172
174
|
basename?: string;
|
|
173
175
|
decodeReply?: DecodeReplyFunction;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './
|
|
2
|
+
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './instrumentation-DvHY1sgY.js';
|
|
3
3
|
|
|
4
4
|
type RSCRouteConfigEntryBase = {
|
|
5
5
|
action?: ActionFunction;
|
|
@@ -138,6 +138,7 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
138
138
|
* @category RSC
|
|
139
139
|
* @mode data
|
|
140
140
|
* @param opts Options
|
|
141
|
+
* @param opts.allowedActionOrigins Origin patterns that are allowed to execute actions.
|
|
141
142
|
* @param opts.basename The basename to use when matching the request.
|
|
142
143
|
* @param opts.createTemporaryReferenceSet A function that returns a temporary
|
|
143
144
|
* reference set for the request, used to track temporary references in the [RSC](https://react.dev/reference/rsc/server-components)
|
|
@@ -167,7 +168,8 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
167
168
|
* that contains the [RSC](https://react.dev/reference/rsc/server-components)
|
|
168
169
|
* data for hydration.
|
|
169
170
|
*/
|
|
170
|
-
declare function matchRSCServerRequest({ createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
171
|
+
declare function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
172
|
+
allowedActionOrigins?: string[];
|
|
171
173
|
createTemporaryReferenceSet: () => unknown;
|
|
172
174
|
basename?: string;
|
|
173
175
|
decodeReply?: DecodeReplyFunction;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v7.
|
|
2
|
+
* react-router v7.12.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
withComponentProps,
|
|
52
52
|
withErrorBoundaryProps,
|
|
53
53
|
withHydrateFallbackProps
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-KYKH2NCS.mjs";
|
|
55
55
|
|
|
56
56
|
// lib/dom/ssr/server.tsx
|
|
57
57
|
import * as React from "react";
|
|
@@ -138,7 +138,8 @@ function createRoutesStub(routes, _context) {
|
|
|
138
138
|
frameworkContextRef.current = {
|
|
139
139
|
future: {
|
|
140
140
|
unstable_subResourceIntegrity: future?.unstable_subResourceIntegrity === true,
|
|
141
|
-
v8_middleware: future?.v8_middleware === true
|
|
141
|
+
v8_middleware: future?.v8_middleware === true,
|
|
142
|
+
unstable_trailingSlashAwareDataRequests: future?.unstable_trailingSlashAwareDataRequests === true
|
|
142
143
|
},
|
|
143
144
|
manifest: {
|
|
144
145
|
routes: {},
|
|
@@ -754,6 +755,85 @@ function prependCookies(parentHeaders, childHeaders) {
|
|
|
754
755
|
}
|
|
755
756
|
}
|
|
756
757
|
|
|
758
|
+
// lib/actions.ts
|
|
759
|
+
function throwIfPotentialCSRFAttack(headers, allowedActionOrigins) {
|
|
760
|
+
let originHeader = headers.get("origin");
|
|
761
|
+
let originDomain = typeof originHeader === "string" && originHeader !== "null" ? new URL(originHeader).host : originHeader;
|
|
762
|
+
let host = parseHostHeader(headers);
|
|
763
|
+
if (originDomain && (!host || originDomain !== host.value)) {
|
|
764
|
+
if (!isAllowedOrigin(originDomain, allowedActionOrigins)) {
|
|
765
|
+
if (host) {
|
|
766
|
+
throw new Error(
|
|
767
|
+
`${host.type} header does not match \`origin\` header from a forwarded action request. Aborting the action.`
|
|
768
|
+
);
|
|
769
|
+
} else {
|
|
770
|
+
throw new Error(
|
|
771
|
+
"`x-forwarded-host` or `host` headers are not provided. One of these is needed to compare the `origin` header from a forwarded action request. Aborting the action."
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
function matchWildcardDomain(domain, pattern) {
|
|
778
|
+
const domainParts = domain.split(".");
|
|
779
|
+
const patternParts = pattern.split(".");
|
|
780
|
+
if (patternParts.length < 1) {
|
|
781
|
+
return false;
|
|
782
|
+
}
|
|
783
|
+
if (domainParts.length < patternParts.length) {
|
|
784
|
+
return false;
|
|
785
|
+
}
|
|
786
|
+
if (patternParts.length === 1 && (patternParts[0] === "*" || patternParts[0] === "**")) {
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
while (patternParts.length) {
|
|
790
|
+
const patternPart = patternParts.pop();
|
|
791
|
+
const domainPart = domainParts.pop();
|
|
792
|
+
switch (patternPart) {
|
|
793
|
+
case "": {
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
case "*": {
|
|
797
|
+
if (domainPart) {
|
|
798
|
+
continue;
|
|
799
|
+
} else {
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
case "**": {
|
|
804
|
+
if (patternParts.length > 0) {
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
return domainPart !== void 0;
|
|
808
|
+
}
|
|
809
|
+
case void 0:
|
|
810
|
+
default: {
|
|
811
|
+
if (domainPart !== patternPart) {
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
return domainParts.length === 0;
|
|
818
|
+
}
|
|
819
|
+
function isAllowedOrigin(originDomain, allowedActionOrigins = []) {
|
|
820
|
+
return allowedActionOrigins.some(
|
|
821
|
+
(allowedOrigin) => allowedOrigin && (allowedOrigin === originDomain || matchWildcardDomain(originDomain, allowedOrigin))
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
function parseHostHeader(headers) {
|
|
825
|
+
let forwardedHostHeader = headers.get("x-forwarded-host");
|
|
826
|
+
let forwardedHostValue = forwardedHostHeader?.split(",")[0]?.trim();
|
|
827
|
+
let hostHeader = headers.get("host");
|
|
828
|
+
return forwardedHostValue ? {
|
|
829
|
+
type: "x-forwarded-host",
|
|
830
|
+
value: forwardedHostValue
|
|
831
|
+
} : hostHeader ? {
|
|
832
|
+
type: "host",
|
|
833
|
+
value: hostHeader
|
|
834
|
+
} : void 0;
|
|
835
|
+
}
|
|
836
|
+
|
|
757
837
|
// lib/server-runtime/single-fetch.ts
|
|
758
838
|
var SERVER_NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([
|
|
759
839
|
...NO_BODY_STATUS_CODES,
|
|
@@ -761,6 +841,10 @@ var SERVER_NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([
|
|
|
761
841
|
]);
|
|
762
842
|
async function singleFetchAction(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
|
|
763
843
|
try {
|
|
844
|
+
throwIfPotentialCSRFAttack(
|
|
845
|
+
request.headers,
|
|
846
|
+
Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []
|
|
847
|
+
);
|
|
764
848
|
let handlerRequest = new Request(handlerUrl, {
|
|
765
849
|
method: request.method,
|
|
766
850
|
body: request.body,
|
|
@@ -1041,13 +1125,21 @@ function derive(build, mode) {
|
|
|
1041
1125
|
let url = new URL(request.url);
|
|
1042
1126
|
let normalizedBasename = build.basename || "/";
|
|
1043
1127
|
let normalizedPath = url.pathname;
|
|
1044
|
-
if (
|
|
1045
|
-
normalizedPath
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1128
|
+
if (build.future.unstable_trailingSlashAwareDataRequests) {
|
|
1129
|
+
if (normalizedPath.endsWith("/_.data")) {
|
|
1130
|
+
normalizedPath = normalizedPath.replace(/_.data$/, "");
|
|
1131
|
+
} else {
|
|
1132
|
+
normalizedPath = normalizedPath.replace(/\.data$/, "");
|
|
1133
|
+
}
|
|
1134
|
+
} else {
|
|
1135
|
+
if (stripBasename(normalizedPath, normalizedBasename) === "/_root.data") {
|
|
1136
|
+
normalizedPath = normalizedBasename;
|
|
1137
|
+
} else if (normalizedPath.endsWith(".data")) {
|
|
1138
|
+
normalizedPath = normalizedPath.replace(/\.data$/, "");
|
|
1139
|
+
}
|
|
1140
|
+
if (stripBasename(normalizedPath, normalizedBasename) !== "/" && normalizedPath.endsWith("/")) {
|
|
1141
|
+
normalizedPath = normalizedPath.slice(0, -1);
|
|
1142
|
+
}
|
|
1051
1143
|
}
|
|
1052
1144
|
let isSpaMode = getBuildTimeHeader(request, "X-React-Router-SPA-Mode") === "yes";
|
|
1053
1145
|
if (!build.ssr) {
|
|
@@ -1303,6 +1395,12 @@ async function handleSingleFetchRequest(serverMode, build, staticHandler, reques
|
|
|
1303
1395
|
}
|
|
1304
1396
|
async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, isSpaMode, criticalCss) {
|
|
1305
1397
|
try {
|
|
1398
|
+
if (request.method === "POST") {
|
|
1399
|
+
throwIfPotentialCSRFAttack(
|
|
1400
|
+
request.headers,
|
|
1401
|
+
Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1306
1404
|
let result = await staticHandler.query(request, {
|
|
1307
1405
|
requestContext: loadContext,
|
|
1308
1406
|
generateMiddlewareResponse: build.future.v8_middleware ? async (query) => {
|
|
@@ -2274,7 +2372,9 @@ function RSCStaticRouter({ getPayload }) {
|
|
|
2274
2372
|
// These flags have no runtime impact so can always be false. If we add
|
|
2275
2373
|
// flags that drive runtime behavior they'll need to be proxied through.
|
|
2276
2374
|
v8_middleware: false,
|
|
2277
|
-
unstable_subResourceIntegrity: false
|
|
2375
|
+
unstable_subResourceIntegrity: false,
|
|
2376
|
+
unstable_trailingSlashAwareDataRequests: true
|
|
2377
|
+
// always on for RSC
|
|
2278
2378
|
},
|
|
2279
2379
|
isSpaMode: false,
|
|
2280
2380
|
ssr: true,
|