UNPKG

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