@tanstack/router-core 1.155.0 → 1.156.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/new-process-route-tree.cjs.map +1 -1
- package/dist/cjs/new-process-route-tree.d.cts +13 -8
- package/dist/cjs/router.cjs +116 -49
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +18 -4
- package/dist/esm/new-process-route-tree.d.ts +13 -8
- package/dist/esm/new-process-route-tree.js.map +1 -1
- package/dist/esm/router.d.ts +18 -4
- package/dist/esm/router.js +117 -50
- package/dist/esm/router.js.map +1 -1
- package/package.json +1 -1
- package/src/new-process-route-tree.ts +12 -8
- package/src/router.ts +166 -48
package/dist/esm/router.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Store, batch } from "@tanstack/store";
|
|
2
2
|
import { createBrowserHistory, parseHref } from "@tanstack/history";
|
|
3
|
-
import { createControlledPromise, isDangerousProtocol, deepEqual, replaceEqualDeep, decodePath, functionalUpdate,
|
|
3
|
+
import { createControlledPromise, isDangerousProtocol, deepEqual, replaceEqualDeep, last, decodePath, functionalUpdate, findLast } from "./utils.js";
|
|
4
4
|
import { processRouteTree, processRouteMasks, findSingleMatch, findRouteMatch, findFlatMatch } from "./new-process-route-tree.js";
|
|
5
5
|
import { compileDecodeCharMap, trimPath, resolvePath, cleanPath, trimPathRight, interpolatePath } from "./path.js";
|
|
6
6
|
import { createLRUCache } from "./lru-cache.js";
|
|
@@ -95,7 +95,23 @@ class RouterCore {
|
|
|
95
95
|
}
|
|
96
96
|
if (this.options.routeTree !== this.routeTree) {
|
|
97
97
|
this.routeTree = this.options.routeTree;
|
|
98
|
-
|
|
98
|
+
let processRouteTreeResult;
|
|
99
|
+
if (this.isServer && globalThis.__TSR_CACHE__ && globalThis.__TSR_CACHE__.routeTree === this.routeTree) {
|
|
100
|
+
const cached = globalThis.__TSR_CACHE__;
|
|
101
|
+
this.resolvePathCache = cached.resolvePathCache;
|
|
102
|
+
processRouteTreeResult = cached.processRouteTreeResult;
|
|
103
|
+
} else {
|
|
104
|
+
this.resolvePathCache = createLRUCache(1e3);
|
|
105
|
+
processRouteTreeResult = this.buildRouteTree();
|
|
106
|
+
if (this.isServer && globalThis.__TSR_CACHE__ === void 0) {
|
|
107
|
+
globalThis.__TSR_CACHE__ = {
|
|
108
|
+
routeTree: this.routeTree,
|
|
109
|
+
processRouteTreeResult,
|
|
110
|
+
resolvePathCache: this.resolvePathCache
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
this.setRoutes(processRouteTreeResult);
|
|
99
115
|
}
|
|
100
116
|
if (!this.__store && this.latestLocation) {
|
|
101
117
|
this.__store = new Store(getInitialRouterState(this.latestLocation), {
|
|
@@ -153,7 +169,7 @@ class RouterCore {
|
|
|
153
169
|
);
|
|
154
170
|
};
|
|
155
171
|
this.buildRouteTree = () => {
|
|
156
|
-
const
|
|
172
|
+
const result = processRouteTree(
|
|
157
173
|
this.routeTree,
|
|
158
174
|
this.options.caseSensitive,
|
|
159
175
|
(route, i) => {
|
|
@@ -163,18 +179,9 @@ class RouterCore {
|
|
|
163
179
|
}
|
|
164
180
|
);
|
|
165
181
|
if (this.options.routeMasks) {
|
|
166
|
-
processRouteMasks(this.options.routeMasks, processedTree);
|
|
167
|
-
}
|
|
168
|
-
this.routesById = routesById;
|
|
169
|
-
this.routesByPath = routesByPath;
|
|
170
|
-
this.processedTree = processedTree;
|
|
171
|
-
const notFoundRoute = this.options.notFoundRoute;
|
|
172
|
-
if (notFoundRoute) {
|
|
173
|
-
notFoundRoute.init({
|
|
174
|
-
originalIndex: 99999999999
|
|
175
|
-
});
|
|
176
|
-
this.routesById[notFoundRoute.id] = notFoundRoute;
|
|
182
|
+
processRouteMasks(this.options.routeMasks, result.processedTree);
|
|
177
183
|
}
|
|
184
|
+
return result;
|
|
178
185
|
};
|
|
179
186
|
this.subscribe = (eventType, fn) => {
|
|
180
187
|
const listener = {
|
|
@@ -229,7 +236,6 @@ class RouterCore {
|
|
|
229
236
|
}
|
|
230
237
|
return location;
|
|
231
238
|
};
|
|
232
|
-
this.resolvePathCache = createLRUCache(1e3);
|
|
233
239
|
this.resolvePathWithBase = (from, path) => {
|
|
234
240
|
const resolvedPath = resolvePath({
|
|
235
241
|
base: from,
|
|
@@ -284,26 +290,23 @@ class RouterCore {
|
|
|
284
290
|
this.buildLocation = (opts) => {
|
|
285
291
|
const build = (dest = {}) => {
|
|
286
292
|
const currentLocation = dest._fromLocation || this.pendingBuiltLocation || this.latestLocation;
|
|
287
|
-
const
|
|
288
|
-
_buildLocation: true
|
|
289
|
-
});
|
|
290
|
-
const lastMatch = last(allCurrentLocationMatches);
|
|
293
|
+
const lightweightResult = this.matchRoutesLightweight(currentLocation);
|
|
291
294
|
if (dest.from && process.env.NODE_ENV !== "production" && dest._isNavigate) {
|
|
292
295
|
const allFromMatches = this.getMatchedRoutes(dest.from).matchedRoutes;
|
|
293
|
-
const matchedFrom = findLast(
|
|
296
|
+
const matchedFrom = findLast(lightweightResult.matchedRoutes, (d) => {
|
|
294
297
|
return comparePaths(d.fullPath, dest.from);
|
|
295
298
|
});
|
|
296
299
|
const matchedCurrent = findLast(allFromMatches, (d) => {
|
|
297
|
-
return comparePaths(d.fullPath,
|
|
300
|
+
return comparePaths(d.fullPath, lightweightResult.fullPath);
|
|
298
301
|
});
|
|
299
302
|
if (!matchedFrom && !matchedCurrent) {
|
|
300
303
|
console.warn(`Could not find match for from: ${dest.from}`);
|
|
301
304
|
}
|
|
302
305
|
}
|
|
303
|
-
const defaultedFromPath = dest.unsafeRelative === "path" ? currentLocation.pathname : dest.from ??
|
|
306
|
+
const defaultedFromPath = dest.unsafeRelative === "path" ? currentLocation.pathname : dest.from ?? lightweightResult.fullPath;
|
|
304
307
|
const fromPath = this.resolvePathWithBase(defaultedFromPath, ".");
|
|
305
|
-
const fromSearch =
|
|
306
|
-
const fromParams = { ...
|
|
308
|
+
const fromSearch = lightweightResult.search;
|
|
309
|
+
const fromParams = { ...lightweightResult.params };
|
|
307
310
|
const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
|
|
308
311
|
const nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : Object.assign(
|
|
309
312
|
fromParams,
|
|
@@ -1032,6 +1035,22 @@ class RouterCore {
|
|
|
1032
1035
|
get state() {
|
|
1033
1036
|
return this.__store.state;
|
|
1034
1037
|
}
|
|
1038
|
+
setRoutes({
|
|
1039
|
+
routesById,
|
|
1040
|
+
routesByPath,
|
|
1041
|
+
processedTree
|
|
1042
|
+
}) {
|
|
1043
|
+
this.routesById = routesById;
|
|
1044
|
+
this.routesByPath = routesByPath;
|
|
1045
|
+
this.processedTree = processedTree;
|
|
1046
|
+
const notFoundRoute = this.options.notFoundRoute;
|
|
1047
|
+
if (notFoundRoute) {
|
|
1048
|
+
notFoundRoute.init({
|
|
1049
|
+
originalIndex: 99999999999
|
|
1050
|
+
});
|
|
1051
|
+
this.routesById[notFoundRoute.id] = notFoundRoute;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1035
1054
|
get looseRoutesById() {
|
|
1036
1055
|
return this.routesById;
|
|
1037
1056
|
}
|
|
@@ -1110,32 +1129,18 @@ class RouterCore {
|
|
|
1110
1129
|
const strictParams = existingMatch?._strictParams ?? usedParams;
|
|
1111
1130
|
let paramsError = void 0;
|
|
1112
1131
|
if (!existingMatch) {
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1132
|
+
try {
|
|
1133
|
+
extractStrictParams(route, usedParams, parsedParams, strictParams);
|
|
1134
|
+
} catch (err) {
|
|
1135
|
+
if (isNotFound(err) || isRedirect(err)) {
|
|
1136
|
+
paramsError = err;
|
|
1137
|
+
} else {
|
|
1138
|
+
paramsError = new PathParamError(err.message, {
|
|
1139
|
+
cause: err
|
|
1140
|
+
});
|
|
1118
1141
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
if (strictParseParams) {
|
|
1122
|
-
try {
|
|
1123
|
-
Object.assign(
|
|
1124
|
-
strictParams,
|
|
1125
|
-
strictParseParams(strictParams)
|
|
1126
|
-
);
|
|
1127
|
-
} catch (err) {
|
|
1128
|
-
if (isNotFound(err) || isRedirect(err)) {
|
|
1129
|
-
paramsError = err;
|
|
1130
|
-
} else {
|
|
1131
|
-
paramsError = new PathParamError(err.message, {
|
|
1132
|
-
cause: err
|
|
1133
|
-
});
|
|
1134
|
-
}
|
|
1135
|
-
if (opts?.throwOnError) {
|
|
1136
|
-
throw paramsError;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1142
|
+
if (opts?.throwOnError) {
|
|
1143
|
+
throw paramsError;
|
|
1139
1144
|
}
|
|
1140
1145
|
}
|
|
1141
1146
|
}
|
|
@@ -1204,7 +1209,7 @@ class RouterCore {
|
|
|
1204
1209
|
matches.forEach((match, index) => {
|
|
1205
1210
|
const route = this.looseRoutesById[match.routeId];
|
|
1206
1211
|
const existingMatch = this.getMatch(match.id);
|
|
1207
|
-
if (!existingMatch
|
|
1212
|
+
if (!existingMatch) {
|
|
1208
1213
|
const parentMatch = matches[index - 1];
|
|
1209
1214
|
const parentContext = getParentContext(parentMatch);
|
|
1210
1215
|
if (route.options.context) {
|
|
@@ -1231,6 +1236,53 @@ class RouterCore {
|
|
|
1231
1236
|
});
|
|
1232
1237
|
return matches;
|
|
1233
1238
|
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Lightweight route matching for buildLocation.
|
|
1241
|
+
* Only computes fullPath, accumulated search, and params - skipping expensive
|
|
1242
|
+
* operations like AbortController, ControlledPromise, loaderDeps, and full match objects.
|
|
1243
|
+
*/
|
|
1244
|
+
matchRoutesLightweight(location) {
|
|
1245
|
+
const { matchedRoutes, routeParams, parsedParams } = this.getMatchedRoutes(
|
|
1246
|
+
location.pathname
|
|
1247
|
+
);
|
|
1248
|
+
const lastRoute = last(matchedRoutes);
|
|
1249
|
+
const accumulatedSearch = { ...location.search };
|
|
1250
|
+
for (const route of matchedRoutes) {
|
|
1251
|
+
try {
|
|
1252
|
+
Object.assign(
|
|
1253
|
+
accumulatedSearch,
|
|
1254
|
+
validateSearch(route.options.validateSearch, accumulatedSearch)
|
|
1255
|
+
);
|
|
1256
|
+
} catch {
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
const lastStateMatch = last(this.state.matches);
|
|
1260
|
+
const canReuseParams = lastStateMatch && lastStateMatch.routeId === lastRoute.id && location.pathname === this.state.location.pathname;
|
|
1261
|
+
let params;
|
|
1262
|
+
if (canReuseParams) {
|
|
1263
|
+
params = lastStateMatch.params;
|
|
1264
|
+
} else {
|
|
1265
|
+
const strictParams = { ...routeParams };
|
|
1266
|
+
for (const route of matchedRoutes) {
|
|
1267
|
+
try {
|
|
1268
|
+
extractStrictParams(
|
|
1269
|
+
route,
|
|
1270
|
+
routeParams,
|
|
1271
|
+
parsedParams ?? {},
|
|
1272
|
+
strictParams
|
|
1273
|
+
);
|
|
1274
|
+
} catch {
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
params = strictParams;
|
|
1278
|
+
}
|
|
1279
|
+
return {
|
|
1280
|
+
matchedRoutes,
|
|
1281
|
+
fullPath: lastRoute.fullPath,
|
|
1282
|
+
search: accumulatedSearch,
|
|
1283
|
+
params
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1234
1286
|
}
|
|
1235
1287
|
class SearchParamError extends Error {
|
|
1236
1288
|
}
|
|
@@ -1393,6 +1445,21 @@ function findGlobalNotFoundRouteId(notFoundMode, routes) {
|
|
|
1393
1445
|
}
|
|
1394
1446
|
return rootRouteId;
|
|
1395
1447
|
}
|
|
1448
|
+
function extractStrictParams(route, referenceParams, parsedParams, accumulatedParams) {
|
|
1449
|
+
const parseParams = route.options.params?.parse ?? route.options.parseParams;
|
|
1450
|
+
if (parseParams) {
|
|
1451
|
+
if (route.options.skipRouteOnParseError) {
|
|
1452
|
+
for (const key in referenceParams) {
|
|
1453
|
+
if (key in parsedParams) {
|
|
1454
|
+
accumulatedParams[key] = parsedParams[key];
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
} else {
|
|
1458
|
+
const result = parseParams(accumulatedParams);
|
|
1459
|
+
Object.assign(accumulatedParams, result);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1396
1463
|
export {
|
|
1397
1464
|
PathParamError,
|
|
1398
1465
|
RouterCore,
|