UNPKG

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