INDIE UNPKG

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