UNPKG

@techsio/storefront-data

Version:

Medusa-first storefront data layer built on TanStack Query.

152 lines (151 loc) • 5.67 kB
import { toComparableTimestamp } from "../shared/date-utils.js"; import { isAuthError } from "../shared/medusa-errors.js"; const normalizeComparableString = (value, lowercase = false)=>{ if ("string" != typeof value) return; const normalized = value.trim(); if (!normalized) return; return lowercase ? normalized.toLowerCase() : normalized; }; const pickNewestAddress = (addresses)=>{ if (0 === addresses.length) return; return [ ...addresses ].sort((left, right)=>{ const rightCreatedAt = toComparableTimestamp(right.created_at); const leftCreatedAt = toComparableTimestamp(left.created_at); if (rightCreatedAt !== leftCreatedAt) return rightCreatedAt - leftCreatedAt; const rightUpdatedAt = toComparableTimestamp(right.updated_at); const leftUpdatedAt = toComparableTimestamp(left.updated_at); return rightUpdatedAt - leftUpdatedAt; })[0]; }; const addressMatchesCreateInput = (address, input)=>{ const stringComparisons = [ { key: "first_name" }, { key: "last_name" }, { key: "company" }, { key: "address_1" }, { key: "address_2" }, { key: "city" }, { key: "province" }, { key: "postal_code" }, { key: "country_code", lowercase: true }, { key: "phone" } ]; for (const comparison of stringComparisons){ const expected = normalizeComparableString(input[comparison.key], comparison.lowercase); if (void 0 === expected) continue; const actual = normalizeComparableString(address[comparison.key], comparison.lowercase); if (actual !== expected) return false; } const booleanComparisons = [ "is_default_shipping", "is_default_billing" ]; for (const key of booleanComparisons){ const expected = input[key]; if ("boolean" != typeof expected) continue; const actual = address[key]; if (actual !== expected) return false; } return true; }; const getAddressIdSet = (addresses)=>new Set(addresses.map((address)=>address.id).filter((id)=>Boolean(id))); const pickSingleOrNewestAddress = (addresses)=>{ if (1 === addresses.length) return addresses[0]; if (addresses.length > 1) return pickNewestAddress(addresses); }; const getNewlyCreatedAddresses = (addresses, existingAddressIds)=>addresses.filter((address)=>"string" == typeof address.id && !existingAddressIds.has(address.id)); const resolveCreatedAddress = (addresses, params, existingAddressIds)=>{ if (existingAddressIds) { const newlyCreatedAddress = pickSingleOrNewestAddress(getNewlyCreatedAddresses(addresses, existingAddressIds)); if (newlyCreatedAddress) return newlyCreatedAddress; } const matchingAddress = pickSingleOrNewestAddress(addresses.filter((address)=>addressMatchesCreateInput(address, params))); if (matchingAddress) return matchingAddress; return pickNewestAddress(addresses); }; function createMedusaCustomerService(sdk) { const fetchAllCustomerAddresses = async ()=>{ const pageSize = 100; const addresses = []; let offset = 0; while(true){ const response = await sdk.store.customer.listAddress({ limit: pageSize, offset }); const page = response.addresses ?? []; addresses.push(...page); if (0 === page.length) break; offset += page.length; if ("number" == typeof response.count && offset >= response.count) break; if ("number" != typeof response.count && page.length < pageSize) break; } return addresses; }; return { async getAddresses (_params, signal) { try { const response = await sdk.client.fetch("/store/customers/me/addresses", { signal }); return { addresses: response.addresses ?? [] }; } catch (error) { if (isAuthError(error)) return { addresses: [] }; throw error; } }, async createAddress (params) { let existingAddressIds = null; try { existingAddressIds = getAddressIdSet(await fetchAllCustomerAddresses()); } catch {} const { customer } = await sdk.store.customer.createAddress(params); const addresses = customer.addresses ?? []; const createdAddress = resolveCreatedAddress(addresses, params, existingAddressIds); if (createdAddress) return createdAddress; throw new Error("Failed to create address"); }, async updateAddress (addressId, params) { const { customer } = await sdk.store.customer.updateAddress(addressId, params); const addresses = customer.addresses ?? []; const address = addresses.find((a)=>a.id === addressId); if (!address) throw new Error("Failed to update address"); return address; }, async deleteAddress (addressId) { await sdk.store.customer.deleteAddress(addressId); }, async updateCustomer (params) { const { customer } = await sdk.store.customer.update(params); return customer; } }; } export { createMedusaCustomerService };