UNPKG

@techsio/storefront-data

Version:

Medusa-first storefront data layer built on TanStack Query.

121 lines (120 loc) • 5.63 kB
import { isPlainRecord } from "./object-utils.js"; import { areQueryKeySegmentsEqual, getSortedRecordKeys, hasQueryKeyPrefix } from "./query-key-match-utils.js"; const matchActiveLeafSegment = ({ candidate, base, cartVariant, regionVariant, cartId })=>{ const changesWithCart = !areQueryKeySegmentsEqual(base, cartVariant); const changesWithRegion = !areQueryKeySegmentsEqual(base, regionVariant); if (!(changesWithCart || changesWithRegion)) return areQueryKeySegmentsEqual(candidate, base); if (changesWithCart && !changesWithRegion) return candidate === cartId; if (!changesWithCart && changesWithRegion) return true; return false; }; const matchesActiveKeySegment = ({ candidate, base, cartVariant, regionVariant, cartId })=>{ if (Array.isArray(base) && Array.isArray(cartVariant) && Array.isArray(regionVariant)) return Array.isArray(candidate) && candidate.length === base.length && cartVariant.length === base.length && regionVariant.length === base.length && base.every((_, index)=>matchesActiveKeySegment({ candidate: candidate[index], base: base[index], cartVariant: cartVariant[index], regionVariant: regionVariant[index], cartId })); if (isPlainRecord(base) && isPlainRecord(cartVariant) && isPlainRecord(regionVariant) && isPlainRecord(candidate)) return getSortedRecordKeys(base, cartVariant, regionVariant).every((key)=>matchesActiveKeySegment({ candidate: candidate[key], base: base[key], cartVariant: cartVariant[key], regionVariant: regionVariant[key], cartId })); return matchActiveLeafSegment({ candidate, base, cartVariant, regionVariant, cartId }); }; const hasCartId = (value, cartId)=>{ if (!isPlainRecord(value)) return false; const valueId = value.id; if ("string" != typeof valueId) return false; if ("string" == typeof cartId) return valueId === cartId; return true; }; const createDefaultActiveCartQueryMatcher = (queryKeys)=>{ const cartPrefix = queryKeys.all(); const baseActiveKey = queryKeys.active({ cartId: "__storefront_data_cart__", regionId: "__storefront_data_region__" }); const cartVariantActiveKey = queryKeys.active({ cartId: "__storefront_data_other_cart__", regionId: "__storefront_data_region__" }); const regionVariantActiveKey = queryKeys.active({ cartId: "__storefront_data_cart__", regionId: "__storefront_data_other_region__" }); return (queryKey, cartId)=>{ if (!hasQueryKeyPrefix(queryKey, cartPrefix)) return false; return matchesActiveKeySegment({ candidate: queryKey, base: baseActiveKey, cartVariant: cartVariantActiveKey, regionVariant: regionVariantActiveKey, cartId }); }; }; const resolveActiveCartQueryMatcher = (queryKeys, options)=>options?.isActiveCartQueryKey ?? createDefaultActiveCartQueryMatcher(queryKeys); function syncCartCaches(queryClient, queryKeys, cart, options) { const isActiveCartQueryKey = resolveActiveCartQueryMatcher(queryKeys, options); const activeKey = queryKeys.active({ cartId: cart.id, regionId: "string" == typeof cart.region_id ? cart.region_id : null }); queryClient.setQueriesData({ predicate: (query)=>isActiveCartQueryKey(query.queryKey, cart.id) }, cart); queryClient.setQueryData(activeKey, cart); queryClient.setQueryData(queryKeys.detail(cart.id), cart); } function invalidateCartCaches(queryClient, queryKeys, cartId, options) { const isActiveCartQueryKey = resolveActiveCartQueryMatcher(queryKeys, options); queryClient.invalidateQueries({ predicate: (query)=>isActiveCartQueryKey(query.queryKey, cartId) }); queryClient.invalidateQueries({ queryKey: queryKeys.detail(cartId) }); } async function cancelCartCaches(queryClient, queryKeys, cartId, options) { const isActiveCartQueryKey = resolveActiveCartQueryMatcher(queryKeys, options); await Promise.all([ queryClient.cancelQueries({ predicate: (query)=>isActiveCartQueryKey(query.queryKey, cartId) }, { silent: true }), queryClient.cancelQueries({ queryKey: queryKeys.detail(cartId) }, { silent: true }) ]); } function patchCartCaches(queryClient, queryKeys, cartId, params) { const isActiveCartQueryKey = resolveActiveCartQueryMatcher(queryKeys, params.options); queryClient.setQueriesData({ predicate: (query)=>isActiveCartQueryKey(query.queryKey, cartId) }, (existing)=>hasCartId(existing, cartId) ? params.patch(existing) : existing); queryClient.setQueryData(queryKeys.detail(cartId), (existing)=>hasCartId(existing, cartId) ? params.patch(existing) : existing); } function getCachedCartById(queryClient, queryKeys, cartId, options) { const detailCart = queryClient.getQueryData(queryKeys.detail(cartId)); if (hasCartId(detailCart, cartId)) return detailCart; const isActiveCartQueryKey = resolveActiveCartQueryMatcher(queryKeys, options); const activeCarts = queryClient.getQueriesData({ predicate: (query)=>isActiveCartQueryKey(query.queryKey, cartId) }); for (const [, cachedCart] of activeCarts)if (hasCartId(cachedCart, cartId)) return cachedCart; return null; } export { cancelCartCaches, createDefaultActiveCartQueryMatcher, getCachedCartById, invalidateCartCaches, patchCartCaches, syncCartCaches };