@tanstack/router-core 0.0.1-beta.174 → 0.0.1-beta.176
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 +1 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +57 -36
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +56 -36
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +158 -191
- package/build/types/defer.d.ts +19 -0
- package/build/types/fileRoute.d.ts +35 -0
- package/build/types/history.d.ts +31 -0
- package/build/types/index.d.ts +12 -780
- package/build/types/link.d.ts +92 -0
- package/build/types/path.d.ts +16 -0
- package/build/types/qss.d.ts +2 -0
- package/build/types/route.d.ts +234 -0
- package/build/types/routeInfo.d.ts +22 -0
- package/build/types/router.d.ts +251 -0
- package/build/types/scroll-restoration.d.ts +6 -0
- package/build/types/searchParams.d.ts +5 -0
- package/build/types/utils.d.ts +53 -0
- package/build/umd/index.development.js +57 -36
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +2 -2
- package/build/umd/index.production.js.map +1 -1
- package/package.json +3 -3
- package/src/route.ts +12 -16
- package/src/router.ts +100 -55
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type NoInfer<T> = [T][T extends any ? 0 : never];
|
|
2
|
+
export type IsAny<T, Y, N> = 1 extends 0 & T ? Y : N;
|
|
3
|
+
export type IsAnyBoolean<T> = 1 extends 0 & T ? true : false;
|
|
4
|
+
export type IsKnown<T, Y, N> = unknown extends T ? N : Y;
|
|
5
|
+
export type PickAsRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
|
6
|
+
export type PickAsPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
7
|
+
export type PickUnsafe<T, K> = K extends keyof T ? Pick<T, K> : never;
|
|
8
|
+
export type PickExtra<T, K> = {
|
|
9
|
+
[TKey in keyof K as string extends TKey ? never : TKey extends keyof T ? never : TKey]: K[TKey];
|
|
10
|
+
};
|
|
11
|
+
export type PickRequired<T> = {
|
|
12
|
+
[K in keyof T as undefined extends T[K] ? never : K]: T[K];
|
|
13
|
+
};
|
|
14
|
+
export type Expand<T> = T extends object ? T extends infer O ? {
|
|
15
|
+
[K in keyof O]: O[K];
|
|
16
|
+
} : never : T;
|
|
17
|
+
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => any ? I : never;
|
|
18
|
+
type Compute<T> = {
|
|
19
|
+
[K in keyof T]: T[K];
|
|
20
|
+
} | never;
|
|
21
|
+
type AllKeys<T> = T extends any ? keyof T : never;
|
|
22
|
+
export type MergeUnion<T, Keys extends keyof T = keyof T> = Compute<{
|
|
23
|
+
[K in Keys]: T[Keys];
|
|
24
|
+
} & {
|
|
25
|
+
[K in AllKeys<T>]?: T extends any ? K extends keyof T ? T[K] : never : never;
|
|
26
|
+
}>;
|
|
27
|
+
export type Values<O> = O[ValueKeys<O>];
|
|
28
|
+
export type ValueKeys<O> = Extract<keyof O, PropertyKey>;
|
|
29
|
+
export type DeepAwaited<T> = T extends Promise<infer A> ? DeepAwaited<A> : T extends Record<infer A, Promise<infer B>> ? {
|
|
30
|
+
[K in A]: DeepAwaited<B>;
|
|
31
|
+
} : T;
|
|
32
|
+
export type PathParamMask<TRoutePath extends string> = TRoutePath extends `${infer L}/$${infer C}/${infer R}` ? PathParamMask<`${L}/${string}/${R}`> : TRoutePath extends `${infer L}/$${infer C}` ? PathParamMask<`${L}/${string}`> : TRoutePath;
|
|
33
|
+
export type Timeout = ReturnType<typeof setTimeout>;
|
|
34
|
+
export type Updater<TPrevious, TResult = TPrevious> = TResult | ((prev?: TPrevious) => TResult);
|
|
35
|
+
export type PickExtract<T, U> = {
|
|
36
|
+
[K in keyof T as T[K] extends U ? K : never]: T[K];
|
|
37
|
+
};
|
|
38
|
+
export type PickExclude<T, U> = {
|
|
39
|
+
[K in keyof T as T[K] extends U ? never : K]: T[K];
|
|
40
|
+
};
|
|
41
|
+
export declare function last<T>(arr: T[]): T | undefined;
|
|
42
|
+
export declare function functionalUpdate<TResult>(updater: Updater<TResult>, previous: TResult): TResult;
|
|
43
|
+
export declare function pick<T, K extends keyof T>(parent: T, keys: K[]): Pick<T, K>;
|
|
44
|
+
/**
|
|
45
|
+
* This function returns `a` if `b` is deeply equal.
|
|
46
|
+
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
47
|
+
* This can be used for structural sharing between immutable JSON values for example.
|
|
48
|
+
* Do not use this with signals
|
|
49
|
+
*/
|
|
50
|
+
export declare function replaceEqualDeep<T>(prev: any, _next: T): T;
|
|
51
|
+
export declare function isPlainObject(o: any): boolean;
|
|
52
|
+
export declare function partialDeepEqual(a: any, b: any): boolean;
|
|
53
|
+
export {};
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
11
|
(function (global, factory) {
|
|
12
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports
|
|
13
|
-
typeof define === 'function' && define.amd ? define(['exports'
|
|
12
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
13
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
14
14
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RouterCore = {}));
|
|
15
15
|
})(this, (function (exports) { 'use strict';
|
|
16
16
|
|
|
@@ -804,6 +804,8 @@
|
|
|
804
804
|
//
|
|
805
805
|
|
|
806
806
|
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
807
|
+
const visibilityChangeEvent = 'visibilitychange';
|
|
808
|
+
const focusEvent = 'focus';
|
|
807
809
|
class Router {
|
|
808
810
|
#unsubHistory;
|
|
809
811
|
resetNextScroll = false;
|
|
@@ -880,12 +882,26 @@
|
|
|
880
882
|
this.__store.setState(s => Object.assign(s, getInitialRouterState()));
|
|
881
883
|
};
|
|
882
884
|
mount = () => {
|
|
883
|
-
//
|
|
884
|
-
//
|
|
885
|
+
// addEventListener does not exist in React Native, but window does
|
|
886
|
+
// In the future, we might need to invert control here for more adapters
|
|
887
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
888
|
+
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
889
|
+
window.addEventListener(visibilityChangeEvent, this.#onFocus, false);
|
|
890
|
+
window.addEventListener(focusEvent, this.#onFocus, false);
|
|
891
|
+
}
|
|
885
892
|
this.safeLoad();
|
|
886
|
-
|
|
893
|
+
return () => {
|
|
894
|
+
if (typeof window !== 'undefined' && window.removeEventListener) {
|
|
895
|
+
window.removeEventListener(visibilityChangeEvent, this.#onFocus);
|
|
896
|
+
window.removeEventListener(focusEvent, this.#onFocus);
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
};
|
|
900
|
+
#onFocus = () => {
|
|
901
|
+
if (this.options.refetchOnWindowFocus ?? true) {
|
|
902
|
+
this.reload();
|
|
903
|
+
}
|
|
887
904
|
};
|
|
888
|
-
|
|
889
905
|
update = opts => {
|
|
890
906
|
this.options = {
|
|
891
907
|
...this.options,
|
|
@@ -956,7 +972,6 @@
|
|
|
956
972
|
};
|
|
957
973
|
|
|
958
974
|
// Cancel any pending matches
|
|
959
|
-
// this.cancelMatches()
|
|
960
975
|
|
|
961
976
|
let pendingMatches;
|
|
962
977
|
this.#emit({
|
|
@@ -999,6 +1014,9 @@
|
|
|
999
1014
|
if (latestPromise = checkLatest()) {
|
|
1000
1015
|
return latestPromise;
|
|
1001
1016
|
}
|
|
1017
|
+
const exitingMatchIds = this.state.matchIds.filter(id => !this.state.pendingMatchIds.includes(id));
|
|
1018
|
+
const enteringMatchIds = this.state.pendingMatchIds.filter(id => !this.state.matchIds.includes(id));
|
|
1019
|
+
const stayingMatchIds = this.state.matchIds.filter(id => this.state.pendingMatchIds.includes(id));
|
|
1002
1020
|
this.__store.setState(s => ({
|
|
1003
1021
|
...s,
|
|
1004
1022
|
status: 'idle',
|
|
@@ -1006,6 +1024,13 @@
|
|
|
1006
1024
|
matchIds: s.pendingMatchIds,
|
|
1007
1025
|
pendingMatchIds: []
|
|
1008
1026
|
}));
|
|
1027
|
+
[[exitingMatchIds, 'onLeave'], [enteringMatchIds, 'onEnter'], [stayingMatchIds, 'onTransition']].forEach(([matchIds, hook]) => {
|
|
1028
|
+
matchIds.forEach(id => {
|
|
1029
|
+
const match = this.getRouteMatch(id);
|
|
1030
|
+
const route = this.getRoute(match.routeId);
|
|
1031
|
+
route.options[hook]?.(match);
|
|
1032
|
+
});
|
|
1033
|
+
});
|
|
1009
1034
|
this.#emit({
|
|
1010
1035
|
type: 'onLoad',
|
|
1011
1036
|
from: prevLocation,
|
|
@@ -1022,6 +1047,9 @@
|
|
|
1022
1047
|
}
|
|
1023
1048
|
});
|
|
1024
1049
|
this.latestLoadPromise = promise;
|
|
1050
|
+
this.latestLoadPromise.then(() => {
|
|
1051
|
+
this.cleanMatches();
|
|
1052
|
+
});
|
|
1025
1053
|
return this.latestLoadPromise;
|
|
1026
1054
|
};
|
|
1027
1055
|
#mergeMatches = (prevMatchesById, nextMatches) => {
|
|
@@ -1066,7 +1094,7 @@
|
|
|
1066
1094
|
const now = Date.now();
|
|
1067
1095
|
const outdatedMatchIds = Object.values(this.state.matchesById).filter(match => {
|
|
1068
1096
|
const route = this.getRoute(match.routeId);
|
|
1069
|
-
return !this.state.matchIds.includes(match.id) && !this.state.pendingMatchIds.includes(match.id) && match.
|
|
1097
|
+
return !this.state.matchIds.includes(match.id) && !this.state.pendingMatchIds.includes(match.id) && (match.preloadMaxAge > -1 ? match.updatedAt + match.preloadMaxAge < now : true) && (route.options.gcMaxAge ? match.updatedAt + route.options.gcMaxAge < now : true);
|
|
1070
1098
|
}).map(d => d.id);
|
|
1071
1099
|
if (outdatedMatchIds.length) {
|
|
1072
1100
|
this.__store.setState(s => {
|
|
@@ -1154,8 +1182,8 @@
|
|
|
1154
1182
|
params: routeParams,
|
|
1155
1183
|
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1156
1184
|
updatedAt: Date.now(),
|
|
1157
|
-
|
|
1158
|
-
|
|
1185
|
+
maxAge: -1,
|
|
1186
|
+
preloadMaxAge: -1,
|
|
1159
1187
|
routeSearch: {},
|
|
1160
1188
|
search: {},
|
|
1161
1189
|
status: hasLoaders ? 'pending' : 'success',
|
|
@@ -1251,11 +1279,10 @@
|
|
|
1251
1279
|
paramsError: match.paramsError,
|
|
1252
1280
|
searchError: match.searchError,
|
|
1253
1281
|
params: match.params,
|
|
1254
|
-
|
|
1282
|
+
preloadMaxAge: 0
|
|
1255
1283
|
}));
|
|
1256
1284
|
});
|
|
1257
1285
|
}
|
|
1258
|
-
this.cleanMatches();
|
|
1259
1286
|
let firstBadMatchIndex;
|
|
1260
1287
|
|
|
1261
1288
|
// Check each match middleware to see if the route can be accessed
|
|
@@ -1317,8 +1344,7 @@
|
|
|
1317
1344
|
matchPromises.push((async () => {
|
|
1318
1345
|
const parentMatchPromise = matchPromises[index - 1];
|
|
1319
1346
|
const route = this.getRoute(match.routeId);
|
|
1320
|
-
if (match.isFetching || match.status === 'success' && !
|
|
1321
|
-
matchId: match.id,
|
|
1347
|
+
if (match.isFetching || match.status === 'success' && !isMatchInvalid(match, {
|
|
1322
1348
|
preload: opts?.preload
|
|
1323
1349
|
})) {
|
|
1324
1350
|
return this.getRouteMatch(match.id)?.loadPromise;
|
|
@@ -1391,7 +1417,6 @@
|
|
|
1391
1417
|
})());
|
|
1392
1418
|
});
|
|
1393
1419
|
await Promise.all(matchPromises);
|
|
1394
|
-
this.cleanMatches();
|
|
1395
1420
|
};
|
|
1396
1421
|
reload = () => {
|
|
1397
1422
|
return this.navigate({
|
|
@@ -1576,7 +1601,7 @@
|
|
|
1576
1601
|
dehydrate = () => {
|
|
1577
1602
|
return {
|
|
1578
1603
|
state: {
|
|
1579
|
-
dehydratedMatches: this.state.matches.map(d => pick(d, ['fetchedAt', 'invalid', '
|
|
1604
|
+
dehydratedMatches: this.state.matches.map(d => pick(d, ['fetchedAt', 'invalid', 'preloadMaxAge', 'maxAge', 'id', 'loaderData', 'status', 'updatedAt']))
|
|
1580
1605
|
}
|
|
1581
1606
|
};
|
|
1582
1607
|
};
|
|
@@ -1815,7 +1840,6 @@
|
|
|
1815
1840
|
...next.state
|
|
1816
1841
|
});
|
|
1817
1842
|
this.resetNextScroll = location.resetScroll ?? true;
|
|
1818
|
-
console.log('resetScroll', this.resetNextScroll);
|
|
1819
1843
|
return this.latestLoadPromise;
|
|
1820
1844
|
};
|
|
1821
1845
|
getRouteMatch = id => {
|
|
@@ -1840,17 +1864,17 @@
|
|
|
1840
1864
|
if (!match) return;
|
|
1841
1865
|
const route = this.getRoute(match.routeId);
|
|
1842
1866
|
const updatedAt = opts?.updatedAt ?? Date.now();
|
|
1843
|
-
const
|
|
1844
|
-
const
|
|
1867
|
+
const preloadMaxAge = opts?.maxAge ?? route.options.preloadMaxAge ?? this.options.defaultPreloadMaxAge ?? 5000;
|
|
1868
|
+
const maxAge = opts?.maxAge ?? route.options.maxAge ?? this.options.defaultMaxAge ?? -1;
|
|
1845
1869
|
this.setRouteMatch(id, s => ({
|
|
1846
1870
|
...s,
|
|
1847
1871
|
error: undefined,
|
|
1848
1872
|
status: 'success',
|
|
1849
1873
|
isFetching: false,
|
|
1850
|
-
updatedAt:
|
|
1874
|
+
updatedAt: updatedAt,
|
|
1851
1875
|
loaderData: functionalUpdate(updater, s.loaderData),
|
|
1852
|
-
|
|
1853
|
-
|
|
1876
|
+
preloadMaxAge,
|
|
1877
|
+
maxAge
|
|
1854
1878
|
}));
|
|
1855
1879
|
};
|
|
1856
1880
|
invalidate = async opts => {
|
|
@@ -1881,20 +1905,6 @@
|
|
|
1881
1905
|
return this.reload();
|
|
1882
1906
|
}
|
|
1883
1907
|
};
|
|
1884
|
-
getIsInvalid = opts => {
|
|
1885
|
-
if (!opts?.matchId) {
|
|
1886
|
-
return !!this.state.matches.find(d => this.getIsInvalid({
|
|
1887
|
-
matchId: d.id,
|
|
1888
|
-
preload: opts?.preload
|
|
1889
|
-
}));
|
|
1890
|
-
}
|
|
1891
|
-
const match = this.getRouteMatch(opts?.matchId);
|
|
1892
|
-
if (!match) {
|
|
1893
|
-
return false;
|
|
1894
|
-
}
|
|
1895
|
-
const now = Date.now();
|
|
1896
|
-
return match.invalid || (opts?.preload ? match.preloadInvalidAt : match.invalidAt) < now;
|
|
1897
|
-
};
|
|
1898
1908
|
}
|
|
1899
1909
|
|
|
1900
1910
|
// Detect if we're in the DOM
|
|
@@ -1940,6 +1950,16 @@
|
|
|
1940
1950
|
return imported[key || 'default'](...args);
|
|
1941
1951
|
};
|
|
1942
1952
|
}
|
|
1953
|
+
function isMatchInvalid(match, opts) {
|
|
1954
|
+
const now = Date.now();
|
|
1955
|
+
if (match.invalid) {
|
|
1956
|
+
return true;
|
|
1957
|
+
}
|
|
1958
|
+
if (opts?.preload) {
|
|
1959
|
+
return match.preloadMaxAge < 0 ? false : match.updatedAt + match.preloadMaxAge < now;
|
|
1960
|
+
}
|
|
1961
|
+
return match.maxAge < 0 ? false : match.updatedAt + match.maxAge < now;
|
|
1962
|
+
}
|
|
1943
1963
|
|
|
1944
1964
|
const windowKey = 'window';
|
|
1945
1965
|
const delimiter = '___';
|
|
@@ -2106,6 +2126,7 @@
|
|
|
2106
2126
|
exports.interpolatePath = interpolatePath;
|
|
2107
2127
|
exports.invariant = invariant;
|
|
2108
2128
|
exports.isDehydratedDeferred = isDehydratedDeferred;
|
|
2129
|
+
exports.isMatchInvalid = isMatchInvalid;
|
|
2109
2130
|
exports.isPlainObject = isPlainObject;
|
|
2110
2131
|
exports.isRedirect = isRedirect;
|
|
2111
2132
|
exports.joinPaths = joinPaths;
|