UNPKG

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