@tanstack/router-core
Version:
Modern and scalable routing for React applications
649 lines (648 loc) • 25.1 kB
JavaScript
import { batch } from "./utils/batch.js";
import { createControlledPromise, isPromise } from "./utils.js";
import { isNotFound } from "./not-found.js";
import { rootRouteId } from "./root.js";
import { isRedirect } from "./redirect.js";
import { isServer } from "@tanstack/router-core/isServer";
import invariant from "tiny-invariant";
//#region src/load-matches.ts
var triggerOnReady = (inner) => {
if (!inner.rendered) {
inner.rendered = true;
return inner.onReady?.();
}
};
var resolvePreload = (inner, matchId) => {
return !!(inner.preload && !inner.router.state.matches.some((d) => d.id === matchId));
};
/**
* Builds the accumulated context from router options and all matches up to (and optionally including) the given index.
* Merges __routeContext and __beforeLoadContext from each match.
*/
var buildMatchContext = (inner, index, includeCurrentMatch = true) => {
const context = { ...inner.router.options.context ?? {} };
const end = includeCurrentMatch ? index : index - 1;
for (let i = 0; i <= end; i++) {
const innerMatch = inner.matches[i];
if (!innerMatch) continue;
const m = inner.router.getMatch(innerMatch.id);
if (!m) continue;
Object.assign(context, m.__routeContext, m.__beforeLoadContext);
}
return context;
};
var getNotFoundBoundaryIndex = (inner, err) => {
if (!inner.matches.length) return;
const requestedRouteId = err.routeId;
const matchedRootIndex = inner.matches.findIndex((m) => m.routeId === inner.router.routeTree.id);
const rootIndex = matchedRootIndex >= 0 ? matchedRootIndex : 0;
let startIndex = requestedRouteId ? inner.matches.findIndex((match) => match.routeId === requestedRouteId) : inner.firstBadMatchIndex ?? inner.matches.length - 1;
if (startIndex < 0) startIndex = rootIndex;
for (let i = startIndex; i >= 0; i--) {
const match = inner.matches[i];
if (inner.router.looseRoutesById[match.routeId].options.notFoundComponent) return i;
}
return requestedRouteId ? startIndex : rootIndex;
};
var handleRedirectAndNotFound = (inner, match, err) => {
if (!isRedirect(err) && !isNotFound(err)) return;
if (isRedirect(err) && err.redirectHandled && !err.options.reloadDocument) throw err;
if (match) {
match._nonReactive.beforeLoadPromise?.resolve();
match._nonReactive.loaderPromise?.resolve();
match._nonReactive.beforeLoadPromise = void 0;
match._nonReactive.loaderPromise = void 0;
match._nonReactive.error = err;
inner.updateMatch(match.id, (prev) => ({
...prev,
status: isRedirect(err) ? "redirected" : prev.status === "pending" ? "success" : prev.status,
context: buildMatchContext(inner, match.index),
isFetching: false,
error: err
}));
if (isNotFound(err) && !err.routeId) err.routeId = match.routeId;
match._nonReactive.loadPromise?.resolve();
}
if (isRedirect(err)) {
inner.rendered = true;
err.options._fromLocation = inner.location;
err.redirectHandled = true;
err = inner.router.resolveRedirect(err);
}
throw err;
};
var shouldSkipLoader = (inner, matchId) => {
const match = inner.router.getMatch(matchId);
if (!match) return true;
if (!(isServer ?? inner.router.isServer) && match._nonReactive.dehydrated) return true;
if ((isServer ?? inner.router.isServer) && match.ssr === false) return true;
return false;
};
var syncMatchContext = (inner, matchId, index) => {
const nextContext = buildMatchContext(inner, index);
inner.updateMatch(matchId, (prev) => {
return {
...prev,
context: nextContext
};
});
};
var handleSerialError = (inner, index, err, routerCode) => {
const { id: matchId, routeId } = inner.matches[index];
const route = inner.router.looseRoutesById[routeId];
if (err instanceof Promise) throw err;
err.routerCode = routerCode;
inner.firstBadMatchIndex ??= index;
handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), err);
try {
route.options.onError?.(err);
} catch (errorHandlerErr) {
err = errorHandlerErr;
handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), err);
}
inner.updateMatch(matchId, (prev) => {
prev._nonReactive.beforeLoadPromise?.resolve();
prev._nonReactive.beforeLoadPromise = void 0;
prev._nonReactive.loadPromise?.resolve();
return {
...prev,
error: err,
status: "error",
isFetching: false,
updatedAt: Date.now(),
abortController: new AbortController()
};
});
if (!inner.preload && !isRedirect(err) && !isNotFound(err)) inner.serialError ??= err;
};
var isBeforeLoadSsr = (inner, matchId, index, route) => {
const existingMatch = inner.router.getMatch(matchId);
const parentMatchId = inner.matches[index - 1]?.id;
const parentMatch = parentMatchId ? inner.router.getMatch(parentMatchId) : void 0;
if (inner.router.isShell()) {
existingMatch.ssr = route.id === rootRouteId;
return;
}
if (parentMatch?.ssr === false) {
existingMatch.ssr = false;
return;
}
const parentOverride = (tempSsr) => {
if (tempSsr === true && parentMatch?.ssr === "data-only") return "data-only";
return tempSsr;
};
const defaultSsr = inner.router.options.defaultSsr ?? true;
if (route.options.ssr === void 0) {
existingMatch.ssr = parentOverride(defaultSsr);
return;
}
if (typeof route.options.ssr !== "function") {
existingMatch.ssr = parentOverride(route.options.ssr);
return;
}
const { search, params } = existingMatch;
const ssrFnContext = {
search: makeMaybe(search, existingMatch.searchError),
params: makeMaybe(params, existingMatch.paramsError),
location: inner.location,
matches: inner.matches.map((match) => ({
index: match.index,
pathname: match.pathname,
fullPath: match.fullPath,
staticData: match.staticData,
id: match.id,
routeId: match.routeId,
search: makeMaybe(match.search, match.searchError),
params: makeMaybe(match.params, match.paramsError),
ssr: match.ssr
}))
};
const tempSsr = route.options.ssr(ssrFnContext);
if (isPromise(tempSsr)) return tempSsr.then((ssr) => {
existingMatch.ssr = parentOverride(ssr ?? defaultSsr);
});
existingMatch.ssr = parentOverride(tempSsr ?? defaultSsr);
};
var setupPendingTimeout = (inner, matchId, route, match) => {
if (match._nonReactive.pendingTimeout !== void 0) return;
const pendingMs = route.options.pendingMs ?? inner.router.options.defaultPendingMs;
if (!!(inner.onReady && !(isServer ?? inner.router.isServer) && !resolvePreload(inner, matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? inner.router.options?.defaultPendingComponent))) {
const pendingTimeout = setTimeout(() => {
triggerOnReady(inner);
}, pendingMs);
match._nonReactive.pendingTimeout = pendingTimeout;
}
};
var preBeforeLoadSetup = (inner, matchId, route) => {
const existingMatch = inner.router.getMatch(matchId);
if (!existingMatch._nonReactive.beforeLoadPromise && !existingMatch._nonReactive.loaderPromise) return;
setupPendingTimeout(inner, matchId, route, existingMatch);
const then = () => {
const match = inner.router.getMatch(matchId);
if (match.preload && (match.status === "redirected" || match.status === "notFound")) handleRedirectAndNotFound(inner, match, match.error);
};
return existingMatch._nonReactive.beforeLoadPromise ? existingMatch._nonReactive.beforeLoadPromise.then(then) : then();
};
var executeBeforeLoad = (inner, matchId, index, route) => {
const match = inner.router.getMatch(matchId);
let prevLoadPromise = match._nonReactive.loadPromise;
match._nonReactive.loadPromise = createControlledPromise(() => {
prevLoadPromise?.resolve();
prevLoadPromise = void 0;
});
const { paramsError, searchError } = match;
if (paramsError) handleSerialError(inner, index, paramsError, "PARSE_PARAMS");
if (searchError) handleSerialError(inner, index, searchError, "VALIDATE_SEARCH");
setupPendingTimeout(inner, matchId, route, match);
const abortController = new AbortController();
let isPending = false;
const pending = () => {
if (isPending) return;
isPending = true;
inner.updateMatch(matchId, (prev) => ({
...prev,
isFetching: "beforeLoad",
fetchCount: prev.fetchCount + 1,
abortController
}));
};
const resolve = () => {
match._nonReactive.beforeLoadPromise?.resolve();
match._nonReactive.beforeLoadPromise = void 0;
inner.updateMatch(matchId, (prev) => ({
...prev,
isFetching: false
}));
};
if (!route.options.beforeLoad) {
batch(() => {
pending();
resolve();
});
return;
}
match._nonReactive.beforeLoadPromise = createControlledPromise();
const context = {
...buildMatchContext(inner, index, false),
...match.__routeContext
};
const { search, params, cause } = match;
const preload = resolvePreload(inner, matchId);
const beforeLoadFnContext = {
search,
abortController,
params,
preload,
context,
location: inner.location,
navigate: (opts) => inner.router.navigate({
...opts,
_fromLocation: inner.location
}),
buildLocation: inner.router.buildLocation,
cause: preload ? "preload" : cause,
matches: inner.matches,
routeId: route.id,
...inner.router.options.additionalContext
};
const updateContext = (beforeLoadContext) => {
if (beforeLoadContext === void 0) {
batch(() => {
pending();
resolve();
});
return;
}
if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
pending();
handleSerialError(inner, index, beforeLoadContext, "BEFORE_LOAD");
}
batch(() => {
pending();
inner.updateMatch(matchId, (prev) => ({
...prev,
__beforeLoadContext: beforeLoadContext
}));
resolve();
});
};
let beforeLoadContext;
try {
beforeLoadContext = route.options.beforeLoad(beforeLoadFnContext);
if (isPromise(beforeLoadContext)) {
pending();
return beforeLoadContext.catch((err) => {
handleSerialError(inner, index, err, "BEFORE_LOAD");
}).then(updateContext);
}
} catch (err) {
pending();
handleSerialError(inner, index, err, "BEFORE_LOAD");
}
updateContext(beforeLoadContext);
};
var handleBeforeLoad = (inner, index) => {
const { id: matchId, routeId } = inner.matches[index];
const route = inner.router.looseRoutesById[routeId];
const serverSsr = () => {
if (isServer ?? inner.router.isServer) {
const maybePromise = isBeforeLoadSsr(inner, matchId, index, route);
if (isPromise(maybePromise)) return maybePromise.then(queueExecution);
}
return queueExecution();
};
const execute = () => executeBeforeLoad(inner, matchId, index, route);
const queueExecution = () => {
if (shouldSkipLoader(inner, matchId)) return;
const result = preBeforeLoadSetup(inner, matchId, route);
return isPromise(result) ? result.then(execute) : execute();
};
return serverSsr();
};
var executeHead = (inner, matchId, route) => {
const match = inner.router.getMatch(matchId);
if (!match) return;
if (!route.options.head && !route.options.scripts && !route.options.headers) return;
const assetContext = {
ssr: inner.router.options.ssr,
matches: inner.matches,
match,
params: match.params,
loaderData: match.loaderData
};
return Promise.all([
route.options.head?.(assetContext),
route.options.scripts?.(assetContext),
route.options.headers?.(assetContext)
]).then(([headFnContent, scripts, headers]) => {
return {
meta: headFnContent?.meta,
links: headFnContent?.links,
headScripts: headFnContent?.scripts,
headers,
scripts,
styles: headFnContent?.styles
};
});
};
var getLoaderContext = (inner, matchPromises, matchId, index, route) => {
const parentMatchPromise = matchPromises[index - 1];
const { params, loaderDeps, abortController, cause } = inner.router.getMatch(matchId);
const context = buildMatchContext(inner, index);
const preload = resolvePreload(inner, matchId);
return {
params,
deps: loaderDeps,
preload: !!preload,
parentMatchPromise,
abortController,
context,
location: inner.location,
navigate: (opts) => inner.router.navigate({
...opts,
_fromLocation: inner.location
}),
cause: preload ? "preload" : cause,
route,
...inner.router.options.additionalContext
};
};
var runLoader = async (inner, matchPromises, matchId, index, route) => {
try {
const match = inner.router.getMatch(matchId);
try {
if (!(isServer ?? inner.router.isServer) || match.ssr === true) loadRouteChunk(route);
const routeLoader = route.options.loader;
const loader = typeof routeLoader === "function" ? routeLoader : routeLoader?.handler;
const loaderResult = loader?.(getLoaderContext(inner, matchPromises, matchId, index, route));
const loaderResultIsPromise = !!loader && isPromise(loaderResult);
if (!!(loaderResultIsPromise || route._lazyPromise || route._componentsPromise || route.options.head || route.options.scripts || route.options.headers || match._nonReactive.minPendingPromise)) inner.updateMatch(matchId, (prev) => ({
...prev,
isFetching: "loader"
}));
if (loader) {
const loaderData = loaderResultIsPromise ? await loaderResult : loaderResult;
handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), loaderData);
if (loaderData !== void 0) inner.updateMatch(matchId, (prev) => ({
...prev,
loaderData
}));
}
if (route._lazyPromise) await route._lazyPromise;
const pendingPromise = match._nonReactive.minPendingPromise;
if (pendingPromise) await pendingPromise;
if (route._componentsPromise) await route._componentsPromise;
inner.updateMatch(matchId, (prev) => ({
...prev,
error: void 0,
context: buildMatchContext(inner, index),
status: "success",
isFetching: false,
updatedAt: Date.now()
}));
} catch (e) {
let error = e;
if (error?.name === "AbortError") {
if (match.abortController.signal.aborted) {
match._nonReactive.loaderPromise?.resolve();
match._nonReactive.loaderPromise = void 0;
return;
}
inner.updateMatch(matchId, (prev) => ({
...prev,
status: prev.status === "pending" ? "success" : prev.status,
isFetching: false,
context: buildMatchContext(inner, index)
}));
return;
}
const pendingPromise = match._nonReactive.minPendingPromise;
if (pendingPromise) await pendingPromise;
if (isNotFound(e)) await route.options.notFoundComponent?.preload?.();
handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), e);
try {
route.options.onError?.(e);
} catch (onErrorError) {
error = onErrorError;
handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), onErrorError);
}
if (!isRedirect(error) && !isNotFound(error)) await loadRouteChunk(route, ["errorComponent"]);
inner.updateMatch(matchId, (prev) => ({
...prev,
error,
context: buildMatchContext(inner, index),
status: "error",
isFetching: false
}));
}
} catch (err) {
const match = inner.router.getMatch(matchId);
if (match) match._nonReactive.loaderPromise = void 0;
handleRedirectAndNotFound(inner, match, err);
}
};
var loadRouteMatch = async (inner, matchPromises, index) => {
async function handleLoader(preload, prevMatch, previousRouteMatchId, match, route) {
const age = Date.now() - prevMatch.updatedAt;
const staleAge = preload ? route.options.preloadStaleTime ?? inner.router.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? inner.router.options.defaultStaleTime ?? 0;
const shouldReloadOption = route.options.shouldReload;
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext(inner, matchPromises, matchId, index, route)) : shouldReloadOption;
const { status, invalid } = match;
const staleMatchShouldReload = age > staleAge && (!!inner.forceStaleReload || match.cause === "enter" || previousRouteMatchId !== void 0 && previousRouteMatchId !== match.id);
loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? staleMatchShouldReload));
if (preload && route.options.preload === false) {} else if (loaderShouldRunAsync && !inner.sync && shouldReloadInBackground) {
loaderIsRunningAsync = true;
(async () => {
try {
await runLoader(inner, matchPromises, matchId, index, route);
const match = inner.router.getMatch(matchId);
match._nonReactive.loaderPromise?.resolve();
match._nonReactive.loadPromise?.resolve();
match._nonReactive.loaderPromise = void 0;
match._nonReactive.loadPromise = void 0;
} catch (err) {
if (isRedirect(err)) await inner.router.navigate(err.options);
}
})();
} else if (status !== "success" || loaderShouldRunAsync) await runLoader(inner, matchPromises, matchId, index, route);
else syncMatchContext(inner, matchId, index);
}
const { id: matchId, routeId } = inner.matches[index];
let loaderShouldRunAsync = false;
let loaderIsRunningAsync = false;
const route = inner.router.looseRoutesById[routeId];
const routeLoader = route.options.loader;
const shouldReloadInBackground = ((typeof routeLoader === "function" ? void 0 : routeLoader?.staleReloadMode) ?? inner.router.options.defaultStaleReloadMode) !== "blocking";
if (shouldSkipLoader(inner, matchId)) {
if (!inner.router.getMatch(matchId)) return inner.matches[index];
syncMatchContext(inner, matchId, index);
if (isServer ?? inner.router.isServer) return inner.router.getMatch(matchId);
} else {
const prevMatch = inner.router.getMatch(matchId);
const previousRouteMatchId = inner.router.state.matches[index]?.routeId === routeId ? inner.router.state.matches[index].id : inner.router.state.matches.find((d) => d.routeId === routeId)?.id;
const preload = resolvePreload(inner, matchId);
if (prevMatch._nonReactive.loaderPromise) {
if (prevMatch.status === "success" && !inner.sync && !prevMatch.preload && shouldReloadInBackground) return prevMatch;
await prevMatch._nonReactive.loaderPromise;
const match = inner.router.getMatch(matchId);
const error = match._nonReactive.error || match.error;
if (error) handleRedirectAndNotFound(inner, match, error);
if (match.status === "pending") await handleLoader(preload, prevMatch, previousRouteMatchId, match, route);
} else {
const nextPreload = preload && !inner.router.state.matches.some((d) => d.id === matchId);
const match = inner.router.getMatch(matchId);
match._nonReactive.loaderPromise = createControlledPromise();
if (nextPreload !== match.preload) inner.updateMatch(matchId, (prev) => ({
...prev,
preload: nextPreload
}));
await handleLoader(preload, prevMatch, previousRouteMatchId, match, route);
}
}
const match = inner.router.getMatch(matchId);
if (!loaderIsRunningAsync) {
match._nonReactive.loaderPromise?.resolve();
match._nonReactive.loadPromise?.resolve();
match._nonReactive.loadPromise = void 0;
}
clearTimeout(match._nonReactive.pendingTimeout);
match._nonReactive.pendingTimeout = void 0;
if (!loaderIsRunningAsync) match._nonReactive.loaderPromise = void 0;
match._nonReactive.dehydrated = void 0;
const nextIsFetching = loaderIsRunningAsync ? match.isFetching : false;
if (nextIsFetching !== match.isFetching || match.invalid !== false) {
inner.updateMatch(matchId, (prev) => ({
...prev,
isFetching: nextIsFetching,
invalid: false
}));
return inner.router.getMatch(matchId);
} else return match;
};
async function loadMatches(arg) {
const inner = arg;
const matchPromises = [];
if (!(isServer ?? inner.router.isServer) && inner.router.state.matches.some((d) => d._forcePending)) triggerOnReady(inner);
let beforeLoadNotFound;
for (let i = 0; i < inner.matches.length; i++) {
try {
const beforeLoad = handleBeforeLoad(inner, i);
if (isPromise(beforeLoad)) await beforeLoad;
} catch (err) {
if (isRedirect(err)) throw err;
if (isNotFound(err)) beforeLoadNotFound = err;
else if (!inner.preload) throw err;
break;
}
if (inner.serialError) break;
}
const baseMaxIndexExclusive = inner.firstBadMatchIndex ?? inner.matches.length;
const boundaryIndex = beforeLoadNotFound && !inner.preload ? getNotFoundBoundaryIndex(inner, beforeLoadNotFound) : void 0;
const maxIndexExclusive = beforeLoadNotFound && inner.preload ? 0 : boundaryIndex !== void 0 ? Math.min(boundaryIndex + 1, baseMaxIndexExclusive) : baseMaxIndexExclusive;
let firstNotFound;
let firstUnhandledRejection;
for (let i = 0; i < maxIndexExclusive; i++) matchPromises.push(loadRouteMatch(inner, matchPromises, i));
try {
await Promise.all(matchPromises);
} catch {
const settled = await Promise.allSettled(matchPromises);
for (const result of settled) {
if (result.status !== "rejected") continue;
const reason = result.reason;
if (isRedirect(reason)) throw reason;
if (isNotFound(reason)) firstNotFound ??= reason;
else firstUnhandledRejection ??= reason;
}
if (firstUnhandledRejection !== void 0) throw firstUnhandledRejection;
}
const notFoundToThrow = firstNotFound ?? (beforeLoadNotFound && !inner.preload ? beforeLoadNotFound : void 0);
let headMaxIndex = inner.serialError ? inner.firstBadMatchIndex ?? 0 : inner.matches.length - 1;
if (!notFoundToThrow && beforeLoadNotFound && inner.preload) return inner.matches;
if (notFoundToThrow) {
const renderedBoundaryIndex = getNotFoundBoundaryIndex(inner, notFoundToThrow);
invariant(renderedBoundaryIndex !== void 0, "Could not find match for notFound boundary");
const boundaryMatch = inner.matches[renderedBoundaryIndex];
const boundaryRoute = inner.router.looseRoutesById[boundaryMatch.routeId];
const defaultNotFoundComponent = inner.router.options?.defaultNotFoundComponent;
if (!boundaryRoute.options.notFoundComponent && defaultNotFoundComponent) boundaryRoute.options.notFoundComponent = defaultNotFoundComponent;
notFoundToThrow.routeId = boundaryMatch.routeId;
const boundaryIsRoot = boundaryMatch.routeId === inner.router.routeTree.id;
inner.updateMatch(boundaryMatch.id, (prev) => ({
...prev,
...boundaryIsRoot ? {
status: "success",
globalNotFound: true,
error: void 0
} : {
status: "notFound",
error: notFoundToThrow
},
isFetching: false
}));
headMaxIndex = renderedBoundaryIndex;
await loadRouteChunk(boundaryRoute, ["notFoundComponent"]);
} else if (!inner.preload) {
const rootMatch = inner.matches[0];
if (!rootMatch.globalNotFound) {
if (inner.router.getMatch(rootMatch.id)?.globalNotFound) inner.updateMatch(rootMatch.id, (prev) => ({
...prev,
globalNotFound: false,
error: void 0
}));
}
}
if (inner.serialError && inner.firstBadMatchIndex !== void 0) {
const errorRoute = inner.router.looseRoutesById[inner.matches[inner.firstBadMatchIndex].routeId];
await loadRouteChunk(errorRoute, ["errorComponent"]);
}
for (let i = 0; i <= headMaxIndex; i++) {
const { id: matchId, routeId } = inner.matches[i];
const route = inner.router.looseRoutesById[routeId];
try {
const headResult = executeHead(inner, matchId, route);
if (headResult) {
const head = await headResult;
inner.updateMatch(matchId, (prev) => ({
...prev,
...head
}));
}
} catch (err) {
console.error(`Error executing head for route ${routeId}:`, err);
}
}
const readyPromise = triggerOnReady(inner);
if (isPromise(readyPromise)) await readyPromise;
if (notFoundToThrow) throw notFoundToThrow;
if (inner.serialError && !inner.preload && !inner.onReady) throw inner.serialError;
return inner.matches;
}
function preloadRouteComponents(route, componentTypesToLoad) {
const preloads = componentTypesToLoad.map((type) => route.options[type]?.preload?.()).filter(Boolean);
if (preloads.length === 0) return void 0;
return Promise.all(preloads);
}
function loadRouteChunk(route, componentTypesToLoad = componentTypes) {
if (!route._lazyLoaded && route._lazyPromise === void 0) if (route.lazyFn) route._lazyPromise = route.lazyFn().then((lazyRoute) => {
const { id: _id, ...options } = lazyRoute.options;
Object.assign(route.options, options);
route._lazyLoaded = true;
route._lazyPromise = void 0;
});
else route._lazyLoaded = true;
const runAfterLazy = () => route._componentsLoaded ? void 0 : componentTypesToLoad === componentTypes ? (() => {
if (route._componentsPromise === void 0) {
const componentsPromise = preloadRouteComponents(route, componentTypes);
if (componentsPromise) route._componentsPromise = componentsPromise.then(() => {
route._componentsLoaded = true;
route._componentsPromise = void 0;
});
else route._componentsLoaded = true;
}
return route._componentsPromise;
})() : preloadRouteComponents(route, componentTypesToLoad);
return route._lazyPromise ? route._lazyPromise.then(runAfterLazy) : runAfterLazy();
}
function makeMaybe(value, error) {
if (error) return {
status: "error",
error
};
return {
status: "success",
value
};
}
function routeNeedsPreload(route) {
for (const componentType of componentTypes) if (route.options[componentType]?.preload) return true;
return false;
}
var componentTypes = [
"component",
"errorComponent",
"pendingComponent",
"notFoundComponent"
];
//#endregion
export { loadMatches, loadRouteChunk, routeNeedsPreload };
//# sourceMappingURL=load-matches.js.map