@tanstack/router-core 0.0.1-beta.36 → 0.0.1-beta.39
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/build/cjs/index.js +2 -1
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/path.js +5 -7
- package/build/cjs/path.js.map +1 -1
- package/build/cjs/route.js +112 -95
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/routeConfig.js +2 -2
- package/build/cjs/routeConfig.js.map +1 -1
- package/build/cjs/routeMatch.js +107 -65
- package/build/cjs/routeMatch.js.map +1 -1
- package/build/cjs/router.js +320 -351
- package/build/cjs/router.js.map +1 -1
- package/build/cjs/searchParams.js +4 -3
- package/build/cjs/searchParams.js.map +1 -1
- package/build/cjs/sharedClone.js +122 -0
- package/build/cjs/sharedClone.js.map +1 -0
- package/build/cjs/utils.js +1 -59
- package/build/cjs/utils.js.map +1 -1
- package/build/esm/index.js +654 -592
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +183 -158
- package/build/types/index.d.ts +54 -68
- package/build/umd/index.development.js +1000 -595
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +1 -0
- package/src/link.ts +20 -12
- package/src/route.ts +160 -139
- package/src/routeMatch.ts +144 -99
- package/src/router.ts +402 -491
- package/src/sharedClone.ts +118 -0
- package/src/utils.ts +0 -65
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -31
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
package/build/esm/index.js
CHANGED
|
@@ -12,64 +12,8 @@ import { createMemoryHistory, createBrowserHistory } from 'history';
|
|
|
12
12
|
export { createBrowserHistory, createHashHistory, createMemoryHistory } from 'history';
|
|
13
13
|
import invariant from 'tiny-invariant';
|
|
14
14
|
export { default as invariant } from 'tiny-invariant';
|
|
15
|
+
import { createStore, batch } from '@solidjs/reactivity';
|
|
15
16
|
|
|
16
|
-
/**
|
|
17
|
-
* This function returns `a` if `b` is deeply equal.
|
|
18
|
-
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
19
|
-
* This can be used for structural sharing between JSON values for example.
|
|
20
|
-
*/
|
|
21
|
-
function replaceEqualDeep(prev, next) {
|
|
22
|
-
if (prev === next) {
|
|
23
|
-
return prev;
|
|
24
|
-
}
|
|
25
|
-
const array = Array.isArray(prev) && Array.isArray(next);
|
|
26
|
-
if (array || isPlainObject(prev) && isPlainObject(next)) {
|
|
27
|
-
const aSize = array ? prev.length : Object.keys(prev).length;
|
|
28
|
-
const bItems = array ? next : Object.keys(next);
|
|
29
|
-
const bSize = bItems.length;
|
|
30
|
-
const copy = array ? [] : {};
|
|
31
|
-
let equalItems = 0;
|
|
32
|
-
for (let i = 0; i < bSize; i++) {
|
|
33
|
-
const key = array ? i : bItems[i];
|
|
34
|
-
copy[key] = replaceEqualDeep(prev[key], next[key]);
|
|
35
|
-
if (copy[key] === prev[key]) {
|
|
36
|
-
equalItems++;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return aSize === bSize && equalItems === aSize ? prev : copy;
|
|
40
|
-
}
|
|
41
|
-
return next;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
45
|
-
function isPlainObject(o) {
|
|
46
|
-
if (!hasObjectPrototype(o)) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// If has modified constructor
|
|
51
|
-
const ctor = o.constructor;
|
|
52
|
-
if (typeof ctor === 'undefined') {
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// If has modified prototype
|
|
57
|
-
const prot = ctor.prototype;
|
|
58
|
-
if (!hasObjectPrototype(prot)) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// If constructor does not have an Object-specific method
|
|
63
|
-
if (!prot.hasOwnProperty('isPrototypeOf')) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Most likely a plain Object
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
function hasObjectPrototype(o) {
|
|
71
|
-
return Object.prototype.toString.call(o) === '[object Object]';
|
|
72
|
-
}
|
|
73
17
|
function last(arr) {
|
|
74
18
|
return arr[arr.length - 1];
|
|
75
19
|
}
|
|
@@ -78,7 +22,7 @@ function warning(cond, message) {
|
|
|
78
22
|
if (typeof console !== 'undefined') console.warn(message);
|
|
79
23
|
try {
|
|
80
24
|
throw new Error(message);
|
|
81
|
-
} catch
|
|
25
|
+
} catch {}
|
|
82
26
|
}
|
|
83
27
|
return true;
|
|
84
28
|
}
|
|
@@ -115,8 +59,8 @@ function trimPath(path) {
|
|
|
115
59
|
return trimPathRight(trimPathLeft(path));
|
|
116
60
|
}
|
|
117
61
|
function resolvePath(basepath, base, to) {
|
|
118
|
-
base = base.replace(new RegExp(
|
|
119
|
-
to = to.replace(new RegExp(
|
|
62
|
+
base = base.replace(new RegExp(`^${basepath}`), '/');
|
|
63
|
+
to = to.replace(new RegExp(`^${basepath}`), '/');
|
|
120
64
|
let baseSegments = parsePathname(base);
|
|
121
65
|
const toSegments = parsePathname(to);
|
|
122
66
|
toSegments.forEach((toSegment, index) => {
|
|
@@ -197,8 +141,7 @@ function interpolatePath(path, params, leaveWildcard) {
|
|
|
197
141
|
return '';
|
|
198
142
|
}
|
|
199
143
|
if (segment.type === 'param') {
|
|
200
|
-
|
|
201
|
-
return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
|
|
144
|
+
return params[segment.value.substring(1)] ?? '';
|
|
202
145
|
}
|
|
203
146
|
return segment.value;
|
|
204
147
|
}));
|
|
@@ -210,16 +153,15 @@ function matchPathname(basepath, currentPathname, matchLocation) {
|
|
|
210
153
|
if (matchLocation.to && !pathParams) {
|
|
211
154
|
return;
|
|
212
155
|
}
|
|
213
|
-
return pathParams
|
|
156
|
+
return pathParams ?? {};
|
|
214
157
|
}
|
|
215
158
|
function matchByPath(basepath, from, matchLocation) {
|
|
216
|
-
var _matchLocation$to;
|
|
217
159
|
if (!from.startsWith(basepath)) {
|
|
218
160
|
return undefined;
|
|
219
161
|
}
|
|
220
162
|
from = basepath != '/' ? from.substring(basepath.length) : from;
|
|
221
163
|
const baseSegments = parsePathname(from);
|
|
222
|
-
const to =
|
|
164
|
+
const to = `${matchLocation.to ?? '*'}`;
|
|
223
165
|
const routeSegments = parsePathname(to);
|
|
224
166
|
const params = {};
|
|
225
167
|
let isMatch = (() => {
|
|
@@ -320,134 +262,136 @@ function decode(str) {
|
|
|
320
262
|
return out;
|
|
321
263
|
}
|
|
322
264
|
|
|
323
|
-
function
|
|
324
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
325
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
326
|
-
var source = arguments[i];
|
|
327
|
-
for (var key in source) {
|
|
328
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
329
|
-
target[key] = source[key];
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
return target;
|
|
334
|
-
};
|
|
335
|
-
return _extends.apply(this, arguments);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function createRoute(routeConfig, options, parent, router) {
|
|
265
|
+
function createRoute(routeConfig, options, originalIndex, parent, router) {
|
|
339
266
|
const {
|
|
340
267
|
id,
|
|
341
268
|
routeId,
|
|
342
269
|
path: routePath,
|
|
343
270
|
fullPath
|
|
344
271
|
} = routeConfig;
|
|
345
|
-
const action = router.state.actions[id] || (() => {
|
|
346
|
-
router.state.actions[id] = {
|
|
347
|
-
submissions: [],
|
|
348
|
-
submit: async (submission, actionOpts) => {
|
|
349
|
-
var _actionOpts$invalidat;
|
|
350
|
-
if (!route) {
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
|
|
354
|
-
if (!(actionOpts != null && actionOpts.multi)) {
|
|
355
|
-
action.submissions = action.submissions.filter(d => d.isMulti);
|
|
356
|
-
}
|
|
357
|
-
const actionState = {
|
|
358
|
-
submittedAt: Date.now(),
|
|
359
|
-
status: 'pending',
|
|
360
|
-
submission,
|
|
361
|
-
isMulti: !!(actionOpts != null && actionOpts.multi)
|
|
362
|
-
};
|
|
363
|
-
action.current = actionState;
|
|
364
|
-
action.latest = actionState;
|
|
365
|
-
action.submissions.push(actionState);
|
|
366
|
-
router.notify();
|
|
367
|
-
try {
|
|
368
|
-
const res = await (route.options.action == null ? void 0 : route.options.action(submission));
|
|
369
|
-
actionState.data = res;
|
|
370
|
-
if (invalidate) {
|
|
371
|
-
router.invalidateRoute({
|
|
372
|
-
to: '.',
|
|
373
|
-
fromCurrent: true
|
|
374
|
-
});
|
|
375
|
-
await router.reload();
|
|
376
|
-
}
|
|
377
|
-
actionState.status = 'success';
|
|
378
|
-
return res;
|
|
379
|
-
} catch (err) {
|
|
380
|
-
console.error(err);
|
|
381
|
-
actionState.error = err;
|
|
382
|
-
actionState.status = 'error';
|
|
383
|
-
} finally {
|
|
384
|
-
router.notify();
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
return router.state.actions[id];
|
|
389
|
-
})();
|
|
390
|
-
const loader = router.state.loaders[id] || (() => {
|
|
391
|
-
router.state.loaders[id] = {
|
|
392
|
-
pending: [],
|
|
393
|
-
fetch: async loaderContext => {
|
|
394
|
-
if (!route) {
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
const loaderState = {
|
|
398
|
-
loadedAt: Date.now(),
|
|
399
|
-
loaderContext
|
|
400
|
-
};
|
|
401
|
-
loader.current = loaderState;
|
|
402
|
-
loader.latest = loaderState;
|
|
403
|
-
loader.pending.push(loaderState);
|
|
404
|
-
|
|
405
|
-
// router.state = {
|
|
406
|
-
// ...router.state,
|
|
407
|
-
// currentAction: loaderState,
|
|
408
|
-
// latestAction: loaderState,
|
|
409
|
-
// }
|
|
410
|
-
|
|
411
|
-
router.notify();
|
|
412
|
-
try {
|
|
413
|
-
return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
|
|
414
|
-
} finally {
|
|
415
|
-
loader.pending = loader.pending.filter(d => d !== loaderState);
|
|
416
|
-
// router.removeActionQueue.push({ loader, loaderState })
|
|
417
|
-
router.notify();
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
return router.state.loaders[id];
|
|
422
|
-
})();
|
|
423
272
|
let route = {
|
|
424
273
|
routeInfo: undefined,
|
|
425
274
|
routeId: id,
|
|
426
275
|
routeRouteId: routeId,
|
|
276
|
+
originalIndex,
|
|
427
277
|
routePath,
|
|
428
278
|
fullPath,
|
|
429
279
|
options,
|
|
430
280
|
router,
|
|
431
281
|
childRoutes: undefined,
|
|
432
282
|
parentRoute: parent,
|
|
433
|
-
action
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
283
|
+
get action() {
|
|
284
|
+
let action = router.store.actions[id] || (() => {
|
|
285
|
+
router.setStore(s => {
|
|
286
|
+
s.actions[id] = {
|
|
287
|
+
submissions: [],
|
|
288
|
+
submit: async (submission, actionOpts) => {
|
|
289
|
+
if (!route) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const invalidate = (actionOpts == null ? void 0 : actionOpts.invalidate) ?? true;
|
|
293
|
+
const [actionStore, setActionStore] = createStore({
|
|
294
|
+
submittedAt: Date.now(),
|
|
295
|
+
status: 'pending',
|
|
296
|
+
submission,
|
|
297
|
+
isMulti: !!(actionOpts != null && actionOpts.multi)
|
|
298
|
+
});
|
|
299
|
+
router.setStore(s => {
|
|
300
|
+
if (!(actionOpts != null && actionOpts.multi)) {
|
|
301
|
+
s.actions[id].submissions = action.submissions.filter(d => d.isMulti);
|
|
302
|
+
}
|
|
303
|
+
s.actions[id].current = actionStore;
|
|
304
|
+
s.actions[id].latest = actionStore;
|
|
305
|
+
s.actions[id].submissions.push(actionStore);
|
|
306
|
+
});
|
|
307
|
+
try {
|
|
308
|
+
const res = await (route.options.action == null ? void 0 : route.options.action(submission));
|
|
309
|
+
setActionStore(s => {
|
|
310
|
+
s.data = res;
|
|
311
|
+
});
|
|
312
|
+
if (invalidate) {
|
|
313
|
+
router.invalidateRoute({
|
|
314
|
+
to: '.',
|
|
315
|
+
fromCurrent: true
|
|
316
|
+
});
|
|
317
|
+
await router.reload();
|
|
318
|
+
}
|
|
319
|
+
setActionStore(s => {
|
|
320
|
+
s.status = 'success';
|
|
321
|
+
});
|
|
322
|
+
return res;
|
|
323
|
+
} catch (err) {
|
|
324
|
+
console.error(err);
|
|
325
|
+
setActionStore(s => {
|
|
326
|
+
s.error = err;
|
|
327
|
+
s.status = 'error';
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
});
|
|
333
|
+
return router.store.actions[id];
|
|
334
|
+
})();
|
|
335
|
+
return action;
|
|
444
336
|
},
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
337
|
+
get loader() {
|
|
338
|
+
let loader = router.store.loaders[id] || (() => {
|
|
339
|
+
router.setStore(s => {
|
|
340
|
+
s.loaders[id] = {
|
|
341
|
+
pending: [],
|
|
342
|
+
fetch: async loaderContext => {
|
|
343
|
+
if (!route) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const loaderState = {
|
|
347
|
+
loadedAt: Date.now(),
|
|
348
|
+
loaderContext
|
|
349
|
+
};
|
|
350
|
+
router.setStore(s => {
|
|
351
|
+
s.loaders[id].current = loaderState;
|
|
352
|
+
s.loaders[id].latest = loaderState;
|
|
353
|
+
s.loaders[id].pending.push(loaderState);
|
|
354
|
+
});
|
|
355
|
+
try {
|
|
356
|
+
return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
|
|
357
|
+
} finally {
|
|
358
|
+
router.setStore(s => {
|
|
359
|
+
s.loaders[id].pending = s.loaders[id].pending.filter(d => d !== loaderState);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
});
|
|
365
|
+
return router.store.loaders[id];
|
|
366
|
+
})();
|
|
367
|
+
return loader;
|
|
449
368
|
}
|
|
369
|
+
|
|
370
|
+
// buildLink: (options) => {
|
|
371
|
+
// return router.buildLink({
|
|
372
|
+
// ...options,
|
|
373
|
+
// from: fullPath,
|
|
374
|
+
// } as any) as any
|
|
375
|
+
// },
|
|
376
|
+
|
|
377
|
+
// navigate: (options) => {
|
|
378
|
+
// return router.navigate({
|
|
379
|
+
// ...options,
|
|
380
|
+
// from: fullPath,
|
|
381
|
+
// } as any) as any
|
|
382
|
+
// },
|
|
383
|
+
|
|
384
|
+
// matchRoute: (matchLocation, opts) => {
|
|
385
|
+
// return router.matchRoute(
|
|
386
|
+
// {
|
|
387
|
+
// ...matchLocation,
|
|
388
|
+
// from: fullPath,
|
|
389
|
+
// } as any,
|
|
390
|
+
// opts,
|
|
391
|
+
// ) as any
|
|
392
|
+
// },
|
|
450
393
|
};
|
|
394
|
+
|
|
451
395
|
router.options.createRoute == null ? void 0 : router.options.createRoute({
|
|
452
396
|
router,
|
|
453
397
|
route
|
|
@@ -456,7 +400,7 @@ function createRoute(routeConfig, options, parent, router) {
|
|
|
456
400
|
}
|
|
457
401
|
|
|
458
402
|
const rootRouteId = '__root__';
|
|
459
|
-
const createRouteConfig = function
|
|
403
|
+
const createRouteConfig = function (options, children, isRoot, parentId, parentPath) {
|
|
460
404
|
if (options === void 0) {
|
|
461
405
|
options = {};
|
|
462
406
|
}
|
|
@@ -496,53 +440,194 @@ const createRouteConfig = function createRouteConfig(options, children, isRoot,
|
|
|
496
440
|
addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
|
|
497
441
|
createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath),
|
|
498
442
|
generate: () => {
|
|
499
|
-
invariant(false,
|
|
443
|
+
invariant(false, `routeConfig.generate() is used by TanStack Router's file-based routing code generation and should not actually be called during runtime. `);
|
|
500
444
|
}
|
|
501
445
|
};
|
|
502
446
|
};
|
|
503
447
|
|
|
448
|
+
/**
|
|
449
|
+
* This function returns `a` if `b` is deeply equal.
|
|
450
|
+
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
451
|
+
* This can be used for structural sharing between JSON values for example.
|
|
452
|
+
*/
|
|
453
|
+
function sharedClone(prev, next, touchAll) {
|
|
454
|
+
const things = new Map();
|
|
455
|
+
function recurse(prev, next) {
|
|
456
|
+
if (prev === next) {
|
|
457
|
+
return prev;
|
|
458
|
+
}
|
|
459
|
+
if (things.has(next)) {
|
|
460
|
+
return things.get(next);
|
|
461
|
+
}
|
|
462
|
+
const prevIsArray = Array.isArray(prev);
|
|
463
|
+
const nextIsArray = Array.isArray(next);
|
|
464
|
+
const prevIsObj = isPlainObject(prev);
|
|
465
|
+
const nextIsObj = isPlainObject(next);
|
|
466
|
+
const isArray = prevIsArray && nextIsArray;
|
|
467
|
+
const isObj = prevIsObj && nextIsObj;
|
|
468
|
+
const isSameStructure = isArray || isObj;
|
|
469
|
+
|
|
470
|
+
// Both are arrays or objects
|
|
471
|
+
if (isSameStructure) {
|
|
472
|
+
const aSize = isArray ? prev.length : Object.keys(prev).length;
|
|
473
|
+
const bItems = isArray ? next : Object.keys(next);
|
|
474
|
+
const bSize = bItems.length;
|
|
475
|
+
const copy = isArray ? [] : {};
|
|
476
|
+
let equalItems = 0;
|
|
477
|
+
for (let i = 0; i < bSize; i++) {
|
|
478
|
+
const key = isArray ? i : bItems[i];
|
|
479
|
+
if (copy[key] === prev[key]) {
|
|
480
|
+
equalItems++;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (aSize === bSize && equalItems === aSize) {
|
|
484
|
+
things.set(next, prev);
|
|
485
|
+
return prev;
|
|
486
|
+
}
|
|
487
|
+
things.set(next, copy);
|
|
488
|
+
for (let i = 0; i < bSize; i++) {
|
|
489
|
+
const key = isArray ? i : bItems[i];
|
|
490
|
+
if (typeof bItems[i] === 'function') {
|
|
491
|
+
copy[key] = prev[key];
|
|
492
|
+
} else {
|
|
493
|
+
copy[key] = recurse(prev[key], next[key]);
|
|
494
|
+
}
|
|
495
|
+
if (copy[key] === prev[key]) {
|
|
496
|
+
equalItems++;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return copy;
|
|
500
|
+
}
|
|
501
|
+
if (nextIsArray) {
|
|
502
|
+
const copy = [];
|
|
503
|
+
things.set(next, copy);
|
|
504
|
+
for (let i = 0; i < next.length; i++) {
|
|
505
|
+
copy[i] = recurse(undefined, next[i]);
|
|
506
|
+
}
|
|
507
|
+
return copy;
|
|
508
|
+
}
|
|
509
|
+
if (nextIsObj) {
|
|
510
|
+
const copy = {};
|
|
511
|
+
things.set(next, copy);
|
|
512
|
+
const nextKeys = Object.keys(next);
|
|
513
|
+
for (let i = 0; i < nextKeys.length; i++) {
|
|
514
|
+
const key = nextKeys[i];
|
|
515
|
+
copy[key] = recurse(undefined, next[key]);
|
|
516
|
+
}
|
|
517
|
+
return copy;
|
|
518
|
+
}
|
|
519
|
+
return next;
|
|
520
|
+
}
|
|
521
|
+
return recurse(prev, next);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
525
|
+
function isPlainObject(o) {
|
|
526
|
+
if (!hasObjectPrototype(o)) {
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// If has modified constructor
|
|
531
|
+
const ctor = o.constructor;
|
|
532
|
+
if (typeof ctor === 'undefined') {
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// If has modified prototype
|
|
537
|
+
const prot = ctor.prototype;
|
|
538
|
+
if (!hasObjectPrototype(prot)) {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// If constructor does not have an Object-specific method
|
|
543
|
+
if (!prot.hasOwnProperty('isPrototypeOf')) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Most likely a plain Object
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
function hasObjectPrototype(o) {
|
|
551
|
+
return Object.prototype.toString.call(o) === '[object Object]';
|
|
552
|
+
}
|
|
553
|
+
|
|
504
554
|
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
505
555
|
function createRouteMatch(router, route, opts) {
|
|
506
|
-
|
|
507
|
-
|
|
556
|
+
let componentsPromise;
|
|
557
|
+
let dataPromise;
|
|
558
|
+
let latestId = '';
|
|
559
|
+
let resolve = () => {};
|
|
560
|
+
function setLoaderData(loaderData) {
|
|
561
|
+
batch(() => {
|
|
562
|
+
setStore(s => {
|
|
563
|
+
s.routeLoaderData = sharedClone(s.routeLoaderData, loaderData);
|
|
564
|
+
});
|
|
565
|
+
updateLoaderData();
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
function updateLoaderData() {
|
|
569
|
+
setStore(s => {
|
|
570
|
+
var _store$parentMatch;
|
|
571
|
+
s.loaderData = sharedClone(s.loaderData, {
|
|
572
|
+
...((_store$parentMatch = store.parentMatch) == null ? void 0 : _store$parentMatch.store.loaderData),
|
|
573
|
+
...s.routeLoaderData
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
const [store, setStore] = createStore({
|
|
508
578
|
routeSearch: {},
|
|
509
579
|
search: {},
|
|
510
|
-
childMatches: [],
|
|
511
580
|
status: 'idle',
|
|
512
581
|
routeLoaderData: {},
|
|
513
582
|
loaderData: {},
|
|
514
583
|
isFetching: false,
|
|
515
|
-
|
|
584
|
+
invalid: false,
|
|
516
585
|
invalidAt: Infinity,
|
|
517
|
-
|
|
518
|
-
getIsInvalid: () => {
|
|
586
|
+
get isInvalid() {
|
|
519
587
|
const now = Date.now();
|
|
520
|
-
return
|
|
521
|
-
}
|
|
588
|
+
return this.invalid || this.invalidAt < now;
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
const routeMatch = {
|
|
592
|
+
...route,
|
|
593
|
+
...opts,
|
|
594
|
+
store,
|
|
595
|
+
// setStore,
|
|
596
|
+
router,
|
|
597
|
+
childMatches: [],
|
|
522
598
|
__: {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
599
|
+
setParentMatch: parentMatch => {
|
|
600
|
+
batch(() => {
|
|
601
|
+
setStore(s => {
|
|
602
|
+
s.parentMatch = parentMatch;
|
|
603
|
+
});
|
|
604
|
+
updateLoaderData();
|
|
605
|
+
});
|
|
529
606
|
},
|
|
607
|
+
abortController: new AbortController(),
|
|
530
608
|
validate: () => {
|
|
531
|
-
var
|
|
609
|
+
var _store$parentMatch2;
|
|
532
610
|
// Validate the search params and stabilize them
|
|
533
|
-
const parentSearch = (
|
|
611
|
+
const parentSearch = ((_store$parentMatch2 = store.parentMatch) == null ? void 0 : _store$parentMatch2.store.search) ?? router.store.currentLocation.search;
|
|
534
612
|
try {
|
|
535
|
-
|
|
536
|
-
const prevSearch = routeMatch.routeSearch;
|
|
613
|
+
const prevSearch = store.routeSearch;
|
|
537
614
|
const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
|
|
538
|
-
let nextSearch =
|
|
615
|
+
let nextSearch = sharedClone(prevSearch, (validator == null ? void 0 : validator(parentSearch)) ?? {});
|
|
616
|
+
batch(() => {
|
|
617
|
+
// Invalidate route matches when search param stability changes
|
|
618
|
+
if (prevSearch !== nextSearch) {
|
|
619
|
+
setStore(s => s.invalid = true);
|
|
620
|
+
}
|
|
539
621
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
622
|
+
// TODO: Alright, do we need batch() here?
|
|
623
|
+
setStore(s => {
|
|
624
|
+
s.routeSearch = nextSearch;
|
|
625
|
+
s.search = sharedClone(parentSearch, {
|
|
626
|
+
...parentSearch,
|
|
627
|
+
...nextSearch
|
|
628
|
+
});
|
|
629
|
+
});
|
|
630
|
+
});
|
|
546
631
|
componentTypes.map(async type => {
|
|
547
632
|
const component = routeMatch.options[type];
|
|
548
633
|
if (typeof routeMatch.__[type] !== 'function') {
|
|
@@ -555,8 +640,11 @@ function createRouteMatch(router, route, opts) {
|
|
|
555
640
|
cause: err
|
|
556
641
|
});
|
|
557
642
|
error.code = 'INVALID_SEARCH_PARAMS';
|
|
558
|
-
|
|
559
|
-
|
|
643
|
+
setStore(s => {
|
|
644
|
+
s.status = 'error';
|
|
645
|
+
s.error = error;
|
|
646
|
+
});
|
|
647
|
+
|
|
560
648
|
// Do not proceed with loading the route
|
|
561
649
|
return;
|
|
562
650
|
}
|
|
@@ -567,7 +655,7 @@ function createRouteMatch(router, route, opts) {
|
|
|
567
655
|
(_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
|
|
568
656
|
},
|
|
569
657
|
invalidate: () => {
|
|
570
|
-
|
|
658
|
+
setStore(s => s.invalid = true);
|
|
571
659
|
},
|
|
572
660
|
hasLoaders: () => {
|
|
573
661
|
return !!(route.options.loader || componentTypes.some(d => {
|
|
@@ -582,17 +670,17 @@ function createRouteMatch(router, route, opts) {
|
|
|
582
670
|
// If this is a preload, add it to the preload cache
|
|
583
671
|
if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
|
|
584
672
|
// If the match is currently active, don't preload it
|
|
585
|
-
if (router.
|
|
673
|
+
if (router.store.currentMatches.find(d => d.matchId === routeMatch.matchId)) {
|
|
586
674
|
return;
|
|
587
675
|
}
|
|
588
|
-
router.matchCache[routeMatch.matchId] = {
|
|
676
|
+
router.store.matchCache[routeMatch.matchId] = {
|
|
589
677
|
gc: now + loaderOpts.gcMaxAge,
|
|
590
678
|
match: routeMatch
|
|
591
679
|
};
|
|
592
680
|
}
|
|
593
681
|
|
|
594
682
|
// If the match is invalid, errored or idle, trigger it to load
|
|
595
|
-
if (
|
|
683
|
+
if (store.status === 'success' && store.isInvalid || store.status === 'error' || store.status === 'idle') {
|
|
596
684
|
const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
|
|
597
685
|
await routeMatch.fetch({
|
|
598
686
|
maxAge
|
|
@@ -601,29 +689,30 @@ function createRouteMatch(router, route, opts) {
|
|
|
601
689
|
},
|
|
602
690
|
fetch: async opts => {
|
|
603
691
|
const loadId = '' + Date.now() + Math.random();
|
|
604
|
-
|
|
692
|
+
latestId = loadId;
|
|
605
693
|
const checkLatest = async () => {
|
|
606
|
-
if (loadId !==
|
|
694
|
+
if (loadId !== latestId) {
|
|
607
695
|
// warning(true, 'Data loader is out of date!')
|
|
608
696
|
return new Promise(() => {});
|
|
609
697
|
}
|
|
610
698
|
};
|
|
699
|
+
batch(() => {
|
|
700
|
+
// If the match was in an error state, set it
|
|
701
|
+
// to a loading state again. Otherwise, keep it
|
|
702
|
+
// as loading or resolved
|
|
703
|
+
if (store.status === 'idle') {
|
|
704
|
+
setStore(s => s.status = 'loading');
|
|
705
|
+
}
|
|
611
706
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
routeMatch.status = 'loading';
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// We started loading the route, so it's no longer invalid
|
|
620
|
-
routeMatch.isInvalid = false;
|
|
621
|
-
routeMatch.__.loadPromise = new Promise(async resolve => {
|
|
707
|
+
// We started loading the route, so it's no longer invalid
|
|
708
|
+
setStore(s => s.invalid = false);
|
|
709
|
+
});
|
|
710
|
+
routeMatch.__.loadPromise = new Promise(async r => {
|
|
622
711
|
// We are now fetching, even if it's in the background of a
|
|
623
712
|
// resolved state
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
713
|
+
setStore(s => s.isFetching = true);
|
|
714
|
+
resolve = r;
|
|
715
|
+
componentsPromise = (async () => {
|
|
627
716
|
// then run all component and data loaders in parallel
|
|
628
717
|
// For each component type, potentially load it asynchronously
|
|
629
718
|
|
|
@@ -635,49 +724,52 @@ function createRouteMatch(router, route, opts) {
|
|
|
635
724
|
}
|
|
636
725
|
}));
|
|
637
726
|
})();
|
|
638
|
-
|
|
727
|
+
dataPromise = Promise.resolve().then(async () => {
|
|
639
728
|
try {
|
|
640
|
-
var _ref, _ref2, _opts$maxAge;
|
|
641
729
|
if (routeMatch.options.loader) {
|
|
642
730
|
const data = await router.loadMatchData(routeMatch);
|
|
643
731
|
await checkLatest();
|
|
644
|
-
|
|
732
|
+
setLoaderData(data);
|
|
645
733
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
734
|
+
setStore(s => {
|
|
735
|
+
s.error = undefined;
|
|
736
|
+
s.status = 'success';
|
|
737
|
+
s.updatedAt = Date.now();
|
|
738
|
+
s.invalidAt = s.updatedAt + ((opts == null ? void 0 : opts.maxAge) ?? routeMatch.options.loaderMaxAge ?? router.options.defaultLoaderMaxAge ?? 0);
|
|
739
|
+
});
|
|
740
|
+
return store.routeLoaderData;
|
|
651
741
|
} catch (err) {
|
|
652
742
|
await checkLatest();
|
|
653
743
|
if (process.env.NODE_ENV !== 'production') {
|
|
654
744
|
console.error(err);
|
|
655
745
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
746
|
+
setStore(s => {
|
|
747
|
+
s.error = err;
|
|
748
|
+
s.status = 'error';
|
|
749
|
+
s.updatedAt = Date.now();
|
|
750
|
+
});
|
|
659
751
|
throw err;
|
|
660
752
|
}
|
|
661
753
|
});
|
|
662
754
|
const after = async () => {
|
|
663
755
|
await checkLatest();
|
|
664
|
-
|
|
756
|
+
setStore(s => s.isFetching = false);
|
|
665
757
|
delete routeMatch.__.loadPromise;
|
|
666
|
-
|
|
758
|
+
resolve();
|
|
667
759
|
};
|
|
668
760
|
try {
|
|
669
|
-
await Promise.all([
|
|
761
|
+
await Promise.all([componentsPromise, dataPromise.catch(() => {})]);
|
|
670
762
|
after();
|
|
671
|
-
} catch
|
|
763
|
+
} catch {
|
|
672
764
|
after();
|
|
673
765
|
}
|
|
674
766
|
});
|
|
675
767
|
await routeMatch.__.loadPromise;
|
|
676
768
|
await checkLatest();
|
|
677
769
|
}
|
|
678
|
-
}
|
|
770
|
+
};
|
|
679
771
|
if (!routeMatch.hasLoaders()) {
|
|
680
|
-
|
|
772
|
+
setStore(s => s.status = 'success');
|
|
681
773
|
}
|
|
682
774
|
return routeMatch;
|
|
683
775
|
}
|
|
@@ -707,7 +799,9 @@ function parseSearchWith(parser) {
|
|
|
707
799
|
}
|
|
708
800
|
function stringifySearchWith(stringify) {
|
|
709
801
|
return search => {
|
|
710
|
-
search =
|
|
802
|
+
search = {
|
|
803
|
+
...search
|
|
804
|
+
};
|
|
711
805
|
if (search) {
|
|
712
806
|
Object.keys(search).forEach(key => {
|
|
713
807
|
const val = search[key];
|
|
@@ -723,7 +817,7 @@ function stringifySearchWith(stringify) {
|
|
|
723
817
|
});
|
|
724
818
|
}
|
|
725
819
|
const searchStr = encode(search).toString();
|
|
726
|
-
return searchStr ?
|
|
820
|
+
return searchStr ? `?${searchStr}` : '';
|
|
727
821
|
};
|
|
728
822
|
}
|
|
729
823
|
|
|
@@ -742,177 +836,277 @@ function getInitialRouterState() {
|
|
|
742
836
|
actions: {},
|
|
743
837
|
loaders: {},
|
|
744
838
|
lastUpdated: Date.now(),
|
|
745
|
-
|
|
746
|
-
|
|
839
|
+
matchCache: {},
|
|
840
|
+
get isFetching() {
|
|
841
|
+
return this.status === 'loading' || this.currentMatches.some(d => d.store.isFetching);
|
|
842
|
+
},
|
|
843
|
+
get isPreloading() {
|
|
844
|
+
return Object.values(this.matchCache).some(d => d.match.store.isFetching && !this.currentMatches.find(dd => dd.matchId === d.match.matchId));
|
|
845
|
+
}
|
|
747
846
|
};
|
|
748
847
|
}
|
|
749
848
|
function createRouter(userOptions) {
|
|
750
|
-
|
|
751
|
-
const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
|
|
752
|
-
const originalOptions = _extends({
|
|
849
|
+
const originalOptions = {
|
|
753
850
|
defaultLoaderGcMaxAge: 5 * 60 * 1000,
|
|
754
851
|
defaultLoaderMaxAge: 0,
|
|
755
852
|
defaultPreloadMaxAge: 2000,
|
|
756
853
|
defaultPreloadDelay: 50,
|
|
757
|
-
context: undefined
|
|
758
|
-
|
|
759
|
-
stringifySearch: (
|
|
760
|
-
parseSearch: (
|
|
761
|
-
}
|
|
762
|
-
|
|
854
|
+
context: undefined,
|
|
855
|
+
...userOptions,
|
|
856
|
+
stringifySearch: (userOptions == null ? void 0 : userOptions.stringifySearch) ?? defaultStringifySearch,
|
|
857
|
+
parseSearch: (userOptions == null ? void 0 : userOptions.parseSearch) ?? defaultParseSearch
|
|
858
|
+
};
|
|
859
|
+
const [store, setStore] = createStore(getInitialRouterState());
|
|
860
|
+
let navigationPromise;
|
|
861
|
+
let startedLoadingAt = Date.now();
|
|
862
|
+
let resolveNavigation = () => {};
|
|
863
|
+
function onFocus() {
|
|
864
|
+
router.load();
|
|
865
|
+
}
|
|
866
|
+
function buildRouteTree(rootRouteConfig) {
|
|
867
|
+
const recurseRoutes = (routeConfigs, parent) => {
|
|
868
|
+
return routeConfigs.map((routeConfig, i) => {
|
|
869
|
+
const routeOptions = routeConfig.options;
|
|
870
|
+
const route = createRoute(routeConfig, routeOptions, i, parent, router);
|
|
871
|
+
const existingRoute = router.routesById[route.routeId];
|
|
872
|
+
if (existingRoute) {
|
|
873
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
874
|
+
console.warn(`Duplicate routes found with id: ${String(route.routeId)}`, router.routesById, route);
|
|
875
|
+
}
|
|
876
|
+
throw new Error();
|
|
877
|
+
}
|
|
878
|
+
router.routesById[route.routeId] = route;
|
|
879
|
+
const children = routeConfig.children;
|
|
880
|
+
route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
|
|
881
|
+
return route;
|
|
882
|
+
});
|
|
883
|
+
};
|
|
884
|
+
const routes = recurseRoutes([rootRouteConfig]);
|
|
885
|
+
return routes[0];
|
|
886
|
+
}
|
|
887
|
+
function parseLocation(location, previousLocation) {
|
|
888
|
+
const parsedSearch = router.options.parseSearch(location.search);
|
|
889
|
+
return {
|
|
890
|
+
pathname: location.pathname,
|
|
891
|
+
searchStr: location.search,
|
|
892
|
+
search: sharedClone(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
|
|
893
|
+
hash: location.hash.split('#').reverse()[0] ?? '',
|
|
894
|
+
href: `${location.pathname}${location.search}${location.hash}`,
|
|
895
|
+
state: location.state,
|
|
896
|
+
key: location.key
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
function navigate(location) {
|
|
900
|
+
const next = router.buildNext(location);
|
|
901
|
+
return commitLocation(next, location.replace);
|
|
902
|
+
}
|
|
903
|
+
function buildLocation(dest) {
|
|
904
|
+
var _last, _dest$__preSearchFilt, _dest$__preSearchFilt2, _dest$__postSearchFil;
|
|
905
|
+
if (dest === void 0) {
|
|
906
|
+
dest = {};
|
|
907
|
+
}
|
|
908
|
+
const fromPathname = dest.fromCurrent ? store.latestLocation.pathname : dest.from ?? store.latestLocation.pathname;
|
|
909
|
+
let pathname = resolvePath(router.basepath ?? '/', fromPathname, `${dest.to ?? '.'}`);
|
|
910
|
+
const fromMatches = router.matchRoutes(store.latestLocation.pathname, {
|
|
911
|
+
strictParseParams: true
|
|
912
|
+
});
|
|
913
|
+
const toMatches = router.matchRoutes(pathname);
|
|
914
|
+
const prevParams = {
|
|
915
|
+
...((_last = last(fromMatches)) == null ? void 0 : _last.params)
|
|
916
|
+
};
|
|
917
|
+
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
918
|
+
if (nextParams) {
|
|
919
|
+
toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
920
|
+
Object.assign({}, nextParams, fn(nextParams));
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
924
|
+
|
|
925
|
+
// Pre filters first
|
|
926
|
+
const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), store.latestLocation.search) : store.latestLocation.search;
|
|
927
|
+
|
|
928
|
+
// Then the link/navigate function
|
|
929
|
+
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
930
|
+
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
931
|
+
: (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
932
|
+
: {};
|
|
933
|
+
|
|
934
|
+
// Then post filters
|
|
935
|
+
const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
936
|
+
const search = sharedClone(store.latestLocation.search, postFilteredSearch);
|
|
937
|
+
const searchStr = router.options.stringifySearch(search);
|
|
938
|
+
let hash = dest.hash === true ? store.latestLocation.hash : functionalUpdate(dest.hash, store.latestLocation.hash);
|
|
939
|
+
hash = hash ? `#${hash}` : '';
|
|
940
|
+
return {
|
|
941
|
+
pathname,
|
|
942
|
+
search,
|
|
943
|
+
searchStr,
|
|
944
|
+
state: store.latestLocation.state,
|
|
945
|
+
hash,
|
|
946
|
+
href: `${pathname}${searchStr}${hash}`,
|
|
947
|
+
key: dest.key
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
function commitLocation(next, replace) {
|
|
951
|
+
const id = '' + Date.now() + Math.random();
|
|
952
|
+
let nextAction = 'replace';
|
|
953
|
+
if (!replace) {
|
|
954
|
+
nextAction = 'push';
|
|
955
|
+
}
|
|
956
|
+
const isSameUrl = parseLocation(router.history.location).href === next.href;
|
|
957
|
+
if (isSameUrl && !next.key) {
|
|
958
|
+
nextAction = 'replace';
|
|
959
|
+
}
|
|
960
|
+
router.history[nextAction]({
|
|
961
|
+
pathname: next.pathname,
|
|
962
|
+
hash: next.hash,
|
|
963
|
+
search: next.searchStr
|
|
964
|
+
}, {
|
|
965
|
+
id,
|
|
966
|
+
...next.state
|
|
967
|
+
});
|
|
968
|
+
return navigationPromise = new Promise(resolve => {
|
|
969
|
+
const previousNavigationResolve = resolveNavigation;
|
|
970
|
+
resolveNavigation = () => {
|
|
971
|
+
previousNavigationResolve();
|
|
972
|
+
resolve();
|
|
973
|
+
};
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
const router = {
|
|
763
977
|
types: undefined,
|
|
764
978
|
// public api
|
|
765
|
-
history,
|
|
979
|
+
history: (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory(),
|
|
980
|
+
store,
|
|
981
|
+
setStore,
|
|
766
982
|
options: originalOptions,
|
|
767
|
-
listeners: [],
|
|
768
|
-
// Resolved after construction
|
|
769
983
|
basepath: '',
|
|
770
984
|
routeTree: undefined,
|
|
771
985
|
routesById: {},
|
|
772
|
-
//
|
|
773
|
-
resolveNavigation: () => {},
|
|
774
|
-
matchCache: {},
|
|
775
|
-
state: getInitialRouterState(),
|
|
776
986
|
reset: () => {
|
|
777
|
-
|
|
778
|
-
router.notify();
|
|
779
|
-
},
|
|
780
|
-
startedLoadingAt: Date.now(),
|
|
781
|
-
subscribe: listener => {
|
|
782
|
-
router.listeners.push(listener);
|
|
783
|
-
return () => {
|
|
784
|
-
router.listeners = router.listeners.filter(x => x !== listener);
|
|
785
|
-
};
|
|
987
|
+
setStore(s => Object.assign(s, getInitialRouterState()));
|
|
786
988
|
},
|
|
787
989
|
getRoute: id => {
|
|
788
990
|
return router.routesById[id];
|
|
789
991
|
},
|
|
790
|
-
notify: () => {
|
|
791
|
-
const isFetching = router.state.status === 'loading' || router.state.currentMatches.some(d => d.isFetching);
|
|
792
|
-
const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.currentMatches.find(dd => dd.matchId === d.match.matchId));
|
|
793
|
-
if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
|
|
794
|
-
router.state = _extends({}, router.state, {
|
|
795
|
-
isFetching,
|
|
796
|
-
isPreloading
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
cascadeLoaderData(router.state.currentMatches);
|
|
800
|
-
router.listeners.forEach(listener => listener(router));
|
|
801
|
-
},
|
|
802
992
|
dehydrate: () => {
|
|
803
993
|
return {
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
994
|
+
store: {
|
|
995
|
+
...pick(store, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
|
|
996
|
+
currentMatches: store.currentMatches.map(match => ({
|
|
997
|
+
matchId: match.matchId,
|
|
998
|
+
store: pick(match.store, ['status', 'routeLoaderData', 'isInvalid', 'invalidAt'])
|
|
999
|
+
}))
|
|
1000
|
+
},
|
|
807
1001
|
context: router.options.context
|
|
808
1002
|
};
|
|
809
1003
|
},
|
|
810
|
-
hydrate:
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
// Update the context
|
|
816
|
-
router.options.context = dehydratedState.context;
|
|
1004
|
+
hydrate: dehydratedRouter => {
|
|
1005
|
+
setStore(s => {
|
|
1006
|
+
// Update the context TODO: make this part of state?
|
|
1007
|
+
router.options.context = dehydratedRouter.context;
|
|
817
1008
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
1009
|
+
// Match the routes
|
|
1010
|
+
const currentMatches = router.matchRoutes(dehydratedRouter.store.latestLocation.pathname, {
|
|
1011
|
+
strictParseParams: true
|
|
1012
|
+
});
|
|
1013
|
+
currentMatches.forEach((match, index) => {
|
|
1014
|
+
const dehydratedMatch = dehydratedRouter.store.currentMatches[index];
|
|
1015
|
+
invariant(dehydratedMatch && dehydratedMatch.matchId === match.matchId, 'Oh no! There was a hydration mismatch when attempting to restore the state of the router! 😬');
|
|
1016
|
+
Object.assign(match, dehydratedMatch);
|
|
1017
|
+
});
|
|
1018
|
+
currentMatches.forEach(match => match.__.validate());
|
|
1019
|
+
Object.assign(s, {
|
|
1020
|
+
...dehydratedRouter.store,
|
|
1021
|
+
currentMatches
|
|
1022
|
+
});
|
|
830
1023
|
});
|
|
831
1024
|
},
|
|
832
1025
|
mount: () => {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
1026
|
+
// Mount only does anything on the client
|
|
1027
|
+
if (!isServer) {
|
|
1028
|
+
// If the router matches are empty, load the matches
|
|
1029
|
+
if (!store.currentMatches.length) {
|
|
1030
|
+
router.load();
|
|
1031
|
+
}
|
|
1032
|
+
const unsub = router.history.listen(event => {
|
|
1033
|
+
router.load(parseLocation(event.location, store.latestLocation));
|
|
1034
|
+
});
|
|
839
1035
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
return () => {
|
|
848
|
-
unsub();
|
|
849
|
-
if (!isServer && window.removeEventListener) {
|
|
850
|
-
// Be sure to unsubscribe if a new handler is set
|
|
851
|
-
window.removeEventListener('visibilitychange', router.onFocus);
|
|
852
|
-
window.removeEventListener('focus', router.onFocus);
|
|
1036
|
+
// addEventListener does not exist in React Native, but window does
|
|
1037
|
+
// In the future, we might need to invert control here for more adapters
|
|
1038
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1039
|
+
if (window.addEventListener) {
|
|
1040
|
+
// Listen to visibilitychange and focus
|
|
1041
|
+
window.addEventListener('visibilitychange', onFocus, false);
|
|
1042
|
+
window.addEventListener('focus', onFocus, false);
|
|
853
1043
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
1044
|
+
return () => {
|
|
1045
|
+
unsub();
|
|
1046
|
+
if (window.removeEventListener) {
|
|
1047
|
+
// Be sure to unsubscribe if a new handler is set
|
|
1048
|
+
window.removeEventListener('visibilitychange', onFocus);
|
|
1049
|
+
window.removeEventListener('focus', onFocus);
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
return () => {};
|
|
858
1054
|
},
|
|
859
1055
|
update: opts => {
|
|
860
|
-
var _trimPath;
|
|
861
1056
|
const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
|
|
862
|
-
if (!
|
|
1057
|
+
if (!store.latestLocation || newHistory) {
|
|
863
1058
|
if (opts != null && opts.history) {
|
|
864
1059
|
router.history = opts.history;
|
|
865
1060
|
}
|
|
866
|
-
|
|
867
|
-
|
|
1061
|
+
setStore(s => {
|
|
1062
|
+
s.latestLocation = parseLocation(router.history.location);
|
|
1063
|
+
s.currentLocation = s.latestLocation;
|
|
1064
|
+
});
|
|
868
1065
|
}
|
|
869
1066
|
Object.assign(router.options, opts);
|
|
870
1067
|
const {
|
|
871
1068
|
basepath,
|
|
872
1069
|
routeConfig
|
|
873
1070
|
} = router.options;
|
|
874
|
-
router.basepath =
|
|
1071
|
+
router.basepath = `/${trimPath(basepath ?? '') ?? ''}`;
|
|
875
1072
|
if (routeConfig) {
|
|
876
1073
|
router.routesById = {};
|
|
877
|
-
router.routeTree =
|
|
1074
|
+
router.routeTree = buildRouteTree(routeConfig);
|
|
878
1075
|
}
|
|
879
1076
|
return router;
|
|
880
1077
|
},
|
|
881
1078
|
cancelMatches: () => {
|
|
882
|
-
|
|
883
|
-
[...router.state.currentMatches, ...((_router$state$pending = router.state.pendingMatches) != null ? _router$state$pending : [])].forEach(match => {
|
|
1079
|
+
[...store.currentMatches, ...(store.pendingMatches || [])].forEach(match => {
|
|
884
1080
|
match.cancel();
|
|
885
1081
|
});
|
|
886
1082
|
},
|
|
887
1083
|
load: async next => {
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
// Ingest the new location
|
|
892
|
-
router.state.latestLocation = next;
|
|
893
|
-
}
|
|
1084
|
+
let now = Date.now();
|
|
1085
|
+
const startedAt = now;
|
|
1086
|
+
startedLoadingAt = startedAt;
|
|
894
1087
|
|
|
895
1088
|
// Cancel any pending matches
|
|
896
1089
|
router.cancelMatches();
|
|
1090
|
+
let matches;
|
|
1091
|
+
batch(() => {
|
|
1092
|
+
if (next) {
|
|
1093
|
+
// Ingest the new location
|
|
1094
|
+
setStore(s => {
|
|
1095
|
+
s.latestLocation = next;
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
897
1098
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
});
|
|
902
|
-
if (typeof document !== 'undefined') {
|
|
903
|
-
router.state = _extends({}, router.state, {
|
|
904
|
-
status: 'loading',
|
|
905
|
-
pendingMatches: matches,
|
|
906
|
-
pendingLocation: router.state.latestLocation
|
|
1099
|
+
// Match the routes
|
|
1100
|
+
matches = router.matchRoutes(store.latestLocation.pathname, {
|
|
1101
|
+
strictParseParams: true
|
|
907
1102
|
});
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
status
|
|
911
|
-
|
|
912
|
-
|
|
1103
|
+
console.log('set loading', matches);
|
|
1104
|
+
setStore(s => {
|
|
1105
|
+
s.status = 'loading';
|
|
1106
|
+
s.pendingMatches = matches;
|
|
1107
|
+
s.pendingLocation = store.latestLocation;
|
|
913
1108
|
});
|
|
914
|
-
}
|
|
915
|
-
router.notify();
|
|
1109
|
+
});
|
|
916
1110
|
|
|
917
1111
|
// Load the matches
|
|
918
1112
|
try {
|
|
@@ -921,11 +1115,11 @@ function createRouter(userOptions) {
|
|
|
921
1115
|
console.log(err);
|
|
922
1116
|
invariant(false, 'Matches failed to load due to error above ☝️. Navigation cancelled!');
|
|
923
1117
|
}
|
|
924
|
-
if (
|
|
925
|
-
// Ignore side-effects of
|
|
926
|
-
return
|
|
1118
|
+
if (startedLoadingAt !== startedAt) {
|
|
1119
|
+
// Ignore side-effects of outdated side-effects
|
|
1120
|
+
return navigationPromise;
|
|
927
1121
|
}
|
|
928
|
-
const previousMatches =
|
|
1122
|
+
const previousMatches = store.currentMatches;
|
|
929
1123
|
const exiting = [],
|
|
930
1124
|
staying = [];
|
|
931
1125
|
previousMatches.forEach(d => {
|
|
@@ -938,22 +1132,21 @@ function createRouter(userOptions) {
|
|
|
938
1132
|
const entering = matches.filter(d => {
|
|
939
1133
|
return !previousMatches.find(dd => dd.matchId === d.matchId);
|
|
940
1134
|
});
|
|
941
|
-
|
|
1135
|
+
now = Date.now();
|
|
942
1136
|
exiting.forEach(d => {
|
|
943
|
-
var _ref, _d$options$loaderGcMa, _ref2, _d$options$loaderMaxA;
|
|
944
1137
|
d.__.onExit == null ? void 0 : d.__.onExit({
|
|
945
1138
|
params: d.params,
|
|
946
|
-
search: d.routeSearch
|
|
1139
|
+
search: d.store.routeSearch
|
|
947
1140
|
});
|
|
948
1141
|
|
|
949
1142
|
// Clear idle error states when match leaves
|
|
950
|
-
if (d.status === 'error' && !d.isFetching) {
|
|
951
|
-
d.status = 'idle';
|
|
952
|
-
d.error = undefined;
|
|
1143
|
+
if (d.store.status === 'error' && !d.store.isFetching) {
|
|
1144
|
+
d.store.status = 'idle';
|
|
1145
|
+
d.store.error = undefined;
|
|
953
1146
|
}
|
|
954
|
-
const gc = Math.max(
|
|
1147
|
+
const gc = Math.max(d.options.loaderGcMaxAge ?? router.options.defaultLoaderGcMaxAge ?? 0, d.options.loaderMaxAge ?? router.options.defaultLoaderMaxAge ?? 0);
|
|
955
1148
|
if (gc > 0) {
|
|
956
|
-
|
|
1149
|
+
store.matchCache[d.matchId] = {
|
|
957
1150
|
gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
|
|
958
1151
|
match: d
|
|
959
1152
|
};
|
|
@@ -962,59 +1155,64 @@ function createRouter(userOptions) {
|
|
|
962
1155
|
staying.forEach(d => {
|
|
963
1156
|
d.options.onTransition == null ? void 0 : d.options.onTransition({
|
|
964
1157
|
params: d.params,
|
|
965
|
-
search: d.routeSearch
|
|
1158
|
+
search: d.store.routeSearch
|
|
966
1159
|
});
|
|
967
1160
|
});
|
|
968
1161
|
entering.forEach(d => {
|
|
969
1162
|
d.__.onExit = d.options.onLoaded == null ? void 0 : d.options.onLoaded({
|
|
970
1163
|
params: d.params,
|
|
971
|
-
search: d.search
|
|
1164
|
+
search: d.store.search
|
|
972
1165
|
});
|
|
973
|
-
delete
|
|
1166
|
+
delete store.matchCache[d.matchId];
|
|
974
1167
|
});
|
|
975
|
-
if (
|
|
1168
|
+
if (startedLoadingAt !== startedAt) {
|
|
976
1169
|
// Ignore side-effects of match loading
|
|
977
1170
|
return;
|
|
978
1171
|
}
|
|
979
1172
|
matches.forEach(match => {
|
|
980
1173
|
// Clear actions
|
|
981
1174
|
if (match.action) {
|
|
1175
|
+
// TODO: Check reactivity here
|
|
982
1176
|
match.action.current = undefined;
|
|
983
1177
|
match.action.submissions = [];
|
|
984
1178
|
}
|
|
985
1179
|
});
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1180
|
+
setStore(s => {
|
|
1181
|
+
console.log('set', matches);
|
|
1182
|
+
Object.assign(s, {
|
|
1183
|
+
status: 'idle',
|
|
1184
|
+
currentLocation: store.latestLocation,
|
|
1185
|
+
currentMatches: matches,
|
|
1186
|
+
pendingLocation: undefined,
|
|
1187
|
+
pendingMatches: undefined
|
|
1188
|
+
});
|
|
992
1189
|
});
|
|
993
|
-
|
|
994
|
-
router.resolveNavigation();
|
|
1190
|
+
resolveNavigation();
|
|
995
1191
|
},
|
|
996
1192
|
cleanMatchCache: () => {
|
|
997
1193
|
const now = Date.now();
|
|
998
|
-
|
|
999
|
-
|
|
1194
|
+
setStore(s => {
|
|
1195
|
+
Object.keys(s.matchCache).forEach(matchId => {
|
|
1196
|
+
const entry = s.matchCache[matchId];
|
|
1000
1197
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1198
|
+
// Don't remove loading matches
|
|
1199
|
+
if (entry.match.store.status === 'loading') {
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1005
1202
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1203
|
+
// Do not remove successful matches that are still valid
|
|
1204
|
+
if (entry.gc > 0 && entry.gc > now) {
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1010
1207
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1208
|
+
// Everything else gets removed
|
|
1209
|
+
delete s.matchCache[matchId];
|
|
1210
|
+
});
|
|
1013
1211
|
});
|
|
1014
1212
|
},
|
|
1015
|
-
loadRoute: async function
|
|
1213
|
+
loadRoute: async function (navigateOpts) {
|
|
1016
1214
|
if (navigateOpts === void 0) {
|
|
1017
|
-
navigateOpts =
|
|
1215
|
+
navigateOpts = store.latestLocation;
|
|
1018
1216
|
}
|
|
1019
1217
|
const next = router.buildNext(navigateOpts);
|
|
1020
1218
|
const matches = router.matchRoutes(next.pathname, {
|
|
@@ -1023,10 +1221,9 @@ function createRouter(userOptions) {
|
|
|
1023
1221
|
await router.loadMatches(matches);
|
|
1024
1222
|
return matches;
|
|
1025
1223
|
},
|
|
1026
|
-
preloadRoute: async function
|
|
1027
|
-
var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
|
|
1224
|
+
preloadRoute: async function (navigateOpts, loaderOpts) {
|
|
1028
1225
|
if (navigateOpts === void 0) {
|
|
1029
|
-
navigateOpts =
|
|
1226
|
+
navigateOpts = store.latestLocation;
|
|
1030
1227
|
}
|
|
1031
1228
|
const next = router.buildNext(navigateOpts);
|
|
1032
1229
|
const matches = router.matchRoutes(next.pathname, {
|
|
@@ -1034,28 +1231,27 @@ function createRouter(userOptions) {
|
|
|
1034
1231
|
});
|
|
1035
1232
|
await router.loadMatches(matches, {
|
|
1036
1233
|
preload: true,
|
|
1037
|
-
maxAge:
|
|
1038
|
-
gcMaxAge:
|
|
1234
|
+
maxAge: loaderOpts.maxAge ?? router.options.defaultPreloadMaxAge ?? router.options.defaultLoaderMaxAge ?? 0,
|
|
1235
|
+
gcMaxAge: loaderOpts.gcMaxAge ?? router.options.defaultPreloadGcMaxAge ?? router.options.defaultLoaderGcMaxAge ?? 0
|
|
1039
1236
|
});
|
|
1040
1237
|
return matches;
|
|
1041
1238
|
},
|
|
1042
1239
|
matchRoutes: (pathname, opts) => {
|
|
1043
|
-
var _router$state$pending2;
|
|
1044
1240
|
router.cleanMatchCache();
|
|
1045
1241
|
const matches = [];
|
|
1046
1242
|
if (!router.routeTree) {
|
|
1047
1243
|
return matches;
|
|
1048
1244
|
}
|
|
1049
|
-
const existingMatches = [...
|
|
1245
|
+
const existingMatches = [...store.currentMatches, ...(store.pendingMatches ?? [])];
|
|
1050
1246
|
const recurse = async routes => {
|
|
1051
|
-
var
|
|
1247
|
+
var _foundRoute$childRout;
|
|
1052
1248
|
const parentMatch = last(matches);
|
|
1053
|
-
let params = (
|
|
1054
|
-
const filteredRoutes = (
|
|
1249
|
+
let params = (parentMatch == null ? void 0 : parentMatch.params) ?? {};
|
|
1250
|
+
const filteredRoutes = (router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) ?? routes;
|
|
1055
1251
|
let foundRoutes = [];
|
|
1056
1252
|
const findMatchInRoutes = (parentRoutes, routes) => {
|
|
1057
1253
|
routes.some(route => {
|
|
1058
|
-
var _route$childRoutes, _route$childRoutes2
|
|
1254
|
+
var _route$childRoutes, _route$childRoutes2;
|
|
1059
1255
|
if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
|
|
1060
1256
|
return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
|
|
1061
1257
|
}
|
|
@@ -1063,28 +1259,21 @@ function createRouter(userOptions) {
|
|
|
1063
1259
|
const matchParams = matchPathname(router.basepath, pathname, {
|
|
1064
1260
|
to: route.fullPath,
|
|
1065
1261
|
fuzzy,
|
|
1066
|
-
caseSensitive:
|
|
1262
|
+
caseSensitive: route.options.caseSensitive ?? router.options.caseSensitive
|
|
1067
1263
|
});
|
|
1068
|
-
|
|
1069
|
-
// console.log(
|
|
1070
|
-
// router.basepath,
|
|
1071
|
-
// route.fullPath,
|
|
1072
|
-
// fuzzy,
|
|
1073
|
-
// pathname,
|
|
1074
|
-
// matchParams,
|
|
1075
|
-
// )
|
|
1076
|
-
|
|
1077
1264
|
if (matchParams) {
|
|
1078
1265
|
let parsedParams;
|
|
1079
1266
|
try {
|
|
1080
|
-
|
|
1081
|
-
parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
|
|
1267
|
+
parsedParams = (route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) ?? matchParams;
|
|
1082
1268
|
} catch (err) {
|
|
1083
1269
|
if (opts != null && opts.strictParseParams) {
|
|
1084
1270
|
throw err;
|
|
1085
1271
|
}
|
|
1086
1272
|
}
|
|
1087
|
-
params =
|
|
1273
|
+
params = {
|
|
1274
|
+
...params,
|
|
1275
|
+
...parsedParams
|
|
1276
|
+
};
|
|
1088
1277
|
}
|
|
1089
1278
|
if (!!matchParams) {
|
|
1090
1279
|
foundRoutes = [...parentRoutes, route];
|
|
@@ -1098,10 +1287,10 @@ function createRouter(userOptions) {
|
|
|
1098
1287
|
return;
|
|
1099
1288
|
}
|
|
1100
1289
|
foundRoutes.forEach(foundRoute => {
|
|
1101
|
-
var
|
|
1290
|
+
var _store$matchCache$mat;
|
|
1102
1291
|
const interpolatedPath = interpolatePath(foundRoute.routePath, params);
|
|
1103
1292
|
const matchId = interpolatePath(foundRoute.routeId, params, true);
|
|
1104
|
-
const match = existingMatches.find(d => d.matchId === matchId) || ((
|
|
1293
|
+
const match = existingMatches.find(d => d.matchId === matchId) || ((_store$matchCache$mat = store.matchCache[matchId]) == null ? void 0 : _store$matchCache$mat.match) || createRouteMatch(router, foundRoute, {
|
|
1105
1294
|
parentMatch,
|
|
1106
1295
|
matchId,
|
|
1107
1296
|
params,
|
|
@@ -1115,7 +1304,7 @@ function createRouter(userOptions) {
|
|
|
1115
1304
|
}
|
|
1116
1305
|
};
|
|
1117
1306
|
recurse([router.routeTree]);
|
|
1118
|
-
|
|
1307
|
+
linkMatches(matches);
|
|
1119
1308
|
return matches;
|
|
1120
1309
|
},
|
|
1121
1310
|
loadMatches: async (resolvedMatches, loaderOpts) => {
|
|
@@ -1140,32 +1329,31 @@ function createRouter(userOptions) {
|
|
|
1140
1329
|
}));
|
|
1141
1330
|
const matchPromises = resolvedMatches.map(async match => {
|
|
1142
1331
|
var _search$__data;
|
|
1143
|
-
const search = match.search;
|
|
1332
|
+
const search = match.store.search;
|
|
1144
1333
|
if ((_search$__data = search.__data) != null && _search$__data.matchId && search.__data.matchId !== match.matchId) {
|
|
1145
1334
|
return;
|
|
1146
1335
|
}
|
|
1147
1336
|
match.load(loaderOpts);
|
|
1148
|
-
if (match.status !== 'success' && match.__.loadPromise) {
|
|
1337
|
+
if (match.store.status !== 'success' && match.__.loadPromise) {
|
|
1149
1338
|
// Wait for the first sign of activity from the match
|
|
1150
1339
|
await match.__.loadPromise;
|
|
1151
1340
|
}
|
|
1152
1341
|
});
|
|
1153
|
-
router.notify();
|
|
1154
1342
|
await Promise.all(matchPromises);
|
|
1155
1343
|
},
|
|
1156
1344
|
loadMatchData: async routeMatch => {
|
|
1157
1345
|
if (isServer || !router.options.useServerData) {
|
|
1158
|
-
|
|
1159
|
-
return (_await$routeMatch$opt = await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
|
|
1346
|
+
return (await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
|
|
1160
1347
|
// parentLoaderPromise: routeMatch.parentMatch?.__.dataPromise,
|
|
1161
1348
|
params: routeMatch.params,
|
|
1162
|
-
search: routeMatch.routeSearch,
|
|
1349
|
+
search: routeMatch.store.routeSearch,
|
|
1163
1350
|
signal: routeMatch.__.abortController.signal
|
|
1164
|
-
})))
|
|
1351
|
+
}))) || {};
|
|
1165
1352
|
} else {
|
|
1166
1353
|
const next = router.buildNext({
|
|
1167
1354
|
to: '.',
|
|
1168
|
-
search: d =>
|
|
1355
|
+
search: d => ({
|
|
1356
|
+
...(d ?? {}),
|
|
1169
1357
|
__data: {
|
|
1170
1358
|
matchId: routeMatch.matchId
|
|
1171
1359
|
}
|
|
@@ -1194,16 +1382,15 @@ function createRouter(userOptions) {
|
|
|
1194
1382
|
}
|
|
1195
1383
|
},
|
|
1196
1384
|
invalidateRoute: opts => {
|
|
1197
|
-
var _router$state$pending3;
|
|
1198
1385
|
const next = router.buildNext(opts);
|
|
1199
1386
|
const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
|
|
1200
|
-
[...
|
|
1387
|
+
[...store.currentMatches, ...(store.pendingMatches ?? [])].forEach(match => {
|
|
1201
1388
|
if (unloadedMatchIds.includes(match.matchId)) {
|
|
1202
1389
|
match.invalidate();
|
|
1203
1390
|
}
|
|
1204
1391
|
});
|
|
1205
1392
|
},
|
|
1206
|
-
reload: () =>
|
|
1393
|
+
reload: () => navigate({
|
|
1207
1394
|
fromCurrent: true,
|
|
1208
1395
|
replace: true,
|
|
1209
1396
|
search: true
|
|
@@ -1212,26 +1399,28 @@ function createRouter(userOptions) {
|
|
|
1212
1399
|
return resolvePath(router.basepath, from, cleanPath(path));
|
|
1213
1400
|
},
|
|
1214
1401
|
matchRoute: (location, opts) => {
|
|
1215
|
-
var _location$from;
|
|
1216
1402
|
// const location = router.buildNext(opts)
|
|
1217
1403
|
|
|
1218
|
-
location =
|
|
1219
|
-
|
|
1220
|
-
|
|
1404
|
+
location = {
|
|
1405
|
+
...location,
|
|
1406
|
+
to: location.to ? router.resolvePath(location.from ?? '', location.to) : undefined
|
|
1407
|
+
};
|
|
1221
1408
|
const next = router.buildNext(location);
|
|
1222
1409
|
if (opts != null && opts.pending) {
|
|
1223
|
-
if (!
|
|
1410
|
+
if (!store.pendingLocation) {
|
|
1224
1411
|
return false;
|
|
1225
1412
|
}
|
|
1226
|
-
return !!matchPathname(router.basepath,
|
|
1413
|
+
return !!matchPathname(router.basepath, store.pendingLocation.pathname, {
|
|
1414
|
+
...opts,
|
|
1227
1415
|
to: next.pathname
|
|
1228
|
-
})
|
|
1416
|
+
});
|
|
1229
1417
|
}
|
|
1230
|
-
return
|
|
1418
|
+
return matchPathname(router.basepath, store.currentLocation.pathname, {
|
|
1419
|
+
...opts,
|
|
1231
1420
|
to: next.pathname
|
|
1232
|
-
})
|
|
1421
|
+
});
|
|
1233
1422
|
},
|
|
1234
|
-
navigate: async
|
|
1423
|
+
navigate: async _ref => {
|
|
1235
1424
|
let {
|
|
1236
1425
|
from,
|
|
1237
1426
|
to = '.',
|
|
@@ -1239,7 +1428,7 @@ function createRouter(userOptions) {
|
|
|
1239
1428
|
hash,
|
|
1240
1429
|
replace,
|
|
1241
1430
|
params
|
|
1242
|
-
} =
|
|
1431
|
+
} = _ref;
|
|
1243
1432
|
// If this link simply reloads the current route,
|
|
1244
1433
|
// make sure it has a new key so it will trigger a data refresh
|
|
1245
1434
|
|
|
@@ -1249,11 +1438,11 @@ function createRouter(userOptions) {
|
|
|
1249
1438
|
const fromString = String(from);
|
|
1250
1439
|
let isExternal;
|
|
1251
1440
|
try {
|
|
1252
|
-
new URL(
|
|
1441
|
+
new URL(`${toString}`);
|
|
1253
1442
|
isExternal = true;
|
|
1254
1443
|
} catch (e) {}
|
|
1255
1444
|
invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
|
|
1256
|
-
return
|
|
1445
|
+
return navigate({
|
|
1257
1446
|
from: fromString,
|
|
1258
1447
|
to: toString,
|
|
1259
1448
|
search,
|
|
@@ -1262,8 +1451,7 @@ function createRouter(userOptions) {
|
|
|
1262
1451
|
params
|
|
1263
1452
|
});
|
|
1264
1453
|
},
|
|
1265
|
-
buildLink:
|
|
1266
|
-
var _preload, _ref9;
|
|
1454
|
+
buildLink: _ref2 => {
|
|
1267
1455
|
let {
|
|
1268
1456
|
from,
|
|
1269
1457
|
to = '.',
|
|
@@ -1278,7 +1466,7 @@ function createRouter(userOptions) {
|
|
|
1278
1466
|
preloadGcMaxAge: userPreloadGcMaxAge,
|
|
1279
1467
|
preloadDelay: userPreloadDelay,
|
|
1280
1468
|
disabled
|
|
1281
|
-
} =
|
|
1469
|
+
} = _ref2;
|
|
1282
1470
|
// If this link simply reloads the current route,
|
|
1283
1471
|
// make sure it has a new key so it will trigger a data refresh
|
|
1284
1472
|
|
|
@@ -1286,7 +1474,7 @@ function createRouter(userOptions) {
|
|
|
1286
1474
|
// null for LinkUtils
|
|
1287
1475
|
|
|
1288
1476
|
try {
|
|
1289
|
-
new URL(
|
|
1477
|
+
new URL(`${to}`);
|
|
1290
1478
|
return {
|
|
1291
1479
|
type: 'external',
|
|
1292
1480
|
href: to
|
|
@@ -1301,15 +1489,15 @@ function createRouter(userOptions) {
|
|
|
1301
1489
|
replace
|
|
1302
1490
|
};
|
|
1303
1491
|
const next = router.buildNext(nextOpts);
|
|
1304
|
-
preload =
|
|
1305
|
-
const preloadDelay =
|
|
1492
|
+
preload = preload ?? router.options.defaultPreload;
|
|
1493
|
+
const preloadDelay = userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0;
|
|
1306
1494
|
|
|
1307
1495
|
// Compare path/hash for matches
|
|
1308
|
-
const pathIsEqual =
|
|
1309
|
-
const currentPathSplit =
|
|
1496
|
+
const pathIsEqual = store.currentLocation.pathname === next.pathname;
|
|
1497
|
+
const currentPathSplit = store.currentLocation.pathname.split('/');
|
|
1310
1498
|
const nextPathSplit = next.pathname.split('/');
|
|
1311
1499
|
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
1312
|
-
const hashIsEqual =
|
|
1500
|
+
const hashIsEqual = store.currentLocation.hash === next.hash;
|
|
1313
1501
|
// Combine the matches based on user options
|
|
1314
1502
|
const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
|
|
1315
1503
|
const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true;
|
|
@@ -1325,8 +1513,8 @@ function createRouter(userOptions) {
|
|
|
1325
1513
|
router.invalidateRoute(nextOpts);
|
|
1326
1514
|
}
|
|
1327
1515
|
|
|
1328
|
-
// All is well? Navigate!
|
|
1329
|
-
|
|
1516
|
+
// All is well? Navigate!
|
|
1517
|
+
navigate(nextOpts);
|
|
1330
1518
|
}
|
|
1331
1519
|
};
|
|
1332
1520
|
|
|
@@ -1379,143 +1567,15 @@ function createRouter(userOptions) {
|
|
|
1379
1567
|
};
|
|
1380
1568
|
},
|
|
1381
1569
|
buildNext: opts => {
|
|
1382
|
-
const next =
|
|
1570
|
+
const next = buildLocation(opts);
|
|
1383
1571
|
const matches = router.matchRoutes(next.pathname);
|
|
1384
|
-
const __preSearchFilters = matches.map(match =>
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
const __postSearchFilters = matches.map(match => {
|
|
1389
|
-
var _match$options$postSe;
|
|
1390
|
-
return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
|
|
1391
|
-
}).flat().filter(Boolean);
|
|
1392
|
-
return router.__.buildLocation(_extends({}, opts, {
|
|
1572
|
+
const __preSearchFilters = matches.map(match => match.options.preSearchFilters ?? []).flat().filter(Boolean);
|
|
1573
|
+
const __postSearchFilters = matches.map(match => match.options.postSearchFilters ?? []).flat().filter(Boolean);
|
|
1574
|
+
return buildLocation({
|
|
1575
|
+
...opts,
|
|
1393
1576
|
__preSearchFilters,
|
|
1394
1577
|
__postSearchFilters
|
|
1395
|
-
})
|
|
1396
|
-
},
|
|
1397
|
-
__: {
|
|
1398
|
-
buildRouteTree: rootRouteConfig => {
|
|
1399
|
-
const recurseRoutes = (routeConfigs, parent) => {
|
|
1400
|
-
return routeConfigs.map(routeConfig => {
|
|
1401
|
-
const routeOptions = routeConfig.options;
|
|
1402
|
-
const route = createRoute(routeConfig, routeOptions, parent, router);
|
|
1403
|
-
const existingRoute = router.routesById[route.routeId];
|
|
1404
|
-
if (existingRoute) {
|
|
1405
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
1406
|
-
console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
|
|
1407
|
-
}
|
|
1408
|
-
throw new Error();
|
|
1409
|
-
}
|
|
1410
|
-
router.routesById[route.routeId] = route;
|
|
1411
|
-
const children = routeConfig.children;
|
|
1412
|
-
route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
|
|
1413
|
-
return route;
|
|
1414
|
-
});
|
|
1415
|
-
};
|
|
1416
|
-
const routes = recurseRoutes([rootRouteConfig]);
|
|
1417
|
-
return routes[0];
|
|
1418
|
-
},
|
|
1419
|
-
parseLocation: (location, previousLocation) => {
|
|
1420
|
-
var _location$hash$split$;
|
|
1421
|
-
const parsedSearch = router.options.parseSearch(location.search);
|
|
1422
|
-
return {
|
|
1423
|
-
pathname: location.pathname,
|
|
1424
|
-
searchStr: location.search,
|
|
1425
|
-
search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
|
|
1426
|
-
hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
|
|
1427
|
-
href: "" + location.pathname + location.search + location.hash,
|
|
1428
|
-
state: location.state,
|
|
1429
|
-
key: location.key
|
|
1430
|
-
};
|
|
1431
|
-
},
|
|
1432
|
-
navigate: location => {
|
|
1433
|
-
const next = router.buildNext(location);
|
|
1434
|
-
return router.__.commitLocation(next, location.replace);
|
|
1435
|
-
},
|
|
1436
|
-
buildLocation: function buildLocation(dest) {
|
|
1437
|
-
var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
|
|
1438
|
-
if (dest === void 0) {
|
|
1439
|
-
dest = {};
|
|
1440
|
-
}
|
|
1441
|
-
const fromPathname = dest.fromCurrent ? router.state.latestLocation.pathname : (_dest$from = dest.from) != null ? _dest$from : router.state.latestLocation.pathname;
|
|
1442
|
-
let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
|
|
1443
|
-
const fromMatches = router.matchRoutes(router.state.latestLocation.pathname, {
|
|
1444
|
-
strictParseParams: true
|
|
1445
|
-
});
|
|
1446
|
-
const toMatches = router.matchRoutes(pathname);
|
|
1447
|
-
const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
|
|
1448
|
-
let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1449
|
-
if (nextParams) {
|
|
1450
|
-
toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1451
|
-
Object.assign({}, nextParams, fn(nextParams));
|
|
1452
|
-
});
|
|
1453
|
-
}
|
|
1454
|
-
pathname = interpolatePath(pathname, nextParams != null ? nextParams : {});
|
|
1455
|
-
|
|
1456
|
-
// Pre filters first
|
|
1457
|
-
const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.state.latestLocation.search) : router.state.latestLocation.search;
|
|
1458
|
-
|
|
1459
|
-
// Then the link/navigate function
|
|
1460
|
-
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
1461
|
-
: dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
|
|
1462
|
-
: (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
1463
|
-
: {};
|
|
1464
|
-
|
|
1465
|
-
// Then post filters
|
|
1466
|
-
const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1467
|
-
const search = replaceEqualDeep(router.state.latestLocation.search, postFilteredSearch);
|
|
1468
|
-
const searchStr = router.options.stringifySearch(search);
|
|
1469
|
-
let hash = dest.hash === true ? router.state.latestLocation.hash : functionalUpdate(dest.hash, router.state.latestLocation.hash);
|
|
1470
|
-
hash = hash ? "#" + hash : '';
|
|
1471
|
-
return {
|
|
1472
|
-
pathname,
|
|
1473
|
-
search,
|
|
1474
|
-
searchStr,
|
|
1475
|
-
state: router.state.latestLocation.state,
|
|
1476
|
-
hash,
|
|
1477
|
-
href: "" + pathname + searchStr + hash,
|
|
1478
|
-
key: dest.key
|
|
1479
|
-
};
|
|
1480
|
-
},
|
|
1481
|
-
commitLocation: (next, replace) => {
|
|
1482
|
-
const id = '' + Date.now() + Math.random();
|
|
1483
|
-
if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
|
|
1484
|
-
let nextAction = 'replace';
|
|
1485
|
-
if (!replace) {
|
|
1486
|
-
nextAction = 'push';
|
|
1487
|
-
}
|
|
1488
|
-
const isSameUrl = router.__.parseLocation(history.location).href === next.href;
|
|
1489
|
-
if (isSameUrl && !next.key) {
|
|
1490
|
-
nextAction = 'replace';
|
|
1491
|
-
}
|
|
1492
|
-
if (nextAction === 'replace') {
|
|
1493
|
-
history.replace({
|
|
1494
|
-
pathname: next.pathname,
|
|
1495
|
-
hash: next.hash,
|
|
1496
|
-
search: next.searchStr
|
|
1497
|
-
}, _extends({
|
|
1498
|
-
id
|
|
1499
|
-
}, next.state));
|
|
1500
|
-
} else {
|
|
1501
|
-
history.push({
|
|
1502
|
-
pathname: next.pathname,
|
|
1503
|
-
hash: next.hash,
|
|
1504
|
-
search: next.searchStr
|
|
1505
|
-
}, {
|
|
1506
|
-
id
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
|
-
router.navigationPromise = new Promise(resolve => {
|
|
1510
|
-
const previousNavigationResolve = router.resolveNavigation;
|
|
1511
|
-
router.resolveNavigation = () => {
|
|
1512
|
-
previousNavigationResolve();
|
|
1513
|
-
resolve();
|
|
1514
|
-
delete router.navigationPromise;
|
|
1515
|
-
};
|
|
1516
|
-
});
|
|
1517
|
-
return router.navigationPromise;
|
|
1518
|
-
}
|
|
1578
|
+
});
|
|
1519
1579
|
}
|
|
1520
1580
|
};
|
|
1521
1581
|
router.update(userOptions);
|
|
@@ -1527,14 +1587,16 @@ function createRouter(userOptions) {
|
|
|
1527
1587
|
function isCtrlEvent(e) {
|
|
1528
1588
|
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
1529
1589
|
}
|
|
1530
|
-
function
|
|
1590
|
+
function linkMatches(matches) {
|
|
1531
1591
|
matches.forEach((match, index) => {
|
|
1532
1592
|
const parent = matches[index - 1];
|
|
1533
1593
|
if (parent) {
|
|
1534
|
-
match.
|
|
1594
|
+
match.__.setParentMatch(parent);
|
|
1595
|
+
} else {
|
|
1596
|
+
match.__.setParentMatch(undefined);
|
|
1535
1597
|
}
|
|
1536
1598
|
});
|
|
1537
1599
|
}
|
|
1538
1600
|
|
|
1539
|
-
export { cleanPath, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, pick,
|
|
1601
|
+
export { cleanPath, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, pick, resolvePath, rootRouteId, sharedClone, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning };
|
|
1540
1602
|
//# sourceMappingURL=index.js.map
|