@tanstack/router-core 1.171.15 → 1.171.16-pre.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/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +3 -12
- package/dist/cjs/await-signal.cjs +21 -0
- package/dist/cjs/await-signal.cjs.map +1 -0
- package/dist/cjs/await-signal.d.cts +1 -0
- package/dist/cjs/index.cjs +3 -1
- package/dist/cjs/index.d.cts +3 -2
- package/dist/cjs/isServer/client.cjs +2 -0
- package/dist/cjs/isServer/client.cjs.map +1 -1
- package/dist/cjs/isServer/client.d.cts +1 -0
- package/dist/cjs/isServer/development.cjs +2 -0
- package/dist/cjs/isServer/development.cjs.map +1 -1
- package/dist/cjs/isServer/development.d.cts +1 -0
- package/dist/cjs/isServer/server.cjs +2 -0
- package/dist/cjs/isServer/server.cjs.map +1 -1
- package/dist/cjs/isServer/server.d.cts +1 -0
- package/dist/cjs/load-client.cjs +1470 -0
- package/dist/cjs/load-client.cjs.map +1 -0
- package/dist/cjs/load-client.d.cts +147 -0
- package/dist/cjs/load-server.cjs +565 -0
- package/dist/cjs/load-server.cjs.map +1 -0
- package/dist/cjs/load-server.d.cts +16 -0
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/redirect.d.cts +0 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/router.cjs +187 -442
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +61 -51
- package/dist/cjs/ssr/client.cjs +2 -2
- package/dist/cjs/ssr/createRequestHandler.cjs +60 -9
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/createRequestHandler.d.cts +1 -0
- package/dist/cjs/ssr/handlerCallback.cjs +49 -4
- package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
- package/dist/cjs/ssr/handlerCallback.d.cts +3 -0
- package/dist/cjs/ssr/server.cjs +4 -0
- package/dist/cjs/ssr/server.d.cts +2 -2
- package/dist/cjs/ssr/ssr-client.d.cts +1 -10
- package/dist/cjs/ssr/ssr-match-id.cjs +2 -2
- package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +6 -6
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +27 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/ssr/transformStreamWithRouter.d.cts +2 -0
- package/dist/cjs/ssr/types.d.cts +0 -1
- package/dist/cjs/stores.cjs +30 -104
- package/dist/cjs/stores.cjs.map +1 -1
- package/dist/cjs/stores.d.cts +7 -32
- package/dist/cjs/utils.cjs +0 -4
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/esm/Matches.d.ts +3 -12
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/await-signal.d.ts +1 -0
- package/dist/esm/await-signal.js +21 -0
- package/dist/esm/await-signal.js.map +1 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +3 -2
- package/dist/esm/isServer/client.d.ts +1 -0
- package/dist/esm/isServer/client.js +2 -1
- package/dist/esm/isServer/client.js.map +1 -1
- package/dist/esm/isServer/development.d.ts +1 -0
- package/dist/esm/isServer/development.js +2 -1
- package/dist/esm/isServer/development.js.map +1 -1
- package/dist/esm/isServer/server.d.ts +1 -0
- package/dist/esm/isServer/server.js +2 -1
- package/dist/esm/isServer/server.js.map +1 -1
- package/dist/esm/load-client.d.ts +147 -0
- package/dist/esm/load-client.js +1462 -0
- package/dist/esm/load-client.js.map +1 -0
- package/dist/esm/load-server.d.ts +16 -0
- package/dist/esm/load-server.js +565 -0
- package/dist/esm/load-server.js.map +1 -0
- package/dist/esm/redirect.d.ts +0 -1
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +61 -51
- package/dist/esm/router.js +188 -444
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/ssr/client.js +1 -1
- package/dist/esm/ssr/createRequestHandler.d.ts +1 -0
- package/dist/esm/ssr/createRequestHandler.js +61 -11
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/handlerCallback.d.ts +3 -0
- package/dist/esm/ssr/handlerCallback.js +47 -5
- package/dist/esm/ssr/handlerCallback.js.map +1 -1
- package/dist/esm/ssr/server.d.ts +2 -2
- package/dist/esm/ssr/server.js +3 -3
- package/dist/esm/ssr/ssr-client.d.ts +1 -10
- package/dist/esm/ssr/ssr-match-id.js +2 -2
- package/dist/esm/ssr/ssr-match-id.js.map +1 -1
- package/dist/esm/ssr/ssr-server.js +6 -6
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.d.ts +2 -0
- package/dist/esm/ssr/transformStreamWithRouter.js +27 -1
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/dist/esm/ssr/types.d.ts +0 -1
- package/dist/esm/stores.d.ts +7 -32
- package/dist/esm/stores.js +30 -104
- package/dist/esm/stores.js.map +1 -1
- package/dist/esm/utils.js +1 -4
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/Matches.ts +6 -21
- package/src/await-signal.ts +27 -0
- package/src/index.ts +1 -3
- package/src/isServer/client.ts +1 -0
- package/src/isServer/development.ts +1 -0
- package/src/isServer/server.ts +1 -0
- package/src/load-client.ts +2701 -0
- package/src/load-server.ts +849 -0
- package/src/redirect.ts +0 -1
- package/src/route.ts +2 -11
- package/src/router.ts +379 -769
- package/src/ssr/createRequestHandler.ts +109 -16
- package/src/ssr/handlerCallback.ts +76 -10
- package/src/ssr/server.ts +4 -1
- package/src/ssr/ssr-client.ts +1 -310
- package/src/ssr/ssr-match-id.ts +11 -2
- package/src/ssr/ssr-server.ts +9 -8
- package/src/ssr/transformStreamWithRouter.ts +37 -1
- package/src/ssr/types.ts +0 -1
- package/src/stores.ts +46 -208
- package/dist/cjs/load-matches.cjs +0 -658
- package/dist/cjs/load-matches.cjs.map +0 -1
- package/dist/cjs/load-matches.d.cts +0 -18
- package/dist/cjs/ssr/ssr-client.cjs +0 -183
- package/dist/cjs/ssr/ssr-client.cjs.map +0 -1
- package/dist/esm/load-matches.d.ts +0 -18
- package/dist/esm/load-matches.js +0 -656
- package/dist/esm/load-matches.js.map +0 -1
- package/dist/esm/ssr/ssr-client.js +0 -183
- package/dist/esm/ssr/ssr-client.js.map +0 -1
- package/src/load-matches.ts +0 -1278
package/dist/esm/router.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_PROTOCOL_ALLOWLIST,
|
|
1
|
+
import { DEFAULT_PROTOCOL_ALLOWLIST, decodePath, deepEqual, encodePathLikeUrl, findLast, functionalUpdate, hasKeys, isDangerousProtocol, last, nullReplaceEqualDeep, replaceEqualDeep } from "./utils.js";
|
|
2
2
|
import { createLRUCache } from "./lru-cache.js";
|
|
3
3
|
import { buildRouteBranch, findFlatMatch, findRouteMatch, findSingleMatch, processRouteMasks, processRouteTree } from "./new-process-route-tree.js";
|
|
4
4
|
import { cleanPath, compileDecodeCharMap, interpolatePath, resolvePath, trimPath, trimPathRight } from "./path.js";
|
|
@@ -6,13 +6,16 @@ import { isNotFound } from "./not-found.js";
|
|
|
6
6
|
import { setupScrollRestoration } from "./scroll-restoration.js";
|
|
7
7
|
import { defaultParseSearch, defaultStringifySearch } from "./searchParams.js";
|
|
8
8
|
import { rootRouteId } from "./root.js";
|
|
9
|
-
import { isRedirect
|
|
10
|
-
import {
|
|
9
|
+
import { isRedirect } from "./redirect.js";
|
|
10
|
+
import { loadClientRoute, loadRouteChunk, preloadClientRoute, refreshClientRoute, replaceRouteChunk, transferMatchResources } from "./load-client.js";
|
|
11
11
|
import { composeRewrites, executeRewriteInput, executeRewriteOutput, rewriteBasepath } from "./rewrite.js";
|
|
12
12
|
import { createRouterStores } from "./stores.js";
|
|
13
13
|
import { createBrowserHistory, parseHref } from "@tanstack/history";
|
|
14
|
-
import { isServer } from "@tanstack/router-core/isServer";
|
|
14
|
+
import { isServer, loadServerRoute } from "@tanstack/router-core/isServer";
|
|
15
15
|
//#region src/router.ts
|
|
16
|
+
function routeNeedsLoad(route) {
|
|
17
|
+
return route.options.loader || route.options.beforeLoad || route.lazyFn || route.options.component?.preload || route.options.pendingComponent?.preload;
|
|
18
|
+
}
|
|
16
19
|
/**
|
|
17
20
|
* Convert an unknown error into a minimal, serializable object.
|
|
18
21
|
* Includes name and message (and stack in development).
|
|
@@ -39,17 +42,34 @@ const trailingSlashOptions = {
|
|
|
39
42
|
* resolved locations.
|
|
40
43
|
*/
|
|
41
44
|
function getLocationChangeInfo(location, resolvedLocation) {
|
|
42
|
-
const fromLocation = resolvedLocation;
|
|
43
|
-
const toLocation = location;
|
|
44
45
|
return {
|
|
45
|
-
fromLocation,
|
|
46
|
-
toLocation,
|
|
47
|
-
pathChanged:
|
|
48
|
-
hrefChanged:
|
|
49
|
-
hashChanged:
|
|
46
|
+
fromLocation: resolvedLocation,
|
|
47
|
+
toLocation: location,
|
|
48
|
+
pathChanged: resolvedLocation?.pathname !== location.pathname,
|
|
49
|
+
hrefChanged: resolvedLocation?.href !== location.href,
|
|
50
|
+
hashChanged: resolvedLocation?.hash !== location.hash
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
53
|
/**
|
|
54
|
+
* Return only state owned by the application, excluding volatile history
|
|
55
|
+
* bookkeeping. Mask payloads (`__tempLocation`/`__tempKey`) are kept: they
|
|
56
|
+
* distinguish otherwise-identical locations.
|
|
57
|
+
*/
|
|
58
|
+
function _getUserHistoryState({ key: _key, __TSR_key: _tsrKey, __TSR_index: _tsrIndex, __hashScrollIntoViewOptions: _hashScroll, ...state }) {
|
|
59
|
+
return state;
|
|
60
|
+
}
|
|
61
|
+
/** Run route lifecycle callbacks in leave/enter/stay phases. */
|
|
62
|
+
function runRouteLifecycle(router, previous, matches, isCurrent) {
|
|
63
|
+
for (const match of previous) {
|
|
64
|
+
if (isCurrent?.() === false) return;
|
|
65
|
+
if (!matches.some((candidate) => candidate.routeId === match.routeId)) router.routesById[match.routeId].options.onLeave?.(match);
|
|
66
|
+
}
|
|
67
|
+
for (const match of matches) {
|
|
68
|
+
if (isCurrent?.() === false) return;
|
|
69
|
+
router.routesById[match.routeId].options[previous.some((candidate) => candidate.routeId === match.routeId) ? "onStay" : "onEnter"]?.(match);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
53
73
|
* Core, framework-agnostic router engine that powers TanStack Router.
|
|
54
74
|
*
|
|
55
75
|
* Provides navigation, matching, loading, preloading, caching and event APIs
|
|
@@ -65,12 +85,15 @@ var RouterCore = class {
|
|
|
65
85
|
constructor(options, getStoreConfig) {
|
|
66
86
|
this.tempLocationKey = `${Math.round(Math.random() * 1e7)}`;
|
|
67
87
|
this._scroll = { next: true };
|
|
68
|
-
this.shouldViewTransition = void 0;
|
|
69
|
-
this.isViewTransitionTypesSupported = void 0;
|
|
70
88
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
89
|
+
this._cache = /* @__PURE__ */ new Map();
|
|
90
|
+
this._committed = [];
|
|
71
91
|
this.routeBranchCache = /* @__PURE__ */ new WeakMap();
|
|
72
92
|
this.lightweightCache = /* @__PURE__ */ new WeakMap();
|
|
73
|
-
this.startTransition = (fn) =>
|
|
93
|
+
this.startTransition = async (fn) => {
|
|
94
|
+
fn();
|
|
95
|
+
return false;
|
|
96
|
+
};
|
|
74
97
|
this.update = (newOptions) => {
|
|
75
98
|
if (process.env.NODE_ENV !== "production") {
|
|
76
99
|
if (newOptions.notFoundRoute) console.warn("The notFoundRoute API is deprecated and will be removed in the next major version. See https://tanstack.com/router/v1/docs/framework/react/guide/not-found-errors#migrating-from-notfoundroute for more info.");
|
|
@@ -83,7 +106,7 @@ var RouterCore = class {
|
|
|
83
106
|
...prevOptions,
|
|
84
107
|
...newOptions
|
|
85
108
|
};
|
|
86
|
-
this.isServer = this.options.isServer ?? typeof document === "undefined";
|
|
109
|
+
this.isServer = this.options.isServer ?? isServer ?? typeof document === "undefined";
|
|
87
110
|
this.protocolAllowlist = new Set(this.options.protocolAllowlist);
|
|
88
111
|
if (this.options.pathParamsAllowedCharacters) this.pathParamsDecoder = compileDecodeCharMap(this.options.pathParamsAllowedCharacters);
|
|
89
112
|
if (!this.history || this.options.history && this.options.history !== this.history) if (!this.options.history) {
|
|
@@ -114,10 +137,9 @@ var RouterCore = class {
|
|
|
114
137
|
if (!this.stores && this.latestLocation) {
|
|
115
138
|
const config = this.getStoreConfig(this);
|
|
116
139
|
this.batch = config.batch;
|
|
117
|
-
this.stores = createRouterStores(
|
|
140
|
+
this.stores = createRouterStores(this.latestLocation, config);
|
|
118
141
|
if (!(isServer ?? this.isServer)) setupScrollRestoration(this);
|
|
119
142
|
}
|
|
120
|
-
let needsLocationUpdate = false;
|
|
121
143
|
const nextBasepath = this.options.basepath ?? "/";
|
|
122
144
|
const nextRewriteOption = this.options.rewrite;
|
|
123
145
|
if (basepathWasUnset || prevBasepath !== nextBasepath || prevRewriteOption !== nextRewriteOption) {
|
|
@@ -128,10 +150,8 @@ var RouterCore = class {
|
|
|
128
150
|
if (nextRewriteOption) rewrites.push(nextRewriteOption);
|
|
129
151
|
this.rewrite = rewrites.length === 0 ? void 0 : rewrites.length === 1 ? rewrites[0] : composeRewrites(rewrites);
|
|
130
152
|
if (this.history) this.updateLatestLocation();
|
|
131
|
-
|
|
153
|
+
if (this.stores) this.stores.location.set(this.latestLocation);
|
|
132
154
|
}
|
|
133
|
-
if (needsLocationUpdate && this.stores) this.stores.location.set(this.latestLocation);
|
|
134
|
-
if (typeof window !== "undefined" && "CSS" in window && typeof window.CSS?.supports === "function") this.isViewTransitionTypesSupported = window.CSS.supports("selector(:active-view-transition-type(a))");
|
|
135
155
|
};
|
|
136
156
|
this.updateLatestLocation = () => {
|
|
137
157
|
this.latestLocation = this.parseLocation(this.history.location, this.latestLocation);
|
|
@@ -154,9 +174,11 @@ var RouterCore = class {
|
|
|
154
174
|
};
|
|
155
175
|
};
|
|
156
176
|
this.emit = (routerEvent) => {
|
|
157
|
-
this.subscribers
|
|
158
|
-
|
|
159
|
-
})
|
|
177
|
+
for (const listener of this.subscribers) if (listener.eventType === routerEvent.type) try {
|
|
178
|
+
listener.fn(routerEvent);
|
|
179
|
+
} catch (e) {
|
|
180
|
+
console.error(e);
|
|
181
|
+
}
|
|
160
182
|
};
|
|
161
183
|
this.parseLocation = (locationToParse, previousLocation) => {
|
|
162
184
|
const parse = ({ pathname, search, hash, href, state }) => {
|
|
@@ -220,33 +242,18 @@ var RouterCore = class {
|
|
|
220
242
|
return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
|
|
221
243
|
};
|
|
222
244
|
this.getMatchedRoutes = (pathname) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (!match) return;
|
|
232
|
-
match.abortController.abort();
|
|
233
|
-
clearTimeout(match._nonReactive.pendingTimeout);
|
|
234
|
-
match._nonReactive.pendingTimeout = void 0;
|
|
235
|
-
};
|
|
236
|
-
this.cancelMatches = () => {
|
|
237
|
-
this.stores.pendingIds.get().forEach((matchId) => {
|
|
238
|
-
this.cancelMatch(matchId);
|
|
239
|
-
});
|
|
240
|
-
this.stores.matchesId.get().forEach((matchId) => {
|
|
241
|
-
if (this.stores.pendingMatchStores.has(matchId)) return;
|
|
242
|
-
const match = this.stores.matchStores.get(matchId)?.get();
|
|
243
|
-
if (!match) return;
|
|
244
|
-
if (match.status === "pending" || match.isFetching === "loader") this.cancelMatch(matchId);
|
|
245
|
-
});
|
|
245
|
+
const routeParams = Object.create(null);
|
|
246
|
+
const match = findRouteMatch(trimPathRight(pathname), this.processedTree, true);
|
|
247
|
+
if (match) Object.assign(routeParams, match.rawParams);
|
|
248
|
+
return {
|
|
249
|
+
matchedRoutes: match?.branch || [this.routesById["__root__"]],
|
|
250
|
+
routeParams,
|
|
251
|
+
foundRoute: match?.route
|
|
252
|
+
};
|
|
246
253
|
};
|
|
247
254
|
this.buildLocation = (opts) => {
|
|
248
255
|
const build = (dest = {}) => {
|
|
249
|
-
const currentLocation = dest._fromLocation || this.
|
|
256
|
+
const currentLocation = dest._fromLocation || this._pendingLocation || this.latestLocation;
|
|
250
257
|
const lightweightResult = this.matchRoutesLightweight(currentLocation);
|
|
251
258
|
if (dest.from && process.env.NODE_ENV !== "production" && dest._isNavigate) {
|
|
252
259
|
const allFromMatches = this.getMatchedRoutes(dest.from).matchedRoutes;
|
|
@@ -264,7 +271,7 @@ var RouterCore = class {
|
|
|
264
271
|
const fromParams = Object.assign(Object.create(null), lightweightResult.params);
|
|
265
272
|
const sourcePath = destTo?.charCodeAt(0) === 47 ? "/" : this.resolvePathWithBase(defaultedFromPath, ".");
|
|
266
273
|
const nextTo = destTo ? this.resolvePathWithBase(sourcePath, destTo) : sourcePath;
|
|
267
|
-
const nextParams =
|
|
274
|
+
const nextParams = resolveNextParams(dest.params, fromParams);
|
|
268
275
|
const destRoute = this.routesByPath[trimPathRight(nextTo)];
|
|
269
276
|
let destRoutes;
|
|
270
277
|
if (destRoute) destRoutes = this.getRouteBranch(destRoute);
|
|
@@ -303,12 +310,7 @@ var RouterCore = class {
|
|
|
303
310
|
});
|
|
304
311
|
nextSearch = validatedSearch;
|
|
305
312
|
}
|
|
306
|
-
nextSearch = applySearchMiddleware(
|
|
307
|
-
search: nextSearch,
|
|
308
|
-
dest,
|
|
309
|
-
destRoutes,
|
|
310
|
-
_includeValidateSearch: opts._includeValidateSearch
|
|
311
|
-
});
|
|
313
|
+
nextSearch = applySearchMiddleware(nextSearch, dest, destRoutes, opts._includeValidateSearch);
|
|
312
314
|
nextSearch = nullReplaceEqualDeep(fromSearch, nextSearch);
|
|
313
315
|
const searchStr = this.options.stringifySearch(nextSearch);
|
|
314
316
|
const hash = dest.hash === true ? currentLocation.hash : dest.hash ? functionalUpdate(dest.hash, currentLocation.hash) : void 0;
|
|
@@ -353,7 +355,7 @@ var RouterCore = class {
|
|
|
353
355
|
if (match) {
|
|
354
356
|
Object.assign(params, match.rawParams);
|
|
355
357
|
const { from: _from, params: maskParams, ...maskProps } = match.route;
|
|
356
|
-
const nextParams =
|
|
358
|
+
const nextParams = resolveNextParams(maskParams, params);
|
|
357
359
|
maskedDest = {
|
|
358
360
|
from: opts.from,
|
|
359
361
|
...maskProps,
|
|
@@ -374,29 +376,18 @@ var RouterCore = class {
|
|
|
374
376
|
};
|
|
375
377
|
this.commitLocation = async ({ viewTransition, ignoreBlocker, ...next }) => {
|
|
376
378
|
let historyAction;
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
"__hashScrollIntoViewOptions"
|
|
383
|
-
];
|
|
384
|
-
ignoredProps.forEach((prop) => {
|
|
385
|
-
next.state[prop] = this.latestLocation.state[prop];
|
|
386
|
-
});
|
|
387
|
-
const isEqual = deepEqual(next.state, this.latestLocation.state);
|
|
388
|
-
ignoredProps.forEach((prop) => {
|
|
389
|
-
delete next.state[prop];
|
|
390
|
-
});
|
|
391
|
-
return isEqual;
|
|
392
|
-
};
|
|
393
|
-
const isSameUrl = trimPathRight(this.latestLocation.href) === trimPathRight(next.href);
|
|
394
|
-
let previousCommitPromise = this.commitLocationPromise;
|
|
395
|
-
this.commitLocationPromise = createControlledPromise(() => {
|
|
396
|
-
previousCommitPromise?.resolve();
|
|
397
|
-
previousCommitPromise = void 0;
|
|
379
|
+
const isSameLocation = trimPathRight(this.latestLocation.href) === trimPathRight(next.href) && deepEqual(_getUserHistoryState(next.state), _getUserHistoryState(this.latestLocation.state));
|
|
380
|
+
const previousCommitPromise = this._commitPromise;
|
|
381
|
+
let resolve;
|
|
382
|
+
const commitPromise = new Promise((done) => {
|
|
383
|
+
resolve = done;
|
|
398
384
|
});
|
|
399
|
-
|
|
385
|
+
commitPromise.resolve = () => {
|
|
386
|
+
resolve();
|
|
387
|
+
previousCommitPromise?.resolve();
|
|
388
|
+
};
|
|
389
|
+
this._commitPromise = commitPromise;
|
|
390
|
+
if (isSameLocation) this.load({ _dedupe: true });
|
|
400
391
|
else {
|
|
401
392
|
let { maskedLocation, hashScrollIntoView, ...nextHistory } = next;
|
|
402
393
|
if (maskedLocation) {
|
|
@@ -424,12 +415,12 @@ var RouterCore = class {
|
|
|
424
415
|
this.shouldViewTransition = viewTransition;
|
|
425
416
|
historyAction = next.replace ? "REPLACE" : "PUSH";
|
|
426
417
|
this.history[historyAction === "REPLACE" ? "replace" : "push"](nextHistory.publicHref, nextHistory.state, { ignoreBlocker });
|
|
418
|
+
if (!this.history.subscribers.size) this.load({ action: { type: historyAction } });
|
|
427
419
|
}
|
|
428
420
|
this._scroll.next = next.resetScroll ?? true;
|
|
429
|
-
|
|
430
|
-
return this.commitLocationPromise;
|
|
421
|
+
return this._commitPromise;
|
|
431
422
|
};
|
|
432
|
-
this.buildAndCommitLocation = ({ replace, resetScroll, hashScrollIntoView, viewTransition, ignoreBlocker, href, ...rest } = {}) => {
|
|
423
|
+
this.buildAndCommitLocation = ({ replace, resetScroll, hashScrollIntoView, viewTransition, ignoreBlocker, _redirects, href, ...rest } = {}) => {
|
|
433
424
|
if (href) {
|
|
434
425
|
const currentIndex = this.history.location.state.__TSR_index;
|
|
435
426
|
const parsed = parseHref(href, { __TSR_index: replace ? currentIndex : currentIndex + 1 });
|
|
@@ -442,7 +433,8 @@ var RouterCore = class {
|
|
|
442
433
|
...rest,
|
|
443
434
|
_includeValidateSearch: true
|
|
444
435
|
});
|
|
445
|
-
|
|
436
|
+
if (_redirects) location._redirects = _redirects;
|
|
437
|
+
this._pendingLocation = location;
|
|
446
438
|
const commitPromise = this.commitLocation({
|
|
447
439
|
...location,
|
|
448
440
|
viewTransition,
|
|
@@ -452,7 +444,7 @@ var RouterCore = class {
|
|
|
452
444
|
ignoreBlocker
|
|
453
445
|
});
|
|
454
446
|
queueMicrotask(() => {
|
|
455
|
-
if (this.
|
|
447
|
+
if (this._pendingLocation === location) this._pendingLocation = void 0;
|
|
456
448
|
});
|
|
457
449
|
return commitPromise;
|
|
458
450
|
};
|
|
@@ -498,216 +490,63 @@ var RouterCore = class {
|
|
|
498
490
|
_isNavigate: true
|
|
499
491
|
});
|
|
500
492
|
};
|
|
501
|
-
this.beforeLoad = () => {
|
|
502
|
-
this.cancelMatches();
|
|
503
|
-
this.updateLatestLocation();
|
|
504
|
-
if (isServer ?? this.isServer) {
|
|
505
|
-
const nextLocation = this.buildLocation({
|
|
506
|
-
to: this.latestLocation.pathname,
|
|
507
|
-
search: true,
|
|
508
|
-
params: true,
|
|
509
|
-
hash: true,
|
|
510
|
-
state: true,
|
|
511
|
-
_includeValidateSearch: true
|
|
512
|
-
});
|
|
513
|
-
if (this.latestLocation.publicHref !== nextLocation.publicHref) {
|
|
514
|
-
const href = this.getParsedLocationHref(nextLocation);
|
|
515
|
-
if (nextLocation.external) throw redirect({ href });
|
|
516
|
-
else throw redirect({
|
|
517
|
-
href,
|
|
518
|
-
_builtLocation: nextLocation
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
const pendingMatches = this.matchRoutes(this.latestLocation);
|
|
523
|
-
const nextCachedMatches = this.stores.cachedMatches.get().filter((d) => !pendingMatches.some((e) => e.id === d.id));
|
|
524
|
-
this.batch(() => {
|
|
525
|
-
this.stores.status.set("pending");
|
|
526
|
-
this.stores.statusCode.set(200);
|
|
527
|
-
this.stores.isLoading.set(true);
|
|
528
|
-
this.stores.location.set(this.latestLocation);
|
|
529
|
-
this.stores.setPending(pendingMatches);
|
|
530
|
-
this.stores.setCached(nextCachedMatches);
|
|
531
|
-
});
|
|
532
|
-
};
|
|
533
493
|
this.load = async (opts) => {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const previousLocation = this.stores.resolvedLocation.get() ?? this.stores.location.get();
|
|
539
|
-
loadPromise = new Promise((resolve) => {
|
|
540
|
-
this.startTransition(async () => {
|
|
541
|
-
try {
|
|
542
|
-
this.beforeLoad();
|
|
543
|
-
if (historyAction) this._scroll.hash = historyAction === "PUSH" || historyAction === "REPLACE";
|
|
544
|
-
const next = this.latestLocation;
|
|
545
|
-
const locationChangeInfo = getLocationChangeInfo(next, this.stores.resolvedLocation.get());
|
|
546
|
-
if (!this.stores.redirect.get()) this.emit({
|
|
547
|
-
type: "onBeforeNavigate",
|
|
548
|
-
...locationChangeInfo
|
|
549
|
-
});
|
|
550
|
-
this.emit({
|
|
551
|
-
type: "onBeforeLoad",
|
|
552
|
-
...locationChangeInfo
|
|
553
|
-
});
|
|
554
|
-
await loadMatches({
|
|
555
|
-
router: this,
|
|
556
|
-
sync: opts?.sync,
|
|
557
|
-
forceStaleReload: previousLocation.href === next.href,
|
|
558
|
-
matches: this.stores.pendingMatches.get(),
|
|
559
|
-
location: next,
|
|
560
|
-
updateMatch: this.updateMatch,
|
|
561
|
-
onReady: async () => {
|
|
562
|
-
this.startTransition(() => {
|
|
563
|
-
this.startViewTransition(async () => {
|
|
564
|
-
let exitingMatches = null;
|
|
565
|
-
let hookExitingMatches = null;
|
|
566
|
-
let hookEnteringMatches = null;
|
|
567
|
-
let hookStayingMatches = null;
|
|
568
|
-
this.batch(() => {
|
|
569
|
-
const pendingMatches = this.stores.pendingMatches.get();
|
|
570
|
-
const mountPending = pendingMatches.length;
|
|
571
|
-
const currentMatches = this.stores.matches.get();
|
|
572
|
-
exitingMatches = mountPending ? currentMatches.filter((match) => !this.stores.pendingMatchStores.has(match.id)) : null;
|
|
573
|
-
const pendingRouteIds = /* @__PURE__ */ new Set();
|
|
574
|
-
for (const s of this.stores.pendingMatchStores.values()) if (s.routeId) pendingRouteIds.add(s.routeId);
|
|
575
|
-
const activeRouteIds = /* @__PURE__ */ new Set();
|
|
576
|
-
for (const s of this.stores.matchStores.values()) if (s.routeId) activeRouteIds.add(s.routeId);
|
|
577
|
-
hookExitingMatches = mountPending ? currentMatches.filter((match) => !pendingRouteIds.has(match.routeId)) : null;
|
|
578
|
-
hookEnteringMatches = mountPending ? pendingMatches.filter((match) => !activeRouteIds.has(match.routeId)) : null;
|
|
579
|
-
hookStayingMatches = mountPending ? pendingMatches.filter((match) => activeRouteIds.has(match.routeId)) : currentMatches;
|
|
580
|
-
this.stores.isLoading.set(false);
|
|
581
|
-
this.stores.loadedAt.set(Date.now());
|
|
582
|
-
/**
|
|
583
|
-
* When committing new matches, cache any exiting matches that are still usable.
|
|
584
|
-
* Routes that resolved with `status: 'error'` or `status: 'notFound'` are
|
|
585
|
-
* deliberately excluded from `cachedMatches` so that subsequent invalidations
|
|
586
|
-
* or reloads re-run their loaders instead of reusing the failed/not-found data.
|
|
587
|
-
*/
|
|
588
|
-
if (mountPending) {
|
|
589
|
-
this.stores.setMatches(pendingMatches);
|
|
590
|
-
this.stores.setPending([]);
|
|
591
|
-
this.stores.setCached([...this.stores.cachedMatches.get(), ...exitingMatches.filter((d) => d.status !== "error" && d.status !== "notFound" && d.status !== "redirected")]);
|
|
592
|
-
this.clearExpiredCache();
|
|
593
|
-
}
|
|
594
|
-
});
|
|
595
|
-
for (const [matches, hook] of [
|
|
596
|
-
[hookExitingMatches, "onLeave"],
|
|
597
|
-
[hookEnteringMatches, "onEnter"],
|
|
598
|
-
[hookStayingMatches, "onStay"]
|
|
599
|
-
]) {
|
|
600
|
-
if (!matches) continue;
|
|
601
|
-
for (const match of matches) this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
} catch (err) {
|
|
608
|
-
if (isRedirect(err)) {
|
|
609
|
-
redirect = err;
|
|
610
|
-
if (!(isServer ?? this.isServer)) this.navigate({
|
|
611
|
-
...redirect.options,
|
|
612
|
-
replace: true,
|
|
613
|
-
ignoreBlocker: true
|
|
614
|
-
});
|
|
615
|
-
} else if (isNotFound(err)) notFound = err;
|
|
616
|
-
const nextStatusCode = redirect ? redirect.status : notFound ? 404 : this.stores.matches.get().some((d) => d.status === "error") ? 500 : 200;
|
|
617
|
-
this.batch(() => {
|
|
618
|
-
this.stores.statusCode.set(nextStatusCode);
|
|
619
|
-
this.stores.redirect.set(redirect);
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
if (this.latestLoadPromise === loadPromise) {
|
|
623
|
-
this.commitLocationPromise?.resolve();
|
|
624
|
-
this.latestLoadPromise = void 0;
|
|
625
|
-
this.commitLocationPromise = void 0;
|
|
626
|
-
}
|
|
627
|
-
resolve();
|
|
628
|
-
});
|
|
629
|
-
});
|
|
630
|
-
this.latestLoadPromise = loadPromise;
|
|
631
|
-
await loadPromise;
|
|
632
|
-
while (this.latestLoadPromise && loadPromise !== this.latestLoadPromise) await this.latestLoadPromise;
|
|
633
|
-
let newStatusCode = void 0;
|
|
634
|
-
if (this.hasNotFoundMatch()) newStatusCode = 404;
|
|
635
|
-
else if (this.stores.matches.get().some((d) => d.status === "error")) newStatusCode = 500;
|
|
636
|
-
if (newStatusCode !== void 0) this.stores.statusCode.set(newStatusCode);
|
|
494
|
+
if (isServer ?? this.isServer) return loadServerRoute(this, opts);
|
|
495
|
+
this.updateLatestLocation();
|
|
496
|
+
if (opts?.action) this._scroll.hash = opts.action.type === "PUSH" || opts.action.type === "REPLACE";
|
|
497
|
+
await loadClientRoute(this, opts);
|
|
637
498
|
};
|
|
638
499
|
this.startViewTransition = (fn) => {
|
|
639
500
|
const shouldViewTransition = this.shouldViewTransition ?? this.options.defaultViewTransition;
|
|
640
501
|
this.shouldViewTransition = void 0;
|
|
641
|
-
if (shouldViewTransition && typeof document
|
|
502
|
+
if (shouldViewTransition && !(isServer ?? typeof document === "undefined") && typeof document.startViewTransition === "function") {
|
|
642
503
|
let startViewTransitionParams;
|
|
643
|
-
if (typeof shouldViewTransition === "object" &&
|
|
504
|
+
if (typeof shouldViewTransition === "object" && window.CSS?.supports?.("selector(:active-view-transition-type(a))")) {
|
|
644
505
|
const next = this.latestLocation;
|
|
645
506
|
const prevLocation = this.stores.resolvedLocation.get();
|
|
646
507
|
const resolvedViewTransitionTypes = typeof shouldViewTransition.types === "function" ? shouldViewTransition.types(getLocationChangeInfo(next, prevLocation)) : shouldViewTransition.types;
|
|
647
|
-
if (resolvedViewTransitionTypes === false)
|
|
648
|
-
fn();
|
|
649
|
-
return;
|
|
650
|
-
}
|
|
508
|
+
if (resolvedViewTransitionTypes === false) return fn();
|
|
651
509
|
startViewTransitionParams = {
|
|
652
510
|
update: fn,
|
|
653
511
|
types: resolvedViewTransitionTypes
|
|
654
512
|
};
|
|
655
513
|
} else startViewTransitionParams = fn;
|
|
656
|
-
document.startViewTransition(startViewTransitionParams);
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
this.updateMatch = (id, updater) => {
|
|
660
|
-
this.startTransition(() => {
|
|
661
|
-
const pendingMatch = this.stores.pendingMatchStores.get(id);
|
|
662
|
-
if (pendingMatch) {
|
|
663
|
-
pendingMatch.set(updater);
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
const activeMatch = this.stores.matchStores.get(id);
|
|
667
|
-
if (activeMatch) {
|
|
668
|
-
activeMatch.set(updater);
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
const cachedMatch = this.stores.cachedMatchStores.get(id);
|
|
672
|
-
if (cachedMatch) {
|
|
673
|
-
const next = updater(cachedMatch.get());
|
|
674
|
-
if (next.status === "redirected") {
|
|
675
|
-
if (this.stores.cachedMatchStores.delete(id)) this.stores.cachedIds.set((prev) => prev.filter((matchId) => matchId !== id));
|
|
676
|
-
} else cachedMatch.set(next);
|
|
677
|
-
}
|
|
678
|
-
});
|
|
679
|
-
};
|
|
680
|
-
this.getMatch = (matchId) => {
|
|
681
|
-
return this.stores.cachedMatchStores.get(matchId)?.get() ?? this.stores.pendingMatchStores.get(matchId)?.get() ?? this.stores.matchStores.get(matchId)?.get();
|
|
514
|
+
return document.startViewTransition(startViewTransitionParams).updateCallbackDone;
|
|
515
|
+
}
|
|
516
|
+
return fn();
|
|
682
517
|
};
|
|
683
518
|
this.invalidate = (opts) => {
|
|
519
|
+
const committedMatches = this._committed;
|
|
520
|
+
const filter = opts?.filter;
|
|
521
|
+
const invalidIds = filter ? new Set([...committedMatches, ...this._cache.values()].filter((match) => filter(match)).map((match) => match.id)) : void 0;
|
|
684
522
|
const invalidate = (d) => {
|
|
685
|
-
if (
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
error
|
|
691
|
-
|
|
692
|
-
|
|
523
|
+
if (!invalidIds || invalidIds.has(d.id)) {
|
|
524
|
+
const route = this.routesById[d.routeId];
|
|
525
|
+
const next = {
|
|
526
|
+
...d,
|
|
527
|
+
invalid: true,
|
|
528
|
+
...(opts?.forcePending || d.status === "error" || d.status === "notFound") && routeNeedsLoad(route) ? {
|
|
529
|
+
status: "pending",
|
|
530
|
+
error: void 0
|
|
531
|
+
} : void 0
|
|
532
|
+
};
|
|
533
|
+
d._flight = void 0;
|
|
534
|
+
return next;
|
|
535
|
+
}
|
|
693
536
|
return d;
|
|
694
537
|
};
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
538
|
+
const committed = committedMatches.map(invalidate);
|
|
539
|
+
this._committed = committed;
|
|
540
|
+
const cache = /* @__PURE__ */ new Map();
|
|
541
|
+
for (const [id, match] of this._cache) cache.set(id, invalidate(match));
|
|
542
|
+
this._cache = cache;
|
|
700
543
|
this.shouldViewTransition = false;
|
|
701
544
|
return this.load({ sync: opts?.sync });
|
|
702
545
|
};
|
|
703
|
-
this.getParsedLocationHref = (location) => {
|
|
704
|
-
return location.publicHref || "/";
|
|
705
|
-
};
|
|
706
546
|
this.resolveRedirect = (redirect) => {
|
|
707
547
|
const locationHeader = redirect.headers.get("Location");
|
|
708
548
|
if (!redirect.options.href || redirect.options._builtLocation) {
|
|
709
|
-
const
|
|
710
|
-
const href = this.getParsedLocationHref(location);
|
|
549
|
+
const href = (redirect.options._builtLocation ?? this.buildLocation(redirect.options)).publicHref || "/";
|
|
711
550
|
redirect.options.href = href;
|
|
712
551
|
redirect.headers.set("Location", href);
|
|
713
552
|
} else if (locationHeader) try {
|
|
@@ -723,60 +562,26 @@ var RouterCore = class {
|
|
|
723
562
|
return redirect;
|
|
724
563
|
};
|
|
725
564
|
this.clearCache = (opts) => {
|
|
565
|
+
const cached = this._cache;
|
|
566
|
+
const preloads = this._preloads;
|
|
726
567
|
const filter = opts?.filter;
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
const
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
this
|
|
568
|
+
const retained = /* @__PURE__ */ new Map();
|
|
569
|
+
const discarded = [];
|
|
570
|
+
for (const [id, match] of cached) if (filter && !filter(match)) retained.set(id, match);
|
|
571
|
+
else discarded.push(match);
|
|
572
|
+
const retainedPreloads = /* @__PURE__ */ new Map();
|
|
573
|
+
const discardedPreloads = [];
|
|
574
|
+
for (const [href, preload] of preloads ?? []) if (!filter || preload[0].some(filter)) {
|
|
575
|
+
discardedPreloads.push(preload);
|
|
576
|
+
discarded.push(...preload[0]);
|
|
577
|
+
} else retainedPreloads.set(href, preload);
|
|
578
|
+
this._cache = retained;
|
|
579
|
+
this._preloads = retainedPreloads;
|
|
580
|
+
transferMatchResources(this, discarded);
|
|
581
|
+
for (const preload of discardedPreloads) preload[1].abort();
|
|
740
582
|
};
|
|
741
583
|
this.loadRouteChunk = loadRouteChunk;
|
|
742
|
-
this.preloadRoute =
|
|
743
|
-
const next = opts._builtLocation ?? this.buildLocation(opts);
|
|
744
|
-
let matches = this.matchRoutes(next, {
|
|
745
|
-
throwOnError: true,
|
|
746
|
-
preload: true,
|
|
747
|
-
dest: opts
|
|
748
|
-
});
|
|
749
|
-
const activeMatchIds = new Set([...this.stores.matchesId.get(), ...this.stores.pendingIds.get()]);
|
|
750
|
-
const loadedMatchIds = new Set([...activeMatchIds, ...this.stores.cachedIds.get()]);
|
|
751
|
-
const matchesToCache = matches.filter((match) => !loadedMatchIds.has(match.id));
|
|
752
|
-
if (matchesToCache.length) {
|
|
753
|
-
const cachedMatches = this.stores.cachedMatches.get();
|
|
754
|
-
this.stores.setCached([...cachedMatches, ...matchesToCache]);
|
|
755
|
-
}
|
|
756
|
-
try {
|
|
757
|
-
matches = await loadMatches({
|
|
758
|
-
router: this,
|
|
759
|
-
matches,
|
|
760
|
-
location: next,
|
|
761
|
-
preload: true,
|
|
762
|
-
updateMatch: (id, updater) => {
|
|
763
|
-
if (activeMatchIds.has(id)) matches = matches.map((d) => d.id === id ? updater(d) : d);
|
|
764
|
-
else this.updateMatch(id, updater);
|
|
765
|
-
}
|
|
766
|
-
});
|
|
767
|
-
return matches;
|
|
768
|
-
} catch (err) {
|
|
769
|
-
if (isRedirect(err)) {
|
|
770
|
-
if (err.options.reloadDocument) return;
|
|
771
|
-
return await this.preloadRoute({
|
|
772
|
-
...err.options,
|
|
773
|
-
_fromLocation: next
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
if (!isNotFound(err)) console.error(err);
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
};
|
|
584
|
+
this.preloadRoute = (opts) => preloadClientRoute(this, opts);
|
|
780
585
|
this.matchRoute = (location, opts) => {
|
|
781
586
|
const matchLocation = {
|
|
782
587
|
...location,
|
|
@@ -785,8 +590,9 @@ var RouterCore = class {
|
|
|
785
590
|
leaveParams: true
|
|
786
591
|
};
|
|
787
592
|
const next = this.buildLocation(matchLocation);
|
|
788
|
-
|
|
789
|
-
|
|
593
|
+
const isPending = this.stores.status.get() === "pending";
|
|
594
|
+
if (opts?.pending && !isPending) return false;
|
|
595
|
+
const baseLocation = opts?.pending ?? !isPending ? this.latestLocation : this.stores.resolvedLocation.get() || this.stores.location.get();
|
|
790
596
|
const match = findSingleMatch(next.pathname, opts?.caseSensitive ?? false, opts?.fuzzy ?? false, baseLocation.pathname, this.processedTree);
|
|
791
597
|
if (!match) return false;
|
|
792
598
|
if (location.params) {
|
|
@@ -795,9 +601,6 @@ var RouterCore = class {
|
|
|
795
601
|
if (opts?.includeSearch ?? true) return deepEqual(baseLocation.search, next.search, { partial: true }) ? match.rawParams : false;
|
|
796
602
|
return match.rawParams;
|
|
797
603
|
};
|
|
798
|
-
this.hasNotFoundMatch = () => {
|
|
799
|
-
return this.stores.matches.get().some((d) => d.status === "notFound" || d.globalNotFound);
|
|
800
|
-
};
|
|
801
604
|
this.getStoreConfig = getStoreConfig;
|
|
802
605
|
this.update({
|
|
803
606
|
defaultPreloadDelay: 50,
|
|
@@ -811,14 +614,11 @@ var RouterCore = class {
|
|
|
811
614
|
parseSearch: options.parseSearch ?? defaultParseSearch,
|
|
812
615
|
protocolAllowlist: options.protocolAllowlist ?? DEFAULT_PROTOCOL_ALLOWLIST
|
|
813
616
|
});
|
|
814
|
-
if (typeof document
|
|
617
|
+
if (!(isServer ?? typeof document === "undefined")) self.__TSR_ROUTER__ = this;
|
|
815
618
|
}
|
|
816
619
|
isShell() {
|
|
817
620
|
return !!this.options.isShell;
|
|
818
621
|
}
|
|
819
|
-
isPrerendering() {
|
|
820
|
-
return !!this.options.isPrerendering;
|
|
821
|
-
}
|
|
822
622
|
get state() {
|
|
823
623
|
return this.stores.__store.get();
|
|
824
624
|
}
|
|
@@ -840,12 +640,6 @@ var RouterCore = class {
|
|
|
840
640
|
}
|
|
841
641
|
return branch;
|
|
842
642
|
}
|
|
843
|
-
get looseRoutesById() {
|
|
844
|
-
return this.routesById;
|
|
845
|
-
}
|
|
846
|
-
getParentContext(parentMatch) {
|
|
847
|
-
return !parentMatch?.id ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
|
|
848
|
-
}
|
|
849
643
|
matchRoutesInternal(next, opts) {
|
|
850
644
|
const matchedRoutesResult = this.getMatchedRoutes(next.pathname);
|
|
851
645
|
const { foundRoute, routeParams } = matchedRoutesResult;
|
|
@@ -853,10 +647,13 @@ var RouterCore = class {
|
|
|
853
647
|
let isGlobalNotFound = false;
|
|
854
648
|
if (foundRoute ? foundRoute.path !== "/" && routeParams["**"] : trimPathRight(next.pathname)) if (this.options.notFoundRoute) matchedRoutes = [...matchedRoutes, this.options.notFoundRoute];
|
|
855
649
|
else isGlobalNotFound = true;
|
|
856
|
-
const
|
|
650
|
+
const _notFoundRouteId = isGlobalNotFound ? findGlobalNotFoundRouteId(this.options.notFoundMode, matchedRoutes) : void 0;
|
|
857
651
|
const matches = new Array(matchedRoutes.length);
|
|
858
|
-
const
|
|
859
|
-
|
|
652
|
+
const committed = this._committed;
|
|
653
|
+
const previousAt = (route, index) => {
|
|
654
|
+
const match = committed[index];
|
|
655
|
+
return match?.routeId === route.id ? match : route === this.options.notFoundRoute ? committed.find((candidate) => candidate.routeId === route.id) : void 0;
|
|
656
|
+
};
|
|
860
657
|
for (let index = 0; index < matchedRoutes.length; index++) {
|
|
861
658
|
const route = matchedRoutes[index];
|
|
862
659
|
const parentMatch = matches[index - 1];
|
|
@@ -876,7 +673,6 @@ var RouterCore = class {
|
|
|
876
673
|
...parentStrictSearch,
|
|
877
674
|
...strictSearch
|
|
878
675
|
};
|
|
879
|
-
searchError = void 0;
|
|
880
676
|
} catch (err) {
|
|
881
677
|
let searchParamError = err;
|
|
882
678
|
if (!(err instanceof SearchParamError)) searchParamError = new SearchParamError(err.message, { cause: err });
|
|
@@ -886,8 +682,15 @@ var RouterCore = class {
|
|
|
886
682
|
searchError = searchParamError;
|
|
887
683
|
}
|
|
888
684
|
}
|
|
889
|
-
|
|
890
|
-
|
|
685
|
+
let loaderDeps = "";
|
|
686
|
+
let loaderDepsHash = "";
|
|
687
|
+
try {
|
|
688
|
+
loaderDeps = route.options.loaderDeps?.({ search: preMatchSearch }) ?? "";
|
|
689
|
+
loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) || "" : "";
|
|
690
|
+
} catch (cause) {
|
|
691
|
+
if (opts?.throwOnError) throw cause;
|
|
692
|
+
searchError ??= cause;
|
|
693
|
+
}
|
|
891
694
|
const { interpolatedPath, usedParams } = interpolatePath({
|
|
892
695
|
path: route.fullPath,
|
|
893
696
|
params: routeParams,
|
|
@@ -895,10 +698,10 @@ var RouterCore = class {
|
|
|
895
698
|
server: this.isServer
|
|
896
699
|
});
|
|
897
700
|
const matchId = route.id + interpolatedPath + loaderDepsHash;
|
|
898
|
-
const
|
|
899
|
-
const
|
|
701
|
+
const previousMatch = previousAt(route, index);
|
|
702
|
+
const existingMatch = process.env.NODE_ENV !== "production" && opts?._rematerialize ? void 0 : this._cache.get(matchId) ?? (previousMatch?.id === matchId ? previousMatch : void 0);
|
|
900
703
|
const strictParams = existingMatch?._strictParams ?? usedParams;
|
|
901
|
-
let paramsError
|
|
704
|
+
let paramsError;
|
|
902
705
|
if (!existingMatch) try {
|
|
903
706
|
extractStrictParams(route, strictParams);
|
|
904
707
|
} catch (err) {
|
|
@@ -915,10 +718,11 @@ var RouterCore = class {
|
|
|
915
718
|
params: previousMatch?.params ?? routeParams,
|
|
916
719
|
_strictParams: strictParams,
|
|
917
720
|
search: previousMatch ? nullReplaceEqualDeep(previousMatch.search, preMatchSearch) : nullReplaceEqualDeep(existingMatch.search, preMatchSearch),
|
|
918
|
-
_strictSearch: strictMatchSearch
|
|
721
|
+
_strictSearch: strictMatchSearch,
|
|
722
|
+
searchError
|
|
919
723
|
};
|
|
920
724
|
else {
|
|
921
|
-
const status =
|
|
725
|
+
const status = routeNeedsLoad(route) ? "pending" : "success";
|
|
922
726
|
match = {
|
|
923
727
|
id: matchId,
|
|
924
728
|
ssr: isServer ?? this.isServer ? void 0 : route.options.ssr,
|
|
@@ -930,83 +734,42 @@ var RouterCore = class {
|
|
|
930
734
|
updatedAt: Date.now(),
|
|
931
735
|
search: previousMatch ? nullReplaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
|
|
932
736
|
_strictSearch: strictMatchSearch,
|
|
933
|
-
searchError
|
|
737
|
+
searchError,
|
|
934
738
|
status,
|
|
935
739
|
isFetching: false,
|
|
936
740
|
error: void 0,
|
|
937
741
|
paramsError,
|
|
938
|
-
__routeContext: void 0,
|
|
939
|
-
_nonReactive: { loadPromise: createControlledPromise() },
|
|
940
|
-
__beforeLoadContext: void 0,
|
|
941
742
|
context: {},
|
|
942
|
-
abortController: new AbortController(),
|
|
943
|
-
fetchCount: 0,
|
|
743
|
+
abortController: opts?._controller ?? new AbortController(),
|
|
944
744
|
cause,
|
|
945
745
|
loaderDeps: previousMatch ? replaceEqualDeep(previousMatch.loaderDeps, loaderDeps) : loaderDeps,
|
|
946
746
|
invalid: false,
|
|
947
747
|
preload: false,
|
|
948
|
-
links: void 0,
|
|
949
|
-
scripts: void 0,
|
|
950
|
-
headScripts: void 0,
|
|
951
|
-
meta: void 0,
|
|
952
748
|
staticData: route.options.staticData || {},
|
|
953
749
|
fullPath: route.fullPath
|
|
954
750
|
};
|
|
955
751
|
}
|
|
956
|
-
|
|
957
|
-
match.
|
|
958
|
-
|
|
959
|
-
match.context = {
|
|
960
|
-
...parentContext,
|
|
961
|
-
...match.__routeContext,
|
|
962
|
-
...match.__beforeLoadContext
|
|
963
|
-
};
|
|
752
|
+
const _notFound = _notFoundRouteId === route.id;
|
|
753
|
+
if (match._notFound && !_notFound) match.error = void 0;
|
|
754
|
+
match._notFound = _notFound;
|
|
964
755
|
matches[index] = match;
|
|
965
756
|
}
|
|
966
757
|
for (let index = 0; index < matches.length; index++) {
|
|
967
758
|
const match = matches[index];
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
const previousMatch = previousActiveMatchesByRouteId.get(match.routeId);
|
|
971
|
-
match.params = previousMatch ? nullReplaceEqualDeep(previousMatch.params, routeParams) : routeParams;
|
|
972
|
-
if (!existingMatch) {
|
|
973
|
-
const parentMatch = matches[index - 1];
|
|
974
|
-
const parentContext = this.getParentContext(parentMatch);
|
|
975
|
-
if (route.options.context) {
|
|
976
|
-
const contextFnContext = {
|
|
977
|
-
deps: match.loaderDeps,
|
|
978
|
-
params: match.params,
|
|
979
|
-
context: parentContext ?? {},
|
|
980
|
-
location: next,
|
|
981
|
-
navigate: (opts) => this.navigate({
|
|
982
|
-
...opts,
|
|
983
|
-
_fromLocation: next
|
|
984
|
-
}),
|
|
985
|
-
buildLocation: this.buildLocation,
|
|
986
|
-
cause: match.cause,
|
|
987
|
-
abortController: match.abortController,
|
|
988
|
-
preload: !!match.preload,
|
|
989
|
-
matches,
|
|
990
|
-
routeId: route.id
|
|
991
|
-
};
|
|
992
|
-
match.__routeContext = route.options.context(contextFnContext) ?? void 0;
|
|
993
|
-
}
|
|
994
|
-
match.context = {
|
|
995
|
-
...parentContext,
|
|
996
|
-
...match.__routeContext,
|
|
997
|
-
...match.__beforeLoadContext
|
|
998
|
-
};
|
|
999
|
-
}
|
|
759
|
+
match.params = match.cause === "stay" ? nullReplaceEqualDeep(match.params, routeParams) : routeParams;
|
|
760
|
+
if (opts?._controller) match.context = {};
|
|
1000
761
|
}
|
|
1001
762
|
return matches;
|
|
1002
763
|
}
|
|
1003
764
|
/**
|
|
1004
765
|
* Lightweight route matching for buildLocation.
|
|
1005
766
|
* Only computes fullPath, accumulated search, and params - skipping expensive
|
|
1006
|
-
* operations like AbortController,
|
|
767
|
+
* operations like AbortController, loaderDeps, and full match objects.
|
|
1007
768
|
*/
|
|
1008
769
|
matchRoutesLightweight(location) {
|
|
1009
|
-
const
|
|
770
|
+
const lastRouteId = last(this.stores.ids.get());
|
|
771
|
+
const lastStateMatch = lastRouteId ? this.stores.byRoute.get(lastRouteId).get() : void 0;
|
|
772
|
+
const lastStateMatchId = lastStateMatch?.id;
|
|
1010
773
|
const cached = this.lightweightCache.get(location);
|
|
1011
774
|
if (cached && cached[0] === lastStateMatchId) return cached[1];
|
|
1012
775
|
const { matchedRoutes, routeParams } = this.getMatchedRoutes(location.pathname);
|
|
@@ -1015,7 +778,6 @@ var RouterCore = class {
|
|
|
1015
778
|
for (const route of matchedRoutes) try {
|
|
1016
779
|
Object.assign(accumulatedSearch, validateSearch(route.options.validateSearch, accumulatedSearch));
|
|
1017
780
|
} catch {}
|
|
1018
|
-
const lastStateMatch = lastStateMatchId && this.stores.matchStores.get(lastStateMatchId)?.get();
|
|
1019
781
|
const canReuseParams = lastStateMatch && lastStateMatch.routeId === lastRoute.id && lastStateMatch.pathname === location.pathname;
|
|
1020
782
|
let params;
|
|
1021
783
|
if (canReuseParams) params = lastStateMatch.params;
|
|
@@ -1036,6 +798,19 @@ var RouterCore = class {
|
|
|
1036
798
|
return result;
|
|
1037
799
|
}
|
|
1038
800
|
};
|
|
801
|
+
/**
|
|
802
|
+
* In non-production environments,
|
|
803
|
+
* augment the RouterCore class with a `_refreshRoute` method
|
|
804
|
+
* dedicated to HMR.
|
|
805
|
+
*/
|
|
806
|
+
if (process.env.NODE_ENV !== "production") {
|
|
807
|
+
RouterCore.prototype._replaceRouteChunk = replaceRouteChunk;
|
|
808
|
+
RouterCore.prototype._refreshRoute = async function() {
|
|
809
|
+
this._serverResult = void 0;
|
|
810
|
+
this.updateLatestLocation();
|
|
811
|
+
await refreshClientRoute(this);
|
|
812
|
+
};
|
|
813
|
+
}
|
|
1039
814
|
/** Error thrown when search parameter validation fails. */
|
|
1040
815
|
var SearchParamError = class extends Error {};
|
|
1041
816
|
/** Error thrown when path parameter parsing/validation fails. */
|
|
@@ -1056,14 +831,11 @@ function lazyFn(fn, key) {
|
|
|
1056
831
|
/** Create an initial RouterState from a parsed location. */
|
|
1057
832
|
function getInitialRouterState(location) {
|
|
1058
833
|
return {
|
|
1059
|
-
loadedAt: 0,
|
|
1060
834
|
isLoading: false,
|
|
1061
|
-
isTransitioning: false,
|
|
1062
835
|
status: "idle",
|
|
1063
836
|
resolvedLocation: void 0,
|
|
1064
837
|
location,
|
|
1065
|
-
matches: []
|
|
1066
|
-
statusCode: 200
|
|
838
|
+
matches: []
|
|
1067
839
|
};
|
|
1068
840
|
}
|
|
1069
841
|
function validateSearch(validateSearch, input) {
|
|
@@ -1078,35 +850,7 @@ function validateSearch(validateSearch, input) {
|
|
|
1078
850
|
if (typeof validateSearch === "function") return validateSearch(input);
|
|
1079
851
|
return {};
|
|
1080
852
|
}
|
|
1081
|
-
|
|
1082
|
-
* Build the matched route chain and extract params for a pathname.
|
|
1083
|
-
* Falls back to the root route if no specific route is found.
|
|
1084
|
-
*/
|
|
1085
|
-
function getMatchedRoutes({ pathname, routesById, processedTree }) {
|
|
1086
|
-
const routeParams = Object.create(null);
|
|
1087
|
-
const trimmedPath = trimPathRight(pathname);
|
|
1088
|
-
let foundRoute = void 0;
|
|
1089
|
-
const match = findRouteMatch(trimmedPath, processedTree, true);
|
|
1090
|
-
if (match) {
|
|
1091
|
-
foundRoute = match.route;
|
|
1092
|
-
Object.assign(routeParams, match.rawParams);
|
|
1093
|
-
}
|
|
1094
|
-
return {
|
|
1095
|
-
matchedRoutes: match?.branch || [routesById["__root__"]],
|
|
1096
|
-
routeParams,
|
|
1097
|
-
foundRoute
|
|
1098
|
-
};
|
|
1099
|
-
}
|
|
1100
|
-
/**
|
|
1101
|
-
* TODO: once caches are persisted across requests on the server,
|
|
1102
|
-
* we can cache the built middleware chain using `last(destRoutes)` as the key
|
|
1103
|
-
*/
|
|
1104
|
-
function applySearchMiddleware({ search, dest, destRoutes, _includeValidateSearch }) {
|
|
1105
|
-
return buildMiddlewareChain(destRoutes)(search, dest, _includeValidateSearch ?? false);
|
|
1106
|
-
}
|
|
1107
|
-
function buildMiddlewareChain(destRoutes) {
|
|
1108
|
-
let dest;
|
|
1109
|
-
let includeValidateSearch;
|
|
853
|
+
function applySearchMiddleware(search, dest, destRoutes, includeValidateSearch) {
|
|
1110
854
|
const middlewares = [];
|
|
1111
855
|
for (const route of destRoutes) {
|
|
1112
856
|
const routeOptions = route.options;
|
|
@@ -1162,28 +906,28 @@ function buildMiddlewareChain(destRoutes) {
|
|
|
1162
906
|
meta
|
|
1163
907
|
});
|
|
1164
908
|
};
|
|
1165
|
-
return
|
|
1166
|
-
dest = nextDest;
|
|
1167
|
-
includeValidateSearch = _includeValidateSearch;
|
|
1168
|
-
return applyNext(0, search);
|
|
1169
|
-
};
|
|
909
|
+
return applyNext(0, search);
|
|
1170
910
|
}
|
|
1171
911
|
function findGlobalNotFoundRouteId(notFoundMode, routes) {
|
|
1172
|
-
if (notFoundMode !== "root")
|
|
1173
|
-
|
|
1174
|
-
|
|
912
|
+
if (notFoundMode !== "root") {
|
|
913
|
+
let fallback;
|
|
914
|
+
for (let i = routes.length - 1; i >= 0; i--) {
|
|
915
|
+
const route = routes[i];
|
|
916
|
+
if (route.options.notFoundComponent) return route.id;
|
|
917
|
+
fallback ||= route.children && route.id;
|
|
918
|
+
}
|
|
919
|
+
if (fallback) return fallback;
|
|
1175
920
|
}
|
|
1176
921
|
return rootRouteId;
|
|
1177
922
|
}
|
|
923
|
+
function resolveNextParams(spec, base) {
|
|
924
|
+
return spec === false || spec === null ? Object.create(null) : (spec ?? true) === true ? base : Object.assign(base, functionalUpdate(spec, base));
|
|
925
|
+
}
|
|
1178
926
|
function extractStrictParams(route, accumulatedParams) {
|
|
1179
927
|
const parseParams = route.options.params?.parse ?? route.options.parseParams;
|
|
1180
|
-
if (parseParams)
|
|
1181
|
-
const result = parseParams(accumulatedParams);
|
|
1182
|
-
if (result === false) throw new Error("Route params.parse returned false for a matched route");
|
|
1183
|
-
Object.assign(accumulatedParams, result);
|
|
1184
|
-
}
|
|
928
|
+
if (parseParams) Object.assign(accumulatedParams, parseParams(accumulatedParams));
|
|
1185
929
|
}
|
|
1186
930
|
//#endregion
|
|
1187
|
-
export { PathParamError, RouterCore, SearchParamError, defaultSerializeError, getInitialRouterState, getLocationChangeInfo,
|
|
931
|
+
export { PathParamError, RouterCore, SearchParamError, _getUserHistoryState, defaultSerializeError, getInitialRouterState, getLocationChangeInfo, lazyFn, runRouteLifecycle, trailingSlashOptions };
|
|
1188
932
|
|
|
1189
933
|
//# sourceMappingURL=router.js.map
|