{"version":3,"file":"router.umd.min.js","sources":["../history.ts","../utils.ts","../router.ts"],"sourcesContent":["////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Actions represent the type of change to a location value.\n */\nexport enum Action {\n /**\n * A POP indicates a change to an arbitrary index in the history stack, such\n * as a back or forward navigation. It does not describe the direction of the\n * navigation, only that the current index changed.\n *\n * Note: This is the default action for newly created history objects.\n */\n Pop = \"POP\",\n\n /**\n * A PUSH indicates a new entry being added to the history stack, such as when\n * a link is clicked and a new page loads. When this happens, all subsequent\n * entries in the stack are lost.\n */\n Push = \"PUSH\",\n\n /**\n * A REPLACE indicates the entry at the current index in the history stack\n * being replaced by a new one.\n */\n Replace = \"REPLACE\",\n}\n\n/**\n * The pathname, search, and hash values of a URL.\n */\nexport interface Path {\n /**\n * A URL pathname, beginning with a /.\n */\n pathname: string;\n\n /**\n * A URL search string, beginning with a ?.\n */\n search: string;\n\n /**\n * A URL fragment identifier, beginning with a #.\n */\n hash: string;\n}\n\n/**\n * An entry in a history stack. A location contains information about the\n * URL path, as well as possibly some arbitrary state and a key.\n */\nexport interface Location extends Path {\n /**\n * A value of arbitrary data associated with this location.\n */\n state: any;\n\n /**\n * A unique string associated with this location. May be used to safely store\n * and retrieve data in some other storage API, like `localStorage`.\n *\n * Note: This value is always \"default\" on the initial location.\n */\n key: string;\n}\n\n/**\n * A change to the current location.\n */\nexport interface Update {\n /**\n * The action that triggered the change.\n */\n action: Action;\n\n /**\n * The new location.\n */\n location: Location;\n\n /**\n * The delta between this location and the former location in the history stack\n */\n delta: number | null;\n}\n\n/**\n * A function that receives notifications about location changes.\n */\nexport interface Listener {\n (update: Update): void;\n}\n\n/**\n * Describes a location that is the destination of some navigation, either via\n * `history.push` or `history.replace`. May be either a URL or the pieces of a\n * URL path.\n */\nexport type To = string | Partial;\n\n/**\n * A history is an interface to the navigation stack. The history serves as the\n * source of truth for the current location, as well as provides a set of\n * methods that may be used to change it.\n *\n * It is similar to the DOM's `window.history` object, but with a smaller, more\n * focused API.\n */\nexport interface History {\n /**\n * The last action that modified the current location. This will always be\n * Action.Pop when a history instance is first created. This value is mutable.\n */\n readonly action: Action;\n\n /**\n * The current location. This value is mutable.\n */\n readonly location: Location;\n\n /**\n * Returns a valid href for the given `to` value that may be used as\n * the value of an attribute.\n *\n * @param to - The destination URL\n */\n createHref(to: To): string;\n\n /**\n * Returns a URL for the given `to` value\n *\n * @param to - The destination URL\n */\n createURL(to: To): URL;\n\n /**\n * Encode a location the same way window.history would do (no-op for memory\n * history) so we ensure our PUSH/REPLACE navigations for data routers\n * behave the same as POP\n *\n * @param to Unencoded path\n */\n encodeLocation(to: To): Path;\n\n /**\n * Pushes a new location onto the history stack, increasing its length by one.\n * If there were any entries in the stack after the current one, they are\n * lost.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n push(to: To, state?: any): void;\n\n /**\n * Replaces the current location in the history stack with a new one. The\n * location that was replaced will no longer be available.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n replace(to: To, state?: any): void;\n\n /**\n * Navigates `n` entries backward/forward in the history stack relative to the\n * current index. For example, a \"back\" navigation would use go(-1).\n *\n * @param delta - The delta in the stack index\n */\n go(delta: number): void;\n\n /**\n * Sets up a listener that will be called whenever the current location\n * changes.\n *\n * @param listener - A function that will be called when the location changes\n * @returns unlisten - A function that may be used to stop listening\n */\n listen(listener: Listener): () => void;\n}\n\ntype HistoryState = {\n usr: any;\n key?: string;\n idx: number;\n};\n\nconst PopStateEventType = \"popstate\";\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Memory History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A user-supplied object that describes a location. Used when providing\n * entries to `createMemoryHistory` via its `initialEntries` option.\n */\nexport type InitialEntry = string | Partial;\n\nexport type MemoryHistoryOptions = {\n initialEntries?: InitialEntry[];\n initialIndex?: number;\n v5Compat?: boolean;\n};\n\n/**\n * A memory history stores locations in memory. This is useful in stateful\n * environments where there is no web browser, such as node tests or React\n * Native.\n */\nexport interface MemoryHistory extends History {\n /**\n * The current index in the history stack.\n */\n readonly index: number;\n}\n\n/**\n * Memory history stores the current location in memory. It is designed for use\n * in stateful non-browser environments like tests and React Native.\n */\nexport function createMemoryHistory(\n options: MemoryHistoryOptions = {}\n): MemoryHistory {\n let { initialEntries = [\"/\"], initialIndex, v5Compat = false } = options;\n let entries: Location[]; // Declare so we can access from createMemoryLocation\n entries = initialEntries.map((entry, index) =>\n createMemoryLocation(\n entry,\n typeof entry === \"string\" ? null : entry.state,\n index === 0 ? \"default\" : undefined\n )\n );\n let index = clampIndex(\n initialIndex == null ? entries.length - 1 : initialIndex\n );\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n function clampIndex(n: number): number {\n return Math.min(Math.max(n, 0), entries.length - 1);\n }\n function getCurrentLocation(): Location {\n return entries[index];\n }\n function createMemoryLocation(\n to: To,\n state: any = null,\n key?: string\n ): Location {\n let location = createLocation(\n entries ? getCurrentLocation().pathname : \"/\",\n to,\n state,\n key\n );\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in memory history: ${JSON.stringify(\n to\n )}`\n );\n return location;\n }\n\n function createHref(to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n let history: MemoryHistory = {\n get index() {\n return index;\n },\n get action() {\n return action;\n },\n get location() {\n return getCurrentLocation();\n },\n createHref,\n createURL(to) {\n return new URL(createHref(to), \"http://localhost\");\n },\n encodeLocation(to: To) {\n let path = typeof to === \"string\" ? parsePath(to) : to;\n return {\n pathname: path.pathname || \"\",\n search: path.search || \"\",\n hash: path.hash || \"\",\n };\n },\n push(to, state) {\n action = Action.Push;\n let nextLocation = createMemoryLocation(to, state);\n index += 1;\n entries.splice(index, entries.length, nextLocation);\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 1 });\n }\n },\n replace(to, state) {\n action = Action.Replace;\n let nextLocation = createMemoryLocation(to, state);\n entries[index] = nextLocation;\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 0 });\n }\n },\n go(delta) {\n action = Action.Pop;\n let nextIndex = clampIndex(index + delta);\n let nextLocation = entries[nextIndex];\n index = nextIndex;\n if (listener) {\n listener({ action, location: nextLocation, delta });\n }\n },\n listen(fn: Listener) {\n listener = fn;\n return () => {\n listener = null;\n };\n },\n };\n\n return history;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Browser History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A browser history stores the current location in regular URLs in a web\n * browser environment. This is the standard for most web apps and provides the\n * cleanest URLs the browser's address bar.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory\n */\nexport interface BrowserHistory extends UrlHistory {}\n\nexport type BrowserHistoryOptions = UrlHistoryOptions;\n\n/**\n * Browser history stores the location in regular URLs. This is the standard for\n * most web apps, but it requires some configuration on the server to ensure you\n * serve the same app at multiple URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory\n */\nexport function createBrowserHistory(\n options: BrowserHistoryOptions = {}\n): BrowserHistory {\n function createBrowserLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let { pathname, search, hash } = window.location;\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createBrowserHref(window: Window, to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n return getUrlBasedHistory(\n createBrowserLocation,\n createBrowserHref,\n null,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Hash History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A hash history stores the current location in the fragment identifier portion\n * of the URL in a web browser environment.\n *\n * This is ideal for apps that do not control the server for some reason\n * (because the fragment identifier is never sent to the server), including some\n * shared hosting environments that do not provide fine-grained controls over\n * which pages are served at which URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory\n */\nexport interface HashHistory extends UrlHistory {}\n\nexport type HashHistoryOptions = UrlHistoryOptions;\n\n/**\n * Hash history stores the location in window.location.hash. This makes it ideal\n * for situations where you don't want to send the location to the server for\n * some reason, either because you do cannot configure it or the URL space is\n * reserved for something else.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory\n */\nexport function createHashHistory(\n options: HashHistoryOptions = {}\n): HashHistory {\n function createHashLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n } = parsePath(window.location.hash.substr(1));\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createHashHref(window: Window, to: To) {\n let base = window.document.querySelector(\"base\");\n let href = \"\";\n\n if (base && base.getAttribute(\"href\")) {\n let url = window.location.href;\n let hashIndex = url.indexOf(\"#\");\n href = hashIndex === -1 ? url : url.slice(0, hashIndex);\n }\n\n return href + \"#\" + (typeof to === \"string\" ? to : createPath(to));\n }\n\n function validateHashLocation(location: Location, to: To) {\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in hash history.push(${JSON.stringify(\n to\n )})`\n );\n }\n\n return getUrlBasedHistory(\n createHashLocation,\n createHashHref,\n validateHashLocation,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region UTILS\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * @private\n */\nexport function invariant(value: boolean, message?: string): asserts value;\nexport function invariant(\n value: T | null | undefined,\n message?: string\n): asserts value is T;\nexport function invariant(value: any, message?: string) {\n if (value === false || value === null || typeof value === \"undefined\") {\n throw new Error(message);\n }\n}\n\nfunction warning(cond: any, message: string) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging history!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nfunction createKey() {\n return Math.random().toString(36).substr(2, 8);\n}\n\n/**\n * For browser-based histories, we combine the state and key into an object\n */\nfunction getHistoryState(location: Location, index: number): HistoryState {\n return {\n usr: location.state,\n key: location.key,\n idx: index,\n };\n}\n\n/**\n * Creates a Location object with a unique key from the given Path\n */\nexport function createLocation(\n current: string | Location,\n to: To,\n state: any = null,\n key?: string\n): Readonly {\n let location: Readonly = {\n pathname: typeof current === \"string\" ? current : current.pathname,\n search: \"\",\n hash: \"\",\n ...(typeof to === \"string\" ? parsePath(to) : to),\n state,\n // TODO: This could be cleaned up. push/replace should probably just take\n // full Locations now and avoid the need to run through this flow at all\n // But that's a pretty big refactor to the current test suite so going to\n // keep as is for the time being and just let any incoming keys take precedence\n key: (to && (to as Location).key) || key || createKey(),\n };\n return location;\n}\n\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nexport function createPath({\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n}: Partial) {\n if (search && search !== \"?\")\n pathname += search.charAt(0) === \"?\" ? search : \"?\" + search;\n if (hash && hash !== \"#\")\n pathname += hash.charAt(0) === \"#\" ? hash : \"#\" + hash;\n return pathname;\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nexport function parsePath(path: string): Partial {\n let parsedPath: Partial = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substr(hashIndex);\n path = path.substr(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substr(searchIndex);\n path = path.substr(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\n\nexport interface UrlHistory extends History {}\n\nexport type UrlHistoryOptions = {\n window?: Window;\n v5Compat?: boolean;\n};\n\nfunction getUrlBasedHistory(\n getLocation: (window: Window, globalHistory: Window[\"history\"]) => Location,\n createHref: (window: Window, to: To) => string,\n validateLocation: ((location: Location, to: To) => void) | null,\n options: UrlHistoryOptions = {}\n): UrlHistory {\n let { window = document.defaultView!, v5Compat = false } = options;\n let globalHistory = window.history;\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n let index = getIndex()!;\n // Index should only be null when we initialize. If not, it's because the\n // user called history.pushState or history.replaceState directly, in which\n // case we should log a warning as it will result in bugs.\n if (index == null) {\n index = 0;\n globalHistory.replaceState({ ...globalHistory.state, idx: index }, \"\");\n }\n\n function getIndex(): number {\n let state = globalHistory.state || { idx: null };\n return state.idx;\n }\n\n function handlePop() {\n action = Action.Pop;\n let nextIndex = getIndex();\n let delta = nextIndex == null ? null : nextIndex - index;\n index = nextIndex;\n if (listener) {\n listener({ action, location: history.location, delta });\n }\n }\n\n function push(to: To, state?: any) {\n action = Action.Push;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex() + 1;\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n\n // try...catch because iOS limits us to 100 pushState calls :/\n try {\n globalHistory.pushState(historyState, \"\", url);\n } catch (error) {\n // They are going to lose state here, but there is no real\n // way to warn them about it since the page will refresh...\n window.location.assign(url);\n }\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 1 });\n }\n }\n\n function replace(to: To, state?: any) {\n action = Action.Replace;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex();\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n globalHistory.replaceState(historyState, \"\", url);\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 0 });\n }\n }\n\n function createURL(to: To): URL {\n // window.location.origin is \"null\" (the literal string value) in Firefox\n // under certain conditions, notably when serving from a local HTML file\n // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n let base =\n window.location.origin !== \"null\"\n ? window.location.origin\n : window.location.href;\n\n let href = typeof to === \"string\" ? to : createPath(to);\n invariant(\n base,\n `No window.location.(origin|href) available to create URL for href: ${href}`\n );\n return new URL(href, base);\n }\n\n let history: History = {\n get action() {\n return action;\n },\n get location() {\n return getLocation(window, globalHistory);\n },\n listen(fn: Listener) {\n if (listener) {\n throw new Error(\"A history only accepts one active listener\");\n }\n window.addEventListener(PopStateEventType, handlePop);\n listener = fn;\n\n return () => {\n window.removeEventListener(PopStateEventType, handlePop);\n listener = null;\n };\n },\n createHref(to) {\n return createHref(window, to);\n },\n createURL,\n encodeLocation(to) {\n // Encode a Location the same way window.location would\n let url = createURL(to);\n return {\n pathname: url.pathname,\n search: url.search,\n hash: url.hash,\n };\n },\n push,\n replace,\n go(n) {\n return globalHistory.go(n);\n },\n };\n\n return history;\n}\n\n//#endregion\n","import type { Location, Path, To } from \"./history\";\nimport { invariant, parsePath } from \"./history\";\n\n/**\n * Map of routeId -> data returned from a loader/action/error\n */\nexport interface RouteData {\n [routeId: string]: any;\n}\n\nexport enum ResultType {\n data = \"data\",\n deferred = \"deferred\",\n redirect = \"redirect\",\n error = \"error\",\n}\n\n/**\n * Successful result from a loader or action\n */\nexport interface SuccessResult {\n type: ResultType.data;\n data: any;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Successful defer() result from a loader or action\n */\nexport interface DeferredResult {\n type: ResultType.deferred;\n deferredData: DeferredData;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Redirect result from a loader or action\n */\nexport interface RedirectResult {\n type: ResultType.redirect;\n status: number;\n location: string;\n revalidate: boolean;\n}\n\n/**\n * Unsuccessful result from a loader or action\n */\nexport interface ErrorResult {\n type: ResultType.error;\n error: any;\n headers?: Headers;\n}\n\n/**\n * Result from a loader or action - potentially successful or unsuccessful\n */\nexport type DataResult =\n | SuccessResult\n | DeferredResult\n | RedirectResult\n | ErrorResult;\n\nexport type MutationFormMethod = \"post\" | \"put\" | \"patch\" | \"delete\";\nexport type FormMethod = \"get\" | MutationFormMethod;\n\nexport type FormEncType =\n | \"application/x-www-form-urlencoded\"\n | \"multipart/form-data\";\n\n/**\n * @private\n * Internal interface to pass around for action submissions, not intended for\n * external consumption\n */\nexport interface Submission {\n formMethod: FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n}\n\n/**\n * @private\n * Arguments passed to route loader/action functions. Same for now but we keep\n * this as a private implementation detail in case they diverge in the future.\n */\ninterface DataFunctionArgs {\n request: Request;\n params: Params;\n context?: any;\n}\n\n/**\n * Arguments passed to loader functions\n */\nexport interface LoaderFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Arguments passed to action functions\n */\nexport interface ActionFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Route loader function signature\n */\nexport interface LoaderFunction {\n (args: LoaderFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route action function signature\n */\nexport interface ActionFunction {\n (args: ActionFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route shouldRevalidate function signature. This runs after any submission\n * (navigation or fetcher), so we flatten the navigation/fetcher submission\n * onto the arguments. It shouldn't matter whether it came from a navigation\n * or a fetcher, what really matters is the URLs and the formData since loaders\n * have to re-run based on the data models that were potentially mutated.\n */\nexport interface ShouldRevalidateFunction {\n (args: {\n currentUrl: URL;\n currentParams: AgnosticDataRouteMatch[\"params\"];\n nextUrl: URL;\n nextParams: AgnosticDataRouteMatch[\"params\"];\n formMethod?: Submission[\"formMethod\"];\n formAction?: Submission[\"formAction\"];\n formEncType?: Submission[\"formEncType\"];\n formData?: Submission[\"formData\"];\n actionResult?: DataResult;\n defaultShouldRevalidate: boolean;\n }): boolean;\n}\n\n/**\n * Base RouteObject with common props shared by all types of routes\n */\ntype AgnosticBaseRouteObject = {\n caseSensitive?: boolean;\n path?: string;\n id?: string;\n loader?: LoaderFunction;\n action?: ActionFunction;\n hasErrorBoundary?: boolean;\n shouldRevalidate?: ShouldRevalidateFunction;\n handle?: any;\n};\n\n/**\n * Index routes must not have children\n */\nexport type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {\n children?: undefined;\n index: true;\n};\n\n/**\n * Non-index routes may have children, but cannot have index\n */\nexport type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {\n children?: AgnosticRouteObject[];\n index?: false;\n};\n\n/**\n * A route object represents a logical route, with (optionally) its child\n * routes organized in a tree-like structure.\n */\nexport type AgnosticRouteObject =\n | AgnosticIndexRouteObject\n | AgnosticNonIndexRouteObject;\n\nexport type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {\n id: string;\n};\n\nexport type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {\n children?: AgnosticDataRouteObject[];\n id: string;\n};\n\n/**\n * A data route object, which is just a RouteObject with a required unique ID\n */\nexport type AgnosticDataRouteObject =\n | AgnosticDataIndexRouteObject\n | AgnosticDataNonIndexRouteObject;\n\n// Recursive helper for finding path parameters in the absence of wildcards\ntype _PathParam =\n // split path into individual path segments\n Path extends `${infer L}/${infer R}`\n ? _PathParam | _PathParam\n : // find params after `:`\n Path extends `:${infer Param}`\n ? Param extends `${infer Optional}?`\n ? Optional\n : Param\n : // otherwise, there aren't any params present\n never;\n\n/**\n * Examples:\n * \"/a/b/*\" -> \"*\"\n * \":a\" -> \"a\"\n * \"/a/:b\" -> \"b\"\n * \"/a/blahblahblah:b\" -> \"b\"\n * \"/:a/:b\" -> \"a\" | \"b\"\n * \"/:a/b/:c/*\" -> \"a\" | \"c\" | \"*\"\n */\ntype PathParam =\n // check if path is just a wildcard\n Path extends \"*\"\n ? \"*\"\n : // look for wildcard at the end of the path\n Path extends `${infer Rest}/*`\n ? \"*\" | _PathParam\n : // look for params in the absence of wildcards\n _PathParam;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey =\n // if could not find path params, fallback to `string`\n [PathParam] extends [never] ? string : PathParam;\n\n/**\n * The parameters that were parsed from the URL path.\n */\nexport type Params = {\n readonly [key in Key]: string | undefined;\n};\n\n/**\n * A RouteMatch contains info about how a route matched a URL.\n */\nexport interface AgnosticRouteMatch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The route object that was used to match.\n */\n route: RouteObjectType;\n}\n\nexport interface AgnosticDataRouteMatch\n extends AgnosticRouteMatch {}\n\nfunction isIndexRoute(\n route: AgnosticRouteObject\n): route is AgnosticIndexRouteObject {\n return route.index === true;\n}\n\n// Walk the route tree generating unique IDs where necessary so we are working\n// solely with AgnosticDataRouteObject's within the Router\nexport function convertRoutesToDataRoutes(\n routes: AgnosticRouteObject[],\n parentPath: number[] = [],\n allIds: Set = new Set()\n): AgnosticDataRouteObject[] {\n return routes.map((route, index) => {\n let treePath = [...parentPath, index];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(\n route.index !== true || !route.children,\n `Cannot specify children on an index route`\n );\n invariant(\n !allIds.has(id),\n `Found a route id collision on id \"${id}\". Route ` +\n \"id's must be globally unique within Data Router usages\"\n );\n allIds.add(id);\n\n if (isIndexRoute(route)) {\n let indexRoute: AgnosticDataIndexRouteObject = { ...route, id };\n return indexRoute;\n } else {\n let pathOrLayoutRoute: AgnosticDataNonIndexRouteObject = {\n ...route,\n id,\n children: route.children\n ? convertRoutesToDataRoutes(route.children, treePath, allIds)\n : undefined,\n };\n return pathOrLayoutRoute;\n }\n });\n}\n\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\nexport function matchRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n locationArg: Partial | string,\n basename = \"/\"\n): AgnosticRouteMatch[] | null {\n let location =\n typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n\n let pathname = stripBasename(location.pathname || \"/\", basename);\n\n if (pathname == null) {\n return null;\n }\n\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n\n let matches = null;\n for (let i = 0; matches == null && i < branches.length; ++i) {\n matches = matchRouteBranch(\n branches[i],\n // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n safelyDecodeURI(pathname)\n );\n }\n\n return matches;\n}\n\ninterface RouteMeta<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n relativePath: string;\n caseSensitive: boolean;\n childrenIndex: number;\n route: RouteObjectType;\n}\n\ninterface RouteBranch<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n path: string;\n score: number;\n routesMeta: RouteMeta[];\n}\n\nfunction flattenRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n branches: RouteBranch[] = [],\n parentsMeta: RouteMeta[] = [],\n parentPath = \"\"\n): RouteBranch[] {\n let flattenRoute = (\n route: RouteObjectType,\n index: number,\n relativePath?: string\n ) => {\n let meta: RouteMeta = {\n relativePath:\n relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route,\n };\n\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(\n meta.relativePath.startsWith(parentPath),\n `Absolute route path \"${meta.relativePath}\" nested under path ` +\n `\"${parentPath}\" is not valid. An absolute child route path ` +\n `must start with the combined path of all its parent routes.`\n );\n\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta);\n\n // Add the children before adding this route to the array so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n if (route.children && route.children.length > 0) {\n invariant(\n // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true,\n `Index routes must not have child routes. Please remove ` +\n `all child routes from route path \"${path}\".`\n );\n\n flattenRoutes(route.children, branches, routesMeta, path);\n }\n\n // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n if (route.path == null && !route.index) {\n return;\n }\n\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta,\n });\n };\n routes.forEach((route, index) => {\n // coarse-grain check for optional params\n if (route.path === \"\" || !route.path?.includes(\"?\")) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n\n return branches;\n}\n\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\nfunction explodeOptionalSegments(path: string): string[] {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n\n let [first, ...rest] = segments;\n\n // Optional path segments are denoted by a trailing `?`\n let isOptional = first.endsWith(\"?\");\n // Compute the corresponding required segment: `foo?` -> `foo`\n let required = first.replace(/\\?$/, \"\");\n\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n\n let result: string[] = [];\n\n // All child paths with the prefix. Do this for all children before the\n // optional version for all children so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explodes _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n result.push(\n ...restExploded.map((subpath) =>\n subpath === \"\" ? required : [required, subpath].join(\"/\")\n )\n );\n\n // Then if this is an optional value, add all child versions without\n if (isOptional) {\n result.push(...restExploded);\n }\n\n // for absolute paths, ensure `/` instead of empty segment\n return result.map((exploded) =>\n path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded\n );\n}\n\nfunction rankRouteBranches(branches: RouteBranch[]): void {\n branches.sort((a, b) =>\n a.score !== b.score\n ? b.score - a.score // Higher score first\n : compareIndexes(\n a.routesMeta.map((meta) => meta.childrenIndex),\n b.routesMeta.map((meta) => meta.childrenIndex)\n )\n );\n}\n\nconst paramRe = /^:\\w+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\nconst isSplat = (s: string) => s === \"*\";\n\nfunction computeScore(path: string, index: boolean | undefined): number {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n\n if (index) {\n initialScore += indexRouteValue;\n }\n\n return segments\n .filter((s) => !isSplat(s))\n .reduce(\n (score, segment) =>\n score +\n (paramRe.test(segment)\n ? dynamicSegmentValue\n : segment === \"\"\n ? emptySegmentValue\n : staticSegmentValue),\n initialScore\n );\n}\n\nfunction compareIndexes(a: number[], b: number[]): number {\n let siblings =\n a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n\n return siblings\n ? // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1]\n : // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\n\nfunction matchRouteBranch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n branch: RouteBranch,\n pathname: string\n): AgnosticRouteMatch[] | null {\n let { routesMeta } = branch;\n\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches: AgnosticRouteMatch[] = [];\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname =\n matchedPathname === \"/\"\n ? pathname\n : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath(\n { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },\n remainingPathname\n );\n\n if (!match) return null;\n\n Object.assign(matchedParams, match.params);\n\n let route = meta.route;\n\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams as Params,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(\n joinPaths([matchedPathname, match.pathnameBase])\n ),\n route,\n });\n\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n\n return matches;\n}\n\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\nexport function generatePath(\n originalPath: Path,\n params: {\n [key in PathParam]: string | null;\n } = {} as any\n): string {\n let path = originalPath;\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(\n false,\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n path = path.replace(/\\*$/, \"/*\") as Path;\n }\n\n return (\n path\n .replace(\n /^:(\\w+)(\\??)/g,\n (_, key: PathParam, optional: string | undefined) => {\n let param = params[key];\n if (optional === \"?\") {\n return param == null ? \"\" : param;\n }\n if (param == null) {\n invariant(false, `Missing \":${key}\" param`);\n }\n return param;\n }\n )\n .replace(\n /\\/:(\\w+)(\\??)/g,\n (_, key: PathParam, optional: string | undefined) => {\n let param = params[key];\n if (optional === \"?\") {\n return param == null ? \"\" : `/${param}`;\n }\n if (param == null) {\n invariant(false, `Missing \":${key}\" param`);\n }\n return `/${param}`;\n }\n )\n // Remove any optional markers from optional static segments\n .replace(/\\?/g, \"\")\n .replace(/(\\/?)\\*/, (_, prefix, __, str) => {\n const star = \"*\" as PathParam;\n\n if (params[star] == null) {\n // If no splat was provided, trim the trailing slash _unless_ it's\n // the entire path\n return str === \"/*\" ? \"/\" : \"\";\n }\n\n // Apply the splat\n return `${prefix}${params[star]}`;\n })\n );\n}\n\n/**\n * A PathPattern is used to match on some portion of a URL pathname.\n */\nexport interface PathPattern {\n /**\n * A string to match against a URL pathname. May contain `:id`-style segments\n * to indicate placeholders for dynamic parameters. May also end with `/*` to\n * indicate matching the rest of the URL pathname.\n */\n path: Path;\n /**\n * Should be `true` if the static portions of the `path` should be matched in\n * the same case.\n */\n caseSensitive?: boolean;\n /**\n * Should be `true` if this pattern should match the entire URL pathname.\n */\n end?: boolean;\n}\n\n/**\n * A PathMatch contains info about how a PathPattern matched on a URL pathname.\n */\nexport interface PathMatch {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The pattern that was used to match.\n */\n pattern: PathPattern;\n}\n\ntype Mutable = {\n -readonly [P in keyof T]: T[P];\n};\n\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\nexport function matchPath<\n ParamKey extends ParamParseKey,\n Path extends string\n>(\n pattern: PathPattern | Path,\n pathname: string\n): PathMatch | null {\n if (typeof pattern === \"string\") {\n pattern = { path: pattern, caseSensitive: false, end: true };\n }\n\n let [matcher, paramNames] = compilePath(\n pattern.path,\n pattern.caseSensitive,\n pattern.end\n );\n\n let match = pathname.match(matcher);\n if (!match) return null;\n\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params: Params = paramNames.reduce>(\n (memo, paramName, index) => {\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname\n .slice(0, matchedPathname.length - splatValue.length)\n .replace(/(.)\\/+$/, \"$1\");\n }\n\n memo[paramName] = safelyDecodeURIComponent(\n captureGroups[index] || \"\",\n paramName\n );\n return memo;\n },\n {}\n );\n\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern,\n };\n}\n\nfunction compilePath(\n path: string,\n caseSensitive = false,\n end = true\n): [RegExp, string[]] {\n warning(\n path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"),\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n\n let paramNames: string[] = [];\n let regexpSource =\n \"^\" +\n path\n .replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^$?{}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:(\\w+)/g, (_: string, paramName: string) => {\n paramNames.push(paramName);\n return \"/([^\\\\/]+)\";\n });\n\n if (path.endsWith(\"*\")) {\n paramNames.push(\"*\");\n regexpSource +=\n path === \"*\" || path === \"/*\"\n ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else {\n // Nothing to match for \"\" or \"/\"\n }\n\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n\n return [matcher, paramNames];\n}\n\nfunction safelyDecodeURI(value: string) {\n try {\n return decodeURI(value);\n } catch (error) {\n warning(\n false,\n `The URL path \"${value}\" could not be decoded because it is is a ` +\n `malformed URL segment. This is probably due to a bad percent ` +\n `encoding (${error}).`\n );\n\n return value;\n }\n}\n\nfunction safelyDecodeURIComponent(value: string, paramName: string) {\n try {\n return decodeURIComponent(value);\n } catch (error) {\n warning(\n false,\n `The value for the URL param \"${paramName}\" will not be decoded because` +\n ` the string \"${value}\" is a malformed URL segment. This is probably` +\n ` due to a bad percent encoding (${error}).`\n );\n\n return value;\n }\n}\n\n/**\n * @private\n */\nexport function stripBasename(\n pathname: string,\n basename: string\n): string | null {\n if (basename === \"/\") return pathname;\n\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n }\n\n // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n let startIndex = basename.endsWith(\"/\")\n ? basename.length - 1\n : basename.length;\n let nextChar = pathname.charAt(startIndex);\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n\n return pathname.slice(startIndex) || \"/\";\n}\n\n/**\n * @private\n */\nexport function warning(cond: any, message: string): void {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging @remix-run/router!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\nexport function resolvePath(to: To, fromPathname = \"/\"): Path {\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\",\n } = typeof to === \"string\" ? parsePath(to) : to;\n\n let pathname = toPathname\n ? toPathname.startsWith(\"/\")\n ? toPathname\n : resolvePathname(toPathname, fromPathname)\n : fromPathname;\n\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash),\n };\n}\n\nfunction resolvePathname(relativePath: string, fromPathname: string): string {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n\n relativeSegments.forEach((segment) => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\n\nfunction getInvalidPathError(\n char: string,\n field: string,\n dest: string,\n path: Partial\n) {\n return (\n `Cannot include a '${char}' character in a manually specified ` +\n `\\`to.${field}\\` field [${JSON.stringify(\n path\n )}]. Please separate it out to the ` +\n `\\`to.${dest}\\` field. Alternatively you may provide the full path as ` +\n `a string in and the router will parse it for you.`\n );\n}\n\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * \n * \n * \n *\n * \n * \n * }> // <-- Does not contribute\n * // <-- Does not contribute\n * \n * \n */\nexport function getPathContributingMatches<\n T extends AgnosticRouteMatch = AgnosticRouteMatch\n>(matches: T[]) {\n return matches.filter(\n (match, index) =>\n index === 0 || (match.route.path && match.route.path.length > 0)\n );\n}\n\n/**\n * @private\n */\nexport function resolveTo(\n toArg: To,\n routePathnames: string[],\n locationPathname: string,\n isPathRelative = false\n): Path {\n let to: Partial;\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = { ...toArg };\n\n invariant(\n !to.pathname || !to.pathname.includes(\"?\"),\n getInvalidPathError(\"?\", \"pathname\", \"search\", to)\n );\n invariant(\n !to.pathname || !to.pathname.includes(\"#\"),\n getInvalidPathError(\"#\", \"pathname\", \"hash\", to)\n );\n invariant(\n !to.search || !to.search.includes(\"#\"),\n getInvalidPathError(\"#\", \"search\", \"hash\", to)\n );\n }\n\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n\n let from: string;\n\n // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n if (isPathRelative || toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n\n if (toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\");\n\n // Each leading .. segment means \"go up one route\" instead of \"go up one\n // URL segment\". This is a key difference from how works and a\n // major reason we call this a \"to\" value instead of a \"href\".\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n\n to.pathname = toSegments.join(\"/\");\n }\n\n // If there are more \"..\" segments than parent routes, resolve relative to\n // the root / URL.\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n\n let path = resolvePath(to, from);\n\n // Ensure the pathname has a trailing slash if the original \"to\" had one\n let hasExplicitTrailingSlash =\n toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\");\n // Or if this was a link to the current path which has a trailing slash\n let hasCurrentTrailingSlash =\n (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n if (\n !path.pathname.endsWith(\"/\") &&\n (hasExplicitTrailingSlash || hasCurrentTrailingSlash)\n ) {\n path.pathname += \"/\";\n }\n\n return path;\n}\n\n/**\n * @private\n */\nexport function getToPathname(to: To): string | undefined {\n // Empty strings should be treated the same as / paths\n return to === \"\" || (to as Path).pathname === \"\"\n ? \"/\"\n : typeof to === \"string\"\n ? parsePath(to).pathname\n : to.pathname;\n}\n\n/**\n * @private\n */\nexport const joinPaths = (paths: string[]): string =>\n paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n\n/**\n * @private\n */\nexport const normalizePathname = (pathname: string): string =>\n pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n\n/**\n * @private\n */\nexport const normalizeSearch = (search: string): string =>\n !search || search === \"?\"\n ? \"\"\n : search.startsWith(\"?\")\n ? search\n : \"?\" + search;\n\n/**\n * @private\n */\nexport const normalizeHash = (hash: string): string =>\n !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n\nexport type JsonFunction = (\n data: Data,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\nexport const json: JsonFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n let headers = new Headers(responseInit.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n\n return new Response(JSON.stringify(data), {\n ...responseInit,\n headers,\n });\n};\n\nexport interface TrackedPromise extends Promise {\n _tracked?: boolean;\n _data?: any;\n _error?: any;\n}\n\nexport class AbortedDeferredError extends Error {}\n\nexport class DeferredData {\n private pendingKeysSet: Set = new Set();\n private controller: AbortController;\n private abortPromise: Promise;\n private unlistenAbortSignal: () => void;\n private subscribers: Set<(aborted: boolean, settledKey?: string) => void> =\n new Set();\n data: Record;\n init?: ResponseInit;\n deferredKeys: string[] = [];\n\n constructor(data: Record, responseInit?: ResponseInit) {\n invariant(\n data && typeof data === \"object\" && !Array.isArray(data),\n \"defer() only accepts plain objects\"\n );\n\n // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n let reject: (e: AbortedDeferredError) => void;\n this.abortPromise = new Promise((_, r) => (reject = r));\n this.controller = new AbortController();\n let onAbort = () =>\n reject(new AbortedDeferredError(\"Deferred data aborted\"));\n this.unlistenAbortSignal = () =>\n this.controller.signal.removeEventListener(\"abort\", onAbort);\n this.controller.signal.addEventListener(\"abort\", onAbort);\n\n this.data = Object.entries(data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: this.trackPromise(key, value),\n }),\n {}\n );\n\n if (this.done) {\n // All incoming values were resolved\n this.unlistenAbortSignal();\n }\n\n this.init = responseInit;\n }\n\n private trackPromise(\n key: string,\n value: Promise | unknown\n ): TrackedPromise | unknown {\n if (!(value instanceof Promise)) {\n return value;\n }\n\n this.deferredKeys.push(key);\n this.pendingKeysSet.add(key);\n\n // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then(\n (data) => this.onSettle(promise, key, null, data as unknown),\n (error) => this.onSettle(promise, key, error as unknown)\n );\n\n // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n promise.catch(() => {});\n\n Object.defineProperty(promise, \"_tracked\", { get: () => true });\n return promise;\n }\n\n private onSettle(\n promise: TrackedPromise,\n key: string,\n error: unknown,\n data?: unknown\n ): unknown {\n if (\n this.controller.signal.aborted &&\n error instanceof AbortedDeferredError\n ) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", { get: () => error });\n return Promise.reject(error);\n }\n\n this.pendingKeysSet.delete(key);\n\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n\n if (error) {\n Object.defineProperty(promise, \"_error\", { get: () => error });\n this.emit(false, key);\n return Promise.reject(error);\n }\n\n Object.defineProperty(promise, \"_data\", { get: () => data });\n this.emit(false, key);\n return data;\n }\n\n private emit(aborted: boolean, settledKey?: string) {\n this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey));\n }\n\n subscribe(fn: (aborted: boolean, settledKey?: string) => void) {\n this.subscribers.add(fn);\n return () => this.subscribers.delete(fn);\n }\n\n cancel() {\n this.controller.abort();\n this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));\n this.emit(true);\n }\n\n async resolveData(signal: AbortSignal) {\n let aborted = false;\n if (!this.done) {\n let onAbort = () => this.cancel();\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise((resolve) => {\n this.subscribe((aborted) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n return aborted;\n }\n\n get done() {\n return this.pendingKeysSet.size === 0;\n }\n\n get unwrappedData() {\n invariant(\n this.data !== null && this.done,\n \"Can only unwrap data on initialized and settled deferreds\"\n );\n\n return Object.entries(this.data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: unwrapTrackedPromise(value),\n }),\n {}\n );\n }\n\n get pendingKeys() {\n return Array.from(this.pendingKeysSet);\n }\n}\n\nfunction isTrackedPromise(value: any): value is TrackedPromise {\n return (\n value instanceof Promise && (value as TrackedPromise)._tracked === true\n );\n}\n\nfunction unwrapTrackedPromise(value: any) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n\n if (value._error) {\n throw value._error;\n }\n return value._data;\n}\n\nexport type DeferFunction = (\n data: Record,\n init?: number | ResponseInit\n) => DeferredData;\n\nexport const defer: DeferFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n return new DeferredData(data, responseInit);\n};\n\nexport type RedirectFunction = (\n url: string,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nexport const redirect: RedirectFunction = (url, init = 302) => {\n let responseInit = init;\n if (typeof responseInit === \"number\") {\n responseInit = { status: responseInit };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...responseInit,\n headers,\n });\n};\n\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n */\nexport class ErrorResponse {\n status: number;\n statusText: string;\n data: any;\n error?: Error;\n internal: boolean;\n\n constructor(\n status: number,\n statusText: string | undefined,\n data: any,\n internal = false\n ) {\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n}\n\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response thrown from an action/loader\n */\nexport function isRouteErrorResponse(error: any): error is ErrorResponse {\n return (\n error != null &&\n typeof error.status === \"number\" &&\n typeof error.statusText === \"string\" &&\n typeof error.internal === \"boolean\" &&\n \"data\" in error\n );\n}\n","import type { History, Location, Path, To } from \"./history\";\nimport {\n Action as HistoryAction,\n createLocation,\n createPath,\n invariant,\n parsePath,\n} from \"./history\";\nimport type {\n DataResult,\n AgnosticDataRouteMatch,\n AgnosticDataRouteObject,\n DeferredResult,\n ErrorResult,\n FormEncType,\n FormMethod,\n RedirectResult,\n RouteData,\n AgnosticRouteObject,\n Submission,\n SuccessResult,\n AgnosticRouteMatch,\n MutationFormMethod,\n ShouldRevalidateFunction,\n} from \"./utils\";\nimport {\n DeferredData,\n ErrorResponse,\n ResultType,\n convertRoutesToDataRoutes,\n getPathContributingMatches,\n isRouteErrorResponse,\n joinPaths,\n matchRoutes,\n resolveTo,\n warning,\n} from \"./utils\";\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A Router instance manages all navigation and data loading/mutations\n */\nexport interface Router {\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the basename for the router\n */\n get basename(): RouterInit[\"basename\"];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the current state of the router\n */\n get state(): RouterState;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the routes for this router instance\n */\n get routes(): AgnosticDataRouteObject[];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Initialize the router, including adding history listeners and kicking off\n * initial data fetches. Returns a function to cleanup listeners and abort\n * any in-progress loads\n */\n initialize(): Router;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Subscribe to router.state updates\n *\n * @param fn function to call with the new state\n */\n subscribe(fn: RouterSubscriber): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Enable scroll restoration behavior in the router\n *\n * @param savedScrollPositions Object that will manage positions, in case\n * it's being restored from sessionStorage\n * @param getScrollPosition Function to get the active Y scroll position\n * @param getKey Function to get the key to use for restoration\n */\n enableScrollRestoration(\n savedScrollPositions: Record,\n getScrollPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Navigate forward/backward in the history stack\n * @param to Delta to move in the history stack\n */\n navigate(to: number): Promise;\n\n /**\n * Navigate to the given path\n * @param to Path to navigate to\n * @param opts Navigation options (method, submission, etc.)\n */\n navigate(to: To, opts?: RouterNavigateOptions): Promise;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a fetcher load/submission\n *\n * @param key Fetcher key\n * @param routeId Route that owns the fetcher\n * @param href href to fetch\n * @param opts Fetcher options, (method, submission, etc.)\n */\n fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterNavigateOptions\n ): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a revalidation of all current route loaders and fetcher loads\n */\n revalidate(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to create an href for the given location\n * @param location\n */\n createHref(location: Location | URL): string;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to URL encode a destination path according to the internal\n * history implementation\n * @param to\n */\n encodeLocation(to: To): Path;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get/create a fetcher for the given key\n * @param key\n */\n getFetcher(key?: string): Fetcher;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete the fetcher for a given key\n * @param key\n */\n deleteFetcher(key?: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Cleanup listeners and abort any in-progress loads\n */\n dispose(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get a navigation blocker\n * @param key The identifier for the blocker\n * @param fn The blocker function implementation\n */\n getBlocker(key: string, fn: BlockerFunction): Blocker;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete a navigation blocker\n * @param key The identifier for the blocker\n */\n deleteBlocker(key: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal fetch AbortControllers accessed by unit tests\n */\n _internalFetchControllers: Map;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal pending DeferredData instances accessed by unit tests\n */\n _internalActiveDeferreds: Map;\n}\n\n/**\n * State maintained internally by the router. During a navigation, all states\n * reflect the the \"old\" location unless otherwise noted.\n */\nexport interface RouterState {\n /**\n * The action of the most recent navigation\n */\n historyAction: HistoryAction;\n\n /**\n * The current location reflected by the router\n */\n location: Location;\n\n /**\n * The current set of route matches\n */\n matches: AgnosticDataRouteMatch[];\n\n /**\n * Tracks whether we've completed our initial data load\n */\n initialized: boolean;\n\n /**\n * Current scroll position we should start at for a new view\n * - number -> scroll position to restore to\n * - false -> do not restore scroll at all (used during submissions)\n * - null -> don't have a saved position, scroll to hash or top of page\n */\n restoreScrollPosition: number | false | null;\n\n /**\n * Indicate whether this navigation should skip resetting the scroll position\n * if we are unable to restore the scroll position\n */\n preventScrollReset: boolean;\n\n /**\n * Tracks the state of the current navigation\n */\n navigation: Navigation;\n\n /**\n * Tracks any in-progress revalidations\n */\n revalidation: RevalidationState;\n\n /**\n * Data from the loaders for the current matches\n */\n loaderData: RouteData;\n\n /**\n * Data from the action for the current matches\n */\n actionData: RouteData | null;\n\n /**\n * Errors caught from loaders for the current matches\n */\n errors: RouteData | null;\n\n /**\n * Map of current fetchers\n */\n fetchers: Map;\n\n /**\n * Map of current blockers\n */\n blockers: Map;\n}\n\n/**\n * Data that can be passed into hydrate a Router from SSR\n */\nexport type HydrationState = Partial<\n Pick\n>;\n\n/**\n * Initialization options for createRouter\n */\nexport interface RouterInit {\n basename?: string;\n routes: AgnosticRouteObject[];\n history: History;\n hydrationData?: HydrationState;\n}\n\n/**\n * State returned from a server-side query() call\n */\nexport interface StaticHandlerContext {\n basename: Router[\"basename\"];\n location: RouterState[\"location\"];\n matches: RouterState[\"matches\"];\n loaderData: RouterState[\"loaderData\"];\n actionData: RouterState[\"actionData\"];\n errors: RouterState[\"errors\"];\n statusCode: number;\n loaderHeaders: Record;\n actionHeaders: Record;\n activeDeferreds: Record | null;\n _deepestRenderedBoundaryId?: string | null;\n}\n\n/**\n * A StaticHandler instance manages a singular SSR navigation/fetch event\n */\nexport interface StaticHandler {\n dataRoutes: AgnosticDataRouteObject[];\n query(\n request: Request,\n opts?: { requestContext?: unknown }\n ): Promise;\n queryRoute(\n request: Request,\n opts?: { routeId?: string; requestContext?: unknown }\n ): Promise;\n}\n\n/**\n * Subscriber function signature for changes to router state\n */\nexport interface RouterSubscriber {\n (state: RouterState): void;\n}\n\ninterface UseMatchesMatch {\n id: string;\n pathname: string;\n params: AgnosticRouteMatch[\"params\"];\n data: unknown;\n handle: unknown;\n}\n\n/**\n * Function signature for determining the key to be used in scroll restoration\n * for a given location\n */\nexport interface GetScrollRestorationKeyFunction {\n (location: Location, matches: UseMatchesMatch[]): string | null;\n}\n\n/**\n * Function signature for determining the current scroll position\n */\nexport interface GetScrollPositionFunction {\n (): number;\n}\n\n/**\n * Options for a navigate() call for a Link navigation\n */\ntype LinkNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n};\n\n/**\n * Options for a navigate() call for a Form navigation\n */\ntype SubmissionNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n formMethod?: FormMethod;\n formEncType?: FormEncType;\n formData: FormData;\n};\n\n/**\n * Options to pass to navigate() for either a Link or Form navigation\n */\nexport type RouterNavigateOptions =\n | LinkNavigateOptions\n | SubmissionNavigateOptions;\n\n/**\n * Options to pass to fetch()\n */\nexport type RouterFetchOptions =\n | Omit\n | Omit;\n\n/**\n * Potential states for state.navigation\n */\nexport type NavigationStates = {\n Idle: {\n state: \"idle\";\n location: undefined;\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n };\n Loading: {\n state: \"loading\";\n location: Location;\n formMethod: FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n };\n Submitting: {\n state: \"submitting\";\n location: Location;\n formMethod: FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n };\n};\n\nexport type Navigation = NavigationStates[keyof NavigationStates];\n\nexport type RevalidationState = \"idle\" | \"loading\";\n\n/**\n * Potential states for fetchers\n */\ntype FetcherStates = {\n Idle: {\n state: \"idle\";\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Loading: {\n state: \"loading\";\n formMethod: FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Submitting: {\n state: \"submitting\";\n formMethod: FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n};\n\nexport type Fetcher =\n FetcherStates[keyof FetcherStates];\n\ninterface BlockerBlocked {\n state: \"blocked\";\n reset(): void;\n proceed(): void;\n location: Location;\n}\n\ninterface BlockerUnblocked {\n state: \"unblocked\";\n reset: undefined;\n proceed: undefined;\n location: undefined;\n}\n\ninterface BlockerProceeding {\n state: \"proceeding\";\n reset: undefined;\n proceed: undefined;\n location: Location;\n}\n\nexport type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;\n\nexport type BlockerFunction = (args: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n}) => boolean;\n\ninterface ShortCircuitable {\n /**\n * startNavigation does not need to complete the navigation because we\n * redirected or got interrupted\n */\n shortCircuited?: boolean;\n}\n\ninterface HandleActionResult extends ShortCircuitable {\n /**\n * Error thrown from the current action, keyed by the route containing the\n * error boundary to render the error. To be committed to the state after\n * loaders have completed\n */\n pendingActionError?: RouteData;\n /**\n * Data returned from the current action, keyed by the route owning the action.\n * To be committed to the state after loaders have completed\n */\n pendingActionData?: RouteData;\n}\n\ninterface HandleLoadersResult extends ShortCircuitable {\n /**\n * loaderData returned from the current set of loaders\n */\n loaderData?: RouterState[\"loaderData\"];\n /**\n * errors thrown from the current set of loaders\n */\n errors?: RouterState[\"errors\"];\n}\n\n/**\n * Cached info for active fetcher.load() instances so they can participate\n * in revalidation\n */\ninterface FetchLoadMatch {\n routeId: string;\n path: string;\n match: AgnosticDataRouteMatch;\n matches: AgnosticDataRouteMatch[];\n}\n\n/**\n * Identified fetcher.load() calls that need to be revalidated\n */\ninterface RevalidatingFetcher extends FetchLoadMatch {\n key: string;\n}\n\n/**\n * Wrapper object to allow us to throw any response out from callLoaderOrAction\n * for queryRouter while preserving whether or not it was thrown or returned\n * from the loader/action\n */\ninterface QueryRouteResponse {\n type: ResultType.data | ResultType.error;\n response: Response;\n}\n\nconst validMutationMethodsArr: MutationFormMethod[] = [\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n];\nconst validMutationMethods = new Set(\n validMutationMethodsArr\n);\n\nconst validRequestMethodsArr: FormMethod[] = [\n \"get\",\n ...validMutationMethodsArr,\n];\nconst validRequestMethods = new Set(validRequestMethodsArr);\n\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\n\nexport const IDLE_NAVIGATION: NavigationStates[\"Idle\"] = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_FETCHER: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_BLOCKER: BlockerUnblocked = {\n state: \"unblocked\",\n proceed: undefined,\n reset: undefined,\n location: undefined,\n};\n\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\nconst isBrowser =\n typeof window !== \"undefined\" &&\n typeof window.document !== \"undefined\" &&\n typeof window.document.createElement !== \"undefined\";\nconst isServer = !isBrowser;\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a router and listen to history POP navigations\n */\nexport function createRouter(init: RouterInit): Router {\n invariant(\n init.routes.length > 0,\n \"You must provide a non-empty routes array to createRouter\"\n );\n\n let dataRoutes = convertRoutesToDataRoutes(init.routes);\n // Cleanup function for history\n let unlistenHistory: (() => void) | null = null;\n // Externally-provided functions to call on all state changes\n let subscribers = new Set();\n // Externally-provided object to hold scroll restoration locations during routing\n let savedScrollPositions: Record | null = null;\n // Externally-provided function to get scroll restoration keys\n let getScrollRestorationKey: GetScrollRestorationKeyFunction | null = null;\n // Externally-provided function to get current scroll position\n let getScrollPosition: GetScrollPositionFunction | null = null;\n // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n let initialScrollRestored = init.hydrationData != null;\n\n let initialMatches = matchRoutes(\n dataRoutes,\n init.history.location,\n init.basename\n );\n let initialErrors: RouteData | null = null;\n\n if (initialMatches == null) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname,\n });\n let { matches, route } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = { [route.id]: error };\n }\n\n let initialized =\n !initialMatches.some((m) => m.route.loader) || init.hydrationData != null;\n\n let router: Router;\n let state: RouterState = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: (init.hydrationData && init.hydrationData.loaderData) || {},\n actionData: (init.hydrationData && init.hydrationData.actionData) || null,\n errors: (init.hydrationData && init.hydrationData.errors) || initialErrors,\n fetchers: new Map(),\n blockers: new Map(),\n };\n\n // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n let pendingAction: HistoryAction = HistoryAction.Pop;\n\n // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n let pendingPreventScrollReset = false;\n\n // AbortController for the active navigation\n let pendingNavigationController: AbortController | null;\n\n // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n let isUninterruptedRevalidation = false;\n\n // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidate()\n // - X-Remix-Revalidate (from redirect)\n let isRevalidationRequired = false;\n\n // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n let cancelledDeferredRoutes: string[] = [];\n\n // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n let cancelledFetcherLoads: string[] = [];\n\n // AbortControllers for any in-flight fetchers\n let fetchControllers = new Map();\n\n // Track loads based on the order in which they started\n let incrementingLoadId = 0;\n\n // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n let pendingNavigationLoadId = -1;\n\n // Fetchers that triggered data reloads as a result of their actions\n let fetchReloadIds = new Map();\n\n // Fetchers that triggered redirect navigations from their actions\n let fetchRedirectIds = new Set();\n\n // Most recent href/match for fetcher.load calls for fetchers\n let fetchLoadMatches = new Map();\n\n // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n let activeDeferreds = new Map();\n\n // Store blocker functions in a separate Map outside of router state since\n // we don't need to update UI state if they change\n let blockerFunctions = new Map();\n\n // Flag to ignore the next history update, so we can revert the URL change on\n // a POP navigation that was blocked by the user without touching router state\n let ignoreNextHistoryUpdate = false;\n\n // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(\n ({ action: historyAction, location, delta }) => {\n // Ignore this event if it was just us resetting the URL from a\n // blocked POP navigation\n if (ignoreNextHistoryUpdate) {\n ignoreNextHistoryUpdate = false;\n return;\n }\n\n warning(\n blockerFunctions.size === 0 || delta != null,\n \"You are trying to use a blocker on a POP navigation to a location \" +\n \"that was not created by @remix-run/router. This will fail silently in \" +\n \"production. This can happen if you are navigating outside the router \" +\n \"via `window.history.pushState`/`window.location.hash` instead of using \" +\n \"router navigation APIs. This can also happen if you are using \" +\n \"createHashRouter and the user manually changes the URL.\"\n );\n\n let blockerKey = shouldBlockNavigation({\n currentLocation: state.location,\n nextLocation: location,\n historyAction,\n });\n\n if (blockerKey && delta != null) {\n // Restore the URL to match the current UI, but don't update router state\n ignoreNextHistoryUpdate = true;\n init.history.go(delta * -1);\n\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location,\n });\n // Re-do the same POP navigation we just blocked\n init.history.go(delta);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(router.state.blockers) });\n },\n });\n return;\n }\n\n return startNavigation(historyAction, location);\n }\n );\n\n // Kick off initial data load if needed. Use Pop to avoid modifying history\n if (!state.initialized) {\n startNavigation(HistoryAction.Pop, state.location);\n }\n\n return router;\n }\n\n // Clean up a router and it's side effects\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n state.blockers.forEach((_, key) => deleteBlocker(key));\n }\n\n // Subscribe to state updates for the router\n function subscribe(fn: RouterSubscriber) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n // Update our state and notify the calling context of the change\n function updateState(newState: Partial): void {\n state = {\n ...state,\n ...newState,\n };\n subscribers.forEach((subscriber) => subscriber(state));\n }\n\n // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n function completeNavigation(\n location: Location,\n newState: Partial>\n ): void {\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a mutation submission\n // - We're past the submitting state and into the loading state\n // - The location being loaded is not the result of a redirect\n let isActionReload =\n state.actionData != null &&\n state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n state.navigation.state === \"loading\" &&\n location.state?._isRedirect !== true;\n\n let actionData: RouteData | null;\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n }\n\n // Always preserve any existing loaderData from re-used routes\n let loaderData = newState.loaderData\n ? mergeLoaderData(\n state.loaderData,\n newState.loaderData,\n newState.matches || [],\n newState.errors\n )\n : state.loaderData;\n\n // On a successful navigation we can assume we got through all blockers\n // so we can start fresh\n for (let [key] of blockerFunctions) {\n deleteBlocker(key);\n }\n\n // Always respect the user flag. Otherwise don't reset on mutation\n // submission navigations unless they redirect\n let preventScrollReset =\n pendingPreventScrollReset === true ||\n (state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n location.state?._isRedirect !== true);\n\n updateState({\n ...newState, // matches, errors, fetchers go through as-is\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n restoreScrollPosition: getSavedScrollPosition(\n location,\n newState.matches || state.matches\n ),\n preventScrollReset,\n blockers: new Map(state.blockers),\n });\n\n if (isUninterruptedRevalidation) {\n // If this was an uninterrupted revalidation then do not touch history\n } else if (pendingAction === HistoryAction.Pop) {\n // Do nothing for POP - URL has already been updated\n } else if (pendingAction === HistoryAction.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === HistoryAction.Replace) {\n init.history.replace(location, location.state);\n }\n\n // Reset stateful navigation vars\n pendingAction = HistoryAction.Pop;\n pendingPreventScrollReset = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n cancelledFetcherLoads = [];\n }\n\n // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n async function navigate(\n to: number | To,\n opts?: RouterNavigateOptions\n ): Promise {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n\n let { path, submission, error } = normalizeNavigateOptions(to, opts);\n\n let currentLocation = state.location;\n let nextLocation = createLocation(state.location, path, opts && opts.state);\n\n // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n nextLocation = {\n ...nextLocation,\n ...init.history.encodeLocation(nextLocation),\n };\n\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n\n let historyAction = HistoryAction.Push;\n\n if (userReplace === true) {\n historyAction = HistoryAction.Replace;\n } else if (userReplace === false) {\n // no-op\n } else if (\n submission != null &&\n isMutationMethod(submission.formMethod) &&\n submission.formAction === state.location.pathname + state.location.search\n ) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = HistoryAction.Replace;\n }\n\n let preventScrollReset =\n opts && \"preventScrollReset\" in opts\n ? opts.preventScrollReset === true\n : undefined;\n\n let blockerKey = shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n });\n if (blockerKey) {\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location: nextLocation,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location: nextLocation,\n });\n // Send the same navigation through\n navigate(to, opts);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(state.blockers) });\n },\n });\n return;\n }\n\n return await startNavigation(historyAction, nextLocation, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace,\n });\n }\n\n // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n function revalidate() {\n interruptActiveLoads();\n updateState({ revalidation: \"loading\" });\n\n // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n if (state.navigation.state === \"submitting\") {\n return;\n }\n\n // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true,\n });\n return;\n }\n\n // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n startNavigation(\n pendingAction || state.historyAction,\n state.navigation.location,\n { overrideNavigation: state.navigation }\n );\n }\n\n // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n async function startNavigation(\n historyAction: HistoryAction,\n location: Location,\n opts?: {\n submission?: Submission;\n overrideNavigation?: Navigation;\n pendingError?: ErrorResponse;\n startUninterruptedRevalidation?: boolean;\n preventScrollReset?: boolean;\n replace?: boolean;\n }\n ): Promise {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation =\n (opts && opts.startUninterruptedRevalidation) === true;\n\n // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(dataRoutes, location, init.basename);\n\n // Short circuit with a 404 on the root error boundary if we match nothing\n if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(dataRoutes);\n // Cancel all pending deferred on 404s since we don't keep any routes\n cancelActiveDeferreds();\n completeNavigation(location, {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error,\n },\n });\n return;\n }\n\n // Short circuit if it's only a hash change and not a mutation submission\n // For example, on /page#hash and submit a
which will\n // default to a navigation to /page\n if (\n isHashChangeOnly(state.location, location) &&\n !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))\n ) {\n completeNavigation(location, { matches });\n return;\n }\n\n // Create a controller/Request for this navigation\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(\n init.history,\n location,\n pendingNavigationController.signal,\n opts && opts.submission\n );\n let pendingActionData: RouteData | undefined;\n let pendingError: RouteData | undefined;\n\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingError = {\n [findNearestBoundary(matches).route.id]: opts.pendingError,\n };\n } else if (\n opts &&\n opts.submission &&\n isMutationMethod(opts.submission.formMethod)\n ) {\n // Call action if we received an action submission\n let actionOutput = await handleAction(\n request,\n location,\n opts.submission,\n matches,\n { replace: opts.replace }\n );\n\n if (actionOutput.shortCircuited) {\n return;\n }\n\n pendingActionData = actionOutput.pendingActionData;\n pendingError = actionOutput.pendingActionError;\n\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n ...opts.submission,\n };\n loadingNavigation = navigation;\n\n // Create a GET request for the loaders\n request = new Request(request.url, { signal: request.signal });\n }\n\n // Call loaders\n let { shortCircuited, loaderData, errors } = await handleLoaders(\n request,\n location,\n matches,\n loadingNavigation,\n opts && opts.submission,\n opts && opts.replace,\n pendingActionData,\n pendingError\n );\n\n if (shortCircuited) {\n return;\n }\n\n // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n pendingNavigationController = null;\n\n completeNavigation(location, {\n matches,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n loaderData,\n errors,\n });\n }\n\n // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n async function handleAction(\n request: Request,\n location: Location,\n submission: Submission,\n matches: AgnosticDataRouteMatch[],\n opts?: { replace?: boolean }\n ): Promise {\n interruptActiveLoads();\n\n // Put us in a submitting state\n let navigation: NavigationStates[\"Submitting\"] = {\n state: \"submitting\",\n location,\n ...submission,\n };\n updateState({ navigation });\n\n // Call our action and get the result\n let result: DataResult;\n let actionMatch = getTargetMatch(matches, location);\n\n if (!actionMatch.route.action) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id,\n }),\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n router.basename\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n }\n\n if (isRedirectResult(result)) {\n let replace: boolean;\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n replace =\n result.location === state.location.pathname + state.location.search;\n }\n await startRedirectNavigation(state, result, { submission, replace });\n return { shortCircuited: true };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n\n // By default, all submissions are REPLACE navigations, but if the\n // action threw an error that'll be rendered in an errorElement, we fall\n // back to PUSH so that the user can use the back button to get back to\n // the pre-submission form location to try again\n if ((opts && opts.replace) !== true) {\n pendingAction = HistoryAction.Push;\n }\n\n return {\n // Send back an empty object we can use to clear out any prior actionData\n pendingActionData: {},\n pendingActionError: { [boundaryMatch.route.id]: result.error },\n };\n }\n\n if (isDeferredResult(result)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n return {\n pendingActionData: { [actionMatch.route.id]: result.data },\n };\n }\n\n // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n async function handleLoaders(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n overrideNavigation?: Navigation,\n submission?: Submission,\n replace?: boolean,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n ): Promise {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation = overrideNavigation;\n if (!loadingNavigation) {\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n };\n loadingNavigation = navigation;\n }\n\n // If this was a redirect from an action we don't have a \"submission\" but\n // we have it on the loading navigation so use that if available\n let activeSubmission = submission\n ? submission\n : loadingNavigation.formMethod &&\n loadingNavigation.formAction &&\n loadingNavigation.formData &&\n loadingNavigation.formEncType\n ? {\n formMethod: loadingNavigation.formMethod,\n formAction: loadingNavigation.formAction,\n formData: loadingNavigation.formData,\n formEncType: loadingNavigation.formEncType,\n }\n : undefined;\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n activeSubmission,\n location,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n pendingActionData,\n pendingError,\n fetchLoadMatches\n );\n\n // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n cancelActiveDeferreds(\n (routeId) =>\n !(matches && matches.some((m) => m.route.id === routeId)) ||\n (matchesToLoad && matchesToLoad.some((m) => m.route.id === routeId))\n );\n\n // Short circuit if we have no loaders to run\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n completeNavigation(location, {\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingError || null,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n });\n return { shortCircuited: true };\n }\n\n // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n if (!isUninterruptedRevalidation) {\n revalidatingFetchers.forEach((rf) => {\n let fetcher = state.fetchers.get(rf.key);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: fetcher && fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(rf.key, revalidatingFetcher);\n });\n let actionData = pendingActionData || state.actionData;\n updateState({\n navigation: loadingNavigation,\n ...(actionData\n ? Object.keys(actionData).length === 0\n ? { actionData: null }\n : { actionData }\n : {}),\n ...(revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n });\n }\n\n pendingNavigationLoadId = ++incrementingLoadId;\n revalidatingFetchers.forEach((rf) =>\n fetchControllers.set(rf.key, pendingNavigationController!)\n );\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n request\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n\n // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));\n\n // If any loaders returned a redirect Response, start a new REPLACE navigation\n let redirect = findRedirect(results);\n if (redirect) {\n await startRedirectNavigation(state, redirect, { replace });\n return { shortCircuited: true };\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n matches,\n matchesToLoad,\n loaderResults,\n pendingError,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n // Wire up subscribers to update loaderData as promises settle\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe((aborted) => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n\n markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n\n return {\n loaderData,\n errors,\n ...(didAbortFetchLoads || revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n };\n }\n\n function getFetcher(key: string): Fetcher {\n return state.fetchers.get(key) || IDLE_FETCHER;\n }\n\n // Trigger a fetcher load/submit for the given fetcher key\n function fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterFetchOptions\n ) {\n if (isServer) {\n throw new Error(\n \"router.fetch() was called during the server render, but it shouldn't be. \" +\n \"You are likely calling a useFetcher() method in the body of your component. \" +\n \"Try moving it to a useEffect or a callback.\"\n );\n }\n\n if (fetchControllers.has(key)) abortFetcher(key);\n\n let matches = matchRoutes(dataRoutes, href, init.basename);\n if (!matches) {\n setFetcherError(\n key,\n routeId,\n getInternalRouterError(404, { pathname: href })\n );\n return;\n }\n\n let { path, submission } = normalizeNavigateOptions(href, opts, true);\n let match = getTargetMatch(matches, path);\n\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(key, routeId, path, match, matches, submission);\n return;\n }\n\n // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n fetchLoadMatches.set(key, { routeId, path, match, matches });\n handleFetcherLoader(key, routeId, path, match, matches, submission);\n }\n\n // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n async function handleFetcherAction(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n requestMatches: AgnosticDataRouteMatch[],\n submission: Submission\n ) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n\n if (!match.route.action) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId,\n });\n setFetcherError(key, routeId, error);\n return;\n }\n\n // Put this fetcher into it's submitting state\n let existingFetcher = state.fetchers.get(key);\n let fetcher: FetcherStates[\"Submitting\"] = {\n state: \"submitting\",\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, fetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the action for the fetcher\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal,\n submission\n );\n fetchControllers.set(key, abortController);\n\n let actionResult = await callLoaderOrAction(\n \"action\",\n fetchRequest,\n match,\n requestMatches,\n router.basename\n );\n\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n return;\n }\n\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n fetchRedirectIds.add(key);\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n ...submission,\n data: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n return startRedirectNavigation(state, actionResult, {\n isFetchActionRedirect: true,\n });\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n\n if (isDeferredResult(actionResult)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(\n init.history,\n\n nextLocation,\n abortController.signal\n );\n let matches =\n state.navigation.state !== \"idle\"\n ? matchRoutes(dataRoutes, state.navigation.location, init.basename)\n : state.matches;\n\n invariant(matches, \"Didn't find any matches after fetcher action\");\n\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n\n let loadFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: actionResult.data,\n ...submission,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadFetcher);\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n submission,\n nextLocation,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n { [match.route.id]: actionResult.data },\n undefined, // No need to send through errors since we short circuit above\n fetchLoadMatches\n );\n\n // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n revalidatingFetchers\n .filter((rf) => rf.key !== key)\n .forEach((rf) => {\n let staleKey = rf.key;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: existingFetcher && existingFetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(staleKey, revalidatingFetcher);\n fetchControllers.set(staleKey, abortController);\n });\n\n updateState({ fetchers: new Map(state.fetchers) });\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n revalidationRequest\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));\n\n let redirect = findRedirect(results);\n if (redirect) {\n return startRedirectNavigation(state, redirect);\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n state.matches,\n matchesToLoad,\n loaderResults,\n undefined,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: actionResult.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n\n let didAbortFetchLoads = abortStaleFetchLoads(loadId);\n\n // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n if (\n state.navigation.state === \"loading\" &&\n loadId > pendingNavigationLoadId\n ) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers),\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState({\n errors,\n loaderData: mergeLoaderData(\n state.loaderData,\n loaderData,\n matches,\n errors\n ),\n ...(didAbortFetchLoads ? { fetchers: new Map(state.fetchers) } : {}),\n });\n isRevalidationRequired = false;\n }\n }\n\n // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n async function handleFetcherLoader(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n submission?: Submission\n ) {\n let existingFetcher = state.fetchers.get(key);\n // Put this fetcher into it's loading state\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the loader for this fetcher route match\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal\n );\n fetchControllers.set(key, abortController);\n let result: DataResult = await callLoaderOrAction(\n \"loader\",\n fetchRequest,\n match,\n matches,\n router.basename\n );\n\n // Deferred isn't supported for fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n if (isDeferredResult(result)) {\n result =\n (await resolveDeferredData(result, fetchRequest.signal, true)) ||\n result;\n }\n\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n if (fetchRequest.signal.aborted) {\n return;\n }\n\n // If the loader threw a redirect Response, start a new REPLACE navigation\n if (isRedirectResult(result)) {\n await startRedirectNavigation(state, result);\n return;\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n state.fetchers.delete(key);\n // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -\n // do we need to behave any differently with our non-redirect errors?\n // What if it was a non-redirect Response?\n updateState({\n fetchers: new Map(state.fetchers),\n errors: {\n [boundaryMatch.route.id]: result.error,\n },\n });\n return;\n }\n\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\");\n\n // Put the fetcher back into an idle state\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n }\n\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n async function startRedirectNavigation(\n state: RouterState,\n redirect: RedirectResult,\n {\n submission,\n replace,\n isFetchActionRedirect,\n }: {\n submission?: Submission;\n replace?: boolean;\n isFetchActionRedirect?: boolean;\n } = {}\n ) {\n if (redirect.revalidate) {\n isRevalidationRequired = true;\n }\n\n let redirectLocation = createLocation(\n state.location,\n redirect.location,\n // TODO: This can be removed once we get rid of useTransition in Remix v2\n {\n _isRedirect: true,\n ...(isFetchActionRedirect ? { _isFetchActionRedirect: true } : {}),\n }\n );\n invariant(\n redirectLocation,\n \"Expected a location on the redirect navigation\"\n );\n\n // Check if this an absolute external redirect that goes to a new origin\n if (\n ABSOLUTE_URL_REGEX.test(redirect.location) &&\n isBrowser &&\n typeof window?.location !== \"undefined\"\n ) {\n let newOrigin = init.history.createURL(redirect.location).origin;\n if (window.location.origin !== newOrigin) {\n if (replace) {\n window.location.replace(redirect.location);\n } else {\n window.location.assign(redirect.location);\n }\n return;\n }\n }\n\n // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n pendingNavigationController = null;\n\n let redirectHistoryAction =\n replace === true ? HistoryAction.Replace : HistoryAction.Push;\n\n // Use the incoming submission if provided, fallback on the active one in\n // state.navigation\n let { formMethod, formAction, formEncType, formData } = state.navigation;\n if (!submission && formMethod && formAction && formData && formEncType) {\n submission = {\n formMethod,\n formAction,\n formEncType,\n formData,\n };\n }\n\n // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n if (\n redirectPreserveMethodStatusCodes.has(redirect.status) &&\n submission &&\n isMutationMethod(submission.formMethod)\n ) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: {\n ...submission,\n formAction: redirect.location,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else {\n // Otherwise, we kick off a new loading navigation, preserving the\n // submission info for the duration of this navigation\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: submission ? submission.formMethod : undefined,\n formAction: submission ? submission.formAction : undefined,\n formEncType: submission ? submission.formEncType : undefined,\n formData: submission ? submission.formData : undefined,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n }\n }\n\n async function callLoadersAndMaybeResolveData(\n currentMatches: AgnosticDataRouteMatch[],\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n fetchersToLoad: RevalidatingFetcher[],\n request: Request\n ) {\n // Call all navigation loaders and revalidating fetcher loaders in parallel,\n // then slice off the results into separate arrays so we can handle them\n // accordingly\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\"loader\", request, match, matches, router.basename)\n ),\n ...fetchersToLoad.map((f) =>\n callLoaderOrAction(\n \"loader\",\n createClientSideRequest(init.history, f.path, request.signal),\n f.match,\n f.matches,\n router.basename\n )\n ),\n ]);\n let loaderResults = results.slice(0, matchesToLoad.length);\n let fetcherResults = results.slice(matchesToLoad.length);\n\n await Promise.all([\n resolveDeferredResults(\n currentMatches,\n matchesToLoad,\n loaderResults,\n request.signal,\n false,\n state.loaderData\n ),\n resolveDeferredResults(\n currentMatches,\n fetchersToLoad.map((f) => f.match),\n fetcherResults,\n request.signal,\n true\n ),\n ]);\n\n return { results, loaderResults, fetcherResults };\n }\n\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true;\n\n // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n cancelledDeferredRoutes.push(...cancelActiveDeferreds());\n\n // Abort in-flight fetcher loads\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.push(key);\n abortFetcher(key);\n }\n });\n }\n\n function setFetcherError(key: string, routeId: string, error: any) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState({\n errors: {\n [boundaryMatch.route.id]: error,\n },\n fetchers: new Map(state.fetchers),\n });\n }\n\n function deleteFetcher(key: string): void {\n if (fetchControllers.has(key)) abortFetcher(key);\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n state.fetchers.delete(key);\n }\n\n function abortFetcher(key: string) {\n let controller = fetchControllers.get(key);\n invariant(controller, `Expected fetch controller: ${key}`);\n controller.abort();\n fetchControllers.delete(key);\n }\n\n function markFetchersDone(keys: string[]) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n function markFetchRedirectsDone(): void {\n let doneKeys = [];\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n }\n }\n markFetchersDone(doneKeys);\n }\n\n function abortStaleFetchLoads(landedId: number): boolean {\n let yeetedKeys = [];\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n\n function getBlocker(key: string, fn: BlockerFunction) {\n let blocker: Blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n if (blockerFunctions.get(key) !== fn) {\n blockerFunctions.set(key, fn);\n }\n\n return blocker;\n }\n\n function deleteBlocker(key: string) {\n state.blockers.delete(key);\n blockerFunctions.delete(key);\n }\n\n // Utility function to update blockers, ensuring valid state transitions\n function updateBlocker(key: string, newBlocker: Blocker) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n // Poor mans state machine :)\n // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM\n invariant(\n (blocker.state === \"unblocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"proceeding\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"unblocked\") ||\n (blocker.state === \"proceeding\" && newBlocker.state === \"unblocked\"),\n `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`\n );\n\n state.blockers.set(key, newBlocker);\n updateState({ blockers: new Map(state.blockers) });\n }\n\n function shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n }: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n }): string | undefined {\n if (blockerFunctions.size === 0) {\n return;\n }\n\n // We ony support a single active blocker at the moment since we don't have\n // any compelling use cases for multi-blocker yet\n if (blockerFunctions.size > 1) {\n warning(false, \"A router only supports one blocker at a time\");\n }\n\n let entries = Array.from(blockerFunctions.entries());\n let [blockerKey, blockerFunction] = entries[entries.length - 1];\n let blocker = state.blockers.get(blockerKey);\n\n if (blocker && blocker.state === \"proceeding\") {\n // If the blocker is currently proceeding, we don't need to re-check\n // it and can let this navigation continue\n return;\n }\n\n // At this point, we know we're unblocked/blocked so we need to check the\n // user-provided blocker function\n if (blockerFunction({ currentLocation, nextLocation, historyAction })) {\n return blockerKey;\n }\n }\n\n function cancelActiveDeferreds(\n predicate?: (routeId: string) => boolean\n ): string[] {\n let cancelledRouteIds: string[] = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n }\n\n // Opt in to capturing and reporting scroll positions during navigations,\n // used by the component\n function enableScrollRestoration(\n positions: Record,\n getPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n getScrollRestorationKey = getKey || ((location) => location.key);\n\n // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered \n // and therefore have no savedScrollPositions available\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n if (y != null) {\n updateState({ restoreScrollPosition: y });\n }\n }\n\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n\n function saveScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): void {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n\n function getSavedScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): number | null {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n let y = savedScrollPositions[key];\n if (typeof y === \"number\") {\n return y;\n }\n }\n return null;\n }\n\n router = {\n get basename() {\n return init.basename;\n },\n get state() {\n return state;\n },\n get routes() {\n return dataRoutes;\n },\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: (to: To) => init.history.createHref(to),\n encodeLocation: (to: To) => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher,\n dispose,\n getBlocker,\n deleteBlocker,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds,\n };\n\n return router;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\n\nexport const UNSAFE_DEFERRED_SYMBOL = Symbol(\"deferred\");\n\nexport function createStaticHandler(\n routes: AgnosticRouteObject[],\n opts?: {\n basename?: string;\n }\n): StaticHandler {\n invariant(\n routes.length > 0,\n \"You must provide a non-empty routes array to createStaticHandler\"\n );\n\n let dataRoutes = convertRoutesToDataRoutes(routes);\n let basename = (opts ? opts.basename : null) || \"/\";\n\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n */\n async function query(\n request: Request,\n { requestContext }: { requestContext?: unknown } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method.toLowerCase();\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"head\") {\n let error = getInternalRouterError(405, { method });\n let { matches: methodNotAllowedMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let result = await queryImpl(request, location, matches, requestContext);\n if (isResponse(result)) {\n return result;\n }\n\n // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n return { location, basename, ...result };\n }\n\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n */\n async function queryRoute(\n request: Request,\n {\n routeId,\n requestContext,\n }: { requestContext?: unknown; routeId?: string } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method.toLowerCase();\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"head\" && method !== \"options\") {\n throw getInternalRouterError(405, { method });\n } else if (!matches) {\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let match = routeId\n ? matches.find((m) => m.route.id === routeId)\n : getTargetMatch(matches, location);\n\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId,\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let result = await queryImpl(\n request,\n location,\n matches,\n requestContext,\n match\n );\n if (isResponse(result)) {\n return result;\n }\n\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n }\n\n // Pick off the right state value to return\n if (result.actionData) {\n return Object.values(result.actionData)[0];\n }\n\n if (result.loaderData) {\n let data = Object.values(result.loaderData)[0];\n if (result.activeDeferreds?.[match.route.id]) {\n data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];\n }\n return data;\n }\n\n return undefined;\n }\n\n async function queryImpl(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch\n ): Promise | Response> {\n invariant(\n request.signal,\n \"query()/queryRoute() requests must contain an AbortController signal\"\n );\n\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(\n request,\n matches,\n routeMatch || getTargetMatch(matches, location),\n requestContext,\n routeMatch != null\n );\n return result;\n }\n\n let result = await loadRouteData(\n request,\n matches,\n requestContext,\n routeMatch\n );\n return isResponse(result)\n ? result\n : {\n ...result,\n actionData: null,\n actionHeaders: {},\n };\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction, we throw\n // it to bail out and then return or throw here based on whether the user\n // returned or threw\n if (isQueryRouteResponse(e)) {\n if (e.type === ResultType.error && !isRedirectResponse(e.response)) {\n throw e.response;\n }\n return e.response;\n }\n // Redirects are always returned since they don't propagate to catch\n // boundaries\n if (isRedirectResponse(e)) {\n return e;\n }\n throw e;\n }\n }\n\n async function submit(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n actionMatch: AgnosticDataRouteMatch,\n requestContext: unknown,\n isRouteRequest: boolean\n ): Promise | Response> {\n let result: DataResult;\n\n if (!actionMatch.route.action) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id,\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n basename,\n true,\n isRouteRequest,\n requestContext\n );\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n }\n\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.status,\n headers: {\n Location: result.location,\n },\n });\n }\n\n if (isDeferredResult(result)) {\n let error = getInternalRouterError(400, { type: \"defer-action\" });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n }\n\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: { [actionMatch.route.id]: result.data },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(\n request,\n matches,\n requestContext,\n undefined,\n {\n [boundaryMatch.route.id]: result.error,\n }\n );\n\n // action status codes take precedence over loader status codes\n return {\n ...context,\n statusCode: isRouteErrorResponse(result.error)\n ? result.error.status\n : 500,\n actionData: null,\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n // Create a GET request for the loaders\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal,\n });\n let context = await loadRouteData(loaderRequest, matches, requestContext);\n\n return {\n ...context,\n // action status codes take precedence over loader status codes\n ...(result.statusCode ? { statusCode: result.statusCode } : {}),\n actionData: {\n [actionMatch.route.id]: result.data,\n },\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n async function loadRouteData(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch,\n pendingActionError?: RouteData\n ): Promise<\n | Omit<\n StaticHandlerContext,\n \"location\" | \"basename\" | \"actionData\" | \"actionHeaders\"\n >\n | Response\n > {\n let isRouteRequest = routeMatch != null;\n\n // Short circuit if we have no loaders to run (queryRoute())\n if (isRouteRequest && !routeMatch?.route.loader) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch?.route.id,\n });\n }\n\n let requestMatches = routeMatch\n ? [routeMatch]\n : getLoaderMatchesUntilBoundary(\n matches,\n Object.keys(pendingActionError || {})[0]\n );\n let matchesToLoad = requestMatches.filter((m) => m.route.loader);\n\n // Short circuit if we have no loaders to run (query())\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce(\n (acc, m) => Object.assign(acc, { [m.route.id]: null }),\n {}\n ),\n errors: pendingActionError || null,\n statusCode: 200,\n loaderHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n basename,\n true,\n isRouteRequest,\n requestContext\n )\n ),\n ]);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n\n // Process and commit output from loaders\n let activeDeferreds = new Map();\n let context = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingActionError,\n activeDeferreds\n );\n\n // Add a null for any non-loader matches for proper revalidation on the client\n let executedLoaders = new Set(\n matchesToLoad.map((match) => match.route.id)\n );\n matches.forEach((match) => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n\n return {\n ...context,\n matches,\n activeDeferreds:\n activeDeferreds.size > 0\n ? Object.fromEntries(activeDeferreds.entries())\n : null,\n };\n }\n\n return {\n dataRoutes,\n query,\n queryRoute,\n };\n}\n\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\nexport function getStaticContextFromError(\n routes: AgnosticDataRouteObject[],\n context: StaticHandlerContext,\n error: any\n) {\n let newContext: StaticHandlerContext = {\n ...context,\n statusCode: 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error,\n },\n };\n return newContext;\n}\n\nfunction isSubmissionNavigation(\n opts: RouterNavigateOptions\n): opts is SubmissionNavigateOptions {\n return opts != null && \"formData\" in opts;\n}\n\n// Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\nfunction normalizeNavigateOptions(\n to: To,\n opts?: RouterNavigateOptions,\n isFetcher = false\n): {\n path: string;\n submission?: Submission;\n error?: ErrorResponse;\n} {\n let path = typeof to === \"string\" ? to : createPath(to);\n\n // Return location verbatim on non-submission navigations\n if (!opts || !isSubmissionNavigation(opts)) {\n return { path };\n }\n\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, { method: opts.formMethod }),\n };\n }\n\n // Create a Submission on non-GET navigations\n let submission: Submission | undefined;\n if (opts.formData) {\n submission = {\n formMethod: opts.formMethod || \"get\",\n formAction: stripHashFromPath(path),\n formEncType:\n (opts && opts.formEncType) || \"application/x-www-form-urlencoded\",\n formData: opts.formData,\n };\n\n if (isMutationMethod(submission.formMethod)) {\n return { path, submission };\n }\n }\n\n // Flatten submission onto URLSearchParams for GET submissions\n let parsedPath = parsePath(path);\n let searchParams = convertFormDataToSearchParams(opts.formData);\n // Since fetcher GET submissions only run a single loader (as opposed to\n // navigation GET submissions which run all loaders), we need to preserve\n // any incoming ?index params\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n parsedPath.search = `?${searchParams}`;\n\n return { path: createPath(parsedPath), submission };\n}\n\n// Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\nfunction getLoaderMatchesUntilBoundary(\n matches: AgnosticDataRouteMatch[],\n boundaryId?: string\n) {\n let boundaryMatches = matches;\n if (boundaryId) {\n let index = matches.findIndex((m) => m.route.id === boundaryId);\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n return boundaryMatches;\n}\n\nfunction getMatchesToLoad(\n history: History,\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n submission: Submission | undefined,\n location: Location,\n isRevalidationRequired: boolean,\n cancelledDeferredRoutes: string[],\n cancelledFetcherLoads: string[],\n pendingActionData?: RouteData,\n pendingError?: RouteData,\n fetchLoadMatches?: Map\n): [AgnosticDataRouteMatch[], RevalidatingFetcher[]] {\n let actionResult = pendingError\n ? Object.values(pendingError)[0]\n : pendingActionData\n ? Object.values(pendingActionData)[0]\n : undefined;\n\n let currentUrl = history.createURL(state.location);\n let nextUrl = history.createURL(location);\n\n let defaultShouldRevalidate =\n // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate\n isRevalidationRequired ||\n // Clicked the same link, resubmitted a GET form\n currentUrl.toString() === nextUrl.toString() ||\n // Search params affect all loaders\n currentUrl.search !== nextUrl.search;\n\n // Pick navigation matches that are net-new or qualify for revalidation\n let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;\n let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);\n\n let navigationMatches = boundaryMatches.filter((match, index) => {\n if (match.route.loader == null) {\n return false;\n }\n\n // Always call the loader on new route instances and pending defer cancellations\n if (\n isNewLoader(state.loaderData, state.matches[index], match) ||\n cancelledDeferredRoutes.some((id) => id === match.route.id)\n ) {\n return true;\n }\n\n // This is the default implementation for when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n let currentRouteMatch = state.matches[index];\n let nextRouteMatch = match;\n\n return shouldRevalidateLoader(match, {\n currentUrl,\n currentParams: currentRouteMatch.params,\n nextUrl,\n nextParams: nextRouteMatch.params,\n ...submission,\n actionResult,\n defaultShouldRevalidate:\n defaultShouldRevalidate ||\n isNewRouteInstance(currentRouteMatch, nextRouteMatch),\n });\n });\n\n // Pick fetcher.loads that need to be revalidated\n let revalidatingFetchers: RevalidatingFetcher[] = [];\n fetchLoadMatches &&\n fetchLoadMatches.forEach((f, key) => {\n if (!matches.some((m) => m.route.id === f.routeId)) {\n // This fetcher is not going to be present in the subsequent render so\n // there's no need to revalidate it\n return;\n } else if (cancelledFetcherLoads.includes(key)) {\n // This fetcher was cancelled from a prior action submission - force reload\n revalidatingFetchers.push({ key, ...f });\n } else {\n // Revalidating fetchers are decoupled from the route matches since they\n // hit a static href, so they _always_ check shouldRevalidate and the\n // default is strictly if a revalidation is explicitly required (action\n // submissions, useRevalidator, X-Remix-Revalidate).\n let shouldRevalidate = shouldRevalidateLoader(f.match, {\n currentUrl,\n currentParams: state.matches[state.matches.length - 1].params,\n nextUrl,\n nextParams: matches[matches.length - 1].params,\n ...submission,\n actionResult,\n defaultShouldRevalidate,\n });\n if (shouldRevalidate) {\n revalidatingFetchers.push({ key, ...f });\n }\n }\n });\n\n return [navigationMatches, revalidatingFetchers];\n}\n\nfunction isNewLoader(\n currentLoaderData: RouteData,\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let isNew =\n // [a] -> [a, b]\n !currentMatch ||\n // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id;\n\n // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n let isMissingData = currentLoaderData[match.route.id] === undefined;\n\n // Always load if this is a net-new route or we don't yet have data\n return isNew || isMissingData;\n}\n\nfunction isNewRouteInstance(\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let currentPath = currentMatch.route.path;\n return (\n // param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname ||\n // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n (currentPath != null &&\n currentPath.endsWith(\"*\") &&\n currentMatch.params[\"*\"] !== match.params[\"*\"])\n );\n}\n\nfunction shouldRevalidateLoader(\n loaderMatch: AgnosticDataRouteMatch,\n arg: Parameters[0]\n) {\n if (loaderMatch.route.shouldRevalidate) {\n let routeChoice = loaderMatch.route.shouldRevalidate(arg);\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n\n return arg.defaultShouldRevalidate;\n}\n\nasync function callLoaderOrAction(\n type: \"loader\" | \"action\",\n request: Request,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n basename = \"/\",\n isStaticRequest: boolean = false,\n isRouteRequest: boolean = false,\n requestContext?: unknown\n): Promise {\n let resultType;\n let result;\n\n // Setup a promise we can race against so that abort signals short circuit\n let reject: () => void;\n let abortPromise = new Promise((_, r) => (reject = r));\n let onReject = () => reject();\n request.signal.addEventListener(\"abort\", onReject);\n\n try {\n let handler = match.route[type];\n invariant(\n handler,\n `Could not find the ${type} to run on the \"${match.route.id}\" route`\n );\n\n result = await Promise.race([\n handler({ request, params: match.params, context: requestContext }),\n abortPromise,\n ]);\n\n invariant(\n result !== undefined,\n `You defined ${type === \"action\" ? \"an action\" : \"a loader\"} for route ` +\n `\"${match.route.id}\" but didn't return anything from your \\`${type}\\` ` +\n `function. Please return a value or \\`null\\`.`\n );\n } catch (e) {\n resultType = ResultType.error;\n result = e;\n } finally {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n\n if (isResponse(result)) {\n let status = result.status;\n\n // Process redirects\n if (redirectStatusCodes.has(status)) {\n let location = result.headers.get(\"Location\");\n invariant(\n location,\n \"Redirects returned/thrown from loaders/actions must have a Location header\"\n );\n\n // Support relative routing in internal redirects\n if (!ABSOLUTE_URL_REGEX.test(location)) {\n let activeMatches = matches.slice(0, matches.indexOf(match) + 1);\n let routePathnames = getPathContributingMatches(activeMatches).map(\n (match) => match.pathnameBase\n );\n let resolvedLocation = resolveTo(\n location,\n routePathnames,\n new URL(request.url).pathname\n );\n invariant(\n createPath(resolvedLocation),\n `Unable to resolve redirect location: ${location}`\n );\n\n // Prepend the basename to the redirect location if we have one\n if (basename) {\n let path = resolvedLocation.pathname;\n resolvedLocation.pathname =\n path === \"/\" ? basename : joinPaths([basename, path]);\n }\n\n location = createPath(resolvedLocation);\n } else if (!isStaticRequest) {\n // Strip off the protocol+origin for same-origin absolute redirects.\n // If this is a static reques, we can let it go back to the browser\n // as-is\n let currentUrl = new URL(request.url);\n let url = location.startsWith(\"//\")\n ? new URL(currentUrl.protocol + location)\n : new URL(location);\n if (url.origin === currentUrl.origin) {\n location = url.pathname + url.search + url.hash;\n }\n }\n\n // Don't process redirects in the router during static requests requests.\n // Instead, throw the Response and let the server handle it with an HTTP\n // redirect. We also update the Location header in place in this flow so\n // basename and relative routing is taken into account\n if (isStaticRequest) {\n result.headers.set(\"Location\", location);\n throw result;\n }\n\n return {\n type: ResultType.redirect,\n status,\n location,\n revalidate: result.headers.get(\"X-Remix-Revalidate\") !== null,\n };\n }\n\n // For SSR single-route requests, we want to hand Responses back directly\n // without unwrapping. We do this with the QueryRouteResponse wrapper\n // interface so we can know whether it was returned or thrown\n if (isRouteRequest) {\n // eslint-disable-next-line no-throw-literal\n throw {\n type: resultType || ResultType.data,\n response: result,\n };\n }\n\n let data: any;\n let contentType = result.headers.get(\"Content-Type\");\n // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n data = await result.json();\n } else {\n data = await result.text();\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: new ErrorResponse(status, result.statusText, data),\n headers: result.headers,\n };\n }\n\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers,\n };\n }\n\n if (resultType === ResultType.error) {\n return { type: resultType, error: result };\n }\n\n if (result instanceof DeferredData) {\n return { type: ResultType.deferred, deferredData: result };\n }\n\n return { type: ResultType.data, data: result };\n}\n\n// Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\nfunction createClientSideRequest(\n history: History,\n location: string | Location,\n signal: AbortSignal,\n submission?: Submission\n): Request {\n let url = history.createURL(stripHashFromPath(location)).toString();\n let init: RequestInit = { signal };\n\n if (submission && isMutationMethod(submission.formMethod)) {\n let { formMethod, formEncType, formData } = submission;\n init.method = formMethod.toUpperCase();\n init.body =\n formEncType === \"application/x-www-form-urlencoded\"\n ? convertFormDataToSearchParams(formData)\n : formData;\n }\n\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n return new Request(url, init);\n}\n\nfunction convertFormDataToSearchParams(formData: FormData): URLSearchParams {\n let searchParams = new URLSearchParams();\n\n for (let [key, value] of formData.entries()) {\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n searchParams.append(key, value instanceof File ? value.name : value);\n }\n\n return searchParams;\n}\n\nfunction processRouteLoaderData(\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors: RouterState[\"errors\"] | null;\n statusCode: number;\n loaderHeaders: Record;\n} {\n // Fill in loaderData/errors from our loaders\n let loaderData: RouterState[\"loaderData\"] = {};\n let errors: RouterState[\"errors\"] | null = null;\n let statusCode: number | undefined;\n let foundError = false;\n let loaderHeaders: Record = {};\n\n // Process loader results into state.loaderData/state.errors\n results.forEach((result, index) => {\n let id = matchesToLoad[index].route.id;\n invariant(\n !isRedirectResult(result),\n \"Cannot handle redirect results in processLoaderData\"\n );\n if (isErrorResult(result)) {\n // Look upwards from the matched route for the closest ancestor\n // error boundary, defaulting to the root match\n let boundaryMatch = findNearestBoundary(matches, id);\n let error = result.error;\n // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n if (pendingError) {\n error = Object.values(pendingError)[0];\n pendingError = undefined;\n }\n\n errors = errors || {};\n\n // Prefer higher error values if lower errors bubble to the same boundary\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n }\n\n // Clear our any prior loaderData for the throwing route\n loaderData[id] = undefined;\n\n // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error)\n ? result.error.status\n : 500;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n if (isDeferredResult(result)) {\n activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data;\n } else {\n loaderData[id] = result.data;\n }\n\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (\n result.statusCode != null &&\n result.statusCode !== 200 &&\n !foundError\n ) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n });\n\n // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n if (pendingError) {\n errors = pendingError;\n loaderData[Object.keys(pendingError)[0]] = undefined;\n }\n\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders,\n };\n}\n\nfunction processLoaderData(\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n revalidatingFetchers: RevalidatingFetcher[],\n fetcherResults: DataResult[],\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors?: RouterState[\"errors\"];\n} {\n let { loaderData, errors } = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingError,\n activeDeferreds\n );\n\n // Process results from our revalidating fetchers\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let { key, match } = revalidatingFetchers[index];\n invariant(\n fetcherResults !== undefined && fetcherResults[index] !== undefined,\n \"Did not find corresponding fetcher result\"\n );\n let result = fetcherResults[index];\n\n // Process fetcher non-redirect errors\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match.route.id);\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = {\n ...errors,\n [boundaryMatch.route.id]: result.error,\n };\n }\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n invariant(false, \"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n invariant(false, \"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n return { loaderData, errors };\n}\n\nfunction mergeLoaderData(\n loaderData: RouteData,\n newLoaderData: RouteData,\n matches: AgnosticDataRouteMatch[],\n errors: RouteData | null | undefined\n): RouteData {\n let mergedLoaderData = { ...newLoaderData };\n for (let match of matches) {\n let id = match.route.id;\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n } else {\n // No-op - this is so we ignore existing data if we have a key in the\n // incoming object with an undefined value, which is how we unset a prior\n // loaderData if we encounter a loader error\n }\n } else if (loaderData[id] !== undefined) {\n mergedLoaderData[id] = loaderData[id];\n }\n\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n return mergedLoaderData;\n}\n\n// Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\nfunction findNearestBoundary(\n matches: AgnosticDataRouteMatch[],\n routeId?: string\n): AgnosticDataRouteMatch {\n let eligibleMatches = routeId\n ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1)\n : [...matches];\n return (\n eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) ||\n matches[0]\n );\n}\n\nfunction getShortCircuitMatches(routes: AgnosticDataRouteObject[]): {\n matches: AgnosticDataRouteMatch[];\n route: AgnosticDataRouteObject;\n} {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route = routes.find((r) => r.index || !r.path || r.path === \"/\") || {\n id: `__shim-error-route__`,\n };\n\n return {\n matches: [\n {\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route,\n },\n ],\n route,\n };\n}\n\nfunction getInternalRouterError(\n status: number,\n {\n pathname,\n routeId,\n method,\n type,\n }: {\n pathname?: string;\n routeId?: string;\n method?: string;\n type?: \"defer-action\";\n } = {}\n) {\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n\n if (status === 400) {\n statusText = \"Bad Request\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method} request to \"${pathname}\" but ` +\n `did not provide a \\`loader\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (type === \"defer-action\") {\n errorMessage = \"defer() is not supported in actions\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = `Route \"${routeId}\" does not match URL \"${pathname}\"`;\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = `No route matches URL \"${pathname}\"`;\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method.toUpperCase()} request to \"${pathname}\" but ` +\n `did not provide an \\`action\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (method) {\n errorMessage = `Invalid request method \"${method.toUpperCase()}\"`;\n }\n }\n\n return new ErrorResponse(\n status || 500,\n statusText,\n new Error(errorMessage),\n true\n );\n}\n\n// Find any returned redirect errors, starting from the lowest match\nfunction findRedirect(results: DataResult[]): RedirectResult | undefined {\n for (let i = results.length - 1; i >= 0; i--) {\n let result = results[i];\n if (isRedirectResult(result)) {\n return result;\n }\n }\n}\n\nfunction stripHashFromPath(path: To) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath({ ...parsedPath, hash: \"\" });\n}\n\nfunction isHashChangeOnly(a: Location, b: Location): boolean {\n return (\n a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash\n );\n}\n\nfunction isDeferredResult(result: DataResult): result is DeferredResult {\n return result.type === ResultType.deferred;\n}\n\nfunction isErrorResult(result: DataResult): result is ErrorResult {\n return result.type === ResultType.error;\n}\n\nfunction isRedirectResult(result?: DataResult): result is RedirectResult {\n return (result && result.type) === ResultType.redirect;\n}\n\nfunction isResponse(value: any): value is Response {\n return (\n value != null &&\n typeof value.status === \"number\" &&\n typeof value.statusText === \"string\" &&\n typeof value.headers === \"object\" &&\n typeof value.body !== \"undefined\"\n );\n}\n\nfunction isRedirectResponse(result: any): result is Response {\n if (!isResponse(result)) {\n return false;\n }\n\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\n\nfunction isQueryRouteResponse(obj: any): obj is QueryRouteResponse {\n return (\n obj &&\n isResponse(obj.response) &&\n (obj.type === ResultType.data || ResultType.error)\n );\n}\n\nfunction isValidMethod(method: string): method is FormMethod {\n return validRequestMethods.has(method as FormMethod);\n}\n\nfunction isMutationMethod(method?: string): method is MutationFormMethod {\n return validMutationMethods.has(method as MutationFormMethod);\n}\n\nasync function resolveDeferredResults(\n currentMatches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n signal: AbortSignal,\n isFetcher: boolean,\n currentLoaderData?: RouteData\n) {\n for (let index = 0; index < results.length; index++) {\n let result = results[index];\n let match = matchesToLoad[index];\n let currentMatch = currentMatches.find(\n (m) => m.route.id === match.route.id\n );\n let isRevalidatingLoader =\n currentMatch != null &&\n !isNewRouteInstance(currentMatch, match) &&\n (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n\n if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n await resolveDeferredData(result, signal, isFetcher).then((result) => {\n if (result) {\n results[index] = result || results[index];\n }\n });\n }\n }\n}\n\nasync function resolveDeferredData(\n result: DeferredResult,\n signal: AbortSignal,\n unwrap = false\n): Promise {\n let aborted = await result.deferredData.resolveData(signal);\n if (aborted) {\n return;\n }\n\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData,\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e,\n };\n }\n }\n\n return {\n type: ResultType.data,\n data: result.deferredData.data,\n };\n}\n\nfunction hasNakedIndexQuery(search: string): boolean {\n return new URLSearchParams(search).getAll(\"index\").some((v) => v === \"\");\n}\n\n// Note: This should match the format exported by useMatches, so if you change\n// this please also change that :) Eventually we'll DRY this up\nfunction createUseMatchesMatch(\n match: AgnosticDataRouteMatch,\n loaderData: RouteData\n): UseMatchesMatch {\n let { route, pathname, params } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id] as unknown,\n handle: route.handle as unknown,\n };\n}\n\nfunction getTargetMatch(\n matches: AgnosticDataRouteMatch[],\n location: Location | string\n) {\n let search =\n typeof location === \"string\" ? parsePath(location).search : location.search;\n if (\n matches[matches.length - 1].route.index &&\n hasNakedIndexQuery(search || \"\")\n ) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n }\n // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n}\n//#endregion\n"],"names":["Action","exports","PopStateEventType","invariant","value","message","Error","warning","cond","console","warn","e","getHistoryState","location","index","usr","state","key","idx","createLocation","current","to","_extends","pathname","search","hash","parsePath","Math","random","toString","substr","createPath","_ref","charAt","path","parsedPath","hashIndex","indexOf","searchIndex","getUrlBasedHistory","getLocation","createHref","validateLocation","options","window","document","defaultView","v5Compat","globalHistory","history","action","Pop","listener","getIndex","handlePop","nextIndex","delta","createURL","base","origin","href","URL","replaceState","listen","fn","addEventListener","removeEventListener","encodeLocation","url","push","Push","historyState","pushState","error","assign","replace","Replace","go","n","ResultType","convertRoutesToDataRoutes","routes","parentPath","allIds","Set","map","route","treePath","id","join","children","has","add","isIndexRoute","undefined","matchRoutes","locationArg","basename","stripBasename","branches","flattenRoutes","sort","a","b","score","length","slice","every","i","compareIndexes","routesMeta","meta","childrenIndex","rankRouteBranches","matches","matchRouteBranch","safelyDecodeURI","parentsMeta","flattenRoute","relativePath","caseSensitive","startsWith","joinPaths","concat","computeScore","forEach","_route$path","includes","exploded","explodeOptionalSegments","segments","split","first","rest","isOptional","endsWith","required","restExploded","result","subpath","paramRe","isSplat","s","initialScore","some","filter","reduce","segment","test","branch","matchedParams","matchedPathname","end","remainingPathname","match","matchPath","Object","params","pathnameBase","normalizePathname","pattern","matcher","paramNames","regexpSource","_","paramName","RegExp","compilePath","captureGroups","memo","splatValue","decodeURIComponent","safelyDecodeURIComponent","decodeURI","toLowerCase","startIndex","nextChar","resolvePath","fromPathname","toPathname","pop","resolvePathname","normalizeSearch","normalizeHash","getInvalidPathError","char","field","dest","JSON","stringify","getPathContributingMatches","resolveTo","toArg","routePathnames","locationPathname","isPathRelative","from","isEmptyPath","routePathnameIndex","toSegments","shift","hasExplicitTrailingSlash","hasCurrentTrailingSlash","paths","AbortedDeferredError","DeferredData","constructor","data","responseInit","reject","this","pendingKeysSet","subscribers","deferredKeys","Array","isArray","abortPromise","Promise","r","controller","AbortController","onAbort","unlistenAbortSignal","signal","entries","acc","trackPromise","done","init","promise","race","then","onSettle","catch","defineProperty","get","aborted","delete","emit","settledKey","subscriber","subscribe","cancel","abort","v","k","async","resolve","size","unwrappedData","_ref2","unwrapTrackedPromise","pendingKeys","_tracked","isTrackedPromise","_error","_data","ErrorResponse","status","statusText","internal","isRouteErrorResponse","validMutationMethodsArr","validMutationMethods","validRequestMethodsArr","validRequestMethods","redirectStatusCodes","redirectPreserveMethodStatusCodes","IDLE_NAVIGATION","formMethod","formAction","formEncType","formData","IDLE_FETCHER","IDLE_BLOCKER","proceed","reset","ABSOLUTE_URL_REGEX","isBrowser","createElement","isServer","UNSAFE_DEFERRED_SYMBOL","Symbol","normalizeNavigateOptions","opts","isFetcher","submission","isSubmissionNavigation","isValidMethod","getInternalRouterError","method","stripHashFromPath","isMutationMethod","searchParams","convertFormDataToSearchParams","hasNakedIndexQuery","append","getLoaderMatchesUntilBoundary","boundaryId","boundaryMatches","findIndex","m","getMatchesToLoad","isRevalidationRequired","cancelledDeferredRoutes","cancelledFetcherLoads","pendingActionData","pendingError","fetchLoadMatches","actionResult","values","currentUrl","nextUrl","defaultShouldRevalidate","keys","navigationMatches","loader","currentLoaderData","currentMatch","isNew","isMissingData","isNewLoader","loaderData","currentRouteMatch","nextRouteMatch","shouldRevalidateLoader","currentParams","nextParams","isNewRouteInstance","revalidatingFetchers","f","routeId","currentPath","loaderMatch","arg","shouldRevalidate","routeChoice","callLoaderOrAction","type","request","isStaticRequest","isRouteRequest","requestContext","resultType","onReject","handler","context","isResponse","headers","protocol","resolvedLocation","set","redirect","revalidate","response","contentType","json","text","statusCode","deferred","deferredData","createClientSideRequest","toUpperCase","body","Request","URLSearchParams","File","name","processRouteLoaderData","matchesToLoad","results","activeDeferreds","errors","foundError","loaderHeaders","isRedirectResult","isErrorResult","boundaryMatch","findNearestBoundary","isDeferredResult","processLoaderData","fetcherResults","fetchers","doneFetcher","mergeLoaderData","newLoaderData","mergedLoaderData","hasOwnProperty","reverse","find","hasErrorBoundary","getShortCircuitMatches","_temp4","errorMessage","findRedirect","isRedirectResponse","resolveDeferredResults","currentMatches","isRevalidatingLoader","resolveDeferredData","unwrap","resolveData","getAll","createUseMatchesMatch","handle","getTargetMatch","pathMatches","querySelector","getAttribute","initialEntries","initialIndex","entry","createMemoryLocation","clampIndex","min","max","getCurrentLocation","nextLocation","splice","dataRoutes","unlistenHistory","savedScrollPositions","getScrollRestorationKey","getScrollPosition","initialScrollRestored","hydrationData","initialMatches","initialErrors","router","pendingNavigationController","initialized","historyAction","navigation","restoreScrollPosition","preventScrollReset","revalidation","actionData","Map","blockers","pendingAction","HistoryAction","pendingPreventScrollReset","isUninterruptedRevalidation","fetchControllers","incrementingLoadId","pendingNavigationLoadId","fetchReloadIds","fetchRedirectIds","blockerFunctions","ignoreNextHistoryUpdate","updateState","newState","completeNavigation","_location$state","_location$state2","isActionReload","_isRedirect","deleteBlocker","getSavedScrollPosition","startNavigation","startUninterruptedRevalidation","userMatches","saveScrollPosition","loadingNavigation","overrideNavigation","notFoundMatches","cancelActiveDeferreds","actionOutput","interruptActiveLoads","actionMatch","shortCircuited","startRedirectNavigation","pendingActionError","handleAction","activeSubmission","rf","fetcher","revalidatingFetcher","loaderResults","callLoadersAndMaybeResolveData","doneKeys","markFetchersDone","markFetchRedirectsDone","didAbortFetchLoads","abortStaleFetchLoads","handleLoaders","getFetcher","_temp","_window","isFetchActionRedirect","redirectLocation","_isFetchActionRedirect","newOrigin","redirectHistoryAction","fetchersToLoad","all","abortFetcher","setFetcherError","deleteFetcher","landedId","yeetedKeys","updateBlocker","newBlocker","blocker","shouldBlockNavigation","currentLocation","blockerKey","blockerFunction","predicate","cancelledRouteIds","dfd","y","initialize","enableScrollRestoration","positions","getPosition","getKey","navigate","userReplace","fetch","requestMatches","existingFetcher","abortController","fetchRequest","loadingFetcher","revalidationRequest","loadId","loadFetcher","staleKey","handleFetcherAction","handleFetcherLoader","dispose","clear","getBlocker","_internalFetchControllers","_internalActiveDeferreds","queryImpl","routeMatch","Response","Location","actionHeaders","loadRouteData","loaderRequest","submit","obj","executedLoaders","fromEntries","query","_temp2","methodNotAllowedMatches","queryRoute","_temp3","_result$activeDeferre","originalPath","optional","param","prefix","__","str","_deepestRenderedBoundaryId","Headers"],"mappings":"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"}