UNPKG

134 kB JavaScript View Raw
1/**
2 * react-router v8.5.1
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11import { AsyncLocalStorage } from "node:async_hooks";
12import * as React from "react";
13import { parse, serialize, splitSetCookieString } from "cookie-es";
14import { BrowserRouter, Form, HashRouter, Link, Links, MemoryRouter, Meta, NavLink, Navigate, Outlet, Outlet as Outlet$1, Route, Router, RouterProvider, Routes, ScrollRestoration, StaticRouter, StaticRouterProvider, UNSAFE_AwaitContextProvider, UNSAFE_WithComponentProps, UNSAFE_WithErrorBoundaryProps, UNSAFE_WithHydrateFallbackProps, unstable_HistoryRouter } from "react-router/internal/react-server-client";
15//#region lib/router/url.ts
16const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i;
17//#endregion
18//#region lib/router/history.ts
19function invariant$1(value, message) {
20 if (value === false || value === null || typeof value === "undefined") throw new Error(message);
21}
22function warning(cond, message) {
23 if (!cond) {
24 if (typeof console !== "undefined") console.warn(message);
25 try {
26 throw new Error(message);
27 } catch {}
28 }
29}
30function createKey$1() {
31 return Math.random().toString(36).substring(2, 10);
32}
33/**
34* Creates a Location object with a unique key from the given Path
35*/
36function createLocation(current, to, state = null, key, mask) {
37 return {
38 pathname: typeof current === "string" ? current : current.pathname,
39 search: "",
40 hash: "",
41 ...typeof to === "string" ? parsePath(to) : to,
42 state,
43 key: to && to.key || key || createKey$1(),
44 mask
45 };
46}
47/**
48* Creates a string URL path from the given pathname, search, and hash components.
49*
50* @public
51* @category Utils
52* @param path The pathname, search, and hash components to combine.
53* @returns The combined URL path.
54*/
55function createPath({ pathname = "/", search = "", hash = "" }) {
56 if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search;
57 if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
58 return pathname;
59}
60/**
61* Parses a string URL path into its separate pathname, search, and hash components.
62*
63* @public
64* @category Utils
65* @param path The URL path to parse.
66* @returns The parsed pathname, search, and hash components.
67*/
68function parsePath(path) {
69 let parsedPath = {};
70 if (path) {
71 let hashIndex = path.indexOf("#");
72 if (hashIndex >= 0) {
73 parsedPath.hash = path.substring(hashIndex);
74 path = path.substring(0, hashIndex);
75 }
76 let searchIndex = path.indexOf("?");
77 if (searchIndex >= 0) {
78 parsedPath.search = path.substring(searchIndex);
79 path = path.substring(0, searchIndex);
80 }
81 if (path) parsedPath.pathname = path;
82 }
83 return parsedPath;
84}
85//#endregion
86//#region lib/router/utils.ts
87/**
88* Creates a type-safe {@link RouterContext} object that can be used to
89* store and retrieve arbitrary values in [`action`](../../start/framework/route-module#action)s,
90* [`loader`](../../start/framework/route-module#loader)s, and [middleware](../../how-to/middleware).
91* Similar to React's [`createContext`](https://react.dev/reference/react/createContext),
92* but specifically designed for React Router's request/response lifecycle.
93*
94* If a `defaultValue` is provided, it will be returned from `context.get()`
95* when no value has been set for the context. Otherwise, reading this context
96* when no value has been set will throw an error.
97*
98* ```tsx filename=app/context.ts
99* import { createContext } from "react-router";
100*
101* // Create a context for user data
102* export const userContext =
103* createContext<User | null>(null);
104* ```
105*
106* ```tsx filename=app/middleware/auth.ts
107* import { getUserFromSession } from "~/auth.server";
108* import { userContext } from "~/context";
109*
110* export const authMiddleware = async ({
111* context,
112* request,
113* }) => {
114* const user = await getUserFromSession(request);
115* context.set(userContext, user);
116* };
117* ```
118*
119* ```tsx filename=app/routes/profile.tsx
120* import { userContext } from "~/context";
121*
122* export async function loader({
123* context,
124* }: Route.LoaderArgs) {
125* const user = context.get(userContext);
126*
127* if (!user) {
128* throw new Response("Unauthorized", { status: 401 });
129* }
130*
131* return { user };
132* }
133* ```
134*
135* @public
136* @category Utils
137* @mode framework
138* @mode data
139* @param defaultValue An optional default value for the context. This value
140* will be returned if no value has been set for this context.
141* @returns A {@link RouterContext} object that can be used with
142* `context.get()` and `context.set()` in [`action`](../../start/framework/route-module#action)s,
143* [`loader`](../../start/framework/route-module#loader)s, and [middleware](../../how-to/middleware).
144*/
145function createContext(defaultValue) {
146 return { defaultValue };
147}
148/**
149* Provides methods for writing/reading values in application context in a
150* type-safe way. Primarily for usage with [middleware](../../how-to/middleware).
151*
152* @example
153* import {
154* createContext,
155* RouterContextProvider
156* } from "react-router";
157*
158* const userContext = createContext<User | null>(null);
159* const contextProvider = new RouterContextProvider();
160* contextProvider.set(userContext, getUser());
161* // ^ Type-safe
162* const user = contextProvider.get(userContext);
163* // ^ User
164*
165* @public
166* @category Utils
167* @mode framework
168* @mode data
169*/
170var RouterContextProvider = class {
171 #map = /* @__PURE__ */ new Map();
172 /**
173 * Create a new `RouterContextProvider` instance
174 * @param init An optional initial context map to populate the provider with
175 */
176 constructor(init) {
177 if (init) for (let [context, value] of init) this.set(context, value);
178 }
179 /**
180 * Access a value from the context. If no value has been set for the context,
181 * it will return the context's `defaultValue` if provided, or throw an error
182 * if no `defaultValue` was set.
183 * @param context The context to get the value for
184 * @returns The value for the context, or the context's `defaultValue` if no
185 * value was set
186 */
187 get(context) {
188 if (this.#map.has(context)) return this.#map.get(context);
189 if (context.defaultValue !== void 0) return context.defaultValue;
190 throw new Error("No value found for context");
191 }
192 /**
193 * Set a value for the context. If the context already has a value set, this
194 * will overwrite it.
195 *
196 * @param context The context to set the value for
197 * @param value The value to set for the context
198 * @returns {void}
199 */
200 set(context, value) {
201 this.#map.set(context, value);
202 }
203};
204const unsupportedLazyRouteObjectKeys = new Set([
205 "lazy",
206 "caseSensitive",
207 "path",
208 "id",
209 "index",
210 "children",
211 "unstable_validateParams"
212]);
213function isUnsupportedLazyRouteObjectKey(key) {
214 return unsupportedLazyRouteObjectKeys.has(key);
215}
216const unsupportedLazyRouteFunctionKeys = new Set([
217 "lazy",
218 "caseSensitive",
219 "path",
220 "id",
221 "index",
222 "middleware",
223 "children",
224 "unstable_validateParams"
225]);
226function isUnsupportedLazyRouteFunctionKey(key) {
227 return unsupportedLazyRouteFunctionKeys.has(key);
228}
229function isIndexRoute(route) {
230 return route.index === true;
231}
232function defaultMapRouteProperties(route) {
233 let updates = {};
234 if (route.Component) {
235 if (route.element) warning(false, "You should not include both `Component` and `element` on your route - `Component` will be used.");
236 Object.assign(updates, {
237 element: React.createElement(route.Component),
238 Component: void 0
239 });
240 }
241 if (route.HydrateFallback) {
242 if (route.hydrateFallbackElement) warning(false, "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used.");
243 Object.assign(updates, {
244 hydrateFallbackElement: React.createElement(route.HydrateFallback),
245 HydrateFallback: void 0
246 });
247 }
248 if (route.ErrorBoundary) {
249 if (route.errorElement) warning(false, "You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used.");
250 Object.assign(updates, {
251 errorElement: React.createElement(route.ErrorBoundary),
252 ErrorBoundary: void 0
253 });
254 }
255 return updates;
256}
257function convertRoutesToDataRoutes(routes, mapRouteProperties = defaultMapRouteProperties, parentPath = [], manifest = {}, allowInPlaceMutations = false) {
258 return routes.map((route, index) => {
259 let treePath = [...parentPath, String(index)];
260 let id = typeof route.id === "string" ? route.id : treePath.join("-");
261 invariant$1(route.index !== true || !route.children, `Cannot specify children on an index route`);
262 invariant$1(allowInPlaceMutations || !manifest[id], `Found a route id collision on id "${id}". Route id's must be globally unique within Data Router usages`);
263 if (isIndexRoute(route)) {
264 let indexRoute = {
265 ...route,
266 id
267 };
268 manifest[id] = mergeRouteUpdates(indexRoute, mapRouteProperties(indexRoute));
269 return indexRoute;
270 } else {
271 let pathOrLayoutRoute = {
272 ...route,
273 id,
274 children: void 0
275 };
276 manifest[id] = mergeRouteUpdates(pathOrLayoutRoute, mapRouteProperties(pathOrLayoutRoute));
277 if (route.children) pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, mapRouteProperties, treePath, manifest, allowInPlaceMutations);
278 return pathOrLayoutRoute;
279 }
280 });
281}
282function mergeRouteUpdates(route, updates) {
283 return Object.assign(route, {
284 ...updates,
285 ...typeof updates.lazy === "object" && updates.lazy != null ? { lazy: {
286 ...route.lazy,
287 ...updates.lazy
288 } } : {}
289 });
290}
291/**
292* Matches the given routes to a location and returns the match data.
293*
294* @example
295* import { matchRoutes } from "react-router";
296*
297* let routes = [{
298* path: "/",
299* Component: Root,
300* children: [{
301* path: "dashboard",
302* Component: Dashboard,
303* }]
304* }];
305*
306* matchRoutes(routes, "/dashboard"); // [rootMatch, dashboardMatch]
307*
308* @public
309* @category Utils
310* @param routes The array of route objects to match against.
311* @param locationArg The location to match against, either a string path or a
312* partial {@link Location} object
313* @param basename Optional base path to strip from the location before matching.
314* Defaults to `/`.
315* @returns An array of matched routes, or `null` if no matches were found.
316*/
317function matchRoutes(routes, locationArg, basename = "/") {
318 return matchRoutesImpl(routes, locationArg, basename, false);
319}
320function matchRoutesImpl(routes, locationArg, basename, allowPartial, precomputedBranches) {
321 let pathname = stripBasename((typeof locationArg === "string" ? parsePath(locationArg) : locationArg).pathname || "/", basename);
322 if (pathname == null) return null;
323 let branches = precomputedBranches ?? flattenAndRankRoutes(routes);
324 let matches = null;
325 let decoded = decodePath(pathname);
326 for (let i = 0; matches == null && i < branches.length; ++i) matches = matchRouteBranch(branches[i], decoded, allowPartial);
327 return matches;
328}
329function convertRouteMatchToUiMatch(match, loaderData) {
330 let { route, pathname, params } = match;
331 return {
332 id: route.id,
333 pathname,
334 params,
335 loaderData: loaderData[route.id],
336 handle: route.handle
337 };
338}
339function flattenAndRankRoutes(routes) {
340 let branches = flattenRoutes(routes);
341 rankRouteBranches(branches);
342 return branches;
343}
344function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "", _hasParentOptionalSegments = false) {
345 let flattenRoute = (route, index, hasParentOptionalSegments = _hasParentOptionalSegments, relativePath) => {
346 let meta = {
347 relativePath: relativePath === void 0 ? route.path || "" : relativePath,
348 caseSensitive: route.caseSensitive === true,
349 childrenIndex: index,
350 route
351 };
352 if (meta.relativePath.startsWith("/")) {
353 if (!meta.relativePath.startsWith(parentPath) && hasParentOptionalSegments) return;
354 invariant$1(meta.relativePath.startsWith(parentPath), `Absolute route path "${meta.relativePath}" nested under path "${parentPath}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`);
355 meta.relativePath = meta.relativePath.slice(parentPath.length);
356 }
357 let path = joinPaths([parentPath, meta.relativePath]);
358 let routesMeta = parentsMeta.concat(meta);
359 if (route.children && route.children.length > 0) {
360 invariant$1(route.index !== true, `Index routes must not have child routes. Please remove all child routes from route path "${path}".`);
361 flattenRoutes(route.children, branches, routesMeta, path, hasParentOptionalSegments);
362 }
363 if (route.path == null && !route.index) return;
364 branches.push({
365 path,
366 score: computeScore(path, route.index),
367 routesMeta: routesMeta.map((meta, i) => {
368 let [matcher, params] = compilePath(meta.relativePath, meta.caseSensitive, i === routesMeta.length - 1);
369 return {
370 ...meta,
371 matcher,
372 compiledParams: params
373 };
374 })
375 });
376 };
377 routes.forEach((route, index) => {
378 if (route.path === "" || !route.path?.includes("?")) flattenRoute(route, index);
379 else for (let exploded of explodeOptionalSegments(route.path)) flattenRoute(route, index, true, exploded);
380 });
381 return branches;
382}
383function explodeOptionalSegments(path) {
384 let segments = path.split("/");
385 if (segments.length === 0) return [];
386 let [first, ...rest] = segments;
387 let isOptional = first.endsWith("?");
388 let required = first.replace(/\?$/, "");
389 if (rest.length === 0) return isOptional ? [required, ""] : [required];
390 let restExploded = explodeOptionalSegments(rest.join("/"));
391 let result = [];
392 result.push(...restExploded.map((subpath) => subpath === "" ? required : [required, subpath].join("/")));
393 if (isOptional) result.push(...restExploded);
394 return result.map((exploded) => path.startsWith("/") && exploded === "" ? "/" : exploded);
395}
396function rankRouteBranches(branches) {
397 branches.sort((a, b) => a.score !== b.score ? b.score - a.score : compareIndexes(a.routesMeta.map((meta) => meta.childrenIndex), b.routesMeta.map((meta) => meta.childrenIndex)));
398}
399const paramRe = /^:[\w-]+$/;
400const partialParamRe = /^:[\w-]+/;
401const partialDynamicSegmentValue = 3.5;
402const dynamicSegmentValue = 3;
403const indexRouteValue = 2;
404const emptySegmentValue = 1;
405const staticSegmentValue = 10;
406const splatPenalty = -2;
407const isSplat = (s) => s === "*";
408function computeScore(path, index) {
409 let segments = path.split("/");
410 let initialScore = segments.length;
411 if (segments.some(isSplat)) initialScore += splatPenalty;
412 if (index) initialScore += indexRouteValue;
413 return segments.filter((s) => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : partialParamRe.test(segment) ? partialDynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
414}
415function compareIndexes(a, b) {
416 return a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]) ? a[a.length - 1] - b[b.length - 1] : 0;
417}
418function matchRouteBranch(branch, pathname, allowPartial = false) {
419 let { routesMeta } = branch;
420 let matchedParams = {};
421 let matchedPathname = "/";
422 let matches = [];
423 for (let i = 0; i < routesMeta.length; ++i) {
424 let meta = routesMeta[i];
425 let end = i === routesMeta.length - 1;
426 let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
427 let pattern = {
428 path: meta.relativePath,
429 caseSensitive: meta.caseSensitive,
430 end
431 };
432 let match = meta.matcher && meta.compiledParams ? matchPathImpl(pattern, remainingPathname, meta.matcher, meta.compiledParams) : matchPath(pattern, remainingPathname);
433 let route = meta.route;
434 if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) match = matchPath({
435 path: meta.relativePath,
436 caseSensitive: meta.caseSensitive,
437 end: false
438 }, remainingPathname);
439 if (!match) return null;
440 Object.assign(matchedParams, match.params);
441 matches.push({
442 params: matchedParams,
443 pathname: joinPaths([matchedPathname, match.pathname]),
444 pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
445 route
446 });
447 if (match.pathnameBase !== "/") matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
448 }
449 return matches;
450}
451/**
452* Characters that `encodeURIComponent` escapes but that are valid literally in
453* a URL path segment. Per RFC 3986 §3.3, a path segment is made of `pchar`:
454*
455* ```
456* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
457* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
458* ```
459*
460* `encodeURIComponent` targets query-string values, where `$ & + , ; = : @`
461* are delimiters and must be escaped — but in a path segment they carry no
462* special meaning, and browsers keep them literal in `location.pathname`.
463* (`! ' ( ) *` and the unreserved set are already left alone by
464* `encodeURIComponent`, so they need no restoring.)
465*/
466const PATH_PARAM_OVERESCAPED = {
467 "%24": "$",
468 "%26": "&",
469 "%2B": "+",
470 "%2C": ",",
471 "%3A": ":",
472 "%3B": ";",
473 "%3D": "=",
474 "%40": "@"
475};
476/**
477* Encodes a param value for interpolation into a single URL path segment.
478*
479* Escapes characters that would break the path (`/ ? # %`, whitespace,
480* non-ASCII, …) while leaving characters that RFC 3986 permits literally in a
481* path segment untouched. Escaping those would needlessly rewrite URLs — e.g.
482* a semver build param `1.0.0+1` would become `1.0.0%2B1` even though browsers
483* display and match the `+` literally in `location.pathname`.
484*
485* See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3))
486*
487* @param value The param value to encode.
488* @returns The encoded value, safe for use as a single path segment.
489*/
490function encodePathParam(value) {
491 return encodeURIComponent(value).replace(/%(?:24|26|2B|2C|3A|3B|3D|40)/g, (match) => PATH_PARAM_OVERESCAPED[match]);
492}
493/**
494* Performs pattern matching on a URL pathname and returns information about
495* the match.
496*
497* @public
498* @category Utils
499* @param pattern The pattern to match against the URL pathname. This can be a
500* string or a {@link PathPattern} object. If a string is provided, it will be
501* treated as a pattern with `caseSensitive` set to `false` and `end` set to
502* `true`.
503* @param pathname The URL pathname to match against the pattern.
504* @returns A path match object if the pattern matches the pathname,
505* or `null` if it does not match.
506*/
507function matchPath(pattern, pathname) {
508 if (typeof pattern === "string") pattern = {
509 path: pattern,
510 caseSensitive: false,
511 end: true
512 };
513 let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
514 return matchPathImpl(pattern, pathname, matcher, compiledParams);
515}
516function matchPathImpl(pattern, pathname, matcher, compiledParams) {
517 let match = pathname.match(matcher);
518 if (!match) return null;
519 let matchedPathname = match[0];
520 let pathnameBase = removeTrailingSlash(matchedPathname, 1);
521 let captureGroups = match.slice(1);
522 return {
523 params: compiledParams.reduce((memo, { paramName, isOptional }, index) => {
524 if (paramName === "*") {
525 let splatValue = captureGroups[index] || "";
526 pathnameBase = removeTrailingSlash(matchedPathname.slice(0, matchedPathname.length - splatValue.length), 1);
527 }
528 const value = captureGroups[index];
529 if (isOptional && !value) memo[paramName] = void 0;
530 else memo[paramName] = (value || "").replace(/%2F/g, "/");
531 return memo;
532 }, {}),
533 pathname: matchedPathname,
534 pathnameBase,
535 pattern
536 };
537}
538function compilePath(path, caseSensitive = false, end = true) {
539 warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".`);
540 let params = [];
541 let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(/\/:([\w-]+)(\?)?/g, (match, paramName, isOptional, index, str) => {
542 params.push({
543 paramName,
544 isOptional: isOptional != null
545 });
546 if (isOptional) {
547 let nextChar = str.charAt(index + match.length);
548 if (nextChar && nextChar !== "/") return "/([^\\/]*)";
549 return "(?:/([^\\/]*))?";
550 }
551 return "/([^\\/]+)";
552 }).replace(/\/((?:[^/?()[\]*^\\]|\\.)+)\?(?=\/|$|\()/g, "(?:/$1)?");
553 if (path.endsWith("*")) {
554 params.push({ paramName: "*" });
555 regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
556 } else if (end) regexpSource += "\\/*$";
557 else if (path !== "" && path !== "/") regexpSource += "(?:(?=\\/|$))";
558 return [new RegExp(regexpSource, caseSensitive ? void 0 : "i"), params];
559}
560function decodePath(value) {
561 try {
562 return value.split("/").map((v) => decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
563 } catch (error) {
564 warning(false, `The URL path "${value}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${error}).`);
565 return value;
566 }
567}
568function stripBasename(pathname, basename) {
569 if (basename === "/") return pathname;
570 if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) return null;
571 let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
572 let nextChar = pathname.charAt(startIndex);
573 if (nextChar && nextChar !== "/") return null;
574 return pathname.slice(startIndex) || "/";
575}
576function prependBasename({ basename, pathname }) {
577 return pathname === "/" ? basename : joinPaths([basename, pathname]);
578}
579const isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX.test(url);
580/**
581* Returns a resolved {@link Path} object relative to the given pathname.
582*
583* @public
584* @category Utils
585* @param to The path to resolve, either a string or a partial {@link Path}
586* object.
587* @param fromPathname The pathname to resolve the path from. Defaults to `/`.
588* @returns A {@link Path} object with the resolved pathname, search, and hash.
589*/
590function resolvePath(to, fromPathname = "/") {
591 let { pathname: toPathname, search = "", hash = "" } = typeof to === "string" ? parsePath(to) : to;
592 let pathname;
593 if (toPathname) {
594 toPathname = removeDoubleSlashes(toPathname);
595 if (toPathname.startsWith("/") || toPathname.startsWith("\\")) pathname = resolvePathname(toPathname.substring(1), "/");
596 else pathname = resolvePathname(toPathname, fromPathname);
597 } else pathname = fromPathname;
598 return {
599 pathname,
600 search: normalizeSearch(search),
601 hash: normalizeHash(hash)
602 };
603}
604function resolvePathname(relativePath, fromPathname) {
605 let segments = removeTrailingSlash(fromPathname).split("/");
606 relativePath.split("/").forEach((segment) => {
607 if (segment === "..") {
608 if (segments.length > 1) segments.pop();
609 } else if (segment !== ".") segments.push(segment);
610 });
611 return segments.length > 1 ? segments.join("/") : "/";
612}
613function getInvalidPathError(char, field, dest, path) {
614 return `Cannot include a '${char}' character in a manually specified \`to.${field}\` field [${JSON.stringify(path)}]. Please separate it out to the \`to.${dest}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`;
615}
616function getPathContributingMatches(matches) {
617 return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
618}
619function getResolveToMatches(matches) {
620 let pathMatches = getPathContributingMatches(matches);
621 return pathMatches.map((match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase);
622}
623function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) {
624 let to;
625 if (typeof toArg === "string") to = parsePath(toArg);
626 else {
627 to = { ...toArg };
628 invariant$1(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
629 invariant$1(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
630 invariant$1(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
631 }
632 let isEmptyPath = toArg === "" || to.pathname === "";
633 let toPathname = isEmptyPath ? "/" : to.pathname;
634 let from;
635 if (toPathname == null) from = locationPathname;
636 else {
637 let routePathnameIndex = routePathnames.length - 1;
638 if (!isPathRelative && toPathname.startsWith("..")) {
639 let toSegments = toPathname.split("/");
640 while (toSegments[0] === "..") {
641 toSegments.shift();
642 routePathnameIndex -= 1;
643 }
644 to.pathname = toSegments.join("/");
645 }
646 from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
647 }
648 let path = resolvePath(to, from);
649 let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
650 let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
651 if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) path.pathname += "/";
652 return path;
653}
654const removeDoubleSlashes = (path) => path.replace(/[\\/]{2,}/g, "/");
655const joinPaths = (paths) => removeDoubleSlashes(paths.join("/"));
656function removeTrailingSlash(path, minLength = 0) {
657 let end = path.length;
658 while (end > minLength && path.charCodeAt(end - 1) === 47) end--;
659 return end === path.length ? path : path.slice(0, end);
660}
661const normalizePathname = (pathname) => removeTrailingSlash(pathname).replace(/^\/*/, "/");
662const normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
663const normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
664var DataWithResponseInit = class {
665 type = "DataWithResponseInit";
666 data;
667 init;
668 constructor(data, init) {
669 this.data = data;
670 this.init = init || null;
671 }
672};
673/**
674* Create "responses" that contain `headers`/`status` without forcing
675* serialization into an actual [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
676*
677* @example
678* import { data } from "react-router";
679*
680* export async function action({ request }: Route.ActionArgs) {
681* let formData = await request.formData();
682* let item = await createItem(formData);
683* return data(item, {
684* headers: { "X-Custom-Header": "value" }
685* status: 201,
686* });
687* }
688*
689* @public
690* @category Utils
691* @mode framework
692* @mode data
693* @param data The data to be included in the response.
694* @param init The status code or a `ResponseInit` object to be included in the
695* response.
696* @returns A {@link DataWithResponseInit} instance containing the data and
697* response init.
698*/
699function data(data, init) {
700 return new DataWithResponseInit(data, typeof init === "number" ? { status: init } : init);
701}
702/**
703* A redirect [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response).
704* Sets the status code and the [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
705* header. Defaults to [`302 Found`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302).
706*
707* This utility accepts absolute URLs and can navigate to external domains, so
708* the application should validate any user-supplied inputs to redirects.
709*
710* @example
711* import { redirect } from "react-router";
712*
713* export async function loader({ request }: Route.LoaderArgs) {
714* if (!isLoggedIn(request))
715* throw redirect("/login");
716* }
717*
718* // ...
719* }
720*
721* @public
722* @category Utils
723* @mode framework
724* @mode data
725* @param url The URL to redirect to.
726* @param init The status code or a `ResponseInit` object to be included in the
727* response.
728* @returns A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
729* object with the redirect status and [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
730* header.
731*/
732const redirect$1 = (url, init = 302) => {
733 let responseInit = init;
734 if (typeof responseInit === "number") responseInit = { status: responseInit };
735 else if (typeof responseInit.status === "undefined") responseInit.status = 302;
736 let headers = new Headers(responseInit.headers);
737 headers.set("Location", url);
738 return new Response(null, {
739 ...responseInit,
740 headers
741 });
742};
743/**
744* A redirect [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
745* that will force a document reload to the new location. Sets the status code
746* and the [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
747* header. Defaults to [`302 Found`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302).
748*
749* This utility accepts absolute URLs and can navigate to external domains, so
750* the application should validate any user-supplied inputs to redirects.
751*
752* ```tsx filename=routes/logout.tsx
753* import { redirectDocument } from "react-router";
754*
755* import { destroySession } from "../sessions.server";
756*
757* export async function action({ request }: Route.ActionArgs) {
758* let session = await getSession(request.headers.get("Cookie"));
759* return redirectDocument("/", {
760* headers: { "Set-Cookie": await destroySession(session) }
761* });
762* }
763* ```
764*
765* @public
766* @category Utils
767* @mode framework
768* @mode data
769* @param url The URL to redirect to.
770* @param init The status code or a `ResponseInit` object to be included in the
771* response.
772* @returns A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
773* object with the redirect status and [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
774* header.
775*/
776const redirectDocument$1 = (url, init) => {
777 let response = redirect$1(url, init);
778 response.headers.set("X-Remix-Reload-Document", "true");
779 return response;
780};
781/**
782* A redirect [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
783* that will perform a [`history.replaceState`](https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState)
784* instead of a [`history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)
785* for client-side navigation redirects. Sets the status code and the [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
786* header. Defaults to [`302 Found`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302).
787*
788* @example
789* import { replace } from "react-router";
790*
791* export async function loader() {
792* return replace("/new-location");
793* }
794*
795* @public
796* @category Utils
797* @mode framework
798* @mode data
799* @param url The URL to redirect to.
800* @param init The status code or a `ResponseInit` object to be included in the
801* response.
802* @returns A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
803* object with the redirect status and [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
804* header.
805*/
806const replace$1 = (url, init) => {
807 let response = redirect$1(url, init);
808 response.headers.set("X-Remix-Replace", "true");
809 return response;
810};
811var ErrorResponseImpl = class {
812 status;
813 statusText;
814 data;
815 error;
816 internal;
817 constructor(status, statusText, data, internal = false) {
818 this.status = status;
819 this.statusText = statusText || "";
820 this.internal = internal;
821 if (data instanceof Error) {
822 this.data = data.toString();
823 this.error = data;
824 } else this.data = data;
825 }
826};
827/**
828* Check if the given error is an {@link ErrorResponse} generated from a 4xx/5xx
829* [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
830* thrown from an [`action`](../../start/framework/route-module#action) or
831* [`loader`](../../start/framework/route-module#loader) function.
832*
833* @example
834* import { isRouteErrorResponse } from "react-router";
835*
836* export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
837* if (isRouteErrorResponse(error)) {
838* return (
839* <>
840* <p>Error: `${error.status}: ${error.statusText}`</p>
841* <p>{error.data}</p>
842* </>
843* );
844* }
845*
846* return (
847* <p>Error: {error instanceof Error ? error.message : "Unknown Error"}</p>
848* );
849* }
850*
851* @public
852* @category Utils
853* @mode framework
854* @mode data
855* @param error The error to check.
856* @returns `true` if the error is an {@link ErrorResponse}, `false` otherwise.
857*/
858function isRouteErrorResponse(error) {
859 return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
860}
861function getRoutePattern(matches) {
862 return joinPaths(matches.map((m) => m.route.path).filter(Boolean)) || "/";
863}
864function createDataFunctionUrl(request, path) {
865 let url = new URL(typeof request === "string" || request instanceof URL ? request : request.url);
866 let parsed = typeof path === "string" ? parsePath(path) : path;
867 url.pathname = parsed.pathname || "/";
868 if (parsed.search) {
869 let searchParams = new URLSearchParams(parsed.search);
870 let indexValues = searchParams.getAll("index");
871 searchParams.delete("index");
872 for (let value of indexValues.filter(Boolean)) searchParams.append("index", value);
873 let search = searchParams.toString();
874 url.search = search ? `?${search}` : "";
875 } else url.search = "";
876 url.hash = parsed.hash || "";
877 return url;
878}
879typeof window !== "undefined" && typeof window.document !== "undefined" && window.document.createElement;
880//#endregion
881//#region lib/router/instrumentation.ts
882const UninstrumentedSymbol = Symbol("Uninstrumented");
883function getRouteInstrumentationUpdates(fns, route) {
884 let aggregated = {
885 lazy: [],
886 "lazy.loader": [],
887 "lazy.action": [],
888 "lazy.middleware": [],
889 middleware: [],
890 loader: [],
891 action: []
892 };
893 fns.forEach((fn) => fn({
894 id: route.id,
895 index: route.index,
896 path: route.path,
897 instrument(i) {
898 if (i.lazy != null) aggregated.lazy.push(i.lazy);
899 if (i["lazy.loader"] != null) aggregated["lazy.loader"].push(i["lazy.loader"]);
900 if (i["lazy.action"] != null) aggregated["lazy.action"].push(i["lazy.action"]);
901 if (i["lazy.middleware"] != null) aggregated["lazy.middleware"].push(i["lazy.middleware"]);
902 if (i.middleware != null) aggregated.middleware.push(i.middleware);
903 if (i.loader != null) aggregated.loader.push(i.loader);
904 if (i.action != null) aggregated.action.push(i.action);
905 }
906 }));
907 let updates = {};
908 if (typeof route.lazy === "function" && aggregated.lazy.length > 0) {
909 let lazy = route.lazy;
910 updates.lazy = async (...args) => {
911 return throwOrReturnResult(await recurseRight(aggregated.lazy, void 0, () => lazy(...args), getInstrumentationInnerResult));
912 };
913 }
914 if (typeof route.lazy === "object") {
915 let lazyObject = route.lazy;
916 if (typeof lazyObject.middleware === "function" && aggregated["lazy.middleware"].length > 0) {
917 let middleware = lazyObject.middleware;
918 updates.lazy = Object.assign(updates.lazy || {}, { middleware: async (...args) => {
919 return throwOrReturnResult(await recurseRight(aggregated["lazy.middleware"], void 0, () => middleware(...args), getInstrumentationInnerResult));
920 } });
921 }
922 if (typeof lazyObject.loader === "function" && aggregated["lazy.loader"].length > 0) {
923 let loader = lazyObject.loader;
924 updates.lazy = Object.assign(updates.lazy || {}, { loader: async (...args) => {
925 return throwOrReturnResult(await recurseRight(aggregated["lazy.loader"], void 0, () => loader(...args), getInstrumentationInnerResult));
926 } });
927 }
928 if (typeof lazyObject.action === "function" && aggregated["lazy.action"].length > 0) {
929 let action = lazyObject.action;
930 updates.lazy = Object.assign(updates.lazy || {}, { action: async (...args) => {
931 return throwOrReturnResult(await recurseRight(aggregated["lazy.action"], void 0, () => action(...args), getInstrumentationInnerResult));
932 } });
933 }
934 }
935 if (typeof route.loader === "function" && aggregated.loader.length > 0) {
936 let original = getUninstrumentedHandler(route.loader);
937 let instrumented = async (...args) => {
938 return throwOrReturnResult(await recurseRight(aggregated.loader, getHandlerInfo(args[0]), () => original(...args), getInstrumentationInnerResult));
939 };
940 if (original.hydrate === true) instrumented.hydrate = true;
941 setUninstrumentedHandler(instrumented, original);
942 updates.loader = instrumented;
943 }
944 if (typeof route.action === "function" && aggregated.action.length > 0) {
945 let original = getUninstrumentedHandler(route.action);
946 let instrumented = async (...args) => {
947 return throwOrReturnResult(await recurseRight(aggregated.action, getHandlerInfo(args[0]), () => original(...args), getInstrumentationInnerResult));
948 };
949 setUninstrumentedHandler(instrumented, original);
950 updates.action = instrumented;
951 }
952 if (route.middleware && route.middleware.length > 0 && aggregated.middleware.length > 0) updates.middleware = route.middleware.map((middleware) => {
953 let original = getUninstrumentedHandler(middleware);
954 let instrumented = async (...args) => {
955 return throwOrReturnResult(await recurseRight(aggregated.middleware, getHandlerInfo(args[0]), () => original(...args), getInstrumentationInnerResult));
956 };
957 setUninstrumentedHandler(instrumented, original);
958 return instrumented;
959 });
960 return updates;
961}
962function getUninstrumentedHandler(handler) {
963 return handler[UninstrumentedSymbol] ?? handler;
964}
965function setUninstrumentedHandler(handler, uninstrumentedHandler) {
966 handler[UninstrumentedSymbol] = uninstrumentedHandler;
967}
968function throwOrReturnResult(result) {
969 if (result.type === "error") throw result.value;
970 return result.value;
971}
972async function recurseRight(impls, info, handler, getInnerResult, state = {
973 result: null,
974 innerResult: null
975}, index = impls.length - 1) {
976 let impl = impls[index];
977 if (!impl) {
978 try {
979 state.result = {
980 type: "success",
981 value: await handler()
982 };
983 } catch (e) {
984 state.result = {
985 type: "error",
986 value: e
987 };
988 }
989 state.innerResult = getInnerResult(state.result, info);
990 } else {
991 let handlerPromise = void 0;
992 let callHandler = async () => {
993 if (handlerPromise) console.error("You cannot call instrumented handlers more than once");
994 else handlerPromise = recurseRight(impls, info, handler, getInnerResult, state, index - 1);
995 await handlerPromise;
996 invariant$1(state.innerResult, "Expected an inner result");
997 return state.innerResult;
998 };
999 try {
1000 await impl(callHandler, info);
1001 } catch (e) {
1002 console.error("An instrumentation function threw an error:", e);
1003 }
1004 if (!handlerPromise) await callHandler();
1005 await handlerPromise;
1006 }
1007 if (state.result) return state.result;
1008 state.result = {
1009 type: "error",
1010 value: /* @__PURE__ */ new Error("No result assigned in instrumentation chain.")
1011 };
1012 state.innerResult = getInnerResult(state.result, info);
1013 return state.result;
1014}
1015function getInstrumentationInnerResult(result) {
1016 if (result.type === "error" && result.value instanceof Error) return {
1017 status: "error",
1018 error: result.value
1019 };
1020 return {
1021 status: "success",
1022 error: void 0
1023 };
1024}
1025function getHandlerInfo(args) {
1026 let { request, context, params } = args;
1027 return {
1028 ...args,
1029 request: getReadonlyRequest(request),
1030 params: { ...params },
1031 context: getReadonlyContext(context)
1032 };
1033}
1034function getReadonlyRequest(request) {
1035 return {
1036 method: request.method,
1037 url: request.url,
1038 headers: { get: (...args) => request.headers.get(...args) }
1039 };
1040}
1041function getReadonlyContext(context) {
1042 return { get: (ctx) => context.get(ctx) };
1043}
1044//#endregion
1045//#region lib/router/matcher.ts
1046var V6RegExMatcher = class {
1047 #routes = [];
1048 #branches = [];
1049 #basename;
1050 #matchCost = 0;
1051 constructor(basename) {
1052 this.#basename = basename;
1053 }
1054 update(routes) {
1055 this.#routes = routes;
1056 this.#branches = flattenAndRankRoutes(routes);
1057 this.#matchCost = this.#branches.reduce((total, branch) => total + branch.routesMeta.length, 0);
1058 }
1059 get matchCost() {
1060 return this.#matchCost;
1061 }
1062 match(locationArg, allowPartial = false) {
1063 return matchRoutesImpl(this.#routes, locationArg, this.#basename, allowPartial, this.#branches);
1064 }
1065};
1066//#endregion
1067//#region lib/router/router.ts
1068const validMutationMethodsArr = [
1069 "POST",
1070 "PUT",
1071 "PATCH",
1072 "DELETE"
1073];
1074const validMutationMethods = new Set(validMutationMethodsArr);
1075const validRequestMethodsArr = ["GET", ...validMutationMethodsArr];
1076const validRequestMethods = new Set(validRequestMethodsArr);
1077const redirectStatusCodes = new Set([
1078 301,
1079 302,
1080 303,
1081 307,
1082 308
1083]);
1084const ResetLoaderDataSymbol = Symbol("ResetLoaderData");
1085function createDataRouteMatcher(future, basename) {
1086 if (future.unstable_routePatternMatching) {
1087 let RoutePatternMatcher = void 0;
1088 invariant$1(RoutePatternMatcher, "You must call unstable_preloadRoutePattern() from \"react-router/route-pattern\" before enabling future.unstable_routePatternMatching.");
1089 return new RoutePatternMatcher(basename);
1090 }
1091 return new V6RegExMatcher(basename);
1092}
1093/**
1094* Create a static handler to perform server-side data loading
1095*
1096* @example
1097* export async function handleRequest(request: Request) {
1098* let { query, dataRoutes } = createStaticHandler(routes);
1099* let context = await query(request);
1100*
1101* if (context instanceof Response) {
1102* return context;
1103* }
1104*
1105* let router = createStaticRouter(dataRoutes, context);
1106* return new Response(
1107* ReactDOMServer.renderToString(<StaticRouterProvider ... />),
1108* { headers: { "Content-Type": "text/html" } }
1109* );
1110* }
1111*
1112* @public
1113* @category Data Routers
1114* @mode data
1115* @param routes The {@link RouteObject | route objects} to create a static
1116* handler for
1117* @param opts Options
1118* @param opts.basename The base URL for the static handler (default: `/`)
1119* @param opts.future Future flags for the static handler
1120* @returns A static handler that can be used to query data for the provided
1121* routes
1122*/
1123function createStaticHandler(routes, opts) {
1124 invariant$1(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
1125 let manifest = {};
1126 let basename = (opts ? opts.basename : null) || "/";
1127 let _mapRouteProperties = opts?.mapRouteProperties;
1128 let mapRouteProperties = _mapRouteProperties ? _mapRouteProperties : () => ({});
1129 let dataRouteMatcher = createDataRouteMatcher({ ...opts?.future }, basename);
1130 if (opts?.instrumentations) {
1131 let instrumentations = opts.instrumentations;
1132 mapRouteProperties = (route) => {
1133 return {
1134 ..._mapRouteProperties?.(route),
1135 ...getRouteInstrumentationUpdates(instrumentations.map((i) => i.route).filter(Boolean), route)
1136 };
1137 };
1138 }
1139 let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, void 0, manifest);
1140 dataRouteMatcher.update(dataRoutes);
1141 let match = (locationArg) => dataRouteMatcher.match(locationArg);
1142 /**
1143 * The query() method is intended for document requests, in which we want to
1144 * call an optional action and potentially multiple loaders for all nested
1145 * routes. It returns a StaticHandlerContext object, which is very similar
1146 * to the router state (location, loaderData, actionData, errors, etc.) and
1147 * also adds SSR-specific information such as the statusCode and headers
1148 * from action/loaders Responses.
1149 *
1150 * It _should_ never throw and should report all errors through the
1151 * returned handlerContext.errors object, properly associating errors to
1152 * their error boundary. Additionally, it tracks _deepestRenderedBoundaryId
1153 * which can be used to emulate React error boundaries during SSR by performing
1154 * a second pass only down to the boundaryId.
1155 *
1156 * The one exception where we do not return a StaticHandlerContext is when a
1157 * redirect response is returned or thrown from any action/loader. We
1158 * propagate that out and return the raw Response so the HTTP server can
1159 * return it directly.
1160 *
1161 * - `opts.requestContext` is an optional server context that will be passed
1162 * to actions/loaders in the `context` parameter
1163 * - `opts.skipLoaderErrorBubbling` is an optional parameter that will prevent
1164 * the bubbling of errors which allows single-fetch-type implementations
1165 * where the client will handle the bubbling and we may need to return data
1166 * for the handling route
1167 */
1168 async function query(request, { requestContext, filterMatchesToLoad, skipLoaderErrorBubbling, skipRevalidation, dataStrategy, generateMiddlewareResponse, normalizePath } = {}) {
1169 let normalizePathImpl = normalizePath || defaultNormalizePath;
1170 let method = request.method;
1171 let location = createLocation("", normalizePathImpl(request), null, "default");
1172 let matches = dataRouteMatcher.match(location);
1173 requestContext = requestContext != null ? requestContext : new RouterContextProvider();
1174 if (!isValidMethod(method) && method !== "HEAD") {
1175 let error = getInternalRouterError(405, { method });
1176 let { matches: methodNotAllowedMatches, route } = getShortCircuitMatches(dataRoutes);
1177 let staticContext = {
1178 basename,
1179 location,
1180 matches: methodNotAllowedMatches,
1181 loaderData: {},
1182 actionData: null,
1183 errors: { [route.id]: error },
1184 statusCode: error.status,
1185 loaderHeaders: {},
1186 actionHeaders: {},
1187 _match: match
1188 };
1189 return generateMiddlewareResponse ? generateMiddlewareResponse(() => Promise.resolve(staticContext)) : staticContext;
1190 } else if (!matches) {
1191 let error = getInternalRouterError(404, { pathname: location.pathname });
1192 let { matches: notFoundMatches, route } = getShortCircuitMatches(dataRoutes);
1193 let staticContext = {
1194 basename,
1195 location,
1196 matches: notFoundMatches,
1197 loaderData: {},
1198 actionData: null,
1199 errors: { [route.id]: error },
1200 statusCode: error.status,
1201 loaderHeaders: {},
1202 actionHeaders: {},
1203 _match: match
1204 };
1205 return generateMiddlewareResponse ? generateMiddlewareResponse(() => Promise.resolve(staticContext)) : staticContext;
1206 }
1207 if (generateMiddlewareResponse) {
1208 invariant$1(requestContext instanceof RouterContextProvider, "When using middleware in `staticHandler.query()`, any provided `requestContext` must be an instance of `RouterContextProvider`");
1209 try {
1210 await loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties);
1211 let renderedStaticContext;
1212 let response = await runServerMiddlewarePipeline({
1213 request,
1214 url: createDataFunctionUrl(request, location),
1215 pattern: getRoutePattern(matches),
1216 matches,
1217 params: matches[0].params,
1218 context: requestContext
1219 }, async () => {
1220 return await generateMiddlewareResponse(async (revalidationRequest, opts = {}) => {
1221 let result = await queryImpl(revalidationRequest, location, matches, requestContext, dataStrategy || null, skipLoaderErrorBubbling === true, null, "filterMatchesToLoad" in opts ? opts.filterMatchesToLoad ?? null : filterMatchesToLoad ?? null, skipRevalidation === true);
1222 if (isResponse(result)) return result;
1223 renderedStaticContext = {
1224 location,
1225 basename,
1226 ...result,
1227 _match: match
1228 };
1229 return renderedStaticContext;
1230 });
1231 }, async (error, routeId) => {
1232 if (isRedirectResponse(error)) return error;
1233 if (isResponse(error)) try {
1234 error = new ErrorResponseImpl(error.status, error.statusText, await parseResponseBody(error));
1235 } catch (e) {
1236 error = e;
1237 }
1238 if (isDataWithResponseInit(error)) error = dataWithResponseInitToErrorResponse(error);
1239 if (renderedStaticContext) {
1240 if (routeId in renderedStaticContext.loaderData) renderedStaticContext.loaderData[routeId] = void 0;
1241 let staticContext = getStaticContextFromError(dataRoutes, renderedStaticContext, error, skipLoaderErrorBubbling ? routeId : findNearestBoundary(matches, routeId).route.id);
1242 return generateMiddlewareResponse(() => Promise.resolve(staticContext));
1243 } else {
1244 let staticContext = {
1245 matches,
1246 location,
1247 basename,
1248 loaderData: {},
1249 actionData: null,
1250 errors: { [skipLoaderErrorBubbling ? routeId : findNearestBoundary(matches, matches.find((m) => m.route.id === routeId || m.route.loader)?.route.id || routeId).route.id]: error },
1251 statusCode: isRouteErrorResponse(error) ? error.status : 500,
1252 actionHeaders: {},
1253 loaderHeaders: {},
1254 _match: match
1255 };
1256 return generateMiddlewareResponse(() => Promise.resolve(staticContext));
1257 }
1258 });
1259 invariant$1(isResponse(response), "Expected a response in query()");
1260 return response;
1261 } catch (e) {
1262 if (isResponse(e)) return e;
1263 throw e;
1264 }
1265 }
1266 let result = await queryImpl(request, location, matches, requestContext, dataStrategy || null, skipLoaderErrorBubbling === true, null, filterMatchesToLoad || null, skipRevalidation === true);
1267 if (isResponse(result)) return result;
1268 return {
1269 location,
1270 basename,
1271 ...result,
1272 _match: match
1273 };
1274 }
1275 /**
1276 * The queryRoute() method is intended for targeted route requests, either
1277 * for fetch ?_data requests or resource route requests. In this case, we
1278 * are only ever calling a single action or loader, and we are returning the
1279 * returned value directly. In most cases, this will be a Response returned
1280 * from the action/loader, but it may be a primitive or other value as well -
1281 * and in such cases the calling context should handle that accordingly.
1282 *
1283 * We do respect the throw/return differentiation, so if an action/loader
1284 * throws, then this method will throw the value. This is important so we
1285 * can do proper boundary identification in Remix where a thrown Response
1286 * must go to the Catch Boundary but a returned Response is happy-path.
1287 *
1288 * One thing to note is that any Router-initiated Errors that make sense
1289 * to associate with a status code will be thrown as an ErrorResponse
1290 * instance which include the raw Error, such that the calling context can
1291 * serialize the error as they see fit while including the proper response
1292 * code. Examples here are 404 and 405 errors that occur prior to reaching
1293 * any user-defined loaders.
1294 *
1295 * - `opts.routeId` allows you to specify the specific route handler to call.
1296 * If not provided the handler will determine the proper route by matching
1297 * against `request.url`
1298 * - `opts.requestContext` is an optional server context that will be passed
1299 * to actions/loaders in the `context` parameter
1300 */
1301 async function queryRoute(request, { routeId, requestContext, dataStrategy, generateMiddlewareResponse, normalizePath } = {}) {
1302 let normalizePathImpl = normalizePath || defaultNormalizePath;
1303 let method = request.method;
1304 let location = createLocation("", normalizePathImpl(request), null, "default");
1305 let matches = dataRouteMatcher.match(location);
1306 requestContext = requestContext != null ? requestContext : new RouterContextProvider();
1307 if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") throw getInternalRouterError(405, { method });
1308 else if (!matches) throw getInternalRouterError(404, { pathname: location.pathname });
1309 let match = routeId ? matches.find((m) => m.route.id === routeId) : getTargetMatch(matches, location);
1310 if (routeId && !match) throw getInternalRouterError(403, {
1311 pathname: location.pathname,
1312 routeId
1313 });
1314 else if (!match) throw getInternalRouterError(404, { pathname: location.pathname });
1315 if (generateMiddlewareResponse) {
1316 invariant$1(requestContext instanceof RouterContextProvider, "When using middleware in `staticHandler.queryRoute()`, any provided `requestContext` must be an instance of `RouterContextProvider`");
1317 await loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties);
1318 return await runServerMiddlewarePipeline({
1319 request,
1320 url: createDataFunctionUrl(request, location),
1321 pattern: getRoutePattern(matches),
1322 matches,
1323 params: matches[0].params,
1324 context: requestContext
1325 }, async () => {
1326 return await generateMiddlewareResponse(async (innerRequest) => {
1327 let processed = handleQueryResult(await queryImpl(innerRequest, location, matches, requestContext, dataStrategy || null, false, match, null, false));
1328 return isResponse(processed) ? processed : typeof processed === "string" ? new Response(processed) : Response.json(processed);
1329 });
1330 }, (error) => {
1331 if (isDataWithResponseInit(error)) return Promise.resolve(dataWithResponseInitToResponse(error));
1332 if (isResponse(error)) return Promise.resolve(error);
1333 throw error;
1334 });
1335 }
1336 return handleQueryResult(await queryImpl(request, location, matches, requestContext, dataStrategy || null, false, match, null, false));
1337 function handleQueryResult(result) {
1338 if (isResponse(result)) return result;
1339 let error = result.errors ? Object.values(result.errors)[0] : void 0;
1340 if (error !== void 0) throw error;
1341 if (result.actionData) return Object.values(result.actionData)[0];
1342 if (result.loaderData) return Object.values(result.loaderData)[0];
1343 }
1344 }
1345 async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, skipRevalidation) {
1346 invariant$1(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
1347 try {
1348 if (isMutationMethod(request.method)) return await submit(request, location, matches, routeMatch || getTargetMatch(matches, location), requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch != null, filterMatchesToLoad, skipRevalidation);
1349 let result = await loadRouteData(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad);
1350 return isResponse(result) ? result : {
1351 ...result,
1352 actionData: null,
1353 actionHeaders: {}
1354 };
1355 } catch (e) {
1356 if (isDataStrategyResult(e) && isResponse(e.result)) {
1357 if (e.type === "error") throw e.result;
1358 return e.result;
1359 }
1360 if (isRedirectResponse(e)) return e;
1361 throw e;
1362 }
1363 }
1364 async function submit(request, location, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest, filterMatchesToLoad, skipRevalidation) {
1365 let result;
1366 if (!actionMatch.route.action && !actionMatch.route.lazy) {
1367 let error = getInternalRouterError(405, {
1368 method: request.method,
1369 pathname: new URL(request.url).pathname,
1370 routeId: actionMatch.route.id
1371 });
1372 if (isRouteRequest) throw error;
1373 result = {
1374 type: "error",
1375 error
1376 };
1377 } else {
1378 result = (await callDataStrategy(request, location, getTargetedDataStrategyMatches(mapRouteProperties, manifest, request, location, matches, actionMatch, [], requestContext), isRouteRequest, requestContext, dataStrategy))[actionMatch.route.id];
1379 if (request.signal.aborted) throwStaticHandlerAbortedError(request, isRouteRequest);
1380 }
1381 if (isRedirectResult(result)) throw new Response(null, {
1382 status: result.response.status,
1383 headers: { Location: result.response.headers.get("Location") }
1384 });
1385 if (isRouteRequest) {
1386 if (isErrorResult(result)) throw result.error;
1387 return {
1388 matches: [actionMatch],
1389 loaderData: {},
1390 actionData: { [actionMatch.route.id]: result.data },
1391 errors: null,
1392 statusCode: 200,
1393 loaderHeaders: {},
1394 actionHeaders: {}
1395 };
1396 }
1397 if (skipRevalidation) if (isErrorResult(result)) {
1398 let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
1399 return {
1400 statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
1401 actionData: null,
1402 actionHeaders: { ...result.headers ? { [actionMatch.route.id]: result.headers } : {} },
1403 matches,
1404 loaderData: {},
1405 errors: { [boundaryMatch.route.id]: result.error },
1406 loaderHeaders: {}
1407 };
1408 } else return {
1409 actionData: { [actionMatch.route.id]: result.data },
1410 actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {},
1411 matches,
1412 loaderData: {},
1413 errors: null,
1414 statusCode: result.statusCode || 200,
1415 loaderHeaders: {}
1416 };
1417 let loaderRequest = new Request(request.url, {
1418 headers: request.headers,
1419 redirect: request.redirect,
1420 signal: request.signal
1421 });
1422 if (isErrorResult(result)) return {
1423 ...await loadRouteData(loaderRequest, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, null, filterMatchesToLoad, [(skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id)).route.id, result]),
1424 statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
1425 actionData: null,
1426 actionHeaders: { ...result.headers ? { [actionMatch.route.id]: result.headers } : {} }
1427 };
1428 return {
1429 ...await loadRouteData(loaderRequest, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, null, filterMatchesToLoad),
1430 actionData: { [actionMatch.route.id]: result.data },
1431 ...result.statusCode ? { statusCode: result.statusCode } : {},
1432 actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {}
1433 };
1434 }
1435 async function loadRouteData(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, pendingActionResult) {
1436 let isRouteRequest = routeMatch != null;
1437 if (isRouteRequest && !routeMatch?.route.loader && !routeMatch?.route.lazy) throw getInternalRouterError(400, {
1438 method: request.method,
1439 pathname: new URL(request.url).pathname,
1440 routeId: routeMatch?.route.id
1441 });
1442 let dsMatches;
1443 if (routeMatch) dsMatches = getTargetedDataStrategyMatches(mapRouteProperties, manifest, request, location, matches, routeMatch, [], requestContext);
1444 else {
1445 let maxIdx = pendingActionResult && isErrorResult(pendingActionResult[1]) ? matches.findIndex((m) => m.route.id === pendingActionResult[0]) - 1 : void 0;
1446 let pattern = getRoutePattern(matches);
1447 dsMatches = matches.map((match, index) => {
1448 if (maxIdx != null && index > maxIdx) return getDataStrategyMatch(mapRouteProperties, manifest, request, location, pattern, match, [], requestContext, false);
1449 return getDataStrategyMatch(mapRouteProperties, manifest, request, location, pattern, match, [], requestContext, (match.route.loader || match.route.lazy) != null && (!filterMatchesToLoad || filterMatchesToLoad(match)));
1450 });
1451 }
1452 if (!dataStrategy && !dsMatches.some((m) => m.shouldLoad)) return {
1453 matches,
1454 loaderData: {},
1455 errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { [pendingActionResult[0]]: pendingActionResult[1].error } : null,
1456 statusCode: 200,
1457 loaderHeaders: {}
1458 };
1459 let results = await callDataStrategy(request, location, dsMatches, isRouteRequest, requestContext, dataStrategy);
1460 if (request.signal.aborted) throwStaticHandlerAbortedError(request, isRouteRequest);
1461 return {
1462 ...processRouteLoaderData(matches, results, pendingActionResult, true, skipLoaderErrorBubbling),
1463 matches
1464 };
1465 }
1466 async function callDataStrategy(request, location, matches, isRouteRequest, requestContext, dataStrategy) {
1467 let results = await callDataStrategyImpl(dataStrategy || defaultDataStrategy, request, location, matches, null, "static", requestContext, true);
1468 let dataResults = {};
1469 await Promise.all(matches.map(async (match) => {
1470 if (!(match.route.id in results)) return;
1471 let result = results[match.route.id];
1472 if (isRedirectDataStrategyResult(result)) {
1473 let response = result.result;
1474 throw normalizeRelativeRoutingRedirectResponse(response, request, match.route.id, matches, basename);
1475 }
1476 if (isRouteRequest) {
1477 if (isResponse(result.result)) throw result;
1478 else if (isDataWithResponseInit(result.result)) throw dataWithResponseInitToResponse(result.result);
1479 }
1480 dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result);
1481 }));
1482 return dataResults;
1483 }
1484 return {
1485 dataRoutes,
1486 get _matchCost() {
1487 return dataRouteMatcher instanceof V6RegExMatcher ? dataRouteMatcher.matchCost : void 0;
1488 },
1489 match,
1490 query,
1491 queryRoute
1492 };
1493}
1494/**
1495* Given an existing StaticHandlerContext and an error thrown at render time,
1496* provide an updated StaticHandlerContext suitable for a second SSR render
1497*
1498* @category Utils
1499*/
1500function getStaticContextFromError(routes, handlerContext, error, boundaryId) {
1501 let errorBoundaryId = boundaryId || handlerContext._deepestRenderedBoundaryId || routes[0].id;
1502 return {
1503 ...handlerContext,
1504 statusCode: isRouteErrorResponse(error) ? error.status : 500,
1505 errors: { [errorBoundaryId]: error }
1506 };
1507}
1508function throwStaticHandlerAbortedError(request, isRouteRequest) {
1509 if (request.signal.reason !== void 0) throw request.signal.reason;
1510 throw new Error(`${isRouteRequest ? "queryRoute" : "query"}() call aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`);
1511}
1512function defaultNormalizePath(request) {
1513 let url = new URL(request.url);
1514 return {
1515 pathname: url.pathname,
1516 search: url.search,
1517 hash: url.hash
1518 };
1519}
1520function normalizeTo(location, matches, basename, to, fromRouteId, relative) {
1521 let contextualMatches;
1522 let activeRouteMatch;
1523 if (fromRouteId) {
1524 contextualMatches = [];
1525 for (let match of matches) {
1526 contextualMatches.push(match);
1527 if (match.route.id === fromRouteId) {
1528 activeRouteMatch = match;
1529 break;
1530 }
1531 }
1532 } else {
1533 contextualMatches = matches;
1534 activeRouteMatch = matches[matches.length - 1];
1535 }
1536 let path = resolveTo(to ? to : ".", getResolveToMatches(contextualMatches), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
1537 if (to == null) {
1538 path.search = location.search;
1539 path.hash = location.hash;
1540 }
1541 if ((to == null || to === "" || to === ".") && activeRouteMatch) {
1542 let nakedIndex = hasNakedIndexQuery(path.search);
1543 if (activeRouteMatch.route.index && !nakedIndex) path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
1544 else if (!activeRouteMatch.route.index && nakedIndex) {
1545 let params = new URLSearchParams(path.search);
1546 let indexValues = params.getAll("index");
1547 params.delete("index");
1548 indexValues.filter((v) => v).forEach((v) => params.append("index", v));
1549 let qs = params.toString();
1550 path.search = qs ? `?${qs}` : "";
1551 }
1552 }
1553 if (basename !== "/") path.pathname = prependBasename({
1554 basename,
1555 pathname: path.pathname
1556 });
1557 return createPath(path);
1558}
1559function shouldRevalidateLoader(loaderMatch, arg) {
1560 if (loaderMatch.route.shouldRevalidate) {
1561 let routeChoice = loaderMatch.route.shouldRevalidate(arg);
1562 if (typeof routeChoice === "boolean") return routeChoice;
1563 }
1564 return arg.defaultShouldRevalidate;
1565}
1566const lazyRoutePropertyCache = /* @__PURE__ */ new WeakMap();
1567const loadLazyRouteProperty = ({ key, route, manifest, mapRouteProperties }) => {
1568 let routeToUpdate = manifest[route.id];
1569 invariant$1(routeToUpdate, "No route found in manifest");
1570 if (!routeToUpdate.lazy || typeof routeToUpdate.lazy !== "object") return;
1571 let lazyFn = routeToUpdate.lazy[key];
1572 if (!lazyFn) return;
1573 let cache = lazyRoutePropertyCache.get(routeToUpdate);
1574 if (!cache) {
1575 cache = {};
1576 lazyRoutePropertyCache.set(routeToUpdate, cache);
1577 }
1578 let cachedPromise = cache[key];
1579 if (cachedPromise) return cachedPromise;
1580 let propertyPromise = (async () => {
1581 let isUnsupported = isUnsupportedLazyRouteObjectKey(key);
1582 let isStaticallyDefined = routeToUpdate[key] !== void 0;
1583 if (isUnsupported) {
1584 warning(!isUnsupported, "Route property " + key + " is not a supported lazy route property. This property will be ignored.");
1585 cache[key] = Promise.resolve();
1586 } else if (isStaticallyDefined) warning(false, `Route "${routeToUpdate.id}" has a static property "${key}" defined. The lazy property will be ignored.`);
1587 else {
1588 let value = await lazyFn();
1589 if (value != null) {
1590 Object.assign(routeToUpdate, { [key]: value });
1591 Object.assign(routeToUpdate, mapRouteProperties(routeToUpdate));
1592 }
1593 }
1594 if (typeof routeToUpdate.lazy === "object") {
1595 routeToUpdate.lazy[key] = void 0;
1596 if (Object.values(routeToUpdate.lazy).every((value) => value === void 0)) routeToUpdate.lazy = void 0;
1597 }
1598 })();
1599 cache[key] = propertyPromise;
1600 propertyPromise.catch(() => {
1601 if (cache[key] === propertyPromise) delete cache[key];
1602 });
1603 return propertyPromise;
1604};
1605const lazyRouteFunctionCache = /* @__PURE__ */ new WeakMap();
1606/**
1607* Execute route.lazy functions to lazily load route modules (loader, action,
1608* shouldRevalidate) and update the routeManifest in place which shares objects
1609* with dataRoutes so those get updated as well.
1610*/
1611function loadLazyRoute(route, type, manifest, mapRouteProperties, lazyRoutePropertiesToSkip) {
1612 let routeToUpdate = manifest[route.id];
1613 invariant$1(routeToUpdate, "No route found in manifest");
1614 if (!route.lazy) return {
1615 lazyRoutePromise: void 0,
1616 lazyHandlerPromise: void 0
1617 };
1618 if (typeof route.lazy === "function") {
1619 let cachedPromise = lazyRouteFunctionCache.get(routeToUpdate);
1620 if (cachedPromise) return {
1621 lazyRoutePromise: cachedPromise,
1622 lazyHandlerPromise: cachedPromise
1623 };
1624 let lazyRoutePromise = (async () => {
1625 invariant$1(typeof route.lazy === "function", "No lazy route function found");
1626 let lazyRoute = await route.lazy();
1627 let routeUpdates = {};
1628 for (let lazyRouteProperty in lazyRoute) {
1629 let lazyValue = lazyRoute[lazyRouteProperty];
1630 if (lazyValue === void 0) continue;
1631 let isUnsupported = isUnsupportedLazyRouteFunctionKey(lazyRouteProperty);
1632 let isStaticallyDefined = routeToUpdate[lazyRouteProperty] !== void 0;
1633 if (isUnsupported) warning(!isUnsupported, "Route property " + lazyRouteProperty + " is not a supported property to be returned from a lazy route function. This property will be ignored.");
1634 else if (isStaticallyDefined) warning(!isStaticallyDefined, `Route "${routeToUpdate.id}" has a static property "${lazyRouteProperty}" defined but its lazy function is also returning a value for this property. The lazy route property "${lazyRouteProperty}" will be ignored.`);
1635 else routeUpdates[lazyRouteProperty] = lazyValue;
1636 }
1637 Object.assign(routeToUpdate, routeUpdates);
1638 Object.assign(routeToUpdate, {
1639 ...mapRouteProperties(routeToUpdate),
1640 lazy: void 0
1641 });
1642 })();
1643 lazyRouteFunctionCache.set(routeToUpdate, lazyRoutePromise);
1644 lazyRoutePromise.catch(() => {
1645 if (lazyRouteFunctionCache.get(routeToUpdate) === lazyRoutePromise) lazyRouteFunctionCache.delete(routeToUpdate);
1646 });
1647 return {
1648 lazyRoutePromise,
1649 lazyHandlerPromise: lazyRoutePromise
1650 };
1651 }
1652 let lazyKeys = Object.keys(route.lazy);
1653 let lazyPropertyPromises = [];
1654 let lazyHandlerPromise = void 0;
1655 for (let key of lazyKeys) {
1656 if (lazyRoutePropertiesToSkip && lazyRoutePropertiesToSkip.includes(key)) continue;
1657 let promise = loadLazyRouteProperty({
1658 key,
1659 route,
1660 manifest,
1661 mapRouteProperties
1662 });
1663 if (promise) {
1664 lazyPropertyPromises.push(promise);
1665 if (key === type) lazyHandlerPromise = promise;
1666 }
1667 }
1668 let lazyRoutePromise = lazyPropertyPromises.length > 0 ? Promise.all(lazyPropertyPromises).then(() => {}) : void 0;
1669 lazyRoutePromise?.catch(() => {});
1670 lazyHandlerPromise?.catch(() => {});
1671 return {
1672 lazyRoutePromise,
1673 lazyHandlerPromise
1674 };
1675}
1676function isNonNullable(value) {
1677 return value !== void 0;
1678}
1679function loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties) {
1680 let promises = matches.map(({ route }) => {
1681 if (typeof route.lazy !== "object" || !route.lazy.middleware) return;
1682 return loadLazyRouteProperty({
1683 key: "middleware",
1684 route,
1685 manifest,
1686 mapRouteProperties
1687 });
1688 }).filter(isNonNullable);
1689 return promises.length > 0 ? Promise.all(promises) : void 0;
1690}
1691async function defaultDataStrategy(args) {
1692 let matchesToLoad = args.matches.filter((m) => m.shouldLoad);
1693 let keyedResults = {};
1694 (await Promise.all(matchesToLoad.map((m) => m.resolve()))).forEach((result, i) => {
1695 keyedResults[matchesToLoad[i].route.id] = result;
1696 });
1697 return keyedResults;
1698}
1699function runServerMiddlewarePipeline(args, handler, errorHandler) {
1700 return runMiddlewarePipeline(args, handler, processResult, isResponse, errorHandler);
1701 function processResult(result) {
1702 return isDataWithResponseInit(result) ? dataWithResponseInitToResponse(result) : result;
1703 }
1704}
1705function runClientMiddlewarePipeline(args, handler) {
1706 return runMiddlewarePipeline(args, handler, (r) => {
1707 if (isRedirectResponse(r)) throw r;
1708 return r;
1709 }, isDataStrategyResults, errorHandler);
1710 async function errorHandler(error, routeId, nextResult) {
1711 if (nextResult) return Object.assign(nextResult.value, { [routeId]: {
1712 type: "error",
1713 result: error
1714 } });
1715 else {
1716 let { matches } = args;
1717 let maxBoundaryIdx = Math.min(Math.max(matches.findIndex((m) => m.route.id === routeId), 0), Math.max(matches.findIndex((m) => m.shouldCallHandler()), 0));
1718 let deepestRouteId = matches[maxBoundaryIdx].route.id;
1719 for (let match of matches.slice(0, maxBoundaryIdx + 1)) try {
1720 await match._lazyPromises?.route;
1721 } catch {
1722 deepestRouteId = match.route.id;
1723 break;
1724 }
1725 return { [findNearestBoundary(matches, deepestRouteId).route.id]: {
1726 type: "error",
1727 result: error
1728 } };
1729 }
1730 }
1731}
1732async function runMiddlewarePipeline(args, handler, processResult, isResult, errorHandler) {
1733 let { matches, ...dataFnArgs } = args;
1734 return await callRouteMiddleware(dataFnArgs, matches.flatMap((m) => m.route.middleware ? m.route.middleware.map((fn) => [m.route.id, fn]) : []), handler, processResult, isResult, errorHandler);
1735}
1736async function callRouteMiddleware(args, middlewares, handler, processResult, isResult, errorHandler, idx = 0) {
1737 let { request } = args;
1738 if (request.signal.aborted) throw request.signal.reason ?? /* @__PURE__ */ new Error(`Request aborted: ${request.method} ${request.url}`);
1739 let tuple = middlewares[idx];
1740 if (!tuple) return await handler();
1741 let [routeId, middleware] = tuple;
1742 let nextResult;
1743 let next = async () => {
1744 if (nextResult) throw new Error("You may only call `next()` once per middleware");
1745 try {
1746 nextResult = { value: await callRouteMiddleware(args, middlewares, handler, processResult, isResult, errorHandler, idx + 1) };
1747 return nextResult.value;
1748 } catch (error) {
1749 nextResult = { value: await errorHandler(error, routeId, nextResult) };
1750 return nextResult.value;
1751 }
1752 };
1753 try {
1754 let value = await middleware(args, next);
1755 let result = value != null ? processResult(value) : void 0;
1756 if (isResult(result)) return result;
1757 else if (nextResult) return result ?? nextResult.value;
1758 else {
1759 nextResult = { value: await next() };
1760 return nextResult.value;
1761 }
1762 } catch (error) {
1763 return await errorHandler(error, routeId, nextResult);
1764 }
1765}
1766function getDataStrategyMatchLazyPromises(mapRouteProperties, manifest, request, match, lazyRoutePropertiesToSkip) {
1767 let lazyMiddlewarePromise = loadLazyRouteProperty({
1768 key: "middleware",
1769 route: match.route,
1770 manifest,
1771 mapRouteProperties
1772 });
1773 let lazyRoutePromises = loadLazyRoute(match.route, isMutationMethod(request.method) ? "action" : "loader", manifest, mapRouteProperties, lazyRoutePropertiesToSkip);
1774 return {
1775 middleware: lazyMiddlewarePromise,
1776 route: lazyRoutePromises.lazyRoutePromise,
1777 handler: lazyRoutePromises.lazyHandlerPromise
1778 };
1779}
1780function getDataStrategyMatch(mapRouteProperties, manifest, request, path, pattern, match, lazyRoutePropertiesToSkip, scopedContext, shouldLoad, shouldRevalidateArgs = null, callSiteDefaultShouldRevalidate) {
1781 let isUsingNewApi = false;
1782 let _lazyPromises = getDataStrategyMatchLazyPromises(mapRouteProperties, manifest, request, match, lazyRoutePropertiesToSkip);
1783 return {
1784 ...match,
1785 _lazyPromises,
1786 shouldLoad,
1787 shouldRevalidateArgs,
1788 shouldCallHandler(defaultShouldRevalidate) {
1789 isUsingNewApi = true;
1790 if (!shouldRevalidateArgs) return shouldLoad;
1791 if (typeof callSiteDefaultShouldRevalidate === "boolean") return shouldRevalidateLoader(match, {
1792 ...shouldRevalidateArgs,
1793 defaultShouldRevalidate: callSiteDefaultShouldRevalidate
1794 });
1795 if (typeof defaultShouldRevalidate === "boolean") return shouldRevalidateLoader(match, {
1796 ...shouldRevalidateArgs,
1797 defaultShouldRevalidate
1798 });
1799 return shouldRevalidateLoader(match, shouldRevalidateArgs);
1800 },
1801 resolve(handlerOverride) {
1802 let { lazy, loader, middleware } = match.route;
1803 let callHandler = isUsingNewApi || shouldLoad || handlerOverride && !isMutationMethod(request.method) && (lazy || loader);
1804 let isMiddlewareOnlyRoute = middleware && middleware.length > 0 && !loader && !lazy;
1805 if (callHandler && (isMutationMethod(request.method) || !isMiddlewareOnlyRoute)) return callLoaderOrAction({
1806 request,
1807 path,
1808 pattern,
1809 match,
1810 lazyHandlerPromise: _lazyPromises?.handler,
1811 lazyRoutePromise: _lazyPromises?.route,
1812 handlerOverride,
1813 scopedContext
1814 });
1815 return Promise.resolve({
1816 type: "data",
1817 result: void 0
1818 });
1819 }
1820 };
1821}
1822function getTargetedDataStrategyMatches(mapRouteProperties, manifest, request, path, matches, targetMatch, lazyRoutePropertiesToSkip, scopedContext, shouldRevalidateArgs = null) {
1823 return matches.map((match) => {
1824 if (match.route.id !== targetMatch.route.id) return {
1825 ...match,
1826 shouldLoad: false,
1827 shouldRevalidateArgs,
1828 shouldCallHandler: () => false,
1829 _lazyPromises: getDataStrategyMatchLazyPromises(mapRouteProperties, manifest, request, match, lazyRoutePropertiesToSkip),
1830 resolve: () => Promise.resolve({
1831 type: "data",
1832 result: void 0
1833 })
1834 };
1835 return getDataStrategyMatch(mapRouteProperties, manifest, request, path, getRoutePattern(matches), match, lazyRoutePropertiesToSkip, scopedContext, true, shouldRevalidateArgs);
1836 });
1837}
1838async function callDataStrategyImpl(dataStrategyImpl, request, path, matches, fetcherKey, initiator, scopedContext, isStaticHandler, navigationType = null) {
1839 if (matches.some((m) => m._lazyPromises?.middleware)) await Promise.all(matches.map((m) => m._lazyPromises?.middleware));
1840 let dataStrategyArgs = {
1841 request,
1842 url: createDataFunctionUrl(request, path),
1843 pattern: getRoutePattern(matches),
1844 params: matches[0].params,
1845 context: scopedContext,
1846 matches,
1847 unstable_initiator: initiator,
1848 unstable_navigationType: initiator === "navigation" ? navigationType : null
1849 };
1850 let runClientMiddleware = isStaticHandler ? () => {
1851 throw new Error("You cannot call `runClientMiddleware()` from a static handler `dataStrategy`. Middleware is run outside of `dataStrategy` during SSR in order to bubble up the Response. You can enable middleware via the `respond` API in `query`/`queryRoute`");
1852 } : (cb) => {
1853 let typedDataStrategyArgs = dataStrategyArgs;
1854 return runClientMiddlewarePipeline(typedDataStrategyArgs, () => {
1855 return cb({
1856 ...typedDataStrategyArgs,
1857 fetcherKey,
1858 runClientMiddleware: () => {
1859 throw new Error("Cannot call `runClientMiddleware()` from within an `runClientMiddleware` handler");
1860 }
1861 });
1862 });
1863 };
1864 let results = await dataStrategyImpl({
1865 ...dataStrategyArgs,
1866 fetcherKey,
1867 runClientMiddleware
1868 });
1869 try {
1870 await Promise.all(matches.flatMap((m) => [m._lazyPromises?.handler, m._lazyPromises?.route]));
1871 } catch {}
1872 return results;
1873}
1874async function callLoaderOrAction({ request, path, pattern, match, lazyHandlerPromise, lazyRoutePromise, handlerOverride, scopedContext }) {
1875 let result;
1876 let onReject;
1877 let isAction = isMutationMethod(request.method);
1878 let type = isAction ? "action" : "loader";
1879 let runHandler = (handler) => {
1880 let reject;
1881 let abortPromise = new Promise((_, r) => reject = r);
1882 onReject = () => reject();
1883 request.signal.addEventListener("abort", onReject);
1884 let actualHandler = (ctx) => {
1885 if (typeof handler !== "function") return Promise.reject(/* @__PURE__ */ new Error(`You cannot call the handler for a route which defines a boolean "${type}" [routeId: ${match.route.id}]`));
1886 return handler({
1887 request,
1888 url: createDataFunctionUrl(request, path),
1889 pattern,
1890 params: match.params,
1891 context: scopedContext
1892 }, ...ctx !== void 0 ? [ctx] : []);
1893 };
1894 let handlerPromise = (async () => {
1895 try {
1896 return {
1897 type: "data",
1898 result: await (handlerOverride ? handlerOverride((ctx) => actualHandler(ctx)) : actualHandler())
1899 };
1900 } catch (e) {
1901 return {
1902 type: "error",
1903 result: e
1904 };
1905 }
1906 })();
1907 return Promise.race([handlerPromise, abortPromise]);
1908 };
1909 try {
1910 let handler = isAction ? match.route.action : match.route.loader;
1911 if (lazyHandlerPromise || lazyRoutePromise) if (handler) {
1912 let handlerError;
1913 let [value] = await Promise.all([
1914 runHandler(handler).catch((e) => {
1915 handlerError = e;
1916 }),
1917 lazyHandlerPromise,
1918 lazyRoutePromise
1919 ]);
1920 if (handlerError !== void 0) throw handlerError;
1921 result = value;
1922 } else {
1923 await lazyHandlerPromise;
1924 let handler = isAction ? match.route.action : match.route.loader;
1925 if (handler) [result] = await Promise.all([runHandler(handler), lazyRoutePromise]);
1926 else if (type === "action") {
1927 let url = new URL(request.url);
1928 let pathname = url.pathname + url.search;
1929 throw getInternalRouterError(405, {
1930 method: request.method,
1931 pathname,
1932 routeId: match.route.id
1933 });
1934 } else {
1935 await lazyRoutePromise;
1936 return {
1937 type: "data",
1938 result: void 0
1939 };
1940 }
1941 }
1942 else if (!handler) {
1943 let url = new URL(request.url);
1944 throw getInternalRouterError(404, { pathname: url.pathname + url.search });
1945 } else result = await runHandler(handler);
1946 } catch (e) {
1947 return {
1948 type: "error",
1949 result: e
1950 };
1951 } finally {
1952 if (onReject) request.signal.removeEventListener("abort", onReject);
1953 }
1954 return result;
1955}
1956async function parseResponseBody(response) {
1957 let contentType = response.headers.get("Content-Type");
1958 if (contentType && /\bapplication\/json\b/.test(contentType)) return response.body == null ? null : response.json();
1959 return response.text();
1960}
1961async function convertDataStrategyResultToDataResult(dataStrategyResult) {
1962 let { result, type } = dataStrategyResult;
1963 if (isResponse(result)) {
1964 let data;
1965 try {
1966 data = await parseResponseBody(result);
1967 } catch (e) {
1968 return {
1969 type: "error",
1970 error: e
1971 };
1972 }
1973 if (type === "error") return {
1974 type: "error",
1975 error: new ErrorResponseImpl(result.status, result.statusText, data),
1976 statusCode: result.status,
1977 headers: result.headers
1978 };
1979 return {
1980 type: "data",
1981 data,
1982 statusCode: result.status,
1983 headers: result.headers
1984 };
1985 }
1986 if (type === "error") {
1987 if (isDataWithResponseInit(result)) {
1988 if (result.data instanceof Error) return {
1989 type: "error",
1990 error: result.data,
1991 statusCode: result.init?.status,
1992 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
1993 };
1994 return {
1995 type: "error",
1996 error: dataWithResponseInitToErrorResponse(result),
1997 statusCode: isRouteErrorResponse(result) ? result.status : void 0,
1998 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
1999 };
2000 }
2001 return {
2002 type: "error",
2003 error: result,
2004 statusCode: isRouteErrorResponse(result) ? result.status : void 0
2005 };
2006 }
2007 if (isDataWithResponseInit(result)) return {
2008 type: "data",
2009 data: result.data,
2010 statusCode: result.init?.status,
2011 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
2012 };
2013 return {
2014 type: "data",
2015 data: result
2016 };
2017}
2018function normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename) {
2019 let location = response.headers.get("Location");
2020 invariant$1(location, "Redirects returned/thrown from loaders/actions must have a Location header");
2021 if (!isAbsoluteUrl(location)) {
2022 let trimmedMatches = matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1);
2023 location = normalizeTo(new URL(request.url), trimmedMatches, basename, location);
2024 response.headers.set("Location", location);
2025 }
2026 return response;
2027}
2028function processRouteLoaderData(matches, results, pendingActionResult, isStaticHandler = false, skipLoaderErrorBubbling = false) {
2029 let loaderData = {};
2030 let errors = null;
2031 let statusCode;
2032 let foundError = false;
2033 let loaderHeaders = {};
2034 let pendingError = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : void 0;
2035 matches.forEach((match) => {
2036 if (!(match.route.id in results)) return;
2037 let id = match.route.id;
2038 let result = results[id];
2039 invariant$1(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData");
2040 if (isErrorResult(result)) {
2041 let error = result.error;
2042 if (pendingError !== void 0) {
2043 error = pendingError;
2044 pendingError = void 0;
2045 }
2046 errors = errors || {};
2047 if (skipLoaderErrorBubbling) errors[id] = error;
2048 else {
2049 let boundaryMatch = findNearestBoundary(matches, id);
2050 if (errors[boundaryMatch.route.id] == null) errors[boundaryMatch.route.id] = error;
2051 }
2052 if (!isStaticHandler) loaderData[id] = ResetLoaderDataSymbol;
2053 if (!foundError) {
2054 foundError = true;
2055 statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;
2056 }
2057 if (result.headers) loaderHeaders[id] = result.headers;
2058 } else {
2059 loaderData[id] = result.data;
2060 if (result.statusCode && result.statusCode !== 200 && !foundError) statusCode = result.statusCode;
2061 if (result.headers) loaderHeaders[id] = result.headers;
2062 }
2063 });
2064 if (pendingError !== void 0 && pendingActionResult) {
2065 errors = { [pendingActionResult[0]]: pendingError };
2066 if (pendingActionResult[2]) loaderData[pendingActionResult[2]] = void 0;
2067 }
2068 return {
2069 loaderData,
2070 errors,
2071 statusCode: statusCode || 200,
2072 loaderHeaders
2073 };
2074}
2075function findNearestBoundary(matches, routeId) {
2076 return (routeId ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1) : [...matches]).reverse().find((m) => m.route.ErrorBoundary != null || m.route.errorElement != null) || matches[0];
2077}
2078function getShortCircuitMatches(routes) {
2079 let route = routes.length === 1 ? routes[0] : routes.find((r) => r.index || !r.path || r.path === "/") || { id: `__shim-error-route__` };
2080 return {
2081 matches: [{
2082 params: {},
2083 pathname: "",
2084 pathnameBase: "",
2085 route
2086 }],
2087 route
2088 };
2089}
2090function getInternalRouterError(status, { pathname, routeId, method, type, message } = {}) {
2091 let statusText = "Unknown Server Error";
2092 let errorMessage = "Unknown @remix-run/router error";
2093 if (status === 400) {
2094 statusText = "Bad Request";
2095 if (method && pathname && routeId) errorMessage = `You made a ${method} request to "${pathname}" but did not provide a \`loader\` for route "${routeId}", so there is no way to handle the request.`;
2096 else if (type === "invalid-body") errorMessage = "Unable to encode submission body";
2097 } else if (status === 403) {
2098 statusText = "Forbidden";
2099 errorMessage = `Route "${routeId}" does not match URL "${pathname}"`;
2100 } else if (status === 404) {
2101 statusText = "Not Found";
2102 errorMessage = `No route matches URL "${pathname}"`;
2103 } else if (status === 405) {
2104 statusText = "Method Not Allowed";
2105 if (method && pathname && routeId) errorMessage = `You made a ${method.toUpperCase()} request to "${pathname}" but did not provide an \`action\` for route "${routeId}", so there is no way to handle the request.`;
2106 else if (method) errorMessage = `Invalid request method "${method.toUpperCase()}"`;
2107 }
2108 return new ErrorResponseImpl(status || 500, statusText, new Error(errorMessage), true);
2109}
2110function dataWithResponseInitToResponse(data) {
2111 return Response.json(data.data, data.init ?? void 0);
2112}
2113function dataWithResponseInitToErrorResponse(data) {
2114 return new ErrorResponseImpl(data.init?.status ?? 500, data.init?.statusText ?? "Internal Server Error", data.data);
2115}
2116function isDataStrategyResults(result) {
2117 return result != null && typeof result === "object" && Object.entries(result).every(([key, value]) => typeof key === "string" && isDataStrategyResult(value));
2118}
2119function isDataStrategyResult(result) {
2120 return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === "data" || result.type === "error");
2121}
2122function isRedirectDataStrategyResult(result) {
2123 return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
2124}
2125function isErrorResult(result) {
2126 return result.type === "error";
2127}
2128function isRedirectResult(result) {
2129 return (result && result.type) === "redirect";
2130}
2131function isDataWithResponseInit(value) {
2132 return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value.type === "DataWithResponseInit";
2133}
2134function isResponse(value) {
2135 return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
2136}
2137function isRedirectStatusCode(statusCode) {
2138 return redirectStatusCodes.has(statusCode);
2139}
2140function isRedirectResponse(result) {
2141 return isResponse(result) && isRedirectStatusCode(result.status) && result.headers.has("Location");
2142}
2143function isValidMethod(method) {
2144 return validRequestMethods.has(method.toUpperCase());
2145}
2146function isMutationMethod(method) {
2147 return validMutationMethods.has(method.toUpperCase());
2148}
2149function hasNakedIndexQuery(search) {
2150 return new URLSearchParams(search).getAll("index").some((v) => v === "");
2151}
2152function getTargetMatch(matches, location) {
2153 let search = typeof location === "string" ? parsePath(location).search : location.search;
2154 if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) return matches[matches.length - 1];
2155 let pathMatches = getPathContributingMatches(matches);
2156 return pathMatches[pathMatches.length - 1];
2157}
2158//#endregion
2159//#region lib/server-runtime/invariant.ts
2160function invariant(value, message) {
2161 if (value === false || value === null || typeof value === "undefined") {
2162 console.error("The following error is a bug in React Router; please open an issue! https://github.com/remix-run/react-router/issues/new/choose");
2163 throw new Error(message);
2164 }
2165}
2166//#endregion
2167//#region lib/server-runtime/headers.ts
2168function getDocumentHeadersImpl(context, getRouteHeadersFn, _defaultHeaders) {
2169 let boundaryIdx = context.errors ? context.matches.findIndex((m) => context.errors[m.route.id]) : -1;
2170 let matches = boundaryIdx >= 0 ? context.matches.slice(0, boundaryIdx + 1) : context.matches;
2171 let errorHeaders;
2172 if (boundaryIdx >= 0) {
2173 let { actionHeaders, actionData, loaderHeaders, loaderData } = context;
2174 context.matches.slice(boundaryIdx).some((match) => {
2175 let id = match.route.id;
2176 if (actionHeaders[id] && (!actionData || !actionData.hasOwnProperty(id))) errorHeaders = actionHeaders[id];
2177 else if (loaderHeaders[id] && !loaderData.hasOwnProperty(id)) errorHeaders = loaderHeaders[id];
2178 return errorHeaders != null;
2179 });
2180 }
2181 const defaultHeaders = new Headers(_defaultHeaders);
2182 return matches.reduce((parentHeaders, match, idx) => {
2183 let { id } = match.route;
2184 let loaderHeaders = context.loaderHeaders[id] || new Headers();
2185 let actionHeaders = context.actionHeaders[id] || new Headers();
2186 let includeErrorHeaders = errorHeaders != null && idx === matches.length - 1;
2187 let includeErrorCookies = includeErrorHeaders && errorHeaders !== loaderHeaders && errorHeaders !== actionHeaders;
2188 let headersFn = getRouteHeadersFn(match);
2189 if (headersFn == null) {
2190 let headers = new Headers(parentHeaders);
2191 if (includeErrorCookies) prependCookies(errorHeaders, headers);
2192 prependCookies(actionHeaders, headers);
2193 prependCookies(loaderHeaders, headers);
2194 return headers;
2195 }
2196 let headers = new Headers(typeof headersFn === "function" ? headersFn({
2197 loaderHeaders,
2198 parentHeaders,
2199 actionHeaders,
2200 errorHeaders: includeErrorHeaders ? errorHeaders : void 0
2201 }) : headersFn);
2202 if (includeErrorCookies) prependCookies(errorHeaders, headers);
2203 prependCookies(actionHeaders, headers);
2204 prependCookies(loaderHeaders, headers);
2205 prependCookies(parentHeaders, headers);
2206 return headers;
2207 }, new Headers(defaultHeaders));
2208}
2209function prependCookies(parentHeaders, childHeaders) {
2210 let parentSetCookieString = parentHeaders.get("Set-Cookie");
2211 if (parentSetCookieString) {
2212 let cookies = splitSetCookieString(parentSetCookieString);
2213 let childCookies = new Set(childHeaders.getSetCookie());
2214 cookies.forEach((cookie) => {
2215 if (!childCookies.has(cookie)) childHeaders.append("Set-Cookie", cookie);
2216 });
2217 }
2218}
2219//#endregion
2220//#region lib/server-runtime/warnings.ts
2221const alreadyWarned = {};
2222function warnOnce(condition, message) {
2223 if (!condition && !alreadyWarned[message]) {
2224 alreadyWarned[message] = true;
2225 console.warn(message);
2226 }
2227}
2228//#endregion
2229//#region lib/errors.ts
2230const ERROR_DIGEST_BASE = "REACT_ROUTER_ERROR";
2231const ERROR_DIGEST_REDIRECT = "REDIRECT";
2232const ERROR_DIGEST_ROUTE_ERROR_RESPONSE = "ROUTE_ERROR_RESPONSE";
2233function createRedirectErrorDigest(response) {
2234 return `${ERROR_DIGEST_BASE}:${ERROR_DIGEST_REDIRECT}:${JSON.stringify({
2235 status: response.status,
2236 statusText: response.statusText,
2237 location: response.headers.get("Location"),
2238 reloadDocument: response.headers.get("X-Remix-Reload-Document") === "true",
2239 replace: response.headers.get("X-Remix-Replace") === "true"
2240 })}`;
2241}
2242function createRouteErrorResponseDigest(response) {
2243 let status = 500;
2244 let statusText = "";
2245 let data;
2246 if (isDataWithResponseInit(response)) {
2247 status = response.init?.status ?? status;
2248 statusText = response.init?.statusText ?? statusText;
2249 data = response.data;
2250 } else {
2251 status = response.status;
2252 statusText = response.statusText;
2253 data = void 0;
2254 }
2255 return `${ERROR_DIGEST_BASE}:${ERROR_DIGEST_ROUTE_ERROR_RESPONSE}:${JSON.stringify({
2256 status,
2257 statusText,
2258 data
2259 })}`;
2260}
2261function getPathsWithAncestors(paths) {
2262 let result = /* @__PURE__ */ new Set();
2263 paths.forEach((path) => {
2264 if (!path.startsWith("/")) path = `/${path}`;
2265 for (let i = 1; i < path.length; i++) if (path[i] === "/") result.add(path.slice(0, i));
2266 result.add(path);
2267 });
2268 return Array.from(result);
2269}
2270const MANIFEST_MATCH_COST_LIMIT = 5e4;
2271const MANIFEST_MATCH_COST_SEGMENT_THRESHOLD = 10;
2272function shouldUseInitialRouteDiscovery(pathname, matchCost = 0) {
2273 let segmentCount = pathname.split("/").length - 1;
2274 return Math.max(segmentCount - 1, 0) * pathname.length + 1 > 7680 || segmentCount > MANIFEST_MATCH_COST_SEGMENT_THRESHOLD && segmentCount * matchCost > MANIFEST_MATCH_COST_LIMIT;
2275}
2276//#endregion
2277//#region lib/actions.ts
2278function throwIfPotentialCSRFAttack(request, allowedActionOrigins) {
2279 let originHeader = request.headers.get("origin");
2280 let originDomain = null;
2281 let originUrl = null;
2282 try {
2283 if (typeof originHeader === "string" && originHeader !== "null") {
2284 originUrl = new URL(originHeader);
2285 originDomain = originUrl.host;
2286 } else originDomain = originHeader;
2287 } catch {
2288 throw new Error(`\`origin\` header is not a valid URL. Aborting the action.`);
2289 }
2290 let requestUrl = new URL(request.url);
2291 let originMatchesRequest = originUrl ? originUrl.origin === requestUrl.origin : originDomain === requestUrl.host;
2292 if (originDomain && !originMatchesRequest) {
2293 if (!isAllowedOrigin(originDomain, allowedActionOrigins)) throw new Error("The `request.url` origin does not match `origin` header from a forwarded action request. Aborting the action.");
2294 }
2295}
2296function matchWildcardDomain(domain, pattern) {
2297 const domainParts = domain.split(".");
2298 const patternParts = pattern.split(".");
2299 if (patternParts.length < 1) return false;
2300 if (domainParts.length < patternParts.length) return false;
2301 while (patternParts.length) {
2302 const patternPart = patternParts.pop();
2303 const domainPart = domainParts.pop();
2304 switch (patternPart) {
2305 case "": return false;
2306 case "*": if (domainPart) continue;
2307 else return false;
2308 case "**":
2309 if (patternParts.length > 0) return false;
2310 return domainPart !== void 0;
2311 case void 0:
2312 default: if (domainPart !== patternPart) return false;
2313 }
2314 }
2315 return domainParts.length === 0;
2316}
2317function isAllowedOrigin(originDomain, allowedActionOrigins = []) {
2318 return allowedActionOrigins.some((allowedOrigin) => allowedOrigin && (allowedOrigin === originDomain || matchWildcardDomain(originDomain, allowedOrigin)));
2319}
2320//#endregion
2321//#region lib/server-runtime/urls.ts
2322function getNormalizedPath(request) {
2323 let url = new URL(request.url);
2324 let pathname = url.pathname;
2325 if (pathname.endsWith("/_.data")) pathname = pathname.replace(/_\.data$/, "");
2326 else pathname = pathname.replace(/\.data$/, "");
2327 let searchParams = new URLSearchParams(url.search);
2328 searchParams.delete("_routes");
2329 let search = searchParams.toString();
2330 if (search) search = `?${search}`;
2331 return {
2332 pathname,
2333 search,
2334 hash: ""
2335 };
2336}
2337//#endregion
2338//#region lib/rsc/server.rsc.ts
2339const Outlet$2 = Outlet$1;
2340const WithComponentProps = UNSAFE_WithComponentProps;
2341const WithErrorBoundaryProps = UNSAFE_WithErrorBoundaryProps;
2342const WithHydrateFallbackProps = UNSAFE_WithHydrateFallbackProps;
2343const globalVar = typeof globalThis !== "undefined" ? globalThis : global;
2344const ServerStorage = globalVar.___reactRouterServerStorage___ ??= new AsyncLocalStorage();
2345function getRequest() {
2346 const ctx = ServerStorage.getStore();
2347 if (!ctx) throw new Error("getRequest must be called from within a React Server render context");
2348 return ctx.request;
2349}
2350const redirect = (...args) => {
2351 const response = redirect$1(...args);
2352 const ctx = ServerStorage.getStore();
2353 if (ctx && ctx.runningAction) ctx.redirect = response;
2354 return response;
2355};
2356const redirectDocument = (...args) => {
2357 const response = redirectDocument$1(...args);
2358 const ctx = ServerStorage.getStore();
2359 if (ctx && ctx.runningAction) ctx.redirect = response;
2360 return response;
2361};
2362const replace = (...args) => {
2363 const response = replace$1(...args);
2364 const ctx = ServerStorage.getStore();
2365 if (ctx && ctx.runningAction) ctx.redirect = response;
2366 return response;
2367};
2368const cachedResolvePromise = React.cache(async (resolve) => {
2369 return Promise.allSettled([resolve]).then((r) => r[0]);
2370});
2371const Await = (async (props) => {
2372 invariant$1("resolve" in props !== "unstable_promise" in props, "<Await> requires exactly one of `resolve` or `unstable_promise`");
2373 let { children, errorElement } = props;
2374 let usePromise = "unstable_promise" in props;
2375 let resolved = await cachedResolvePromise(usePromise ? props.unstable_promise : props.resolve);
2376 if (resolved.status === "rejected" && !errorElement) throw resolved.reason;
2377 if (resolved.status === "rejected") return React.createElement(UNSAFE_AwaitContextProvider, {
2378 children: React.createElement(React.Fragment, null, errorElement),
2379 value: usePromise ? resolved : {
2380 _tracked: true,
2381 _error: resolved.reason
2382 }
2383 });
2384 const toRender = typeof children === "function" ? children(resolved.value) : children;
2385 return React.createElement(UNSAFE_AwaitContextProvider, {
2386 children: toRender,
2387 value: usePromise ? resolved : {
2388 _tracked: true,
2389 _data: resolved.value
2390 }
2391 });
2392});
2393/**
2394* Matches the given routes to a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
2395* and returns an [RSC](https://react.dev/reference/rsc/server-components)
2396* [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
2397* encoding an {@link unstable_RSCPayload} for consumption by an [RSC](https://react.dev/reference/rsc/server-components)
2398* enabled client router.
2399*
2400* Treat every React Server Function as a public endpoint. Server Functions are
2401* not inherently associated with a route. Any route middleware that runs is
2402* selected from the URL used to call a Server Function, but the client controls
2403* both the Server Function identifier and the URL. Perform all access control
2404* checks within each Server Function, or use a route action for
2405* middleware-driven access control.
2406*
2407* @example
2408* import {
2409* createTemporaryReferenceSet,
2410* decodeAction,
2411* decodeReply,
2412* loadServerAction,
2413* renderToReadableStream,
2414* } from "@vitejs/plugin-rsc/rsc";
2415* import { unstable_matchRSCServerRequest as matchRSCServerRequest } from "react-router";
2416*
2417* matchRSCServerRequest({
2418* createTemporaryReferenceSet,
2419* decodeAction,
2420* decodeFormState,
2421* decodeReply,
2422* loadServerAction,
2423* request,
2424* routes: routes(),
2425* generateResponse(match) {
2426* return new Response(
2427* renderToReadableStream(match.payload),
2428* {
2429* status: match.statusCode,
2430* headers: match.headers,
2431* }
2432* );
2433* },
2434* });
2435*
2436* @name unstable_matchRSCServerRequest
2437* @public
2438* @category RSC
2439* @mode data
2440* @param opts Options
2441* @param opts.allowedActionOrigins Origin patterns that are allowed to execute actions.
2442* @param opts.basename The basename to use when matching the request.
2443* @param opts.createTemporaryReferenceSet A function that returns a temporary
2444* reference set for the request, used to track temporary references in the [RSC](https://react.dev/reference/rsc/server-components)
2445* stream.
2446* @param opts.decodeAction Your `react-server-dom-xyz/server`'s `decodeAction`
2447* function, responsible for loading a server action.
2448* @param opts.decodeFormState A function responsible for decoding form state for
2449* progressively enhanceable forms with React's [`useActionState`](https://react.dev/reference/react/useActionState)
2450* using your `react-server-dom-xyz/server`'s `decodeFormState`.
2451* @param opts.decodeReply Your `react-server-dom-xyz/server`'s `decodeReply`
2452* function, used to decode the server function's arguments and bind them to the
2453* implementation for invocation by the router.
2454* @param opts.generateResponse A function responsible for using your
2455* `renderToReadableStream` to generate a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
2456* encoding the {@link unstable_RSCPayload}.
2457* @param opts.loadServerAction Your `react-server-dom-xyz/server`'s
2458* `loadServerAction` function, used to load a server action by ID.
2459* @param opts.clientVersion A version derived from the client build output used
2460* to detect stale clients during lazy route discovery.
2461* @param opts.onError An optional error handler that will be called with any
2462* errors that occur during the request processing.
2463* @param opts.request The [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
2464* to match against.
2465* @param opts.requestContext An instance of {@link RouterContextProvider}
2466* that should be created per request, to be passed to [`action`](../../start/data/route-object#action)s,
2467* [`loader`](../../start/data/route-object#loader)s and [middleware](../../how-to/middleware).
2468* @param opts.routeDiscovery The route discovery configuration, used to determine how the router should discover new routes during navigations.
2469* @param opts.routes Your {@link unstable_RSCRouteConfigEntry | route definitions}.
2470* @returns A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
2471* that contains the [RSC](https://react.dev/reference/rsc/server-components)
2472* data for hydration.
2473*/
2474async function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, routeDiscovery, loadServerAction, decodeAction, decodeFormState, clientVersion, onError, request, routes, generateResponse: encodeResponse }) {
2475 let generateResponse = (match, options) => {
2476 let response = encodeResponse(match, options);
2477 response.headers.set("Content-Type", "text/x-component");
2478 return response;
2479 };
2480 let url = new URL(request.url);
2481 basename = basename || "/";
2482 let normalizedPath = url.pathname;
2483 if (url.pathname.endsWith("/_.rsc")) normalizedPath = url.pathname.replace(/_\.rsc$/, "");
2484 else if (url.pathname.endsWith(".rsc")) normalizedPath = url.pathname.replace(/\.rsc$/, "");
2485 if (stripBasename(normalizedPath, basename) !== "/" && normalizedPath.endsWith("/")) normalizedPath = normalizedPath.slice(0, -1);
2486 url.pathname = normalizedPath;
2487 basename = basename.length > normalizedPath.length ? normalizedPath : basename;
2488 let routerRequest = new Request(url.toString(), {
2489 method: request.method,
2490 headers: request.headers,
2491 body: request.body,
2492 signal: request.signal,
2493 duplex: request.body ? "half" : void 0
2494 });
2495 const temporaryReferences = createTemporaryReferenceSet();
2496 const requestUrl = new URL(request.url);
2497 if (isManifestRequest(requestUrl)) return await generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery, clientVersion);
2498 let isDataRequest = isReactServerRequest(requestUrl);
2499 let staticHandler = createStaticHandler(routes, { basename });
2500 let matches = staticHandler.match(url.pathname);
2501 if (matches) await Promise.all(matches.map((m) => explodeLazyRoute(m.route)));
2502 const leafMatch = matches?.[matches.length - 1];
2503 if (!isDataRequest && leafMatch && !leafMatch.route.Component && !leafMatch.route.ErrorBoundary) return generateResourceResponse(routerRequest, staticHandler, leafMatch.route.id, requestContext, onError);
2504 let response = await generateRenderResponse(routerRequest, staticHandler, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery, clientVersion);
2505 response.headers.set("X-Remix-Response", "yes");
2506 return response;
2507}
2508async function generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery, clientVersion) {
2509 let url = new URL(request.url);
2510 if (url.toString().length > 7680) return new Response(null, {
2511 statusText: "Bad Request",
2512 status: 400
2513 });
2514 if (clientVersion !== void 0 && clientVersion !== url.searchParams.get("version")) return new Response(null, {
2515 status: 204,
2516 headers: { "X-Remix-Reload-Document": "true" }
2517 });
2518 if (routeDiscovery?.mode === "initial") {
2519 let payload = {
2520 type: "manifest",
2521 patches: getAllRoutePatches(routes, basename)
2522 };
2523 return generateResponse({
2524 statusCode: 200,
2525 headers: new Headers({
2526 "Content-Type": "text/x-component",
2527 Vary: "Content-Type"
2528 }),
2529 payload
2530 }, {
2531 temporaryReferences,
2532 onError: defaultOnError
2533 });
2534 }
2535 let pathParam = url.searchParams.get("paths");
2536 let pathnames = pathParam ? pathParam.split(",").filter(Boolean) : [url.pathname.replace(/\.manifest$/, "")];
2537 let staticHandler = routes.length > 0 ? createStaticHandler(routes, { basename }) : void 0;
2538 let routeIds = /* @__PURE__ */ new Set();
2539 let matchedRoutes = staticHandler ? pathnames.flatMap((pathname) => {
2540 let pathnameMatches = staticHandler.match(pathname);
2541 return pathnameMatches?.map((m, i) => ({
2542 ...m.route,
2543 parentId: pathnameMatches[i - 1]?.route.id
2544 })) ?? [];
2545 }).filter((route) => {
2546 if (!routeIds.has(route.id)) {
2547 routeIds.add(route.id);
2548 return true;
2549 }
2550 return false;
2551 }) : [];
2552 let payload = {
2553 type: "manifest",
2554 patches: Promise.all([...matchedRoutes.map((route) => getManifestRoute(route)), staticHandler ? getAdditionalRoutePatches(pathnames, staticHandler, Array.from(routeIds)) : Promise.resolve([])]).then((r) => r.flat(1))
2555 };
2556 return generateResponse({
2557 statusCode: 200,
2558 headers: new Headers({ "Content-Type": "text/x-component" }),
2559 payload
2560 }, {
2561 temporaryReferences,
2562 onError: defaultOnError
2563 });
2564}
2565function prependBasenameToRedirectResponse(response, basename = "/") {
2566 if (basename === "/") return response;
2567 let redirect = response.headers.get("Location");
2568 if (!redirect || isAbsoluteUrl(redirect)) return response;
2569 response.headers.set("Location", prependBasename({
2570 basename,
2571 pathname: redirect
2572 }));
2573 return response;
2574}
2575async function processServerAction(request, basename, decodeReply, loadServerAction, decodeAction, decodeFormState, onError, temporaryReferences) {
2576 const getRevalidationRequest = () => new Request(request.url, {
2577 method: "GET",
2578 headers: request.headers,
2579 signal: request.signal
2580 });
2581 const isFormRequest = canDecodeWithFormData(request.headers.get("Content-Type"));
2582 const actionId = request.headers.get("rsc-action-id");
2583 if (actionId) {
2584 if (!decodeReply || !loadServerAction) throw new Error("Cannot handle enhanced server action without decodeReply and loadServerAction functions");
2585 const actionArgs = await decodeReply(isFormRequest ? await request.formData() : await request.text(), { temporaryReferences });
2586 const serverAction = (await loadServerAction(actionId)).bind(null, ...actionArgs);
2587 let actionResult = Promise.resolve(serverAction());
2588 try {
2589 await actionResult;
2590 } catch (error) {
2591 if (isResponse(error)) return error;
2592 onError?.(error);
2593 }
2594 let maybeFormData = actionArgs.length === 1 ? actionArgs[0] : actionArgs[1];
2595 let skipRevalidation = (maybeFormData && typeof maybeFormData === "object" && maybeFormData instanceof FormData ? maybeFormData : null)?.has("$SKIP_REVALIDATION") ?? false;
2596 return {
2597 actionResult,
2598 revalidationRequest: getRevalidationRequest(),
2599 skipRevalidation
2600 };
2601 } else if (isFormRequest) {
2602 const formData = await request.clone().formData();
2603 if (Array.from(formData.keys()).some((k) => k.startsWith("$ACTION_"))) {
2604 if (!decodeAction) throw new Error("Cannot handle form actions without a decodeAction function");
2605 const action = await decodeAction(formData);
2606 let formState = void 0;
2607 try {
2608 let result = await action();
2609 if (isRedirectResponse(result)) result = prependBasenameToRedirectResponse(result, basename);
2610 formState = await decodeFormState?.(result, formData);
2611 } catch (error) {
2612 if (isRedirectResponse(error)) return prependBasenameToRedirectResponse(error, basename);
2613 if (isResponse(error)) return error;
2614 onError?.(error);
2615 }
2616 return {
2617 formState,
2618 revalidationRequest: getRevalidationRequest(),
2619 skipRevalidation: false
2620 };
2621 }
2622 }
2623}
2624async function generateResourceResponse(request, staticHandler, routeId, requestContext, onError) {
2625 try {
2626 return tagResourceResponse(await staticHandler.queryRoute(request, {
2627 routeId,
2628 requestContext,
2629 async generateMiddlewareResponse(queryRoute) {
2630 try {
2631 return tagResourceResponse(await queryRoute(request));
2632 } catch (error) {
2633 return generateErrorResponse(error);
2634 }
2635 },
2636 normalizePath: (r) => getNormalizedPath(r)
2637 }));
2638 } catch (error) {
2639 return generateErrorResponse(error);
2640 }
2641 function generateErrorResponse(error) {
2642 let response;
2643 if (isResponse(error)) response = error;
2644 else if (isRouteErrorResponse(error)) {
2645 onError?.(error);
2646 const errorMessage = typeof error.data === "string" ? error.data : error.statusText;
2647 response = new Response(errorMessage, {
2648 status: error.status,
2649 statusText: error.statusText
2650 });
2651 } else {
2652 onError?.(error);
2653 response = new Response("Internal Server Error", { status: 500 });
2654 }
2655 return tagResourceResponse(response);
2656 }
2657}
2658function tagResourceResponse(response) {
2659 const headers = new Headers(response.headers);
2660 headers.set("React-Router-Resource", "true");
2661 return new Response(response.body, {
2662 status: response.status,
2663 statusText: response.statusText,
2664 headers
2665 });
2666}
2667async function generateRenderResponse(request, staticHandler, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery, clientVersion) {
2668 let statusCode = 200;
2669 let url = new URL(request.url);
2670 let isSubmission = isMutationMethod(request.method);
2671 let routeIdsToLoad = !isSubmission && url.searchParams.has("_routes") ? url.searchParams.get("_routes").split(",") : null;
2672 let actionResult;
2673 const ctx = {
2674 request,
2675 runningAction: false
2676 };
2677 const result = await ServerStorage.run(ctx, () => staticHandler.query(request, {
2678 requestContext,
2679 skipLoaderErrorBubbling: isDataRequest,
2680 skipRevalidation: isSubmission,
2681 ...routeIdsToLoad ? { filterMatchesToLoad: (m) => routeIdsToLoad.includes(m.route.id) } : {},
2682 normalizePath: (r) => getNormalizedPath(r),
2683 async generateMiddlewareResponse(query) {
2684 let formState;
2685 let skipRevalidation = false;
2686 let potentialCSRFAttackError;
2687 if (isMutationMethod(request.method)) {
2688 try {
2689 throwIfPotentialCSRFAttack(request, allowedActionOrigins);
2690 } catch (error) {
2691 onError?.(error);
2692 potentialCSRFAttackError = error;
2693 request = new Request(request.url, {
2694 method: "GET",
2695 headers: request.headers,
2696 signal: request.signal
2697 });
2698 }
2699 if (!potentialCSRFAttackError) {
2700 ctx.runningAction = true;
2701 let result = await processServerAction(request, basename, decodeReply, loadServerAction, decodeAction, decodeFormState, onError, temporaryReferences).finally(() => {
2702 ctx.runningAction = false;
2703 });
2704 if (isResponse(result)) return generateRedirectResponse(result, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, result === ctx.redirect ? void 0 : ctx.redirect?.headers);
2705 skipRevalidation = result?.skipRevalidation ?? false;
2706 actionResult = result?.actionResult;
2707 formState = result?.formState;
2708 request = result?.revalidationRequest ?? request;
2709 if (ctx.redirect) return generateRedirectResponse(ctx.redirect, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, void 0);
2710 }
2711 }
2712 let staticContext = await query(request, skipRevalidation ? { filterMatchesToLoad: () => false } : void 0);
2713 if (isResponse(staticContext)) return generateRedirectResponse(staticContext, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
2714 if (potentialCSRFAttackError) {
2715 staticContext.errors ??= {};
2716 staticContext.errors[staticContext.matches[0].route.id] = potentialCSRFAttackError;
2717 staticContext.statusCode = 400;
2718 }
2719 return generateStaticContextResponse(staticHandler, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, ctx.redirect?.headers, routeDiscovery, clientVersion);
2720 }
2721 }));
2722 if (isRedirectResponse(result)) return generateRedirectResponse(result, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
2723 invariant(isResponse(result), "Expected a response from query");
2724 if (result.headers.get("Content-Type")?.split(";")[0].trim().toLowerCase() !== "text/x-component") return tagResourceResponse(result);
2725 return result;
2726}
2727function generateRedirectResponse(response, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, sideEffectRedirectHeaders) {
2728 let redirect = response.headers.get("Location");
2729 if (isDataRequest && basename) redirect = stripBasename(redirect, basename) || redirect;
2730 let payload = {
2731 type: "redirect",
2732 location: redirect,
2733 reload: response.headers.get("X-Remix-Reload-Document") === "true",
2734 replace: response.headers.get("X-Remix-Replace") === "true",
2735 status: response.status,
2736 actionResult
2737 };
2738 let headers = new Headers(sideEffectRedirectHeaders === response.headers ? void 0 : sideEffectRedirectHeaders);
2739 for (const [key, value] of response.headers.entries()) headers.append(key, value);
2740 headers.delete("Location");
2741 headers.delete("X-Remix-Reload-Document");
2742 headers.delete("X-Remix-Replace");
2743 headers.delete("Content-Length");
2744 headers.set("Content-Type", "text/x-component");
2745 return generateResponse({
2746 statusCode: 202,
2747 headers,
2748 payload
2749 }, {
2750 temporaryReferences,
2751 onError: defaultOnError
2752 });
2753}
2754async function generateStaticContextResponse(staticHandler, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, sideEffectRedirectHeaders, routeDiscovery, clientVersion) {
2755 statusCode = staticContext.statusCode ?? statusCode;
2756 if (staticContext.errors) staticContext.errors = Object.fromEntries(Object.entries(staticContext.errors).map(([key, error]) => [key, isRouteErrorResponse(error) ? Object.fromEntries(Object.entries(error)) : error]));
2757 staticContext.matches.forEach((m) => {
2758 const routeHasNoLoaderData = staticContext.loaderData[m.route.id] === void 0;
2759 const routeHasError = Boolean(staticContext.errors && m.route.id in staticContext.errors);
2760 if (routeHasNoLoaderData && !routeHasError) staticContext.loaderData[m.route.id] = null;
2761 });
2762 let headers = getDocumentHeadersImpl(staticContext, (match) => match.route.headers, sideEffectRedirectHeaders);
2763 headers.delete("Content-Length");
2764 const baseRenderPayload = {
2765 type: "render",
2766 basename: staticContext.basename,
2767 clientVersion,
2768 routeDiscovery: routeDiscovery ?? { mode: "lazy" },
2769 actionData: staticContext.actionData,
2770 errors: staticContext.errors,
2771 loaderData: staticContext.loaderData,
2772 location: staticContext.location,
2773 formState
2774 };
2775 const renderPayloadPromise = () => getRenderPayload(baseRenderPayload, staticHandler, basename, routeIdsToLoad, isDataRequest, staticContext, routeDiscovery);
2776 let payload;
2777 if (actionResult) payload = {
2778 type: "action",
2779 actionResult,
2780 rerender: skipRevalidation ? void 0 : renderPayloadPromise()
2781 };
2782 else if (isSubmission && isDataRequest) payload = {
2783 ...baseRenderPayload,
2784 matches: [],
2785 patches: Promise.resolve([])
2786 };
2787 else payload = await renderPayloadPromise();
2788 return generateResponse({
2789 statusCode,
2790 headers,
2791 payload
2792 }, {
2793 temporaryReferences,
2794 onError: defaultOnError
2795 });
2796}
2797async function getRenderPayload(baseRenderPayload, staticHandler, basename, routeIdsToLoad, isDataRequest, staticContext, routeDiscovery) {
2798 let routes = staticHandler.dataRoutes;
2799 let deepestRenderedRouteIdx = staticContext.matches.length - 1;
2800 let parentIds = {};
2801 staticContext.matches.forEach((m, i) => {
2802 if (i > 0) parentIds[m.route.id] = staticContext.matches[i - 1].route.id;
2803 if (staticContext.errors && m.route.id in staticContext.errors && deepestRenderedRouteIdx > i) deepestRenderedRouteIdx = i;
2804 });
2805 let matchesPromise = Promise.all(staticContext.matches.map((match, i) => {
2806 let isBelowErrorBoundary = i > deepestRenderedRouteIdx;
2807 let parentId = parentIds[match.route.id];
2808 return getRSCRouteMatch({
2809 staticContext,
2810 match,
2811 routeIdsToLoad,
2812 isBelowErrorBoundary,
2813 parentId
2814 });
2815 }));
2816 let pathname = staticContext.location.pathname;
2817 let useInitialRouteDiscovery = routeDiscovery?.mode === "initial" && !isDataRequest || shouldUseInitialRouteDiscovery(pathname, staticHandler._matchCost);
2818 let patches;
2819 if (useInitialRouteDiscovery) patches = getAllRoutePatches(routes, basename).then((patches) => patches.filter((patch) => !staticContext.matches.some((m) => m.route.id === patch.id)));
2820 else patches = getAdditionalRoutePatches(getPathsWithAncestors([pathname]).slice(0, -1), staticHandler, staticContext.matches.map((m) => m.route.id));
2821 return {
2822 ...baseRenderPayload,
2823 routeDiscovery: useInitialRouteDiscovery ? { mode: "initial" } : baseRenderPayload.routeDiscovery,
2824 matches: await matchesPromise,
2825 patches
2826 };
2827}
2828async function getRSCRouteMatch({ staticContext, match, isBelowErrorBoundary, routeIdsToLoad, parentId }) {
2829 const route = match.route;
2830 await explodeLazyRoute(route);
2831 const Layout = route.Layout || React.Fragment;
2832 const Component = route.Component;
2833 const ErrorBoundary = route.ErrorBoundary;
2834 const HydrateFallback = route.HydrateFallback;
2835 const loaderData = staticContext.loaderData[route.id];
2836 const actionData = staticContext.actionData?.[route.id];
2837 const params = match.params;
2838 let element = void 0;
2839 let shouldLoadRoute = !routeIdsToLoad || routeIdsToLoad.includes(route.id);
2840 if (Component && shouldLoadRoute) element = !isBelowErrorBoundary ? React.createElement(Layout, null, isClientReference(Component) ? React.createElement(WithComponentProps, { children: React.createElement(Component) }) : React.createElement(Component, {
2841 loaderData,
2842 actionData,
2843 params,
2844 matches: staticContext.matches.map((match) => convertRouteMatchToUiMatch(match, staticContext.loaderData))
2845 })) : React.createElement(Outlet$2);
2846 let error = void 0;
2847 if (ErrorBoundary && staticContext.errors) error = staticContext.errors[route.id];
2848 const errorElement = ErrorBoundary ? React.createElement(Layout, null, isClientReference(ErrorBoundary) ? React.createElement(WithErrorBoundaryProps, { children: React.createElement(ErrorBoundary) }) : React.createElement(ErrorBoundary, {
2849 loaderData,
2850 actionData,
2851 params,
2852 error
2853 })) : void 0;
2854 const hydrateFallbackElement = HydrateFallback ? React.createElement(Layout, null, isClientReference(HydrateFallback) ? React.createElement(WithHydrateFallbackProps, { children: React.createElement(HydrateFallback) }) : React.createElement(HydrateFallback, {
2855 loaderData,
2856 actionData,
2857 params
2858 })) : void 0;
2859 const hmrRoute = route;
2860 return {
2861 clientAction: route.clientAction,
2862 clientLoader: route.clientLoader,
2863 element,
2864 errorElement,
2865 handle: route.handle,
2866 hasAction: !!route.action,
2867 hasComponent: !!Component,
2868 hasLoader: !!route.loader,
2869 hydrateFallbackElement,
2870 id: route.id,
2871 index: "index" in route ? route.index : void 0,
2872 links: route.links,
2873 meta: route.meta,
2874 params,
2875 parentId,
2876 path: route.path,
2877 pathname: match.pathname,
2878 pathnameBase: match.pathnameBase,
2879 shouldRevalidate: route.shouldRevalidate,
2880 ...hmrRoute.__ensureClientRouteModuleForHMR ? { __ensureClientRouteModuleForHMR: hmrRoute.__ensureClientRouteModuleForHMR } : {}
2881 };
2882}
2883async function getManifestRoute(route) {
2884 await explodeLazyRoute(route);
2885 const Layout = route.Layout || React.Fragment;
2886 const errorElement = route.ErrorBoundary ? React.createElement(Layout, null, React.createElement(route.ErrorBoundary)) : void 0;
2887 return {
2888 clientAction: route.clientAction,
2889 clientLoader: route.clientLoader,
2890 handle: route.handle,
2891 hasAction: !!route.action,
2892 hasComponent: !!route.Component,
2893 errorElement,
2894 hasLoader: !!route.loader,
2895 id: route.id,
2896 parentId: route.parentId,
2897 path: route.path,
2898 index: "index" in route ? route.index : void 0,
2899 links: route.links,
2900 meta: route.meta
2901 };
2902}
2903async function explodeLazyRoute(route) {
2904 if ("lazy" in route && route.lazy) {
2905 let { default: lazyDefaultExport, Component: lazyComponentExport, ...lazyProperties } = await route.lazy();
2906 let Component = lazyComponentExport || lazyDefaultExport;
2907 if (Component && !route.Component) route.Component = Component;
2908 for (let [k, v] of Object.entries(lazyProperties)) if (k !== "id" && k !== "path" && k !== "index" && k !== "children" && route[k] == null) route[k] = v;
2909 route.lazy = void 0;
2910 }
2911}
2912async function getAllRoutePatches(routes, basename) {
2913 let patches = [];
2914 async function traverse(route, parentId) {
2915 let manifestRoute = await getManifestRoute({
2916 ...route,
2917 parentId
2918 });
2919 patches.push(manifestRoute);
2920 if ("children" in route && route.children?.length) for (let child of route.children) await traverse(child, route.id);
2921 }
2922 for (let route of routes) await traverse(route, void 0);
2923 return patches.filter((p) => !!p.parentId);
2924}
2925async function getAdditionalRoutePatches(pathnames, staticHandler, matchedRouteIds) {
2926 let patchRouteMatches = /* @__PURE__ */ new Map();
2927 let matchedPaths = /* @__PURE__ */ new Set();
2928 for (const pathname of pathnames) {
2929 if (matchedPaths.has(pathname)) continue;
2930 matchedPaths.add(pathname);
2931 let matches = staticHandler.match(pathname) || [];
2932 matches.forEach((m, i) => {
2933 if (patchRouteMatches.get(m.route.id)) return;
2934 patchRouteMatches.set(m.route.id, {
2935 ...m.route,
2936 parentId: matches[i - 1]?.route.id
2937 });
2938 });
2939 }
2940 return await Promise.all([...patchRouteMatches.values()].filter((route) => !matchedRouteIds.some((id) => id === route.id)).map((route) => getManifestRoute(route)));
2941}
2942function isReactServerRequest(url) {
2943 return url.pathname.endsWith(".rsc");
2944}
2945function isManifestRequest(url) {
2946 return url.pathname.endsWith(".manifest");
2947}
2948function defaultOnError(error) {
2949 if (isRedirectResponse(error)) return createRedirectErrorDigest(error);
2950 if (isResponse(error) || isDataWithResponseInit(error)) return createRouteErrorResponseDigest(error);
2951}
2952function isClientReference(x) {
2953 try {
2954 return x.$$typeof === Symbol.for("react.client.reference");
2955 } catch {
2956 return false;
2957 }
2958}
2959function canDecodeWithFormData(contentType) {
2960 if (!contentType) return false;
2961 return contentType.match(/\bapplication\/x-www-form-urlencoded\b/) || contentType.match(/\bmultipart\/form-data\b/);
2962}
2963//#endregion
2964//#region lib/href.ts
2965function stringify(p) {
2966 return p == null ? "" : typeof p === "string" ? p : String(p);
2967}
2968/**
2969* Returns a resolved URL path for the specified route.
2970*
2971* Param values are percent-encoded for use in a path segment: characters that
2972* would change the URL structure (`/`, `?`, `#`, `%`, whitespace, non-ASCII)
2973* are escaped, while characters that RFC 3986 allows literally in a path
2974* segment (`$ & + , ; = : @`) are kept as-is. Note this differs from query-string
2975* encoding (`encodeURIComponent`/`URLSearchParams`), where those characters are
2976* delimiters and must be escaped. Splat (`*`) values are encoded per segment,
2977* preserving `/` separators.
2978*
2979* See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3)
2980*
2981* @example
2982* const h = href("/:lang?/about", { lang: "en" })
2983* // -> `/en/about`
2984*
2985* <Link to={href("/products/:id", { id: "abc123" })} />
2986*
2987* @public
2988* @category Utils
2989* @mode framework
2990* @param path The route path to resolve
2991* @param args The route params to use when resolving the path
2992* @returns The resolved URL path
2993*/
2994function href(path, ...args) {
2995 let params = args[0];
2996 let result = trimTrailingSplat(path).replace(/\/:([\w-]+)(\?)?/g, (_, param, questionMark) => {
2997 const isRequired = questionMark === void 0;
2998 const value = params?.[param];
2999 if (isRequired && value === void 0) throw new Error(`Path '${path}' requires param '${param}' but it was not provided`);
3000 return value == null ? "" : "/" + encodePathParam(stringify(value));
3001 });
3002 if (path.endsWith("*")) {
3003 const value = params?.["*"];
3004 if (value !== void 0) result += "/" + stringify(value).split("/").map(encodePathParam).join("/");
3005 }
3006 return result || "/";
3007}
3008/**
3009* Removes a trailing splat and any number of slashes from the end of the path.
3010*
3011* Benchmarked to be faster than `path.replace(/\/*\*?$/, "")`, which backtracks.
3012*/
3013function trimTrailingSplat(path) {
3014 let i = path.length - 1;
3015 let char = path[i];
3016 if (char !== "*" && char !== "/") return path;
3017 i--;
3018 for (; i >= 0; i--) if (path[i] !== "/") break;
3019 return path.slice(0, i + 1);
3020}
3021//#endregion
3022//#region lib/server-runtime/crypto.ts
3023const encoder = /* @__PURE__ */ new TextEncoder();
3024const sign = async (value, secret) => {
3025 let data = encoder.encode(value);
3026 let key = await createKey(secret, ["sign"]);
3027 let signature = await crypto.subtle.sign("HMAC", key, data);
3028 let hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/=+$/, "");
3029 return value + "." + hash;
3030};
3031const unsign = async (cookie, secret) => {
3032 let index = cookie.lastIndexOf(".");
3033 let value = cookie.slice(0, index);
3034 let hash = cookie.slice(index + 1);
3035 let data = encoder.encode(value);
3036 let key = await createKey(secret, ["verify"]);
3037 try {
3038 let signature = byteStringToUint8Array(atob(hash));
3039 return await crypto.subtle.verify("HMAC", key, signature, data) ? value : false;
3040 } catch {
3041 return false;
3042 }
3043};
3044const createKey = async (secret, usages) => crypto.subtle.importKey("raw", encoder.encode(secret), {
3045 name: "HMAC",
3046 hash: "SHA-256"
3047}, false, usages);
3048function byteStringToUint8Array(byteString) {
3049 let array = new Uint8Array(byteString.length);
3050 for (let i = 0; i < byteString.length; i++) array[i] = byteString.charCodeAt(i);
3051 return array;
3052}
3053//#endregion
3054//#region lib/server-runtime/cookies.ts
3055/**
3056* Creates a logical container for managing a browser cookie from the server.
3057*
3058* @public
3059* @category Utils
3060* @mode framework
3061* @mode data
3062* @param name The name of the cookie.
3063* @param cookieOptions Options for parsing and serializing the cookie.
3064* @returns A {@link Cookie} object for parsing and serializing the cookie.
3065*/
3066const createCookie = (name, cookieOptions = {}) => {
3067 let { secrets = [], ...options } = {
3068 path: "/",
3069 sameSite: "lax",
3070 ...cookieOptions
3071 };
3072 warnOnceAboutExpiresCookie(name, options.expires);
3073 return {
3074 get name() {
3075 return name;
3076 },
3077 get isSigned() {
3078 return secrets.length > 0;
3079 },
3080 get expires() {
3081 return typeof options.maxAge !== "undefined" ? new Date(Date.now() + options.maxAge * 1e3) : options.expires;
3082 },
3083 async parse(cookieHeader, parseOptions) {
3084 if (!cookieHeader) return null;
3085 let cookies = parse(cookieHeader, {
3086 ...options,
3087 ...parseOptions
3088 });
3089 if (name in cookies) {
3090 let value = cookies[name];
3091 if (typeof value === "string" && value !== "") return await decodeCookieValue(value, secrets);
3092 else return "";
3093 } else return null;
3094 },
3095 async serialize(value, serializeOptions) {
3096 return serialize(name, value === "" ? "" : await encodeCookieValue(value, secrets), {
3097 ...options,
3098 ...serializeOptions
3099 });
3100 }
3101 };
3102};
3103/**
3104* Returns `true` if a value is a React Router {@link Cookie} object.
3105*
3106* @public
3107* @category Utils
3108* @mode framework
3109* @mode data
3110* @param object The value to check.
3111* @returns `true` if the value is a React Router {@link Cookie} object;
3112* otherwise, `false`.
3113*/
3114const isCookie = (object) => {
3115 return object != null && typeof object.name === "string" && typeof object.isSigned === "boolean" && typeof object.parse === "function" && typeof object.serialize === "function";
3116};
3117async function encodeCookieValue(value, secrets) {
3118 let encoded = encodeData(value);
3119 if (secrets.length > 0) encoded = await sign(encoded, secrets[0]);
3120 return encoded;
3121}
3122async function decodeCookieValue(value, secrets) {
3123 if (secrets.length > 0) {
3124 for (let secret of secrets) {
3125 let unsignedValue = await unsign(value, secret);
3126 if (unsignedValue !== false) return decodeData(unsignedValue);
3127 }
3128 return null;
3129 }
3130 return decodeData(value);
3131}
3132function encodeData(value) {
3133 return btoa(myUnescape(encodeURIComponent(JSON.stringify(value))));
3134}
3135function decodeData(value) {
3136 try {
3137 return JSON.parse(decodeURIComponent(myEscape(atob(value))));
3138 } catch {
3139 return {};
3140 }
3141}
3142function myEscape(value) {
3143 let str = value.toString();
3144 let result = "";
3145 let index = 0;
3146 let chr, code;
3147 while (index < str.length) {
3148 chr = str.charAt(index++);
3149 if (/[\w*+\-./@]/.exec(chr)) result += chr;
3150 else {
3151 code = chr.charCodeAt(0);
3152 if (code < 256) result += "%" + hex(code, 2);
3153 else result += "%u" + hex(code, 4).toUpperCase();
3154 }
3155 }
3156 return result;
3157}
3158function hex(code, length) {
3159 let result = code.toString(16);
3160 while (result.length < length) result = "0" + result;
3161 return result;
3162}
3163function myUnescape(value) {
3164 let str = value.toString();
3165 let result = "";
3166 let index = 0;
3167 let chr, part;
3168 while (index < str.length) {
3169 chr = str.charAt(index++);
3170 if (chr === "%") if (str.charAt(index) === "u") {
3171 part = str.slice(index + 1, index + 5);
3172 if (/^[\da-f]{4}$/i.exec(part)) {
3173 result += String.fromCharCode(parseInt(part, 16));
3174 index += 5;
3175 continue;
3176 }
3177 } else {
3178 part = str.slice(index, index + 2);
3179 if (/^[\da-f]{2}$/i.exec(part)) {
3180 result += String.fromCharCode(parseInt(part, 16));
3181 index += 2;
3182 continue;
3183 }
3184 }
3185 result += chr;
3186 }
3187 return result;
3188}
3189function warnOnceAboutExpiresCookie(name, expires) {
3190 warnOnce(!expires, `The "${name}" cookie has an "expires" property set. This will cause the expires value to not be updated when the session is committed. Instead, you should set the expires value when serializing the cookie. You can use \`commitSession(session, { expires })\` if using a session storage object, or \`cookie.serialize("value", { expires })\` if you're using the cookie directly.`);
3191}
3192//#endregion
3193//#region lib/server-runtime/sessions.ts
3194function flash(name) {
3195 return `__flash_${name}__`;
3196}
3197/**
3198* Creates a new Session object.
3199*
3200* Note: This function is typically not invoked directly by application code.
3201* Instead, use a `SessionStorage` object's `getSession` method.
3202*
3203* @category Utils
3204* @param initialData The initial data for the session.
3205* @param id The identifier for the session. Defaults to an empty string for a
3206* new session.
3207* @returns A new {@link Session} object.
3208*/
3209const createSession = (initialData = {}, id = "") => {
3210 let map = new Map(Object.entries(initialData));
3211 return {
3212 get id() {
3213 return id;
3214 },
3215 get data() {
3216 return Object.fromEntries(map);
3217 },
3218 has(name) {
3219 return map.has(name) || map.has(flash(name));
3220 },
3221 get(name) {
3222 if (map.has(name)) return map.get(name);
3223 let flashName = flash(name);
3224 if (map.has(flashName)) {
3225 let value = map.get(flashName);
3226 map.delete(flashName);
3227 return value;
3228 }
3229 },
3230 set(name, value) {
3231 map.set(name, value);
3232 },
3233 flash(name, value) {
3234 map.set(flash(name), value);
3235 },
3236 unset(name) {
3237 map.delete(name);
3238 }
3239 };
3240};
3241/**
3242* Returns `true` if a value is a React Router {@link Session} object.
3243*
3244* @public
3245* @category Utils
3246* @mode framework
3247* @mode data
3248* @param object The value to check.
3249* @returns `true` if the value is a React Router {@link Session} object;
3250* otherwise, `false`.
3251*/
3252const isSession = (object) => {
3253 return object != null && typeof object.id === "string" && typeof object.data !== "undefined" && typeof object.has === "function" && typeof object.get === "function" && typeof object.set === "function" && typeof object.flash === "function" && typeof object.unset === "function";
3254};
3255/**
3256* Creates a SessionStorage object using a SessionIdStorageStrategy.
3257*
3258* Note: This is a low-level API that should only be used if none of the
3259* existing session storage options meet your requirements.
3260*
3261* @category Utils
3262* @param strategy The strategy used to store session identifiers and data.
3263* @returns A {@link SessionStorage} object that persists session data using the
3264* provided strategy.
3265*/
3266function createSessionStorage({ cookie: cookieArg, createData, readData, updateData, deleteData }) {
3267 let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
3268 warnOnceAboutSigningSessionCookie(cookie);
3269 return {
3270 async getSession(cookieHeader, options) {
3271 let id = cookieHeader && await cookie.parse(cookieHeader, options);
3272 return createSession(id && await readData(id) || {}, id || "");
3273 },
3274 async commitSession(session, options) {
3275 let { id, data } = session;
3276 let expires = options?.maxAge != null ? new Date(Date.now() + options.maxAge * 1e3) : options?.expires != null ? options.expires : cookie.expires;
3277 if (id) await updateData(id, data, expires);
3278 else id = await createData(data, expires);
3279 return cookie.serialize(id, options);
3280 },
3281 async destroySession(session, options) {
3282 if (session.id) await deleteData(session.id);
3283 return cookie.serialize("", {
3284 ...options,
3285 maxAge: void 0,
3286 expires: /* @__PURE__ */ new Date(0)
3287 });
3288 }
3289 };
3290}
3291function warnOnceAboutSigningSessionCookie(cookie) {
3292 warnOnce(cookie.isSigned, `The "${cookie.name}" cookie is not signed, but session cookies should be signed to prevent tampering on the client before they are sent back to the server. See https://reactrouter.com/explanation/sessions-and-cookies#signing-cookies for more information.`);
3293}
3294//#endregion
3295//#region lib/server-runtime/sessions/cookieStorage.ts
3296/**
3297* Creates and returns a SessionStorage object that stores all session data
3298* directly in the session cookie itself.
3299*
3300* This has the advantage that no database or other backend services are
3301* needed, and can help to simplify some load-balanced scenarios. However, it
3302* also has the limitation that serialized session data may not exceed the
3303* browser's maximum cookie size. Trade-offs!
3304*
3305* @public
3306* @category Utils
3307* @mode framework
3308* @mode data
3309* @param options Options for creating the cookie-backed session storage.
3310* @returns A {@link SessionStorage} object that stores all session data in its
3311* cookie.
3312*/
3313function createCookieSessionStorage({ cookie: cookieArg } = {}) {
3314 let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
3315 warnOnceAboutSigningSessionCookie(cookie);
3316 return {
3317 async getSession(cookieHeader, options) {
3318 return createSession(cookieHeader && await cookie.parse(cookieHeader, options) || {});
3319 },
3320 async commitSession(session, options) {
3321 let serializedCookie = await cookie.serialize(session.data, options);
3322 if (serializedCookie.length > 4096) throw new Error("Cookie length will exceed browser maximum. Length: " + serializedCookie.length);
3323 return serializedCookie;
3324 },
3325 async destroySession(_session, options) {
3326 return cookie.serialize("", {
3327 ...options,
3328 maxAge: void 0,
3329 expires: /* @__PURE__ */ new Date(0)
3330 });
3331 }
3332 };
3333}
3334//#endregion
3335//#region lib/server-runtime/sessions/memoryStorage.ts
3336/**
3337* Creates and returns a simple in-memory SessionStorage object.
3338*
3339* Intended for local development and testing. It does not scale beyond a single
3340* process, and all session data is lost when the server process stops/restarts.
3341*
3342* @public
3343* @category Utils
3344* @mode framework
3345* @mode data
3346* @param options Options for creating the in-memory session storage.
3347* @returns A {@link SessionStorage} object that stores session data in memory.
3348*/
3349function createMemorySessionStorage({ cookie } = {}) {
3350 let map = /* @__PURE__ */ new Map();
3351 return createSessionStorage({
3352 cookie,
3353 async createData(data, expires) {
3354 let id = crypto.randomUUID();
3355 map.set(id, {
3356 data,
3357 expires
3358 });
3359 return id;
3360 },
3361 async readData(id) {
3362 if (map.has(id)) {
3363 let { data, expires } = map.get(id);
3364 if (!expires || expires > /* @__PURE__ */ new Date()) return data;
3365 if (expires) map.delete(id);
3366 }
3367 return null;
3368 },
3369 async updateData(id, data, expires) {
3370 map.set(id, {
3371 data,
3372 expires
3373 });
3374 },
3375 async deleteData(id) {
3376 map.delete(id);
3377 }
3378 });
3379}
3380//#endregion
3381export { Await, BrowserRouter, Form, HashRouter, Link, Links, MemoryRouter, Meta, NavLink, Navigate, Outlet, Route, Router, RouterContextProvider, RouterProvider, Routes, ScrollRestoration, StaticRouter, StaticRouterProvider, createContext, createCookie, createCookieSessionStorage, createMemorySessionStorage, createSession, createSessionStorage, createStaticHandler, data, href, isCookie, isRouteErrorResponse, isSession, matchRoutes, redirect, redirectDocument, replace, unstable_HistoryRouter, getRequest as unstable_getRequest, matchRSCServerRequest as unstable_matchRSCServerRequest };