@cimplify/sdk 0.6.7 → 0.6.9

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.mjs CHANGED
@@ -711,6 +711,15 @@ function CimplifyCheckout({
711
711
  }
712
712
 
713
713
  // src/types/common.ts
714
+ function money(value) {
715
+ return value;
716
+ }
717
+ function moneyFromNumber(value) {
718
+ return value.toFixed(2);
719
+ }
720
+ function currencyCode(value) {
721
+ return value;
722
+ }
714
723
  var ErrorCode = {
715
724
  // General
716
725
  UNKNOWN_ERROR: "UNKNOWN_ERROR",
@@ -822,6 +831,11 @@ function err(error) {
822
831
  return { ok: false, error };
823
832
  }
824
833
 
834
+ // src/query/builder.ts
835
+ function escapeQueryValue(value) {
836
+ return value.replace(/'/g, "\\'");
837
+ }
838
+
825
839
  // src/catalogue.ts
826
840
  function toCimplifyError(error) {
827
841
  if (error instanceof CimplifyError) return enrichError(error);
@@ -902,7 +916,7 @@ var CatalogueQueries = class {
902
916
  let query = "products";
903
917
  const filters = [];
904
918
  if (options?.category) {
905
- filters.push(`@.category_id=='${options.category}'`);
919
+ filters.push(`@.category_id=='${escapeQueryValue(options.category)}'`);
906
920
  }
907
921
  if (options?.featured !== void 0) {
908
922
  filters.push(`@.featured==${options.featured}`);
@@ -911,7 +925,7 @@ var CatalogueQueries = class {
911
925
  filters.push(`@.in_stock==${options.in_stock}`);
912
926
  }
913
927
  if (options?.search) {
914
- filters.push(`@.name contains '${options.search}'`);
928
+ filters.push(`@.name contains '${escapeQueryValue(options.search)}'`);
915
929
  }
916
930
  if (options?.min_price !== void 0) {
917
931
  filters.push(`@.price>=${options.min_price}`);
@@ -942,7 +956,9 @@ var CatalogueQueries = class {
942
956
  }
943
957
  async getProductBySlug(slug) {
944
958
  const filteredResult = await safe(
945
- this.client.query(`products[?(@.slug=='${slug}')]`)
959
+ this.client.query(
960
+ `products[?(@.slug=='${escapeQueryValue(slug)}')]`
961
+ )
946
962
  );
947
963
  if (!filteredResult.ok) return filteredResult;
948
964
  const exactMatch = findProductBySlug(filteredResult.value, slug);
@@ -994,7 +1010,7 @@ var CatalogueQueries = class {
994
1010
  }
995
1011
  async getCategoryBySlug(slug) {
996
1012
  const result = await safe(
997
- this.client.query(`categories[?(@.slug=='${slug}')]`)
1013
+ this.client.query(`categories[?(@.slug=='${escapeQueryValue(slug)}')]`)
998
1014
  );
999
1015
  if (!result.ok) return result;
1000
1016
  if (!result.value.length) {
@@ -1003,7 +1019,11 @@ var CatalogueQueries = class {
1003
1019
  return ok(result.value[0]);
1004
1020
  }
1005
1021
  async getCategoryProducts(categoryId) {
1006
- return safe(this.client.query(`products[?(@.category_id=='${categoryId}')]`));
1022
+ return safe(
1023
+ this.client.query(
1024
+ `products[?(@.category_id=='${escapeQueryValue(categoryId)}')]`
1025
+ )
1026
+ );
1007
1027
  }
1008
1028
  async getCollections() {
1009
1029
  return safe(this.client.query("collections"));
@@ -1013,7 +1033,9 @@ var CatalogueQueries = class {
1013
1033
  }
1014
1034
  async getCollectionBySlug(slug) {
1015
1035
  const result = await safe(
1016
- this.client.query(`collections[?(@.slug=='${slug}')]`)
1036
+ this.client.query(
1037
+ `collections[?(@.slug=='${escapeQueryValue(slug)}')]`
1038
+ )
1017
1039
  );
1018
1040
  if (!result.ok) return result;
1019
1041
  if (!result.value.length) {
@@ -1026,7 +1048,9 @@ var CatalogueQueries = class {
1026
1048
  }
1027
1049
  async searchCollections(query, limit = 20) {
1028
1050
  return safe(
1029
- this.client.query(`collections[?(@.name contains '${query}')]#limit(${limit})`)
1051
+ this.client.query(
1052
+ `collections[?(@.name contains '${escapeQueryValue(query)}')]#limit(${limit})`
1053
+ )
1030
1054
  );
1031
1055
  }
1032
1056
  async getBundles() {
@@ -1037,7 +1061,9 @@ var CatalogueQueries = class {
1037
1061
  }
1038
1062
  async getBundleBySlug(slug) {
1039
1063
  const result = await safe(
1040
- this.client.query(`bundles[?(@.slug=='${slug}')]`)
1064
+ this.client.query(
1065
+ `bundles[?(@.slug=='${escapeQueryValue(slug)}')]`
1066
+ )
1041
1067
  );
1042
1068
  if (!result.ok) return result;
1043
1069
  if (!result.value.length) {
@@ -1047,7 +1073,9 @@ var CatalogueQueries = class {
1047
1073
  }
1048
1074
  async searchBundles(query, limit = 20) {
1049
1075
  return safe(
1050
- this.client.query(`bundles[?(@.name contains '${query}')]#limit(${limit})`)
1076
+ this.client.query(
1077
+ `bundles[?(@.name contains '${escapeQueryValue(query)}')]#limit(${limit})`
1078
+ )
1051
1079
  );
1052
1080
  }
1053
1081
  async getComposites(options) {
@@ -1087,9 +1115,9 @@ var CatalogueQueries = class {
1087
1115
  }
1088
1116
  async search(query, options) {
1089
1117
  const limit = options?.limit ?? 20;
1090
- let searchQuery = `products[?(@.name contains '${query}')]`;
1118
+ let searchQuery = `products[?(@.name contains '${escapeQueryValue(query)}')]`;
1091
1119
  if (options?.category) {
1092
- searchQuery = `products[?(@.name contains '${query}' && @.category_id=='${options.category}')]`;
1120
+ searchQuery = `products[?(@.name contains '${escapeQueryValue(query)}' && @.category_id=='${escapeQueryValue(options.category)}')]`;
1093
1121
  }
1094
1122
  searchQuery += `#limit(${limit})`;
1095
1123
  return safe(this.client.query(searchQuery));
@@ -1106,7 +1134,7 @@ var CatalogueQueries = class {
1106
1134
  async getMenu(options) {
1107
1135
  let query = "menu";
1108
1136
  if (options?.category) {
1109
- query = `menu[?(@.category=='${options.category}')]`;
1137
+ query = `menu[?(@.category=='${escapeQueryValue(options.category)}')]`;
1110
1138
  }
1111
1139
  if (options?.limit) {
1112
1140
  query += `#limit(${options.limit})`;
@@ -1253,9 +1281,6 @@ var CartOperations = class {
1253
1281
 
1254
1282
  // src/constants.ts
1255
1283
  var LINK_QUERY = {
1256
- DATA: "link.data",
1257
- ADDRESSES: "link.addresses",
1258
- MOBILE_MONEY: "link.mobile_money",
1259
1284
  PREFERENCES: "link.preferences"};
1260
1285
  var LINK_MUTATION = {
1261
1286
  CHECK_STATUS: "link.check_status",
@@ -1264,12 +1289,8 @@ var LINK_MUTATION = {
1264
1289
  UPDATE_PREFERENCES: "link.update_preferences",
1265
1290
  CREATE_ADDRESS: "link.create_address",
1266
1291
  UPDATE_ADDRESS: "link.update_address",
1267
- DELETE_ADDRESS: "link.delete_address",
1268
- SET_DEFAULT_ADDRESS: "link.set_default_address",
1269
1292
  TRACK_ADDRESS_USAGE: "link.track_address_usage",
1270
1293
  CREATE_MOBILE_MONEY: "link.create_mobile_money",
1271
- DELETE_MOBILE_MONEY: "link.delete_mobile_money",
1272
- SET_DEFAULT_MOBILE_MONEY: "link.set_default_mobile_money",
1273
1294
  TRACK_MOBILE_MONEY_USAGE: "link.track_mobile_money_usage",
1274
1295
  VERIFY_MOBILE_MONEY: "link.verify_mobile_money"};
1275
1296
  var AUTH_MUTATION = {
@@ -1400,6 +1421,8 @@ function normalizeStatusResponse(response) {
1400
1421
  }
1401
1422
  const res = response;
1402
1423
  const normalizedStatus = normalizePaymentStatusValue(res.status ?? void 0);
1424
+ const normalizedAmount = typeof res.amount === "string" ? money(res.amount) : typeof res.amount === "number" && Number.isFinite(res.amount) ? moneyFromNumber(res.amount) : void 0;
1425
+ const normalizedCurrency = typeof res.currency === "string" && res.currency.trim().length > 0 ? currencyCode(res.currency) : void 0;
1403
1426
  const paidValue = res.paid === true;
1404
1427
  const derivedPaid = paidValue || [
1405
1428
  "success",
@@ -1412,8 +1435,8 @@ function normalizeStatusResponse(response) {
1412
1435
  return {
1413
1436
  status: normalizedStatus,
1414
1437
  paid: derivedPaid,
1415
- amount: res.amount,
1416
- currency: res.currency,
1438
+ amount: normalizedAmount,
1439
+ currency: normalizedCurrency,
1417
1440
  reference: res.reference,
1418
1441
  message: res.message || ""
1419
1442
  };
@@ -2105,14 +2128,17 @@ var CheckoutService = class {
2105
2128
  pay_currency: data.pay_currency,
2106
2129
  fx_quote_id: data.fx_quote_id
2107
2130
  };
2108
- const baseCurrency = (cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase();
2131
+ const baseCurrency = currencyCode(
2132
+ (cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase()
2133
+ );
2109
2134
  const payCurrency = data.pay_currency?.trim().toUpperCase();
2135
+ const payCurrencyCode = payCurrency ? currencyCode(payCurrency) : void 0;
2110
2136
  const cartTotalAmount = Number.parseFloat(cart.pricing.total_price || "0");
2111
- if (payCurrency && payCurrency !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
2137
+ if (payCurrencyCode && payCurrencyCode !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
2112
2138
  const fxQuoteResult = await this.client.fx.lockQuote({
2113
2139
  from: baseCurrency,
2114
- to: payCurrency,
2115
- amount: cartTotalAmount
2140
+ to: payCurrencyCode,
2141
+ amount: cart.pricing.total_price
2116
2142
  });
2117
2143
  if (!fxQuoteResult.ok) {
2118
2144
  return ok(
@@ -2123,7 +2149,7 @@ var CheckoutService = class {
2123
2149
  )
2124
2150
  );
2125
2151
  }
2126
- checkoutData.pay_currency = payCurrency;
2152
+ checkoutData.pay_currency = payCurrencyCode;
2127
2153
  checkoutData.fx_quote_id = fxQuoteResult.value.id;
2128
2154
  }
2129
2155
  data.on_status_change?.("processing", {});
@@ -2228,6 +2254,9 @@ var LinkService = class {
2228
2254
  constructor(client) {
2229
2255
  this.client = client;
2230
2256
  }
2257
+ async getProfile() {
2258
+ return safe5(this.client.linkGet("/v1/link/profile"));
2259
+ }
2231
2260
  async requestOtp(input) {
2232
2261
  return safe5(this.client.linkPost("/v1/link/auth/request-otp", input));
2233
2262
  }
@@ -2255,13 +2284,13 @@ var LinkService = class {
2255
2284
  );
2256
2285
  }
2257
2286
  async getLinkData() {
2258
- return safe5(this.client.query(LINK_QUERY.DATA));
2287
+ return safe5(this.client.linkGet("/v1/link/data"));
2259
2288
  }
2260
2289
  async getAddresses() {
2261
- return safe5(this.client.query(LINK_QUERY.ADDRESSES));
2290
+ return safe5(this.client.linkGet("/v1/link/addresses"));
2262
2291
  }
2263
2292
  async getMobileMoney() {
2264
- return safe5(this.client.query(LINK_QUERY.MOBILE_MONEY));
2293
+ return safe5(this.client.linkGet("/v1/link/mobile-money"));
2265
2294
  }
2266
2295
  async getPreferences() {
2267
2296
  return safe5(this.client.query(LINK_QUERY.PREFERENCES));
@@ -2284,10 +2313,10 @@ var LinkService = class {
2284
2313
  return safe5(this.client.call(LINK_MUTATION.UPDATE_ADDRESS, input));
2285
2314
  }
2286
2315
  async deleteAddress(addressId) {
2287
- return safe5(this.client.call(LINK_MUTATION.DELETE_ADDRESS, addressId));
2316
+ return safe5(this.client.linkDelete(`/v1/link/addresses/${addressId}`));
2288
2317
  }
2289
2318
  async setDefaultAddress(addressId) {
2290
- return safe5(this.client.call(LINK_MUTATION.SET_DEFAULT_ADDRESS, addressId));
2319
+ return safe5(this.client.linkPost(`/v1/link/addresses/${addressId}/default`));
2291
2320
  }
2292
2321
  async trackAddressUsage(addressId) {
2293
2322
  return safe5(
@@ -2300,11 +2329,13 @@ var LinkService = class {
2300
2329
  return safe5(this.client.call(LINK_MUTATION.CREATE_MOBILE_MONEY, input));
2301
2330
  }
2302
2331
  async deleteMobileMoney(mobileMoneyId) {
2303
- return safe5(this.client.call(LINK_MUTATION.DELETE_MOBILE_MONEY, mobileMoneyId));
2332
+ return safe5(
2333
+ this.client.linkDelete(`/v1/link/mobile-money/${mobileMoneyId}`)
2334
+ );
2304
2335
  }
2305
2336
  async setDefaultMobileMoney(mobileMoneyId) {
2306
2337
  return safe5(
2307
- this.client.call(LINK_MUTATION.SET_DEFAULT_MOBILE_MONEY, mobileMoneyId)
2338
+ this.client.linkPost(`/v1/link/mobile-money/${mobileMoneyId}/default`)
2308
2339
  );
2309
2340
  }
2310
2341
  async trackMobileMoneyUsage(mobileMoneyId) {
@@ -3430,7 +3461,7 @@ var CimplifyClient = class {
3430
3461
  this.retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY_MS;
3431
3462
  this.hooks = config.hooks ?? {};
3432
3463
  this.accessToken = this.loadAccessToken();
3433
- if (!this.publicKey) {
3464
+ if (!this.publicKey && !config.suppressPublicKeyWarning) {
3434
3465
  console.warn(
3435
3466
  '[Cimplify] No public key found. Set NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY in your environment, or pass { publicKey: "pk_..." } to createCimplifyClient().'
3436
3467
  );
@@ -3543,9 +3574,12 @@ var CimplifyClient = class {
3543
3574
  }
3544
3575
  getHeaders() {
3545
3576
  const headers = {
3546
- "Content-Type": "application/json",
3547
- "X-API-Key": this.publicKey
3577
+ "Content-Type": "application/json"
3548
3578
  };
3579
+ const trimmedPublicKey = this.publicKey.trim();
3580
+ if (trimmedPublicKey) {
3581
+ headers["X-API-Key"] = trimmedPublicKey;
3582
+ }
3549
3583
  if (this.accessToken) {
3550
3584
  headers["Authorization"] = `Bearer ${this.accessToken}`;
3551
3585
  }
@@ -3574,7 +3608,7 @@ var CimplifyClient = class {
3574
3608
  signal: controller.signal
3575
3609
  });
3576
3610
  clearTimeout(timeoutId);
3577
- if (response.ok || response.status >= 400 && response.status < 500) {
3611
+ if (response.ok) {
3578
3612
  this.hooks.onRequestSuccess?.({
3579
3613
  ...context,
3580
3614
  status: response.status,
@@ -3582,6 +3616,21 @@ var CimplifyClient = class {
3582
3616
  });
3583
3617
  return response;
3584
3618
  }
3619
+ if (response.status >= 400 && response.status < 500) {
3620
+ this.hooks.onRequestError?.({
3621
+ ...context,
3622
+ error: new CimplifyError(
3623
+ `HTTP_${response.status}`,
3624
+ `Request failed with status ${response.status}`,
3625
+ false
3626
+ ),
3627
+ status: response.status,
3628
+ durationMs: Date.now() - startTime,
3629
+ retryCount,
3630
+ retryable: false
3631
+ });
3632
+ return response;
3633
+ }
3585
3634
  if (response.status >= 500 && attempt < this.maxRetries) {
3586
3635
  retryCount++;
3587
3636
  const delay = this.retryDelay * Math.pow(2, attempt);
@@ -3594,10 +3643,17 @@ var CimplifyClient = class {
3594
3643
  await sleep(delay);
3595
3644
  continue;
3596
3645
  }
3597
- this.hooks.onRequestSuccess?.({
3646
+ this.hooks.onRequestError?.({
3598
3647
  ...context,
3648
+ error: new CimplifyError(
3649
+ "SERVER_ERROR",
3650
+ `Server error ${response.status} after ${retryCount} retries`,
3651
+ false
3652
+ ),
3599
3653
  status: response.status,
3600
- durationMs: Date.now() - startTime
3654
+ durationMs: Date.now() - startTime,
3655
+ retryCount,
3656
+ retryable: false
3601
3657
  });
3602
3658
  return response;
3603
3659
  } catch (error) {
@@ -5083,6 +5139,750 @@ function useLocations(options = {}) {
5083
5139
  isLoading
5084
5140
  };
5085
5141
  }
5142
+ var collectionsCache = /* @__PURE__ */ new Map();
5143
+ var collectionsInflight = /* @__PURE__ */ new Map();
5144
+ function buildCollectionsCacheKey(client, locationId) {
5145
+ return JSON.stringify({
5146
+ key: client.getPublicKey(),
5147
+ location_id: locationId || "__none__"
5148
+ });
5149
+ }
5150
+ function useCollections(options = {}) {
5151
+ const context = useOptionalCimplify();
5152
+ const client = options.client ?? context?.client;
5153
+ if (!client) {
5154
+ throw new Error("useCollections must be used within CimplifyProvider or passed { client }.");
5155
+ }
5156
+ const enabled = options.enabled ?? true;
5157
+ const locationId = client.getLocationId();
5158
+ const previousLocationIdRef = useRef(locationId);
5159
+ const requestIdRef = useRef(0);
5160
+ const cacheKey = useMemo(
5161
+ () => buildCollectionsCacheKey(client, locationId),
5162
+ [client, locationId]
5163
+ );
5164
+ const cached = collectionsCache.get(cacheKey);
5165
+ const [collections, setCollections] = useState(cached?.collections ?? []);
5166
+ const [isLoading, setIsLoading] = useState(enabled && !cached);
5167
+ const [error, setError] = useState(null);
5168
+ useEffect(() => {
5169
+ if (previousLocationIdRef.current !== locationId) {
5170
+ collectionsCache.clear();
5171
+ collectionsInflight.clear();
5172
+ previousLocationIdRef.current = locationId;
5173
+ }
5174
+ }, [locationId]);
5175
+ const load = useCallback(
5176
+ async (force = false) => {
5177
+ if (!enabled) {
5178
+ setIsLoading(false);
5179
+ return;
5180
+ }
5181
+ const nextRequestId = ++requestIdRef.current;
5182
+ setError(null);
5183
+ if (!force) {
5184
+ const cacheEntry = collectionsCache.get(cacheKey);
5185
+ if (cacheEntry) {
5186
+ setCollections(cacheEntry.collections);
5187
+ setIsLoading(false);
5188
+ return;
5189
+ }
5190
+ }
5191
+ setIsLoading(true);
5192
+ try {
5193
+ const existing = collectionsInflight.get(cacheKey);
5194
+ const promise = existing ?? (async () => {
5195
+ const result = await client.catalogue.getCollections();
5196
+ if (!result.ok) {
5197
+ throw result.error;
5198
+ }
5199
+ return result.value;
5200
+ })();
5201
+ if (!existing) {
5202
+ collectionsInflight.set(cacheKey, promise);
5203
+ promise.finally(() => {
5204
+ collectionsInflight.delete(cacheKey);
5205
+ }).catch(() => void 0);
5206
+ }
5207
+ const value = await promise;
5208
+ collectionsCache.set(cacheKey, { collections: value });
5209
+ if (nextRequestId === requestIdRef.current) {
5210
+ setCollections(value);
5211
+ setError(null);
5212
+ }
5213
+ } catch (loadError) {
5214
+ if (nextRequestId === requestIdRef.current) {
5215
+ setError(loadError);
5216
+ }
5217
+ } finally {
5218
+ if (nextRequestId === requestIdRef.current) {
5219
+ setIsLoading(false);
5220
+ }
5221
+ }
5222
+ },
5223
+ [cacheKey, client, enabled]
5224
+ );
5225
+ useEffect(() => {
5226
+ void load(false);
5227
+ }, [load]);
5228
+ const refetch = useCallback(async () => {
5229
+ collectionsCache.delete(cacheKey);
5230
+ await load(true);
5231
+ }, [cacheKey, load]);
5232
+ return { collections, isLoading, error, refetch };
5233
+ }
5234
+ var collectionCache = /* @__PURE__ */ new Map();
5235
+ var collectionInflight = /* @__PURE__ */ new Map();
5236
+ function isLikelySlug2(value) {
5237
+ return /^[a-z0-9-]+$/.test(value);
5238
+ }
5239
+ function buildCollectionCacheKey(client, locationId, idOrSlug) {
5240
+ return JSON.stringify({
5241
+ key: client.getPublicKey(),
5242
+ location_id: locationId || "__none__",
5243
+ collection: idOrSlug
5244
+ });
5245
+ }
5246
+ function useCollection(idOrSlug, options = {}) {
5247
+ const context = useOptionalCimplify();
5248
+ const client = options.client ?? context?.client;
5249
+ if (!client) {
5250
+ throw new Error("useCollection must be used within CimplifyProvider or passed { client }.");
5251
+ }
5252
+ const enabled = options.enabled ?? true;
5253
+ const locationId = client.getLocationId();
5254
+ const previousLocationIdRef = useRef(locationId);
5255
+ const requestIdRef = useRef(0);
5256
+ const normalizedIdOrSlug = useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5257
+ const cacheKey = useMemo(
5258
+ () => buildCollectionCacheKey(client, locationId, normalizedIdOrSlug),
5259
+ [client, locationId, normalizedIdOrSlug]
5260
+ );
5261
+ const cached = collectionCache.get(cacheKey);
5262
+ const [collection, setCollection] = useState(cached?.collection ?? null);
5263
+ const [products, setProducts] = useState(cached?.products ?? []);
5264
+ const [isLoading, setIsLoading] = useState(
5265
+ enabled && normalizedIdOrSlug.length > 0 && !cached
5266
+ );
5267
+ const [error, setError] = useState(null);
5268
+ useEffect(() => {
5269
+ if (previousLocationIdRef.current !== locationId) {
5270
+ collectionCache.clear();
5271
+ collectionInflight.clear();
5272
+ previousLocationIdRef.current = locationId;
5273
+ }
5274
+ }, [locationId]);
5275
+ const load = useCallback(
5276
+ async (force = false) => {
5277
+ if (!enabled || normalizedIdOrSlug.length === 0) {
5278
+ setCollection(null);
5279
+ setProducts([]);
5280
+ setIsLoading(false);
5281
+ return;
5282
+ }
5283
+ const nextRequestId = ++requestIdRef.current;
5284
+ setError(null);
5285
+ if (!force) {
5286
+ const cacheEntry = collectionCache.get(cacheKey);
5287
+ if (cacheEntry) {
5288
+ setCollection(cacheEntry.collection);
5289
+ setProducts(cacheEntry.products);
5290
+ setIsLoading(false);
5291
+ return;
5292
+ }
5293
+ }
5294
+ setIsLoading(true);
5295
+ try {
5296
+ const existing = collectionInflight.get(cacheKey);
5297
+ const promise = existing ?? (async () => {
5298
+ const collectionResult = isLikelySlug2(normalizedIdOrSlug) ? await client.catalogue.getCollectionBySlug(normalizedIdOrSlug) : await client.catalogue.getCollection(normalizedIdOrSlug);
5299
+ if (!collectionResult.ok) {
5300
+ throw collectionResult.error;
5301
+ }
5302
+ const productsResult = await client.catalogue.getCollectionProducts(
5303
+ collectionResult.value.id
5304
+ );
5305
+ if (!productsResult.ok) {
5306
+ throw productsResult.error;
5307
+ }
5308
+ return {
5309
+ collection: collectionResult.value,
5310
+ products: productsResult.value
5311
+ };
5312
+ })();
5313
+ if (!existing) {
5314
+ collectionInflight.set(cacheKey, promise);
5315
+ promise.finally(() => {
5316
+ collectionInflight.delete(cacheKey);
5317
+ }).catch(() => void 0);
5318
+ }
5319
+ const value = await promise;
5320
+ collectionCache.set(cacheKey, value);
5321
+ if (nextRequestId === requestIdRef.current) {
5322
+ setCollection(value.collection);
5323
+ setProducts(value.products);
5324
+ setError(null);
5325
+ }
5326
+ } catch (loadError) {
5327
+ if (nextRequestId === requestIdRef.current) {
5328
+ setError(loadError);
5329
+ }
5330
+ } finally {
5331
+ if (nextRequestId === requestIdRef.current) {
5332
+ setIsLoading(false);
5333
+ }
5334
+ }
5335
+ },
5336
+ [cacheKey, client, enabled, normalizedIdOrSlug]
5337
+ );
5338
+ useEffect(() => {
5339
+ void load(false);
5340
+ }, [load]);
5341
+ const refetch = useCallback(async () => {
5342
+ collectionCache.delete(cacheKey);
5343
+ await load(true);
5344
+ }, [cacheKey, load]);
5345
+ return { collection, products, isLoading, error, refetch };
5346
+ }
5347
+ var bundleCache = /* @__PURE__ */ new Map();
5348
+ var bundleInflight = /* @__PURE__ */ new Map();
5349
+ function isLikelySlug3(value) {
5350
+ return /^[a-z0-9-]+$/.test(value);
5351
+ }
5352
+ function buildBundleCacheKey(client, locationId, idOrSlug) {
5353
+ return JSON.stringify({
5354
+ key: client.getPublicKey(),
5355
+ location_id: locationId || "__none__",
5356
+ bundle: idOrSlug
5357
+ });
5358
+ }
5359
+ function useBundle(idOrSlug, options = {}) {
5360
+ const context = useOptionalCimplify();
5361
+ const client = options.client ?? context?.client;
5362
+ if (!client) {
5363
+ throw new Error("useBundle must be used within CimplifyProvider or passed { client }.");
5364
+ }
5365
+ const enabled = options.enabled ?? true;
5366
+ const locationId = client.getLocationId();
5367
+ const previousLocationIdRef = useRef(locationId);
5368
+ const requestIdRef = useRef(0);
5369
+ const normalizedIdOrSlug = useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5370
+ const cacheKey = useMemo(
5371
+ () => buildBundleCacheKey(client, locationId, normalizedIdOrSlug),
5372
+ [client, locationId, normalizedIdOrSlug]
5373
+ );
5374
+ const cached = bundleCache.get(cacheKey);
5375
+ const [bundle, setBundle] = useState(cached?.bundle ?? null);
5376
+ const [isLoading, setIsLoading] = useState(
5377
+ enabled && normalizedIdOrSlug.length > 0 && !cached
5378
+ );
5379
+ const [error, setError] = useState(null);
5380
+ useEffect(() => {
5381
+ if (previousLocationIdRef.current !== locationId) {
5382
+ bundleCache.clear();
5383
+ bundleInflight.clear();
5384
+ previousLocationIdRef.current = locationId;
5385
+ }
5386
+ }, [locationId]);
5387
+ const load = useCallback(
5388
+ async (force = false) => {
5389
+ if (!enabled || normalizedIdOrSlug.length === 0) {
5390
+ setBundle(null);
5391
+ setIsLoading(false);
5392
+ return;
5393
+ }
5394
+ const nextRequestId = ++requestIdRef.current;
5395
+ setError(null);
5396
+ if (!force) {
5397
+ const cacheEntry = bundleCache.get(cacheKey);
5398
+ if (cacheEntry) {
5399
+ setBundle(cacheEntry.bundle);
5400
+ setIsLoading(false);
5401
+ return;
5402
+ }
5403
+ }
5404
+ setIsLoading(true);
5405
+ try {
5406
+ const existing = bundleInflight.get(cacheKey);
5407
+ const promise = existing ?? (async () => {
5408
+ const result = isLikelySlug3(normalizedIdOrSlug) ? await client.catalogue.getBundleBySlug(normalizedIdOrSlug) : await client.catalogue.getBundle(normalizedIdOrSlug);
5409
+ if (!result.ok) {
5410
+ throw result.error;
5411
+ }
5412
+ return result.value;
5413
+ })();
5414
+ if (!existing) {
5415
+ bundleInflight.set(cacheKey, promise);
5416
+ promise.finally(() => {
5417
+ bundleInflight.delete(cacheKey);
5418
+ }).catch(() => void 0);
5419
+ }
5420
+ const value = await promise;
5421
+ bundleCache.set(cacheKey, { bundle: value });
5422
+ if (nextRequestId === requestIdRef.current) {
5423
+ setBundle(value);
5424
+ setError(null);
5425
+ }
5426
+ } catch (loadError) {
5427
+ if (nextRequestId === requestIdRef.current) {
5428
+ setError(loadError);
5429
+ }
5430
+ } finally {
5431
+ if (nextRequestId === requestIdRef.current) {
5432
+ setIsLoading(false);
5433
+ }
5434
+ }
5435
+ },
5436
+ [cacheKey, client, enabled, normalizedIdOrSlug]
5437
+ );
5438
+ useEffect(() => {
5439
+ void load(false);
5440
+ }, [load]);
5441
+ const refetch = useCallback(async () => {
5442
+ bundleCache.delete(cacheKey);
5443
+ await load(true);
5444
+ }, [cacheKey, load]);
5445
+ return { bundle, isLoading, error, refetch };
5446
+ }
5447
+ var compositeCache = /* @__PURE__ */ new Map();
5448
+ var compositeInflight = /* @__PURE__ */ new Map();
5449
+ function shouldFetchByProductId(idOrProductId, byProductId) {
5450
+ if (typeof byProductId === "boolean") {
5451
+ return byProductId;
5452
+ }
5453
+ return idOrProductId.startsWith("prod_");
5454
+ }
5455
+ function buildCompositeCacheKey(client, locationId, idOrProductId, byProductId) {
5456
+ return JSON.stringify({
5457
+ key: client.getPublicKey(),
5458
+ location_id: locationId || "__none__",
5459
+ composite: idOrProductId,
5460
+ by_product_id: byProductId
5461
+ });
5462
+ }
5463
+ function useComposite(idOrProductId, options = {}) {
5464
+ const context = useOptionalCimplify();
5465
+ const client = options.client ?? context?.client;
5466
+ if (!client) {
5467
+ throw new Error("useComposite must be used within CimplifyProvider or passed { client }.");
5468
+ }
5469
+ const enabled = options.enabled ?? true;
5470
+ const locationId = client.getLocationId();
5471
+ const previousLocationIdRef = useRef(locationId);
5472
+ const requestIdRef = useRef(0);
5473
+ const priceRequestIdRef = useRef(0);
5474
+ const normalizedIdOrProductId = useMemo(
5475
+ () => (idOrProductId || "").trim(),
5476
+ [idOrProductId]
5477
+ );
5478
+ const byProductId = useMemo(
5479
+ () => shouldFetchByProductId(normalizedIdOrProductId, options.byProductId),
5480
+ [normalizedIdOrProductId, options.byProductId]
5481
+ );
5482
+ const cacheKey = useMemo(
5483
+ () => buildCompositeCacheKey(client, locationId, normalizedIdOrProductId, byProductId),
5484
+ [byProductId, client, locationId, normalizedIdOrProductId]
5485
+ );
5486
+ const cached = compositeCache.get(cacheKey);
5487
+ const [composite, setComposite] = useState(cached?.composite ?? null);
5488
+ const [isLoading, setIsLoading] = useState(
5489
+ enabled && normalizedIdOrProductId.length > 0 && !cached
5490
+ );
5491
+ const [error, setError] = useState(null);
5492
+ const [priceResult, setPriceResult] = useState(null);
5493
+ const [isPriceLoading, setIsPriceLoading] = useState(false);
5494
+ useEffect(() => {
5495
+ if (previousLocationIdRef.current !== locationId) {
5496
+ compositeCache.clear();
5497
+ compositeInflight.clear();
5498
+ previousLocationIdRef.current = locationId;
5499
+ }
5500
+ }, [locationId]);
5501
+ const load = useCallback(
5502
+ async (force = false) => {
5503
+ if (!enabled || normalizedIdOrProductId.length === 0) {
5504
+ setComposite(null);
5505
+ setPriceResult(null);
5506
+ setIsLoading(false);
5507
+ return;
5508
+ }
5509
+ const nextRequestId = ++requestIdRef.current;
5510
+ setError(null);
5511
+ if (!force) {
5512
+ const cacheEntry = compositeCache.get(cacheKey);
5513
+ if (cacheEntry) {
5514
+ setComposite(cacheEntry.composite);
5515
+ setIsLoading(false);
5516
+ return;
5517
+ }
5518
+ }
5519
+ setIsLoading(true);
5520
+ try {
5521
+ const existing = compositeInflight.get(cacheKey);
5522
+ const promise = existing ?? (async () => {
5523
+ const result = byProductId ? await client.catalogue.getCompositeByProductId(normalizedIdOrProductId) : await client.catalogue.getComposite(normalizedIdOrProductId);
5524
+ if (!result.ok) {
5525
+ throw result.error;
5526
+ }
5527
+ return result.value;
5528
+ })();
5529
+ if (!existing) {
5530
+ compositeInflight.set(cacheKey, promise);
5531
+ promise.finally(() => {
5532
+ compositeInflight.delete(cacheKey);
5533
+ }).catch(() => void 0);
5534
+ }
5535
+ const value = await promise;
5536
+ compositeCache.set(cacheKey, { composite: value });
5537
+ if (nextRequestId === requestIdRef.current) {
5538
+ setComposite(value);
5539
+ setPriceResult(null);
5540
+ setError(null);
5541
+ }
5542
+ } catch (loadError) {
5543
+ if (nextRequestId === requestIdRef.current) {
5544
+ setError(loadError);
5545
+ }
5546
+ } finally {
5547
+ if (nextRequestId === requestIdRef.current) {
5548
+ setIsLoading(false);
5549
+ }
5550
+ }
5551
+ },
5552
+ [byProductId, cacheKey, client, enabled, normalizedIdOrProductId]
5553
+ );
5554
+ useEffect(() => {
5555
+ void load(false);
5556
+ }, [load]);
5557
+ const calculatePrice = useCallback(
5558
+ async (selections, overrideLocationId) => {
5559
+ if (!composite) {
5560
+ return null;
5561
+ }
5562
+ const nextRequestId = ++priceRequestIdRef.current;
5563
+ setIsPriceLoading(true);
5564
+ try {
5565
+ const result = await client.catalogue.calculateCompositePrice(
5566
+ composite.id,
5567
+ selections,
5568
+ overrideLocationId
5569
+ );
5570
+ if (!result.ok) {
5571
+ throw result.error;
5572
+ }
5573
+ if (nextRequestId === priceRequestIdRef.current) {
5574
+ setPriceResult(result.value);
5575
+ setError(null);
5576
+ }
5577
+ return result.value;
5578
+ } catch (loadError) {
5579
+ if (nextRequestId === priceRequestIdRef.current) {
5580
+ setError(loadError);
5581
+ }
5582
+ return null;
5583
+ } finally {
5584
+ if (nextRequestId === priceRequestIdRef.current) {
5585
+ setIsPriceLoading(false);
5586
+ }
5587
+ }
5588
+ },
5589
+ [client, composite]
5590
+ );
5591
+ const refetch = useCallback(async () => {
5592
+ compositeCache.delete(cacheKey);
5593
+ await load(true);
5594
+ }, [cacheKey, load]);
5595
+ return { composite, isLoading, error, refetch, calculatePrice, priceResult, isPriceLoading };
5596
+ }
5597
+ function useSearch(options = {}) {
5598
+ const context = useOptionalCimplify();
5599
+ const client = options.client ?? context?.client;
5600
+ if (!client) {
5601
+ throw new Error("useSearch must be used within CimplifyProvider or passed { client }.");
5602
+ }
5603
+ const minLength = Math.max(0, options.minLength ?? 2);
5604
+ const debounceMs = Math.max(0, options.debounceMs ?? 300);
5605
+ const limit = Math.max(1, options.limit ?? 20);
5606
+ const [query, setQueryState] = useState("");
5607
+ const [results, setResults] = useState([]);
5608
+ const [isLoading, setIsLoading] = useState(false);
5609
+ const [error, setError] = useState(null);
5610
+ const requestIdRef = useRef(0);
5611
+ const timerRef = useRef(null);
5612
+ useEffect(() => {
5613
+ if (timerRef.current) {
5614
+ clearTimeout(timerRef.current);
5615
+ timerRef.current = null;
5616
+ }
5617
+ const trimmedQuery = query.trim();
5618
+ if (trimmedQuery.length < minLength) {
5619
+ setResults([]);
5620
+ setError(null);
5621
+ setIsLoading(false);
5622
+ return;
5623
+ }
5624
+ const nextRequestId = ++requestIdRef.current;
5625
+ setError(null);
5626
+ setIsLoading(true);
5627
+ timerRef.current = setTimeout(() => {
5628
+ void (async () => {
5629
+ try {
5630
+ const result = await client.catalogue.searchProducts(trimmedQuery, {
5631
+ limit,
5632
+ category: options.category
5633
+ });
5634
+ if (!result.ok) {
5635
+ throw result.error;
5636
+ }
5637
+ if (nextRequestId === requestIdRef.current) {
5638
+ setResults(result.value);
5639
+ setError(null);
5640
+ }
5641
+ } catch (loadError) {
5642
+ if (nextRequestId === requestIdRef.current) {
5643
+ setError(loadError);
5644
+ }
5645
+ } finally {
5646
+ if (nextRequestId === requestIdRef.current) {
5647
+ setIsLoading(false);
5648
+ }
5649
+ }
5650
+ })();
5651
+ }, debounceMs);
5652
+ return () => {
5653
+ if (timerRef.current) {
5654
+ clearTimeout(timerRef.current);
5655
+ timerRef.current = null;
5656
+ }
5657
+ };
5658
+ }, [client, debounceMs, limit, minLength, options.category, query]);
5659
+ const setQuery = useCallback((nextQuery) => {
5660
+ setQueryState(nextQuery);
5661
+ }, []);
5662
+ const clear = useCallback(() => {
5663
+ requestIdRef.current += 1;
5664
+ if (timerRef.current) {
5665
+ clearTimeout(timerRef.current);
5666
+ timerRef.current = null;
5667
+ }
5668
+ setQueryState("");
5669
+ setResults([]);
5670
+ setError(null);
5671
+ setIsLoading(false);
5672
+ }, []);
5673
+ return { results, isLoading, error, query, setQuery, clear };
5674
+ }
5675
+ var quoteCache = /* @__PURE__ */ new Map();
5676
+ var quoteInflight = /* @__PURE__ */ new Map();
5677
+ function buildQuoteCacheKey(client, locationId, inputSignature) {
5678
+ return JSON.stringify({
5679
+ key: client.getPublicKey(),
5680
+ location_id: locationId || "__none__",
5681
+ input: inputSignature
5682
+ });
5683
+ }
5684
+ function isQuoteExpired(quote) {
5685
+ if (!quote?.expires_at) {
5686
+ return false;
5687
+ }
5688
+ const expiresAt = Date.parse(quote.expires_at);
5689
+ if (!Number.isFinite(expiresAt)) {
5690
+ return false;
5691
+ }
5692
+ return expiresAt <= Date.now();
5693
+ }
5694
+ function normalizeInput(input, fallbackLocationId) {
5695
+ const productId = input.productId.trim();
5696
+ const variantId = input.variantId?.trim();
5697
+ const locationId = input.locationId?.trim() || fallbackLocationId || void 0;
5698
+ return {
5699
+ product_id: productId,
5700
+ variant_id: variantId && variantId.length > 0 ? variantId : void 0,
5701
+ location_id: locationId && locationId.length > 0 ? locationId : void 0,
5702
+ quantity: input.quantity,
5703
+ add_on_option_ids: input.addOnOptionIds,
5704
+ bundle_selections: input.bundleSelections,
5705
+ composite_selections: input.compositeSelections
5706
+ };
5707
+ }
5708
+ function useQuote(input, options = {}) {
5709
+ const context = useOptionalCimplify();
5710
+ const client = options.client ?? context?.client;
5711
+ if (!client) {
5712
+ throw new Error("useQuote must be used within CimplifyProvider or passed { client }.");
5713
+ }
5714
+ const enabled = options.enabled ?? true;
5715
+ const autoRefresh = options.autoRefresh ?? true;
5716
+ const refreshBeforeExpiryMs = Math.max(0, options.refreshBeforeExpiryMs ?? 3e4);
5717
+ const locationId = client.getLocationId();
5718
+ const requestIdRef = useRef(0);
5719
+ const refreshTimerRef = useRef(null);
5720
+ const expiryTimerRef = useRef(null);
5721
+ const inputSignature = useMemo(() => JSON.stringify(input ?? null), [input]);
5722
+ const normalizedInput = useMemo(() => {
5723
+ if (!input) {
5724
+ return null;
5725
+ }
5726
+ const normalized = normalizeInput(input, locationId);
5727
+ return normalized.product_id.length > 0 ? normalized : null;
5728
+ }, [inputSignature, locationId]);
5729
+ const cacheKey = useMemo(
5730
+ () => buildQuoteCacheKey(client, locationId, inputSignature),
5731
+ [client, inputSignature, locationId]
5732
+ );
5733
+ const cached = quoteCache.get(cacheKey);
5734
+ const [quote, setQuote] = useState(cached?.quote ?? null);
5735
+ const [isLoading, setIsLoading] = useState(enabled && normalizedInput !== null && !cached);
5736
+ const [error, setError] = useState(null);
5737
+ const [isExpired, setIsExpired] = useState(isQuoteExpired(cached?.quote ?? null));
5738
+ const [messages, setMessages] = useState(cached?.quote?.ui_messages ?? []);
5739
+ const load = useCallback(
5740
+ async (force = false) => {
5741
+ if (!enabled || !normalizedInput) {
5742
+ setQuote(null);
5743
+ setMessages([]);
5744
+ setIsExpired(false);
5745
+ setError(null);
5746
+ setIsLoading(false);
5747
+ return;
5748
+ }
5749
+ const nextRequestId = ++requestIdRef.current;
5750
+ setError(null);
5751
+ if (!force) {
5752
+ const cacheEntry = quoteCache.get(cacheKey);
5753
+ if (cacheEntry) {
5754
+ setQuote(cacheEntry.quote);
5755
+ setMessages(cacheEntry.quote?.ui_messages ?? []);
5756
+ setIsExpired(isQuoteExpired(cacheEntry.quote));
5757
+ setIsLoading(false);
5758
+ return;
5759
+ }
5760
+ }
5761
+ setIsLoading(true);
5762
+ try {
5763
+ const existing = quoteInflight.get(cacheKey);
5764
+ const promise = existing ?? (async () => {
5765
+ const result = await client.catalogue.fetchQuote(normalizedInput);
5766
+ if (!result.ok) {
5767
+ throw result.error;
5768
+ }
5769
+ return result.value;
5770
+ })();
5771
+ if (!existing) {
5772
+ quoteInflight.set(cacheKey, promise);
5773
+ promise.finally(() => {
5774
+ quoteInflight.delete(cacheKey);
5775
+ }).catch(() => void 0);
5776
+ }
5777
+ const value = await promise;
5778
+ quoteCache.set(cacheKey, { quote: value });
5779
+ if (nextRequestId === requestIdRef.current) {
5780
+ setQuote(value);
5781
+ setMessages(value.ui_messages ?? []);
5782
+ setIsExpired(isQuoteExpired(value));
5783
+ setError(null);
5784
+ }
5785
+ } catch (loadError) {
5786
+ if (nextRequestId === requestIdRef.current) {
5787
+ setError(loadError);
5788
+ }
5789
+ } finally {
5790
+ if (nextRequestId === requestIdRef.current) {
5791
+ setIsLoading(false);
5792
+ }
5793
+ }
5794
+ },
5795
+ [cacheKey, client, enabled, normalizedInput]
5796
+ );
5797
+ useEffect(() => {
5798
+ void load(false);
5799
+ }, [load]);
5800
+ const refresh = useCallback(async () => {
5801
+ if (!enabled || !normalizedInput) {
5802
+ return;
5803
+ }
5804
+ if (!quote?.quote_id) {
5805
+ await load(true);
5806
+ return;
5807
+ }
5808
+ const nextRequestId = ++requestIdRef.current;
5809
+ setError(null);
5810
+ setIsLoading(true);
5811
+ try {
5812
+ const result = await client.catalogue.refreshQuote({
5813
+ quote_id: quote.quote_id,
5814
+ ...normalizedInput
5815
+ });
5816
+ if (!result.ok) {
5817
+ throw result.error;
5818
+ }
5819
+ const refreshed = result.value.quote;
5820
+ quoteCache.set(cacheKey, { quote: refreshed });
5821
+ if (nextRequestId === requestIdRef.current) {
5822
+ setQuote(refreshed);
5823
+ setMessages(refreshed.ui_messages ?? []);
5824
+ setIsExpired(isQuoteExpired(refreshed));
5825
+ setError(null);
5826
+ }
5827
+ } catch (refreshError) {
5828
+ if (nextRequestId === requestIdRef.current) {
5829
+ setError(refreshError);
5830
+ }
5831
+ } finally {
5832
+ if (nextRequestId === requestIdRef.current) {
5833
+ setIsLoading(false);
5834
+ }
5835
+ }
5836
+ }, [cacheKey, client, enabled, load, normalizedInput, quote]);
5837
+ useEffect(() => {
5838
+ if (expiryTimerRef.current) {
5839
+ clearTimeout(expiryTimerRef.current);
5840
+ expiryTimerRef.current = null;
5841
+ }
5842
+ const expiresAt = quote?.expires_at ? Date.parse(quote.expires_at) : NaN;
5843
+ if (!Number.isFinite(expiresAt)) {
5844
+ setIsExpired(false);
5845
+ return;
5846
+ }
5847
+ const expired = expiresAt <= Date.now();
5848
+ setIsExpired(expired);
5849
+ if (!expired) {
5850
+ expiryTimerRef.current = setTimeout(() => {
5851
+ setIsExpired(true);
5852
+ }, Math.max(0, expiresAt - Date.now()));
5853
+ }
5854
+ return () => {
5855
+ if (expiryTimerRef.current) {
5856
+ clearTimeout(expiryTimerRef.current);
5857
+ expiryTimerRef.current = null;
5858
+ }
5859
+ };
5860
+ }, [quote?.expires_at, quote?.quote_id]);
5861
+ useEffect(() => {
5862
+ if (refreshTimerRef.current) {
5863
+ clearTimeout(refreshTimerRef.current);
5864
+ refreshTimerRef.current = null;
5865
+ }
5866
+ if (!autoRefresh || !enabled || !quote?.expires_at) {
5867
+ return;
5868
+ }
5869
+ const expiresAt = Date.parse(quote.expires_at);
5870
+ if (!Number.isFinite(expiresAt)) {
5871
+ return;
5872
+ }
5873
+ const delay = Math.max(0, expiresAt - Date.now() - refreshBeforeExpiryMs);
5874
+ refreshTimerRef.current = setTimeout(() => {
5875
+ void refresh();
5876
+ }, delay);
5877
+ return () => {
5878
+ if (refreshTimerRef.current) {
5879
+ clearTimeout(refreshTimerRef.current);
5880
+ refreshTimerRef.current = null;
5881
+ }
5882
+ };
5883
+ }, [autoRefresh, enabled, quote?.expires_at, quote?.quote_id, refresh, refreshBeforeExpiryMs]);
5884
+ return { quote, isLoading, error, refresh, isExpired, messages };
5885
+ }
5086
5886
  var ElementsContext = createContext({
5087
5887
  elements: null,
5088
5888
  isReady: false
@@ -5243,4 +6043,4 @@ function useCheckout() {
5243
6043
  return { submit, process, isLoading };
5244
6044
  }
5245
6045
 
5246
- export { Ad, AdProvider, AddressElement, AuthElement, CimplifyCheckout, CimplifyProvider, ElementsProvider, PaymentElement, useAds, useCart, useCategories, useCheckout, useCimplify, useElements, useElementsReady, useLocations, useOptionalCimplify, useOrder, useProduct, useProducts };
6046
+ export { Ad, AdProvider, AddressElement, AuthElement, CimplifyCheckout, CimplifyProvider, ElementsProvider, PaymentElement, useAds, useBundle, useCart, useCategories, useCheckout, useCimplify, useCollection, useCollections, useComposite, useElements, useElementsReady, useLocations, useOptionalCimplify, useOrder, useProduct, useProducts, useQuote, useSearch };