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