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