@cimplify/sdk 0.6.6 → 0.6.8
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/README.md +19 -0
- package/dist/advanced.d.mts +2 -2
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.js +228 -101
- package/dist/advanced.mjs +228 -101
- package/dist/{client-CUFdFugo.d.mts → client-D4vA6FY_.d.ts} +40 -34
- package/dist/{client-CjqNbEM6.d.ts → client-FQUyv41r.d.mts} +40 -34
- package/dist/{index-CJ9GkIXf.d.mts → index-DaKJxoEh.d.mts} +13 -12
- package/dist/{index-B5Bj-Ikg.d.ts → index-pztT_bcJ.d.ts} +13 -12
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +315 -131
- package/dist/index.mjs +309 -132
- package/dist/{payment-D-u3asA8.d.mts → payment-Cu75tmUc.d.mts} +34 -8
- package/dist/{payment-D-u3asA8.d.ts → payment-Cu75tmUc.d.ts} +34 -8
- package/dist/react.d.mts +225 -4
- package/dist/react.d.ts +225 -4
- package/dist/react.js +2097 -63
- package/dist/react.mjs +2086 -65
- package/dist/utils.d.mts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +76 -4
- package/dist/utils.mjs +76 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/types/common.ts
|
|
4
|
+
function money(value) {
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
function moneyFromNumber(value) {
|
|
8
|
+
return value.toFixed(2);
|
|
9
|
+
}
|
|
10
|
+
var ZERO = "0.00";
|
|
11
|
+
function currencyCode(value) {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
4
14
|
var ErrorCode = {
|
|
5
15
|
// General
|
|
6
16
|
UNKNOWN_ERROR: "UNKNOWN_ERROR",
|
|
@@ -40,11 +50,72 @@ var ErrorCode = {
|
|
|
40
50
|
OUT_OF_STOCK: "OUT_OF_STOCK",
|
|
41
51
|
INSUFFICIENT_QUANTITY: "INSUFFICIENT_QUANTITY"
|
|
42
52
|
};
|
|
53
|
+
var DOCS_ERROR_BASE_URL = "https://docs.cimplify.io/reference/error-codes";
|
|
54
|
+
function docsUrlForCode(code) {
|
|
55
|
+
return `${DOCS_ERROR_BASE_URL}#${code.toLowerCase().replace(/_/g, "-")}`;
|
|
56
|
+
}
|
|
57
|
+
var ERROR_SUGGESTIONS = {
|
|
58
|
+
UNKNOWN_ERROR: "An unexpected error occurred. Capture the request/response payload and retry with exponential backoff.",
|
|
59
|
+
NETWORK_ERROR: "Check the shopper's connection and retry. If this persists, inspect CORS, DNS, and API reachability.",
|
|
60
|
+
TIMEOUT: "The request exceeded the timeout. Retry once, then poll order status before charging again.",
|
|
61
|
+
UNAUTHORIZED: "Authentication is missing or expired. Ensure a valid access token is set and refresh the session if needed.",
|
|
62
|
+
FORBIDDEN: "The key/session lacks permission for this resource. Verify business ownership and API key scope.",
|
|
63
|
+
NOT_FOUND: "The requested resource does not exist or is not visible in this environment.",
|
|
64
|
+
VALIDATION_ERROR: "One or more fields are invalid. Validate required fields and enum values before retrying.",
|
|
65
|
+
CART_EMPTY: "The cart has no items. Redirect back to menu/catalogue and require at least one line item.",
|
|
66
|
+
CART_EXPIRED: "This cart is no longer active. Recreate a new cart and re-add shopper selections.",
|
|
67
|
+
CART_NOT_FOUND: "Cart could not be located. It may have expired or belongs to a different key/location.",
|
|
68
|
+
ITEM_UNAVAILABLE: "The selected item is unavailable at this location/time. Prompt the shopper to pick an alternative.",
|
|
69
|
+
VARIANT_NOT_FOUND: "The requested variant no longer exists. Refresh product data and require re-selection.",
|
|
70
|
+
VARIANT_OUT_OF_STOCK: "The selected variant is out of stock. Show in-stock variants and block checkout for this line.",
|
|
71
|
+
ADDON_REQUIRED: "A required add-on is missing. Ensure required modifier groups are completed before add-to-cart.",
|
|
72
|
+
ADDON_MAX_EXCEEDED: "Too many add-ons were selected. Enforce max selections client-side before submission.",
|
|
73
|
+
CHECKOUT_VALIDATION_FAILED: "Checkout payload failed validation. Verify customer, order type, and address fields are complete.",
|
|
74
|
+
DELIVERY_ADDRESS_REQUIRED: "Delivery orders require an address. Collect and pass address info before processing checkout.",
|
|
75
|
+
CUSTOMER_INFO_REQUIRED: "Customer details are required. Ensure name/email/phone are available before checkout.",
|
|
76
|
+
PAYMENT_FAILED: "Payment provider rejected or failed processing. Show retry/change-method options to the shopper.",
|
|
77
|
+
PAYMENT_CANCELLED: "Payment was cancelled by the shopper or provider flow. Allow a safe retry path.",
|
|
78
|
+
INSUFFICIENT_FUNDS: "Payment method has insufficient funds. Prompt shopper to use another method.",
|
|
79
|
+
CARD_DECLINED: "Card was declined. Ask shopper to retry or switch payment method.",
|
|
80
|
+
INVALID_OTP: "Authorization code is invalid. Let shopper re-enter OTP/PIN and retry.",
|
|
81
|
+
OTP_EXPIRED: "Authorization code expired. Request a new OTP and re-submit authorization.",
|
|
82
|
+
AUTHORIZATION_FAILED: "Additional payment authorization failed. Retry authorization or change payment method.",
|
|
83
|
+
PAYMENT_ACTION_NOT_COMPLETED: "Required payment action was not completed. Resume provider flow and poll for status.",
|
|
84
|
+
SLOT_UNAVAILABLE: "Selected schedule slot is unavailable. Refresh available slots and ask shopper to reselect.",
|
|
85
|
+
BOOKING_CONFLICT: "The requested booking conflicts with an existing reservation. Pick another slot/resource.",
|
|
86
|
+
SERVICE_NOT_FOUND: "Requested service no longer exists. Refresh service catalogue and retry selection.",
|
|
87
|
+
OUT_OF_STOCK: "Inventory is depleted for this item. Remove it or reduce quantity before checkout.",
|
|
88
|
+
INSUFFICIENT_QUANTITY: "Requested quantity exceeds available inventory. Reduce quantity and retry.",
|
|
89
|
+
BUSINESS_ID_REQUIRED: "Business context could not be resolved. Verify the public key and business bootstrap call.",
|
|
90
|
+
INVALID_CART: "Cart is invalid for checkout. Sync cart state, ensure items exist, then retry.",
|
|
91
|
+
ORDER_TYPE_REQUIRED: "Order type is required. Provide one of delivery, pickup, or dine_in before checkout.",
|
|
92
|
+
NO_PAYMENT_ELEMENT: "PaymentElement is required for processCheckout(). Mount it before triggering checkout.",
|
|
93
|
+
PAYMENT_NOT_MOUNTED: "PaymentElement iframe is not mounted. Mount it in the DOM before processCheckout().",
|
|
94
|
+
AUTH_INCOMPLETE: "AuthElement has not completed authentication. Wait for AUTHENTICATED before checkout.",
|
|
95
|
+
AUTH_LOST: "Session was cleared during checkout. Re-authenticate and restart checkout safely.",
|
|
96
|
+
ALREADY_PROCESSING: "Checkout is already in progress. Disable duplicate submits until completion.",
|
|
97
|
+
CHECKOUT_NOT_READY: "Checkout elements are still initializing. Wait for readiness before submit.",
|
|
98
|
+
CANCELLED: "Checkout was cancelled. Preserve cart state and allow shopper to retry.",
|
|
99
|
+
REQUEST_TIMEOUT: "Provider call timed out. Poll payment/order status before issuing another charge attempt.",
|
|
100
|
+
POPUP_BLOCKED: "Browser blocked provider popup. Ask shopper to enable popups and retry.",
|
|
101
|
+
FX_QUOTE_FAILED: "Failed to lock FX quote. Retry currency quote or fallback to base currency."
|
|
102
|
+
};
|
|
103
|
+
var ERROR_HINTS = Object.fromEntries(
|
|
104
|
+
Object.entries(ERROR_SUGGESTIONS).map(([code, suggestion]) => [
|
|
105
|
+
code,
|
|
106
|
+
{
|
|
107
|
+
docs_url: docsUrlForCode(code),
|
|
108
|
+
suggestion
|
|
109
|
+
}
|
|
110
|
+
])
|
|
111
|
+
);
|
|
43
112
|
var CimplifyError = class extends Error {
|
|
44
|
-
constructor(code, message, retryable = false) {
|
|
113
|
+
constructor(code, message, retryable = false, docs_url, suggestion) {
|
|
45
114
|
super(message);
|
|
46
115
|
this.code = code;
|
|
47
116
|
this.retryable = retryable;
|
|
117
|
+
this.docs_url = docs_url;
|
|
118
|
+
this.suggestion = suggestion;
|
|
48
119
|
this.name = "CimplifyError";
|
|
49
120
|
}
|
|
50
121
|
/** User-friendly message safe to display */
|
|
@@ -55,6 +126,28 @@ var CimplifyError = class extends Error {
|
|
|
55
126
|
function isCimplifyError(error) {
|
|
56
127
|
return error instanceof CimplifyError;
|
|
57
128
|
}
|
|
129
|
+
function getErrorHint(code) {
|
|
130
|
+
return ERROR_HINTS[code];
|
|
131
|
+
}
|
|
132
|
+
function enrichError(error, options = {}) {
|
|
133
|
+
const hint = getErrorHint(error.code);
|
|
134
|
+
if (hint) {
|
|
135
|
+
if (!error.docs_url) {
|
|
136
|
+
error.docs_url = hint.docs_url;
|
|
137
|
+
}
|
|
138
|
+
if (!error.suggestion) {
|
|
139
|
+
error.suggestion = hint.suggestion;
|
|
140
|
+
}
|
|
141
|
+
} else if (!error.docs_url) {
|
|
142
|
+
error.docs_url = docsUrlForCode(error.code || ErrorCode.UNKNOWN_ERROR);
|
|
143
|
+
}
|
|
144
|
+
if (options.isTestMode && !error.message.includes("pk_test_")) {
|
|
145
|
+
error.message = `${error.message}
|
|
146
|
+
|
|
147
|
+
\u2139 Your API key is a test-mode key (pk_test_...). Verify test data/session before retrying.`;
|
|
148
|
+
}
|
|
149
|
+
return error;
|
|
150
|
+
}
|
|
58
151
|
function isRetryableError(error) {
|
|
59
152
|
if (isCimplifyError(error)) {
|
|
60
153
|
return error.retryable;
|
|
@@ -136,13 +229,81 @@ function combineObject(results) {
|
|
|
136
229
|
return ok(values);
|
|
137
230
|
}
|
|
138
231
|
|
|
232
|
+
// src/query/builder.ts
|
|
233
|
+
function escapeQueryValue(value) {
|
|
234
|
+
return value.replace(/'/g, "\\'");
|
|
235
|
+
}
|
|
236
|
+
var QueryBuilder = class {
|
|
237
|
+
constructor(entity) {
|
|
238
|
+
this.filters = [];
|
|
239
|
+
this.modifiers = [];
|
|
240
|
+
this.pathSegments = [];
|
|
241
|
+
this.entity = entity;
|
|
242
|
+
}
|
|
243
|
+
path(segment) {
|
|
244
|
+
this.pathSegments.push(segment);
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
where(field, op, value) {
|
|
248
|
+
const v = typeof value === "string" ? `'${escapeQueryValue(value)}'` : value;
|
|
249
|
+
if (op === "contains" || op === "startsWith") {
|
|
250
|
+
this.filters.push(`@.${field} ${op} ${v}`);
|
|
251
|
+
} else {
|
|
252
|
+
this.filters.push(`@.${field}${op}${v}`);
|
|
253
|
+
}
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
and(field, op, value) {
|
|
257
|
+
return this.where(field, op, value);
|
|
258
|
+
}
|
|
259
|
+
sort(field, order = "asc") {
|
|
260
|
+
this.modifiers.push(`sort(${field},${order})`);
|
|
261
|
+
return this;
|
|
262
|
+
}
|
|
263
|
+
limit(n) {
|
|
264
|
+
this.modifiers.push(`limit(${n})`);
|
|
265
|
+
return this;
|
|
266
|
+
}
|
|
267
|
+
offset(n) {
|
|
268
|
+
this.modifiers.push(`offset(${n})`);
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
count() {
|
|
272
|
+
this.modifiers.push("count");
|
|
273
|
+
return this;
|
|
274
|
+
}
|
|
275
|
+
enriched() {
|
|
276
|
+
this.modifiers.push("enriched");
|
|
277
|
+
return this;
|
|
278
|
+
}
|
|
279
|
+
build() {
|
|
280
|
+
let query2 = this.entity;
|
|
281
|
+
if (this.pathSegments.length > 0) {
|
|
282
|
+
query2 += "." + this.pathSegments.join(".");
|
|
283
|
+
}
|
|
284
|
+
if (this.filters.length > 0) {
|
|
285
|
+
query2 += `[?(${this.filters.join(" && ")})]`;
|
|
286
|
+
}
|
|
287
|
+
for (const mod of this.modifiers) {
|
|
288
|
+
query2 += `#${mod}`;
|
|
289
|
+
}
|
|
290
|
+
return query2;
|
|
291
|
+
}
|
|
292
|
+
toString() {
|
|
293
|
+
return this.build();
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
function query(entity) {
|
|
297
|
+
return new QueryBuilder(entity);
|
|
298
|
+
}
|
|
299
|
+
|
|
139
300
|
// src/catalogue.ts
|
|
140
301
|
function toCimplifyError(error) {
|
|
141
|
-
if (error instanceof CimplifyError) return error;
|
|
302
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
142
303
|
if (error instanceof Error) {
|
|
143
|
-
return new CimplifyError(
|
|
304
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
144
305
|
}
|
|
145
|
-
return new CimplifyError(
|
|
306
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
146
307
|
}
|
|
147
308
|
async function safe(promise) {
|
|
148
309
|
try {
|
|
@@ -216,7 +377,7 @@ var CatalogueQueries = class {
|
|
|
216
377
|
let query2 = "products";
|
|
217
378
|
const filters = [];
|
|
218
379
|
if (options?.category) {
|
|
219
|
-
filters.push(`@.category_id=='${options.category}'`);
|
|
380
|
+
filters.push(`@.category_id=='${escapeQueryValue(options.category)}'`);
|
|
220
381
|
}
|
|
221
382
|
if (options?.featured !== void 0) {
|
|
222
383
|
filters.push(`@.featured==${options.featured}`);
|
|
@@ -225,7 +386,7 @@ var CatalogueQueries = class {
|
|
|
225
386
|
filters.push(`@.in_stock==${options.in_stock}`);
|
|
226
387
|
}
|
|
227
388
|
if (options?.search) {
|
|
228
|
-
filters.push(`@.name contains '${options.search}'`);
|
|
389
|
+
filters.push(`@.name contains '${escapeQueryValue(options.search)}'`);
|
|
229
390
|
}
|
|
230
391
|
if (options?.min_price !== void 0) {
|
|
231
392
|
filters.push(`@.price>=${options.min_price}`);
|
|
@@ -256,7 +417,9 @@ var CatalogueQueries = class {
|
|
|
256
417
|
}
|
|
257
418
|
async getProductBySlug(slug) {
|
|
258
419
|
const filteredResult = await safe(
|
|
259
|
-
this.client.query(
|
|
420
|
+
this.client.query(
|
|
421
|
+
`products[?(@.slug=='${escapeQueryValue(slug)}')]`
|
|
422
|
+
)
|
|
260
423
|
);
|
|
261
424
|
if (!filteredResult.ok) return filteredResult;
|
|
262
425
|
const exactMatch = findProductBySlug(filteredResult.value, slug);
|
|
@@ -308,7 +471,7 @@ var CatalogueQueries = class {
|
|
|
308
471
|
}
|
|
309
472
|
async getCategoryBySlug(slug) {
|
|
310
473
|
const result = await safe(
|
|
311
|
-
this.client.query(`categories[?(@.slug=='${slug}')]`)
|
|
474
|
+
this.client.query(`categories[?(@.slug=='${escapeQueryValue(slug)}')]`)
|
|
312
475
|
);
|
|
313
476
|
if (!result.ok) return result;
|
|
314
477
|
if (!result.value.length) {
|
|
@@ -317,7 +480,11 @@ var CatalogueQueries = class {
|
|
|
317
480
|
return ok(result.value[0]);
|
|
318
481
|
}
|
|
319
482
|
async getCategoryProducts(categoryId) {
|
|
320
|
-
return safe(
|
|
483
|
+
return safe(
|
|
484
|
+
this.client.query(
|
|
485
|
+
`products[?(@.category_id=='${escapeQueryValue(categoryId)}')]`
|
|
486
|
+
)
|
|
487
|
+
);
|
|
321
488
|
}
|
|
322
489
|
async getCollections() {
|
|
323
490
|
return safe(this.client.query("collections"));
|
|
@@ -327,7 +494,9 @@ var CatalogueQueries = class {
|
|
|
327
494
|
}
|
|
328
495
|
async getCollectionBySlug(slug) {
|
|
329
496
|
const result = await safe(
|
|
330
|
-
this.client.query(
|
|
497
|
+
this.client.query(
|
|
498
|
+
`collections[?(@.slug=='${escapeQueryValue(slug)}')]`
|
|
499
|
+
)
|
|
331
500
|
);
|
|
332
501
|
if (!result.ok) return result;
|
|
333
502
|
if (!result.value.length) {
|
|
@@ -340,7 +509,9 @@ var CatalogueQueries = class {
|
|
|
340
509
|
}
|
|
341
510
|
async searchCollections(query2, limit = 20) {
|
|
342
511
|
return safe(
|
|
343
|
-
this.client.query(
|
|
512
|
+
this.client.query(
|
|
513
|
+
`collections[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
|
|
514
|
+
)
|
|
344
515
|
);
|
|
345
516
|
}
|
|
346
517
|
async getBundles() {
|
|
@@ -351,7 +522,9 @@ var CatalogueQueries = class {
|
|
|
351
522
|
}
|
|
352
523
|
async getBundleBySlug(slug) {
|
|
353
524
|
const result = await safe(
|
|
354
|
-
this.client.query(
|
|
525
|
+
this.client.query(
|
|
526
|
+
`bundles[?(@.slug=='${escapeQueryValue(slug)}')]`
|
|
527
|
+
)
|
|
355
528
|
);
|
|
356
529
|
if (!result.ok) return result;
|
|
357
530
|
if (!result.value.length) {
|
|
@@ -361,7 +534,9 @@ var CatalogueQueries = class {
|
|
|
361
534
|
}
|
|
362
535
|
async searchBundles(query2, limit = 20) {
|
|
363
536
|
return safe(
|
|
364
|
-
this.client.query(
|
|
537
|
+
this.client.query(
|
|
538
|
+
`bundles[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
|
|
539
|
+
)
|
|
365
540
|
);
|
|
366
541
|
}
|
|
367
542
|
async getComposites(options) {
|
|
@@ -401,9 +576,9 @@ var CatalogueQueries = class {
|
|
|
401
576
|
}
|
|
402
577
|
async search(query2, options) {
|
|
403
578
|
const limit = options?.limit ?? 20;
|
|
404
|
-
let searchQuery = `products[?(@.name contains '${query2}')]`;
|
|
579
|
+
let searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}')]`;
|
|
405
580
|
if (options?.category) {
|
|
406
|
-
searchQuery = `products[?(@.name contains '${query2}' && @.category_id=='${options.category}')]`;
|
|
581
|
+
searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}' && @.category_id=='${escapeQueryValue(options.category)}')]`;
|
|
407
582
|
}
|
|
408
583
|
searchQuery += `#limit(${limit})`;
|
|
409
584
|
return safe(this.client.query(searchQuery));
|
|
@@ -420,7 +595,7 @@ var CatalogueQueries = class {
|
|
|
420
595
|
async getMenu(options) {
|
|
421
596
|
let query2 = "menu";
|
|
422
597
|
if (options?.category) {
|
|
423
|
-
query2 = `menu[?(@.category=='${options.category}')]`;
|
|
598
|
+
query2 = `menu[?(@.category=='${escapeQueryValue(options.category)}')]`;
|
|
424
599
|
}
|
|
425
600
|
if (options?.limit) {
|
|
426
601
|
query2 += `#limit(${options.limit})`;
|
|
@@ -437,11 +612,11 @@ var CatalogueQueries = class {
|
|
|
437
612
|
|
|
438
613
|
// src/cart.ts
|
|
439
614
|
function toCimplifyError2(error) {
|
|
440
|
-
if (error instanceof CimplifyError) return error;
|
|
615
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
441
616
|
if (error instanceof Error) {
|
|
442
|
-
return new CimplifyError(
|
|
617
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
443
618
|
}
|
|
444
|
-
return new CimplifyError(
|
|
619
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
445
620
|
}
|
|
446
621
|
async function safe2(promise) {
|
|
447
622
|
try {
|
|
@@ -737,8 +912,8 @@ var CURRENCY_SYMBOLS = {
|
|
|
737
912
|
KMF: "CF",
|
|
738
913
|
BIF: "FBu"
|
|
739
914
|
};
|
|
740
|
-
function getCurrencySymbol(
|
|
741
|
-
return CURRENCY_SYMBOLS[
|
|
915
|
+
function getCurrencySymbol(currencyCode2) {
|
|
916
|
+
return CURRENCY_SYMBOLS[currencyCode2.toUpperCase()] || currencyCode2;
|
|
742
917
|
}
|
|
743
918
|
function formatNumberCompact(value, decimals = 1) {
|
|
744
919
|
const absValue = Math.abs(value);
|
|
@@ -1062,6 +1237,8 @@ function normalizeStatusResponse(response) {
|
|
|
1062
1237
|
}
|
|
1063
1238
|
const res = response;
|
|
1064
1239
|
const normalizedStatus = normalizePaymentStatusValue(res.status ?? void 0);
|
|
1240
|
+
const normalizedAmount = typeof res.amount === "string" ? money(res.amount) : typeof res.amount === "number" && Number.isFinite(res.amount) ? moneyFromNumber(res.amount) : void 0;
|
|
1241
|
+
const normalizedCurrency = typeof res.currency === "string" && res.currency.trim().length > 0 ? currencyCode(res.currency) : void 0;
|
|
1065
1242
|
const paidValue = res.paid === true;
|
|
1066
1243
|
const derivedPaid = paidValue || [
|
|
1067
1244
|
"success",
|
|
@@ -1074,8 +1251,8 @@ function normalizeStatusResponse(response) {
|
|
|
1074
1251
|
return {
|
|
1075
1252
|
status: normalizedStatus,
|
|
1076
1253
|
paid: derivedPaid,
|
|
1077
|
-
amount:
|
|
1078
|
-
currency:
|
|
1254
|
+
amount: normalizedAmount,
|
|
1255
|
+
currency: normalizedCurrency,
|
|
1079
1256
|
reference: res.reference,
|
|
1080
1257
|
message: res.message || ""
|
|
1081
1258
|
};
|
|
@@ -1656,11 +1833,11 @@ var CheckoutResolver = class {
|
|
|
1656
1833
|
|
|
1657
1834
|
// src/checkout.ts
|
|
1658
1835
|
function toCimplifyError3(error) {
|
|
1659
|
-
if (error instanceof CimplifyError) return error;
|
|
1836
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
1660
1837
|
if (error instanceof Error) {
|
|
1661
|
-
return new CimplifyError(
|
|
1838
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
1662
1839
|
}
|
|
1663
|
-
return new CimplifyError(
|
|
1840
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
1664
1841
|
}
|
|
1665
1842
|
async function safe3(promise) {
|
|
1666
1843
|
try {
|
|
@@ -1782,14 +1959,17 @@ var CheckoutService = class {
|
|
|
1782
1959
|
pay_currency: data.pay_currency,
|
|
1783
1960
|
fx_quote_id: data.fx_quote_id
|
|
1784
1961
|
};
|
|
1785
|
-
const baseCurrency = (
|
|
1962
|
+
const baseCurrency = currencyCode(
|
|
1963
|
+
(cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase()
|
|
1964
|
+
);
|
|
1786
1965
|
const payCurrency = data.pay_currency?.trim().toUpperCase();
|
|
1966
|
+
const payCurrencyCode = payCurrency ? currencyCode(payCurrency) : void 0;
|
|
1787
1967
|
const cartTotalAmount = Number.parseFloat(cart.pricing.total_price || "0");
|
|
1788
|
-
if (
|
|
1968
|
+
if (payCurrencyCode && payCurrencyCode !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
|
|
1789
1969
|
const fxQuoteResult = await this.client.fx.lockQuote({
|
|
1790
1970
|
from: baseCurrency,
|
|
1791
|
-
to:
|
|
1792
|
-
amount:
|
|
1971
|
+
to: payCurrencyCode,
|
|
1972
|
+
amount: cart.pricing.total_price
|
|
1793
1973
|
});
|
|
1794
1974
|
if (!fxQuoteResult.ok) {
|
|
1795
1975
|
return ok(
|
|
@@ -1800,7 +1980,7 @@ var CheckoutService = class {
|
|
|
1800
1980
|
)
|
|
1801
1981
|
);
|
|
1802
1982
|
}
|
|
1803
|
-
checkoutData.pay_currency =
|
|
1983
|
+
checkoutData.pay_currency = payCurrencyCode;
|
|
1804
1984
|
checkoutData.fx_quote_id = fxQuoteResult.value.id;
|
|
1805
1985
|
}
|
|
1806
1986
|
data.on_status_change?.("processing", {});
|
|
@@ -1836,11 +2016,11 @@ var CheckoutService = class {
|
|
|
1836
2016
|
|
|
1837
2017
|
// src/orders.ts
|
|
1838
2018
|
function toCimplifyError4(error) {
|
|
1839
|
-
if (error instanceof CimplifyError) return error;
|
|
2019
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
1840
2020
|
if (error instanceof Error) {
|
|
1841
|
-
return new CimplifyError(
|
|
2021
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
1842
2022
|
}
|
|
1843
|
-
return new CimplifyError(
|
|
2023
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
1844
2024
|
}
|
|
1845
2025
|
async function safe4(promise) {
|
|
1846
2026
|
try {
|
|
@@ -2097,11 +2277,11 @@ var AuthService = class {
|
|
|
2097
2277
|
|
|
2098
2278
|
// src/business.ts
|
|
2099
2279
|
function toCimplifyError7(error) {
|
|
2100
|
-
if (error instanceof CimplifyError) return error;
|
|
2280
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
2101
2281
|
if (error instanceof Error) {
|
|
2102
|
-
return new CimplifyError(
|
|
2282
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
2103
2283
|
}
|
|
2104
|
-
return new CimplifyError(
|
|
2284
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
2105
2285
|
}
|
|
2106
2286
|
async function safe7(promise) {
|
|
2107
2287
|
try {
|
|
@@ -2487,12 +2667,15 @@ var EVENT_TYPES = {
|
|
|
2487
2667
|
|
|
2488
2668
|
// src/elements.ts
|
|
2489
2669
|
function toCheckoutError(code, message, recoverable) {
|
|
2670
|
+
const hint = getErrorHint(code);
|
|
2490
2671
|
return {
|
|
2491
2672
|
success: false,
|
|
2492
2673
|
error: {
|
|
2493
2674
|
code,
|
|
2494
2675
|
message,
|
|
2495
|
-
recoverable
|
|
2676
|
+
recoverable,
|
|
2677
|
+
docs_url: hint?.docs_url,
|
|
2678
|
+
suggestion: hint?.suggestion
|
|
2496
2679
|
}
|
|
2497
2680
|
};
|
|
2498
2681
|
}
|
|
@@ -2533,6 +2716,7 @@ var CimplifyElements = class {
|
|
|
2533
2716
|
this.paymentData = null;
|
|
2534
2717
|
this.checkoutInProgress = false;
|
|
2535
2718
|
this.activeCheckoutAbort = null;
|
|
2719
|
+
this.hasWarnedMissingAuthElement = false;
|
|
2536
2720
|
this.businessIdResolvePromise = null;
|
|
2537
2721
|
this.client = client;
|
|
2538
2722
|
this.businessId = businessId ?? null;
|
|
@@ -2628,6 +2812,12 @@ var CimplifyElements = class {
|
|
|
2628
2812
|
);
|
|
2629
2813
|
}
|
|
2630
2814
|
const authElement = this.elements.get(ELEMENT_TYPES.AUTH);
|
|
2815
|
+
if (!authElement && !this.hasWarnedMissingAuthElement) {
|
|
2816
|
+
this.hasWarnedMissingAuthElement = true;
|
|
2817
|
+
console.warn(
|
|
2818
|
+
"[Cimplify] processCheckout() called without AuthElement mounted. For best conversion and Link enrollment, mount <AuthElement> before checkout."
|
|
2819
|
+
);
|
|
2820
|
+
}
|
|
2631
2821
|
if (authElement && !this.accessToken) {
|
|
2632
2822
|
return toCheckoutError(
|
|
2633
2823
|
"AUTH_INCOMPLETE",
|
|
@@ -3064,28 +3254,37 @@ function isRetryable(error) {
|
|
|
3064
3254
|
}
|
|
3065
3255
|
return false;
|
|
3066
3256
|
}
|
|
3067
|
-
function toNetworkError(error) {
|
|
3257
|
+
function toNetworkError(error, isTestMode) {
|
|
3068
3258
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
3069
|
-
return
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3259
|
+
return enrichError(
|
|
3260
|
+
new CimplifyError(
|
|
3261
|
+
ErrorCode.TIMEOUT,
|
|
3262
|
+
"Request timed out. Please check your connection and try again.",
|
|
3263
|
+
true
|
|
3264
|
+
),
|
|
3265
|
+
{ isTestMode }
|
|
3073
3266
|
);
|
|
3074
3267
|
}
|
|
3075
3268
|
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
3076
|
-
return
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3269
|
+
return enrichError(
|
|
3270
|
+
new CimplifyError(
|
|
3271
|
+
ErrorCode.NETWORK_ERROR,
|
|
3272
|
+
"Network error. Please check your internet connection.",
|
|
3273
|
+
true
|
|
3274
|
+
),
|
|
3275
|
+
{ isTestMode }
|
|
3080
3276
|
);
|
|
3081
3277
|
}
|
|
3082
3278
|
if (error instanceof CimplifyError) {
|
|
3083
|
-
return error;
|
|
3084
|
-
}
|
|
3085
|
-
return
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3279
|
+
return enrichError(error, { isTestMode });
|
|
3280
|
+
}
|
|
3281
|
+
return enrichError(
|
|
3282
|
+
new CimplifyError(
|
|
3283
|
+
ErrorCode.UNKNOWN_ERROR,
|
|
3284
|
+
error instanceof Error ? error.message : "An unknown error occurred",
|
|
3285
|
+
false
|
|
3286
|
+
),
|
|
3287
|
+
{ isTestMode }
|
|
3089
3288
|
);
|
|
3090
3289
|
}
|
|
3091
3290
|
function deriveUrls() {
|
|
@@ -3147,6 +3346,9 @@ var CimplifyClient = class {
|
|
|
3147
3346
|
getPublicKey() {
|
|
3148
3347
|
return this.publicKey;
|
|
3149
3348
|
}
|
|
3349
|
+
isTestMode() {
|
|
3350
|
+
return this.publicKey.trim().startsWith("pk_test_");
|
|
3351
|
+
}
|
|
3150
3352
|
setAccessToken(token) {
|
|
3151
3353
|
const previous = this.accessToken;
|
|
3152
3354
|
this.accessToken = token;
|
|
@@ -3268,7 +3470,7 @@ var CimplifyClient = class {
|
|
|
3268
3470
|
signal: controller.signal
|
|
3269
3471
|
});
|
|
3270
3472
|
clearTimeout(timeoutId);
|
|
3271
|
-
if (response.ok
|
|
3473
|
+
if (response.ok) {
|
|
3272
3474
|
this.hooks.onRequestSuccess?.({
|
|
3273
3475
|
...context,
|
|
3274
3476
|
status: response.status,
|
|
@@ -3276,6 +3478,21 @@ var CimplifyClient = class {
|
|
|
3276
3478
|
});
|
|
3277
3479
|
return response;
|
|
3278
3480
|
}
|
|
3481
|
+
if (response.status >= 400 && response.status < 500) {
|
|
3482
|
+
this.hooks.onRequestError?.({
|
|
3483
|
+
...context,
|
|
3484
|
+
error: new CimplifyError(
|
|
3485
|
+
`HTTP_${response.status}`,
|
|
3486
|
+
`Request failed with status ${response.status}`,
|
|
3487
|
+
false
|
|
3488
|
+
),
|
|
3489
|
+
status: response.status,
|
|
3490
|
+
durationMs: Date.now() - startTime,
|
|
3491
|
+
retryCount,
|
|
3492
|
+
retryable: false
|
|
3493
|
+
});
|
|
3494
|
+
return response;
|
|
3495
|
+
}
|
|
3279
3496
|
if (response.status >= 500 && attempt < this.maxRetries) {
|
|
3280
3497
|
retryCount++;
|
|
3281
3498
|
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
@@ -3288,15 +3505,22 @@ var CimplifyClient = class {
|
|
|
3288
3505
|
await sleep(delay);
|
|
3289
3506
|
continue;
|
|
3290
3507
|
}
|
|
3291
|
-
this.hooks.
|
|
3508
|
+
this.hooks.onRequestError?.({
|
|
3292
3509
|
...context,
|
|
3510
|
+
error: new CimplifyError(
|
|
3511
|
+
"SERVER_ERROR",
|
|
3512
|
+
`Server error ${response.status} after ${retryCount} retries`,
|
|
3513
|
+
false
|
|
3514
|
+
),
|
|
3293
3515
|
status: response.status,
|
|
3294
|
-
durationMs: Date.now() - startTime
|
|
3516
|
+
durationMs: Date.now() - startTime,
|
|
3517
|
+
retryCount,
|
|
3518
|
+
retryable: false
|
|
3295
3519
|
});
|
|
3296
3520
|
return response;
|
|
3297
3521
|
} catch (error) {
|
|
3298
3522
|
lastError = error;
|
|
3299
|
-
const networkError = toNetworkError(error);
|
|
3523
|
+
const networkError = toNetworkError(error, this.isTestMode());
|
|
3300
3524
|
const errorRetryable = isRetryable(error);
|
|
3301
3525
|
if (!errorRetryable || attempt >= this.maxRetries) {
|
|
3302
3526
|
this.hooks.onRequestError?.({
|
|
@@ -3319,7 +3543,7 @@ var CimplifyClient = class {
|
|
|
3319
3543
|
await sleep(delay);
|
|
3320
3544
|
}
|
|
3321
3545
|
}
|
|
3322
|
-
const finalError = toNetworkError(lastError);
|
|
3546
|
+
const finalError = toNetworkError(lastError, this.isTestMode());
|
|
3323
3547
|
this.hooks.onRequestError?.({
|
|
3324
3548
|
...context,
|
|
3325
3549
|
error: finalError,
|
|
@@ -3437,22 +3661,40 @@ var CimplifyClient = class {
|
|
|
3437
3661
|
async handleRestResponse(response) {
|
|
3438
3662
|
const json = await response.json();
|
|
3439
3663
|
if (!response.ok) {
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3664
|
+
const error = enrichError(
|
|
3665
|
+
new CimplifyError(
|
|
3666
|
+
json.error?.error_code || "API_ERROR",
|
|
3667
|
+
json.error?.error_message || "An error occurred",
|
|
3668
|
+
false
|
|
3669
|
+
),
|
|
3670
|
+
{ isTestMode: this.isTestMode() }
|
|
3444
3671
|
);
|
|
3672
|
+
if (response.status === 401 || error.code === ErrorCode.UNAUTHORIZED) {
|
|
3673
|
+
console.warn(
|
|
3674
|
+
"[Cimplify] Received 401 Unauthorized. Access token may be missing/expired. Refresh authentication and retry the request."
|
|
3675
|
+
);
|
|
3676
|
+
}
|
|
3677
|
+
throw error;
|
|
3445
3678
|
}
|
|
3446
3679
|
return json.data;
|
|
3447
3680
|
}
|
|
3448
3681
|
async handleResponse(response) {
|
|
3449
3682
|
const json = await response.json();
|
|
3450
3683
|
if (!json.success || json.error) {
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3684
|
+
const error = enrichError(
|
|
3685
|
+
new CimplifyError(
|
|
3686
|
+
json.error?.code || "UNKNOWN_ERROR",
|
|
3687
|
+
json.error?.message || "An unknown error occurred",
|
|
3688
|
+
json.error?.retryable || false
|
|
3689
|
+
),
|
|
3690
|
+
{ isTestMode: this.isTestMode() }
|
|
3455
3691
|
);
|
|
3692
|
+
if (response.status === 401 || error.code === ErrorCode.UNAUTHORIZED) {
|
|
3693
|
+
console.warn(
|
|
3694
|
+
"[Cimplify] Received 401 Unauthorized. Access token may be missing/expired. Refresh authentication and retry the request."
|
|
3695
|
+
);
|
|
3696
|
+
}
|
|
3697
|
+
throw error;
|
|
3456
3698
|
}
|
|
3457
3699
|
return json.data;
|
|
3458
3700
|
}
|
|
@@ -3547,71 +3789,6 @@ function createCimplifyClient(config = {}) {
|
|
|
3547
3789
|
return new CimplifyClient(config);
|
|
3548
3790
|
}
|
|
3549
3791
|
|
|
3550
|
-
// src/query/builder.ts
|
|
3551
|
-
var QueryBuilder = class {
|
|
3552
|
-
constructor(entity) {
|
|
3553
|
-
this.filters = [];
|
|
3554
|
-
this.modifiers = [];
|
|
3555
|
-
this.pathSegments = [];
|
|
3556
|
-
this.entity = entity;
|
|
3557
|
-
}
|
|
3558
|
-
path(segment) {
|
|
3559
|
-
this.pathSegments.push(segment);
|
|
3560
|
-
return this;
|
|
3561
|
-
}
|
|
3562
|
-
where(field, op, value) {
|
|
3563
|
-
const v = typeof value === "string" ? `'${value}'` : value;
|
|
3564
|
-
if (op === "contains" || op === "startsWith") {
|
|
3565
|
-
this.filters.push(`@.${field} ${op} ${v}`);
|
|
3566
|
-
} else {
|
|
3567
|
-
this.filters.push(`@.${field}${op}${v}`);
|
|
3568
|
-
}
|
|
3569
|
-
return this;
|
|
3570
|
-
}
|
|
3571
|
-
and(field, op, value) {
|
|
3572
|
-
return this.where(field, op, value);
|
|
3573
|
-
}
|
|
3574
|
-
sort(field, order = "asc") {
|
|
3575
|
-
this.modifiers.push(`sort(${field},${order})`);
|
|
3576
|
-
return this;
|
|
3577
|
-
}
|
|
3578
|
-
limit(n) {
|
|
3579
|
-
this.modifiers.push(`limit(${n})`);
|
|
3580
|
-
return this;
|
|
3581
|
-
}
|
|
3582
|
-
offset(n) {
|
|
3583
|
-
this.modifiers.push(`offset(${n})`);
|
|
3584
|
-
return this;
|
|
3585
|
-
}
|
|
3586
|
-
count() {
|
|
3587
|
-
this.modifiers.push("count");
|
|
3588
|
-
return this;
|
|
3589
|
-
}
|
|
3590
|
-
enriched() {
|
|
3591
|
-
this.modifiers.push("enriched");
|
|
3592
|
-
return this;
|
|
3593
|
-
}
|
|
3594
|
-
build() {
|
|
3595
|
-
let query2 = this.entity;
|
|
3596
|
-
if (this.pathSegments.length > 0) {
|
|
3597
|
-
query2 += "." + this.pathSegments.join(".");
|
|
3598
|
-
}
|
|
3599
|
-
if (this.filters.length > 0) {
|
|
3600
|
-
query2 += `[?(${this.filters.join(" && ")})]`;
|
|
3601
|
-
}
|
|
3602
|
-
for (const mod of this.modifiers) {
|
|
3603
|
-
query2 += `#${mod}`;
|
|
3604
|
-
}
|
|
3605
|
-
return query2;
|
|
3606
|
-
}
|
|
3607
|
-
toString() {
|
|
3608
|
-
return this.build();
|
|
3609
|
-
}
|
|
3610
|
-
};
|
|
3611
|
-
function query(entity) {
|
|
3612
|
-
return new QueryBuilder(entity);
|
|
3613
|
-
}
|
|
3614
|
-
|
|
3615
3792
|
exports.AUTHORIZATION_TYPE = AUTHORIZATION_TYPE;
|
|
3616
3793
|
exports.AUTH_MUTATION = AUTH_MUTATION;
|
|
3617
3794
|
exports.AuthService = AuthService;
|
|
@@ -3633,6 +3810,7 @@ exports.DEFAULT_COUNTRY = DEFAULT_COUNTRY;
|
|
|
3633
3810
|
exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
|
|
3634
3811
|
exports.DEVICE_TYPE = DEVICE_TYPE;
|
|
3635
3812
|
exports.ELEMENT_TYPES = ELEMENT_TYPES;
|
|
3813
|
+
exports.ERROR_HINTS = ERROR_HINTS;
|
|
3636
3814
|
exports.EVENT_TYPES = EVENT_TYPES;
|
|
3637
3815
|
exports.ErrorCode = ErrorCode;
|
|
3638
3816
|
exports.FxService = FxService;
|
|
@@ -3653,12 +3831,15 @@ exports.PAYMENT_STATE = PAYMENT_STATE;
|
|
|
3653
3831
|
exports.PICKUP_TIME_TYPE = PICKUP_TIME_TYPE;
|
|
3654
3832
|
exports.QueryBuilder = QueryBuilder;
|
|
3655
3833
|
exports.SchedulingService = SchedulingService;
|
|
3834
|
+
exports.ZERO = ZERO;
|
|
3656
3835
|
exports.categorizePaymentError = categorizePaymentError;
|
|
3657
3836
|
exports.combine = combine;
|
|
3658
3837
|
exports.combineObject = combineObject;
|
|
3659
3838
|
exports.createCimplifyClient = createCimplifyClient;
|
|
3660
3839
|
exports.createElements = createElements;
|
|
3840
|
+
exports.currencyCode = currencyCode;
|
|
3661
3841
|
exports.detectMobileMoneyProvider = detectMobileMoneyProvider;
|
|
3842
|
+
exports.enrichError = enrichError;
|
|
3662
3843
|
exports.err = err;
|
|
3663
3844
|
exports.flatMap = flatMap;
|
|
3664
3845
|
exports.formatMoney = formatMoney;
|
|
@@ -3673,6 +3854,7 @@ exports.getBasePrice = getBasePrice;
|
|
|
3673
3854
|
exports.getCurrencySymbol = getCurrencySymbol;
|
|
3674
3855
|
exports.getDiscountPercentage = getDiscountPercentage;
|
|
3675
3856
|
exports.getDisplayPrice = getDisplayPrice;
|
|
3857
|
+
exports.getErrorHint = getErrorHint;
|
|
3676
3858
|
exports.getMarkupPercentage = getMarkupPercentage;
|
|
3677
3859
|
exports.getOrElse = getOrElse;
|
|
3678
3860
|
exports.getProductCurrency = getProductCurrency;
|
|
@@ -3686,6 +3868,8 @@ exports.isPaymentStatusSuccess = isPaymentStatusSuccess;
|
|
|
3686
3868
|
exports.isRetryableError = isRetryableError;
|
|
3687
3869
|
exports.mapError = mapError;
|
|
3688
3870
|
exports.mapResult = mapResult;
|
|
3871
|
+
exports.money = money;
|
|
3872
|
+
exports.moneyFromNumber = moneyFromNumber;
|
|
3689
3873
|
exports.normalizePaymentResponse = normalizePaymentResponse;
|
|
3690
3874
|
exports.normalizeStatusResponse = normalizeStatusResponse;
|
|
3691
3875
|
exports.ok = ok;
|