@cimplify/sdk 0.6.4 → 0.6.6

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.
@@ -0,0 +1,2639 @@
1
+ 'use strict';
2
+
3
+ // src/types/result.ts
4
+ function ok(value) {
5
+ return { ok: true, value };
6
+ }
7
+ function err(error) {
8
+ return { ok: false, error };
9
+ }
10
+
11
+ // src/types/common.ts
12
+ var CimplifyError = class extends Error {
13
+ constructor(code, message, retryable = false) {
14
+ super(message);
15
+ this.code = code;
16
+ this.retryable = retryable;
17
+ this.name = "CimplifyError";
18
+ }
19
+ /** User-friendly message safe to display */
20
+ get userMessage() {
21
+ return this.message;
22
+ }
23
+ };
24
+
25
+ // src/catalogue.ts
26
+ function toCimplifyError(error) {
27
+ if (error instanceof CimplifyError) return error;
28
+ if (error instanceof Error) {
29
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
30
+ }
31
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
32
+ }
33
+ async function safe(promise) {
34
+ try {
35
+ return ok(await promise);
36
+ } catch (error) {
37
+ return err(toCimplifyError(error));
38
+ }
39
+ }
40
+ function isRecord(value) {
41
+ return typeof value === "object" && value !== null;
42
+ }
43
+ function readFinalPrice(value) {
44
+ if (!isRecord(value)) return void 0;
45
+ const finalPrice = value.final_price;
46
+ if (typeof finalPrice === "string" || typeof finalPrice === "number") {
47
+ return finalPrice;
48
+ }
49
+ return void 0;
50
+ }
51
+ function normalizeCatalogueProductPayload(product) {
52
+ const normalized = { ...product };
53
+ const defaultPrice = normalized["default_price"];
54
+ if (defaultPrice === void 0 || defaultPrice === null || defaultPrice === "") {
55
+ const derivedDefaultPrice = readFinalPrice(normalized["default_price_info"]) || readFinalPrice(normalized["price_info"]) || (typeof normalized["final_price"] === "string" || typeof normalized["final_price"] === "number" ? normalized["final_price"] : void 0);
56
+ normalized["default_price"] = derivedDefaultPrice ?? "0";
57
+ }
58
+ const variants = normalized["variants"];
59
+ if (Array.isArray(variants)) {
60
+ normalized["variants"] = variants.map((variant) => {
61
+ if (!isRecord(variant)) return variant;
62
+ const normalizedVariant = { ...variant };
63
+ const variantAdjustment = normalizedVariant["price_adjustment"];
64
+ if (variantAdjustment === void 0 || variantAdjustment === null || variantAdjustment === "") {
65
+ normalizedVariant["price_adjustment"] = readFinalPrice(normalizedVariant["price_info"]) ?? "0";
66
+ }
67
+ return normalizedVariant;
68
+ });
69
+ }
70
+ const addOns = normalized["add_ons"];
71
+ if (Array.isArray(addOns)) {
72
+ normalized["add_ons"] = addOns.map((addOn) => {
73
+ if (!isRecord(addOn)) return addOn;
74
+ const normalizedAddOn = { ...addOn };
75
+ const options = normalizedAddOn["options"];
76
+ if (!Array.isArray(options)) return normalizedAddOn;
77
+ normalizedAddOn["options"] = options.map((option) => {
78
+ if (!isRecord(option)) return option;
79
+ const normalizedOption = { ...option };
80
+ const optionPrice = normalizedOption["default_price"];
81
+ if (optionPrice === void 0 || optionPrice === null || optionPrice === "") {
82
+ normalizedOption["default_price"] = readFinalPrice(normalizedOption["default_price_info"]) || readFinalPrice(normalizedOption["price_info"]) || "0";
83
+ }
84
+ return normalizedOption;
85
+ });
86
+ return normalizedAddOn;
87
+ });
88
+ }
89
+ return normalized;
90
+ }
91
+ function findProductBySlug(products, slug) {
92
+ return products.find((product) => {
93
+ const value = product["slug"];
94
+ return typeof value === "string" && value === slug;
95
+ });
96
+ }
97
+ var CatalogueQueries = class {
98
+ constructor(client) {
99
+ this.client = client;
100
+ }
101
+ async getProducts(options) {
102
+ let query2 = "products";
103
+ const filters = [];
104
+ if (options?.category) {
105
+ filters.push(`@.category_id=='${options.category}'`);
106
+ }
107
+ if (options?.featured !== void 0) {
108
+ filters.push(`@.featured==${options.featured}`);
109
+ }
110
+ if (options?.in_stock !== void 0) {
111
+ filters.push(`@.in_stock==${options.in_stock}`);
112
+ }
113
+ if (options?.search) {
114
+ filters.push(`@.name contains '${options.search}'`);
115
+ }
116
+ if (options?.min_price !== void 0) {
117
+ filters.push(`@.price>=${options.min_price}`);
118
+ }
119
+ if (options?.max_price !== void 0) {
120
+ filters.push(`@.price<=${options.max_price}`);
121
+ }
122
+ if (filters.length > 0) {
123
+ query2 += `[?(${filters.join(" && ")})]`;
124
+ }
125
+ if (options?.sort_by) {
126
+ query2 += `#sort(${options.sort_by},${options.sort_order || "asc"})`;
127
+ }
128
+ if (options?.limit) {
129
+ query2 += `#limit(${options.limit})`;
130
+ }
131
+ if (options?.offset) {
132
+ query2 += `#offset(${options.offset})`;
133
+ }
134
+ const result = await safe(this.client.query(query2));
135
+ if (!result.ok) return result;
136
+ return ok(result.value.map((product) => normalizeCatalogueProductPayload(product)));
137
+ }
138
+ async getProduct(id) {
139
+ const result = await safe(this.client.query(`products.${id}`));
140
+ if (!result.ok) return result;
141
+ return ok(normalizeCatalogueProductPayload(result.value));
142
+ }
143
+ async getProductBySlug(slug) {
144
+ const filteredResult = await safe(
145
+ this.client.query(`products[?(@.slug=='${slug}')]`)
146
+ );
147
+ if (!filteredResult.ok) return filteredResult;
148
+ const exactMatch = findProductBySlug(filteredResult.value, slug);
149
+ if (exactMatch) {
150
+ return ok(normalizeCatalogueProductPayload(exactMatch));
151
+ }
152
+ if (filteredResult.value.length === 1) {
153
+ return ok(normalizeCatalogueProductPayload(filteredResult.value[0]));
154
+ }
155
+ const unfilteredResult = await safe(this.client.query("products"));
156
+ if (!unfilteredResult.ok) return unfilteredResult;
157
+ const fallbackMatch = findProductBySlug(unfilteredResult.value, slug);
158
+ if (!fallbackMatch) {
159
+ return err(new CimplifyError("NOT_FOUND", `Product not found: ${slug}`, false));
160
+ }
161
+ return ok(normalizeCatalogueProductPayload(fallbackMatch));
162
+ }
163
+ async getVariants(productId) {
164
+ return safe(this.client.query(`products.${productId}.variants`));
165
+ }
166
+ async getVariantAxes(productId) {
167
+ return safe(this.client.query(`products.${productId}.variant_axes`));
168
+ }
169
+ /**
170
+ * Find a variant by axis selections (e.g., { "Size": "Large", "Color": "Red" })
171
+ * Returns the matching variant or null if no match found.
172
+ */
173
+ async getVariantByAxisSelections(productId, selections) {
174
+ return safe(
175
+ this.client.query(`products.${productId}.variant`, {
176
+ axis_selections: selections
177
+ })
178
+ );
179
+ }
180
+ /**
181
+ * Get a specific variant by its ID
182
+ */
183
+ async getVariantById(productId, variantId) {
184
+ return safe(this.client.query(`products.${productId}.variant.${variantId}`));
185
+ }
186
+ async getAddOns(productId) {
187
+ return safe(this.client.query(`products.${productId}.add_ons`));
188
+ }
189
+ async getCategories() {
190
+ return safe(this.client.query("categories"));
191
+ }
192
+ async getCategory(id) {
193
+ return safe(this.client.query(`categories.${id}`));
194
+ }
195
+ async getCategoryBySlug(slug) {
196
+ const result = await safe(
197
+ this.client.query(`categories[?(@.slug=='${slug}')]`)
198
+ );
199
+ if (!result.ok) return result;
200
+ if (!result.value.length) {
201
+ return err(new CimplifyError("NOT_FOUND", `Category not found: ${slug}`, false));
202
+ }
203
+ return ok(result.value[0]);
204
+ }
205
+ async getCategoryProducts(categoryId) {
206
+ return safe(this.client.query(`products[?(@.category_id=='${categoryId}')]`));
207
+ }
208
+ async getCollections() {
209
+ return safe(this.client.query("collections"));
210
+ }
211
+ async getCollection(id) {
212
+ return safe(this.client.query(`collections.${id}`));
213
+ }
214
+ async getCollectionBySlug(slug) {
215
+ const result = await safe(
216
+ this.client.query(`collections[?(@.slug=='${slug}')]`)
217
+ );
218
+ if (!result.ok) return result;
219
+ if (!result.value.length) {
220
+ return err(new CimplifyError("NOT_FOUND", `Collection not found: ${slug}`, false));
221
+ }
222
+ return ok(result.value[0]);
223
+ }
224
+ async getCollectionProducts(collectionId) {
225
+ return safe(this.client.query(`collections.${collectionId}.products`));
226
+ }
227
+ async searchCollections(query2, limit = 20) {
228
+ return safe(
229
+ this.client.query(`collections[?(@.name contains '${query2}')]#limit(${limit})`)
230
+ );
231
+ }
232
+ async getBundles() {
233
+ return safe(this.client.query("bundles"));
234
+ }
235
+ async getBundle(id) {
236
+ return safe(this.client.query(`bundles.${id}`));
237
+ }
238
+ async getBundleBySlug(slug) {
239
+ const result = await safe(
240
+ this.client.query(`bundles[?(@.slug=='${slug}')]`)
241
+ );
242
+ if (!result.ok) return result;
243
+ if (!result.value.length) {
244
+ return err(new CimplifyError("NOT_FOUND", `Bundle not found: ${slug}`, false));
245
+ }
246
+ return ok(result.value[0]);
247
+ }
248
+ async searchBundles(query2, limit = 20) {
249
+ return safe(
250
+ this.client.query(`bundles[?(@.name contains '${query2}')]#limit(${limit})`)
251
+ );
252
+ }
253
+ async getComposites(options) {
254
+ let query2 = "composites";
255
+ if (options?.limit) {
256
+ query2 += `#limit(${options.limit})`;
257
+ }
258
+ return safe(this.client.query(query2));
259
+ }
260
+ async getComposite(id) {
261
+ return safe(this.client.query(`composites.${id}`));
262
+ }
263
+ async getCompositeByProductId(productId) {
264
+ return safe(this.client.query(`composites.by_product.${productId}`));
265
+ }
266
+ async calculateCompositePrice(compositeId, selections, locationId) {
267
+ return safe(
268
+ this.client.call("composite.calculatePrice", {
269
+ composite_id: compositeId,
270
+ selections,
271
+ location_id: locationId
272
+ })
273
+ );
274
+ }
275
+ async fetchQuote(input) {
276
+ return safe(this.client.call("catalogue.createQuote", input));
277
+ }
278
+ async getQuote(quoteId) {
279
+ return safe(
280
+ this.client.call("catalogue.getQuote", {
281
+ quote_id: quoteId
282
+ })
283
+ );
284
+ }
285
+ async refreshQuote(input) {
286
+ return safe(this.client.call("catalogue.refreshQuote", input));
287
+ }
288
+ async search(query2, options) {
289
+ const limit = options?.limit ?? 20;
290
+ let searchQuery = `products[?(@.name contains '${query2}')]`;
291
+ if (options?.category) {
292
+ searchQuery = `products[?(@.name contains '${query2}' && @.category_id=='${options.category}')]`;
293
+ }
294
+ searchQuery += `#limit(${limit})`;
295
+ return safe(this.client.query(searchQuery));
296
+ }
297
+ async searchProducts(query2, options) {
298
+ return safe(
299
+ this.client.call("catalogue.search", {
300
+ query: query2,
301
+ limit: options?.limit ?? 20,
302
+ category: options?.category
303
+ })
304
+ );
305
+ }
306
+ async getMenu(options) {
307
+ let query2 = "menu";
308
+ if (options?.category) {
309
+ query2 = `menu[?(@.category=='${options.category}')]`;
310
+ }
311
+ if (options?.limit) {
312
+ query2 += `#limit(${options.limit})`;
313
+ }
314
+ return safe(this.client.query(query2));
315
+ }
316
+ async getMenuCategory(categoryId) {
317
+ return safe(this.client.query(`menu.category.${categoryId}`));
318
+ }
319
+ async getMenuItem(itemId) {
320
+ return safe(this.client.query(`menu.${itemId}`));
321
+ }
322
+ };
323
+
324
+ // src/cart.ts
325
+ function toCimplifyError2(error) {
326
+ if (error instanceof CimplifyError) return error;
327
+ if (error instanceof Error) {
328
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
329
+ }
330
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
331
+ }
332
+ async function safe2(promise) {
333
+ try {
334
+ return ok(await promise);
335
+ } catch (error) {
336
+ return err(toCimplifyError2(error));
337
+ }
338
+ }
339
+ function isUICartResponse(value) {
340
+ return "cart" in value;
341
+ }
342
+ function unwrapEnrichedCart(value) {
343
+ return isUICartResponse(value) ? value.cart : value;
344
+ }
345
+ var CartOperations = class {
346
+ constructor(client) {
347
+ this.client = client;
348
+ }
349
+ async get() {
350
+ const result = await safe2(this.client.query("cart#enriched"));
351
+ if (!result.ok) return result;
352
+ return ok(unwrapEnrichedCart(result.value));
353
+ }
354
+ async getRaw() {
355
+ return safe2(this.client.query("cart"));
356
+ }
357
+ async getItems() {
358
+ return safe2(this.client.query("cart_items"));
359
+ }
360
+ async getCount() {
361
+ return safe2(this.client.query("cart#count"));
362
+ }
363
+ async getTotal() {
364
+ return safe2(this.client.query("cart#total"));
365
+ }
366
+ async getSummary() {
367
+ const cartResult = await this.get();
368
+ if (!cartResult.ok) return cartResult;
369
+ const cart = cartResult.value;
370
+ return ok({
371
+ item_count: cart.items.length,
372
+ total_items: cart.items.reduce((sum, item) => sum + item.quantity, 0),
373
+ subtotal: cart.pricing.subtotal,
374
+ discount_amount: cart.pricing.total_discounts,
375
+ tax_amount: cart.pricing.tax_amount,
376
+ total: cart.pricing.total_price,
377
+ currency: cart.pricing.currency
378
+ });
379
+ }
380
+ async addItem(input) {
381
+ return safe2(this.client.call("cart.addItem", input));
382
+ }
383
+ async updateItem(cartItemId, updates) {
384
+ return safe2(
385
+ this.client.call("cart.updateItem", {
386
+ cart_item_id: cartItemId,
387
+ ...updates
388
+ })
389
+ );
390
+ }
391
+ async updateQuantity(cartItemId, quantity) {
392
+ return safe2(
393
+ this.client.call("cart.updateItemQuantity", {
394
+ cart_item_id: cartItemId,
395
+ quantity
396
+ })
397
+ );
398
+ }
399
+ async removeItem(cartItemId) {
400
+ return safe2(
401
+ this.client.call("cart.removeItem", {
402
+ cart_item_id: cartItemId
403
+ })
404
+ );
405
+ }
406
+ async clear() {
407
+ return safe2(this.client.call("cart.clearCart"));
408
+ }
409
+ async applyCoupon(code) {
410
+ return safe2(
411
+ this.client.call("cart.applyCoupon", {
412
+ coupon_code: code
413
+ })
414
+ );
415
+ }
416
+ async removeCoupon() {
417
+ return safe2(this.client.call("cart.removeCoupon"));
418
+ }
419
+ async isEmpty() {
420
+ const countResult = await this.getCount();
421
+ if (!countResult.ok) return countResult;
422
+ return ok(countResult.value === 0);
423
+ }
424
+ async hasItem(productId, variantId) {
425
+ const itemsResult = await this.getItems();
426
+ if (!itemsResult.ok) return itemsResult;
427
+ const found = itemsResult.value.some((item) => {
428
+ const matchesProduct = item.item_id === productId;
429
+ if (!variantId) return matchesProduct;
430
+ const config = item.configuration;
431
+ if ("variant" in config && config.variant) {
432
+ return matchesProduct && config.variant.variant_id === variantId;
433
+ }
434
+ return matchesProduct;
435
+ });
436
+ return ok(found);
437
+ }
438
+ async findItem(productId, variantId) {
439
+ const itemsResult = await this.getItems();
440
+ if (!itemsResult.ok) return itemsResult;
441
+ const found = itemsResult.value.find((item) => {
442
+ const matchesProduct = item.item_id === productId;
443
+ if (!variantId) return matchesProduct;
444
+ const config = item.configuration;
445
+ if ("variant" in config && config.variant) {
446
+ return matchesProduct && config.variant.variant_id === variantId;
447
+ }
448
+ return matchesProduct;
449
+ });
450
+ return ok(found);
451
+ }
452
+ };
453
+
454
+ // src/constants.ts
455
+ var LINK_QUERY = {
456
+ DATA: "link.data",
457
+ ADDRESSES: "link.addresses",
458
+ MOBILE_MONEY: "link.mobile_money",
459
+ PREFERENCES: "link.preferences"};
460
+ var LINK_MUTATION = {
461
+ CHECK_STATUS: "link.check_status",
462
+ ENROLL: "link.enroll",
463
+ ENROLL_AND_LINK_ORDER: "link.enroll_and_link_order",
464
+ UPDATE_PREFERENCES: "link.update_preferences",
465
+ CREATE_ADDRESS: "link.create_address",
466
+ UPDATE_ADDRESS: "link.update_address",
467
+ DELETE_ADDRESS: "link.delete_address",
468
+ SET_DEFAULT_ADDRESS: "link.set_default_address",
469
+ TRACK_ADDRESS_USAGE: "link.track_address_usage",
470
+ CREATE_MOBILE_MONEY: "link.create_mobile_money",
471
+ DELETE_MOBILE_MONEY: "link.delete_mobile_money",
472
+ SET_DEFAULT_MOBILE_MONEY: "link.set_default_mobile_money",
473
+ TRACK_MOBILE_MONEY_USAGE: "link.track_mobile_money_usage",
474
+ VERIFY_MOBILE_MONEY: "link.verify_mobile_money"};
475
+ var AUTH_MUTATION = {
476
+ REQUEST_OTP: "auth.request_otp",
477
+ VERIFY_OTP: "auth.verify_otp"
478
+ };
479
+ var CHECKOUT_MUTATION = {
480
+ PROCESS: "checkout.process"
481
+ };
482
+ var PAYMENT_MUTATION = {
483
+ SUBMIT_AUTHORIZATION: "payment.submit_authorization",
484
+ CHECK_STATUS: "order.poll_payment_status"
485
+ };
486
+ var ORDER_MUTATION = {
487
+ UPDATE_CUSTOMER: "order.update_order_customer"
488
+ };
489
+
490
+ // src/utils/payment.ts
491
+ var PAYMENT_SUCCESS_STATUSES = /* @__PURE__ */ new Set([
492
+ "success",
493
+ "succeeded",
494
+ "paid",
495
+ "captured",
496
+ "completed",
497
+ "authorized"
498
+ ]);
499
+ var PAYMENT_FAILURE_STATUSES = /* @__PURE__ */ new Set([
500
+ "failed",
501
+ "declined",
502
+ "cancelled",
503
+ "voided",
504
+ "error"
505
+ ]);
506
+ var PAYMENT_REQUIRES_ACTION_STATUSES = /* @__PURE__ */ new Set([
507
+ "requires_action",
508
+ "requires_payment_method",
509
+ "requires_capture"
510
+ ]);
511
+ var PAYMENT_STATUS_ALIAS_MAP = {
512
+ ok: "success",
513
+ done: "success",
514
+ paid: "paid",
515
+ paid_in_full: "paid",
516
+ paid_successfully: "paid",
517
+ succeeded: "success",
518
+ captured: "captured",
519
+ completed: "completed",
520
+ pending_confirmation: "pending_confirmation",
521
+ requires_authorization: "requires_action",
522
+ requires_action: "requires_action",
523
+ requires_payment_method: "requires_payment_method",
524
+ requires_capture: "requires_capture",
525
+ partially_paid: "partially_paid",
526
+ partially_refunded: "partially_refunded",
527
+ card_declined: "declined",
528
+ canceled: "cancelled",
529
+ authorized: "authorized",
530
+ cancelled: "cancelled",
531
+ unresolved: "pending"
532
+ };
533
+ var KNOWN_PAYMENT_STATUSES = /* @__PURE__ */ new Set([
534
+ "pending",
535
+ "processing",
536
+ "created",
537
+ "pending_confirmation",
538
+ "success",
539
+ "succeeded",
540
+ "failed",
541
+ "declined",
542
+ "authorized",
543
+ "refunded",
544
+ "partially_refunded",
545
+ "partially_paid",
546
+ "paid",
547
+ "unpaid",
548
+ "requires_action",
549
+ "requires_payment_method",
550
+ "requires_capture",
551
+ "captured",
552
+ "cancelled",
553
+ "completed",
554
+ "voided",
555
+ "error",
556
+ "unknown"
557
+ ]);
558
+ function normalizeStatusToken(status) {
559
+ return status?.trim().toLowerCase().replace(/[\s-]+/g, "_") ?? "";
560
+ }
561
+ function normalizePaymentStatusValue(status) {
562
+ const normalized = normalizeStatusToken(status);
563
+ if (Object.prototype.hasOwnProperty.call(PAYMENT_STATUS_ALIAS_MAP, normalized)) {
564
+ return PAYMENT_STATUS_ALIAS_MAP[normalized];
565
+ }
566
+ return KNOWN_PAYMENT_STATUSES.has(normalized) ? normalized : "unknown";
567
+ }
568
+ function isPaymentStatusSuccess(status) {
569
+ const normalizedStatus = normalizePaymentStatusValue(status);
570
+ return PAYMENT_SUCCESS_STATUSES.has(normalizedStatus);
571
+ }
572
+ function isPaymentStatusFailure(status) {
573
+ const normalizedStatus = normalizePaymentStatusValue(status);
574
+ return PAYMENT_FAILURE_STATUSES.has(normalizedStatus);
575
+ }
576
+ function isPaymentStatusRequiresAction(status) {
577
+ const normalizedStatus = normalizePaymentStatusValue(status);
578
+ return PAYMENT_REQUIRES_ACTION_STATUSES.has(normalizedStatus);
579
+ }
580
+ function normalizeStatusResponse(response) {
581
+ if (!response || typeof response !== "object") {
582
+ return {
583
+ status: "pending",
584
+ paid: false,
585
+ message: "No status available"
586
+ };
587
+ }
588
+ const res = response;
589
+ const normalizedStatus = normalizePaymentStatusValue(res.status ?? void 0);
590
+ const paidValue = res.paid === true;
591
+ const derivedPaid = paidValue || [
592
+ "success",
593
+ "succeeded",
594
+ "paid",
595
+ "captured",
596
+ "authorized",
597
+ "completed"
598
+ ].includes(normalizedStatus);
599
+ return {
600
+ status: normalizedStatus,
601
+ paid: derivedPaid,
602
+ amount: res.amount,
603
+ currency: res.currency,
604
+ reference: res.reference,
605
+ message: res.message || ""
606
+ };
607
+ }
608
+
609
+ // src/utils/paystack.ts
610
+ async function openPaystackPopup(options, signal) {
611
+ if (typeof window === "undefined") {
612
+ return { success: false, error: "PROVIDER_UNAVAILABLE" };
613
+ }
614
+ let PaystackPop;
615
+ try {
616
+ const imported = await import('@paystack/inline-js');
617
+ PaystackPop = imported.default;
618
+ } catch {
619
+ return { success: false, error: "PROVIDER_UNAVAILABLE" };
620
+ }
621
+ return new Promise((resolve) => {
622
+ let settled = false;
623
+ const resolveOnce = (result) => {
624
+ if (settled) {
625
+ return;
626
+ }
627
+ settled = true;
628
+ if (signal) {
629
+ signal.removeEventListener("abort", onAbort);
630
+ }
631
+ resolve(result);
632
+ };
633
+ const onAbort = () => {
634
+ resolveOnce({ success: false, error: "CANCELLED" });
635
+ };
636
+ if (signal?.aborted) {
637
+ resolveOnce({ success: false, error: "CANCELLED" });
638
+ return;
639
+ }
640
+ if (signal) {
641
+ signal.addEventListener("abort", onAbort, { once: true });
642
+ }
643
+ try {
644
+ const popup = new PaystackPop();
645
+ popup.newTransaction({
646
+ key: options.key,
647
+ email: options.email,
648
+ amount: options.amount,
649
+ currency: options.currency,
650
+ reference: options.reference,
651
+ accessCode: options.accessCode,
652
+ onSuccess: (transaction) => {
653
+ resolveOnce({
654
+ success: true,
655
+ reference: transaction.reference ?? options.reference
656
+ });
657
+ },
658
+ onCancel: () => {
659
+ resolveOnce({ success: false, error: "PAYMENT_CANCELLED" });
660
+ },
661
+ onError: (error) => {
662
+ resolveOnce({
663
+ success: false,
664
+ error: error?.message || "PAYMENT_FAILED"
665
+ });
666
+ }
667
+ });
668
+ } catch {
669
+ resolveOnce({ success: false, error: "POPUP_BLOCKED" });
670
+ }
671
+ });
672
+ }
673
+
674
+ // src/utils/checkout-resolver.ts
675
+ var DEFAULT_POLL_INTERVAL_MS = 3e3;
676
+ var DEFAULT_MAX_POLL_ATTEMPTS = 60;
677
+ var MAX_CONSECUTIVE_NETWORK_ERRORS = 5;
678
+ var CARD_PROVIDER_PAYSTACK = "paystack";
679
+ function normalizeCardPopupError(error) {
680
+ if (!error || error === "PAYMENT_CANCELLED" || error === "CANCELLED") {
681
+ return "PAYMENT_CANCELLED";
682
+ }
683
+ if (error === "PROVIDER_UNAVAILABLE") {
684
+ return "PROVIDER_UNAVAILABLE";
685
+ }
686
+ if (error === "POPUP_BLOCKED") {
687
+ return "POPUP_BLOCKED";
688
+ }
689
+ return "PAYMENT_FAILED";
690
+ }
691
+ function normalizeCardProvider(value) {
692
+ const normalized = value?.trim().toLowerCase();
693
+ return normalized && normalized.length > 0 ? normalized : CARD_PROVIDER_PAYSTACK;
694
+ }
695
+ async function openCardPopup(provider, checkoutResult, email, currency, signal) {
696
+ if (typeof window === "undefined") {
697
+ return { success: false, error: "PROVIDER_UNAVAILABLE" };
698
+ }
699
+ if (provider === CARD_PROVIDER_PAYSTACK) {
700
+ return openPaystackPopup(
701
+ {
702
+ key: checkoutResult.public_key || "",
703
+ email,
704
+ accessCode: checkoutResult.client_secret,
705
+ reference: checkoutResult.payment_reference || checkoutResult.client_secret,
706
+ currency
707
+ },
708
+ signal
709
+ );
710
+ }
711
+ return { success: false, error: "PROVIDER_UNAVAILABLE" };
712
+ }
713
+ function normalizeAuthorizationType(value) {
714
+ return value === "otp" || value === "pin" ? value : void 0;
715
+ }
716
+ function formatMoney2(value) {
717
+ if (typeof value === "number" && Number.isFinite(value)) {
718
+ return value.toFixed(2);
719
+ }
720
+ if (typeof value === "string" && value.trim().length > 0) {
721
+ return value;
722
+ }
723
+ return "0.00";
724
+ }
725
+ function createAbortError() {
726
+ const error = new Error("CANCELLED");
727
+ error.name = "AbortError";
728
+ return error;
729
+ }
730
+ function isAbortError(error) {
731
+ if (error instanceof DOMException && error.name === "AbortError") {
732
+ return true;
733
+ }
734
+ return error instanceof Error && (error.name === "AbortError" || error.message === "CANCELLED");
735
+ }
736
+ var CheckoutResolver = class {
737
+ constructor(options) {
738
+ this.client = options.client;
739
+ this.checkoutData = options.checkoutData;
740
+ this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
741
+ this.maxPollAttempts = options.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS;
742
+ this.onStatusChange = options.onStatusChange;
743
+ this.onAuthorizationRequired = options.onAuthorizationRequired;
744
+ this.signal = options.signal;
745
+ this.returnUrl = options.returnUrl;
746
+ this.enrollInLink = options.enrollInLink !== false;
747
+ this.businessId = options.businessId;
748
+ this.addressData = options.addressData;
749
+ this.paymentData = options.paymentData;
750
+ this.orderType = options.orderType;
751
+ this.cartTotal = options.cartTotal;
752
+ this.cartCurrency = options.cartCurrency;
753
+ this.allowPopups = options.allowPopups ?? typeof window !== "undefined";
754
+ }
755
+ async resolve(checkoutResult) {
756
+ try {
757
+ this.ensureNotAborted();
758
+ if (!checkoutResult.order_id) {
759
+ return this.fail("CHECKOUT_FAILED", "Checkout did not return an order ID.", false);
760
+ }
761
+ let latestCheckoutResult = checkoutResult;
762
+ let authorizationType = normalizeAuthorizationType(checkoutResult.authorization_type);
763
+ let paymentReference = checkoutResult.payment_reference;
764
+ if (this.isSuccessfulStatus(checkoutResult.payment_status)) {
765
+ return this.finalizeSuccess(checkoutResult);
766
+ }
767
+ if (checkoutResult.client_secret && checkoutResult.public_key) {
768
+ const provider = normalizeCardProvider(checkoutResult.provider);
769
+ this.emit("awaiting_authorization", {
770
+ display_text: "Complete payment in the card authorization popup.",
771
+ order_id: checkoutResult.order_id,
772
+ order_number: checkoutResult.order_number
773
+ });
774
+ if (!this.allowPopups) {
775
+ return this.fail(
776
+ "PROVIDER_UNAVAILABLE",
777
+ "Card payment popup is unavailable in this environment.",
778
+ false
779
+ );
780
+ }
781
+ const popupResult = await openCardPopup(
782
+ provider,
783
+ checkoutResult,
784
+ this.checkoutData.customer.email || "customer@cimplify.io",
785
+ this.getOrderCurrency(checkoutResult),
786
+ this.signal
787
+ );
788
+ if (!popupResult.success) {
789
+ const popupError = normalizeCardPopupError(popupResult.error);
790
+ if (popupError === "POPUP_BLOCKED") {
791
+ return this.fail(
792
+ "POPUP_BLOCKED",
793
+ "Unable to open card payment popup. Please allow popups and try again.",
794
+ true
795
+ );
796
+ }
797
+ if (popupError === "PROVIDER_UNAVAILABLE") {
798
+ return this.fail(
799
+ "PROVIDER_UNAVAILABLE",
800
+ "Card payment provider is unavailable.",
801
+ false
802
+ );
803
+ }
804
+ return this.fail(
805
+ "PAYMENT_CANCELLED",
806
+ "Card payment was cancelled before completion.",
807
+ true
808
+ );
809
+ }
810
+ paymentReference = popupResult.reference || paymentReference;
811
+ }
812
+ if (checkoutResult.authorization_url) {
813
+ if (typeof window !== "undefined" && this.returnUrl) {
814
+ window.location.assign(checkoutResult.authorization_url);
815
+ return this.fail(
816
+ "REDIRECT_REQUIRED",
817
+ "Redirecting to complete payment authorization.",
818
+ true
819
+ );
820
+ }
821
+ if (typeof window !== "undefined") {
822
+ const popup = window.open(
823
+ checkoutResult.authorization_url,
824
+ "cimplify-auth",
825
+ "width=520,height=760,noopener,noreferrer"
826
+ );
827
+ if (!popup) {
828
+ return this.fail(
829
+ "POPUP_BLOCKED",
830
+ "Authorization popup was blocked. Please allow popups and retry.",
831
+ true
832
+ );
833
+ }
834
+ }
835
+ }
836
+ if (checkoutResult.requires_authorization || isPaymentStatusRequiresAction(checkoutResult.payment_status)) {
837
+ const authorization = await this.handleAuthorization({
838
+ authorizationType,
839
+ paymentReference,
840
+ displayText: checkoutResult.display_text,
841
+ provider: checkoutResult.provider
842
+ });
843
+ if (!authorization.ok) {
844
+ return authorization.result;
845
+ }
846
+ if (authorization.value) {
847
+ latestCheckoutResult = authorization.value;
848
+ paymentReference = authorization.value.payment_reference || paymentReference;
849
+ authorizationType = normalizeAuthorizationType(authorization.value.authorization_type) || authorizationType;
850
+ if (this.isSuccessfulStatus(authorization.value.payment_status)) {
851
+ return this.finalizeSuccess(authorization.value);
852
+ }
853
+ if (this.isFailureStatus(authorization.value.payment_status)) {
854
+ return this.fail(
855
+ "AUTHORIZATION_FAILED",
856
+ authorization.value.display_text || "Payment authorization failed.",
857
+ false
858
+ );
859
+ }
860
+ }
861
+ }
862
+ return this.pollUntilTerminal({
863
+ orderId: checkoutResult.order_id,
864
+ latestCheckoutResult,
865
+ paymentReference,
866
+ authorizationType
867
+ });
868
+ } catch (error) {
869
+ if (isAbortError(error)) {
870
+ return this.fail("CANCELLED", "Checkout was cancelled.", true);
871
+ }
872
+ const message = error instanceof Error ? error.message : "Checkout failed unexpectedly.";
873
+ return this.fail("CHECKOUT_FAILED", message, true);
874
+ }
875
+ }
876
+ async pollUntilTerminal(input) {
877
+ let consecutiveErrors = 0;
878
+ let latestCheckoutResult = input.latestCheckoutResult;
879
+ let paymentReference = input.paymentReference;
880
+ let authorizationType = input.authorizationType;
881
+ for (let attempt = 0; attempt < this.maxPollAttempts; attempt++) {
882
+ this.ensureNotAborted();
883
+ this.emit("polling", {
884
+ poll_attempt: attempt,
885
+ max_poll_attempts: this.maxPollAttempts,
886
+ order_id: input.orderId,
887
+ order_number: latestCheckoutResult.order_number
888
+ });
889
+ const statusResult = await this.client.checkout.pollPaymentStatus(input.orderId);
890
+ if (!statusResult.ok) {
891
+ consecutiveErrors += 1;
892
+ if (consecutiveErrors >= MAX_CONSECUTIVE_NETWORK_ERRORS) {
893
+ return this.fail(
894
+ "NETWORK_ERROR",
895
+ "Unable to confirm payment due to repeated network errors.",
896
+ true
897
+ );
898
+ }
899
+ await this.wait(this.pollIntervalMs);
900
+ continue;
901
+ }
902
+ consecutiveErrors = 0;
903
+ if (statusResult.value.reference) {
904
+ paymentReference = statusResult.value.reference;
905
+ }
906
+ const normalized = normalizeStatusResponse(statusResult.value);
907
+ if (normalized.paid || isPaymentStatusSuccess(normalized.status)) {
908
+ return this.finalizeSuccess(latestCheckoutResult);
909
+ }
910
+ if (isPaymentStatusFailure(normalized.status)) {
911
+ return this.fail(
912
+ normalized.status ? normalized.status.toUpperCase() : "PAYMENT_FAILED",
913
+ normalized.message || "Payment failed during confirmation.",
914
+ false
915
+ );
916
+ }
917
+ if (isPaymentStatusRequiresAction(normalized.status)) {
918
+ const authorization = await this.handleAuthorization({
919
+ authorizationType,
920
+ paymentReference,
921
+ displayText: normalized.message || latestCheckoutResult.display_text,
922
+ provider: latestCheckoutResult.provider
923
+ });
924
+ if (!authorization.ok) {
925
+ return authorization.result;
926
+ }
927
+ if (authorization.value) {
928
+ latestCheckoutResult = authorization.value;
929
+ paymentReference = authorization.value.payment_reference || paymentReference;
930
+ authorizationType = normalizeAuthorizationType(authorization.value.authorization_type) || authorizationType;
931
+ if (this.isSuccessfulStatus(authorization.value.payment_status)) {
932
+ return this.finalizeSuccess(authorization.value);
933
+ }
934
+ if (this.isFailureStatus(authorization.value.payment_status)) {
935
+ return this.fail(
936
+ "AUTHORIZATION_FAILED",
937
+ authorization.value.display_text || "Payment authorization failed.",
938
+ false
939
+ );
940
+ }
941
+ }
942
+ }
943
+ await this.wait(this.pollIntervalMs);
944
+ }
945
+ return this.fail(
946
+ "PAYMENT_TIMEOUT",
947
+ "Payment confirmation timed out. Please retry checkout.",
948
+ true
949
+ );
950
+ }
951
+ async handleAuthorization(input) {
952
+ const authorizationType = input.authorizationType;
953
+ const paymentReference = input.paymentReference;
954
+ if (!authorizationType || !paymentReference) {
955
+ return { ok: true };
956
+ }
957
+ this.emit("awaiting_authorization", {
958
+ authorization_type: authorizationType,
959
+ display_text: input.displayText,
960
+ provider: input.provider
961
+ });
962
+ let authorizationResult;
963
+ const submit = async (code) => {
964
+ this.ensureNotAborted();
965
+ const trimmedCode = code.trim();
966
+ if (!trimmedCode) {
967
+ throw new Error("Authorization code is required.");
968
+ }
969
+ const submitResult = await this.client.checkout.submitAuthorization({
970
+ reference: paymentReference,
971
+ auth_type: authorizationType,
972
+ value: trimmedCode
973
+ });
974
+ if (!submitResult.ok) {
975
+ throw new Error(submitResult.error.message || "Authorization failed.");
976
+ }
977
+ authorizationResult = submitResult.value;
978
+ };
979
+ try {
980
+ if (this.onAuthorizationRequired) {
981
+ await this.onAuthorizationRequired(authorizationType, submit);
982
+ } else {
983
+ return {
984
+ ok: false,
985
+ result: this.fail(
986
+ "AUTHORIZATION_REQUIRED",
987
+ "Authorization callback is required in headless checkout mode.",
988
+ false
989
+ )
990
+ };
991
+ }
992
+ } catch (error) {
993
+ if (isAbortError(error)) {
994
+ return {
995
+ ok: false,
996
+ result: this.fail("CANCELLED", "Checkout was cancelled.", true)
997
+ };
998
+ }
999
+ const message = error instanceof Error ? error.message : "Payment authorization failed.";
1000
+ return {
1001
+ ok: false,
1002
+ result: this.fail("AUTHORIZATION_FAILED", message, true)
1003
+ };
1004
+ }
1005
+ return {
1006
+ ok: true,
1007
+ value: authorizationResult
1008
+ };
1009
+ }
1010
+ async finalizeSuccess(checkoutResult) {
1011
+ this.emit("finalizing", {
1012
+ order_id: checkoutResult.order_id,
1013
+ order_number: checkoutResult.order_number
1014
+ });
1015
+ const enrolledInLink = await this.maybeEnrollInLink(checkoutResult.order_id);
1016
+ this.emit("success", {
1017
+ order_id: checkoutResult.order_id,
1018
+ order_number: checkoutResult.order_number
1019
+ });
1020
+ return {
1021
+ success: true,
1022
+ order: {
1023
+ id: checkoutResult.order_id,
1024
+ order_number: checkoutResult.order_number || checkoutResult.order_id,
1025
+ status: checkoutResult.payment_status || "paid",
1026
+ total: this.getOrderTotal(checkoutResult),
1027
+ currency: this.getOrderCurrency(checkoutResult)
1028
+ },
1029
+ enrolled_in_link: enrolledInLink
1030
+ };
1031
+ }
1032
+ async maybeEnrollInLink(orderId) {
1033
+ if (!this.enrollInLink || !orderId) {
1034
+ return false;
1035
+ }
1036
+ let businessId = this.businessId;
1037
+ if (!businessId) {
1038
+ const businessResult = await this.client.business.getInfo();
1039
+ if (!businessResult.ok || !businessResult.value?.id) {
1040
+ return false;
1041
+ }
1042
+ businessId = businessResult.value.id;
1043
+ }
1044
+ const address = this.getEnrollmentAddress();
1045
+ const mobileMoney = this.getEnrollmentMobileMoney();
1046
+ try {
1047
+ const enrollment = await this.client.link.enrollAndLinkOrder({
1048
+ order_id: orderId,
1049
+ business_id: businessId,
1050
+ order_type: this.orderType || this.checkoutData.order_type,
1051
+ address,
1052
+ mobile_money: mobileMoney
1053
+ });
1054
+ return enrollment.ok && enrollment.value.success;
1055
+ } catch {
1056
+ return false;
1057
+ }
1058
+ }
1059
+ getEnrollmentAddress() {
1060
+ const source = this.addressData ?? this.checkoutData.address_info;
1061
+ if (!source?.street_address) {
1062
+ return void 0;
1063
+ }
1064
+ return {
1065
+ label: "Default",
1066
+ street_address: source.street_address,
1067
+ apartment: source.apartment || void 0,
1068
+ city: source.city || "",
1069
+ region: source.region || "",
1070
+ delivery_instructions: source.delivery_instructions || void 0,
1071
+ phone_for_delivery: source.phone_for_delivery || void 0
1072
+ };
1073
+ }
1074
+ getEnrollmentMobileMoney() {
1075
+ if (this.paymentData?.type === "mobile_money" && this.paymentData.phone_number && this.paymentData.provider) {
1076
+ return {
1077
+ phone_number: this.paymentData.phone_number,
1078
+ provider: this.paymentData.provider,
1079
+ label: this.paymentData.label || "Mobile Money"
1080
+ };
1081
+ }
1082
+ if (this.checkoutData.mobile_money_details?.phone_number) {
1083
+ return {
1084
+ phone_number: this.checkoutData.mobile_money_details.phone_number,
1085
+ provider: this.checkoutData.mobile_money_details.provider,
1086
+ label: "Mobile Money"
1087
+ };
1088
+ }
1089
+ return void 0;
1090
+ }
1091
+ getOrderTotal(checkoutResult) {
1092
+ if (checkoutResult.fx?.pay_amount !== void 0) {
1093
+ return formatMoney2(checkoutResult.fx.pay_amount);
1094
+ }
1095
+ if (this.cartTotal !== void 0) {
1096
+ return formatMoney2(this.cartTotal);
1097
+ }
1098
+ return "0.00";
1099
+ }
1100
+ getOrderCurrency(checkoutResult) {
1101
+ if (checkoutResult.fx?.pay_currency) {
1102
+ return checkoutResult.fx.pay_currency;
1103
+ }
1104
+ if (this.cartCurrency) {
1105
+ return this.cartCurrency;
1106
+ }
1107
+ if (this.checkoutData.pay_currency) {
1108
+ return this.checkoutData.pay_currency;
1109
+ }
1110
+ return "GHS";
1111
+ }
1112
+ emit(status, context = {}) {
1113
+ if (!this.onStatusChange) {
1114
+ return;
1115
+ }
1116
+ try {
1117
+ this.onStatusChange(status, context);
1118
+ } catch {
1119
+ }
1120
+ }
1121
+ fail(code, message, recoverable) {
1122
+ this.emit("failed", {
1123
+ display_text: message
1124
+ });
1125
+ return {
1126
+ success: false,
1127
+ error: {
1128
+ code,
1129
+ message,
1130
+ recoverable
1131
+ }
1132
+ };
1133
+ }
1134
+ isSuccessfulStatus(status) {
1135
+ const normalized = normalizeStatusResponse({ status, paid: false });
1136
+ return normalized.paid || isPaymentStatusSuccess(normalized.status);
1137
+ }
1138
+ isFailureStatus(status) {
1139
+ const normalized = normalizeStatusResponse({ status, paid: false });
1140
+ return isPaymentStatusFailure(normalized.status);
1141
+ }
1142
+ ensureNotAborted() {
1143
+ if (this.signal?.aborted) {
1144
+ throw createAbortError();
1145
+ }
1146
+ }
1147
+ wait(ms) {
1148
+ this.ensureNotAborted();
1149
+ return new Promise((resolve, reject) => {
1150
+ const timer = setTimeout(() => {
1151
+ if (this.signal) {
1152
+ this.signal.removeEventListener("abort", onAbort);
1153
+ }
1154
+ resolve();
1155
+ }, ms);
1156
+ const onAbort = () => {
1157
+ clearTimeout(timer);
1158
+ reject(createAbortError());
1159
+ };
1160
+ if (this.signal) {
1161
+ this.signal.addEventListener("abort", onAbort, { once: true });
1162
+ }
1163
+ });
1164
+ }
1165
+ };
1166
+
1167
+ // src/checkout.ts
1168
+ function toCimplifyError3(error) {
1169
+ if (error instanceof CimplifyError) return error;
1170
+ if (error instanceof Error) {
1171
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1172
+ }
1173
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1174
+ }
1175
+ async function safe3(promise) {
1176
+ try {
1177
+ return ok(await promise);
1178
+ } catch (error) {
1179
+ return err(toCimplifyError3(error));
1180
+ }
1181
+ }
1182
+ function toTerminalFailure(code, message, recoverable) {
1183
+ return {
1184
+ success: false,
1185
+ error: {
1186
+ code,
1187
+ message,
1188
+ recoverable
1189
+ }
1190
+ };
1191
+ }
1192
+ function generateIdempotencyKey() {
1193
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
1194
+ return `idem_${crypto.randomUUID()}`;
1195
+ }
1196
+ const timestamp = Date.now().toString(36);
1197
+ const random = Math.random().toString(36).substring(2, 15);
1198
+ return `idem_${timestamp}_${random}`;
1199
+ }
1200
+ var CheckoutService = class {
1201
+ constructor(client) {
1202
+ this.client = client;
1203
+ }
1204
+ async process(data) {
1205
+ const checkoutData = {
1206
+ ...data,
1207
+ idempotency_key: data.idempotency_key || generateIdempotencyKey()
1208
+ };
1209
+ return safe3(
1210
+ this.client.call(CHECKOUT_MUTATION.PROCESS, {
1211
+ checkout_data: checkoutData
1212
+ })
1213
+ );
1214
+ }
1215
+ async initializePayment(orderId, method) {
1216
+ return safe3(
1217
+ this.client.call("order.initializePayment", {
1218
+ order_id: orderId,
1219
+ payment_method: method
1220
+ })
1221
+ );
1222
+ }
1223
+ async submitAuthorization(input) {
1224
+ return safe3(
1225
+ this.client.call(PAYMENT_MUTATION.SUBMIT_AUTHORIZATION, input)
1226
+ );
1227
+ }
1228
+ async pollPaymentStatus(orderId) {
1229
+ return safe3(
1230
+ this.client.call(PAYMENT_MUTATION.CHECK_STATUS, orderId)
1231
+ );
1232
+ }
1233
+ async updateOrderCustomer(orderId, customer) {
1234
+ return safe3(
1235
+ this.client.call(ORDER_MUTATION.UPDATE_CUSTOMER, {
1236
+ order_id: orderId,
1237
+ ...customer
1238
+ })
1239
+ );
1240
+ }
1241
+ async verifyPayment(orderId) {
1242
+ return safe3(
1243
+ this.client.call("order.verifyPayment", {
1244
+ order_id: orderId
1245
+ })
1246
+ );
1247
+ }
1248
+ async processAndResolve(data) {
1249
+ data.on_status_change?.("preparing", {});
1250
+ if (!data.cart_id) {
1251
+ return ok(
1252
+ toTerminalFailure(
1253
+ "INVALID_CART",
1254
+ "A valid cart is required before checkout can start.",
1255
+ false
1256
+ )
1257
+ );
1258
+ }
1259
+ const cartResult = await this.client.cart.get();
1260
+ if (!cartResult.ok || !cartResult.value?.id) {
1261
+ return ok(
1262
+ toTerminalFailure(
1263
+ "INVALID_CART",
1264
+ "Unable to load cart for checkout.",
1265
+ false
1266
+ )
1267
+ );
1268
+ }
1269
+ const cart = cartResult.value;
1270
+ if (cart.id !== data.cart_id || cart.items.length === 0) {
1271
+ return ok(
1272
+ toTerminalFailure(
1273
+ "INVALID_CART",
1274
+ "Cart is empty or no longer valid. Please refresh and try again.",
1275
+ false
1276
+ )
1277
+ );
1278
+ }
1279
+ const checkoutData = {
1280
+ cart_id: data.cart_id,
1281
+ location_id: data.location_id,
1282
+ customer: data.customer,
1283
+ order_type: data.order_type,
1284
+ address_info: data.address_info,
1285
+ payment_method: data.payment_method,
1286
+ mobile_money_details: data.mobile_money_details,
1287
+ special_instructions: data.special_instructions,
1288
+ link_address_id: data.link_address_id,
1289
+ link_payment_method_id: data.link_payment_method_id,
1290
+ idempotency_key: data.idempotency_key || generateIdempotencyKey(),
1291
+ metadata: data.metadata,
1292
+ pay_currency: data.pay_currency,
1293
+ fx_quote_id: data.fx_quote_id
1294
+ };
1295
+ const baseCurrency = (cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase();
1296
+ const payCurrency = data.pay_currency?.trim().toUpperCase();
1297
+ const cartTotalAmount = Number.parseFloat(cart.pricing.total_price || "0");
1298
+ if (payCurrency && payCurrency !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
1299
+ const fxQuoteResult = await this.client.fx.lockQuote({
1300
+ from: baseCurrency,
1301
+ to: payCurrency,
1302
+ amount: cartTotalAmount
1303
+ });
1304
+ if (!fxQuoteResult.ok) {
1305
+ return ok(
1306
+ toTerminalFailure(
1307
+ "FX_QUOTE_FAILED",
1308
+ fxQuoteResult.error.message || "Unable to lock FX quote for checkout.",
1309
+ true
1310
+ )
1311
+ );
1312
+ }
1313
+ checkoutData.pay_currency = payCurrency;
1314
+ checkoutData.fx_quote_id = fxQuoteResult.value.id;
1315
+ }
1316
+ data.on_status_change?.("processing", {});
1317
+ const processResult = await this.process(checkoutData);
1318
+ if (!processResult.ok) {
1319
+ return ok(
1320
+ toTerminalFailure(
1321
+ processResult.error.code || "CHECKOUT_FAILED",
1322
+ processResult.error.message || "Unable to process checkout.",
1323
+ processResult.error.retryable ?? true
1324
+ )
1325
+ );
1326
+ }
1327
+ const resolver = new CheckoutResolver({
1328
+ client: this.client,
1329
+ checkoutData,
1330
+ pollIntervalMs: data.poll_interval_ms,
1331
+ maxPollAttempts: data.max_poll_attempts,
1332
+ onStatusChange: data.on_status_change,
1333
+ onAuthorizationRequired: data.on_authorization_required,
1334
+ signal: data.signal,
1335
+ returnUrl: data.return_url,
1336
+ enrollInLink: data.enroll_in_link,
1337
+ cartTotal: cart.pricing.total_price,
1338
+ cartCurrency: checkoutData.pay_currency || cart.pricing.currency || "GHS",
1339
+ orderType: checkoutData.order_type,
1340
+ allowPopups: data.allow_popups
1341
+ });
1342
+ const resolved = await resolver.resolve(processResult.value);
1343
+ return ok(resolved);
1344
+ }
1345
+ };
1346
+
1347
+ // src/orders.ts
1348
+ function toCimplifyError4(error) {
1349
+ if (error instanceof CimplifyError) return error;
1350
+ if (error instanceof Error) {
1351
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1352
+ }
1353
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1354
+ }
1355
+ async function safe4(promise) {
1356
+ try {
1357
+ return ok(await promise);
1358
+ } catch (error) {
1359
+ return err(toCimplifyError4(error));
1360
+ }
1361
+ }
1362
+ var OrderQueries = class {
1363
+ constructor(client) {
1364
+ this.client = client;
1365
+ }
1366
+ async list(options) {
1367
+ let query2 = "orders";
1368
+ if (options?.status) {
1369
+ query2 += `[?(@.status=='${options.status}')]`;
1370
+ }
1371
+ query2 += "#sort(created_at,desc)";
1372
+ if (options?.limit) {
1373
+ query2 += `#limit(${options.limit})`;
1374
+ }
1375
+ if (options?.offset) {
1376
+ query2 += `#offset(${options.offset})`;
1377
+ }
1378
+ return safe4(this.client.query(query2));
1379
+ }
1380
+ async get(orderId) {
1381
+ return safe4(this.client.query(`orders.${orderId}`));
1382
+ }
1383
+ async getRecent(limit = 5) {
1384
+ return safe4(this.client.query(`orders#sort(created_at,desc)#limit(${limit})`));
1385
+ }
1386
+ async getByStatus(status) {
1387
+ return safe4(this.client.query(`orders[?(@.status=='${status}')]`));
1388
+ }
1389
+ async cancel(orderId, reason) {
1390
+ return safe4(
1391
+ this.client.call("order.cancelOrder", {
1392
+ order_id: orderId,
1393
+ reason
1394
+ })
1395
+ );
1396
+ }
1397
+ };
1398
+
1399
+ // src/link.ts
1400
+ function toCimplifyError5(error) {
1401
+ if (error instanceof CimplifyError) return error;
1402
+ if (error instanceof Error) {
1403
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1404
+ }
1405
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1406
+ }
1407
+ async function safe5(promise) {
1408
+ try {
1409
+ return ok(await promise);
1410
+ } catch (error) {
1411
+ return err(toCimplifyError5(error));
1412
+ }
1413
+ }
1414
+ var LinkService = class {
1415
+ constructor(client) {
1416
+ this.client = client;
1417
+ }
1418
+ async requestOtp(input) {
1419
+ return safe5(this.client.linkPost("/v1/link/auth/request-otp", input));
1420
+ }
1421
+ async verifyOtp(input) {
1422
+ const result = await safe5(
1423
+ this.client.linkPost("/v1/link/auth/verify-otp", input)
1424
+ );
1425
+ if (result.ok && result.value.session_token) {
1426
+ this.client.setSessionToken(result.value.session_token);
1427
+ }
1428
+ return result;
1429
+ }
1430
+ async logout() {
1431
+ const result = await safe5(this.client.linkPost("/v1/link/auth/logout"));
1432
+ if (result.ok) {
1433
+ this.client.clearSession();
1434
+ }
1435
+ return result;
1436
+ }
1437
+ async checkStatus(contact) {
1438
+ return safe5(
1439
+ this.client.call(LINK_MUTATION.CHECK_STATUS, {
1440
+ contact
1441
+ })
1442
+ );
1443
+ }
1444
+ async getLinkData() {
1445
+ return safe5(this.client.query(LINK_QUERY.DATA));
1446
+ }
1447
+ async getAddresses() {
1448
+ return safe5(this.client.query(LINK_QUERY.ADDRESSES));
1449
+ }
1450
+ async getMobileMoney() {
1451
+ return safe5(this.client.query(LINK_QUERY.MOBILE_MONEY));
1452
+ }
1453
+ async getPreferences() {
1454
+ return safe5(this.client.query(LINK_QUERY.PREFERENCES));
1455
+ }
1456
+ async enroll(data) {
1457
+ return safe5(this.client.call(LINK_MUTATION.ENROLL, data));
1458
+ }
1459
+ async enrollAndLinkOrder(data) {
1460
+ return safe5(
1461
+ this.client.call(LINK_MUTATION.ENROLL_AND_LINK_ORDER, data)
1462
+ );
1463
+ }
1464
+ async updatePreferences(preferences) {
1465
+ return safe5(this.client.call(LINK_MUTATION.UPDATE_PREFERENCES, preferences));
1466
+ }
1467
+ async createAddress(input) {
1468
+ return safe5(this.client.call(LINK_MUTATION.CREATE_ADDRESS, input));
1469
+ }
1470
+ async updateAddress(input) {
1471
+ return safe5(this.client.call(LINK_MUTATION.UPDATE_ADDRESS, input));
1472
+ }
1473
+ async deleteAddress(addressId) {
1474
+ return safe5(this.client.call(LINK_MUTATION.DELETE_ADDRESS, addressId));
1475
+ }
1476
+ async setDefaultAddress(addressId) {
1477
+ return safe5(this.client.call(LINK_MUTATION.SET_DEFAULT_ADDRESS, addressId));
1478
+ }
1479
+ async trackAddressUsage(addressId) {
1480
+ return safe5(
1481
+ this.client.call(LINK_MUTATION.TRACK_ADDRESS_USAGE, {
1482
+ address_id: addressId
1483
+ })
1484
+ );
1485
+ }
1486
+ async createMobileMoney(input) {
1487
+ return safe5(this.client.call(LINK_MUTATION.CREATE_MOBILE_MONEY, input));
1488
+ }
1489
+ async deleteMobileMoney(mobileMoneyId) {
1490
+ return safe5(this.client.call(LINK_MUTATION.DELETE_MOBILE_MONEY, mobileMoneyId));
1491
+ }
1492
+ async setDefaultMobileMoney(mobileMoneyId) {
1493
+ return safe5(
1494
+ this.client.call(LINK_MUTATION.SET_DEFAULT_MOBILE_MONEY, mobileMoneyId)
1495
+ );
1496
+ }
1497
+ async trackMobileMoneyUsage(mobileMoneyId) {
1498
+ return safe5(
1499
+ this.client.call(LINK_MUTATION.TRACK_MOBILE_MONEY_USAGE, {
1500
+ mobile_money_id: mobileMoneyId
1501
+ })
1502
+ );
1503
+ }
1504
+ async verifyMobileMoney(mobileMoneyId) {
1505
+ return safe5(
1506
+ this.client.call(LINK_MUTATION.VERIFY_MOBILE_MONEY, mobileMoneyId)
1507
+ );
1508
+ }
1509
+ async getSessions() {
1510
+ return safe5(this.client.linkGet("/v1/link/sessions"));
1511
+ }
1512
+ async revokeSession(sessionId) {
1513
+ return safe5(this.client.linkDelete(`/v1/link/sessions/${sessionId}`));
1514
+ }
1515
+ async revokeAllSessions() {
1516
+ return safe5(this.client.linkDelete("/v1/link/sessions"));
1517
+ }
1518
+ async getAddressesRest() {
1519
+ return safe5(this.client.linkGet("/v1/link/addresses"));
1520
+ }
1521
+ async createAddressRest(input) {
1522
+ return safe5(this.client.linkPost("/v1/link/addresses", input));
1523
+ }
1524
+ async deleteAddressRest(addressId) {
1525
+ return safe5(this.client.linkDelete(`/v1/link/addresses/${addressId}`));
1526
+ }
1527
+ async setDefaultAddressRest(addressId) {
1528
+ return safe5(this.client.linkPost(`/v1/link/addresses/${addressId}/default`));
1529
+ }
1530
+ async getMobileMoneyRest() {
1531
+ return safe5(this.client.linkGet("/v1/link/mobile-money"));
1532
+ }
1533
+ async createMobileMoneyRest(input) {
1534
+ return safe5(this.client.linkPost("/v1/link/mobile-money", input));
1535
+ }
1536
+ async deleteMobileMoneyRest(mobileMoneyId) {
1537
+ return safe5(this.client.linkDelete(`/v1/link/mobile-money/${mobileMoneyId}`));
1538
+ }
1539
+ async setDefaultMobileMoneyRest(mobileMoneyId) {
1540
+ return safe5(
1541
+ this.client.linkPost(`/v1/link/mobile-money/${mobileMoneyId}/default`)
1542
+ );
1543
+ }
1544
+ };
1545
+
1546
+ // src/auth.ts
1547
+ function toCimplifyError6(error) {
1548
+ if (error instanceof CimplifyError) return error;
1549
+ if (error instanceof Error) {
1550
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1551
+ }
1552
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1553
+ }
1554
+ async function safe6(promise) {
1555
+ try {
1556
+ return ok(await promise);
1557
+ } catch (error) {
1558
+ return err(toCimplifyError6(error));
1559
+ }
1560
+ }
1561
+ var AuthService = class {
1562
+ constructor(client) {
1563
+ this.client = client;
1564
+ }
1565
+ async getStatus() {
1566
+ return safe6(this.client.query("auth"));
1567
+ }
1568
+ async getCurrentUser() {
1569
+ const result = await this.getStatus();
1570
+ if (!result.ok) return result;
1571
+ return ok(result.value.customer || null);
1572
+ }
1573
+ async isAuthenticated() {
1574
+ const result = await this.getStatus();
1575
+ if (!result.ok) return result;
1576
+ return ok(result.value.is_authenticated);
1577
+ }
1578
+ async requestOtp(contact, contactType) {
1579
+ return safe6(
1580
+ this.client.call(AUTH_MUTATION.REQUEST_OTP, {
1581
+ contact,
1582
+ contact_type: contactType
1583
+ })
1584
+ );
1585
+ }
1586
+ async verifyOtp(code, contact) {
1587
+ return safe6(
1588
+ this.client.call(AUTH_MUTATION.VERIFY_OTP, {
1589
+ otp_code: code,
1590
+ contact
1591
+ })
1592
+ );
1593
+ }
1594
+ async logout() {
1595
+ return safe6(this.client.call("auth.logout"));
1596
+ }
1597
+ async updateProfile(input) {
1598
+ return safe6(this.client.call("auth.update_profile", input));
1599
+ }
1600
+ async changePassword(input) {
1601
+ return safe6(this.client.call("auth.change_password", input));
1602
+ }
1603
+ async resetPassword(email) {
1604
+ return safe6(this.client.call("auth.reset_password", { email }));
1605
+ }
1606
+ };
1607
+
1608
+ // src/business.ts
1609
+ function toCimplifyError7(error) {
1610
+ if (error instanceof CimplifyError) return error;
1611
+ if (error instanceof Error) {
1612
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1613
+ }
1614
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1615
+ }
1616
+ async function safe7(promise) {
1617
+ try {
1618
+ return ok(await promise);
1619
+ } catch (error) {
1620
+ return err(toCimplifyError7(error));
1621
+ }
1622
+ }
1623
+ var BusinessService = class {
1624
+ constructor(client) {
1625
+ this.client = client;
1626
+ }
1627
+ async getInfo() {
1628
+ return safe7(this.client.query("business.info"));
1629
+ }
1630
+ async getByHandle(handle) {
1631
+ return safe7(this.client.query(`business.handle.${handle}`));
1632
+ }
1633
+ async getByDomain(domain) {
1634
+ return safe7(this.client.query("business.domain", { domain }));
1635
+ }
1636
+ async getSettings() {
1637
+ return safe7(this.client.query("business.settings"));
1638
+ }
1639
+ async getTheme() {
1640
+ return safe7(this.client.query("business.theme"));
1641
+ }
1642
+ async getLocations() {
1643
+ return safe7(this.client.query("business.locations"));
1644
+ }
1645
+ async getLocation(locationId) {
1646
+ return safe7(this.client.query(`business.locations.${locationId}`));
1647
+ }
1648
+ async getHours() {
1649
+ return safe7(this.client.query("business.hours"));
1650
+ }
1651
+ async getLocationHours(locationId) {
1652
+ return safe7(this.client.query(`business.locations.${locationId}.hours`));
1653
+ }
1654
+ async getBootstrap() {
1655
+ const [businessResult, locationsResult, categoriesResult] = await Promise.all([
1656
+ this.getInfo(),
1657
+ this.getLocations(),
1658
+ safe7(this.client.query("categories#select(id,name,slug)"))
1659
+ ]);
1660
+ if (!businessResult.ok) return businessResult;
1661
+ if (!locationsResult.ok) return locationsResult;
1662
+ if (!categoriesResult.ok) return categoriesResult;
1663
+ const business = businessResult.value;
1664
+ const locations = locationsResult.value;
1665
+ const categories = categoriesResult.value;
1666
+ const defaultLocation = locations[0];
1667
+ return ok({
1668
+ business,
1669
+ location: defaultLocation,
1670
+ locations,
1671
+ categories,
1672
+ currency: business.default_currency,
1673
+ is_open: defaultLocation?.accepts_online_orders ?? false,
1674
+ accepts_orders: defaultLocation?.accepts_online_orders ?? false
1675
+ });
1676
+ }
1677
+ };
1678
+
1679
+ // src/inventory.ts
1680
+ function toCimplifyError8(error) {
1681
+ if (error instanceof CimplifyError) return error;
1682
+ if (error instanceof Error) {
1683
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1684
+ }
1685
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1686
+ }
1687
+ async function safe8(promise) {
1688
+ try {
1689
+ return ok(await promise);
1690
+ } catch (error) {
1691
+ return err(toCimplifyError8(error));
1692
+ }
1693
+ }
1694
+ var InventoryService = class {
1695
+ constructor(client) {
1696
+ this.client = client;
1697
+ }
1698
+ async getStockLevels() {
1699
+ return safe8(this.client.query("inventory.stock_levels"));
1700
+ }
1701
+ async getProductStock(productId, locationId) {
1702
+ if (locationId) {
1703
+ return safe8(
1704
+ this.client.query("inventory.product", {
1705
+ product_id: productId,
1706
+ location_id: locationId
1707
+ })
1708
+ );
1709
+ }
1710
+ return safe8(
1711
+ this.client.query("inventory.product", {
1712
+ product_id: productId
1713
+ })
1714
+ );
1715
+ }
1716
+ async getVariantStock(variantId, locationId) {
1717
+ return safe8(
1718
+ this.client.query("inventory.variant", {
1719
+ variant_id: variantId,
1720
+ location_id: locationId
1721
+ })
1722
+ );
1723
+ }
1724
+ async checkProductAvailability(productId, quantity, locationId) {
1725
+ return safe8(
1726
+ this.client.query("inventory.check_availability", {
1727
+ product_id: productId,
1728
+ quantity,
1729
+ location_id: locationId
1730
+ })
1731
+ );
1732
+ }
1733
+ async checkVariantAvailability(variantId, quantity, locationId) {
1734
+ return safe8(
1735
+ this.client.query("inventory.check_availability", {
1736
+ variant_id: variantId,
1737
+ quantity,
1738
+ location_id: locationId
1739
+ })
1740
+ );
1741
+ }
1742
+ async checkMultipleAvailability(items, locationId) {
1743
+ const results = await Promise.all(
1744
+ items.map(
1745
+ (item) => item.variant_id ? this.checkVariantAvailability(item.variant_id, item.quantity, locationId) : this.checkProductAvailability(item.product_id, item.quantity, locationId)
1746
+ )
1747
+ );
1748
+ for (const result of results) {
1749
+ if (!result.ok) return result;
1750
+ }
1751
+ return ok(results.map((r) => r.value));
1752
+ }
1753
+ async getSummary() {
1754
+ return safe8(this.client.query("inventory.summary"));
1755
+ }
1756
+ async isInStock(productId, locationId) {
1757
+ const result = await this.checkProductAvailability(productId, 1, locationId);
1758
+ if (!result.ok) return result;
1759
+ return ok(result.value.is_available);
1760
+ }
1761
+ async getAvailableQuantity(productId, locationId) {
1762
+ const result = await this.getProductStock(productId, locationId);
1763
+ if (!result.ok) return result;
1764
+ return ok(result.value.available_quantity);
1765
+ }
1766
+ };
1767
+
1768
+ // src/scheduling.ts
1769
+ function toVariables(input) {
1770
+ return Object.fromEntries(Object.entries(input));
1771
+ }
1772
+ function toCimplifyError9(error) {
1773
+ if (error instanceof CimplifyError) return error;
1774
+ if (error instanceof Error) {
1775
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1776
+ }
1777
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1778
+ }
1779
+ async function safe9(promise) {
1780
+ try {
1781
+ return ok(await promise);
1782
+ } catch (error) {
1783
+ return err(toCimplifyError9(error));
1784
+ }
1785
+ }
1786
+ var SchedulingService = class {
1787
+ constructor(client) {
1788
+ this.client = client;
1789
+ }
1790
+ async getServices() {
1791
+ return safe9(this.client.query("scheduling.services"));
1792
+ }
1793
+ /**
1794
+ * Get a specific service by ID
1795
+ * Note: Filters from all services client-side (no single-service endpoint)
1796
+ */
1797
+ async getService(serviceId) {
1798
+ const result = await this.getServices();
1799
+ if (!result.ok) return result;
1800
+ return ok(result.value.find((s) => s.id === serviceId) || null);
1801
+ }
1802
+ async getAvailableSlots(input) {
1803
+ return safe9(
1804
+ this.client.query("scheduling.slots", toVariables(input))
1805
+ );
1806
+ }
1807
+ async checkSlotAvailability(input) {
1808
+ return safe9(
1809
+ this.client.query(
1810
+ "scheduling.check_availability",
1811
+ toVariables(input)
1812
+ )
1813
+ );
1814
+ }
1815
+ async getServiceAvailability(params) {
1816
+ return safe9(
1817
+ this.client.query(
1818
+ "scheduling.availability",
1819
+ toVariables(params)
1820
+ )
1821
+ );
1822
+ }
1823
+ async getBooking(bookingId) {
1824
+ return safe9(this.client.query(`scheduling.${bookingId}`));
1825
+ }
1826
+ async getCustomerBookings() {
1827
+ return safe9(this.client.query("scheduling"));
1828
+ }
1829
+ async getUpcomingBookings() {
1830
+ return safe9(
1831
+ this.client.query(
1832
+ "scheduling[?(@.status!='completed' && @.status!='cancelled')]#sort(start_time,asc)"
1833
+ )
1834
+ );
1835
+ }
1836
+ async getPastBookings(limit = 10) {
1837
+ return safe9(
1838
+ this.client.query(
1839
+ `scheduling[?(@.status=='completed')]#sort(start_time,desc)#limit(${limit})`
1840
+ )
1841
+ );
1842
+ }
1843
+ async cancelBooking(input) {
1844
+ return safe9(this.client.call("scheduling.cancel_booking", input));
1845
+ }
1846
+ async rescheduleBooking(input) {
1847
+ return safe9(this.client.call("scheduling.reschedule_booking", input));
1848
+ }
1849
+ async getNextAvailableSlot(serviceId, fromDate) {
1850
+ const date = fromDate || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1851
+ const result = await this.getAvailableSlots({
1852
+ service_id: serviceId,
1853
+ date
1854
+ });
1855
+ if (!result.ok) return result;
1856
+ return ok(result.value.find((slot) => slot.is_available) || null);
1857
+ }
1858
+ async hasAvailabilityOn(serviceId, date) {
1859
+ const result = await this.getAvailableSlots({
1860
+ service_id: serviceId,
1861
+ date
1862
+ });
1863
+ if (!result.ok) return result;
1864
+ return ok(result.value.some((slot) => slot.is_available));
1865
+ }
1866
+ };
1867
+
1868
+ // src/lite.ts
1869
+ function toCimplifyError10(error) {
1870
+ if (error instanceof CimplifyError) return error;
1871
+ if (error instanceof Error) {
1872
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1873
+ }
1874
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1875
+ }
1876
+ async function safe10(promise) {
1877
+ try {
1878
+ return ok(await promise);
1879
+ } catch (error) {
1880
+ return err(toCimplifyError10(error));
1881
+ }
1882
+ }
1883
+ var LiteService = class {
1884
+ constructor(client) {
1885
+ this.client = client;
1886
+ }
1887
+ async getBootstrap() {
1888
+ return safe10(this.client.query("lite.bootstrap"));
1889
+ }
1890
+ async getTable(tableId) {
1891
+ return safe10(this.client.query(`lite.table.${tableId}`));
1892
+ }
1893
+ async getTableByNumber(tableNumber, locationId) {
1894
+ return safe10(
1895
+ this.client.query("lite.table_by_number", {
1896
+ table_number: tableNumber,
1897
+ location_id: locationId
1898
+ })
1899
+ );
1900
+ }
1901
+ async sendToKitchen(tableId, items) {
1902
+ return safe10(
1903
+ this.client.call("lite.send_to_kitchen", {
1904
+ table_id: tableId,
1905
+ items
1906
+ })
1907
+ );
1908
+ }
1909
+ async callWaiter(tableId, reason) {
1910
+ return safe10(
1911
+ this.client.call("lite.call_waiter", {
1912
+ table_id: tableId,
1913
+ reason
1914
+ })
1915
+ );
1916
+ }
1917
+ async requestBill(tableId) {
1918
+ return safe10(
1919
+ this.client.call("lite.request_bill", {
1920
+ table_id: tableId
1921
+ })
1922
+ );
1923
+ }
1924
+ async getMenu() {
1925
+ return safe10(this.client.query("lite.menu"));
1926
+ }
1927
+ async getMenuByCategory(categoryId) {
1928
+ return safe10(this.client.query(`lite.menu.category.${categoryId}`));
1929
+ }
1930
+ };
1931
+
1932
+ // src/fx.ts
1933
+ function toCimplifyError11(error) {
1934
+ if (error instanceof CimplifyError) return error;
1935
+ if (error instanceof Error) {
1936
+ return new CimplifyError("UNKNOWN_ERROR", error.message, false);
1937
+ }
1938
+ return new CimplifyError("UNKNOWN_ERROR", String(error), false);
1939
+ }
1940
+ async function safe11(promise) {
1941
+ try {
1942
+ return ok(await promise);
1943
+ } catch (error) {
1944
+ return err(toCimplifyError11(error));
1945
+ }
1946
+ }
1947
+ var FxService = class {
1948
+ constructor(client) {
1949
+ this.client = client;
1950
+ }
1951
+ async getRate(from, to) {
1952
+ return safe11(this.client.call("fx.getRate", { from, to }));
1953
+ }
1954
+ async lockQuote(request) {
1955
+ return safe11(this.client.call("fx.lockQuote", request));
1956
+ }
1957
+ };
1958
+
1959
+ // src/types/elements.ts
1960
+ var ELEMENT_TYPES = {
1961
+ AUTH: "auth",
1962
+ ADDRESS: "address",
1963
+ PAYMENT: "payment"
1964
+ };
1965
+ var MESSAGE_TYPES = {
1966
+ // Parent → Iframe
1967
+ INIT: "init",
1968
+ SET_TOKEN: "set_token",
1969
+ GET_DATA: "get_data",
1970
+ REFRESH_TOKEN: "refresh_token",
1971
+ LOGOUT: "logout",
1972
+ PROCESS_CHECKOUT: "process_checkout",
1973
+ ABORT_CHECKOUT: "abort_checkout",
1974
+ // Iframe → Parent
1975
+ READY: "ready",
1976
+ HEIGHT_CHANGE: "height_change",
1977
+ AUTHENTICATED: "authenticated",
1978
+ REQUIRES_OTP: "requires_otp",
1979
+ ERROR: "error",
1980
+ ADDRESS_CHANGED: "address_changed",
1981
+ ADDRESS_SELECTED: "address_selected",
1982
+ PAYMENT_METHOD_SELECTED: "payment_method_selected",
1983
+ TOKEN_REFRESHED: "token_refreshed",
1984
+ LOGOUT_COMPLETE: "logout_complete",
1985
+ CHECKOUT_STATUS: "checkout_status",
1986
+ CHECKOUT_COMPLETE: "checkout_complete"
1987
+ };
1988
+ var EVENT_TYPES = {
1989
+ READY: "ready",
1990
+ AUTHENTICATED: "authenticated",
1991
+ REQUIRES_OTP: "requires_otp",
1992
+ ERROR: "error",
1993
+ CHANGE: "change",
1994
+ BLUR: "blur",
1995
+ FOCUS: "focus"
1996
+ };
1997
+
1998
+ // src/elements.ts
1999
+ function toCheckoutError(code, message, recoverable) {
2000
+ return {
2001
+ success: false,
2002
+ error: {
2003
+ code,
2004
+ message,
2005
+ recoverable
2006
+ }
2007
+ };
2008
+ }
2009
+ var DEFAULT_LINK_URL = "https://link.cimplify.io";
2010
+ function isAllowedOrigin(origin) {
2011
+ try {
2012
+ const url = new URL(origin);
2013
+ const hostname = url.hostname;
2014
+ if (hostname === "localhost" || hostname === "127.0.0.1") {
2015
+ return true;
2016
+ }
2017
+ if (url.protocol !== "https:") {
2018
+ return false;
2019
+ }
2020
+ return hostname === "cimplify.io" || hostname.endsWith(".cimplify.io");
2021
+ } catch {
2022
+ return false;
2023
+ }
2024
+ }
2025
+ function parseIframeMessage(data) {
2026
+ if (!data || typeof data !== "object") {
2027
+ return null;
2028
+ }
2029
+ const maybeType = data.type;
2030
+ if (typeof maybeType !== "string") {
2031
+ return null;
2032
+ }
2033
+ return data;
2034
+ }
2035
+ var CimplifyElements = class {
2036
+ constructor(client, businessId, options = {}) {
2037
+ this.elements = /* @__PURE__ */ new Map();
2038
+ this.accessToken = null;
2039
+ this.accountId = null;
2040
+ this.customerId = null;
2041
+ this.customerData = null;
2042
+ this.addressData = null;
2043
+ this.paymentData = null;
2044
+ this.checkoutInProgress = false;
2045
+ this.activeCheckoutAbort = null;
2046
+ this.businessIdResolvePromise = null;
2047
+ this.client = client;
2048
+ this.businessId = businessId ?? null;
2049
+ this.linkUrl = options.linkUrl || DEFAULT_LINK_URL;
2050
+ this.options = options;
2051
+ this.boundHandleMessage = this.handleMessage.bind(this);
2052
+ if (typeof window !== "undefined") {
2053
+ window.addEventListener("message", this.boundHandleMessage);
2054
+ }
2055
+ }
2056
+ create(type, options = {}) {
2057
+ const existing = this.elements.get(type);
2058
+ if (existing) return existing;
2059
+ const element = new CimplifyElement(type, this.businessId, this.linkUrl, options, this);
2060
+ this.elements.set(type, element);
2061
+ return element;
2062
+ }
2063
+ getElement(type) {
2064
+ return this.elements.get(type);
2065
+ }
2066
+ destroy() {
2067
+ this.elements.forEach((element) => element.destroy());
2068
+ this.elements.clear();
2069
+ if (typeof window !== "undefined") {
2070
+ window.removeEventListener("message", this.boundHandleMessage);
2071
+ }
2072
+ }
2073
+ async submitCheckout(data) {
2074
+ const result = await this.processCheckout({
2075
+ cart_id: data.cart_id,
2076
+ order_type: data.order_type ?? "delivery",
2077
+ location_id: data.location_id,
2078
+ notes: data.notes,
2079
+ scheduled_time: data.scheduled_time,
2080
+ tip_amount: data.tip_amount,
2081
+ enroll_in_link: true
2082
+ });
2083
+ if (result.success) {
2084
+ return {
2085
+ success: true,
2086
+ order: {
2087
+ id: result.order?.id || "",
2088
+ status: result.order?.status || "unknown",
2089
+ total: result.order?.total || ""
2090
+ }
2091
+ };
2092
+ }
2093
+ return {
2094
+ success: false,
2095
+ error: {
2096
+ code: result.error?.code || "CHECKOUT_FAILED",
2097
+ message: result.error?.message || "Checkout failed"
2098
+ }
2099
+ };
2100
+ }
2101
+ processCheckout(options) {
2102
+ let abortFn = null;
2103
+ const task = (async () => {
2104
+ if (this.checkoutInProgress) {
2105
+ return toCheckoutError(
2106
+ "ALREADY_PROCESSING",
2107
+ "Checkout is already in progress.",
2108
+ false
2109
+ );
2110
+ }
2111
+ if (!options.cart_id) {
2112
+ return toCheckoutError(
2113
+ "INVALID_CART",
2114
+ "A valid cart is required before checkout can start.",
2115
+ false
2116
+ );
2117
+ }
2118
+ if (!options.order_type) {
2119
+ return toCheckoutError(
2120
+ "ORDER_TYPE_REQUIRED",
2121
+ "Order type is required before checkout can start.",
2122
+ false
2123
+ );
2124
+ }
2125
+ const paymentElement = this.elements.get(ELEMENT_TYPES.PAYMENT);
2126
+ if (!paymentElement) {
2127
+ return toCheckoutError(
2128
+ "NO_PAYMENT_ELEMENT",
2129
+ "Payment element must be mounted before checkout.",
2130
+ false
2131
+ );
2132
+ }
2133
+ if (!paymentElement.isMounted()) {
2134
+ return toCheckoutError(
2135
+ "PAYMENT_NOT_MOUNTED",
2136
+ "Payment element must be mounted before checkout.",
2137
+ false
2138
+ );
2139
+ }
2140
+ const authElement = this.elements.get(ELEMENT_TYPES.AUTH);
2141
+ if (authElement && !this.accessToken) {
2142
+ return toCheckoutError(
2143
+ "AUTH_INCOMPLETE",
2144
+ "Authentication must complete before checkout can start.",
2145
+ true
2146
+ );
2147
+ }
2148
+ const addressElement = this.elements.get(ELEMENT_TYPES.ADDRESS);
2149
+ if (addressElement) {
2150
+ await addressElement.getData();
2151
+ }
2152
+ await this.hydrateCustomerData();
2153
+ const processMessage = {
2154
+ type: MESSAGE_TYPES.PROCESS_CHECKOUT,
2155
+ cart_id: options.cart_id,
2156
+ order_type: options.order_type,
2157
+ location_id: options.location_id,
2158
+ notes: options.notes,
2159
+ scheduled_time: options.scheduled_time,
2160
+ tip_amount: options.tip_amount,
2161
+ pay_currency: options.pay_currency,
2162
+ enroll_in_link: options.enroll_in_link ?? true,
2163
+ address: this.addressData ?? void 0,
2164
+ customer: this.customerData ? {
2165
+ name: this.customerData.name,
2166
+ email: this.customerData.email,
2167
+ phone: this.customerData.phone
2168
+ } : null,
2169
+ account_id: this.accountId ?? void 0,
2170
+ customer_id: this.customerId ?? void 0
2171
+ };
2172
+ const timeoutMs = options.timeout_ms ?? 18e4;
2173
+ const paymentWindow = paymentElement.getContentWindow();
2174
+ this.checkoutInProgress = true;
2175
+ return new Promise((resolve) => {
2176
+ let settled = false;
2177
+ const cleanup = () => {
2178
+ if (typeof window !== "undefined") {
2179
+ window.removeEventListener("message", handleCheckoutMessage);
2180
+ }
2181
+ clearTimeout(timeout);
2182
+ this.checkoutInProgress = false;
2183
+ this.activeCheckoutAbort = null;
2184
+ };
2185
+ const settle = (result) => {
2186
+ if (settled) {
2187
+ return;
2188
+ }
2189
+ settled = true;
2190
+ cleanup();
2191
+ resolve(result);
2192
+ };
2193
+ const timeout = setTimeout(() => {
2194
+ settle(
2195
+ toCheckoutError(
2196
+ "TIMEOUT",
2197
+ "Checkout timed out before receiving a terminal response.",
2198
+ true
2199
+ )
2200
+ );
2201
+ }, timeoutMs);
2202
+ const handleCheckoutMessage = (event) => {
2203
+ if (!isAllowedOrigin(event.origin)) {
2204
+ return;
2205
+ }
2206
+ const message = parseIframeMessage(event.data);
2207
+ if (!message) {
2208
+ return;
2209
+ }
2210
+ if (message.type === MESSAGE_TYPES.LOGOUT_COMPLETE) {
2211
+ paymentElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
2212
+ settle(
2213
+ toCheckoutError(
2214
+ "AUTH_LOST",
2215
+ "Authentication was cleared during checkout.",
2216
+ true
2217
+ )
2218
+ );
2219
+ return;
2220
+ }
2221
+ if (paymentWindow && event.source && event.source !== paymentWindow) {
2222
+ return;
2223
+ }
2224
+ if (message.type === MESSAGE_TYPES.CHECKOUT_STATUS) {
2225
+ options.on_status_change?.(message.status, message.context);
2226
+ return;
2227
+ }
2228
+ if (message.type === MESSAGE_TYPES.CHECKOUT_COMPLETE) {
2229
+ settle({
2230
+ success: message.success,
2231
+ order: message.order,
2232
+ error: message.error,
2233
+ enrolled_in_link: message.enrolled_in_link
2234
+ });
2235
+ }
2236
+ };
2237
+ if (typeof window !== "undefined") {
2238
+ window.addEventListener("message", handleCheckoutMessage);
2239
+ }
2240
+ abortFn = () => {
2241
+ paymentElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
2242
+ settle(
2243
+ toCheckoutError(
2244
+ "CANCELLED",
2245
+ "Checkout was cancelled.",
2246
+ true
2247
+ )
2248
+ );
2249
+ };
2250
+ this.activeCheckoutAbort = abortFn;
2251
+ paymentElement.sendMessage(processMessage);
2252
+ });
2253
+ })();
2254
+ const abortable = task;
2255
+ abortable.abort = () => {
2256
+ if (abortFn) {
2257
+ abortFn();
2258
+ }
2259
+ };
2260
+ return abortable;
2261
+ }
2262
+ isAuthenticated() {
2263
+ return this.accessToken !== null;
2264
+ }
2265
+ getAccessToken() {
2266
+ return this.accessToken;
2267
+ }
2268
+ getPublicKey() {
2269
+ return this.client.getPublicKey();
2270
+ }
2271
+ getBusinessId() {
2272
+ return this.businessId;
2273
+ }
2274
+ async resolveBusinessId() {
2275
+ if (this.businessId) {
2276
+ return this.businessId;
2277
+ }
2278
+ if (this.businessIdResolvePromise) {
2279
+ return this.businessIdResolvePromise;
2280
+ }
2281
+ this.businessIdResolvePromise = this.client.resolveBusinessId().then((resolvedBusinessId) => {
2282
+ this.businessId = resolvedBusinessId;
2283
+ return resolvedBusinessId;
2284
+ }).catch(() => null).finally(() => {
2285
+ this.businessIdResolvePromise = null;
2286
+ });
2287
+ return this.businessIdResolvePromise;
2288
+ }
2289
+ getAppearance() {
2290
+ return this.options.appearance;
2291
+ }
2292
+ async hydrateCustomerData() {
2293
+ if (!this.accessToken || this.customerData) {
2294
+ return;
2295
+ }
2296
+ if (!this.client.getAccessToken()) {
2297
+ this.client.setAccessToken(this.accessToken);
2298
+ }
2299
+ const linkDataResult = await this.client.link.getLinkData();
2300
+ if (!linkDataResult.ok || !linkDataResult.value?.customer) {
2301
+ return;
2302
+ }
2303
+ const customer = linkDataResult.value.customer;
2304
+ this.customerData = {
2305
+ name: customer.name || "",
2306
+ email: customer.email || null,
2307
+ phone: customer.phone || null
2308
+ };
2309
+ }
2310
+ handleMessage(event) {
2311
+ if (!isAllowedOrigin(event.origin)) {
2312
+ return;
2313
+ }
2314
+ const message = parseIframeMessage(event.data);
2315
+ if (!message) return;
2316
+ switch (message.type) {
2317
+ case MESSAGE_TYPES.AUTHENTICATED:
2318
+ const customer = message.customer ?? {
2319
+ name: "",
2320
+ email: null,
2321
+ phone: null
2322
+ };
2323
+ this.accessToken = message.token;
2324
+ this.accountId = message.accountId;
2325
+ this.customerId = message.customerId;
2326
+ this.customerData = customer;
2327
+ this.client.setAccessToken(message.token);
2328
+ this.elements.forEach((element, type) => {
2329
+ if (type !== ELEMENT_TYPES.AUTH) {
2330
+ element.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token: message.token });
2331
+ }
2332
+ });
2333
+ break;
2334
+ case MESSAGE_TYPES.TOKEN_REFRESHED:
2335
+ this.accessToken = message.token;
2336
+ break;
2337
+ case MESSAGE_TYPES.ADDRESS_CHANGED:
2338
+ case MESSAGE_TYPES.ADDRESS_SELECTED:
2339
+ this.addressData = message.address;
2340
+ break;
2341
+ case MESSAGE_TYPES.PAYMENT_METHOD_SELECTED:
2342
+ this.paymentData = message.method;
2343
+ break;
2344
+ case MESSAGE_TYPES.LOGOUT_COMPLETE:
2345
+ if (this.checkoutInProgress && this.activeCheckoutAbort) {
2346
+ this.activeCheckoutAbort();
2347
+ }
2348
+ this.accessToken = null;
2349
+ this.accountId = null;
2350
+ this.customerId = null;
2351
+ this.customerData = null;
2352
+ this.addressData = null;
2353
+ this.paymentData = null;
2354
+ this.client.clearSession();
2355
+ break;
2356
+ }
2357
+ }
2358
+ _setAddressData(data) {
2359
+ this.addressData = data;
2360
+ }
2361
+ _setPaymentData(data) {
2362
+ this.paymentData = data;
2363
+ }
2364
+ };
2365
+ var CimplifyElement = class {
2366
+ constructor(type, businessId, linkUrl, options, parent) {
2367
+ this.iframe = null;
2368
+ this.container = null;
2369
+ this.mounted = false;
2370
+ this.eventHandlers = /* @__PURE__ */ new Map();
2371
+ this.resolvers = /* @__PURE__ */ new Map();
2372
+ this.type = type;
2373
+ this.businessId = businessId;
2374
+ this.linkUrl = linkUrl;
2375
+ this.options = options;
2376
+ this.parent = parent;
2377
+ this.boundHandleMessage = this.handleMessage.bind(this);
2378
+ if (typeof window !== "undefined") {
2379
+ window.addEventListener("message", this.boundHandleMessage);
2380
+ }
2381
+ }
2382
+ mount(container) {
2383
+ if (this.mounted) {
2384
+ console.warn(`Element ${this.type} is already mounted`);
2385
+ return;
2386
+ }
2387
+ const target = typeof container === "string" ? document.querySelector(container) : container;
2388
+ if (!target) {
2389
+ console.error(`Container not found: ${container}`);
2390
+ return;
2391
+ }
2392
+ this.container = target;
2393
+ this.mounted = true;
2394
+ void this.createIframe();
2395
+ }
2396
+ destroy() {
2397
+ if (this.iframe) {
2398
+ this.iframe.remove();
2399
+ this.iframe = null;
2400
+ }
2401
+ this.container = null;
2402
+ this.mounted = false;
2403
+ this.eventHandlers.clear();
2404
+ this.resolvers.forEach((entry) => clearTimeout(entry.timeoutId));
2405
+ this.resolvers.clear();
2406
+ if (typeof window !== "undefined") {
2407
+ window.removeEventListener("message", this.boundHandleMessage);
2408
+ }
2409
+ }
2410
+ on(event, handler) {
2411
+ if (!this.eventHandlers.has(event)) {
2412
+ this.eventHandlers.set(event, /* @__PURE__ */ new Set());
2413
+ }
2414
+ this.eventHandlers.get(event).add(handler);
2415
+ }
2416
+ off(event, handler) {
2417
+ this.eventHandlers.get(event)?.delete(handler);
2418
+ }
2419
+ async getData() {
2420
+ if (!this.isMounted()) {
2421
+ return null;
2422
+ }
2423
+ return new Promise((resolve) => {
2424
+ const id = Math.random().toString(36).slice(2);
2425
+ const timeoutId = setTimeout(() => {
2426
+ const entry = this.resolvers.get(id);
2427
+ if (!entry) {
2428
+ return;
2429
+ }
2430
+ this.resolvers.delete(id);
2431
+ entry.resolve(null);
2432
+ }, 5e3);
2433
+ this.resolvers.set(id, { resolve, timeoutId });
2434
+ this.sendMessage({ type: MESSAGE_TYPES.GET_DATA });
2435
+ });
2436
+ }
2437
+ sendMessage(message) {
2438
+ if (this.iframe?.contentWindow) {
2439
+ this.iframe.contentWindow.postMessage(message, this.linkUrl);
2440
+ }
2441
+ }
2442
+ getContentWindow() {
2443
+ return this.iframe?.contentWindow ?? null;
2444
+ }
2445
+ isMounted() {
2446
+ return this.mounted && Boolean(this.iframe) && this.iframe?.isConnected === true;
2447
+ }
2448
+ async createIframe() {
2449
+ if (!this.container) return;
2450
+ const resolvedBusinessId = this.businessId ?? await this.parent.resolveBusinessId();
2451
+ if (!resolvedBusinessId || !this.container || !this.mounted) {
2452
+ console.error("Unable to mount element without a resolved business ID");
2453
+ this.emit(EVENT_TYPES.ERROR, {
2454
+ code: "BUSINESS_ID_REQUIRED",
2455
+ message: "Unable to initialize checkout without a business ID."
2456
+ });
2457
+ return;
2458
+ }
2459
+ this.businessId = resolvedBusinessId;
2460
+ const iframe = document.createElement("iframe");
2461
+ const url = new URL(`${this.linkUrl}/elements/${this.type}`);
2462
+ url.searchParams.set("businessId", resolvedBusinessId);
2463
+ if (this.options.prefillEmail) url.searchParams.set("email", this.options.prefillEmail);
2464
+ if (this.options.mode) url.searchParams.set("mode", this.options.mode);
2465
+ iframe.src = url.toString();
2466
+ iframe.style.border = "none";
2467
+ iframe.style.width = "100%";
2468
+ iframe.style.display = "block";
2469
+ iframe.style.overflow = "hidden";
2470
+ iframe.setAttribute("allowtransparency", "true");
2471
+ iframe.setAttribute("frameborder", "0");
2472
+ iframe.setAttribute(
2473
+ "sandbox",
2474
+ "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
2475
+ );
2476
+ this.iframe = iframe;
2477
+ this.container.appendChild(iframe);
2478
+ iframe.onload = () => {
2479
+ const publicKey = this.parent.getPublicKey();
2480
+ this.sendMessage({
2481
+ type: MESSAGE_TYPES.INIT,
2482
+ businessId: resolvedBusinessId,
2483
+ publicKey,
2484
+ demoMode: publicKey.length === 0,
2485
+ prefillEmail: this.options.prefillEmail,
2486
+ appearance: this.parent.getAppearance()
2487
+ });
2488
+ const token = this.parent.getAccessToken();
2489
+ if (token && this.type !== ELEMENT_TYPES.AUTH) {
2490
+ this.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token });
2491
+ }
2492
+ };
2493
+ }
2494
+ handleMessage(event) {
2495
+ if (!isAllowedOrigin(event.origin)) {
2496
+ return;
2497
+ }
2498
+ const message = parseIframeMessage(event.data);
2499
+ if (!message) return;
2500
+ switch (message.type) {
2501
+ case MESSAGE_TYPES.READY:
2502
+ this.emit(EVENT_TYPES.READY, { height: message.height });
2503
+ break;
2504
+ case MESSAGE_TYPES.HEIGHT_CHANGE:
2505
+ if (this.iframe) this.iframe.style.height = `${message.height}px`;
2506
+ break;
2507
+ case MESSAGE_TYPES.AUTHENTICATED:
2508
+ const customer = message.customer ?? {
2509
+ name: "",
2510
+ email: null,
2511
+ phone: null
2512
+ };
2513
+ this.emit(EVENT_TYPES.AUTHENTICATED, {
2514
+ accountId: message.accountId,
2515
+ customerId: message.customerId,
2516
+ token: message.token,
2517
+ customer
2518
+ });
2519
+ break;
2520
+ case MESSAGE_TYPES.REQUIRES_OTP:
2521
+ this.emit(EVENT_TYPES.REQUIRES_OTP, { contactMasked: message.contactMasked });
2522
+ break;
2523
+ case MESSAGE_TYPES.ERROR:
2524
+ this.emit(EVENT_TYPES.ERROR, { code: message.code, message: message.message });
2525
+ break;
2526
+ case MESSAGE_TYPES.ADDRESS_CHANGED:
2527
+ case MESSAGE_TYPES.ADDRESS_SELECTED:
2528
+ this.parent._setAddressData(message.address);
2529
+ this.emit(EVENT_TYPES.CHANGE, { address: message.address });
2530
+ this.resolveData(message.address);
2531
+ break;
2532
+ case MESSAGE_TYPES.PAYMENT_METHOD_SELECTED:
2533
+ this.parent._setPaymentData(message.method);
2534
+ this.emit(EVENT_TYPES.CHANGE, { paymentMethod: message.method });
2535
+ this.resolveData(message.method);
2536
+ break;
2537
+ }
2538
+ }
2539
+ emit(event, data) {
2540
+ this.eventHandlers.get(event)?.forEach((handler) => handler(data));
2541
+ }
2542
+ resolveData(data) {
2543
+ this.resolvers.forEach((entry) => {
2544
+ clearTimeout(entry.timeoutId);
2545
+ entry.resolve(data);
2546
+ });
2547
+ this.resolvers.clear();
2548
+ }
2549
+ };
2550
+ function createElements(client, businessId, options) {
2551
+ return new CimplifyElements(client, businessId, options);
2552
+ }
2553
+
2554
+ // src/query/builder.ts
2555
+ var QueryBuilder = class {
2556
+ constructor(entity) {
2557
+ this.filters = [];
2558
+ this.modifiers = [];
2559
+ this.pathSegments = [];
2560
+ this.entity = entity;
2561
+ }
2562
+ path(segment) {
2563
+ this.pathSegments.push(segment);
2564
+ return this;
2565
+ }
2566
+ where(field, op, value) {
2567
+ const v = typeof value === "string" ? `'${value}'` : value;
2568
+ if (op === "contains" || op === "startsWith") {
2569
+ this.filters.push(`@.${field} ${op} ${v}`);
2570
+ } else {
2571
+ this.filters.push(`@.${field}${op}${v}`);
2572
+ }
2573
+ return this;
2574
+ }
2575
+ and(field, op, value) {
2576
+ return this.where(field, op, value);
2577
+ }
2578
+ sort(field, order = "asc") {
2579
+ this.modifiers.push(`sort(${field},${order})`);
2580
+ return this;
2581
+ }
2582
+ limit(n) {
2583
+ this.modifiers.push(`limit(${n})`);
2584
+ return this;
2585
+ }
2586
+ offset(n) {
2587
+ this.modifiers.push(`offset(${n})`);
2588
+ return this;
2589
+ }
2590
+ count() {
2591
+ this.modifiers.push("count");
2592
+ return this;
2593
+ }
2594
+ enriched() {
2595
+ this.modifiers.push("enriched");
2596
+ return this;
2597
+ }
2598
+ build() {
2599
+ let query2 = this.entity;
2600
+ if (this.pathSegments.length > 0) {
2601
+ query2 += "." + this.pathSegments.join(".");
2602
+ }
2603
+ if (this.filters.length > 0) {
2604
+ query2 += `[?(${this.filters.join(" && ")})]`;
2605
+ }
2606
+ for (const mod of this.modifiers) {
2607
+ query2 += `#${mod}`;
2608
+ }
2609
+ return query2;
2610
+ }
2611
+ toString() {
2612
+ return this.build();
2613
+ }
2614
+ };
2615
+ function query(entity) {
2616
+ return new QueryBuilder(entity);
2617
+ }
2618
+
2619
+ exports.AuthService = AuthService;
2620
+ exports.BusinessService = BusinessService;
2621
+ exports.CartOperations = CartOperations;
2622
+ exports.CatalogueQueries = CatalogueQueries;
2623
+ exports.CheckoutOperations = CheckoutService;
2624
+ exports.CheckoutService = CheckoutService;
2625
+ exports.CimplifyElement = CimplifyElement;
2626
+ exports.CimplifyElements = CimplifyElements;
2627
+ exports.ELEMENT_TYPES = ELEMENT_TYPES;
2628
+ exports.EVENT_TYPES = EVENT_TYPES;
2629
+ exports.FxService = FxService;
2630
+ exports.InventoryService = InventoryService;
2631
+ exports.LinkService = LinkService;
2632
+ exports.LiteService = LiteService;
2633
+ exports.MESSAGE_TYPES = MESSAGE_TYPES;
2634
+ exports.OrderQueries = OrderQueries;
2635
+ exports.QueryBuilder = QueryBuilder;
2636
+ exports.SchedulingService = SchedulingService;
2637
+ exports.createElements = createElements;
2638
+ exports.generateIdempotencyKey = generateIdempotencyKey;
2639
+ exports.query = query;