@shoppexio/storefront 1.0.73 → 1.0.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.75
4
+
5
+ - `getStore`, `getStorefront`, `resolveStoreByDomain`, `getProducts`, `getStorefrontProductsPage`, `getProduct` and `getCategories` now forward the full failure contract (`code`, `errorParams`, `status`, `responseReceived`, `responseDefinitive`) instead of rebuilding `{ success: false, message }`, so `code === 'errors.storefront.currency_unavailable'` is branchable through every catalog read. A slug `getProduct()` whose store lookup failed returns that failure instead of a misleading not-found.
6
+
7
+ ## 1.0.74
8
+
9
+ - Catalog reads now resolve the buyer currency with the same rule as cart quotes and checkout: a `?currency=` on the page URL wins, then `init({ currency })`. Before, a merchant-hosted page with `?currency=` priced the catalog in the init currency and the cart in the URL currency.
10
+ - `shoppex.invalidateCache(prefixOrKey)` matches the bare key again across every locale/currency namespace (1.0.73 keys are `<locale>|<currency>|<key>`, which made prefix invalidation a no-op).
11
+ - A rejected `init()` (invalid currency) leaves the previous configuration, including the cached shop id, untouched.
12
+
3
13
  ## 1.0.73
4
14
 
5
15
  - `init({ currency })` is now enforced on every priced read (ADR-0066). `getStorefront`, `getStore`, `resolveStoreByDomain`, `getProducts`, `getStorefrontProductsPage` and `getProduct` send it as `?currency=`; before, only cart quotes and checkout used it, so a catalog could show one currency and the checkout price in another.
package/dist/index.cjs CHANGED
@@ -18074,6 +18074,9 @@ function normalizeRequestedCurrency(value) {
18074
18074
  const normalized = value?.trim().toUpperCase();
18075
18075
  return normalized && /^[A-Z]{3}$/.test(normalized) ? normalized : null;
18076
18076
  }
18077
+ function resolveBuyerCurrency(configCurrency) {
18078
+ return getRequestedCurrencyFromLocation() ?? normalizeRequestedCurrency(configCurrency);
18079
+ }
18077
18080
  function getRequestedCurrencyFromLocation() {
18078
18081
  if (typeof window === "undefined" || !window.location) {
18079
18082
  return null;
@@ -18101,12 +18104,13 @@ var currentConfig = null;
18101
18104
  var cachedShopId = null;
18102
18105
  var DEFAULT_CHECKOUT_BASE_URL = "https://checkout.shoppex.io";
18103
18106
  function initConfig(storeSlug, options) {
18107
+ const currency = normalizeInitCurrency(options?.currency);
18104
18108
  const normalizedShopId = options?.shopId?.trim();
18105
18109
  cachedShopId = normalizedShopId ? normalizedShopId : null;
18106
18110
  currentConfig = {
18107
18111
  storeSlug,
18108
18112
  locale: options?.locale,
18109
- currency: normalizeInitCurrency(options?.currency),
18113
+ currency,
18110
18114
  apiBaseUrl: options?.apiBaseUrl ?? DEFAULT_API_BASE_URL,
18111
18115
  checkoutBaseUrl: options?.checkoutBaseUrl ?? DEFAULT_CHECKOUT_BASE_URL
18112
18116
  };
@@ -18559,9 +18563,11 @@ function clearCache() {
18559
18563
  cache.clear();
18560
18564
  pending.clear();
18561
18565
  }
18566
+ var AUDIENCE_PREFIX = /^[^|]*\|[^|]*\|/;
18562
18567
  function invalidateCache(prefixOrKey) {
18563
18568
  for (const key of cache.keys()) {
18564
- if (key === prefixOrKey || key.startsWith(prefixOrKey)) {
18569
+ const bareKey = key.replace(AUDIENCE_PREFIX, "");
18570
+ if (key === prefixOrKey || key.startsWith(prefixOrKey) || bareKey === prefixOrKey || bareKey.startsWith(prefixOrKey)) {
18565
18571
  cache.delete(key);
18566
18572
  }
18567
18573
  }
@@ -18760,6 +18766,15 @@ function appendQueryParam(url2, key, value) {
18760
18766
  const separator = url2.includes("?") ? "&" : "?";
18761
18767
  return `${url2}${separator}${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
18762
18768
  }
18769
+ function forwardFailure(response, overrides = {}) {
18770
+ const { success: _success2, data: _data, ...failure } = response;
18771
+ return {
18772
+ ...failure,
18773
+ success: false,
18774
+ message: overrides.message ?? response.message,
18775
+ ...overrides.data !== void 0 ? { data: overrides.data } : {}
18776
+ };
18777
+ }
18763
18778
  async function request(endpoint, options = {}) {
18764
18779
  const config2 = options.baseUrl ? null : getConfig();
18765
18780
  const audience = config2 ?? (isInitialized() ? getConfig() : null);
@@ -18775,7 +18790,7 @@ async function request(endpoint, options = {}) {
18775
18790
  } = options;
18776
18791
  const retryCount = retries ?? (method === "GET" ? MAX_RETRIES : 0);
18777
18792
  const apiBaseUrl = baseUrl ?? config2?.apiBaseUrl ?? "";
18778
- const buyerCurrency = pricesInBuyerCurrency && audience?.currency ? audience.currency : null;
18793
+ const buyerCurrency = pricesInBuyerCurrency ? resolveBuyerCurrency(audience?.currency) : null;
18779
18794
  const url2 = buyerCurrency ? appendQueryParam(`${apiBaseUrl}${endpoint}`, "currency", buyerCurrency) : `${apiBaseUrl}${endpoint}`;
18780
18795
  const headers = {
18781
18796
  "Content-Type": "application/json",
@@ -18994,10 +19009,7 @@ async function getStore() {
18994
19009
  data: response.data.shop
18995
19010
  };
18996
19011
  }
18997
- return {
18998
- success: false,
18999
- message: response.message
19000
- };
19012
+ return forwardFailure(response);
19001
19013
  }
19002
19014
  async function resolveStoreByDomain(domain2, apiBaseUrl) {
19003
19015
  const resolvedDomain = domain2 ?? (typeof window !== "undefined" ? window.location.hostname : "");
@@ -19032,10 +19044,7 @@ async function resolveStoreByDomain(domain2, apiBaseUrl) {
19032
19044
  data: response.data.shop
19033
19045
  };
19034
19046
  }
19035
- return {
19036
- success: false,
19037
- message: response.message ?? "Failed to resolve store"
19038
- };
19047
+ return forwardFailure(response, { message: response.message ?? "Failed to resolve store" });
19039
19048
  }
19040
19049
  async function getStorefront(options) {
19041
19050
  const config2 = getConfig();
@@ -19077,10 +19086,7 @@ async function getStorefront(options) {
19077
19086
  }
19078
19087
  };
19079
19088
  }
19080
- return {
19081
- success: false,
19082
- message: response.message
19083
- };
19089
+ return forwardFailure(response);
19084
19090
  }
19085
19091
  async function getStoreLogoUrl() {
19086
19092
  const response = await getStore();
@@ -19164,11 +19170,7 @@ async function getProducts() {
19164
19170
  data: getMergedStorefrontProducts(response.data.products.map(normalizeProduct))
19165
19171
  };
19166
19172
  }
19167
- return {
19168
- success: false,
19169
- message: response.message,
19170
- data: []
19171
- };
19173
+ return forwardFailure(response, { data: [] });
19172
19174
  }
19173
19175
  async function getStorefrontProductsPage(options) {
19174
19176
  const config2 = getConfig();
@@ -19211,16 +19213,16 @@ async function getStorefrontProductsPage(options) {
19211
19213
  }
19212
19214
  };
19213
19215
  }
19214
- return {
19215
- success: false,
19216
- message: response.message
19217
- };
19216
+ return forwardFailure(response);
19218
19217
  }
19219
19218
  async function getProduct(idOrSlug) {
19220
19219
  let shopId = getShopId();
19221
19220
  if (!shopId) {
19222
19221
  const store = await getStore();
19223
- shopId = store.success ? store.data?.id ?? null : null;
19222
+ if (!store.success) {
19223
+ return forwardFailure(store);
19224
+ }
19225
+ shopId = store.data?.id ?? null;
19224
19226
  }
19225
19227
  const queryParams = shopId ? `?slug_shop_id=${encodeURIComponent(shopId)}` : "";
19226
19228
  const response = await get(
@@ -19240,18 +19242,12 @@ async function getProduct(idOrSlug) {
19240
19242
  data: normalizeProduct(response.data.product)
19241
19243
  };
19242
19244
  }
19243
- return {
19244
- success: false,
19245
- message: response.message
19246
- };
19245
+ return forwardFailure(response);
19247
19246
  }
19248
19247
  async function getCategories() {
19249
19248
  const products = await getProducts();
19250
19249
  if (!products.success || !products.data) {
19251
- return {
19252
- success: false,
19253
- message: products.message
19254
- };
19250
+ return forwardFailure(products);
19255
19251
  }
19256
19252
  const categories = /* @__PURE__ */ new Set();
19257
19253
  for (const product of products.data) {
@@ -20088,7 +20084,7 @@ function clearLatestQuoteToken() {
20088
20084
  async function quoteCart(coupon, currency) {
20089
20085
  const sequence = quoteSequence += 1;
20090
20086
  const payload = getCartPayload(coupon);
20091
- const normalizedCurrency = normalizeRequestedCurrency(currency) ?? getRequestedCurrencyFromLocation() ?? normalizeRequestedCurrency(getConfig().currency);
20087
+ const normalizedCurrency = normalizeRequestedCurrency(currency) ?? resolveBuyerCurrency(getConfig().currency);
20092
20088
  const response = await post("/v1/storefront/cart/quote", {
20093
20089
  shop_slug: payload.store_slug,
20094
20090
  cart: payload.items,
@@ -20175,10 +20171,10 @@ function resolveRequestedCheckoutCurrency(options) {
20175
20171
  if (options.currency !== void 0) {
20176
20172
  return normalizeRequestedCurrency(options.currency);
20177
20173
  }
20178
- return getRequestedCurrencyFromLocation() ?? normalizeRequestedCurrency(getConfig().currency);
20174
+ return resolveBuyerCurrency(getConfig().currency);
20179
20175
  }
20180
20176
  function getRequestedCheckoutCurrency() {
20181
- return getRequestedCurrencyFromLocation() ?? normalizeRequestedCurrency(getConfig().currency);
20177
+ return resolveBuyerCurrency(getConfig().currency);
20182
20178
  }
20183
20179
  function normalizeCheckoutFailureMessage(rawMessage) {
20184
20180
  const message = rawMessage?.trim() ?? "";