@tanstack/router-core
Version:
Modern and scalable routing for React applications
146 lines (145 loc) • 4.83 kB
JavaScript
import { arraysEqual, functionalUpdate } from "./utils.js";
import { createLRUCache } from "./lru-cache.js";
//#region src/stores.ts
/** SSR non-reactive createMutableStore */
function createNonReactiveMutableStore(initialValue) {
let value = initialValue;
return {
get() {
return value;
},
set(nextOrUpdater) {
value = functionalUpdate(nextOrUpdater, value);
}
};
}
/** SSR non-reactive createReadonlyStore */
function createNonReactiveReadonlyStore(read) {
return { get() {
return read();
} };
}
function createRouterStores(initialState, config) {
const { createMutableStore, createReadonlyStore, batch, init } = config;
const matchStores = /* @__PURE__ */ new Map();
const pendingMatchStores = /* @__PURE__ */ new Map();
const cachedMatchStores = /* @__PURE__ */ new Map();
const status = createMutableStore(initialState.status);
const loadedAt = createMutableStore(initialState.loadedAt);
const isLoading = createMutableStore(initialState.isLoading);
const isTransitioning = createMutableStore(initialState.isTransitioning);
const location = createMutableStore(initialState.location);
const resolvedLocation = createMutableStore(initialState.resolvedLocation);
const statusCode = createMutableStore(initialState.statusCode);
const redirect = createMutableStore(initialState.redirect);
const matchesId = createMutableStore([]);
const pendingIds = createMutableStore([]);
const cachedIds = createMutableStore([]);
const matches = createReadonlyStore(() => readPoolMatches(matchStores, matchesId.get()));
const pendingMatches = createReadonlyStore(() => readPoolMatches(pendingMatchStores, pendingIds.get()));
const cachedMatches = createReadonlyStore(() => readPoolMatches(cachedMatchStores, cachedIds.get()));
const firstId = createReadonlyStore(() => matchesId.get()[0]);
const hasPending = createReadonlyStore(() => matchesId.get().some((matchId) => {
return matchStores.get(matchId)?.get().status === "pending";
}));
const matchRouteDeps = createReadonlyStore(() => ({
locationHref: location.get().href,
resolvedLocationHref: resolvedLocation.get()?.href,
status: status.get()
}));
const __store = createReadonlyStore(() => ({
status: status.get(),
loadedAt: loadedAt.get(),
isLoading: isLoading.get(),
isTransitioning: isTransitioning.get(),
matches: matches.get(),
location: location.get(),
resolvedLocation: resolvedLocation.get(),
statusCode: statusCode.get(),
redirect: redirect.get()
}));
const matchStoreByRouteIdCache = createLRUCache(64);
function getRouteMatchStore(routeId) {
let cached = matchStoreByRouteIdCache.get(routeId);
if (!cached) {
cached = createReadonlyStore(() => {
const ids = matchesId.get();
for (const id of ids) {
const matchStore = matchStores.get(id);
if (matchStore && matchStore.routeId === routeId) return matchStore.get();
}
});
matchStoreByRouteIdCache.set(routeId, cached);
}
return cached;
}
const store = {
status,
loadedAt,
isLoading,
isTransitioning,
location,
resolvedLocation,
statusCode,
redirect,
matchesId,
pendingIds,
cachedIds,
matches,
pendingMatches,
cachedMatches,
firstId,
hasPending,
matchRouteDeps,
matchStores,
pendingMatchStores,
cachedMatchStores,
__store,
getRouteMatchStore,
setMatches,
setPending,
setCached
};
setMatches(initialState.matches);
init?.(store);
function setMatches(nextMatches) {
reconcileMatchPool(nextMatches, matchStores, matchesId, createMutableStore, batch);
}
function setPending(nextMatches) {
reconcileMatchPool(nextMatches, pendingMatchStores, pendingIds, createMutableStore, batch);
}
function setCached(nextMatches) {
reconcileMatchPool(nextMatches, cachedMatchStores, cachedIds, createMutableStore, batch);
}
return store;
}
function readPoolMatches(pool, ids) {
const matches = [];
for (const id of ids) {
const matchStore = pool.get(id);
if (matchStore) matches.push(matchStore.get());
}
return matches;
}
function reconcileMatchPool(nextMatches, pool, idStore, createMutableStore, batch) {
const nextIds = nextMatches.map((d) => d.id);
const nextIdSet = new Set(nextIds);
batch(() => {
for (const id of pool.keys()) if (!nextIdSet.has(id)) pool.delete(id);
for (const nextMatch of nextMatches) {
const existing = pool.get(nextMatch.id);
if (!existing) {
const matchStore = createMutableStore(nextMatch);
matchStore.routeId = nextMatch.routeId;
pool.set(nextMatch.id, matchStore);
continue;
}
existing.routeId = nextMatch.routeId;
if (existing.get() !== nextMatch) existing.set(nextMatch);
}
if (!arraysEqual(idStore.get(), nextIds)) idStore.set(nextIds);
});
}
//#endregion
export { createNonReactiveMutableStore, createNonReactiveReadonlyStore, createRouterStores };
//# sourceMappingURL=stores.js.map