@tanstack/router-core 1.168.9 → 1.168.11
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/hash-scroll.cjs +1 -1
- package/dist/cjs/hash-scroll.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/load-matches.cjs +6 -6
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/router.cjs +57 -58
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -1
- package/dist/cjs/scroll-restoration.cjs +1 -1
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/ssr/createRequestHandler.cjs +2 -2
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.cjs +41 -32
- package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.d.cts +12 -4
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.d.cts +2 -2
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -1
- package/dist/cjs/ssr/serializer/transformer.cjs +16 -14
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.d.cts +24 -23
- package/dist/cjs/ssr/ssr-client.cjs +9 -9
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +31 -9
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.d.cts +3 -2
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +4 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/stores.cjs +57 -57
- package/dist/cjs/stores.cjs.map +1 -1
- package/dist/cjs/stores.d.cts +16 -16
- package/dist/esm/hash-scroll.js +1 -1
- package/dist/esm/hash-scroll.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/load-matches.js +6 -6
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/router.d.ts +3 -1
- package/dist/esm/router.js +57 -58
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.js +1 -1
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/ssr/createRequestHandler.js +2 -2
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/serializer/RawStream.d.ts +12 -4
- package/dist/esm/ssr/serializer/RawStream.js +41 -32
- package/dist/esm/ssr/serializer/RawStream.js.map +1 -1
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.d.ts +2 -2
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -1
- package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -1
- package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -1
- package/dist/esm/ssr/serializer/transformer.d.ts +24 -23
- package/dist/esm/ssr/serializer/transformer.js +16 -14
- package/dist/esm/ssr/serializer/transformer.js.map +1 -1
- package/dist/esm/ssr/ssr-client.js +9 -9
- package/dist/esm/ssr/ssr-client.js.map +1 -1
- package/dist/esm/ssr/ssr-server.d.ts +3 -2
- package/dist/esm/ssr/ssr-server.js +31 -9
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.js +4 -1
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/dist/esm/stores.d.ts +16 -16
- package/dist/esm/stores.js +58 -58
- package/dist/esm/stores.js.map +1 -1
- package/package.json +3 -3
- package/src/hash-scroll.ts +1 -1
- package/src/index.ts +1 -1
- package/src/load-matches.ts +8 -11
- package/src/router.ts +74 -85
- package/src/scroll-restoration.ts +1 -1
- package/src/ssr/createRequestHandler.ts +4 -5
- package/src/ssr/serializer/RawStream.ts +65 -56
- package/src/ssr/serializer/ShallowErrorPlugin.ts +2 -2
- package/src/ssr/serializer/seroval-plugins.ts +2 -1
- package/src/ssr/serializer/transformer.ts +71 -76
- package/src/ssr/ssr-client.ts +8 -12
- package/src/ssr/ssr-server.ts +39 -7
- package/src/ssr/transformStreamWithRouter.ts +3 -0
- package/src/stores.ts +86 -86
package/dist/cjs/stores.cjs
CHANGED
|
@@ -5,25 +5,25 @@ const require_lru_cache = require("./lru-cache.cjs");
|
|
|
5
5
|
function createNonReactiveMutableStore(initialValue) {
|
|
6
6
|
let value = initialValue;
|
|
7
7
|
return {
|
|
8
|
-
get
|
|
8
|
+
get() {
|
|
9
9
|
return value;
|
|
10
10
|
},
|
|
11
|
-
|
|
12
|
-
value =
|
|
11
|
+
set(nextOrUpdater) {
|
|
12
|
+
value = require_utils.functionalUpdate(nextOrUpdater, value);
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
/** SSR non-reactive createReadonlyStore */
|
|
17
17
|
function createNonReactiveReadonlyStore(read) {
|
|
18
|
-
return { get
|
|
18
|
+
return { get() {
|
|
19
19
|
return read();
|
|
20
20
|
} };
|
|
21
21
|
}
|
|
22
22
|
function createRouterStores(initialState, config) {
|
|
23
23
|
const { createMutableStore, createReadonlyStore, batch, init } = config;
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
24
|
+
const matchStores = /* @__PURE__ */ new Map();
|
|
25
|
+
const pendingMatchStores = /* @__PURE__ */ new Map();
|
|
26
|
+
const cachedMatchStores = /* @__PURE__ */ new Map();
|
|
27
27
|
const status = createMutableStore(initialState.status);
|
|
28
28
|
const loadedAt = createMutableStore(initialState.loadedAt);
|
|
29
29
|
const isLoading = createMutableStore(initialState.isLoading);
|
|
@@ -33,40 +33,40 @@ function createRouterStores(initialState, config) {
|
|
|
33
33
|
const statusCode = createMutableStore(initialState.statusCode);
|
|
34
34
|
const redirect = createMutableStore(initialState.redirect);
|
|
35
35
|
const matchesId = createMutableStore([]);
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
return
|
|
36
|
+
const pendingIds = createMutableStore([]);
|
|
37
|
+
const cachedIds = createMutableStore([]);
|
|
38
|
+
const matches = createReadonlyStore(() => readPoolMatches(matchStores, matchesId.get()));
|
|
39
|
+
const pendingMatches = createReadonlyStore(() => readPoolMatches(pendingMatchStores, pendingIds.get()));
|
|
40
|
+
const cachedMatches = createReadonlyStore(() => readPoolMatches(cachedMatchStores, cachedIds.get()));
|
|
41
|
+
const firstId = createReadonlyStore(() => matchesId.get()[0]);
|
|
42
|
+
const hasPending = createReadonlyStore(() => matchesId.get().some((matchId) => {
|
|
43
|
+
return matchStores.get(matchId)?.get().status === "pending";
|
|
44
44
|
}));
|
|
45
|
-
const
|
|
46
|
-
locationHref: location.
|
|
47
|
-
resolvedLocationHref: resolvedLocation.
|
|
48
|
-
status: status.
|
|
45
|
+
const matchRouteDeps = createReadonlyStore(() => ({
|
|
46
|
+
locationHref: location.get().href,
|
|
47
|
+
resolvedLocationHref: resolvedLocation.get()?.href,
|
|
48
|
+
status: status.get()
|
|
49
49
|
}));
|
|
50
50
|
const __store = createReadonlyStore(() => ({
|
|
51
|
-
status: status.
|
|
52
|
-
loadedAt: loadedAt.
|
|
53
|
-
isLoading: isLoading.
|
|
54
|
-
isTransitioning: isTransitioning.
|
|
55
|
-
matches:
|
|
56
|
-
location: location.
|
|
57
|
-
resolvedLocation: resolvedLocation.
|
|
58
|
-
statusCode: statusCode.
|
|
59
|
-
redirect: redirect.
|
|
51
|
+
status: status.get(),
|
|
52
|
+
loadedAt: loadedAt.get(),
|
|
53
|
+
isLoading: isLoading.get(),
|
|
54
|
+
isTransitioning: isTransitioning.get(),
|
|
55
|
+
matches: matches.get(),
|
|
56
|
+
location: location.get(),
|
|
57
|
+
resolvedLocation: resolvedLocation.get(),
|
|
58
|
+
statusCode: statusCode.get(),
|
|
59
|
+
redirect: redirect.get()
|
|
60
60
|
}));
|
|
61
61
|
const matchStoreByRouteIdCache = require_lru_cache.createLRUCache(64);
|
|
62
|
-
function
|
|
62
|
+
function getRouteMatchStore(routeId) {
|
|
63
63
|
let cached = matchStoreByRouteIdCache.get(routeId);
|
|
64
64
|
if (!cached) {
|
|
65
65
|
cached = createReadonlyStore(() => {
|
|
66
|
-
const ids = matchesId.
|
|
66
|
+
const ids = matchesId.get();
|
|
67
67
|
for (const id of ids) {
|
|
68
|
-
const matchStore =
|
|
69
|
-
if (matchStore && matchStore.routeId === routeId) return matchStore.
|
|
68
|
+
const matchStore = matchStores.get(id);
|
|
69
|
+
if (matchStore && matchStore.routeId === routeId) return matchStore.get();
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
matchStoreByRouteIdCache.set(routeId, cached);
|
|
@@ -83,33 +83,33 @@ function createRouterStores(initialState, config) {
|
|
|
83
83
|
statusCode,
|
|
84
84
|
redirect,
|
|
85
85
|
matchesId,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
86
|
+
pendingIds,
|
|
87
|
+
cachedIds,
|
|
88
|
+
matches,
|
|
89
|
+
pendingMatches,
|
|
90
|
+
cachedMatches,
|
|
91
|
+
firstId,
|
|
92
|
+
hasPending,
|
|
93
|
+
matchRouteDeps,
|
|
94
|
+
matchStores,
|
|
95
|
+
pendingMatchStores,
|
|
96
|
+
cachedMatchStores,
|
|
97
97
|
__store,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
getRouteMatchStore,
|
|
99
|
+
setMatches,
|
|
100
|
+
setPending,
|
|
101
|
+
setCached
|
|
102
102
|
};
|
|
103
|
-
|
|
103
|
+
setMatches(initialState.matches);
|
|
104
104
|
init?.(store);
|
|
105
|
-
function
|
|
106
|
-
reconcileMatchPool(nextMatches,
|
|
105
|
+
function setMatches(nextMatches) {
|
|
106
|
+
reconcileMatchPool(nextMatches, matchStores, matchesId, createMutableStore, batch);
|
|
107
107
|
}
|
|
108
|
-
function
|
|
109
|
-
reconcileMatchPool(nextMatches,
|
|
108
|
+
function setPending(nextMatches) {
|
|
109
|
+
reconcileMatchPool(nextMatches, pendingMatchStores, pendingIds, createMutableStore, batch);
|
|
110
110
|
}
|
|
111
|
-
function
|
|
112
|
-
reconcileMatchPool(nextMatches,
|
|
111
|
+
function setCached(nextMatches) {
|
|
112
|
+
reconcileMatchPool(nextMatches, cachedMatchStores, cachedIds, createMutableStore, batch);
|
|
113
113
|
}
|
|
114
114
|
return store;
|
|
115
115
|
}
|
|
@@ -117,7 +117,7 @@ function readPoolMatches(pool, ids) {
|
|
|
117
117
|
const matches = [];
|
|
118
118
|
for (const id of ids) {
|
|
119
119
|
const matchStore = pool.get(id);
|
|
120
|
-
if (matchStore) matches.push(matchStore.
|
|
120
|
+
if (matchStore) matches.push(matchStore.get());
|
|
121
121
|
}
|
|
122
122
|
return matches;
|
|
123
123
|
}
|
|
@@ -135,9 +135,9 @@ function reconcileMatchPool(nextMatches, pool, idStore, createMutableStore, batc
|
|
|
135
135
|
continue;
|
|
136
136
|
}
|
|
137
137
|
existing.routeId = nextMatch.routeId;
|
|
138
|
-
if (existing.
|
|
138
|
+
if (existing.get() !== nextMatch) existing.set(nextMatch);
|
|
139
139
|
}
|
|
140
|
-
if (!require_utils.arraysEqual(idStore.
|
|
140
|
+
if (!require_utils.arraysEqual(idStore.get(), nextIds)) idStore.set(nextIds);
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
143
|
//#endregion
|
package/dist/cjs/stores.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stores.cjs","names":[],"sources":["../../src/stores.ts"],"sourcesContent":["import { createLRUCache } from './lru-cache'\nimport { arraysEqual } from './utils'\n\nimport type { AnyRoute } from './route'\nimport type { RouterState } from './router'\nimport type { FullSearchSchema } from './routeInfo'\nimport type { ParsedLocation } from './location'\nimport type { AnyRedirect } from './redirect'\nimport type { AnyRouteMatch } from './Matches'\n\nexport interface RouterReadableStore<TValue> {\n readonly state: TValue\n}\n\nexport interface RouterWritableStore<\n TValue,\n> extends RouterReadableStore<TValue> {\n setState: (updater: (prev: TValue) => TValue) => void\n}\n\nexport type RouterBatchFn = (fn: () => void) => void\n\nexport type MutableStoreFactory = <TValue>(\n initialValue: TValue,\n) => RouterWritableStore<TValue>\n\nexport type ReadonlyStoreFactory = <TValue>(\n read: () => TValue,\n) => RouterReadableStore<TValue>\n\nexport type GetStoreConfig = (opts: { isServer?: boolean }) => StoreConfig\n\nexport type StoreConfig = {\n createMutableStore: MutableStoreFactory\n createReadonlyStore: ReadonlyStoreFactory\n batch: RouterBatchFn\n init?: (stores: RouterStores<AnyRoute>) => void\n}\n\ntype MatchStore = RouterWritableStore<AnyRouteMatch> & {\n routeId?: string\n}\ntype ReadableStore<TValue> = RouterReadableStore<TValue>\n\n/** SSR non-reactive createMutableStore */\nexport function createNonReactiveMutableStore<TValue>(\n initialValue: TValue,\n): RouterWritableStore<TValue> {\n let value = initialValue\n\n return {\n get state() {\n return value\n },\n setState(updater: (prev: TValue) => TValue) {\n value = updater(value)\n },\n }\n}\n\n/** SSR non-reactive createReadonlyStore */\nexport function createNonReactiveReadonlyStore<TValue>(\n read: () => TValue,\n): RouterReadableStore<TValue> {\n return {\n get state() {\n return read()\n },\n }\n}\n\nexport interface RouterStores<in out TRouteTree extends AnyRoute> {\n status: RouterWritableStore<RouterState<TRouteTree>['status']>\n loadedAt: RouterWritableStore<number>\n isLoading: RouterWritableStore<boolean>\n isTransitioning: RouterWritableStore<boolean>\n location: RouterWritableStore<ParsedLocation<FullSearchSchema<TRouteTree>>>\n resolvedLocation: RouterWritableStore<\n ParsedLocation<FullSearchSchema<TRouteTree>> | undefined\n >\n statusCode: RouterWritableStore<number>\n redirect: RouterWritableStore<AnyRedirect | undefined>\n matchesId: RouterWritableStore<Array<string>>\n pendingMatchesId: RouterWritableStore<Array<string>>\n /** @internal */\n cachedMatchesId: RouterWritableStore<Array<string>>\n activeMatchesSnapshot: ReadableStore<Array<AnyRouteMatch>>\n pendingMatchesSnapshot: ReadableStore<Array<AnyRouteMatch>>\n cachedMatchesSnapshot: ReadableStore<Array<AnyRouteMatch>>\n firstMatchId: ReadableStore<string | undefined>\n hasPendingMatches: ReadableStore<boolean>\n matchRouteReactivity: ReadableStore<{\n locationHref: string\n resolvedLocationHref: string | undefined\n status: RouterState<TRouteTree>['status']\n }>\n __store: RouterReadableStore<RouterState<TRouteTree>>\n\n activeMatchStoresById: Map<string, MatchStore>\n pendingMatchStoresById: Map<string, MatchStore>\n cachedMatchStoresById: Map<string, MatchStore>\n\n /**\n * Get a computed store that resolves a routeId to its current match state.\n * Returns the same cached store instance for repeated calls with the same key.\n * The computed depends on matchesId + the individual match store, so\n * subscribers are only notified when the resolved match state changes.\n */\n getMatchStoreByRouteId: (\n routeId: string,\n ) => RouterReadableStore<AnyRouteMatch | undefined>\n\n setActiveMatches: (nextMatches: Array<AnyRouteMatch>) => void\n setPendingMatches: (nextMatches: Array<AnyRouteMatch>) => void\n setCachedMatches: (nextMatches: Array<AnyRouteMatch>) => void\n}\n\nexport function createRouterStores<TRouteTree extends AnyRoute>(\n initialState: RouterState<TRouteTree>,\n config: StoreConfig,\n): RouterStores<TRouteTree> {\n const { createMutableStore, createReadonlyStore, batch, init } = config\n\n // non reactive utilities\n const activeMatchStoresById = new Map<string, MatchStore>()\n const pendingMatchStoresById = new Map<string, MatchStore>()\n const cachedMatchStoresById = new Map<string, MatchStore>()\n\n // atoms\n const status = createMutableStore(initialState.status)\n const loadedAt = createMutableStore(initialState.loadedAt)\n const isLoading = createMutableStore(initialState.isLoading)\n const isTransitioning = createMutableStore(initialState.isTransitioning)\n const location = createMutableStore(initialState.location)\n const resolvedLocation = createMutableStore(initialState.resolvedLocation)\n const statusCode = createMutableStore(initialState.statusCode)\n const redirect = createMutableStore(initialState.redirect)\n const matchesId = createMutableStore<Array<string>>([])\n const pendingMatchesId = createMutableStore<Array<string>>([])\n const cachedMatchesId = createMutableStore<Array<string>>([])\n\n // 1st order derived stores\n const activeMatchesSnapshot = createReadonlyStore(() =>\n readPoolMatches(activeMatchStoresById, matchesId.state),\n )\n const pendingMatchesSnapshot = createReadonlyStore(() =>\n readPoolMatches(pendingMatchStoresById, pendingMatchesId.state),\n )\n const cachedMatchesSnapshot = createReadonlyStore(() =>\n readPoolMatches(cachedMatchStoresById, cachedMatchesId.state),\n )\n const firstMatchId = createReadonlyStore(() => matchesId.state[0])\n const hasPendingMatches = createReadonlyStore(() =>\n matchesId.state.some((matchId) => {\n const store = activeMatchStoresById.get(matchId)\n return store?.state.status === 'pending'\n }),\n )\n const matchRouteReactivity = createReadonlyStore(() => ({\n locationHref: location.state.href,\n resolvedLocationHref: resolvedLocation.state?.href,\n status: status.state,\n }))\n\n // compatibility \"big\" state store\n const __store = createReadonlyStore(() => ({\n status: status.state,\n loadedAt: loadedAt.state,\n isLoading: isLoading.state,\n isTransitioning: isTransitioning.state,\n matches: activeMatchesSnapshot.state,\n location: location.state,\n resolvedLocation: resolvedLocation.state,\n statusCode: statusCode.state,\n redirect: redirect.state,\n }))\n\n // Per-routeId computed store cache.\n // Each entry resolves routeId → match state through the signal graph,\n // giving consumers a single store to subscribe to instead of the\n // two-level byRouteId → matchStore pattern.\n //\n // 64 max size is arbitrary, this is only for active matches anyway so\n // it should be plenty. And we already have a 32 limit due to route\n // matching bitmask anyway.\n const matchStoreByRouteIdCache = createLRUCache<\n string,\n RouterReadableStore<AnyRouteMatch | undefined>\n >(64)\n\n function getMatchStoreByRouteId(\n routeId: string,\n ): RouterReadableStore<AnyRouteMatch | undefined> {\n let cached = matchStoreByRouteIdCache.get(routeId)\n if (!cached) {\n cached = createReadonlyStore(() => {\n // Reading matchesId.state tracks it as a dependency.\n // When matchesId changes (navigation), this computed re-evaluates.\n const ids = matchesId.state\n for (const id of ids) {\n const matchStore = activeMatchStoresById.get(id)\n if (matchStore && matchStore.routeId === routeId) {\n // Reading matchStore.state tracks it as a dependency.\n // When the match store's state changes, this re-evaluates.\n return matchStore.state\n }\n }\n return undefined\n })\n matchStoreByRouteIdCache.set(routeId, cached)\n }\n return cached\n }\n\n const store = {\n // atoms\n status,\n loadedAt,\n isLoading,\n isTransitioning,\n location,\n resolvedLocation,\n statusCode,\n redirect,\n matchesId,\n pendingMatchesId,\n cachedMatchesId,\n\n // derived\n activeMatchesSnapshot,\n pendingMatchesSnapshot,\n cachedMatchesSnapshot,\n firstMatchId,\n hasPendingMatches,\n matchRouteReactivity,\n\n // non-reactive state\n activeMatchStoresById,\n pendingMatchStoresById,\n cachedMatchStoresById,\n\n // compatibility \"big\" state\n __store,\n\n // per-key computed stores\n getMatchStoreByRouteId,\n\n // methods\n setActiveMatches,\n setPendingMatches,\n setCachedMatches,\n }\n\n // initialize the active matches\n setActiveMatches(initialState.matches as Array<AnyRouteMatch>)\n init?.(store)\n\n // setters to update non-reactive utilities in sync with the reactive stores\n function setActiveMatches(nextMatches: Array<AnyRouteMatch>) {\n reconcileMatchPool(\n nextMatches,\n activeMatchStoresById,\n matchesId,\n createMutableStore,\n batch,\n )\n }\n\n function setPendingMatches(nextMatches: Array<AnyRouteMatch>) {\n reconcileMatchPool(\n nextMatches,\n pendingMatchStoresById,\n pendingMatchesId,\n createMutableStore,\n batch,\n )\n }\n\n function setCachedMatches(nextMatches: Array<AnyRouteMatch>) {\n reconcileMatchPool(\n nextMatches,\n cachedMatchStoresById,\n cachedMatchesId,\n createMutableStore,\n batch,\n )\n }\n\n return store\n}\n\nfunction readPoolMatches(\n pool: Map<string, MatchStore>,\n ids: Array<string>,\n): Array<AnyRouteMatch> {\n const matches: Array<AnyRouteMatch> = []\n for (const id of ids) {\n const matchStore = pool.get(id)\n if (matchStore) {\n matches.push(matchStore.state)\n }\n }\n return matches\n}\n\nfunction reconcileMatchPool(\n nextMatches: Array<AnyRouteMatch>,\n pool: Map<string, MatchStore>,\n idStore: RouterWritableStore<Array<string>>,\n createMutableStore: MutableStoreFactory,\n batch: RouterBatchFn,\n): void {\n const nextIds = nextMatches.map((d) => d.id)\n const nextIdSet = new Set(nextIds)\n\n batch(() => {\n for (const id of pool.keys()) {\n if (!nextIdSet.has(id)) {\n pool.delete(id)\n }\n }\n\n for (const nextMatch of nextMatches) {\n const existing = pool.get(nextMatch.id)\n if (!existing) {\n const matchStore = createMutableStore(nextMatch) as MatchStore\n matchStore.routeId = nextMatch.routeId\n pool.set(nextMatch.id, matchStore)\n continue\n }\n\n existing.routeId = nextMatch.routeId\n if (existing.state !== nextMatch) {\n existing.setState(() => nextMatch)\n }\n }\n\n if (!arraysEqual(idStore.state, nextIds)) {\n idStore.setState(() => nextIds)\n }\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stores.cjs","names":[],"sources":["../../src/stores.ts"],"sourcesContent":["import { createLRUCache } from './lru-cache'\nimport { arraysEqual, functionalUpdate } from './utils'\n\nimport type { AnyRoute } from './route'\nimport type { RouterState } from './router'\nimport type { FullSearchSchema } from './routeInfo'\nimport type { ParsedLocation } from './location'\nimport type { AnyRedirect } from './redirect'\nimport type { AnyRouteMatch } from './Matches'\n\nexport interface RouterReadableStore<TValue> {\n get: () => TValue\n}\n\nexport interface RouterWritableStore<\n TValue,\n> extends RouterReadableStore<TValue> {\n set: ((updater: (prev: TValue) => TValue) => void) & ((value: TValue) => void)\n}\n\nexport type RouterBatchFn = (fn: () => void) => void\n\nexport type MutableStoreFactory = <TValue>(\n initialValue: TValue,\n) => RouterWritableStore<TValue>\n\nexport type ReadonlyStoreFactory = <TValue>(\n read: () => TValue,\n) => RouterReadableStore<TValue>\n\nexport type GetStoreConfig = (opts: { isServer?: boolean }) => StoreConfig\n\nexport type StoreConfig = {\n createMutableStore: MutableStoreFactory\n createReadonlyStore: ReadonlyStoreFactory\n batch: RouterBatchFn\n init?: (stores: RouterStores<AnyRoute>) => void\n}\n\ntype MatchStore = RouterWritableStore<AnyRouteMatch> & {\n routeId?: string\n}\ntype ReadableStore<TValue> = RouterReadableStore<TValue>\n\n/** SSR non-reactive createMutableStore */\nexport function createNonReactiveMutableStore<TValue>(\n initialValue: TValue,\n): RouterWritableStore<TValue> {\n let value = initialValue\n\n return {\n get() {\n return value\n },\n set(nextOrUpdater: TValue | ((prev: TValue) => TValue)) {\n value = functionalUpdate(nextOrUpdater, value)\n },\n }\n}\n\n/** SSR non-reactive createReadonlyStore */\nexport function createNonReactiveReadonlyStore<TValue>(\n read: () => TValue,\n): RouterReadableStore<TValue> {\n return {\n get() {\n return read()\n },\n }\n}\n\nexport interface RouterStores<in out TRouteTree extends AnyRoute> {\n status: RouterWritableStore<RouterState<TRouteTree>['status']>\n loadedAt: RouterWritableStore<number>\n isLoading: RouterWritableStore<boolean>\n isTransitioning: RouterWritableStore<boolean>\n location: RouterWritableStore<ParsedLocation<FullSearchSchema<TRouteTree>>>\n resolvedLocation: RouterWritableStore<\n ParsedLocation<FullSearchSchema<TRouteTree>> | undefined\n >\n statusCode: RouterWritableStore<number>\n redirect: RouterWritableStore<AnyRedirect | undefined>\n matchesId: RouterWritableStore<Array<string>>\n pendingIds: RouterWritableStore<Array<string>>\n /** @internal */\n cachedIds: RouterWritableStore<Array<string>>\n matches: ReadableStore<Array<AnyRouteMatch>>\n pendingMatches: ReadableStore<Array<AnyRouteMatch>>\n cachedMatches: ReadableStore<Array<AnyRouteMatch>>\n firstId: ReadableStore<string | undefined>\n hasPending: ReadableStore<boolean>\n matchRouteDeps: ReadableStore<{\n locationHref: string\n resolvedLocationHref: string | undefined\n status: RouterState<TRouteTree>['status']\n }>\n __store: RouterReadableStore<RouterState<TRouteTree>>\n\n matchStores: Map<string, MatchStore>\n pendingMatchStores: Map<string, MatchStore>\n cachedMatchStores: Map<string, MatchStore>\n\n /**\n * Get a computed store that resolves a routeId to its current match state.\n * Returns the same cached store instance for repeated calls with the same key.\n * The computed depends on matchesId + the individual match store, so\n * subscribers are only notified when the resolved match state changes.\n */\n getRouteMatchStore: (\n routeId: string,\n ) => RouterReadableStore<AnyRouteMatch | undefined>\n\n setMatches: (nextMatches: Array<AnyRouteMatch>) => void\n setPending: (nextMatches: Array<AnyRouteMatch>) => void\n setCached: (nextMatches: Array<AnyRouteMatch>) => void\n}\n\nexport function createRouterStores<TRouteTree extends AnyRoute>(\n initialState: RouterState<TRouteTree>,\n config: StoreConfig,\n): RouterStores<TRouteTree> {\n const { createMutableStore, createReadonlyStore, batch, init } = config\n\n // non reactive utilities\n const matchStores = new Map<string, MatchStore>()\n const pendingMatchStores = new Map<string, MatchStore>()\n const cachedMatchStores = new Map<string, MatchStore>()\n\n // atoms\n const status = createMutableStore(initialState.status)\n const loadedAt = createMutableStore(initialState.loadedAt)\n const isLoading = createMutableStore(initialState.isLoading)\n const isTransitioning = createMutableStore(initialState.isTransitioning)\n const location = createMutableStore(initialState.location)\n const resolvedLocation = createMutableStore(initialState.resolvedLocation)\n const statusCode = createMutableStore(initialState.statusCode)\n const redirect = createMutableStore(initialState.redirect)\n const matchesId = createMutableStore<Array<string>>([])\n const pendingIds = createMutableStore<Array<string>>([])\n const cachedIds = createMutableStore<Array<string>>([])\n\n // 1st order derived stores\n const matches = createReadonlyStore(() =>\n readPoolMatches(matchStores, matchesId.get()),\n )\n const pendingMatches = createReadonlyStore(() =>\n readPoolMatches(pendingMatchStores, pendingIds.get()),\n )\n const cachedMatches = createReadonlyStore(() =>\n readPoolMatches(cachedMatchStores, cachedIds.get()),\n )\n const firstId = createReadonlyStore(() => matchesId.get()[0])\n const hasPending = createReadonlyStore(() =>\n matchesId.get().some((matchId) => {\n const store = matchStores.get(matchId)\n return store?.get().status === 'pending'\n }),\n )\n const matchRouteDeps = createReadonlyStore(() => ({\n locationHref: location.get().href,\n resolvedLocationHref: resolvedLocation.get()?.href,\n status: status.get(),\n }))\n\n // compatibility \"big\" state store\n const __store = createReadonlyStore(() => ({\n status: status.get(),\n loadedAt: loadedAt.get(),\n isLoading: isLoading.get(),\n isTransitioning: isTransitioning.get(),\n matches: matches.get(),\n location: location.get(),\n resolvedLocation: resolvedLocation.get(),\n statusCode: statusCode.get(),\n redirect: redirect.get(),\n }))\n\n // Per-routeId computed store cache.\n // Each entry resolves routeId → match state through the signal graph,\n // giving consumers a single store to subscribe to instead of the\n // two-level byRouteId → matchStore pattern.\n //\n // 64 max size is arbitrary, this is only for active matches anyway so\n // it should be plenty. And we already have a 32 limit due to route\n // matching bitmask anyway.\n const matchStoreByRouteIdCache = createLRUCache<\n string,\n RouterReadableStore<AnyRouteMatch | undefined>\n >(64)\n\n function getRouteMatchStore(\n routeId: string,\n ): RouterReadableStore<AnyRouteMatch | undefined> {\n let cached = matchStoreByRouteIdCache.get(routeId)\n if (!cached) {\n cached = createReadonlyStore(() => {\n // Reading matchesId.get() tracks it as a dependency.\n // When matchesId changes (navigation), this computed re-evaluates.\n const ids = matchesId.get()\n for (const id of ids) {\n const matchStore = matchStores.get(id)\n if (matchStore && matchStore.routeId === routeId) {\n // Reading matchStore.get() tracks it as a dependency.\n // When the match store's state changes, this re-evaluates.\n return matchStore.get()\n }\n }\n return undefined\n })\n matchStoreByRouteIdCache.set(routeId, cached)\n }\n return cached\n }\n\n const store = {\n // atoms\n status,\n loadedAt,\n isLoading,\n isTransitioning,\n location,\n resolvedLocation,\n statusCode,\n redirect,\n matchesId,\n pendingIds,\n cachedIds,\n\n // derived\n matches,\n pendingMatches,\n cachedMatches,\n firstId,\n hasPending,\n matchRouteDeps,\n\n // non-reactive state\n matchStores,\n pendingMatchStores,\n cachedMatchStores,\n\n // compatibility \"big\" state\n __store,\n\n // per-key computed stores\n getRouteMatchStore,\n\n // methods\n setMatches,\n setPending,\n setCached,\n }\n\n // initialize the active matches\n setMatches(initialState.matches as Array<AnyRouteMatch>)\n init?.(store)\n\n // setters to update non-reactive utilities in sync with the reactive stores\n function setMatches(nextMatches: Array<AnyRouteMatch>) {\n reconcileMatchPool(\n nextMatches,\n matchStores,\n matchesId,\n createMutableStore,\n batch,\n )\n }\n\n function setPending(nextMatches: Array<AnyRouteMatch>) {\n reconcileMatchPool(\n nextMatches,\n pendingMatchStores,\n pendingIds,\n createMutableStore,\n batch,\n )\n }\n\n function setCached(nextMatches: Array<AnyRouteMatch>) {\n reconcileMatchPool(\n nextMatches,\n cachedMatchStores,\n cachedIds,\n createMutableStore,\n batch,\n )\n }\n\n return store\n}\n\nfunction readPoolMatches(\n pool: Map<string, MatchStore>,\n ids: Array<string>,\n): Array<AnyRouteMatch> {\n const matches: Array<AnyRouteMatch> = []\n for (const id of ids) {\n const matchStore = pool.get(id)\n if (matchStore) {\n matches.push(matchStore.get())\n }\n }\n return matches\n}\n\nfunction reconcileMatchPool(\n nextMatches: Array<AnyRouteMatch>,\n pool: Map<string, MatchStore>,\n idStore: RouterWritableStore<Array<string>>,\n createMutableStore: MutableStoreFactory,\n batch: RouterBatchFn,\n): void {\n const nextIds = nextMatches.map((d) => d.id)\n const nextIdSet = new Set(nextIds)\n\n batch(() => {\n for (const id of pool.keys()) {\n if (!nextIdSet.has(id)) {\n pool.delete(id)\n }\n }\n\n for (const nextMatch of nextMatches) {\n const existing = pool.get(nextMatch.id)\n if (!existing) {\n const matchStore = createMutableStore(nextMatch) as MatchStore\n matchStore.routeId = nextMatch.routeId\n pool.set(nextMatch.id, matchStore)\n continue\n }\n\n existing.routeId = nextMatch.routeId\n if (existing.get() !== nextMatch) {\n existing.set(nextMatch)\n }\n }\n\n if (!arraysEqual(idStore.get(), nextIds)) {\n idStore.set(nextIds)\n }\n })\n}\n"],"mappings":"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"}
|
package/dist/cjs/stores.d.cts
CHANGED
|
@@ -5,10 +5,10 @@ import { ParsedLocation } from './location.cjs';
|
|
|
5
5
|
import { AnyRedirect } from './redirect.cjs';
|
|
6
6
|
import { AnyRouteMatch } from './Matches.cjs';
|
|
7
7
|
export interface RouterReadableStore<TValue> {
|
|
8
|
-
|
|
8
|
+
get: () => TValue;
|
|
9
9
|
}
|
|
10
10
|
export interface RouterWritableStore<TValue> extends RouterReadableStore<TValue> {
|
|
11
|
-
|
|
11
|
+
set: ((updater: (prev: TValue) => TValue) => void) & ((value: TValue) => void);
|
|
12
12
|
}
|
|
13
13
|
export type RouterBatchFn = (fn: () => void) => void;
|
|
14
14
|
export type MutableStoreFactory = <TValue>(initialValue: TValue) => RouterWritableStore<TValue>;
|
|
@@ -40,31 +40,31 @@ export interface RouterStores<in out TRouteTree extends AnyRoute> {
|
|
|
40
40
|
statusCode: RouterWritableStore<number>;
|
|
41
41
|
redirect: RouterWritableStore<AnyRedirect | undefined>;
|
|
42
42
|
matchesId: RouterWritableStore<Array<string>>;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
pendingIds: RouterWritableStore<Array<string>>;
|
|
44
|
+
matches: ReadableStore<Array<AnyRouteMatch>>;
|
|
45
|
+
pendingMatches: ReadableStore<Array<AnyRouteMatch>>;
|
|
46
|
+
cachedMatches: ReadableStore<Array<AnyRouteMatch>>;
|
|
47
|
+
firstId: ReadableStore<string | undefined>;
|
|
48
|
+
hasPending: ReadableStore<boolean>;
|
|
49
|
+
matchRouteDeps: ReadableStore<{
|
|
50
50
|
locationHref: string;
|
|
51
51
|
resolvedLocationHref: string | undefined;
|
|
52
52
|
status: RouterState<TRouteTree>['status'];
|
|
53
53
|
}>;
|
|
54
54
|
__store: RouterReadableStore<RouterState<TRouteTree>>;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
matchStores: Map<string, MatchStore>;
|
|
56
|
+
pendingMatchStores: Map<string, MatchStore>;
|
|
57
|
+
cachedMatchStores: Map<string, MatchStore>;
|
|
58
58
|
/**
|
|
59
59
|
* Get a computed store that resolves a routeId to its current match state.
|
|
60
60
|
* Returns the same cached store instance for repeated calls with the same key.
|
|
61
61
|
* The computed depends on matchesId + the individual match store, so
|
|
62
62
|
* subscribers are only notified when the resolved match state changes.
|
|
63
63
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
getRouteMatchStore: (routeId: string) => RouterReadableStore<AnyRouteMatch | undefined>;
|
|
65
|
+
setMatches: (nextMatches: Array<AnyRouteMatch>) => void;
|
|
66
|
+
setPending: (nextMatches: Array<AnyRouteMatch>) => void;
|
|
67
|
+
setCached: (nextMatches: Array<AnyRouteMatch>) => void;
|
|
68
68
|
}
|
|
69
69
|
export declare function createRouterStores<TRouteTree extends AnyRoute>(initialState: RouterState<TRouteTree>, config: StoreConfig): RouterStores<TRouteTree>;
|
|
70
70
|
export {};
|
package/dist/esm/hash-scroll.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
function handleHashScroll(router) {
|
|
8
8
|
if (typeof document !== "undefined" && document.querySelector) {
|
|
9
|
-
const location = router.stores.location.
|
|
9
|
+
const location = router.stores.location.get();
|
|
10
10
|
const hashScrollIntoViewOptions = location.state.__hashScrollIntoViewOptions ?? true;
|
|
11
11
|
if (hashScrollIntoViewOptions && location.hash !== "") {
|
|
12
12
|
const el = document.getElementById(location.hash);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash-scroll.js","names":[],"sources":["../../src/hash-scroll.ts"],"sourcesContent":["import type { AnyRouter } from './router'\n\n/**\n * @private\n * Handles hash-based scrolling after navigation completes.\n * To be used in framework-specific <Transitioner> components during the onResolved event.\n */\nexport function handleHashScroll(router: AnyRouter) {\n if (typeof document !== 'undefined' && (document as any).querySelector) {\n const location = router.stores.location.
|
|
1
|
+
{"version":3,"file":"hash-scroll.js","names":[],"sources":["../../src/hash-scroll.ts"],"sourcesContent":["import type { AnyRouter } from './router'\n\n/**\n * @private\n * Handles hash-based scrolling after navigation completes.\n * To be used in framework-specific <Transitioner> components during the onResolved event.\n */\nexport function handleHashScroll(router: AnyRouter) {\n if (typeof document !== 'undefined' && (document as any).querySelector) {\n const location = router.stores.location.get()\n const hashScrollIntoViewOptions =\n location.state.__hashScrollIntoViewOptions ?? true\n\n if (hashScrollIntoViewOptions && location.hash !== '') {\n const el = document.getElementById(location.hash)\n if (el) {\n el.scrollIntoView(hashScrollIntoViewOptions)\n }\n }\n }\n}\n"],"mappings":";;;;;;AAOA,SAAgB,iBAAiB,QAAmB;AAClD,KAAI,OAAO,aAAa,eAAgB,SAAiB,eAAe;EACtE,MAAM,WAAW,OAAO,OAAO,SAAS,KAAK;EAC7C,MAAM,4BACJ,SAAS,MAAM,+BAA+B;AAEhD,MAAI,6BAA6B,SAAS,SAAS,IAAI;GACrD,MAAM,KAAK,SAAS,eAAe,SAAS,KAAK;AACjD,OAAI,GACF,IAAG,eAAe,0BAA0B"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export { defaultGetScrollRestorationKey, getElementScrollRestorationEntry, stora
|
|
|
44
44
|
export { handleHashScroll } from './hash-scroll.js';
|
|
45
45
|
export type { ScrollRestorationOptions, ScrollRestorationEntry, } from './scroll-restoration.js';
|
|
46
46
|
export type { ValidateFromPath, ValidateToPath, ValidateSearch, ValidateParams, InferFrom, InferTo, InferMaskTo, InferMaskFrom, ValidateNavigateOptions, ValidateNavigateOptionsArray, ValidateRedirectOptions, ValidateRedirectOptionsArray, ValidateId, InferStrict, InferShouldThrow, InferSelected, ValidateUseSearchResult, ValidateUseParamsResult, } from './typePrimitives.js';
|
|
47
|
-
export type { AnySerializationAdapter, SerializationAdapter, ValidateSerializableInput,
|
|
47
|
+
export type { AnySerializationAdapter, SerializationAdapter, ValidateSerializableInput, SerializerExtensions, ValidateSerializable, RegisteredSerializableInput, SerializableExtensions, DefaultSerializable, Serializable, TSR_SERIALIZABLE, TsrSerializable, SerializationError, } from './ssr/serializer/transformer.js';
|
|
48
48
|
export { createSerializationAdapter, makeSerovalPlugin, makeSsrSerovalPlugin, } from './ssr/serializer/transformer.js';
|
|
49
49
|
export { defaultSerovalPlugins } from './ssr/serializer/seroval-plugins.js';
|
|
50
50
|
export { RawStream, createRawStreamRPCPlugin, createRawStreamDeserializePlugin, } from './ssr/serializer/RawStream.js';
|
package/dist/esm/load-matches.js
CHANGED
|
@@ -12,12 +12,12 @@ var triggerOnReady = (inner) => {
|
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
var hasForcePendingActiveMatch = (router) => {
|
|
15
|
-
return router.stores.matchesId.
|
|
16
|
-
return router.stores.
|
|
15
|
+
return router.stores.matchesId.get().some((matchId) => {
|
|
16
|
+
return router.stores.matchStores.get(matchId)?.get()._forcePending;
|
|
17
17
|
});
|
|
18
18
|
};
|
|
19
19
|
var resolvePreload = (inner, matchId) => {
|
|
20
|
-
return !!(inner.preload && !inner.router.stores.
|
|
20
|
+
return !!(inner.preload && !inner.router.stores.matchStores.has(matchId));
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
23
|
* Builds the accumulated context from router options and all matches up to (and optionally including) the given index.
|
|
@@ -463,8 +463,8 @@ var loadRouteMatch = async (inner, matchPromises, index) => {
|
|
|
463
463
|
if (isServer ?? inner.router.isServer) return inner.router.getMatch(matchId);
|
|
464
464
|
} else {
|
|
465
465
|
const prevMatch = inner.router.getMatch(matchId);
|
|
466
|
-
const activeIdAtIndex = inner.router.stores.matchesId.
|
|
467
|
-
const previousRouteMatchId = (activeIdAtIndex && inner.router.stores.
|
|
466
|
+
const activeIdAtIndex = inner.router.stores.matchesId.get()[index];
|
|
467
|
+
const previousRouteMatchId = (activeIdAtIndex && inner.router.stores.matchStores.get(activeIdAtIndex) || null)?.routeId === routeId ? activeIdAtIndex : inner.router.stores.matches.get().find((d) => d.routeId === routeId)?.id;
|
|
468
468
|
const preload = resolvePreload(inner, matchId);
|
|
469
469
|
if (prevMatch._nonReactive.loaderPromise) {
|
|
470
470
|
if (prevMatch.status === "success" && !inner.sync && !prevMatch.preload && shouldReloadInBackground) return prevMatch;
|
|
@@ -474,7 +474,7 @@ var loadRouteMatch = async (inner, matchPromises, index) => {
|
|
|
474
474
|
if (error) handleRedirectAndNotFound(inner, match, error);
|
|
475
475
|
if (match.status === "pending") await handleLoader(preload, prevMatch, previousRouteMatchId, match, route);
|
|
476
476
|
} else {
|
|
477
|
-
const nextPreload = preload && !inner.router.stores.
|
|
477
|
+
const nextPreload = preload && !inner.router.stores.matchStores.has(matchId);
|
|
478
478
|
const match = inner.router.getMatch(matchId);
|
|
479
479
|
match._nonReactive.loaderPromise = createControlledPromise();
|
|
480
480
|
if (nextPreload !== match.preload) inner.updateMatch(matchId, (prev) => ({
|