UNPKG

@tanstack/router-core

Version:

Modern and scalable routing for React applications

146 lines (145 loc) 4.83 kB
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