@cimplify/sdk 0.6.7 → 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 CHANGED
@@ -142,6 +142,25 @@ if (isOnSale(product)) {
142
142
  }
143
143
  ```
144
144
 
145
+ ### Type-Safe Money
146
+
147
+ All monetary values use the branded `Money` type: string at runtime, distinct from
148
+ plain `string` at compile time.
149
+
150
+ ```typescript
151
+ import { money, type Money } from "@cimplify/sdk";
152
+
153
+ const price = money("29.99");
154
+ const zero = money("0.00");
155
+
156
+ parseFloat(price); // 29.99
157
+ console.log(price); // "29.99"
158
+
159
+ // Compile-time safety:
160
+ // const bad: Money = "29.99"; // Error
161
+ // const bad2: Money = "coffee"; // Error
162
+ ```
163
+
145
164
  ## Error Handling
146
165
 
147
166
  ```typescript
@@ -1,5 +1,5 @@
1
- export { A as AuthService, B as BusinessService, i as CartOperations, b as CatalogueQueries, j as CheckoutOperations, j as CheckoutService, v as CimplifyElement, u as CimplifyElements, x as ELEMENT_TYPES, E as EVENT_TYPES, H as ElementEventType, z as ElementOptions, D as ElementType, y as ElementsOptions, F as FetchQuoteInput, r as FxService, G as GetProductsOptions, I as InventoryService, L as LinkService, q as LiteService, M as MESSAGE_TYPES, O as OrderQueries, P as PriceQuote, d as QuoteBundleSelectionInput, Q as QuoteCompositeSelectionInput, f as QuoteDynamicBuckets, e as QuoteStatus, g as QuoteUiMessage, R as RefreshQuoteInput, h as RefreshQuoteResult, p as SchedulingService, S as SearchOptions, w as createElements, k as generateIdempotencyKey } from './client-B4etj3AD.mjs';
2
- import './payment-pjpfIKX8.mjs';
1
+ export { A as AuthService, B as BusinessService, i as CartOperations, b as CatalogueQueries, j as CheckoutOperations, j as CheckoutService, v as CimplifyElement, u as CimplifyElements, x as ELEMENT_TYPES, E as EVENT_TYPES, H as ElementEventType, z as ElementOptions, D as ElementType, y as ElementsOptions, F as FetchQuoteInput, r as FxService, G as GetProductsOptions, I as InventoryService, L as LinkService, q as LiteService, M as MESSAGE_TYPES, O as OrderQueries, P as PriceQuote, d as QuoteBundleSelectionInput, Q as QuoteCompositeSelectionInput, f as QuoteDynamicBuckets, e as QuoteStatus, g as QuoteUiMessage, R as RefreshQuoteInput, h as RefreshQuoteResult, p as SchedulingService, S as SearchOptions, w as createElements, k as generateIdempotencyKey } from './client-FQUyv41r.mjs';
2
+ import './payment-Cu75tmUc.mjs';
3
3
 
4
4
  type Operator = "==" | "!=" | ">" | "<" | ">=" | "<=" | "contains" | "startsWith";
5
5
  type SortOrder = "asc" | "desc";
@@ -1,5 +1,5 @@
1
- export { A as AuthService, B as BusinessService, i as CartOperations, b as CatalogueQueries, j as CheckoutOperations, j as CheckoutService, v as CimplifyElement, u as CimplifyElements, x as ELEMENT_TYPES, E as EVENT_TYPES, H as ElementEventType, z as ElementOptions, D as ElementType, y as ElementsOptions, F as FetchQuoteInput, r as FxService, G as GetProductsOptions, I as InventoryService, L as LinkService, q as LiteService, M as MESSAGE_TYPES, O as OrderQueries, P as PriceQuote, d as QuoteBundleSelectionInput, Q as QuoteCompositeSelectionInput, f as QuoteDynamicBuckets, e as QuoteStatus, g as QuoteUiMessage, R as RefreshQuoteInput, h as RefreshQuoteResult, p as SchedulingService, S as SearchOptions, w as createElements, k as generateIdempotencyKey } from './client-CYVVuP5J.js';
2
- import './payment-pjpfIKX8.js';
1
+ export { A as AuthService, B as BusinessService, i as CartOperations, b as CatalogueQueries, j as CheckoutOperations, j as CheckoutService, v as CimplifyElement, u as CimplifyElements, x as ELEMENT_TYPES, E as EVENT_TYPES, H as ElementEventType, z as ElementOptions, D as ElementType, y as ElementsOptions, F as FetchQuoteInput, r as FxService, G as GetProductsOptions, I as InventoryService, L as LinkService, q as LiteService, M as MESSAGE_TYPES, O as OrderQueries, P as PriceQuote, d as QuoteBundleSelectionInput, Q as QuoteCompositeSelectionInput, f as QuoteDynamicBuckets, e as QuoteStatus, g as QuoteUiMessage, R as RefreshQuoteInput, h as RefreshQuoteResult, p as SchedulingService, S as SearchOptions, w as createElements, k as generateIdempotencyKey } from './client-D4vA6FY_.js';
2
+ import './payment-Cu75tmUc.js';
3
3
 
4
4
  type Operator = "==" | "!=" | ">" | "<" | ">=" | "<=" | "contains" | "startsWith";
5
5
  type SortOrder = "asc" | "desc";
package/dist/advanced.js CHANGED
@@ -9,6 +9,15 @@ function err(error) {
9
9
  }
10
10
 
11
11
  // src/types/common.ts
12
+ function money(value) {
13
+ return value;
14
+ }
15
+ function moneyFromNumber(value) {
16
+ return value.toFixed(2);
17
+ }
18
+ function currencyCode(value) {
19
+ return value;
20
+ }
12
21
  var ErrorCode = {
13
22
  // General
14
23
  UNKNOWN_ERROR: "UNKNOWN_ERROR"};
@@ -108,6 +117,74 @@ function enrichError(error, options = {}) {
108
117
  return error;
109
118
  }
110
119
 
120
+ // src/query/builder.ts
121
+ function escapeQueryValue(value) {
122
+ return value.replace(/'/g, "\\'");
123
+ }
124
+ var QueryBuilder = class {
125
+ constructor(entity) {
126
+ this.filters = [];
127
+ this.modifiers = [];
128
+ this.pathSegments = [];
129
+ this.entity = entity;
130
+ }
131
+ path(segment) {
132
+ this.pathSegments.push(segment);
133
+ return this;
134
+ }
135
+ where(field, op, value) {
136
+ const v = typeof value === "string" ? `'${escapeQueryValue(value)}'` : value;
137
+ if (op === "contains" || op === "startsWith") {
138
+ this.filters.push(`@.${field} ${op} ${v}`);
139
+ } else {
140
+ this.filters.push(`@.${field}${op}${v}`);
141
+ }
142
+ return this;
143
+ }
144
+ and(field, op, value) {
145
+ return this.where(field, op, value);
146
+ }
147
+ sort(field, order = "asc") {
148
+ this.modifiers.push(`sort(${field},${order})`);
149
+ return this;
150
+ }
151
+ limit(n) {
152
+ this.modifiers.push(`limit(${n})`);
153
+ return this;
154
+ }
155
+ offset(n) {
156
+ this.modifiers.push(`offset(${n})`);
157
+ return this;
158
+ }
159
+ count() {
160
+ this.modifiers.push("count");
161
+ return this;
162
+ }
163
+ enriched() {
164
+ this.modifiers.push("enriched");
165
+ return this;
166
+ }
167
+ build() {
168
+ let query2 = this.entity;
169
+ if (this.pathSegments.length > 0) {
170
+ query2 += "." + this.pathSegments.join(".");
171
+ }
172
+ if (this.filters.length > 0) {
173
+ query2 += `[?(${this.filters.join(" && ")})]`;
174
+ }
175
+ for (const mod of this.modifiers) {
176
+ query2 += `#${mod}`;
177
+ }
178
+ return query2;
179
+ }
180
+ toString() {
181
+ return this.build();
182
+ }
183
+ };
184
+ function query(entity) {
185
+ return new QueryBuilder(entity);
186
+ }
187
+
111
188
  // src/catalogue.ts
112
189
  function toCimplifyError(error) {
113
190
  if (error instanceof CimplifyError) return enrichError(error);
@@ -188,7 +265,7 @@ var CatalogueQueries = class {
188
265
  let query2 = "products";
189
266
  const filters = [];
190
267
  if (options?.category) {
191
- filters.push(`@.category_id=='${options.category}'`);
268
+ filters.push(`@.category_id=='${escapeQueryValue(options.category)}'`);
192
269
  }
193
270
  if (options?.featured !== void 0) {
194
271
  filters.push(`@.featured==${options.featured}`);
@@ -197,7 +274,7 @@ var CatalogueQueries = class {
197
274
  filters.push(`@.in_stock==${options.in_stock}`);
198
275
  }
199
276
  if (options?.search) {
200
- filters.push(`@.name contains '${options.search}'`);
277
+ filters.push(`@.name contains '${escapeQueryValue(options.search)}'`);
201
278
  }
202
279
  if (options?.min_price !== void 0) {
203
280
  filters.push(`@.price>=${options.min_price}`);
@@ -228,7 +305,9 @@ var CatalogueQueries = class {
228
305
  }
229
306
  async getProductBySlug(slug) {
230
307
  const filteredResult = await safe(
231
- this.client.query(`products[?(@.slug=='${slug}')]`)
308
+ this.client.query(
309
+ `products[?(@.slug=='${escapeQueryValue(slug)}')]`
310
+ )
232
311
  );
233
312
  if (!filteredResult.ok) return filteredResult;
234
313
  const exactMatch = findProductBySlug(filteredResult.value, slug);
@@ -280,7 +359,7 @@ var CatalogueQueries = class {
280
359
  }
281
360
  async getCategoryBySlug(slug) {
282
361
  const result = await safe(
283
- this.client.query(`categories[?(@.slug=='${slug}')]`)
362
+ this.client.query(`categories[?(@.slug=='${escapeQueryValue(slug)}')]`)
284
363
  );
285
364
  if (!result.ok) return result;
286
365
  if (!result.value.length) {
@@ -289,7 +368,11 @@ var CatalogueQueries = class {
289
368
  return ok(result.value[0]);
290
369
  }
291
370
  async getCategoryProducts(categoryId) {
292
- return safe(this.client.query(`products[?(@.category_id=='${categoryId}')]`));
371
+ return safe(
372
+ this.client.query(
373
+ `products[?(@.category_id=='${escapeQueryValue(categoryId)}')]`
374
+ )
375
+ );
293
376
  }
294
377
  async getCollections() {
295
378
  return safe(this.client.query("collections"));
@@ -299,7 +382,9 @@ var CatalogueQueries = class {
299
382
  }
300
383
  async getCollectionBySlug(slug) {
301
384
  const result = await safe(
302
- this.client.query(`collections[?(@.slug=='${slug}')]`)
385
+ this.client.query(
386
+ `collections[?(@.slug=='${escapeQueryValue(slug)}')]`
387
+ )
303
388
  );
304
389
  if (!result.ok) return result;
305
390
  if (!result.value.length) {
@@ -312,7 +397,9 @@ var CatalogueQueries = class {
312
397
  }
313
398
  async searchCollections(query2, limit = 20) {
314
399
  return safe(
315
- this.client.query(`collections[?(@.name contains '${query2}')]#limit(${limit})`)
400
+ this.client.query(
401
+ `collections[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
402
+ )
316
403
  );
317
404
  }
318
405
  async getBundles() {
@@ -323,7 +410,9 @@ var CatalogueQueries = class {
323
410
  }
324
411
  async getBundleBySlug(slug) {
325
412
  const result = await safe(
326
- this.client.query(`bundles[?(@.slug=='${slug}')]`)
413
+ this.client.query(
414
+ `bundles[?(@.slug=='${escapeQueryValue(slug)}')]`
415
+ )
327
416
  );
328
417
  if (!result.ok) return result;
329
418
  if (!result.value.length) {
@@ -333,7 +422,9 @@ var CatalogueQueries = class {
333
422
  }
334
423
  async searchBundles(query2, limit = 20) {
335
424
  return safe(
336
- this.client.query(`bundles[?(@.name contains '${query2}')]#limit(${limit})`)
425
+ this.client.query(
426
+ `bundles[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
427
+ )
337
428
  );
338
429
  }
339
430
  async getComposites(options) {
@@ -373,9 +464,9 @@ var CatalogueQueries = class {
373
464
  }
374
465
  async search(query2, options) {
375
466
  const limit = options?.limit ?? 20;
376
- let searchQuery = `products[?(@.name contains '${query2}')]`;
467
+ let searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}')]`;
377
468
  if (options?.category) {
378
- searchQuery = `products[?(@.name contains '${query2}' && @.category_id=='${options.category}')]`;
469
+ searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}' && @.category_id=='${escapeQueryValue(options.category)}')]`;
379
470
  }
380
471
  searchQuery += `#limit(${limit})`;
381
472
  return safe(this.client.query(searchQuery));
@@ -392,7 +483,7 @@ var CatalogueQueries = class {
392
483
  async getMenu(options) {
393
484
  let query2 = "menu";
394
485
  if (options?.category) {
395
- query2 = `menu[?(@.category=='${options.category}')]`;
486
+ query2 = `menu[?(@.category=='${escapeQueryValue(options.category)}')]`;
396
487
  }
397
488
  if (options?.limit) {
398
489
  query2 += `#limit(${options.limit})`;
@@ -673,6 +764,8 @@ function normalizeStatusResponse(response) {
673
764
  }
674
765
  const res = response;
675
766
  const normalizedStatus = normalizePaymentStatusValue(res.status ?? void 0);
767
+ const normalizedAmount = typeof res.amount === "string" ? money(res.amount) : typeof res.amount === "number" && Number.isFinite(res.amount) ? moneyFromNumber(res.amount) : void 0;
768
+ const normalizedCurrency = typeof res.currency === "string" && res.currency.trim().length > 0 ? currencyCode(res.currency) : void 0;
676
769
  const paidValue = res.paid === true;
677
770
  const derivedPaid = paidValue || [
678
771
  "success",
@@ -685,8 +778,8 @@ function normalizeStatusResponse(response) {
685
778
  return {
686
779
  status: normalizedStatus,
687
780
  paid: derivedPaid,
688
- amount: res.amount,
689
- currency: res.currency,
781
+ amount: normalizedAmount,
782
+ currency: normalizedCurrency,
690
783
  reference: res.reference,
691
784
  message: res.message || ""
692
785
  };
@@ -1378,14 +1471,17 @@ var CheckoutService = class {
1378
1471
  pay_currency: data.pay_currency,
1379
1472
  fx_quote_id: data.fx_quote_id
1380
1473
  };
1381
- const baseCurrency = (cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase();
1474
+ const baseCurrency = currencyCode(
1475
+ (cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase()
1476
+ );
1382
1477
  const payCurrency = data.pay_currency?.trim().toUpperCase();
1478
+ const payCurrencyCode = payCurrency ? currencyCode(payCurrency) : void 0;
1383
1479
  const cartTotalAmount = Number.parseFloat(cart.pricing.total_price || "0");
1384
- if (payCurrency && payCurrency !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
1480
+ if (payCurrencyCode && payCurrencyCode !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
1385
1481
  const fxQuoteResult = await this.client.fx.lockQuote({
1386
1482
  from: baseCurrency,
1387
- to: payCurrency,
1388
- amount: cartTotalAmount
1483
+ to: payCurrencyCode,
1484
+ amount: cart.pricing.total_price
1389
1485
  });
1390
1486
  if (!fxQuoteResult.ok) {
1391
1487
  return ok(
@@ -1396,7 +1492,7 @@ var CheckoutService = class {
1396
1492
  )
1397
1493
  );
1398
1494
  }
1399
- checkoutData.pay_currency = payCurrency;
1495
+ checkoutData.pay_currency = payCurrencyCode;
1400
1496
  checkoutData.fx_quote_id = fxQuoteResult.value.id;
1401
1497
  }
1402
1498
  data.on_status_change?.("processing", {});
@@ -2647,71 +2743,6 @@ function createElements(client, businessId, options) {
2647
2743
  return new CimplifyElements(client, businessId, options);
2648
2744
  }
2649
2745
 
2650
- // src/query/builder.ts
2651
- var QueryBuilder = class {
2652
- constructor(entity) {
2653
- this.filters = [];
2654
- this.modifiers = [];
2655
- this.pathSegments = [];
2656
- this.entity = entity;
2657
- }
2658
- path(segment) {
2659
- this.pathSegments.push(segment);
2660
- return this;
2661
- }
2662
- where(field, op, value) {
2663
- const v = typeof value === "string" ? `'${value}'` : value;
2664
- if (op === "contains" || op === "startsWith") {
2665
- this.filters.push(`@.${field} ${op} ${v}`);
2666
- } else {
2667
- this.filters.push(`@.${field}${op}${v}`);
2668
- }
2669
- return this;
2670
- }
2671
- and(field, op, value) {
2672
- return this.where(field, op, value);
2673
- }
2674
- sort(field, order = "asc") {
2675
- this.modifiers.push(`sort(${field},${order})`);
2676
- return this;
2677
- }
2678
- limit(n) {
2679
- this.modifiers.push(`limit(${n})`);
2680
- return this;
2681
- }
2682
- offset(n) {
2683
- this.modifiers.push(`offset(${n})`);
2684
- return this;
2685
- }
2686
- count() {
2687
- this.modifiers.push("count");
2688
- return this;
2689
- }
2690
- enriched() {
2691
- this.modifiers.push("enriched");
2692
- return this;
2693
- }
2694
- build() {
2695
- let query2 = this.entity;
2696
- if (this.pathSegments.length > 0) {
2697
- query2 += "." + this.pathSegments.join(".");
2698
- }
2699
- if (this.filters.length > 0) {
2700
- query2 += `[?(${this.filters.join(" && ")})]`;
2701
- }
2702
- for (const mod of this.modifiers) {
2703
- query2 += `#${mod}`;
2704
- }
2705
- return query2;
2706
- }
2707
- toString() {
2708
- return this.build();
2709
- }
2710
- };
2711
- function query(entity) {
2712
- return new QueryBuilder(entity);
2713
- }
2714
-
2715
2746
  exports.AuthService = AuthService;
2716
2747
  exports.BusinessService = BusinessService;
2717
2748
  exports.CartOperations = CartOperations;
package/dist/advanced.mjs CHANGED
@@ -7,6 +7,15 @@ 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
+ }
10
19
  var ErrorCode = {
11
20
  // General
12
21
  UNKNOWN_ERROR: "UNKNOWN_ERROR"};
@@ -106,6 +115,74 @@ function enrichError(error, options = {}) {
106
115
  return error;
107
116
  }
108
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
+ }
185
+
109
186
  // src/catalogue.ts
110
187
  function toCimplifyError(error) {
111
188
  if (error instanceof CimplifyError) return enrichError(error);
@@ -186,7 +263,7 @@ var CatalogueQueries = class {
186
263
  let query2 = "products";
187
264
  const filters = [];
188
265
  if (options?.category) {
189
- filters.push(`@.category_id=='${options.category}'`);
266
+ filters.push(`@.category_id=='${escapeQueryValue(options.category)}'`);
190
267
  }
191
268
  if (options?.featured !== void 0) {
192
269
  filters.push(`@.featured==${options.featured}`);
@@ -195,7 +272,7 @@ var CatalogueQueries = class {
195
272
  filters.push(`@.in_stock==${options.in_stock}`);
196
273
  }
197
274
  if (options?.search) {
198
- filters.push(`@.name contains '${options.search}'`);
275
+ filters.push(`@.name contains '${escapeQueryValue(options.search)}'`);
199
276
  }
200
277
  if (options?.min_price !== void 0) {
201
278
  filters.push(`@.price>=${options.min_price}`);
@@ -226,7 +303,9 @@ var CatalogueQueries = class {
226
303
  }
227
304
  async getProductBySlug(slug) {
228
305
  const filteredResult = await safe(
229
- this.client.query(`products[?(@.slug=='${slug}')]`)
306
+ this.client.query(
307
+ `products[?(@.slug=='${escapeQueryValue(slug)}')]`
308
+ )
230
309
  );
231
310
  if (!filteredResult.ok) return filteredResult;
232
311
  const exactMatch = findProductBySlug(filteredResult.value, slug);
@@ -278,7 +357,7 @@ var CatalogueQueries = class {
278
357
  }
279
358
  async getCategoryBySlug(slug) {
280
359
  const result = await safe(
281
- this.client.query(`categories[?(@.slug=='${slug}')]`)
360
+ this.client.query(`categories[?(@.slug=='${escapeQueryValue(slug)}')]`)
282
361
  );
283
362
  if (!result.ok) return result;
284
363
  if (!result.value.length) {
@@ -287,7 +366,11 @@ var CatalogueQueries = class {
287
366
  return ok(result.value[0]);
288
367
  }
289
368
  async getCategoryProducts(categoryId) {
290
- return safe(this.client.query(`products[?(@.category_id=='${categoryId}')]`));
369
+ return safe(
370
+ this.client.query(
371
+ `products[?(@.category_id=='${escapeQueryValue(categoryId)}')]`
372
+ )
373
+ );
291
374
  }
292
375
  async getCollections() {
293
376
  return safe(this.client.query("collections"));
@@ -297,7 +380,9 @@ var CatalogueQueries = class {
297
380
  }
298
381
  async getCollectionBySlug(slug) {
299
382
  const result = await safe(
300
- this.client.query(`collections[?(@.slug=='${slug}')]`)
383
+ this.client.query(
384
+ `collections[?(@.slug=='${escapeQueryValue(slug)}')]`
385
+ )
301
386
  );
302
387
  if (!result.ok) return result;
303
388
  if (!result.value.length) {
@@ -310,7 +395,9 @@ var CatalogueQueries = class {
310
395
  }
311
396
  async searchCollections(query2, limit = 20) {
312
397
  return safe(
313
- this.client.query(`collections[?(@.name contains '${query2}')]#limit(${limit})`)
398
+ this.client.query(
399
+ `collections[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
400
+ )
314
401
  );
315
402
  }
316
403
  async getBundles() {
@@ -321,7 +408,9 @@ var CatalogueQueries = class {
321
408
  }
322
409
  async getBundleBySlug(slug) {
323
410
  const result = await safe(
324
- this.client.query(`bundles[?(@.slug=='${slug}')]`)
411
+ this.client.query(
412
+ `bundles[?(@.slug=='${escapeQueryValue(slug)}')]`
413
+ )
325
414
  );
326
415
  if (!result.ok) return result;
327
416
  if (!result.value.length) {
@@ -331,7 +420,9 @@ var CatalogueQueries = class {
331
420
  }
332
421
  async searchBundles(query2, limit = 20) {
333
422
  return safe(
334
- this.client.query(`bundles[?(@.name contains '${query2}')]#limit(${limit})`)
423
+ this.client.query(
424
+ `bundles[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
425
+ )
335
426
  );
336
427
  }
337
428
  async getComposites(options) {
@@ -371,9 +462,9 @@ var CatalogueQueries = class {
371
462
  }
372
463
  async search(query2, options) {
373
464
  const limit = options?.limit ?? 20;
374
- let searchQuery = `products[?(@.name contains '${query2}')]`;
465
+ let searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}')]`;
375
466
  if (options?.category) {
376
- searchQuery = `products[?(@.name contains '${query2}' && @.category_id=='${options.category}')]`;
467
+ searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}' && @.category_id=='${escapeQueryValue(options.category)}')]`;
377
468
  }
378
469
  searchQuery += `#limit(${limit})`;
379
470
  return safe(this.client.query(searchQuery));
@@ -390,7 +481,7 @@ var CatalogueQueries = class {
390
481
  async getMenu(options) {
391
482
  let query2 = "menu";
392
483
  if (options?.category) {
393
- query2 = `menu[?(@.category=='${options.category}')]`;
484
+ query2 = `menu[?(@.category=='${escapeQueryValue(options.category)}')]`;
394
485
  }
395
486
  if (options?.limit) {
396
487
  query2 += `#limit(${options.limit})`;
@@ -671,6 +762,8 @@ function normalizeStatusResponse(response) {
671
762
  }
672
763
  const res = response;
673
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;
674
767
  const paidValue = res.paid === true;
675
768
  const derivedPaid = paidValue || [
676
769
  "success",
@@ -683,8 +776,8 @@ function normalizeStatusResponse(response) {
683
776
  return {
684
777
  status: normalizedStatus,
685
778
  paid: derivedPaid,
686
- amount: res.amount,
687
- currency: res.currency,
779
+ amount: normalizedAmount,
780
+ currency: normalizedCurrency,
688
781
  reference: res.reference,
689
782
  message: res.message || ""
690
783
  };
@@ -1376,14 +1469,17 @@ var CheckoutService = class {
1376
1469
  pay_currency: data.pay_currency,
1377
1470
  fx_quote_id: data.fx_quote_id
1378
1471
  };
1379
- const baseCurrency = (cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase();
1472
+ const baseCurrency = currencyCode(
1473
+ (cart.pricing.currency || checkoutData.pay_currency || "GHS").toUpperCase()
1474
+ );
1380
1475
  const payCurrency = data.pay_currency?.trim().toUpperCase();
1476
+ const payCurrencyCode = payCurrency ? currencyCode(payCurrency) : void 0;
1381
1477
  const cartTotalAmount = Number.parseFloat(cart.pricing.total_price || "0");
1382
- if (payCurrency && payCurrency !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
1478
+ if (payCurrencyCode && payCurrencyCode !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
1383
1479
  const fxQuoteResult = await this.client.fx.lockQuote({
1384
1480
  from: baseCurrency,
1385
- to: payCurrency,
1386
- amount: cartTotalAmount
1481
+ to: payCurrencyCode,
1482
+ amount: cart.pricing.total_price
1387
1483
  });
1388
1484
  if (!fxQuoteResult.ok) {
1389
1485
  return ok(
@@ -1394,7 +1490,7 @@ var CheckoutService = class {
1394
1490
  )
1395
1491
  );
1396
1492
  }
1397
- checkoutData.pay_currency = payCurrency;
1493
+ checkoutData.pay_currency = payCurrencyCode;
1398
1494
  checkoutData.fx_quote_id = fxQuoteResult.value.id;
1399
1495
  }
1400
1496
  data.on_status_change?.("processing", {});
@@ -2645,69 +2741,4 @@ function createElements(client, businessId, options) {
2645
2741
  return new CimplifyElements(client, businessId, options);
2646
2742
  }
2647
2743
 
2648
- // src/query/builder.ts
2649
- var QueryBuilder = class {
2650
- constructor(entity) {
2651
- this.filters = [];
2652
- this.modifiers = [];
2653
- this.pathSegments = [];
2654
- this.entity = entity;
2655
- }
2656
- path(segment) {
2657
- this.pathSegments.push(segment);
2658
- return this;
2659
- }
2660
- where(field, op, value) {
2661
- const v = typeof value === "string" ? `'${value}'` : value;
2662
- if (op === "contains" || op === "startsWith") {
2663
- this.filters.push(`@.${field} ${op} ${v}`);
2664
- } else {
2665
- this.filters.push(`@.${field}${op}${v}`);
2666
- }
2667
- return this;
2668
- }
2669
- and(field, op, value) {
2670
- return this.where(field, op, value);
2671
- }
2672
- sort(field, order = "asc") {
2673
- this.modifiers.push(`sort(${field},${order})`);
2674
- return this;
2675
- }
2676
- limit(n) {
2677
- this.modifiers.push(`limit(${n})`);
2678
- return this;
2679
- }
2680
- offset(n) {
2681
- this.modifiers.push(`offset(${n})`);
2682
- return this;
2683
- }
2684
- count() {
2685
- this.modifiers.push("count");
2686
- return this;
2687
- }
2688
- enriched() {
2689
- this.modifiers.push("enriched");
2690
- return this;
2691
- }
2692
- build() {
2693
- let query2 = this.entity;
2694
- if (this.pathSegments.length > 0) {
2695
- query2 += "." + this.pathSegments.join(".");
2696
- }
2697
- if (this.filters.length > 0) {
2698
- query2 += `[?(${this.filters.join(" && ")})]`;
2699
- }
2700
- for (const mod of this.modifiers) {
2701
- query2 += `#${mod}`;
2702
- }
2703
- return query2;
2704
- }
2705
- toString() {
2706
- return this.build();
2707
- }
2708
- };
2709
- function query(entity) {
2710
- return new QueryBuilder(entity);
2711
- }
2712
-
2713
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 };