@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/advanced.mjs
CHANGED
|
@@ -7,11 +7,84 @@ function err(error) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
// src/types/common.ts
|
|
10
|
+
function money(value) {
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function moneyFromNumber(value) {
|
|
14
|
+
return value.toFixed(2);
|
|
15
|
+
}
|
|
16
|
+
function currencyCode(value) {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
var ErrorCode = {
|
|
20
|
+
// General
|
|
21
|
+
UNKNOWN_ERROR: "UNKNOWN_ERROR"};
|
|
22
|
+
var DOCS_ERROR_BASE_URL = "https://docs.cimplify.io/reference/error-codes";
|
|
23
|
+
function docsUrlForCode(code) {
|
|
24
|
+
return `${DOCS_ERROR_BASE_URL}#${code.toLowerCase().replace(/_/g, "-")}`;
|
|
25
|
+
}
|
|
26
|
+
var ERROR_SUGGESTIONS = {
|
|
27
|
+
UNKNOWN_ERROR: "An unexpected error occurred. Capture the request/response payload and retry with exponential backoff.",
|
|
28
|
+
NETWORK_ERROR: "Check the shopper's connection and retry. If this persists, inspect CORS, DNS, and API reachability.",
|
|
29
|
+
TIMEOUT: "The request exceeded the timeout. Retry once, then poll order status before charging again.",
|
|
30
|
+
UNAUTHORIZED: "Authentication is missing or expired. Ensure a valid access token is set and refresh the session if needed.",
|
|
31
|
+
FORBIDDEN: "The key/session lacks permission for this resource. Verify business ownership and API key scope.",
|
|
32
|
+
NOT_FOUND: "The requested resource does not exist or is not visible in this environment.",
|
|
33
|
+
VALIDATION_ERROR: "One or more fields are invalid. Validate required fields and enum values before retrying.",
|
|
34
|
+
CART_EMPTY: "The cart has no items. Redirect back to menu/catalogue and require at least one line item.",
|
|
35
|
+
CART_EXPIRED: "This cart is no longer active. Recreate a new cart and re-add shopper selections.",
|
|
36
|
+
CART_NOT_FOUND: "Cart could not be located. It may have expired or belongs to a different key/location.",
|
|
37
|
+
ITEM_UNAVAILABLE: "The selected item is unavailable at this location/time. Prompt the shopper to pick an alternative.",
|
|
38
|
+
VARIANT_NOT_FOUND: "The requested variant no longer exists. Refresh product data and require re-selection.",
|
|
39
|
+
VARIANT_OUT_OF_STOCK: "The selected variant is out of stock. Show in-stock variants and block checkout for this line.",
|
|
40
|
+
ADDON_REQUIRED: "A required add-on is missing. Ensure required modifier groups are completed before add-to-cart.",
|
|
41
|
+
ADDON_MAX_EXCEEDED: "Too many add-ons were selected. Enforce max selections client-side before submission.",
|
|
42
|
+
CHECKOUT_VALIDATION_FAILED: "Checkout payload failed validation. Verify customer, order type, and address fields are complete.",
|
|
43
|
+
DELIVERY_ADDRESS_REQUIRED: "Delivery orders require an address. Collect and pass address info before processing checkout.",
|
|
44
|
+
CUSTOMER_INFO_REQUIRED: "Customer details are required. Ensure name/email/phone are available before checkout.",
|
|
45
|
+
PAYMENT_FAILED: "Payment provider rejected or failed processing. Show retry/change-method options to the shopper.",
|
|
46
|
+
PAYMENT_CANCELLED: "Payment was cancelled by the shopper or provider flow. Allow a safe retry path.",
|
|
47
|
+
INSUFFICIENT_FUNDS: "Payment method has insufficient funds. Prompt shopper to use another method.",
|
|
48
|
+
CARD_DECLINED: "Card was declined. Ask shopper to retry or switch payment method.",
|
|
49
|
+
INVALID_OTP: "Authorization code is invalid. Let shopper re-enter OTP/PIN and retry.",
|
|
50
|
+
OTP_EXPIRED: "Authorization code expired. Request a new OTP and re-submit authorization.",
|
|
51
|
+
AUTHORIZATION_FAILED: "Additional payment authorization failed. Retry authorization or change payment method.",
|
|
52
|
+
PAYMENT_ACTION_NOT_COMPLETED: "Required payment action was not completed. Resume provider flow and poll for status.",
|
|
53
|
+
SLOT_UNAVAILABLE: "Selected schedule slot is unavailable. Refresh available slots and ask shopper to reselect.",
|
|
54
|
+
BOOKING_CONFLICT: "The requested booking conflicts with an existing reservation. Pick another slot/resource.",
|
|
55
|
+
SERVICE_NOT_FOUND: "Requested service no longer exists. Refresh service catalogue and retry selection.",
|
|
56
|
+
OUT_OF_STOCK: "Inventory is depleted for this item. Remove it or reduce quantity before checkout.",
|
|
57
|
+
INSUFFICIENT_QUANTITY: "Requested quantity exceeds available inventory. Reduce quantity and retry.",
|
|
58
|
+
BUSINESS_ID_REQUIRED: "Business context could not be resolved. Verify the public key and business bootstrap call.",
|
|
59
|
+
INVALID_CART: "Cart is invalid for checkout. Sync cart state, ensure items exist, then retry.",
|
|
60
|
+
ORDER_TYPE_REQUIRED: "Order type is required. Provide one of delivery, pickup, or dine_in before checkout.",
|
|
61
|
+
NO_PAYMENT_ELEMENT: "PaymentElement is required for processCheckout(). Mount it before triggering checkout.",
|
|
62
|
+
PAYMENT_NOT_MOUNTED: "PaymentElement iframe is not mounted. Mount it in the DOM before processCheckout().",
|
|
63
|
+
AUTH_INCOMPLETE: "AuthElement has not completed authentication. Wait for AUTHENTICATED before checkout.",
|
|
64
|
+
AUTH_LOST: "Session was cleared during checkout. Re-authenticate and restart checkout safely.",
|
|
65
|
+
ALREADY_PROCESSING: "Checkout is already in progress. Disable duplicate submits until completion.",
|
|
66
|
+
CHECKOUT_NOT_READY: "Checkout elements are still initializing. Wait for readiness before submit.",
|
|
67
|
+
CANCELLED: "Checkout was cancelled. Preserve cart state and allow shopper to retry.",
|
|
68
|
+
REQUEST_TIMEOUT: "Provider call timed out. Poll payment/order status before issuing another charge attempt.",
|
|
69
|
+
POPUP_BLOCKED: "Browser blocked provider popup. Ask shopper to enable popups and retry.",
|
|
70
|
+
FX_QUOTE_FAILED: "Failed to lock FX quote. Retry currency quote or fallback to base currency."
|
|
71
|
+
};
|
|
72
|
+
var ERROR_HINTS = Object.fromEntries(
|
|
73
|
+
Object.entries(ERROR_SUGGESTIONS).map(([code, suggestion]) => [
|
|
74
|
+
code,
|
|
75
|
+
{
|
|
76
|
+
docs_url: docsUrlForCode(code),
|
|
77
|
+
suggestion
|
|
78
|
+
}
|
|
79
|
+
])
|
|
80
|
+
);
|
|
10
81
|
var CimplifyError = class extends Error {
|
|
11
|
-
constructor(code, message, retryable = false) {
|
|
82
|
+
constructor(code, message, retryable = false, docs_url, suggestion) {
|
|
12
83
|
super(message);
|
|
13
84
|
this.code = code;
|
|
14
85
|
this.retryable = retryable;
|
|
86
|
+
this.docs_url = docs_url;
|
|
87
|
+
this.suggestion = suggestion;
|
|
15
88
|
this.name = "CimplifyError";
|
|
16
89
|
}
|
|
17
90
|
/** User-friendly message safe to display */
|
|
@@ -19,14 +92,104 @@ var CimplifyError = class extends Error {
|
|
|
19
92
|
return this.message;
|
|
20
93
|
}
|
|
21
94
|
};
|
|
95
|
+
function getErrorHint(code) {
|
|
96
|
+
return ERROR_HINTS[code];
|
|
97
|
+
}
|
|
98
|
+
function enrichError(error, options = {}) {
|
|
99
|
+
const hint = getErrorHint(error.code);
|
|
100
|
+
if (hint) {
|
|
101
|
+
if (!error.docs_url) {
|
|
102
|
+
error.docs_url = hint.docs_url;
|
|
103
|
+
}
|
|
104
|
+
if (!error.suggestion) {
|
|
105
|
+
error.suggestion = hint.suggestion;
|
|
106
|
+
}
|
|
107
|
+
} else if (!error.docs_url) {
|
|
108
|
+
error.docs_url = docsUrlForCode(error.code || ErrorCode.UNKNOWN_ERROR);
|
|
109
|
+
}
|
|
110
|
+
if (options.isTestMode && !error.message.includes("pk_test_")) {
|
|
111
|
+
error.message = `${error.message}
|
|
112
|
+
|
|
113
|
+
\u2139 Your API key is a test-mode key (pk_test_...). Verify test data/session before retrying.`;
|
|
114
|
+
}
|
|
115
|
+
return error;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/query/builder.ts
|
|
119
|
+
function escapeQueryValue(value) {
|
|
120
|
+
return value.replace(/'/g, "\\'");
|
|
121
|
+
}
|
|
122
|
+
var QueryBuilder = class {
|
|
123
|
+
constructor(entity) {
|
|
124
|
+
this.filters = [];
|
|
125
|
+
this.modifiers = [];
|
|
126
|
+
this.pathSegments = [];
|
|
127
|
+
this.entity = entity;
|
|
128
|
+
}
|
|
129
|
+
path(segment) {
|
|
130
|
+
this.pathSegments.push(segment);
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
where(field, op, value) {
|
|
134
|
+
const v = typeof value === "string" ? `'${escapeQueryValue(value)}'` : value;
|
|
135
|
+
if (op === "contains" || op === "startsWith") {
|
|
136
|
+
this.filters.push(`@.${field} ${op} ${v}`);
|
|
137
|
+
} else {
|
|
138
|
+
this.filters.push(`@.${field}${op}${v}`);
|
|
139
|
+
}
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
and(field, op, value) {
|
|
143
|
+
return this.where(field, op, value);
|
|
144
|
+
}
|
|
145
|
+
sort(field, order = "asc") {
|
|
146
|
+
this.modifiers.push(`sort(${field},${order})`);
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
limit(n) {
|
|
150
|
+
this.modifiers.push(`limit(${n})`);
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
offset(n) {
|
|
154
|
+
this.modifiers.push(`offset(${n})`);
|
|
155
|
+
return this;
|
|
156
|
+
}
|
|
157
|
+
count() {
|
|
158
|
+
this.modifiers.push("count");
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
enriched() {
|
|
162
|
+
this.modifiers.push("enriched");
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
build() {
|
|
166
|
+
let query2 = this.entity;
|
|
167
|
+
if (this.pathSegments.length > 0) {
|
|
168
|
+
query2 += "." + this.pathSegments.join(".");
|
|
169
|
+
}
|
|
170
|
+
if (this.filters.length > 0) {
|
|
171
|
+
query2 += `[?(${this.filters.join(" && ")})]`;
|
|
172
|
+
}
|
|
173
|
+
for (const mod of this.modifiers) {
|
|
174
|
+
query2 += `#${mod}`;
|
|
175
|
+
}
|
|
176
|
+
return query2;
|
|
177
|
+
}
|
|
178
|
+
toString() {
|
|
179
|
+
return this.build();
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
function query(entity) {
|
|
183
|
+
return new QueryBuilder(entity);
|
|
184
|
+
}
|
|
22
185
|
|
|
23
186
|
// src/catalogue.ts
|
|
24
187
|
function toCimplifyError(error) {
|
|
25
|
-
if (error instanceof CimplifyError) return error;
|
|
188
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
26
189
|
if (error instanceof Error) {
|
|
27
|
-
return new CimplifyError(
|
|
190
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
28
191
|
}
|
|
29
|
-
return new CimplifyError(
|
|
192
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
30
193
|
}
|
|
31
194
|
async function safe(promise) {
|
|
32
195
|
try {
|
|
@@ -100,7 +263,7 @@ var CatalogueQueries = class {
|
|
|
100
263
|
let query2 = "products";
|
|
101
264
|
const filters = [];
|
|
102
265
|
if (options?.category) {
|
|
103
|
-
filters.push(`@.category_id=='${options.category}'`);
|
|
266
|
+
filters.push(`@.category_id=='${escapeQueryValue(options.category)}'`);
|
|
104
267
|
}
|
|
105
268
|
if (options?.featured !== void 0) {
|
|
106
269
|
filters.push(`@.featured==${options.featured}`);
|
|
@@ -109,7 +272,7 @@ var CatalogueQueries = class {
|
|
|
109
272
|
filters.push(`@.in_stock==${options.in_stock}`);
|
|
110
273
|
}
|
|
111
274
|
if (options?.search) {
|
|
112
|
-
filters.push(`@.name contains '${options.search}'`);
|
|
275
|
+
filters.push(`@.name contains '${escapeQueryValue(options.search)}'`);
|
|
113
276
|
}
|
|
114
277
|
if (options?.min_price !== void 0) {
|
|
115
278
|
filters.push(`@.price>=${options.min_price}`);
|
|
@@ -140,7 +303,9 @@ var CatalogueQueries = class {
|
|
|
140
303
|
}
|
|
141
304
|
async getProductBySlug(slug) {
|
|
142
305
|
const filteredResult = await safe(
|
|
143
|
-
this.client.query(
|
|
306
|
+
this.client.query(
|
|
307
|
+
`products[?(@.slug=='${escapeQueryValue(slug)}')]`
|
|
308
|
+
)
|
|
144
309
|
);
|
|
145
310
|
if (!filteredResult.ok) return filteredResult;
|
|
146
311
|
const exactMatch = findProductBySlug(filteredResult.value, slug);
|
|
@@ -192,7 +357,7 @@ var CatalogueQueries = class {
|
|
|
192
357
|
}
|
|
193
358
|
async getCategoryBySlug(slug) {
|
|
194
359
|
const result = await safe(
|
|
195
|
-
this.client.query(`categories[?(@.slug=='${slug}')]`)
|
|
360
|
+
this.client.query(`categories[?(@.slug=='${escapeQueryValue(slug)}')]`)
|
|
196
361
|
);
|
|
197
362
|
if (!result.ok) return result;
|
|
198
363
|
if (!result.value.length) {
|
|
@@ -201,7 +366,11 @@ var CatalogueQueries = class {
|
|
|
201
366
|
return ok(result.value[0]);
|
|
202
367
|
}
|
|
203
368
|
async getCategoryProducts(categoryId) {
|
|
204
|
-
return safe(
|
|
369
|
+
return safe(
|
|
370
|
+
this.client.query(
|
|
371
|
+
`products[?(@.category_id=='${escapeQueryValue(categoryId)}')]`
|
|
372
|
+
)
|
|
373
|
+
);
|
|
205
374
|
}
|
|
206
375
|
async getCollections() {
|
|
207
376
|
return safe(this.client.query("collections"));
|
|
@@ -211,7 +380,9 @@ var CatalogueQueries = class {
|
|
|
211
380
|
}
|
|
212
381
|
async getCollectionBySlug(slug) {
|
|
213
382
|
const result = await safe(
|
|
214
|
-
this.client.query(
|
|
383
|
+
this.client.query(
|
|
384
|
+
`collections[?(@.slug=='${escapeQueryValue(slug)}')]`
|
|
385
|
+
)
|
|
215
386
|
);
|
|
216
387
|
if (!result.ok) return result;
|
|
217
388
|
if (!result.value.length) {
|
|
@@ -224,7 +395,9 @@ var CatalogueQueries = class {
|
|
|
224
395
|
}
|
|
225
396
|
async searchCollections(query2, limit = 20) {
|
|
226
397
|
return safe(
|
|
227
|
-
this.client.query(
|
|
398
|
+
this.client.query(
|
|
399
|
+
`collections[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
|
|
400
|
+
)
|
|
228
401
|
);
|
|
229
402
|
}
|
|
230
403
|
async getBundles() {
|
|
@@ -235,7 +408,9 @@ var CatalogueQueries = class {
|
|
|
235
408
|
}
|
|
236
409
|
async getBundleBySlug(slug) {
|
|
237
410
|
const result = await safe(
|
|
238
|
-
this.client.query(
|
|
411
|
+
this.client.query(
|
|
412
|
+
`bundles[?(@.slug=='${escapeQueryValue(slug)}')]`
|
|
413
|
+
)
|
|
239
414
|
);
|
|
240
415
|
if (!result.ok) return result;
|
|
241
416
|
if (!result.value.length) {
|
|
@@ -245,7 +420,9 @@ var CatalogueQueries = class {
|
|
|
245
420
|
}
|
|
246
421
|
async searchBundles(query2, limit = 20) {
|
|
247
422
|
return safe(
|
|
248
|
-
this.client.query(
|
|
423
|
+
this.client.query(
|
|
424
|
+
`bundles[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
|
|
425
|
+
)
|
|
249
426
|
);
|
|
250
427
|
}
|
|
251
428
|
async getComposites(options) {
|
|
@@ -285,9 +462,9 @@ var CatalogueQueries = class {
|
|
|
285
462
|
}
|
|
286
463
|
async search(query2, options) {
|
|
287
464
|
const limit = options?.limit ?? 20;
|
|
288
|
-
let searchQuery = `products[?(@.name contains '${query2}')]`;
|
|
465
|
+
let searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}')]`;
|
|
289
466
|
if (options?.category) {
|
|
290
|
-
searchQuery = `products[?(@.name contains '${query2}' && @.category_id=='${options.category}')]`;
|
|
467
|
+
searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}' && @.category_id=='${escapeQueryValue(options.category)}')]`;
|
|
291
468
|
}
|
|
292
469
|
searchQuery += `#limit(${limit})`;
|
|
293
470
|
return safe(this.client.query(searchQuery));
|
|
@@ -304,7 +481,7 @@ var CatalogueQueries = class {
|
|
|
304
481
|
async getMenu(options) {
|
|
305
482
|
let query2 = "menu";
|
|
306
483
|
if (options?.category) {
|
|
307
|
-
query2 = `menu[?(@.category=='${options.category}')]`;
|
|
484
|
+
query2 = `menu[?(@.category=='${escapeQueryValue(options.category)}')]`;
|
|
308
485
|
}
|
|
309
486
|
if (options?.limit) {
|
|
310
487
|
query2 += `#limit(${options.limit})`;
|
|
@@ -321,11 +498,11 @@ var CatalogueQueries = class {
|
|
|
321
498
|
|
|
322
499
|
// src/cart.ts
|
|
323
500
|
function toCimplifyError2(error) {
|
|
324
|
-
if (error instanceof CimplifyError) return error;
|
|
501
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
325
502
|
if (error instanceof Error) {
|
|
326
|
-
return new CimplifyError(
|
|
503
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
327
504
|
}
|
|
328
|
-
return new CimplifyError(
|
|
505
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
329
506
|
}
|
|
330
507
|
async function safe2(promise) {
|
|
331
508
|
try {
|
|
@@ -585,6 +762,8 @@ function normalizeStatusResponse(response) {
|
|
|
585
762
|
}
|
|
586
763
|
const res = response;
|
|
587
764
|
const normalizedStatus = normalizePaymentStatusValue(res.status ?? void 0);
|
|
765
|
+
const normalizedAmount = typeof res.amount === "string" ? money(res.amount) : typeof res.amount === "number" && Number.isFinite(res.amount) ? moneyFromNumber(res.amount) : void 0;
|
|
766
|
+
const normalizedCurrency = typeof res.currency === "string" && res.currency.trim().length > 0 ? currencyCode(res.currency) : void 0;
|
|
588
767
|
const paidValue = res.paid === true;
|
|
589
768
|
const derivedPaid = paidValue || [
|
|
590
769
|
"success",
|
|
@@ -597,8 +776,8 @@ function normalizeStatusResponse(response) {
|
|
|
597
776
|
return {
|
|
598
777
|
status: normalizedStatus,
|
|
599
778
|
paid: derivedPaid,
|
|
600
|
-
amount:
|
|
601
|
-
currency:
|
|
779
|
+
amount: normalizedAmount,
|
|
780
|
+
currency: normalizedCurrency,
|
|
602
781
|
reference: res.reference,
|
|
603
782
|
message: res.message || ""
|
|
604
783
|
};
|
|
@@ -1164,11 +1343,11 @@ var CheckoutResolver = class {
|
|
|
1164
1343
|
|
|
1165
1344
|
// src/checkout.ts
|
|
1166
1345
|
function toCimplifyError3(error) {
|
|
1167
|
-
if (error instanceof CimplifyError) return error;
|
|
1346
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
1168
1347
|
if (error instanceof Error) {
|
|
1169
|
-
return new CimplifyError(
|
|
1348
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
1170
1349
|
}
|
|
1171
|
-
return new CimplifyError(
|
|
1350
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
1172
1351
|
}
|
|
1173
1352
|
async function safe3(promise) {
|
|
1174
1353
|
try {
|
|
@@ -1290,14 +1469,17 @@ var CheckoutService = class {
|
|
|
1290
1469
|
pay_currency: data.pay_currency,
|
|
1291
1470
|
fx_quote_id: data.fx_quote_id
|
|
1292
1471
|
};
|
|
1293
|
-
const baseCurrency = (
|
|
1472
|
+
const baseCurrency = currencyCode(
|
|
1473
|
+
(cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase()
|
|
1474
|
+
);
|
|
1294
1475
|
const payCurrency = data.pay_currency?.trim().toUpperCase();
|
|
1476
|
+
const payCurrencyCode = payCurrency ? currencyCode(payCurrency) : void 0;
|
|
1295
1477
|
const cartTotalAmount = Number.parseFloat(cart.pricing.total_price || "0");
|
|
1296
|
-
if (
|
|
1478
|
+
if (payCurrencyCode && payCurrencyCode !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
|
|
1297
1479
|
const fxQuoteResult = await this.client.fx.lockQuote({
|
|
1298
1480
|
from: baseCurrency,
|
|
1299
|
-
to:
|
|
1300
|
-
amount:
|
|
1481
|
+
to: payCurrencyCode,
|
|
1482
|
+
amount: cart.pricing.total_price
|
|
1301
1483
|
});
|
|
1302
1484
|
if (!fxQuoteResult.ok) {
|
|
1303
1485
|
return ok(
|
|
@@ -1308,7 +1490,7 @@ var CheckoutService = class {
|
|
|
1308
1490
|
)
|
|
1309
1491
|
);
|
|
1310
1492
|
}
|
|
1311
|
-
checkoutData.pay_currency =
|
|
1493
|
+
checkoutData.pay_currency = payCurrencyCode;
|
|
1312
1494
|
checkoutData.fx_quote_id = fxQuoteResult.value.id;
|
|
1313
1495
|
}
|
|
1314
1496
|
data.on_status_change?.("processing", {});
|
|
@@ -1344,11 +1526,11 @@ var CheckoutService = class {
|
|
|
1344
1526
|
|
|
1345
1527
|
// src/orders.ts
|
|
1346
1528
|
function toCimplifyError4(error) {
|
|
1347
|
-
if (error instanceof CimplifyError) return error;
|
|
1529
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
1348
1530
|
if (error instanceof Error) {
|
|
1349
|
-
return new CimplifyError(
|
|
1531
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
1350
1532
|
}
|
|
1351
|
-
return new CimplifyError(
|
|
1533
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
1352
1534
|
}
|
|
1353
1535
|
async function safe4(promise) {
|
|
1354
1536
|
try {
|
|
@@ -1605,11 +1787,11 @@ var AuthService = class {
|
|
|
1605
1787
|
|
|
1606
1788
|
// src/business.ts
|
|
1607
1789
|
function toCimplifyError7(error) {
|
|
1608
|
-
if (error instanceof CimplifyError) return error;
|
|
1790
|
+
if (error instanceof CimplifyError) return enrichError(error);
|
|
1609
1791
|
if (error instanceof Error) {
|
|
1610
|
-
return new CimplifyError(
|
|
1792
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
1611
1793
|
}
|
|
1612
|
-
return new CimplifyError(
|
|
1794
|
+
return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
|
|
1613
1795
|
}
|
|
1614
1796
|
async function safe7(promise) {
|
|
1615
1797
|
try {
|
|
@@ -1995,12 +2177,15 @@ var EVENT_TYPES = {
|
|
|
1995
2177
|
|
|
1996
2178
|
// src/elements.ts
|
|
1997
2179
|
function toCheckoutError(code, message, recoverable) {
|
|
2180
|
+
const hint = getErrorHint(code);
|
|
1998
2181
|
return {
|
|
1999
2182
|
success: false,
|
|
2000
2183
|
error: {
|
|
2001
2184
|
code,
|
|
2002
2185
|
message,
|
|
2003
|
-
recoverable
|
|
2186
|
+
recoverable,
|
|
2187
|
+
docs_url: hint?.docs_url,
|
|
2188
|
+
suggestion: hint?.suggestion
|
|
2004
2189
|
}
|
|
2005
2190
|
};
|
|
2006
2191
|
}
|
|
@@ -2041,6 +2226,7 @@ var CimplifyElements = class {
|
|
|
2041
2226
|
this.paymentData = null;
|
|
2042
2227
|
this.checkoutInProgress = false;
|
|
2043
2228
|
this.activeCheckoutAbort = null;
|
|
2229
|
+
this.hasWarnedMissingAuthElement = false;
|
|
2044
2230
|
this.businessIdResolvePromise = null;
|
|
2045
2231
|
this.client = client;
|
|
2046
2232
|
this.businessId = businessId ?? null;
|
|
@@ -2136,6 +2322,12 @@ var CimplifyElements = class {
|
|
|
2136
2322
|
);
|
|
2137
2323
|
}
|
|
2138
2324
|
const authElement = this.elements.get(ELEMENT_TYPES.AUTH);
|
|
2325
|
+
if (!authElement && !this.hasWarnedMissingAuthElement) {
|
|
2326
|
+
this.hasWarnedMissingAuthElement = true;
|
|
2327
|
+
console.warn(
|
|
2328
|
+
"[Cimplify] processCheckout() called without AuthElement mounted. For best conversion and Link enrollment, mount <AuthElement> before checkout."
|
|
2329
|
+
);
|
|
2330
|
+
}
|
|
2139
2331
|
if (authElement && !this.accessToken) {
|
|
2140
2332
|
return toCheckoutError(
|
|
2141
2333
|
"AUTH_INCOMPLETE",
|
|
@@ -2549,69 +2741,4 @@ function createElements(client, businessId, options) {
|
|
|
2549
2741
|
return new CimplifyElements(client, businessId, options);
|
|
2550
2742
|
}
|
|
2551
2743
|
|
|
2552
|
-
// src/query/builder.ts
|
|
2553
|
-
var QueryBuilder = class {
|
|
2554
|
-
constructor(entity) {
|
|
2555
|
-
this.filters = [];
|
|
2556
|
-
this.modifiers = [];
|
|
2557
|
-
this.pathSegments = [];
|
|
2558
|
-
this.entity = entity;
|
|
2559
|
-
}
|
|
2560
|
-
path(segment) {
|
|
2561
|
-
this.pathSegments.push(segment);
|
|
2562
|
-
return this;
|
|
2563
|
-
}
|
|
2564
|
-
where(field, op, value) {
|
|
2565
|
-
const v = typeof value === "string" ? `'${value}'` : value;
|
|
2566
|
-
if (op === "contains" || op === "startsWith") {
|
|
2567
|
-
this.filters.push(`@.${field} ${op} ${v}`);
|
|
2568
|
-
} else {
|
|
2569
|
-
this.filters.push(`@.${field}${op}${v}`);
|
|
2570
|
-
}
|
|
2571
|
-
return this;
|
|
2572
|
-
}
|
|
2573
|
-
and(field, op, value) {
|
|
2574
|
-
return this.where(field, op, value);
|
|
2575
|
-
}
|
|
2576
|
-
sort(field, order = "asc") {
|
|
2577
|
-
this.modifiers.push(`sort(${field},${order})`);
|
|
2578
|
-
return this;
|
|
2579
|
-
}
|
|
2580
|
-
limit(n) {
|
|
2581
|
-
this.modifiers.push(`limit(${n})`);
|
|
2582
|
-
return this;
|
|
2583
|
-
}
|
|
2584
|
-
offset(n) {
|
|
2585
|
-
this.modifiers.push(`offset(${n})`);
|
|
2586
|
-
return this;
|
|
2587
|
-
}
|
|
2588
|
-
count() {
|
|
2589
|
-
this.modifiers.push("count");
|
|
2590
|
-
return this;
|
|
2591
|
-
}
|
|
2592
|
-
enriched() {
|
|
2593
|
-
this.modifiers.push("enriched");
|
|
2594
|
-
return this;
|
|
2595
|
-
}
|
|
2596
|
-
build() {
|
|
2597
|
-
let query2 = this.entity;
|
|
2598
|
-
if (this.pathSegments.length > 0) {
|
|
2599
|
-
query2 += "." + this.pathSegments.join(".");
|
|
2600
|
-
}
|
|
2601
|
-
if (this.filters.length > 0) {
|
|
2602
|
-
query2 += `[?(${this.filters.join(" && ")})]`;
|
|
2603
|
-
}
|
|
2604
|
-
for (const mod of this.modifiers) {
|
|
2605
|
-
query2 += `#${mod}`;
|
|
2606
|
-
}
|
|
2607
|
-
return query2;
|
|
2608
|
-
}
|
|
2609
|
-
toString() {
|
|
2610
|
-
return this.build();
|
|
2611
|
-
}
|
|
2612
|
-
};
|
|
2613
|
-
function query(entity) {
|
|
2614
|
-
return new QueryBuilder(entity);
|
|
2615
|
-
}
|
|
2616
|
-
|
|
2617
2744
|
export { AuthService, BusinessService, CartOperations, CatalogueQueries, CheckoutService as CheckoutOperations, CheckoutService, CimplifyElement, CimplifyElements, ELEMENT_TYPES, EVENT_TYPES, FxService, InventoryService, LinkService, LiteService, MESSAGE_TYPES, OrderQueries, QueryBuilder, SchedulingService, createElements, generateIdempotencyKey, query };
|