UNPKG

@techsio/storefront-data

Version:

Medusa-first storefront data layer built on TanStack Query.

187 lines (186 loc) • 8.53 kB
import { compactRecord } from "../shared/object-utils.js"; const DEFAULT_PRODUCT_LISTS_PATH = "/store/product-lists"; const normalizeQuantity = (quantity)=>{ if ("number" != typeof quantity || !Number.isFinite(quantity)) return; return Math.max(1, Math.floor(quantity)); }; const normalizeQuantityDelta = (quantity)=>{ if ("number" != typeof quantity || !Number.isFinite(quantity)) return 1; const quantityDelta = Math.trunc(quantity); if (0 === quantityDelta) throw new Error("Quantity change must be a non-zero integer."); return quantityDelta; }; const normalizeProductListsResponse = (response, fallbackLimit, fallbackOffset)=>{ const productLists = response.product_lists ?? response.productLists ?? response.lists ?? []; return { productLists, count: response.count ?? productLists.length, limit: response.limit ?? fallbackLimit, offset: response.offset ?? fallbackOffset }; }; const resolveProductListFromResponse = (response)=>response.product_list ?? response.productList ?? response.list ?? null; const resolveProductListItemFromResponse = (response)=>response.product_list_item ?? response.productListItem ?? response.item ?? null; const resolveProductListCartFromResponse = (response)=>response.cart ?? null; function createMedusaProductListService(sdk, config) { const basePath = config?.basePath ?? DEFAULT_PRODUCT_LISTS_PATH; const defaultLimit = config?.defaultLimit ?? 20; const defaultOffset = config?.defaultOffset ?? 0; const transformProductList = config?.transformProductList ?? ((list)=>list); const transformProductListItem = config?.transformProductListItem ?? ((item)=>item); const transformCart = config?.transformCart ?? ((cart)=>cart); const mapList = (list)=>transformProductList(list); const mapItem = (item)=>transformProductListItem(item); const resolveListQuery = (params)=>{ const normalized = config?.normalizeListQuery?.(params) ?? params; const { limit = defaultLimit, offset = defaultOffset, ...query } = normalized; return compactRecord({ ...query, limit, offset }); }; const resolveItemFromResponse = (response)=>{ const item = resolveProductListItemFromResponse(response); return item ? mapItem(item) : null; }; return { async listProductLists (params, signal) { const query = resolveListQuery(params); const response = await sdk.client.fetch(basePath, { query, signal }); const normalized = normalizeProductListsResponse(response, Number(query.limit ?? defaultLimit), Number(query.offset ?? defaultOffset)); return { ...normalized, productLists: normalized.productLists.map(mapList) }; }, async getProductList (params, signal) { if (!params.id) return null; const response = await sdk.client.fetch(`${basePath}/${params.id}`, { signal }); const productList = resolveProductListFromResponse(response); return productList ? mapList(productList) : null; }, async createFavoriteProductList (input = {}) { const response = await sdk.client.fetch(`${basePath}/favorites`, { method: "POST", body: compactRecord(input) }); const productList = resolveProductListFromResponse(response); return productList ? mapList(productList) : null; }, async createCustomProductList (input) { const response = await sdk.client.fetch(`${basePath}/custom`, { method: "POST", body: compactRecord({ ...input, access_type: input.access_type ?? "private" }) }); const productList = resolveProductListFromResponse(response); return productList ? mapList(productList) : null; }, async updateProductList (input) { const response = await sdk.client.fetch(`${basePath}/${input.listId}`, { method: "POST", body: compactRecord({ title: input.title, access_type: input.access_type, description: input.description, handle: input.handle, metadata: input.metadata }) }); const productList = resolveProductListFromResponse(response); return productList ? mapList(productList) : null; }, deleteProductList (input) { return sdk.client.fetch(`${basePath}/${input.listId}`, { method: "DELETE" }); }, async addProductListItem (input) { const response = await sdk.client.fetch(`${basePath}/${input.listId}/items`, { method: "POST", body: compactRecord({ product_id: input.productId, variant_id: input.variantId ?? void 0, quantity: normalizeQuantity(input.quantity), note: input.note, sort_order: input.sortOrder, metadata: input.metadata }) }); return resolveItemFromResponse(response); }, async addFavoriteProductListItem (input) { const response = await sdk.client.fetch(`${basePath}/favorites/items`, { method: "POST", body: compactRecord({ product_id: input.productId, variant_id: input.variantId ?? void 0, quantity: normalizeQuantity(input.quantity), note: input.note, sort_order: input.sortOrder, metadata: input.metadata }) }); return resolveItemFromResponse(response); }, async createProductListCart (input) { const response = await sdk.client.fetch(`${basePath}/${input.listId}/cart`, { method: "POST", body: compactRecord({ region_id: input.regionId ?? void 0, country_code: input.countryCode ?? void 0, email: input.email ?? void 0, sales_channel_id: input.salesChannelId ?? void 0 }) }); const cart = resolveProductListCartFromResponse(response); if (!cart) throw new Error("Product list cart response did not include a cart."); return transformCart(cart); }, async updateProductListItem (input) { const response = await sdk.client.fetch(`${basePath}/items/${input.itemId}`, { method: "POST", body: compactRecord({ quantity: normalizeQuantity(input.quantity), note: input.note, sort_order: input.sortOrder, metadata: input.metadata }) }); return resolveItemFromResponse(response); }, async changeProductListItemQuantity (input) { const response = await sdk.client.fetch(`${basePath}/items/${input.itemId}/change-quantity`, { method: "POST", body: compactRecord({ quantity: normalizeQuantityDelta(input.quantity) }) }); return resolveItemFromResponse(response); }, async incrementProductListItem (input) { const response = await sdk.client.fetch(`${basePath}/items/${input.itemId}/increment`, { method: "POST", body: compactRecord({ quantity: normalizeQuantity(input.quantity) ?? 1 }) }); return resolveItemFromResponse(response); }, deleteProductListItem (input) { const path = input.listId ? `${basePath}/${input.listId}/items/${input.itemId}` : `${basePath}/items/${input.itemId}`; return sdk.client.fetch(path, { method: "DELETE" }); } }; } export { createMedusaProductListService, normalizeProductListsResponse, resolveProductListCartFromResponse, resolveProductListFromResponse, resolveProductListItemFromResponse };