@cimplify/sdk 0.3.5 → 0.4.0

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/index.mjs CHANGED
@@ -153,9 +153,6 @@ var CatalogueQueries = class {
153
153
  constructor(client) {
154
154
  this.client = client;
155
155
  }
156
- // --------------------------------------------------------------------------
157
- // PRODUCTS
158
- // --------------------------------------------------------------------------
159
156
  async getProducts(options) {
160
157
  let query2 = "products";
161
158
  const filters = [];
@@ -204,9 +201,6 @@ var CatalogueQueries = class {
204
201
  }
205
202
  return ok(result.value[0]);
206
203
  }
207
- // --------------------------------------------------------------------------
208
- // VARIANTS
209
- // --------------------------------------------------------------------------
210
204
  async getVariants(productId) {
211
205
  return safe(this.client.query(`products.${productId}.variants`));
212
206
  }
@@ -230,15 +224,9 @@ var CatalogueQueries = class {
230
224
  async getVariantById(productId, variantId) {
231
225
  return safe(this.client.query(`products.${productId}.variant.${variantId}`));
232
226
  }
233
- // --------------------------------------------------------------------------
234
- // ADD-ONS
235
- // --------------------------------------------------------------------------
236
227
  async getAddOns(productId) {
237
228
  return safe(this.client.query(`products.${productId}.add_ons`));
238
229
  }
239
- // --------------------------------------------------------------------------
240
- // CATEGORIES
241
- // --------------------------------------------------------------------------
242
230
  async getCategories() {
243
231
  return safe(this.client.query("categories"));
244
232
  }
@@ -258,9 +246,6 @@ var CatalogueQueries = class {
258
246
  async getCategoryProducts(categoryId) {
259
247
  return safe(this.client.query(`products[?(@.category_id=='${categoryId}')]`));
260
248
  }
261
- // --------------------------------------------------------------------------
262
- // COLLECTIONS
263
- // --------------------------------------------------------------------------
264
249
  async getCollections() {
265
250
  return safe(this.client.query("collections"));
266
251
  }
@@ -285,9 +270,6 @@ var CatalogueQueries = class {
285
270
  this.client.query(`collections[?(@.name contains '${query2}')]#limit(${limit})`)
286
271
  );
287
272
  }
288
- // --------------------------------------------------------------------------
289
- // BUNDLES
290
- // --------------------------------------------------------------------------
291
273
  async getBundles() {
292
274
  return safe(this.client.query("bundles"));
293
275
  }
@@ -309,9 +291,6 @@ var CatalogueQueries = class {
309
291
  this.client.query(`bundles[?(@.name contains '${query2}')]#limit(${limit})`)
310
292
  );
311
293
  }
312
- // --------------------------------------------------------------------------
313
- // COMPOSITES (Build-Your-Own)
314
- // --------------------------------------------------------------------------
315
294
  async getComposites(options) {
316
295
  let query2 = "composites";
317
296
  if (options?.limit) {
@@ -334,9 +313,6 @@ var CatalogueQueries = class {
334
313
  })
335
314
  );
336
315
  }
337
- // --------------------------------------------------------------------------
338
- // SEARCH
339
- // --------------------------------------------------------------------------
340
316
  async search(query2, options) {
341
317
  const limit = options?.limit ?? 20;
342
318
  let searchQuery = `products[?(@.name contains '${query2}')]`;
@@ -355,9 +331,6 @@ var CatalogueQueries = class {
355
331
  })
356
332
  );
357
333
  }
358
- // --------------------------------------------------------------------------
359
- // MENU (Restaurant-specific)
360
- // --------------------------------------------------------------------------
361
334
  async getMenu(options) {
362
335
  let query2 = "menu";
363
336
  if (options?.category) {
@@ -395,13 +368,6 @@ var CartOperations = class {
395
368
  constructor(client) {
396
369
  this.client = client;
397
370
  }
398
- // --------------------------------------------------------------------------
399
- // CART QUERIES
400
- // --------------------------------------------------------------------------
401
- /**
402
- * Get the enriched cart with product names, images, and details.
403
- * This is the main method for storefront display.
404
- */
405
371
  async get() {
406
372
  return safe2(this.client.query("cart#enriched"));
407
373
  }
@@ -431,33 +397,6 @@ var CartOperations = class {
431
397
  currency: cart.pricing.currency
432
398
  });
433
399
  }
434
- // --------------------------------------------------------------------------
435
- // CART MUTATIONS
436
- // --------------------------------------------------------------------------
437
- /**
438
- * Add an item to the cart.
439
- *
440
- * @example
441
- * ```typescript
442
- * const result = await client.cart.addItem({
443
- * item_id: "prod_burger",
444
- * quantity: 2,
445
- * variant_id: "var_large",
446
- * add_on_options: ["addon_cheese", "addon_bacon"],
447
- * });
448
- *
449
- * if (!result.ok) {
450
- * switch (result.error.code) {
451
- * case ErrorCode.ITEM_UNAVAILABLE:
452
- * toast.error("Item no longer available");
453
- * break;
454
- * case ErrorCode.VARIANT_OUT_OF_STOCK:
455
- * toast.error("Selected option is out of stock");
456
- * break;
457
- * }
458
- * }
459
- * ```
460
- */
461
400
  async addItem(input) {
462
401
  return safe2(this.client.call("cart.addItem", input));
463
402
  }
@@ -487,9 +426,6 @@ var CartOperations = class {
487
426
  async clear() {
488
427
  return safe2(this.client.call("cart.clearCart"));
489
428
  }
490
- // --------------------------------------------------------------------------
491
- // COUPONS & DISCOUNTS
492
- // --------------------------------------------------------------------------
493
429
  async applyCoupon(code) {
494
430
  return safe2(
495
431
  this.client.call("cart.applyCoupon", {
@@ -500,9 +436,6 @@ var CartOperations = class {
500
436
  async removeCoupon() {
501
437
  return safe2(this.client.call("cart.removeCoupon"));
502
438
  }
503
- // --------------------------------------------------------------------------
504
- // CONVENIENCE METHODS
505
- // --------------------------------------------------------------------------
506
439
  async isEmpty() {
507
440
  const countResult = await this.getCount();
508
441
  if (!countResult.ok) return countResult;
@@ -586,6 +519,15 @@ var AUTHORIZATION_TYPE = {
586
519
  BIRTHDAY: "birthday",
587
520
  ADDRESS: "address"
588
521
  };
522
+ var DEVICE_TYPE = {
523
+ MOBILE: "mobile",
524
+ DESKTOP: "desktop",
525
+ TABLET: "tablet"
526
+ };
527
+ var CONTACT_TYPE = {
528
+ PHONE: "phone",
529
+ EMAIL: "email"
530
+ };
589
531
  var LINK_QUERY = {
590
532
  DATA: "link.data",
591
533
  ADDRESSES: "link.addresses",
@@ -655,35 +597,6 @@ var CheckoutService = class {
655
597
  constructor(client) {
656
598
  this.client = client;
657
599
  }
658
- /**
659
- * Process checkout with cart data.
660
- *
661
- * Automatically generates an idempotency key if not provided to ensure
662
- * payment safety. The same key is used across retries, preventing
663
- * duplicate charges if a network error occurs after payment processing.
664
- *
665
- * @example
666
- * ```typescript
667
- * const result = await client.checkout.process({
668
- * cart_id: cart.id,
669
- * customer: { name, email, phone, save_details: true },
670
- * order_type: "pickup",
671
- * payment_method: "mobile_money",
672
- * mobile_money_details: { phone_number, provider: "mtn" },
673
- * });
674
- *
675
- * if (!result.ok) {
676
- * switch (result.error.code) {
677
- * case ErrorCode.CART_EMPTY:
678
- * toast.error("Your cart is empty");
679
- * break;
680
- * case ErrorCode.PAYMENT_FAILED:
681
- * toast.error("Payment failed. Please try again.");
682
- * break;
683
- * }
684
- * }
685
- * ```
686
- */
687
600
  async process(data) {
688
601
  const checkoutData = {
689
602
  ...data,
@@ -801,9 +714,6 @@ var LinkService = class {
801
714
  constructor(client) {
802
715
  this.client = client;
803
716
  }
804
- // --------------------------------------------------------------------------
805
- // AUTHENTICATION
806
- // --------------------------------------------------------------------------
807
717
  async requestOtp(input) {
808
718
  return safe5(this.client.linkPost("/v1/link/auth/request-otp", input));
809
719
  }
@@ -823,9 +733,6 @@ var LinkService = class {
823
733
  }
824
734
  return result;
825
735
  }
826
- // --------------------------------------------------------------------------
827
- // STATUS & DATA
828
- // --------------------------------------------------------------------------
829
736
  async checkStatus(contact) {
830
737
  return safe5(
831
738
  this.client.call(LINK_MUTATION.CHECK_STATUS, {
@@ -845,9 +752,6 @@ var LinkService = class {
845
752
  async getPreferences() {
846
753
  return safe5(this.client.query(LINK_QUERY.PREFERENCES));
847
754
  }
848
- // --------------------------------------------------------------------------
849
- // ENROLLMENT
850
- // --------------------------------------------------------------------------
851
755
  async enroll(data) {
852
756
  return safe5(this.client.call(LINK_MUTATION.ENROLL, data));
853
757
  }
@@ -856,15 +760,9 @@ var LinkService = class {
856
760
  this.client.call(LINK_MUTATION.ENROLL_AND_LINK_ORDER, data)
857
761
  );
858
762
  }
859
- // --------------------------------------------------------------------------
860
- // PREFERENCES
861
- // --------------------------------------------------------------------------
862
763
  async updatePreferences(preferences) {
863
764
  return safe5(this.client.call(LINK_MUTATION.UPDATE_PREFERENCES, preferences));
864
765
  }
865
- // --------------------------------------------------------------------------
866
- // ADDRESSES
867
- // --------------------------------------------------------------------------
868
766
  async createAddress(input) {
869
767
  return safe5(this.client.call(LINK_MUTATION.CREATE_ADDRESS, input));
870
768
  }
@@ -884,9 +782,6 @@ var LinkService = class {
884
782
  })
885
783
  );
886
784
  }
887
- // --------------------------------------------------------------------------
888
- // MOBILE MONEY
889
- // --------------------------------------------------------------------------
890
785
  async createMobileMoney(input) {
891
786
  return safe5(this.client.call(LINK_MUTATION.CREATE_MOBILE_MONEY, input));
892
787
  }
@@ -910,9 +805,6 @@ var LinkService = class {
910
805
  this.client.call(LINK_MUTATION.VERIFY_MOBILE_MONEY, mobileMoneyId)
911
806
  );
912
807
  }
913
- // --------------------------------------------------------------------------
914
- // SESSIONS
915
- // --------------------------------------------------------------------------
916
808
  async getSessions() {
917
809
  return safe5(this.client.linkGet("/v1/link/sessions"));
918
810
  }
@@ -922,9 +814,6 @@ var LinkService = class {
922
814
  async revokeAllSessions() {
923
815
  return safe5(this.client.linkDelete("/v1/link/sessions"));
924
816
  }
925
- // --------------------------------------------------------------------------
926
- // REST ALTERNATIVES (for direct API access)
927
- // --------------------------------------------------------------------------
928
817
  async getAddressesRest() {
929
818
  return safe5(this.client.linkGet("/v1/link/addresses"));
930
819
  }
@@ -972,9 +861,6 @@ var AuthService = class {
972
861
  constructor(client) {
973
862
  this.client = client;
974
863
  }
975
- // --------------------------------------------------------------------------
976
- // STATUS & USER
977
- // --------------------------------------------------------------------------
978
864
  async getStatus() {
979
865
  return safe6(this.client.query("auth"));
980
866
  }
@@ -988,9 +874,6 @@ var AuthService = class {
988
874
  if (!result.ok) return result;
989
875
  return ok(result.value.is_authenticated);
990
876
  }
991
- // --------------------------------------------------------------------------
992
- // OTP AUTHENTICATION
993
- // --------------------------------------------------------------------------
994
877
  async requestOtp(contact, contactType) {
995
878
  return safe6(
996
879
  this.client.call(AUTH_MUTATION.REQUEST_OTP, {
@@ -1007,15 +890,9 @@ var AuthService = class {
1007
890
  })
1008
891
  );
1009
892
  }
1010
- // --------------------------------------------------------------------------
1011
- // SESSION MANAGEMENT
1012
- // --------------------------------------------------------------------------
1013
893
  async logout() {
1014
894
  return safe6(this.client.call("auth.logout"));
1015
895
  }
1016
- // --------------------------------------------------------------------------
1017
- // PROFILE MANAGEMENT
1018
- // --------------------------------------------------------------------------
1019
896
  async updateProfile(input) {
1020
897
  return safe6(this.client.call("auth.update_profile", input));
1021
898
  }
@@ -1046,9 +923,6 @@ var BusinessService = class {
1046
923
  constructor(client) {
1047
924
  this.client = client;
1048
925
  }
1049
- // --------------------------------------------------------------------------
1050
- // BUSINESS INFO
1051
- // --------------------------------------------------------------------------
1052
926
  async getInfo() {
1053
927
  return safe7(this.client.query("business.info"));
1054
928
  }
@@ -1064,27 +938,18 @@ var BusinessService = class {
1064
938
  async getTheme() {
1065
939
  return safe7(this.client.query("business.theme"));
1066
940
  }
1067
- // --------------------------------------------------------------------------
1068
- // LOCATIONS
1069
- // --------------------------------------------------------------------------
1070
941
  async getLocations() {
1071
942
  return safe7(this.client.query("business.locations"));
1072
943
  }
1073
944
  async getLocation(locationId) {
1074
945
  return safe7(this.client.query(`business.locations.${locationId}`));
1075
946
  }
1076
- // --------------------------------------------------------------------------
1077
- // HOURS
1078
- // --------------------------------------------------------------------------
1079
947
  async getHours() {
1080
948
  return safe7(this.client.query("business.hours"));
1081
949
  }
1082
950
  async getLocationHours(locationId) {
1083
951
  return safe7(this.client.query(`business.locations.${locationId}.hours`));
1084
952
  }
1085
- // --------------------------------------------------------------------------
1086
- // BOOTSTRAP (for storefront initialization)
1087
- // --------------------------------------------------------------------------
1088
953
  async getBootstrap() {
1089
954
  const [businessResult, locationsResult, categoriesResult] = await Promise.all([
1090
955
  this.getInfo(),
@@ -1129,9 +994,6 @@ var InventoryService = class {
1129
994
  constructor(client) {
1130
995
  this.client = client;
1131
996
  }
1132
- // --------------------------------------------------------------------------
1133
- // STOCK QUERIES
1134
- // --------------------------------------------------------------------------
1135
997
  async getStockLevels() {
1136
998
  return safe8(this.client.query("inventory.stock_levels"));
1137
999
  }
@@ -1158,9 +1020,6 @@ var InventoryService = class {
1158
1020
  })
1159
1021
  );
1160
1022
  }
1161
- // --------------------------------------------------------------------------
1162
- // AVAILABILITY CHECKS
1163
- // --------------------------------------------------------------------------
1164
1023
  async checkProductAvailability(productId, quantity, locationId) {
1165
1024
  return safe8(
1166
1025
  this.client.query("inventory.check_availability", {
@@ -1190,15 +1049,9 @@ var InventoryService = class {
1190
1049
  }
1191
1050
  return ok(results.map((r) => r.value));
1192
1051
  }
1193
- // --------------------------------------------------------------------------
1194
- // SUMMARY
1195
- // --------------------------------------------------------------------------
1196
1052
  async getSummary() {
1197
1053
  return safe8(this.client.query("inventory.summary"));
1198
1054
  }
1199
- // --------------------------------------------------------------------------
1200
- // CONVENIENCE METHODS
1201
- // --------------------------------------------------------------------------
1202
1055
  async isInStock(productId, locationId) {
1203
1056
  const result = await this.checkProductAvailability(productId, 1, locationId);
1204
1057
  if (!result.ok) return result;
@@ -1230,9 +1083,6 @@ var SchedulingService = class {
1230
1083
  constructor(client) {
1231
1084
  this.client = client;
1232
1085
  }
1233
- // --------------------------------------------------------------------------
1234
- // SERVICES
1235
- // --------------------------------------------------------------------------
1236
1086
  async getServices() {
1237
1087
  return safe9(this.client.query("scheduling.services"));
1238
1088
  }
@@ -1245,9 +1095,6 @@ var SchedulingService = class {
1245
1095
  if (!result.ok) return result;
1246
1096
  return ok(result.value.find((s) => s.id === serviceId) || null);
1247
1097
  }
1248
- // --------------------------------------------------------------------------
1249
- // AVAILABILITY
1250
- // --------------------------------------------------------------------------
1251
1098
  async getAvailableSlots(input) {
1252
1099
  return safe9(
1253
1100
  this.client.query(
@@ -1272,9 +1119,6 @@ var SchedulingService = class {
1272
1119
  )
1273
1120
  );
1274
1121
  }
1275
- // --------------------------------------------------------------------------
1276
- // BOOKINGS
1277
- // --------------------------------------------------------------------------
1278
1122
  async getBooking(bookingId) {
1279
1123
  return safe9(this.client.query(`scheduling.${bookingId}`));
1280
1124
  }
@@ -1295,18 +1139,12 @@ var SchedulingService = class {
1295
1139
  )
1296
1140
  );
1297
1141
  }
1298
- // --------------------------------------------------------------------------
1299
- // BOOKING MANAGEMENT
1300
- // --------------------------------------------------------------------------
1301
1142
  async cancelBooking(input) {
1302
1143
  return safe9(this.client.call("scheduling.cancel_booking", input));
1303
1144
  }
1304
1145
  async rescheduleBooking(input) {
1305
1146
  return safe9(this.client.call("scheduling.reschedule_booking", input));
1306
1147
  }
1307
- // --------------------------------------------------------------------------
1308
- // CONVENIENCE METHODS
1309
- // --------------------------------------------------------------------------
1310
1148
  async getNextAvailableSlot(serviceId, fromDate) {
1311
1149
  const date = fromDate || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1312
1150
  const result = await this.getAvailableSlots({
@@ -1345,15 +1183,9 @@ var LiteService = class {
1345
1183
  constructor(client) {
1346
1184
  this.client = client;
1347
1185
  }
1348
- // --------------------------------------------------------------------------
1349
- // BOOTSTRAP
1350
- // --------------------------------------------------------------------------
1351
1186
  async getBootstrap() {
1352
1187
  return safe10(this.client.query("lite.bootstrap"));
1353
1188
  }
1354
- // --------------------------------------------------------------------------
1355
- // TABLE MANAGEMENT
1356
- // --------------------------------------------------------------------------
1357
1189
  async getTable(tableId) {
1358
1190
  return safe10(this.client.query(`lite.table.${tableId}`));
1359
1191
  }
@@ -1365,9 +1197,6 @@ var LiteService = class {
1365
1197
  })
1366
1198
  );
1367
1199
  }
1368
- // --------------------------------------------------------------------------
1369
- // KITCHEN ORDERS
1370
- // --------------------------------------------------------------------------
1371
1200
  async sendToKitchen(tableId, items) {
1372
1201
  return safe10(
1373
1202
  this.client.call("lite.send_to_kitchen", {
@@ -1391,9 +1220,6 @@ var LiteService = class {
1391
1220
  })
1392
1221
  );
1393
1222
  }
1394
- // --------------------------------------------------------------------------
1395
- // MENU (optimized for lite/QR experience)
1396
- // --------------------------------------------------------------------------
1397
1223
  async getMenu() {
1398
1224
  return safe10(this.client.query("lite.menu"));
1399
1225
  }
@@ -1402,6 +1228,297 @@ var LiteService = class {
1402
1228
  }
1403
1229
  };
1404
1230
 
1231
+ // src/types/elements.ts
1232
+ var ELEMENT_TYPES = {
1233
+ AUTH: "auth",
1234
+ ADDRESS: "address",
1235
+ PAYMENT: "payment"
1236
+ };
1237
+ var MESSAGE_TYPES = {
1238
+ // Parent → Iframe
1239
+ INIT: "init",
1240
+ SET_TOKEN: "set_token",
1241
+ GET_DATA: "get_data",
1242
+ REFRESH_TOKEN: "refresh_token",
1243
+ LOGOUT: "logout",
1244
+ // Iframe → Parent
1245
+ READY: "ready",
1246
+ HEIGHT_CHANGE: "height_change",
1247
+ AUTHENTICATED: "authenticated",
1248
+ REQUIRES_OTP: "requires_otp",
1249
+ ERROR: "error",
1250
+ ADDRESS_CHANGED: "address_changed",
1251
+ ADDRESS_SELECTED: "address_selected",
1252
+ PAYMENT_METHOD_SELECTED: "payment_method_selected",
1253
+ TOKEN_REFRESHED: "token_refreshed",
1254
+ LOGOUT_COMPLETE: "logout_complete"
1255
+ };
1256
+ var EVENT_TYPES = {
1257
+ READY: "ready",
1258
+ AUTHENTICATED: "authenticated",
1259
+ REQUIRES_OTP: "requires_otp",
1260
+ ERROR: "error",
1261
+ CHANGE: "change",
1262
+ BLUR: "blur",
1263
+ FOCUS: "focus"
1264
+ };
1265
+
1266
+ // src/elements.ts
1267
+ var DEFAULT_LINK_URL = "https://link.cimplify.io";
1268
+ var CimplifyElements = class {
1269
+ constructor(client, businessId, options = {}) {
1270
+ this.elements = /* @__PURE__ */ new Map();
1271
+ this.accessToken = null;
1272
+ this.accountId = null;
1273
+ this.customerId = null;
1274
+ this.addressData = null;
1275
+ this.paymentData = null;
1276
+ this.client = client;
1277
+ this.businessId = businessId;
1278
+ this.linkUrl = options.linkUrl || DEFAULT_LINK_URL;
1279
+ this.options = options;
1280
+ if (typeof window !== "undefined") {
1281
+ window.addEventListener("message", this.handleMessage.bind(this));
1282
+ }
1283
+ }
1284
+ create(type, options = {}) {
1285
+ const existing = this.elements.get(type);
1286
+ if (existing) return existing;
1287
+ const element = new CimplifyElement(type, this.businessId, this.linkUrl, options, this);
1288
+ this.elements.set(type, element);
1289
+ return element;
1290
+ }
1291
+ getElement(type) {
1292
+ return this.elements.get(type);
1293
+ }
1294
+ destroy() {
1295
+ this.elements.forEach((element) => element.destroy());
1296
+ this.elements.clear();
1297
+ if (typeof window !== "undefined") {
1298
+ window.removeEventListener("message", this.handleMessage.bind(this));
1299
+ }
1300
+ }
1301
+ async submitCheckout(data) {
1302
+ const addressElement = this.elements.get(ELEMENT_TYPES.ADDRESS);
1303
+ if (addressElement) await addressElement.getData();
1304
+ const paymentElement = this.elements.get(ELEMENT_TYPES.PAYMENT);
1305
+ if (paymentElement) await paymentElement.getData();
1306
+ const checkoutData = {
1307
+ ...data,
1308
+ customer: this.accountId ? { account_id: this.accountId, customer_id: this.customerId } : void 0,
1309
+ address: this.addressData,
1310
+ payment_method: this.paymentData
1311
+ };
1312
+ const result = await this.client.checkout.process(checkoutData);
1313
+ if (result.ok) {
1314
+ return { success: true, order: result.value };
1315
+ }
1316
+ return {
1317
+ success: false,
1318
+ error: {
1319
+ code: result.error.code || "CHECKOUT_FAILED",
1320
+ message: result.error.message || "Checkout failed"
1321
+ }
1322
+ };
1323
+ }
1324
+ isAuthenticated() {
1325
+ return this.accessToken !== null;
1326
+ }
1327
+ getAccessToken() {
1328
+ return this.accessToken;
1329
+ }
1330
+ handleMessage(event) {
1331
+ if (!event.origin.includes("cimplify.io") && !event.origin.includes("localhost")) {
1332
+ return;
1333
+ }
1334
+ const message = event.data;
1335
+ if (!message?.type) return;
1336
+ switch (message.type) {
1337
+ case MESSAGE_TYPES.AUTHENTICATED:
1338
+ this.accessToken = message.token;
1339
+ this.accountId = message.accountId;
1340
+ this.customerId = message.customerId;
1341
+ this.elements.forEach((element, type) => {
1342
+ if (type !== ELEMENT_TYPES.AUTH) {
1343
+ element.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token: message.token });
1344
+ }
1345
+ });
1346
+ break;
1347
+ case MESSAGE_TYPES.TOKEN_REFRESHED:
1348
+ this.accessToken = message.token;
1349
+ break;
1350
+ case MESSAGE_TYPES.ADDRESS_CHANGED:
1351
+ case MESSAGE_TYPES.ADDRESS_SELECTED:
1352
+ this.addressData = message.address;
1353
+ break;
1354
+ case MESSAGE_TYPES.PAYMENT_METHOD_SELECTED:
1355
+ this.paymentData = message.method;
1356
+ break;
1357
+ case MESSAGE_TYPES.LOGOUT_COMPLETE:
1358
+ this.accessToken = null;
1359
+ this.accountId = null;
1360
+ this.customerId = null;
1361
+ this.addressData = null;
1362
+ this.paymentData = null;
1363
+ break;
1364
+ }
1365
+ }
1366
+ _setAddressData(data) {
1367
+ this.addressData = data;
1368
+ }
1369
+ _setPaymentData(data) {
1370
+ this.paymentData = data;
1371
+ }
1372
+ };
1373
+ var CimplifyElement = class {
1374
+ constructor(type, businessId, linkUrl, options, parent) {
1375
+ this.iframe = null;
1376
+ this.container = null;
1377
+ this.mounted = false;
1378
+ this.eventHandlers = /* @__PURE__ */ new Map();
1379
+ this.resolvers = /* @__PURE__ */ new Map();
1380
+ this.type = type;
1381
+ this.businessId = businessId;
1382
+ this.linkUrl = linkUrl;
1383
+ this.options = options;
1384
+ this.parent = parent;
1385
+ if (typeof window !== "undefined") {
1386
+ window.addEventListener("message", this.handleMessage.bind(this));
1387
+ }
1388
+ }
1389
+ mount(container) {
1390
+ if (this.mounted) {
1391
+ console.warn(`Element ${this.type} is already mounted`);
1392
+ return;
1393
+ }
1394
+ const target = typeof container === "string" ? document.querySelector(container) : container;
1395
+ if (!target) {
1396
+ console.error(`Container not found: ${container}`);
1397
+ return;
1398
+ }
1399
+ this.container = target;
1400
+ this.createIframe();
1401
+ this.mounted = true;
1402
+ }
1403
+ destroy() {
1404
+ if (this.iframe) {
1405
+ this.iframe.remove();
1406
+ this.iframe = null;
1407
+ }
1408
+ this.container = null;
1409
+ this.mounted = false;
1410
+ this.eventHandlers.clear();
1411
+ if (typeof window !== "undefined") {
1412
+ window.removeEventListener("message", this.handleMessage.bind(this));
1413
+ }
1414
+ }
1415
+ on(event, handler) {
1416
+ if (!this.eventHandlers.has(event)) {
1417
+ this.eventHandlers.set(event, /* @__PURE__ */ new Set());
1418
+ }
1419
+ this.eventHandlers.get(event).add(handler);
1420
+ }
1421
+ off(event, handler) {
1422
+ this.eventHandlers.get(event)?.delete(handler);
1423
+ }
1424
+ async getData() {
1425
+ return new Promise((resolve) => {
1426
+ const id = Math.random().toString(36).slice(2);
1427
+ this.resolvers.set(id, resolve);
1428
+ this.sendMessage({ type: MESSAGE_TYPES.GET_DATA });
1429
+ setTimeout(() => {
1430
+ if (this.resolvers.has(id)) {
1431
+ this.resolvers.delete(id);
1432
+ resolve(null);
1433
+ }
1434
+ }, 5e3);
1435
+ });
1436
+ }
1437
+ sendMessage(message) {
1438
+ if (this.iframe?.contentWindow) {
1439
+ this.iframe.contentWindow.postMessage(message, this.linkUrl);
1440
+ }
1441
+ }
1442
+ createIframe() {
1443
+ if (!this.container) return;
1444
+ const iframe = document.createElement("iframe");
1445
+ const url = new URL(`${this.linkUrl}/elements/${this.type}`);
1446
+ url.searchParams.set("businessId", this.businessId);
1447
+ if (this.options.prefillEmail) url.searchParams.set("email", this.options.prefillEmail);
1448
+ if (this.options.mode) url.searchParams.set("mode", this.options.mode);
1449
+ iframe.src = url.toString();
1450
+ iframe.style.border = "none";
1451
+ iframe.style.width = "100%";
1452
+ iframe.style.display = "block";
1453
+ iframe.style.overflow = "hidden";
1454
+ iframe.setAttribute("allowtransparency", "true");
1455
+ iframe.setAttribute("frameborder", "0");
1456
+ iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups");
1457
+ this.iframe = iframe;
1458
+ this.container.appendChild(iframe);
1459
+ iframe.onload = () => {
1460
+ this.sendMessage({
1461
+ type: MESSAGE_TYPES.INIT,
1462
+ businessId: this.businessId,
1463
+ prefillEmail: this.options.prefillEmail
1464
+ });
1465
+ const token = this.parent.getAccessToken();
1466
+ if (token && this.type !== ELEMENT_TYPES.AUTH) {
1467
+ this.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token });
1468
+ }
1469
+ };
1470
+ }
1471
+ handleMessage(event) {
1472
+ if (!event.origin.includes("cimplify.io") && !event.origin.includes("localhost")) {
1473
+ return;
1474
+ }
1475
+ const message = event.data;
1476
+ if (!message?.type) return;
1477
+ switch (message.type) {
1478
+ case MESSAGE_TYPES.READY:
1479
+ this.emit(EVENT_TYPES.READY, { height: message.height });
1480
+ break;
1481
+ case MESSAGE_TYPES.HEIGHT_CHANGE:
1482
+ if (this.iframe) this.iframe.style.height = `${message.height}px`;
1483
+ break;
1484
+ case MESSAGE_TYPES.AUTHENTICATED:
1485
+ this.emit(EVENT_TYPES.AUTHENTICATED, {
1486
+ accountId: message.accountId,
1487
+ customerId: message.customerId,
1488
+ token: message.token
1489
+ });
1490
+ break;
1491
+ case MESSAGE_TYPES.REQUIRES_OTP:
1492
+ this.emit(EVENT_TYPES.REQUIRES_OTP, { contactMasked: message.contactMasked });
1493
+ break;
1494
+ case MESSAGE_TYPES.ERROR:
1495
+ this.emit(EVENT_TYPES.ERROR, { code: message.code, message: message.message });
1496
+ break;
1497
+ case MESSAGE_TYPES.ADDRESS_CHANGED:
1498
+ case MESSAGE_TYPES.ADDRESS_SELECTED:
1499
+ this.parent._setAddressData(message.address);
1500
+ this.emit(EVENT_TYPES.CHANGE, { address: message.address });
1501
+ this.resolveData(message.address);
1502
+ break;
1503
+ case MESSAGE_TYPES.PAYMENT_METHOD_SELECTED:
1504
+ this.parent._setPaymentData(message.method);
1505
+ this.emit(EVENT_TYPES.CHANGE, { paymentMethod: message.method });
1506
+ this.resolveData(message.method);
1507
+ break;
1508
+ }
1509
+ }
1510
+ emit(event, data) {
1511
+ this.eventHandlers.get(event)?.forEach((handler) => handler(data));
1512
+ }
1513
+ resolveData(data) {
1514
+ this.resolvers.forEach((resolve) => resolve(data));
1515
+ this.resolvers.clear();
1516
+ }
1517
+ };
1518
+ function createElements(client, businessId, options) {
1519
+ return new CimplifyElements(client, businessId, options);
1520
+ }
1521
+
1405
1522
  // src/client.ts
1406
1523
  var SESSION_TOKEN_HEADER = "x-session-token";
1407
1524
  var SESSION_STORAGE_KEY = "cimplify_session_token";
@@ -1467,7 +1584,6 @@ function deriveUrls() {
1467
1584
  var CimplifyClient = class {
1468
1585
  constructor(config = {}) {
1469
1586
  this.sessionToken = null;
1470
- /** In-flight request deduplication map */
1471
1587
  this.inflightRequests = /* @__PURE__ */ new Map();
1472
1588
  this.publicKey = config.publicKey || "";
1473
1589
  const urls = deriveUrls();
@@ -1541,10 +1657,6 @@ var CimplifyClient = class {
1541
1657
  });
1542
1658
  }
1543
1659
  }
1544
- /**
1545
- * Resilient fetch with timeout, automatic retries, and observability hooks.
1546
- * Uses exponential backoff: 1s, 2s, 4s between retries.
1547
- */
1548
1660
  async resilientFetch(url, options) {
1549
1661
  const method = options.method || "GET";
1550
1662
  const path = url.replace(this.baseUrl, "").replace(this.linkApiUrl, "");
@@ -1629,18 +1741,9 @@ var CimplifyClient = class {
1629
1741
  });
1630
1742
  throw finalError;
1631
1743
  }
1632
- /**
1633
- * Generate a deduplication key for a request.
1634
- * Same query + variables = same key = deduplicated.
1635
- */
1636
1744
  getDedupeKey(type, payload) {
1637
1745
  return `${type}:${JSON.stringify(payload)}`;
1638
1746
  }
1639
- /**
1640
- * Execute a request with deduplication.
1641
- * If an identical request is already in-flight, return the same promise.
1642
- * This prevents redundant network calls when multiple components request the same data.
1643
- */
1644
1747
  async deduplicatedRequest(key, requestFn) {
1645
1748
  const existing = this.inflightRequests.get(key);
1646
1749
  if (existing) {
@@ -1652,10 +1755,6 @@ var CimplifyClient = class {
1652
1755
  this.inflightRequests.set(key, request);
1653
1756
  return request;
1654
1757
  }
1655
- /**
1656
- * Execute a query with deduplication.
1657
- * Multiple identical queries made simultaneously will share a single network request.
1658
- */
1659
1758
  async query(query2, variables) {
1660
1759
  const body = { query: query2 };
1661
1760
  if (variables) {
@@ -1673,9 +1772,6 @@ var CimplifyClient = class {
1673
1772
  return this.handleResponse(response);
1674
1773
  });
1675
1774
  }
1676
- /**
1677
- * Execute a mutation. NOT deduplicated - mutations have side effects.
1678
- */
1679
1775
  async call(method, args) {
1680
1776
  const body = {
1681
1777
  method,
@@ -1834,6 +1930,23 @@ var CimplifyClient = class {
1834
1930
  }
1835
1931
  return this._lite;
1836
1932
  }
1933
+ /**
1934
+ * Create a CimplifyElements instance for embedding checkout components.
1935
+ * Like Stripe's stripe.elements().
1936
+ *
1937
+ * @param businessId - The business ID for checkout context
1938
+ * @param options - Optional configuration for elements
1939
+ *
1940
+ * @example
1941
+ * ```ts
1942
+ * const elements = client.elements('bus_xxx');
1943
+ * const authElement = elements.create('auth');
1944
+ * authElement.mount('#auth-container');
1945
+ * ```
1946
+ */
1947
+ elements(businessId, options) {
1948
+ return createElements(this, businessId, options);
1949
+ }
1837
1950
  };
1838
1951
  function createCimplifyClient(config) {
1839
1952
  return new CimplifyClient(config);
@@ -2390,4 +2503,4 @@ function detectMobileMoneyProvider(phoneNumber) {
2390
2503
  return null;
2391
2504
  }
2392
2505
 
2393
- export { AUTHORIZATION_TYPE, AUTH_MUTATION, AuthService, BusinessService, CHECKOUT_MODE, CHECKOUT_MUTATION, CHECKOUT_STEP, CURRENCY_SYMBOLS, CartOperations, CatalogueQueries, CheckoutService as CheckoutOperations, CheckoutService, CimplifyClient, CimplifyError, DEFAULT_COUNTRY, DEFAULT_CURRENCY, ErrorCode, InventoryService, LINK_MUTATION, LINK_QUERY, LinkService, LiteService, MOBILE_MONEY_PROVIDER, MOBILE_MONEY_PROVIDERS, ORDER_MUTATION, ORDER_TYPE, OrderQueries, PAYMENT_METHOD, PAYMENT_MUTATION, PAYMENT_STATE, PICKUP_TIME_TYPE, QueryBuilder, SchedulingService, categorizePaymentError, combine, combineObject, createCimplifyClient, detectMobileMoneyProvider, err, extractPriceInfo, flatMap, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatProductPrice, fromPromise, generateIdempotencyKey, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getOrElse, getProductCurrency, isCimplifyError, isErr, isOk, isOnSale, isRetryableError, mapError, mapResult, normalizePaymentResponse, normalizeStatusResponse, ok, parsePrice, parsePricePath, parsedPriceToPriceInfo, query, toNullable, tryCatch, unwrap };
2506
+ export { AUTHORIZATION_TYPE, AUTH_MUTATION, AuthService, BusinessService, CHECKOUT_MODE, CHECKOUT_MUTATION, CHECKOUT_STEP, CONTACT_TYPE, CURRENCY_SYMBOLS, CartOperations, CatalogueQueries, CheckoutService as CheckoutOperations, CheckoutService, CimplifyClient, CimplifyElement, CimplifyElements, CimplifyError, DEFAULT_COUNTRY, DEFAULT_CURRENCY, DEVICE_TYPE, ELEMENT_TYPES, EVENT_TYPES, ErrorCode, InventoryService, LINK_MUTATION, LINK_QUERY, LinkService, LiteService, MESSAGE_TYPES, MOBILE_MONEY_PROVIDER, MOBILE_MONEY_PROVIDERS, ORDER_MUTATION, ORDER_TYPE, OrderQueries, PAYMENT_METHOD, PAYMENT_MUTATION, PAYMENT_STATE, PICKUP_TIME_TYPE, QueryBuilder, SchedulingService, categorizePaymentError, combine, combineObject, createCimplifyClient, createElements, detectMobileMoneyProvider, err, extractPriceInfo, flatMap, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatProductPrice, fromPromise, generateIdempotencyKey, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getOrElse, getProductCurrency, isCimplifyError, isErr, isOk, isOnSale, isRetryableError, mapError, mapResult, normalizePaymentResponse, normalizeStatusResponse, ok, parsePrice, parsePricePath, parsedPriceToPriceInfo, query, toNullable, tryCatch, unwrap };