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