@techsio/storefront-data
Version:
Medusa-first storefront data layer built on TanStack Query.
121 lines (120 loc) • 5.63 kB
JavaScript
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 };