@cimplify/sdk 0.1.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 ADDED
@@ -0,0 +1,1500 @@
1
+ 'use strict';
2
+
3
+ // src/types/common.ts
4
+ var CimplifyError = class extends Error {
5
+ constructor(code, message, retryable = false) {
6
+ super(message);
7
+ this.code = code;
8
+ this.retryable = retryable;
9
+ this.name = "CimplifyError";
10
+ }
11
+ };
12
+
13
+ // src/catalogue.ts
14
+ var CatalogueQueries = class {
15
+ constructor(client) {
16
+ this.client = client;
17
+ }
18
+ // --------------------------------------------------------------------------
19
+ // PRODUCTS
20
+ // --------------------------------------------------------------------------
21
+ async getProducts(options) {
22
+ let query2 = "products";
23
+ const filters = [];
24
+ if (options?.category) {
25
+ filters.push(`@.category_id=='${options.category}'`);
26
+ }
27
+ if (options?.featured !== void 0) {
28
+ filters.push(`@.featured==${options.featured}`);
29
+ }
30
+ if (options?.in_stock !== void 0) {
31
+ filters.push(`@.in_stock==${options.in_stock}`);
32
+ }
33
+ if (options?.search) {
34
+ filters.push(`@.name contains '${options.search}'`);
35
+ }
36
+ if (options?.min_price !== void 0) {
37
+ filters.push(`@.price>=${options.min_price}`);
38
+ }
39
+ if (options?.max_price !== void 0) {
40
+ filters.push(`@.price<=${options.max_price}`);
41
+ }
42
+ if (filters.length > 0) {
43
+ query2 += `[?(${filters.join(" && ")})]`;
44
+ }
45
+ if (options?.sort_by) {
46
+ query2 += `#sort(${options.sort_by},${options.sort_order || "asc"})`;
47
+ }
48
+ if (options?.limit) {
49
+ query2 += `#limit(${options.limit})`;
50
+ }
51
+ if (options?.offset) {
52
+ query2 += `#offset(${options.offset})`;
53
+ }
54
+ return this.client.query(query2);
55
+ }
56
+ async getProduct(id) {
57
+ return this.client.query(`products.${id}`);
58
+ }
59
+ async getProductBySlug(slug) {
60
+ const products = await this.client.query(
61
+ `products[?(@.slug=='${slug}')]`
62
+ );
63
+ if (!products.length) {
64
+ throw new Error(`Product not found: ${slug}`);
65
+ }
66
+ return products[0];
67
+ }
68
+ // --------------------------------------------------------------------------
69
+ // VARIANTS
70
+ // --------------------------------------------------------------------------
71
+ async getVariants(productId) {
72
+ return this.client.query(`products.${productId}.variants`);
73
+ }
74
+ async getVariantAxes(productId) {
75
+ return this.client.query(`products.${productId}.variant_axes`);
76
+ }
77
+ /**
78
+ * Find a variant by axis selections (e.g., { "Size": "Large", "Color": "Red" })
79
+ * Returns the matching variant or null if no match found.
80
+ */
81
+ async getVariantByAxisSelections(productId, selections) {
82
+ return this.client.query(
83
+ `products.${productId}.variant`,
84
+ { axis_selections: selections }
85
+ );
86
+ }
87
+ /**
88
+ * Get a specific variant by its ID
89
+ */
90
+ async getVariantById(productId, variantId) {
91
+ return this.client.query(
92
+ `products.${productId}.variant.${variantId}`
93
+ );
94
+ }
95
+ // --------------------------------------------------------------------------
96
+ // ADD-ONS
97
+ // --------------------------------------------------------------------------
98
+ async getAddOns(productId) {
99
+ return this.client.query(`products.${productId}.add_ons`);
100
+ }
101
+ // --------------------------------------------------------------------------
102
+ // CATEGORIES
103
+ // --------------------------------------------------------------------------
104
+ async getCategories() {
105
+ return this.client.query("categories");
106
+ }
107
+ async getCategory(id) {
108
+ return this.client.query(`categories.${id}`);
109
+ }
110
+ async getCategoryBySlug(slug) {
111
+ const categories = await this.client.query(
112
+ `categories[?(@.slug=='${slug}')]`
113
+ );
114
+ if (!categories.length) {
115
+ throw new Error(`Category not found: ${slug}`);
116
+ }
117
+ return categories[0];
118
+ }
119
+ async getCategoryProducts(categoryId) {
120
+ return this.client.query(
121
+ `products[?(@.category_id=='${categoryId}')]`
122
+ );
123
+ }
124
+ // --------------------------------------------------------------------------
125
+ // COLLECTIONS
126
+ // --------------------------------------------------------------------------
127
+ async getCollections() {
128
+ return this.client.query("collections");
129
+ }
130
+ async getCollection(id) {
131
+ return this.client.query(`collections.${id}`);
132
+ }
133
+ async getCollectionBySlug(slug) {
134
+ const collections = await this.client.query(
135
+ `collections[?(@.slug=='${slug}')]`
136
+ );
137
+ if (!collections.length) {
138
+ throw new Error(`Collection not found: ${slug}`);
139
+ }
140
+ return collections[0];
141
+ }
142
+ async getCollectionProducts(collectionId) {
143
+ return this.client.query(`collections.${collectionId}.products`);
144
+ }
145
+ async searchCollections(query2, limit = 20) {
146
+ return this.client.query(
147
+ `collections[?(@.name contains '${query2}')]#limit(${limit})`
148
+ );
149
+ }
150
+ // --------------------------------------------------------------------------
151
+ // BUNDLES
152
+ // --------------------------------------------------------------------------
153
+ async getBundles() {
154
+ return this.client.query("bundles");
155
+ }
156
+ async getBundle(id) {
157
+ return this.client.query(`bundles.${id}`);
158
+ }
159
+ async getBundleBySlug(slug) {
160
+ const bundles = await this.client.query(
161
+ `bundles[?(@.slug=='${slug}')]`
162
+ );
163
+ if (!bundles.length) {
164
+ throw new Error(`Bundle not found: ${slug}`);
165
+ }
166
+ return bundles[0];
167
+ }
168
+ async searchBundles(query2, limit = 20) {
169
+ return this.client.query(
170
+ `bundles[?(@.name contains '${query2}')]#limit(${limit})`
171
+ );
172
+ }
173
+ // --------------------------------------------------------------------------
174
+ // COMPOSITES (Build-Your-Own)
175
+ // --------------------------------------------------------------------------
176
+ async getComposites(options) {
177
+ let query2 = "composites";
178
+ if (options?.limit) {
179
+ query2 += `#limit(${options.limit})`;
180
+ }
181
+ return this.client.query(query2);
182
+ }
183
+ async getComposite(id) {
184
+ return this.client.query(`composites.${id}`);
185
+ }
186
+ async getCompositeByProductId(productId) {
187
+ return this.client.query(
188
+ `composites.by_product.${productId}`
189
+ );
190
+ }
191
+ async calculateCompositePrice(compositeId, selections, locationId) {
192
+ return this.client.call(
193
+ "composite.calculatePrice",
194
+ {
195
+ composite_id: compositeId,
196
+ selections,
197
+ location_id: locationId
198
+ }
199
+ );
200
+ }
201
+ // --------------------------------------------------------------------------
202
+ // SEARCH
203
+ // --------------------------------------------------------------------------
204
+ async search(query2, options) {
205
+ const limit = options?.limit ?? 20;
206
+ let searchQuery = `products[?(@.name contains '${query2}')]`;
207
+ if (options?.category) {
208
+ searchQuery = `products[?(@.name contains '${query2}' && @.category_id=='${options.category}')]`;
209
+ }
210
+ searchQuery += `#limit(${limit})`;
211
+ return this.client.query(searchQuery);
212
+ }
213
+ async searchProducts(query2, options) {
214
+ return this.client.call("catalogue.search", {
215
+ query: query2,
216
+ limit: options?.limit ?? 20,
217
+ category: options?.category
218
+ });
219
+ }
220
+ // --------------------------------------------------------------------------
221
+ // MENU (Restaurant-specific)
222
+ // --------------------------------------------------------------------------
223
+ async getMenu(options) {
224
+ let query2 = "menu";
225
+ if (options?.category) {
226
+ query2 = `menu[?(@.category=='${options.category}')]`;
227
+ }
228
+ if (options?.limit) {
229
+ query2 += `#limit(${options.limit})`;
230
+ }
231
+ return this.client.query(query2);
232
+ }
233
+ async getMenuCategory(categoryId) {
234
+ return this.client.query(`menu.category.${categoryId}`);
235
+ }
236
+ async getMenuItem(itemId) {
237
+ return this.client.query(`menu.${itemId}`);
238
+ }
239
+ };
240
+
241
+ // src/cart.ts
242
+ var CartOperations = class {
243
+ constructor(client) {
244
+ this.client = client;
245
+ }
246
+ // --------------------------------------------------------------------------
247
+ // CART QUERIES
248
+ // --------------------------------------------------------------------------
249
+ /**
250
+ * Get the enriched cart with product names, images, and details.
251
+ * This is the main method for storefront display.
252
+ */
253
+ async get() {
254
+ return this.client.query("cart#enriched");
255
+ }
256
+ async getRaw() {
257
+ return this.client.query("cart");
258
+ }
259
+ async getItems() {
260
+ return this.client.query("cart_items");
261
+ }
262
+ async getCount() {
263
+ return this.client.query("cart#count");
264
+ }
265
+ async getTotal() {
266
+ return this.client.query("cart#total");
267
+ }
268
+ async getSummary() {
269
+ const cart = await this.get();
270
+ return {
271
+ item_count: cart.items.length,
272
+ total_items: cart.items.reduce((sum, item) => sum + item.quantity, 0),
273
+ subtotal: cart.pricing.subtotal,
274
+ discount_amount: cart.pricing.total_discounts,
275
+ tax_amount: cart.pricing.tax_amount,
276
+ total: cart.pricing.total_price,
277
+ currency: cart.pricing.currency
278
+ };
279
+ }
280
+ // --------------------------------------------------------------------------
281
+ // CART MUTATIONS
282
+ // --------------------------------------------------------------------------
283
+ async addItem(input) {
284
+ return this.client.call("cart.addItem", input);
285
+ }
286
+ async updateItem(cartItemId, updates) {
287
+ return this.client.call("cart.updateItem", {
288
+ cart_item_id: cartItemId,
289
+ ...updates
290
+ });
291
+ }
292
+ async updateQuantity(cartItemId, quantity) {
293
+ return this.client.call("cart.updateItemQuantity", {
294
+ cart_item_id: cartItemId,
295
+ quantity
296
+ });
297
+ }
298
+ async removeItem(cartItemId) {
299
+ return this.client.call("cart.removeItem", {
300
+ cart_item_id: cartItemId
301
+ });
302
+ }
303
+ async clear() {
304
+ return this.client.call("cart.clearCart");
305
+ }
306
+ // --------------------------------------------------------------------------
307
+ // COUPONS & DISCOUNTS
308
+ // --------------------------------------------------------------------------
309
+ async applyCoupon(code) {
310
+ return this.client.call("cart.applyCoupon", {
311
+ coupon_code: code
312
+ });
313
+ }
314
+ async removeCoupon() {
315
+ return this.client.call("cart.removeCoupon");
316
+ }
317
+ // --------------------------------------------------------------------------
318
+ // CONVENIENCE METHODS
319
+ // --------------------------------------------------------------------------
320
+ async isEmpty() {
321
+ const count = await this.getCount();
322
+ return count === 0;
323
+ }
324
+ async hasItem(productId, variantId) {
325
+ const items = await this.getItems();
326
+ return items.some((item) => {
327
+ const matchesProduct = item.item_id === productId;
328
+ if (!variantId) return matchesProduct;
329
+ const config = item.configuration;
330
+ if ("variant" in config && config.variant) {
331
+ return matchesProduct && config.variant.variant_id === variantId;
332
+ }
333
+ return matchesProduct;
334
+ });
335
+ }
336
+ async findItem(productId, variantId) {
337
+ const items = await this.getItems();
338
+ return items.find((item) => {
339
+ const matchesProduct = item.item_id === productId;
340
+ if (!variantId) return matchesProduct;
341
+ const config = item.configuration;
342
+ if ("variant" in config && config.variant) {
343
+ return matchesProduct && config.variant.variant_id === variantId;
344
+ }
345
+ return matchesProduct;
346
+ });
347
+ }
348
+ };
349
+
350
+ // src/constants.ts
351
+ var CHECKOUT_MODE = {
352
+ LINK: "link",
353
+ GUEST: "guest"
354
+ };
355
+ var ORDER_TYPE = {
356
+ DELIVERY: "delivery",
357
+ PICKUP: "pickup",
358
+ DINE_IN: "dine-in",
359
+ WALK_IN: "walk-in"
360
+ };
361
+ var PAYMENT_METHOD = {
362
+ MOBILE_MONEY: "mobile_money",
363
+ CARD: "card"
364
+ };
365
+ var CHECKOUT_STEP = {
366
+ AUTHENTICATION: "authentication",
367
+ ORDER_DETAILS: "order_details",
368
+ PAYMENT_METHOD: "payment_method",
369
+ PAYMENT: "payment",
370
+ CONFIRMATION: "confirmation"
371
+ };
372
+ var PAYMENT_STATE = {
373
+ INITIAL: "initial",
374
+ PREPARING: "preparing",
375
+ PROCESSING: "processing",
376
+ VERIFYING: "verifying",
377
+ AWAITING_AUTHORIZATION: "awaiting_authorization",
378
+ SUCCESS: "success",
379
+ ERROR: "error",
380
+ TIMEOUT: "timeout"
381
+ };
382
+ var PICKUP_TIME_TYPE = {
383
+ ASAP: "asap",
384
+ SCHEDULED: "scheduled"
385
+ };
386
+ var MOBILE_MONEY_PROVIDER = {
387
+ MTN: "mtn",
388
+ VODAFONE: "vodafone",
389
+ AIRTEL: "airtel"
390
+ };
391
+ var AUTHORIZATION_TYPE = {
392
+ OTP: "otp",
393
+ PIN: "pin",
394
+ PHONE: "phone",
395
+ BIRTHDAY: "birthday",
396
+ ADDRESS: "address"
397
+ };
398
+ var LINK_QUERY = {
399
+ DATA: "link.data",
400
+ ADDRESSES: "link.addresses",
401
+ MOBILE_MONEY: "link.mobile_money",
402
+ PREFERENCES: "link.preferences",
403
+ SESSIONS: "link.sessions"
404
+ };
405
+ var LINK_MUTATION = {
406
+ CHECK_STATUS: "link.check_status",
407
+ ENROLL: "link.enroll",
408
+ ENROLL_AND_LINK_ORDER: "link.enroll_and_link_order",
409
+ UPDATE_PREFERENCES: "link.update_preferences",
410
+ CREATE_ADDRESS: "link.create_address",
411
+ UPDATE_ADDRESS: "link.update_address",
412
+ DELETE_ADDRESS: "link.delete_address",
413
+ SET_DEFAULT_ADDRESS: "link.set_default_address",
414
+ TRACK_ADDRESS_USAGE: "link.track_address_usage",
415
+ CREATE_MOBILE_MONEY: "link.create_mobile_money",
416
+ DELETE_MOBILE_MONEY: "link.delete_mobile_money",
417
+ SET_DEFAULT_MOBILE_MONEY: "link.set_default_mobile_money",
418
+ TRACK_MOBILE_MONEY_USAGE: "link.track_mobile_money_usage",
419
+ VERIFY_MOBILE_MONEY: "link.verify_mobile_money",
420
+ REVOKE_SESSION: "link.revoke_session",
421
+ REVOKE_ALL_SESSIONS: "link.revoke_all_sessions"
422
+ };
423
+ var AUTH_MUTATION = {
424
+ REQUEST_OTP: "auth.request_otp",
425
+ VERIFY_OTP: "auth.verify_otp"
426
+ };
427
+ var CHECKOUT_MUTATION = {
428
+ PROCESS: "checkout.process"
429
+ };
430
+ var PAYMENT_MUTATION = {
431
+ SUBMIT_AUTHORIZATION: "payment.submit_authorization",
432
+ CHECK_STATUS: "order.poll_payment_status"
433
+ };
434
+ var ORDER_MUTATION = {
435
+ UPDATE_CUSTOMER: "order.update_order_customer"
436
+ };
437
+ var DEFAULT_CURRENCY = "GHS";
438
+ var DEFAULT_COUNTRY = "GHA";
439
+
440
+ // src/checkout.ts
441
+ var CheckoutService = class {
442
+ constructor(client) {
443
+ this.client = client;
444
+ }
445
+ async process(data) {
446
+ return this.client.call(CHECKOUT_MUTATION.PROCESS, {
447
+ checkout_data: data
448
+ });
449
+ }
450
+ async initializePayment(orderId, method) {
451
+ return this.client.call("order.initializePayment", {
452
+ order_id: orderId,
453
+ payment_method: method
454
+ });
455
+ }
456
+ async submitAuthorization(input) {
457
+ return this.client.call(
458
+ PAYMENT_MUTATION.SUBMIT_AUTHORIZATION,
459
+ input
460
+ );
461
+ }
462
+ async pollPaymentStatus(orderId) {
463
+ return this.client.call(
464
+ PAYMENT_MUTATION.CHECK_STATUS,
465
+ orderId
466
+ );
467
+ }
468
+ async updateOrderCustomer(orderId, customer) {
469
+ return this.client.call(ORDER_MUTATION.UPDATE_CUSTOMER, {
470
+ order_id: orderId,
471
+ ...customer
472
+ });
473
+ }
474
+ async verifyPayment(orderId) {
475
+ return this.client.call("order.verifyPayment", {
476
+ order_id: orderId
477
+ });
478
+ }
479
+ };
480
+
481
+ // src/orders.ts
482
+ var OrderQueries = class {
483
+ constructor(client) {
484
+ this.client = client;
485
+ }
486
+ async list(options) {
487
+ let query2 = "orders";
488
+ if (options?.status) {
489
+ query2 += `[?(@.status=='${options.status}')]`;
490
+ }
491
+ query2 += "#sort(created_at,desc)";
492
+ if (options?.limit) {
493
+ query2 += `#limit(${options.limit})`;
494
+ }
495
+ if (options?.offset) {
496
+ query2 += `#offset(${options.offset})`;
497
+ }
498
+ return this.client.query(query2);
499
+ }
500
+ async get(orderId) {
501
+ return this.client.query(`orders.${orderId}`);
502
+ }
503
+ async getRecent(limit = 5) {
504
+ return this.client.query(
505
+ `orders#sort(created_at,desc)#limit(${limit})`
506
+ );
507
+ }
508
+ async getByStatus(status) {
509
+ return this.client.query(`orders[?(@.status=='${status}')]`);
510
+ }
511
+ async cancel(orderId, reason) {
512
+ return this.client.call("order.cancelOrder", {
513
+ order_id: orderId,
514
+ reason
515
+ });
516
+ }
517
+ };
518
+
519
+ // src/link.ts
520
+ var LinkService = class {
521
+ constructor(client) {
522
+ this.client = client;
523
+ }
524
+ async requestOtp(input) {
525
+ return this.client.linkPost("/v1/link/auth/request-otp", input);
526
+ }
527
+ async verifyOtp(input) {
528
+ const response = await this.client.linkPost(
529
+ "/v1/link/auth/verify-otp",
530
+ input
531
+ );
532
+ if (response.session_token) {
533
+ this.client.setSessionToken(response.session_token);
534
+ }
535
+ return response;
536
+ }
537
+ async logout() {
538
+ const result = await this.client.linkPost("/v1/link/auth/logout");
539
+ this.client.clearSession();
540
+ return result;
541
+ }
542
+ async checkStatus(contact) {
543
+ return this.client.call(LINK_MUTATION.CHECK_STATUS, {
544
+ contact
545
+ });
546
+ }
547
+ async getLinkData() {
548
+ return this.client.query(LINK_QUERY.DATA);
549
+ }
550
+ async getAddresses() {
551
+ return this.client.query(LINK_QUERY.ADDRESSES);
552
+ }
553
+ async getMobileMoney() {
554
+ return this.client.query(LINK_QUERY.MOBILE_MONEY);
555
+ }
556
+ async getPreferences() {
557
+ return this.client.query(LINK_QUERY.PREFERENCES);
558
+ }
559
+ async enroll(data) {
560
+ return this.client.call(LINK_MUTATION.ENROLL, data);
561
+ }
562
+ async enrollAndLinkOrder(data) {
563
+ return this.client.call(
564
+ LINK_MUTATION.ENROLL_AND_LINK_ORDER,
565
+ data
566
+ );
567
+ }
568
+ async updatePreferences(preferences) {
569
+ return this.client.call(
570
+ LINK_MUTATION.UPDATE_PREFERENCES,
571
+ preferences
572
+ );
573
+ }
574
+ async createAddress(input) {
575
+ return this.client.call(
576
+ LINK_MUTATION.CREATE_ADDRESS,
577
+ input
578
+ );
579
+ }
580
+ async updateAddress(input) {
581
+ return this.client.call(LINK_MUTATION.UPDATE_ADDRESS, input);
582
+ }
583
+ async deleteAddress(addressId) {
584
+ return this.client.call(
585
+ LINK_MUTATION.DELETE_ADDRESS,
586
+ addressId
587
+ );
588
+ }
589
+ async setDefaultAddress(addressId) {
590
+ return this.client.call(
591
+ LINK_MUTATION.SET_DEFAULT_ADDRESS,
592
+ addressId
593
+ );
594
+ }
595
+ async trackAddressUsage(addressId) {
596
+ return this.client.call(LINK_MUTATION.TRACK_ADDRESS_USAGE, {
597
+ address_id: addressId
598
+ });
599
+ }
600
+ async createMobileMoney(input) {
601
+ return this.client.call(
602
+ LINK_MUTATION.CREATE_MOBILE_MONEY,
603
+ input
604
+ );
605
+ }
606
+ async deleteMobileMoney(mobileMoneyId) {
607
+ return this.client.call(
608
+ LINK_MUTATION.DELETE_MOBILE_MONEY,
609
+ mobileMoneyId
610
+ );
611
+ }
612
+ async setDefaultMobileMoney(mobileMoneyId) {
613
+ return this.client.call(
614
+ LINK_MUTATION.SET_DEFAULT_MOBILE_MONEY,
615
+ mobileMoneyId
616
+ );
617
+ }
618
+ async trackMobileMoneyUsage(mobileMoneyId) {
619
+ return this.client.call(LINK_MUTATION.TRACK_MOBILE_MONEY_USAGE, {
620
+ mobile_money_id: mobileMoneyId
621
+ });
622
+ }
623
+ async verifyMobileMoney(mobileMoneyId) {
624
+ return this.client.call(
625
+ LINK_MUTATION.VERIFY_MOBILE_MONEY,
626
+ mobileMoneyId
627
+ );
628
+ }
629
+ async getSessions() {
630
+ return this.client.linkGet("/v1/link/sessions");
631
+ }
632
+ async revokeSession(sessionId) {
633
+ return this.client.linkDelete(
634
+ `/v1/link/sessions/${sessionId}`
635
+ );
636
+ }
637
+ async revokeAllSessions() {
638
+ return this.client.linkDelete("/v1/link/sessions");
639
+ }
640
+ async getAddressesRest() {
641
+ return this.client.linkGet("/v1/link/addresses");
642
+ }
643
+ async createAddressRest(input) {
644
+ return this.client.linkPost("/v1/link/addresses", input);
645
+ }
646
+ async deleteAddressRest(addressId) {
647
+ return this.client.linkDelete(`/v1/link/addresses/${addressId}`);
648
+ }
649
+ async setDefaultAddressRest(addressId) {
650
+ return this.client.linkPost(
651
+ `/v1/link/addresses/${addressId}/default`
652
+ );
653
+ }
654
+ async getMobileMoneyRest() {
655
+ return this.client.linkGet("/v1/link/mobile-money");
656
+ }
657
+ async createMobileMoneyRest(input) {
658
+ return this.client.linkPost("/v1/link/mobile-money", input);
659
+ }
660
+ async deleteMobileMoneyRest(mobileMoneyId) {
661
+ return this.client.linkDelete(
662
+ `/v1/link/mobile-money/${mobileMoneyId}`
663
+ );
664
+ }
665
+ async setDefaultMobileMoneyRest(mobileMoneyId) {
666
+ return this.client.linkPost(
667
+ `/v1/link/mobile-money/${mobileMoneyId}/default`
668
+ );
669
+ }
670
+ };
671
+
672
+ // src/auth.ts
673
+ var AuthService = class {
674
+ constructor(client) {
675
+ this.client = client;
676
+ }
677
+ // --------------------------------------------------------------------------
678
+ // STATUS & USER
679
+ // --------------------------------------------------------------------------
680
+ async getStatus() {
681
+ return this.client.query("auth");
682
+ }
683
+ async getCurrentUser() {
684
+ const status = await this.getStatus();
685
+ return status.customer || null;
686
+ }
687
+ async isAuthenticated() {
688
+ const status = await this.getStatus();
689
+ return status.is_authenticated;
690
+ }
691
+ // --------------------------------------------------------------------------
692
+ // OTP AUTHENTICATION
693
+ // --------------------------------------------------------------------------
694
+ async requestOtp(contact, contactType) {
695
+ await this.client.call(AUTH_MUTATION.REQUEST_OTP, {
696
+ contact,
697
+ contact_type: contactType
698
+ });
699
+ }
700
+ async verifyOtp(code, contact) {
701
+ return this.client.call(AUTH_MUTATION.VERIFY_OTP, {
702
+ otp_code: code,
703
+ contact
704
+ });
705
+ }
706
+ // --------------------------------------------------------------------------
707
+ // SESSION MANAGEMENT
708
+ // --------------------------------------------------------------------------
709
+ async logout() {
710
+ return this.client.call("auth.logout");
711
+ }
712
+ // --------------------------------------------------------------------------
713
+ // PROFILE MANAGEMENT
714
+ // --------------------------------------------------------------------------
715
+ async updateProfile(input) {
716
+ return this.client.call("auth.update_profile", input);
717
+ }
718
+ async changePassword(input) {
719
+ return this.client.call("auth.change_password", input);
720
+ }
721
+ async resetPassword(email) {
722
+ return this.client.call("auth.reset_password", { email });
723
+ }
724
+ };
725
+
726
+ // src/business.ts
727
+ var BusinessService = class {
728
+ constructor(client) {
729
+ this.client = client;
730
+ }
731
+ // --------------------------------------------------------------------------
732
+ // BUSINESS INFO
733
+ // --------------------------------------------------------------------------
734
+ async getInfo() {
735
+ return this.client.query("business.info");
736
+ }
737
+ async getByHandle(handle) {
738
+ return this.client.query(`business.handle.${handle}`);
739
+ }
740
+ async getByDomain(domain) {
741
+ return this.client.query("business.domain", { domain });
742
+ }
743
+ async getSettings() {
744
+ return this.client.query("business.settings");
745
+ }
746
+ async getTheme() {
747
+ return this.client.query("business.theme");
748
+ }
749
+ // --------------------------------------------------------------------------
750
+ // LOCATIONS
751
+ // --------------------------------------------------------------------------
752
+ async getLocations() {
753
+ return this.client.query("business.locations");
754
+ }
755
+ async getLocation(locationId) {
756
+ return this.client.query(`business.locations.${locationId}`);
757
+ }
758
+ // --------------------------------------------------------------------------
759
+ // HOURS
760
+ // --------------------------------------------------------------------------
761
+ async getHours() {
762
+ return this.client.query("business.hours");
763
+ }
764
+ async getLocationHours(locationId) {
765
+ return this.client.query(
766
+ `business.locations.${locationId}.hours`
767
+ );
768
+ }
769
+ // --------------------------------------------------------------------------
770
+ // BOOTSTRAP (for storefront initialization)
771
+ // --------------------------------------------------------------------------
772
+ async getBootstrap() {
773
+ const [business, locations, categories] = await Promise.all([
774
+ this.getInfo(),
775
+ this.getLocations(),
776
+ this.client.query("categories#select(id,name,slug)")
777
+ ]);
778
+ const defaultLocation = locations[0];
779
+ return {
780
+ business,
781
+ location: defaultLocation,
782
+ locations,
783
+ categories,
784
+ currency: business.default_currency,
785
+ is_open: defaultLocation?.accepts_online_orders ?? false,
786
+ accepts_orders: defaultLocation?.accepts_online_orders ?? false
787
+ };
788
+ }
789
+ };
790
+
791
+ // src/inventory.ts
792
+ var InventoryService = class {
793
+ constructor(client) {
794
+ this.client = client;
795
+ }
796
+ // --------------------------------------------------------------------------
797
+ // STOCK QUERIES
798
+ // --------------------------------------------------------------------------
799
+ async getStockLevels() {
800
+ return this.client.query("inventory.stock_levels");
801
+ }
802
+ async getProductStock(productId, locationId) {
803
+ if (locationId) {
804
+ return this.client.query("inventory.product", {
805
+ product_id: productId,
806
+ location_id: locationId
807
+ });
808
+ }
809
+ return this.client.query("inventory.product", {
810
+ product_id: productId
811
+ });
812
+ }
813
+ async getVariantStock(variantId, locationId) {
814
+ return this.client.query("inventory.variant", {
815
+ variant_id: variantId,
816
+ location_id: locationId
817
+ });
818
+ }
819
+ // --------------------------------------------------------------------------
820
+ // AVAILABILITY CHECKS
821
+ // --------------------------------------------------------------------------
822
+ async checkProductAvailability(productId, quantity, locationId) {
823
+ return this.client.query("inventory.check_availability", {
824
+ product_id: productId,
825
+ quantity,
826
+ location_id: locationId
827
+ });
828
+ }
829
+ async checkVariantAvailability(variantId, quantity, locationId) {
830
+ return this.client.query("inventory.check_availability", {
831
+ variant_id: variantId,
832
+ quantity,
833
+ location_id: locationId
834
+ });
835
+ }
836
+ async checkMultipleAvailability(items, locationId) {
837
+ const results = await Promise.all(
838
+ items.map(
839
+ (item) => item.variant_id ? this.checkVariantAvailability(item.variant_id, item.quantity, locationId) : this.checkProductAvailability(item.product_id, item.quantity, locationId)
840
+ )
841
+ );
842
+ return results;
843
+ }
844
+ // --------------------------------------------------------------------------
845
+ // SUMMARY
846
+ // --------------------------------------------------------------------------
847
+ async getSummary() {
848
+ return this.client.query("inventory.summary");
849
+ }
850
+ // --------------------------------------------------------------------------
851
+ // CONVENIENCE METHODS
852
+ // --------------------------------------------------------------------------
853
+ async isInStock(productId, locationId) {
854
+ const result = await this.checkProductAvailability(productId, 1, locationId);
855
+ return result.is_available;
856
+ }
857
+ async getAvailableQuantity(productId, locationId) {
858
+ const stock = await this.getProductStock(productId, locationId);
859
+ return stock.available_quantity;
860
+ }
861
+ };
862
+
863
+ // src/scheduling.ts
864
+ var SchedulingService = class {
865
+ constructor(client) {
866
+ this.client = client;
867
+ }
868
+ // --------------------------------------------------------------------------
869
+ // SERVICES
870
+ // --------------------------------------------------------------------------
871
+ async getServices() {
872
+ return this.client.query("scheduling.services");
873
+ }
874
+ async getService(serviceId) {
875
+ return this.client.query(`scheduling.services.${serviceId}`);
876
+ }
877
+ // --------------------------------------------------------------------------
878
+ // AVAILABILITY
879
+ // --------------------------------------------------------------------------
880
+ async getAvailableSlots(input) {
881
+ return this.client.query(
882
+ "scheduling.available_slots",
883
+ input
884
+ );
885
+ }
886
+ async checkSlotAvailability(input) {
887
+ return this.client.query(
888
+ "scheduling.check_slot",
889
+ input
890
+ );
891
+ }
892
+ async getServiceAvailability(params) {
893
+ return this.client.query(
894
+ "scheduling.service_availability",
895
+ params
896
+ );
897
+ }
898
+ // --------------------------------------------------------------------------
899
+ // BOOKINGS
900
+ // --------------------------------------------------------------------------
901
+ async getBooking(bookingId) {
902
+ return this.client.query(`scheduling.bookings.${bookingId}`);
903
+ }
904
+ async getCustomerBookings() {
905
+ return this.client.query("scheduling.customer_bookings");
906
+ }
907
+ async getUpcomingBookings() {
908
+ return this.client.query(
909
+ "scheduling.customer_bookings[?(@.status!='completed' && @.status!='cancelled')]#sort(start_time,asc)"
910
+ );
911
+ }
912
+ async getPastBookings(limit = 10) {
913
+ return this.client.query(
914
+ `scheduling.customer_bookings[?(@.status=='completed')]#sort(start_time,desc)#limit(${limit})`
915
+ );
916
+ }
917
+ // --------------------------------------------------------------------------
918
+ // BOOKING MANAGEMENT
919
+ // --------------------------------------------------------------------------
920
+ async cancelBooking(input) {
921
+ return this.client.call("scheduling.cancel_booking", input);
922
+ }
923
+ async rescheduleBooking(input) {
924
+ return this.client.call("scheduling.reschedule_booking", input);
925
+ }
926
+ // --------------------------------------------------------------------------
927
+ // CONVENIENCE METHODS
928
+ // --------------------------------------------------------------------------
929
+ async getNextAvailableSlot(serviceId, fromDate) {
930
+ const date = fromDate || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
931
+ const slots = await this.getAvailableSlots({
932
+ service_id: serviceId,
933
+ date
934
+ });
935
+ return slots.find((slot) => slot.is_available) || null;
936
+ }
937
+ async hasAvailabilityOn(serviceId, date) {
938
+ const slots = await this.getAvailableSlots({
939
+ service_id: serviceId,
940
+ date
941
+ });
942
+ return slots.some((slot) => slot.is_available);
943
+ }
944
+ };
945
+
946
+ // src/lite.ts
947
+ var LiteService = class {
948
+ constructor(client) {
949
+ this.client = client;
950
+ }
951
+ // --------------------------------------------------------------------------
952
+ // BOOTSTRAP
953
+ // --------------------------------------------------------------------------
954
+ async getBootstrap() {
955
+ return this.client.query("lite.bootstrap");
956
+ }
957
+ // --------------------------------------------------------------------------
958
+ // TABLE MANAGEMENT
959
+ // --------------------------------------------------------------------------
960
+ async getTable(tableId) {
961
+ return this.client.query(`lite.table.${tableId}`);
962
+ }
963
+ async getTableByNumber(tableNumber, locationId) {
964
+ return this.client.query("lite.table_by_number", {
965
+ table_number: tableNumber,
966
+ location_id: locationId
967
+ });
968
+ }
969
+ // --------------------------------------------------------------------------
970
+ // KITCHEN ORDERS
971
+ // --------------------------------------------------------------------------
972
+ async sendToKitchen(tableId, items) {
973
+ return this.client.call("lite.send_to_kitchen", {
974
+ table_id: tableId,
975
+ items
976
+ });
977
+ }
978
+ async callWaiter(tableId, reason) {
979
+ return this.client.call("lite.call_waiter", {
980
+ table_id: tableId,
981
+ reason
982
+ });
983
+ }
984
+ async requestBill(tableId) {
985
+ return this.client.call(
986
+ "lite.request_bill",
987
+ { table_id: tableId }
988
+ );
989
+ }
990
+ // --------------------------------------------------------------------------
991
+ // MENU (optimized for lite/QR experience)
992
+ // --------------------------------------------------------------------------
993
+ async getMenu() {
994
+ return this.client.query("lite.menu");
995
+ }
996
+ async getMenuByCategory(categoryId) {
997
+ return this.client.query(`lite.menu.category.${categoryId}`);
998
+ }
999
+ };
1000
+
1001
+ // src/client.ts
1002
+ var SESSION_TOKEN_HEADER = "x-session-token";
1003
+ var SESSION_STORAGE_KEY = "cimplify_session_token";
1004
+ function deriveUrls() {
1005
+ const hostname = typeof window !== "undefined" ? window.location.hostname : "";
1006
+ if (hostname === "localhost" || hostname === "127.0.0.1") {
1007
+ const protocol = window.location.protocol;
1008
+ return {
1009
+ baseUrl: `${protocol}//${hostname}:8082`,
1010
+ linkApiUrl: `${protocol}//${hostname}:8080`
1011
+ };
1012
+ }
1013
+ return {
1014
+ baseUrl: "https://storefronts.cimplify.io",
1015
+ linkApiUrl: "https://api.cimplify.io"
1016
+ };
1017
+ }
1018
+ var CimplifyClient = class {
1019
+ constructor(config = {}) {
1020
+ this.sessionToken = null;
1021
+ this.publicKey = config.publicKey || "";
1022
+ const urls = deriveUrls();
1023
+ this.baseUrl = urls.baseUrl;
1024
+ this.linkApiUrl = urls.linkApiUrl;
1025
+ this.credentials = config.credentials || "include";
1026
+ this.sessionToken = this.loadSessionToken();
1027
+ }
1028
+ getSessionToken() {
1029
+ return this.sessionToken;
1030
+ }
1031
+ setSessionToken(token) {
1032
+ this.sessionToken = token;
1033
+ this.saveSessionToken(token);
1034
+ }
1035
+ clearSession() {
1036
+ this.sessionToken = null;
1037
+ this.saveSessionToken(null);
1038
+ }
1039
+ loadSessionToken() {
1040
+ if (typeof window !== "undefined" && window.localStorage) {
1041
+ return localStorage.getItem(SESSION_STORAGE_KEY);
1042
+ }
1043
+ return null;
1044
+ }
1045
+ saveSessionToken(token) {
1046
+ if (typeof window !== "undefined" && window.localStorage) {
1047
+ if (token) {
1048
+ localStorage.setItem(SESSION_STORAGE_KEY, token);
1049
+ } else {
1050
+ localStorage.removeItem(SESSION_STORAGE_KEY);
1051
+ }
1052
+ }
1053
+ }
1054
+ getHeaders() {
1055
+ const headers = {
1056
+ "Content-Type": "application/json",
1057
+ "X-API-Key": this.publicKey
1058
+ };
1059
+ if (this.sessionToken) {
1060
+ headers[SESSION_TOKEN_HEADER] = this.sessionToken;
1061
+ }
1062
+ return headers;
1063
+ }
1064
+ updateSessionFromResponse(response) {
1065
+ const newToken = response.headers.get(SESSION_TOKEN_HEADER);
1066
+ if (newToken && newToken !== this.sessionToken) {
1067
+ this.sessionToken = newToken;
1068
+ this.saveSessionToken(newToken);
1069
+ }
1070
+ }
1071
+ async query(query2, variables) {
1072
+ const body = { query: query2 };
1073
+ if (variables) {
1074
+ body.variables = variables;
1075
+ }
1076
+ const response = await fetch(`${this.baseUrl}/api/q`, {
1077
+ method: "POST",
1078
+ credentials: this.credentials,
1079
+ headers: this.getHeaders(),
1080
+ body: JSON.stringify(body)
1081
+ });
1082
+ this.updateSessionFromResponse(response);
1083
+ return this.handleResponse(response);
1084
+ }
1085
+ async call(method, args) {
1086
+ const body = {
1087
+ method,
1088
+ args: args !== void 0 ? [args] : []
1089
+ };
1090
+ const response = await fetch(`${this.baseUrl}/api/m`, {
1091
+ method: "POST",
1092
+ credentials: this.credentials,
1093
+ headers: this.getHeaders(),
1094
+ body: JSON.stringify(body)
1095
+ });
1096
+ this.updateSessionFromResponse(response);
1097
+ return this.handleResponse(response);
1098
+ }
1099
+ async get(path) {
1100
+ const response = await fetch(`${this.baseUrl}${path}`, {
1101
+ method: "GET",
1102
+ credentials: this.credentials,
1103
+ headers: this.getHeaders()
1104
+ });
1105
+ this.updateSessionFromResponse(response);
1106
+ return this.handleRestResponse(response);
1107
+ }
1108
+ async post(path, body) {
1109
+ const response = await fetch(`${this.baseUrl}${path}`, {
1110
+ method: "POST",
1111
+ credentials: this.credentials,
1112
+ headers: this.getHeaders(),
1113
+ body: body ? JSON.stringify(body) : void 0
1114
+ });
1115
+ this.updateSessionFromResponse(response);
1116
+ return this.handleRestResponse(response);
1117
+ }
1118
+ async delete(path) {
1119
+ const response = await fetch(`${this.baseUrl}${path}`, {
1120
+ method: "DELETE",
1121
+ credentials: this.credentials,
1122
+ headers: this.getHeaders()
1123
+ });
1124
+ this.updateSessionFromResponse(response);
1125
+ return this.handleRestResponse(response);
1126
+ }
1127
+ async linkGet(path) {
1128
+ const response = await fetch(`${this.linkApiUrl}${path}`, {
1129
+ method: "GET",
1130
+ credentials: this.credentials,
1131
+ headers: this.getHeaders()
1132
+ });
1133
+ this.updateSessionFromResponse(response);
1134
+ return this.handleRestResponse(response);
1135
+ }
1136
+ async linkPost(path, body) {
1137
+ const response = await fetch(`${this.linkApiUrl}${path}`, {
1138
+ method: "POST",
1139
+ credentials: this.credentials,
1140
+ headers: this.getHeaders(),
1141
+ body: body ? JSON.stringify(body) : void 0
1142
+ });
1143
+ this.updateSessionFromResponse(response);
1144
+ return this.handleRestResponse(response);
1145
+ }
1146
+ async linkDelete(path) {
1147
+ const response = await fetch(`${this.linkApiUrl}${path}`, {
1148
+ method: "DELETE",
1149
+ credentials: this.credentials,
1150
+ headers: this.getHeaders()
1151
+ });
1152
+ this.updateSessionFromResponse(response);
1153
+ return this.handleRestResponse(response);
1154
+ }
1155
+ async handleRestResponse(response) {
1156
+ const json = await response.json();
1157
+ if (!response.ok) {
1158
+ throw new CimplifyError(
1159
+ json.error?.error_code || "API_ERROR",
1160
+ json.error?.error_message || "An error occurred",
1161
+ false
1162
+ );
1163
+ }
1164
+ return json.data;
1165
+ }
1166
+ async handleResponse(response) {
1167
+ const json = await response.json();
1168
+ if (!json.success || json.error) {
1169
+ throw new CimplifyError(
1170
+ json.error?.code || "UNKNOWN_ERROR",
1171
+ json.error?.message || "An unknown error occurred",
1172
+ json.error?.retryable || false
1173
+ );
1174
+ }
1175
+ return json.data;
1176
+ }
1177
+ get catalogue() {
1178
+ if (!this._catalogue) {
1179
+ this._catalogue = new CatalogueQueries(this);
1180
+ }
1181
+ return this._catalogue;
1182
+ }
1183
+ get cart() {
1184
+ if (!this._cart) {
1185
+ this._cart = new CartOperations(this);
1186
+ }
1187
+ return this._cart;
1188
+ }
1189
+ get checkout() {
1190
+ if (!this._checkout) {
1191
+ this._checkout = new CheckoutService(this);
1192
+ }
1193
+ return this._checkout;
1194
+ }
1195
+ get orders() {
1196
+ if (!this._orders) {
1197
+ this._orders = new OrderQueries(this);
1198
+ }
1199
+ return this._orders;
1200
+ }
1201
+ get link() {
1202
+ if (!this._link) {
1203
+ this._link = new LinkService(this);
1204
+ }
1205
+ return this._link;
1206
+ }
1207
+ get auth() {
1208
+ if (!this._auth) {
1209
+ this._auth = new AuthService(this);
1210
+ }
1211
+ return this._auth;
1212
+ }
1213
+ get business() {
1214
+ if (!this._business) {
1215
+ this._business = new BusinessService(this);
1216
+ }
1217
+ return this._business;
1218
+ }
1219
+ get inventory() {
1220
+ if (!this._inventory) {
1221
+ this._inventory = new InventoryService(this);
1222
+ }
1223
+ return this._inventory;
1224
+ }
1225
+ get scheduling() {
1226
+ if (!this._scheduling) {
1227
+ this._scheduling = new SchedulingService(this);
1228
+ }
1229
+ return this._scheduling;
1230
+ }
1231
+ get lite() {
1232
+ if (!this._lite) {
1233
+ this._lite = new LiteService(this);
1234
+ }
1235
+ return this._lite;
1236
+ }
1237
+ };
1238
+ function createCimplifyClient(config) {
1239
+ return new CimplifyClient(config);
1240
+ }
1241
+
1242
+ // src/query/builder.ts
1243
+ var QueryBuilder = class {
1244
+ constructor(entity) {
1245
+ this.filters = [];
1246
+ this.modifiers = [];
1247
+ this.pathSegments = [];
1248
+ this.entity = entity;
1249
+ }
1250
+ path(segment) {
1251
+ this.pathSegments.push(segment);
1252
+ return this;
1253
+ }
1254
+ where(field, op, value) {
1255
+ const v = typeof value === "string" ? `'${value}'` : value;
1256
+ if (op === "contains" || op === "startsWith") {
1257
+ this.filters.push(`@.${field} ${op} ${v}`);
1258
+ } else {
1259
+ this.filters.push(`@.${field}${op}${v}`);
1260
+ }
1261
+ return this;
1262
+ }
1263
+ and(field, op, value) {
1264
+ return this.where(field, op, value);
1265
+ }
1266
+ sort(field, order = "asc") {
1267
+ this.modifiers.push(`sort(${field},${order})`);
1268
+ return this;
1269
+ }
1270
+ limit(n) {
1271
+ this.modifiers.push(`limit(${n})`);
1272
+ return this;
1273
+ }
1274
+ offset(n) {
1275
+ this.modifiers.push(`offset(${n})`);
1276
+ return this;
1277
+ }
1278
+ count() {
1279
+ this.modifiers.push("count");
1280
+ return this;
1281
+ }
1282
+ enriched() {
1283
+ this.modifiers.push("enriched");
1284
+ return this;
1285
+ }
1286
+ build() {
1287
+ let query2 = this.entity;
1288
+ if (this.pathSegments.length > 0) {
1289
+ query2 += "." + this.pathSegments.join(".");
1290
+ }
1291
+ if (this.filters.length > 0) {
1292
+ query2 += `[?(${this.filters.join(" && ")})]`;
1293
+ }
1294
+ for (const mod of this.modifiers) {
1295
+ query2 += `#${mod}`;
1296
+ }
1297
+ return query2;
1298
+ }
1299
+ toString() {
1300
+ return this.build();
1301
+ }
1302
+ };
1303
+ function query(entity) {
1304
+ return new QueryBuilder(entity);
1305
+ }
1306
+
1307
+ // src/utils/payment.ts
1308
+ var CURRENCY_SYMBOLS = {
1309
+ GHS: "GH\u20B5",
1310
+ USD: "$",
1311
+ EUR: "\u20AC",
1312
+ GBP: "\xA3",
1313
+ NGN: "\u20A6",
1314
+ KES: "KSh",
1315
+ ZAR: "R",
1316
+ XOF: "CFA",
1317
+ XAF: "FCFA"
1318
+ };
1319
+ function formatMoney(amount, currency = "GHS") {
1320
+ const symbol = CURRENCY_SYMBOLS[currency.toUpperCase()] || currency;
1321
+ const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
1322
+ return `${symbol}${numAmount.toFixed(2)}`;
1323
+ }
1324
+ function categorizePaymentError(error, errorCode) {
1325
+ let message = "An unexpected error occurred during payment processing. Please try again or contact support.";
1326
+ let recoverable = true;
1327
+ let code = errorCode || "PAYMENT_ERROR";
1328
+ const technical = error.stack;
1329
+ const errorMessage = error.message?.toLowerCase() || "";
1330
+ if (errorCode === "INSUFFICIENT_FUNDS" || errorMessage.includes("insufficient") || errorMessage.includes("funds")) {
1331
+ code = "INSUFFICIENT_FUNDS";
1332
+ message = "Your payment method has insufficient funds. Please try another payment method.";
1333
+ } else if (errorCode === "CARD_DECLINED" || errorMessage.includes("declined")) {
1334
+ code = "CARD_DECLINED";
1335
+ message = "Your card was declined. Please try another card or payment method.";
1336
+ } else if (errorMessage.includes("cancelled") || errorMessage.includes("canceled") || errorCode === "PAYMENT_CANCELLED") {
1337
+ code = "PAYMENT_CANCELLED";
1338
+ message = "Payment was cancelled. You can try again when ready.";
1339
+ } else if (errorMessage.includes("network") || errorMessage.includes("connection") || errorCode === "NETWORK_ERROR") {
1340
+ code = "NETWORK_ERROR";
1341
+ message = "Network connection issue. Please check your internet connection and try again.";
1342
+ } else if (errorMessage.includes("timeout") || errorCode === "TIMEOUT") {
1343
+ code = "TIMEOUT";
1344
+ message = "Payment processing timed out. Please try again.";
1345
+ } else if (errorCode === "PAYMENT_ACTION_NOT_COMPLETED") {
1346
+ code = "PAYMENT_ACTION_NOT_COMPLETED";
1347
+ message = "Payment action was not completed. Please try again.";
1348
+ } else if (errorCode === "AUTHORIZATION_FAILED") {
1349
+ code = "AUTHORIZATION_FAILED";
1350
+ message = "Authorization failed. Please check your code and try again.";
1351
+ } else if (errorCode === "INVALID_OTP") {
1352
+ code = "INVALID_OTP";
1353
+ message = "Invalid verification code. Please check and try again.";
1354
+ }
1355
+ return { code, message, recoverable, technical };
1356
+ }
1357
+ function isQuickPaymentResponse(response) {
1358
+ return response !== null && typeof response === "object" && "payment" in response && typeof response.payment === "object";
1359
+ }
1360
+ function isWebPaymentResponse(response) {
1361
+ return response !== null && typeof response === "object" && "transaction" in response && typeof response.transaction === "object";
1362
+ }
1363
+ function normalizePaymentResponse(response) {
1364
+ if (!response) {
1365
+ return {
1366
+ method: "unknown",
1367
+ provider: "unknown",
1368
+ requires_action: false,
1369
+ metadata: {}
1370
+ };
1371
+ }
1372
+ if (isQuickPaymentResponse(response)) {
1373
+ return {
1374
+ method: response.payment.type?.toLowerCase() || "unknown",
1375
+ provider: response.payment.provider?.toLowerCase() || "unknown",
1376
+ requires_action: !!response.payment.redirect_url || !!response.payment.access_code,
1377
+ public_key: response.payment.public_key,
1378
+ client_secret: response.payment.access_code,
1379
+ access_code: response.payment.access_code,
1380
+ redirect_url: response.payment.redirect_url,
1381
+ transaction_id: response.payment.reference,
1382
+ order_id: response.order_id,
1383
+ reference: response.payment.reference,
1384
+ instructions: response.payment.instructions,
1385
+ metadata: response.payment.metadata
1386
+ };
1387
+ }
1388
+ if (isWebPaymentResponse(response)) {
1389
+ const authType = response.authorization_type?.toLowerCase();
1390
+ const validAuthTypes = ["otp", "pin", "phone", "birthday", "address"];
1391
+ const safeAuthType = authType && validAuthTypes.includes(authType) ? authType : void 0;
1392
+ return {
1393
+ provider: response.transaction.provider_type?.toLowerCase() || "unknown",
1394
+ requires_action: response.requires_action || false,
1395
+ public_key: response.public_key,
1396
+ client_secret: response.client_secret,
1397
+ redirect_url: response.authorization_url,
1398
+ transaction_id: response.transaction.id,
1399
+ order_id: response.transaction.order_id,
1400
+ reference: response.transaction.provider_reference,
1401
+ metadata: response.transaction.metadata,
1402
+ method: response.transaction.payment_method?.toLowerCase() || "unknown",
1403
+ instructions: response.display_text,
1404
+ display_text: response.display_text,
1405
+ requires_authorization: response.requires_authorization,
1406
+ authorization_type: safeAuthType,
1407
+ provider_payment_id: response.provider_payment_id || response.transaction.provider_reference
1408
+ };
1409
+ }
1410
+ return {
1411
+ method: "unknown",
1412
+ provider: "unknown",
1413
+ requires_action: false,
1414
+ metadata: {}
1415
+ };
1416
+ }
1417
+ function normalizeStatusResponse(response) {
1418
+ if (!response || typeof response !== "object") {
1419
+ return {
1420
+ status: "pending",
1421
+ paid: false,
1422
+ message: "No status available"
1423
+ };
1424
+ }
1425
+ const res = response;
1426
+ const status = res.status?.toLowerCase() || "";
1427
+ let standardStatus;
1428
+ if (status === "success" || status === "completed" || res.paid === true) {
1429
+ standardStatus = "success";
1430
+ } else if (status === "failed" || status === "declined" || status === "cancelled") {
1431
+ standardStatus = "failed";
1432
+ } else if (status === "processing" || status === "pending_confirmation") {
1433
+ standardStatus = "processing";
1434
+ } else {
1435
+ standardStatus = "pending";
1436
+ }
1437
+ return {
1438
+ status: standardStatus,
1439
+ paid: res.paid || standardStatus === "success",
1440
+ amount: res.amount,
1441
+ currency: res.currency,
1442
+ reference: res.reference,
1443
+ message: res.message || ""
1444
+ };
1445
+ }
1446
+ var MOBILE_MONEY_PROVIDERS = {
1447
+ mtn: { name: "MTN Mobile Money", prefix: ["024", "054", "055", "059"] },
1448
+ vodafone: { name: "Vodafone Cash", prefix: ["020", "050"] },
1449
+ airtel: { name: "AirtelTigo Money", prefix: ["027", "057", "026", "056"] }
1450
+ };
1451
+ function detectMobileMoneyProvider(phoneNumber) {
1452
+ const cleaned = phoneNumber.replace(/\D/g, "");
1453
+ const prefix = cleaned.slice(-9, -6);
1454
+ for (const [provider, info] of Object.entries(MOBILE_MONEY_PROVIDERS)) {
1455
+ if (info.prefix.some((p) => prefix.startsWith(p.slice(1)))) {
1456
+ return provider;
1457
+ }
1458
+ }
1459
+ return null;
1460
+ }
1461
+
1462
+ exports.AUTHORIZATION_TYPE = AUTHORIZATION_TYPE;
1463
+ exports.AUTH_MUTATION = AUTH_MUTATION;
1464
+ exports.AuthService = AuthService;
1465
+ exports.BusinessService = BusinessService;
1466
+ exports.CHECKOUT_MODE = CHECKOUT_MODE;
1467
+ exports.CHECKOUT_MUTATION = CHECKOUT_MUTATION;
1468
+ exports.CHECKOUT_STEP = CHECKOUT_STEP;
1469
+ exports.CURRENCY_SYMBOLS = CURRENCY_SYMBOLS;
1470
+ exports.CartOperations = CartOperations;
1471
+ exports.CatalogueQueries = CatalogueQueries;
1472
+ exports.CheckoutOperations = CheckoutService;
1473
+ exports.CheckoutService = CheckoutService;
1474
+ exports.CimplifyClient = CimplifyClient;
1475
+ exports.CimplifyError = CimplifyError;
1476
+ exports.DEFAULT_COUNTRY = DEFAULT_COUNTRY;
1477
+ exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
1478
+ exports.InventoryService = InventoryService;
1479
+ exports.LINK_MUTATION = LINK_MUTATION;
1480
+ exports.LINK_QUERY = LINK_QUERY;
1481
+ exports.LinkService = LinkService;
1482
+ exports.LiteService = LiteService;
1483
+ exports.MOBILE_MONEY_PROVIDER = MOBILE_MONEY_PROVIDER;
1484
+ exports.MOBILE_MONEY_PROVIDERS = MOBILE_MONEY_PROVIDERS;
1485
+ exports.ORDER_MUTATION = ORDER_MUTATION;
1486
+ exports.ORDER_TYPE = ORDER_TYPE;
1487
+ exports.OrderQueries = OrderQueries;
1488
+ exports.PAYMENT_METHOD = PAYMENT_METHOD;
1489
+ exports.PAYMENT_MUTATION = PAYMENT_MUTATION;
1490
+ exports.PAYMENT_STATE = PAYMENT_STATE;
1491
+ exports.PICKUP_TIME_TYPE = PICKUP_TIME_TYPE;
1492
+ exports.QueryBuilder = QueryBuilder;
1493
+ exports.SchedulingService = SchedulingService;
1494
+ exports.categorizePaymentError = categorizePaymentError;
1495
+ exports.createCimplifyClient = createCimplifyClient;
1496
+ exports.detectMobileMoneyProvider = detectMobileMoneyProvider;
1497
+ exports.formatMoney = formatMoney;
1498
+ exports.normalizePaymentResponse = normalizePaymentResponse;
1499
+ exports.normalizeStatusResponse = normalizeStatusResponse;
1500
+ exports.query = query;