UNPKG

340 kBJavaScriptView Raw
1/**
2 * react-router v7.4.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 */
11"use strict";
12var __create = Object.create;
13var __defProp = Object.defineProperty;
14var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
15var __getOwnPropNames = Object.getOwnPropertyNames;
16var __getProtoOf = Object.getPrototypeOf;
17var __hasOwnProp = Object.prototype.hasOwnProperty;
18var __typeError = (msg) => {
19 throw TypeError(msg);
20};
21var __export = (target, all) => {
22 for (var name in all)
23 __defProp(target, name, { get: all[name], enumerable: true });
24};
25var __copyProps = (to, from, except, desc) => {
26 if (from && typeof from === "object" || typeof from === "function") {
27 for (let key of __getOwnPropNames(from))
28 if (!__hasOwnProp.call(to, key) && key !== except)
29 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
30 }
31 return to;
32};
33var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
34 // If the importer is in node compatibility mode or this is not an ESM
35 // file that has been converted to a CommonJS file using a Babel-
36 // compatible transform (i.e. "__esModule" has not been set), then set
37 // "default" to the CommonJS "module.exports" for node compatibility.
38 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
39 mod
40));
41var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
42var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
43var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
44var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
45
46// index.ts
47var react_router_exports = {};
48__export(react_router_exports, {
49 Await: () => Await,
50 BrowserRouter: () => BrowserRouter,
51 Form: () => Form,
52 HashRouter: () => HashRouter,
53 IDLE_BLOCKER: () => IDLE_BLOCKER,
54 IDLE_FETCHER: () => IDLE_FETCHER,
55 IDLE_NAVIGATION: () => IDLE_NAVIGATION,
56 Link: () => Link,
57 Links: () => Links,
58 MemoryRouter: () => MemoryRouter,
59 Meta: () => Meta,
60 NavLink: () => NavLink,
61 Navigate: () => Navigate,
62 NavigationType: () => Action,
63 Outlet: () => Outlet,
64 PrefetchPageLinks: () => PrefetchPageLinks,
65 Route: () => Route,
66 Router: () => Router,
67 RouterProvider: () => RouterProvider,
68 Routes: () => Routes,
69 Scripts: () => Scripts,
70 ScrollRestoration: () => ScrollRestoration,
71 ServerRouter: () => ServerRouter,
72 StaticRouter: () => StaticRouter,
73 StaticRouterProvider: () => StaticRouterProvider,
74 UNSAFE_DataRouterContext: () => DataRouterContext,
75 UNSAFE_DataRouterStateContext: () => DataRouterStateContext,
76 UNSAFE_ErrorResponseImpl: () => ErrorResponseImpl,
77 UNSAFE_FetchersContext: () => FetchersContext,
78 UNSAFE_FrameworkContext: () => FrameworkContext,
79 UNSAFE_LocationContext: () => LocationContext,
80 UNSAFE_NavigationContext: () => NavigationContext,
81 UNSAFE_RemixErrorBoundary: () => RemixErrorBoundary,
82 UNSAFE_RouteContext: () => RouteContext,
83 UNSAFE_ServerMode: () => ServerMode,
84 UNSAFE_SingleFetchRedirectSymbol: () => SingleFetchRedirectSymbol,
85 UNSAFE_ViewTransitionContext: () => ViewTransitionContext,
86 UNSAFE_createBrowserHistory: () => createBrowserHistory,
87 UNSAFE_createClientRoutes: () => createClientRoutes,
88 UNSAFE_createClientRoutesWithHMRRevalidationOptOut: () => createClientRoutesWithHMRRevalidationOptOut,
89 UNSAFE_createRouter: () => createRouter,
90 UNSAFE_decodeViaTurboStream: () => decodeViaTurboStream,
91 UNSAFE_deserializeErrors: () => deserializeErrors2,
92 UNSAFE_getPatchRoutesOnNavigationFunction: () => getPatchRoutesOnNavigationFunction,
93 UNSAFE_getSingleFetchDataStrategy: () => getSingleFetchDataStrategy,
94 UNSAFE_invariant: () => invariant,
95 UNSAFE_mapRouteProperties: () => mapRouteProperties,
96 UNSAFE_shouldHydrateRouteLoader: () => shouldHydrateRouteLoader,
97 UNSAFE_useFogOFWarDiscovery: () => useFogOFWarDiscovery,
98 UNSAFE_useScrollRestoration: () => useScrollRestoration,
99 createBrowserRouter: () => createBrowserRouter,
100 createCookie: () => createCookie,
101 createCookieSessionStorage: () => createCookieSessionStorage,
102 createHashRouter: () => createHashRouter,
103 createMemoryRouter: () => createMemoryRouter,
104 createMemorySessionStorage: () => createMemorySessionStorage,
105 createPath: () => createPath,
106 createRequestHandler: () => createRequestHandler,
107 createRoutesFromChildren: () => createRoutesFromChildren,
108 createRoutesFromElements: () => createRoutesFromElements,
109 createRoutesStub: () => createRoutesStub,
110 createSearchParams: () => createSearchParams,
111 createSession: () => createSession,
112 createSessionStorage: () => createSessionStorage,
113 createStaticHandler: () => createStaticHandler2,
114 createStaticRouter: () => createStaticRouter,
115 data: () => data,
116 generatePath: () => generatePath,
117 href: () => href,
118 isCookie: () => isCookie,
119 isRouteErrorResponse: () => isRouteErrorResponse,
120 isSession: () => isSession,
121 matchPath: () => matchPath,
122 matchRoutes: () => matchRoutes,
123 parsePath: () => parsePath,
124 redirect: () => redirect,
125 redirectDocument: () => redirectDocument,
126 renderMatches: () => renderMatches,
127 replace: () => replace,
128 resolvePath: () => resolvePath,
129 unstable_HistoryRouter: () => HistoryRouter,
130 unstable_RouterContextProvider: () => unstable_RouterContextProvider,
131 unstable_createContext: () => unstable_createContext,
132 unstable_setDevServerHooks: () => setDevServerHooks,
133 unstable_usePrompt: () => usePrompt,
134 useActionData: () => useActionData,
135 useAsyncError: () => useAsyncError,
136 useAsyncValue: () => useAsyncValue,
137 useBeforeUnload: () => useBeforeUnload,
138 useBlocker: () => useBlocker,
139 useFetcher: () => useFetcher,
140 useFetchers: () => useFetchers,
141 useFormAction: () => useFormAction,
142 useHref: () => useHref,
143 useInRouterContext: () => useInRouterContext,
144 useLinkClickHandler: () => useLinkClickHandler,
145 useLoaderData: () => useLoaderData,
146 useLocation: () => useLocation,
147 useMatch: () => useMatch,
148 useMatches: () => useMatches,
149 useNavigate: () => useNavigate,
150 useNavigation: () => useNavigation,
151 useNavigationType: () => useNavigationType,
152 useOutlet: () => useOutlet,
153 useOutletContext: () => useOutletContext,
154 useParams: () => useParams,
155 useResolvedPath: () => useResolvedPath,
156 useRevalidator: () => useRevalidator,
157 useRouteError: () => useRouteError,
158 useRouteLoaderData: () => useRouteLoaderData,
159 useRoutes: () => useRoutes,
160 useSearchParams: () => useSearchParams,
161 useSubmit: () => useSubmit,
162 useViewTransitionState: () => useViewTransitionState
163});
164module.exports = __toCommonJS(react_router_exports);
165
166// lib/router/history.ts
167var Action = /* @__PURE__ */ ((Action2) => {
168 Action2["Pop"] = "POP";
169 Action2["Push"] = "PUSH";
170 Action2["Replace"] = "REPLACE";
171 return Action2;
172})(Action || {});
173var PopStateEventType = "popstate";
174function createMemoryHistory(options = {}) {
175 let { initialEntries = ["/"], initialIndex, v5Compat = false } = options;
176 let entries;
177 entries = initialEntries.map(
178 (entry, index2) => createMemoryLocation(
179 entry,
180 typeof entry === "string" ? null : entry.state,
181 index2 === 0 ? "default" : void 0
182 )
183 );
184 let index = clampIndex(
185 initialIndex == null ? entries.length - 1 : initialIndex
186 );
187 let action = "POP" /* Pop */;
188 let listener = null;
189 function clampIndex(n) {
190 return Math.min(Math.max(n, 0), entries.length - 1);
191 }
192 function getCurrentLocation() {
193 return entries[index];
194 }
195 function createMemoryLocation(to, state = null, key) {
196 let location = createLocation(
197 entries ? getCurrentLocation().pathname : "/",
198 to,
199 state,
200 key
201 );
202 warning(
203 location.pathname.charAt(0) === "/",
204 `relative pathnames are not supported in memory history: ${JSON.stringify(
205 to
206 )}`
207 );
208 return location;
209 }
210 function createHref2(to) {
211 return typeof to === "string" ? to : createPath(to);
212 }
213 let history = {
214 get index() {
215 return index;
216 },
217 get action() {
218 return action;
219 },
220 get location() {
221 return getCurrentLocation();
222 },
223 createHref: createHref2,
224 createURL(to) {
225 return new URL(createHref2(to), "http://localhost");
226 },
227 encodeLocation(to) {
228 let path = typeof to === "string" ? parsePath(to) : to;
229 return {
230 pathname: path.pathname || "",
231 search: path.search || "",
232 hash: path.hash || ""
233 };
234 },
235 push(to, state) {
236 action = "PUSH" /* Push */;
237 let nextLocation = createMemoryLocation(to, state);
238 index += 1;
239 entries.splice(index, entries.length, nextLocation);
240 if (v5Compat && listener) {
241 listener({ action, location: nextLocation, delta: 1 });
242 }
243 },
244 replace(to, state) {
245 action = "REPLACE" /* Replace */;
246 let nextLocation = createMemoryLocation(to, state);
247 entries[index] = nextLocation;
248 if (v5Compat && listener) {
249 listener({ action, location: nextLocation, delta: 0 });
250 }
251 },
252 go(delta) {
253 action = "POP" /* Pop */;
254 let nextIndex = clampIndex(index + delta);
255 let nextLocation = entries[nextIndex];
256 index = nextIndex;
257 if (listener) {
258 listener({ action, location: nextLocation, delta });
259 }
260 },
261 listen(fn) {
262 listener = fn;
263 return () => {
264 listener = null;
265 };
266 }
267 };
268 return history;
269}
270function createBrowserHistory(options = {}) {
271 function createBrowserLocation(window2, globalHistory) {
272 let { pathname, search, hash } = window2.location;
273 return createLocation(
274 "",
275 { pathname, search, hash },
276 // state defaults to `null` because `window.history.state` does
277 globalHistory.state && globalHistory.state.usr || null,
278 globalHistory.state && globalHistory.state.key || "default"
279 );
280 }
281 function createBrowserHref(window2, to) {
282 return typeof to === "string" ? to : createPath(to);
283 }
284 return getUrlBasedHistory(
285 createBrowserLocation,
286 createBrowserHref,
287 null,
288 options
289 );
290}
291function createHashHistory(options = {}) {
292 function createHashLocation(window2, globalHistory) {
293 let {
294 pathname = "/",
295 search = "",
296 hash = ""
297 } = parsePath(window2.location.hash.substring(1));
298 if (!pathname.startsWith("/") && !pathname.startsWith(".")) {
299 pathname = "/" + pathname;
300 }
301 return createLocation(
302 "",
303 { pathname, search, hash },
304 // state defaults to `null` because `window.history.state` does
305 globalHistory.state && globalHistory.state.usr || null,
306 globalHistory.state && globalHistory.state.key || "default"
307 );
308 }
309 function createHashHref(window2, to) {
310 let base = window2.document.querySelector("base");
311 let href2 = "";
312 if (base && base.getAttribute("href")) {
313 let url = window2.location.href;
314 let hashIndex = url.indexOf("#");
315 href2 = hashIndex === -1 ? url : url.slice(0, hashIndex);
316 }
317 return href2 + "#" + (typeof to === "string" ? to : createPath(to));
318 }
319 function validateHashLocation(location, to) {
320 warning(
321 location.pathname.charAt(0) === "/",
322 `relative pathnames are not supported in hash history.push(${JSON.stringify(
323 to
324 )})`
325 );
326 }
327 return getUrlBasedHistory(
328 createHashLocation,
329 createHashHref,
330 validateHashLocation,
331 options
332 );
333}
334function invariant(value, message) {
335 if (value === false || value === null || typeof value === "undefined") {
336 throw new Error(message);
337 }
338}
339function warning(cond, message) {
340 if (!cond) {
341 if (typeof console !== "undefined") console.warn(message);
342 try {
343 throw new Error(message);
344 } catch (e) {
345 }
346 }
347}
348function createKey() {
349 return Math.random().toString(36).substring(2, 10);
350}
351function getHistoryState(location, index) {
352 return {
353 usr: location.state,
354 key: location.key,
355 idx: index
356 };
357}
358function createLocation(current, to, state = null, key) {
359 let location = {
360 pathname: typeof current === "string" ? current : current.pathname,
361 search: "",
362 hash: "",
363 ...typeof to === "string" ? parsePath(to) : to,
364 state,
365 // TODO: This could be cleaned up. push/replace should probably just take
366 // full Locations now and avoid the need to run through this flow at all
367 // But that's a pretty big refactor to the current test suite so going to
368 // keep as is for the time being and just let any incoming keys take precedence
369 key: to && to.key || key || createKey()
370 };
371 return location;
372}
373function createPath({
374 pathname = "/",
375 search = "",
376 hash = ""
377}) {
378 if (search && search !== "?")
379 pathname += search.charAt(0) === "?" ? search : "?" + search;
380 if (hash && hash !== "#")
381 pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
382 return pathname;
383}
384function parsePath(path) {
385 let parsedPath = {};
386 if (path) {
387 let hashIndex = path.indexOf("#");
388 if (hashIndex >= 0) {
389 parsedPath.hash = path.substring(hashIndex);
390 path = path.substring(0, hashIndex);
391 }
392 let searchIndex = path.indexOf("?");
393 if (searchIndex >= 0) {
394 parsedPath.search = path.substring(searchIndex);
395 path = path.substring(0, searchIndex);
396 }
397 if (path) {
398 parsedPath.pathname = path;
399 }
400 }
401 return parsedPath;
402}
403function getUrlBasedHistory(getLocation, createHref2, validateLocation, options = {}) {
404 let { window: window2 = document.defaultView, v5Compat = false } = options;
405 let globalHistory = window2.history;
406 let action = "POP" /* Pop */;
407 let listener = null;
408 let index = getIndex();
409 if (index == null) {
410 index = 0;
411 globalHistory.replaceState({ ...globalHistory.state, idx: index }, "");
412 }
413 function getIndex() {
414 let state = globalHistory.state || { idx: null };
415 return state.idx;
416 }
417 function handlePop() {
418 action = "POP" /* Pop */;
419 let nextIndex = getIndex();
420 let delta = nextIndex == null ? null : nextIndex - index;
421 index = nextIndex;
422 if (listener) {
423 listener({ action, location: history.location, delta });
424 }
425 }
426 function push(to, state) {
427 action = "PUSH" /* Push */;
428 let location = createLocation(history.location, to, state);
429 if (validateLocation) validateLocation(location, to);
430 index = getIndex() + 1;
431 let historyState = getHistoryState(location, index);
432 let url = history.createHref(location);
433 try {
434 globalHistory.pushState(historyState, "", url);
435 } catch (error) {
436 if (error instanceof DOMException && error.name === "DataCloneError") {
437 throw error;
438 }
439 window2.location.assign(url);
440 }
441 if (v5Compat && listener) {
442 listener({ action, location: history.location, delta: 1 });
443 }
444 }
445 function replace2(to, state) {
446 action = "REPLACE" /* Replace */;
447 let location = createLocation(history.location, to, state);
448 if (validateLocation) validateLocation(location, to);
449 index = getIndex();
450 let historyState = getHistoryState(location, index);
451 let url = history.createHref(location);
452 globalHistory.replaceState(historyState, "", url);
453 if (v5Compat && listener) {
454 listener({ action, location: history.location, delta: 0 });
455 }
456 }
457 function createURL(to) {
458 let base = window2.location.origin !== "null" ? window2.location.origin : window2.location.href;
459 let href2 = typeof to === "string" ? to : createPath(to);
460 href2 = href2.replace(/ $/, "%20");
461 invariant(
462 base,
463 `No window.location.(origin|href) available to create URL for href: ${href2}`
464 );
465 return new URL(href2, base);
466 }
467 let history = {
468 get action() {
469 return action;
470 },
471 get location() {
472 return getLocation(window2, globalHistory);
473 },
474 listen(fn) {
475 if (listener) {
476 throw new Error("A history only accepts one active listener");
477 }
478 window2.addEventListener(PopStateEventType, handlePop);
479 listener = fn;
480 return () => {
481 window2.removeEventListener(PopStateEventType, handlePop);
482 listener = null;
483 };
484 },
485 createHref(to) {
486 return createHref2(window2, to);
487 },
488 createURL,
489 encodeLocation(to) {
490 let url = createURL(to);
491 return {
492 pathname: url.pathname,
493 search: url.search,
494 hash: url.hash
495 };
496 },
497 push,
498 replace: replace2,
499 go(n) {
500 return globalHistory.go(n);
501 }
502 };
503 return history;
504}
505
506// lib/router/utils.ts
507function unstable_createContext(defaultValue) {
508 return { defaultValue };
509}
510var _map;
511var unstable_RouterContextProvider = class {
512 constructor(init) {
513 __privateAdd(this, _map, /* @__PURE__ */ new Map());
514 if (init) {
515 for (let [context, value] of init) {
516 this.set(context, value);
517 }
518 }
519 }
520 get(context) {
521 if (__privateGet(this, _map).has(context)) {
522 return __privateGet(this, _map).get(context);
523 }
524 if (context.defaultValue !== void 0) {
525 return context.defaultValue;
526 }
527 throw new Error("No value found for context");
528 }
529 set(context, value) {
530 __privateGet(this, _map).set(context, value);
531 }
532};
533_map = new WeakMap();
534var immutableRouteKeys = /* @__PURE__ */ new Set([
535 "lazy",
536 "caseSensitive",
537 "path",
538 "id",
539 "index",
540 "children"
541]);
542function isIndexRoute(route) {
543 return route.index === true;
544}
545function convertRoutesToDataRoutes(routes, mapRouteProperties2, parentPath = [], manifest = {}) {
546 return routes.map((route, index) => {
547 let treePath = [...parentPath, String(index)];
548 let id = typeof route.id === "string" ? route.id : treePath.join("-");
549 invariant(
550 route.index !== true || !route.children,
551 `Cannot specify children on an index route`
552 );
553 invariant(
554 !manifest[id],
555 `Found a route id collision on id "${id}". Route id's must be globally unique within Data Router usages`
556 );
557 if (isIndexRoute(route)) {
558 let indexRoute = {
559 ...route,
560 ...mapRouteProperties2(route),
561 id
562 };
563 manifest[id] = indexRoute;
564 return indexRoute;
565 } else {
566 let pathOrLayoutRoute = {
567 ...route,
568 ...mapRouteProperties2(route),
569 id,
570 children: void 0
571 };
572 manifest[id] = pathOrLayoutRoute;
573 if (route.children) {
574 pathOrLayoutRoute.children = convertRoutesToDataRoutes(
575 route.children,
576 mapRouteProperties2,
577 treePath,
578 manifest
579 );
580 }
581 return pathOrLayoutRoute;
582 }
583 });
584}
585function matchRoutes(routes, locationArg, basename = "/") {
586 return matchRoutesImpl(routes, locationArg, basename, false);
587}
588function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
589 let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
590 let pathname = stripBasename(location.pathname || "/", basename);
591 if (pathname == null) {
592 return null;
593 }
594 let branches = flattenRoutes(routes);
595 rankRouteBranches(branches);
596 let matches = null;
597 for (let i = 0; matches == null && i < branches.length; ++i) {
598 let decoded = decodePath(pathname);
599 matches = matchRouteBranch(
600 branches[i],
601 decoded,
602 allowPartial
603 );
604 }
605 return matches;
606}
607function convertRouteMatchToUiMatch(match, loaderData) {
608 let { route, pathname, params } = match;
609 return {
610 id: route.id,
611 pathname,
612 params,
613 data: loaderData[route.id],
614 handle: route.handle
615 };
616}
617function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "") {
618 let flattenRoute = (route, index, relativePath) => {
619 let meta = {
620 relativePath: relativePath === void 0 ? route.path || "" : relativePath,
621 caseSensitive: route.caseSensitive === true,
622 childrenIndex: index,
623 route
624 };
625 if (meta.relativePath.startsWith("/")) {
626 invariant(
627 meta.relativePath.startsWith(parentPath),
628 `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.`
629 );
630 meta.relativePath = meta.relativePath.slice(parentPath.length);
631 }
632 let path = joinPaths([parentPath, meta.relativePath]);
633 let routesMeta = parentsMeta.concat(meta);
634 if (route.children && route.children.length > 0) {
635 invariant(
636 // Our types know better, but runtime JS may not!
637 // @ts-expect-error
638 route.index !== true,
639 `Index routes must not have child routes. Please remove all child routes from route path "${path}".`
640 );
641 flattenRoutes(route.children, branches, routesMeta, path);
642 }
643 if (route.path == null && !route.index) {
644 return;
645 }
646 branches.push({
647 path,
648 score: computeScore(path, route.index),
649 routesMeta
650 });
651 };
652 routes.forEach((route, index) => {
653 if (route.path === "" || !route.path?.includes("?")) {
654 flattenRoute(route, index);
655 } else {
656 for (let exploded of explodeOptionalSegments(route.path)) {
657 flattenRoute(route, index, exploded);
658 }
659 }
660 });
661 return branches;
662}
663function explodeOptionalSegments(path) {
664 let segments = path.split("/");
665 if (segments.length === 0) return [];
666 let [first, ...rest] = segments;
667 let isOptional = first.endsWith("?");
668 let required = first.replace(/\?$/, "");
669 if (rest.length === 0) {
670 return isOptional ? [required, ""] : [required];
671 }
672 let restExploded = explodeOptionalSegments(rest.join("/"));
673 let result = [];
674 result.push(
675 ...restExploded.map(
676 (subpath) => subpath === "" ? required : [required, subpath].join("/")
677 )
678 );
679 if (isOptional) {
680 result.push(...restExploded);
681 }
682 return result.map(
683 (exploded) => path.startsWith("/") && exploded === "" ? "/" : exploded
684 );
685}
686function rankRouteBranches(branches) {
687 branches.sort(
688 (a, b) => a.score !== b.score ? b.score - a.score : compareIndexes(
689 a.routesMeta.map((meta) => meta.childrenIndex),
690 b.routesMeta.map((meta) => meta.childrenIndex)
691 )
692 );
693}
694var paramRe = /^:[\w-]+$/;
695var dynamicSegmentValue = 3;
696var indexRouteValue = 2;
697var emptySegmentValue = 1;
698var staticSegmentValue = 10;
699var splatPenalty = -2;
700var isSplat = (s) => s === "*";
701function computeScore(path, index) {
702 let segments = path.split("/");
703 let initialScore = segments.length;
704 if (segments.some(isSplat)) {
705 initialScore += splatPenalty;
706 }
707 if (index) {
708 initialScore += indexRouteValue;
709 }
710 return segments.filter((s) => !isSplat(s)).reduce(
711 (score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue),
712 initialScore
713 );
714}
715function compareIndexes(a, b) {
716 let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
717 return siblings ? (
718 // If two routes are siblings, we should try to match the earlier sibling
719 // first. This allows people to have fine-grained control over the matching
720 // behavior by simply putting routes with identical paths in the order they
721 // want them tried.
722 a[a.length - 1] - b[b.length - 1]
723 ) : (
724 // Otherwise, it doesn't really make sense to rank non-siblings by index,
725 // so they sort equally.
726 0
727 );
728}
729function matchRouteBranch(branch, pathname, allowPartial = false) {
730 let { routesMeta } = branch;
731 let matchedParams = {};
732 let matchedPathname = "/";
733 let matches = [];
734 for (let i = 0; i < routesMeta.length; ++i) {
735 let meta = routesMeta[i];
736 let end = i === routesMeta.length - 1;
737 let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
738 let match = matchPath(
739 { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },
740 remainingPathname
741 );
742 let route = meta.route;
743 if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) {
744 match = matchPath(
745 {
746 path: meta.relativePath,
747 caseSensitive: meta.caseSensitive,
748 end: false
749 },
750 remainingPathname
751 );
752 }
753 if (!match) {
754 return null;
755 }
756 Object.assign(matchedParams, match.params);
757 matches.push({
758 // TODO: Can this as be avoided?
759 params: matchedParams,
760 pathname: joinPaths([matchedPathname, match.pathname]),
761 pathnameBase: normalizePathname(
762 joinPaths([matchedPathname, match.pathnameBase])
763 ),
764 route
765 });
766 if (match.pathnameBase !== "/") {
767 matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
768 }
769 }
770 return matches;
771}
772function generatePath(originalPath, params = {}) {
773 let path = originalPath;
774 if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) {
775 warning(
776 false,
777 `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(/\*$/, "/*")}".`
778 );
779 path = path.replace(/\*$/, "/*");
780 }
781 const prefix = path.startsWith("/") ? "/" : "";
782 const stringify = (p) => p == null ? "" : typeof p === "string" ? p : String(p);
783 const segments = path.split(/\/+/).map((segment, index, array) => {
784 const isLastSegment = index === array.length - 1;
785 if (isLastSegment && segment === "*") {
786 const star = "*";
787 return stringify(params[star]);
788 }
789 const keyMatch = segment.match(/^:([\w-]+)(\??)$/);
790 if (keyMatch) {
791 const [, key, optional] = keyMatch;
792 let param = params[key];
793 invariant(optional === "?" || param != null, `Missing ":${key}" param`);
794 return stringify(param);
795 }
796 return segment.replace(/\?$/g, "");
797 }).filter((segment) => !!segment);
798 return prefix + segments.join("/");
799}
800function matchPath(pattern, pathname) {
801 if (typeof pattern === "string") {
802 pattern = { path: pattern, caseSensitive: false, end: true };
803 }
804 let [matcher, compiledParams] = compilePath(
805 pattern.path,
806 pattern.caseSensitive,
807 pattern.end
808 );
809 let match = pathname.match(matcher);
810 if (!match) return null;
811 let matchedPathname = match[0];
812 let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
813 let captureGroups = match.slice(1);
814 let params = compiledParams.reduce(
815 (memo2, { paramName, isOptional }, index) => {
816 if (paramName === "*") {
817 let splatValue = captureGroups[index] || "";
818 pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
819 }
820 const value = captureGroups[index];
821 if (isOptional && !value) {
822 memo2[paramName] = void 0;
823 } else {
824 memo2[paramName] = (value || "").replace(/%2F/g, "/");
825 }
826 return memo2;
827 },
828 {}
829 );
830 return {
831 params,
832 pathname: matchedPathname,
833 pathnameBase,
834 pattern
835 };
836}
837function compilePath(path, caseSensitive = false, end = true) {
838 warning(
839 path === "*" || !path.endsWith("*") || path.endsWith("/*"),
840 `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(/\*$/, "/*")}".`
841 );
842 let params = [];
843 let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(
844 /\/:([\w-]+)(\?)?/g,
845 (_, paramName, isOptional) => {
846 params.push({ paramName, isOptional: isOptional != null });
847 return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
848 }
849 );
850 if (path.endsWith("*")) {
851 params.push({ paramName: "*" });
852 regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
853 } else if (end) {
854 regexpSource += "\\/*$";
855 } else if (path !== "" && path !== "/") {
856 regexpSource += "(?:(?=\\/|$))";
857 } else {
858 }
859 let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i");
860 return [matcher, params];
861}
862function decodePath(value) {
863 try {
864 return value.split("/").map((v) => decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
865 } catch (error) {
866 warning(
867 false,
868 `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}).`
869 );
870 return value;
871 }
872}
873function stripBasename(pathname, basename) {
874 if (basename === "/") return pathname;
875 if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
876 return null;
877 }
878 let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
879 let nextChar = pathname.charAt(startIndex);
880 if (nextChar && nextChar !== "/") {
881 return null;
882 }
883 return pathname.slice(startIndex) || "/";
884}
885function resolvePath(to, fromPathname = "/") {
886 let {
887 pathname: toPathname,
888 search = "",
889 hash = ""
890 } = typeof to === "string" ? parsePath(to) : to;
891 let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
892 return {
893 pathname,
894 search: normalizeSearch(search),
895 hash: normalizeHash(hash)
896 };
897}
898function resolvePathname(relativePath, fromPathname) {
899 let segments = fromPathname.replace(/\/+$/, "").split("/");
900 let relativeSegments = relativePath.split("/");
901 relativeSegments.forEach((segment) => {
902 if (segment === "..") {
903 if (segments.length > 1) segments.pop();
904 } else if (segment !== ".") {
905 segments.push(segment);
906 }
907 });
908 return segments.length > 1 ? segments.join("/") : "/";
909}
910function getInvalidPathError(char, field, dest, path) {
911 return `Cannot include a '${char}' character in a manually specified \`to.${field}\` field [${JSON.stringify(
912 path
913 )}]. 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.`;
914}
915function getPathContributingMatches(matches) {
916 return matches.filter(
917 (match, index) => index === 0 || match.route.path && match.route.path.length > 0
918 );
919}
920function getResolveToMatches(matches) {
921 let pathMatches = getPathContributingMatches(matches);
922 return pathMatches.map(
923 (match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase
924 );
925}
926function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) {
927 let to;
928 if (typeof toArg === "string") {
929 to = parsePath(toArg);
930 } else {
931 to = { ...toArg };
932 invariant(
933 !to.pathname || !to.pathname.includes("?"),
934 getInvalidPathError("?", "pathname", "search", to)
935 );
936 invariant(
937 !to.pathname || !to.pathname.includes("#"),
938 getInvalidPathError("#", "pathname", "hash", to)
939 );
940 invariant(
941 !to.search || !to.search.includes("#"),
942 getInvalidPathError("#", "search", "hash", to)
943 );
944 }
945 let isEmptyPath = toArg === "" || to.pathname === "";
946 let toPathname = isEmptyPath ? "/" : to.pathname;
947 let from;
948 if (toPathname == null) {
949 from = locationPathname;
950 } else {
951 let routePathnameIndex = routePathnames.length - 1;
952 if (!isPathRelative && toPathname.startsWith("..")) {
953 let toSegments = toPathname.split("/");
954 while (toSegments[0] === "..") {
955 toSegments.shift();
956 routePathnameIndex -= 1;
957 }
958 to.pathname = toSegments.join("/");
959 }
960 from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
961 }
962 let path = resolvePath(to, from);
963 let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
964 let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
965 if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
966 path.pathname += "/";
967 }
968 return path;
969}
970var joinPaths = (paths) => paths.join("/").replace(/\/\/+/g, "/");
971var normalizePathname = (pathname) => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
972var normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
973var normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
974var DataWithResponseInit = class {
975 constructor(data2, init) {
976 this.type = "DataWithResponseInit";
977 this.data = data2;
978 this.init = init || null;
979 }
980};
981function data(data2, init) {
982 return new DataWithResponseInit(
983 data2,
984 typeof init === "number" ? { status: init } : init
985 );
986}
987var redirect = (url, init = 302) => {
988 let responseInit = init;
989 if (typeof responseInit === "number") {
990 responseInit = { status: responseInit };
991 } else if (typeof responseInit.status === "undefined") {
992 responseInit.status = 302;
993 }
994 let headers = new Headers(responseInit.headers);
995 headers.set("Location", url);
996 return new Response(null, { ...responseInit, headers });
997};
998var redirectDocument = (url, init) => {
999 let response = redirect(url, init);
1000 response.headers.set("X-Remix-Reload-Document", "true");
1001 return response;
1002};
1003var replace = (url, init) => {
1004 let response = redirect(url, init);
1005 response.headers.set("X-Remix-Replace", "true");
1006 return response;
1007};
1008var ErrorResponseImpl = class {
1009 constructor(status, statusText, data2, internal = false) {
1010 this.status = status;
1011 this.statusText = statusText || "";
1012 this.internal = internal;
1013 if (data2 instanceof Error) {
1014 this.data = data2.toString();
1015 this.error = data2;
1016 } else {
1017 this.data = data2;
1018 }
1019 }
1020};
1021function isRouteErrorResponse(error) {
1022 return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
1023}
1024
1025// lib/router/router.ts
1026var validMutationMethodsArr = [
1027 "POST",
1028 "PUT",
1029 "PATCH",
1030 "DELETE"
1031];
1032var validMutationMethods = new Set(
1033 validMutationMethodsArr
1034);
1035var validRequestMethodsArr = [
1036 "GET",
1037 ...validMutationMethodsArr
1038];
1039var validRequestMethods = new Set(validRequestMethodsArr);
1040var redirectStatusCodes = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
1041var redirectPreserveMethodStatusCodes = /* @__PURE__ */ new Set([307, 308]);
1042var IDLE_NAVIGATION = {
1043 state: "idle",
1044 location: void 0,
1045 formMethod: void 0,
1046 formAction: void 0,
1047 formEncType: void 0,
1048 formData: void 0,
1049 json: void 0,
1050 text: void 0
1051};
1052var IDLE_FETCHER = {
1053 state: "idle",
1054 data: void 0,
1055 formMethod: void 0,
1056 formAction: void 0,
1057 formEncType: void 0,
1058 formData: void 0,
1059 json: void 0,
1060 text: void 0
1061};
1062var IDLE_BLOCKER = {
1063 state: "unblocked",
1064 proceed: void 0,
1065 reset: void 0,
1066 location: void 0
1067};
1068var ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
1069var defaultMapRouteProperties = (route) => ({
1070 hasErrorBoundary: Boolean(route.hasErrorBoundary)
1071});
1072var TRANSITIONS_STORAGE_KEY = "remix-router-transitions";
1073var ResetLoaderDataSymbol = Symbol("ResetLoaderData");
1074function createRouter(init) {
1075 const routerWindow = init.window ? init.window : typeof window !== "undefined" ? window : void 0;
1076 const isBrowser2 = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && typeof routerWindow.document.createElement !== "undefined";
1077 invariant(
1078 init.routes.length > 0,
1079 "You must provide a non-empty routes array to createRouter"
1080 );
1081 let mapRouteProperties2 = init.mapRouteProperties || defaultMapRouteProperties;
1082 let manifest = {};
1083 let dataRoutes = convertRoutesToDataRoutes(
1084 init.routes,
1085 mapRouteProperties2,
1086 void 0,
1087 manifest
1088 );
1089 let inFlightDataRoutes;
1090 let basename = init.basename || "/";
1091 let dataStrategyImpl = init.dataStrategy || defaultDataStrategyWithMiddleware;
1092 let future = {
1093 unstable_middleware: false,
1094 ...init.future
1095 };
1096 let unlistenHistory = null;
1097 let subscribers = /* @__PURE__ */ new Set();
1098 let savedScrollPositions2 = null;
1099 let getScrollRestorationKey2 = null;
1100 let getScrollPosition = null;
1101 let initialScrollRestored = init.hydrationData != null;
1102 let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
1103 let initialMatchesIsFOW = false;
1104 let initialErrors = null;
1105 if (initialMatches == null && !init.patchRoutesOnNavigation) {
1106 let error = getInternalRouterError(404, {
1107 pathname: init.history.location.pathname
1108 });
1109 let { matches, route } = getShortCircuitMatches(dataRoutes);
1110 initialMatches = matches;
1111 initialErrors = { [route.id]: error };
1112 }
1113 if (initialMatches && !init.hydrationData) {
1114 let fogOfWar = checkFogOfWar(
1115 initialMatches,
1116 dataRoutes,
1117 init.history.location.pathname
1118 );
1119 if (fogOfWar.active) {
1120 initialMatches = null;
1121 }
1122 }
1123 let initialized;
1124 if (!initialMatches) {
1125 initialized = false;
1126 initialMatches = [];
1127 let fogOfWar = checkFogOfWar(
1128 null,
1129 dataRoutes,
1130 init.history.location.pathname
1131 );
1132 if (fogOfWar.active && fogOfWar.matches) {
1133 initialMatchesIsFOW = true;
1134 initialMatches = fogOfWar.matches;
1135 }
1136 } else if (initialMatches.some((m) => m.route.lazy)) {
1137 initialized = false;
1138 } else if (!initialMatches.some((m) => m.route.loader)) {
1139 initialized = true;
1140 } else {
1141 let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
1142 let errors = init.hydrationData ? init.hydrationData.errors : null;
1143 if (errors) {
1144 let idx = initialMatches.findIndex(
1145 (m) => errors[m.route.id] !== void 0
1146 );
1147 initialized = initialMatches.slice(0, idx + 1).every((m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors));
1148 } else {
1149 initialized = initialMatches.every(
1150 (m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors)
1151 );
1152 }
1153 }
1154 let router;
1155 let state = {
1156 historyAction: init.history.action,
1157 location: init.history.location,
1158 matches: initialMatches,
1159 initialized,
1160 navigation: IDLE_NAVIGATION,
1161 // Don't restore on initial updateState() if we were SSR'd
1162 restoreScrollPosition: init.hydrationData != null ? false : null,
1163 preventScrollReset: false,
1164 revalidation: "idle",
1165 loaderData: init.hydrationData && init.hydrationData.loaderData || {},
1166 actionData: init.hydrationData && init.hydrationData.actionData || null,
1167 errors: init.hydrationData && init.hydrationData.errors || initialErrors,
1168 fetchers: /* @__PURE__ */ new Map(),
1169 blockers: /* @__PURE__ */ new Map()
1170 };
1171 let pendingAction = "POP" /* Pop */;
1172 let pendingPreventScrollReset = false;
1173 let pendingNavigationController;
1174 let pendingViewTransitionEnabled = false;
1175 let appliedViewTransitions = /* @__PURE__ */ new Map();
1176 let removePageHideEventListener = null;
1177 let isUninterruptedRevalidation = false;
1178 let isRevalidationRequired = false;
1179 let cancelledFetcherLoads = /* @__PURE__ */ new Set();
1180 let fetchControllers = /* @__PURE__ */ new Map();
1181 let incrementingLoadId = 0;
1182 let pendingNavigationLoadId = -1;
1183 let fetchReloadIds = /* @__PURE__ */ new Map();
1184 let fetchRedirectIds = /* @__PURE__ */ new Set();
1185 let fetchLoadMatches = /* @__PURE__ */ new Map();
1186 let activeFetchers = /* @__PURE__ */ new Map();
1187 let fetchersQueuedForDeletion = /* @__PURE__ */ new Set();
1188 let blockerFunctions = /* @__PURE__ */ new Map();
1189 let unblockBlockerHistoryUpdate = void 0;
1190 let pendingRevalidationDfd = null;
1191 function initialize() {
1192 unlistenHistory = init.history.listen(
1193 ({ action: historyAction, location, delta }) => {
1194 if (unblockBlockerHistoryUpdate) {
1195 unblockBlockerHistoryUpdate();
1196 unblockBlockerHistoryUpdate = void 0;
1197 return;
1198 }
1199 warning(
1200 blockerFunctions.size === 0 || delta != null,
1201 "You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs. This can also happen if you are using createHashRouter and the user manually changes the URL."
1202 );
1203 let blockerKey = shouldBlockNavigation({
1204 currentLocation: state.location,
1205 nextLocation: location,
1206 historyAction
1207 });
1208 if (blockerKey && delta != null) {
1209 let nextHistoryUpdatePromise = new Promise((resolve) => {
1210 unblockBlockerHistoryUpdate = resolve;
1211 });
1212 init.history.go(delta * -1);
1213 updateBlocker(blockerKey, {
1214 state: "blocked",
1215 location,
1216 proceed() {
1217 updateBlocker(blockerKey, {
1218 state: "proceeding",
1219 proceed: void 0,
1220 reset: void 0,
1221 location
1222 });
1223 nextHistoryUpdatePromise.then(() => init.history.go(delta));
1224 },
1225 reset() {
1226 let blockers = new Map(state.blockers);
1227 blockers.set(blockerKey, IDLE_BLOCKER);
1228 updateState({ blockers });
1229 }
1230 });
1231 return;
1232 }
1233 return startNavigation(historyAction, location);
1234 }
1235 );
1236 if (isBrowser2) {
1237 restoreAppliedTransitions(routerWindow, appliedViewTransitions);
1238 let _saveAppliedTransitions = () => persistAppliedTransitions(routerWindow, appliedViewTransitions);
1239 routerWindow.addEventListener("pagehide", _saveAppliedTransitions);
1240 removePageHideEventListener = () => routerWindow.removeEventListener("pagehide", _saveAppliedTransitions);
1241 }
1242 if (!state.initialized) {
1243 startNavigation("POP" /* Pop */, state.location, {
1244 initialHydration: true
1245 });
1246 }
1247 return router;
1248 }
1249 function dispose() {
1250 if (unlistenHistory) {
1251 unlistenHistory();
1252 }
1253 if (removePageHideEventListener) {
1254 removePageHideEventListener();
1255 }
1256 subscribers.clear();
1257 pendingNavigationController && pendingNavigationController.abort();
1258 state.fetchers.forEach((_, key) => deleteFetcher(key));
1259 state.blockers.forEach((_, key) => deleteBlocker(key));
1260 }
1261 function subscribe(fn) {
1262 subscribers.add(fn);
1263 return () => subscribers.delete(fn);
1264 }
1265 function updateState(newState, opts = {}) {
1266 state = {
1267 ...state,
1268 ...newState
1269 };
1270 let unmountedFetchers = [];
1271 let mountedFetchers = [];
1272 state.fetchers.forEach((fetcher, key) => {
1273 if (fetcher.state === "idle") {
1274 if (fetchersQueuedForDeletion.has(key)) {
1275 unmountedFetchers.push(key);
1276 } else {
1277 mountedFetchers.push(key);
1278 }
1279 }
1280 });
1281 fetchersQueuedForDeletion.forEach((key) => {
1282 if (!state.fetchers.has(key) && !fetchControllers.has(key)) {
1283 unmountedFetchers.push(key);
1284 }
1285 });
1286 [...subscribers].forEach(
1287 (subscriber) => subscriber(state, {
1288 deletedFetchers: unmountedFetchers,
1289 viewTransitionOpts: opts.viewTransitionOpts,
1290 flushSync: opts.flushSync === true
1291 })
1292 );
1293 unmountedFetchers.forEach((key) => deleteFetcher(key));
1294 mountedFetchers.forEach((key) => state.fetchers.delete(key));
1295 }
1296 function completeNavigation(location, newState, { flushSync } = {}) {
1297 let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && location.state?._isRedirect !== true;
1298 let actionData;
1299 if (newState.actionData) {
1300 if (Object.keys(newState.actionData).length > 0) {
1301 actionData = newState.actionData;
1302 } else {
1303 actionData = null;
1304 }
1305 } else if (isActionReload) {
1306 actionData = state.actionData;
1307 } else {
1308 actionData = null;
1309 }
1310 let loaderData = newState.loaderData ? mergeLoaderData(
1311 state.loaderData,
1312 newState.loaderData,
1313 newState.matches || [],
1314 newState.errors
1315 ) : state.loaderData;
1316 let blockers = state.blockers;
1317 if (blockers.size > 0) {
1318 blockers = new Map(blockers);
1319 blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER));
1320 }
1321 let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && location.state?._isRedirect !== true;
1322 if (inFlightDataRoutes) {
1323 dataRoutes = inFlightDataRoutes;
1324 inFlightDataRoutes = void 0;
1325 }
1326 if (isUninterruptedRevalidation) {
1327 } else if (pendingAction === "POP" /* Pop */) {
1328 } else if (pendingAction === "PUSH" /* Push */) {
1329 init.history.push(location, location.state);
1330 } else if (pendingAction === "REPLACE" /* Replace */) {
1331 init.history.replace(location, location.state);
1332 }
1333 let viewTransitionOpts;
1334 if (pendingAction === "POP" /* Pop */) {
1335 let priorPaths = appliedViewTransitions.get(state.location.pathname);
1336 if (priorPaths && priorPaths.has(location.pathname)) {
1337 viewTransitionOpts = {
1338 currentLocation: state.location,
1339 nextLocation: location
1340 };
1341 } else if (appliedViewTransitions.has(location.pathname)) {
1342 viewTransitionOpts = {
1343 currentLocation: location,
1344 nextLocation: state.location
1345 };
1346 }
1347 } else if (pendingViewTransitionEnabled) {
1348 let toPaths = appliedViewTransitions.get(state.location.pathname);
1349 if (toPaths) {
1350 toPaths.add(location.pathname);
1351 } else {
1352 toPaths = /* @__PURE__ */ new Set([location.pathname]);
1353 appliedViewTransitions.set(state.location.pathname, toPaths);
1354 }
1355 viewTransitionOpts = {
1356 currentLocation: state.location,
1357 nextLocation: location
1358 };
1359 }
1360 updateState(
1361 {
1362 ...newState,
1363 // matches, errors, fetchers go through as-is
1364 actionData,
1365 loaderData,
1366 historyAction: pendingAction,
1367 location,
1368 initialized: true,
1369 navigation: IDLE_NAVIGATION,
1370 revalidation: "idle",
1371 restoreScrollPosition: getSavedScrollPosition(
1372 location,
1373 newState.matches || state.matches
1374 ),
1375 preventScrollReset,
1376 blockers
1377 },
1378 {
1379 viewTransitionOpts,
1380 flushSync: flushSync === true
1381 }
1382 );
1383 pendingAction = "POP" /* Pop */;
1384 pendingPreventScrollReset = false;
1385 pendingViewTransitionEnabled = false;
1386 isUninterruptedRevalidation = false;
1387 isRevalidationRequired = false;
1388 pendingRevalidationDfd?.resolve();
1389 pendingRevalidationDfd = null;
1390 }
1391 async function navigate(to, opts) {
1392 if (typeof to === "number") {
1393 init.history.go(to);
1394 return;
1395 }
1396 let normalizedPath = normalizeTo(
1397 state.location,
1398 state.matches,
1399 basename,
1400 to,
1401 opts?.fromRouteId,
1402 opts?.relative
1403 );
1404 let { path, submission, error } = normalizeNavigateOptions(
1405 false,
1406 normalizedPath,
1407 opts
1408 );
1409 let currentLocation = state.location;
1410 let nextLocation = createLocation(state.location, path, opts && opts.state);
1411 nextLocation = {
1412 ...nextLocation,
1413 ...init.history.encodeLocation(nextLocation)
1414 };
1415 let userReplace = opts && opts.replace != null ? opts.replace : void 0;
1416 let historyAction = "PUSH" /* Push */;
1417 if (userReplace === true) {
1418 historyAction = "REPLACE" /* Replace */;
1419 } else if (userReplace === false) {
1420 } else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {
1421 historyAction = "REPLACE" /* Replace */;
1422 }
1423 let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : void 0;
1424 let flushSync = (opts && opts.flushSync) === true;
1425 let blockerKey = shouldBlockNavigation({
1426 currentLocation,
1427 nextLocation,
1428 historyAction
1429 });
1430 if (blockerKey) {
1431 updateBlocker(blockerKey, {
1432 state: "blocked",
1433 location: nextLocation,
1434 proceed() {
1435 updateBlocker(blockerKey, {
1436 state: "proceeding",
1437 proceed: void 0,
1438 reset: void 0,
1439 location: nextLocation
1440 });
1441 navigate(to, opts);
1442 },
1443 reset() {
1444 let blockers = new Map(state.blockers);
1445 blockers.set(blockerKey, IDLE_BLOCKER);
1446 updateState({ blockers });
1447 }
1448 });
1449 return;
1450 }
1451 await startNavigation(historyAction, nextLocation, {
1452 submission,
1453 // Send through the formData serialization error if we have one so we can
1454 // render at the right error boundary after we match routes
1455 pendingError: error,
1456 preventScrollReset,
1457 replace: opts && opts.replace,
1458 enableViewTransition: opts && opts.viewTransition,
1459 flushSync
1460 });
1461 }
1462 function revalidate() {
1463 if (!pendingRevalidationDfd) {
1464 pendingRevalidationDfd = createDeferred();
1465 }
1466 interruptActiveLoads();
1467 updateState({ revalidation: "loading" });
1468 let promise = pendingRevalidationDfd.promise;
1469 if (state.navigation.state === "submitting") {
1470 return promise;
1471 }
1472 if (state.navigation.state === "idle") {
1473 startNavigation(state.historyAction, state.location, {
1474 startUninterruptedRevalidation: true
1475 });
1476 return promise;
1477 }
1478 startNavigation(
1479 pendingAction || state.historyAction,
1480 state.navigation.location,
1481 {
1482 overrideNavigation: state.navigation,
1483 // Proxy through any rending view transition
1484 enableViewTransition: pendingViewTransitionEnabled === true
1485 }
1486 );
1487 return promise;
1488 }
1489 async function startNavigation(historyAction, location, opts) {
1490 pendingNavigationController && pendingNavigationController.abort();
1491 pendingNavigationController = null;
1492 pendingAction = historyAction;
1493 isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true;
1494 saveScrollPosition(state.location, state.matches);
1495 pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
1496 pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
1497 let routesToUse = inFlightDataRoutes || dataRoutes;
1498 let loadingNavigation = opts && opts.overrideNavigation;
1499 let matches = opts?.initialHydration && state.matches && state.matches.length > 0 && !initialMatchesIsFOW ? (
1500 // `matchRoutes()` has already been called if we're in here via `router.initialize()`
1501 state.matches
1502 ) : matchRoutes(routesToUse, location, basename);
1503 let flushSync = (opts && opts.flushSync) === true;
1504 if (matches && state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
1505 completeNavigation(location, { matches }, { flushSync });
1506 return;
1507 }
1508 let fogOfWar = checkFogOfWar(matches, routesToUse, location.pathname);
1509 if (fogOfWar.active && fogOfWar.matches) {
1510 matches = fogOfWar.matches;
1511 }
1512 if (!matches) {
1513 let { error, notFoundMatches, route } = handleNavigational404(
1514 location.pathname
1515 );
1516 completeNavigation(
1517 location,
1518 {
1519 matches: notFoundMatches,
1520 loaderData: {},
1521 errors: {
1522 [route.id]: error
1523 }
1524 },
1525 { flushSync }
1526 );
1527 return;
1528 }
1529 pendingNavigationController = new AbortController();
1530 let request = createClientSideRequest(
1531 init.history,
1532 location,
1533 pendingNavigationController.signal,
1534 opts && opts.submission
1535 );
1536 let scopedContext = new unstable_RouterContextProvider(
1537 init.unstable_getContext ? await init.unstable_getContext() : void 0
1538 );
1539 let pendingActionResult;
1540 if (opts && opts.pendingError) {
1541 pendingActionResult = [
1542 findNearestBoundary(matches).route.id,
1543 { type: "error" /* error */, error: opts.pendingError }
1544 ];
1545 } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
1546 let actionResult = await handleAction(
1547 request,
1548 location,
1549 opts.submission,
1550 matches,
1551 scopedContext,
1552 fogOfWar.active,
1553 { replace: opts.replace, flushSync }
1554 );
1555 if (actionResult.shortCircuited) {
1556 return;
1557 }
1558 if (actionResult.pendingActionResult) {
1559 let [routeId, result] = actionResult.pendingActionResult;
1560 if (isErrorResult(result) && isRouteErrorResponse(result.error) && result.error.status === 404) {
1561 pendingNavigationController = null;
1562 completeNavigation(location, {
1563 matches: actionResult.matches,
1564 loaderData: {},
1565 errors: {
1566 [routeId]: result.error
1567 }
1568 });
1569 return;
1570 }
1571 }
1572 matches = actionResult.matches || matches;
1573 pendingActionResult = actionResult.pendingActionResult;
1574 loadingNavigation = getLoadingNavigation(location, opts.submission);
1575 flushSync = false;
1576 fogOfWar.active = false;
1577 request = createClientSideRequest(
1578 init.history,
1579 request.url,
1580 request.signal
1581 );
1582 }
1583 let {
1584 shortCircuited,
1585 matches: updatedMatches,
1586 loaderData,
1587 errors
1588 } = await handleLoaders(
1589 request,
1590 location,
1591 matches,
1592 scopedContext,
1593 fogOfWar.active,
1594 loadingNavigation,
1595 opts && opts.submission,
1596 opts && opts.fetcherSubmission,
1597 opts && opts.replace,
1598 opts && opts.initialHydration === true,
1599 flushSync,
1600 pendingActionResult
1601 );
1602 if (shortCircuited) {
1603 return;
1604 }
1605 pendingNavigationController = null;
1606 completeNavigation(location, {
1607 matches: updatedMatches || matches,
1608 ...getActionDataForCommit(pendingActionResult),
1609 loaderData,
1610 errors
1611 });
1612 }
1613 async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, opts = {}) {
1614 interruptActiveLoads();
1615 let navigation = getSubmittingNavigation(location, submission);
1616 updateState({ navigation }, { flushSync: opts.flushSync === true });
1617 if (isFogOfWar) {
1618 let discoverResult = await discoverRoutes(
1619 matches,
1620 location.pathname,
1621 request.signal
1622 );
1623 if (discoverResult.type === "aborted") {
1624 return { shortCircuited: true };
1625 } else if (discoverResult.type === "error") {
1626 let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
1627 return {
1628 matches: discoverResult.partialMatches,
1629 pendingActionResult: [
1630 boundaryId,
1631 {
1632 type: "error" /* error */,
1633 error: discoverResult.error
1634 }
1635 ]
1636 };
1637 } else if (!discoverResult.matches) {
1638 let { notFoundMatches, error, route } = handleNavigational404(
1639 location.pathname
1640 );
1641 return {
1642 matches: notFoundMatches,
1643 pendingActionResult: [
1644 route.id,
1645 {
1646 type: "error" /* error */,
1647 error
1648 }
1649 ]
1650 };
1651 } else {
1652 matches = discoverResult.matches;
1653 }
1654 }
1655 let result;
1656 let actionMatch = getTargetMatch(matches, location);
1657 if (!actionMatch.route.action && !actionMatch.route.lazy) {
1658 result = {
1659 type: "error" /* error */,
1660 error: getInternalRouterError(405, {
1661 method: request.method,
1662 pathname: location.pathname,
1663 routeId: actionMatch.route.id
1664 })
1665 };
1666 } else {
1667 let results = await callDataStrategy(
1668 "action",
1669 request,
1670 [actionMatch],
1671 matches,
1672 scopedContext,
1673 null
1674 );
1675 result = results[actionMatch.route.id];
1676 if (!result) {
1677 for (let match of matches) {
1678 if (results[match.route.id]) {
1679 result = results[match.route.id];
1680 break;
1681 }
1682 }
1683 }
1684 if (request.signal.aborted) {
1685 return { shortCircuited: true };
1686 }
1687 }
1688 if (isRedirectResult(result)) {
1689 let replace2;
1690 if (opts && opts.replace != null) {
1691 replace2 = opts.replace;
1692 } else {
1693 let location2 = normalizeRedirectLocation(
1694 result.response.headers.get("Location"),
1695 new URL(request.url),
1696 basename
1697 );
1698 replace2 = location2 === state.location.pathname + state.location.search;
1699 }
1700 await startRedirectNavigation(request, result, true, {
1701 submission,
1702 replace: replace2
1703 });
1704 return { shortCircuited: true };
1705 }
1706 if (isErrorResult(result)) {
1707 let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
1708 if ((opts && opts.replace) !== true) {
1709 pendingAction = "PUSH" /* Push */;
1710 }
1711 return {
1712 matches,
1713 pendingActionResult: [boundaryMatch.route.id, result]
1714 };
1715 }
1716 return {
1717 matches,
1718 pendingActionResult: [actionMatch.route.id, result]
1719 };
1720 }
1721 async function handleLoaders(request, location, matches, scopedContext, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync, pendingActionResult) {
1722 let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
1723 let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
1724 let shouldUpdateNavigationState = !isUninterruptedRevalidation && !initialHydration;
1725 if (isFogOfWar) {
1726 if (shouldUpdateNavigationState) {
1727 let actionData = getUpdatedActionData(pendingActionResult);
1728 updateState(
1729 {
1730 navigation: loadingNavigation,
1731 ...actionData !== void 0 ? { actionData } : {}
1732 },
1733 {
1734 flushSync
1735 }
1736 );
1737 }
1738 let discoverResult = await discoverRoutes(
1739 matches,
1740 location.pathname,
1741 request.signal
1742 );
1743 if (discoverResult.type === "aborted") {
1744 return { shortCircuited: true };
1745 } else if (discoverResult.type === "error") {
1746 let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
1747 return {
1748 matches: discoverResult.partialMatches,
1749 loaderData: {},
1750 errors: {
1751 [boundaryId]: discoverResult.error
1752 }
1753 };
1754 } else if (!discoverResult.matches) {
1755 let { error, notFoundMatches, route } = handleNavigational404(
1756 location.pathname
1757 );
1758 return {
1759 matches: notFoundMatches,
1760 loaderData: {},
1761 errors: {
1762 [route.id]: error
1763 }
1764 };
1765 } else {
1766 matches = discoverResult.matches;
1767 }
1768 }
1769 let routesToUse = inFlightDataRoutes || dataRoutes;
1770 let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(
1771 init.history,
1772 state,
1773 matches,
1774 activeSubmission,
1775 location,
1776 initialHydration === true,
1777 isRevalidationRequired,
1778 cancelledFetcherLoads,
1779 fetchersQueuedForDeletion,
1780 fetchLoadMatches,
1781 fetchRedirectIds,
1782 routesToUse,
1783 basename,
1784 pendingActionResult
1785 );
1786 pendingNavigationLoadId = ++incrementingLoadId;
1787 if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
1788 let updatedFetchers2 = markFetchRedirectsDone();
1789 completeNavigation(
1790 location,
1791 {
1792 matches,
1793 loaderData: {},
1794 // Commit pending error if we're short circuiting
1795 errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { [pendingActionResult[0]]: pendingActionResult[1].error } : null,
1796 ...getActionDataForCommit(pendingActionResult),
1797 ...updatedFetchers2 ? { fetchers: new Map(state.fetchers) } : {}
1798 },
1799 { flushSync }
1800 );
1801 return { shortCircuited: true };
1802 }
1803 if (shouldUpdateNavigationState) {
1804 let updates = {};
1805 if (!isFogOfWar) {
1806 updates.navigation = loadingNavigation;
1807 let actionData = getUpdatedActionData(pendingActionResult);
1808 if (actionData !== void 0) {
1809 updates.actionData = actionData;
1810 }
1811 }
1812 if (revalidatingFetchers.length > 0) {
1813 updates.fetchers = getUpdatedRevalidatingFetchers(revalidatingFetchers);
1814 }
1815 updateState(updates, { flushSync });
1816 }
1817 revalidatingFetchers.forEach((rf) => {
1818 abortFetcher(rf.key);
1819 if (rf.controller) {
1820 fetchControllers.set(rf.key, rf.controller);
1821 }
1822 });
1823 let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((f) => abortFetcher(f.key));
1824 if (pendingNavigationController) {
1825 pendingNavigationController.signal.addEventListener(
1826 "abort",
1827 abortPendingFetchRevalidations
1828 );
1829 }
1830 let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
1831 matches,
1832 matchesToLoad,
1833 revalidatingFetchers,
1834 request,
1835 scopedContext
1836 );
1837 if (request.signal.aborted) {
1838 return { shortCircuited: true };
1839 }
1840 if (pendingNavigationController) {
1841 pendingNavigationController.signal.removeEventListener(
1842 "abort",
1843 abortPendingFetchRevalidations
1844 );
1845 }
1846 revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));
1847 let redirect2 = findRedirect(loaderResults);
1848 if (redirect2) {
1849 await startRedirectNavigation(request, redirect2.result, true, {
1850 replace: replace2
1851 });
1852 return { shortCircuited: true };
1853 }
1854 redirect2 = findRedirect(fetcherResults);
1855 if (redirect2) {
1856 fetchRedirectIds.add(redirect2.key);
1857 await startRedirectNavigation(request, redirect2.result, true, {
1858 replace: replace2
1859 });
1860 return { shortCircuited: true };
1861 }
1862 let { loaderData, errors } = processLoaderData(
1863 state,
1864 matches,
1865 loaderResults,
1866 pendingActionResult,
1867 revalidatingFetchers,
1868 fetcherResults
1869 );
1870 if (initialHydration && state.errors) {
1871 errors = { ...state.errors, ...errors };
1872 }
1873 let updatedFetchers = markFetchRedirectsDone();
1874 let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
1875 let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;
1876 return {
1877 matches,
1878 loaderData,
1879 errors,
1880 ...shouldUpdateFetchers ? { fetchers: new Map(state.fetchers) } : {}
1881 };
1882 }
1883 function getUpdatedActionData(pendingActionResult) {
1884 if (pendingActionResult && !isErrorResult(pendingActionResult[1])) {
1885 return {
1886 [pendingActionResult[0]]: pendingActionResult[1].data
1887 };
1888 } else if (state.actionData) {
1889 if (Object.keys(state.actionData).length === 0) {
1890 return null;
1891 } else {
1892 return state.actionData;
1893 }
1894 }
1895 }
1896 function getUpdatedRevalidatingFetchers(revalidatingFetchers) {
1897 revalidatingFetchers.forEach((rf) => {
1898 let fetcher = state.fetchers.get(rf.key);
1899 let revalidatingFetcher = getLoadingFetcher(
1900 void 0,
1901 fetcher ? fetcher.data : void 0
1902 );
1903 state.fetchers.set(rf.key, revalidatingFetcher);
1904 });
1905 return new Map(state.fetchers);
1906 }
1907 async function fetch2(key, routeId, href2, opts) {
1908 abortFetcher(key);
1909 let flushSync = (opts && opts.flushSync) === true;
1910 let routesToUse = inFlightDataRoutes || dataRoutes;
1911 let normalizedPath = normalizeTo(
1912 state.location,
1913 state.matches,
1914 basename,
1915 href2,
1916 routeId,
1917 opts?.relative
1918 );
1919 let matches = matchRoutes(routesToUse, normalizedPath, basename);
1920 let fogOfWar = checkFogOfWar(matches, routesToUse, normalizedPath);
1921 if (fogOfWar.active && fogOfWar.matches) {
1922 matches = fogOfWar.matches;
1923 }
1924 if (!matches) {
1925 setFetcherError(
1926 key,
1927 routeId,
1928 getInternalRouterError(404, { pathname: normalizedPath }),
1929 { flushSync }
1930 );
1931 return;
1932 }
1933 let { path, submission, error } = normalizeNavigateOptions(
1934 true,
1935 normalizedPath,
1936 opts
1937 );
1938 if (error) {
1939 setFetcherError(key, routeId, error, { flushSync });
1940 return;
1941 }
1942 let match = getTargetMatch(matches, path);
1943 let scopedContext = new unstable_RouterContextProvider(
1944 init.unstable_getContext ? await init.unstable_getContext() : void 0
1945 );
1946 let preventScrollReset = (opts && opts.preventScrollReset) === true;
1947 if (submission && isMutationMethod(submission.formMethod)) {
1948 await handleFetcherAction(
1949 key,
1950 routeId,
1951 path,
1952 match,
1953 matches,
1954 scopedContext,
1955 fogOfWar.active,
1956 flushSync,
1957 preventScrollReset,
1958 submission
1959 );
1960 return;
1961 }
1962 fetchLoadMatches.set(key, { routeId, path });
1963 await handleFetcherLoader(
1964 key,
1965 routeId,
1966 path,
1967 match,
1968 matches,
1969 scopedContext,
1970 fogOfWar.active,
1971 flushSync,
1972 preventScrollReset,
1973 submission
1974 );
1975 }
1976 async function handleFetcherAction(key, routeId, path, match, requestMatches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission) {
1977 interruptActiveLoads();
1978 fetchLoadMatches.delete(key);
1979 function detectAndHandle405Error(m) {
1980 if (!m.route.action && !m.route.lazy) {
1981 let error = getInternalRouterError(405, {
1982 method: submission.formMethod,
1983 pathname: path,
1984 routeId
1985 });
1986 setFetcherError(key, routeId, error, { flushSync });
1987 return true;
1988 }
1989 return false;
1990 }
1991 if (!isFogOfWar && detectAndHandle405Error(match)) {
1992 return;
1993 }
1994 let existingFetcher = state.fetchers.get(key);
1995 updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {
1996 flushSync
1997 });
1998 let abortController = new AbortController();
1999 let fetchRequest = createClientSideRequest(
2000 init.history,
2001 path,
2002 abortController.signal,
2003 submission
2004 );
2005 if (isFogOfWar) {
2006 let discoverResult = await discoverRoutes(
2007 requestMatches,
2008 path,
2009 fetchRequest.signal,
2010 key
2011 );
2012 if (discoverResult.type === "aborted") {
2013 return;
2014 } else if (discoverResult.type === "error") {
2015 setFetcherError(key, routeId, discoverResult.error, { flushSync });
2016 return;
2017 } else if (!discoverResult.matches) {
2018 setFetcherError(
2019 key,
2020 routeId,
2021 getInternalRouterError(404, { pathname: path }),
2022 { flushSync }
2023 );
2024 return;
2025 } else {
2026 requestMatches = discoverResult.matches;
2027 match = getTargetMatch(requestMatches, path);
2028 if (detectAndHandle405Error(match)) {
2029 return;
2030 }
2031 }
2032 }
2033 fetchControllers.set(key, abortController);
2034 let originatingLoadId = incrementingLoadId;
2035 let actionResults = await callDataStrategy(
2036 "action",
2037 fetchRequest,
2038 [match],
2039 requestMatches,
2040 scopedContext,
2041 key
2042 );
2043 let actionResult = actionResults[match.route.id];
2044 if (fetchRequest.signal.aborted) {
2045 if (fetchControllers.get(key) === abortController) {
2046 fetchControllers.delete(key);
2047 }
2048 return;
2049 }
2050 if (fetchersQueuedForDeletion.has(key)) {
2051 if (isRedirectResult(actionResult) || isErrorResult(actionResult)) {
2052 updateFetcherState(key, getDoneFetcher(void 0));
2053 return;
2054 }
2055 } else {
2056 if (isRedirectResult(actionResult)) {
2057 fetchControllers.delete(key);
2058 if (pendingNavigationLoadId > originatingLoadId) {
2059 updateFetcherState(key, getDoneFetcher(void 0));
2060 return;
2061 } else {
2062 fetchRedirectIds.add(key);
2063 updateFetcherState(key, getLoadingFetcher(submission));
2064 return startRedirectNavigation(fetchRequest, actionResult, false, {
2065 fetcherSubmission: submission,
2066 preventScrollReset
2067 });
2068 }
2069 }
2070 if (isErrorResult(actionResult)) {
2071 setFetcherError(key, routeId, actionResult.error);
2072 return;
2073 }
2074 }
2075 let nextLocation = state.navigation.location || state.location;
2076 let revalidationRequest = createClientSideRequest(
2077 init.history,
2078 nextLocation,
2079 abortController.signal
2080 );
2081 let routesToUse = inFlightDataRoutes || dataRoutes;
2082 let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, basename) : state.matches;
2083 invariant(matches, "Didn't find any matches after fetcher action");
2084 let loadId = ++incrementingLoadId;
2085 fetchReloadIds.set(key, loadId);
2086 let loadFetcher = getLoadingFetcher(submission, actionResult.data);
2087 state.fetchers.set(key, loadFetcher);
2088 let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(
2089 init.history,
2090 state,
2091 matches,
2092 submission,
2093 nextLocation,
2094 false,
2095 isRevalidationRequired,
2096 cancelledFetcherLoads,
2097 fetchersQueuedForDeletion,
2098 fetchLoadMatches,
2099 fetchRedirectIds,
2100 routesToUse,
2101 basename,
2102 [match.route.id, actionResult]
2103 );
2104 revalidatingFetchers.filter((rf) => rf.key !== key).forEach((rf) => {
2105 let staleKey = rf.key;
2106 let existingFetcher2 = state.fetchers.get(staleKey);
2107 let revalidatingFetcher = getLoadingFetcher(
2108 void 0,
2109 existingFetcher2 ? existingFetcher2.data : void 0
2110 );
2111 state.fetchers.set(staleKey, revalidatingFetcher);
2112 abortFetcher(staleKey);
2113 if (rf.controller) {
2114 fetchControllers.set(staleKey, rf.controller);
2115 }
2116 });
2117 updateState({ fetchers: new Map(state.fetchers) });
2118 let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((rf) => abortFetcher(rf.key));
2119 abortController.signal.addEventListener(
2120 "abort",
2121 abortPendingFetchRevalidations
2122 );
2123 let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
2124 matches,
2125 matchesToLoad,
2126 revalidatingFetchers,
2127 revalidationRequest,
2128 scopedContext
2129 );
2130 if (abortController.signal.aborted) {
2131 return;
2132 }
2133 abortController.signal.removeEventListener(
2134 "abort",
2135 abortPendingFetchRevalidations
2136 );
2137 fetchReloadIds.delete(key);
2138 fetchControllers.delete(key);
2139 revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));
2140 let redirect2 = findRedirect(loaderResults);
2141 if (redirect2) {
2142 return startRedirectNavigation(
2143 revalidationRequest,
2144 redirect2.result,
2145 false,
2146 { preventScrollReset }
2147 );
2148 }
2149 redirect2 = findRedirect(fetcherResults);
2150 if (redirect2) {
2151 fetchRedirectIds.add(redirect2.key);
2152 return startRedirectNavigation(
2153 revalidationRequest,
2154 redirect2.result,
2155 false,
2156 { preventScrollReset }
2157 );
2158 }
2159 let { loaderData, errors } = processLoaderData(
2160 state,
2161 matches,
2162 loaderResults,
2163 void 0,
2164 revalidatingFetchers,
2165 fetcherResults
2166 );
2167 if (state.fetchers.has(key)) {
2168 let doneFetcher = getDoneFetcher(actionResult.data);
2169 state.fetchers.set(key, doneFetcher);
2170 }
2171 abortStaleFetchLoads(loadId);
2172 if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
2173 invariant(pendingAction, "Expected pending action");
2174 pendingNavigationController && pendingNavigationController.abort();
2175 completeNavigation(state.navigation.location, {
2176 matches,
2177 loaderData,
2178 errors,
2179 fetchers: new Map(state.fetchers)
2180 });
2181 } else {
2182 updateState({
2183 errors,
2184 loaderData: mergeLoaderData(
2185 state.loaderData,
2186 loaderData,
2187 matches,
2188 errors
2189 ),
2190 fetchers: new Map(state.fetchers)
2191 });
2192 isRevalidationRequired = false;
2193 }
2194 }
2195 async function handleFetcherLoader(key, routeId, path, match, matches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission) {
2196 let existingFetcher = state.fetchers.get(key);
2197 updateFetcherState(
2198 key,
2199 getLoadingFetcher(
2200 submission,
2201 existingFetcher ? existingFetcher.data : void 0
2202 ),
2203 { flushSync }
2204 );
2205 let abortController = new AbortController();
2206 let fetchRequest = createClientSideRequest(
2207 init.history,
2208 path,
2209 abortController.signal
2210 );
2211 if (isFogOfWar) {
2212 let discoverResult = await discoverRoutes(
2213 matches,
2214 path,
2215 fetchRequest.signal,
2216 key
2217 );
2218 if (discoverResult.type === "aborted") {
2219 return;
2220 } else if (discoverResult.type === "error") {
2221 setFetcherError(key, routeId, discoverResult.error, { flushSync });
2222 return;
2223 } else if (!discoverResult.matches) {
2224 setFetcherError(
2225 key,
2226 routeId,
2227 getInternalRouterError(404, { pathname: path }),
2228 { flushSync }
2229 );
2230 return;
2231 } else {
2232 matches = discoverResult.matches;
2233 match = getTargetMatch(matches, path);
2234 }
2235 }
2236 fetchControllers.set(key, abortController);
2237 let originatingLoadId = incrementingLoadId;
2238 let results = await callDataStrategy(
2239 "loader",
2240 fetchRequest,
2241 [match],
2242 matches,
2243 scopedContext,
2244 key
2245 );
2246 let result = results[match.route.id];
2247 if (fetchControllers.get(key) === abortController) {
2248 fetchControllers.delete(key);
2249 }
2250 if (fetchRequest.signal.aborted) {
2251 return;
2252 }
2253 if (fetchersQueuedForDeletion.has(key)) {
2254 updateFetcherState(key, getDoneFetcher(void 0));
2255 return;
2256 }
2257 if (isRedirectResult(result)) {
2258 if (pendingNavigationLoadId > originatingLoadId) {
2259 updateFetcherState(key, getDoneFetcher(void 0));
2260 return;
2261 } else {
2262 fetchRedirectIds.add(key);
2263 await startRedirectNavigation(fetchRequest, result, false, {
2264 preventScrollReset
2265 });
2266 return;
2267 }
2268 }
2269 if (isErrorResult(result)) {
2270 setFetcherError(key, routeId, result.error);
2271 return;
2272 }
2273 updateFetcherState(key, getDoneFetcher(result.data));
2274 }
2275 async function startRedirectNavigation(request, redirect2, isNavigation, {
2276 submission,
2277 fetcherSubmission,
2278 preventScrollReset,
2279 replace: replace2
2280 } = {}) {
2281 if (redirect2.response.headers.has("X-Remix-Revalidate")) {
2282 isRevalidationRequired = true;
2283 }
2284 let location = redirect2.response.headers.get("Location");
2285 invariant(location, "Expected a Location header on the redirect Response");
2286 location = normalizeRedirectLocation(
2287 location,
2288 new URL(request.url),
2289 basename
2290 );
2291 let redirectLocation = createLocation(state.location, location, {
2292 _isRedirect: true
2293 });
2294 if (isBrowser2) {
2295 let isDocumentReload = false;
2296 if (redirect2.response.headers.has("X-Remix-Reload-Document")) {
2297 isDocumentReload = true;
2298 } else if (ABSOLUTE_URL_REGEX.test(location)) {
2299 const url = init.history.createURL(location);
2300 isDocumentReload = // Hard reload if it's an absolute URL to a new origin
2301 url.origin !== routerWindow.location.origin || // Hard reload if it's an absolute URL that does not match our basename
2302 stripBasename(url.pathname, basename) == null;
2303 }
2304 if (isDocumentReload) {
2305 if (replace2) {
2306 routerWindow.location.replace(location);
2307 } else {
2308 routerWindow.location.assign(location);
2309 }
2310 return;
2311 }
2312 }
2313 pendingNavigationController = null;
2314 let redirectNavigationType = replace2 === true || redirect2.response.headers.has("X-Remix-Replace") ? "REPLACE" /* Replace */ : "PUSH" /* Push */;
2315 let { formMethod, formAction, formEncType } = state.navigation;
2316 if (!submission && !fetcherSubmission && formMethod && formAction && formEncType) {
2317 submission = getSubmissionFromNavigation(state.navigation);
2318 }
2319 let activeSubmission = submission || fetcherSubmission;
2320 if (redirectPreserveMethodStatusCodes.has(redirect2.response.status) && activeSubmission && isMutationMethod(activeSubmission.formMethod)) {
2321 await startNavigation(redirectNavigationType, redirectLocation, {
2322 submission: {
2323 ...activeSubmission,
2324 formAction: location
2325 },
2326 // Preserve these flags across redirects
2327 preventScrollReset: preventScrollReset || pendingPreventScrollReset,
2328 enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0
2329 });
2330 } else {
2331 let overrideNavigation = getLoadingNavigation(
2332 redirectLocation,
2333 submission
2334 );
2335 await startNavigation(redirectNavigationType, redirectLocation, {
2336 overrideNavigation,
2337 // Send fetcher submissions through for shouldRevalidate
2338 fetcherSubmission,
2339 // Preserve these flags across redirects
2340 preventScrollReset: preventScrollReset || pendingPreventScrollReset,
2341 enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0
2342 });
2343 }
2344 }
2345 async function callDataStrategy(type, request, matchesToLoad, matches, scopedContext, fetcherKey) {
2346 let results;
2347 let dataResults = {};
2348 try {
2349 results = await callDataStrategyImpl(
2350 dataStrategyImpl,
2351 type,
2352 request,
2353 matchesToLoad,
2354 matches,
2355 fetcherKey,
2356 manifest,
2357 mapRouteProperties2,
2358 scopedContext,
2359 future.unstable_middleware
2360 );
2361 } catch (e) {
2362 matchesToLoad.forEach((m) => {
2363 dataResults[m.route.id] = {
2364 type: "error" /* error */,
2365 error: e
2366 };
2367 });
2368 return dataResults;
2369 }
2370 for (let [routeId, result] of Object.entries(results)) {
2371 if (isRedirectDataStrategyResult(result)) {
2372 let response = result.result;
2373 dataResults[routeId] = {
2374 type: "redirect" /* redirect */,
2375 response: normalizeRelativeRoutingRedirectResponse(
2376 response,
2377 request,
2378 routeId,
2379 matches,
2380 basename
2381 )
2382 };
2383 } else {
2384 dataResults[routeId] = await convertDataStrategyResultToDataResult(
2385 result
2386 );
2387 }
2388 }
2389 return dataResults;
2390 }
2391 async function callLoadersAndMaybeResolveData(matches, matchesToLoad, fetchersToLoad, request, scopedContext) {
2392 let loaderResultsPromise = callDataStrategy(
2393 "loader",
2394 request,
2395 matchesToLoad,
2396 matches,
2397 scopedContext,
2398 null
2399 );
2400 let fetcherResultsPromise = Promise.all(
2401 fetchersToLoad.map(async (f) => {
2402 if (f.matches && f.match && f.controller) {
2403 let results = await callDataStrategy(
2404 "loader",
2405 createClientSideRequest(init.history, f.path, f.controller.signal),
2406 [f.match],
2407 f.matches,
2408 scopedContext,
2409 f.key
2410 );
2411 let result = results[f.match.route.id];
2412 return { [f.key]: result };
2413 } else {
2414 return Promise.resolve({
2415 [f.key]: {
2416 type: "error" /* error */,
2417 error: getInternalRouterError(404, {
2418 pathname: f.path
2419 })
2420 }
2421 });
2422 }
2423 })
2424 );
2425 let loaderResults = await loaderResultsPromise;
2426 let fetcherResults = (await fetcherResultsPromise).reduce(
2427 (acc, r) => Object.assign(acc, r),
2428 {}
2429 );
2430 return {
2431 loaderResults,
2432 fetcherResults
2433 };
2434 }
2435 function interruptActiveLoads() {
2436 isRevalidationRequired = true;
2437 fetchLoadMatches.forEach((_, key) => {
2438 if (fetchControllers.has(key)) {
2439 cancelledFetcherLoads.add(key);
2440 }
2441 abortFetcher(key);
2442 });
2443 }
2444 function updateFetcherState(key, fetcher, opts = {}) {
2445 state.fetchers.set(key, fetcher);
2446 updateState(
2447 { fetchers: new Map(state.fetchers) },
2448 { flushSync: (opts && opts.flushSync) === true }
2449 );
2450 }
2451 function setFetcherError(key, routeId, error, opts = {}) {
2452 let boundaryMatch = findNearestBoundary(state.matches, routeId);
2453 deleteFetcher(key);
2454 updateState(
2455 {
2456 errors: {
2457 [boundaryMatch.route.id]: error
2458 },
2459 fetchers: new Map(state.fetchers)
2460 },
2461 { flushSync: (opts && opts.flushSync) === true }
2462 );
2463 }
2464 function getFetcher(key) {
2465 activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
2466 if (fetchersQueuedForDeletion.has(key)) {
2467 fetchersQueuedForDeletion.delete(key);
2468 }
2469 return state.fetchers.get(key) || IDLE_FETCHER;
2470 }
2471 function deleteFetcher(key) {
2472 let fetcher = state.fetchers.get(key);
2473 if (fetchControllers.has(key) && !(fetcher && fetcher.state === "loading" && fetchReloadIds.has(key))) {
2474 abortFetcher(key);
2475 }
2476 fetchLoadMatches.delete(key);
2477 fetchReloadIds.delete(key);
2478 fetchRedirectIds.delete(key);
2479 fetchersQueuedForDeletion.delete(key);
2480 cancelledFetcherLoads.delete(key);
2481 state.fetchers.delete(key);
2482 }
2483 function queueFetcherForDeletion(key) {
2484 let count = (activeFetchers.get(key) || 0) - 1;
2485 if (count <= 0) {
2486 activeFetchers.delete(key);
2487 fetchersQueuedForDeletion.add(key);
2488 } else {
2489 activeFetchers.set(key, count);
2490 }
2491 updateState({ fetchers: new Map(state.fetchers) });
2492 }
2493 function abortFetcher(key) {
2494 let controller = fetchControllers.get(key);
2495 if (controller) {
2496 controller.abort();
2497 fetchControllers.delete(key);
2498 }
2499 }
2500 function markFetchersDone(keys) {
2501 for (let key of keys) {
2502 let fetcher = getFetcher(key);
2503 let doneFetcher = getDoneFetcher(fetcher.data);
2504 state.fetchers.set(key, doneFetcher);
2505 }
2506 }
2507 function markFetchRedirectsDone() {
2508 let doneKeys = [];
2509 let updatedFetchers = false;
2510 for (let key of fetchRedirectIds) {
2511 let fetcher = state.fetchers.get(key);
2512 invariant(fetcher, `Expected fetcher: ${key}`);
2513 if (fetcher.state === "loading") {
2514 fetchRedirectIds.delete(key);
2515 doneKeys.push(key);
2516 updatedFetchers = true;
2517 }
2518 }
2519 markFetchersDone(doneKeys);
2520 return updatedFetchers;
2521 }
2522 function abortStaleFetchLoads(landedId) {
2523 let yeetedKeys = [];
2524 for (let [key, id] of fetchReloadIds) {
2525 if (id < landedId) {
2526 let fetcher = state.fetchers.get(key);
2527 invariant(fetcher, `Expected fetcher: ${key}`);
2528 if (fetcher.state === "loading") {
2529 abortFetcher(key);
2530 fetchReloadIds.delete(key);
2531 yeetedKeys.push(key);
2532 }
2533 }
2534 }
2535 markFetchersDone(yeetedKeys);
2536 return yeetedKeys.length > 0;
2537 }
2538 function getBlocker(key, fn) {
2539 let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2540 if (blockerFunctions.get(key) !== fn) {
2541 blockerFunctions.set(key, fn);
2542 }
2543 return blocker;
2544 }
2545 function deleteBlocker(key) {
2546 state.blockers.delete(key);
2547 blockerFunctions.delete(key);
2548 }
2549 function updateBlocker(key, newBlocker) {
2550 let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2551 invariant(
2552 blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked",
2553 `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`
2554 );
2555 let blockers = new Map(state.blockers);
2556 blockers.set(key, newBlocker);
2557 updateState({ blockers });
2558 }
2559 function shouldBlockNavigation({
2560 currentLocation,
2561 nextLocation,
2562 historyAction
2563 }) {
2564 if (blockerFunctions.size === 0) {
2565 return;
2566 }
2567 if (blockerFunctions.size > 1) {
2568 warning(false, "A router only supports one blocker at a time");
2569 }
2570 let entries = Array.from(blockerFunctions.entries());
2571 let [blockerKey, blockerFunction] = entries[entries.length - 1];
2572 let blocker = state.blockers.get(blockerKey);
2573 if (blocker && blocker.state === "proceeding") {
2574 return;
2575 }
2576 if (blockerFunction({ currentLocation, nextLocation, historyAction })) {
2577 return blockerKey;
2578 }
2579 }
2580 function handleNavigational404(pathname) {
2581 let error = getInternalRouterError(404, { pathname });
2582 let routesToUse = inFlightDataRoutes || dataRoutes;
2583 let { matches, route } = getShortCircuitMatches(routesToUse);
2584 return { notFoundMatches: matches, route, error };
2585 }
2586 function enableScrollRestoration(positions, getPosition, getKey) {
2587 savedScrollPositions2 = positions;
2588 getScrollPosition = getPosition;
2589 getScrollRestorationKey2 = getKey || null;
2590 if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {
2591 initialScrollRestored = true;
2592 let y = getSavedScrollPosition(state.location, state.matches);
2593 if (y != null) {
2594 updateState({ restoreScrollPosition: y });
2595 }
2596 }
2597 return () => {
2598 savedScrollPositions2 = null;
2599 getScrollPosition = null;
2600 getScrollRestorationKey2 = null;
2601 };
2602 }
2603 function getScrollKey(location, matches) {
2604 if (getScrollRestorationKey2) {
2605 let key = getScrollRestorationKey2(
2606 location,
2607 matches.map((m) => convertRouteMatchToUiMatch(m, state.loaderData))
2608 );
2609 return key || location.key;
2610 }
2611 return location.key;
2612 }
2613 function saveScrollPosition(location, matches) {
2614 if (savedScrollPositions2 && getScrollPosition) {
2615 let key = getScrollKey(location, matches);
2616 savedScrollPositions2[key] = getScrollPosition();
2617 }
2618 }
2619 function getSavedScrollPosition(location, matches) {
2620 if (savedScrollPositions2) {
2621 let key = getScrollKey(location, matches);
2622 let y = savedScrollPositions2[key];
2623 if (typeof y === "number") {
2624 return y;
2625 }
2626 }
2627 return null;
2628 }
2629 function checkFogOfWar(matches, routesToUse, pathname) {
2630 if (init.patchRoutesOnNavigation) {
2631 if (!matches) {
2632 let fogMatches = matchRoutesImpl(
2633 routesToUse,
2634 pathname,
2635 basename,
2636 true
2637 );
2638 return { active: true, matches: fogMatches || [] };
2639 } else {
2640 if (Object.keys(matches[0].params).length > 0) {
2641 let partialMatches = matchRoutesImpl(
2642 routesToUse,
2643 pathname,
2644 basename,
2645 true
2646 );
2647 return { active: true, matches: partialMatches };
2648 }
2649 }
2650 }
2651 return { active: false, matches: null };
2652 }
2653 async function discoverRoutes(matches, pathname, signal, fetcherKey) {
2654 if (!init.patchRoutesOnNavigation) {
2655 return { type: "success", matches };
2656 }
2657 let partialMatches = matches;
2658 while (true) {
2659 let isNonHMR = inFlightDataRoutes == null;
2660 let routesToUse = inFlightDataRoutes || dataRoutes;
2661 let localManifest = manifest;
2662 try {
2663 await init.patchRoutesOnNavigation({
2664 signal,
2665 path: pathname,
2666 matches: partialMatches,
2667 fetcherKey,
2668 patch: (routeId, children) => {
2669 if (signal.aborted) return;
2670 patchRoutesImpl(
2671 routeId,
2672 children,
2673 routesToUse,
2674 localManifest,
2675 mapRouteProperties2
2676 );
2677 }
2678 });
2679 } catch (e) {
2680 return { type: "error", error: e, partialMatches };
2681 } finally {
2682 if (isNonHMR && !signal.aborted) {
2683 dataRoutes = [...dataRoutes];
2684 }
2685 }
2686 if (signal.aborted) {
2687 return { type: "aborted" };
2688 }
2689 let newMatches = matchRoutes(routesToUse, pathname, basename);
2690 if (newMatches) {
2691 return { type: "success", matches: newMatches };
2692 }
2693 let newPartialMatches = matchRoutesImpl(
2694 routesToUse,
2695 pathname,
2696 basename,
2697 true
2698 );
2699 if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every(
2700 (m, i) => m.route.id === newPartialMatches[i].route.id
2701 )) {
2702 return { type: "success", matches: null };
2703 }
2704 partialMatches = newPartialMatches;
2705 }
2706 }
2707 function _internalSetRoutes(newRoutes) {
2708 manifest = {};
2709 inFlightDataRoutes = convertRoutesToDataRoutes(
2710 newRoutes,
2711 mapRouteProperties2,
2712 void 0,
2713 manifest
2714 );
2715 }
2716 function patchRoutes(routeId, children) {
2717 let isNonHMR = inFlightDataRoutes == null;
2718 let routesToUse = inFlightDataRoutes || dataRoutes;
2719 patchRoutesImpl(
2720 routeId,
2721 children,
2722 routesToUse,
2723 manifest,
2724 mapRouteProperties2
2725 );
2726 if (isNonHMR) {
2727 dataRoutes = [...dataRoutes];
2728 updateState({});
2729 }
2730 }
2731 router = {
2732 get basename() {
2733 return basename;
2734 },
2735 get future() {
2736 return future;
2737 },
2738 get state() {
2739 return state;
2740 },
2741 get routes() {
2742 return dataRoutes;
2743 },
2744 get window() {
2745 return routerWindow;
2746 },
2747 initialize,
2748 subscribe,
2749 enableScrollRestoration,
2750 navigate,
2751 fetch: fetch2,
2752 revalidate,
2753 // Passthrough to history-aware createHref used by useHref so we get proper
2754 // hash-aware URLs in DOM paths
2755 createHref: (to) => init.history.createHref(to),
2756 encodeLocation: (to) => init.history.encodeLocation(to),
2757 getFetcher,
2758 deleteFetcher: queueFetcherForDeletion,
2759 dispose,
2760 getBlocker,
2761 deleteBlocker,
2762 patchRoutes,
2763 _internalFetchControllers: fetchControllers,
2764 // TODO: Remove setRoutes, it's temporary to avoid dealing with
2765 // updating the tree while validating the update algorithm.
2766 _internalSetRoutes
2767 };
2768 return router;
2769}
2770function createStaticHandler(routes, opts) {
2771 invariant(
2772 routes.length > 0,
2773 "You must provide a non-empty routes array to createStaticHandler"
2774 );
2775 let manifest = {};
2776 let basename = (opts ? opts.basename : null) || "/";
2777 let mapRouteProperties2 = opts?.mapRouteProperties || defaultMapRouteProperties;
2778 let dataRoutes = convertRoutesToDataRoutes(
2779 routes,
2780 mapRouteProperties2,
2781 void 0,
2782 manifest
2783 );
2784 async function query(request, {
2785 requestContext,
2786 filterMatchesToLoad,
2787 skipLoaderErrorBubbling,
2788 skipRevalidation,
2789 dataStrategy,
2790 unstable_respond: respond
2791 } = {}) {
2792 let url = new URL(request.url);
2793 let method = request.method;
2794 let location = createLocation("", createPath(url), null, "default");
2795 let matches = matchRoutes(dataRoutes, location, basename);
2796 requestContext = requestContext != null ? requestContext : new unstable_RouterContextProvider();
2797 if (!isValidMethod(method) && method !== "HEAD") {
2798 let error = getInternalRouterError(405, { method });
2799 let { matches: methodNotAllowedMatches, route } = getShortCircuitMatches(dataRoutes);
2800 let staticContext = {
2801 basename,
2802 location,
2803 matches: methodNotAllowedMatches,
2804 loaderData: {},
2805 actionData: null,
2806 errors: {
2807 [route.id]: error
2808 },
2809 statusCode: error.status,
2810 loaderHeaders: {},
2811 actionHeaders: {}
2812 };
2813 return respond ? respond(staticContext) : staticContext;
2814 } else if (!matches) {
2815 let error = getInternalRouterError(404, { pathname: location.pathname });
2816 let { matches: notFoundMatches, route } = getShortCircuitMatches(dataRoutes);
2817 let staticContext = {
2818 basename,
2819 location,
2820 matches: notFoundMatches,
2821 loaderData: {},
2822 actionData: null,
2823 errors: {
2824 [route.id]: error
2825 },
2826 statusCode: error.status,
2827 loaderHeaders: {},
2828 actionHeaders: {}
2829 };
2830 return respond ? respond(staticContext) : staticContext;
2831 }
2832 if (respond && matches.some((m) => m.route.unstable_middleware)) {
2833 invariant(
2834 requestContext instanceof unstable_RouterContextProvider,
2835 "When using middleware in `staticHandler.query()`, any provided `requestContext` must be an instance of `unstable_RouterContextProvider`"
2836 );
2837 try {
2838 let renderedStaticContext;
2839 let response = await runMiddlewarePipeline(
2840 {
2841 request,
2842 matches,
2843 params: matches[0].params,
2844 // If we're calling middleware then it must be enabled so we can cast
2845 // this to the proper type knowing it's not an `AppLoadContext`
2846 context: requestContext
2847 },
2848 true,
2849 async () => {
2850 let result2 = await queryImpl(
2851 request,
2852 location,
2853 matches,
2854 requestContext,
2855 dataStrategy || null,
2856 skipLoaderErrorBubbling === true,
2857 null,
2858 filterMatchesToLoad || null,
2859 skipRevalidation === true
2860 );
2861 if (isResponse(result2)) {
2862 return result2;
2863 }
2864 renderedStaticContext = { location, basename, ...result2 };
2865 let res = await respond(renderedStaticContext);
2866 return res;
2867 },
2868 async (error, routeId) => {
2869 if (isResponse(error)) {
2870 return error;
2871 }
2872 if (renderedStaticContext) {
2873 if (routeId in renderedStaticContext.loaderData) {
2874 renderedStaticContext.loaderData[routeId] = void 0;
2875 }
2876 return respond(
2877 getStaticContextFromError(
2878 dataRoutes,
2879 renderedStaticContext,
2880 error,
2881 findNearestBoundary(matches, routeId).route.id
2882 )
2883 );
2884 } else {
2885 let loaderIdx = matches.findIndex((m) => m.route.loader);
2886 let boundary = loaderIdx >= 0 ? findNearestBoundary(matches, matches[loaderIdx].route.id) : findNearestBoundary(matches);
2887 return respond({
2888 matches,
2889 location,
2890 basename,
2891 loaderData: {},
2892 actionData: null,
2893 errors: {
2894 [boundary.route.id]: error
2895 },
2896 statusCode: isRouteErrorResponse(error) ? error.status : 500,
2897 actionHeaders: {},
2898 loaderHeaders: {}
2899 });
2900 }
2901 }
2902 );
2903 invariant(isResponse(response), "Expected a response in query()");
2904 return response;
2905 } catch (e) {
2906 if (isResponse(e)) {
2907 return e;
2908 }
2909 throw e;
2910 }
2911 }
2912 let result = await queryImpl(
2913 request,
2914 location,
2915 matches,
2916 requestContext,
2917 dataStrategy || null,
2918 skipLoaderErrorBubbling === true,
2919 null,
2920 filterMatchesToLoad || null,
2921 skipRevalidation === true
2922 );
2923 if (isResponse(result)) {
2924 return result;
2925 }
2926 return { location, basename, ...result };
2927 }
2928 async function queryRoute(request, {
2929 routeId,
2930 requestContext,
2931 dataStrategy,
2932 unstable_respond: respond
2933 } = {}) {
2934 let url = new URL(request.url);
2935 let method = request.method;
2936 let location = createLocation("", createPath(url), null, "default");
2937 let matches = matchRoutes(dataRoutes, location, basename);
2938 requestContext = requestContext != null ? requestContext : new unstable_RouterContextProvider();
2939 if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") {
2940 throw getInternalRouterError(405, { method });
2941 } else if (!matches) {
2942 throw getInternalRouterError(404, { pathname: location.pathname });
2943 }
2944 let match = routeId ? matches.find((m) => m.route.id === routeId) : getTargetMatch(matches, location);
2945 if (routeId && !match) {
2946 throw getInternalRouterError(403, {
2947 pathname: location.pathname,
2948 routeId
2949 });
2950 } else if (!match) {
2951 throw getInternalRouterError(404, { pathname: location.pathname });
2952 }
2953 if (respond && matches.some((m) => m.route.unstable_middleware)) {
2954 invariant(
2955 requestContext instanceof unstable_RouterContextProvider,
2956 "When using middleware in `staticHandler.queryRoute()`, any provided `requestContext` must be an instance of `unstable_RouterContextProvider`"
2957 );
2958 let response = await runMiddlewarePipeline(
2959 {
2960 request,
2961 matches,
2962 params: matches[0].params,
2963 // If we're calling middleware then it must be enabled so we can cast
2964 // this to the proper type knowing it's not an `AppLoadContext`
2965 context: requestContext
2966 },
2967 true,
2968 async () => {
2969 let result2 = await queryImpl(
2970 request,
2971 location,
2972 matches,
2973 requestContext,
2974 dataStrategy || null,
2975 false,
2976 match,
2977 null,
2978 false
2979 );
2980 if (isResponse(result2)) {
2981 return respond(result2);
2982 }
2983 let error2 = result2.errors ? Object.values(result2.errors)[0] : void 0;
2984 if (error2 !== void 0) {
2985 throw error2;
2986 }
2987 let value = result2.actionData ? Object.values(result2.actionData)[0] : Object.values(result2.loaderData)[0];
2988 return typeof value === "string" ? new Response(value) : Response.json(value);
2989 },
2990 (error2) => {
2991 if (isResponse(error2)) {
2992 return respond(error2);
2993 }
2994 return new Response(String(error2), {
2995 status: 500,
2996 statusText: "Unexpected Server Error"
2997 });
2998 }
2999 );
3000 return response;
3001 }
3002 let result = await queryImpl(
3003 request,
3004 location,
3005 matches,
3006 requestContext,
3007 dataStrategy || null,
3008 false,
3009 match,
3010 null,
3011 false
3012 );
3013 if (isResponse(result)) {
3014 return result;
3015 }
3016 let error = result.errors ? Object.values(result.errors)[0] : void 0;
3017 if (error !== void 0) {
3018 throw error;
3019 }
3020 if (result.actionData) {
3021 return Object.values(result.actionData)[0];
3022 }
3023 if (result.loaderData) {
3024 return Object.values(result.loaderData)[0];
3025 }
3026 return void 0;
3027 }
3028 async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, skipRevalidation) {
3029 invariant(
3030 request.signal,
3031 "query()/queryRoute() requests must contain an AbortController signal"
3032 );
3033 try {
3034 if (isMutationMethod(request.method)) {
3035 let result2 = await submit(
3036 request,
3037 matches,
3038 routeMatch || getTargetMatch(matches, location),
3039 requestContext,
3040 dataStrategy,
3041 skipLoaderErrorBubbling,
3042 routeMatch != null,
3043 filterMatchesToLoad,
3044 skipRevalidation
3045 );
3046 return result2;
3047 }
3048 let result = await loadRouteData(
3049 request,
3050 matches,
3051 requestContext,
3052 dataStrategy,
3053 skipLoaderErrorBubbling,
3054 routeMatch,
3055 filterMatchesToLoad
3056 );
3057 return isResponse(result) ? result : {
3058 ...result,
3059 actionData: null,
3060 actionHeaders: {}
3061 };
3062 } catch (e) {
3063 if (isDataStrategyResult(e) && isResponse(e.result)) {
3064 if (e.type === "error" /* error */) {
3065 throw e.result;
3066 }
3067 return e.result;
3068 }
3069 if (isRedirectResponse(e)) {
3070 return e;
3071 }
3072 throw e;
3073 }
3074 }
3075 async function submit(request, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest, filterMatchesToLoad, skipRevalidation) {
3076 let result;
3077 if (!actionMatch.route.action && !actionMatch.route.lazy) {
3078 let error = getInternalRouterError(405, {
3079 method: request.method,
3080 pathname: new URL(request.url).pathname,
3081 routeId: actionMatch.route.id
3082 });
3083 if (isRouteRequest) {
3084 throw error;
3085 }
3086 result = {
3087 type: "error" /* error */,
3088 error
3089 };
3090 } else {
3091 let results = await callDataStrategy(
3092 "action",
3093 request,
3094 [actionMatch],
3095 matches,
3096 isRouteRequest,
3097 requestContext,
3098 dataStrategy
3099 );
3100 result = results[actionMatch.route.id];
3101 if (request.signal.aborted) {
3102 throwStaticHandlerAbortedError(request, isRouteRequest);
3103 }
3104 }
3105 if (isRedirectResult(result)) {
3106 throw new Response(null, {
3107 status: result.response.status,
3108 headers: {
3109 Location: result.response.headers.get("Location")
3110 }
3111 });
3112 }
3113 if (isRouteRequest) {
3114 if (isErrorResult(result)) {
3115 throw result.error;
3116 }
3117 return {
3118 matches: [actionMatch],
3119 loaderData: {},
3120 actionData: { [actionMatch.route.id]: result.data },
3121 errors: null,
3122 // Note: statusCode + headers are unused here since queryRoute will
3123 // return the raw Response or value
3124 statusCode: 200,
3125 loaderHeaders: {},
3126 actionHeaders: {}
3127 };
3128 }
3129 if (skipRevalidation) {
3130 if (isErrorResult(result)) {
3131 let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
3132 return {
3133 statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
3134 actionData: null,
3135 actionHeaders: {
3136 ...result.headers ? { [actionMatch.route.id]: result.headers } : {}
3137 },
3138 matches,
3139 loaderData: {},
3140 errors: {
3141 [boundaryMatch.route.id]: result.error
3142 },
3143 loaderHeaders: {}
3144 };
3145 } else {
3146 return {
3147 actionData: {
3148 [actionMatch.route.id]: result.data
3149 },
3150 actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {},
3151 matches,
3152 loaderData: {},
3153 errors: null,
3154 statusCode: result.statusCode || 200,
3155 loaderHeaders: {}
3156 };
3157 }
3158 }
3159 let loaderRequest = new Request(request.url, {
3160 headers: request.headers,
3161 redirect: request.redirect,
3162 signal: request.signal
3163 });
3164 if (isErrorResult(result)) {
3165 let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
3166 let handlerContext2 = await loadRouteData(
3167 loaderRequest,
3168 matches,
3169 requestContext,
3170 dataStrategy,
3171 skipLoaderErrorBubbling,
3172 null,
3173 filterMatchesToLoad,
3174 [boundaryMatch.route.id, result]
3175 );
3176 return {
3177 ...handlerContext2,
3178 statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
3179 actionData: null,
3180 actionHeaders: {
3181 ...result.headers ? { [actionMatch.route.id]: result.headers } : {}
3182 }
3183 };
3184 }
3185 let handlerContext = await loadRouteData(
3186 loaderRequest,
3187 matches,
3188 requestContext,
3189 dataStrategy,
3190 skipLoaderErrorBubbling,
3191 null,
3192 filterMatchesToLoad
3193 );
3194 return {
3195 ...handlerContext,
3196 actionData: {
3197 [actionMatch.route.id]: result.data
3198 },
3199 // action status codes take precedence over loader status codes
3200 ...result.statusCode ? { statusCode: result.statusCode } : {},
3201 actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {}
3202 };
3203 }
3204 async function loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, pendingActionResult) {
3205 let isRouteRequest = routeMatch != null;
3206 if (isRouteRequest && !routeMatch?.route.loader && !routeMatch?.route.lazy) {
3207 throw getInternalRouterError(400, {
3208 method: request.method,
3209 pathname: new URL(request.url).pathname,
3210 routeId: routeMatch?.route.id
3211 });
3212 }
3213 let requestMatches = routeMatch ? [routeMatch] : pendingActionResult && isErrorResult(pendingActionResult[1]) ? getLoaderMatchesUntilBoundary(matches, pendingActionResult[0]) : matches;
3214 let matchesToLoad = requestMatches.filter(
3215 (m) => (m.route.loader || m.route.lazy) && (!filterMatchesToLoad || filterMatchesToLoad(m))
3216 );
3217 if (matchesToLoad.length === 0) {
3218 return {
3219 matches,
3220 // Add a null for all matched routes for proper revalidation on the client
3221 loaderData: matches.reduce(
3222 (acc, m) => Object.assign(acc, { [m.route.id]: null }),
3223 {}
3224 ),
3225 errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? {
3226 [pendingActionResult[0]]: pendingActionResult[1].error
3227 } : null,
3228 statusCode: 200,
3229 loaderHeaders: {}
3230 };
3231 }
3232 let results = await callDataStrategy(
3233 "loader",
3234 request,
3235 matchesToLoad,
3236 matches,
3237 isRouteRequest,
3238 requestContext,
3239 dataStrategy
3240 );
3241 if (request.signal.aborted) {
3242 throwStaticHandlerAbortedError(request, isRouteRequest);
3243 }
3244 let handlerContext = processRouteLoaderData(
3245 matches,
3246 results,
3247 pendingActionResult,
3248 true,
3249 skipLoaderErrorBubbling
3250 );
3251 let executedLoaders = new Set(
3252 matchesToLoad.map((match) => match.route.id)
3253 );
3254 matches.forEach((match) => {
3255 if (!executedLoaders.has(match.route.id)) {
3256 handlerContext.loaderData[match.route.id] = null;
3257 }
3258 });
3259 return {
3260 ...handlerContext,
3261 matches
3262 };
3263 }
3264 async function callDataStrategy(type, request, matchesToLoad, matches, isRouteRequest, requestContext, dataStrategy) {
3265 let results = await callDataStrategyImpl(
3266 dataStrategy || defaultDataStrategy,
3267 type,
3268 request,
3269 matchesToLoad,
3270 matches,
3271 null,
3272 manifest,
3273 mapRouteProperties2,
3274 requestContext,
3275 false
3276 // middleware not done via dataStrategy in the static handler
3277 );
3278 let dataResults = {};
3279 await Promise.all(
3280 matches.map(async (match) => {
3281 if (!(match.route.id in results)) {
3282 return;
3283 }
3284 let result = results[match.route.id];
3285 if (isRedirectDataStrategyResult(result)) {
3286 let response = result.result;
3287 throw normalizeRelativeRoutingRedirectResponse(
3288 response,
3289 request,
3290 match.route.id,
3291 matches,
3292 basename
3293 );
3294 }
3295 if (isResponse(result.result) && isRouteRequest) {
3296 throw result;
3297 }
3298 dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result);
3299 })
3300 );
3301 return dataResults;
3302 }
3303 return {
3304 dataRoutes,
3305 query,
3306 queryRoute
3307 };
3308}
3309function getStaticContextFromError(routes, handlerContext, error, boundaryId) {
3310 let errorBoundaryId = boundaryId || handlerContext._deepestRenderedBoundaryId || routes[0].id;
3311 return {
3312 ...handlerContext,
3313 statusCode: isRouteErrorResponse(error) ? error.status : 500,
3314 errors: {
3315 [errorBoundaryId]: error
3316 }
3317 };
3318}
3319function throwStaticHandlerAbortedError(request, isRouteRequest) {
3320 if (request.signal.reason !== void 0) {
3321 throw request.signal.reason;
3322 }
3323 let method = isRouteRequest ? "queryRoute" : "query";
3324 throw new Error(
3325 `${method}() call aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`
3326 );
3327}
3328function isSubmissionNavigation(opts) {
3329 return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== void 0);
3330}
3331function normalizeTo(location, matches, basename, to, fromRouteId, relative) {
3332 let contextualMatches;
3333 let activeRouteMatch;
3334 if (fromRouteId) {
3335 contextualMatches = [];
3336 for (let match of matches) {
3337 contextualMatches.push(match);
3338 if (match.route.id === fromRouteId) {
3339 activeRouteMatch = match;
3340 break;
3341 }
3342 }
3343 } else {
3344 contextualMatches = matches;
3345 activeRouteMatch = matches[matches.length - 1];
3346 }
3347 let path = resolveTo(
3348 to ? to : ".",
3349 getResolveToMatches(contextualMatches),
3350 stripBasename(location.pathname, basename) || location.pathname,
3351 relative === "path"
3352 );
3353 if (to == null) {
3354 path.search = location.search;
3355 path.hash = location.hash;
3356 }
3357 if ((to == null || to === "" || to === ".") && activeRouteMatch) {
3358 let nakedIndex = hasNakedIndexQuery(path.search);
3359 if (activeRouteMatch.route.index && !nakedIndex) {
3360 path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
3361 } else if (!activeRouteMatch.route.index && nakedIndex) {
3362 let params = new URLSearchParams(path.search);
3363 let indexValues = params.getAll("index");
3364 params.delete("index");
3365 indexValues.filter((v) => v).forEach((v) => params.append("index", v));
3366 let qs = params.toString();
3367 path.search = qs ? `?${qs}` : "";
3368 }
3369 }
3370 if (basename !== "/") {
3371 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
3372 }
3373 return createPath(path);
3374}
3375function normalizeNavigateOptions(isFetcher, path, opts) {
3376 if (!opts || !isSubmissionNavigation(opts)) {
3377 return { path };
3378 }
3379 if (opts.formMethod && !isValidMethod(opts.formMethod)) {
3380 return {
3381 path,
3382 error: getInternalRouterError(405, { method: opts.formMethod })
3383 };
3384 }
3385 let getInvalidBodyError = () => ({
3386 path,
3387 error: getInternalRouterError(400, { type: "invalid-body" })
3388 });
3389 let rawFormMethod = opts.formMethod || "get";
3390 let formMethod = rawFormMethod.toUpperCase();
3391 let formAction = stripHashFromPath(path);
3392 if (opts.body !== void 0) {
3393 if (opts.formEncType === "text/plain") {
3394 if (!isMutationMethod(formMethod)) {
3395 return getInvalidBodyError();
3396 }
3397 let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ? (
3398 // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
3399 Array.from(opts.body.entries()).reduce(
3400 (acc, [name, value]) => `${acc}${name}=${value}
3401`,
3402 ""
3403 )
3404 ) : String(opts.body);
3405 return {
3406 path,
3407 submission: {
3408 formMethod,
3409 formAction,
3410 formEncType: opts.formEncType,
3411 formData: void 0,
3412 json: void 0,
3413 text
3414 }
3415 };
3416 } else if (opts.formEncType === "application/json") {
3417 if (!isMutationMethod(formMethod)) {
3418 return getInvalidBodyError();
3419 }
3420 try {
3421 let json = typeof opts.body === "string" ? JSON.parse(opts.body) : opts.body;
3422 return {
3423 path,
3424 submission: {
3425 formMethod,
3426 formAction,
3427 formEncType: opts.formEncType,
3428 formData: void 0,
3429 json,
3430 text: void 0
3431 }
3432 };
3433 } catch (e) {
3434 return getInvalidBodyError();
3435 }
3436 }
3437 }
3438 invariant(
3439 typeof FormData === "function",
3440 "FormData is not available in this environment"
3441 );
3442 let searchParams;
3443 let formData;
3444 if (opts.formData) {
3445 searchParams = convertFormDataToSearchParams(opts.formData);
3446 formData = opts.formData;
3447 } else if (opts.body instanceof FormData) {
3448 searchParams = convertFormDataToSearchParams(opts.body);
3449 formData = opts.body;
3450 } else if (opts.body instanceof URLSearchParams) {
3451 searchParams = opts.body;
3452 formData = convertSearchParamsToFormData(searchParams);
3453 } else if (opts.body == null) {
3454 searchParams = new URLSearchParams();
3455 formData = new FormData();
3456 } else {
3457 try {
3458 searchParams = new URLSearchParams(opts.body);
3459 formData = convertSearchParamsToFormData(searchParams);
3460 } catch (e) {
3461 return getInvalidBodyError();
3462 }
3463 }
3464 let submission = {
3465 formMethod,
3466 formAction,
3467 formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
3468 formData,
3469 json: void 0,
3470 text: void 0
3471 };
3472 if (isMutationMethod(submission.formMethod)) {
3473 return { path, submission };
3474 }
3475 let parsedPath = parsePath(path);
3476 if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
3477 searchParams.append("index", "");
3478 }
3479 parsedPath.search = `?${searchParams}`;
3480 return { path: createPath(parsedPath), submission };
3481}
3482function getLoaderMatchesUntilBoundary(matches, boundaryId, includeBoundary = false) {
3483 let index = matches.findIndex((m) => m.route.id === boundaryId);
3484 if (index >= 0) {
3485 return matches.slice(0, includeBoundary ? index + 1 : index);
3486 }
3487 return matches;
3488}
3489function getMatchesToLoad(history, state, matches, submission, location, initialHydration, isRevalidationRequired, cancelledFetcherLoads, fetchersQueuedForDeletion, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
3490 let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : void 0;
3491 let currentUrl = history.createURL(state.location);
3492 let nextUrl = history.createURL(location);
3493 let boundaryMatches = matches;
3494 if (initialHydration && state.errors) {
3495 boundaryMatches = getLoaderMatchesUntilBoundary(
3496 matches,
3497 Object.keys(state.errors)[0],
3498 true
3499 );
3500 } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) {
3501 boundaryMatches = getLoaderMatchesUntilBoundary(
3502 matches,
3503 pendingActionResult[0]
3504 );
3505 }
3506 let actionStatus = pendingActionResult ? pendingActionResult[1].statusCode : void 0;
3507 let shouldSkipRevalidation = actionStatus && actionStatus >= 400;
3508 let navigationMatches = boundaryMatches.filter((match, index) => {
3509 let { route } = match;
3510 if (route.lazy) {
3511 return true;
3512 }
3513 if (route.loader == null) {
3514 return false;
3515 }
3516 if (initialHydration) {
3517 return shouldLoadRouteOnHydration(route, state.loaderData, state.errors);
3518 }
3519 if (isNewLoader(state.loaderData, state.matches[index], match)) {
3520 return true;
3521 }
3522 let currentRouteMatch = state.matches[index];
3523 let nextRouteMatch = match;
3524 return shouldRevalidateLoader(match, {
3525 currentUrl,
3526 currentParams: currentRouteMatch.params,
3527 nextUrl,
3528 nextParams: nextRouteMatch.params,
3529 ...submission,
3530 actionResult,
3531 actionStatus,
3532 defaultShouldRevalidate: shouldSkipRevalidation ? false : (
3533 // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
3534 isRevalidationRequired || currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search || // Search params affect all loaders
3535 currentUrl.search !== nextUrl.search || isNewRouteInstance(currentRouteMatch, nextRouteMatch)
3536 )
3537 });
3538 });
3539 let revalidatingFetchers = [];
3540 fetchLoadMatches.forEach((f, key) => {
3541 if (initialHydration || !matches.some((m) => m.route.id === f.routeId) || fetchersQueuedForDeletion.has(key)) {
3542 return;
3543 }
3544 let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
3545 if (!fetcherMatches) {
3546 revalidatingFetchers.push({
3547 key,
3548 routeId: f.routeId,
3549 path: f.path,
3550 matches: null,
3551 match: null,
3552 controller: null
3553 });
3554 return;
3555 }
3556 let fetcher = state.fetchers.get(key);
3557 let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
3558 let shouldRevalidate = false;
3559 if (fetchRedirectIds.has(key)) {
3560 shouldRevalidate = false;
3561 } else if (cancelledFetcherLoads.has(key)) {
3562 cancelledFetcherLoads.delete(key);
3563 shouldRevalidate = true;
3564 } else if (fetcher && fetcher.state !== "idle" && fetcher.data === void 0) {
3565 shouldRevalidate = isRevalidationRequired;
3566 } else {
3567 shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {
3568 currentUrl,
3569 currentParams: state.matches[state.matches.length - 1].params,
3570 nextUrl,
3571 nextParams: matches[matches.length - 1].params,
3572 ...submission,
3573 actionResult,
3574 actionStatus,
3575 defaultShouldRevalidate: shouldSkipRevalidation ? false : isRevalidationRequired
3576 });
3577 }
3578 if (shouldRevalidate) {
3579 revalidatingFetchers.push({
3580 key,
3581 routeId: f.routeId,
3582 path: f.path,
3583 matches: fetcherMatches,
3584 match: fetcherMatch,
3585 controller: new AbortController()
3586 });
3587 }
3588 });
3589 return [navigationMatches, revalidatingFetchers];
3590}
3591function shouldLoadRouteOnHydration(route, loaderData, errors) {
3592 if (route.lazy) {
3593 return true;
3594 }
3595 if (!route.loader) {
3596 return false;
3597 }
3598 let hasData = loaderData != null && loaderData[route.id] !== void 0;
3599 let hasError = errors != null && errors[route.id] !== void 0;
3600 if (!hasData && hasError) {
3601 return false;
3602 }
3603 if (typeof route.loader === "function" && route.loader.hydrate === true) {
3604 return true;
3605 }
3606 return !hasData && !hasError;
3607}
3608function isNewLoader(currentLoaderData, currentMatch, match) {
3609 let isNew = (
3610 // [a] -> [a, b]
3611 !currentMatch || // [a, b] -> [a, c]
3612 match.route.id !== currentMatch.route.id
3613 );
3614 let isMissingData = !currentLoaderData.hasOwnProperty(match.route.id);
3615 return isNew || isMissingData;
3616}
3617function isNewRouteInstance(currentMatch, match) {
3618 let currentPath = currentMatch.route.path;
3619 return (
3620 // param change for this match, /users/123 -> /users/456
3621 currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path
3622 // e.g. /files/images/avatar.jpg -> files/finances.xls
3623 currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
3624 );
3625}
3626function shouldRevalidateLoader(loaderMatch, arg) {
3627 if (loaderMatch.route.shouldRevalidate) {
3628 let routeChoice = loaderMatch.route.shouldRevalidate(arg);
3629 if (typeof routeChoice === "boolean") {
3630 return routeChoice;
3631 }
3632 }
3633 return arg.defaultShouldRevalidate;
3634}
3635function patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties2) {
3636 let childrenToPatch;
3637 if (routeId) {
3638 let route = manifest[routeId];
3639 invariant(
3640 route,
3641 `No route found to patch children into: routeId = ${routeId}`
3642 );
3643 if (!route.children) {
3644 route.children = [];
3645 }
3646 childrenToPatch = route.children;
3647 } else {
3648 childrenToPatch = routesToUse;
3649 }
3650 let uniqueChildren = children.filter(
3651 (newRoute) => !childrenToPatch.some(
3652 (existingRoute) => isSameRoute(newRoute, existingRoute)
3653 )
3654 );
3655 let newRoutes = convertRoutesToDataRoutes(
3656 uniqueChildren,
3657 mapRouteProperties2,
3658 [routeId || "_", "patch", String(childrenToPatch?.length || "0")],
3659 manifest
3660 );
3661 childrenToPatch.push(...newRoutes);
3662}
3663function isSameRoute(newRoute, existingRoute) {
3664 if ("id" in newRoute && "id" in existingRoute && newRoute.id === existingRoute.id) {
3665 return true;
3666 }
3667 if (!(newRoute.index === existingRoute.index && newRoute.path === existingRoute.path && newRoute.caseSensitive === existingRoute.caseSensitive)) {
3668 return false;
3669 }
3670 if ((!newRoute.children || newRoute.children.length === 0) && (!existingRoute.children || existingRoute.children.length === 0)) {
3671 return true;
3672 }
3673 return newRoute.children.every(
3674 (aChild, i) => existingRoute.children?.some((bChild) => isSameRoute(aChild, bChild))
3675 );
3676}
3677async function loadLazyRouteModule(route, mapRouteProperties2, manifest) {
3678 if (!route.lazy) {
3679 return;
3680 }
3681 let lazyRoute = await route.lazy();
3682 if (!route.lazy) {
3683 return;
3684 }
3685 let routeToUpdate = manifest[route.id];
3686 invariant(routeToUpdate, "No route found in manifest");
3687 let routeUpdates = {};
3688 for (let lazyRouteProperty in lazyRoute) {
3689 let staticRouteValue = routeToUpdate[lazyRouteProperty];
3690 let isPropertyStaticallyDefined = staticRouteValue !== void 0 && // This property isn't static since it should always be updated based
3691 // on the route updates
3692 lazyRouteProperty !== "hasErrorBoundary";
3693 warning(
3694 !isPropertyStaticallyDefined,
3695 `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.`
3696 );
3697 if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) {
3698 routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty];
3699 }
3700 }
3701 Object.assign(routeToUpdate, routeUpdates);
3702 Object.assign(routeToUpdate, {
3703 // To keep things framework agnostic, we use the provided `mapRouteProperties`
3704 // function to set the framework-aware properties (`element`/`hasErrorBoundary`)
3705 // since the logic will differ between frameworks.
3706 ...mapRouteProperties2(routeToUpdate),
3707 lazy: void 0
3708 });
3709}
3710async function defaultDataStrategy(args) {
3711 let matchesToLoad = args.matches.filter((m) => m.shouldLoad);
3712 let keyedResults = {};
3713 let results = await Promise.all(matchesToLoad.map((m) => m.resolve()));
3714 results.forEach((result, i) => {
3715 keyedResults[matchesToLoad[i].route.id] = result;
3716 });
3717 return keyedResults;
3718}
3719async function defaultDataStrategyWithMiddleware(args) {
3720 if (!args.matches.some((m) => m.route.unstable_middleware)) {
3721 return defaultDataStrategy(args);
3722 }
3723 return runMiddlewarePipeline(
3724 args,
3725 false,
3726 () => defaultDataStrategy(args),
3727 (error, routeId) => ({ [routeId]: { type: "error", result: error } })
3728 );
3729}
3730async function runMiddlewarePipeline(args, propagateResult, handler, errorHandler) {
3731 let { matches, request, params, context } = args;
3732 let middlewareState = {
3733 handlerResult: void 0
3734 };
3735 try {
3736 let tuples = matches.flatMap(
3737 (m) => m.route.unstable_middleware ? m.route.unstable_middleware.map((fn) => [m.route.id, fn]) : []
3738 );
3739 let result = await callRouteMiddleware(
3740 { request, params, context },
3741 tuples,
3742 propagateResult,
3743 middlewareState,
3744 handler
3745 );
3746 return propagateResult ? result : middlewareState.handlerResult;
3747 } catch (e) {
3748 if (!middlewareState.middlewareError) {
3749 throw e;
3750 }
3751 let result = await errorHandler(
3752 middlewareState.middlewareError.error,
3753 middlewareState.middlewareError.routeId
3754 );
3755 if (propagateResult || !middlewareState.handlerResult) {
3756 return result;
3757 }
3758 return Object.assign(middlewareState.handlerResult, result);
3759 }
3760}
3761async function callRouteMiddleware(args, middlewares, propagateResult, middlewareState, handler, idx = 0) {
3762 let { request } = args;
3763 if (request.signal.aborted) {
3764 if (request.signal.reason) {
3765 throw request.signal.reason;
3766 }
3767 throw new Error(
3768 `Request aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`
3769 );
3770 }
3771 let tuple = middlewares[idx];
3772 if (!tuple) {
3773 middlewareState.handlerResult = await handler();
3774 return middlewareState.handlerResult;
3775 }
3776 let [routeId, middleware] = tuple;
3777 let nextCalled = false;
3778 let nextResult = void 0;
3779 let next = async () => {
3780 if (nextCalled) {
3781 throw new Error("You may only call `next()` once per middleware");
3782 }
3783 nextCalled = true;
3784 let result = await callRouteMiddleware(
3785 args,
3786 middlewares,
3787 propagateResult,
3788 middlewareState,
3789 handler,
3790 idx + 1
3791 );
3792 if (propagateResult) {
3793 nextResult = result;
3794 return nextResult;
3795 }
3796 };
3797 try {
3798 let result = await middleware(
3799 {
3800 request: args.request,
3801 params: args.params,
3802 context: args.context
3803 },
3804 next
3805 );
3806 if (nextCalled) {
3807 if (result === void 0) {
3808 return nextResult;
3809 } else {
3810 return result;
3811 }
3812 } else {
3813 return next();
3814 }
3815 } catch (error) {
3816 if (!middlewareState.middlewareError) {
3817 middlewareState.middlewareError = { routeId, error };
3818 } else if (middlewareState.middlewareError.error !== error) {
3819 middlewareState.middlewareError = { routeId, error };
3820 }
3821 throw error;
3822 }
3823}
3824async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, scopedContext, enableMiddleware) {
3825 let loadRouteDefinitionsPromises = matches.map(
3826 (m) => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties2, manifest) : void 0
3827 );
3828 if (enableMiddleware) {
3829 await Promise.all(loadRouteDefinitionsPromises);
3830 }
3831 let dsMatches = matches.map((match, i) => {
3832 let loadRoutePromise = loadRouteDefinitionsPromises[i];
3833 let shouldLoad = matchesToLoad.some((m) => m.route.id === match.route.id);
3834 let resolve = async (handlerOverride) => {
3835 if (handlerOverride && request.method === "GET" && (match.route.lazy || match.route.loader)) {
3836 shouldLoad = true;
3837 }
3838 return shouldLoad ? callLoaderOrAction(
3839 type,
3840 request,
3841 match,
3842 loadRoutePromise,
3843 handlerOverride,
3844 scopedContext
3845 ) : Promise.resolve({ type: "data" /* data */, result: void 0 });
3846 };
3847 return {
3848 ...match,
3849 shouldLoad,
3850 resolve
3851 };
3852 });
3853 let results = await dataStrategyImpl({
3854 matches: dsMatches,
3855 request,
3856 params: matches[0].params,
3857 fetcherKey,
3858 context: scopedContext
3859 });
3860 try {
3861 await Promise.all(loadRouteDefinitionsPromises);
3862 } catch (e) {
3863 }
3864 return results;
3865}
3866async function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, scopedContext) {
3867 let result;
3868 let onReject;
3869 let runHandler = (handler) => {
3870 let reject;
3871 let abortPromise = new Promise((_, r) => reject = r);
3872 onReject = () => reject();
3873 request.signal.addEventListener("abort", onReject);
3874 let actualHandler = (ctx) => {
3875 if (typeof handler !== "function") {
3876 return Promise.reject(
3877 new Error(
3878 `You cannot call the handler for a route which defines a boolean "${type}" [routeId: ${match.route.id}]`
3879 )
3880 );
3881 }
3882 return handler(
3883 {
3884 request,
3885 params: match.params,
3886 context: scopedContext
3887 },
3888 ...ctx !== void 0 ? [ctx] : []
3889 );
3890 };
3891 let handlerPromise = (async () => {
3892 try {
3893 let val = await (handlerOverride ? handlerOverride((ctx) => actualHandler(ctx)) : actualHandler());
3894 return { type: "data", result: val };
3895 } catch (e) {
3896 return { type: "error", result: e };
3897 }
3898 })();
3899 return Promise.race([handlerPromise, abortPromise]);
3900 };
3901 try {
3902 let handler = match.route[type];
3903 if (loadRoutePromise) {
3904 if (handler) {
3905 let handlerError;
3906 let [value] = await Promise.all([
3907 // If the handler throws, don't let it immediately bubble out,
3908 // since we need to let the lazy() execution finish so we know if this
3909 // route has a boundary that can handle the error
3910 runHandler(handler).catch((e) => {
3911 handlerError = e;
3912 }),
3913 loadRoutePromise
3914 ]);
3915 if (handlerError !== void 0) {
3916 throw handlerError;
3917 }
3918 result = value;
3919 } else {
3920 await loadRoutePromise;
3921 handler = match.route[type];
3922 if (handler) {
3923 result = await runHandler(handler);
3924 } else if (type === "action") {
3925 let url = new URL(request.url);
3926 let pathname = url.pathname + url.search;
3927 throw getInternalRouterError(405, {
3928 method: request.method,
3929 pathname,
3930 routeId: match.route.id
3931 });
3932 } else {
3933 return { type: "data" /* data */, result: void 0 };
3934 }
3935 }
3936 } else if (!handler) {
3937 let url = new URL(request.url);
3938 let pathname = url.pathname + url.search;
3939 throw getInternalRouterError(404, {
3940 pathname
3941 });
3942 } else {
3943 result = await runHandler(handler);
3944 }
3945 } catch (e) {
3946 return { type: "error" /* error */, result: e };
3947 } finally {
3948 if (onReject) {
3949 request.signal.removeEventListener("abort", onReject);
3950 }
3951 }
3952 return result;
3953}
3954async function convertDataStrategyResultToDataResult(dataStrategyResult) {
3955 let { result, type } = dataStrategyResult;
3956 if (isResponse(result)) {
3957 let data2;
3958 try {
3959 let contentType = result.headers.get("Content-Type");
3960 if (contentType && /\bapplication\/json\b/.test(contentType)) {
3961 if (result.body == null) {
3962 data2 = null;
3963 } else {
3964 data2 = await result.json();
3965 }
3966 } else {
3967 data2 = await result.text();
3968 }
3969 } catch (e) {
3970 return { type: "error" /* error */, error: e };
3971 }
3972 if (type === "error" /* error */) {
3973 return {
3974 type: "error" /* error */,
3975 error: new ErrorResponseImpl(result.status, result.statusText, data2),
3976 statusCode: result.status,
3977 headers: result.headers
3978 };
3979 }
3980 return {
3981 type: "data" /* data */,
3982 data: data2,
3983 statusCode: result.status,
3984 headers: result.headers
3985 };
3986 }
3987 if (type === "error" /* error */) {
3988 if (isDataWithResponseInit(result)) {
3989 if (result.data instanceof Error) {
3990 return {
3991 type: "error" /* error */,
3992 error: result.data,
3993 statusCode: result.init?.status,
3994 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
3995 };
3996 }
3997 return {
3998 type: "error" /* error */,
3999 error: new ErrorResponseImpl(
4000 result.init?.status || 500,
4001 void 0,
4002 result.data
4003 ),
4004 statusCode: isRouteErrorResponse(result) ? result.status : void 0,
4005 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
4006 };
4007 }
4008 return {
4009 type: "error" /* error */,
4010 error: result,
4011 statusCode: isRouteErrorResponse(result) ? result.status : void 0
4012 };
4013 }
4014 if (isDataWithResponseInit(result)) {
4015 return {
4016 type: "data" /* data */,
4017 data: result.data,
4018 statusCode: result.init?.status,
4019 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
4020 };
4021 }
4022 return { type: "data" /* data */, data: result };
4023}
4024function normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename) {
4025 let location = response.headers.get("Location");
4026 invariant(
4027 location,
4028 "Redirects returned/thrown from loaders/actions must have a Location header"
4029 );
4030 if (!ABSOLUTE_URL_REGEX.test(location)) {
4031 let trimmedMatches = matches.slice(
4032 0,
4033 matches.findIndex((m) => m.route.id === routeId) + 1
4034 );
4035 location = normalizeTo(
4036 new URL(request.url),
4037 trimmedMatches,
4038 basename,
4039 location
4040 );
4041 response.headers.set("Location", location);
4042 }
4043 return response;
4044}
4045function normalizeRedirectLocation(location, currentUrl, basename) {
4046 if (ABSOLUTE_URL_REGEX.test(location)) {
4047 let normalizedLocation = location;
4048 let url = normalizedLocation.startsWith("//") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation);
4049 let isSameBasename = stripBasename(url.pathname, basename) != null;
4050 if (url.origin === currentUrl.origin && isSameBasename) {
4051 return url.pathname + url.search + url.hash;
4052 }
4053 }
4054 return location;
4055}
4056function createClientSideRequest(history, location, signal, submission) {
4057 let url = history.createURL(stripHashFromPath(location)).toString();
4058 let init = { signal };
4059 if (submission && isMutationMethod(submission.formMethod)) {
4060 let { formMethod, formEncType } = submission;
4061 init.method = formMethod.toUpperCase();
4062 if (formEncType === "application/json") {
4063 init.headers = new Headers({ "Content-Type": formEncType });
4064 init.body = JSON.stringify(submission.json);
4065 } else if (formEncType === "text/plain") {
4066 init.body = submission.text;
4067 } else if (formEncType === "application/x-www-form-urlencoded" && submission.formData) {
4068 init.body = convertFormDataToSearchParams(submission.formData);
4069 } else {
4070 init.body = submission.formData;
4071 }
4072 }
4073 return new Request(url, init);
4074}
4075function convertFormDataToSearchParams(formData) {
4076 let searchParams = new URLSearchParams();
4077 for (let [key, value] of formData.entries()) {
4078 searchParams.append(key, typeof value === "string" ? value : value.name);
4079 }
4080 return searchParams;
4081}
4082function convertSearchParamsToFormData(searchParams) {
4083 let formData = new FormData();
4084 for (let [key, value] of searchParams.entries()) {
4085 formData.append(key, value);
4086 }
4087 return formData;
4088}
4089function processRouteLoaderData(matches, results, pendingActionResult, isStaticHandler = false, skipLoaderErrorBubbling = false) {
4090 let loaderData = {};
4091 let errors = null;
4092 let statusCode;
4093 let foundError = false;
4094 let loaderHeaders = {};
4095 let pendingError = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : void 0;
4096 matches.forEach((match) => {
4097 if (!(match.route.id in results)) {
4098 return;
4099 }
4100 let id = match.route.id;
4101 let result = results[id];
4102 invariant(
4103 !isRedirectResult(result),
4104 "Cannot handle redirect results in processLoaderData"
4105 );
4106 if (isErrorResult(result)) {
4107 let error = result.error;
4108 if (pendingError !== void 0) {
4109 error = pendingError;
4110 pendingError = void 0;
4111 }
4112 errors = errors || {};
4113 if (skipLoaderErrorBubbling) {
4114 errors[id] = error;
4115 } else {
4116 let boundaryMatch = findNearestBoundary(matches, id);
4117 if (errors[boundaryMatch.route.id] == null) {
4118 errors[boundaryMatch.route.id] = error;
4119 }
4120 }
4121 if (!isStaticHandler) {
4122 loaderData[id] = ResetLoaderDataSymbol;
4123 }
4124 if (!foundError) {
4125 foundError = true;
4126 statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;
4127 }
4128 if (result.headers) {
4129 loaderHeaders[id] = result.headers;
4130 }
4131 } else {
4132 loaderData[id] = result.data;
4133 if (result.statusCode && result.statusCode !== 200 && !foundError) {
4134 statusCode = result.statusCode;
4135 }
4136 if (result.headers) {
4137 loaderHeaders[id] = result.headers;
4138 }
4139 }
4140 });
4141 if (pendingError !== void 0 && pendingActionResult) {
4142 errors = { [pendingActionResult[0]]: pendingError };
4143 loaderData[pendingActionResult[0]] = void 0;
4144 }
4145 return {
4146 loaderData,
4147 errors,
4148 statusCode: statusCode || 200,
4149 loaderHeaders
4150 };
4151}
4152function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults) {
4153 let { loaderData, errors } = processRouteLoaderData(
4154 matches,
4155 results,
4156 pendingActionResult
4157 );
4158 revalidatingFetchers.forEach((rf) => {
4159 let { key, match, controller } = rf;
4160 let result = fetcherResults[key];
4161 invariant(result, "Did not find corresponding fetcher result");
4162 if (controller && controller.signal.aborted) {
4163 return;
4164 } else if (isErrorResult(result)) {
4165 let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);
4166 if (!(errors && errors[boundaryMatch.route.id])) {
4167 errors = {
4168 ...errors,
4169 [boundaryMatch.route.id]: result.error
4170 };
4171 }
4172 state.fetchers.delete(key);
4173 } else if (isRedirectResult(result)) {
4174 invariant(false, "Unhandled fetcher revalidation redirect");
4175 } else {
4176 let doneFetcher = getDoneFetcher(result.data);
4177 state.fetchers.set(key, doneFetcher);
4178 }
4179 });
4180 return { loaderData, errors };
4181}
4182function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
4183 let mergedLoaderData = Object.entries(newLoaderData).filter(([, v]) => v !== ResetLoaderDataSymbol).reduce((merged, [k, v]) => {
4184 merged[k] = v;
4185 return merged;
4186 }, {});
4187 for (let match of matches) {
4188 let id = match.route.id;
4189 if (!newLoaderData.hasOwnProperty(id) && loaderData.hasOwnProperty(id) && match.route.loader) {
4190 mergedLoaderData[id] = loaderData[id];
4191 }
4192 if (errors && errors.hasOwnProperty(id)) {
4193 break;
4194 }
4195 }
4196 return mergedLoaderData;
4197}
4198function getActionDataForCommit(pendingActionResult) {
4199 if (!pendingActionResult) {
4200 return {};
4201 }
4202 return isErrorResult(pendingActionResult[1]) ? {
4203 // Clear out prior actionData on errors
4204 actionData: {}
4205 } : {
4206 actionData: {
4207 [pendingActionResult[0]]: pendingActionResult[1].data
4208 }
4209 };
4210}
4211function findNearestBoundary(matches, routeId) {
4212 let eligibleMatches = routeId ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1) : [...matches];
4213 return eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) || matches[0];
4214}
4215function getShortCircuitMatches(routes) {
4216 let route = routes.length === 1 ? routes[0] : routes.find((r) => r.index || !r.path || r.path === "/") || {
4217 id: `__shim-error-route__`
4218 };
4219 return {
4220 matches: [
4221 {
4222 params: {},
4223 pathname: "",
4224 pathnameBase: "",
4225 route
4226 }
4227 ],
4228 route
4229 };
4230}
4231function getInternalRouterError(status, {
4232 pathname,
4233 routeId,
4234 method,
4235 type,
4236 message
4237} = {}) {
4238 let statusText = "Unknown Server Error";
4239 let errorMessage = "Unknown @remix-run/router error";
4240 if (status === 400) {
4241 statusText = "Bad Request";
4242 if (method && pathname && routeId) {
4243 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.`;
4244 } else if (type === "invalid-body") {
4245 errorMessage = "Unable to encode submission body";
4246 }
4247 } else if (status === 403) {
4248 statusText = "Forbidden";
4249 errorMessage = `Route "${routeId}" does not match URL "${pathname}"`;
4250 } else if (status === 404) {
4251 statusText = "Not Found";
4252 errorMessage = `No route matches URL "${pathname}"`;
4253 } else if (status === 405) {
4254 statusText = "Method Not Allowed";
4255 if (method && pathname && routeId) {
4256 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.`;
4257 } else if (method) {
4258 errorMessage = `Invalid request method "${method.toUpperCase()}"`;
4259 }
4260 }
4261 return new ErrorResponseImpl(
4262 status || 500,
4263 statusText,
4264 new Error(errorMessage),
4265 true
4266 );
4267}
4268function findRedirect(results) {
4269 let entries = Object.entries(results);
4270 for (let i = entries.length - 1; i >= 0; i--) {
4271 let [key, result] = entries[i];
4272 if (isRedirectResult(result)) {
4273 return { key, result };
4274 }
4275 }
4276}
4277function stripHashFromPath(path) {
4278 let parsedPath = typeof path === "string" ? parsePath(path) : path;
4279 return createPath({ ...parsedPath, hash: "" });
4280}
4281function isHashChangeOnly(a, b) {
4282 if (a.pathname !== b.pathname || a.search !== b.search) {
4283 return false;
4284 }
4285 if (a.hash === "") {
4286 return b.hash !== "";
4287 } else if (a.hash === b.hash) {
4288 return true;
4289 } else if (b.hash !== "") {
4290 return true;
4291 }
4292 return false;
4293}
4294function isDataStrategyResult(result) {
4295 return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === "data" /* data */ || result.type === "error" /* error */);
4296}
4297function isRedirectDataStrategyResult(result) {
4298 return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
4299}
4300function isErrorResult(result) {
4301 return result.type === "error" /* error */;
4302}
4303function isRedirectResult(result) {
4304 return (result && result.type) === "redirect" /* redirect */;
4305}
4306function isDataWithResponseInit(value) {
4307 return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value.type === "DataWithResponseInit";
4308}
4309function isResponse(value) {
4310 return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
4311}
4312function isRedirectStatusCode(statusCode) {
4313 return redirectStatusCodes.has(statusCode);
4314}
4315function isRedirectResponse(result) {
4316 return isResponse(result) && isRedirectStatusCode(result.status) && result.headers.has("Location");
4317}
4318function isValidMethod(method) {
4319 return validRequestMethods.has(method.toUpperCase());
4320}
4321function isMutationMethod(method) {
4322 return validMutationMethods.has(method.toUpperCase());
4323}
4324function hasNakedIndexQuery(search) {
4325 return new URLSearchParams(search).getAll("index").some((v) => v === "");
4326}
4327function getTargetMatch(matches, location) {
4328 let search = typeof location === "string" ? parsePath(location).search : location.search;
4329 if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) {
4330 return matches[matches.length - 1];
4331 }
4332 let pathMatches = getPathContributingMatches(matches);
4333 return pathMatches[pathMatches.length - 1];
4334}
4335function getSubmissionFromNavigation(navigation) {
4336 let { formMethod, formAction, formEncType, text, formData, json } = navigation;
4337 if (!formMethod || !formAction || !formEncType) {
4338 return;
4339 }
4340 if (text != null) {
4341 return {
4342 formMethod,
4343 formAction,
4344 formEncType,
4345 formData: void 0,
4346 json: void 0,
4347 text
4348 };
4349 } else if (formData != null) {
4350 return {
4351 formMethod,
4352 formAction,
4353 formEncType,
4354 formData,
4355 json: void 0,
4356 text: void 0
4357 };
4358 } else if (json !== void 0) {
4359 return {
4360 formMethod,
4361 formAction,
4362 formEncType,
4363 formData: void 0,
4364 json,
4365 text: void 0
4366 };
4367 }
4368}
4369function getLoadingNavigation(location, submission) {
4370 if (submission) {
4371 let navigation = {
4372 state: "loading",
4373 location,
4374 formMethod: submission.formMethod,
4375 formAction: submission.formAction,
4376 formEncType: submission.formEncType,
4377 formData: submission.formData,
4378 json: submission.json,
4379 text: submission.text
4380 };
4381 return navigation;
4382 } else {
4383 let navigation = {
4384 state: "loading",
4385 location,
4386 formMethod: void 0,
4387 formAction: void 0,
4388 formEncType: void 0,
4389 formData: void 0,
4390 json: void 0,
4391 text: void 0
4392 };
4393 return navigation;
4394 }
4395}
4396function getSubmittingNavigation(location, submission) {
4397 let navigation = {
4398 state: "submitting",
4399 location,
4400 formMethod: submission.formMethod,
4401 formAction: submission.formAction,
4402 formEncType: submission.formEncType,
4403 formData: submission.formData,
4404 json: submission.json,
4405 text: submission.text
4406 };
4407 return navigation;
4408}
4409function getLoadingFetcher(submission, data2) {
4410 if (submission) {
4411 let fetcher = {
4412 state: "loading",
4413 formMethod: submission.formMethod,
4414 formAction: submission.formAction,
4415 formEncType: submission.formEncType,
4416 formData: submission.formData,
4417 json: submission.json,
4418 text: submission.text,
4419 data: data2
4420 };
4421 return fetcher;
4422 } else {
4423 let fetcher = {
4424 state: "loading",
4425 formMethod: void 0,
4426 formAction: void 0,
4427 formEncType: void 0,
4428 formData: void 0,
4429 json: void 0,
4430 text: void 0,
4431 data: data2
4432 };
4433 return fetcher;
4434 }
4435}
4436function getSubmittingFetcher(submission, existingFetcher) {
4437 let fetcher = {
4438 state: "submitting",
4439 formMethod: submission.formMethod,
4440 formAction: submission.formAction,
4441 formEncType: submission.formEncType,
4442 formData: submission.formData,
4443 json: submission.json,
4444 text: submission.text,
4445 data: existingFetcher ? existingFetcher.data : void 0
4446 };
4447 return fetcher;
4448}
4449function getDoneFetcher(data2) {
4450 let fetcher = {
4451 state: "idle",
4452 formMethod: void 0,
4453 formAction: void 0,
4454 formEncType: void 0,
4455 formData: void 0,
4456 json: void 0,
4457 text: void 0,
4458 data: data2
4459 };
4460 return fetcher;
4461}
4462function restoreAppliedTransitions(_window, transitions) {
4463 try {
4464 let sessionPositions = _window.sessionStorage.getItem(
4465 TRANSITIONS_STORAGE_KEY
4466 );
4467 if (sessionPositions) {
4468 let json = JSON.parse(sessionPositions);
4469 for (let [k, v] of Object.entries(json || {})) {
4470 if (v && Array.isArray(v)) {
4471 transitions.set(k, new Set(v || []));
4472 }
4473 }
4474 }
4475 } catch (e) {
4476 }
4477}
4478function persistAppliedTransitions(_window, transitions) {
4479 if (transitions.size > 0) {
4480 let json = {};
4481 for (let [k, v] of transitions) {
4482 json[k] = [...v];
4483 }
4484 try {
4485 _window.sessionStorage.setItem(
4486 TRANSITIONS_STORAGE_KEY,
4487 JSON.stringify(json)
4488 );
4489 } catch (error) {
4490 warning(
4491 false,
4492 `Failed to save applied view transitions in sessionStorage (${error}).`
4493 );
4494 }
4495 }
4496}
4497function createDeferred() {
4498 let resolve;
4499 let reject;
4500 let promise = new Promise((res, rej) => {
4501 resolve = async (val) => {
4502 res(val);
4503 try {
4504 await promise;
4505 } catch (e) {
4506 }
4507 };
4508 reject = async (error) => {
4509 rej(error);
4510 try {
4511 await promise;
4512 } catch (e) {
4513 }
4514 };
4515 });
4516 return {
4517 promise,
4518 //@ts-ignore
4519 resolve,
4520 //@ts-ignore
4521 reject
4522 };
4523}
4524
4525// lib/components.tsx
4526var React3 = __toESM(require("react"));
4527
4528// lib/context.ts
4529var React = __toESM(require("react"));
4530var DataRouterContext = React.createContext(null);
4531DataRouterContext.displayName = "DataRouter";
4532var DataRouterStateContext = React.createContext(null);
4533DataRouterStateContext.displayName = "DataRouterState";
4534var ViewTransitionContext = React.createContext({
4535 isTransitioning: false
4536});
4537ViewTransitionContext.displayName = "ViewTransition";
4538var FetchersContext = React.createContext(
4539 /* @__PURE__ */ new Map()
4540);
4541FetchersContext.displayName = "Fetchers";
4542var AwaitContext = React.createContext(null);
4543AwaitContext.displayName = "Await";
4544var NavigationContext = React.createContext(
4545 null
4546);
4547NavigationContext.displayName = "Navigation";
4548var LocationContext = React.createContext(
4549 null
4550);
4551LocationContext.displayName = "Location";
4552var RouteContext = React.createContext({
4553 outlet: null,
4554 matches: [],
4555 isDataRoute: false
4556});
4557RouteContext.displayName = "Route";
4558var RouteErrorContext = React.createContext(null);
4559RouteErrorContext.displayName = "RouteError";
4560
4561// lib/hooks.tsx
4562var React2 = __toESM(require("react"));
4563var ENABLE_DEV_WARNINGS = true;
4564function useHref(to, { relative } = {}) {
4565 invariant(
4566 useInRouterContext(),
4567 // TODO: This error is probably because they somehow have 2 versions of the
4568 // router loaded. We can help them understand how to avoid that.
4569 `useHref() may be used only in the context of a <Router> component.`
4570 );
4571 let { basename, navigator: navigator2 } = React2.useContext(NavigationContext);
4572 let { hash, pathname, search } = useResolvedPath(to, { relative });
4573 let joinedPathname = pathname;
4574 if (basename !== "/") {
4575 joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]);
4576 }
4577 return navigator2.createHref({ pathname: joinedPathname, search, hash });
4578}
4579function useInRouterContext() {
4580 return React2.useContext(LocationContext) != null;
4581}
4582function useLocation() {
4583 invariant(
4584 useInRouterContext(),
4585 // TODO: This error is probably because they somehow have 2 versions of the
4586 // router loaded. We can help them understand how to avoid that.
4587 `useLocation() may be used only in the context of a <Router> component.`
4588 );
4589 return React2.useContext(LocationContext).location;
4590}
4591function useNavigationType() {
4592 return React2.useContext(LocationContext).navigationType;
4593}
4594function useMatch(pattern) {
4595 invariant(
4596 useInRouterContext(),
4597 // TODO: This error is probably because they somehow have 2 versions of the
4598 // router loaded. We can help them understand how to avoid that.
4599 `useMatch() may be used only in the context of a <Router> component.`
4600 );
4601 let { pathname } = useLocation();
4602 return React2.useMemo(
4603 () => matchPath(pattern, decodePath(pathname)),
4604 [pathname, pattern]
4605 );
4606}
4607var navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when your component is first rendered.`;
4608function useIsomorphicLayoutEffect(cb) {
4609 let isStatic = React2.useContext(NavigationContext).static;
4610 if (!isStatic) {
4611 React2.useLayoutEffect(cb);
4612 }
4613}
4614function useNavigate() {
4615 let { isDataRoute } = React2.useContext(RouteContext);
4616 return isDataRoute ? useNavigateStable() : useNavigateUnstable();
4617}
4618function useNavigateUnstable() {
4619 invariant(
4620 useInRouterContext(),
4621 // TODO: This error is probably because they somehow have 2 versions of the
4622 // router loaded. We can help them understand how to avoid that.
4623 `useNavigate() may be used only in the context of a <Router> component.`
4624 );
4625 let dataRouterContext = React2.useContext(DataRouterContext);
4626 let { basename, navigator: navigator2 } = React2.useContext(NavigationContext);
4627 let { matches } = React2.useContext(RouteContext);
4628 let { pathname: locationPathname } = useLocation();
4629 let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
4630 let activeRef = React2.useRef(false);
4631 useIsomorphicLayoutEffect(() => {
4632 activeRef.current = true;
4633 });
4634 let navigate = React2.useCallback(
4635 (to, options = {}) => {
4636 warning(activeRef.current, navigateEffectWarning);
4637 if (!activeRef.current) return;
4638 if (typeof to === "number") {
4639 navigator2.go(to);
4640 return;
4641 }
4642 let path = resolveTo(
4643 to,
4644 JSON.parse(routePathnamesJson),
4645 locationPathname,
4646 options.relative === "path"
4647 );
4648 if (dataRouterContext == null && basename !== "/") {
4649 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
4650 }
4651 (!!options.replace ? navigator2.replace : navigator2.push)(
4652 path,
4653 options.state,
4654 options
4655 );
4656 },
4657 [
4658 basename,
4659 navigator2,
4660 routePathnamesJson,
4661 locationPathname,
4662 dataRouterContext
4663 ]
4664 );
4665 return navigate;
4666}
4667var OutletContext = React2.createContext(null);
4668function useOutletContext() {
4669 return React2.useContext(OutletContext);
4670}
4671function useOutlet(context) {
4672 let outlet = React2.useContext(RouteContext).outlet;
4673 if (outlet) {
4674 return /* @__PURE__ */ React2.createElement(OutletContext.Provider, { value: context }, outlet);
4675 }
4676 return outlet;
4677}
4678function useParams() {
4679 let { matches } = React2.useContext(RouteContext);
4680 let routeMatch = matches[matches.length - 1];
4681 return routeMatch ? routeMatch.params : {};
4682}
4683function useResolvedPath(to, { relative } = {}) {
4684 let { matches } = React2.useContext(RouteContext);
4685 let { pathname: locationPathname } = useLocation();
4686 let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
4687 return React2.useMemo(
4688 () => resolveTo(
4689 to,
4690 JSON.parse(routePathnamesJson),
4691 locationPathname,
4692 relative === "path"
4693 ),
4694 [to, routePathnamesJson, locationPathname, relative]
4695 );
4696}
4697function useRoutes(routes, locationArg) {
4698 return useRoutesImpl(routes, locationArg);
4699}
4700function useRoutesImpl(routes, locationArg, dataRouterState, future) {
4701 invariant(
4702 useInRouterContext(),
4703 // TODO: This error is probably because they somehow have 2 versions of the
4704 // router loaded. We can help them understand how to avoid that.
4705 `useRoutes() may be used only in the context of a <Router> component.`
4706 );
4707 let { navigator: navigator2, static: isStatic } = React2.useContext(NavigationContext);
4708 let { matches: parentMatches } = React2.useContext(RouteContext);
4709 let routeMatch = parentMatches[parentMatches.length - 1];
4710 let parentParams = routeMatch ? routeMatch.params : {};
4711 let parentPathname = routeMatch ? routeMatch.pathname : "/";
4712 let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
4713 let parentRoute = routeMatch && routeMatch.route;
4714 if (ENABLE_DEV_WARNINGS) {
4715 let parentPath = parentRoute && parentRoute.path || "";
4716 warningOnce(
4717 parentPathname,
4718 !parentRoute || parentPath.endsWith("*") || parentPath.endsWith("*?"),
4719 `You rendered descendant <Routes> (or called \`useRoutes()\`) at "${parentPathname}" (under <Route path="${parentPath}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
4720
4721Please change the parent <Route path="${parentPath}"> to <Route path="${parentPath === "/" ? "*" : `${parentPath}/*`}">.`
4722 );
4723 }
4724 let locationFromContext = useLocation();
4725 let location;
4726 if (locationArg) {
4727 let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
4728 invariant(
4729 parentPathnameBase === "/" || parsedLocationArg.pathname?.startsWith(parentPathnameBase),
4730 `When overriding the location using \`<Routes location>\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${parentPathnameBase}" but pathname "${parsedLocationArg.pathname}" was given in the \`location\` prop.`
4731 );
4732 location = parsedLocationArg;
4733 } else {
4734 location = locationFromContext;
4735 }
4736 let pathname = location.pathname || "/";
4737 let remainingPathname = pathname;
4738 if (parentPathnameBase !== "/") {
4739 let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
4740 let segments = pathname.replace(/^\//, "").split("/");
4741 remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
4742 }
4743 let matches = !isStatic && dataRouterState && dataRouterState.matches && dataRouterState.matches.length > 0 ? dataRouterState.matches : matchRoutes(routes, { pathname: remainingPathname });
4744 if (ENABLE_DEV_WARNINGS) {
4745 warning(
4746 parentRoute || matches != null,
4747 `No routes matched location "${location.pathname}${location.search}${location.hash}" `
4748 );
4749 warning(
4750 matches == null || matches[matches.length - 1].route.element !== void 0 || matches[matches.length - 1].route.Component !== void 0 || matches[matches.length - 1].route.lazy !== void 0,
4751 `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`
4752 );
4753 }
4754 let renderedMatches = _renderMatches(
4755 matches && matches.map(
4756 (match) => Object.assign({}, match, {
4757 params: Object.assign({}, parentParams, match.params),
4758 pathname: joinPaths([
4759 parentPathnameBase,
4760 // Re-encode pathnames that were decoded inside matchRoutes
4761 navigator2.encodeLocation ? navigator2.encodeLocation(match.pathname).pathname : match.pathname
4762 ]),
4763 pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([
4764 parentPathnameBase,
4765 // Re-encode pathnames that were decoded inside matchRoutes
4766 navigator2.encodeLocation ? navigator2.encodeLocation(match.pathnameBase).pathname : match.pathnameBase
4767 ])
4768 })
4769 ),
4770 parentMatches,
4771 dataRouterState,
4772 future
4773 );
4774 if (locationArg && renderedMatches) {
4775 return /* @__PURE__ */ React2.createElement(
4776 LocationContext.Provider,
4777 {
4778 value: {
4779 location: {
4780 pathname: "/",
4781 search: "",
4782 hash: "",
4783 state: null,
4784 key: "default",
4785 ...location
4786 },
4787 navigationType: "POP" /* Pop */
4788 }
4789 },
4790 renderedMatches
4791 );
4792 }
4793 return renderedMatches;
4794}
4795function DefaultErrorComponent() {
4796 let error = useRouteError();
4797 let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error);
4798 let stack = error instanceof Error ? error.stack : null;
4799 let lightgrey = "rgba(200,200,200, 0.5)";
4800 let preStyles = { padding: "0.5rem", backgroundColor: lightgrey };
4801 let codeStyles = { padding: "2px 4px", backgroundColor: lightgrey };
4802 let devInfo = null;
4803 if (ENABLE_DEV_WARNINGS) {
4804 console.error(
4805 "Error handled by React Router default ErrorBoundary:",
4806 error
4807 );
4808 devInfo = /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("p", null, "\u{1F4BF} Hey developer \u{1F44B}"), /* @__PURE__ */ React2.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /* @__PURE__ */ React2.createElement("code", { style: codeStyles }, "ErrorBoundary"), " or", " ", /* @__PURE__ */ React2.createElement("code", { style: codeStyles }, "errorElement"), " prop on your route."));
4809 }
4810 return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("h2", null, "Unexpected Application Error!"), /* @__PURE__ */ React2.createElement("h3", { style: { fontStyle: "italic" } }, message), stack ? /* @__PURE__ */ React2.createElement("pre", { style: preStyles }, stack) : null, devInfo);
4811}
4812var defaultErrorElement = /* @__PURE__ */ React2.createElement(DefaultErrorComponent, null);
4813var RenderErrorBoundary = class extends React2.Component {
4814 constructor(props) {
4815 super(props);
4816 this.state = {
4817 location: props.location,
4818 revalidation: props.revalidation,
4819 error: props.error
4820 };
4821 }
4822 static getDerivedStateFromError(error) {
4823 return { error };
4824 }
4825 static getDerivedStateFromProps(props, state) {
4826 if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
4827 return {
4828 error: props.error,
4829 location: props.location,
4830 revalidation: props.revalidation
4831 };
4832 }
4833 return {
4834 error: props.error !== void 0 ? props.error : state.error,
4835 location: state.location,
4836 revalidation: props.revalidation || state.revalidation
4837 };
4838 }
4839 componentDidCatch(error, errorInfo) {
4840 console.error(
4841 "React Router caught the following error during render",
4842 error,
4843 errorInfo
4844 );
4845 }
4846 render() {
4847 return this.state.error !== void 0 ? /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React2.createElement(
4848 RouteErrorContext.Provider,
4849 {
4850 value: this.state.error,
4851 children: this.props.component
4852 }
4853 )) : this.props.children;
4854 }
4855};
4856function RenderedRoute({ routeContext, match, children }) {
4857 let dataRouterContext = React2.useContext(DataRouterContext);
4858 if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
4859 dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
4860 }
4861 return /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: routeContext }, children);
4862}
4863function _renderMatches(matches, parentMatches = [], dataRouterState = null, future = null) {
4864 if (matches == null) {
4865 if (!dataRouterState) {
4866 return null;
4867 }
4868 if (dataRouterState.errors) {
4869 matches = dataRouterState.matches;
4870 } else if (parentMatches.length === 0 && !dataRouterState.initialized && dataRouterState.matches.length > 0) {
4871 matches = dataRouterState.matches;
4872 } else {
4873 return null;
4874 }
4875 }
4876 let renderedMatches = matches;
4877 let errors = dataRouterState?.errors;
4878 if (errors != null) {
4879 let errorIndex = renderedMatches.findIndex(
4880 (m) => m.route.id && errors?.[m.route.id] !== void 0
4881 );
4882 invariant(
4883 errorIndex >= 0,
4884 `Could not find a matching route for errors on route IDs: ${Object.keys(
4885 errors
4886 ).join(",")}`
4887 );
4888 renderedMatches = renderedMatches.slice(
4889 0,
4890 Math.min(renderedMatches.length, errorIndex + 1)
4891 );
4892 }
4893 let renderFallback = false;
4894 let fallbackIndex = -1;
4895 if (dataRouterState) {
4896 for (let i = 0; i < renderedMatches.length; i++) {
4897 let match = renderedMatches[i];
4898 if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
4899 fallbackIndex = i;
4900 }
4901 if (match.route.id) {
4902 let { loaderData, errors: errors2 } = dataRouterState;
4903 let needsToRunLoader = match.route.loader && !loaderData.hasOwnProperty(match.route.id) && (!errors2 || errors2[match.route.id] === void 0);
4904 if (match.route.lazy || needsToRunLoader) {
4905 renderFallback = true;
4906 if (fallbackIndex >= 0) {
4907 renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
4908 } else {
4909 renderedMatches = [renderedMatches[0]];
4910 }
4911 break;
4912 }
4913 }
4914 }
4915 }
4916 return renderedMatches.reduceRight((outlet, match, index) => {
4917 let error;
4918 let shouldRenderHydrateFallback = false;
4919 let errorElement = null;
4920 let hydrateFallbackElement = null;
4921 if (dataRouterState) {
4922 error = errors && match.route.id ? errors[match.route.id] : void 0;
4923 errorElement = match.route.errorElement || defaultErrorElement;
4924 if (renderFallback) {
4925 if (fallbackIndex < 0 && index === 0) {
4926 warningOnce(
4927 "route-fallback",
4928 false,
4929 "No `HydrateFallback` element provided to render during initial hydration"
4930 );
4931 shouldRenderHydrateFallback = true;
4932 hydrateFallbackElement = null;
4933 } else if (fallbackIndex === index) {
4934 shouldRenderHydrateFallback = true;
4935 hydrateFallbackElement = match.route.hydrateFallbackElement || null;
4936 }
4937 }
4938 }
4939 let matches2 = parentMatches.concat(renderedMatches.slice(0, index + 1));
4940 let getChildren = () => {
4941 let children;
4942 if (error) {
4943 children = errorElement;
4944 } else if (shouldRenderHydrateFallback) {
4945 children = hydrateFallbackElement;
4946 } else if (match.route.Component) {
4947 children = /* @__PURE__ */ React2.createElement(match.route.Component, null);
4948 } else if (match.route.element) {
4949 children = match.route.element;
4950 } else {
4951 children = outlet;
4952 }
4953 return /* @__PURE__ */ React2.createElement(
4954 RenderedRoute,
4955 {
4956 match,
4957 routeContext: {
4958 outlet,
4959 matches: matches2,
4960 isDataRoute: dataRouterState != null
4961 },
4962 children
4963 }
4964 );
4965 };
4966 return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /* @__PURE__ */ React2.createElement(
4967 RenderErrorBoundary,
4968 {
4969 location: dataRouterState.location,
4970 revalidation: dataRouterState.revalidation,
4971 component: errorElement,
4972 error,
4973 children: getChildren(),
4974 routeContext: { outlet: null, matches: matches2, isDataRoute: true }
4975 }
4976 ) : getChildren();
4977 }, null);
4978}
4979function getDataRouterConsoleError(hookName) {
4980 return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
4981}
4982function useDataRouterContext(hookName) {
4983 let ctx = React2.useContext(DataRouterContext);
4984 invariant(ctx, getDataRouterConsoleError(hookName));
4985 return ctx;
4986}
4987function useDataRouterState(hookName) {
4988 let state = React2.useContext(DataRouterStateContext);
4989 invariant(state, getDataRouterConsoleError(hookName));
4990 return state;
4991}
4992function useRouteContext(hookName) {
4993 let route = React2.useContext(RouteContext);
4994 invariant(route, getDataRouterConsoleError(hookName));
4995 return route;
4996}
4997function useCurrentRouteId(hookName) {
4998 let route = useRouteContext(hookName);
4999 let thisRoute = route.matches[route.matches.length - 1];
5000 invariant(
5001 thisRoute.route.id,
5002 `${hookName} can only be used on routes that contain a unique "id"`
5003 );
5004 return thisRoute.route.id;
5005}
5006function useRouteId() {
5007 return useCurrentRouteId("useRouteId" /* UseRouteId */);
5008}
5009function useNavigation() {
5010 let state = useDataRouterState("useNavigation" /* UseNavigation */);
5011 return state.navigation;
5012}
5013function useRevalidator() {
5014 let dataRouterContext = useDataRouterContext("useRevalidator" /* UseRevalidator */);
5015 let state = useDataRouterState("useRevalidator" /* UseRevalidator */);
5016 return React2.useMemo(
5017 () => ({
5018 async revalidate() {
5019 await dataRouterContext.router.revalidate();
5020 },
5021 state: state.revalidation
5022 }),
5023 [dataRouterContext.router, state.revalidation]
5024 );
5025}
5026function useMatches() {
5027 let { matches, loaderData } = useDataRouterState(
5028 "useMatches" /* UseMatches */
5029 );
5030 return React2.useMemo(
5031 () => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)),
5032 [matches, loaderData]
5033 );
5034}
5035function useLoaderData() {
5036 let state = useDataRouterState("useLoaderData" /* UseLoaderData */);
5037 let routeId = useCurrentRouteId("useLoaderData" /* UseLoaderData */);
5038 return state.loaderData[routeId];
5039}
5040function useRouteLoaderData(routeId) {
5041 let state = useDataRouterState("useRouteLoaderData" /* UseRouteLoaderData */);
5042 return state.loaderData[routeId];
5043}
5044function useActionData() {
5045 let state = useDataRouterState("useActionData" /* UseActionData */);
5046 let routeId = useCurrentRouteId("useLoaderData" /* UseLoaderData */);
5047 return state.actionData ? state.actionData[routeId] : void 0;
5048}
5049function useRouteError() {
5050 let error = React2.useContext(RouteErrorContext);
5051 let state = useDataRouterState("useRouteError" /* UseRouteError */);
5052 let routeId = useCurrentRouteId("useRouteError" /* UseRouteError */);
5053 if (error !== void 0) {
5054 return error;
5055 }
5056 return state.errors?.[routeId];
5057}
5058function useAsyncValue() {
5059 let value = React2.useContext(AwaitContext);
5060 return value?._data;
5061}
5062function useAsyncError() {
5063 let value = React2.useContext(AwaitContext);
5064 return value?._error;
5065}
5066var blockerId = 0;
5067function useBlocker(shouldBlock) {
5068 let { router, basename } = useDataRouterContext("useBlocker" /* UseBlocker */);
5069 let state = useDataRouterState("useBlocker" /* UseBlocker */);
5070 let [blockerKey, setBlockerKey] = React2.useState("");
5071 let blockerFunction = React2.useCallback(
5072 (arg) => {
5073 if (typeof shouldBlock !== "function") {
5074 return !!shouldBlock;
5075 }
5076 if (basename === "/") {
5077 return shouldBlock(arg);
5078 }
5079 let { currentLocation, nextLocation, historyAction } = arg;
5080 return shouldBlock({
5081 currentLocation: {
5082 ...currentLocation,
5083 pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname
5084 },
5085 nextLocation: {
5086 ...nextLocation,
5087 pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname
5088 },
5089 historyAction
5090 });
5091 },
5092 [basename, shouldBlock]
5093 );
5094 React2.useEffect(() => {
5095 let key = String(++blockerId);
5096 setBlockerKey(key);
5097 return () => router.deleteBlocker(key);
5098 }, [router]);
5099 React2.useEffect(() => {
5100 if (blockerKey !== "") {
5101 router.getBlocker(blockerKey, blockerFunction);
5102 }
5103 }, [router, blockerKey, blockerFunction]);
5104 return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : IDLE_BLOCKER;
5105}
5106function useNavigateStable() {
5107 let { router } = useDataRouterContext("useNavigate" /* UseNavigateStable */);
5108 let id = useCurrentRouteId("useNavigate" /* UseNavigateStable */);
5109 let activeRef = React2.useRef(false);
5110 useIsomorphicLayoutEffect(() => {
5111 activeRef.current = true;
5112 });
5113 let navigate = React2.useCallback(
5114 async (to, options = {}) => {
5115 warning(activeRef.current, navigateEffectWarning);
5116 if (!activeRef.current) return;
5117 if (typeof to === "number") {
5118 router.navigate(to);
5119 } else {
5120 await router.navigate(to, { fromRouteId: id, ...options });
5121 }
5122 },
5123 [router, id]
5124 );
5125 return navigate;
5126}
5127var alreadyWarned = {};
5128function warningOnce(key, cond, message) {
5129 if (!cond && !alreadyWarned[key]) {
5130 alreadyWarned[key] = true;
5131 warning(false, message);
5132 }
5133}
5134
5135// lib/server-runtime/warnings.ts
5136var alreadyWarned2 = {};
5137function warnOnce(condition, message) {
5138 if (!condition && !alreadyWarned2[message]) {
5139 alreadyWarned2[message] = true;
5140 console.warn(message);
5141 }
5142}
5143
5144// lib/components.tsx
5145var ENABLE_DEV_WARNINGS2 = true;
5146function mapRouteProperties(route) {
5147 let updates = {
5148 // Note: this check also occurs in createRoutesFromChildren so update
5149 // there if you change this -- please and thank you!
5150 hasErrorBoundary: route.hasErrorBoundary || route.ErrorBoundary != null || route.errorElement != null
5151 };
5152 if (route.Component) {
5153 if (ENABLE_DEV_WARNINGS2) {
5154 if (route.element) {
5155 warning(
5156 false,
5157 "You should not include both `Component` and `element` on your route - `Component` will be used."
5158 );
5159 }
5160 }
5161 Object.assign(updates, {
5162 element: React3.createElement(route.Component),
5163 Component: void 0
5164 });
5165 }
5166 if (route.HydrateFallback) {
5167 if (ENABLE_DEV_WARNINGS2) {
5168 if (route.hydrateFallbackElement) {
5169 warning(
5170 false,
5171 "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used."
5172 );
5173 }
5174 }
5175 Object.assign(updates, {
5176 hydrateFallbackElement: React3.createElement(route.HydrateFallback),
5177 HydrateFallback: void 0
5178 });
5179 }
5180 if (route.ErrorBoundary) {
5181 if (ENABLE_DEV_WARNINGS2) {
5182 if (route.errorElement) {
5183 warning(
5184 false,
5185 "You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used."
5186 );
5187 }
5188 }
5189 Object.assign(updates, {
5190 errorElement: React3.createElement(route.ErrorBoundary),
5191 ErrorBoundary: void 0
5192 });
5193 }
5194 return updates;
5195}
5196function createMemoryRouter(routes, opts) {
5197 return createRouter({
5198 basename: opts?.basename,
5199 unstable_getContext: opts?.unstable_getContext,
5200 future: opts?.future,
5201 history: createMemoryHistory({
5202 initialEntries: opts?.initialEntries,
5203 initialIndex: opts?.initialIndex
5204 }),
5205 hydrationData: opts?.hydrationData,
5206 routes,
5207 mapRouteProperties,
5208 dataStrategy: opts?.dataStrategy,
5209 patchRoutesOnNavigation: opts?.patchRoutesOnNavigation
5210 }).initialize();
5211}
5212var Deferred = class {
5213 constructor() {
5214 this.status = "pending";
5215 this.promise = new Promise((resolve, reject) => {
5216 this.resolve = (value) => {
5217 if (this.status === "pending") {
5218 this.status = "resolved";
5219 resolve(value);
5220 }
5221 };
5222 this.reject = (reason) => {
5223 if (this.status === "pending") {
5224 this.status = "rejected";
5225 reject(reason);
5226 }
5227 };
5228 });
5229 }
5230};
5231function RouterProvider({
5232 router,
5233 flushSync: reactDomFlushSyncImpl
5234}) {
5235 let [state, setStateImpl] = React3.useState(router.state);
5236 let [pendingState, setPendingState] = React3.useState();
5237 let [vtContext, setVtContext] = React3.useState({
5238 isTransitioning: false
5239 });
5240 let [renderDfd, setRenderDfd] = React3.useState();
5241 let [transition, setTransition] = React3.useState();
5242 let [interruption, setInterruption] = React3.useState();
5243 let fetcherData = React3.useRef(/* @__PURE__ */ new Map());
5244 let setState = React3.useCallback(
5245 (newState, { deletedFetchers, flushSync, viewTransitionOpts }) => {
5246 newState.fetchers.forEach((fetcher, key) => {
5247 if (fetcher.data !== void 0) {
5248 fetcherData.current.set(key, fetcher.data);
5249 }
5250 });
5251 deletedFetchers.forEach((key) => fetcherData.current.delete(key));
5252 warnOnce(
5253 flushSync === false || reactDomFlushSyncImpl != null,
5254 'You provided the `flushSync` option to a router update, but you are not using the `<RouterProvider>` from `react-router/dom` so `ReactDOM.flushSync()` is unavailable. Please update your app to `import { RouterProvider } from "react-router/dom"` and ensure you have `react-dom` installed as a dependency to use the `flushSync` option.'
5255 );
5256 let isViewTransitionAvailable = router.window != null && router.window.document != null && typeof router.window.document.startViewTransition === "function";
5257 warnOnce(
5258 viewTransitionOpts == null || isViewTransitionAvailable,
5259 "You provided the `viewTransition` option to a router update, but you do not appear to be running in a DOM environment as `window.startViewTransition` is not available."
5260 );
5261 if (!viewTransitionOpts || !isViewTransitionAvailable) {
5262 if (reactDomFlushSyncImpl && flushSync) {
5263 reactDomFlushSyncImpl(() => setStateImpl(newState));
5264 } else {
5265 React3.startTransition(() => setStateImpl(newState));
5266 }
5267 return;
5268 }
5269 if (reactDomFlushSyncImpl && flushSync) {
5270 reactDomFlushSyncImpl(() => {
5271 if (transition) {
5272 renderDfd && renderDfd.resolve();
5273 transition.skipTransition();
5274 }
5275 setVtContext({
5276 isTransitioning: true,
5277 flushSync: true,
5278 currentLocation: viewTransitionOpts.currentLocation,
5279 nextLocation: viewTransitionOpts.nextLocation
5280 });
5281 });
5282 let t = router.window.document.startViewTransition(() => {
5283 reactDomFlushSyncImpl(() => setStateImpl(newState));
5284 });
5285 t.finished.finally(() => {
5286 reactDomFlushSyncImpl(() => {
5287 setRenderDfd(void 0);
5288 setTransition(void 0);
5289 setPendingState(void 0);
5290 setVtContext({ isTransitioning: false });
5291 });
5292 });
5293 reactDomFlushSyncImpl(() => setTransition(t));
5294 return;
5295 }
5296 if (transition) {
5297 renderDfd && renderDfd.resolve();
5298 transition.skipTransition();
5299 setInterruption({
5300 state: newState,
5301 currentLocation: viewTransitionOpts.currentLocation,
5302 nextLocation: viewTransitionOpts.nextLocation
5303 });
5304 } else {
5305 setPendingState(newState);
5306 setVtContext({
5307 isTransitioning: true,
5308 flushSync: false,
5309 currentLocation: viewTransitionOpts.currentLocation,
5310 nextLocation: viewTransitionOpts.nextLocation
5311 });
5312 }
5313 },
5314 [router.window, reactDomFlushSyncImpl, transition, renderDfd]
5315 );
5316 React3.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
5317 React3.useEffect(() => {
5318 if (vtContext.isTransitioning && !vtContext.flushSync) {
5319 setRenderDfd(new Deferred());
5320 }
5321 }, [vtContext]);
5322 React3.useEffect(() => {
5323 if (renderDfd && pendingState && router.window) {
5324 let newState = pendingState;
5325 let renderPromise = renderDfd.promise;
5326 let transition2 = router.window.document.startViewTransition(async () => {
5327 React3.startTransition(() => setStateImpl(newState));
5328 await renderPromise;
5329 });
5330 transition2.finished.finally(() => {
5331 setRenderDfd(void 0);
5332 setTransition(void 0);
5333 setPendingState(void 0);
5334 setVtContext({ isTransitioning: false });
5335 });
5336 setTransition(transition2);
5337 }
5338 }, [pendingState, renderDfd, router.window]);
5339 React3.useEffect(() => {
5340 if (renderDfd && pendingState && state.location.key === pendingState.location.key) {
5341 renderDfd.resolve();
5342 }
5343 }, [renderDfd, transition, state.location, pendingState]);
5344 React3.useEffect(() => {
5345 if (!vtContext.isTransitioning && interruption) {
5346 setPendingState(interruption.state);
5347 setVtContext({
5348 isTransitioning: true,
5349 flushSync: false,
5350 currentLocation: interruption.currentLocation,
5351 nextLocation: interruption.nextLocation
5352 });
5353 setInterruption(void 0);
5354 }
5355 }, [vtContext.isTransitioning, interruption]);
5356 let navigator2 = React3.useMemo(() => {
5357 return {
5358 createHref: router.createHref,
5359 encodeLocation: router.encodeLocation,
5360 go: (n) => router.navigate(n),
5361 push: (to, state2, opts) => router.navigate(to, {
5362 state: state2,
5363 preventScrollReset: opts?.preventScrollReset
5364 }),
5365 replace: (to, state2, opts) => router.navigate(to, {
5366 replace: true,
5367 state: state2,
5368 preventScrollReset: opts?.preventScrollReset
5369 })
5370 };
5371 }, [router]);
5372 let basename = router.basename || "/";
5373 let dataRouterContext = React3.useMemo(
5374 () => ({
5375 router,
5376 navigator: navigator2,
5377 static: false,
5378 basename
5379 }),
5380 [router, navigator2, basename]
5381 );
5382 return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React3.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React3.createElement(FetchersContext.Provider, { value: fetcherData.current }, /* @__PURE__ */ React3.createElement(ViewTransitionContext.Provider, { value: vtContext }, /* @__PURE__ */ React3.createElement(
5383 Router,
5384 {
5385 basename,
5386 location: state.location,
5387 navigationType: state.historyAction,
5388 navigator: navigator2
5389 },
5390 /* @__PURE__ */ React3.createElement(
5391 MemoizedDataRoutes,
5392 {
5393 routes: router.routes,
5394 future: router.future,
5395 state
5396 }
5397 )
5398 ))))), null);
5399}
5400var MemoizedDataRoutes = React3.memo(DataRoutes);
5401function DataRoutes({
5402 routes,
5403 future,
5404 state
5405}) {
5406 return useRoutesImpl(routes, void 0, state, future);
5407}
5408function MemoryRouter({
5409 basename,
5410 children,
5411 initialEntries,
5412 initialIndex
5413}) {
5414 let historyRef = React3.useRef();
5415 if (historyRef.current == null) {
5416 historyRef.current = createMemoryHistory({
5417 initialEntries,
5418 initialIndex,
5419 v5Compat: true
5420 });
5421 }
5422 let history = historyRef.current;
5423 let [state, setStateImpl] = React3.useState({
5424 action: history.action,
5425 location: history.location
5426 });
5427 let setState = React3.useCallback(
5428 (newState) => {
5429 React3.startTransition(() => setStateImpl(newState));
5430 },
5431 [setStateImpl]
5432 );
5433 React3.useLayoutEffect(() => history.listen(setState), [history, setState]);
5434 return /* @__PURE__ */ React3.createElement(
5435 Router,
5436 {
5437 basename,
5438 children,
5439 location: state.location,
5440 navigationType: state.action,
5441 navigator: history
5442 }
5443 );
5444}
5445function Navigate({
5446 to,
5447 replace: replace2,
5448 state,
5449 relative
5450}) {
5451 invariant(
5452 useInRouterContext(),
5453 // TODO: This error is probably because they somehow have 2 versions of
5454 // the router loaded. We can help them understand how to avoid that.
5455 `<Navigate> may be used only in the context of a <Router> component.`
5456 );
5457 let { static: isStatic } = React3.useContext(NavigationContext);
5458 warning(
5459 !isStatic,
5460 `<Navigate> must not be used on the initial render in a <StaticRouter>. This is a no-op, but you should modify your code so the <Navigate> is only ever rendered in response to some user interaction or state change.`
5461 );
5462 let { matches } = React3.useContext(RouteContext);
5463 let { pathname: locationPathname } = useLocation();
5464 let navigate = useNavigate();
5465 let path = resolveTo(
5466 to,
5467 getResolveToMatches(matches),
5468 locationPathname,
5469 relative === "path"
5470 );
5471 let jsonPath = JSON.stringify(path);
5472 React3.useEffect(() => {
5473 navigate(JSON.parse(jsonPath), { replace: replace2, state, relative });
5474 }, [navigate, jsonPath, relative, replace2, state]);
5475 return null;
5476}
5477function Outlet(props) {
5478 return useOutlet(props.context);
5479}
5480function Route(_props) {
5481 invariant(
5482 false,
5483 `A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.`
5484 );
5485}
5486function Router({
5487 basename: basenameProp = "/",
5488 children = null,
5489 location: locationProp,
5490 navigationType = "POP" /* Pop */,
5491 navigator: navigator2,
5492 static: staticProp = false
5493}) {
5494 invariant(
5495 !useInRouterContext(),
5496 `You cannot render a <Router> inside another <Router>. You should never have more than one in your app.`
5497 );
5498 let basename = basenameProp.replace(/^\/*/, "/");
5499 let navigationContext = React3.useMemo(
5500 () => ({
5501 basename,
5502 navigator: navigator2,
5503 static: staticProp,
5504 future: {}
5505 }),
5506 [basename, navigator2, staticProp]
5507 );
5508 if (typeof locationProp === "string") {
5509 locationProp = parsePath(locationProp);
5510 }
5511 let {
5512 pathname = "/",
5513 search = "",
5514 hash = "",
5515 state = null,
5516 key = "default"
5517 } = locationProp;
5518 let locationContext = React3.useMemo(() => {
5519 let trailingPathname = stripBasename(pathname, basename);
5520 if (trailingPathname == null) {
5521 return null;
5522 }
5523 return {
5524 location: {
5525 pathname: trailingPathname,
5526 search,
5527 hash,
5528 state,
5529 key
5530 },
5531 navigationType
5532 };
5533 }, [basename, pathname, search, hash, state, key, navigationType]);
5534 warning(
5535 locationContext != null,
5536 `<Router basename="${basename}"> is not able to match the URL "${pathname}${search}${hash}" because it does not start with the basename, so the <Router> won't render anything.`
5537 );
5538 if (locationContext == null) {
5539 return null;
5540 }
5541 return /* @__PURE__ */ React3.createElement(NavigationContext.Provider, { value: navigationContext }, /* @__PURE__ */ React3.createElement(LocationContext.Provider, { children, value: locationContext }));
5542}
5543function Routes({
5544 children,
5545 location
5546}) {
5547 return useRoutes(createRoutesFromChildren(children), location);
5548}
5549function Await({
5550 children,
5551 errorElement,
5552 resolve
5553}) {
5554 return /* @__PURE__ */ React3.createElement(AwaitErrorBoundary, { resolve, errorElement }, /* @__PURE__ */ React3.createElement(ResolveAwait, null, children));
5555}
5556var AwaitErrorBoundary = class extends React3.Component {
5557 constructor(props) {
5558 super(props);
5559 this.state = { error: null };
5560 }
5561 static getDerivedStateFromError(error) {
5562 return { error };
5563 }
5564 componentDidCatch(error, errorInfo) {
5565 console.error(
5566 "<Await> caught the following error during render",
5567 error,
5568 errorInfo
5569 );
5570 }
5571 render() {
5572 let { children, errorElement, resolve } = this.props;
5573 let promise = null;
5574 let status = 0 /* pending */;
5575 if (!(resolve instanceof Promise)) {
5576 status = 1 /* success */;
5577 promise = Promise.resolve();
5578 Object.defineProperty(promise, "_tracked", { get: () => true });
5579 Object.defineProperty(promise, "_data", { get: () => resolve });
5580 } else if (this.state.error) {
5581 status = 2 /* error */;
5582 let renderError = this.state.error;
5583 promise = Promise.reject().catch(() => {
5584 });
5585 Object.defineProperty(promise, "_tracked", { get: () => true });
5586 Object.defineProperty(promise, "_error", { get: () => renderError });
5587 } else if (resolve._tracked) {
5588 promise = resolve;
5589 status = "_error" in promise ? 2 /* error */ : "_data" in promise ? 1 /* success */ : 0 /* pending */;
5590 } else {
5591 status = 0 /* pending */;
5592 Object.defineProperty(resolve, "_tracked", { get: () => true });
5593 promise = resolve.then(
5594 (data2) => Object.defineProperty(resolve, "_data", { get: () => data2 }),
5595 (error) => Object.defineProperty(resolve, "_error", { get: () => error })
5596 );
5597 }
5598 if (status === 2 /* error */ && !errorElement) {
5599 throw promise._error;
5600 }
5601 if (status === 2 /* error */) {
5602 return /* @__PURE__ */ React3.createElement(AwaitContext.Provider, { value: promise, children: errorElement });
5603 }
5604 if (status === 1 /* success */) {
5605 return /* @__PURE__ */ React3.createElement(AwaitContext.Provider, { value: promise, children });
5606 }
5607 throw promise;
5608 }
5609};
5610function ResolveAwait({
5611 children
5612}) {
5613 let data2 = useAsyncValue();
5614 let toRender = typeof children === "function" ? children(data2) : children;
5615 return /* @__PURE__ */ React3.createElement(React3.Fragment, null, toRender);
5616}
5617function createRoutesFromChildren(children, parentPath = []) {
5618 let routes = [];
5619 React3.Children.forEach(children, (element, index) => {
5620 if (!React3.isValidElement(element)) {
5621 return;
5622 }
5623 let treePath = [...parentPath, index];
5624 if (element.type === React3.Fragment) {
5625 routes.push.apply(
5626 routes,
5627 createRoutesFromChildren(element.props.children, treePath)
5628 );
5629 return;
5630 }
5631 invariant(
5632 element.type === Route,
5633 `[${typeof element.type === "string" ? element.type : element.type.name}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`
5634 );
5635 invariant(
5636 !element.props.index || !element.props.children,
5637 "An index route cannot have child routes."
5638 );
5639 let route = {
5640 id: element.props.id || treePath.join("-"),
5641 caseSensitive: element.props.caseSensitive,
5642 element: element.props.element,
5643 Component: element.props.Component,
5644 index: element.props.index,
5645 path: element.props.path,
5646 loader: element.props.loader,
5647 action: element.props.action,
5648 hydrateFallbackElement: element.props.hydrateFallbackElement,
5649 HydrateFallback: element.props.HydrateFallback,
5650 errorElement: element.props.errorElement,
5651 ErrorBoundary: element.props.ErrorBoundary,
5652 hasErrorBoundary: element.props.hasErrorBoundary === true || element.props.ErrorBoundary != null || element.props.errorElement != null,
5653 shouldRevalidate: element.props.shouldRevalidate,
5654 handle: element.props.handle,
5655 lazy: element.props.lazy
5656 };
5657 if (element.props.children) {
5658 route.children = createRoutesFromChildren(
5659 element.props.children,
5660 treePath
5661 );
5662 }
5663 routes.push(route);
5664 });
5665 return routes;
5666}
5667var createRoutesFromElements = createRoutesFromChildren;
5668function renderMatches(matches) {
5669 return _renderMatches(matches);
5670}
5671
5672// lib/dom/lib.tsx
5673var React10 = __toESM(require("react"));
5674
5675// lib/dom/dom.ts
5676var defaultMethod = "get";
5677var defaultEncType = "application/x-www-form-urlencoded";
5678function isHtmlElement(object) {
5679 return object != null && typeof object.tagName === "string";
5680}
5681function isButtonElement(object) {
5682 return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
5683}
5684function isFormElement(object) {
5685 return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
5686}
5687function isInputElement(object) {
5688 return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
5689}
5690function isModifiedEvent(event) {
5691 return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
5692}
5693function shouldProcessLinkClick(event, target) {
5694 return event.button === 0 && // Ignore everything but left clicks
5695 (!target || target === "_self") && // Let browser handle "target=_blank" etc.
5696 !isModifiedEvent(event);
5697}
5698function createSearchParams(init = "") {
5699 return new URLSearchParams(
5700 typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo2, key) => {
5701 let value = init[key];
5702 return memo2.concat(
5703 Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]]
5704 );
5705 }, [])
5706 );
5707}
5708function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
5709 let searchParams = createSearchParams(locationSearch);
5710 if (defaultSearchParams) {
5711 defaultSearchParams.forEach((_, key) => {
5712 if (!searchParams.has(key)) {
5713 defaultSearchParams.getAll(key).forEach((value) => {
5714 searchParams.append(key, value);
5715 });
5716 }
5717 });
5718 }
5719 return searchParams;
5720}
5721var _formDataSupportsSubmitter = null;
5722function isFormDataSubmitterSupported() {
5723 if (_formDataSupportsSubmitter === null) {
5724 try {
5725 new FormData(
5726 document.createElement("form"),
5727 // @ts-expect-error if FormData supports the submitter parameter, this will throw
5728 0
5729 );
5730 _formDataSupportsSubmitter = false;
5731 } catch (e) {
5732 _formDataSupportsSubmitter = true;
5733 }
5734 }
5735 return _formDataSupportsSubmitter;
5736}
5737var supportedFormEncTypes = /* @__PURE__ */ new Set([
5738 "application/x-www-form-urlencoded",
5739 "multipart/form-data",
5740 "text/plain"
5741]);
5742function getFormEncType(encType) {
5743 if (encType != null && !supportedFormEncTypes.has(encType)) {
5744 warning(
5745 false,
5746 `"${encType}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${defaultEncType}"`
5747 );
5748 return null;
5749 }
5750 return encType;
5751}
5752function getFormSubmissionInfo(target, basename) {
5753 let method;
5754 let action;
5755 let encType;
5756 let formData;
5757 let body;
5758 if (isFormElement(target)) {
5759 let attr = target.getAttribute("action");
5760 action = attr ? stripBasename(attr, basename) : null;
5761 method = target.getAttribute("method") || defaultMethod;
5762 encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
5763 formData = new FormData(target);
5764 } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
5765 let form = target.form;
5766 if (form == null) {
5767 throw new Error(
5768 `Cannot submit a <button> or <input type="submit"> without a <form>`
5769 );
5770 }
5771 let attr = target.getAttribute("formaction") || form.getAttribute("action");
5772 action = attr ? stripBasename(attr, basename) : null;
5773 method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
5774 encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
5775 formData = new FormData(form, target);
5776 if (!isFormDataSubmitterSupported()) {
5777 let { name, type, value } = target;
5778 if (type === "image") {
5779 let prefix = name ? `${name}.` : "";
5780 formData.append(`${prefix}x`, "0");
5781 formData.append(`${prefix}y`, "0");
5782 } else if (name) {
5783 formData.append(name, value);
5784 }
5785 }
5786 } else if (isHtmlElement(target)) {
5787 throw new Error(
5788 `Cannot submit element that is not <form>, <button>, or <input type="submit|image">`
5789 );
5790 } else {
5791 method = defaultMethod;
5792 action = null;
5793 encType = defaultEncType;
5794 body = target;
5795 }
5796 if (formData && encType === "text/plain") {
5797 body = formData;
5798 formData = void 0;
5799 }
5800 return { action, method: method.toLowerCase(), encType, formData, body };
5801}
5802
5803// lib/dom/ssr/components.tsx
5804var React9 = __toESM(require("react"));
5805
5806// lib/dom/ssr/invariant.ts
5807function invariant2(value, message) {
5808 if (value === false || value === null || typeof value === "undefined") {
5809 throw new Error(message);
5810 }
5811}
5812
5813// lib/dom/ssr/routeModules.ts
5814async function loadRouteModule(route, routeModulesCache) {
5815 if (route.id in routeModulesCache) {
5816 return routeModulesCache[route.id];
5817 }
5818 try {
5819 let routeModule = await import(
5820 /* @vite-ignore */
5821 /* webpackIgnore: true */
5822 route.module
5823 );
5824 routeModulesCache[route.id] = routeModule;
5825 return routeModule;
5826 } catch (error) {
5827 console.error(
5828 `Error loading route module \`${route.module}\`, reloading page...`
5829 );
5830 console.error(error);
5831 if (window.__reactRouterContext && window.__reactRouterContext.isSpaMode && // @ts-expect-error
5832 void 0) {
5833 throw error;
5834 }
5835 window.location.reload();
5836 return new Promise(() => {
5837 });
5838 }
5839}
5840
5841// lib/dom/ssr/links.ts
5842function getKeyedLinksForMatches(matches, routeModules, manifest) {
5843 let descriptors = matches.map((match) => {
5844 let module2 = routeModules[match.route.id];
5845 let route = manifest.routes[match.route.id];
5846 return [
5847 route && route.css ? route.css.map((href2) => ({ rel: "stylesheet", href: href2 })) : [],
5848 module2?.links?.() || []
5849 ];
5850 }).flat(2);
5851 let preloads = getModuleLinkHrefs(matches, manifest);
5852 return dedupeLinkDescriptors(descriptors, preloads);
5853}
5854function getRouteCssDescriptors(route) {
5855 if (!route.css) return [];
5856 return route.css.map((href2) => ({ rel: "stylesheet", href: href2 }));
5857}
5858async function prefetchRouteCss(route) {
5859 if (!route.css) return;
5860 let descriptors = getRouteCssDescriptors(route);
5861 await Promise.all(descriptors.map(prefetchStyleLink));
5862}
5863async function prefetchStyleLinks(route, routeModule) {
5864 if (!route.css && !routeModule.links || !isPreloadSupported()) return;
5865 let descriptors = [];
5866 if (route.css) {
5867 descriptors.push(...getRouteCssDescriptors(route));
5868 }
5869 if (routeModule.links) {
5870 descriptors.push(...routeModule.links());
5871 }
5872 if (descriptors.length === 0) return;
5873 let styleLinks = [];
5874 for (let descriptor of descriptors) {
5875 if (!isPageLinkDescriptor(descriptor) && descriptor.rel === "stylesheet") {
5876 styleLinks.push({
5877 ...descriptor,
5878 rel: "preload",
5879 as: "style"
5880 });
5881 }
5882 }
5883 await Promise.all(styleLinks.map(prefetchStyleLink));
5884}
5885async function prefetchStyleLink(descriptor) {
5886 return new Promise((resolve) => {
5887 if (descriptor.media && !window.matchMedia(descriptor.media).matches || document.querySelector(
5888 `link[rel="stylesheet"][href="${descriptor.href}"]`
5889 )) {
5890 return resolve();
5891 }
5892 let link = document.createElement("link");
5893 Object.assign(link, descriptor);
5894 function removeLink() {
5895 if (document.head.contains(link)) {
5896 document.head.removeChild(link);
5897 }
5898 }
5899 link.onload = () => {
5900 removeLink();
5901 resolve();
5902 };
5903 link.onerror = () => {
5904 removeLink();
5905 resolve();
5906 };
5907 document.head.appendChild(link);
5908 });
5909}
5910function isPageLinkDescriptor(object) {
5911 return object != null && typeof object.page === "string";
5912}
5913function isHtmlLinkDescriptor(object) {
5914 if (object == null) {
5915 return false;
5916 }
5917 if (object.href == null) {
5918 return object.rel === "preload" && typeof object.imageSrcSet === "string" && typeof object.imageSizes === "string";
5919 }
5920 return typeof object.rel === "string" && typeof object.href === "string";
5921}
5922async function getKeyedPrefetchLinks(matches, manifest, routeModules) {
5923 let links = await Promise.all(
5924 matches.map(async (match) => {
5925 let route = manifest.routes[match.route.id];
5926 if (route) {
5927 let mod = await loadRouteModule(route, routeModules);
5928 return mod.links ? mod.links() : [];
5929 }
5930 return [];
5931 })
5932 );
5933 return dedupeLinkDescriptors(
5934 links.flat(1).filter(isHtmlLinkDescriptor).filter((link) => link.rel === "stylesheet" || link.rel === "preload").map(
5935 (link) => link.rel === "stylesheet" ? { ...link, rel: "prefetch", as: "style" } : { ...link, rel: "prefetch" }
5936 )
5937 );
5938}
5939function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
5940 let isNew = (match, index) => {
5941 if (!currentMatches[index]) return true;
5942 return match.route.id !== currentMatches[index].route.id;
5943 };
5944 let matchPathChanged = (match, index) => {
5945 return (
5946 // param change, /users/123 -> /users/456
5947 currentMatches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path
5948 // e.g. /files/images/avatar.jpg -> files/finances.xls
5949 currentMatches[index].route.path?.endsWith("*") && currentMatches[index].params["*"] !== match.params["*"]
5950 );
5951 };
5952 if (mode === "assets") {
5953 return nextMatches.filter(
5954 (match, index) => isNew(match, index) || matchPathChanged(match, index)
5955 );
5956 }
5957 if (mode === "data") {
5958 return nextMatches.filter((match, index) => {
5959 let manifestRoute = manifest.routes[match.route.id];
5960 if (!manifestRoute || !manifestRoute.hasLoader) {
5961 return false;
5962 }
5963 if (isNew(match, index) || matchPathChanged(match, index)) {
5964 return true;
5965 }
5966 if (match.route.shouldRevalidate) {
5967 let routeChoice = match.route.shouldRevalidate({
5968 currentUrl: new URL(
5969 location.pathname + location.search + location.hash,
5970 window.origin
5971 ),
5972 currentParams: currentMatches[0]?.params || {},
5973 nextUrl: new URL(page, window.origin),
5974 nextParams: match.params,
5975 defaultShouldRevalidate: true
5976 });
5977 if (typeof routeChoice === "boolean") {
5978 return routeChoice;
5979 }
5980 }
5981 return true;
5982 });
5983 }
5984 return [];
5985}
5986function getModuleLinkHrefs(matches, manifest, { includeHydrateFallback } = {}) {
5987 return dedupeHrefs(
5988 matches.map((match) => {
5989 let route = manifest.routes[match.route.id];
5990 if (!route) return [];
5991 let hrefs = [route.module];
5992 if (route.clientActionModule) {
5993 hrefs = hrefs.concat(route.clientActionModule);
5994 }
5995 if (route.clientLoaderModule) {
5996 hrefs = hrefs.concat(route.clientLoaderModule);
5997 }
5998 if (includeHydrateFallback && route.hydrateFallbackModule) {
5999 hrefs = hrefs.concat(route.hydrateFallbackModule);
6000 }
6001 if (route.imports) {
6002 hrefs = hrefs.concat(route.imports);
6003 }
6004 return hrefs;
6005 }).flat(1)
6006 );
6007}
6008function dedupeHrefs(hrefs) {
6009 return [...new Set(hrefs)];
6010}
6011function sortKeys(obj) {
6012 let sorted = {};
6013 let keys = Object.keys(obj).sort();
6014 for (let key of keys) {
6015 sorted[key] = obj[key];
6016 }
6017 return sorted;
6018}
6019function dedupeLinkDescriptors(descriptors, preloads) {
6020 let set = /* @__PURE__ */ new Set();
6021 let preloadsSet = new Set(preloads);
6022 return descriptors.reduce((deduped, descriptor) => {
6023 let alreadyModulePreload = preloads && !isPageLinkDescriptor(descriptor) && descriptor.as === "script" && descriptor.href && preloadsSet.has(descriptor.href);
6024 if (alreadyModulePreload) {
6025 return deduped;
6026 }
6027 let key = JSON.stringify(sortKeys(descriptor));
6028 if (!set.has(key)) {
6029 set.add(key);
6030 deduped.push({ key, link: descriptor });
6031 }
6032 return deduped;
6033 }, []);
6034}
6035var _isPreloadSupported;
6036function isPreloadSupported() {
6037 if (_isPreloadSupported !== void 0) {
6038 return _isPreloadSupported;
6039 }
6040 let el = document.createElement("link");
6041 _isPreloadSupported = el.relList.supports("preload");
6042 el = null;
6043 return _isPreloadSupported;
6044}
6045
6046// lib/dom/ssr/markup.ts
6047var ESCAPE_LOOKUP = {
6048 "&": "\\u0026",
6049 ">": "\\u003e",
6050 "<": "\\u003c",
6051 "\u2028": "\\u2028",
6052 "\u2029": "\\u2029"
6053};
6054var ESCAPE_REGEX = /[&><\u2028\u2029]/g;
6055function escapeHtml(html) {
6056 return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
6057}
6058function createHtml(html) {
6059 return { __html: html };
6060}
6061
6062// lib/dom/ssr/single-fetch.tsx
6063var React4 = __toESM(require("react"));
6064var import_turbo_stream = require("turbo-stream");
6065
6066// lib/dom/ssr/data.ts
6067async function createRequestInit(request) {
6068 let init = { signal: request.signal };
6069 if (request.method !== "GET") {
6070 init.method = request.method;
6071 let contentType = request.headers.get("Content-Type");
6072 if (contentType && /\bapplication\/json\b/.test(contentType)) {
6073 init.headers = { "Content-Type": contentType };
6074 init.body = JSON.stringify(await request.json());
6075 } else if (contentType && /\btext\/plain\b/.test(contentType)) {
6076 init.headers = { "Content-Type": contentType };
6077 init.body = await request.text();
6078 } else if (contentType && /\bapplication\/x-www-form-urlencoded\b/.test(contentType)) {
6079 init.body = new URLSearchParams(await request.text());
6080 } else {
6081 init.body = await request.formData();
6082 }
6083 }
6084 return init;
6085}
6086
6087// lib/dom/ssr/single-fetch.tsx
6088var SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
6089function StreamTransfer({
6090 context,
6091 identifier,
6092 reader,
6093 textDecoder,
6094 nonce
6095}) {
6096 if (!context.renderMeta || !context.renderMeta.didRenderScripts) {
6097 return null;
6098 }
6099 if (!context.renderMeta.streamCache) {
6100 context.renderMeta.streamCache = {};
6101 }
6102 let { streamCache } = context.renderMeta;
6103 let promise = streamCache[identifier];
6104 if (!promise) {
6105 promise = streamCache[identifier] = reader.read().then((result) => {
6106 streamCache[identifier].result = {
6107 done: result.done,
6108 value: textDecoder.decode(result.value, { stream: true })
6109 };
6110 }).catch((e) => {
6111 streamCache[identifier].error = e;
6112 });
6113 }
6114 if (promise.error) {
6115 throw promise.error;
6116 }
6117 if (promise.result === void 0) {
6118 throw promise;
6119 }
6120 let { done, value } = promise.result;
6121 let scriptTag = value ? /* @__PURE__ */ React4.createElement(
6122 "script",
6123 {
6124 nonce,
6125 dangerouslySetInnerHTML: {
6126 __html: `window.__reactRouterContext.streamController.enqueue(${escapeHtml(
6127 JSON.stringify(value)
6128 )});`
6129 }
6130 }
6131 ) : null;
6132 if (done) {
6133 return /* @__PURE__ */ React4.createElement(React4.Fragment, null, scriptTag, /* @__PURE__ */ React4.createElement(
6134 "script",
6135 {
6136 nonce,
6137 dangerouslySetInnerHTML: {
6138 __html: `window.__reactRouterContext.streamController.close();`
6139 }
6140 }
6141 ));
6142 } else {
6143 return /* @__PURE__ */ React4.createElement(React4.Fragment, null, scriptTag, /* @__PURE__ */ React4.createElement(React4.Suspense, null, /* @__PURE__ */ React4.createElement(
6144 StreamTransfer,
6145 {
6146 context,
6147 identifier: identifier + 1,
6148 reader,
6149 textDecoder,
6150 nonce
6151 }
6152 )));
6153 }
6154}
6155function handleMiddlewareError(error, routeId) {
6156 return { [routeId]: { type: "error", result: error } };
6157}
6158function getSingleFetchDataStrategy(manifest, routeModules, ssr, basename, getRouter) {
6159 return async (args) => {
6160 let { request, matches, fetcherKey } = args;
6161 if (request.method !== "GET") {
6162 return runMiddlewarePipeline(
6163 args,
6164 false,
6165 () => singleFetchActionStrategy(request, matches, basename),
6166 handleMiddlewareError
6167 );
6168 }
6169 if (!ssr) {
6170 let foundRevalidatingServerLoader = matches.some(
6171 (m) => m.shouldLoad && manifest.routes[m.route.id]?.hasLoader && !manifest.routes[m.route.id]?.hasClientLoader
6172 );
6173 if (!foundRevalidatingServerLoader) {
6174 return runMiddlewarePipeline(
6175 args,
6176 false,
6177 () => nonSsrStrategy(manifest, request, matches, basename),
6178 handleMiddlewareError
6179 );
6180 }
6181 }
6182 if (fetcherKey) {
6183 return runMiddlewarePipeline(
6184 args,
6185 false,
6186 () => singleFetchLoaderFetcherStrategy(request, matches, basename),
6187 handleMiddlewareError
6188 );
6189 }
6190 return runMiddlewarePipeline(
6191 args,
6192 false,
6193 () => singleFetchLoaderNavigationStrategy(
6194 manifest,
6195 routeModules,
6196 ssr,
6197 getRouter(),
6198 request,
6199 matches,
6200 basename
6201 ),
6202 handleMiddlewareError
6203 );
6204 };
6205}
6206async function singleFetchActionStrategy(request, matches, basename) {
6207 let actionMatch = matches.find((m) => m.shouldLoad);
6208 invariant2(actionMatch, "No action match found");
6209 let actionStatus = void 0;
6210 let result = await actionMatch.resolve(async (handler) => {
6211 let result2 = await handler(async () => {
6212 let url = singleFetchUrl(request.url, basename);
6213 let init = await createRequestInit(request);
6214 let { data: data2, status } = await fetchAndDecode(url, init);
6215 actionStatus = status;
6216 return unwrapSingleFetchResult(
6217 data2,
6218 actionMatch.route.id
6219 );
6220 });
6221 return result2;
6222 });
6223 if (isResponse(result.result) || isRouteErrorResponse(result.result)) {
6224 return { [actionMatch.route.id]: result };
6225 }
6226 return {
6227 [actionMatch.route.id]: {
6228 type: result.type,
6229 result: data(result.result, actionStatus)
6230 }
6231 };
6232}
6233async function nonSsrStrategy(manifest, request, matches, basename) {
6234 let matchesToLoad = matches.filter((m) => m.shouldLoad);
6235 let url = stripIndexParam(singleFetchUrl(request.url, basename));
6236 let init = await createRequestInit(request);
6237 let results = {};
6238 await Promise.all(
6239 matchesToLoad.map(
6240 (m) => m.resolve(async (handler) => {
6241 try {
6242 let result = manifest.routes[m.route.id]?.hasClientLoader ? await fetchSingleLoader(handler, url, init, m.route.id) : await handler();
6243 results[m.route.id] = { type: "data", result };
6244 } catch (e) {
6245 results[m.route.id] = { type: "error", result: e };
6246 }
6247 })
6248 )
6249 );
6250 return results;
6251}
6252async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr, router, request, matches, basename) {
6253 let routesParams = /* @__PURE__ */ new Set();
6254 let foundOptOutRoute = false;
6255 let routeDfds = matches.map(() => createDeferred2());
6256 let routesLoadedPromise = Promise.all(routeDfds.map((d) => d.promise));
6257 let singleFetchDfd = createDeferred2();
6258 let url = stripIndexParam(singleFetchUrl(request.url, basename));
6259 let init = await createRequestInit(request);
6260 let results = {};
6261 let resolvePromise = Promise.all(
6262 matches.map(
6263 async (m, i) => m.resolve(async (handler) => {
6264 routeDfds[i].resolve();
6265 let manifestRoute = manifest.routes[m.route.id];
6266 if (!m.shouldLoad) {
6267 if (!router.state.initialized) {
6268 return;
6269 }
6270 if (m.route.id in router.state.loaderData && manifestRoute && m.route.shouldRevalidate) {
6271 if (manifestRoute.hasLoader) {
6272 foundOptOutRoute = true;
6273 }
6274 return;
6275 }
6276 }
6277 if (manifestRoute && manifestRoute.hasClientLoader) {
6278 if (manifestRoute.hasLoader) {
6279 foundOptOutRoute = true;
6280 }
6281 try {
6282 let result = await fetchSingleLoader(
6283 handler,
6284 url,
6285 init,
6286 m.route.id
6287 );
6288 results[m.route.id] = { type: "data", result };
6289 } catch (e) {
6290 results[m.route.id] = { type: "error", result: e };
6291 }
6292 return;
6293 }
6294 if (manifestRoute && manifestRoute.hasLoader) {
6295 routesParams.add(m.route.id);
6296 }
6297 try {
6298 let result = await handler(async () => {
6299 let data2 = await singleFetchDfd.promise;
6300 return unwrapSingleFetchResults(data2, m.route.id);
6301 });
6302 results[m.route.id] = {
6303 type: "data",
6304 result
6305 };
6306 } catch (e) {
6307 results[m.route.id] = {
6308 type: "error",
6309 result: e
6310 };
6311 }
6312 })
6313 )
6314 );
6315 await routesLoadedPromise;
6316 if ((!router.state.initialized || routesParams.size === 0) && !window.__reactRouterHdrActive) {
6317 singleFetchDfd.resolve({});
6318 } else {
6319 try {
6320 if (ssr && foundOptOutRoute && routesParams.size > 0) {
6321 url.searchParams.set(
6322 "_routes",
6323 matches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(",")
6324 );
6325 }
6326 let data2 = await fetchAndDecode(url, init);
6327 singleFetchDfd.resolve(data2.data);
6328 } catch (e) {
6329 singleFetchDfd.reject(e);
6330 }
6331 }
6332 await resolvePromise;
6333 return results;
6334}
6335async function singleFetchLoaderFetcherStrategy(request, matches, basename) {
6336 let fetcherMatch = matches.find((m) => m.shouldLoad);
6337 invariant2(fetcherMatch, "No fetcher match found");
6338 let result = await fetcherMatch.resolve(async (handler) => {
6339 let url = stripIndexParam(singleFetchUrl(request.url, basename));
6340 let init = await createRequestInit(request);
6341 return fetchSingleLoader(handler, url, init, fetcherMatch.route.id);
6342 });
6343 return { [fetcherMatch.route.id]: result };
6344}
6345function fetchSingleLoader(handler, url, init, routeId) {
6346 return handler(async () => {
6347 let singleLoaderUrl = new URL(url);
6348 singleLoaderUrl.searchParams.set("_routes", routeId);
6349 let { data: data2 } = await fetchAndDecode(singleLoaderUrl, init);
6350 return unwrapSingleFetchResults(data2, routeId);
6351 });
6352}
6353function stripIndexParam(url) {
6354 let indexValues = url.searchParams.getAll("index");
6355 url.searchParams.delete("index");
6356 let indexValuesToKeep = [];
6357 for (let indexValue of indexValues) {
6358 if (indexValue) {
6359 indexValuesToKeep.push(indexValue);
6360 }
6361 }
6362 for (let toKeep of indexValuesToKeep) {
6363 url.searchParams.append("index", toKeep);
6364 }
6365 return url;
6366}
6367function singleFetchUrl(reqUrl, basename) {
6368 let url = typeof reqUrl === "string" ? new URL(
6369 reqUrl,
6370 // This can be called during the SSR flow via PrefetchPageLinksImpl so
6371 // don't assume window is available
6372 typeof window === "undefined" ? "server://singlefetch/" : window.location.origin
6373 ) : reqUrl;
6374 if (url.pathname === "/") {
6375 url.pathname = "_root.data";
6376 } else if (basename && stripBasename(url.pathname, basename) === "/") {
6377 url.pathname = `${basename.replace(/\/$/, "")}/_root.data`;
6378 } else {
6379 url.pathname = `${url.pathname.replace(/\/$/, "")}.data`;
6380 }
6381 return url;
6382}
6383async function fetchAndDecode(url, init) {
6384 let res = await fetch(url, init);
6385 if (res.status === 404 && !res.headers.has("X-Remix-Response")) {
6386 throw new ErrorResponseImpl(404, "Not Found", true);
6387 }
6388 const NO_BODY_STATUS_CODES2 = /* @__PURE__ */ new Set([100, 101, 204, 205]);
6389 if (NO_BODY_STATUS_CODES2.has(res.status)) {
6390 if (!init.method || init.method === "GET") {
6391 return { status: res.status, data: {} };
6392 } else {
6393 return { status: res.status, data: { data: void 0 } };
6394 }
6395 }
6396 invariant2(res.body, "No response body to decode");
6397 try {
6398 let decoded = await decodeViaTurboStream(res.body, window);
6399 return { status: res.status, data: decoded.value };
6400 } catch (e) {
6401 throw new Error("Unable to decode turbo-stream response");
6402 }
6403}
6404function decodeViaTurboStream(body, global2) {
6405 return (0, import_turbo_stream.decode)(body, {
6406 plugins: [
6407 (type, ...rest) => {
6408 if (type === "SanitizedError") {
6409 let [name, message, stack] = rest;
6410 let Constructor = Error;
6411 if (name && name in global2 && typeof global2[name] === "function") {
6412 Constructor = global2[name];
6413 }
6414 let error = new Constructor(message);
6415 error.stack = stack;
6416 return { value: error };
6417 }
6418 if (type === "ErrorResponse") {
6419 let [data2, status, statusText] = rest;
6420 return {
6421 value: new ErrorResponseImpl(status, statusText, data2)
6422 };
6423 }
6424 if (type === "SingleFetchRedirect") {
6425 return { value: { [SingleFetchRedirectSymbol]: rest[0] } };
6426 }
6427 if (type === "SingleFetchClassInstance") {
6428 return { value: rest[0] };
6429 }
6430 if (type === "SingleFetchFallback") {
6431 return { value: void 0 };
6432 }
6433 }
6434 ]
6435 });
6436}
6437function unwrapSingleFetchResults(results, routeId) {
6438 let redirect2 = results[SingleFetchRedirectSymbol];
6439 if (redirect2) {
6440 return unwrapSingleFetchResult(redirect2, routeId);
6441 }
6442 return results[routeId] !== void 0 ? unwrapSingleFetchResult(results[routeId], routeId) : null;
6443}
6444function unwrapSingleFetchResult(result, routeId) {
6445 if ("error" in result) {
6446 throw result.error;
6447 } else if ("redirect" in result) {
6448 let headers = {};
6449 if (result.revalidate) {
6450 headers["X-Remix-Revalidate"] = "yes";
6451 }
6452 if (result.reload) {
6453 headers["X-Remix-Reload-Document"] = "yes";
6454 }
6455 if (result.replace) {
6456 headers["X-Remix-Replace"] = "yes";
6457 }
6458 throw redirect(result.redirect, { status: result.status, headers });
6459 } else if ("data" in result) {
6460 return result.data;
6461 } else {
6462 throw new Error(`No response found for routeId "${routeId}"`);
6463 }
6464}
6465function createDeferred2() {
6466 let resolve;
6467 let reject;
6468 let promise = new Promise((res, rej) => {
6469 resolve = async (val) => {
6470 res(val);
6471 try {
6472 await promise;
6473 } catch (e) {
6474 }
6475 };
6476 reject = async (error) => {
6477 rej(error);
6478 try {
6479 await promise;
6480 } catch (e) {
6481 }
6482 };
6483 });
6484 return {
6485 promise,
6486 //@ts-ignore
6487 resolve,
6488 //@ts-ignore
6489 reject
6490 };
6491}
6492
6493// lib/dom/ssr/fog-of-war.ts
6494var React8 = __toESM(require("react"));
6495
6496// lib/dom/ssr/routes.tsx
6497var React7 = __toESM(require("react"));
6498
6499// lib/dom/ssr/errorBoundaries.tsx
6500var React5 = __toESM(require("react"));
6501var RemixErrorBoundary = class extends React5.Component {
6502 constructor(props) {
6503 super(props);
6504 this.state = { error: props.error || null, location: props.location };
6505 }
6506 static getDerivedStateFromError(error) {
6507 return { error };
6508 }
6509 static getDerivedStateFromProps(props, state) {
6510 if (state.location !== props.location) {
6511 return { error: props.error || null, location: props.location };
6512 }
6513 return { error: props.error || state.error, location: state.location };
6514 }
6515 render() {
6516 if (this.state.error) {
6517 return /* @__PURE__ */ React5.createElement(
6518 RemixRootDefaultErrorBoundary,
6519 {
6520 error: this.state.error,
6521 isOutsideRemixApp: true
6522 }
6523 );
6524 } else {
6525 return this.props.children;
6526 }
6527 }
6528};
6529function RemixRootDefaultErrorBoundary({
6530 error,
6531 isOutsideRemixApp
6532}) {
6533 console.error(error);
6534 let heyDeveloper = /* @__PURE__ */ React5.createElement(
6535 "script",
6536 {
6537 dangerouslySetInnerHTML: {
6538 __html: `
6539 console.log(
6540 "\u{1F4BF} Hey developer \u{1F44B}. You can provide a way better UX than this when your app throws errors. Check out https://remix.run/guides/errors for more information."
6541 );
6542 `
6543 }
6544 }
6545 );
6546 if (isRouteErrorResponse(error)) {
6547 return /* @__PURE__ */ React5.createElement(BoundaryShell, { title: "Unhandled Thrown Response!" }, /* @__PURE__ */ React5.createElement("h1", { style: { fontSize: "24px" } }, error.status, " ", error.statusText), heyDeveloper);
6548 }
6549 let errorInstance;
6550 if (error instanceof Error) {
6551 errorInstance = error;
6552 } else {
6553 let errorString = error == null ? "Unknown Error" : typeof error === "object" && "toString" in error ? error.toString() : JSON.stringify(error);
6554 errorInstance = new Error(errorString);
6555 }
6556 return /* @__PURE__ */ React5.createElement(
6557 BoundaryShell,
6558 {
6559 title: "Application Error!",
6560 isOutsideRemixApp
6561 },
6562 /* @__PURE__ */ React5.createElement("h1", { style: { fontSize: "24px" } }, "Application Error"),
6563 /* @__PURE__ */ React5.createElement(
6564 "pre",
6565 {
6566 style: {
6567 padding: "2rem",
6568 background: "hsla(10, 50%, 50%, 0.1)",
6569 color: "red",
6570 overflow: "auto"
6571 }
6572 },
6573 errorInstance.stack
6574 ),
6575 heyDeveloper
6576 );
6577}
6578function BoundaryShell({
6579 title,
6580 renderScripts,
6581 isOutsideRemixApp,
6582 children
6583}) {
6584 let { routeModules } = useFrameworkContext();
6585 if (routeModules.root?.Layout && !isOutsideRemixApp) {
6586 return children;
6587 }
6588 return /* @__PURE__ */ React5.createElement("html", { lang: "en" }, /* @__PURE__ */ React5.createElement("head", null, /* @__PURE__ */ React5.createElement("meta", { charSet: "utf-8" }), /* @__PURE__ */ React5.createElement(
6589 "meta",
6590 {
6591 name: "viewport",
6592 content: "width=device-width,initial-scale=1,viewport-fit=cover"
6593 }
6594 ), /* @__PURE__ */ React5.createElement("title", null, title)), /* @__PURE__ */ React5.createElement("body", null, /* @__PURE__ */ React5.createElement("main", { style: { fontFamily: "system-ui, sans-serif", padding: "2rem" } }, children, renderScripts ? /* @__PURE__ */ React5.createElement(Scripts, null) : null)));
6595}
6596
6597// lib/dom/ssr/fallback.tsx
6598var React6 = __toESM(require("react"));
6599function RemixRootDefaultHydrateFallback() {
6600 return /* @__PURE__ */ React6.createElement(BoundaryShell, { title: "Loading...", renderScripts: true }, /* @__PURE__ */ React6.createElement(
6601 "script",
6602 {
6603 dangerouslySetInnerHTML: {
6604 __html: `
6605 console.log(
6606 "\u{1F4BF} Hey developer \u{1F44B}. You can provide a way better UX than this " +
6607 "when your app is loading JS modules and/or running \`clientLoader\` " +
6608 "functions. Check out https://remix.run/route/hydrate-fallback " +
6609 "for more information."
6610 );
6611 `
6612 }
6613 }
6614 ));
6615}
6616
6617// lib/dom/ssr/routes.tsx
6618function groupRoutesByParentId(manifest) {
6619 let routes = {};
6620 Object.values(manifest).forEach((route) => {
6621 if (route) {
6622 let parentId = route.parentId || "";
6623 if (!routes[parentId]) {
6624 routes[parentId] = [];
6625 }
6626 routes[parentId].push(route);
6627 }
6628 });
6629 return routes;
6630}
6631function getRouteComponents(route, routeModule, isSpaMode) {
6632 let Component4 = getRouteModuleComponent(routeModule);
6633 let HydrateFallback = routeModule.HydrateFallback && (!isSpaMode || route.id === "root") ? routeModule.HydrateFallback : route.id === "root" ? RemixRootDefaultHydrateFallback : void 0;
6634 let ErrorBoundary = routeModule.ErrorBoundary ? routeModule.ErrorBoundary : route.id === "root" ? () => /* @__PURE__ */ React7.createElement(RemixRootDefaultErrorBoundary, { error: useRouteError() }) : void 0;
6635 if (route.id === "root" && routeModule.Layout) {
6636 return {
6637 ...Component4 ? {
6638 element: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(Component4, null))
6639 } : { Component: Component4 },
6640 ...ErrorBoundary ? {
6641 errorElement: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(ErrorBoundary, null))
6642 } : { ErrorBoundary },
6643 ...HydrateFallback ? {
6644 hydrateFallbackElement: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(HydrateFallback, null))
6645 } : { HydrateFallback }
6646 };
6647 }
6648 return { Component: Component4, ErrorBoundary, HydrateFallback };
6649}
6650function createServerRoutes(manifest, routeModules, future, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), spaModeLazyPromise = Promise.resolve({ Component: () => null })) {
6651 return (routesByParentId[parentId] || []).map((route) => {
6652 let routeModule = routeModules[route.id];
6653 invariant2(
6654 routeModule,
6655 "No `routeModule` available to create server routes"
6656 );
6657 let dataRoute = {
6658 ...getRouteComponents(route, routeModule, isSpaMode),
6659 caseSensitive: route.caseSensitive,
6660 id: route.id,
6661 index: route.index,
6662 path: route.path,
6663 handle: routeModule.handle,
6664 // For SPA Mode, all routes are lazy except root. However we tell the
6665 // router root is also lazy here too since we don't need a full
6666 // implementation - we just need a `lazy` prop to tell the RR rendering
6667 // where to stop which is always at the root route in SPA mode
6668 lazy: isSpaMode ? () => spaModeLazyPromise : void 0,
6669 // For partial hydration rendering, we need to indicate when the route
6670 // has a loader/clientLoader, but it won't ever be called during the static
6671 // render, so just give it a no-op function so we can render down to the
6672 // proper fallback
6673 loader: route.hasLoader || route.hasClientLoader ? () => null : void 0
6674 // We don't need middleware/action/shouldRevalidate on these routes since
6675 // they're for a static render
6676 };
6677 let children = createServerRoutes(
6678 manifest,
6679 routeModules,
6680 future,
6681 isSpaMode,
6682 route.id,
6683 routesByParentId,
6684 spaModeLazyPromise
6685 );
6686 if (children.length > 0) dataRoute.children = children;
6687 return dataRoute;
6688 });
6689}
6690function createClientRoutesWithHMRRevalidationOptOut(needsRevalidation, manifest, routeModulesCache, initialState, ssr, isSpaMode) {
6691 return createClientRoutes(
6692 manifest,
6693 routeModulesCache,
6694 initialState,
6695 ssr,
6696 isSpaMode,
6697 "",
6698 groupRoutesByParentId(manifest),
6699 needsRevalidation
6700 );
6701}
6702function preventInvalidServerHandlerCall(type, route) {
6703 if (type === "loader" && !route.hasLoader || type === "action" && !route.hasAction) {
6704 let fn = type === "action" ? "serverAction()" : "serverLoader()";
6705 let msg = `You are trying to call ${fn} on a route that does not have a server ${type} (routeId: "${route.id}")`;
6706 console.error(msg);
6707 throw new ErrorResponseImpl(400, "Bad Request", new Error(msg), true);
6708 }
6709}
6710function noActionDefinedError(type, routeId) {
6711 let article = type === "clientAction" ? "a" : "an";
6712 let msg = `Route "${routeId}" does not have ${article} ${type}, but you are trying to submit to it. To fix this, please add ${article} \`${type}\` function to the route`;
6713 console.error(msg);
6714 throw new ErrorResponseImpl(405, "Method Not Allowed", new Error(msg), true);
6715}
6716function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), needsRevalidation) {
6717 return (routesByParentId[parentId] || []).map((route) => {
6718 let routeModule = routeModulesCache[route.id];
6719 function fetchServerHandler(singleFetch) {
6720 invariant2(
6721 typeof singleFetch === "function",
6722 "No single fetch function available for route handler"
6723 );
6724 return singleFetch();
6725 }
6726 function fetchServerLoader(singleFetch) {
6727 if (!route.hasLoader) return Promise.resolve(null);
6728 return fetchServerHandler(singleFetch);
6729 }
6730 function fetchServerAction(singleFetch) {
6731 if (!route.hasAction) {
6732 throw noActionDefinedError("action", route.id);
6733 }
6734 return fetchServerHandler(singleFetch);
6735 }
6736 function prefetchModule(modulePath) {
6737 import(
6738 /* @vite-ignore */
6739 /* webpackIgnore: true */
6740 modulePath
6741 );
6742 }
6743 function prefetchRouteModuleChunks(route2) {
6744 if (route2.clientActionModule) {
6745 prefetchModule(route2.clientActionModule);
6746 }
6747 if (route2.clientLoaderModule) {
6748 prefetchModule(route2.clientLoaderModule);
6749 }
6750 }
6751 async function prefetchStylesAndCallHandler(handler) {
6752 let cachedModule = routeModulesCache[route.id];
6753 let linkPrefetchPromise = cachedModule ? prefetchStyleLinks(route, cachedModule) : Promise.resolve();
6754 try {
6755 return handler();
6756 } finally {
6757 await linkPrefetchPromise;
6758 }
6759 }
6760 let dataRoute = {
6761 id: route.id,
6762 index: route.index,
6763 path: route.path
6764 };
6765 if (routeModule) {
6766 Object.assign(dataRoute, {
6767 ...dataRoute,
6768 ...getRouteComponents(route, routeModule, isSpaMode),
6769 unstable_middleware: routeModule.unstable_clientMiddleware,
6770 handle: routeModule.handle,
6771 shouldRevalidate: getShouldRevalidateFunction(
6772 routeModule,
6773 route,
6774 ssr,
6775 needsRevalidation
6776 )
6777 });
6778 let hasInitialData = initialState && initialState.loaderData && route.id in initialState.loaderData;
6779 let initialData = hasInitialData ? initialState?.loaderData?.[route.id] : void 0;
6780 let hasInitialError = initialState && initialState.errors && route.id in initialState.errors;
6781 let initialError = hasInitialError ? initialState?.errors?.[route.id] : void 0;
6782 let isHydrationRequest = needsRevalidation == null && (routeModule.clientLoader?.hydrate === true || !route.hasLoader);
6783 dataRoute.loader = async ({ request, params, context }, singleFetch) => {
6784 try {
6785 let result = await prefetchStylesAndCallHandler(async () => {
6786 invariant2(
6787 routeModule,
6788 "No `routeModule` available for critical-route loader"
6789 );
6790 if (!routeModule.clientLoader) {
6791 return fetchServerLoader(singleFetch);
6792 }
6793 return routeModule.clientLoader({
6794 request,
6795 params,
6796 context,
6797 async serverLoader() {
6798 preventInvalidServerHandlerCall("loader", route);
6799 if (isHydrationRequest) {
6800 if (hasInitialData) {
6801 return initialData;
6802 }
6803 if (hasInitialError) {
6804 throw initialError;
6805 }
6806 }
6807 return fetchServerLoader(singleFetch);
6808 }
6809 });
6810 });
6811 return result;
6812 } finally {
6813 isHydrationRequest = false;
6814 }
6815 };
6816 dataRoute.loader.hydrate = shouldHydrateRouteLoader(
6817 route,
6818 routeModule,
6819 isSpaMode
6820 );
6821 dataRoute.action = ({ request, params, context }, singleFetch) => {
6822 return prefetchStylesAndCallHandler(async () => {
6823 invariant2(
6824 routeModule,
6825 "No `routeModule` available for critical-route action"
6826 );
6827 if (!routeModule.clientAction) {
6828 if (isSpaMode) {
6829 throw noActionDefinedError("clientAction", route.id);
6830 }
6831 return fetchServerAction(singleFetch);
6832 }
6833 return routeModule.clientAction({
6834 request,
6835 params,
6836 context,
6837 async serverAction() {
6838 preventInvalidServerHandlerCall("action", route);
6839 return fetchServerAction(singleFetch);
6840 }
6841 });
6842 });
6843 };
6844 } else {
6845 if (!route.hasClientLoader) {
6846 dataRoute.loader = (_, singleFetch) => prefetchStylesAndCallHandler(() => {
6847 return fetchServerLoader(singleFetch);
6848 });
6849 } else if (route.clientLoaderModule) {
6850 dataRoute.loader = async (args, singleFetch) => {
6851 invariant2(route.clientLoaderModule);
6852 let { clientLoader } = await import(
6853 /* @vite-ignore */
6854 /* webpackIgnore: true */
6855 route.clientLoaderModule
6856 );
6857 return clientLoader({
6858 ...args,
6859 async serverLoader() {
6860 preventInvalidServerHandlerCall("loader", route);
6861 return fetchServerLoader(singleFetch);
6862 }
6863 });
6864 };
6865 }
6866 if (!route.hasClientAction) {
6867 dataRoute.action = (_, singleFetch) => prefetchStylesAndCallHandler(() => {
6868 if (isSpaMode) {
6869 throw noActionDefinedError("clientAction", route.id);
6870 }
6871 return fetchServerAction(singleFetch);
6872 });
6873 } else if (route.clientActionModule) {
6874 dataRoute.action = async (args, singleFetch) => {
6875 invariant2(route.clientActionModule);
6876 prefetchRouteModuleChunks(route);
6877 let { clientAction } = await import(
6878 /* @vite-ignore */
6879 /* webpackIgnore: true */
6880 route.clientActionModule
6881 );
6882 return clientAction({
6883 ...args,
6884 async serverAction() {
6885 preventInvalidServerHandlerCall("action", route);
6886 return fetchServerAction(singleFetch);
6887 }
6888 });
6889 };
6890 }
6891 dataRoute.lazy = async () => {
6892 if (route.clientLoaderModule || route.clientActionModule) {
6893 await new Promise((resolve) => setTimeout(resolve, 0));
6894 }
6895 let modPromise = loadRouteModuleWithBlockingLinks(
6896 route,
6897 routeModulesCache
6898 );
6899 prefetchRouteModuleChunks(route);
6900 let mod = await modPromise;
6901 let lazyRoute = { ...mod };
6902 if (mod.clientLoader) {
6903 let clientLoader = mod.clientLoader;
6904 lazyRoute.loader = (args, singleFetch) => clientLoader({
6905 ...args,
6906 async serverLoader() {
6907 preventInvalidServerHandlerCall("loader", route);
6908 return fetchServerLoader(singleFetch);
6909 }
6910 });
6911 }
6912 if (mod.clientAction) {
6913 let clientAction = mod.clientAction;
6914 lazyRoute.action = (args, singleFetch) => clientAction({
6915 ...args,
6916 async serverAction() {
6917 preventInvalidServerHandlerCall("action", route);
6918 return fetchServerAction(singleFetch);
6919 }
6920 });
6921 }
6922 return {
6923 ...lazyRoute.loader ? { loader: lazyRoute.loader } : {},
6924 ...lazyRoute.action ? { action: lazyRoute.action } : {},
6925 unstable_middleware: mod.unstable_clientMiddleware,
6926 hasErrorBoundary: lazyRoute.hasErrorBoundary,
6927 shouldRevalidate: getShouldRevalidateFunction(
6928 lazyRoute,
6929 route,
6930 ssr,
6931 needsRevalidation
6932 ),
6933 handle: lazyRoute.handle,
6934 // No need to wrap these in layout since the root route is never
6935 // loaded via route.lazy()
6936 Component: lazyRoute.Component,
6937 ErrorBoundary: lazyRoute.ErrorBoundary
6938 };
6939 };
6940 }
6941 let children = createClientRoutes(
6942 manifest,
6943 routeModulesCache,
6944 initialState,
6945 ssr,
6946 isSpaMode,
6947 route.id,
6948 routesByParentId,
6949 needsRevalidation
6950 );
6951 if (children.length > 0) dataRoute.children = children;
6952 return dataRoute;
6953 });
6954}
6955function getShouldRevalidateFunction(route, manifestRoute, ssr, needsRevalidation) {
6956 if (needsRevalidation) {
6957 return wrapShouldRevalidateForHdr(
6958 manifestRoute.id,
6959 route.shouldRevalidate,
6960 needsRevalidation
6961 );
6962 }
6963 if (!ssr && manifestRoute.hasLoader && !manifestRoute.hasClientLoader) {
6964 if (route.shouldRevalidate) {
6965 let fn = route.shouldRevalidate;
6966 return (opts) => fn({ ...opts, defaultShouldRevalidate: false });
6967 } else {
6968 return () => false;
6969 }
6970 }
6971 if (ssr && route.shouldRevalidate) {
6972 let fn = route.shouldRevalidate;
6973 return (opts) => fn({ ...opts, defaultShouldRevalidate: true });
6974 }
6975 return route.shouldRevalidate;
6976}
6977function wrapShouldRevalidateForHdr(routeId, routeShouldRevalidate, needsRevalidation) {
6978 let handledRevalidation = false;
6979 return (arg) => {
6980 if (!handledRevalidation) {
6981 handledRevalidation = true;
6982 return needsRevalidation.has(routeId);
6983 }
6984 return routeShouldRevalidate ? routeShouldRevalidate(arg) : arg.defaultShouldRevalidate;
6985 };
6986}
6987async function loadRouteModuleWithBlockingLinks(route, routeModules) {
6988 let routeModulePromise = loadRouteModule(route, routeModules);
6989 let prefetchRouteCssPromise = prefetchRouteCss(route);
6990 let routeModule = await routeModulePromise;
6991 await Promise.all([
6992 prefetchRouteCssPromise,
6993 prefetchStyleLinks(route, routeModule)
6994 ]);
6995 return {
6996 Component: getRouteModuleComponent(routeModule),
6997 ErrorBoundary: routeModule.ErrorBoundary,
6998 unstable_clientMiddleware: routeModule.unstable_clientMiddleware,
6999 clientAction: routeModule.clientAction,
7000 clientLoader: routeModule.clientLoader,
7001 handle: routeModule.handle,
7002 links: routeModule.links,
7003 meta: routeModule.meta,
7004 shouldRevalidate: routeModule.shouldRevalidate
7005 };
7006}
7007function getRouteModuleComponent(routeModule) {
7008 if (routeModule.default == null) return void 0;
7009 let isEmptyObject = typeof routeModule.default === "object" && Object.keys(routeModule.default).length === 0;
7010 if (!isEmptyObject) {
7011 return routeModule.default;
7012 }
7013}
7014function shouldHydrateRouteLoader(route, routeModule, isSpaMode) {
7015 return isSpaMode && route.id !== "root" || routeModule.clientLoader != null && (routeModule.clientLoader.hydrate === true || route.hasLoader !== true);
7016}
7017
7018// lib/dom/ssr/fog-of-war.ts
7019var nextPaths = /* @__PURE__ */ new Set();
7020var discoveredPathsMaxSize = 1e3;
7021var discoveredPaths = /* @__PURE__ */ new Set();
7022var URL_LIMIT = 7680;
7023function isFogOfWarEnabled(ssr) {
7024 return ssr === true;
7025}
7026function getPartialManifest(manifest, router) {
7027 let routeIds = new Set(router.state.matches.map((m) => m.route.id));
7028 let segments = router.state.location.pathname.split("/").filter(Boolean);
7029 let paths = ["/"];
7030 segments.pop();
7031 while (segments.length > 0) {
7032 paths.push(`/${segments.join("/")}`);
7033 segments.pop();
7034 }
7035 paths.forEach((path) => {
7036 let matches = matchRoutes(router.routes, path, router.basename);
7037 if (matches) {
7038 matches.forEach((m) => routeIds.add(m.route.id));
7039 }
7040 });
7041 let initialRoutes = [...routeIds].reduce(
7042 (acc, id) => Object.assign(acc, { [id]: manifest.routes[id] }),
7043 {}
7044 );
7045 return {
7046 ...manifest,
7047 routes: initialRoutes
7048 };
7049}
7050function getPatchRoutesOnNavigationFunction(manifest, routeModules, ssr, isSpaMode, basename) {
7051 if (!isFogOfWarEnabled(ssr)) {
7052 return void 0;
7053 }
7054 return async ({ path, patch, signal, fetcherKey }) => {
7055 if (discoveredPaths.has(path)) {
7056 return;
7057 }
7058 await fetchAndApplyManifestPatches(
7059 [path],
7060 fetcherKey ? window.location.href : path,
7061 manifest,
7062 routeModules,
7063 ssr,
7064 isSpaMode,
7065 basename,
7066 patch,
7067 signal
7068 );
7069 };
7070}
7071function useFogOFWarDiscovery(router, manifest, routeModules, ssr, isSpaMode) {
7072 React8.useEffect(() => {
7073 if (!isFogOfWarEnabled(ssr) || navigator.connection?.saveData === true) {
7074 return;
7075 }
7076 function registerElement(el) {
7077 let path = el.tagName === "FORM" ? el.getAttribute("action") : el.getAttribute("href");
7078 if (!path) {
7079 return;
7080 }
7081 let pathname = el.tagName === "A" ? el.pathname : new URL(path, window.location.origin).pathname;
7082 if (!discoveredPaths.has(pathname)) {
7083 nextPaths.add(pathname);
7084 }
7085 }
7086 async function fetchPatches() {
7087 document.querySelectorAll("a[data-discover], form[data-discover]").forEach(registerElement);
7088 let lazyPaths = Array.from(nextPaths.keys()).filter((path) => {
7089 if (discoveredPaths.has(path)) {
7090 nextPaths.delete(path);
7091 return false;
7092 }
7093 return true;
7094 });
7095 if (lazyPaths.length === 0) {
7096 return;
7097 }
7098 try {
7099 await fetchAndApplyManifestPatches(
7100 lazyPaths,
7101 null,
7102 manifest,
7103 routeModules,
7104 ssr,
7105 isSpaMode,
7106 router.basename,
7107 router.patchRoutes
7108 );
7109 } catch (e) {
7110 console.error("Failed to fetch manifest patches", e);
7111 }
7112 }
7113 let debouncedFetchPatches = debounce(fetchPatches, 100);
7114 fetchPatches();
7115 let observer = new MutationObserver(() => debouncedFetchPatches());
7116 observer.observe(document.documentElement, {
7117 subtree: true,
7118 childList: true,
7119 attributes: true,
7120 attributeFilter: ["data-discover", "href", "action"]
7121 });
7122 return () => observer.disconnect();
7123 }, [ssr, isSpaMode, manifest, routeModules, router]);
7124}
7125var MANIFEST_VERSION_STORAGE_KEY = "react-router-manifest-version";
7126async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, routeModules, ssr, isSpaMode, basename, patchRoutes, signal) {
7127 let manifestPath = `${basename != null ? basename : "/"}/__manifest`.replace(
7128 /\/+/g,
7129 "/"
7130 );
7131 let url = new URL(manifestPath, window.location.origin);
7132 paths.sort().forEach((path) => url.searchParams.append("p", path));
7133 url.searchParams.set("version", manifest.version);
7134 if (url.toString().length > URL_LIMIT) {
7135 nextPaths.clear();
7136 return;
7137 }
7138 let serverPatches;
7139 try {
7140 let res = await fetch(url, { signal });
7141 if (!res.ok) {
7142 throw new Error(`${res.status} ${res.statusText}`);
7143 } else if (res.status === 204 && res.headers.has("X-Remix-Reload-Document")) {
7144 if (!errorReloadPath) {
7145 console.warn(
7146 "Detected a manifest version mismatch during eager route discovery. The next navigation/fetch to an undiscovered route will result in a new document navigation to sync up with the latest manifest."
7147 );
7148 return;
7149 }
7150 if (sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === manifest.version) {
7151 console.error(
7152 "Unable to discover routes due to manifest version mismatch."
7153 );
7154 return;
7155 }
7156 sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, manifest.version);
7157 window.location.href = errorReloadPath;
7158 throw new Error("Detected manifest version mismatch, reloading...");
7159 } else if (res.status >= 400) {
7160 throw new Error(await res.text());
7161 }
7162 sessionStorage.removeItem(MANIFEST_VERSION_STORAGE_KEY);
7163 serverPatches = await res.json();
7164 } catch (e) {
7165 if (signal?.aborted) return;
7166 throw e;
7167 }
7168 let knownRoutes = new Set(Object.keys(manifest.routes));
7169 let patches = Object.values(serverPatches).reduce((acc, route) => {
7170 if (route && !knownRoutes.has(route.id)) {
7171 acc[route.id] = route;
7172 }
7173 return acc;
7174 }, {});
7175 Object.assign(manifest.routes, patches);
7176 paths.forEach((p) => addToFifoQueue(p, discoveredPaths));
7177 let parentIds = /* @__PURE__ */ new Set();
7178 Object.values(patches).forEach((patch) => {
7179 if (patch && (!patch.parentId || !patches[patch.parentId])) {
7180 parentIds.add(patch.parentId);
7181 }
7182 });
7183 parentIds.forEach(
7184 (parentId) => patchRoutes(
7185 parentId || null,
7186 createClientRoutes(patches, routeModules, null, ssr, isSpaMode, parentId)
7187 )
7188 );
7189}
7190function addToFifoQueue(path, queue) {
7191 if (queue.size >= discoveredPathsMaxSize) {
7192 let first = queue.values().next().value;
7193 queue.delete(first);
7194 }
7195 queue.add(path);
7196}
7197function debounce(callback, wait) {
7198 let timeoutId;
7199 return (...args) => {
7200 window.clearTimeout(timeoutId);
7201 timeoutId = window.setTimeout(() => callback(...args), wait);
7202 };
7203}
7204
7205// lib/dom/ssr/components.tsx
7206function useDataRouterContext2() {
7207 let context = React9.useContext(DataRouterContext);
7208 invariant2(
7209 context,
7210 "You must render this element inside a <DataRouterContext.Provider> element"
7211 );
7212 return context;
7213}
7214function useDataRouterStateContext() {
7215 let context = React9.useContext(DataRouterStateContext);
7216 invariant2(
7217 context,
7218 "You must render this element inside a <DataRouterStateContext.Provider> element"
7219 );
7220 return context;
7221}
7222var FrameworkContext = React9.createContext(void 0);
7223FrameworkContext.displayName = "FrameworkContext";
7224function useFrameworkContext() {
7225 let context = React9.useContext(FrameworkContext);
7226 invariant2(
7227 context,
7228 "You must render this element inside a <HydratedRouter> element"
7229 );
7230 return context;
7231}
7232function usePrefetchBehavior(prefetch, theirElementProps) {
7233 let frameworkContext = React9.useContext(FrameworkContext);
7234 let [maybePrefetch, setMaybePrefetch] = React9.useState(false);
7235 let [shouldPrefetch, setShouldPrefetch] = React9.useState(false);
7236 let { onFocus, onBlur, onMouseEnter, onMouseLeave, onTouchStart } = theirElementProps;
7237 let ref = React9.useRef(null);
7238 React9.useEffect(() => {
7239 if (prefetch === "render") {
7240 setShouldPrefetch(true);
7241 }
7242 if (prefetch === "viewport") {
7243 let callback = (entries) => {
7244 entries.forEach((entry) => {
7245 setShouldPrefetch(entry.isIntersecting);
7246 });
7247 };
7248 let observer = new IntersectionObserver(callback, { threshold: 0.5 });
7249 if (ref.current) observer.observe(ref.current);
7250 return () => {
7251 observer.disconnect();
7252 };
7253 }
7254 }, [prefetch]);
7255 React9.useEffect(() => {
7256 if (maybePrefetch) {
7257 let id = setTimeout(() => {
7258 setShouldPrefetch(true);
7259 }, 100);
7260 return () => {
7261 clearTimeout(id);
7262 };
7263 }
7264 }, [maybePrefetch]);
7265 let setIntent = () => {
7266 setMaybePrefetch(true);
7267 };
7268 let cancelIntent = () => {
7269 setMaybePrefetch(false);
7270 setShouldPrefetch(false);
7271 };
7272 if (!frameworkContext) {
7273 return [false, ref, {}];
7274 }
7275 if (prefetch !== "intent") {
7276 return [shouldPrefetch, ref, {}];
7277 }
7278 return [
7279 shouldPrefetch,
7280 ref,
7281 {
7282 onFocus: composeEventHandlers(onFocus, setIntent),
7283 onBlur: composeEventHandlers(onBlur, cancelIntent),
7284 onMouseEnter: composeEventHandlers(onMouseEnter, setIntent),
7285 onMouseLeave: composeEventHandlers(onMouseLeave, cancelIntent),
7286 onTouchStart: composeEventHandlers(onTouchStart, setIntent)
7287 }
7288 ];
7289}
7290function composeEventHandlers(theirHandler, ourHandler) {
7291 return (event) => {
7292 theirHandler && theirHandler(event);
7293 if (!event.defaultPrevented) {
7294 ourHandler(event);
7295 }
7296 };
7297}
7298function getActiveMatches(matches, errors, isSpaMode) {
7299 if (isSpaMode && !isHydrated) {
7300 return [matches[0]];
7301 }
7302 if (errors) {
7303 let errorIdx = matches.findIndex((m) => errors[m.route.id] !== void 0);
7304 return matches.slice(0, errorIdx + 1);
7305 }
7306 return matches;
7307}
7308function Links() {
7309 let { isSpaMode, manifest, routeModules, criticalCss } = useFrameworkContext();
7310 let { errors, matches: routerMatches } = useDataRouterStateContext();
7311 let matches = getActiveMatches(routerMatches, errors, isSpaMode);
7312 let keyedLinks = React9.useMemo(
7313 () => getKeyedLinksForMatches(matches, routeModules, manifest),
7314 [matches, routeModules, manifest]
7315 );
7316 return /* @__PURE__ */ React9.createElement(React9.Fragment, null, typeof criticalCss === "string" ? /* @__PURE__ */ React9.createElement("style", { dangerouslySetInnerHTML: { __html: criticalCss } }) : null, typeof criticalCss === "object" ? /* @__PURE__ */ React9.createElement("link", { rel: "stylesheet", href: criticalCss.href }) : null, keyedLinks.map(
7317 ({ key, link }) => isPageLinkDescriptor(link) ? /* @__PURE__ */ React9.createElement(PrefetchPageLinks, { key, ...link }) : /* @__PURE__ */ React9.createElement("link", { key, ...link })
7318 ));
7319}
7320function PrefetchPageLinks({
7321 page,
7322 ...dataLinkProps
7323}) {
7324 let { router } = useDataRouterContext2();
7325 let matches = React9.useMemo(
7326 () => matchRoutes(router.routes, page, router.basename),
7327 [router.routes, page, router.basename]
7328 );
7329 if (!matches) {
7330 return null;
7331 }
7332 return /* @__PURE__ */ React9.createElement(PrefetchPageLinksImpl, { page, matches, ...dataLinkProps });
7333}
7334function useKeyedPrefetchLinks(matches) {
7335 let { manifest, routeModules } = useFrameworkContext();
7336 let [keyedPrefetchLinks, setKeyedPrefetchLinks] = React9.useState([]);
7337 React9.useEffect(() => {
7338 let interrupted = false;
7339 void getKeyedPrefetchLinks(matches, manifest, routeModules).then(
7340 (links) => {
7341 if (!interrupted) {
7342 setKeyedPrefetchLinks(links);
7343 }
7344 }
7345 );
7346 return () => {
7347 interrupted = true;
7348 };
7349 }, [matches, manifest, routeModules]);
7350 return keyedPrefetchLinks;
7351}
7352function PrefetchPageLinksImpl({
7353 page,
7354 matches: nextMatches,
7355 ...linkProps
7356}) {
7357 let location = useLocation();
7358 let { manifest, routeModules } = useFrameworkContext();
7359 let { basename } = useDataRouterContext2();
7360 let { loaderData, matches } = useDataRouterStateContext();
7361 let newMatchesForData = React9.useMemo(
7362 () => getNewMatchesForLinks(
7363 page,
7364 nextMatches,
7365 matches,
7366 manifest,
7367 location,
7368 "data"
7369 ),
7370 [page, nextMatches, matches, manifest, location]
7371 );
7372 let newMatchesForAssets = React9.useMemo(
7373 () => getNewMatchesForLinks(
7374 page,
7375 nextMatches,
7376 matches,
7377 manifest,
7378 location,
7379 "assets"
7380 ),
7381 [page, nextMatches, matches, manifest, location]
7382 );
7383 let dataHrefs = React9.useMemo(() => {
7384 if (page === location.pathname + location.search + location.hash) {
7385 return [];
7386 }
7387 let routesParams = /* @__PURE__ */ new Set();
7388 let foundOptOutRoute = false;
7389 nextMatches.forEach((m) => {
7390 let manifestRoute = manifest.routes[m.route.id];
7391 if (!manifestRoute || !manifestRoute.hasLoader) {
7392 return;
7393 }
7394 if (!newMatchesForData.some((m2) => m2.route.id === m.route.id) && m.route.id in loaderData && routeModules[m.route.id]?.shouldRevalidate) {
7395 foundOptOutRoute = true;
7396 } else if (manifestRoute.hasClientLoader) {
7397 foundOptOutRoute = true;
7398 } else {
7399 routesParams.add(m.route.id);
7400 }
7401 });
7402 if (routesParams.size === 0) {
7403 return [];
7404 }
7405 let url = singleFetchUrl(page, basename);
7406 if (foundOptOutRoute && routesParams.size > 0) {
7407 url.searchParams.set(
7408 "_routes",
7409 nextMatches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(",")
7410 );
7411 }
7412 return [url.pathname + url.search];
7413 }, [
7414 basename,
7415 loaderData,
7416 location,
7417 manifest,
7418 newMatchesForData,
7419 nextMatches,
7420 page,
7421 routeModules
7422 ]);
7423 let moduleHrefs = React9.useMemo(
7424 () => getModuleLinkHrefs(newMatchesForAssets, manifest),
7425 [newMatchesForAssets, manifest]
7426 );
7427 let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
7428 return /* @__PURE__ */ React9.createElement(React9.Fragment, null, dataHrefs.map((href2) => /* @__PURE__ */ React9.createElement("link", { key: href2, rel: "prefetch", as: "fetch", href: href2, ...linkProps })), moduleHrefs.map((href2) => /* @__PURE__ */ React9.createElement("link", { key: href2, rel: "modulepreload", href: href2, ...linkProps })), keyedPrefetchLinks.map(({ key, link }) => (
7429 // these don't spread `linkProps` because they are full link descriptors
7430 // already with their own props
7431 /* @__PURE__ */ React9.createElement("link", { key, ...link })
7432 )));
7433}
7434function Meta() {
7435 let { isSpaMode, routeModules } = useFrameworkContext();
7436 let {
7437 errors,
7438 matches: routerMatches,
7439 loaderData
7440 } = useDataRouterStateContext();
7441 let location = useLocation();
7442 let _matches = getActiveMatches(routerMatches, errors, isSpaMode);
7443 let error = null;
7444 if (errors) {
7445 error = errors[_matches[_matches.length - 1].route.id];
7446 }
7447 let meta = [];
7448 let leafMeta = null;
7449 let matches = [];
7450 for (let i = 0; i < _matches.length; i++) {
7451 let _match = _matches[i];
7452 let routeId = _match.route.id;
7453 let data2 = loaderData[routeId];
7454 let params = _match.params;
7455 let routeModule = routeModules[routeId];
7456 let routeMeta = [];
7457 let match = {
7458 id: routeId,
7459 data: data2,
7460 meta: [],
7461 params: _match.params,
7462 pathname: _match.pathname,
7463 handle: _match.route.handle,
7464 error
7465 };
7466 matches[i] = match;
7467 if (routeModule?.meta) {
7468 routeMeta = typeof routeModule.meta === "function" ? routeModule.meta({
7469 data: data2,
7470 params,
7471 location,
7472 matches,
7473 error
7474 }) : Array.isArray(routeModule.meta) ? [...routeModule.meta] : routeModule.meta;
7475 } else if (leafMeta) {
7476 routeMeta = [...leafMeta];
7477 }
7478 routeMeta = routeMeta || [];
7479 if (!Array.isArray(routeMeta)) {
7480 throw new Error(
7481 "The route at " + _match.route.path + " returns an invalid value. All route meta functions must return an array of meta objects.\n\nTo reference the meta function API, see https://remix.run/route/meta"
7482 );
7483 }
7484 match.meta = routeMeta;
7485 matches[i] = match;
7486 meta = [...routeMeta];
7487 leafMeta = meta;
7488 }
7489 return /* @__PURE__ */ React9.createElement(React9.Fragment, null, meta.flat().map((metaProps) => {
7490 if (!metaProps) {
7491 return null;
7492 }
7493 if ("tagName" in metaProps) {
7494 let { tagName, ...rest } = metaProps;
7495 if (!isValidMetaTag(tagName)) {
7496 console.warn(
7497 `A meta object uses an invalid tagName: ${tagName}. Expected either 'link' or 'meta'`
7498 );
7499 return null;
7500 }
7501 let Comp = tagName;
7502 return /* @__PURE__ */ React9.createElement(Comp, { key: JSON.stringify(rest), ...rest });
7503 }
7504 if ("title" in metaProps) {
7505 return /* @__PURE__ */ React9.createElement("title", { key: "title" }, String(metaProps.title));
7506 }
7507 if ("charset" in metaProps) {
7508 metaProps.charSet ?? (metaProps.charSet = metaProps.charset);
7509 delete metaProps.charset;
7510 }
7511 if ("charSet" in metaProps && metaProps.charSet != null) {
7512 return typeof metaProps.charSet === "string" ? /* @__PURE__ */ React9.createElement("meta", { key: "charSet", charSet: metaProps.charSet }) : null;
7513 }
7514 if ("script:ld+json" in metaProps) {
7515 try {
7516 let json = JSON.stringify(metaProps["script:ld+json"]);
7517 return /* @__PURE__ */ React9.createElement(
7518 "script",
7519 {
7520 key: `script:ld+json:${json}`,
7521 type: "application/ld+json",
7522 dangerouslySetInnerHTML: { __html: json }
7523 }
7524 );
7525 } catch (err) {
7526 return null;
7527 }
7528 }
7529 return /* @__PURE__ */ React9.createElement("meta", { key: JSON.stringify(metaProps), ...metaProps });
7530 }));
7531}
7532function isValidMetaTag(tagName) {
7533 return typeof tagName === "string" && /^(meta|link)$/.test(tagName);
7534}
7535var isHydrated = false;
7536function Scripts(props) {
7537 let { manifest, serverHandoffString, isSpaMode, ssr, renderMeta } = useFrameworkContext();
7538 let { router, static: isStatic, staticContext } = useDataRouterContext2();
7539 let { matches: routerMatches } = useDataRouterStateContext();
7540 let enableFogOfWar = isFogOfWarEnabled(ssr);
7541 if (renderMeta) {
7542 renderMeta.didRenderScripts = true;
7543 }
7544 let matches = getActiveMatches(routerMatches, null, isSpaMode);
7545 React9.useEffect(() => {
7546 isHydrated = true;
7547 }, []);
7548 let initialScripts = React9.useMemo(() => {
7549 let streamScript = "window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());";
7550 let contextScript = staticContext ? `window.__reactRouterContext = ${serverHandoffString};${streamScript}` : " ";
7551 let routeModulesScript = !isStatic ? " " : `${manifest.hmr?.runtime ? `import ${JSON.stringify(manifest.hmr.runtime)};` : ""}${!enableFogOfWar ? `import ${JSON.stringify(manifest.url)}` : ""};
7552${matches.map((match, routeIndex) => {
7553 let routeVarName = `route${routeIndex}`;
7554 let manifestEntry = manifest.routes[match.route.id];
7555 invariant2(manifestEntry, `Route ${match.route.id} not found in manifest`);
7556 let {
7557 clientActionModule,
7558 clientLoaderModule,
7559 hydrateFallbackModule,
7560 module: module2
7561 } = manifestEntry;
7562 let chunks = [
7563 ...clientActionModule ? [
7564 {
7565 module: clientActionModule,
7566 varName: `${routeVarName}_clientAction`
7567 }
7568 ] : [],
7569 ...clientLoaderModule ? [
7570 {
7571 module: clientLoaderModule,
7572 varName: `${routeVarName}_clientLoader`
7573 }
7574 ] : [],
7575 ...hydrateFallbackModule ? [
7576 {
7577 module: hydrateFallbackModule,
7578 varName: `${routeVarName}_HydrateFallback`
7579 }
7580 ] : [],
7581 { module: module2, varName: `${routeVarName}_main` }
7582 ];
7583 if (chunks.length === 1) {
7584 return `import * as ${routeVarName} from ${JSON.stringify(module2)};`;
7585 }
7586 let chunkImportsSnippet = chunks.map((chunk) => `import * as ${chunk.varName} from "${chunk.module}";`).join("\n");
7587 let mergedChunksSnippet = `const ${routeVarName} = {${chunks.map((chunk) => `...${chunk.varName}`).join(",")}};`;
7588 return [chunkImportsSnippet, mergedChunksSnippet].join("\n");
7589 }).join("\n")}
7590 ${enableFogOfWar ? (
7591 // Inline a minimal manifest with the SSR matches
7592 `window.__reactRouterManifest = ${JSON.stringify(
7593 getPartialManifest(manifest, router),
7594 null,
7595 2
7596 )};`
7597 ) : ""}
7598 window.__reactRouterRouteModules = {${matches.map((match, index) => `${JSON.stringify(match.route.id)}:route${index}`).join(",")}};
7599
7600import(${JSON.stringify(manifest.entry.module)});`;
7601 return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
7602 "script",
7603 {
7604 ...props,
7605 suppressHydrationWarning: true,
7606 dangerouslySetInnerHTML: createHtml(contextScript),
7607 type: void 0
7608 }
7609 ), /* @__PURE__ */ React9.createElement(
7610 "script",
7611 {
7612 ...props,
7613 suppressHydrationWarning: true,
7614 dangerouslySetInnerHTML: createHtml(routeModulesScript),
7615 type: "module",
7616 async: true
7617 }
7618 ));
7619 }, []);
7620 let preloads = isHydrated ? [] : manifest.entry.imports.concat(
7621 getModuleLinkHrefs(matches, manifest, {
7622 includeHydrateFallback: true
7623 })
7624 );
7625 return isHydrated ? null : /* @__PURE__ */ React9.createElement(React9.Fragment, null, !enableFogOfWar ? /* @__PURE__ */ React9.createElement(
7626 "link",
7627 {
7628 rel: "modulepreload",
7629 href: manifest.url,
7630 crossOrigin: props.crossOrigin
7631 }
7632 ) : null, /* @__PURE__ */ React9.createElement(
7633 "link",
7634 {
7635 rel: "modulepreload",
7636 href: manifest.entry.module,
7637 crossOrigin: props.crossOrigin
7638 }
7639 ), dedupe(preloads).map((path) => /* @__PURE__ */ React9.createElement(
7640 "link",
7641 {
7642 key: path,
7643 rel: "modulepreload",
7644 href: path,
7645 crossOrigin: props.crossOrigin
7646 }
7647 )), initialScripts);
7648}
7649function dedupe(array) {
7650 return [...new Set(array)];
7651}
7652function mergeRefs(...refs) {
7653 return (value) => {
7654 refs.forEach((ref) => {
7655 if (typeof ref === "function") {
7656 ref(value);
7657 } else if (ref != null) {
7658 ref.current = value;
7659 }
7660 });
7661 };
7662}
7663
7664// lib/dom/lib.tsx
7665var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
7666try {
7667 if (isBrowser) {
7668 window.__reactRouterVersion = "7.4.0";
7669 }
7670} catch (e) {
7671}
7672function createBrowserRouter(routes, opts) {
7673 return createRouter({
7674 basename: opts?.basename,
7675 unstable_getContext: opts?.unstable_getContext,
7676 future: opts?.future,
7677 history: createBrowserHistory({ window: opts?.window }),
7678 hydrationData: opts?.hydrationData || parseHydrationData(),
7679 routes,
7680 mapRouteProperties,
7681 dataStrategy: opts?.dataStrategy,
7682 patchRoutesOnNavigation: opts?.patchRoutesOnNavigation,
7683 window: opts?.window
7684 }).initialize();
7685}
7686function createHashRouter(routes, opts) {
7687 return createRouter({
7688 basename: opts?.basename,
7689 unstable_getContext: opts?.unstable_getContext,
7690 future: opts?.future,
7691 history: createHashHistory({ window: opts?.window }),
7692 hydrationData: opts?.hydrationData || parseHydrationData(),
7693 routes,
7694 mapRouteProperties,
7695 dataStrategy: opts?.dataStrategy,
7696 patchRoutesOnNavigation: opts?.patchRoutesOnNavigation,
7697 window: opts?.window
7698 }).initialize();
7699}
7700function parseHydrationData() {
7701 let state = window?.__staticRouterHydrationData;
7702 if (state && state.errors) {
7703 state = {
7704 ...state,
7705 errors: deserializeErrors(state.errors)
7706 };
7707 }
7708 return state;
7709}
7710function deserializeErrors(errors) {
7711 if (!errors) return null;
7712 let entries = Object.entries(errors);
7713 let serialized = {};
7714 for (let [key, val] of entries) {
7715 if (val && val.__type === "RouteErrorResponse") {
7716 serialized[key] = new ErrorResponseImpl(
7717 val.status,
7718 val.statusText,
7719 val.data,
7720 val.internal === true
7721 );
7722 } else if (val && val.__type === "Error") {
7723 if (val.__subType) {
7724 let ErrorConstructor = window[val.__subType];
7725 if (typeof ErrorConstructor === "function") {
7726 try {
7727 let error = new ErrorConstructor(val.message);
7728 error.stack = "";
7729 serialized[key] = error;
7730 } catch (e) {
7731 }
7732 }
7733 }
7734 if (serialized[key] == null) {
7735 let error = new Error(val.message);
7736 error.stack = "";
7737 serialized[key] = error;
7738 }
7739 } else {
7740 serialized[key] = val;
7741 }
7742 }
7743 return serialized;
7744}
7745function BrowserRouter({
7746 basename,
7747 children,
7748 window: window2
7749}) {
7750 let historyRef = React10.useRef();
7751 if (historyRef.current == null) {
7752 historyRef.current = createBrowserHistory({ window: window2, v5Compat: true });
7753 }
7754 let history = historyRef.current;
7755 let [state, setStateImpl] = React10.useState({
7756 action: history.action,
7757 location: history.location
7758 });
7759 let setState = React10.useCallback(
7760 (newState) => {
7761 React10.startTransition(() => setStateImpl(newState));
7762 },
7763 [setStateImpl]
7764 );
7765 React10.useLayoutEffect(() => history.listen(setState), [history, setState]);
7766 return /* @__PURE__ */ React10.createElement(
7767 Router,
7768 {
7769 basename,
7770 children,
7771 location: state.location,
7772 navigationType: state.action,
7773 navigator: history
7774 }
7775 );
7776}
7777function HashRouter({ basename, children, window: window2 }) {
7778 let historyRef = React10.useRef();
7779 if (historyRef.current == null) {
7780 historyRef.current = createHashHistory({ window: window2, v5Compat: true });
7781 }
7782 let history = historyRef.current;
7783 let [state, setStateImpl] = React10.useState({
7784 action: history.action,
7785 location: history.location
7786 });
7787 let setState = React10.useCallback(
7788 (newState) => {
7789 React10.startTransition(() => setStateImpl(newState));
7790 },
7791 [setStateImpl]
7792 );
7793 React10.useLayoutEffect(() => history.listen(setState), [history, setState]);
7794 return /* @__PURE__ */ React10.createElement(
7795 Router,
7796 {
7797 basename,
7798 children,
7799 location: state.location,
7800 navigationType: state.action,
7801 navigator: history
7802 }
7803 );
7804}
7805function HistoryRouter({
7806 basename,
7807 children,
7808 history
7809}) {
7810 let [state, setStateImpl] = React10.useState({
7811 action: history.action,
7812 location: history.location
7813 });
7814 let setState = React10.useCallback(
7815 (newState) => {
7816 React10.startTransition(() => setStateImpl(newState));
7817 },
7818 [setStateImpl]
7819 );
7820 React10.useLayoutEffect(() => history.listen(setState), [history, setState]);
7821 return /* @__PURE__ */ React10.createElement(
7822 Router,
7823 {
7824 basename,
7825 children,
7826 location: state.location,
7827 navigationType: state.action,
7828 navigator: history
7829 }
7830 );
7831}
7832HistoryRouter.displayName = "unstable_HistoryRouter";
7833var ABSOLUTE_URL_REGEX2 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
7834var Link = React10.forwardRef(
7835 function LinkWithRef({
7836 onClick,
7837 discover = "render",
7838 prefetch = "none",
7839 relative,
7840 reloadDocument,
7841 replace: replace2,
7842 state,
7843 target,
7844 to,
7845 preventScrollReset,
7846 viewTransition,
7847 ...rest
7848 }, forwardedRef) {
7849 let { basename } = React10.useContext(NavigationContext);
7850 let isAbsolute = typeof to === "string" && ABSOLUTE_URL_REGEX2.test(to);
7851 let absoluteHref;
7852 let isExternal = false;
7853 if (typeof to === "string" && isAbsolute) {
7854 absoluteHref = to;
7855 if (isBrowser) {
7856 try {
7857 let currentUrl = new URL(window.location.href);
7858 let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
7859 let path = stripBasename(targetUrl.pathname, basename);
7860 if (targetUrl.origin === currentUrl.origin && path != null) {
7861 to = path + targetUrl.search + targetUrl.hash;
7862 } else {
7863 isExternal = true;
7864 }
7865 } catch (e) {
7866 warning(
7867 false,
7868 `<Link to="${to}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`
7869 );
7870 }
7871 }
7872 }
7873 let href2 = useHref(to, { relative });
7874 let [shouldPrefetch, prefetchRef, prefetchHandlers] = usePrefetchBehavior(
7875 prefetch,
7876 rest
7877 );
7878 let internalOnClick = useLinkClickHandler(to, {
7879 replace: replace2,
7880 state,
7881 target,
7882 preventScrollReset,
7883 relative,
7884 viewTransition
7885 });
7886 function handleClick(event) {
7887 if (onClick) onClick(event);
7888 if (!event.defaultPrevented) {
7889 internalOnClick(event);
7890 }
7891 }
7892 let link = (
7893 // eslint-disable-next-line jsx-a11y/anchor-has-content
7894 /* @__PURE__ */ React10.createElement(
7895 "a",
7896 {
7897 ...rest,
7898 ...prefetchHandlers,
7899 href: absoluteHref || href2,
7900 onClick: isExternal || reloadDocument ? onClick : handleClick,
7901 ref: mergeRefs(forwardedRef, prefetchRef),
7902 target,
7903 "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
7904 }
7905 )
7906 );
7907 return shouldPrefetch && !isAbsolute ? /* @__PURE__ */ React10.createElement(React10.Fragment, null, link, /* @__PURE__ */ React10.createElement(PrefetchPageLinks, { page: href2 })) : link;
7908 }
7909);
7910Link.displayName = "Link";
7911var NavLink = React10.forwardRef(
7912 function NavLinkWithRef({
7913 "aria-current": ariaCurrentProp = "page",
7914 caseSensitive = false,
7915 className: classNameProp = "",
7916 end = false,
7917 style: styleProp,
7918 to,
7919 viewTransition,
7920 children,
7921 ...rest
7922 }, ref) {
7923 let path = useResolvedPath(to, { relative: rest.relative });
7924 let location = useLocation();
7925 let routerState = React10.useContext(DataRouterStateContext);
7926 let { navigator: navigator2, basename } = React10.useContext(NavigationContext);
7927 let isTransitioning = routerState != null && // Conditional usage is OK here because the usage of a data router is static
7928 // eslint-disable-next-line react-hooks/rules-of-hooks
7929 useViewTransitionState(path) && viewTransition === true;
7930 let toPathname = navigator2.encodeLocation ? navigator2.encodeLocation(path).pathname : path.pathname;
7931 let locationPathname = location.pathname;
7932 let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
7933 if (!caseSensitive) {
7934 locationPathname = locationPathname.toLowerCase();
7935 nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
7936 toPathname = toPathname.toLowerCase();
7937 }
7938 if (nextLocationPathname && basename) {
7939 nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
7940 }
7941 const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
7942 let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
7943 let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
7944 let renderProps = {
7945 isActive,
7946 isPending,
7947 isTransitioning
7948 };
7949 let ariaCurrent = isActive ? ariaCurrentProp : void 0;
7950 let className;
7951 if (typeof classNameProp === "function") {
7952 className = classNameProp(renderProps);
7953 } else {
7954 className = [
7955 classNameProp,
7956 isActive ? "active" : null,
7957 isPending ? "pending" : null,
7958 isTransitioning ? "transitioning" : null
7959 ].filter(Boolean).join(" ");
7960 }
7961 let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
7962 return /* @__PURE__ */ React10.createElement(
7963 Link,
7964 {
7965 ...rest,
7966 "aria-current": ariaCurrent,
7967 className,
7968 ref,
7969 style,
7970 to,
7971 viewTransition
7972 },
7973 typeof children === "function" ? children(renderProps) : children
7974 );
7975 }
7976);
7977NavLink.displayName = "NavLink";
7978var Form = React10.forwardRef(
7979 ({
7980 discover = "render",
7981 fetcherKey,
7982 navigate,
7983 reloadDocument,
7984 replace: replace2,
7985 state,
7986 method = defaultMethod,
7987 action,
7988 onSubmit,
7989 relative,
7990 preventScrollReset,
7991 viewTransition,
7992 ...props
7993 }, forwardedRef) => {
7994 let submit = useSubmit();
7995 let formAction = useFormAction(action, { relative });
7996 let formMethod = method.toLowerCase() === "get" ? "get" : "post";
7997 let isAbsolute = typeof action === "string" && ABSOLUTE_URL_REGEX2.test(action);
7998 let submitHandler = (event) => {
7999 onSubmit && onSubmit(event);
8000 if (event.defaultPrevented) return;
8001 event.preventDefault();
8002 let submitter = event.nativeEvent.submitter;
8003 let submitMethod = submitter?.getAttribute("formmethod") || method;
8004 submit(submitter || event.currentTarget, {
8005 fetcherKey,
8006 method: submitMethod,
8007 navigate,
8008 replace: replace2,
8009 state,
8010 relative,
8011 preventScrollReset,
8012 viewTransition
8013 });
8014 };
8015 return /* @__PURE__ */ React10.createElement(
8016 "form",
8017 {
8018 ref: forwardedRef,
8019 method: formMethod,
8020 action: formAction,
8021 onSubmit: reloadDocument ? onSubmit : submitHandler,
8022 ...props,
8023 "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
8024 }
8025 );
8026 }
8027);
8028Form.displayName = "Form";
8029function ScrollRestoration({
8030 getKey,
8031 storageKey,
8032 ...props
8033}) {
8034 let remixContext = React10.useContext(FrameworkContext);
8035 let { basename } = React10.useContext(NavigationContext);
8036 let location = useLocation();
8037 let matches = useMatches();
8038 useScrollRestoration({ getKey, storageKey });
8039 let ssrKey = React10.useMemo(
8040 () => {
8041 if (!remixContext || !getKey) return null;
8042 let userKey = getScrollRestorationKey(
8043 location,
8044 matches,
8045 basename,
8046 getKey
8047 );
8048 return userKey !== location.key ? userKey : null;
8049 },
8050 // Nah, we only need this the first time for the SSR render
8051 // eslint-disable-next-line react-hooks/exhaustive-deps
8052 []
8053 );
8054 if (!remixContext || remixContext.isSpaMode) {
8055 return null;
8056 }
8057 let restoreScroll = ((storageKey2, restoreKey) => {
8058 if (!window.history.state || !window.history.state.key) {
8059 let key = Math.random().toString(32).slice(2);
8060 window.history.replaceState({ key }, "");
8061 }
8062 try {
8063 let positions = JSON.parse(sessionStorage.getItem(storageKey2) || "{}");
8064 let storedY = positions[restoreKey || window.history.state.key];
8065 if (typeof storedY === "number") {
8066 window.scrollTo(0, storedY);
8067 }
8068 } catch (error) {
8069 console.error(error);
8070 sessionStorage.removeItem(storageKey2);
8071 }
8072 }).toString();
8073 return /* @__PURE__ */ React10.createElement(
8074 "script",
8075 {
8076 ...props,
8077 suppressHydrationWarning: true,
8078 dangerouslySetInnerHTML: {
8079 __html: `(${restoreScroll})(${JSON.stringify(
8080 storageKey || SCROLL_RESTORATION_STORAGE_KEY
8081 )}, ${JSON.stringify(ssrKey)})`
8082 }
8083 }
8084 );
8085}
8086ScrollRestoration.displayName = "ScrollRestoration";
8087function getDataRouterConsoleError2(hookName) {
8088 return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
8089}
8090function useDataRouterContext3(hookName) {
8091 let ctx = React10.useContext(DataRouterContext);
8092 invariant(ctx, getDataRouterConsoleError2(hookName));
8093 return ctx;
8094}
8095function useDataRouterState2(hookName) {
8096 let state = React10.useContext(DataRouterStateContext);
8097 invariant(state, getDataRouterConsoleError2(hookName));
8098 return state;
8099}
8100function useLinkClickHandler(to, {
8101 target,
8102 replace: replaceProp,
8103 state,
8104 preventScrollReset,
8105 relative,
8106 viewTransition
8107} = {}) {
8108 let navigate = useNavigate();
8109 let location = useLocation();
8110 let path = useResolvedPath(to, { relative });
8111 return React10.useCallback(
8112 (event) => {
8113 if (shouldProcessLinkClick(event, target)) {
8114 event.preventDefault();
8115 let replace2 = replaceProp !== void 0 ? replaceProp : createPath(location) === createPath(path);
8116 navigate(to, {
8117 replace: replace2,
8118 state,
8119 preventScrollReset,
8120 relative,
8121 viewTransition
8122 });
8123 }
8124 },
8125 [
8126 location,
8127 navigate,
8128 path,
8129 replaceProp,
8130 state,
8131 target,
8132 to,
8133 preventScrollReset,
8134 relative,
8135 viewTransition
8136 ]
8137 );
8138}
8139function useSearchParams(defaultInit) {
8140 warning(
8141 typeof URLSearchParams !== "undefined",
8142 `You cannot use the \`useSearchParams\` hook in a browser that does not support the URLSearchParams API. If you need to support Internet Explorer 11, we recommend you load a polyfill such as https://github.com/ungap/url-search-params.`
8143 );
8144 let defaultSearchParamsRef = React10.useRef(createSearchParams(defaultInit));
8145 let hasSetSearchParamsRef = React10.useRef(false);
8146 let location = useLocation();
8147 let searchParams = React10.useMemo(
8148 () => (
8149 // Only merge in the defaults if we haven't yet called setSearchParams.
8150 // Once we call that we want those to take precedence, otherwise you can't
8151 // remove a param with setSearchParams({}) if it has an initial value
8152 getSearchParamsForLocation(
8153 location.search,
8154 hasSetSearchParamsRef.current ? null : defaultSearchParamsRef.current
8155 )
8156 ),
8157 [location.search]
8158 );
8159 let navigate = useNavigate();
8160 let setSearchParams = React10.useCallback(
8161 (nextInit, navigateOptions) => {
8162 const newSearchParams = createSearchParams(
8163 typeof nextInit === "function" ? nextInit(searchParams) : nextInit
8164 );
8165 hasSetSearchParamsRef.current = true;
8166 navigate("?" + newSearchParams, navigateOptions);
8167 },
8168 [navigate, searchParams]
8169 );
8170 return [searchParams, setSearchParams];
8171}
8172var fetcherId = 0;
8173var getUniqueFetcherId = () => `__${String(++fetcherId)}__`;
8174function useSubmit() {
8175 let { router } = useDataRouterContext3("useSubmit" /* UseSubmit */);
8176 let { basename } = React10.useContext(NavigationContext);
8177 let currentRouteId = useRouteId();
8178 return React10.useCallback(
8179 async (target, options = {}) => {
8180 let { action, method, encType, formData, body } = getFormSubmissionInfo(
8181 target,
8182 basename
8183 );
8184 if (options.navigate === false) {
8185 let key = options.fetcherKey || getUniqueFetcherId();
8186 await router.fetch(key, currentRouteId, options.action || action, {
8187 preventScrollReset: options.preventScrollReset,
8188 formData,
8189 body,
8190 formMethod: options.method || method,
8191 formEncType: options.encType || encType,
8192 flushSync: options.flushSync
8193 });
8194 } else {
8195 await router.navigate(options.action || action, {
8196 preventScrollReset: options.preventScrollReset,
8197 formData,
8198 body,
8199 formMethod: options.method || method,
8200 formEncType: options.encType || encType,
8201 replace: options.replace,
8202 state: options.state,
8203 fromRouteId: currentRouteId,
8204 flushSync: options.flushSync,
8205 viewTransition: options.viewTransition
8206 });
8207 }
8208 },
8209 [router, basename, currentRouteId]
8210 );
8211}
8212function useFormAction(action, { relative } = {}) {
8213 let { basename } = React10.useContext(NavigationContext);
8214 let routeContext = React10.useContext(RouteContext);
8215 invariant(routeContext, "useFormAction must be used inside a RouteContext");
8216 let [match] = routeContext.matches.slice(-1);
8217 let path = { ...useResolvedPath(action ? action : ".", { relative }) };
8218 let location = useLocation();
8219 if (action == null) {
8220 path.search = location.search;
8221 let params = new URLSearchParams(path.search);
8222 let indexValues = params.getAll("index");
8223 let hasNakedIndexParam = indexValues.some((v) => v === "");
8224 if (hasNakedIndexParam) {
8225 params.delete("index");
8226 indexValues.filter((v) => v).forEach((v) => params.append("index", v));
8227 let qs = params.toString();
8228 path.search = qs ? `?${qs}` : "";
8229 }
8230 }
8231 if ((!action || action === ".") && match.route.index) {
8232 path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
8233 }
8234 if (basename !== "/") {
8235 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
8236 }
8237 return createPath(path);
8238}
8239function useFetcher({
8240 key
8241} = {}) {
8242 let { router } = useDataRouterContext3("useFetcher" /* UseFetcher */);
8243 let state = useDataRouterState2("useFetcher" /* UseFetcher */);
8244 let fetcherData = React10.useContext(FetchersContext);
8245 let route = React10.useContext(RouteContext);
8246 let routeId = route.matches[route.matches.length - 1]?.route.id;
8247 invariant(fetcherData, `useFetcher must be used inside a FetchersContext`);
8248 invariant(route, `useFetcher must be used inside a RouteContext`);
8249 invariant(
8250 routeId != null,
8251 `useFetcher can only be used on routes that contain a unique "id"`
8252 );
8253 let defaultKey = React10.useId();
8254 let [fetcherKey, setFetcherKey] = React10.useState(key || defaultKey);
8255 if (key && key !== fetcherKey) {
8256 setFetcherKey(key);
8257 }
8258 React10.useEffect(() => {
8259 router.getFetcher(fetcherKey);
8260 return () => router.deleteFetcher(fetcherKey);
8261 }, [router, fetcherKey]);
8262 let load = React10.useCallback(
8263 async (href2, opts) => {
8264 invariant(routeId, "No routeId available for fetcher.load()");
8265 await router.fetch(fetcherKey, routeId, href2, opts);
8266 },
8267 [fetcherKey, routeId, router]
8268 );
8269 let submitImpl = useSubmit();
8270 let submit = React10.useCallback(
8271 async (target, opts) => {
8272 await submitImpl(target, {
8273 ...opts,
8274 navigate: false,
8275 fetcherKey
8276 });
8277 },
8278 [fetcherKey, submitImpl]
8279 );
8280 let FetcherForm = React10.useMemo(() => {
8281 let FetcherForm2 = React10.forwardRef(
8282 (props, ref) => {
8283 return /* @__PURE__ */ React10.createElement(Form, { ...props, navigate: false, fetcherKey, ref });
8284 }
8285 );
8286 FetcherForm2.displayName = "fetcher.Form";
8287 return FetcherForm2;
8288 }, [fetcherKey]);
8289 let fetcher = state.fetchers.get(fetcherKey) || IDLE_FETCHER;
8290 let data2 = fetcherData.get(fetcherKey);
8291 let fetcherWithComponents = React10.useMemo(
8292 () => ({
8293 Form: FetcherForm,
8294 submit,
8295 load,
8296 ...fetcher,
8297 data: data2
8298 }),
8299 [FetcherForm, submit, load, fetcher, data2]
8300 );
8301 return fetcherWithComponents;
8302}
8303function useFetchers() {
8304 let state = useDataRouterState2("useFetchers" /* UseFetchers */);
8305 return Array.from(state.fetchers.entries()).map(([key, fetcher]) => ({
8306 ...fetcher,
8307 key
8308 }));
8309}
8310var SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
8311var savedScrollPositions = {};
8312function getScrollRestorationKey(location, matches, basename, getKey) {
8313 let key = null;
8314 if (getKey) {
8315 if (basename !== "/") {
8316 key = getKey(
8317 {
8318 ...location,
8319 pathname: stripBasename(location.pathname, basename) || location.pathname
8320 },
8321 matches
8322 );
8323 } else {
8324 key = getKey(location, matches);
8325 }
8326 }
8327 if (key == null) {
8328 key = location.key;
8329 }
8330 return key;
8331}
8332function useScrollRestoration({
8333 getKey,
8334 storageKey
8335} = {}) {
8336 let { router } = useDataRouterContext3("useScrollRestoration" /* UseScrollRestoration */);
8337 let { restoreScrollPosition, preventScrollReset } = useDataRouterState2(
8338 "useScrollRestoration" /* UseScrollRestoration */
8339 );
8340 let { basename } = React10.useContext(NavigationContext);
8341 let location = useLocation();
8342 let matches = useMatches();
8343 let navigation = useNavigation();
8344 React10.useEffect(() => {
8345 window.history.scrollRestoration = "manual";
8346 return () => {
8347 window.history.scrollRestoration = "auto";
8348 };
8349 }, []);
8350 usePageHide(
8351 React10.useCallback(() => {
8352 if (navigation.state === "idle") {
8353 let key = getScrollRestorationKey(location, matches, basename, getKey);
8354 savedScrollPositions[key] = window.scrollY;
8355 }
8356 try {
8357 sessionStorage.setItem(
8358 storageKey || SCROLL_RESTORATION_STORAGE_KEY,
8359 JSON.stringify(savedScrollPositions)
8360 );
8361 } catch (error) {
8362 warning(
8363 false,
8364 `Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (${error}).`
8365 );
8366 }
8367 window.history.scrollRestoration = "auto";
8368 }, [navigation.state, getKey, basename, location, matches, storageKey])
8369 );
8370 if (typeof document !== "undefined") {
8371 React10.useLayoutEffect(() => {
8372 try {
8373 let sessionPositions = sessionStorage.getItem(
8374 storageKey || SCROLL_RESTORATION_STORAGE_KEY
8375 );
8376 if (sessionPositions) {
8377 savedScrollPositions = JSON.parse(sessionPositions);
8378 }
8379 } catch (e) {
8380 }
8381 }, [storageKey]);
8382 React10.useLayoutEffect(() => {
8383 let disableScrollRestoration = router?.enableScrollRestoration(
8384 savedScrollPositions,
8385 () => window.scrollY,
8386 getKey ? (location2, matches2) => getScrollRestorationKey(location2, matches2, basename, getKey) : void 0
8387 );
8388 return () => disableScrollRestoration && disableScrollRestoration();
8389 }, [router, basename, getKey]);
8390 React10.useLayoutEffect(() => {
8391 if (restoreScrollPosition === false) {
8392 return;
8393 }
8394 if (typeof restoreScrollPosition === "number") {
8395 window.scrollTo(0, restoreScrollPosition);
8396 return;
8397 }
8398 if (location.hash) {
8399 let el = document.getElementById(
8400 decodeURIComponent(location.hash.slice(1))
8401 );
8402 if (el) {
8403 el.scrollIntoView();
8404 return;
8405 }
8406 }
8407 if (preventScrollReset === true) {
8408 return;
8409 }
8410 window.scrollTo(0, 0);
8411 }, [location, restoreScrollPosition, preventScrollReset]);
8412 }
8413}
8414function useBeforeUnload(callback, options) {
8415 let { capture } = options || {};
8416 React10.useEffect(() => {
8417 let opts = capture != null ? { capture } : void 0;
8418 window.addEventListener("beforeunload", callback, opts);
8419 return () => {
8420 window.removeEventListener("beforeunload", callback, opts);
8421 };
8422 }, [callback, capture]);
8423}
8424function usePageHide(callback, options) {
8425 let { capture } = options || {};
8426 React10.useEffect(() => {
8427 let opts = capture != null ? { capture } : void 0;
8428 window.addEventListener("pagehide", callback, opts);
8429 return () => {
8430 window.removeEventListener("pagehide", callback, opts);
8431 };
8432 }, [callback, capture]);
8433}
8434function usePrompt({
8435 when,
8436 message
8437}) {
8438 let blocker = useBlocker(when);
8439 React10.useEffect(() => {
8440 if (blocker.state === "blocked") {
8441 let proceed = window.confirm(message);
8442 if (proceed) {
8443 setTimeout(blocker.proceed, 0);
8444 } else {
8445 blocker.reset();
8446 }
8447 }
8448 }, [blocker, message]);
8449 React10.useEffect(() => {
8450 if (blocker.state === "blocked" && !when) {
8451 blocker.reset();
8452 }
8453 }, [blocker, when]);
8454}
8455function useViewTransitionState(to, opts = {}) {
8456 let vtContext = React10.useContext(ViewTransitionContext);
8457 invariant(
8458 vtContext != null,
8459 "`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?"
8460 );
8461 let { basename } = useDataRouterContext3(
8462 "useViewTransitionState" /* useViewTransitionState */
8463 );
8464 let path = useResolvedPath(to, { relative: opts.relative });
8465 if (!vtContext.isTransitioning) {
8466 return false;
8467 }
8468 let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
8469 let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
8470 return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
8471}
8472
8473// lib/dom/server.tsx
8474var React11 = __toESM(require("react"));
8475function StaticRouter({
8476 basename,
8477 children,
8478 location: locationProp = "/"
8479}) {
8480 if (typeof locationProp === "string") {
8481 locationProp = parsePath(locationProp);
8482 }
8483 let action = "POP" /* Pop */;
8484 let location = {
8485 pathname: locationProp.pathname || "/",
8486 search: locationProp.search || "",
8487 hash: locationProp.hash || "",
8488 state: locationProp.state != null ? locationProp.state : null,
8489 key: locationProp.key || "default"
8490 };
8491 let staticNavigator = getStatelessNavigator();
8492 return /* @__PURE__ */ React11.createElement(
8493 Router,
8494 {
8495 basename,
8496 children,
8497 location,
8498 navigationType: action,
8499 navigator: staticNavigator,
8500 static: true
8501 }
8502 );
8503}
8504function StaticRouterProvider({
8505 context,
8506 router,
8507 hydrate = true,
8508 nonce
8509}) {
8510 invariant(
8511 router && context,
8512 "You must provide `router` and `context` to <StaticRouterProvider>"
8513 );
8514 let dataRouterContext = {
8515 router,
8516 navigator: getStatelessNavigator(),
8517 static: true,
8518 staticContext: context,
8519 basename: context.basename || "/"
8520 };
8521 let fetchersContext = /* @__PURE__ */ new Map();
8522 let hydrateScript = "";
8523 if (hydrate !== false) {
8524 let data2 = {
8525 loaderData: context.loaderData,
8526 actionData: context.actionData,
8527 errors: serializeErrors(context.errors)
8528 };
8529 let json = htmlEscape(JSON.stringify(JSON.stringify(data2)));
8530 hydrateScript = `window.__staticRouterHydrationData = JSON.parse(${json});`;
8531 }
8532 let { state } = dataRouterContext.router;
8533 return /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React11.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React11.createElement(FetchersContext.Provider, { value: fetchersContext }, /* @__PURE__ */ React11.createElement(ViewTransitionContext.Provider, { value: { isTransitioning: false } }, /* @__PURE__ */ React11.createElement(
8534 Router,
8535 {
8536 basename: dataRouterContext.basename,
8537 location: state.location,
8538 navigationType: state.historyAction,
8539 navigator: dataRouterContext.navigator,
8540 static: dataRouterContext.static
8541 },
8542 /* @__PURE__ */ React11.createElement(
8543 DataRoutes2,
8544 {
8545 routes: router.routes,
8546 future: router.future,
8547 state
8548 }
8549 )
8550 ))))), hydrateScript ? /* @__PURE__ */ React11.createElement(
8551 "script",
8552 {
8553 suppressHydrationWarning: true,
8554 nonce,
8555 dangerouslySetInnerHTML: { __html: hydrateScript }
8556 }
8557 ) : null);
8558}
8559function DataRoutes2({
8560 routes,
8561 future,
8562 state
8563}) {
8564 return useRoutesImpl(routes, void 0, state, future);
8565}
8566function serializeErrors(errors) {
8567 if (!errors) return null;
8568 let entries = Object.entries(errors);
8569 let serialized = {};
8570 for (let [key, val] of entries) {
8571 if (isRouteErrorResponse(val)) {
8572 serialized[key] = { ...val, __type: "RouteErrorResponse" };
8573 } else if (val instanceof Error) {
8574 serialized[key] = {
8575 message: val.message,
8576 __type: "Error",
8577 // If this is a subclass (i.e., ReferenceError), send up the type so we
8578 // can re-create the same type during hydration.
8579 ...val.name !== "Error" ? {
8580 __subType: val.name
8581 } : {}
8582 };
8583 } else {
8584 serialized[key] = val;
8585 }
8586 }
8587 return serialized;
8588}
8589function getStatelessNavigator() {
8590 return {
8591 createHref,
8592 encodeLocation,
8593 push(to) {
8594 throw new Error(
8595 `You cannot use navigator.push() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${JSON.stringify(to)})\` somewhere in your app.`
8596 );
8597 },
8598 replace(to) {
8599 throw new Error(
8600 `You cannot use navigator.replace() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${JSON.stringify(to)}, { replace: true })\` somewhere in your app.`
8601 );
8602 },
8603 go(delta) {
8604 throw new Error(
8605 `You cannot use navigator.go() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${delta})\` somewhere in your app.`
8606 );
8607 },
8608 back() {
8609 throw new Error(
8610 `You cannot use navigator.back() on the server because it is a stateless environment.`
8611 );
8612 },
8613 forward() {
8614 throw new Error(
8615 `You cannot use navigator.forward() on the server because it is a stateless environment.`
8616 );
8617 }
8618 };
8619}
8620function createStaticHandler2(routes, opts) {
8621 return createStaticHandler(routes, {
8622 ...opts,
8623 mapRouteProperties
8624 });
8625}
8626function createStaticRouter(routes, context, opts = {}) {
8627 let manifest = {};
8628 let dataRoutes = convertRoutesToDataRoutes(
8629 routes,
8630 mapRouteProperties,
8631 void 0,
8632 manifest
8633 );
8634 let matches = context.matches.map((match) => {
8635 let route = manifest[match.route.id] || match.route;
8636 return {
8637 ...match,
8638 route
8639 };
8640 });
8641 let msg = (method) => `You cannot use router.${method}() on the server because it is a stateless environment`;
8642 return {
8643 get basename() {
8644 return context.basename;
8645 },
8646 get future() {
8647 return {
8648 unstable_middleware: false,
8649 ...opts?.future
8650 };
8651 },
8652 get state() {
8653 return {
8654 historyAction: "POP" /* Pop */,
8655 location: context.location,
8656 matches,
8657 loaderData: context.loaderData,
8658 actionData: context.actionData,
8659 errors: context.errors,
8660 initialized: true,
8661 navigation: IDLE_NAVIGATION,
8662 restoreScrollPosition: null,
8663 preventScrollReset: false,
8664 revalidation: "idle",
8665 fetchers: /* @__PURE__ */ new Map(),
8666 blockers: /* @__PURE__ */ new Map()
8667 };
8668 },
8669 get routes() {
8670 return dataRoutes;
8671 },
8672 get window() {
8673 return void 0;
8674 },
8675 initialize() {
8676 throw msg("initialize");
8677 },
8678 subscribe() {
8679 throw msg("subscribe");
8680 },
8681 enableScrollRestoration() {
8682 throw msg("enableScrollRestoration");
8683 },
8684 navigate() {
8685 throw msg("navigate");
8686 },
8687 fetch() {
8688 throw msg("fetch");
8689 },
8690 revalidate() {
8691 throw msg("revalidate");
8692 },
8693 createHref,
8694 encodeLocation,
8695 getFetcher() {
8696 return IDLE_FETCHER;
8697 },
8698 deleteFetcher() {
8699 throw msg("deleteFetcher");
8700 },
8701 dispose() {
8702 throw msg("dispose");
8703 },
8704 getBlocker() {
8705 return IDLE_BLOCKER;
8706 },
8707 deleteBlocker() {
8708 throw msg("deleteBlocker");
8709 },
8710 patchRoutes() {
8711 throw msg("patchRoutes");
8712 },
8713 _internalFetchControllers: /* @__PURE__ */ new Map(),
8714 _internalSetRoutes() {
8715 throw msg("_internalSetRoutes");
8716 }
8717 };
8718}
8719function createHref(to) {
8720 return typeof to === "string" ? to : createPath(to);
8721}
8722function encodeLocation(to) {
8723 let href2 = typeof to === "string" ? to : createPath(to);
8724 href2 = href2.replace(/ $/, "%20");
8725 let encoded = ABSOLUTE_URL_REGEX3.test(href2) ? new URL(href2) : new URL(href2, "http://localhost");
8726 return {
8727 pathname: encoded.pathname,
8728 search: encoded.search,
8729 hash: encoded.hash
8730 };
8731}
8732var ABSOLUTE_URL_REGEX3 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
8733var ESCAPE_LOOKUP2 = {
8734 "&": "\\u0026",
8735 ">": "\\u003e",
8736 "<": "\\u003c",
8737 "\u2028": "\\u2028",
8738 "\u2029": "\\u2029"
8739};
8740var ESCAPE_REGEX2 = /[&><\u2028\u2029]/g;
8741function htmlEscape(str) {
8742 return str.replace(ESCAPE_REGEX2, (match) => ESCAPE_LOOKUP2[match]);
8743}
8744
8745// lib/dom/ssr/server.tsx
8746var React12 = __toESM(require("react"));
8747function ServerRouter({
8748 context,
8749 url,
8750 nonce
8751}) {
8752 if (typeof url === "string") {
8753 url = new URL(url);
8754 }
8755 let { manifest, routeModules, criticalCss, serverHandoffString } = context;
8756 let routes = createServerRoutes(
8757 manifest.routes,
8758 routeModules,
8759 context.future,
8760 context.isSpaMode
8761 );
8762 context.staticHandlerContext.loaderData = {
8763 ...context.staticHandlerContext.loaderData
8764 };
8765 for (let match of context.staticHandlerContext.matches) {
8766 let routeId = match.route.id;
8767 let route = routeModules[routeId];
8768 let manifestRoute = context.manifest.routes[routeId];
8769 if (route && manifestRoute && shouldHydrateRouteLoader(manifestRoute, route, context.isSpaMode) && (route.HydrateFallback || !manifestRoute.hasLoader)) {
8770 delete context.staticHandlerContext.loaderData[routeId];
8771 }
8772 }
8773 let router = createStaticRouter(routes, context.staticHandlerContext);
8774 return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(
8775 FrameworkContext.Provider,
8776 {
8777 value: {
8778 manifest,
8779 routeModules,
8780 criticalCss,
8781 serverHandoffString,
8782 future: context.future,
8783 ssr: context.ssr,
8784 isSpaMode: context.isSpaMode,
8785 serializeError: context.serializeError,
8786 renderMeta: context.renderMeta
8787 }
8788 },
8789 /* @__PURE__ */ React12.createElement(RemixErrorBoundary, { location: router.state.location }, /* @__PURE__ */ React12.createElement(
8790 StaticRouterProvider,
8791 {
8792 router,
8793 context: context.staticHandlerContext,
8794 hydrate: false
8795 }
8796 ))
8797 ), context.serverHandoffStream ? /* @__PURE__ */ React12.createElement(React12.Suspense, null, /* @__PURE__ */ React12.createElement(
8798 StreamTransfer,
8799 {
8800 context,
8801 identifier: 0,
8802 reader: context.serverHandoffStream.getReader(),
8803 textDecoder: new TextDecoder(),
8804 nonce
8805 }
8806 )) : null);
8807}
8808
8809// lib/dom/ssr/routes-test-stub.tsx
8810var React13 = __toESM(require("react"));
8811function createRoutesStub(routes, unstable_getContext) {
8812 return function RoutesTestStub({
8813 initialEntries,
8814 initialIndex,
8815 hydrationData,
8816 future
8817 }) {
8818 let routerRef = React13.useRef();
8819 let remixContextRef = React13.useRef();
8820 if (routerRef.current == null) {
8821 remixContextRef.current = {
8822 future: {
8823 unstable_middleware: future?.unstable_middleware === true
8824 },
8825 manifest: {
8826 routes: {},
8827 entry: { imports: [], module: "" },
8828 url: "",
8829 version: ""
8830 },
8831 routeModules: {},
8832 ssr: false,
8833 isSpaMode: false
8834 };
8835 let patched = processRoutes(
8836 // @ts-expect-error `StubRouteObject` is stricter about `loader`/`action`
8837 // types compared to `AgnosticRouteObject`
8838 convertRoutesToDataRoutes(routes, (r) => r),
8839 remixContextRef.current.manifest,
8840 remixContextRef.current.routeModules
8841 );
8842 routerRef.current = createMemoryRouter(patched, {
8843 unstable_getContext,
8844 initialEntries,
8845 initialIndex,
8846 hydrationData
8847 });
8848 }
8849 return /* @__PURE__ */ React13.createElement(FrameworkContext.Provider, { value: remixContextRef.current }, /* @__PURE__ */ React13.createElement(RouterProvider, { router: routerRef.current }));
8850 };
8851}
8852function processRoutes(routes, manifest, routeModules, parentId) {
8853 return routes.map((route) => {
8854 if (!route.id) {
8855 throw new Error(
8856 "Expected a route.id in @remix-run/testing processRoutes() function"
8857 );
8858 }
8859 let newRoute = {
8860 id: route.id,
8861 path: route.path,
8862 index: route.index,
8863 Component: route.Component,
8864 HydrateFallback: route.HydrateFallback,
8865 ErrorBoundary: route.ErrorBoundary,
8866 action: route.action,
8867 loader: route.loader,
8868 handle: route.handle,
8869 shouldRevalidate: route.shouldRevalidate
8870 };
8871 let entryRoute = {
8872 id: route.id,
8873 path: route.path,
8874 index: route.index,
8875 parentId,
8876 hasAction: route.action != null,
8877 hasLoader: route.loader != null,
8878 // When testing routes, you should just be stubbing loader/action, not
8879 // trying to re-implement the full loader/clientLoader/SSR/hydration flow.
8880 // That is better tested via E2E tests.
8881 hasClientAction: false,
8882 hasClientLoader: false,
8883 hasErrorBoundary: route.ErrorBoundary != null,
8884 // any need for these?
8885 module: "build/stub-path-to-module.js",
8886 clientActionModule: void 0,
8887 clientLoaderModule: void 0,
8888 hydrateFallbackModule: void 0
8889 };
8890 manifest.routes[newRoute.id] = entryRoute;
8891 routeModules[route.id] = {
8892 default: route.Component || Outlet,
8893 ErrorBoundary: route.ErrorBoundary || void 0,
8894 handle: route.handle,
8895 links: route.links,
8896 meta: route.meta,
8897 shouldRevalidate: route.shouldRevalidate
8898 };
8899 if (route.children) {
8900 newRoute.children = processRoutes(
8901 route.children,
8902 manifest,
8903 routeModules,
8904 newRoute.id
8905 );
8906 }
8907 return newRoute;
8908 });
8909}
8910
8911// lib/server-runtime/cookies.ts
8912var import_cookie = require("cookie");
8913
8914// lib/server-runtime/crypto.ts
8915var encoder = new TextEncoder();
8916var sign = async (value, secret) => {
8917 let data2 = encoder.encode(value);
8918 let key = await createKey2(secret, ["sign"]);
8919 let signature = await crypto.subtle.sign("HMAC", key, data2);
8920 let hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(
8921 /=+$/,
8922 ""
8923 );
8924 return value + "." + hash;
8925};
8926var unsign = async (cookie, secret) => {
8927 let index = cookie.lastIndexOf(".");
8928 let value = cookie.slice(0, index);
8929 let hash = cookie.slice(index + 1);
8930 let data2 = encoder.encode(value);
8931 let key = await createKey2(secret, ["verify"]);
8932 let signature = byteStringToUint8Array(atob(hash));
8933 let valid = await crypto.subtle.verify("HMAC", key, signature, data2);
8934 return valid ? value : false;
8935};
8936var createKey2 = async (secret, usages) => crypto.subtle.importKey(
8937 "raw",
8938 encoder.encode(secret),
8939 { name: "HMAC", hash: "SHA-256" },
8940 false,
8941 usages
8942);
8943function byteStringToUint8Array(byteString) {
8944 let array = new Uint8Array(byteString.length);
8945 for (let i = 0; i < byteString.length; i++) {
8946 array[i] = byteString.charCodeAt(i);
8947 }
8948 return array;
8949}
8950
8951// lib/server-runtime/cookies.ts
8952var createCookie = (name, cookieOptions = {}) => {
8953 let { secrets = [], ...options } = {
8954 path: "/",
8955 sameSite: "lax",
8956 ...cookieOptions
8957 };
8958 warnOnceAboutExpiresCookie(name, options.expires);
8959 return {
8960 get name() {
8961 return name;
8962 },
8963 get isSigned() {
8964 return secrets.length > 0;
8965 },
8966 get expires() {
8967 return typeof options.maxAge !== "undefined" ? new Date(Date.now() + options.maxAge * 1e3) : options.expires;
8968 },
8969 async parse(cookieHeader, parseOptions) {
8970 if (!cookieHeader) return null;
8971 let cookies = (0, import_cookie.parse)(cookieHeader, { ...options, ...parseOptions });
8972 if (name in cookies) {
8973 let value = cookies[name];
8974 if (typeof value === "string" && value !== "") {
8975 let decoded = await decodeCookieValue(value, secrets);
8976 return decoded;
8977 } else {
8978 return "";
8979 }
8980 } else {
8981 return null;
8982 }
8983 },
8984 async serialize(value, serializeOptions) {
8985 return (0, import_cookie.serialize)(
8986 name,
8987 value === "" ? "" : await encodeCookieValue(value, secrets),
8988 {
8989 ...options,
8990 ...serializeOptions
8991 }
8992 );
8993 }
8994 };
8995};
8996var isCookie = (object) => {
8997 return object != null && typeof object.name === "string" && typeof object.isSigned === "boolean" && typeof object.parse === "function" && typeof object.serialize === "function";
8998};
8999async function encodeCookieValue(value, secrets) {
9000 let encoded = encodeData(value);
9001 if (secrets.length > 0) {
9002 encoded = await sign(encoded, secrets[0]);
9003 }
9004 return encoded;
9005}
9006async function decodeCookieValue(value, secrets) {
9007 if (secrets.length > 0) {
9008 for (let secret of secrets) {
9009 let unsignedValue = await unsign(value, secret);
9010 if (unsignedValue !== false) {
9011 return decodeData(unsignedValue);
9012 }
9013 }
9014 return null;
9015 }
9016 return decodeData(value);
9017}
9018function encodeData(value) {
9019 return btoa(myUnescape(encodeURIComponent(JSON.stringify(value))));
9020}
9021function decodeData(value) {
9022 try {
9023 return JSON.parse(decodeURIComponent(myEscape(atob(value))));
9024 } catch (error) {
9025 return {};
9026 }
9027}
9028function myEscape(value) {
9029 let str = value.toString();
9030 let result = "";
9031 let index = 0;
9032 let chr, code;
9033 while (index < str.length) {
9034 chr = str.charAt(index++);
9035 if (/[\w*+\-./@]/.exec(chr)) {
9036 result += chr;
9037 } else {
9038 code = chr.charCodeAt(0);
9039 if (code < 256) {
9040 result += "%" + hex(code, 2);
9041 } else {
9042 result += "%u" + hex(code, 4).toUpperCase();
9043 }
9044 }
9045 }
9046 return result;
9047}
9048function hex(code, length) {
9049 let result = code.toString(16);
9050 while (result.length < length) result = "0" + result;
9051 return result;
9052}
9053function myUnescape(value) {
9054 let str = value.toString();
9055 let result = "";
9056 let index = 0;
9057 let chr, part;
9058 while (index < str.length) {
9059 chr = str.charAt(index++);
9060 if (chr === "%") {
9061 if (str.charAt(index) === "u") {
9062 part = str.slice(index + 1, index + 5);
9063 if (/^[\da-f]{4}$/i.exec(part)) {
9064 result += String.fromCharCode(parseInt(part, 16));
9065 index += 5;
9066 continue;
9067 }
9068 } else {
9069 part = str.slice(index, index + 2);
9070 if (/^[\da-f]{2}$/i.exec(part)) {
9071 result += String.fromCharCode(parseInt(part, 16));
9072 index += 2;
9073 continue;
9074 }
9075 }
9076 }
9077 result += chr;
9078 }
9079 return result;
9080}
9081function warnOnceAboutExpiresCookie(name, expires) {
9082 warnOnce(
9083 !expires,
9084 `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.`
9085 );
9086}
9087
9088// lib/server-runtime/entry.ts
9089function createEntryRouteModules(manifest) {
9090 return Object.keys(manifest).reduce((memo2, routeId) => {
9091 let route = manifest[routeId];
9092 if (route) {
9093 memo2[routeId] = route.module;
9094 }
9095 return memo2;
9096 }, {});
9097}
9098
9099// lib/server-runtime/mode.ts
9100var ServerMode = /* @__PURE__ */ ((ServerMode2) => {
9101 ServerMode2["Development"] = "development";
9102 ServerMode2["Production"] = "production";
9103 ServerMode2["Test"] = "test";
9104 return ServerMode2;
9105})(ServerMode || {});
9106function isServerMode(value) {
9107 return value === "development" /* Development */ || value === "production" /* Production */ || value === "test" /* Test */;
9108}
9109
9110// lib/server-runtime/errors.ts
9111function sanitizeError(error, serverMode) {
9112 if (error instanceof Error && serverMode !== "development" /* Development */) {
9113 let sanitized = new Error("Unexpected Server Error");
9114 sanitized.stack = void 0;
9115 return sanitized;
9116 }
9117 return error;
9118}
9119function sanitizeErrors(errors, serverMode) {
9120 return Object.entries(errors).reduce((acc, [routeId, error]) => {
9121 return Object.assign(acc, { [routeId]: sanitizeError(error, serverMode) });
9122 }, {});
9123}
9124function serializeError(error, serverMode) {
9125 let sanitized = sanitizeError(error, serverMode);
9126 return {
9127 message: sanitized.message,
9128 stack: sanitized.stack
9129 };
9130}
9131function serializeErrors2(errors, serverMode) {
9132 if (!errors) return null;
9133 let entries = Object.entries(errors);
9134 let serialized = {};
9135 for (let [key, val] of entries) {
9136 if (isRouteErrorResponse(val)) {
9137 serialized[key] = { ...val, __type: "RouteErrorResponse" };
9138 } else if (val instanceof Error) {
9139 let sanitized = sanitizeError(val, serverMode);
9140 serialized[key] = {
9141 message: sanitized.message,
9142 stack: sanitized.stack,
9143 __type: "Error",
9144 // If this is a subclass (i.e., ReferenceError), send up the type so we
9145 // can re-create the same type during hydration. This will only apply
9146 // in dev mode since all production errors are sanitized to normal
9147 // Error instances
9148 ...sanitized.name !== "Error" ? {
9149 __subType: sanitized.name
9150 } : {}
9151 };
9152 } else {
9153 serialized[key] = val;
9154 }
9155 }
9156 return serialized;
9157}
9158
9159// lib/server-runtime/routeMatching.ts
9160function matchServerRoutes(routes, pathname, basename) {
9161 let matches = matchRoutes(
9162 routes,
9163 pathname,
9164 basename
9165 );
9166 if (!matches) return null;
9167 return matches.map((match) => ({
9168 params: match.params,
9169 pathname: match.pathname,
9170 route: match.route
9171 }));
9172}
9173
9174// lib/server-runtime/data.ts
9175async function callRouteHandler(handler, args) {
9176 let result = await handler({
9177 request: stripRoutesParam(stripIndexParam2(args.request)),
9178 params: args.params,
9179 context: args.context
9180 });
9181 if (isDataWithResponseInit(result) && result.init && result.init.status && isRedirectStatusCode(result.init.status)) {
9182 throw new Response(null, result.init);
9183 }
9184 return result;
9185}
9186function stripIndexParam2(request) {
9187 let url = new URL(request.url);
9188 let indexValues = url.searchParams.getAll("index");
9189 url.searchParams.delete("index");
9190 let indexValuesToKeep = [];
9191 for (let indexValue of indexValues) {
9192 if (indexValue) {
9193 indexValuesToKeep.push(indexValue);
9194 }
9195 }
9196 for (let toKeep of indexValuesToKeep) {
9197 url.searchParams.append("index", toKeep);
9198 }
9199 let init = {
9200 method: request.method,
9201 body: request.body,
9202 headers: request.headers,
9203 signal: request.signal
9204 };
9205 if (init.body) {
9206 init.duplex = "half";
9207 }
9208 return new Request(url.href, init);
9209}
9210function stripRoutesParam(request) {
9211 let url = new URL(request.url);
9212 url.searchParams.delete("_routes");
9213 let init = {
9214 method: request.method,
9215 body: request.body,
9216 headers: request.headers,
9217 signal: request.signal
9218 };
9219 if (init.body) {
9220 init.duplex = "half";
9221 }
9222 return new Request(url.href, init);
9223}
9224
9225// lib/server-runtime/invariant.ts
9226function invariant3(value, message) {
9227 if (value === false || value === null || typeof value === "undefined") {
9228 console.error(
9229 "The following error is a bug in React Router; please open an issue! https://github.com/remix-run/react-router/issues/new/choose"
9230 );
9231 throw new Error(message);
9232 }
9233}
9234
9235// lib/server-runtime/routes.ts
9236function groupRoutesByParentId2(manifest) {
9237 let routes = {};
9238 Object.values(manifest).forEach((route) => {
9239 if (route) {
9240 let parentId = route.parentId || "";
9241 if (!routes[parentId]) {
9242 routes[parentId] = [];
9243 }
9244 routes[parentId].push(route);
9245 }
9246 });
9247 return routes;
9248}
9249function createRoutes(manifest, parentId = "", routesByParentId = groupRoutesByParentId2(manifest)) {
9250 return (routesByParentId[parentId] || []).map((route) => ({
9251 ...route,
9252 children: createRoutes(manifest, route.id, routesByParentId)
9253 }));
9254}
9255function createStaticHandlerDataRoutes(manifest, future, parentId = "", routesByParentId = groupRoutesByParentId2(manifest)) {
9256 return (routesByParentId[parentId] || []).map((route) => {
9257 let commonRoute = {
9258 // Always include root due to default boundaries
9259 hasErrorBoundary: route.id === "root" || route.module.ErrorBoundary != null,
9260 id: route.id,
9261 path: route.path,
9262 unstable_middleware: route.module.unstable_middleware,
9263 // Need to use RR's version in the param typed here to permit the optional
9264 // context even though we know it'll always be provided in remix
9265 loader: route.module.loader ? async (args) => {
9266 if (args.request.headers.has("X-React-Router-Prerender-Data")) {
9267 const preRenderedData = args.request.headers.get(
9268 "X-React-Router-Prerender-Data"
9269 );
9270 let encoded = preRenderedData ? decodeURI(preRenderedData) : preRenderedData;
9271 invariant3(encoded, "Missing prerendered data for route");
9272 let uint8array = new TextEncoder().encode(encoded);
9273 let stream = new ReadableStream({
9274 start(controller) {
9275 controller.enqueue(uint8array);
9276 controller.close();
9277 }
9278 });
9279 let decoded = await decodeViaTurboStream(stream, global);
9280 let data2 = decoded.value;
9281 invariant3(
9282 data2 && route.id in data2,
9283 "Unable to decode prerendered data"
9284 );
9285 let result = data2[route.id];
9286 invariant3("data" in result, "Unable to process prerendered data");
9287 return result.data;
9288 }
9289 let val = await callRouteHandler(route.module.loader, args);
9290 return val;
9291 } : void 0,
9292 action: route.module.action ? (args) => callRouteHandler(route.module.action, args) : void 0,
9293 handle: route.module.handle
9294 };
9295 return route.index ? {
9296 index: true,
9297 ...commonRoute
9298 } : {
9299 caseSensitive: route.caseSensitive,
9300 children: createStaticHandlerDataRoutes(
9301 manifest,
9302 future,
9303 route.id,
9304 routesByParentId
9305 ),
9306 ...commonRoute
9307 };
9308 });
9309}
9310
9311// lib/server-runtime/markup.ts
9312var ESCAPE_LOOKUP3 = {
9313 "&": "\\u0026",
9314 ">": "\\u003e",
9315 "<": "\\u003c",
9316 "\u2028": "\\u2028",
9317 "\u2029": "\\u2029"
9318};
9319var ESCAPE_REGEX3 = /[&><\u2028\u2029]/g;
9320function escapeHtml2(html) {
9321 return html.replace(ESCAPE_REGEX3, (match) => ESCAPE_LOOKUP3[match]);
9322}
9323
9324// lib/server-runtime/serverHandoff.ts
9325function createServerHandoffString(serverHandoff) {
9326 return escapeHtml2(JSON.stringify(serverHandoff));
9327}
9328
9329// lib/server-runtime/dev.ts
9330var globalDevServerHooksKey = "__reactRouterDevServerHooks";
9331function setDevServerHooks(devServerHooks) {
9332 globalThis[globalDevServerHooksKey] = devServerHooks;
9333}
9334function getDevServerHooks() {
9335 return globalThis[globalDevServerHooksKey];
9336}
9337
9338// lib/server-runtime/single-fetch.ts
9339var import_turbo_stream2 = require("turbo-stream");
9340
9341// lib/server-runtime/headers.ts
9342var import_set_cookie_parser = require("set-cookie-parser");
9343function getDocumentHeaders(build, context) {
9344 let boundaryIdx = context.errors ? context.matches.findIndex((m) => context.errors[m.route.id]) : -1;
9345 let matches = boundaryIdx >= 0 ? context.matches.slice(0, boundaryIdx + 1) : context.matches;
9346 let errorHeaders;
9347 if (boundaryIdx >= 0) {
9348 let { actionHeaders, actionData, loaderHeaders, loaderData } = context;
9349 context.matches.slice(boundaryIdx).some((match) => {
9350 let id = match.route.id;
9351 if (actionHeaders[id] && (!actionData || !actionData.hasOwnProperty(id))) {
9352 errorHeaders = actionHeaders[id];
9353 } else if (loaderHeaders[id] && !loaderData.hasOwnProperty(id)) {
9354 errorHeaders = loaderHeaders[id];
9355 }
9356 return errorHeaders != null;
9357 });
9358 }
9359 return matches.reduce((parentHeaders, match, idx) => {
9360 let { id } = match.route;
9361 let route = build.routes[id];
9362 invariant3(route, `Route with id "${id}" not found in build`);
9363 let routeModule = route.module;
9364 let loaderHeaders = context.loaderHeaders[id] || new Headers();
9365 let actionHeaders = context.actionHeaders[id] || new Headers();
9366 let includeErrorHeaders = errorHeaders != null && idx === matches.length - 1;
9367 let includeErrorCookies = includeErrorHeaders && errorHeaders !== loaderHeaders && errorHeaders !== actionHeaders;
9368 if (routeModule.headers == null) {
9369 let headers2 = new Headers(parentHeaders);
9370 if (includeErrorCookies) {
9371 prependCookies(errorHeaders, headers2);
9372 }
9373 prependCookies(actionHeaders, headers2);
9374 prependCookies(loaderHeaders, headers2);
9375 return headers2;
9376 }
9377 let headers = new Headers(
9378 routeModule.headers ? typeof routeModule.headers === "function" ? routeModule.headers({
9379 loaderHeaders,
9380 parentHeaders,
9381 actionHeaders,
9382 errorHeaders: includeErrorHeaders ? errorHeaders : void 0
9383 }) : routeModule.headers : void 0
9384 );
9385 if (includeErrorCookies) {
9386 prependCookies(errorHeaders, headers);
9387 }
9388 prependCookies(actionHeaders, headers);
9389 prependCookies(loaderHeaders, headers);
9390 prependCookies(parentHeaders, headers);
9391 return headers;
9392 }, new Headers());
9393}
9394function prependCookies(parentHeaders, childHeaders) {
9395 let parentSetCookieString = parentHeaders.get("Set-Cookie");
9396 if (parentSetCookieString) {
9397 let cookies = (0, import_set_cookie_parser.splitCookiesString)(parentSetCookieString);
9398 let childCookies = new Set(childHeaders.getSetCookie());
9399 cookies.forEach((cookie) => {
9400 if (!childCookies.has(cookie)) {
9401 childHeaders.append("Set-Cookie", cookie);
9402 }
9403 });
9404 }
9405}
9406
9407// lib/server-runtime/single-fetch.ts
9408var NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([100, 101, 204, 205, 304]);
9409var SINGLE_FETCH_REDIRECT_STATUS = 202;
9410async function singleFetchAction(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
9411 try {
9412 let respond2 = function(context) {
9413 let headers = getDocumentHeaders(build, context);
9414 if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
9415 return generateSingleFetchResponse(request, build, serverMode, {
9416 result: getSingleFetchRedirect(
9417 context.statusCode,
9418 headers,
9419 build.basename
9420 ),
9421 headers,
9422 status: SINGLE_FETCH_REDIRECT_STATUS
9423 });
9424 }
9425 if (context.errors) {
9426 Object.values(context.errors).forEach((err) => {
9427 if (!isRouteErrorResponse(err) || err.error) {
9428 handleError(err);
9429 }
9430 });
9431 context.errors = sanitizeErrors(context.errors, serverMode);
9432 }
9433 let singleFetchResult;
9434 if (context.errors) {
9435 singleFetchResult = { error: Object.values(context.errors)[0] };
9436 } else {
9437 singleFetchResult = {
9438 data: Object.values(context.actionData || {})[0]
9439 };
9440 }
9441 return generateSingleFetchResponse(request, build, serverMode, {
9442 result: singleFetchResult,
9443 headers,
9444 status: context.statusCode
9445 });
9446 };
9447 var respond = respond2;
9448 let handlerRequest = new Request(handlerUrl, {
9449 method: request.method,
9450 body: request.body,
9451 headers: request.headers,
9452 signal: request.signal,
9453 ...request.body ? { duplex: "half" } : void 0
9454 });
9455 let result = await staticHandler.query(handlerRequest, {
9456 requestContext: loadContext,
9457 skipLoaderErrorBubbling: true,
9458 skipRevalidation: true,
9459 unstable_respond: respond2
9460 });
9461 if (!isResponse(result)) {
9462 result = respond2(result);
9463 }
9464 if (isRedirectResponse(result)) {
9465 return generateSingleFetchResponse(request, build, serverMode, {
9466 result: getSingleFetchRedirect(
9467 result.status,
9468 result.headers,
9469 build.basename
9470 ),
9471 headers: result.headers,
9472 status: SINGLE_FETCH_REDIRECT_STATUS
9473 });
9474 }
9475 return result;
9476 } catch (error) {
9477 handleError(error);
9478 return generateSingleFetchResponse(request, build, serverMode, {
9479 result: { error },
9480 headers: new Headers(),
9481 status: 500
9482 });
9483 }
9484}
9485async function singleFetchLoaders(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
9486 try {
9487 let respond2 = function(context) {
9488 let headers = getDocumentHeaders(build, context);
9489 if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
9490 return generateSingleFetchResponse(request, build, serverMode, {
9491 result: {
9492 [SingleFetchRedirectSymbol]: getSingleFetchRedirect(
9493 context.statusCode,
9494 headers,
9495 build.basename
9496 )
9497 },
9498 headers,
9499 status: SINGLE_FETCH_REDIRECT_STATUS
9500 });
9501 }
9502 if (context.errors) {
9503 Object.values(context.errors).forEach((err) => {
9504 if (!isRouteErrorResponse(err) || err.error) {
9505 handleError(err);
9506 }
9507 });
9508 context.errors = sanitizeErrors(context.errors, serverMode);
9509 }
9510 let results = {};
9511 let loadedMatches = new Set(
9512 context.matches.filter(
9513 (m) => loadRouteIds ? loadRouteIds.has(m.route.id) : m.route.loader != null
9514 ).map((m) => m.route.id)
9515 );
9516 if (context.errors) {
9517 for (let [id, error] of Object.entries(context.errors)) {
9518 results[id] = { error };
9519 }
9520 }
9521 for (let [id, data2] of Object.entries(context.loaderData)) {
9522 if (!(id in results) && loadedMatches.has(id)) {
9523 results[id] = { data: data2 };
9524 }
9525 }
9526 return generateSingleFetchResponse(request, build, serverMode, {
9527 result: results,
9528 headers,
9529 status: context.statusCode
9530 });
9531 };
9532 var respond = respond2;
9533 let handlerRequest = new Request(handlerUrl, {
9534 headers: request.headers,
9535 signal: request.signal
9536 });
9537 let routesParam = new URL(request.url).searchParams.get("_routes");
9538 let loadRouteIds = routesParam ? new Set(routesParam.split(",")) : null;
9539 let result = await staticHandler.query(handlerRequest, {
9540 requestContext: loadContext,
9541 filterMatchesToLoad: (m) => !loadRouteIds || loadRouteIds.has(m.route.id),
9542 skipLoaderErrorBubbling: true,
9543 unstable_respond: respond2
9544 });
9545 if (!isResponse(result)) {
9546 result = respond2(result);
9547 }
9548 if (isRedirectResponse(result)) {
9549 return generateSingleFetchResponse(request, build, serverMode, {
9550 result: {
9551 [SingleFetchRedirectSymbol]: getSingleFetchRedirect(
9552 result.status,
9553 result.headers,
9554 build.basename
9555 )
9556 },
9557 headers: result.headers,
9558 status: SINGLE_FETCH_REDIRECT_STATUS
9559 });
9560 }
9561 return result;
9562 } catch (error) {
9563 handleError(error);
9564 return generateSingleFetchResponse(request, build, serverMode, {
9565 result: { root: { error } },
9566 headers: new Headers(),
9567 status: 500
9568 });
9569 }
9570}
9571function generateSingleFetchResponse(request, build, serverMode, {
9572 result,
9573 headers,
9574 status
9575}) {
9576 let resultHeaders = new Headers(headers);
9577 resultHeaders.set("X-Remix-Response", "yes");
9578 if (NO_BODY_STATUS_CODES.has(status)) {
9579 return new Response(null, { status, headers: resultHeaders });
9580 }
9581 resultHeaders.set("Content-Type", "text/x-script");
9582 return new Response(
9583 encodeViaTurboStream(
9584 result,
9585 request.signal,
9586 build.entry.module.streamTimeout,
9587 serverMode
9588 ),
9589 {
9590 status: status || 200,
9591 headers: resultHeaders
9592 }
9593 );
9594}
9595function getSingleFetchRedirect(status, headers, basename) {
9596 let redirect2 = headers.get("Location");
9597 if (basename) {
9598 redirect2 = stripBasename(redirect2, basename) || redirect2;
9599 }
9600 return {
9601 redirect: redirect2,
9602 status,
9603 revalidate: (
9604 // Technically X-Remix-Revalidate isn't needed here - that was an implementation
9605 // detail of ?_data requests as our way to tell the front end to revalidate when
9606 // we didn't have a response body to include that information in.
9607 // With single fetch, we tell the front end via this revalidate boolean field.
9608 // However, we're respecting it for now because it may be something folks have
9609 // used in their own responses
9610 // TODO(v3): Consider removing or making this official public API
9611 headers.has("X-Remix-Revalidate") || headers.has("Set-Cookie")
9612 ),
9613 reload: headers.has("X-Remix-Reload-Document"),
9614 replace: headers.has("X-Remix-Replace")
9615 };
9616}
9617function encodeViaTurboStream(data2, requestSignal, streamTimeout, serverMode) {
9618 let controller = new AbortController();
9619 let timeoutId = setTimeout(
9620 () => controller.abort(new Error("Server Timeout")),
9621 typeof streamTimeout === "number" ? streamTimeout : 4950
9622 );
9623 requestSignal.addEventListener("abort", () => clearTimeout(timeoutId));
9624 return (0, import_turbo_stream2.encode)(data2, {
9625 signal: controller.signal,
9626 plugins: [
9627 (value) => {
9628 if (value instanceof Error) {
9629 let { name, message, stack } = serverMode === "production" /* Production */ ? sanitizeError(value, serverMode) : value;
9630 return ["SanitizedError", name, message, stack];
9631 }
9632 if (value instanceof ErrorResponseImpl) {
9633 let { data: data3, status, statusText } = value;
9634 return ["ErrorResponse", data3, status, statusText];
9635 }
9636 if (value && typeof value === "object" && SingleFetchRedirectSymbol in value) {
9637 return ["SingleFetchRedirect", value[SingleFetchRedirectSymbol]];
9638 }
9639 }
9640 ],
9641 postPlugins: [
9642 (value) => {
9643 if (!value) return;
9644 if (typeof value !== "object") return;
9645 return [
9646 "SingleFetchClassInstance",
9647 Object.fromEntries(Object.entries(value))
9648 ];
9649 },
9650 () => ["SingleFetchFallback"]
9651 ]
9652 });
9653}
9654
9655// lib/server-runtime/server.ts
9656function derive(build, mode) {
9657 let routes = createRoutes(build.routes);
9658 let dataRoutes = createStaticHandlerDataRoutes(build.routes, build.future);
9659 let serverMode = isServerMode(mode) ? mode : "production" /* Production */;
9660 let staticHandler = createStaticHandler(dataRoutes, {
9661 basename: build.basename
9662 });
9663 let errorHandler = build.entry.module.handleError || ((error, { request }) => {
9664 if (serverMode !== "test" /* Test */ && !request.signal.aborted) {
9665 console.error(
9666 // @ts-expect-error This is "private" from users but intended for internal use
9667 isRouteErrorResponse(error) && error.error ? error.error : error
9668 );
9669 }
9670 });
9671 return {
9672 routes,
9673 dataRoutes,
9674 serverMode,
9675 staticHandler,
9676 errorHandler
9677 };
9678}
9679var createRequestHandler = (build, mode) => {
9680 let _build;
9681 let routes;
9682 let serverMode;
9683 let staticHandler;
9684 let errorHandler;
9685 return async function requestHandler(request, initialContext) {
9686 _build = typeof build === "function" ? await build() : build;
9687 let loadContext = _build.future.unstable_middleware ? new unstable_RouterContextProvider(
9688 initialContext
9689 ) : initialContext || {};
9690 if (typeof build === "function") {
9691 let derived = derive(_build, mode);
9692 routes = derived.routes;
9693 serverMode = derived.serverMode;
9694 staticHandler = derived.staticHandler;
9695 errorHandler = derived.errorHandler;
9696 } else if (!routes || !serverMode || !staticHandler || !errorHandler) {
9697 let derived = derive(_build, mode);
9698 routes = derived.routes;
9699 serverMode = derived.serverMode;
9700 staticHandler = derived.staticHandler;
9701 errorHandler = derived.errorHandler;
9702 }
9703 let url = new URL(request.url);
9704 let normalizedBasename = _build.basename || "/";
9705 let normalizedPath = url.pathname;
9706 if (stripBasename(normalizedPath, normalizedBasename) === "/_root.data") {
9707 normalizedPath = normalizedBasename;
9708 } else if (normalizedPath.endsWith(".data")) {
9709 normalizedPath = normalizedPath.replace(/\.data$/, "");
9710 }
9711 if (stripBasename(normalizedPath, normalizedBasename) !== "/" && normalizedPath.endsWith("/")) {
9712 normalizedPath = normalizedPath.slice(0, -1);
9713 }
9714 let params = {};
9715 let handleError = (error) => {
9716 if (mode === "development" /* Development */) {
9717 getDevServerHooks()?.processRequestError?.(error);
9718 }
9719 errorHandler(error, {
9720 context: loadContext,
9721 params,
9722 request
9723 });
9724 };
9725 if (!_build.ssr) {
9726 if (_build.prerender.length === 0) {
9727 request.headers.set("X-React-Router-SPA-Mode", "yes");
9728 } else if (!_build.prerender.includes(normalizedPath) && !_build.prerender.includes(normalizedPath + "/")) {
9729 if (url.pathname.endsWith(".data")) {
9730 errorHandler(
9731 new ErrorResponseImpl(
9732 404,
9733 "Not Found",
9734 `Refusing to SSR the path \`${normalizedPath}\` because \`ssr:false\` is set and the path is not included in the \`prerender\` config, so in production the path will be a 404.`
9735 ),
9736 {
9737 context: loadContext,
9738 params,
9739 request
9740 }
9741 );
9742 return new Response("Not Found", {
9743 status: 404,
9744 statusText: "Not Found"
9745 });
9746 } else {
9747 request.headers.set("X-React-Router-SPA-Mode", "yes");
9748 }
9749 }
9750 }
9751 let manifestUrl = `${normalizedBasename}/__manifest`.replace(/\/+/g, "/");
9752 if (url.pathname === manifestUrl) {
9753 try {
9754 let res = await handleManifestRequest(_build, routes, url);
9755 return res;
9756 } catch (e) {
9757 handleError(e);
9758 return new Response("Unknown Server Error", { status: 500 });
9759 }
9760 }
9761 let matches = matchServerRoutes(routes, url.pathname, _build.basename);
9762 if (matches && matches.length > 0) {
9763 Object.assign(params, matches[0].params);
9764 }
9765 let response;
9766 if (url.pathname.endsWith(".data")) {
9767 let handlerUrl = new URL(request.url);
9768 handlerUrl.pathname = normalizedPath;
9769 let singleFetchMatches = matchServerRoutes(
9770 routes,
9771 handlerUrl.pathname,
9772 _build.basename
9773 );
9774 response = await handleSingleFetchRequest(
9775 serverMode,
9776 _build,
9777 staticHandler,
9778 request,
9779 handlerUrl,
9780 loadContext,
9781 handleError
9782 );
9783 if (_build.entry.module.handleDataRequest) {
9784 response = await _build.entry.module.handleDataRequest(response, {
9785 context: loadContext,
9786 params: singleFetchMatches ? singleFetchMatches[0].params : {},
9787 request
9788 });
9789 if (isRedirectResponse(response)) {
9790 let result = getSingleFetchRedirect(
9791 response.status,
9792 response.headers,
9793 _build.basename
9794 );
9795 if (request.method === "GET") {
9796 result = {
9797 [SingleFetchRedirectSymbol]: result
9798 };
9799 }
9800 let headers = new Headers(response.headers);
9801 headers.set("Content-Type", "text/x-script");
9802 return new Response(
9803 encodeViaTurboStream(
9804 result,
9805 request.signal,
9806 _build.entry.module.streamTimeout,
9807 serverMode
9808 ),
9809 {
9810 status: SINGLE_FETCH_REDIRECT_STATUS,
9811 headers
9812 }
9813 );
9814 }
9815 }
9816 } else if (!request.headers.has("X-React-Router-SPA-Mode") && matches && matches[matches.length - 1].route.module.default == null && matches[matches.length - 1].route.module.ErrorBoundary == null) {
9817 response = await handleResourceRequest(
9818 serverMode,
9819 _build,
9820 staticHandler,
9821 matches.slice(-1)[0].route.id,
9822 request,
9823 loadContext,
9824 handleError
9825 );
9826 } else {
9827 let { pathname } = url;
9828 let criticalCss = void 0;
9829 if (_build.unstable_getCriticalCss) {
9830 criticalCss = await _build.unstable_getCriticalCss({ pathname });
9831 } else if (mode === "development" /* Development */ && getDevServerHooks()?.getCriticalCss) {
9832 criticalCss = await getDevServerHooks()?.getCriticalCss?.(pathname);
9833 }
9834 response = await handleDocumentRequest(
9835 serverMode,
9836 _build,
9837 staticHandler,
9838 request,
9839 loadContext,
9840 handleError,
9841 criticalCss
9842 );
9843 }
9844 if (request.method === "HEAD") {
9845 return new Response(null, {
9846 headers: response.headers,
9847 status: response.status,
9848 statusText: response.statusText
9849 });
9850 }
9851 return response;
9852 };
9853};
9854async function handleManifestRequest(build, routes, url) {
9855 if (build.assets.version !== url.searchParams.get("version")) {
9856 return new Response(null, {
9857 status: 204,
9858 headers: {
9859 "X-Remix-Reload-Document": "true"
9860 }
9861 });
9862 }
9863 let patches = {};
9864 if (url.searchParams.has("p")) {
9865 let paths = /* @__PURE__ */ new Set();
9866 url.searchParams.getAll("p").forEach((path) => {
9867 if (!path.startsWith("/")) {
9868 path = `/${path}`;
9869 }
9870 let segments = path.split("/").slice(1);
9871 segments.forEach((_, i) => {
9872 let partialPath = segments.slice(0, i + 1).join("/");
9873 paths.add(`/${partialPath}`);
9874 });
9875 });
9876 for (let path of paths) {
9877 let matches = matchServerRoutes(routes, path, build.basename);
9878 if (matches) {
9879 for (let match of matches) {
9880 let routeId = match.route.id;
9881 let route = build.assets.routes[routeId];
9882 if (route) {
9883 patches[routeId] = route;
9884 }
9885 }
9886 }
9887 }
9888 return Response.json(patches, {
9889 headers: {
9890 "Cache-Control": "public, max-age=31536000, immutable"
9891 }
9892 });
9893 }
9894 return new Response("Invalid Request", { status: 400 });
9895}
9896async function handleSingleFetchRequest(serverMode, build, staticHandler, request, handlerUrl, loadContext, handleError) {
9897 let response = request.method !== "GET" ? await singleFetchAction(
9898 build,
9899 serverMode,
9900 staticHandler,
9901 request,
9902 handlerUrl,
9903 loadContext,
9904 handleError
9905 ) : await singleFetchLoaders(
9906 build,
9907 serverMode,
9908 staticHandler,
9909 request,
9910 handlerUrl,
9911 loadContext,
9912 handleError
9913 );
9914 return response;
9915}
9916async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, criticalCss) {
9917 let isSpaMode = request.headers.has("X-React-Router-SPA-Mode");
9918 try {
9919 let response = await staticHandler.query(request, {
9920 requestContext: loadContext,
9921 unstable_respond: build.future.unstable_middleware ? (ctx) => renderHtml(ctx, isSpaMode) : void 0
9922 });
9923 return isResponse(response) ? response : renderHtml(response, isSpaMode);
9924 } catch (error) {
9925 handleError(error);
9926 return new Response(null, { status: 500 });
9927 }
9928 async function renderHtml(context, isSpaMode2) {
9929 if (isResponse(context)) {
9930 return context;
9931 }
9932 let headers = getDocumentHeaders(build, context);
9933 if (NO_BODY_STATUS_CODES.has(context.statusCode)) {
9934 return new Response(null, { status: context.statusCode, headers });
9935 }
9936 if (context.errors) {
9937 Object.values(context.errors).forEach((err) => {
9938 if (!isRouteErrorResponse(err) || err.error) {
9939 handleError(err);
9940 }
9941 });
9942 context.errors = sanitizeErrors(context.errors, serverMode);
9943 }
9944 let state = {
9945 loaderData: context.loaderData,
9946 actionData: context.actionData,
9947 errors: serializeErrors2(context.errors, serverMode)
9948 };
9949 let entryContext = {
9950 manifest: build.assets,
9951 routeModules: createEntryRouteModules(build.routes),
9952 staticHandlerContext: context,
9953 criticalCss,
9954 serverHandoffString: createServerHandoffString({
9955 basename: build.basename,
9956 criticalCss,
9957 future: build.future,
9958 ssr: build.ssr,
9959 isSpaMode: isSpaMode2
9960 }),
9961 serverHandoffStream: encodeViaTurboStream(
9962 state,
9963 request.signal,
9964 build.entry.module.streamTimeout,
9965 serverMode
9966 ),
9967 renderMeta: {},
9968 future: build.future,
9969 ssr: build.ssr,
9970 isSpaMode: isSpaMode2,
9971 serializeError: (err) => serializeError(err, serverMode)
9972 };
9973 let handleDocumentRequestFunction = build.entry.module.default;
9974 try {
9975 return await handleDocumentRequestFunction(
9976 request,
9977 context.statusCode,
9978 headers,
9979 entryContext,
9980 loadContext
9981 );
9982 } catch (error) {
9983 handleError(error);
9984 let errorForSecondRender = error;
9985 if (isResponse(error)) {
9986 try {
9987 let data2 = await unwrapResponse(error);
9988 errorForSecondRender = new ErrorResponseImpl(
9989 error.status,
9990 error.statusText,
9991 data2
9992 );
9993 } catch (e) {
9994 }
9995 }
9996 context = getStaticContextFromError(
9997 staticHandler.dataRoutes,
9998 context,
9999 errorForSecondRender
10000 );
10001 if (context.errors) {
10002 context.errors = sanitizeErrors(context.errors, serverMode);
10003 }
10004 let state2 = {
10005 loaderData: context.loaderData,
10006 actionData: context.actionData,
10007 errors: serializeErrors2(context.errors, serverMode)
10008 };
10009 entryContext = {
10010 ...entryContext,
10011 staticHandlerContext: context,
10012 serverHandoffString: createServerHandoffString({
10013 basename: build.basename,
10014 future: build.future,
10015 ssr: build.ssr,
10016 isSpaMode: isSpaMode2
10017 }),
10018 serverHandoffStream: encodeViaTurboStream(
10019 state2,
10020 request.signal,
10021 build.entry.module.streamTimeout,
10022 serverMode
10023 ),
10024 renderMeta: {}
10025 };
10026 try {
10027 return await handleDocumentRequestFunction(
10028 request,
10029 context.statusCode,
10030 headers,
10031 entryContext,
10032 loadContext
10033 );
10034 } catch (error2) {
10035 handleError(error2);
10036 return returnLastResortErrorResponse(error2, serverMode);
10037 }
10038 }
10039 }
10040}
10041async function handleResourceRequest(serverMode, build, staticHandler, routeId, request, loadContext, handleError) {
10042 try {
10043 let response = await staticHandler.queryRoute(request, {
10044 routeId,
10045 requestContext: loadContext,
10046 unstable_respond: build.future.unstable_middleware ? (ctx) => ctx : void 0
10047 });
10048 if (isResponse(response)) {
10049 return response;
10050 }
10051 if (typeof response === "string") {
10052 return new Response(response);
10053 }
10054 return Response.json(response);
10055 } catch (error) {
10056 if (isResponse(error)) {
10057 error.headers.set("X-Remix-Catch", "yes");
10058 return error;
10059 }
10060 if (isRouteErrorResponse(error)) {
10061 if (error) {
10062 handleError(error);
10063 }
10064 return errorResponseToJson(error, serverMode);
10065 }
10066 if (error instanceof Error && error.message === "Expected a response from queryRoute") {
10067 let newError = new Error(
10068 "Expected a Response to be returned from resource route handler"
10069 );
10070 handleError(newError);
10071 return returnLastResortErrorResponse(newError, serverMode);
10072 }
10073 handleError(error);
10074 return returnLastResortErrorResponse(error, serverMode);
10075 }
10076}
10077function errorResponseToJson(errorResponse, serverMode) {
10078 return Response.json(
10079 serializeError(
10080 // @ts-expect-error This is "private" from users but intended for internal use
10081 errorResponse.error || new Error("Unexpected Server Error"),
10082 serverMode
10083 ),
10084 {
10085 status: errorResponse.status,
10086 statusText: errorResponse.statusText,
10087 headers: {
10088 "X-Remix-Error": "yes"
10089 }
10090 }
10091 );
10092}
10093function returnLastResortErrorResponse(error, serverMode) {
10094 let message = "Unexpected Server Error";
10095 if (serverMode !== "production" /* Production */) {
10096 message += `
10097
10098${String(error)}`;
10099 }
10100 return new Response(message, {
10101 status: 500,
10102 headers: {
10103 "Content-Type": "text/plain"
10104 }
10105 });
10106}
10107function unwrapResponse(response) {
10108 let contentType = response.headers.get("Content-Type");
10109 return contentType && /\bapplication\/json\b/.test(contentType) ? response.body == null ? null : response.json() : response.text();
10110}
10111
10112// lib/server-runtime/sessions.ts
10113function flash(name) {
10114 return `__flash_${name}__`;
10115}
10116var createSession = (initialData = {}, id = "") => {
10117 let map = new Map(Object.entries(initialData));
10118 return {
10119 get id() {
10120 return id;
10121 },
10122 get data() {
10123 return Object.fromEntries(map);
10124 },
10125 has(name) {
10126 return map.has(name) || map.has(flash(name));
10127 },
10128 get(name) {
10129 if (map.has(name)) return map.get(name);
10130 let flashName = flash(name);
10131 if (map.has(flashName)) {
10132 let value = map.get(flashName);
10133 map.delete(flashName);
10134 return value;
10135 }
10136 return void 0;
10137 },
10138 set(name, value) {
10139 map.set(name, value);
10140 },
10141 flash(name, value) {
10142 map.set(flash(name), value);
10143 },
10144 unset(name) {
10145 map.delete(name);
10146 }
10147 };
10148};
10149var isSession = (object) => {
10150 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";
10151};
10152function createSessionStorage({
10153 cookie: cookieArg,
10154 createData,
10155 readData,
10156 updateData,
10157 deleteData
10158}) {
10159 let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
10160 warnOnceAboutSigningSessionCookie(cookie);
10161 return {
10162 async getSession(cookieHeader, options) {
10163 let id = cookieHeader && await cookie.parse(cookieHeader, options);
10164 let data2 = id && await readData(id);
10165 return createSession(data2 || {}, id || "");
10166 },
10167 async commitSession(session, options) {
10168 let { id, data: data2 } = session;
10169 let expires = options?.maxAge != null ? new Date(Date.now() + options.maxAge * 1e3) : options?.expires != null ? options.expires : cookie.expires;
10170 if (id) {
10171 await updateData(id, data2, expires);
10172 } else {
10173 id = await createData(data2, expires);
10174 }
10175 return cookie.serialize(id, options);
10176 },
10177 async destroySession(session, options) {
10178 await deleteData(session.id);
10179 return cookie.serialize("", {
10180 ...options,
10181 maxAge: void 0,
10182 expires: /* @__PURE__ */ new Date(0)
10183 });
10184 }
10185 };
10186}
10187function warnOnceAboutSigningSessionCookie(cookie) {
10188 warnOnce(
10189 cookie.isSigned,
10190 `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://remix.run/utils/cookies#signing-cookies for more information.`
10191 );
10192}
10193
10194// lib/server-runtime/sessions/cookieStorage.ts
10195function createCookieSessionStorage({ cookie: cookieArg } = {}) {
10196 let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
10197 warnOnceAboutSigningSessionCookie(cookie);
10198 return {
10199 async getSession(cookieHeader, options) {
10200 return createSession(
10201 cookieHeader && await cookie.parse(cookieHeader, options) || {}
10202 );
10203 },
10204 async commitSession(session, options) {
10205 let serializedCookie = await cookie.serialize(session.data, options);
10206 if (serializedCookie.length > 4096) {
10207 throw new Error(
10208 "Cookie length will exceed browser maximum. Length: " + serializedCookie.length
10209 );
10210 }
10211 return serializedCookie;
10212 },
10213 async destroySession(_session, options) {
10214 return cookie.serialize("", {
10215 ...options,
10216 maxAge: void 0,
10217 expires: /* @__PURE__ */ new Date(0)
10218 });
10219 }
10220 };
10221}
10222
10223// lib/server-runtime/sessions/memoryStorage.ts
10224function createMemorySessionStorage({ cookie } = {}) {
10225 let map = /* @__PURE__ */ new Map();
10226 return createSessionStorage({
10227 cookie,
10228 async createData(data2, expires) {
10229 let id = Math.random().toString(36).substring(2, 10);
10230 map.set(id, { data: data2, expires });
10231 return id;
10232 },
10233 async readData(id) {
10234 if (map.has(id)) {
10235 let { data: data2, expires } = map.get(id);
10236 if (!expires || expires > /* @__PURE__ */ new Date()) {
10237 return data2;
10238 }
10239 if (expires) map.delete(id);
10240 }
10241 return null;
10242 },
10243 async updateData(id, data2, expires) {
10244 map.set(id, { data: data2, expires });
10245 },
10246 async deleteData(id) {
10247 map.delete(id);
10248 }
10249 });
10250}
10251
10252// lib/href.ts
10253function href(path, ...args) {
10254 let params = args[0];
10255 return path.split("/").map((segment) => {
10256 const match = segment.match(/^:([\w-]+)(\?)?/);
10257 if (!match) return segment;
10258 const param = match[1];
10259 const value = params ? params[param] : void 0;
10260 const isRequired = match[2] === void 0;
10261 if (isRequired && value === void 0) {
10262 throw Error(
10263 `Path '${path}' requires param '${param}' but it was not provided`
10264 );
10265 }
10266 return value;
10267 }).filter((segment) => segment !== void 0).join("/");
10268}
10269
10270// lib/dom/ssr/errors.ts
10271function deserializeErrors2(errors) {
10272 if (!errors) return null;
10273 let entries = Object.entries(errors);
10274 let serialized = {};
10275 for (let [key, val] of entries) {
10276 if (val && val.__type === "RouteErrorResponse") {
10277 serialized[key] = new ErrorResponseImpl(
10278 val.status,
10279 val.statusText,
10280 val.data,
10281 val.internal === true
10282 );
10283 } else if (val && val.__type === "Error") {
10284 if (val.__subType) {
10285 let ErrorConstructor = window[val.__subType];
10286 if (typeof ErrorConstructor === "function") {
10287 try {
10288 let error = new ErrorConstructor(val.message);
10289 error.stack = val.stack;
10290 serialized[key] = error;
10291 } catch (e) {
10292 }
10293 }
10294 }
10295 if (serialized[key] == null) {
10296 let error = new Error(val.message);
10297 error.stack = val.stack;
10298 serialized[key] = error;
10299 }
10300 } else {
10301 serialized[key] = val;
10302 }
10303 }
10304 return serialized;
10305}
10306// Annotate the CommonJS export names for ESM import in node:
103070 && (module.exports = {
10308 Await,
10309 BrowserRouter,
10310 Form,
10311 HashRouter,
10312 IDLE_BLOCKER,
10313 IDLE_FETCHER,
10314 IDLE_NAVIGATION,
10315 Link,
10316 Links,
10317 MemoryRouter,
10318 Meta,
10319 NavLink,
10320 Navigate,
10321 NavigationType,
10322 Outlet,
10323 PrefetchPageLinks,
10324 Route,
10325 Router,
10326 RouterProvider,
10327 Routes,
10328 Scripts,
10329 ScrollRestoration,
10330 ServerRouter,
10331 StaticRouter,
10332 StaticRouterProvider,
10333 UNSAFE_DataRouterContext,
10334 UNSAFE_DataRouterStateContext,
10335 UNSAFE_ErrorResponseImpl,
10336 UNSAFE_FetchersContext,
10337 UNSAFE_FrameworkContext,
10338 UNSAFE_LocationContext,
10339 UNSAFE_NavigationContext,
10340 UNSAFE_RemixErrorBoundary,
10341 UNSAFE_RouteContext,
10342 UNSAFE_ServerMode,
10343 UNSAFE_SingleFetchRedirectSymbol,
10344 UNSAFE_ViewTransitionContext,
10345 UNSAFE_createBrowserHistory,
10346 UNSAFE_createClientRoutes,
10347 UNSAFE_createClientRoutesWithHMRRevalidationOptOut,
10348 UNSAFE_createRouter,
10349 UNSAFE_decodeViaTurboStream,
10350 UNSAFE_deserializeErrors,
10351 UNSAFE_getPatchRoutesOnNavigationFunction,
10352 UNSAFE_getSingleFetchDataStrategy,
10353 UNSAFE_invariant,
10354 UNSAFE_mapRouteProperties,
10355 UNSAFE_shouldHydrateRouteLoader,
10356 UNSAFE_useFogOFWarDiscovery,
10357 UNSAFE_useScrollRestoration,
10358 createBrowserRouter,
10359 createCookie,
10360 createCookieSessionStorage,
10361 createHashRouter,
10362 createMemoryRouter,
10363 createMemorySessionStorage,
10364 createPath,
10365 createRequestHandler,
10366 createRoutesFromChildren,
10367 createRoutesFromElements,
10368 createRoutesStub,
10369 createSearchParams,
10370 createSession,
10371 createSessionStorage,
10372 createStaticHandler,
10373 createStaticRouter,
10374 data,
10375 generatePath,
10376 href,
10377 isCookie,
10378 isRouteErrorResponse,
10379 isSession,
10380 matchPath,
10381 matchRoutes,
10382 parsePath,
10383 redirect,
10384 redirectDocument,
10385 renderMatches,
10386 replace,
10387 resolvePath,
10388 unstable_HistoryRouter,
10389 unstable_RouterContextProvider,
10390 unstable_createContext,
10391 unstable_setDevServerHooks,
10392 unstable_usePrompt,
10393 useActionData,
10394 useAsyncError,
10395 useAsyncValue,
10396 useBeforeUnload,
10397 useBlocker,
10398 useFetcher,
10399 useFetchers,
10400 useFormAction,
10401 useHref,
10402 useInRouterContext,
10403 useLinkClickHandler,
10404 useLoaderData,
10405 useLocation,
10406 useMatch,
10407 useMatches,
10408 useNavigate,
10409 useNavigation,
10410 useNavigationType,
10411 useOutlet,
10412 useOutletContext,
10413 useParams,
10414 useResolvedPath,
10415 useRevalidator,
10416 useRouteError,
10417 useRouteLoaderData,
10418 useRoutes,
10419 useSearchParams,
10420 useSubmit,
10421 useViewTransitionState
10422});