Socket
Socket
Sign inDemoInstall

@tanstack/router

Package Overview
Dependencies
Maintainers
1
Versions
104
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/router - npm Package Compare versions

Comparing version 0.0.1-beta.61 to 0.0.1-beta.62

7

build/cjs/route.js

@@ -34,3 +34,5 @@ /**

}
init = () => {
init = opts => {
this.originalIndex = opts.originalIndex;
this.router = opts.router;
const allOptions = this.options;

@@ -83,2 +85,5 @@ const isRoot = !allOptions?.path && !allOptions?.id;

}
static withRouterContext = () => {
return options => new RootRoute(options);
};
}

@@ -85,0 +90,0 @@

113

build/cjs/routeMatch.js

@@ -35,4 +35,9 @@ /**

status: 'idle'
}, {
onUpdate: next => {
this.state = next;
}
})
});
this.state = this.store.state;
if (!this.#hasLoaders()) {

@@ -45,2 +50,56 @@ this.store.setState(s => ({

}
#hasLoaders = () => {
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
};
__init = opts => {
// Validate the search params and stabilize them
this.parentMatch = opts.parentMatch;
const parentSearch = this.parentMatch?.state.search ?? this.router.state.latestLocation.search;
try {
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
let nextSearch = validator?.(parentSearch) ?? {};
this.store.setState(s => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch
}
}));
componentTypes.map(async type => {
const component = this.route.options[type];
if (typeof this[type] !== 'function') {
this[type] = component;
}
});
const parent = this.parentMatch;
this.routeContext = this.route.options.getContext?.({
parentContext: parent?.routeContext,
context: parent?.context,
params: this.params,
search: this.state.search
}) || {};
this.context = parent ? {
...parent.context,
...this.routeContext
} : {
...this.router?.options.context,
...this.routeContext
};
} catch (err) {
console.error(err);
const error = new Error('Invalid search params found', {
cause: err
});
error.code = 'INVALID_SEARCH_PARAMS';
this.store.setState(s => ({
...s,
status: 'error',
error: error
}));
// Do not proceed with loading the route
return;
}
};
cancel = () => {

@@ -51,3 +110,3 @@ this.abortController?.abort();

// If the match is invalid, errored or idle, trigger it to load
if (this.store.state.status !== 'pending') {
if (this.state.status !== 'pending') {
await this.fetch(opts);

@@ -69,3 +128,3 @@ }

// as loading or resolved
if (this.store.state.status === 'idle') {
if (this.state.status === 'idle') {
this.store.setState(s => ({

@@ -92,5 +151,7 @@ ...s,

params: this.params,
search: this.store.state.search,
search: this.state.search,
signal: this.abortController.signal,
preload: !!opts?.preload
preload: !!opts?.preload,
routeContext: this.routeContext,
context: this.context
});

@@ -123,46 +184,2 @@ }

};
#hasLoaders = () => {
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
};
__setParentMatch = parentMatch => {
if (!this.parentMatch && parentMatch) {
this.parentMatch = parentMatch;
}
};
__validate = () => {
// Validate the search params and stabilize them
const parentSearch = this.parentMatch?.store.state.search ?? this.router.store.state.latestLocation.search;
try {
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
let nextSearch = validator?.(parentSearch) ?? {};
this.store.setState(s => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch
}
}));
componentTypes.map(async type => {
const component = this.route.options[type];
if (typeof this[type] !== 'function') {
this[type] = component;
}
});
} catch (err) {
console.error(err);
const error = new Error('Invalid search params found', {
cause: err
});
error.code = 'INVALID_SEARCH_PARAMS';
this.store.setState(s => ({
...s,
status: 'error',
error: error
}));
// Do not proceed with loading the route
return;
}
};
}

@@ -169,0 +186,0 @@

@@ -62,3 +62,8 @@ /**

};
this.store = new store.Store(getInitialRouterState());
this.store = new store.Store(getInitialRouterState(), {
onUpdate: state => {
this.state = state;
}
});
this.state = this.store.state;
this.basepath = '';

@@ -77,3 +82,3 @@ this.update(options);

// If the router matches are empty, load the matches
if (!this.store.state.currentMatches.length) {
if (!this.state.currentMatches.length) {
this.load();

@@ -117,3 +122,5 @@ }

this.#unsubHistory = this.history.listen(() => {
this.load(this.#parseLocation(this.store.state.latestLocation));
this.load({
next: this.#parseLocation(this.state.latestLocation)
});
});

@@ -144,7 +151,7 @@ }

cancelMatches = () => {
[...this.store.state.currentMatches, ...(this.store.state.pendingMatches || [])].forEach(match => {
[...this.state.currentMatches, ...(this.state.pendingMatches || [])].forEach(match => {
match.cancel();
});
};
load = async next => {
load = async opts => {
let now = Date.now();

@@ -158,7 +165,7 @@ const startedAt = now;

this.store.batch(() => {
if (next) {
if (opts?.next) {
// Ingest the new location
this.store.setState(s => ({
...s,
latestLocation: next
latestLocation: opts.next
}));

@@ -168,3 +175,3 @@ }

// Match the routes
matches = this.matchRoutes(this.store.state.latestLocation.pathname, {
matches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true

@@ -176,3 +183,3 @@ });

pendingMatches: matches,
pendingLocation: this.store.state.latestLocation
pendingLocation: this.state.latestLocation
}));

@@ -183,3 +190,5 @@ });

try {
await this.loadMatches(matches);
await this.loadMatches(matches
// opts
);
} catch (err) {

@@ -193,3 +202,3 @@ console.warn(err);

}
const previousMatches = this.store.state.currentMatches;
const previousMatches = this.state.currentMatches;
const exiting = [],

@@ -211,7 +220,7 @@ staying = [];

params: d.params,
search: d.store.state.routeSearch
search: d.state.routeSearch
});
// Clear non-loading error states when match leaves
if (d.store.state.status === 'error') {
if (d.state.status === 'error') {
this.store.setState(s => ({

@@ -227,3 +236,3 @@ ...s,

params: d.params,
search: d.store.state.routeSearch
search: d.state.routeSearch
});

@@ -234,11 +243,9 @@ });

params: d.params,
search: d.store.state.search
search: d.state.search
});
// delete this.store.state.matchCache[d.id] // TODO:
});
this.store.setState(s => ({
...s,
status: 'idle',
currentLocation: this.store.state.latestLocation,
currentLocation: this.state.latestLocation,
currentMatches: matches,

@@ -256,3 +263,3 @@ pendingLocation: undefined,

};
loadRoute = async (navigateOpts = this.store.state.latestLocation) => {
loadRoute = async (navigateOpts = this.state.latestLocation) => {
const next = this.buildNext(navigateOpts);

@@ -265,3 +272,3 @@ const matches = this.matchRoutes(next.pathname, {

};
preloadRoute = async (navigateOpts = this.store.state.latestLocation) => {
preloadRoute = async (navigateOpts = this.state.latestLocation) => {
const next = this.buildNext(navigateOpts);

@@ -281,3 +288,3 @@ const matches = this.matchRoutes(next.pathname, {

}
const existingMatches = [...this.store.state.currentMatches, ...(this.store.state.pendingMatches ?? [])];
const existingMatches = [...this.state.currentMatches, ...(this.state.pendingMatches ?? [])];
const findInRouteTree = async routes => {

@@ -328,5 +335,3 @@ const parentMatch = utils.last(matches);

const matchId = path.interpolatePath(foundRoute.id, params, true);
const match = existingMatches.find(d => d.id === matchId) ||
// this.store.state.matchCache[matchId]?.match || // TODO:
new routeMatch.RouteMatch(this, foundRoute, {
const match = existingMatches.find(d => d.id === matchId) || new routeMatch.RouteMatch(this, foundRoute, {
id: matchId,

@@ -347,11 +352,5 @@ params,

};
loadMatches = async (resolvedMatches, loaderOpts) => {
linkMatches(resolvedMatches);
loadMatches = async (resolvedMatches, opts) => {
initMatches(resolvedMatches);
// this.cleanMatchCache()
resolvedMatches.forEach(async match => {
// Validate the match (loads search params etc)
match.__validate();
});
// Check each match middleware to see if the route can be accessed

@@ -365,3 +364,3 @@ await Promise.all(resolvedMatches.map(async match => {

} catch (err) {
if (!loaderOpts?.preload) {
if (!opts?.preload) {
match.route.options.onLoadError?.(err);

@@ -374,10 +373,12 @@ }

const prevMatch = resolvedMatches[1];
const search = match.store.state.search;
if (search.__data?.matchId && search.__data.matchId !== match.id) {
return;
}
match.state.search;
// if (opts?.filter && !opts.filter(match)) {
// return
// }
match.load({
preload: loaderOpts?.preload
preload: opts?.preload
});
if (match.store.state.status !== 'success' && match.__loadPromise) {
if (match.state.status !== 'success' && match.__loadPromise) {
// Wait for the first sign of activity from the match

@@ -439,6 +440,6 @@ await match.__loadPromise;

if (opts?.pending) {
if (!this.store.state.pendingLocation) {
if (!this.state.pendingLocation) {
return false;
}
return path.matchPathname(this.basepath, this.store.state.pendingLocation.pathname, {
return path.matchPathname(this.basepath, this.state.pendingLocation.pathname, {
...opts,

@@ -448,3 +449,3 @@ to: next.pathname

}
return path.matchPathname(this.basepath, this.store.state.currentLocation.pathname, {
return path.matchPathname(this.basepath, this.state.currentLocation.pathname, {
...opts,

@@ -495,7 +496,7 @@ to: next.pathname

// Compare path/hash for matches
const pathIsEqual = this.store.state.currentLocation.pathname === next.pathname;
const currentPathSplit = this.store.state.currentLocation.pathname.split('/');
const pathIsEqual = this.state.currentLocation.pathname === next.pathname;
const currentPathSplit = this.state.currentLocation.pathname.split('/');
const nextPathSplit = next.pathname.split('/');
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
const hashIsEqual = this.store.state.currentLocation.hash === next.hash;
const hashIsEqual = this.state.currentLocation.hash === next.hash;
// Combine the matches based on user options

@@ -563,11 +564,10 @@ const pathTest = activeOptions?.exact ? pathIsEqual : pathIsFuzzyEqual;

state: {
...utils.pick(this.store.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
currentMatches: this.store.state.currentMatches.map(match => ({
...utils.pick(this.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
currentMatches: this.state.currentMatches.map(match => ({
id: match.id,
state: {
...utils.pick(match.store.state, ['status'])
status: match.state.status
}
}))
},
context: this.options.context
}
};

@@ -577,4 +577,2 @@ };

this.store.setState(s => {
this.options.context = dehydratedRouter.context;
// Match the routes

@@ -592,3 +590,3 @@ const currentMatches = this.matchRoutes(dehydratedRouter.state.latestLocation.pathname, {

});
currentMatches.forEach(match => match.__validate());
initMatches(currentMatches);
return {

@@ -604,5 +602,6 @@ ...s,

routes.forEach((route, i) => {
route.init();
route.originalIndex = i;
route.router = this;
route.init({
originalIndex: i,
router: this
});
const existingRoute = this.routesById[route.id];

@@ -645,5 +644,5 @@ if (existingRoute) {

#buildLocation = (dest = {}) => {
const fromPathname = dest.fromCurrent ? this.store.state.latestLocation.pathname : dest.from ?? this.store.state.latestLocation.pathname;
const fromPathname = dest.fromCurrent ? this.state.latestLocation.pathname : dest.from ?? this.state.latestLocation.pathname;
let pathname = path.resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? '.'}`);
const fromMatches = this.matchRoutes(this.store.state.latestLocation.pathname, {
const fromMatches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true

@@ -664,3 +663,3 @@ });

// Pre filters first
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.store.state.latestLocation.search) : this.store.state.latestLocation.search;
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.state.latestLocation.search) : this.state.latestLocation.search;

@@ -675,5 +674,5 @@ // Then the link/navigate function

const postFilteredSearch = dest.__postSearchFilters?.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
const search = utils.replaceEqualDeep(this.store.state.latestLocation.search, postFilteredSearch);
const search = utils.replaceEqualDeep(this.state.latestLocation.search, postFilteredSearch);
const searchStr = this.options.stringifySearch(search);
let hash = dest.hash === true ? this.store.state.latestLocation.hash : utils.functionalUpdate(dest.hash, this.store.state.latestLocation.hash);
let hash = dest.hash === true ? this.state.latestLocation.hash : utils.functionalUpdate(dest.hash, this.state.latestLocation.hash);
hash = hash ? `#${hash}` : '';

@@ -684,3 +683,3 @@ return {

searchStr,
state: this.store.state.latestLocation.state,
state: this.state.latestLocation.state,
hash,

@@ -699,3 +698,3 @@ href: `${pathname}${searchStr}${hash}`,

}
const isSameUrl = this.store.state.latestLocation.href === next.href;
const isSameUrl = this.state.latestLocation.href === next.href;
if (isSameUrl && !next.key) {

@@ -710,3 +709,3 @@ nextAction = 'replace';

// this.load(this.#parseLocation(this.store.state.latestLocation))
// this.load(this.#parseLocation(this.state.latestLocation))

@@ -737,8 +736,8 @@ return this.navigationPromise = new Promise(resolve => {

}
function linkMatches(matches) {
function initMatches(matches) {
matches.forEach((match, index) => {
const parent = matches[index - 1];
if (parent) {
match.__setParentMatch(parent);
}
const parentMatch = matches[index - 1];
match.__init({
parentMatch
});
});

@@ -745,0 +744,0 @@ }

@@ -473,3 +473,5 @@ /**

}
init = () => {
init = opts => {
this.originalIndex = opts.originalIndex;
this.router = opts.router;
const allOptions = this.options;

@@ -522,2 +524,5 @@ const isRoot = !allOptions?.path && !allOptions?.id;

}
static withRouterContext = () => {
return options => new RootRoute(options);
};
}

@@ -587,4 +592,9 @@

status: 'idle'
}, {
onUpdate: next => {
this.state = next;
}
})
});
this.state = this.store.state;
if (!this.#hasLoaders()) {

@@ -597,2 +607,56 @@ this.store.setState(s => ({

}
#hasLoaders = () => {
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
};
__init = opts => {
// Validate the search params and stabilize them
this.parentMatch = opts.parentMatch;
const parentSearch = this.parentMatch?.state.search ?? this.router.state.latestLocation.search;
try {
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
let nextSearch = validator?.(parentSearch) ?? {};
this.store.setState(s => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch
}
}));
componentTypes.map(async type => {
const component = this.route.options[type];
if (typeof this[type] !== 'function') {
this[type] = component;
}
});
const parent = this.parentMatch;
this.routeContext = this.route.options.getContext?.({
parentContext: parent?.routeContext,
context: parent?.context,
params: this.params,
search: this.state.search
}) || {};
this.context = parent ? {
...parent.context,
...this.routeContext
} : {
...this.router?.options.context,
...this.routeContext
};
} catch (err) {
console.error(err);
const error = new Error('Invalid search params found', {
cause: err
});
error.code = 'INVALID_SEARCH_PARAMS';
this.store.setState(s => ({
...s,
status: 'error',
error: error
}));
// Do not proceed with loading the route
return;
}
};
cancel = () => {

@@ -603,3 +667,3 @@ this.abortController?.abort();

// If the match is invalid, errored or idle, trigger it to load
if (this.store.state.status !== 'pending') {
if (this.state.status !== 'pending') {
await this.fetch(opts);

@@ -621,3 +685,3 @@ }

// as loading or resolved
if (this.store.state.status === 'idle') {
if (this.state.status === 'idle') {
this.store.setState(s => ({

@@ -644,5 +708,7 @@ ...s,

params: this.params,
search: this.store.state.search,
search: this.state.search,
signal: this.abortController.signal,
preload: !!opts?.preload
preload: !!opts?.preload,
routeContext: this.routeContext,
context: this.context
});

@@ -675,46 +741,2 @@ }

};
#hasLoaders = () => {
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
};
__setParentMatch = parentMatch => {
if (!this.parentMatch && parentMatch) {
this.parentMatch = parentMatch;
}
};
__validate = () => {
// Validate the search params and stabilize them
const parentSearch = this.parentMatch?.store.state.search ?? this.router.store.state.latestLocation.search;
try {
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
let nextSearch = validator?.(parentSearch) ?? {};
this.store.setState(s => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch
}
}));
componentTypes.map(async type => {
const component = this.route.options[type];
if (typeof this[type] !== 'function') {
this[type] = component;
}
});
} catch (err) {
console.error(err);
const error = new Error('Invalid search params found', {
cause: err
});
error.code = 'INVALID_SEARCH_PARAMS';
this.store.setState(s => ({
...s,
status: 'error',
error: error
}));
// Do not proceed with loading the route
return;
}
};
}

@@ -804,3 +826,8 @@

};
this.store = new Store(getInitialRouterState());
this.store = new Store(getInitialRouterState(), {
onUpdate: state => {
this.state = state;
}
});
this.state = this.store.state;
this.basepath = '';

@@ -819,3 +846,3 @@ this.update(options);

// If the router matches are empty, load the matches
if (!this.store.state.currentMatches.length) {
if (!this.state.currentMatches.length) {
this.load();

@@ -859,3 +886,5 @@ }

this.#unsubHistory = this.history.listen(() => {
this.load(this.#parseLocation(this.store.state.latestLocation));
this.load({
next: this.#parseLocation(this.state.latestLocation)
});
});

@@ -886,7 +915,7 @@ }

cancelMatches = () => {
[...this.store.state.currentMatches, ...(this.store.state.pendingMatches || [])].forEach(match => {
[...this.state.currentMatches, ...(this.state.pendingMatches || [])].forEach(match => {
match.cancel();
});
};
load = async next => {
load = async opts => {
let now = Date.now();

@@ -900,7 +929,7 @@ const startedAt = now;

this.store.batch(() => {
if (next) {
if (opts?.next) {
// Ingest the new location
this.store.setState(s => ({
...s,
latestLocation: next
latestLocation: opts.next
}));

@@ -910,3 +939,3 @@ }

// Match the routes
matches = this.matchRoutes(this.store.state.latestLocation.pathname, {
matches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true

@@ -918,3 +947,3 @@ });

pendingMatches: matches,
pendingLocation: this.store.state.latestLocation
pendingLocation: this.state.latestLocation
}));

@@ -925,3 +954,5 @@ });

try {
await this.loadMatches(matches);
await this.loadMatches(matches
// opts
);
} catch (err) {

@@ -935,3 +966,3 @@ console.warn(err);

}
const previousMatches = this.store.state.currentMatches;
const previousMatches = this.state.currentMatches;
const exiting = [],

@@ -953,7 +984,7 @@ staying = [];

params: d.params,
search: d.store.state.routeSearch
search: d.state.routeSearch
});
// Clear non-loading error states when match leaves
if (d.store.state.status === 'error') {
if (d.state.status === 'error') {
this.store.setState(s => ({

@@ -969,3 +1000,3 @@ ...s,

params: d.params,
search: d.store.state.routeSearch
search: d.state.routeSearch
});

@@ -976,11 +1007,9 @@ });

params: d.params,
search: d.store.state.search
search: d.state.search
});
// delete this.store.state.matchCache[d.id] // TODO:
});
this.store.setState(s => ({
...s,
status: 'idle',
currentLocation: this.store.state.latestLocation,
currentLocation: this.state.latestLocation,
currentMatches: matches,

@@ -998,3 +1027,3 @@ pendingLocation: undefined,

};
loadRoute = async (navigateOpts = this.store.state.latestLocation) => {
loadRoute = async (navigateOpts = this.state.latestLocation) => {
const next = this.buildNext(navigateOpts);

@@ -1007,3 +1036,3 @@ const matches = this.matchRoutes(next.pathname, {

};
preloadRoute = async (navigateOpts = this.store.state.latestLocation) => {
preloadRoute = async (navigateOpts = this.state.latestLocation) => {
const next = this.buildNext(navigateOpts);

@@ -1023,3 +1052,3 @@ const matches = this.matchRoutes(next.pathname, {

}
const existingMatches = [...this.store.state.currentMatches, ...(this.store.state.pendingMatches ?? [])];
const existingMatches = [...this.state.currentMatches, ...(this.state.pendingMatches ?? [])];
const findInRouteTree = async routes => {

@@ -1070,5 +1099,3 @@ const parentMatch = last(matches);

const matchId = interpolatePath(foundRoute.id, params, true);
const match = existingMatches.find(d => d.id === matchId) ||
// this.store.state.matchCache[matchId]?.match || // TODO:
new RouteMatch(this, foundRoute, {
const match = existingMatches.find(d => d.id === matchId) || new RouteMatch(this, foundRoute, {
id: matchId,

@@ -1089,11 +1116,5 @@ params,

};
loadMatches = async (resolvedMatches, loaderOpts) => {
linkMatches(resolvedMatches);
loadMatches = async (resolvedMatches, opts) => {
initMatches(resolvedMatches);
// this.cleanMatchCache()
resolvedMatches.forEach(async match => {
// Validate the match (loads search params etc)
match.__validate();
});
// Check each match middleware to see if the route can be accessed

@@ -1107,3 +1128,3 @@ await Promise.all(resolvedMatches.map(async match => {

} catch (err) {
if (!loaderOpts?.preload) {
if (!opts?.preload) {
match.route.options.onLoadError?.(err);

@@ -1116,10 +1137,12 @@ }

const prevMatch = resolvedMatches[1];
const search = match.store.state.search;
if (search.__data?.matchId && search.__data.matchId !== match.id) {
return;
}
match.state.search;
// if (opts?.filter && !opts.filter(match)) {
// return
// }
match.load({
preload: loaderOpts?.preload
preload: opts?.preload
});
if (match.store.state.status !== 'success' && match.__loadPromise) {
if (match.state.status !== 'success' && match.__loadPromise) {
// Wait for the first sign of activity from the match

@@ -1181,6 +1204,6 @@ await match.__loadPromise;

if (opts?.pending) {
if (!this.store.state.pendingLocation) {
if (!this.state.pendingLocation) {
return false;
}
return matchPathname(this.basepath, this.store.state.pendingLocation.pathname, {
return matchPathname(this.basepath, this.state.pendingLocation.pathname, {
...opts,

@@ -1190,3 +1213,3 @@ to: next.pathname

}
return matchPathname(this.basepath, this.store.state.currentLocation.pathname, {
return matchPathname(this.basepath, this.state.currentLocation.pathname, {
...opts,

@@ -1237,7 +1260,7 @@ to: next.pathname

// Compare path/hash for matches
const pathIsEqual = this.store.state.currentLocation.pathname === next.pathname;
const currentPathSplit = this.store.state.currentLocation.pathname.split('/');
const pathIsEqual = this.state.currentLocation.pathname === next.pathname;
const currentPathSplit = this.state.currentLocation.pathname.split('/');
const nextPathSplit = next.pathname.split('/');
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
const hashIsEqual = this.store.state.currentLocation.hash === next.hash;
const hashIsEqual = this.state.currentLocation.hash === next.hash;
// Combine the matches based on user options

@@ -1305,11 +1328,10 @@ const pathTest = activeOptions?.exact ? pathIsEqual : pathIsFuzzyEqual;

state: {
...pick(this.store.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
currentMatches: this.store.state.currentMatches.map(match => ({
...pick(this.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
currentMatches: this.state.currentMatches.map(match => ({
id: match.id,
state: {
...pick(match.store.state, ['status'])
status: match.state.status
}
}))
},
context: this.options.context
}
};

@@ -1319,4 +1341,2 @@ };

this.store.setState(s => {
this.options.context = dehydratedRouter.context;
// Match the routes

@@ -1334,3 +1354,3 @@ const currentMatches = this.matchRoutes(dehydratedRouter.state.latestLocation.pathname, {

});
currentMatches.forEach(match => match.__validate());
initMatches(currentMatches);
return {

@@ -1346,5 +1366,6 @@ ...s,

routes.forEach((route, i) => {
route.init();
route.originalIndex = i;
route.router = this;
route.init({
originalIndex: i,
router: this
});
const existingRoute = this.routesById[route.id];

@@ -1387,5 +1408,5 @@ if (existingRoute) {

#buildLocation = (dest = {}) => {
const fromPathname = dest.fromCurrent ? this.store.state.latestLocation.pathname : dest.from ?? this.store.state.latestLocation.pathname;
const fromPathname = dest.fromCurrent ? this.state.latestLocation.pathname : dest.from ?? this.state.latestLocation.pathname;
let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? '.'}`);
const fromMatches = this.matchRoutes(this.store.state.latestLocation.pathname, {
const fromMatches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true

@@ -1406,3 +1427,3 @@ });

// Pre filters first
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.store.state.latestLocation.search) : this.store.state.latestLocation.search;
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.state.latestLocation.search) : this.state.latestLocation.search;

@@ -1417,5 +1438,5 @@ // Then the link/navigate function

const postFilteredSearch = dest.__postSearchFilters?.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
const search = replaceEqualDeep(this.store.state.latestLocation.search, postFilteredSearch);
const search = replaceEqualDeep(this.state.latestLocation.search, postFilteredSearch);
const searchStr = this.options.stringifySearch(search);
let hash = dest.hash === true ? this.store.state.latestLocation.hash : functionalUpdate(dest.hash, this.store.state.latestLocation.hash);
let hash = dest.hash === true ? this.state.latestLocation.hash : functionalUpdate(dest.hash, this.state.latestLocation.hash);
hash = hash ? `#${hash}` : '';

@@ -1426,3 +1447,3 @@ return {

searchStr,
state: this.store.state.latestLocation.state,
state: this.state.latestLocation.state,
hash,

@@ -1441,3 +1462,3 @@ href: `${pathname}${searchStr}${hash}`,

}
const isSameUrl = this.store.state.latestLocation.href === next.href;
const isSameUrl = this.state.latestLocation.href === next.href;
if (isSameUrl && !next.key) {

@@ -1452,3 +1473,3 @@ nextAction = 'replace';

// this.load(this.#parseLocation(this.store.state.latestLocation))
// this.load(this.#parseLocation(this.state.latestLocation))

@@ -1479,8 +1500,8 @@ return this.navigationPromise = new Promise(resolve => {

}
function linkMatches(matches) {
function initMatches(matches) {
matches.forEach((match, index) => {
const parent = matches[index - 1];
if (parent) {
match.__setParentMatch(parent);
}
const parentMatch = matches[index - 1];
match.__init({
parentMatch
});
});

@@ -1487,0 +1508,0 @@ }

@@ -11,3 +11,3 @@ {

"name": "node_modules/.pnpm/tiny-invariant@1.3.1/node_modules/tiny-invariant/dist/esm/tiny-invariant.js",
"uid": "eda2-30"
"uid": "dcf0-30"
},

@@ -21,35 +21,35 @@ {

{
"uid": "eda2-32",
"uid": "dcf0-32",
"name": "history.ts"
},
{
"uid": "eda2-34",
"uid": "dcf0-34",
"name": "utils.ts"
},
{
"uid": "eda2-36",
"uid": "dcf0-36",
"name": "path.ts"
},
{
"uid": "eda2-38",
"uid": "dcf0-38",
"name": "qss.ts"
},
{
"uid": "eda2-40",
"uid": "dcf0-40",
"name": "route.ts"
},
{
"uid": "eda2-44",
"uid": "dcf0-44",
"name": "routeMatch.ts"
},
{
"uid": "eda2-46",
"uid": "dcf0-46",
"name": "searchParams.ts"
},
{
"uid": "eda2-48",
"uid": "dcf0-48",
"name": "router.ts"
},
{
"uid": "eda2-50",
"uid": "dcf0-50",
"name": "index.ts"

@@ -61,3 +61,3 @@ }

"name": "store/build/esm/index.js",
"uid": "eda2-42"
"uid": "dcf0-42"
}

@@ -72,74 +72,74 @@ ]

"nodeParts": {
"eda2-30": {
"dcf0-30": {
"renderedLength": 199,
"gzipLength": 134,
"brotliLength": 0,
"mainUid": "eda2-29"
"mainUid": "dcf0-29"
},
"eda2-32": {
"dcf0-32": {
"renderedLength": 4236,
"gzipLength": 1085,
"brotliLength": 0,
"mainUid": "eda2-31"
"mainUid": "dcf0-31"
},
"eda2-34": {
"dcf0-34": {
"renderedLength": 2572,
"gzipLength": 950,
"brotliLength": 0,
"mainUid": "eda2-33"
"mainUid": "dcf0-33"
},
"eda2-36": {
"dcf0-36": {
"renderedLength": 5601,
"gzipLength": 1328,
"brotliLength": 0,
"mainUid": "eda2-35"
"mainUid": "dcf0-35"
},
"eda2-38": {
"dcf0-38": {
"renderedLength": 1395,
"gzipLength": 558,
"brotliLength": 0,
"mainUid": "eda2-37"
"mainUid": "dcf0-37"
},
"eda2-40": {
"renderedLength": 2962,
"gzipLength": 894,
"dcf0-40": {
"renderedLength": 3148,
"gzipLength": 944,
"brotliLength": 0,
"mainUid": "eda2-39"
"mainUid": "dcf0-39"
},
"eda2-42": {
"renderedLength": 1386,
"gzipLength": 501,
"dcf0-42": {
"renderedLength": 1384,
"gzipLength": 502,
"brotliLength": 0,
"mainUid": "eda2-41"
"mainUid": "dcf0-41"
},
"eda2-44": {
"renderedLength": 4873,
"gzipLength": 1357,
"dcf0-44": {
"renderedLength": 5448,
"gzipLength": 1470,
"brotliLength": 0,
"mainUid": "eda2-43"
"mainUid": "dcf0-43"
},
"eda2-46": {
"dcf0-46": {
"renderedLength": 1387,
"gzipLength": 483,
"brotliLength": 0,
"mainUid": "eda2-45"
"mainUid": "dcf0-45"
},
"eda2-48": {
"renderedLength": 23650,
"gzipLength": 5501,
"dcf0-48": {
"renderedLength": 23107,
"gzipLength": 5390,
"brotliLength": 0,
"mainUid": "eda2-47"
"mainUid": "dcf0-47"
},
"eda2-50": {
"dcf0-50": {
"renderedLength": 0,
"gzipLength": 0,
"brotliLength": 0,
"mainUid": "eda2-49"
"mainUid": "dcf0-49"
}
},
"nodeMetas": {
"eda2-29": {
"dcf0-29": {
"id": "/node_modules/.pnpm/tiny-invariant@1.3.1/node_modules/tiny-invariant/dist/esm/tiny-invariant.js",
"moduleParts": {
"index.production.js": "eda2-30"
"index.production.js": "dcf0-30"
},

@@ -149,16 +149,16 @@ "imported": [],

{
"uid": "eda2-49"
"uid": "dcf0-49"
},
{
"uid": "eda2-39"
"uid": "dcf0-39"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
}
]
},
"eda2-31": {
"dcf0-31": {
"id": "/packages/router/src/history.ts",
"moduleParts": {
"index.production.js": "eda2-32"
"index.production.js": "dcf0-32"
},

@@ -168,13 +168,13 @@ "imported": [],

{
"uid": "eda2-49"
"uid": "dcf0-49"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
}
]
},
"eda2-33": {
"dcf0-33": {
"id": "/packages/router/src/utils.ts",
"moduleParts": {
"index.production.js": "eda2-34"
"index.production.js": "dcf0-34"
},

@@ -184,20 +184,20 @@ "imported": [],

{
"uid": "eda2-49"
"uid": "dcf0-49"
},
{
"uid": "eda2-35"
"uid": "dcf0-35"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
}
]
},
"eda2-35": {
"dcf0-35": {
"id": "/packages/router/src/path.ts",
"moduleParts": {
"index.production.js": "eda2-36"
"index.production.js": "dcf0-36"
},
"imported": [
{
"uid": "eda2-33"
"uid": "dcf0-33"
}

@@ -207,16 +207,16 @@ ],

{
"uid": "eda2-49"
"uid": "dcf0-49"
},
{
"uid": "eda2-39"
"uid": "dcf0-39"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
}
]
},
"eda2-37": {
"dcf0-37": {
"id": "/packages/router/src/qss.ts",
"moduleParts": {
"index.production.js": "eda2-38"
"index.production.js": "dcf0-38"
},

@@ -226,20 +226,20 @@ "imported": [],

{
"uid": "eda2-49"
"uid": "dcf0-49"
},
{
"uid": "eda2-45"
"uid": "dcf0-45"
}
]
},
"eda2-39": {
"dcf0-39": {
"id": "/packages/router/src/route.ts",
"moduleParts": {
"index.production.js": "eda2-40"
"index.production.js": "dcf0-40"
},
"imported": [
{
"uid": "eda2-29"
"uid": "dcf0-29"
},
{
"uid": "eda2-35"
"uid": "dcf0-35"
}

@@ -249,10 +249,10 @@ ],

{
"uid": "eda2-49"
"uid": "dcf0-49"
}
]
},
"eda2-41": {
"dcf0-41": {
"id": "/packages/store/build/esm/index.js",
"moduleParts": {
"index.production.js": "eda2-42"
"index.production.js": "dcf0-42"
},

@@ -262,17 +262,17 @@ "imported": [],

{
"uid": "eda2-43"
"uid": "dcf0-43"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
}
]
},
"eda2-43": {
"dcf0-43": {
"id": "/packages/router/src/routeMatch.ts",
"moduleParts": {
"index.production.js": "eda2-44"
"index.production.js": "dcf0-44"
},
"imported": [
{
"uid": "eda2-41"
"uid": "dcf0-41"
}

@@ -282,17 +282,17 @@ ],

{
"uid": "eda2-49"
"uid": "dcf0-49"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
}
]
},
"eda2-45": {
"dcf0-45": {
"id": "/packages/router/src/searchParams.ts",
"moduleParts": {
"index.production.js": "eda2-46"
"index.production.js": "dcf0-46"
},
"imported": [
{
"uid": "eda2-37"
"uid": "dcf0-37"
}

@@ -302,35 +302,35 @@ ],

{
"uid": "eda2-49"
"uid": "dcf0-49"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
}
]
},
"eda2-47": {
"dcf0-47": {
"id": "/packages/router/src/router.ts",
"moduleParts": {
"index.production.js": "eda2-48"
"index.production.js": "dcf0-48"
},
"imported": [
{
"uid": "eda2-41"
"uid": "dcf0-41"
},
{
"uid": "eda2-29"
"uid": "dcf0-29"
},
{
"uid": "eda2-35"
"uid": "dcf0-35"
},
{
"uid": "eda2-43"
"uid": "dcf0-43"
},
{
"uid": "eda2-45"
"uid": "dcf0-45"
},
{
"uid": "eda2-33"
"uid": "dcf0-33"
},
{
"uid": "eda2-31"
"uid": "dcf0-31"
}

@@ -340,47 +340,47 @@ ],

{
"uid": "eda2-49"
"uid": "dcf0-49"
}
]
},
"eda2-49": {
"dcf0-49": {
"id": "/packages/router/src/index.ts",
"moduleParts": {
"index.production.js": "eda2-50"
"index.production.js": "dcf0-50"
},
"imported": [
{
"uid": "eda2-29"
"uid": "dcf0-29"
},
{
"uid": "eda2-31"
"uid": "dcf0-31"
},
{
"uid": "eda2-51"
"uid": "dcf0-51"
},
{
"uid": "eda2-52"
"uid": "dcf0-52"
},
{
"uid": "eda2-35"
"uid": "dcf0-35"
},
{
"uid": "eda2-37"
"uid": "dcf0-37"
},
{
"uid": "eda2-39"
"uid": "dcf0-39"
},
{
"uid": "eda2-53"
"uid": "dcf0-53"
},
{
"uid": "eda2-43"
"uid": "dcf0-43"
},
{
"uid": "eda2-47"
"uid": "dcf0-47"
},
{
"uid": "eda2-45"
"uid": "dcf0-45"
},
{
"uid": "eda2-33"
"uid": "dcf0-33"
}

@@ -391,3 +391,3 @@ ],

},
"eda2-51": {
"dcf0-51": {
"id": "/packages/router/src/frameworks.ts",

@@ -398,7 +398,7 @@ "moduleParts": {},

{
"uid": "eda2-49"
"uid": "dcf0-49"
}
]
},
"eda2-52": {
"dcf0-52": {
"id": "/packages/router/src/link.ts",

@@ -409,7 +409,7 @@ "moduleParts": {},

{
"uid": "eda2-49"
"uid": "dcf0-49"
}
]
},
"eda2-53": {
"dcf0-53": {
"id": "/packages/router/src/routeInfo.ts",

@@ -420,3 +420,3 @@ "moduleParts": {},

{
"uid": "eda2-49"
"uid": "dcf0-49"
}

@@ -423,0 +423,0 @@ ]

@@ -53,5 +53,5 @@ /**

type PickUnsafe<T, K> = K extends keyof T ? Pick<T, K> : never;
type PickExtra<T, K> = Expand<{
type PickExtra<T, K> = {
[TKey in keyof K as string extends TKey ? never : TKey extends keyof T ? never : TKey]: K[TKey];
}>;
};
type PickRequired<T> = {

@@ -93,8 +93,8 @@ [K in keyof T as undefined extends T[K] ? never : K]: T[K];

}
type AnyRouter = Router<any, any, any>;
type AnyRouter = Router<any, any>;
type RegisteredRouter = Register extends {
router: Router<infer TRoute, infer TRoutesInfo, infer TRouterContext>;
} ? Router<TRoute, TRoutesInfo, TRouterContext> : Router;
router: Router<infer TRoute, infer TRoutesInfo>;
} ? Router<TRoute, TRoutesInfo> : Router;
type RegisteredRoutesInfo = Register extends {
router: Router<infer TRoute, infer TRoutesInfo, infer TRouterContext>;
router: Router<infer TRoute, infer TRoutesInfo>;
} ? TRoutesInfo : AnyRoutesInfo;

@@ -121,3 +121,8 @@ interface LocationState {

type FilterRoutesFn = <TRoute extends AnyRoute>(routes: TRoute[]) => TRoute[];
interface RouterOptions<TRouteTree extends AnyRootRoute, TRouterContext> {
type RouterContextOptions<TRouteTree extends AnyRoute> = AnyContext extends TRouteTree['__types']['routerContext'] ? {
context?: TRouteTree['__types']['routerContext'];
} : {
context: TRouteTree['__types']['routerContext'];
};
interface RouterOptions<TRouteTree extends AnyRoute> {
history?: RouterHistory;

@@ -142,6 +147,6 @@ stringifySearch?: SearchSerializer;

}) => void;
context?: TRouterContext;
loadComponent?: (component: GetFrameworkGeneric<'Component'>) => Promise<GetFrameworkGeneric<'Component'>>;
onRouteChange?: () => void;
fetchServerDataFn?: FetchServerDataFn;
context?: TRouteTree['__types']['routerContext'];
}

@@ -156,9 +161,9 @@ type FetchServerDataFn = (ctx: {

}
interface RouterStore<TSearchObj extends AnySearchSchema = {}, TState extends LocationState = LocationState> {
interface RouterStore<TRoutesInfo extends AnyRoutesInfo = AnyRoutesInfo, TState extends LocationState = LocationState> {
status: 'idle' | 'pending';
latestLocation: ParsedLocation<TSearchObj, TState>;
currentMatches: RouteMatch[];
currentLocation: ParsedLocation<TSearchObj, TState>;
pendingMatches?: RouteMatch[];
pendingLocation?: ParsedLocation<TSearchObj, TState>;
latestLocation: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>;
currentMatches: RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>[];
currentLocation: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>;
pendingMatches?: RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>[];
pendingLocation?: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>;
lastUpdated: number;

@@ -198,5 +203,4 @@ }

}
interface DehydratedRouter<TRouterContext = unknown> {
interface DehydratedRouter {
state: DehydratedRouterState;
context: TRouterContext;
}

@@ -211,3 +215,3 @@ type MatchCache = Record<string, MatchCacheEntry>;

declare const defaultFetchServerDataFn: FetchServerDataFn;
declare class Router<TRouteTree extends AnyRoute = Route, TRoutesInfo extends AnyRoutesInfo = RoutesInfo<TRouteTree>, TRouterContext = unknown> {
declare class Router<TRouteTree extends AnyRoute = RootRoute, TRoutesInfo extends AnyRoutesInfo = RoutesInfo<TRouteTree>> {
#private;

@@ -218,6 +222,6 @@ types: {

};
options: PickAsRequired<RouterOptions<TRouteTree, TRouterContext>, 'stringifySearch' | 'parseSearch' | 'context'>;
options: PickAsRequired<Omit<RouterOptions<TRouteTree>, 'context'>, 'stringifySearch' | 'parseSearch'> & RouterContextOptions<TRouteTree>;
history: RouterHistory;
basepath: string;
routeTree: Route;
routeTree: RootRoute;
routesById: RoutesById<TRoutesInfo>;

@@ -227,19 +231,22 @@ navigateTimeout: undefined | Timeout;

navigationPromise: undefined | Promise<void>;
store: Store<RouterStore<TRoutesInfo['fullSearchSchema']>>;
store: Store<RouterStore<TRoutesInfo>>;
state: RouterStore<TRoutesInfo>;
startedLoadingAt: number;
resolveNavigation: () => void;
constructor(options?: RouterOptions<TRouteTree, TRouterContext>);
constructor(options?: RouterOptions<TRouteTree>);
reset: () => void;
mount: () => () => void;
update: <TRoute extends AnyRootRoute = AnyRootRoute, TRoutesInfo_1 extends AnyRoutesInfo = RoutesInfo<TRoute>, TRouterContext_1 = unknown>(opts?: RouterOptions<TRoute, TRouterContext_1> | undefined) => this;
update: (opts?: RouterOptions<TRouteTree>) => this;
buildNext: (opts: BuildNextOptions) => ParsedLocation<{}, LocationState>;
cancelMatches: () => void;
load: (next?: ParsedLocation) => Promise<void>;
load: (opts?: {
next?: ParsedLocation;
}) => Promise<void>;
getRoute: <TId extends keyof TRoutesInfo["routesById"]>(id: TId) => TRoutesInfo["routesById"][TId];
loadRoute: (navigateOpts?: BuildNextOptions) => Promise<RouteMatch[]>;
preloadRoute: (navigateOpts?: BuildNextOptions) => Promise<RouteMatch<DefaultRoutesInfo, AnyRoute>[]>;
preloadRoute: (navigateOpts?: BuildNextOptions) => Promise<AnyRouteMatch[]>;
matchRoutes: (pathname: string, opts?: {
strictParseParams?: boolean;
}) => RouteMatch<DefaultRoutesInfo, AnyRoute>[];
loadMatches: (resolvedMatches: RouteMatch[], loaderOpts?: {
}) => AnyRouteMatch[];
loadMatches: (resolvedMatches: RouteMatch[], opts?: {
preload?: boolean;

@@ -252,4 +259,4 @@ }) => Promise<void>;

buildLink: <TFrom extends ValidFromPath<TRoutesInfo> = "/", TTo extends string = ".">({ from, to, search, params, hash, target, replace, activeOptions, preload, preloadMaxAge: userPreloadMaxAge, preloadGcMaxAge: userPreloadGcMaxAge, preloadDelay: userPreloadDelay, disabled, }: LinkOptions<TRoutesInfo, TFrom, TTo>) => LinkInfo;
dehydrate: () => DehydratedRouter<TRouterContext>;
hydrate: (dehydratedRouter: DehydratedRouter<TRouterContext>) => void;
dehydrate: () => DehydratedRouter;
hydrate: (dehydratedRouter: DehydratedRouter) => void;
}

@@ -259,3 +266,3 @@

routeSearch: TRoute['__types']['searchSchema'];
search: Expand<TRoutesInfo['fullSearchSchema'] & TRoute['__types']['fullSearchSchema']>;
search: TRoutesInfo['fullSearchSchema'] & TRoute['__types']['fullSearchSchema'];
status: 'idle' | 'pending' | 'success' | 'error';

@@ -265,2 +272,4 @@ error?: unknown;

}
interface AnyRouteMatch extends RouteMatch<any, any> {
}
declare class RouteMatch<TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo, TRoute extends AnyRoute = AnyRoute> {

@@ -271,5 +280,8 @@ #private;

store: Store<RouteMatchStore<TRoutesInfo, TRoute>>;
state: RouteMatchStore<TRoutesInfo, TRoute>;
id: string;
pathname: string;
params: TRoute['__types']['allParams'];
routeContext: TRoute['__types']['routeContext'];
context: TRoute['__types']['context'];
component: GetFrameworkGeneric<'Component'>;

@@ -291,2 +303,5 @@ errorComponent: GetFrameworkGeneric<'ErrorComponent'>;

});
__init: (opts: {
parentMatch?: RouteMatch;
}) => void;
cancel: () => void;

@@ -299,4 +314,2 @@ load: (opts?: {

}) => Promise<void>;
__setParentMatch: (parentMatch?: RouteMatch) => void;
__validate: () => void;
}

@@ -309,2 +322,3 @@

type AnySearchSchema = {};
type AnyContext = {};
interface RouteMeta {

@@ -318,3 +332,5 @@ }

type RouteOptionsBaseIntersection<TCustomId, TPath> = UnionToIntersection<RouteOptionsBase<TCustomId, TPath>>;
type RouteOptions<TParentRoute extends AnyRoute = AnyRoute, TCustomId extends string = string, TPath extends string = string, TParentSearchSchema extends {} = {}, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = TSearchSchema, TParentParams extends AnyPathParams = {}, TParams extends Record<ParsePathParams<TPath>, unknown> = Record<ParsePathParams<TPath>, string>, TAllParams extends AnyPathParams = {}> = RouteOptionsBase<TCustomId, TPath> & {
interface FrameworkRouteOptions {
}
type RouteOptions<TParentRoute extends AnyRoute = AnyRoute, TCustomId extends string = string, TPath extends string = string, TParentSearchSchema extends {} = {}, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = TSearchSchema, TParentParams extends AnyPathParams = {}, TParams extends Record<ParsePathParams<TPath>, unknown> = Record<ParsePathParams<TPath>, string>, TAllParams extends AnyPathParams = {}, TParentContext extends AnyContext = AnyContext, TAllParentContext extends AnyContext = AnyContext, TRouteContext extends AnyContext = AnyContext, TContext extends AnyContext = TRouteContext> = RouteOptionsBase<TCustomId, TPath> & FrameworkRouteOptions & {
getParentRoute: () => TParentRoute;

@@ -332,3 +348,3 @@ caseSensitive?: boolean;

}) => Promise<void> | void;
onLoad?: OnLoadFn<TFullSearchSchema, TAllParams>;
onLoad?: OnLoadFn<TFullSearchSchema, TAllParams, TRouteContext, TContext>;
onLoadError?: (err: any) => void;

@@ -346,3 +362,12 @@ onLoaded?: (matchContext: {

}) => void;
meta?: RouteMeta;
getContext?: (opts: {
params: TAllParams;
search: TFullSearchSchema;
} & (TParentRoute extends undefined ? {
context?: TAllParentContext;
parentContext?: TParentContext;
} : {
context: TAllParentContext;
parentContext: TParentContext;
})) => TRouteContext;
} & ({

@@ -367,4 +392,4 @@ parseParams?: never;

};
type OnLoadFn<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}> = (loaderContext: LoaderContext<TFullSearchSchema, TAllParams>) => Promise<any> | void;
interface LoaderContext<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}> {
type OnLoadFn<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}, TContext extends AnyContext = AnyContext, TAllContext extends AnyContext = AnyContext> = (loaderContext: LoaderContext<TFullSearchSchema, TAllParams, TContext, TAllContext>) => Promise<any> | void;
interface LoaderContext<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}, TContext extends AnyContext = AnyContext, TAllContext extends AnyContext = AnyContext> {
params: TAllParams;

@@ -374,8 +399,10 @@ search: TFullSearchSchema;

preload: boolean;
routeContext: TContext;
context: TAllContext;
}
type UnloaderFn<TPath extends string> = (routeMatch: RouteMatch<any, Route>) => void;
type SearchFilter<T, U = T> = (prev: T) => U;
type ResolveId<TParentRoute, TCustomId extends string, TPath extends string> = TParentRoute extends Route<any> ? RootRouteId : TParentRoute extends {
type ResolveId<TParentRoute, TCustomId extends string, TPath extends string> = TParentRoute extends {
id: infer TParentId extends string;
} ? RoutePrefix<TParentId, string extends TCustomId ? TPath : TCustomId> : never;
} ? RoutePrefix<TParentId, string extends TCustomId ? TPath : TCustomId> : RootRouteId;
type InferFullSearchSchema<TRoute> = TRoute extends {

@@ -391,7 +418,7 @@ isRoot: true;

} ? TFullSearchSchema : {};
type ResolveFullSearchSchema<TParentRoute, TSearchSchema> = Expand<InferFullSearchSchema<TParentRoute> & TSearchSchema>;
interface AnyRoute extends Route<any, any, any, any, any, any, any, any, any, any, any> {
type ResolveFullSearchSchema<TParentRoute, TSearchSchema> = InferFullSearchSchema<TParentRoute> & TSearchSchema;
interface AnyRoute extends Route<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any> {
}
type RouteWithRoutesInfo<TRoute> = TRoute extends Route<infer TParentRoute, infer TPath, infer TFullPath, infer TCustomId, infer TId, infer TSearchSchema, infer TFullSearchSchema, infer TParams, infer TAllParams, infer TChildren> ? Route<any, any, any, any, any, any, any, any, any, TChildren, any> : never;
declare class Route<TParentRoute extends AnyRoute = AnyRoute, TPath extends string = string, TFullPath extends ResolveFullPath<TParentRoute, TPath> = ResolveFullPath<TParentRoute, TPath>, TCustomId extends string = string, TId extends ResolveId<TParentRoute, TCustomId, TPath> = ResolveId<TParentRoute, TCustomId, TPath>, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends Record<ParsePathParams<TPath>, unknown> = Record<ParsePathParams<TPath>, string>, TAllParams extends Expand<TParentRoute['__types']['allParams'] & TParams> = Expand<TParentRoute['__types']['allParams'] & TParams>, TChildren extends unknown = unknown, TRoutesInfo extends DefaultRoutesInfo = DefaultRoutesInfo> {
type MergeFromParent<T, U> = IsAny<T, U, T & U>;
declare class Route<TParentRoute extends AnyRoute = AnyRoute, TPath extends string = string, TFullPath extends ResolveFullPath<TParentRoute, TPath> = ResolveFullPath<TParentRoute, TPath>, TCustomId extends string = string, TId extends ResolveId<TParentRoute, TCustomId, TPath> = ResolveId<TParentRoute, TCustomId, TPath>, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends Record<ParsePathParams<TPath>, unknown> = Record<ParsePathParams<TPath>, string>, TAllParams extends MergeFromParent<TParentRoute['__types']['allParams'], TParams> = MergeFromParent<TParentRoute['__types']['allParams'], TParams>, TParentContext extends TParentRoute['__types']['routeContext'] = TParentRoute['__types']['routeContext'], TAllParentContext extends TParentRoute['__types']['context'] = TParentRoute['__types']['context'], TRouteContext extends AnyContext = AnyContext, TContext extends MergeFromParent<TParentRoute['__types']['context'], TRouteContext> = MergeFromParent<TParentRoute['__types']['context'], TRouteContext>, TRouterContext extends AnyContext = AnyContext, TChildren extends unknown = unknown, TRoutesInfo extends DefaultRoutesInfo = DefaultRoutesInfo> {
__types: {

@@ -401,2 +428,3 @@ parentRoute: TParentRoute;

fullPath: TFullPath;
customId: TCustomId;
id: TId;

@@ -407,7 +435,12 @@ searchSchema: TSearchSchema;

allParams: TAllParams;
parentContext: TParentContext;
allParentContext: TAllParentContext;
routeContext: TRouteContext;
context: TContext;
children: TChildren;
routesInfo: TRoutesInfo;
routerContext: TRouterContext;
};
isRoot: TParentRoute extends Route<any> ? true : false;
options: RouteOptions<TParentRoute, TCustomId, TPath, InferFullSearchSchema<TParentRoute>, TSearchSchema, Expand<InferFullSearchSchema<TParentRoute> & TSearchSchema>, TParentRoute['__types']['allParams'], TParams, TAllParams>;
options: RouteOptions<TParentRoute, TCustomId, TPath, InferFullSearchSchema<TParentRoute>, TSearchSchema, InferFullSearchSchema<TParentRoute> & TSearchSchema, TParentRoute['__types']['allParams'], TParams, TAllParams, TParentContext, TAllParentContext, TRouteContext, TContext>;
parentRoute: TParentRoute;

@@ -419,10 +452,14 @@ id: TId;

originalIndex?: number;
router?: Router<TRoutesInfo['routeTree'], TRoutesInfo, unknown>;
constructor(options: RouteOptions<TParentRoute, TCustomId, TPath, InferFullSearchSchema<TParentRoute>, TSearchSchema, TFullSearchSchema, TParentRoute['__types']['allParams'], TParams, TAllParams>);
init: () => void;
addChildren: <TNewChildren extends AnyRoute[]>(children: TNewChildren) => Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchSchema, TFullSearchSchema, TParams, TAllParams, TNewChildren, DefaultRoutesInfo>;
router?: Router<TRoutesInfo['routeTree'], TRoutesInfo>;
constructor(options: RouteOptions<TParentRoute, TCustomId, TPath, InferFullSearchSchema<TParentRoute>, TSearchSchema, TFullSearchSchema, TParentRoute['__types']['allParams'], TParams, TAllParams, TParentContext, TAllParentContext, TRouteContext, TContext>);
init: (opts: {
originalIndex: number;
router: AnyRouter;
}) => void;
addChildren: <TNewChildren extends AnyRoute[]>(children: TNewChildren) => Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchSchema, TFullSearchSchema, TParams, TAllParams, TParentContext, TAllParentContext, TRouteContext, TContext, TRouterContext, TNewChildren, TRoutesInfo>;
}
type AnyRootRoute = RootRoute<any>;
declare class RootRoute<TSearchSchema extends AnySearchSchema = {}> extends Route<any, '/', '/', string, RootRouteId, TSearchSchema, TSearchSchema, {}, {}> {
constructor(options?: Omit<RouteOptions<AnyRoute, RootRouteId, '', {}, TSearchSchema, NoInfer<TSearchSchema>, {}, {}, {}>, 'path' | 'id' | 'getParentRoute' | 'caseSensitive'>);
type AnyRootRoute = RootRoute<any, any, any>;
declare class RootRoute<TSearchSchema extends AnySearchSchema = {}, TContext extends AnyContext = AnyContext, TRouterContext extends AnyContext = AnyContext> extends Route<any, '/', '/', string, RootRouteId, TSearchSchema, TSearchSchema, {}, {}, TRouterContext, TRouterContext, TContext, MergeFromParent<TRouterContext, TContext>, TRouterContext> {
constructor(options?: Omit<RouteOptions<AnyRoute, RootRouteId, '', {}, TSearchSchema, NoInfer<TSearchSchema>, {}, TRouterContext, TRouterContext, TContext, NoInfer<TContext>>, 'path' | 'id' | 'getParentRoute' | 'caseSensitive'>);
static withRouterContext: <TRouterContext_1 extends AnyContext>() => <TSearchSchema_1 extends AnySearchSchema = {}, TContext_1 extends AnyContext = AnyContext>(options?: Omit<RouteOptions<AnyRoute, "__root__", "", {}, TSearchSchema_1, NoInfer<TSearchSchema_1>, {}, TRouterContext_1, TRouterContext_1, TContext_1, TRouterContext_1 & TContext_1, AnyContext, AnyContext>, "caseSensitive" | "id" | "path" | "getParentRoute"> | undefined) => RootRoute<TSearchSchema_1, TContext_1, TRouterContext_1>;
}

@@ -436,3 +473,4 @@ type ResolveFullPath<TParentRoute extends AnyRoute, TPath extends string, TPrefixed extends RoutePrefix<TParentRoute['fullPath'], TPath> = RoutePrefix<TParentRoute['fullPath'], TPath>> = TPrefixed extends RootRouteId ? '/' : TrimPathRight<`${TPrefixed}`>;

interface AnyRoutesInfo {
routeTree: AnyRoute;
routeTree: AnyRootRoute;
routeUnion: AnyRoute;
routesById: Record<string, AnyRoute>;

@@ -442,2 +480,3 @@ routesByFullPath: Record<string, AnyRoute>;

routePaths: any;
routeIntersection: AnyRoute;
fullSearchSchema: Record<string, any>;

@@ -447,3 +486,4 @@ allParams: Record<string, any>;

interface DefaultRoutesInfo {
routeTree: Route;
routeTree: RootRoute;
routeUnion: AnyRoute;
routesById: Record<string, Route>;

@@ -453,2 +493,3 @@ routesByFullPath: Record<string, Route>;

routePaths: string;
routeIntersection: AnyRoute;
fullSearchSchema: AnySearchSchema;

@@ -459,13 +500,13 @@ allParams: AnyPathParams;

}
interface RoutesInfoInner<TRouteTree extends AnyRoute, TRoutes extends AnyRoute = Route, TRoutesById = {
'/': TRoutes;
interface RoutesInfoInner<TRouteTree extends AnyRoute, TRouteUnion extends AnyRoute = Route, TRoutesById = {
'/': TRouteUnion;
} & {
[TRoute in TRoutes as TRoute['id']]: TRoute;
[TRoute in TRouteUnion as TRoute['id']]: TRoute;
}, TRoutesByFullPath = {
'/': TRoutes;
'/': TRouteUnion;
} & {
[TRoute in TRoutes as TRoute['fullPath'] extends RootRouteId ? never : string extends TRoute['fullPath'] ? never : TRoute['fullPath']]: TRoute;
[TRoute in TRouteUnion as TRoute['fullPath'] extends RootRouteId ? never : string extends TRoute['fullPath'] ? never : TRoute['fullPath']]: TRoute;
}> {
routeTree: TRouteTree;
routes: TRoutes;
routeUnion: TRouteUnion;
routesById: TRoutesById;

@@ -475,7 +516,28 @@ routesByFullPath: TRoutesByFullPath;

routePaths: keyof TRoutesByFullPath;
fullSearchSchema: Partial<UnionToIntersection<TRoutes['__types']['fullSearchSchema']>>;
allParams: Partial<UnionToIntersection<TRoutes['__types']['allParams']>>;
routeIntersection: Route<TRouteUnion['__types']['parentRoute'], // TParentRoute,
TRouteUnion['__types']['path'], // TPath,
TRouteUnion['__types']['fullPath'], // TFullPath,
TRouteUnion['__types']['customId'], // TCustomId,
TRouteUnion['__types']['id'], // TId,
// TId,
UnionToIntersection<TRouteUnion['__types']['searchSchema']> & {}, // TSearchSchema,
// TSearchSchema,
UnionToIntersection<TRouteUnion['__types']['fullSearchSchema']> & {}, // TFullSearchSchema,
UnionToIntersection<TRouteUnion['__types']['params']>, // TParams,
UnionToIntersection<TRouteUnion['__types']['allParams']>, // TAllParams,
UnionToIntersection<TRouteUnion['__types']['parentContext']>, // TParentContext,
UnionToIntersection<TRouteUnion['__types']['allParentContext']>, // TAllParentContext,
// TAllParentContext,
UnionToIntersection<TRouteUnion['__types']['routerContext']> & {}, // TContext,
// TContext,
UnionToIntersection<TRouteUnion['__types']['context']> & {}, // TAllContext,
// TAllContext,
UnionToIntersection<TRouteUnion['__types']['routerContext']> & {}, // TRouterContext,
TRouteUnion['__types']['children'], // TChildren,
TRouteUnion['__types']['routesInfo']>;
fullSearchSchema: Partial<UnionToIntersection<TRouteUnion['__types']['fullSearchSchema']>>;
allParams: Partial<UnionToIntersection<TRouteUnion['__types']['allParams']>>;
}
type ParseRoute<TRouteTree> = TRouteTree extends AnyRoute ? TRouteTree | ParseRouteChildren<TRouteTree> : never;
type ParseRouteChildren<TRouteTree> = TRouteTree extends Route<any, any, any, any, any, any, any, any, any, infer TChildren, any> ? unknown extends TChildren ? never : TChildren extends AnyRoute[] ? Values<{
type ParseRouteChildren<TRouteTree> = TRouteTree extends Route<any, any, any, any, any, any, any, any, any, any, any, any, any, any, infer TChildren, any> ? unknown extends TChildren ? never : TChildren extends AnyRoute[] ? Values<{
[TId in TChildren[number]['id']]: ParseRouteChild<TChildren[number], TId>;

@@ -529,3 +591,3 @@ }> : never : never;

} & CheckPath<TRoutesInfo, NoInfer<TResolvedTo>, {}> & SearchParamOptions<TRoutesInfo, TFrom, TResolvedTo> & PathParamOptions<TRoutesInfo, TFrom, TResolvedTo>;
type SearchParamOptions<TRoutesInfo extends AnyRoutesInfo, TFrom, TTo, TFromSchema = Expand<UnionToIntersection<TRoutesInfo['fullSearchSchema'] & RouteByPath<TRoutesInfo, TFrom> extends never ? {} : RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']>>, TToSchema = Partial<RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']> & Omit<RouteByPath<TRoutesInfo, TTo>['__types']['fullSearchSchema'], keyof PickRequired<RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']>>, TFromFullSchema = Expand<UnionToIntersection<TRoutesInfo['fullSearchSchema'] & TFromSchema>>, TToFullSchema = Expand<UnionToIntersection<TRoutesInfo['fullSearchSchema'] & TToSchema>>> = keyof PickRequired<TToSchema> extends never ? {
type SearchParamOptions<TRoutesInfo extends AnyRoutesInfo, TFrom, TTo, TFromSchema = UnionToIntersection<TRoutesInfo['fullSearchSchema'] & RouteByPath<TRoutesInfo, TFrom> extends never ? {} : RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']>, TToSchema = Partial<RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']> & Omit<RouteByPath<TRoutesInfo, TTo>['__types']['fullSearchSchema'], keyof PickRequired<RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']>>, TFromFullSchema = UnionToIntersection<TRoutesInfo['fullSearchSchema'] & TFromSchema>, TToFullSchema = UnionToIntersection<TRoutesInfo['fullSearchSchema'] & TToSchema>> = keyof PickRequired<TToSchema> extends never ? {
search?: true | SearchReducer<TFromFullSchema, TToFullSchema>;

@@ -538,3 +600,3 @@ } : {

} | ((current: TFrom) => TTo);
type PathParamOptions<TRoutesInfo extends AnyRoutesInfo, TFrom, TTo, TFromSchema = Expand<UnionToIntersection<RouteByPath<TRoutesInfo, TFrom> extends never ? {} : RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']>>, TToSchema = Partial<RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']> & Omit<RouteByPath<TRoutesInfo, TTo>['__types']['allParams'], keyof PickRequired<RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']>>, TFromFullParams = Expand<UnionToIntersection<TRoutesInfo['allParams'] & TFromSchema>>, TToFullParams = Expand<UnionToIntersection<TRoutesInfo['allParams'] & TToSchema>>> = keyof PickRequired<TToSchema> extends never ? {
type PathParamOptions<TRoutesInfo extends AnyRoutesInfo, TFrom, TTo, TFromSchema = UnionToIntersection<RouteByPath<TRoutesInfo, TFrom> extends never ? {} : RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']>, TToSchema = Partial<RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']> & Omit<RouteByPath<TRoutesInfo, TTo>['__types']['allParams'], keyof PickRequired<RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']>>, TFromFullParams = UnionToIntersection<TRoutesInfo['allParams'] & TFromSchema>, TToFullParams = UnionToIntersection<TRoutesInfo['allParams'] & TToSchema>> = keyof PickRequired<TToSchema> extends never ? {
params?: ParamsReducer<TFromFullParams, TToFullParams>;

@@ -565,11 +627,11 @@ } : {

type CheckPath<TRoutesInfo extends AnyRoutesInfo, TPath, TPass> = Exclude<TPath, TRoutesInfo['routePaths']> extends never ? TPass : CheckPathError<TRoutesInfo, Exclude<TPath, TRoutesInfo['routePaths']>>;
type CheckPathError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = Expand<{
type CheckPathError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = {
Error: `${TInvalids extends string ? TInvalids : never} is not a valid route path.`;
'Valid Route Paths': TRoutesInfo['routePaths'];
}>;
};
type CheckId<TRoutesInfo extends AnyRoutesInfo, TPath, TPass> = Exclude<TPath, TRoutesInfo['routeIds']> extends never ? TPass : CheckIdError<TRoutesInfo, Exclude<TPath, TRoutesInfo['routeIds']>>;
type CheckIdError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = Expand<{
type CheckIdError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = {
Error: `${TInvalids extends string ? TInvalids : never} is not a valid route ID.`;
'Valid Route IDs': TRoutesInfo['routeIds'];
}>;
};
type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string ? TTo extends string ? TTo extends '.' ? TFrom : TTo extends `./` ? Join<[TFrom, '/']> : TTo extends `./${infer TRest}` ? ResolveRelativePath<TFrom, TRest> : TTo extends `/${infer TRest}` ? TTo : Split<TTo> extends ['..', ...infer ToRest] ? Split<TFrom> extends [...infer FromRest, infer FromTail] ? ToRest extends ['/'] ? Join<[...FromRest, '/']> : ResolveRelativePath<Join<FromRest>, Join<ToRest>> : never : Split<TTo> extends ['.', ...infer ToRest] ? ToRest extends ['/'] ? Join<[TFrom, '/']> : ResolveRelativePath<TFrom, Join<ToRest>> : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>> : never : never;

@@ -601,2 +663,2 @@ type ValidFromPath<TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo> = undefined | (string extends TRoutesInfo['routePaths'] ? string : TRoutesInfo['routePaths']);

export { ActiveOptions, AnyLoaderData, AnyPathParams, AnyRootRoute, AnyRoute, AnyRouter, AnyRoutesInfo, AnySearchSchema, BuildNextOptions, CheckId, CheckIdError, CheckPath, CheckPathError, CheckRelativePath, DeepAwaited, DefaultRoutesInfo, DefinedPathParamWarning, DehydratedRouter, DehydratedRouterState, Expand, FilterRoutesFn, FrameworkGenerics, FromLocation, GetFrameworkGeneric, InferFullSearchSchema, IsAny, IsAnyBoolean, IsKnown, LinkInfo, LinkOptions, ListenerFn, LoaderContext, LoaderState, LocationState, MatchCache, MatchCacheEntry, MatchLocation, MatchRouteOptions, NavigateOptions, NoInfer, OnLoadFn, ParentParams, ParsePathParams, ParseRoute, ParseRouteChild, ParseRouteChildren, ParsedLocation, ParsedPath, PathParamMask, PathParamOptions, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, Register, RegisteredRouter, RegisteredRoutesInfo, RelativeToPathAutoComplete, ResolveFullSearchSchema, ResolveRelativePath, RootRoute, RootRouteId, Route, RouteById, RouteByPath, RouteMatch, RouteMatchStore, RouteMeta, RouteOptions, RouteOptionsBase, RouteOptionsBaseIntersection, RouteWithRoutesInfo, Router, RouterContext, RouterHistory, RouterLocation, RouterOptions, RouterStore, RoutesById, RoutesInfo, RoutesInfoInner, SearchFilter, SearchParamOptions, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, Timeout, ToIdOption, ToOptions, ToPathOption, UnionToIntersection, UnloaderFn, Updater, ValidFromPath, ValueKeys, Values, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultFetchServerDataFn, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, isPlainObject, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, pick, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning };
export { ActiveOptions, AnyContext, AnyLoaderData, AnyPathParams, AnyRootRoute, AnyRoute, AnyRouteMatch, AnyRouter, AnyRoutesInfo, AnySearchSchema, BuildNextOptions, CheckId, CheckIdError, CheckPath, CheckPathError, CheckRelativePath, DeepAwaited, DefaultRoutesInfo, DefinedPathParamWarning, DehydratedRouter, DehydratedRouterState, Expand, FilterRoutesFn, FrameworkGenerics, FrameworkRouteOptions, FromLocation, GetFrameworkGeneric, InferFullSearchSchema, IsAny, IsAnyBoolean, IsKnown, LinkInfo, LinkOptions, ListenerFn, LoaderContext, LoaderState, LocationState, MatchCache, MatchCacheEntry, MatchLocation, MatchRouteOptions, NavigateOptions, NoInfer, OnLoadFn, ParentParams, ParsePathParams, ParseRoute, ParseRouteChild, ParseRouteChildren, ParsedLocation, ParsedPath, PathParamMask, PathParamOptions, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, Register, RegisteredRouter, RegisteredRoutesInfo, RelativeToPathAutoComplete, ResolveFullSearchSchema, ResolveRelativePath, RootRoute, RootRouteId, Route, RouteById, RouteByPath, RouteMatch, RouteMatchStore, RouteMeta, RouteOptions, RouteOptionsBase, RouteOptionsBaseIntersection, Router, RouterContext, RouterHistory, RouterLocation, RouterOptions, RouterStore, RoutesById, RoutesInfo, RoutesInfoInner, SearchFilter, SearchParamOptions, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, Timeout, ToIdOption, ToOptions, ToPathOption, UnionToIntersection, UnloaderFn, Updater, ValidFromPath, ValueKeys, Values, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultFetchServerDataFn, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, isPlainObject, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, pick, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning };

@@ -485,3 +485,5 @@ /**

}
init = () => {
init = opts => {
this.originalIndex = opts.originalIndex;
this.router = opts.router;
const allOptions = this.options;

@@ -534,2 +536,5 @@ const isRoot = !allOptions?.path && !allOptions?.id;

}
static withRouterContext = () => {
return options => new RootRoute(options);
};
}

@@ -611,5 +616,5 @@

if (this.state === previous) return;
this.options?.onUpdate?.(this.state, previous);
this.queue.push(() => {
this.listeners.forEach(listener => listener(this.state, previous));
this.options?.onUpdate?.(this.state, previous);
});

@@ -649,4 +654,9 @@ this.#flush();

status: 'idle'
}, {
onUpdate: next => {
this.state = next;
}
})
});
this.state = this.store.state;
if (!this.#hasLoaders()) {

@@ -659,2 +669,56 @@ this.store.setState(s => ({

}
#hasLoaders = () => {
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
};
__init = opts => {
// Validate the search params and stabilize them
this.parentMatch = opts.parentMatch;
const parentSearch = this.parentMatch?.state.search ?? this.router.state.latestLocation.search;
try {
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
let nextSearch = validator?.(parentSearch) ?? {};
this.store.setState(s => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch
}
}));
componentTypes.map(async type => {
const component = this.route.options[type];
if (typeof this[type] !== 'function') {
this[type] = component;
}
});
const parent = this.parentMatch;
this.routeContext = this.route.options.getContext?.({
parentContext: parent?.routeContext,
context: parent?.context,
params: this.params,
search: this.state.search
}) || {};
this.context = parent ? {
...parent.context,
...this.routeContext
} : {
...this.router?.options.context,
...this.routeContext
};
} catch (err) {
console.error(err);
const error = new Error('Invalid search params found', {
cause: err
});
error.code = 'INVALID_SEARCH_PARAMS';
this.store.setState(s => ({
...s,
status: 'error',
error: error
}));
// Do not proceed with loading the route
return;
}
};
cancel = () => {

@@ -665,3 +729,3 @@ this.abortController?.abort();

// If the match is invalid, errored or idle, trigger it to load
if (this.store.state.status !== 'pending') {
if (this.state.status !== 'pending') {
await this.fetch(opts);

@@ -683,3 +747,3 @@ }

// as loading or resolved
if (this.store.state.status === 'idle') {
if (this.state.status === 'idle') {
this.store.setState(s => ({

@@ -706,5 +770,7 @@ ...s,

params: this.params,
search: this.store.state.search,
search: this.state.search,
signal: this.abortController.signal,
preload: !!opts?.preload
preload: !!opts?.preload,
routeContext: this.routeContext,
context: this.context
});

@@ -737,46 +803,2 @@ }

};
#hasLoaders = () => {
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
};
__setParentMatch = parentMatch => {
if (!this.parentMatch && parentMatch) {
this.parentMatch = parentMatch;
}
};
__validate = () => {
// Validate the search params and stabilize them
const parentSearch = this.parentMatch?.store.state.search ?? this.router.store.state.latestLocation.search;
try {
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
let nextSearch = validator?.(parentSearch) ?? {};
this.store.setState(s => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch
}
}));
componentTypes.map(async type => {
const component = this.route.options[type];
if (typeof this[type] !== 'function') {
this[type] = component;
}
});
} catch (err) {
console.error(err);
const error = new Error('Invalid search params found', {
cause: err
});
error.code = 'INVALID_SEARCH_PARAMS';
this.store.setState(s => ({
...s,
status: 'error',
error: error
}));
// Do not proceed with loading the route
return;
}
};
}

@@ -866,3 +888,8 @@

};
this.store = new Store(getInitialRouterState());
this.store = new Store(getInitialRouterState(), {
onUpdate: state => {
this.state = state;
}
});
this.state = this.store.state;
this.basepath = '';

@@ -881,3 +908,3 @@ this.update(options);

// If the router matches are empty, load the matches
if (!this.store.state.currentMatches.length) {
if (!this.state.currentMatches.length) {
this.load();

@@ -921,3 +948,5 @@ }

this.#unsubHistory = this.history.listen(() => {
this.load(this.#parseLocation(this.store.state.latestLocation));
this.load({
next: this.#parseLocation(this.state.latestLocation)
});
});

@@ -948,7 +977,7 @@ }

cancelMatches = () => {
[...this.store.state.currentMatches, ...(this.store.state.pendingMatches || [])].forEach(match => {
[...this.state.currentMatches, ...(this.state.pendingMatches || [])].forEach(match => {
match.cancel();
});
};
load = async next => {
load = async opts => {
let now = Date.now();

@@ -962,7 +991,7 @@ const startedAt = now;

this.store.batch(() => {
if (next) {
if (opts?.next) {
// Ingest the new location
this.store.setState(s => ({
...s,
latestLocation: next
latestLocation: opts.next
}));

@@ -972,3 +1001,3 @@ }

// Match the routes
matches = this.matchRoutes(this.store.state.latestLocation.pathname, {
matches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true

@@ -980,3 +1009,3 @@ });

pendingMatches: matches,
pendingLocation: this.store.state.latestLocation
pendingLocation: this.state.latestLocation
}));

@@ -987,3 +1016,5 @@ });

try {
await this.loadMatches(matches);
await this.loadMatches(matches
// opts
);
} catch (err) {

@@ -997,3 +1028,3 @@ console.warn(err);

}
const previousMatches = this.store.state.currentMatches;
const previousMatches = this.state.currentMatches;
const exiting = [],

@@ -1015,7 +1046,7 @@ staying = [];

params: d.params,
search: d.store.state.routeSearch
search: d.state.routeSearch
});
// Clear non-loading error states when match leaves
if (d.store.state.status === 'error') {
if (d.state.status === 'error') {
this.store.setState(s => ({

@@ -1031,3 +1062,3 @@ ...s,

params: d.params,
search: d.store.state.routeSearch
search: d.state.routeSearch
});

@@ -1038,11 +1069,9 @@ });

params: d.params,
search: d.store.state.search
search: d.state.search
});
// delete this.store.state.matchCache[d.id] // TODO:
});
this.store.setState(s => ({
...s,
status: 'idle',
currentLocation: this.store.state.latestLocation,
currentLocation: this.state.latestLocation,
currentMatches: matches,

@@ -1060,3 +1089,3 @@ pendingLocation: undefined,

};
loadRoute = async (navigateOpts = this.store.state.latestLocation) => {
loadRoute = async (navigateOpts = this.state.latestLocation) => {
const next = this.buildNext(navigateOpts);

@@ -1069,3 +1098,3 @@ const matches = this.matchRoutes(next.pathname, {

};
preloadRoute = async (navigateOpts = this.store.state.latestLocation) => {
preloadRoute = async (navigateOpts = this.state.latestLocation) => {
const next = this.buildNext(navigateOpts);

@@ -1085,3 +1114,3 @@ const matches = this.matchRoutes(next.pathname, {

}
const existingMatches = [...this.store.state.currentMatches, ...(this.store.state.pendingMatches ?? [])];
const existingMatches = [...this.state.currentMatches, ...(this.state.pendingMatches ?? [])];
const findInRouteTree = async routes => {

@@ -1132,5 +1161,3 @@ const parentMatch = last(matches);

const matchId = interpolatePath(foundRoute.id, params, true);
const match = existingMatches.find(d => d.id === matchId) ||
// this.store.state.matchCache[matchId]?.match || // TODO:
new RouteMatch(this, foundRoute, {
const match = existingMatches.find(d => d.id === matchId) || new RouteMatch(this, foundRoute, {
id: matchId,

@@ -1151,11 +1178,5 @@ params,

};
loadMatches = async (resolvedMatches, loaderOpts) => {
linkMatches(resolvedMatches);
loadMatches = async (resolvedMatches, opts) => {
initMatches(resolvedMatches);
// this.cleanMatchCache()
resolvedMatches.forEach(async match => {
// Validate the match (loads search params etc)
match.__validate();
});
// Check each match middleware to see if the route can be accessed

@@ -1169,3 +1190,3 @@ await Promise.all(resolvedMatches.map(async match => {

} catch (err) {
if (!loaderOpts?.preload) {
if (!opts?.preload) {
match.route.options.onLoadError?.(err);

@@ -1178,10 +1199,12 @@ }

const prevMatch = resolvedMatches[1];
const search = match.store.state.search;
if (search.__data?.matchId && search.__data.matchId !== match.id) {
return;
}
match.state.search;
// if (opts?.filter && !opts.filter(match)) {
// return
// }
match.load({
preload: loaderOpts?.preload
preload: opts?.preload
});
if (match.store.state.status !== 'success' && match.__loadPromise) {
if (match.state.status !== 'success' && match.__loadPromise) {
// Wait for the first sign of activity from the match

@@ -1243,6 +1266,6 @@ await match.__loadPromise;

if (opts?.pending) {
if (!this.store.state.pendingLocation) {
if (!this.state.pendingLocation) {
return false;
}
return matchPathname(this.basepath, this.store.state.pendingLocation.pathname, {
return matchPathname(this.basepath, this.state.pendingLocation.pathname, {
...opts,

@@ -1252,3 +1275,3 @@ to: next.pathname

}
return matchPathname(this.basepath, this.store.state.currentLocation.pathname, {
return matchPathname(this.basepath, this.state.currentLocation.pathname, {
...opts,

@@ -1299,7 +1322,7 @@ to: next.pathname

// Compare path/hash for matches
const pathIsEqual = this.store.state.currentLocation.pathname === next.pathname;
const currentPathSplit = this.store.state.currentLocation.pathname.split('/');
const pathIsEqual = this.state.currentLocation.pathname === next.pathname;
const currentPathSplit = this.state.currentLocation.pathname.split('/');
const nextPathSplit = next.pathname.split('/');
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
const hashIsEqual = this.store.state.currentLocation.hash === next.hash;
const hashIsEqual = this.state.currentLocation.hash === next.hash;
// Combine the matches based on user options

@@ -1367,11 +1390,10 @@ const pathTest = activeOptions?.exact ? pathIsEqual : pathIsFuzzyEqual;

state: {
...pick(this.store.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
currentMatches: this.store.state.currentMatches.map(match => ({
...pick(this.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
currentMatches: this.state.currentMatches.map(match => ({
id: match.id,
state: {
...pick(match.store.state, ['status'])
status: match.state.status
}
}))
},
context: this.options.context
}
};

@@ -1381,4 +1403,2 @@ };

this.store.setState(s => {
this.options.context = dehydratedRouter.context;
// Match the routes

@@ -1396,3 +1416,3 @@ const currentMatches = this.matchRoutes(dehydratedRouter.state.latestLocation.pathname, {

});
currentMatches.forEach(match => match.__validate());
initMatches(currentMatches);
return {

@@ -1408,5 +1428,6 @@ ...s,

routes.forEach((route, i) => {
route.init();
route.originalIndex = i;
route.router = this;
route.init({
originalIndex: i,
router: this
});
const existingRoute = this.routesById[route.id];

@@ -1449,5 +1470,5 @@ if (existingRoute) {

#buildLocation = (dest = {}) => {
const fromPathname = dest.fromCurrent ? this.store.state.latestLocation.pathname : dest.from ?? this.store.state.latestLocation.pathname;
const fromPathname = dest.fromCurrent ? this.state.latestLocation.pathname : dest.from ?? this.state.latestLocation.pathname;
let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? '.'}`);
const fromMatches = this.matchRoutes(this.store.state.latestLocation.pathname, {
const fromMatches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true

@@ -1468,3 +1489,3 @@ });

// Pre filters first
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.store.state.latestLocation.search) : this.store.state.latestLocation.search;
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.state.latestLocation.search) : this.state.latestLocation.search;

@@ -1479,5 +1500,5 @@ // Then the link/navigate function

const postFilteredSearch = dest.__postSearchFilters?.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
const search = replaceEqualDeep(this.store.state.latestLocation.search, postFilteredSearch);
const search = replaceEqualDeep(this.state.latestLocation.search, postFilteredSearch);
const searchStr = this.options.stringifySearch(search);
let hash = dest.hash === true ? this.store.state.latestLocation.hash : functionalUpdate(dest.hash, this.store.state.latestLocation.hash);
let hash = dest.hash === true ? this.state.latestLocation.hash : functionalUpdate(dest.hash, this.state.latestLocation.hash);
hash = hash ? `#${hash}` : '';

@@ -1488,3 +1509,3 @@ return {

searchStr,
state: this.store.state.latestLocation.state,
state: this.state.latestLocation.state,
hash,

@@ -1503,3 +1524,3 @@ href: `${pathname}${searchStr}${hash}`,

}
const isSameUrl = this.store.state.latestLocation.href === next.href;
const isSameUrl = this.state.latestLocation.href === next.href;
if (isSameUrl && !next.key) {

@@ -1514,3 +1535,3 @@ nextAction = 'replace';

// this.load(this.#parseLocation(this.store.state.latestLocation))
// this.load(this.#parseLocation(this.state.latestLocation))

@@ -1541,8 +1562,8 @@ return this.navigationPromise = new Promise(resolve => {

}
function linkMatches(matches) {
function initMatches(matches) {
matches.forEach((match, index) => {
const parent = matches[index - 1];
if (parent) {
match.__setParentMatch(parent);
}
const parentMatch = matches[index - 1];
match.__init({
parentMatch
});
});

@@ -1549,0 +1570,0 @@ }

@@ -11,3 +11,3 @@ /**

*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).RouterCore={})}(this,(function(t){"use strict";function e(t,e){if(!t)throw new Error("Invariant failed")}const s="popstate";function a(t){let e=t.getLocation(),s=()=>{},a=new Set;const o=()=>{e=t.getLocation(),a.forEach((t=>t()))};return{get location(){return e},listen:e=>(0===a.size&&(s=t.listener(o)),a.add(e),()=>{a.delete(e),0===a.size&&s()}),push:(e,s)=>{t.pushState(e,s),o()},replace:(e,s)=>{t.replaceState(e,s),o()},go:e=>{t.go(e),o()},back:()=>{t.back(),o()},forward:()=>{t.forward(),o()}}}function o(t){const e=t?.getHref??(()=>`${window.location.pathname}${window.location.hash}${window.location.search}`),o=t?.createHref??(t=>t);return a({getLocation:()=>i(e(),history.state),listener:t=>(window.addEventListener(s,t),()=>{window.removeEventListener(s,t)}),pushState:(t,e)=>{window.history.pushState({...e,key:n()},"",o(t))},replaceState:(t,e)=>{window.history.replaceState({...e,key:n()},"",o(t))},back:()=>window.history.back(),forward:()=>window.history.forward(),go:t=>window.history.go(t)})}function r(t={initialEntries:["/"]}){const e=t.initialEntries;let s=t.initialIndex??e.length-1,o={};return a({getLocation:()=>i(e[s],o),listener:()=>()=>{},pushState:(t,a)=>{o={...a,key:n()},e.push(t),s++},replaceState:(t,a)=>{o={...a,key:n()},e[s]=t},back:()=>{s--},forward:()=>{s=Math.min(s+1,e.length-1)},go:t=>window.history.go(t)})}function i(t,e){let s=t.indexOf("#"),a=t.indexOf("?");return{href:t,pathname:t.substring(0,s>0?a>0?Math.min(s,a):s:a>0?a:t.length),hash:s>-1?t.substring(s,a):"",search:a>-1?t.substring(a):"",state:e}}function n(){return(Math.random()+1).toString(36).substring(7)}function h(t){return t[t.length-1]}function c(t,e){return"function"==typeof t?t(e):t}function u(t,e){return e.reduce(((e,s)=>(e[s]=t[s],e)),{})}function l(t,e){if(t===e)return t;const s=e,a=Array.isArray(t)&&Array.isArray(s);if(a||p(t)&&p(s)){const e=a?t.length:Object.keys(t).length,o=a?s:Object.keys(s),r=o.length,i=a?[]:{};let n=0;for(let e=0;e<r;e++){const r=a?e:o[e];i[r]=l(t[r],s[r]),i[r]===t[r]&&n++}return e===r&&n===e?t:i}return s}function p(t){if(!d(t))return!1;const e=t.constructor;if(void 0===e)return!0;const s=e.prototype;return!!d(s)&&!!s.hasOwnProperty("isPrototypeOf")}function d(t){return"[object Object]"===Object.prototype.toString.call(t)}function f(t){return m(t.filter(Boolean).join("/"))}function m(t){return t.replace(/\/{2,}/g,"/")}function g(t){return"/"===t?t:t.replace(/^\/{1,}/,"")}function y(t){return"/"===t?t:t.replace(/\/{1,}$/,"")}function w(t){return y(g(t))}function v(t,e,s){e=e.replace(new RegExp(`^${t}`),"/"),s=s.replace(new RegExp(`^${t}`),"/");let a=b(e);const o=b(s);o.forEach(((t,e)=>{if("/"===t.value)e?e===o.length-1&&a.push(t):a=[t];else if(".."===t.value)a.length>1&&"/"===h(a)?.value&&a.pop(),a.pop();else{if("."===t.value)return;a.push(t)}}));return m(f([t,...a.map((t=>t.value))]))}function b(t){if(!t)return[];const e=[];if("/"===(t=m(t)).slice(0,1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),!t)return e;const s=t.split("/").filter(Boolean);return e.push(...s.map((t=>t.startsWith("*")?{type:"wildcard",value:t}:"$"===t.charAt(0)?{type:"param",value:t}:{type:"pathname",value:t}))),"/"===t.slice(-1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),e}function L(t,e,s){return f(b(t).map((t=>"*"!==t.value||s?"param"===t.type?e[t.value.substring(1)]??"":t.value:"")))}function S(t,e,s){const a=_(t,e,s);if(!s.to||a)return a??{}}function _(t,e,s){if(!e.startsWith(t))return;const a=b(e="/"!=t?e.substring(t.length):e),o=b(`${s.to??"*"}`),r={};return(()=>{for(let t=0;t<Math.max(a.length,o.length);t++){const e=a[t],i=o[t],n=t===o.length-1,h=t===a.length-1;if(i){if("wildcard"===i.type)return!!e?.value&&(r["*"]=f(a.slice(t).map((t=>t.value))),!0);if("pathname"===i.type){if("/"===i.value&&!e?.value)return!0;if(e)if(s.caseSensitive){if(i.value!==e.value)return!1}else if(i.value.toLowerCase()!==e.value.toLowerCase())return!1}if(!e)return!1;if("param"===i.type){if("/"===e?.value)return!1;"$"!==e.value.charAt(0)&&(r[i.value.substring(1)]=e.value)}}if(n&&!h)return!!s.fuzzy}return!0})()?r:void 0}function P(t,e){var s,a,o,r="";for(s in t)if(void 0!==(o=t[s]))if(Array.isArray(o))for(a=0;a<o.length;a++)r&&(r+="&"),r+=encodeURIComponent(s)+"="+encodeURIComponent(o[a]);else r&&(r+="&"),r+=encodeURIComponent(s)+"="+encodeURIComponent(o);return(e||"")+r}function E(t){if(!t)return"";var e=decodeURIComponent(t);return"false"!==e&&("true"===e||("0"===e.charAt(0)?e:0*+e==0?+e:e))}function R(t){for(var e,s,a={},o=t.split("&");e=o.shift();)void 0!==a[s=(e=e.split("=")).shift()]?a[s]=[].concat(a[s],E(e.shift())):a[s]=E(e.shift());return a}const M="__root__";class x{constructor(t){this.options=t||{},this.isRoot=!t?.getParentRoute}init=()=>{const t=this.options,s=!t?.path&&!t?.id,a=this.options?.getParentRoute?.();s?this.path=M:e(a);let o=s?M:t.path;o&&"/"!==o&&(o=w(o));const r=t?.id||o;let i=s?M:f([a.id===M?"":a.id,r]);o===M&&(o="/"),i!==M&&(i=f(["/",i]));const n=i===M?"/":y(f([a.fullPath,o]));this.path=o,this.id=i,this.fullPath=n};addChildren=t=>(this.children=t,this)}
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).RouterCore={})}(this,(function(t){"use strict";function e(t,e){if(!t)throw new Error("Invariant failed")}const s="popstate";function a(t){let e=t.getLocation(),s=()=>{},a=new Set;const o=()=>{e=t.getLocation(),a.forEach((t=>t()))};return{get location(){return e},listen:e=>(0===a.size&&(s=t.listener(o)),a.add(e),()=>{a.delete(e),0===a.size&&s()}),push:(e,s)=>{t.pushState(e,s),o()},replace:(e,s)=>{t.replaceState(e,s),o()},go:e=>{t.go(e),o()},back:()=>{t.back(),o()},forward:()=>{t.forward(),o()}}}function o(t){const e=t?.getHref??(()=>`${window.location.pathname}${window.location.hash}${window.location.search}`),o=t?.createHref??(t=>t);return a({getLocation:()=>i(e(),history.state),listener:t=>(window.addEventListener(s,t),()=>{window.removeEventListener(s,t)}),pushState:(t,e)=>{window.history.pushState({...e,key:n()},"",o(t))},replaceState:(t,e)=>{window.history.replaceState({...e,key:n()},"",o(t))},back:()=>window.history.back(),forward:()=>window.history.forward(),go:t=>window.history.go(t)})}function r(t={initialEntries:["/"]}){const e=t.initialEntries;let s=t.initialIndex??e.length-1,o={};return a({getLocation:()=>i(e[s],o),listener:()=>()=>{},pushState:(t,a)=>{o={...a,key:n()},e.push(t),s++},replaceState:(t,a)=>{o={...a,key:n()},e[s]=t},back:()=>{s--},forward:()=>{s=Math.min(s+1,e.length-1)},go:t=>window.history.go(t)})}function i(t,e){let s=t.indexOf("#"),a=t.indexOf("?");return{href:t,pathname:t.substring(0,s>0?a>0?Math.min(s,a):s:a>0?a:t.length),hash:s>-1?t.substring(s,a):"",search:a>-1?t.substring(a):"",state:e}}function n(){return(Math.random()+1).toString(36).substring(7)}function h(t){return t[t.length-1]}function c(t,e){return"function"==typeof t?t(e):t}function u(t,e){return e.reduce(((e,s)=>(e[s]=t[s],e)),{})}function l(t,e){if(t===e)return t;const s=e,a=Array.isArray(t)&&Array.isArray(s);if(a||p(t)&&p(s)){const e=a?t.length:Object.keys(t).length,o=a?s:Object.keys(s),r=o.length,i=a?[]:{};let n=0;for(let e=0;e<r;e++){const r=a?e:o[e];i[r]=l(t[r],s[r]),i[r]===t[r]&&n++}return e===r&&n===e?t:i}return s}function p(t){if(!d(t))return!1;const e=t.constructor;if(void 0===e)return!0;const s=e.prototype;return!!d(s)&&!!s.hasOwnProperty("isPrototypeOf")}function d(t){return"[object Object]"===Object.prototype.toString.call(t)}function f(t){return m(t.filter(Boolean).join("/"))}function m(t){return t.replace(/\/{2,}/g,"/")}function g(t){return"/"===t?t:t.replace(/^\/{1,}/,"")}function y(t){return"/"===t?t:t.replace(/\/{1,}$/,"")}function w(t){return y(g(t))}function v(t,e,s){e=e.replace(new RegExp(`^${t}`),"/"),s=s.replace(new RegExp(`^${t}`),"/");let a=b(e);const o=b(s);o.forEach(((t,e)=>{if("/"===t.value)e?e===o.length-1&&a.push(t):a=[t];else if(".."===t.value)a.length>1&&"/"===h(a)?.value&&a.pop(),a.pop();else{if("."===t.value)return;a.push(t)}}));return m(f([t,...a.map((t=>t.value))]))}function b(t){if(!t)return[];const e=[];if("/"===(t=m(t)).slice(0,1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),!t)return e;const s=t.split("/").filter(Boolean);return e.push(...s.map((t=>t.startsWith("*")?{type:"wildcard",value:t}:"$"===t.charAt(0)?{type:"param",value:t}:{type:"pathname",value:t}))),"/"===t.slice(-1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),e}function L(t,e,s){return f(b(t).map((t=>"*"!==t.value||s?"param"===t.type?e[t.value.substring(1)]??"":t.value:"")))}function S(t,e,s){const a=P(t,e,s);if(!s.to||a)return a??{}}function P(t,e,s){if(!e.startsWith(t))return;const a=b(e="/"!=t?e.substring(t.length):e),o=b(`${s.to??"*"}`),r={};return(()=>{for(let t=0;t<Math.max(a.length,o.length);t++){const e=a[t],i=o[t],n=t===o.length-1,h=t===a.length-1;if(i){if("wildcard"===i.type)return!!e?.value&&(r["*"]=f(a.slice(t).map((t=>t.value))),!0);if("pathname"===i.type){if("/"===i.value&&!e?.value)return!0;if(e)if(s.caseSensitive){if(i.value!==e.value)return!1}else if(i.value.toLowerCase()!==e.value.toLowerCase())return!1}if(!e)return!1;if("param"===i.type){if("/"===e?.value)return!1;"$"!==e.value.charAt(0)&&(r[i.value.substring(1)]=e.value)}}if(n&&!h)return!!s.fuzzy}return!0})()?r:void 0}function _(t,e){var s,a,o,r="";for(s in t)if(void 0!==(o=t[s]))if(Array.isArray(o))for(a=0;a<o.length;a++)r&&(r+="&"),r+=encodeURIComponent(s)+"="+encodeURIComponent(o[a]);else r&&(r+="&"),r+=encodeURIComponent(s)+"="+encodeURIComponent(o);return(e||"")+r}function x(t){if(!t)return"";var e=decodeURIComponent(t);return"false"!==e&&("true"===e||("0"===e.charAt(0)?e:0*+e==0?+e:e))}function E(t){for(var e,s,a={},o=t.split("&");e=o.shift();)void 0!==a[s=(e=e.split("=")).shift()]?a[s]=[].concat(a[s],x(e.shift())):a[s]=x(e.shift());return a}const R="__root__";class M{constructor(t){this.options=t||{},this.isRoot=!t?.getParentRoute}init=t=>{this.originalIndex=t.originalIndex,this.router=t.router;const s=this.options,a=!s?.path&&!s?.id,o=this.options?.getParentRoute?.();a?this.path=R:e(o);let r=a?R:s.path;r&&"/"!==r&&(r=w(r));const i=s?.id||r;let n=a?R:f([o.id===R?"":o.id,i]);r===R&&(r="/"),n!==R&&(n=f(["/",n]));const h=n===R?"/":y(f([o.fullPath,r]));this.path=r,this.id=n,this.fullPath=h};addChildren=t=>(this.children=t,this)}class C extends M{constructor(t){super(t)}static withRouterContext=()=>t=>new C(t)}
/**

@@ -22,4 +22,3 @@ * store

* @license MIT
*/
class ${listeners=new Set;batching=!1;queue=[];constructor(t,e){this.state=t,this.options=e}subscribe=t=>{this.listeners.add(t);const e=this.options?.onSubscribe?.(t,this);return()=>{this.listeners.delete(t),e?.()}};setState=t=>{const e=this.state;this.state=this.options?.updateFn?this.options.updateFn(e)(t):t(e),this.state!==e&&(this.queue.push((()=>{this.listeners.forEach((t=>t(this.state,e))),this.options?.onUpdate?.(this.state,e)})),this.#t())};#t=()=>{this.batching||(this.queue.forEach((t=>t())),this.queue=[])};batch=t=>{this.batching=!0,t(),this.batching=!1,this.#t()}}const A=["component","errorComponent","pendingComponent"];class C{abortController=new AbortController;onLoaderDataListeners=new Set;constructor(t,e,s){Object.assign(this,{route:e,router:t,id:s.id,pathname:s.pathname,params:s.params,store:new $({updatedAt:0,routeSearch:{},search:{},status:"idle"})}),this.#e()||this.store.setState((t=>({...t,status:"success"})))}cancel=()=>{this.abortController?.abort()};load=async t=>{"pending"!==this.store.state.status&&await this.fetch(t)};#s="";fetch=async t=>(this.__loadPromise=Promise.resolve().then((async()=>{const e=""+Date.now()+Math.random();this.#s=e;const s=()=>e!==this.#s?this.__loadPromise:void 0;let a;this.store.batch((()=>{"idle"===this.store.state.status&&this.store.setState((t=>({...t,status:"pending"})))}));const o=(async()=>{await Promise.all(A.map((async t=>{const e=this.route.options[t];this[t]?.preload&&(this[t]=await this.router.options.loadComponent(e))})))})(),r=Promise.resolve().then((()=>{if(this.route.options.onLoad)return this.route.options.onLoad({params:this.params,search:this.store.state.search,signal:this.abortController.signal,preload:!!t?.preload})}));try{if(await o,await r,a=s())return await a;this.store.setState((t=>({...t,error:void 0,status:"success",updatedAt:Date.now()})))}catch(t){this.store.setState((e=>({...e,error:t,status:"error",updatedAt:Date.now()})))}finally{delete this.__loadPromise}})),this.__loadPromise);#e=()=>!(!this.route.options.onLoad&&!A.some((t=>this.route.options[t]?.preload)));__setParentMatch=t=>{!this.parentMatch&&t&&(this.parentMatch=t)};__validate=()=>{const t=this.parentMatch?.store.state.search??this.router.store.state.latestLocation.search;try{let e=("object"==typeof this.route.options.validateSearch?this.route.options.validateSearch.parse:this.route.options.validateSearch)?.(t)??{};this.store.setState((s=>({...s,routeSearch:e,search:{...t,...e}}))),A.map((async t=>{const e=this.route.options[t];"function"!=typeof this[t]&&(this[t]=e)}))}catch(t){console.error(t);const e=new Error("Invalid search params found",{cause:t});return e.code="INVALID_SEARCH_PARAMS",void this.store.setState((t=>({...t,status:"error",error:e})))}}}const F=k(JSON.parse),I=T(JSON.stringify);function k(t){return e=>{"?"===e.substring(0,1)&&(e=e.substring(1));let s=R(e);for(let e in s){const a=s[e];if("string"==typeof a)try{s[e]=t(a)}catch(t){}}return s}}function T(t){return e=>{(e={...e})&&Object.keys(e).forEach((s=>{const a=e[s];if(void 0===a||void 0===a)delete e[s];else if(a&&"object"==typeof a&&null!==a)try{e[s]=t(a)}catch(t){}}));const s=P(e).toString();return s?`?${s}`:""}}const j=async({router:t,routeMatch:e})=>{const s=t.buildNext({to:".",search:t=>({...t??{},__data:{matchId:e.id}})}),a=await fetch(s.href,{method:"GET",signal:e.abortController.signal});if(a.ok)return a.json();throw new Error("Failed to fetch match data")};const D="undefined"==typeof window||!window.document.createElement;function O(){return{status:"idle",latestLocation:null,currentLocation:null,currentMatches:[],lastUpdated:Date.now()}}t.RootRoute=class extends x{constructor(t){super(t)}},t.Route=x,t.RouteMatch=C,t.Router=class{#a;startedLoadingAt=Date.now();resolveNavigation=()=>{};constructor(t){this.options={defaultPreloadDelay:50,context:void 0,...t,stringifySearch:t?.stringifySearch??I,parseSearch:t?.parseSearch??F,fetchServerDataFn:t?.fetchServerDataFn??j},this.store=new $(O()),this.basepath="",this.update(t),this.options.Router?.(this)}reset=()=>{this.store.setState((t=>Object.assign(t,O())))};mount=()=>{if(!D){this.store.state.currentMatches.length||this.load();const t="visibilitychange",e="focus";return window.addEventListener&&(window.addEventListener(t,this.#o,!1),window.addEventListener(e,this.#o,!1)),()=>{window.removeEventListener&&(window.removeEventListener(t,this.#o),window.removeEventListener(e,this.#o))}}return()=>{}};update=t=>{if(Object.assign(this.options,t),!this.history||this.options.history&&this.options.history!==this.history){this.#a&&this.#a(),this.history=this.options.history??(D?r():o());const t=this.#r();this.store.setState((e=>({...e,latestLocation:t,currentLocation:t}))),this.#a=this.history.listen((()=>{this.load(this.#r(this.store.state.latestLocation))}))}const{basepath:e,routeTree:s}=this.options;return this.basepath=`/${w(e??"")??""}`,s&&(this.routesById={},this.routeTree=this.#i(s)),this};buildNext=t=>{const e=this.#n(t),s=this.matchRoutes(e.pathname),a=s.map((t=>t.route.options.preSearchFilters??[])).flat().filter(Boolean),o=s.map((t=>t.route.options.postSearchFilters??[])).flat().filter(Boolean);return this.#n({...t,__preSearchFilters:a,__postSearchFilters:o})};cancelMatches=()=>{[...this.store.state.currentMatches,...this.store.state.pendingMatches||[]].forEach((t=>{t.cancel()}))};load=async t=>{let s=Date.now();const a=s;let o;this.startedLoadingAt=a,this.cancelMatches(),this.store.batch((()=>{t&&this.store.setState((e=>({...e,latestLocation:t}))),o=this.matchRoutes(this.store.state.latestLocation.pathname,{strictParseParams:!0}),this.store.setState((t=>({...t,status:"pending",pendingMatches:o,pendingLocation:this.store.state.latestLocation})))}));try{await this.loadMatches(o)}catch(t){console.warn(t),e(!1)}if(this.startedLoadingAt!==a)return this.navigationPromise;const r=this.store.state.currentMatches,i=[],n=[];r.forEach((t=>{o.find((e=>e.id===t.id))?n.push(t):i.push(t)}));const h=o.filter((t=>!r.find((e=>e.id===t.id))));s=Date.now(),i.forEach((t=>{t.__onExit?.({params:t.params,search:t.store.state.routeSearch}),"error"===t.store.state.status&&this.store.setState((t=>({...t,status:"idle",error:void 0})))})),n.forEach((t=>{t.route.options.onTransition?.({params:t.params,search:t.store.state.routeSearch})})),h.forEach((t=>{t.__onExit=t.route.options.onLoaded?.({params:t.params,search:t.store.state.search})})),this.store.setState((t=>({...t,status:"idle",currentLocation:this.store.state.latestLocation,currentMatches:o,pendingLocation:void 0,pendingMatches:void 0}))),this.options.onRouteChange?.(),this.resolveNavigation()};getRoute=t=>{const s=this.routesById[t];return e(s),s};loadRoute=async(t=this.store.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s),s};preloadRoute=async(t=this.store.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s,{preload:!0}),s};matchRoutes=(t,e)=>{const s=[];if(!this.routeTree)return s;const a=[...this.store.state.currentMatches,...this.store.state.pendingMatches??[]],o=async r=>{let i=h(s)?.params??{};const n=this.options.filterRoutes?.(r)??r;let c=[];const u=(s,a)=>(a.some((a=>{const o=a.children;if(!a.path&&o?.length)return u([...c,a],o);const r=!("/"===a.path&&!o?.length),n=S(this.basepath,t,{to:a.fullPath,fuzzy:r,caseSensitive:a.options.caseSensitive??this.options.caseSensitive});if(n){let t;try{t=a.options.parseParams?.(n)??n}catch(t){if(e?.strictParseParams)throw t}i={...i,...t}}return n&&(c=[...s,a]),!!c.length})),!!c.length);if(u([],n),!c.length)return;c.forEach((t=>{const e=L(t.path,i),o=L(t.id,i,!0),r=a.find((t=>t.id===o))||new C(this,t,{id:o,params:i,pathname:f([this.basepath,e])});s.push(r)}));const l=h(c).children;l?.length&&o(l)};return o([this.routeTree]),s};loadMatches=async(t,e)=>{var s;(s=t).forEach(((t,e)=>{const a=s[e-1];a&&t.__setParentMatch(a)})),t.forEach((async t=>{t.__validate()})),await Promise.all(t.map((async t=>{try{await(t.route.options.beforeLoad?.({router:this,match:t}))}catch(s){throw e?.preload||t.route.options.onLoadError?.(s),s}})));const a=t.map((async(s,a)=>{const o=t[1],r=s.store.state.search;r.__data?.matchId&&r.__data.matchId!==s.id||(s.load({preload:e?.preload}),"success"!==s.store.state.status&&s.__loadPromise&&await s.__loadPromise,o&&await o.__loadPromise)}));await Promise.all(a)};reload=()=>{this.navigate({fromCurrent:!0,replace:!0,search:!0})};resolvePath=(t,e)=>v(this.basepath,t,m(e));navigate=async({from:t,to:s=".",search:a,hash:o,replace:r,params:i})=>{const n=String(s),h=void 0===t?t:String(t);let c;try{new URL(`${n}`),c=!0}catch(t){}return e(!c),this.#h({from:h,to:n,search:a,hash:o,replace:r,params:i})};matchRoute=(t,e)=>{t={...t,to:t.to?this.resolvePath(t.from??"",t.to):void 0};const s=this.buildNext(t);return e?.pending?!!this.store.state.pendingLocation&&S(this.basepath,this.store.state.pendingLocation.pathname,{...e,to:s.pathname}):S(this.basepath,this.store.state.currentLocation.pathname,{...e,to:s.pathname})};buildLink=({from:t,to:e=".",search:s,params:a,hash:o,target:r,replace:i,activeOptions:n,preload:h,preloadMaxAge:c,preloadGcMaxAge:u,preloadDelay:l,disabled:p})=>{try{return new URL(`${e}`),{type:"external",href:e}}catch(t){}const d={from:t,to:e,search:s,params:a,hash:o,replace:i},f=this.buildNext(d);h=h??this.options.defaultPreload;const m=l??this.options.defaultPreloadDelay??0,g=this.store.state.currentLocation.pathname===f.pathname,y=this.store.state.currentLocation.pathname.split("/"),w=f.pathname.split("/").every(((t,e)=>t===y[e])),v=this.store.state.currentLocation.hash===f.hash;return{type:"internal",next:f,handleFocus:t=>{h&&this.preloadRoute(d).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))},handleClick:t=>{p||function(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}(t)||t.defaultPrevented||r&&"_self"!==r||0!==t.button||(t.preventDefault(),this.#h(d))},handleEnter:t=>{const e=t.target||{};if(h){if(e.preloadTimeout)return;e.preloadTimeout=setTimeout((()=>{e.preloadTimeout=null,this.preloadRoute(d).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))}),m)}},handleLeave:t=>{const e=t.target||{};e.preloadTimeout&&(clearTimeout(e.preloadTimeout),e.preloadTimeout=null)},isActive:(n?.exact?g:w)&&(!n?.includeHash||v),disabled:p}};dehydrate=()=>({state:{...u(this.store.state,["latestLocation","currentLocation","status","lastUpdated"]),currentMatches:this.store.state.currentMatches.map((t=>({id:t.id,state:{...u(t.store.state,["status"])}})))},context:this.options.context});hydrate=t=>{this.store.setState((s=>{this.options.context=t.context;const a=this.matchRoutes(t.state.latestLocation.pathname,{strictParseParams:!0});return a.forEach(((s,a)=>{const o=t.state.currentMatches[a];e(o&&o.id===s.id),s.store.setState((t=>({...t,...o.state})))})),a.forEach((t=>t.__validate())),{...s,...t.state,currentMatches:a}}))};#i=t=>{const e=t=>{t.forEach(((t,s)=>{t.init(),t.originalIndex=s,t.router=this;if(this.routesById[t.id])throw new Error;this.routesById[t.id]=t;const a=t.children;a?.length&&e(a)}))};return e([t]),t};#r=t=>{let{pathname:e,search:s,hash:a,state:o}=this.history.location;const r=this.options.parseSearch(s);return{pathname:e,searchStr:s,search:l(t?.search,r),hash:a.split("#").reverse()[0]??"",href:`${e}${s}${a}`,state:o,key:o?.key||"__init__"}};#o=()=>{this.load()};#n=(t={})=>{const e=t.fromCurrent?this.store.state.latestLocation.pathname:t.from??this.store.state.latestLocation.pathname;let s=v(this.basepath??"/",e,`${t.to??"."}`);const a=this.matchRoutes(this.store.state.latestLocation.pathname,{strictParseParams:!0}),o=this.matchRoutes(s),r={...h(a)?.params};let i=!0===(t.params??!0)?r:c(t.params,r);i&&o.map((t=>t.route.options.stringifyParams)).filter(Boolean).forEach((t=>{Object.assign({},i,t(i))})),s=L(s,i??{});const n=t.__preSearchFilters?.length?t.__preSearchFilters?.reduce(((t,e)=>e(t)),this.store.state.latestLocation.search):this.store.state.latestLocation.search,u=!0===t.search?n:t.search?c(t.search,n)??{}:t.__preSearchFilters?.length?n:{},p=t.__postSearchFilters?.length?t.__postSearchFilters.reduce(((t,e)=>e(t)),u):u,d=l(this.store.state.latestLocation.search,p),f=this.options.stringifySearch(d);let m=!0===t.hash?this.store.state.latestLocation.hash:c(t.hash,this.store.state.latestLocation.hash);return m=m?`#${m}`:"",{pathname:s,search:d,searchStr:f,state:this.store.state.latestLocation.state,hash:m,href:`${s}${f}${m}`,key:t.key}};#h=t=>{const e=this.buildNext(t),s=""+Date.now()+Math.random();this.navigateTimeout&&clearTimeout(this.navigateTimeout);let a="replace";t.replace||(a="push");this.store.state.latestLocation.href===e.href&&!e.key&&(a="replace");const o=`${e.pathname}${e.searchStr}${e.hash?`#${e.hash}`:""}`;return this.history["push"===a?"push":"replace"](o,{id:s,...e.state}),this.navigationPromise=new Promise((t=>{const e=this.resolveNavigation;this.resolveNavigation=()=>{e(),t()}}))}},t.cleanPath=m,t.createBrowserHistory=o,t.createHashHistory=function(){return o({getHref:()=>window.location.hash.substring(1),createHref:t=>`#${t}`})},t.createMemoryHistory=r,t.decode=R,t.defaultFetchServerDataFn=j,t.defaultParseSearch=F,t.defaultStringifySearch=I,t.encode=P,t.functionalUpdate=c,t.interpolatePath=L,t.invariant=e,t.isPlainObject=p,t.joinPaths=f,t.last=h,t.matchByPath=_,t.matchPathname=S,t.parsePathname=b,t.parseSearchWith=k,t.pick=u,t.replaceEqualDeep=l,t.resolvePath=v,t.rootRouteId=M,t.stringifySearchWith=T,t.trimPath=w,t.trimPathLeft=g,t.trimPathRight=y,t.warning=function(t,e){if(t){"undefined"!=typeof console&&console.warn(e);try{throw new Error(e)}catch{}}return!0},Object.defineProperty(t,"__esModule",{value:!0})}));
*/class ${listeners=new Set;batching=!1;queue=[];constructor(t,e){this.state=t,this.options=e}subscribe=t=>{this.listeners.add(t);const e=this.options?.onSubscribe?.(t,this);return()=>{this.listeners.delete(t),e?.()}};setState=t=>{const e=this.state;this.state=this.options?.updateFn?this.options.updateFn(e)(t):t(e),this.state!==e&&(this.options?.onUpdate?.(this.state,e),this.queue.push((()=>{this.listeners.forEach((t=>t(this.state,e)))})),this.#t())};#t=()=>{this.batching||(this.queue.forEach((t=>t())),this.queue=[])};batch=t=>{this.batching=!0,t(),this.batching=!1,this.#t()}}const A=["component","errorComponent","pendingComponent"];class F{abortController=new AbortController;onLoaderDataListeners=new Set;constructor(t,e,s){Object.assign(this,{route:e,router:t,id:s.id,pathname:s.pathname,params:s.params,store:new $({updatedAt:0,routeSearch:{},search:{},status:"idle"},{onUpdate:t=>{this.state=t}})}),this.state=this.store.state,this.#e()||this.store.setState((t=>({...t,status:"success"})))}#e=()=>!(!this.route.options.onLoad&&!A.some((t=>this.route.options[t]?.preload)));__init=t=>{this.parentMatch=t.parentMatch;const e=this.parentMatch?.state.search??this.router.state.latestLocation.search;try{let t=("object"==typeof this.route.options.validateSearch?this.route.options.validateSearch.parse:this.route.options.validateSearch)?.(e)??{};this.store.setState((s=>({...s,routeSearch:t,search:{...e,...t}}))),A.map((async t=>{const e=this.route.options[t];"function"!=typeof this[t]&&(this[t]=e)}));const s=this.parentMatch;this.routeContext=this.route.options.getContext?.({parentContext:s?.routeContext,context:s?.context,params:this.params,search:this.state.search})||{},this.context=s?{...s.context,...this.routeContext}:{...this.router?.options.context,...this.routeContext}}catch(t){console.error(t);const e=new Error("Invalid search params found",{cause:t});return e.code="INVALID_SEARCH_PARAMS",void this.store.setState((t=>({...t,status:"error",error:e})))}};cancel=()=>{this.abortController?.abort()};load=async t=>{"pending"!==this.state.status&&await this.fetch(t)};#s="";fetch=async t=>(this.__loadPromise=Promise.resolve().then((async()=>{const e=""+Date.now()+Math.random();this.#s=e;const s=()=>e!==this.#s?this.__loadPromise:void 0;let a;this.store.batch((()=>{"idle"===this.state.status&&this.store.setState((t=>({...t,status:"pending"})))}));const o=(async()=>{await Promise.all(A.map((async t=>{const e=this.route.options[t];this[t]?.preload&&(this[t]=await this.router.options.loadComponent(e))})))})(),r=Promise.resolve().then((()=>{if(this.route.options.onLoad)return this.route.options.onLoad({params:this.params,search:this.state.search,signal:this.abortController.signal,preload:!!t?.preload,routeContext:this.routeContext,context:this.context})}));try{if(await o,await r,a=s())return await a;this.store.setState((t=>({...t,error:void 0,status:"success",updatedAt:Date.now()})))}catch(t){this.store.setState((e=>({...e,error:t,status:"error",updatedAt:Date.now()})))}finally{delete this.__loadPromise}})),this.__loadPromise)}const I=T(JSON.parse),k=j(JSON.stringify);function T(t){return e=>{"?"===e.substring(0,1)&&(e=e.substring(1));let s=E(e);for(let e in s){const a=s[e];if("string"==typeof a)try{s[e]=t(a)}catch(t){}}return s}}function j(t){return e=>{(e={...e})&&Object.keys(e).forEach((s=>{const a=e[s];if(void 0===a||void 0===a)delete e[s];else if(a&&"object"==typeof a&&null!==a)try{e[s]=t(a)}catch(t){}}));const s=_(e).toString();return s?`?${s}`:""}}const D=async({router:t,routeMatch:e})=>{const s=t.buildNext({to:".",search:t=>({...t??{},__data:{matchId:e.id}})}),a=await fetch(s.href,{method:"GET",signal:e.abortController.signal});if(a.ok)return a.json();throw new Error("Failed to fetch match data")};const O="undefined"==typeof window||!window.document.createElement;function H(){return{status:"idle",latestLocation:null,currentLocation:null,currentMatches:[],lastUpdated:Date.now()}}function N(t){t.forEach(((e,s)=>{const a=t[s-1];e.__init({parentMatch:a})}))}t.RootRoute=C,t.Route=M,t.RouteMatch=F,t.Router=class{#a;startedLoadingAt=Date.now();resolveNavigation=()=>{};constructor(t){this.options={defaultPreloadDelay:50,context:void 0,...t,stringifySearch:t?.stringifySearch??k,parseSearch:t?.parseSearch??I,fetchServerDataFn:t?.fetchServerDataFn??D},this.store=new $(H(),{onUpdate:t=>{this.state=t}}),this.state=this.store.state,this.basepath="",this.update(t),this.options.Router?.(this)}reset=()=>{this.store.setState((t=>Object.assign(t,H())))};mount=()=>{if(!O){this.state.currentMatches.length||this.load();const t="visibilitychange",e="focus";return window.addEventListener&&(window.addEventListener(t,this.#o,!1),window.addEventListener(e,this.#o,!1)),()=>{window.removeEventListener&&(window.removeEventListener(t,this.#o),window.removeEventListener(e,this.#o))}}return()=>{}};update=t=>{if(Object.assign(this.options,t),!this.history||this.options.history&&this.options.history!==this.history){this.#a&&this.#a(),this.history=this.options.history??(O?r():o());const t=this.#r();this.store.setState((e=>({...e,latestLocation:t,currentLocation:t}))),this.#a=this.history.listen((()=>{this.load({next:this.#r(this.state.latestLocation)})}))}const{basepath:e,routeTree:s}=this.options;return this.basepath=`/${w(e??"")??""}`,s&&(this.routesById={},this.routeTree=this.#i(s)),this};buildNext=t=>{const e=this.#n(t),s=this.matchRoutes(e.pathname),a=s.map((t=>t.route.options.preSearchFilters??[])).flat().filter(Boolean),o=s.map((t=>t.route.options.postSearchFilters??[])).flat().filter(Boolean);return this.#n({...t,__preSearchFilters:a,__postSearchFilters:o})};cancelMatches=()=>{[...this.state.currentMatches,...this.state.pendingMatches||[]].forEach((t=>{t.cancel()}))};load=async t=>{let s=Date.now();const a=s;let o;this.startedLoadingAt=a,this.cancelMatches(),this.store.batch((()=>{t?.next&&this.store.setState((e=>({...e,latestLocation:t.next}))),o=this.matchRoutes(this.state.latestLocation.pathname,{strictParseParams:!0}),this.store.setState((t=>({...t,status:"pending",pendingMatches:o,pendingLocation:this.state.latestLocation})))}));try{await this.loadMatches(o)}catch(t){console.warn(t),e(!1)}if(this.startedLoadingAt!==a)return this.navigationPromise;const r=this.state.currentMatches,i=[],n=[];r.forEach((t=>{o.find((e=>e.id===t.id))?n.push(t):i.push(t)}));const h=o.filter((t=>!r.find((e=>e.id===t.id))));s=Date.now(),i.forEach((t=>{t.__onExit?.({params:t.params,search:t.state.routeSearch}),"error"===t.state.status&&this.store.setState((t=>({...t,status:"idle",error:void 0})))})),n.forEach((t=>{t.route.options.onTransition?.({params:t.params,search:t.state.routeSearch})})),h.forEach((t=>{t.__onExit=t.route.options.onLoaded?.({params:t.params,search:t.state.search})})),this.store.setState((t=>({...t,status:"idle",currentLocation:this.state.latestLocation,currentMatches:o,pendingLocation:void 0,pendingMatches:void 0}))),this.options.onRouteChange?.(),this.resolveNavigation()};getRoute=t=>{const s=this.routesById[t];return e(s),s};loadRoute=async(t=this.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s),s};preloadRoute=async(t=this.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s,{preload:!0}),s};matchRoutes=(t,e)=>{const s=[];if(!this.routeTree)return s;const a=[...this.state.currentMatches,...this.state.pendingMatches??[]],o=async r=>{let i=h(s)?.params??{};const n=this.options.filterRoutes?.(r)??r;let c=[];const u=(s,a)=>(a.some((a=>{const o=a.children;if(!a.path&&o?.length)return u([...c,a],o);const r=!("/"===a.path&&!o?.length),n=S(this.basepath,t,{to:a.fullPath,fuzzy:r,caseSensitive:a.options.caseSensitive??this.options.caseSensitive});if(n){let t;try{t=a.options.parseParams?.(n)??n}catch(t){if(e?.strictParseParams)throw t}i={...i,...t}}return n&&(c=[...s,a]),!!c.length})),!!c.length);if(u([],n),!c.length)return;c.forEach((t=>{const e=L(t.path,i),o=L(t.id,i,!0),r=a.find((t=>t.id===o))||new F(this,t,{id:o,params:i,pathname:f([this.basepath,e])});s.push(r)}));const l=h(c).children;l?.length&&o(l)};return o([this.routeTree]),s};loadMatches=async(t,e)=>{N(t),await Promise.all(t.map((async t=>{try{await(t.route.options.beforeLoad?.({router:this,match:t}))}catch(s){throw e?.preload||t.route.options.onLoadError?.(s),s}})));const s=t.map((async(s,a)=>{const o=t[1];s.state.search,s.load({preload:e?.preload}),"success"!==s.state.status&&s.__loadPromise&&await s.__loadPromise,o&&await o.__loadPromise}));await Promise.all(s)};reload=()=>{this.navigate({fromCurrent:!0,replace:!0,search:!0})};resolvePath=(t,e)=>v(this.basepath,t,m(e));navigate=async({from:t,to:s=".",search:a,hash:o,replace:r,params:i})=>{const n=String(s),h=void 0===t?t:String(t);let c;try{new URL(`${n}`),c=!0}catch(t){}return e(!c),this.#h({from:h,to:n,search:a,hash:o,replace:r,params:i})};matchRoute=(t,e)=>{t={...t,to:t.to?this.resolvePath(t.from??"",t.to):void 0};const s=this.buildNext(t);return e?.pending?!!this.state.pendingLocation&&S(this.basepath,this.state.pendingLocation.pathname,{...e,to:s.pathname}):S(this.basepath,this.state.currentLocation.pathname,{...e,to:s.pathname})};buildLink=({from:t,to:e=".",search:s,params:a,hash:o,target:r,replace:i,activeOptions:n,preload:h,preloadMaxAge:c,preloadGcMaxAge:u,preloadDelay:l,disabled:p})=>{try{return new URL(`${e}`),{type:"external",href:e}}catch(t){}const d={from:t,to:e,search:s,params:a,hash:o,replace:i},f=this.buildNext(d);h=h??this.options.defaultPreload;const m=l??this.options.defaultPreloadDelay??0,g=this.state.currentLocation.pathname===f.pathname,y=this.state.currentLocation.pathname.split("/"),w=f.pathname.split("/").every(((t,e)=>t===y[e])),v=this.state.currentLocation.hash===f.hash;return{type:"internal",next:f,handleFocus:t=>{h&&this.preloadRoute(d).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))},handleClick:t=>{p||function(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}(t)||t.defaultPrevented||r&&"_self"!==r||0!==t.button||(t.preventDefault(),this.#h(d))},handleEnter:t=>{const e=t.target||{};if(h){if(e.preloadTimeout)return;e.preloadTimeout=setTimeout((()=>{e.preloadTimeout=null,this.preloadRoute(d).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))}),m)}},handleLeave:t=>{const e=t.target||{};e.preloadTimeout&&(clearTimeout(e.preloadTimeout),e.preloadTimeout=null)},isActive:(n?.exact?g:w)&&(!n?.includeHash||v),disabled:p}};dehydrate=()=>({state:{...u(this.state,["latestLocation","currentLocation","status","lastUpdated"]),currentMatches:this.state.currentMatches.map((t=>({id:t.id,state:{status:t.state.status}})))}});hydrate=t=>{this.store.setState((s=>{const a=this.matchRoutes(t.state.latestLocation.pathname,{strictParseParams:!0});return a.forEach(((s,a)=>{const o=t.state.currentMatches[a];e(o&&o.id===s.id),s.store.setState((t=>({...t,...o.state})))})),N(a),{...s,...t.state,currentMatches:a}}))};#i=t=>{const e=t=>{t.forEach(((t,s)=>{t.init({originalIndex:s,router:this});if(this.routesById[t.id])throw new Error;this.routesById[t.id]=t;const a=t.children;a?.length&&e(a)}))};return e([t]),t};#r=t=>{let{pathname:e,search:s,hash:a,state:o}=this.history.location;const r=this.options.parseSearch(s);return{pathname:e,searchStr:s,search:l(t?.search,r),hash:a.split("#").reverse()[0]??"",href:`${e}${s}${a}`,state:o,key:o?.key||"__init__"}};#o=()=>{this.load()};#n=(t={})=>{const e=t.fromCurrent?this.state.latestLocation.pathname:t.from??this.state.latestLocation.pathname;let s=v(this.basepath??"/",e,`${t.to??"."}`);const a=this.matchRoutes(this.state.latestLocation.pathname,{strictParseParams:!0}),o=this.matchRoutes(s),r={...h(a)?.params};let i=!0===(t.params??!0)?r:c(t.params,r);i&&o.map((t=>t.route.options.stringifyParams)).filter(Boolean).forEach((t=>{Object.assign({},i,t(i))})),s=L(s,i??{});const n=t.__preSearchFilters?.length?t.__preSearchFilters?.reduce(((t,e)=>e(t)),this.state.latestLocation.search):this.state.latestLocation.search,u=!0===t.search?n:t.search?c(t.search,n)??{}:t.__preSearchFilters?.length?n:{},p=t.__postSearchFilters?.length?t.__postSearchFilters.reduce(((t,e)=>e(t)),u):u,d=l(this.state.latestLocation.search,p),f=this.options.stringifySearch(d);let m=!0===t.hash?this.state.latestLocation.hash:c(t.hash,this.state.latestLocation.hash);return m=m?`#${m}`:"",{pathname:s,search:d,searchStr:f,state:this.state.latestLocation.state,hash:m,href:`${s}${f}${m}`,key:t.key}};#h=t=>{const e=this.buildNext(t),s=""+Date.now()+Math.random();this.navigateTimeout&&clearTimeout(this.navigateTimeout);let a="replace";t.replace||(a="push");this.state.latestLocation.href===e.href&&!e.key&&(a="replace");const o=`${e.pathname}${e.searchStr}${e.hash?`#${e.hash}`:""}`;return this.history["push"===a?"push":"replace"](o,{id:s,...e.state}),this.navigationPromise=new Promise((t=>{const e=this.resolveNavigation;this.resolveNavigation=()=>{e(),t()}}))}},t.cleanPath=m,t.createBrowserHistory=o,t.createHashHistory=function(){return o({getHref:()=>window.location.hash.substring(1),createHref:t=>`#${t}`})},t.createMemoryHistory=r,t.decode=E,t.defaultFetchServerDataFn=D,t.defaultParseSearch=I,t.defaultStringifySearch=k,t.encode=_,t.functionalUpdate=c,t.interpolatePath=L,t.invariant=e,t.isPlainObject=p,t.joinPaths=f,t.last=h,t.matchByPath=P,t.matchPathname=S,t.parsePathname=b,t.parseSearchWith=T,t.pick=u,t.replaceEqualDeep=l,t.resolvePath=v,t.rootRouteId=R,t.stringifySearchWith=j,t.trimPath=w,t.trimPathLeft=g,t.trimPathRight=y,t.warning=function(t,e){if(t){"undefined"!=typeof console&&console.warn(e);try{throw new Error(e)}catch{}}return!0},Object.defineProperty(t,"__esModule",{value:!0})}));
//# sourceMappingURL=index.production.js.map
{
"name": "@tanstack/router",
"author": "Tanner Linsley",
"version": "0.0.1-beta.61",
"version": "0.0.1-beta.62",
"license": "MIT",

@@ -40,4 +40,4 @@ "repository": "tanstack/router",

"tiny-invariant": "^1.3.1",
"@tanstack/store": "0.0.1-beta.57"
"@tanstack/store": "0.0.1-beta.62"
}
}

@@ -5,4 +5,2 @@ // While the public API was clearly inspired by the "history" npm package,

import { match } from 'assert'
export interface RouterHistory {

@@ -9,0 +7,0 @@ location: RouterLocation

@@ -149,9 +149,7 @@ import { AnyRoutesInfo, DefaultRoutesInfo, RouteByPath } from './routeInfo'

TTo,
TFromSchema = Expand<
UnionToIntersection<
TRoutesInfo['fullSearchSchema'] &
RouteByPath<TRoutesInfo, TFrom> extends never
? {}
: RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']
>
TFromSchema = UnionToIntersection<
TRoutesInfo['fullSearchSchema'] &
RouteByPath<TRoutesInfo, TFrom> extends never
? {}
: RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']
>,

@@ -169,7 +167,7 @@ // Find the schema for the new path, and make optional any keys

>,
TFromFullSchema = Expand<
UnionToIntersection<TRoutesInfo['fullSearchSchema'] & TFromSchema>
TFromFullSchema = UnionToIntersection<
TRoutesInfo['fullSearchSchema'] & TFromSchema
>,
TToFullSchema = Expand<
UnionToIntersection<TRoutesInfo['fullSearchSchema'] & TToSchema>
TToFullSchema = UnionToIntersection<
TRoutesInfo['fullSearchSchema'] & TToSchema
>,

@@ -192,8 +190,6 @@ > = keyof PickRequired<TToSchema> extends never

TTo,
TFromSchema = Expand<
UnionToIntersection<
RouteByPath<TRoutesInfo, TFrom> extends never
? {}
: RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']
>
TFromSchema = UnionToIntersection<
RouteByPath<TRoutesInfo, TFrom> extends never
? {}
: RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']
>,

@@ -209,8 +205,4 @@ // Find the schema for the new path, and make optional any keys

>,
TFromFullParams = Expand<
UnionToIntersection<TRoutesInfo['allParams'] & TFromSchema>
>,
TToFullParams = Expand<
UnionToIntersection<TRoutesInfo['allParams'] & TToSchema>
>,
TFromFullParams = UnionToIntersection<TRoutesInfo['allParams'] & TFromSchema>,
TToFullParams = UnionToIntersection<TRoutesInfo['allParams'] & TToSchema>,
> = keyof PickRequired<TToSchema> extends never

@@ -302,6 +294,3 @@ ? {

export type CheckPathError<
TRoutesInfo extends AnyRoutesInfo,
TInvalids,
> = Expand<{
export type CheckPathError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = {
Error: `${TInvalids extends string

@@ -311,3 +300,3 @@ ? TInvalids

'Valid Route Paths': TRoutesInfo['routePaths']
}>
}

@@ -321,6 +310,3 @@ export type CheckId<TRoutesInfo extends AnyRoutesInfo, TPath, TPass> = Exclude<

export type CheckIdError<
TRoutesInfo extends AnyRoutesInfo,
TInvalids,
> = Expand<{
export type CheckIdError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = {
Error: `${TInvalids extends string

@@ -330,3 +316,3 @@ ? TInvalids

'Valid Route IDs': TRoutesInfo['routeIds']
}>
}

@@ -333,0 +319,0 @@ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string

import { GetFrameworkGeneric } from './frameworks'
import { ParsePathParams } from './link'
import { RouteMatch } from './routeMatch'
import { AnyRouter, Router } from './router'
import { AnyRouter, RegisteredRouter, Router } from './router'
import {

@@ -22,2 +22,3 @@ Expand,

export type AnySearchSchema = {}
export type AnyContext = {}
export interface RouteMeta {}

@@ -36,2 +37,4 @@

export interface FrameworkRouteOptions {}
export type RouteOptions<

@@ -50,53 +53,70 @@ TParentRoute extends AnyRoute = AnyRoute,

TAllParams extends AnyPathParams = {},
> = RouteOptionsBase<TCustomId, TPath> & {
getParentRoute: () => TParentRoute
// If true, this route will be matched as case-sensitive
caseSensitive?: boolean
validateSearch?: SearchSchemaValidator<TSearchSchema, TParentSearchSchema>
// Filter functions that can manipulate search params *before* they are passed to links and navigate
// calls that match this route.
preSearchFilters?: SearchFilter<TFullSearchSchema>[]
// Filter functions that can manipulate search params *after* they are passed to links and navigate
// calls that match this route.
postSearchFilters?: SearchFilter<TFullSearchSchema>[]
// The content to be rendered when the route is matched. If no component is provided, defaults to `<Outlet />`
component?: GetFrameworkGeneric<'Component'> // , NoInfer<TParentAllLoaderData>>
// The content to be rendered when the route encounters an error
errorComponent?: GetFrameworkGeneric<'ErrorComponent'> // , NoInfer<TParentAllLoaderData>>
// If supported by your framework, the content to be rendered as the fallback content until the route is ready to render
pendingComponent?: GetFrameworkGeneric<'Component'> //, NoInfer<TParentAllLoaderData>>
TParentContext extends AnyContext = AnyContext,
TAllParentContext extends AnyContext = AnyContext,
TRouteContext extends AnyContext = AnyContext,
TContext extends AnyContext = TRouteContext,
> = RouteOptionsBase<TCustomId, TPath> &
FrameworkRouteOptions & {
getParentRoute: () => TParentRoute
// If true, this route will be matched as case-sensitive
caseSensitive?: boolean
validateSearch?: SearchSchemaValidator<TSearchSchema, TParentSearchSchema>
// Filter functions that can manipulate search params *before* they are passed to links and navigate
// calls that match this route.
preSearchFilters?: SearchFilter<TFullSearchSchema>[]
// Filter functions that can manipulate search params *after* they are passed to links and navigate
// calls that match this route.
postSearchFilters?: SearchFilter<TFullSearchSchema>[]
// The content to be rendered when the route is matched. If no component is provided, defaults to `<Outlet />`
component?: GetFrameworkGeneric<'Component'> // , NoInfer<TParentAllLoaderData>>
// The content to be rendered when the route encounters an error
errorComponent?: GetFrameworkGeneric<'ErrorComponent'> // , NoInfer<TParentAllLoaderData>>
// If supported by your framework, the content to be rendered as the fallback content until the route is ready to render
pendingComponent?: GetFrameworkGeneric<'Component'> //, NoInfer<TParentAllLoaderData>>
// This async function is called before a route is loaded.
// If an error is thrown here, the route's loader will not be called.
// If thrown during a navigation, the navigation will be cancelled and the error will be passed to the `onLoadError` function.
// If thrown during a preload event, the error will be logged to the console.
beforeLoad?: (opts: {
router: AnyRouter
match: RouteMatch
}) => Promise<void> | void
// This async function is called before a route is loaded.
// If an error is thrown here, the route's loader will not be called.
// If thrown during a navigation, the navigation will be cancelled and the error will be passed to the `onLoadError` function.
// If thrown during a preload event, the error will be logged to the console.
beforeLoad?: (opts: {
router: AnyRouter
match: RouteMatch
}) => Promise<void> | void
// An asynchronous function responsible for preparing or fetching data for the route before it is rendered
onLoad?: OnLoadFn<TFullSearchSchema, TAllParams, TRouteContext, TContext>
// An asynchronous function responsible for preparing or fetching data for the route before it is rendered
onLoad?: OnLoadFn<TFullSearchSchema, TAllParams>
// This function will be called if the route's loader throws an error **during an attempted navigation**.
// If you want to redirect due to an error, call `router.navigate()` from within this function.
onLoadError?: (err: any) => void
// This function is called
// when moving from an inactive state to an active one. Likewise, when moving from
// an active to an inactive state, the return function (if provided) is called.
onLoaded?: (matchContext: {
params: TAllParams
search: TFullSearchSchema
}) =>
| void
| undefined
| ((match: { params: TAllParams; search: TFullSearchSchema }) => void)
// This function is called when the route remains active from one transition to the next.
onTransition?: (match: {
params: TAllParams
search: TFullSearchSchema
}) => void
// An object of whatever you want! This object is accessible anywhere matches are.
meta?: RouteMeta // TODO: Make this nested and mergeable
} & (
// This function will be called if the route's loader throws an error **during an attempted navigation**.
// If you want to redirect due to an error, call `router.navigate()` from within this function.
onLoadError?: (err: any) => void
// This function is called
// when moving from an inactive state to an active one. Likewise, when moving from
// an active to an inactive state, the return function (if provided) is called.
onLoaded?: (matchContext: {
params: TAllParams
search: TFullSearchSchema
}) =>
| void
| undefined
| ((match: { params: TAllParams; search: TFullSearchSchema }) => void)
// This function is called when the route remains active from one transition to the next.
onTransition?: (match: {
params: TAllParams
search: TFullSearchSchema
}) => void
// An object of whatever you want! This object is accessible anywhere matches are.
getContext?: (
opts: {
params: TAllParams
search: TFullSearchSchema
} & (TParentRoute extends undefined
? {
context?: TAllParentContext
parentContext?: TParentContext
}
: {
context: TAllParentContext
parentContext: TParentContext
}),
) => TRouteContext
} & (
| {

@@ -152,4 +172,11 @@ parseParams?: never

TAllParams extends AnyPathParams = {},
TContext extends AnyContext = AnyContext,
TAllContext extends AnyContext = AnyContext,
> = (
loaderContext: LoaderContext<TFullSearchSchema, TAllParams>,
loaderContext: LoaderContext<
TFullSearchSchema,
TAllParams,
TContext,
TAllContext
>,
) => Promise<any> | void

@@ -160,2 +187,4 @@

TAllParams extends AnyPathParams = {},
TContext extends AnyContext = AnyContext,
TAllContext extends AnyContext = AnyContext,
> {

@@ -166,3 +195,4 @@ params: TAllParams

preload: boolean
// parentLoaderPromise?: Promise<TParentRouteLoaderData>
routeContext: TContext
context: TAllContext
}

@@ -180,7 +210,5 @@

TPath extends string,
> = TParentRoute extends Route<any>
? RootRouteId
: TParentRoute extends { id: infer TParentId extends string }
> = TParentRoute extends { id: infer TParentId extends string }
? RoutePrefix<TParentId, string extends TCustomId ? TPath : TCustomId>
: never
: RootRouteId

@@ -202,23 +230,26 @@ export type InferFullSearchSchema<TRoute> = TRoute extends {

export type ResolveFullSearchSchema<TParentRoute, TSearchSchema> = Expand<
export type ResolveFullSearchSchema<TParentRoute, TSearchSchema> =
InferFullSearchSchema<TParentRoute> & TSearchSchema
>
export interface AnyRoute
extends Route<any, any, any, any, any, any, any, any, any, any, any> {}
extends Route<
any,
any,
any,
any,
any,
any,
any,
any,
any,
any,
any,
any,
any,
any,
any,
any
> {}
export type RouteWithRoutesInfo<TRoute> = TRoute extends Route<
infer TParentRoute,
infer TPath,
infer TFullPath,
infer TCustomId,
infer TId,
infer TSearchSchema,
infer TFullSearchSchema,
infer TParams,
infer TAllParams,
infer TChildren
>
? Route<any, any, any, any, any, any, any, any, any, TChildren, any>
: never
type MergeFromParent<T, U> = IsAny<T, U, T & U>

@@ -247,5 +278,14 @@ export class Route<

>,
TAllParams extends Expand<
TParentRoute['__types']['allParams'] & TParams
> = Expand<TParentRoute['__types']['allParams'] & TParams>,
TAllParams extends MergeFromParent<
TParentRoute['__types']['allParams'],
TParams
> = MergeFromParent<TParentRoute['__types']['allParams'], TParams>,
TParentContext extends TParentRoute['__types']['routeContext'] = TParentRoute['__types']['routeContext'],
TAllParentContext extends TParentRoute['__types']['context'] = TParentRoute['__types']['context'],
TRouteContext extends AnyContext = AnyContext,
TContext extends MergeFromParent<
TParentRoute['__types']['context'],
TRouteContext
> = MergeFromParent<TParentRoute['__types']['context'], TRouteContext>,
TRouterContext extends AnyContext = AnyContext,
TChildren extends unknown = unknown,

@@ -258,3 +298,3 @@ TRoutesInfo extends DefaultRoutesInfo = DefaultRoutesInfo,

fullPath: TFullPath
// customId: TCustomId
customId: TCustomId
id: TId

@@ -265,4 +305,9 @@ searchSchema: TSearchSchema

allParams: TAllParams
parentContext: TParentContext
allParentContext: TAllParentContext
routeContext: TRouteContext
context: TContext
children: TChildren
routesInfo: TRoutesInfo
routerContext: TRouterContext
}

@@ -276,6 +321,10 @@ isRoot: TParentRoute extends Route<any> ? true : false

TSearchSchema,
Expand<InferFullSearchSchema<TParentRoute> & TSearchSchema>,
InferFullSearchSchema<TParentRoute> & TSearchSchema,
TParentRoute['__types']['allParams'],
TParams,
TAllParams
TAllParams,
TParentContext,
TAllParentContext,
TRouteContext,
TContext
>

@@ -293,3 +342,3 @@

originalIndex?: number
router?: Router<TRoutesInfo['routeTree'], TRoutesInfo, unknown>
router?: Router<TRoutesInfo['routeTree'], TRoutesInfo>

@@ -306,3 +355,7 @@ constructor(

TParams,
TAllParams
TAllParams,
TParentContext,
TAllParentContext,
TRouteContext,
TContext
>,

@@ -314,3 +367,6 @@ ) {

init = () => {
init = (opts: { originalIndex: number; router: AnyRouter }) => {
this.originalIndex = opts.originalIndex
this.router = opts.router
const allOptions = this.options as RouteOptions<

@@ -325,3 +381,7 @@ TParentRoute,

TParams,
TAllParams
TAllParams,
TParentContext,
TAllParentContext,
TRouteContext,
TContext
> &

@@ -379,16 +439,24 @@ RouteOptionsBaseIntersection<TCustomId, TPath>

addChildren = <TNewChildren extends AnyRoute[]>(children: TNewChildren) => {
addChildren = <TNewChildren extends AnyRoute[]>(
children: TNewChildren,
): Route<
TParentRoute,
TPath,
TFullPath,
TCustomId,
TId,
TSearchSchema,
TFullSearchSchema,
TParams,
TAllParams,
TParentContext,
TAllParentContext,
TRouteContext,
TContext,
TRouterContext,
TNewChildren,
TRoutesInfo
> => {
this.children = children as any
return this as unknown as Route<
TParentRoute,
TPath,
TFullPath,
TCustomId,
TId,
TSearchSchema,
TFullSearchSchema,
TParams,
TAllParams,
TNewChildren
>
return this as any
}

@@ -404,6 +472,8 @@

export type AnyRootRoute = RootRoute<any>
export type AnyRootRoute = RootRoute<any, any, any>
export class RootRoute<
TSearchSchema extends AnySearchSchema = {},
TContext extends AnyContext = AnyContext,
TRouterContext extends AnyContext = AnyContext,
> extends Route<

@@ -418,3 +488,8 @@ any,

{},
{}
{},
TRouterContext,
TRouterContext,
TContext,
MergeFromParent<TRouterContext, TContext>,
TRouterContext
> {

@@ -431,4 +506,6 @@ constructor(

{},
{},
{}
TRouterContext,
TRouterContext,
TContext,
NoInfer<TContext>
>,

@@ -440,2 +517,26 @@ 'path' | 'id' | 'getParentRoute' | 'caseSensitive'

}
static withRouterContext = <TRouterContext extends AnyContext>() => {
return <
TSearchSchema extends AnySearchSchema = {},
TContext extends AnyContext = AnyContext,
>(
options?: Omit<
RouteOptions<
AnyRoute,
RootRouteId,
'',
{},
TSearchSchema,
NoInfer<TSearchSchema>,
{},
TRouterContext,
TRouterContext,
TContext,
TRouterContext & TContext
>,
'path' | 'id' | 'getParentRoute' | 'caseSensitive'
>,
) => new RootRoute<TSearchSchema, TContext, TRouterContext>(options as any)
}
}

@@ -442,0 +543,0 @@

@@ -1,2 +0,2 @@

import { AnyRoute, Route } from './route'
import { AnyRootRoute, AnyRoute, RootRoute, Route } from './route'
import { AnyPathParams, AnySearchSchema, RootRouteId } from './route'

@@ -6,3 +6,4 @@ import { IsAny, UnionToIntersection, Values } from './utils'

export interface AnyRoutesInfo {
routeTree: AnyRoute
routeTree: AnyRootRoute
routeUnion: AnyRoute
routesById: Record<string, AnyRoute>

@@ -12,2 +13,3 @@ routesByFullPath: Record<string, AnyRoute>

routePaths: any
routeIntersection: AnyRoute
fullSearchSchema: Record<string, any>

@@ -18,3 +20,4 @@ allParams: Record<string, any>

export interface DefaultRoutesInfo {
routeTree: Route
routeTree: RootRoute
routeUnion: AnyRoute
routesById: Record<string, Route>

@@ -24,2 +27,3 @@ routesByFullPath: Record<string, Route>

routePaths: string
routeIntersection: AnyRoute
fullSearchSchema: AnySearchSchema

@@ -34,8 +38,8 @@ allParams: AnyPathParams

TRouteTree extends AnyRoute,
TRoutes extends AnyRoute = Route,
TRoutesById = { '/': TRoutes } & {
[TRoute in TRoutes as TRoute['id']]: TRoute
TRouteUnion extends AnyRoute = Route,
TRoutesById = { '/': TRouteUnion } & {
[TRoute in TRouteUnion as TRoute['id']]: TRoute
},
TRoutesByFullPath = { '/': TRoutes } & {
[TRoute in TRoutes as TRoute['fullPath'] extends RootRouteId
TRoutesByFullPath = { '/': TRouteUnion } & {
[TRoute in TRouteUnion as TRoute['fullPath'] extends RootRouteId
? never

@@ -48,3 +52,3 @@ : string extends TRoute['fullPath']

routeTree: TRouteTree
routes: TRoutes
routeUnion: TRouteUnion
routesById: TRoutesById

@@ -54,6 +58,24 @@ routesByFullPath: TRoutesByFullPath

routePaths: keyof TRoutesByFullPath
routeIntersection: Route<
TRouteUnion['__types']['parentRoute'], // TParentRoute,
TRouteUnion['__types']['path'], // TPath,
TRouteUnion['__types']['fullPath'], // TFullPath,
TRouteUnion['__types']['customId'], // TCustomId,
TRouteUnion['__types']['id'], // TId,
UnionToIntersection<TRouteUnion['__types']['searchSchema']> & {}, // TSearchSchema,
UnionToIntersection<TRouteUnion['__types']['fullSearchSchema']> & {}, // TFullSearchSchema,
UnionToIntersection<TRouteUnion['__types']['params']>, // TParams,
UnionToIntersection<TRouteUnion['__types']['allParams']>, // TAllParams,
UnionToIntersection<TRouteUnion['__types']['parentContext']>, // TParentContext,
UnionToIntersection<TRouteUnion['__types']['allParentContext']>, // TAllParentContext,
UnionToIntersection<TRouteUnion['__types']['routerContext']> & {}, // TContext,
UnionToIntersection<TRouteUnion['__types']['context']> & {}, // TAllContext,
UnionToIntersection<TRouteUnion['__types']['routerContext']> & {}, // TRouterContext,
TRouteUnion['__types']['children'], // TChildren,
TRouteUnion['__types']['routesInfo'] // TRoutesInfo,
>
fullSearchSchema: Partial<
UnionToIntersection<TRoutes['__types']['fullSearchSchema']>
UnionToIntersection<TRouteUnion['__types']['fullSearchSchema']>
>
allParams: Partial<UnionToIntersection<TRoutes['__types']['allParams']>>
allParams: Partial<UnionToIntersection<TRouteUnion['__types']['allParams']>>
}

@@ -75,2 +97,7 @@

any,
any,
any,
any,
any,
any,
infer TChildren,

@@ -77,0 +104,0 @@ any

@@ -7,3 +7,3 @@ import { Store } from '@tanstack/store'

import { AnyRouter, Router } from './router'
import { Expand } from './utils'
import { Expand, pick } from './utils'

@@ -15,5 +15,4 @@ export interface RouteMatchStore<

routeSearch: TRoute['__types']['searchSchema']
search: Expand<
TRoutesInfo['fullSearchSchema'] & TRoute['__types']['fullSearchSchema']
>
search: TRoutesInfo['fullSearchSchema'] &
TRoute['__types']['fullSearchSchema']
status: 'idle' | 'pending' | 'success' | 'error'

@@ -30,2 +29,4 @@ error?: unknown

export interface AnyRouteMatch extends RouteMatch<any, any> {}
export class RouteMatch<

@@ -38,5 +39,8 @@ TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo,

store!: Store<RouteMatchStore<TRoutesInfo, TRoute>>
state!: RouteMatchStore<TRoutesInfo, TRoute>
id!: string
pathname!: string
params!: TRoute['__types']['allParams']
routeContext!: TRoute['__types']['routeContext']
context!: TRoute['__types']['context']

@@ -73,10 +77,19 @@ component: GetFrameworkGeneric<'Component'>

params: opts.params,
store: new Store<RouteMatchStore<TRoutesInfo, TRoute>>({
updatedAt: 0,
routeSearch: {},
search: {} as any,
status: 'idle',
}),
store: new Store<RouteMatchStore<TRoutesInfo, TRoute>>(
{
updatedAt: 0,
routeSearch: {},
search: {} as any,
status: 'idle',
},
{
onUpdate: (next) => {
this.state = next
},
},
),
})
this.state = this.store.state
if (!this.#hasLoaders()) {

@@ -90,2 +103,74 @@ this.store.setState((s) => ({

#hasLoaders = () => {
return !!(
this.route.options.onLoad ||
componentTypes.some((d) => this.route.options[d]?.preload)
)
}
__init = (opts: { parentMatch?: RouteMatch }) => {
// Validate the search params and stabilize them
this.parentMatch = opts.parentMatch
const parentSearch =
this.parentMatch?.state.search ?? this.router.state.latestLocation.search
try {
const validator =
typeof this.route.options.validateSearch === 'object'
? this.route.options.validateSearch.parse
: this.route.options.validateSearch
let nextSearch = validator?.(parentSearch) ?? {}
this.store.setState((s) => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch,
} as any,
}))
componentTypes.map(async (type) => {
const component = this.route.options[type]
if (typeof this[type] !== 'function') {
this[type] = component
}
})
const parent = this.parentMatch
this.routeContext =
this.route.options.getContext?.({
parentContext: parent?.routeContext,
context: parent?.context,
params: this.params,
search: this.state.search,
}) || ({} as any)
this.context = (
parent
? { ...parent.context, ...this.routeContext }
: { ...this.router?.options.context, ...this.routeContext }
) as any
} catch (err: any) {
console.error(err)
const error = new (Error as any)('Invalid search params found', {
cause: err,
})
error.code = 'INVALID_SEARCH_PARAMS'
this.store.setState((s) => ({
...s,
status: 'error',
error: error,
}))
// Do not proceed with loading the route
return
}
}
cancel = () => {

@@ -97,3 +182,3 @@ this.abortController?.abort()

// If the match is invalid, errored or idle, trigger it to load
if (this.store.state.status !== 'pending') {
if (this.state.status !== 'pending') {
await this.fetch(opts)

@@ -120,3 +205,3 @@ }

// as loading or resolved
if (this.store.state.status === 'idle') {
if (this.state.status === 'idle') {
this.store.setState((s) => ({

@@ -148,5 +233,7 @@ ...s,

params: this.params,
search: this.store.state.search,
search: this.state.search,
signal: this.abortController.signal,
preload: !!opts?.preload,
routeContext: this.routeContext,
context: this.context,
})

@@ -181,63 +268,2 @@ }

}
#hasLoaders = () => {
return !!(
this.route.options.onLoad ||
componentTypes.some((d) => this.route.options[d]?.preload)
)
}
__setParentMatch = (parentMatch?: RouteMatch) => {
if (!this.parentMatch && parentMatch) {
this.parentMatch = parentMatch
}
}
__validate = () => {
// Validate the search params and stabilize them
const parentSearch =
this.parentMatch?.store.state.search ??
this.router.store.state.latestLocation.search
try {
const validator =
typeof this.route.options.validateSearch === 'object'
? this.route.options.validateSearch.parse
: this.route.options.validateSearch
let nextSearch = validator?.(parentSearch) ?? {}
this.store.setState((s) => ({
...s,
routeSearch: nextSearch,
search: {
...parentSearch,
...nextSearch,
} as any,
}))
componentTypes.map(async (type) => {
const component = this.route.options[type]
if (typeof this[type] !== 'function') {
this[type] = component
}
})
} catch (err: any) {
console.error(err)
const error = new (Error as any)('Invalid search params found', {
cause: err,
})
error.code = 'INVALID_SEARCH_PARAMS'
this.store.setState((s) => ({
...s,
status: 'error',
error: error,
}))
// Do not proceed with loading the route
return
}
}
}

@@ -27,10 +27,11 @@ import { Store } from '@tanstack/store'

AnyPathParams,
AnyRoute,
AnySearchSchema,
LoaderContext,
SearchFilter,
AnyRootRoute,
AnyRoute,
RootRoute,
AnyContext,
} from './route'
import { RoutesInfo, AnyRoutesInfo, RoutesById } from './routeInfo'
import { RouteMatch, RouteMatchStore } from './routeMatch'
import { AnyRouteMatch, RouteMatch, RouteMatchStore } from './routeMatch'
import { defaultParseSearch, defaultStringifySearch } from './searchParams'

@@ -58,12 +59,12 @@ import {

export type AnyRouter = Router<any, any, any>
export type AnyRouter = Router<any, any>
export type RegisteredRouter = Register extends {
router: Router<infer TRoute, infer TRoutesInfo, infer TRouterContext>
router: Router<infer TRoute, infer TRoutesInfo>
}
? Router<TRoute, TRoutesInfo, TRouterContext>
? Router<TRoute, TRoutesInfo>
: Router
export type RegisteredRoutesInfo = Register extends {
router: Router<infer TRoute, infer TRoutesInfo, infer TRouterContext>
router: Router<infer TRoute, infer TRoutesInfo>
}

@@ -101,6 +102,12 @@ ? TRoutesInfo

export interface RouterOptions<
TRouteTree extends AnyRootRoute,
TRouterContext,
> {
type RouterContextOptions<TRouteTree extends AnyRoute> =
AnyContext extends TRouteTree['__types']['routerContext']
? {
context?: TRouteTree['__types']['routerContext']
}
: {
context: TRouteTree['__types']['routerContext']
}
export interface RouterOptions<TRouteTree extends AnyRoute> {
history?: RouterHistory

@@ -122,3 +129,2 @@ stringifySearch?: SearchSerializer

createRoute?: (opts: { route: AnyRoute; router: AnyRouter }) => void
context?: TRouterContext
loadComponent?: (

@@ -129,2 +135,3 @@ component: GetFrameworkGeneric<'Component'>,

fetchServerDataFn?: FetchServerDataFn
context?: TRouteTree['__types']['routerContext']
}

@@ -146,11 +153,11 @@

export interface RouterStore<
TSearchObj extends AnySearchSchema = {},
TRoutesInfo extends AnyRoutesInfo = AnyRoutesInfo,
TState extends LocationState = LocationState,
> {
status: 'idle' | 'pending'
latestLocation: ParsedLocation<TSearchObj, TState>
currentMatches: RouteMatch[]
currentLocation: ParsedLocation<TSearchObj, TState>
pendingMatches?: RouteMatch[]
pendingLocation?: ParsedLocation<TSearchObj, TState>
latestLocation: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>
currentMatches: RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>[]
currentLocation: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>
pendingMatches?: RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>[]
pendingLocation?: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>
lastUpdated: number

@@ -205,6 +212,4 @@ }

export interface DehydratedRouter<TRouterContext = unknown> {
// location: Router['__location']
export interface DehydratedRouter {
state: DehydratedRouterState
context: TRouterContext
}

@@ -248,5 +253,4 @@

export class Router<
TRouteTree extends AnyRoute = Route,
TRouteTree extends AnyRoute = RootRoute,
TRoutesInfo extends AnyRoutesInfo = RoutesInfo<TRouteTree>,
TRouterContext = unknown,
> {

@@ -260,5 +264,6 @@ types!: {

options: PickAsRequired<
RouterOptions<TRouteTree, TRouterContext>,
'stringifySearch' | 'parseSearch' | 'context'
>
Omit<RouterOptions<TRouteTree>, 'context'>,
'stringifySearch' | 'parseSearch'
> &
RouterContextOptions<TRouteTree>
history!: RouterHistory

@@ -268,3 +273,3 @@ #unsubHistory?: () => void

// __location: Location<TRoutesInfo['fullSearchSchema']>
routeTree!: Route
routeTree!: RootRoute
routesById!: RoutesById<TRoutesInfo>

@@ -275,7 +280,8 @@ navigateTimeout: undefined | Timeout

store: Store<RouterStore<TRoutesInfo['fullSearchSchema']>>
store: Store<RouterStore<TRoutesInfo>>
state: RouterStore<TRoutesInfo>
startedLoadingAt = Date.now()
resolveNavigation = () => {}
constructor(options?: RouterOptions<TRouteTree, TRouterContext>) {
constructor(options?: RouterOptions<TRouteTree>) {
this.options = {

@@ -290,3 +296,8 @@ defaultPreloadDelay: 50,

this.store = new Store(getInitialRouterState())
this.store = new Store<RouterStore<TRoutesInfo>>(getInitialRouterState(), {
onUpdate: (state) => {
this.state = state
},
})
this.state = this.store.state
this.basepath = ''

@@ -308,3 +319,3 @@

// If the router matches are empty, load the matches
if (!this.store.state.currentMatches.length) {
if (!this.state.currentMatches.length) {
this.load()

@@ -338,9 +349,3 @@ }

update = <
TRoute extends AnyRootRoute = AnyRootRoute,
TRoutesInfo extends AnyRoutesInfo = RoutesInfo<TRoute>,
TRouterContext = unknown,
>(
opts?: RouterOptions<TRoute, TRouterContext>,
): this => {
update = (opts?: RouterOptions<TRouteTree>): this => {
Object.assign(this.options, opts)

@@ -369,3 +374,5 @@

this.#unsubHistory = this.history.listen(() => {
this.load(this.#parseLocation(this.store.state.latestLocation))
this.load({
next: this.#parseLocation(this.state.latestLocation),
})
})

@@ -383,3 +390,3 @@ }

return this as any
return this
}

@@ -411,4 +418,4 @@

;[
...this.store.state.currentMatches,
...(this.store.state.pendingMatches || []),
...this.state.currentMatches,
...(this.state.pendingMatches || []),
].forEach((match) => {

@@ -419,3 +426,6 @@ match.cancel()

load = async (next?: ParsedLocation) => {
load = async (opts?: {
next?: ParsedLocation
// filter?: (match: RouteMatch<any, any>) => any
}) => {
let now = Date.now()

@@ -431,7 +441,7 @@ const startedAt = now

this.store.batch(() => {
if (next) {
if (opts?.next) {
// Ingest the new location
this.store.setState((s) => ({
...s,
latestLocation: next,
latestLocation: opts.next!,
}))

@@ -441,3 +451,3 @@ }

// Match the routes
matches = this.matchRoutes(this.store.state.latestLocation.pathname, {
matches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true,

@@ -450,3 +460,3 @@ })

pendingMatches: matches,
pendingLocation: this.store.state.latestLocation,
pendingLocation: this.state.latestLocation,
}))

@@ -457,3 +467,6 @@ })

try {
await this.loadMatches(matches)
await this.loadMatches(
matches,
// opts
)
} catch (err: any) {

@@ -472,6 +485,6 @@ console.warn(err)

const previousMatches = this.store.state.currentMatches
const previousMatches = this.state.currentMatches
const exiting: RouteMatch[] = [],
staying: RouteMatch[] = []
const exiting: AnyRouteMatch[] = [],
staying: AnyRouteMatch[] = []

@@ -495,7 +508,7 @@ previousMatches.forEach((d) => {

params: d.params,
search: d.store.state.routeSearch,
search: d.state.routeSearch,
})
// Clear non-loading error states when match leaves
if (d.store.state.status === 'error') {
if (d.state.status === 'error') {
this.store.setState((s) => ({

@@ -512,3 +525,3 @@ ...s,

params: d.params,
search: d.store.state.routeSearch,
search: d.state.routeSearch,
})

@@ -520,5 +533,4 @@ })

params: d.params,
search: d.store.state.search,
search: d.state.search,
})
// delete this.store.state.matchCache[d.id] // TODO:
})

@@ -529,3 +541,3 @@

status: 'idle',
currentLocation: this.store.state.latestLocation,
currentLocation: this.state.latestLocation,
currentMatches: matches,

@@ -552,3 +564,3 @@ pendingLocation: undefined,

loadRoute = async (
navigateOpts: BuildNextOptions = this.store.state.latestLocation,
navigateOpts: BuildNextOptions = this.state.latestLocation,
): Promise<RouteMatch[]> => {

@@ -564,3 +576,3 @@ const next = this.buildNext(navigateOpts)

preloadRoute = async (
navigateOpts: BuildNextOptions = this.store.state.latestLocation,
navigateOpts: BuildNextOptions = this.state.latestLocation,
) => {

@@ -579,3 +591,3 @@ const next = this.buildNext(navigateOpts)

matchRoutes = (pathname: string, opts?: { strictParseParams?: boolean }) => {
const matches: RouteMatch[] = []
const matches: AnyRouteMatch[] = []

@@ -587,4 +599,4 @@ if (!this.routeTree) {

const existingMatches = [
...this.store.state.currentMatches,
...(this.store.state.pendingMatches ?? []),
...this.state.currentMatches,
...(this.state.pendingMatches ?? []),
]

@@ -661,3 +673,2 @@

existingMatches.find((d) => d.id === matchId) ||
// this.store.state.matchCache[matchId]?.match || // TODO:
new RouteMatch(this, foundRoute, {

@@ -688,12 +699,9 @@ id: matchId,

resolvedMatches: RouteMatch[],
loaderOpts?: { preload?: boolean },
opts?: {
preload?: boolean
// filter?: (match: RouteMatch<any, any>) => any
},
) => {
linkMatches(resolvedMatches)
initMatches(resolvedMatches)
// this.cleanMatchCache()
resolvedMatches.forEach(async (match) => {
// Validate the match (loads search params etc)
match.__validate()
})
// Check each match middleware to see if the route can be accessed

@@ -708,3 +716,3 @@ await Promise.all(

} catch (err) {
if (!loaderOpts?.preload) {
if (!opts?.preload) {
match.route.options.onLoadError?.(err)

@@ -720,11 +728,11 @@ }

const prevMatch = resolvedMatches[(index = 1)]
const search = match.store.state.search as { __data?: any }
const search = match.state.search as { __data?: any }
if (search.__data?.matchId && search.__data.matchId !== match.id) {
return
}
// if (opts?.filter && !opts.filter(match)) {
// return
// }
match.load({ preload: loaderOpts?.preload })
match.load({ preload: opts?.preload })
if (match.store.state.status !== 'success' && match.__loadPromise) {
if (match.state.status !== 'success' && match.__loadPromise) {
// Wait for the first sign of activity from the match

@@ -812,3 +820,3 @@ await match.__loadPromise

if (opts?.pending) {
if (!this.store.state.pendingLocation) {
if (!this.state.pendingLocation) {
return false

@@ -819,3 +827,3 @@ }

this.basepath,
this.store.state.pendingLocation!.pathname,
this.state.pendingLocation!.pathname,
{

@@ -828,10 +836,6 @@ ...opts,

return matchPathname(
this.basepath,
this.store.state.currentLocation.pathname,
{
...opts,
to: next.pathname,
},
) as any
return matchPathname(this.basepath, this.state.currentLocation.pathname, {
...opts,
to: next.pathname,
}) as any
}

@@ -887,6 +891,4 @@

// Compare path/hash for matches
const pathIsEqual =
this.store.state.currentLocation.pathname === next.pathname
const currentPathSplit =
this.store.state.currentLocation.pathname.split('/')
const pathIsEqual = this.state.currentLocation.pathname === next.pathname
const currentPathSplit = this.state.currentLocation.pathname.split('/')
const nextPathSplit = next.pathname.split('/')

@@ -896,3 +898,3 @@ const pathIsFuzzyEqual = nextPathSplit.every(

)
const hashIsEqual = this.store.state.currentLocation.hash === next.hash
const hashIsEqual = this.state.currentLocation.hash === next.hash
// Combine the matches based on user options

@@ -970,6 +972,6 @@ const pathTest = activeOptions?.exact ? pathIsEqual : pathIsFuzzyEqual

dehydrate = (): DehydratedRouter<TRouterContext> => {
dehydrate = (): DehydratedRouter => {
return {
state: {
...pick(this.store.state, [
...pick(this.state, [
'latestLocation',

@@ -980,17 +982,14 @@ 'currentLocation',

]),
currentMatches: this.store.state.currentMatches.map((match) => ({
currentMatches: this.state.currentMatches.map((match) => ({
id: match.id,
state: {
...pick(match.store.state, ['status']),
status: match.state.status,
},
})),
},
context: this.options.context as TRouterContext,
}
}
hydrate = (dehydratedRouter: DehydratedRouter<TRouterContext>) => {
hydrate = (dehydratedRouter: DehydratedRouter) => {
this.store.setState((s) => {
this.options.context = dehydratedRouter.context
// Match the routes

@@ -1016,3 +1015,3 @@ const currentMatches = this.matchRoutes(

currentMatches.forEach((match) => match.__validate())
initMatches(currentMatches)

@@ -1027,10 +1026,7 @@ return {

#buildRouteTree = (routeTree: Route) => {
#buildRouteTree = (routeTree: AnyRoute) => {
const recurseRoutes = (routes: Route[]) => {
routes.forEach((route, i) => {
route.init()
route.init({ originalIndex: i, router: this })
route.originalIndex = i
route.router = this as any
const existingRoute = (this.routesById as any)[route.id]

@@ -1057,3 +1053,3 @@

recurseRoutes([routeTree])
recurseRoutes([routeTree] as Route[])

@@ -1085,4 +1081,4 @@ return routeTree

const fromPathname = dest.fromCurrent
? this.store.state.latestLocation.pathname
: dest.from ?? this.store.state.latestLocation.pathname
? this.state.latestLocation.pathname
: dest.from ?? this.state.latestLocation.pathname

@@ -1095,8 +1091,5 @@ let pathname = resolvePath(

const fromMatches = this.matchRoutes(
this.store.state.latestLocation.pathname,
{
strictParseParams: true,
},
)
const fromMatches = this.matchRoutes(this.state.latestLocation.pathname, {
strictParseParams: true,
})

@@ -1127,5 +1120,5 @@ const toMatches = this.matchRoutes(pathname)

(prev, next) => next(prev),
this.store.state.latestLocation.search,
this.state.latestLocation.search,
)
: this.store.state.latestLocation.search
: this.state.latestLocation.search

@@ -1148,3 +1141,3 @@ // Then the link/navigate function

const search = replaceEqualDeep(
this.store.state.latestLocation.search,
this.state.latestLocation.search,
postFilteredSearch,

@@ -1156,4 +1149,4 @@ )

dest.hash === true
? this.store.state.latestLocation.hash
: functionalUpdate(dest.hash!, this.store.state.latestLocation.hash)
? this.state.latestLocation.hash
: functionalUpdate(dest.hash!, this.state.latestLocation.hash)
hash = hash ? `#${hash}` : ''

@@ -1165,3 +1158,3 @@

searchStr,
state: this.store.state.latestLocation.state,
state: this.state.latestLocation.state,
hash,

@@ -1185,3 +1178,3 @@ href: `${pathname}${searchStr}${hash}`,

const isSameUrl = this.store.state.latestLocation.href === next.href
const isSameUrl = this.state.latestLocation.href === next.href

@@ -1201,3 +1194,3 @@ if (isSameUrl && !next.key) {

// this.load(this.#parseLocation(this.store.state.latestLocation))
// this.load(this.#parseLocation(this.state.latestLocation))

@@ -1218,3 +1211,3 @@ return (this.navigationPromise = new Promise((resolve) => {

function getInitialRouterState(): RouterStore {
function getInitialRouterState(): RouterStore<any, any> {
return {

@@ -1233,10 +1226,7 @@ status: 'idle',

function linkMatches(matches: RouteMatch<any, any>[]) {
function initMatches(matches: RouteMatch<any, any>[]) {
matches.forEach((match, index) => {
const parent = matches[index - 1]
if (parent) {
match.__setParentMatch(parent)
}
const parentMatch = matches[index - 1]
match.__init({ parentMatch })
})
}

@@ -10,3 +10,3 @@ export type NoInfer<T> = [T][T extends any ? 0 : never]

export type PickUnsafe<T, K> = K extends keyof T ? Pick<T, K> : never
export type PickExtra<T, K> = Expand<{
export type PickExtra<T, K> = {
[TKey in keyof K as string extends TKey

@@ -17,3 +17,4 @@ ? never

: TKey]: K[TKey]
}>
}
export type PickRequired<T> = {

@@ -20,0 +21,0 @@ [K in keyof T as undefined extends T[K] ? never : K]: T[K]

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc