@cimplify/sdk 0.22.0 → 0.22.1

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/dist/react.js CHANGED
@@ -1684,41 +1684,130 @@ function Price({ amount, className, prefix }) {
1684
1684
  chunk64OCG2TJ_js.formatPrice(convertPrice(amount), displayCurrency)
1685
1685
  ] });
1686
1686
  }
1687
- var productsCache = /* @__PURE__ */ new Map();
1688
- var productsInflight = /* @__PURE__ */ new Map();
1689
- function buildProductsCacheKey(client, locationId, options) {
1690
- return [
1691
- client.getPublicKey(),
1692
- locationId ?? "",
1693
- options.category ?? "",
1694
- options.taxonomy ?? "",
1695
- options.search ?? "",
1696
- options.featured ?? "",
1697
- options.limit ?? "",
1698
- options.sort_by ?? "",
1699
- options.sort_order ?? "",
1700
- options.tags?.join(",") ?? "",
1701
- options.in_stock ?? "",
1702
- options.min_price ?? "",
1703
- options.max_price ?? "",
1704
- options.page ?? "",
1705
- options.properties ? JSON.stringify(options.properties) : ""
1706
- ].join("|");
1707
- }
1708
- function useProducts(options = {}) {
1709
- const context = useOptionalCimplifyClient();
1710
- const client = options.client ?? context?.client;
1711
- if (!client) {
1712
- throw new Error("useProducts must be used within CimplifyProvider or passed { client }.");
1687
+ function createCachedQuery(config) {
1688
+ const cache = /* @__PURE__ */ new Map();
1689
+ const inflight = /* @__PURE__ */ new Map();
1690
+ const gcMaxAge = config.gcMaxAge ?? 3e5;
1691
+ let lastSweep = 0;
1692
+ function sweep() {
1693
+ const now = Date.now();
1694
+ if (now - lastSweep < 6e4) return;
1695
+ lastSweep = now;
1696
+ const cutoff = now - gcMaxAge;
1697
+ for (const [key, entry] of cache) {
1698
+ if (entry.ts < cutoff) cache.delete(key);
1699
+ }
1713
1700
  }
1714
- const enabled = options.enabled ?? true;
1715
- const locationId = client.getLocationId();
1716
- const previousLocationIdRef = React3.useRef(locationId);
1717
- const requestIdRef = React3.useRef(0);
1718
- const tagsSignature = options.tags?.join(",") ?? "";
1719
- const propertiesSignature = options.properties ? JSON.stringify(options.properties) : "";
1720
- const queryOptions = React3.useMemo(
1721
- () => ({
1701
+ function useCachedQuery(options = {}) {
1702
+ const context = useOptionalCimplifyClient();
1703
+ const client = options.client ?? context?.client;
1704
+ if (!client) {
1705
+ throw new Error(
1706
+ `${config.name} must be used within CimplifyProvider or passed { client }.`
1707
+ );
1708
+ }
1709
+ const enabled = options.enabled ?? true;
1710
+ const locationId = client.getLocationId();
1711
+ const previousLocationRef = React3.useRef(locationId);
1712
+ const requestIdRef = React3.useRef(0);
1713
+ const optionsRef = React3.useRef(options);
1714
+ optionsRef.current = options;
1715
+ if (config.locationSensitive && previousLocationRef.current !== locationId) {
1716
+ cache.clear();
1717
+ inflight.clear();
1718
+ previousLocationRef.current = locationId;
1719
+ }
1720
+ sweep();
1721
+ const cacheKey2 = config.key(client, options);
1722
+ const cached = cache.get(cacheKey2);
1723
+ const [data, setData] = React3.useState(cached?.data ?? null);
1724
+ const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
1725
+ const [error, setError] = React3.useState(null);
1726
+ const load = React3.useCallback(
1727
+ async (force = false) => {
1728
+ if (!enabled) {
1729
+ setIsLoading(false);
1730
+ return;
1731
+ }
1732
+ const nextRequestId = ++requestIdRef.current;
1733
+ setError(null);
1734
+ if (!force) {
1735
+ const hit = cache.get(cacheKey2);
1736
+ if (hit) {
1737
+ setData(hit.data);
1738
+ setIsLoading(false);
1739
+ return;
1740
+ }
1741
+ }
1742
+ setIsLoading(true);
1743
+ try {
1744
+ const existing = inflight.get(cacheKey2);
1745
+ const promise = existing ?? (async () => config.fetch(client, optionsRef.current))();
1746
+ if (!existing) {
1747
+ inflight.set(cacheKey2, promise);
1748
+ promise.finally(() => inflight.delete(cacheKey2)).catch(() => {
1749
+ });
1750
+ }
1751
+ const value = await promise;
1752
+ cache.set(cacheKey2, { data: value, ts: Date.now() });
1753
+ if (nextRequestId === requestIdRef.current) {
1754
+ setData(value);
1755
+ setError(null);
1756
+ }
1757
+ } catch (loadError) {
1758
+ if (nextRequestId === requestIdRef.current) {
1759
+ setError(loadError);
1760
+ }
1761
+ } finally {
1762
+ if (nextRequestId === requestIdRef.current) {
1763
+ setIsLoading(false);
1764
+ }
1765
+ }
1766
+ },
1767
+ [cacheKey2, client, enabled]
1768
+ );
1769
+ React3.useEffect(() => {
1770
+ void load(false);
1771
+ }, [load]);
1772
+ const refetch = React3.useCallback(async () => {
1773
+ cache.delete(cacheKey2);
1774
+ await load(true);
1775
+ }, [cacheKey2, load]);
1776
+ return { data, isLoading, error, refetch };
1777
+ }
1778
+ useCachedQuery.clear = () => {
1779
+ cache.clear();
1780
+ inflight.clear();
1781
+ };
1782
+ return useCachedQuery;
1783
+ }
1784
+ function cacheKey(...parts) {
1785
+ return parts.map((p) => String(p ?? "")).join("|");
1786
+ }
1787
+
1788
+ // src/react/hooks/use-products.ts
1789
+ var productsQuery = createCachedQuery({
1790
+ name: "useProducts",
1791
+ locationSensitive: true,
1792
+ key: (client, options) => cacheKey(
1793
+ client.getPublicKey(),
1794
+ client.getLocationId(),
1795
+ options.category,
1796
+ options.taxonomy,
1797
+ options.search,
1798
+ options.featured,
1799
+ options.limit,
1800
+ options.sort_by,
1801
+ options.sort_order,
1802
+ options.tags?.join(","),
1803
+ options.in_stock,
1804
+ options.min_price,
1805
+ options.max_price,
1806
+ options.page,
1807
+ options.properties ? JSON.stringify(options.properties) : void 0
1808
+ ),
1809
+ fetch: async (client, options) => {
1810
+ const result = await client.catalogue.getProducts({
1722
1811
  category: options.category,
1723
1812
  taxonomy: options.taxonomy,
1724
1813
  search: options.search,
@@ -1732,301 +1821,71 @@ function useProducts(options = {}) {
1732
1821
  max_price: options.max_price,
1733
1822
  page: options.page,
1734
1823
  properties: options.properties
1735
- }),
1736
- [
1737
- options.category,
1738
- options.taxonomy,
1739
- options.search,
1740
- options.featured,
1741
- options.limit,
1742
- options.sort_by,
1743
- options.sort_order,
1744
- tagsSignature,
1745
- options.in_stock,
1746
- options.min_price,
1747
- options.max_price,
1748
- options.page,
1749
- propertiesSignature
1750
- ]
1751
- );
1752
- const cacheKey = React3.useMemo(
1753
- () => buildProductsCacheKey(client, locationId, queryOptions),
1754
- [client, locationId, queryOptions]
1755
- );
1756
- const cached = productsCache.get(cacheKey);
1757
- const [products, setProducts] = React3.useState(cached?.products ?? []);
1758
- const [isComplete, setIsComplete] = React3.useState(cached?.is_complete ?? true);
1759
- const [totalAvailable, setTotalAvailable] = React3.useState(cached?.total_available);
1760
- const [pagination, setPagination] = React3.useState(cached?.pagination);
1761
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
1762
- const [error, setError] = React3.useState(null);
1763
- React3.useEffect(() => {
1764
- if (previousLocationIdRef.current !== locationId) {
1765
- productsCache.clear();
1766
- productsInflight.clear();
1767
- previousLocationIdRef.current = locationId;
1768
- }
1769
- }, [locationId]);
1770
- const load = React3.useCallback(
1771
- async (force = false) => {
1772
- if (!enabled) {
1773
- setIsLoading(false);
1774
- return;
1775
- }
1776
- const nextRequestId = ++requestIdRef.current;
1777
- setError(null);
1778
- if (!force) {
1779
- const cacheEntry = productsCache.get(cacheKey);
1780
- if (cacheEntry) {
1781
- setProducts(cacheEntry.products);
1782
- setIsComplete(cacheEntry.is_complete);
1783
- setTotalAvailable(cacheEntry.total_available);
1784
- setPagination(cacheEntry.pagination);
1785
- setIsLoading(false);
1786
- return;
1787
- }
1788
- }
1789
- setIsLoading(true);
1790
- try {
1791
- const existing = productsInflight.get(cacheKey);
1792
- const promise = existing ?? (async () => {
1793
- const result = await client.catalogue.getProducts(queryOptions);
1794
- if (!result.ok) {
1795
- throw result.error;
1796
- }
1797
- return result.value;
1798
- })();
1799
- if (!existing) {
1800
- productsInflight.set(
1801
- cacheKey,
1802
- promise.finally(() => {
1803
- productsInflight.delete(cacheKey);
1804
- })
1805
- );
1806
- }
1807
- const value = await promise;
1808
- productsCache.set(cacheKey, {
1809
- products: value.items,
1810
- is_complete: value.is_complete,
1811
- total_available: value.total_available,
1812
- pagination: value.pagination
1813
- });
1814
- if (nextRequestId === requestIdRef.current) {
1815
- setProducts(value.items);
1816
- setIsComplete(value.is_complete);
1817
- setTotalAvailable(value.total_available);
1818
- setPagination(value.pagination);
1819
- setError(null);
1820
- }
1821
- } catch (loadError) {
1822
- if (nextRequestId === requestIdRef.current) {
1823
- setError(loadError);
1824
- }
1825
- } finally {
1826
- if (nextRequestId === requestIdRef.current) {
1827
- setIsLoading(false);
1828
- }
1829
- }
1830
- },
1831
- [cacheKey, client, enabled, queryOptions]
1832
- );
1833
- React3.useEffect(() => {
1834
- void load(false);
1835
- }, [load]);
1836
- const refetch = React3.useCallback(async () => {
1837
- productsCache.delete(cacheKey);
1838
- await load(true);
1839
- }, [cacheKey, load]);
1824
+ });
1825
+ if (!result.ok) throw result.error;
1826
+ return {
1827
+ products: result.value.items,
1828
+ is_complete: result.value.is_complete,
1829
+ total_available: result.value.total_available,
1830
+ pagination: result.value.pagination
1831
+ };
1832
+ }
1833
+ });
1834
+ function useProducts(options = {}) {
1835
+ const { data, isLoading, error, refetch } = productsQuery(options);
1840
1836
  return {
1841
- products,
1842
- is_complete: isComplete,
1843
- total_available: totalAvailable,
1844
- pagination,
1837
+ products: data?.products ?? [],
1838
+ is_complete: data?.is_complete ?? true,
1839
+ total_available: data?.total_available,
1840
+ pagination: data?.pagination,
1845
1841
  isLoading,
1846
1842
  error,
1847
1843
  refetch
1848
1844
  };
1849
1845
  }
1850
- var productCache = /* @__PURE__ */ new Map();
1851
- var productInflight = /* @__PURE__ */ new Map();
1846
+
1847
+ // src/react/hooks/use-product.ts
1852
1848
  function isLikelySlug(value) {
1853
1849
  return /^[a-z0-9-]+$/.test(value);
1854
1850
  }
1855
- function buildProductCacheKey(client, locationId, slugOrId) {
1856
- return JSON.stringify({
1857
- key: client.getPublicKey(),
1858
- location_id: locationId || "__none__",
1859
- slug_or_id: slugOrId
1851
+ var productQuery = createCachedQuery({
1852
+ name: "useProduct",
1853
+ locationSensitive: true,
1854
+ key: (client, options) => cacheKey(client.getPublicKey(), client.getLocationId(), options.slugOrId),
1855
+ fetch: async (client, options) => {
1856
+ const result = isLikelySlug(options.slugOrId) ? await client.catalogue.getProductBySlug(options.slugOrId) : await client.catalogue.getProduct(options.slugOrId);
1857
+ if (!result.ok) throw result.error;
1858
+ client.activity.trackProductView(result.value.id, {
1859
+ productName: result.value.name,
1860
+ categoryId: result.value.category_id,
1861
+ price: String(result.value.default_price)
1862
+ });
1863
+ return result.value;
1864
+ }
1865
+ });
1866
+ function useProduct(slugOrId, options = {}) {
1867
+ const normalized = (slugOrId || "").trim();
1868
+ const { data, isLoading, error, refetch } = productQuery({
1869
+ ...options,
1870
+ slugOrId: normalized,
1871
+ enabled: (options.enabled ?? true) && normalized.length > 0
1860
1872
  });
1873
+ return { product: data, isLoading, error, refetch };
1861
1874
  }
1862
- function useProduct(slugOrId, options = {}) {
1863
- const context = useOptionalCimplifyClient();
1864
- const client = options.client ?? context?.client;
1865
- if (!client) {
1866
- throw new Error("useProduct must be used within CimplifyProvider or passed { client }.");
1875
+
1876
+ // src/react/hooks/use-categories.ts
1877
+ var categoriesQuery = createCachedQuery({
1878
+ name: "useCategories",
1879
+ key: (client) => client.getPublicKey() || "__demo__",
1880
+ fetch: async (client) => {
1881
+ const result = await client.catalogue.getCategories();
1882
+ if (!result.ok) throw result.error;
1883
+ return result.value;
1867
1884
  }
1868
- const enabled = options.enabled ?? true;
1869
- const locationId = client.getLocationId();
1870
- const previousLocationIdRef = React3.useRef(locationId);
1871
- const requestIdRef = React3.useRef(0);
1872
- const trackedProductRef = React3.useRef(null);
1873
- const normalizedSlugOrId = React3.useMemo(() => (slugOrId || "").trim(), [slugOrId]);
1874
- const cacheKey = React3.useMemo(
1875
- () => buildProductCacheKey(client, locationId, normalizedSlugOrId),
1876
- [client, locationId, normalizedSlugOrId]
1877
- );
1878
- const cached = productCache.get(cacheKey);
1879
- const [product, setProduct] = React3.useState(cached?.product ?? null);
1880
- const [isLoading, setIsLoading] = React3.useState(
1881
- enabled && normalizedSlugOrId.length > 0 && !cached
1882
- );
1883
- const [error, setError] = React3.useState(null);
1884
- React3.useEffect(() => {
1885
- if (previousLocationIdRef.current !== locationId) {
1886
- productCache.clear();
1887
- productInflight.clear();
1888
- previousLocationIdRef.current = locationId;
1889
- }
1890
- }, [locationId]);
1891
- const load = React3.useCallback(
1892
- async (force = false) => {
1893
- if (!enabled || normalizedSlugOrId.length === 0) {
1894
- setProduct(null);
1895
- setIsLoading(false);
1896
- return;
1897
- }
1898
- const nextRequestId = ++requestIdRef.current;
1899
- setError(null);
1900
- if (!force) {
1901
- const cacheEntry = productCache.get(cacheKey);
1902
- if (cacheEntry) {
1903
- setProduct(cacheEntry.product);
1904
- setIsLoading(false);
1905
- return;
1906
- }
1907
- }
1908
- setIsLoading(true);
1909
- try {
1910
- const existing = productInflight.get(cacheKey);
1911
- const promise = existing ?? (async () => {
1912
- const result = isLikelySlug(normalizedSlugOrId) ? await client.catalogue.getProductBySlug(normalizedSlugOrId) : await client.catalogue.getProduct(normalizedSlugOrId);
1913
- if (!result.ok) {
1914
- throw result.error;
1915
- }
1916
- return result.value;
1917
- })();
1918
- if (!existing) {
1919
- productInflight.set(
1920
- cacheKey,
1921
- promise.finally(() => {
1922
- productInflight.delete(cacheKey);
1923
- })
1924
- );
1925
- }
1926
- const value = await promise;
1927
- productCache.set(cacheKey, { product: value });
1928
- if (nextRequestId === requestIdRef.current) {
1929
- setProduct(value);
1930
- setError(null);
1931
- if (value && trackedProductRef.current !== value.id) {
1932
- trackedProductRef.current = value.id;
1933
- client.activity.trackProductView(value.id, {
1934
- productName: value.name,
1935
- categoryId: value.category_id,
1936
- price: String(value.default_price)
1937
- });
1938
- }
1939
- }
1940
- } catch (loadError) {
1941
- if (nextRequestId === requestIdRef.current) {
1942
- setError(loadError);
1943
- }
1944
- } finally {
1945
- if (nextRequestId === requestIdRef.current) {
1946
- setIsLoading(false);
1947
- }
1948
- }
1949
- },
1950
- [cacheKey, client, enabled, normalizedSlugOrId]
1951
- );
1952
- React3.useEffect(() => {
1953
- void load(false);
1954
- }, [load]);
1955
- const refetch = React3.useCallback(async () => {
1956
- productCache.delete(cacheKey);
1957
- await load(true);
1958
- }, [cacheKey, load]);
1959
- return { product, isLoading, error, refetch };
1960
- }
1961
- var categoriesCache = /* @__PURE__ */ new Map();
1962
- var categoriesInflight = /* @__PURE__ */ new Map();
1963
- function buildCategoriesCacheKey(client) {
1964
- return client.getPublicKey() || "__demo__";
1965
- }
1885
+ });
1966
1886
  function useCategories(options = {}) {
1967
- const context = useOptionalCimplifyClient();
1968
- const client = options.client ?? context?.client;
1969
- if (!client) {
1970
- throw new Error("useCategories must be used within CimplifyProvider or passed { client }.");
1971
- }
1972
- const enabled = options.enabled ?? true;
1973
- const cacheKey = React3.useMemo(() => buildCategoriesCacheKey(client), [client]);
1974
- const cached = categoriesCache.get(cacheKey);
1975
- const [categories, setCategories] = React3.useState(cached ?? []);
1976
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
1977
- const [error, setError] = React3.useState(null);
1978
- const load = React3.useCallback(
1979
- async (force = false) => {
1980
- if (!enabled) {
1981
- setIsLoading(false);
1982
- return;
1983
- }
1984
- setError(null);
1985
- if (!force) {
1986
- const cachedCategories = categoriesCache.get(cacheKey);
1987
- if (cachedCategories) {
1988
- setCategories(cachedCategories);
1989
- setIsLoading(false);
1990
- return;
1991
- }
1992
- }
1993
- setIsLoading(true);
1994
- try {
1995
- const existing = categoriesInflight.get(cacheKey);
1996
- const promise = existing ?? (async () => {
1997
- const result = await client.catalogue.getCategories();
1998
- if (!result.ok) {
1999
- throw result.error;
2000
- }
2001
- return result.value;
2002
- })();
2003
- if (!existing) {
2004
- categoriesInflight.set(
2005
- cacheKey,
2006
- promise.finally(() => {
2007
- categoriesInflight.delete(cacheKey);
2008
- })
2009
- );
2010
- }
2011
- const value = await promise;
2012
- categoriesCache.set(cacheKey, value);
2013
- setCategories(value);
2014
- } catch (loadError) {
2015
- setError(loadError);
2016
- } finally {
2017
- setIsLoading(false);
2018
- }
2019
- },
2020
- [cacheKey, client, enabled]
2021
- );
2022
- React3.useEffect(() => {
2023
- void load(false);
2024
- }, [load]);
2025
- const refetch = React3.useCallback(async () => {
2026
- categoriesCache.delete(cacheKey);
2027
- await load(true);
2028
- }, [cacheKey, load]);
2029
- return { categories, isLoading, error, refetch };
1887
+ const { data, isLoading, error, refetch } = categoriesQuery(options);
1888
+ return { categories: data ?? [], isLoading, error, refetch };
2030
1889
  }
2031
1890
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "cancelled", "refunded"]);
2032
1891
  var orderCache = /* @__PURE__ */ new Map();
@@ -2048,11 +1907,11 @@ function useOrder(orderId, options = {}) {
2048
1907
  const previousStatusRef = React3.useRef(null);
2049
1908
  const onStatusChangeRef = React3.useRef(options.onStatusChange);
2050
1909
  onStatusChangeRef.current = options.onStatusChange;
2051
- const cacheKey = React3.useMemo(
1910
+ const cacheKey2 = React3.useMemo(
2052
1911
  () => buildOrderCacheKey(client, normalizedOrderId),
2053
1912
  [client, normalizedOrderId]
2054
1913
  );
2055
- const cached = orderCache.get(cacheKey);
1914
+ const cached = orderCache.get(cacheKey2);
2056
1915
  const [order, setOrder] = React3.useState(cached?.order ?? null);
2057
1916
  const [isLoading, setIsLoading] = React3.useState(
2058
1917
  enabled && normalizedOrderId.length > 0 && !cached
@@ -2068,7 +1927,7 @@ function useOrder(orderId, options = {}) {
2068
1927
  const nextRequestId = ++requestIdRef.current;
2069
1928
  setError(null);
2070
1929
  if (!force) {
2071
- const cacheEntry = orderCache.get(cacheKey);
1930
+ const cacheEntry = orderCache.get(cacheKey2);
2072
1931
  if (cacheEntry) {
2073
1932
  setOrder(cacheEntry.order);
2074
1933
  setIsLoading(false);
@@ -2077,7 +1936,7 @@ function useOrder(orderId, options = {}) {
2077
1936
  }
2078
1937
  setIsLoading(true);
2079
1938
  try {
2080
- const existing = orderInflight.get(cacheKey);
1939
+ const existing = orderInflight.get(cacheKey2);
2081
1940
  const promise = existing ?? (async () => {
2082
1941
  const result = await client.orders.get(normalizedOrderId);
2083
1942
  if (!result.ok) {
@@ -2087,14 +1946,14 @@ function useOrder(orderId, options = {}) {
2087
1946
  })();
2088
1947
  if (!existing) {
2089
1948
  orderInflight.set(
2090
- cacheKey,
1949
+ cacheKey2,
2091
1950
  promise.finally(() => {
2092
- orderInflight.delete(cacheKey);
1951
+ orderInflight.delete(cacheKey2);
2093
1952
  })
2094
1953
  );
2095
1954
  }
2096
1955
  const value = await promise;
2097
- orderCache.set(cacheKey, { order: value });
1956
+ orderCache.set(cacheKey2, { order: value });
2098
1957
  if (nextRequestId === requestIdRef.current) {
2099
1958
  setOrder(value);
2100
1959
  setError(null);
@@ -2115,7 +1974,7 @@ function useOrder(orderId, options = {}) {
2115
1974
  }
2116
1975
  }
2117
1976
  },
2118
- [cacheKey, client, enabled, normalizedOrderId]
1977
+ [cacheKey2, client, enabled, normalizedOrderId]
2119
1978
  );
2120
1979
  React3.useEffect(() => {
2121
1980
  void load(false);
@@ -2133,9 +1992,9 @@ function useOrder(orderId, options = {}) {
2133
1992
  };
2134
1993
  }, [enabled, isTerminal, load, normalizedOrderId, poll, pollInterval]);
2135
1994
  const refetch = React3.useCallback(async () => {
2136
- orderCache.delete(cacheKey);
1995
+ orderCache.delete(cacheKey2);
2137
1996
  await load(true);
2138
- }, [cacheKey, load]);
1997
+ }, [cacheKey2, load]);
2139
1998
  return { order, isLoading, error, refetch, isTerminal };
2140
1999
  }
2141
2000
  var LOCATION_STORAGE_KEY2 = "cimplify_location_id";
@@ -2238,216 +2097,64 @@ function useLocations(options = {}) {
2238
2097
  isLoading
2239
2098
  };
2240
2099
  }
2241
- var collectionsCache = /* @__PURE__ */ new Map();
2242
- var collectionsInflight = /* @__PURE__ */ new Map();
2243
- function buildCollectionsCacheKey(client, locationId) {
2244
- return JSON.stringify({
2245
- key: client.getPublicKey(),
2246
- location_id: locationId || "__none__"
2100
+
2101
+ // src/react/hooks/use-collections.ts
2102
+ var collectionsQuery = createCachedQuery({
2103
+ name: "useCollections",
2104
+ locationSensitive: true,
2105
+ key: (client) => cacheKey(client.getPublicKey(), client.getLocationId()),
2106
+ fetch: async (client) => {
2107
+ const result = await client.catalogue.getCollections();
2108
+ if (!result.ok) throw result.error;
2109
+ return result.value;
2110
+ }
2111
+ });
2112
+ function useCollections(options = {}) {
2113
+ const { data, isLoading, error, refetch } = collectionsQuery(options);
2114
+ return { collections: data ?? [], isLoading, error, refetch };
2115
+ }
2116
+
2117
+ // src/react/hooks/use-collection.ts
2118
+ function isLikelySlug2(value) {
2119
+ return /^[a-z0-9-]+$/.test(value);
2120
+ }
2121
+ var collectionQuery = createCachedQuery({
2122
+ name: "useCollection",
2123
+ locationSensitive: true,
2124
+ key: (client, options) => cacheKey(client.getPublicKey(), client.getLocationId(), options.idOrSlug),
2125
+ fetch: async (client, options) => {
2126
+ const collectionResult = isLikelySlug2(options.idOrSlug) ? await client.catalogue.getCollectionBySlug(options.idOrSlug) : await client.catalogue.getCollection(options.idOrSlug);
2127
+ if (!collectionResult.ok) throw collectionResult.error;
2128
+ const productsResult = await client.catalogue.getCollectionProducts(
2129
+ collectionResult.value.id
2130
+ );
2131
+ if (!productsResult.ok) throw productsResult.error;
2132
+ return {
2133
+ collection: collectionResult.value,
2134
+ products: productsResult.value
2135
+ };
2136
+ }
2137
+ });
2138
+ function useCollection(idOrSlug, options = {}) {
2139
+ const normalized = (idOrSlug || "").trim();
2140
+ const { data, isLoading, error, refetch } = collectionQuery({
2141
+ ...options,
2142
+ idOrSlug: normalized,
2143
+ enabled: (options.enabled ?? true) && normalized.length > 0
2247
2144
  });
2145
+ return {
2146
+ collection: data?.collection ?? null,
2147
+ products: data?.products ?? [],
2148
+ isLoading,
2149
+ error,
2150
+ refetch
2151
+ };
2248
2152
  }
2249
- function useCollections(options = {}) {
2153
+ function useSearch(options = {}) {
2250
2154
  const context = useOptionalCimplifyClient();
2251
2155
  const client = options.client ?? context?.client;
2252
2156
  if (!client) {
2253
- throw new Error("useCollections must be used within CimplifyProvider or passed { client }.");
2254
- }
2255
- const enabled = options.enabled ?? true;
2256
- const locationId = client.getLocationId();
2257
- const previousLocationIdRef = React3.useRef(locationId);
2258
- const requestIdRef = React3.useRef(0);
2259
- const cacheKey = React3.useMemo(
2260
- () => buildCollectionsCacheKey(client, locationId),
2261
- [client, locationId]
2262
- );
2263
- const cached = collectionsCache.get(cacheKey);
2264
- const [collections, setCollections] = React3.useState(cached?.collections ?? []);
2265
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
2266
- const [error, setError] = React3.useState(null);
2267
- React3.useEffect(() => {
2268
- if (previousLocationIdRef.current !== locationId) {
2269
- collectionsCache.clear();
2270
- collectionsInflight.clear();
2271
- previousLocationIdRef.current = locationId;
2272
- }
2273
- }, [locationId]);
2274
- const load = React3.useCallback(
2275
- async (force = false) => {
2276
- if (!enabled) {
2277
- setIsLoading(false);
2278
- return;
2279
- }
2280
- const nextRequestId = ++requestIdRef.current;
2281
- setError(null);
2282
- if (!force) {
2283
- const cacheEntry = collectionsCache.get(cacheKey);
2284
- if (cacheEntry) {
2285
- setCollections(cacheEntry.collections);
2286
- setIsLoading(false);
2287
- return;
2288
- }
2289
- }
2290
- setIsLoading(true);
2291
- try {
2292
- const existing = collectionsInflight.get(cacheKey);
2293
- const promise = existing ?? (async () => {
2294
- const result = await client.catalogue.getCollections();
2295
- if (!result.ok) {
2296
- throw result.error;
2297
- }
2298
- return result.value;
2299
- })();
2300
- if (!existing) {
2301
- collectionsInflight.set(cacheKey, promise);
2302
- promise.finally(() => {
2303
- collectionsInflight.delete(cacheKey);
2304
- }).catch(() => void 0);
2305
- }
2306
- const value = await promise;
2307
- collectionsCache.set(cacheKey, { collections: value });
2308
- if (nextRequestId === requestIdRef.current) {
2309
- setCollections(value);
2310
- setError(null);
2311
- }
2312
- } catch (loadError) {
2313
- if (nextRequestId === requestIdRef.current) {
2314
- setError(loadError);
2315
- }
2316
- } finally {
2317
- if (nextRequestId === requestIdRef.current) {
2318
- setIsLoading(false);
2319
- }
2320
- }
2321
- },
2322
- [cacheKey, client, enabled]
2323
- );
2324
- React3.useEffect(() => {
2325
- void load(false);
2326
- }, [load]);
2327
- const refetch = React3.useCallback(async () => {
2328
- collectionsCache.delete(cacheKey);
2329
- await load(true);
2330
- }, [cacheKey, load]);
2331
- return { collections, isLoading, error, refetch };
2332
- }
2333
- var collectionCache = /* @__PURE__ */ new Map();
2334
- var collectionInflight = /* @__PURE__ */ new Map();
2335
- function isLikelySlug2(value) {
2336
- return /^[a-z0-9-]+$/.test(value);
2337
- }
2338
- function buildCollectionCacheKey(client, locationId, idOrSlug) {
2339
- return JSON.stringify({
2340
- key: client.getPublicKey(),
2341
- location_id: locationId || "__none__",
2342
- collection: idOrSlug
2343
- });
2344
- }
2345
- function useCollection(idOrSlug, options = {}) {
2346
- const context = useOptionalCimplifyClient();
2347
- const client = options.client ?? context?.client;
2348
- if (!client) {
2349
- throw new Error("useCollection must be used within CimplifyProvider or passed { client }.");
2350
- }
2351
- const enabled = options.enabled ?? true;
2352
- const locationId = client.getLocationId();
2353
- const previousLocationIdRef = React3.useRef(locationId);
2354
- const requestIdRef = React3.useRef(0);
2355
- const normalizedIdOrSlug = React3.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
2356
- const cacheKey = React3.useMemo(
2357
- () => buildCollectionCacheKey(client, locationId, normalizedIdOrSlug),
2358
- [client, locationId, normalizedIdOrSlug]
2359
- );
2360
- const cached = collectionCache.get(cacheKey);
2361
- const [collection, setCollection] = React3.useState(cached?.collection ?? null);
2362
- const [products, setProducts] = React3.useState(cached?.products ?? []);
2363
- const [isLoading, setIsLoading] = React3.useState(
2364
- enabled && normalizedIdOrSlug.length > 0 && !cached
2365
- );
2366
- const [error, setError] = React3.useState(null);
2367
- React3.useEffect(() => {
2368
- if (previousLocationIdRef.current !== locationId) {
2369
- collectionCache.clear();
2370
- collectionInflight.clear();
2371
- previousLocationIdRef.current = locationId;
2372
- }
2373
- }, [locationId]);
2374
- const load = React3.useCallback(
2375
- async (force = false) => {
2376
- if (!enabled || normalizedIdOrSlug.length === 0) {
2377
- setCollection(null);
2378
- setProducts([]);
2379
- setIsLoading(false);
2380
- return;
2381
- }
2382
- const nextRequestId = ++requestIdRef.current;
2383
- setError(null);
2384
- if (!force) {
2385
- const cacheEntry = collectionCache.get(cacheKey);
2386
- if (cacheEntry) {
2387
- setCollection(cacheEntry.collection);
2388
- setProducts(cacheEntry.products);
2389
- setIsLoading(false);
2390
- return;
2391
- }
2392
- }
2393
- setIsLoading(true);
2394
- try {
2395
- const existing = collectionInflight.get(cacheKey);
2396
- const promise = existing ?? (async () => {
2397
- const collectionResult = isLikelySlug2(normalizedIdOrSlug) ? await client.catalogue.getCollectionBySlug(normalizedIdOrSlug) : await client.catalogue.getCollection(normalizedIdOrSlug);
2398
- if (!collectionResult.ok) {
2399
- throw collectionResult.error;
2400
- }
2401
- const productsResult = await client.catalogue.getCollectionProducts(
2402
- collectionResult.value.id
2403
- );
2404
- if (!productsResult.ok) {
2405
- throw productsResult.error;
2406
- }
2407
- return {
2408
- collection: collectionResult.value,
2409
- products: productsResult.value
2410
- };
2411
- })();
2412
- if (!existing) {
2413
- collectionInflight.set(cacheKey, promise);
2414
- promise.finally(() => {
2415
- collectionInflight.delete(cacheKey);
2416
- }).catch(() => void 0);
2417
- }
2418
- const value = await promise;
2419
- collectionCache.set(cacheKey, value);
2420
- if (nextRequestId === requestIdRef.current) {
2421
- setCollection(value.collection);
2422
- setProducts(value.products);
2423
- setError(null);
2424
- }
2425
- } catch (loadError) {
2426
- if (nextRequestId === requestIdRef.current) {
2427
- setError(loadError);
2428
- }
2429
- } finally {
2430
- if (nextRequestId === requestIdRef.current) {
2431
- setIsLoading(false);
2432
- }
2433
- }
2434
- },
2435
- [cacheKey, client, enabled, normalizedIdOrSlug]
2436
- );
2437
- React3.useEffect(() => {
2438
- void load(false);
2439
- }, [load]);
2440
- const refetch = React3.useCallback(async () => {
2441
- collectionCache.delete(cacheKey);
2442
- await load(true);
2443
- }, [cacheKey, load]);
2444
- return { collection, products, isLoading, error, refetch };
2445
- }
2446
- function useSearch(options = {}) {
2447
- const context = useOptionalCimplifyClient();
2448
- const client = options.client ?? context?.client;
2449
- if (!client) {
2450
- throw new Error("useSearch must be used within CimplifyProvider or passed { client }.");
2157
+ throw new Error("useSearch must be used within CimplifyProvider or passed { client }.");
2451
2158
  }
2452
2159
  const minLength = Math.max(0, options.minLength ?? 2);
2453
2160
  const debounceMs = Math.max(0, options.debounceMs ?? 300);
@@ -2618,11 +2325,11 @@ function useQuote(input, options = {}) {
2618
2325
  const normalized = normalizeInput(input, locationId);
2619
2326
  return normalized.product_id.length > 0 ? normalized : null;
2620
2327
  }, [inputSignature, locationId]);
2621
- const cacheKey = React3.useMemo(
2328
+ const cacheKey2 = React3.useMemo(
2622
2329
  () => buildQuoteCacheKey(client, locationId, inputSignature),
2623
2330
  [client, inputSignature, locationId]
2624
2331
  );
2625
- const cached = quoteCache.get(cacheKey);
2332
+ const cached = quoteCache.get(cacheKey2);
2626
2333
  const [quote, setQuote] = React3.useState(cached?.quote ?? null);
2627
2334
  const [isLoading, setIsLoading] = React3.useState(enabled && normalizedInput !== null && !cached);
2628
2335
  const [error, setError] = React3.useState(null);
@@ -2648,7 +2355,7 @@ function useQuote(input, options = {}) {
2648
2355
  const nextRequestId = ++requestIdRef.current;
2649
2356
  setError(null);
2650
2357
  if (!force) {
2651
- const cacheEntry = quoteCache.get(cacheKey);
2358
+ const cacheEntry = quoteCache.get(cacheKey2);
2652
2359
  if (cacheEntry) {
2653
2360
  setQuote(cacheEntry.quote);
2654
2361
  setMessages(cacheEntry.quote?.ui_messages ?? []);
@@ -2661,7 +2368,7 @@ function useQuote(input, options = {}) {
2661
2368
  setQuote(null);
2662
2369
  setMessages([]);
2663
2370
  try {
2664
- const existing = quoteInflight.get(cacheKey);
2371
+ const existing = quoteInflight.get(cacheKey2);
2665
2372
  const promise = existing ?? (async () => {
2666
2373
  const result = await client.catalogue.fetchQuote(normalizedInput);
2667
2374
  if (!result.ok) {
@@ -2670,13 +2377,13 @@ function useQuote(input, options = {}) {
2670
2377
  return result.value;
2671
2378
  })();
2672
2379
  if (!existing) {
2673
- quoteInflight.set(cacheKey, promise);
2380
+ quoteInflight.set(cacheKey2, promise);
2674
2381
  promise.finally(() => {
2675
- quoteInflight.delete(cacheKey);
2382
+ quoteInflight.delete(cacheKey2);
2676
2383
  }).catch(() => void 0);
2677
2384
  }
2678
2385
  const value = await promise;
2679
- quoteCache.set(cacheKey, { quote: value });
2386
+ quoteCache.set(cacheKey2, { quote: value });
2680
2387
  if (nextRequestId === requestIdRef.current) {
2681
2388
  setQuote(value);
2682
2389
  setMessages(value.ui_messages ?? []);
@@ -2693,13 +2400,13 @@ function useQuote(input, options = {}) {
2693
2400
  }
2694
2401
  }
2695
2402
  },
2696
- [cacheKey, client, enabled, normalizedInput]
2403
+ [cacheKey2, client, enabled, normalizedInput]
2697
2404
  );
2698
2405
  React3.useEffect(() => {
2699
2406
  if (debounceTimerRef.current) {
2700
2407
  clearTimeout(debounceTimerRef.current);
2701
2408
  }
2702
- const hasCached = quoteCache.has(cacheKey);
2409
+ const hasCached = quoteCache.has(cacheKey2);
2703
2410
  if (hasCached || !enabled || !normalizedInput) {
2704
2411
  void load(false);
2705
2412
  } else {
@@ -2713,7 +2420,7 @@ function useQuote(input, options = {}) {
2713
2420
  debounceTimerRef.current = null;
2714
2421
  }
2715
2422
  };
2716
- }, [load, cacheKey, enabled, normalizedInput]);
2423
+ }, [load, cacheKey2, enabled, normalizedInput]);
2717
2424
  const refresh = React3.useCallback(async () => {
2718
2425
  if (!enabled || !normalizedInput) {
2719
2426
  return;
@@ -2734,7 +2441,7 @@ function useQuote(input, options = {}) {
2734
2441
  throw result.error;
2735
2442
  }
2736
2443
  const refreshed = result.value.quote;
2737
- quoteCache.set(cacheKey, { quote: refreshed });
2444
+ quoteCache.set(cacheKey2, { quote: refreshed });
2738
2445
  if (nextRequestId === requestIdRef.current) {
2739
2446
  setQuote(refreshed);
2740
2447
  setMessages(refreshed.ui_messages ?? []);
@@ -2750,7 +2457,7 @@ function useQuote(input, options = {}) {
2750
2457
  setIsLoading(false);
2751
2458
  }
2752
2459
  }
2753
- }, [cacheKey, client, enabled, load, normalizedInput, quote]);
2460
+ }, [cacheKey2, client, enabled, load, normalizedInput, quote]);
2754
2461
  React3.useEffect(() => {
2755
2462
  if (!Number.isFinite(quoteExpiryTimestamp)) {
2756
2463
  setIsExpired(false);
@@ -2782,1402 +2489,391 @@ function useQuote(input, options = {}) {
2782
2489
  }, [autoRefresh, enabled, quoteExpiryTimestamp, refresh, refreshBeforeExpiryMs]);
2783
2490
  return { quote, isLoading, error, refresh, isExpired, messages };
2784
2491
  }
2785
- var taxonomiesCache = /* @__PURE__ */ new Map();
2786
- var taxonomiesInflight = /* @__PURE__ */ new Map();
2787
- function buildTaxonomiesCacheKey(client, parentId) {
2788
- return JSON.stringify({
2789
- key: client.getPublicKey(),
2790
- parent_id: parentId || "__root__"
2791
- });
2792
- }
2492
+
2493
+ // src/react/hooks/use-taxonomies.ts
2494
+ var taxonomiesQuery = createCachedQuery({
2495
+ name: "useTaxonomies",
2496
+ key: (client, options) => cacheKey(client.getPublicKey(), options.parentId ?? "__root__"),
2497
+ fetch: async (client, options) => {
2498
+ const result = await client.catalogue.getTaxonomies(options.parentId);
2499
+ if (!result.ok) throw result.error;
2500
+ return result.value;
2501
+ }
2502
+ });
2793
2503
  function useTaxonomies(options = {}) {
2504
+ const { data, isLoading, error, refetch } = taxonomiesQuery(options);
2505
+ return { taxonomies: data ?? [], isLoading, error, refetch };
2506
+ }
2507
+
2508
+ // src/react/hooks/use-taxonomy.ts
2509
+ var taxonomyQuery = createCachedQuery({
2510
+ name: "useTaxonomy",
2511
+ key: (client, options) => cacheKey(client.getPublicKey(), options.id),
2512
+ fetch: async (client, options) => {
2513
+ const result = await client.catalogue.getTaxonomy(options.id);
2514
+ if (!result.ok) throw result.error;
2515
+ client.activity.trackCategoryView(result.value.id, {
2516
+ categoryName: result.value.name
2517
+ });
2518
+ return result.value;
2519
+ }
2520
+ });
2521
+ function useTaxonomy(id, options = {}) {
2522
+ const { data, isLoading, error, refetch } = taxonomyQuery({ ...options, id });
2523
+ return { taxonomy: data, isLoading, error, refetch };
2524
+ }
2525
+
2526
+ // src/react/hooks/use-taxonomy-path.ts
2527
+ var taxonomyPathQuery = createCachedQuery({
2528
+ name: "useTaxonomyPath",
2529
+ key: (client, options) => cacheKey(client.getPublicKey(), options.id),
2530
+ fetch: async (client, options) => {
2531
+ const result = await client.catalogue.getTaxonomyPath(options.id);
2532
+ if (!result.ok) throw result.error;
2533
+ return result.value;
2534
+ }
2535
+ });
2536
+ function useTaxonomyPath(id, options = {}) {
2537
+ const { data, isLoading, error, refetch } = taxonomyPathQuery({ ...options, id });
2538
+ return { path: data ?? [], isLoading, error, refetch };
2539
+ }
2540
+
2541
+ // src/react/hooks/use-product-schedules.ts
2542
+ var productSchedulesQuery = createCachedQuery({
2543
+ name: "useProductSchedules",
2544
+ key: (client, options) => cacheKey(client.getPublicKey(), options.productId),
2545
+ fetch: async (client, options) => {
2546
+ const result = await client.catalogue.getProductSchedules(options.productId);
2547
+ if (!result.ok) throw result.error;
2548
+ return result.value;
2549
+ }
2550
+ });
2551
+ function useProductSchedules(productId, options = {}) {
2552
+ const { data, isLoading, error, refetch } = productSchedulesQuery({ ...options, productId });
2553
+ return { schedules: data ?? [], isLoading, error, refetch };
2554
+ }
2555
+
2556
+ // src/react/hooks/use-product-availability.ts
2557
+ var productAvailabilityQuery = createCachedQuery({
2558
+ name: "useProductAvailability",
2559
+ locationSensitive: true,
2560
+ key: (client, options) => {
2561
+ const locationId = options.locationId ?? client.getLocationId();
2562
+ return cacheKey(client.getPublicKey(), options.productId, locationId);
2563
+ },
2564
+ fetch: async (client, options) => {
2565
+ const locationId = options.locationId ?? client.getLocationId();
2566
+ if (!locationId) return null;
2567
+ const result = await client.catalogue.checkProductAvailableNow(options.productId, locationId);
2568
+ if (!result.ok) throw result.error;
2569
+ return result.value;
2570
+ }
2571
+ });
2572
+ function useProductAvailability(productId, options = {}) {
2573
+ const { data, isLoading, error, refetch } = productAvailabilityQuery({ ...options, productId });
2574
+ return {
2575
+ isAvailable: data?.is_available ?? null,
2576
+ schedulesToday: data?.schedules_today ?? [],
2577
+ isLoading,
2578
+ error,
2579
+ refetch
2580
+ };
2581
+ }
2582
+
2583
+ // src/react/hooks/use-deals.ts
2584
+ function resolveLocationId(client, options) {
2585
+ return options.locationId ?? client.getLocationId() ?? void 0;
2586
+ }
2587
+ var dealsQuery = createCachedQuery({
2588
+ name: "useDeals",
2589
+ locationSensitive: true,
2590
+ key: (client, options) => cacheKey(client.getPublicKey(), resolveLocationId(client, options)),
2591
+ fetch: async (client, options) => {
2592
+ const result = await client.catalogue.getDeals(resolveLocationId(client, options));
2593
+ if (!result.ok) throw result.error;
2594
+ return result.value;
2595
+ }
2596
+ });
2597
+ function useDeals(options = {}) {
2598
+ const { data, isLoading, error, refetch } = dealsQuery(options);
2599
+ return { deals: data ?? [], isLoading, error, refetch };
2600
+ }
2601
+
2602
+ // src/react/hooks/use-products-on-sale.ts
2603
+ var productsOnSaleQuery = createCachedQuery({
2604
+ name: "useProductsOnSale",
2605
+ key: (client) => client.getPublicKey() || "__demo__",
2606
+ fetch: async (client) => {
2607
+ const result = await client.catalogue.getProductsOnSale();
2608
+ if (!result.ok) throw result.error;
2609
+ return result.value;
2610
+ }
2611
+ });
2612
+ function useProductsOnSale(options = {}) {
2613
+ const { data, isLoading, error, refetch } = productsOnSaleQuery(options);
2614
+ return { products: data ?? [], isLoading, error, refetch };
2615
+ }
2616
+
2617
+ // src/react/hooks/use-product-deals.ts
2618
+ var productDealsQuery = createCachedQuery({
2619
+ name: "useProductDeals",
2620
+ key: (client, options) => cacheKey(client.getPublicKey(), options.productId),
2621
+ fetch: async (client, options) => {
2622
+ const result = await client.catalogue.getProductDeals(options.productId);
2623
+ if (!result.ok) throw result.error;
2624
+ return result.value;
2625
+ }
2626
+ });
2627
+ function useProductDeals(productId, options = {}) {
2628
+ const { data, isLoading, error, refetch } = productDealsQuery({ ...options, productId });
2629
+ return { deals: data ?? [], isLoading, error, refetch };
2630
+ }
2631
+ function useValidateDiscount(options = {}) {
2794
2632
  const context = useOptionalCimplifyClient();
2795
2633
  const client = options.client ?? context?.client;
2796
2634
  if (!client) {
2797
- throw new Error("useTaxonomies must be used within CimplifyProvider or passed { client }.");
2635
+ throw new Error("useValidateDiscount must be used within CimplifyProvider or passed { client }.");
2798
2636
  }
2799
- const enabled = options.enabled ?? true;
2800
- const cacheKey = React3.useMemo(
2801
- () => buildTaxonomiesCacheKey(client, options.parentId),
2802
- [client, options.parentId]
2803
- );
2804
- const cached = taxonomiesCache.get(cacheKey);
2805
- const [taxonomies, setTaxonomies] = React3.useState(cached ?? []);
2806
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
2637
+ const [isValidating, setIsValidating] = React3.useState(false);
2807
2638
  const [error, setError] = React3.useState(null);
2808
- const parentId = options.parentId;
2809
- const load = React3.useCallback(
2810
- async (force = false) => {
2811
- if (!enabled) {
2812
- setIsLoading(false);
2813
- return;
2814
- }
2639
+ const validate = React3.useCallback(
2640
+ async (code, orderSubtotal, locationId) => {
2815
2641
  setError(null);
2816
- if (!force) {
2817
- const cachedTaxonomies = taxonomiesCache.get(cacheKey);
2818
- if (cachedTaxonomies) {
2819
- setTaxonomies(cachedTaxonomies);
2820
- setIsLoading(false);
2821
- return;
2822
- }
2823
- }
2824
- setIsLoading(true);
2642
+ setIsValidating(true);
2825
2643
  try {
2826
- const existing = taxonomiesInflight.get(cacheKey);
2827
- const promise = existing ?? (async () => {
2828
- const result = await client.catalogue.getTaxonomies(parentId);
2829
- if (!result.ok) {
2830
- throw result.error;
2831
- }
2832
- return result.value;
2833
- })();
2834
- if (!existing) {
2835
- taxonomiesInflight.set(
2836
- cacheKey,
2837
- promise.finally(() => {
2838
- taxonomiesInflight.delete(cacheKey);
2839
- })
2840
- );
2644
+ const result = await client.catalogue.validateDiscountCode(code, orderSubtotal, locationId);
2645
+ if (!result.ok) {
2646
+ setError(result.error);
2647
+ return null;
2841
2648
  }
2842
- const value = await promise;
2843
- taxonomiesCache.set(cacheKey, value);
2844
- setTaxonomies(value);
2845
- } catch (loadError) {
2846
- setError(loadError);
2649
+ return result.value;
2650
+ } catch (validateError) {
2651
+ setError(validateError);
2652
+ return null;
2847
2653
  } finally {
2848
- setIsLoading(false);
2654
+ setIsValidating(false);
2849
2655
  }
2850
2656
  },
2851
- [cacheKey, client, enabled, parentId]
2657
+ [client]
2852
2658
  );
2853
- React3.useEffect(() => {
2854
- void load(false);
2855
- }, [load]);
2856
- const refetch = React3.useCallback(async () => {
2857
- taxonomiesCache.delete(cacheKey);
2858
- await load(true);
2859
- }, [cacheKey, load]);
2860
- return { taxonomies, isLoading, error, refetch };
2861
- }
2862
- var taxonomyCache = /* @__PURE__ */ new Map();
2863
- var taxonomyInflight = /* @__PURE__ */ new Map();
2864
- function buildTaxonomyCacheKey(client, id) {
2865
- return JSON.stringify({
2866
- key: client.getPublicKey(),
2867
- id
2868
- });
2659
+ return { validate, isValidating, error };
2869
2660
  }
2870
- function useTaxonomy(id, options = {}) {
2871
- const context = useOptionalCimplifyClient();
2872
- const client = options.client ?? context?.client;
2873
- if (!client) {
2874
- throw new Error("useTaxonomy must be used within CimplifyProvider or passed { client }.");
2661
+
2662
+ // src/react/hooks/use-bundles.ts
2663
+ var bundlesQuery = createCachedQuery({
2664
+ name: "useBundles",
2665
+ locationSensitive: true,
2666
+ key: (client) => cacheKey(client.getPublicKey(), client.getLocationId()),
2667
+ fetch: async (client) => {
2668
+ const result = await client.catalogue.getBundles();
2669
+ if (!result.ok) throw result.error;
2670
+ return result.value;
2875
2671
  }
2876
- const enabled = options.enabled ?? true;
2877
- const cacheKey = React3.useMemo(() => buildTaxonomyCacheKey(client, id), [client, id]);
2878
- const cached = taxonomyCache.get(cacheKey);
2879
- const [taxonomy, setTaxonomy] = React3.useState(cached ?? null);
2880
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
2881
- const [error, setError] = React3.useState(null);
2882
- const trackedTaxonomyRef = React3.useRef(null);
2883
- const load = React3.useCallback(
2884
- async (force = false) => {
2885
- if (!enabled) {
2886
- setIsLoading(false);
2887
- return;
2888
- }
2889
- setError(null);
2890
- if (!force) {
2891
- const cachedTaxonomy = taxonomyCache.get(cacheKey);
2892
- if (cachedTaxonomy) {
2893
- setTaxonomy(cachedTaxonomy);
2894
- setIsLoading(false);
2895
- return;
2896
- }
2897
- }
2898
- setIsLoading(true);
2899
- try {
2900
- const existing = taxonomyInflight.get(cacheKey);
2901
- const promise = existing ?? (async () => {
2902
- const result = await client.catalogue.getTaxonomy(id);
2903
- if (!result.ok) {
2904
- throw result.error;
2905
- }
2906
- return result.value;
2907
- })();
2908
- if (!existing) {
2909
- taxonomyInflight.set(
2910
- cacheKey,
2911
- promise.finally(() => {
2912
- taxonomyInflight.delete(cacheKey);
2913
- })
2914
- );
2915
- }
2916
- const value = await promise;
2917
- taxonomyCache.set(cacheKey, value);
2918
- setTaxonomy(value);
2919
- if (value && trackedTaxonomyRef.current !== value.id) {
2920
- trackedTaxonomyRef.current = value.id;
2921
- client.activity.trackCategoryView(value.id, {
2922
- categoryName: value.name
2923
- });
2924
- }
2925
- } catch (loadError) {
2926
- setError(loadError);
2927
- } finally {
2928
- setIsLoading(false);
2929
- }
2930
- },
2931
- [cacheKey, client, enabled, id]
2932
- );
2933
- React3.useEffect(() => {
2934
- void load(false);
2935
- }, [load]);
2936
- const refetch = React3.useCallback(async () => {
2937
- taxonomyCache.delete(cacheKey);
2938
- await load(true);
2939
- }, [cacheKey, load]);
2940
- return { taxonomy, isLoading, error, refetch };
2941
- }
2942
- var taxonomyPathCache = /* @__PURE__ */ new Map();
2943
- var taxonomyPathInflight = /* @__PURE__ */ new Map();
2944
- function buildTaxonomyPathCacheKey(client, id) {
2945
- return JSON.stringify({
2946
- key: client.getPublicKey(),
2947
- id
2948
- });
2949
- }
2950
- function useTaxonomyPath(id, options = {}) {
2951
- const context = useOptionalCimplifyClient();
2952
- const client = options.client ?? context?.client;
2953
- if (!client) {
2954
- throw new Error("useTaxonomyPath must be used within CimplifyProvider or passed { client }.");
2955
- }
2956
- const enabled = options.enabled ?? true;
2957
- const cacheKey = React3.useMemo(() => buildTaxonomyPathCacheKey(client, id), [client, id]);
2958
- const cached = taxonomyPathCache.get(cacheKey);
2959
- const [path, setPath] = React3.useState(cached ?? []);
2960
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
2961
- const [error, setError] = React3.useState(null);
2962
- const load = React3.useCallback(
2963
- async (force = false) => {
2964
- if (!enabled) {
2965
- setIsLoading(false);
2966
- return;
2967
- }
2968
- setError(null);
2969
- if (!force) {
2970
- const cachedPath = taxonomyPathCache.get(cacheKey);
2971
- if (cachedPath) {
2972
- setPath(cachedPath);
2973
- setIsLoading(false);
2974
- return;
2975
- }
2976
- }
2977
- setIsLoading(true);
2978
- try {
2979
- const existing = taxonomyPathInflight.get(cacheKey);
2980
- const promise = existing ?? (async () => {
2981
- const result = await client.catalogue.getTaxonomyPath(id);
2982
- if (!result.ok) {
2983
- throw result.error;
2984
- }
2985
- return result.value;
2986
- })();
2987
- if (!existing) {
2988
- taxonomyPathInflight.set(
2989
- cacheKey,
2990
- promise.finally(() => {
2991
- taxonomyPathInflight.delete(cacheKey);
2992
- })
2993
- );
2994
- }
2995
- const value = await promise;
2996
- taxonomyPathCache.set(cacheKey, value);
2997
- setPath(value);
2998
- } catch (loadError) {
2999
- setError(loadError);
3000
- } finally {
3001
- setIsLoading(false);
3002
- }
3003
- },
3004
- [cacheKey, client, enabled, id]
3005
- );
3006
- React3.useEffect(() => {
3007
- void load(false);
3008
- }, [load]);
3009
- const refetch = React3.useCallback(async () => {
3010
- taxonomyPathCache.delete(cacheKey);
3011
- await load(true);
3012
- }, [cacheKey, load]);
3013
- return { path, isLoading, error, refetch };
3014
- }
3015
- var schedulesCache = /* @__PURE__ */ new Map();
3016
- var schedulesInflight = /* @__PURE__ */ new Map();
3017
- function buildSchedulesCacheKey(client, productId) {
3018
- return JSON.stringify({
3019
- key: client.getPublicKey(),
3020
- product_id: productId
3021
- });
3022
- }
3023
- function useProductSchedules(productId, options = {}) {
3024
- const context = useOptionalCimplifyClient();
3025
- const client = options.client ?? context?.client;
3026
- if (!client) {
3027
- throw new Error("useProductSchedules must be used within CimplifyProvider or passed { client }.");
3028
- }
3029
- const enabled = options.enabled ?? true;
3030
- const cacheKey = React3.useMemo(() => buildSchedulesCacheKey(client, productId), [client, productId]);
3031
- const cached = schedulesCache.get(cacheKey);
3032
- const [schedules, setSchedules] = React3.useState(cached ?? []);
3033
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3034
- const [error, setError] = React3.useState(null);
3035
- const load = React3.useCallback(
3036
- async (force = false) => {
3037
- if (!enabled) {
3038
- setIsLoading(false);
3039
- return;
3040
- }
3041
- setError(null);
3042
- if (!force) {
3043
- const cachedSchedules = schedulesCache.get(cacheKey);
3044
- if (cachedSchedules) {
3045
- setSchedules(cachedSchedules);
3046
- setIsLoading(false);
3047
- return;
3048
- }
3049
- }
3050
- setIsLoading(true);
3051
- try {
3052
- const existing = schedulesInflight.get(cacheKey);
3053
- const promise = existing ?? (async () => {
3054
- const result = await client.catalogue.getProductSchedules(productId);
3055
- if (!result.ok) {
3056
- throw result.error;
3057
- }
3058
- return result.value;
3059
- })();
3060
- if (!existing) {
3061
- schedulesInflight.set(
3062
- cacheKey,
3063
- promise.finally(() => {
3064
- schedulesInflight.delete(cacheKey);
3065
- })
3066
- );
3067
- }
3068
- const value = await promise;
3069
- schedulesCache.set(cacheKey, value);
3070
- setSchedules(value);
3071
- } catch (loadError) {
3072
- setError(loadError);
3073
- } finally {
3074
- setIsLoading(false);
3075
- }
3076
- },
3077
- [cacheKey, client, enabled, productId]
3078
- );
3079
- React3.useEffect(() => {
3080
- void load(false);
3081
- }, [load]);
3082
- const refetch = React3.useCallback(async () => {
3083
- schedulesCache.delete(cacheKey);
3084
- await load(true);
3085
- }, [cacheKey, load]);
3086
- return { schedules, isLoading, error, refetch };
3087
- }
3088
- var availabilityCache = /* @__PURE__ */ new Map();
3089
- var availabilityInflight = /* @__PURE__ */ new Map();
3090
- function buildAvailabilityCacheKey(client, productId, locationId) {
3091
- return JSON.stringify({
3092
- key: client.getPublicKey(),
3093
- product_id: productId,
3094
- location_id: locationId
3095
- });
3096
- }
3097
- function useProductAvailability(productId, options = {}) {
3098
- const context = useOptionalCimplifyClient();
3099
- const client = options.client ?? context?.client;
3100
- if (!client) {
3101
- throw new Error("useProductAvailability must be used within CimplifyProvider or passed { client }.");
3102
- }
3103
- const enabled = options.enabled ?? true;
3104
- const locationId = options.locationId ?? client.getLocationId();
3105
- const previousLocationIdRef = React3.useRef(locationId);
3106
- const cacheKey = React3.useMemo(
3107
- () => locationId ? buildAvailabilityCacheKey(client, productId, locationId) : null,
3108
- [client, productId, locationId]
3109
- );
3110
- const cached = cacheKey ? availabilityCache.get(cacheKey) : void 0;
3111
- const [isAvailable, setIsAvailable] = React3.useState(cached?.is_available ?? null);
3112
- const [schedulesToday, setSchedulesToday] = React3.useState(
3113
- cached?.schedules_today ?? []
3114
- );
3115
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached && !!locationId);
3116
- const [error, setError] = React3.useState(null);
3117
- React3.useEffect(() => {
3118
- if (previousLocationIdRef.current !== locationId) {
3119
- availabilityCache.clear();
3120
- availabilityInflight.clear();
3121
- previousLocationIdRef.current = locationId;
3122
- }
3123
- }, [locationId]);
3124
- const load = React3.useCallback(
3125
- async (force = false) => {
3126
- if (!enabled || !locationId || !cacheKey) {
3127
- setIsLoading(false);
3128
- return;
3129
- }
3130
- setError(null);
3131
- if (!force) {
3132
- const cachedAvailability = availabilityCache.get(cacheKey);
3133
- if (cachedAvailability) {
3134
- setIsAvailable(cachedAvailability.is_available);
3135
- setSchedulesToday(cachedAvailability.schedules_today);
3136
- setIsLoading(false);
3137
- return;
3138
- }
3139
- }
3140
- setIsLoading(true);
3141
- try {
3142
- const existing = availabilityInflight.get(cacheKey);
3143
- const promise = existing ?? (async () => {
3144
- const result = await client.catalogue.checkProductAvailableNow(productId, locationId);
3145
- if (!result.ok) {
3146
- throw result.error;
3147
- }
3148
- return result.value;
3149
- })();
3150
- if (!existing) {
3151
- availabilityInflight.set(
3152
- cacheKey,
3153
- promise.finally(() => {
3154
- availabilityInflight.delete(cacheKey);
3155
- })
3156
- );
3157
- }
3158
- const value = await promise;
3159
- availabilityCache.set(cacheKey, value);
3160
- setIsAvailable(value.is_available);
3161
- setSchedulesToday(value.schedules_today);
3162
- } catch (loadError) {
3163
- setError(loadError);
3164
- } finally {
3165
- setIsLoading(false);
3166
- }
3167
- },
3168
- [cacheKey, client, enabled, locationId, productId]
3169
- );
3170
- React3.useEffect(() => {
3171
- void load(false);
3172
- }, [load]);
3173
- const refetch = React3.useCallback(async () => {
3174
- if (cacheKey) {
3175
- availabilityCache.delete(cacheKey);
3176
- }
3177
- await load(true);
3178
- }, [cacheKey, load]);
3179
- return { isAvailable, schedulesToday, isLoading, error, refetch };
3180
- }
3181
- var dealsCache = /* @__PURE__ */ new Map();
3182
- var dealsInflight = /* @__PURE__ */ new Map();
3183
- function buildDealsCacheKey(client, locationId) {
3184
- return JSON.stringify({ key: client.getPublicKey(), location_id: locationId });
3185
- }
3186
- function useDeals(options = {}) {
3187
- const context = useOptionalCimplifyClient();
3188
- const client = options.client ?? context?.client;
3189
- if (!client) {
3190
- throw new Error("useDeals must be used within CimplifyProvider or passed { client }.");
3191
- }
3192
- const enabled = options.enabled ?? true;
3193
- const locationId = options.locationId ?? client.getLocationId() ?? void 0;
3194
- const previousLocationIdRef = React3.useRef(locationId);
3195
- const cacheKey = React3.useMemo(() => buildDealsCacheKey(client, locationId), [client, locationId]);
3196
- const cached = dealsCache.get(cacheKey);
3197
- const [deals, setDeals] = React3.useState(cached ?? []);
3198
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3199
- const [error, setError] = React3.useState(null);
3200
- React3.useEffect(() => {
3201
- if (previousLocationIdRef.current !== locationId) {
3202
- dealsCache.clear();
3203
- dealsInflight.clear();
3204
- previousLocationIdRef.current = locationId;
3205
- }
3206
- }, [locationId]);
3207
- const load = React3.useCallback(
3208
- async (force = false) => {
3209
- if (!enabled) {
3210
- setIsLoading(false);
3211
- return;
3212
- }
3213
- setError(null);
3214
- if (!force) {
3215
- const cachedDeals = dealsCache.get(cacheKey);
3216
- if (cachedDeals) {
3217
- setDeals(cachedDeals);
3218
- setIsLoading(false);
3219
- return;
3220
- }
3221
- }
3222
- setIsLoading(true);
3223
- try {
3224
- const existing = dealsInflight.get(cacheKey);
3225
- const promise = existing ?? (async () => {
3226
- const result = await client.catalogue.getDeals(locationId);
3227
- if (!result.ok) {
3228
- throw result.error;
3229
- }
3230
- return result.value;
3231
- })();
3232
- if (!existing) {
3233
- dealsInflight.set(
3234
- cacheKey,
3235
- promise.finally(() => {
3236
- dealsInflight.delete(cacheKey);
3237
- })
3238
- );
3239
- }
3240
- const value = await promise;
3241
- dealsCache.set(cacheKey, value);
3242
- setDeals(value);
3243
- } catch (loadError) {
3244
- setError(loadError);
3245
- } finally {
3246
- setIsLoading(false);
3247
- }
3248
- },
3249
- [cacheKey, client, enabled, locationId]
3250
- );
3251
- React3.useEffect(() => {
3252
- void load(false);
3253
- }, [load]);
3254
- const refetch = React3.useCallback(async () => {
3255
- dealsCache.delete(cacheKey);
3256
- await load(true);
3257
- }, [cacheKey, load]);
3258
- return { deals, isLoading, error, refetch };
3259
- }
3260
- var onSaleCache = /* @__PURE__ */ new Map();
3261
- var onSaleInflight = /* @__PURE__ */ new Map();
3262
- function buildOnSaleCacheKey(client) {
3263
- return client.getPublicKey() || "__demo__";
3264
- }
3265
- function useProductsOnSale(options = {}) {
3266
- const context = useOptionalCimplifyClient();
3267
- const client = options.client ?? context?.client;
3268
- if (!client) {
3269
- throw new Error("useProductsOnSale must be used within CimplifyProvider or passed { client }.");
3270
- }
3271
- const enabled = options.enabled ?? true;
3272
- const cacheKey = React3.useMemo(() => buildOnSaleCacheKey(client), [client]);
3273
- const cached = onSaleCache.get(cacheKey);
3274
- const [products, setProducts] = React3.useState(cached ?? []);
3275
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3276
- const [error, setError] = React3.useState(null);
3277
- const load = React3.useCallback(
3278
- async (force = false) => {
3279
- if (!enabled) {
3280
- setIsLoading(false);
3281
- return;
3282
- }
3283
- setError(null);
3284
- if (!force) {
3285
- const cachedProducts = onSaleCache.get(cacheKey);
3286
- if (cachedProducts) {
3287
- setProducts(cachedProducts);
3288
- setIsLoading(false);
3289
- return;
3290
- }
3291
- }
3292
- setIsLoading(true);
3293
- try {
3294
- const existing = onSaleInflight.get(cacheKey);
3295
- const promise = existing ?? (async () => {
3296
- const result = await client.catalogue.getProductsOnSale();
3297
- if (!result.ok) {
3298
- throw result.error;
3299
- }
3300
- return result.value;
3301
- })();
3302
- if (!existing) {
3303
- onSaleInflight.set(
3304
- cacheKey,
3305
- promise.finally(() => {
3306
- onSaleInflight.delete(cacheKey);
3307
- })
3308
- );
3309
- }
3310
- const value = await promise;
3311
- onSaleCache.set(cacheKey, value);
3312
- setProducts(value);
3313
- } catch (loadError) {
3314
- setError(loadError);
3315
- } finally {
3316
- setIsLoading(false);
3317
- }
3318
- },
3319
- [cacheKey, client, enabled]
3320
- );
3321
- React3.useEffect(() => {
3322
- void load(false);
3323
- }, [load]);
3324
- const refetch = React3.useCallback(async () => {
3325
- onSaleCache.delete(cacheKey);
3326
- await load(true);
3327
- }, [cacheKey, load]);
3328
- return { products, isLoading, error, refetch };
3329
- }
3330
- var productDealsCache = /* @__PURE__ */ new Map();
3331
- var productDealsInflight = /* @__PURE__ */ new Map();
3332
- function buildProductDealsCacheKey(client, productId) {
3333
- return JSON.stringify({ key: client.getPublicKey(), product_id: productId });
3334
- }
3335
- function useProductDeals(productId, options = {}) {
3336
- const context = useOptionalCimplifyClient();
3337
- const client = options.client ?? context?.client;
3338
- if (!client) {
3339
- throw new Error("useProductDeals must be used within CimplifyProvider or passed { client }.");
3340
- }
3341
- const enabled = options.enabled ?? true;
3342
- const cacheKey = React3.useMemo(
3343
- () => buildProductDealsCacheKey(client, productId),
3344
- [client, productId]
3345
- );
3346
- const cached = productDealsCache.get(cacheKey);
3347
- const [deals, setDeals] = React3.useState(cached ?? []);
3348
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3349
- const [error, setError] = React3.useState(null);
3350
- const load = React3.useCallback(
3351
- async (force = false) => {
3352
- if (!enabled) {
3353
- setIsLoading(false);
3354
- return;
3355
- }
3356
- setError(null);
3357
- if (!force) {
3358
- const cachedDeals = productDealsCache.get(cacheKey);
3359
- if (cachedDeals) {
3360
- setDeals(cachedDeals);
3361
- setIsLoading(false);
3362
- return;
3363
- }
3364
- }
3365
- setIsLoading(true);
3366
- try {
3367
- const existing = productDealsInflight.get(cacheKey);
3368
- const promise = existing ?? (async () => {
3369
- const result = await client.catalogue.getProductDeals(productId);
3370
- if (!result.ok) {
3371
- throw result.error;
3372
- }
3373
- return result.value;
3374
- })();
3375
- if (!existing) {
3376
- productDealsInflight.set(
3377
- cacheKey,
3378
- promise.finally(() => {
3379
- productDealsInflight.delete(cacheKey);
3380
- })
3381
- );
3382
- }
3383
- const value = await promise;
3384
- productDealsCache.set(cacheKey, value);
3385
- setDeals(value);
3386
- } catch (loadError) {
3387
- setError(loadError);
3388
- } finally {
3389
- setIsLoading(false);
3390
- }
3391
- },
3392
- [cacheKey, client, enabled, productId]
3393
- );
3394
- React3.useEffect(() => {
3395
- void load(false);
3396
- }, [load]);
3397
- const refetch = React3.useCallback(async () => {
3398
- productDealsCache.delete(cacheKey);
3399
- await load(true);
3400
- }, [cacheKey, load]);
3401
- return { deals, isLoading, error, refetch };
3402
- }
3403
- function useValidateDiscount(options = {}) {
3404
- const context = useOptionalCimplifyClient();
3405
- const client = options.client ?? context?.client;
3406
- if (!client) {
3407
- throw new Error("useValidateDiscount must be used within CimplifyProvider or passed { client }.");
3408
- }
3409
- const [isValidating, setIsValidating] = React3.useState(false);
3410
- const [error, setError] = React3.useState(null);
3411
- const validate = React3.useCallback(
3412
- async (code, orderSubtotal, locationId) => {
3413
- setError(null);
3414
- setIsValidating(true);
3415
- try {
3416
- const result = await client.catalogue.validateDiscountCode(code, orderSubtotal, locationId);
3417
- if (!result.ok) {
3418
- setError(result.error);
3419
- return null;
3420
- }
3421
- return result.value;
3422
- } catch (validateError) {
3423
- setError(validateError);
3424
- return null;
3425
- } finally {
3426
- setIsValidating(false);
3427
- }
3428
- },
3429
- [client]
3430
- );
3431
- return { validate, isValidating, error };
3432
- }
3433
- var bundlesCache = /* @__PURE__ */ new Map();
3434
- var bundlesInflight = /* @__PURE__ */ new Map();
3435
- function buildBundlesCacheKey(client, locationId) {
3436
- return JSON.stringify({
3437
- key: client.getPublicKey(),
3438
- location_id: locationId || "__none__"
3439
- });
3440
- }
3441
- function useBundles(options = {}) {
3442
- const context = useOptionalCimplifyClient();
3443
- const client = options.client ?? context?.client;
3444
- if (!client) {
3445
- throw new Error("useBundles must be used within CimplifyProvider or passed { client }.");
3446
- }
3447
- const enabled = options.enabled ?? true;
3448
- const locationId = client.getLocationId();
3449
- const previousLocationIdRef = React3.useRef(locationId);
3450
- const requestIdRef = React3.useRef(0);
3451
- const cacheKey = React3.useMemo(
3452
- () => buildBundlesCacheKey(client, locationId),
3453
- [client, locationId]
3454
- );
3455
- const cached = bundlesCache.get(cacheKey);
3456
- const [bundles, setBundles] = React3.useState(cached?.bundles ?? []);
3457
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3458
- const [error, setError] = React3.useState(null);
3459
- React3.useEffect(() => {
3460
- if (previousLocationIdRef.current !== locationId) {
3461
- bundlesCache.clear();
3462
- bundlesInflight.clear();
3463
- previousLocationIdRef.current = locationId;
3464
- }
3465
- }, [locationId]);
3466
- const load = React3.useCallback(
3467
- async (force = false) => {
3468
- if (!enabled) {
3469
- setIsLoading(false);
3470
- return;
3471
- }
3472
- const nextRequestId = ++requestIdRef.current;
3473
- setError(null);
3474
- if (!force) {
3475
- const cacheEntry = bundlesCache.get(cacheKey);
3476
- if (cacheEntry) {
3477
- setBundles(cacheEntry.bundles);
3478
- setIsLoading(false);
3479
- return;
3480
- }
3481
- }
3482
- setIsLoading(true);
3483
- try {
3484
- const existing = bundlesInflight.get(cacheKey);
3485
- const promise = existing ?? (async () => {
3486
- const result = await client.catalogue.getBundles();
3487
- if (!result.ok) {
3488
- throw result.error;
3489
- }
3490
- return result.value;
3491
- })();
3492
- if (!existing) {
3493
- bundlesInflight.set(cacheKey, promise);
3494
- promise.finally(() => {
3495
- bundlesInflight.delete(cacheKey);
3496
- }).catch(() => void 0);
3497
- }
3498
- const value = await promise;
3499
- bundlesCache.set(cacheKey, { bundles: value });
3500
- if (nextRequestId === requestIdRef.current) {
3501
- setBundles(value);
3502
- setError(null);
3503
- }
3504
- } catch (loadError) {
3505
- if (nextRequestId === requestIdRef.current) {
3506
- setError(loadError);
3507
- }
3508
- } finally {
3509
- if (nextRequestId === requestIdRef.current) {
3510
- setIsLoading(false);
3511
- }
3512
- }
3513
- },
3514
- [cacheKey, client, enabled]
3515
- );
3516
- React3.useEffect(() => {
3517
- void load(false);
3518
- }, [load]);
3519
- const refetch = React3.useCallback(async () => {
3520
- bundlesCache.delete(cacheKey);
3521
- await load(true);
3522
- }, [cacheKey, load]);
3523
- return { bundles, isLoading, error, refetch };
3524
- }
3525
- function useProductPrice(input) {
3526
- const {
3527
- product,
3528
- quantity = 1,
3529
- variant,
3530
- addOnOptions,
3531
- compositePrice,
3532
- bundleTotalPrice
3533
- } = input;
3534
- return React3.useMemo(() => {
3535
- let unitPrice;
3536
- if (bundleTotalPrice != null) {
3537
- unitPrice = bundleTotalPrice;
3538
- } else if (compositePrice) {
3539
- unitPrice = chunk64OCG2TJ_js.parsePrice(compositePrice.final_price);
3540
- } else {
3541
- unitPrice = chunk64OCG2TJ_js.parsePrice(product.default_price);
3542
- if (variant?.price_adjustment) {
3543
- unitPrice += chunk64OCG2TJ_js.parsePrice(variant.price_adjustment);
3544
- }
3545
- if (addOnOptions) {
3546
- for (const option of addOnOptions) {
3547
- if (option.default_price) {
3548
- unitPrice += chunk64OCG2TJ_js.parsePrice(option.default_price);
3549
- }
3550
- }
3551
- }
3552
- }
3553
- unitPrice = Math.round(unitPrice * 100) / 100;
3554
- const totalPrice = Math.round(unitPrice * quantity * 100) / 100;
3555
- return {
3556
- unitPrice,
3557
- totalPrice,
3558
- displayTotalPrice: totalPrice
3559
- };
3560
- }, [product.default_price, quantity, variant?.price_adjustment, addOnOptions, compositePrice, bundleTotalPrice]);
3561
- }
3562
- var ordersCache = /* @__PURE__ */ new Map();
3563
- var ordersInflight = /* @__PURE__ */ new Map();
3564
- function buildOrdersCacheKey(client, status, limit) {
3565
- return JSON.stringify({ key: client.getPublicKey(), status, limit });
3566
- }
3567
- function useOrders(options = {}) {
3568
- const context = useOptionalCimplifyClient();
3569
- const client = options.client ?? context?.client;
3570
- if (!client) {
3571
- throw new Error("useOrders must be used within CimplifyProvider or passed { client }.");
3572
- }
3573
- const enabled = options.enabled ?? true;
3574
- const requestIdRef = React3.useRef(0);
3575
- const cacheKey = React3.useMemo(
3576
- () => buildOrdersCacheKey(client, options.status, options.limit),
3577
- [client, options.status, options.limit]
3578
- );
3579
- const cached = ordersCache.get(cacheKey);
3580
- const [orders, setOrders] = React3.useState(cached ?? []);
3581
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3582
- const [error, setError] = React3.useState(null);
3583
- const load = React3.useCallback(
3584
- async (force = false) => {
3585
- if (!enabled) {
3586
- setIsLoading(false);
3587
- return;
3588
- }
3589
- const nextRequestId = ++requestIdRef.current;
3590
- setError(null);
3591
- if (!force) {
3592
- const cachedOrders = ordersCache.get(cacheKey);
3593
- if (cachedOrders) {
3594
- setOrders(cachedOrders);
3595
- setIsLoading(false);
3596
- return;
3597
- }
3598
- }
3599
- setIsLoading(true);
3600
- try {
3601
- const existing = ordersInflight.get(cacheKey);
3602
- const promise = existing ?? (async () => {
3603
- const result = await client.orders.list({
3604
- status: options.status,
3605
- limit: options.limit
3606
- });
3607
- if (!result.ok) {
3608
- throw result.error;
3609
- }
3610
- return result.value;
3611
- })();
3612
- if (!existing) {
3613
- ordersInflight.set(
3614
- cacheKey,
3615
- promise.finally(() => {
3616
- ordersInflight.delete(cacheKey);
3617
- })
3618
- );
3619
- }
3620
- const value = await promise;
3621
- ordersCache.set(cacheKey, value);
3622
- if (nextRequestId === requestIdRef.current) {
3623
- setOrders(value);
3624
- setError(null);
3625
- }
3626
- } catch (loadError) {
3627
- if (nextRequestId === requestIdRef.current) {
3628
- setError(loadError);
3629
- }
3630
- } finally {
3631
- if (nextRequestId === requestIdRef.current) {
3632
- setIsLoading(false);
3633
- }
3634
- }
3635
- },
3636
- [cacheKey, client, enabled, options.status, options.limit]
3637
- );
3638
- React3.useEffect(() => {
3639
- void load(false);
3640
- }, [load]);
3641
- const refetch = React3.useCallback(async () => {
3642
- ordersCache.delete(cacheKey);
3643
- await load(true);
3644
- }, [cacheKey, load]);
3645
- return { orders, isLoading, error, refetch };
3646
- }
3647
- var servicesCache = /* @__PURE__ */ new Map();
3648
- var servicesInflight = /* @__PURE__ */ new Map();
3649
- function buildServicesCacheKey(client) {
3650
- return JSON.stringify({ key: client.getPublicKey() });
3651
- }
3652
- function useServices(options = {}) {
3653
- const context = useOptionalCimplifyClient();
3654
- const client = options.client ?? context?.client;
3655
- if (!client) {
3656
- throw new Error("useServices must be used within CimplifyProvider or passed { client }.");
3657
- }
3658
- const enabled = options.enabled ?? true;
3659
- const requestIdRef = React3.useRef(0);
3660
- const cacheKey = React3.useMemo(() => buildServicesCacheKey(client), [client]);
3661
- const cached = servicesCache.get(cacheKey);
3662
- const [services, setServices] = React3.useState(cached ?? []);
3663
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3664
- const [error, setError] = React3.useState(null);
3665
- const load = React3.useCallback(
3666
- async (force = false) => {
3667
- if (!enabled) {
3668
- setIsLoading(false);
3669
- return;
3670
- }
3671
- const nextRequestId = ++requestIdRef.current;
3672
- setError(null);
3673
- if (!force) {
3674
- const cachedServices = servicesCache.get(cacheKey);
3675
- if (cachedServices) {
3676
- setServices(cachedServices);
3677
- setIsLoading(false);
3678
- return;
3679
- }
3680
- }
3681
- setIsLoading(true);
3682
- try {
3683
- const existing = servicesInflight.get(cacheKey);
3684
- const promise = existing ?? (async () => {
3685
- const result = await client.scheduling.getServices();
3686
- if (!result.ok) {
3687
- throw result.error;
3688
- }
3689
- return result.value;
3690
- })();
3691
- if (!existing) {
3692
- servicesInflight.set(
3693
- cacheKey,
3694
- promise.finally(() => {
3695
- servicesInflight.delete(cacheKey);
3696
- })
3697
- );
3698
- }
3699
- const value = await promise;
3700
- servicesCache.set(cacheKey, value);
3701
- if (nextRequestId === requestIdRef.current) {
3702
- setServices(value);
3703
- setError(null);
3704
- }
3705
- } catch (loadError) {
3706
- if (nextRequestId === requestIdRef.current) {
3707
- setError(loadError);
3708
- }
3709
- } finally {
3710
- if (nextRequestId === requestIdRef.current) {
3711
- setIsLoading(false);
3712
- }
3713
- }
3714
- },
3715
- [cacheKey, client, enabled]
3716
- );
3717
- React3.useEffect(() => {
3718
- void load(false);
3719
- }, [load]);
3720
- const refetch = React3.useCallback(async () => {
3721
- servicesCache.delete(cacheKey);
3722
- await load(true);
3723
- }, [cacheKey, load]);
3724
- return { services, isLoading, error, refetch };
3725
- }
3726
- var slotsCache = /* @__PURE__ */ new Map();
3727
- var slotsInflight = /* @__PURE__ */ new Map();
3728
- function buildSlotsCacheKey(client, serviceId, date, participantCount) {
3729
- return JSON.stringify({
3730
- key: client.getPublicKey(),
3731
- serviceId,
3732
- date,
3733
- participantCount
3734
- });
3735
- }
3736
- function useAvailableSlots(serviceId, date, options = {}) {
3737
- const context = useOptionalCimplifyClient();
3738
- const client = options.client ?? context?.client;
3739
- if (!client) {
3740
- throw new Error("useAvailableSlots must be used within CimplifyProvider or passed { client }.");
3741
- }
3742
- const enabled = (options.enabled ?? true) && !!serviceId && !!date;
3743
- const requestIdRef = React3.useRef(0);
3744
- const cacheKey = React3.useMemo(
3745
- () => serviceId && date ? buildSlotsCacheKey(client, serviceId, date, options.participantCount) : null,
3746
- [client, serviceId, date, options.participantCount]
3747
- );
3748
- const cached = cacheKey ? slotsCache.get(cacheKey) : void 0;
3749
- const [slots, setSlots] = React3.useState(cached ?? []);
3750
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3751
- const [error, setError] = React3.useState(null);
3752
- const load = React3.useCallback(
3753
- async (force = false) => {
3754
- if (!enabled || !cacheKey || !serviceId || !date) {
3755
- setIsLoading(false);
3756
- return;
3757
- }
3758
- const nextRequestId = ++requestIdRef.current;
3759
- setError(null);
3760
- if (!force) {
3761
- const cachedSlots = slotsCache.get(cacheKey);
3762
- if (cachedSlots) {
3763
- setSlots(cachedSlots);
3764
- setIsLoading(false);
3765
- return;
3766
- }
3767
- }
3768
- setIsLoading(true);
3769
- try {
3770
- const existing = slotsInflight.get(cacheKey);
3771
- const promise = existing ?? (async () => {
3772
- const result = await client.scheduling.getAvailableSlots({
3773
- service_id: serviceId,
3774
- date,
3775
- participant_count: options.participantCount
3776
- });
3777
- if (!result.ok) {
3778
- throw result.error;
3779
- }
3780
- return result.value;
3781
- })();
3782
- if (!existing) {
3783
- slotsInflight.set(
3784
- cacheKey,
3785
- promise.finally(() => {
3786
- slotsInflight.delete(cacheKey);
3787
- })
3788
- );
3789
- }
3790
- const value = await promise;
3791
- slotsCache.set(cacheKey, value);
3792
- if (nextRequestId === requestIdRef.current) {
3793
- setSlots(value);
3794
- setError(null);
3795
- }
3796
- } catch (loadError) {
3797
- if (nextRequestId === requestIdRef.current) {
3798
- setError(loadError);
3799
- }
3800
- } finally {
3801
- if (nextRequestId === requestIdRef.current) {
3802
- setIsLoading(false);
3803
- }
3804
- }
3805
- },
3806
- [cacheKey, client, enabled, serviceId, date, options.participantCount]
3807
- );
3808
- React3.useEffect(() => {
3809
- void load(false);
3810
- }, [load]);
3811
- const refetch = React3.useCallback(async () => {
3812
- if (cacheKey) {
3813
- slotsCache.delete(cacheKey);
3814
- }
3815
- await load(true);
3816
- }, [cacheKey, load]);
3817
- return { slots, isLoading, error, refetch };
3818
- }
3819
- var availabilityCache2 = /* @__PURE__ */ new Map();
3820
- var availabilityInflight2 = /* @__PURE__ */ new Map();
3821
- function buildAvailabilityCacheKey2(client, serviceId, startDate, endDate, participantCount) {
3822
- return JSON.stringify({
3823
- key: client.getPublicKey(),
3824
- serviceId,
3825
- startDate,
3826
- endDate,
3827
- participantCount
3828
- });
3829
- }
3830
- function useServiceAvailability(serviceId, startDate, endDate, options = {}) {
3831
- const context = useOptionalCimplifyClient();
3832
- const client = options.client ?? context?.client;
3833
- if (!client) {
3834
- throw new Error(
3835
- "useServiceAvailability must be used within CimplifyProvider or passed { client }."
3836
- );
3837
- }
3838
- const enabled = (options.enabled ?? true) && !!serviceId && !!startDate && !!endDate;
3839
- const requestIdRef = React3.useRef(0);
3840
- const cacheKey = React3.useMemo(
3841
- () => serviceId && startDate && endDate ? buildAvailabilityCacheKey2(
3842
- client,
3843
- serviceId,
3844
- startDate,
3845
- endDate,
3846
- options.participantCount
3847
- ) : null,
3848
- [client, serviceId, startDate, endDate, options.participantCount]
3849
- );
3850
- const cached = cacheKey ? availabilityCache2.get(cacheKey) : void 0;
3851
- const [days, setDays] = React3.useState(cached ?? []);
3852
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3853
- const [error, setError] = React3.useState(null);
3854
- const load = React3.useCallback(
3855
- async (force = false) => {
3856
- if (!enabled || !cacheKey || !serviceId || !startDate || !endDate) {
3857
- setIsLoading(false);
3858
- return;
3859
- }
3860
- const nextRequestId = ++requestIdRef.current;
3861
- setError(null);
3862
- if (!force) {
3863
- const cachedDays = availabilityCache2.get(cacheKey);
3864
- if (cachedDays) {
3865
- setDays(cachedDays);
3866
- setIsLoading(false);
3867
- return;
3868
- }
2672
+ });
2673
+ function useBundles(options = {}) {
2674
+ const { data, isLoading, error, refetch } = bundlesQuery(options);
2675
+ return { bundles: data ?? [], isLoading, error, refetch };
2676
+ }
2677
+ function useProductPrice(input) {
2678
+ const {
2679
+ product,
2680
+ quantity = 1,
2681
+ variant,
2682
+ addOnOptions,
2683
+ compositePrice,
2684
+ bundleTotalPrice
2685
+ } = input;
2686
+ return React3.useMemo(() => {
2687
+ let unitPrice;
2688
+ if (bundleTotalPrice != null) {
2689
+ unitPrice = bundleTotalPrice;
2690
+ } else if (compositePrice) {
2691
+ unitPrice = chunk64OCG2TJ_js.parsePrice(compositePrice.final_price);
2692
+ } else {
2693
+ unitPrice = chunk64OCG2TJ_js.parsePrice(product.default_price);
2694
+ if (variant?.price_adjustment) {
2695
+ unitPrice += chunk64OCG2TJ_js.parsePrice(variant.price_adjustment);
3869
2696
  }
3870
- setIsLoading(true);
3871
- try {
3872
- const existing = availabilityInflight2.get(cacheKey);
3873
- const promise = existing ?? (async () => {
3874
- const result = await client.scheduling.getServiceAvailability({
3875
- service_id: serviceId,
3876
- start_date: startDate,
3877
- end_date: endDate,
3878
- location_id: options.locationId,
3879
- participant_count: options.participantCount
3880
- });
3881
- if (!result.ok) {
3882
- throw result.error;
2697
+ if (addOnOptions) {
2698
+ for (const option of addOnOptions) {
2699
+ if (option.default_price) {
2700
+ unitPrice += chunk64OCG2TJ_js.parsePrice(option.default_price);
3883
2701
  }
3884
- return result.value.availability;
3885
- })();
3886
- if (!existing) {
3887
- availabilityInflight2.set(
3888
- cacheKey,
3889
- promise.finally(() => {
3890
- availabilityInflight2.delete(cacheKey);
3891
- })
3892
- );
3893
- }
3894
- const value = await promise;
3895
- availabilityCache2.set(cacheKey, value);
3896
- if (nextRequestId === requestIdRef.current) {
3897
- setDays(value);
3898
- setError(null);
3899
- }
3900
- } catch (loadError) {
3901
- if (nextRequestId === requestIdRef.current) {
3902
- setError(loadError);
3903
- }
3904
- } finally {
3905
- if (nextRequestId === requestIdRef.current) {
3906
- setIsLoading(false);
3907
2702
  }
3908
2703
  }
3909
- },
3910
- [cacheKey, client, enabled, serviceId, startDate, endDate, options.locationId, options.participantCount]
3911
- );
3912
- React3.useEffect(() => {
3913
- void load(false);
3914
- }, [load]);
3915
- const refetch = React3.useCallback(async () => {
3916
- if (cacheKey) {
3917
- availabilityCache2.delete(cacheKey);
3918
2704
  }
3919
- await load(true);
3920
- }, [cacheKey, load]);
3921
- return { days, isLoading, error, refetch };
2705
+ unitPrice = Math.round(unitPrice * 100) / 100;
2706
+ const totalPrice = Math.round(unitPrice * quantity * 100) / 100;
2707
+ return {
2708
+ unitPrice,
2709
+ totalPrice,
2710
+ displayTotalPrice: totalPrice
2711
+ };
2712
+ }, [product.default_price, quantity, variant?.price_adjustment, addOnOptions, compositePrice, bundleTotalPrice]);
2713
+ }
2714
+
2715
+ // src/react/hooks/use-orders.ts
2716
+ var ordersQuery = createCachedQuery({
2717
+ name: "useOrders",
2718
+ key: (client, options) => cacheKey(client.getPublicKey(), options.status, options.limit),
2719
+ fetch: async (client, options) => {
2720
+ const result = await client.orders.list({
2721
+ status: options.status,
2722
+ limit: options.limit
2723
+ });
2724
+ if (!result.ok) throw result.error;
2725
+ return result.value;
2726
+ }
2727
+ });
2728
+ function useOrders(options = {}) {
2729
+ const { data, isLoading, error, refetch } = ordersQuery(options);
2730
+ return { orders: data ?? [], isLoading, error, refetch };
2731
+ }
2732
+
2733
+ // src/react/hooks/use-services.ts
2734
+ var servicesQuery = createCachedQuery({
2735
+ name: "useServices",
2736
+ key: (client) => cacheKey(client.getPublicKey()),
2737
+ fetch: async (client) => {
2738
+ const result = await client.scheduling.getServices();
2739
+ if (!result.ok) throw result.error;
2740
+ return result.value;
2741
+ }
2742
+ });
2743
+ function useServices(options = {}) {
2744
+ const { data, isLoading, error, refetch } = servicesQuery(options);
2745
+ return { services: data ?? [], isLoading, error, refetch };
3922
2746
  }
3923
- var bookingsCache = /* @__PURE__ */ new Map();
3924
- var bookingsInflight = /* @__PURE__ */ new Map();
3925
- function buildBookingsCacheKey(client, filter) {
3926
- return JSON.stringify({ key: client.getPublicKey(), filter });
2747
+
2748
+ // src/react/hooks/use-available-slots.ts
2749
+ var slotsQuery = createCachedQuery({
2750
+ name: "useAvailableSlots",
2751
+ key: (client, options) => cacheKey(client.getPublicKey(), options.serviceId, options.date, options.participantCount),
2752
+ fetch: async (client, options) => {
2753
+ const result = await client.scheduling.getAvailableSlots({
2754
+ service_id: options.serviceId,
2755
+ date: options.date,
2756
+ participant_count: options.participantCount
2757
+ });
2758
+ if (!result.ok) throw result.error;
2759
+ return result.value;
2760
+ }
2761
+ });
2762
+ function useAvailableSlots(serviceId, date, options = {}) {
2763
+ const { data, isLoading, error, refetch } = slotsQuery({
2764
+ ...options,
2765
+ serviceId: serviceId || "",
2766
+ date: date || "",
2767
+ enabled: (options.enabled ?? true) && !!serviceId && !!date
2768
+ });
2769
+ return { slots: data ?? [], isLoading, error, refetch };
3927
2770
  }
2771
+
2772
+ // src/react/hooks/use-service-availability.ts
2773
+ var serviceAvailabilityQuery = createCachedQuery({
2774
+ name: "useServiceAvailability",
2775
+ key: (client, options) => cacheKey(
2776
+ client.getPublicKey(),
2777
+ options.serviceId,
2778
+ options.startDate,
2779
+ options.endDate,
2780
+ options.participantCount
2781
+ ),
2782
+ fetch: async (client, options) => {
2783
+ const result = await client.scheduling.getServiceAvailability({
2784
+ service_id: options.serviceId,
2785
+ start_date: options.startDate,
2786
+ end_date: options.endDate,
2787
+ location_id: options.locationId,
2788
+ participant_count: options.participantCount
2789
+ });
2790
+ if (!result.ok) throw result.error;
2791
+ return result.value.availability;
2792
+ }
2793
+ });
2794
+ function useServiceAvailability(serviceId, startDate, endDate, options = {}) {
2795
+ const { data, isLoading, error, refetch } = serviceAvailabilityQuery({
2796
+ ...options,
2797
+ serviceId: serviceId || "",
2798
+ startDate: startDate || "",
2799
+ endDate: endDate || "",
2800
+ enabled: (options.enabled ?? true) && !!serviceId && !!startDate && !!endDate
2801
+ });
2802
+ return { days: data ?? [], isLoading, error, refetch };
2803
+ }
2804
+ var bookingsQuery = createCachedQuery({
2805
+ name: "useBookings",
2806
+ key: (client, options) => cacheKey(client.getPublicKey(), options.filter ?? "all"),
2807
+ fetch: async (client, options) => {
2808
+ const filter = options.filter ?? "all";
2809
+ let result;
2810
+ switch (filter) {
2811
+ case "upcoming":
2812
+ result = await client.scheduling.getUpcomingBookings();
2813
+ break;
2814
+ case "past":
2815
+ result = await client.scheduling.getPastBookings();
2816
+ break;
2817
+ default:
2818
+ result = await client.scheduling.getCustomerBookings();
2819
+ break;
2820
+ }
2821
+ if (!result.ok) throw result.error;
2822
+ return result.value;
2823
+ }
2824
+ });
3928
2825
  function useBookings(options = {}) {
3929
2826
  const context = useOptionalCimplifyClient();
3930
2827
  const client = options.client ?? context?.client;
3931
- if (!client) {
3932
- throw new Error("useBookings must be used within CimplifyProvider or passed { client }.");
3933
- }
3934
- const filter = options.filter ?? "all";
3935
- const enabled = options.enabled ?? true;
3936
- const requestIdRef = React3.useRef(0);
3937
- const cacheKey = React3.useMemo(
3938
- () => buildBookingsCacheKey(client, filter),
3939
- [client, filter]
3940
- );
3941
- const cached = bookingsCache.get(cacheKey);
3942
- const [bookings, setBookings] = React3.useState(cached ?? []);
3943
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
3944
- const [error, setError] = React3.useState(null);
3945
- const load = React3.useCallback(
3946
- async (force = false) => {
3947
- if (!enabled) {
3948
- setIsLoading(false);
3949
- return;
3950
- }
3951
- const nextRequestId = ++requestIdRef.current;
3952
- setError(null);
3953
- if (!force) {
3954
- const cachedBookings = bookingsCache.get(cacheKey);
3955
- if (cachedBookings) {
3956
- setBookings(cachedBookings);
3957
- setIsLoading(false);
3958
- return;
3959
- }
3960
- }
3961
- setIsLoading(true);
3962
- try {
3963
- const existing = bookingsInflight.get(cacheKey);
3964
- const promise = existing ?? (async () => {
3965
- let result;
3966
- switch (filter) {
3967
- case "upcoming":
3968
- result = await client.scheduling.getUpcomingBookings();
3969
- break;
3970
- case "past":
3971
- result = await client.scheduling.getPastBookings();
3972
- break;
3973
- default:
3974
- result = await client.scheduling.getCustomerBookings();
3975
- break;
3976
- }
3977
- if (!result.ok) {
3978
- throw result.error;
3979
- }
3980
- return result.value;
3981
- })();
3982
- if (!existing) {
3983
- bookingsInflight.set(
3984
- cacheKey,
3985
- promise.finally(() => {
3986
- bookingsInflight.delete(cacheKey);
3987
- })
3988
- );
3989
- }
3990
- const value = await promise;
3991
- bookingsCache.set(cacheKey, value);
3992
- if (nextRequestId === requestIdRef.current) {
3993
- setBookings(value);
3994
- setError(null);
3995
- }
3996
- } catch (loadError) {
3997
- if (nextRequestId === requestIdRef.current) {
3998
- setError(loadError);
3999
- }
4000
- } finally {
4001
- if (nextRequestId === requestIdRef.current) {
4002
- setIsLoading(false);
4003
- }
4004
- }
4005
- },
4006
- [cacheKey, client, enabled, filter]
4007
- );
4008
- React3.useEffect(() => {
4009
- void load(false);
4010
- }, [load]);
4011
- const refetch = React3.useCallback(async () => {
4012
- bookingsCache.delete(cacheKey);
4013
- await load(true);
4014
- }, [cacheKey, load]);
2828
+ const { data, isLoading, error, refetch } = bookingsQuery(options);
4015
2829
  const cancelBooking = React3.useCallback(
4016
2830
  async (bookingId, reason) => {
2831
+ if (!client) throw new Error("useBookings must be used within CimplifyProvider or passed { client }.");
4017
2832
  const result = await client.scheduling.cancelBooking({
4018
2833
  booking_id: bookingId,
4019
2834
  reason
4020
2835
  });
4021
- if (!result.ok) {
4022
- throw result.error;
4023
- }
4024
- for (const key of bookingsCache.keys()) {
4025
- bookingsCache.delete(key);
4026
- }
4027
- await load(true);
2836
+ if (!result.ok) throw result.error;
2837
+ bookingsQuery.clear();
2838
+ await refetch();
4028
2839
  return result.value;
4029
2840
  },
4030
- [client, load]
2841
+ [client, refetch]
4031
2842
  );
4032
- return { bookings, isLoading, error, refetch, cancelBooking };
2843
+ return { bookings: data ?? [], isLoading, error, refetch, cancelBooking };
4033
2844
  }
4034
- var definitionsCache = /* @__PURE__ */ new Map();
4035
- var definitionsInflight = /* @__PURE__ */ new Map();
4036
- function buildCacheKey(client, namespace) {
4037
- return `attr_defs_${client.getPublicKey() || "__demo__"}${namespace ? `_${namespace}` : ""}`;
4038
- }
4039
- function useAttributeDefinitions(options = {}) {
4040
- const context = useOptionalCimplifyClient();
4041
- const client = options.client ?? context?.client;
4042
- if (!client) {
4043
- throw new Error(
4044
- "useAttributeDefinitions must be used within CimplifyProvider or passed { client }."
4045
- );
2845
+
2846
+ // src/react/hooks/use-attribute-definitions.ts
2847
+ var attributeDefinitionsQuery = createCachedQuery({
2848
+ name: "useAttributeDefinitions",
2849
+ key: (client, options) => cacheKey(client.getPublicKey() || "__demo__", options.namespace),
2850
+ fetch: async (client, options) => {
2851
+ const result = await client.catalogue.getAttributeDefinitions(options.namespace);
2852
+ if (!result.ok) throw result.error;
2853
+ return result.value;
4046
2854
  }
4047
- const enabled = options.enabled ?? true;
4048
- const namespace = options.namespace;
4049
- const cacheKey = React3.useMemo(() => buildCacheKey(client, namespace), [client, namespace]);
4050
- const cached = definitionsCache.get(cacheKey);
4051
- const [definitions, setDefinitions] = React3.useState(cached ?? []);
4052
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4053
- const [error, setError] = React3.useState(null);
4054
- const load = React3.useCallback(
4055
- async (force = false) => {
4056
- if (!enabled) {
4057
- setIsLoading(false);
4058
- return;
4059
- }
4060
- setError(null);
4061
- if (!force) {
4062
- const cachedDefs = definitionsCache.get(cacheKey);
4063
- if (cachedDefs) {
4064
- setDefinitions(cachedDefs);
4065
- setIsLoading(false);
4066
- return;
4067
- }
4068
- }
4069
- setIsLoading(true);
4070
- try {
4071
- const existing = definitionsInflight.get(cacheKey);
4072
- const promise = existing ?? (async () => {
4073
- const result = await client.catalogue.getAttributeDefinitions(namespace);
4074
- if (!result.ok) {
4075
- throw result.error;
4076
- }
4077
- return result.value;
4078
- })();
4079
- if (!existing) {
4080
- definitionsInflight.set(
4081
- cacheKey,
4082
- promise.finally(() => {
4083
- definitionsInflight.delete(cacheKey);
4084
- })
4085
- );
4086
- }
4087
- const value = await promise;
4088
- definitionsCache.set(cacheKey, value);
4089
- setDefinitions(value);
4090
- } catch (loadError) {
4091
- setError(loadError);
4092
- } finally {
4093
- setIsLoading(false);
4094
- }
4095
- },
4096
- [cacheKey, client, enabled]
4097
- );
4098
- React3.useEffect(() => {
4099
- void load(false);
4100
- }, [load]);
4101
- const refetch = React3.useCallback(async () => {
4102
- definitionsCache.delete(cacheKey);
4103
- await load(true);
4104
- }, [cacheKey, load]);
4105
- return { definitions, isLoading, error, refetch };
2855
+ });
2856
+ function useAttributeDefinitions(options = {}) {
2857
+ const { data, isLoading, error, refetch } = attributeDefinitionsQuery(options);
2858
+ return { definitions: data ?? [], isLoading, error, refetch };
4106
2859
  }
4107
- var facetsCache = /* @__PURE__ */ new Map();
4108
- var facetsInflight = /* @__PURE__ */ new Map();
4109
- function usePropertyFacets(options = {}) {
4110
- const context = useOptionalCimplifyClient();
4111
- const client = options.client ?? context?.client;
4112
- if (!client) {
4113
- throw new Error(
4114
- "usePropertyFacets must be used within CimplifyProvider or passed { client }."
4115
- );
2860
+
2861
+ // src/react/hooks/use-property-facets.ts
2862
+ var propertyFacetsQuery = createCachedQuery({
2863
+ name: "usePropertyFacets",
2864
+ key: (client, options) => cacheKey(client.getPublicKey() || "__demo__", options.category_id, options.product_type),
2865
+ fetch: async (client, options) => {
2866
+ const result = await client.catalogue.getPropertyFacets({
2867
+ category_id: options.category_id,
2868
+ product_type: options.product_type
2869
+ });
2870
+ if (!result.ok) throw result.error;
2871
+ return result.value;
4116
2872
  }
4117
- const enabled = options.enabled ?? true;
4118
- const cacheKey = React3.useMemo(
4119
- () => `facets_${client.getPublicKey() || "__demo__"}_${options.category_id ?? ""}_${options.product_type ?? ""}`,
4120
- [client, options.category_id, options.product_type]
4121
- );
4122
- const cached = facetsCache.get(cacheKey);
4123
- const [facets, setFacets] = React3.useState(cached ?? []);
4124
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4125
- const [error, setError] = React3.useState(null);
4126
- const load = React3.useCallback(
4127
- async (force = false) => {
4128
- if (!enabled) {
4129
- setIsLoading(false);
4130
- return;
4131
- }
4132
- setError(null);
4133
- if (!force) {
4134
- const cachedFacets = facetsCache.get(cacheKey);
4135
- if (cachedFacets) {
4136
- setFacets(cachedFacets);
4137
- setIsLoading(false);
4138
- return;
4139
- }
4140
- }
4141
- setIsLoading(true);
4142
- try {
4143
- const existing = facetsInflight.get(cacheKey);
4144
- const promise = existing ?? (async () => {
4145
- const result = await client.catalogue.getPropertyFacets({
4146
- category_id: options.category_id,
4147
- product_type: options.product_type
4148
- });
4149
- if (!result.ok) {
4150
- throw result.error;
4151
- }
4152
- return result.value;
4153
- })();
4154
- if (!existing) {
4155
- facetsInflight.set(
4156
- cacheKey,
4157
- promise.finally(() => {
4158
- facetsInflight.delete(cacheKey);
4159
- })
4160
- );
4161
- }
4162
- const value = await promise;
4163
- facetsCache.set(cacheKey, value);
4164
- setFacets(value);
4165
- } catch (loadError) {
4166
- setError(loadError);
4167
- } finally {
4168
- setIsLoading(false);
4169
- }
4170
- },
4171
- [cacheKey, client, enabled, options.category_id, options.product_type]
4172
- );
4173
- React3.useEffect(() => {
4174
- void load(false);
4175
- }, [load]);
4176
- const refetch = React3.useCallback(async () => {
4177
- facetsCache.delete(cacheKey);
4178
- await load(true);
4179
- }, [cacheKey, load]);
4180
- return { facets, isLoading, error, refetch };
2873
+ });
2874
+ function usePropertyFacets(options = {}) {
2875
+ const { data, isLoading, error, refetch } = propertyFacetsQuery(options);
2876
+ return { facets: data ?? [], isLoading, error, refetch };
4181
2877
  }
4182
2878
  function useBillingPlans(productId, options = {}) {
4183
2879
  const context = useOptionalCimplifyClient();
@@ -4309,417 +3005,112 @@ function useVariantSelector(options) {
4309
3005
  reset
4310
3006
  };
4311
3007
  }
4312
- var activityStateCache = /* @__PURE__ */ new Map();
4313
- var activityStateInflight = /* @__PURE__ */ new Map();
4314
- function buildActivityStateCacheKey(client) {
4315
- return JSON.stringify({ key: client.getPublicKey(), type: "activity_state" });
4316
- }
3008
+ var activityStateQuery = createCachedQuery({
3009
+ name: "useActivityState",
3010
+ key: (client) => cacheKey(client.getPublicKey()),
3011
+ fetch: async (client) => {
3012
+ const result = await client.activity.getState();
3013
+ if (!result.ok) throw result.error;
3014
+ return result.value;
3015
+ }
3016
+ });
4317
3017
  function useActivityState(options = {}) {
4318
3018
  const context = useOptionalCimplifyClient();
4319
3019
  const client = options.client ?? context?.client;
4320
- if (!client) {
4321
- throw new Error("useActivityState must be used within CimplifyProvider or passed { client }.");
4322
- }
4323
- const enabled = options.enabled ?? true;
4324
- const cacheKey = React3.useMemo(() => buildActivityStateCacheKey(client), [client]);
4325
- const cached = activityStateCache.get(cacheKey);
4326
- const [state, setState] = React3.useState(cached ?? null);
4327
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4328
- const [error, setError] = React3.useState(null);
4329
- const load = React3.useCallback(
4330
- async (force = false) => {
4331
- if (!enabled) {
4332
- setIsLoading(false);
4333
- return;
4334
- }
4335
- setError(null);
4336
- if (!force) {
4337
- const cachedState = activityStateCache.get(cacheKey);
4338
- if (cachedState) {
4339
- setState(cachedState);
4340
- setIsLoading(false);
4341
- return;
4342
- }
4343
- }
4344
- setIsLoading(true);
4345
- try {
4346
- const existing = activityStateInflight.get(cacheKey);
4347
- const promise = existing ?? (async () => {
4348
- const result = await client.activity.getState();
4349
- if (!result.ok) {
4350
- throw result.error;
4351
- }
4352
- return result.value;
4353
- })();
4354
- if (!existing) {
4355
- activityStateInflight.set(
4356
- cacheKey,
4357
- promise.finally(() => {
4358
- activityStateInflight.delete(cacheKey);
4359
- })
4360
- );
4361
- }
4362
- const value = await promise;
4363
- activityStateCache.set(cacheKey, value);
4364
- setState(value);
4365
- } catch (loadError) {
4366
- setError(loadError);
4367
- } finally {
4368
- setIsLoading(false);
4369
- }
4370
- },
4371
- [cacheKey, client, enabled]
4372
- );
4373
- React3.useEffect(() => {
4374
- void load(false);
4375
- }, [load]);
4376
- const refetch = React3.useCallback(async () => {
4377
- activityStateCache.delete(cacheKey);
4378
- await load(true);
4379
- }, [cacheKey, load]);
3020
+ const { data, isLoading, error, refetch } = activityStateQuery(options);
4380
3021
  const dismissMessage = React3.useCallback(
4381
3022
  async (code) => {
3023
+ if (!client) return;
4382
3024
  const result = await client.activity.dismissMessage(code);
4383
- if (!result.ok) {
4384
- setError(result.error);
4385
- return;
4386
- }
4387
- setState((prev) => {
4388
- if (!prev) return prev;
4389
- return { ...prev, messages: result.value.messages };
4390
- });
4391
- activityStateCache.delete(cacheKey);
4392
- await load(true);
3025
+ if (!result.ok) return;
3026
+ activityStateQuery.clear();
3027
+ await refetch();
4393
3028
  },
4394
- [cacheKey, client, load]
3029
+ [client, refetch]
4395
3030
  );
4396
- const messages = state?.messages ?? [];
4397
- const intent = state?.intent ?? "";
4398
- return { state, messages, intent, isLoading, error, refetch, dismissMessage };
4399
- }
4400
- var recommendationsCache = /* @__PURE__ */ new Map();
4401
- var recommendationsInflight = /* @__PURE__ */ new Map();
4402
- function buildRecommendationsCacheKey(client, locationId, limit) {
4403
- return JSON.stringify({
4404
- key: client.getPublicKey(),
4405
- type: "recommendations",
4406
- location_id: locationId,
4407
- limit
4408
- });
3031
+ return {
3032
+ state: data,
3033
+ messages: data?.messages ?? [],
3034
+ intent: data?.intent ?? "",
3035
+ isLoading,
3036
+ error,
3037
+ refetch,
3038
+ dismissMessage
3039
+ };
4409
3040
  }
4410
- function useRecommendations(options = {}) {
4411
- const context = useOptionalCimplifyClient();
4412
- const client = options.client ?? context?.client;
4413
- if (!client) {
4414
- throw new Error(
4415
- "useRecommendations must be used within CimplifyProvider or passed { client }."
4416
- );
3041
+
3042
+ // src/react/hooks/use-recommendations.ts
3043
+ var recommendationsQuery = createCachedQuery({
3044
+ name: "useRecommendations",
3045
+ locationSensitive: true,
3046
+ key: (client, options) => {
3047
+ const locationId = options.locationId ?? client.getLocationId();
3048
+ return cacheKey(client.getPublicKey(), locationId, options.limit);
3049
+ },
3050
+ fetch: async (client, options) => {
3051
+ const locationId = options.locationId ?? client.getLocationId() ?? void 0;
3052
+ const result = await client.activity.getRecommendations({
3053
+ location_id: locationId,
3054
+ limit: options.limit
3055
+ });
3056
+ if (!result.ok) throw result.error;
3057
+ return result.value;
4417
3058
  }
4418
- const enabled = options.enabled ?? true;
4419
- const locationId = options.locationId ?? client.getLocationId() ?? void 0;
4420
- const limit = options.limit;
4421
- const previousLocationIdRef = React3.useRef(locationId);
4422
- const cacheKey = React3.useMemo(
4423
- () => buildRecommendationsCacheKey(client, locationId, limit),
4424
- [client, locationId, limit]
4425
- );
4426
- const cached = recommendationsCache.get(cacheKey);
4427
- const [response, setResponse] = React3.useState(cached ?? null);
4428
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4429
- const [error, setError] = React3.useState(null);
4430
- React3.useEffect(() => {
4431
- if (previousLocationIdRef.current !== locationId) {
4432
- recommendationsCache.clear();
4433
- recommendationsInflight.clear();
4434
- previousLocationIdRef.current = locationId;
4435
- }
4436
- }, [locationId]);
4437
- const load = React3.useCallback(
4438
- async (force = false) => {
4439
- if (!enabled) {
4440
- setIsLoading(false);
4441
- return;
4442
- }
4443
- setError(null);
4444
- if (!force) {
4445
- const cachedResponse = recommendationsCache.get(cacheKey);
4446
- if (cachedResponse) {
4447
- setResponse(cachedResponse);
4448
- setIsLoading(false);
4449
- return;
4450
- }
4451
- }
4452
- setIsLoading(true);
4453
- try {
4454
- const existing = recommendationsInflight.get(cacheKey);
4455
- const promise = existing ?? (async () => {
4456
- const result = await client.activity.getRecommendations({
4457
- location_id: locationId,
4458
- limit
4459
- });
4460
- if (!result.ok) {
4461
- throw result.error;
4462
- }
4463
- return result.value;
4464
- })();
4465
- if (!existing) {
4466
- recommendationsInflight.set(
4467
- cacheKey,
4468
- promise.finally(() => {
4469
- recommendationsInflight.delete(cacheKey);
4470
- })
4471
- );
4472
- }
4473
- const value = await promise;
4474
- recommendationsCache.set(cacheKey, value);
4475
- setResponse(value);
4476
- } catch (loadError) {
4477
- setError(loadError);
4478
- } finally {
4479
- setIsLoading(false);
4480
- }
4481
- },
4482
- [cacheKey, client, enabled, locationId, limit]
4483
- );
4484
- React3.useEffect(() => {
4485
- void load(false);
4486
- }, [load]);
4487
- const refetch = React3.useCallback(async () => {
4488
- recommendationsCache.delete(cacheKey);
4489
- await load(true);
4490
- }, [cacheKey, load]);
4491
- const recommendations = response?.recommendations ?? [];
4492
- const intent = response?.intent ?? "";
4493
- return { recommendations, intent, isLoading, error, refetch };
4494
- }
4495
- var deliveryFeeCache = /* @__PURE__ */ new Map();
4496
- var deliveryFeeInflight = /* @__PURE__ */ new Map();
4497
- function buildDeliveryFeeCacheKey(client, latitude, longitude, country) {
4498
- return JSON.stringify({
4499
- key: client.getPublicKey(),
4500
- lat: latitude,
4501
- lng: longitude,
4502
- country
4503
- });
3059
+ });
3060
+ function useRecommendations(options = {}) {
3061
+ const { data, isLoading, error, refetch } = recommendationsQuery(options);
3062
+ return {
3063
+ recommendations: data?.recommendations ?? [],
3064
+ intent: data?.intent ?? "",
3065
+ isLoading,
3066
+ error,
3067
+ refetch
3068
+ };
4504
3069
  }
4505
- function useDeliveryFee(options) {
4506
- const context = useOptionalCimplifyClient();
4507
- const client = options.client ?? context?.client;
4508
- if (!client) {
4509
- throw new Error("useDeliveryFee must be used within CimplifyProvider or passed { client }.");
3070
+
3071
+ // src/react/hooks/use-delivery-fee.ts
3072
+ var deliveryFeeQuery = createCachedQuery({
3073
+ name: "useDeliveryFee",
3074
+ key: (client, options) => cacheKey(client.getPublicKey(), options.latitude, options.longitude, options.country),
3075
+ fetch: async (client, options) => {
3076
+ const result = await client.delivery.getFee(options.latitude, options.longitude, options.country);
3077
+ if (!result.ok) throw result.error;
3078
+ return result.value;
4510
3079
  }
4511
- const enabled = options.enabled ?? true;
4512
- const { latitude, longitude, country } = options;
4513
- const cacheKey = React3.useMemo(
4514
- () => buildDeliveryFeeCacheKey(client, latitude, longitude, country),
4515
- [client, latitude, longitude, country]
4516
- );
4517
- const cached = deliveryFeeCache.get(cacheKey);
4518
- const [fee, setFee] = React3.useState(cached ?? null);
4519
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4520
- const [error, setError] = React3.useState(null);
4521
- const requestIdRef = React3.useRef(0);
4522
- const load = React3.useCallback(
4523
- async (force = false) => {
4524
- if (!enabled) {
4525
- setIsLoading(false);
4526
- return;
4527
- }
4528
- setError(null);
4529
- if (!force) {
4530
- const cachedFee = deliveryFeeCache.get(cacheKey);
4531
- if (cachedFee) {
4532
- setFee(cachedFee);
4533
- setIsLoading(false);
4534
- return;
4535
- }
4536
- }
4537
- setIsLoading(true);
4538
- const currentRequestId = ++requestIdRef.current;
4539
- try {
4540
- const existing = deliveryFeeInflight.get(cacheKey);
4541
- const promise = existing ?? (async () => {
4542
- const result = await client.delivery.getFee(latitude, longitude, country);
4543
- if (!result.ok) {
4544
- throw result.error;
4545
- }
4546
- return result.value;
4547
- })();
4548
- if (!existing) {
4549
- deliveryFeeInflight.set(
4550
- cacheKey,
4551
- promise.finally(() => {
4552
- deliveryFeeInflight.delete(cacheKey);
4553
- })
4554
- );
4555
- }
4556
- const value = await promise;
4557
- if (currentRequestId !== requestIdRef.current) return;
4558
- deliveryFeeCache.set(cacheKey, value);
4559
- setFee(value);
4560
- } catch (loadError) {
4561
- if (currentRequestId !== requestIdRef.current) return;
4562
- setError(loadError);
4563
- } finally {
4564
- if (currentRequestId === requestIdRef.current) {
4565
- setIsLoading(false);
4566
- }
4567
- }
4568
- },
4569
- [cacheKey, client, country, enabled, latitude, longitude]
4570
- );
4571
- React3.useEffect(() => {
4572
- void load(false);
4573
- }, [load]);
4574
- const refetch = React3.useCallback(async () => {
4575
- deliveryFeeCache.delete(cacheKey);
4576
- await load(true);
4577
- }, [cacheKey, load]);
4578
- return { fee, isLoading, error, refetch };
4579
- }
4580
- var fxRateCache = /* @__PURE__ */ new Map();
4581
- var fxRateInflight = /* @__PURE__ */ new Map();
4582
- function buildFxRateCacheKey(client, from, to) {
4583
- return JSON.stringify({ key: client.getPublicKey(), from, to });
3080
+ });
3081
+ function useDeliveryFee(options) {
3082
+ const { data, isLoading, error, refetch } = deliveryFeeQuery(options);
3083
+ return { fee: data, isLoading, error, refetch };
4584
3084
  }
4585
- function useFxRate(options) {
4586
- const context = useOptionalCimplifyClient();
4587
- const client = options.client ?? context?.client;
4588
- if (!client) {
4589
- throw new Error("useFxRate must be used within CimplifyProvider or passed { client }.");
3085
+
3086
+ // src/react/hooks/use-fx-rate.ts
3087
+ var fxRateQuery = createCachedQuery({
3088
+ name: "useFxRate",
3089
+ key: (client, options) => cacheKey(client.getPublicKey(), options.from, options.to),
3090
+ fetch: async (client, options) => {
3091
+ const result = await client.fx.getRate(options.from, options.to);
3092
+ if (!result.ok) throw result.error;
3093
+ return result.value;
4590
3094
  }
4591
- const enabled = options.enabled ?? true;
4592
- const { from, to } = options;
4593
- const cacheKey = React3.useMemo(
4594
- () => buildFxRateCacheKey(client, from, to),
4595
- [client, from, to]
4596
- );
4597
- const cached = fxRateCache.get(cacheKey);
4598
- const [rate, setRate] = React3.useState(cached ?? null);
4599
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4600
- const [error, setError] = React3.useState(null);
4601
- const load = React3.useCallback(
4602
- async (force = false) => {
4603
- if (!enabled) {
4604
- setIsLoading(false);
4605
- return;
4606
- }
4607
- setError(null);
4608
- if (!force) {
4609
- const cachedRate = fxRateCache.get(cacheKey);
4610
- if (cachedRate) {
4611
- setRate(cachedRate);
4612
- setIsLoading(false);
4613
- return;
4614
- }
4615
- }
4616
- setIsLoading(true);
4617
- try {
4618
- const existing = fxRateInflight.get(cacheKey);
4619
- const promise = existing ?? (async () => {
4620
- const result = await client.fx.getRate(from, to);
4621
- if (!result.ok) {
4622
- throw result.error;
4623
- }
4624
- return result.value;
4625
- })();
4626
- if (!existing) {
4627
- fxRateInflight.set(
4628
- cacheKey,
4629
- promise.finally(() => {
4630
- fxRateInflight.delete(cacheKey);
4631
- })
4632
- );
4633
- }
4634
- const value = await promise;
4635
- fxRateCache.set(cacheKey, value);
4636
- setRate(value);
4637
- } catch (loadError) {
4638
- setError(loadError);
4639
- } finally {
4640
- setIsLoading(false);
4641
- }
4642
- },
4643
- [cacheKey, client, enabled, from, to]
4644
- );
4645
- React3.useEffect(() => {
4646
- void load(false);
4647
- }, [load]);
4648
- const refetch = React3.useCallback(async () => {
4649
- fxRateCache.delete(cacheKey);
4650
- await load(true);
4651
- }, [cacheKey, load]);
4652
- return { rate, isLoading, error, refetch };
4653
- }
4654
- var bootstrapCache = /* @__PURE__ */ new Map();
4655
- var bootstrapInflight = /* @__PURE__ */ new Map();
4656
- function buildBootstrapCacheKey(client) {
4657
- return JSON.stringify({ key: client.getPublicKey(), type: "bootstrap" });
3095
+ });
3096
+ function useFxRate(options) {
3097
+ const { data, isLoading, error, refetch } = fxRateQuery(options);
3098
+ return { rate: data, isLoading, error, refetch };
4658
3099
  }
4659
- function useBootstrap(options = {}) {
4660
- const context = useOptionalCimplifyClient();
4661
- const client = options.client ?? context?.client;
4662
- if (!client) {
4663
- throw new Error("useBootstrap must be used within CimplifyProvider or passed { client }.");
3100
+
3101
+ // src/react/hooks/use-bootstrap.ts
3102
+ var bootstrapQuery = createCachedQuery({
3103
+ name: "useBootstrap",
3104
+ key: (client) => cacheKey(client.getPublicKey()),
3105
+ fetch: async (client) => {
3106
+ const result = await client.business.getBootstrap();
3107
+ if (!result.ok) throw result.error;
3108
+ return result.value;
4664
3109
  }
4665
- const enabled = options.enabled ?? true;
4666
- const cacheKey = React3.useMemo(() => buildBootstrapCacheKey(client), [client]);
4667
- const cached = bootstrapCache.get(cacheKey);
4668
- const [bootstrap, setBootstrap] = React3.useState(cached ?? null);
4669
- const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4670
- const [error, setError] = React3.useState(null);
4671
- const load = React3.useCallback(
4672
- async (force = false) => {
4673
- if (!enabled) {
4674
- setIsLoading(false);
4675
- return;
4676
- }
4677
- setError(null);
4678
- if (!force) {
4679
- const cachedBootstrap = bootstrapCache.get(cacheKey);
4680
- if (cachedBootstrap) {
4681
- setBootstrap(cachedBootstrap);
4682
- setIsLoading(false);
4683
- return;
4684
- }
4685
- }
4686
- setIsLoading(true);
4687
- try {
4688
- const existing = bootstrapInflight.get(cacheKey);
4689
- const promise = existing ?? (async () => {
4690
- const result = await client.business.getBootstrap();
4691
- if (!result.ok) {
4692
- throw result.error;
4693
- }
4694
- return result.value;
4695
- })();
4696
- if (!existing) {
4697
- bootstrapInflight.set(
4698
- cacheKey,
4699
- promise.finally(() => {
4700
- bootstrapInflight.delete(cacheKey);
4701
- })
4702
- );
4703
- }
4704
- const value = await promise;
4705
- bootstrapCache.set(cacheKey, value);
4706
- setBootstrap(value);
4707
- } catch (loadError) {
4708
- setError(loadError);
4709
- } finally {
4710
- setIsLoading(false);
4711
- }
4712
- },
4713
- [cacheKey, client, enabled]
4714
- );
4715
- React3.useEffect(() => {
4716
- void load(false);
4717
- }, [load]);
4718
- const refetch = React3.useCallback(async () => {
4719
- bootstrapCache.delete(cacheKey);
4720
- await load(true);
4721
- }, [cacheKey, load]);
4722
- return { bootstrap, isLoading, error, refetch };
3110
+ });
3111
+ function useBootstrap(options = {}) {
3112
+ const { data, isLoading, error, refetch } = bootstrapQuery(options);
3113
+ return { bootstrap: data, isLoading, error, refetch };
4723
3114
  }
4724
3115
  var ElementsContext = React3.createContext({
4725
3116
  elements: null,