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