@cimplify/sdk 0.6.11 → 0.7.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 CHANGED
@@ -33,6 +33,11 @@ var ErrorCode = {
33
33
  CHECKOUT_VALIDATION_FAILED: "CHECKOUT_VALIDATION_FAILED",
34
34
  DELIVERY_ADDRESS_REQUIRED: "DELIVERY_ADDRESS_REQUIRED",
35
35
  CUSTOMER_INFO_REQUIRED: "CUSTOMER_INFO_REQUIRED",
36
+ // Quote
37
+ QUOTE_NOT_FOUND: "QUOTE_NOT_FOUND",
38
+ QUOTE_EXPIRED: "QUOTE_EXPIRED",
39
+ QUOTE_CONSUMED: "QUOTE_CONSUMED",
40
+ QUOTE_STORAGE_UNAVAILABLE: "QUOTE_STORAGE_UNAVAILABLE",
36
41
  // Payment
37
42
  PAYMENT_FAILED: "PAYMENT_FAILED",
38
43
  PAYMENT_CANCELLED: "PAYMENT_CANCELLED",
@@ -73,6 +78,10 @@ var ERROR_SUGGESTIONS = {
73
78
  CHECKOUT_VALIDATION_FAILED: "Checkout payload failed validation. Verify customer, order type, and address fields are complete.",
74
79
  DELIVERY_ADDRESS_REQUIRED: "Delivery orders require an address. Collect and pass address info before processing checkout.",
75
80
  CUSTOMER_INFO_REQUIRED: "Customer details are required. Ensure name/email/phone are available before checkout.",
81
+ QUOTE_NOT_FOUND: "Quote could not be found. Refresh pricing and create a new quote before checkout.",
82
+ QUOTE_EXPIRED: "Quote has expired. Re-fetch pricing to generate a new quote with a valid expiry window.",
83
+ QUOTE_CONSUMED: "Quote has already been used. Request a fresh quote to prevent duplicate checkout attempts.",
84
+ QUOTE_STORAGE_UNAVAILABLE: "Quote storage is temporarily unavailable. Retry shortly and avoid charging until quote fetch succeeds.",
76
85
  PAYMENT_FAILED: "Payment provider rejected or failed processing. Show retry/change-method options to the shopper.",
77
86
  PAYMENT_CANCELLED: "Payment was cancelled by the shopper or provider flow. Allow a safe retry path.",
78
87
  INSUFFICIENT_FUNDS: "Payment method has insufficient funds. Prompt shopper to use another method.",
@@ -312,6 +321,23 @@ async function safe(promise) {
312
321
  return err(toCimplifyError(error));
313
322
  }
314
323
  }
324
+ async function safeWithFallback(primary, fallback) {
325
+ const primaryResult = await safe(primary());
326
+ if (primaryResult.ok) return primaryResult;
327
+ if (primaryResult.error.code !== "HTTP_404" && primaryResult.error.code !== "API_ERROR") {
328
+ return primaryResult;
329
+ }
330
+ return safe(fallback());
331
+ }
332
+ function withQuery(path, params) {
333
+ const query2 = new URLSearchParams();
334
+ for (const [key, value] of Object.entries(params)) {
335
+ if (value === void 0) continue;
336
+ query2.set(key, String(value));
337
+ }
338
+ const queryString = query2.toString();
339
+ return queryString ? `${path}?${queryString}` : path;
340
+ }
315
341
  function isRecord(value) {
316
342
  return typeof value === "object" && value !== null;
317
343
  }
@@ -369,6 +395,69 @@ function findProductBySlug(products, slug) {
369
395
  return typeof value === "string" && value === slug;
370
396
  });
371
397
  }
398
+ function findCategoryBySlug(categories, slug) {
399
+ return categories.find((category) => {
400
+ const value = category["slug"];
401
+ return typeof value === "string" && value === slug;
402
+ });
403
+ }
404
+ function hasCategorySlug(category) {
405
+ const value = category["slug"];
406
+ return typeof value === "string" && value.trim().length > 0;
407
+ }
408
+ function toFiniteNumber(value) {
409
+ if (typeof value === "number" && Number.isFinite(value)) {
410
+ return value;
411
+ }
412
+ if (typeof value === "string" && value.trim().length > 0) {
413
+ const parsed = Number(value);
414
+ if (Number.isFinite(parsed)) {
415
+ return parsed;
416
+ }
417
+ }
418
+ return void 0;
419
+ }
420
+ function normalizePagination(value) {
421
+ if (!isRecord(value)) {
422
+ return void 0;
423
+ }
424
+ const totalCount = toFiniteNumber(value.total_count);
425
+ const currentPage = toFiniteNumber(value.current_page);
426
+ const pageSize = toFiniteNumber(value.page_size);
427
+ const totalPages = toFiniteNumber(value.total_pages);
428
+ if (totalCount === void 0 || currentPage === void 0 || pageSize === void 0 || totalPages === void 0) {
429
+ return void 0;
430
+ }
431
+ return {
432
+ total_count: totalCount,
433
+ current_page: currentPage,
434
+ page_size: pageSize,
435
+ total_pages: totalPages,
436
+ has_more: value.has_more === true,
437
+ next_cursor: typeof value.next_cursor === "string" ? value.next_cursor : void 0
438
+ };
439
+ }
440
+ function normalizeCatalogueResult(payload) {
441
+ if (Array.isArray(payload)) {
442
+ return {
443
+ items: payload.map((product) => normalizeCatalogueProductPayload(product)),
444
+ is_complete: true
445
+ };
446
+ }
447
+ if (!isRecord(payload)) {
448
+ return {
449
+ items: [],
450
+ is_complete: true
451
+ };
452
+ }
453
+ const rawItems = Array.isArray(payload.products) ? payload.products : Array.isArray(payload.items) ? payload.items : [];
454
+ return {
455
+ items: rawItems.map((product) => normalizeCatalogueProductPayload(product)),
456
+ is_complete: typeof payload.is_complete === "boolean" ? payload.is_complete : true,
457
+ total_available: toFiniteNumber(payload.total_available),
458
+ pagination: normalizePagination(payload.pagination)
459
+ };
460
+ }
372
461
  var CatalogueQueries = class {
373
462
  constructor(client) {
374
463
  this.client = client;
@@ -388,6 +477,13 @@ var CatalogueQueries = class {
388
477
  if (options?.search) {
389
478
  filters.push(`@.name contains '${escapeQueryValue(options.search)}'`);
390
479
  }
480
+ if (options?.tags?.length) {
481
+ for (const tag of options.tags) {
482
+ if (tag.trim().length > 0) {
483
+ filters.push(`@.tags contains '${escapeQueryValue(tag)}'`);
484
+ }
485
+ }
486
+ }
391
487
  if (options?.min_price !== void 0) {
392
488
  filters.push(`@.price>=${options.min_price}`);
393
489
  }
@@ -400,25 +496,57 @@ var CatalogueQueries = class {
400
496
  if (options?.sort_by) {
401
497
  query2 += `#sort(${options.sort_by},${options.sort_order || "asc"})`;
402
498
  }
403
- if (options?.limit) {
499
+ if (options?.limit !== void 0) {
404
500
  query2 += `#limit(${options.limit})`;
405
501
  }
406
- if (options?.offset) {
502
+ if (options?.offset !== void 0) {
407
503
  query2 += `#offset(${options.offset})`;
408
504
  }
409
- const result = await safe(this.client.query(query2));
505
+ const path = withQuery("/api/v1/catalogue/products", {
506
+ category_id: options?.category,
507
+ search: options?.search,
508
+ page: options?.page,
509
+ tags: options?.tags?.join(","),
510
+ featured: options?.featured,
511
+ in_stock: options?.in_stock,
512
+ min_price: options?.min_price,
513
+ max_price: options?.max_price,
514
+ sort_by: options?.sort_by,
515
+ sort_order: options?.sort_order,
516
+ limit: options?.limit,
517
+ offset: options?.offset,
518
+ cursor: options?.cursor
519
+ });
520
+ const result = await safeWithFallback(
521
+ () => this.client.get(path),
522
+ () => this.client.query(query2)
523
+ );
410
524
  if (!result.ok) return result;
411
- return ok(result.value.map((product) => normalizeCatalogueProductPayload(product)));
525
+ return ok(normalizeCatalogueResult(result.value));
412
526
  }
413
527
  async getProduct(id) {
414
- const result = await safe(this.client.query(`products.${id}`));
528
+ const encodedId = encodeURIComponent(id);
529
+ const result = await safeWithFallback(
530
+ () => this.client.get(`/api/v1/catalogue/products/${encodedId}`),
531
+ () => this.client.query(`products.${id}`)
532
+ );
415
533
  if (!result.ok) return result;
416
534
  return ok(normalizeCatalogueProductPayload(result.value));
417
535
  }
418
536
  async getProductBySlug(slug) {
537
+ const encodedSlug = encodeURIComponent(slug);
538
+ const restResult = await safe(
539
+ this.client.get(`/api/v1/catalogue/products/slug/${encodedSlug}`)
540
+ );
541
+ if (restResult.ok) {
542
+ return ok(normalizeCatalogueProductPayload(restResult.value));
543
+ }
544
+ if (restResult.error.code !== "HTTP_404" && restResult.error.code !== "API_ERROR") {
545
+ return restResult;
546
+ }
419
547
  const filteredResult = await safe(
420
548
  this.client.query(
421
- `products[?(@.slug=='${escapeQueryValue(slug)}')]`
549
+ `products[?(@.slug=='${escapeQueryValue(slug)}')]#limit(50)`
422
550
  )
423
551
  );
424
552
  if (!filteredResult.ok) return filteredResult;
@@ -429,7 +557,9 @@ var CatalogueQueries = class {
429
557
  if (filteredResult.value.length === 1) {
430
558
  return ok(normalizeCatalogueProductPayload(filteredResult.value[0]));
431
559
  }
432
- const unfilteredResult = await safe(this.client.query("products"));
560
+ const unfilteredResult = await safe(
561
+ this.client.query("products#limit(200)")
562
+ );
433
563
  if (!unfilteredResult.ok) return unfilteredResult;
434
564
  const fallbackMatch = findProductBySlug(unfilteredResult.value, slug);
435
565
  if (!fallbackMatch) {
@@ -438,18 +568,33 @@ var CatalogueQueries = class {
438
568
  return ok(normalizeCatalogueProductPayload(fallbackMatch));
439
569
  }
440
570
  async getVariants(productId) {
441
- return safe(this.client.query(`products.${productId}.variants`));
571
+ const encodedId = encodeURIComponent(productId);
572
+ return safeWithFallback(
573
+ () => this.client.get(`/api/v1/catalogue/products/${encodedId}/variants`),
574
+ () => this.client.query(`products.${productId}.variants`)
575
+ );
442
576
  }
443
577
  async getVariantAxes(productId) {
444
- return safe(this.client.query(`products.${productId}.variant_axes`));
578
+ const encodedId = encodeURIComponent(productId);
579
+ return safeWithFallback(
580
+ () => this.client.get(`/api/v1/catalogue/products/${encodedId}/variant-axes`),
581
+ () => this.client.query(`products.${productId}.variant_axes`)
582
+ );
445
583
  }
446
584
  /**
447
585
  * Find a variant by axis selections (e.g., { "Size": "Large", "Color": "Red" })
448
586
  * Returns the matching variant or null if no match found.
449
587
  */
450
588
  async getVariantByAxisSelections(productId, selections) {
451
- return safe(
452
- this.client.query(`products.${productId}.variant`, {
589
+ const encodedId = encodeURIComponent(productId);
590
+ return safeWithFallback(
591
+ () => this.client.post(
592
+ `/api/v1/catalogue/products/${encodedId}/variants/find`,
593
+ {
594
+ axis_selections: selections
595
+ }
596
+ ),
597
+ () => this.client.query(`products.${productId}.variant`, {
453
598
  axis_selections: selections
454
599
  })
455
600
  );
@@ -458,45 +603,107 @@ var CatalogueQueries = class {
458
603
  * Get a specific variant by its ID
459
604
  */
460
605
  async getVariantById(productId, variantId) {
461
- return safe(this.client.query(`products.${productId}.variant.${variantId}`));
606
+ const encodedProductId = encodeURIComponent(productId);
607
+ const encodedVariantId = encodeURIComponent(variantId);
608
+ return safeWithFallback(
609
+ () => this.client.get(
610
+ `/api/v1/catalogue/products/${encodedProductId}/variants/${encodedVariantId}`
611
+ ),
612
+ () => this.client.query(`products.${productId}.variant.${variantId}`)
613
+ );
462
614
  }
463
615
  async getAddOns(productId) {
464
- return safe(this.client.query(`products.${productId}.add_ons`));
616
+ const encodedId = encodeURIComponent(productId);
617
+ return safeWithFallback(
618
+ () => this.client.get(`/api/v1/catalogue/products/${encodedId}/add-ons`),
619
+ () => this.client.query(`products.${productId}.add_ons`)
620
+ );
465
621
  }
466
622
  async getCategories() {
467
- return safe(this.client.query("categories"));
623
+ const result = await safeWithFallback(
624
+ () => this.client.get("/api/v1/catalogue/categories"),
625
+ () => this.client.query("categories")
626
+ );
627
+ if (!result.ok) return result;
628
+ if (result.value.some(hasCategorySlug)) {
629
+ return result;
630
+ }
631
+ const catalogueResult = await safe(
632
+ this.client.query("catalogue#limit(1)")
633
+ );
634
+ if (!catalogueResult.ok) {
635
+ return result;
636
+ }
637
+ const fallbackCategories = Array.isArray(catalogueResult.value.categories) ? catalogueResult.value.categories : [];
638
+ return fallbackCategories.length > 0 ? ok(fallbackCategories) : result;
468
639
  }
469
640
  async getCategory(id) {
470
- return safe(this.client.query(`categories.${id}`));
641
+ const encodedId = encodeURIComponent(id);
642
+ return safeWithFallback(
643
+ () => this.client.get(`/api/v1/catalogue/categories/${encodedId}`),
644
+ () => this.client.query(`categories.${id}`)
645
+ );
471
646
  }
472
647
  async getCategoryBySlug(slug) {
648
+ const encodedSlug = encodeURIComponent(slug);
649
+ const restResult = await safe(this.client.get(`/api/v1/catalogue/categories/slug/${encodedSlug}`));
650
+ if (restResult.ok) {
651
+ return restResult;
652
+ }
653
+ if (restResult.error.code !== "HTTP_404" && restResult.error.code !== "API_ERROR") {
654
+ return restResult;
655
+ }
473
656
  const result = await safe(
474
657
  this.client.query(`categories[?(@.slug=='${escapeQueryValue(slug)}')]`)
475
658
  );
476
659
  if (!result.ok) return result;
477
- if (!result.value.length) {
660
+ const exactMatch = findCategoryBySlug(result.value, slug);
661
+ if (exactMatch) {
662
+ return ok(exactMatch);
663
+ }
664
+ const categoriesResult = await this.getCategories();
665
+ if (!categoriesResult.ok) {
666
+ return categoriesResult;
667
+ }
668
+ const fallbackMatch = findCategoryBySlug(categoriesResult.value, slug);
669
+ if (!fallbackMatch) {
478
670
  return err(new CimplifyError("NOT_FOUND", `Category not found: ${slug}`, false));
479
671
  }
480
- return ok(result.value[0]);
672
+ return ok(fallbackMatch);
481
673
  }
482
674
  async getCategoryProducts(categoryId) {
483
- return safe(
484
- this.client.query(
675
+ const encodedId = encodeURIComponent(categoryId);
676
+ return safeWithFallback(
677
+ () => this.client.get(`/api/v1/catalogue/categories/${encodedId}/products`),
678
+ () => this.client.query(
485
679
  `products[?(@.category_id=='${escapeQueryValue(categoryId)}')]`
486
680
  )
487
681
  );
488
682
  }
489
683
  async getCollections() {
490
- return safe(this.client.query("collections"));
684
+ return safeWithFallback(
685
+ () => this.client.get("/api/v1/catalogue/collections"),
686
+ () => this.client.query("collections")
687
+ );
491
688
  }
492
689
  async getCollection(id) {
493
- return safe(this.client.query(`collections.${id}`));
690
+ const encodedId = encodeURIComponent(id);
691
+ return safeWithFallback(
692
+ () => this.client.get(`/api/v1/catalogue/collections/${encodedId}`),
693
+ () => this.client.query(`collections.${id}`)
694
+ );
494
695
  }
495
696
  async getCollectionBySlug(slug) {
697
+ const encodedSlug = encodeURIComponent(slug);
698
+ const restResult = await safe(
699
+ this.client.get(`/api/v1/catalogue/collections/slug/${encodedSlug}`)
700
+ );
701
+ if (restResult.ok) return restResult;
702
+ if (restResult.error.code !== "HTTP_404" && restResult.error.code !== "API_ERROR") {
703
+ return restResult;
704
+ }
496
705
  const result = await safe(
497
- this.client.query(
498
- `collections[?(@.slug=='${escapeQueryValue(slug)}')]`
499
- )
706
+ this.client.query(`collections[?(@.slug=='${escapeQueryValue(slug)}')]`)
500
707
  );
501
708
  if (!result.ok) return result;
502
709
  if (!result.value.length) {
@@ -505,22 +712,43 @@ var CatalogueQueries = class {
505
712
  return ok(result.value[0]);
506
713
  }
507
714
  async getCollectionProducts(collectionId) {
508
- return safe(this.client.query(`collections.${collectionId}.products`));
715
+ const encodedId = encodeURIComponent(collectionId);
716
+ return safeWithFallback(
717
+ () => this.client.get(`/api/v1/catalogue/collections/${encodedId}/products`),
718
+ () => this.client.query(`collections.${collectionId}.products`)
719
+ );
509
720
  }
510
721
  async searchCollections(query2, limit = 20) {
511
- return safe(
512
- this.client.query(
722
+ const path = withQuery("/api/v1/catalogue/collections", { search: query2, limit });
723
+ return safeWithFallback(
724
+ () => this.client.get(path),
725
+ () => this.client.query(
513
726
  `collections[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
514
727
  )
515
728
  );
516
729
  }
517
730
  async getBundles() {
518
- return safe(this.client.query("bundles"));
731
+ return safeWithFallback(
732
+ () => this.client.get("/api/v1/catalogue/bundles"),
733
+ () => this.client.query("bundles")
734
+ );
519
735
  }
520
736
  async getBundle(id) {
521
- return safe(this.client.query(`bundles.${id}`));
737
+ const encodedId = encodeURIComponent(id);
738
+ return safeWithFallback(
739
+ () => this.client.get(`/api/v1/catalogue/bundles/${encodedId}`),
740
+ () => this.client.query(`bundles.${id}`)
741
+ );
522
742
  }
523
743
  async getBundleBySlug(slug) {
744
+ const encodedSlug = encodeURIComponent(slug);
745
+ const restResult = await safe(
746
+ this.client.get(`/api/v1/catalogue/bundles/slug/${encodedSlug}`)
747
+ );
748
+ if (restResult.ok) return restResult;
749
+ if (restResult.error.code !== "HTTP_404" && restResult.error.code !== "API_ERROR") {
750
+ return restResult;
751
+ }
524
752
  const result = await safe(
525
753
  this.client.query(
526
754
  `bundles[?(@.slug=='${escapeQueryValue(slug)}')]`
@@ -533,8 +761,10 @@ var CatalogueQueries = class {
533
761
  return ok(result.value[0]);
534
762
  }
535
763
  async searchBundles(query2, limit = 20) {
536
- return safe(
537
- this.client.query(
764
+ const path = withQuery("/api/v1/catalogue/bundles", { search: query2, limit });
765
+ return safeWithFallback(
766
+ () => this.client.get(path),
767
+ () => this.client.query(
538
768
  `bundles[?(@.name contains '${escapeQueryValue(query2)}')]#limit(${limit})`
539
769
  )
540
770
  );
@@ -544,17 +774,39 @@ var CatalogueQueries = class {
544
774
  if (options?.limit) {
545
775
  query2 += `#limit(${options.limit})`;
546
776
  }
547
- return safe(this.client.query(query2));
777
+ const path = withQuery("/api/v1/catalogue/composites", { limit: options?.limit });
778
+ return safeWithFallback(
779
+ () => this.client.get(path),
780
+ () => this.client.query(query2)
781
+ );
548
782
  }
549
783
  async getComposite(id) {
550
- return safe(this.client.query(`composites.${id}`));
784
+ const encodedId = encodeURIComponent(id);
785
+ return safeWithFallback(
786
+ () => this.client.get(`/api/v1/catalogue/composites/${encodedId}`),
787
+ () => this.client.query(`composites.${id}`)
788
+ );
551
789
  }
552
790
  async getCompositeByProductId(productId) {
553
- return safe(this.client.query(`composites.by_product.${productId}`));
791
+ const encodedId = encodeURIComponent(productId);
792
+ return safeWithFallback(
793
+ () => this.client.get(
794
+ `/api/v1/catalogue/composites/by-product/${encodedId}`
795
+ ),
796
+ () => this.client.query(`composites.by_product.${productId}`)
797
+ );
554
798
  }
555
799
  async calculateCompositePrice(compositeId, selections, locationId) {
556
- return safe(
557
- this.client.call("composite.calculatePrice", {
800
+ const encodedId = encodeURIComponent(compositeId);
801
+ return safeWithFallback(
802
+ () => this.client.post(
803
+ `/api/v1/catalogue/composites/${encodedId}/calculate-price`,
804
+ {
805
+ selections,
806
+ location_id: locationId
807
+ }
808
+ ),
809
+ () => this.client.call("composite.calculatePrice", {
558
810
  composite_id: compositeId,
559
811
  selections,
560
812
  location_id: locationId
@@ -562,35 +814,41 @@ var CatalogueQueries = class {
562
814
  );
563
815
  }
564
816
  async fetchQuote(input) {
565
- return safe(this.client.call("catalogue.createQuote", input));
817
+ return safeWithFallback(
818
+ () => this.client.post("/api/v1/catalogue/quotes", input),
819
+ () => this.client.call("catalogue.createQuote", input)
820
+ );
566
821
  }
567
822
  async getQuote(quoteId) {
568
- return safe(
569
- this.client.call("catalogue.getQuote", {
823
+ const encodedQuoteId = encodeURIComponent(quoteId);
824
+ return safeWithFallback(
825
+ () => this.client.get(`/api/v1/catalogue/quotes/${encodedQuoteId}`),
826
+ () => this.client.call("catalogue.getQuote", {
570
827
  quote_id: quoteId
571
828
  })
572
829
  );
573
830
  }
574
831
  async refreshQuote(input) {
575
- return safe(this.client.call("catalogue.refreshQuote", input));
832
+ const encodedQuoteId = encodeURIComponent(input.quote_id);
833
+ return safeWithFallback(
834
+ () => this.client.post(
835
+ `/api/v1/catalogue/quotes/${encodedQuoteId}/refresh`,
836
+ input
837
+ ),
838
+ () => this.client.call("catalogue.refreshQuote", input)
839
+ );
576
840
  }
577
841
  async search(query2, options) {
578
- const limit = options?.limit ?? 20;
579
- let searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}')]`;
580
- if (options?.category) {
581
- searchQuery = `products[?(@.name contains '${escapeQueryValue(query2)}' && @.category_id=='${escapeQueryValue(options.category)}')]`;
582
- }
583
- searchQuery += `#limit(${limit})`;
584
- return safe(this.client.query(searchQuery));
842
+ const result = await this.getProducts({
843
+ search: query2,
844
+ category: options?.category,
845
+ limit: options?.limit ?? 20
846
+ });
847
+ if (!result.ok) return result;
848
+ return ok(result.value.items);
585
849
  }
586
850
  async searchProducts(query2, options) {
587
- return safe(
588
- this.client.call("catalogue.search", {
589
- query: query2,
590
- limit: options?.limit ?? 20,
591
- category: options?.category
592
- })
593
- );
851
+ return this.search(query2, options);
594
852
  }
595
853
  async getMenu(options) {
596
854
  let query2 = "menu";
@@ -600,13 +858,28 @@ var CatalogueQueries = class {
600
858
  if (options?.limit) {
601
859
  query2 += `#limit(${options.limit})`;
602
860
  }
603
- return safe(this.client.query(query2));
861
+ const path = withQuery("/api/v1/catalogue/menu", {
862
+ category_id: options?.category,
863
+ limit: options?.limit
864
+ });
865
+ return safeWithFallback(
866
+ () => this.client.get(path),
867
+ () => this.client.query(query2)
868
+ );
604
869
  }
605
870
  async getMenuCategory(categoryId) {
606
- return safe(this.client.query(`menu.category.${categoryId}`));
871
+ const encodedId = encodeURIComponent(categoryId);
872
+ return safeWithFallback(
873
+ () => this.client.get(`/api/v1/catalogue/menu/categories/${encodedId}`),
874
+ () => this.client.query(`menu.category.${categoryId}`)
875
+ );
607
876
  }
608
877
  async getMenuItem(itemId) {
609
- return safe(this.client.query(`menu.${itemId}`));
878
+ const encodedId = encodeURIComponent(itemId);
879
+ return safeWithFallback(
880
+ () => this.client.get(`/api/v1/catalogue/menu/items/${encodedId}`),
881
+ () => this.client.query(`menu.${itemId}`)
882
+ );
610
883
  }
611
884
  };
612
885
 
@@ -625,6 +898,14 @@ async function safe2(promise) {
625
898
  return err(toCimplifyError2(error));
626
899
  }
627
900
  }
901
+ async function safeWithFallback2(primary, fallback) {
902
+ const primaryResult = await safe2(primary());
903
+ if (primaryResult.ok) return primaryResult;
904
+ if (primaryResult.error.code !== "HTTP_404" && primaryResult.error.code !== "API_ERROR") {
905
+ return primaryResult;
906
+ }
907
+ return safe2(fallback());
908
+ }
628
909
  function isUICartResponse(value) {
629
910
  return "cart" in value;
630
911
  }
@@ -636,21 +917,36 @@ var CartOperations = class {
636
917
  this.client = client;
637
918
  }
638
919
  async get() {
639
- const result = await safe2(this.client.query("cart#enriched"));
920
+ const result = await safeWithFallback2(
921
+ () => this.client.get("/api/v1/cart"),
922
+ () => this.client.query("cart#enriched")
923
+ );
640
924
  if (!result.ok) return result;
641
925
  return ok(unwrapEnrichedCart(result.value));
642
926
  }
643
927
  async getRaw() {
644
- return safe2(this.client.query("cart"));
928
+ return safeWithFallback2(
929
+ () => this.client.get("/api/v1/cart"),
930
+ () => this.client.query("cart")
931
+ );
645
932
  }
646
933
  async getItems() {
647
- return safe2(this.client.query("cart_items"));
934
+ return safeWithFallback2(
935
+ () => this.client.get("/api/v1/cart/items"),
936
+ () => this.client.query("cart_items")
937
+ );
648
938
  }
649
939
  async getCount() {
650
- return safe2(this.client.query("cart#count"));
940
+ return safeWithFallback2(
941
+ () => this.client.get("/api/v1/cart/count"),
942
+ () => this.client.query("cart#count")
943
+ );
651
944
  }
652
945
  async getTotal() {
653
- return safe2(this.client.query("cart#total"));
946
+ return safeWithFallback2(
947
+ () => this.client.get("/api/v1/cart/total"),
948
+ () => this.client.query("cart#total")
949
+ );
654
950
  }
655
951
  async getSummary() {
656
952
  const cartResult = await this.get();
@@ -667,43 +963,66 @@ var CartOperations = class {
667
963
  });
668
964
  }
669
965
  async addItem(input) {
670
- return safe2(this.client.call("cart.addItem", input));
966
+ return safeWithFallback2(
967
+ () => this.client.post("/api/v1/cart/items", input),
968
+ () => this.client.call("cart.addItem", input)
969
+ );
671
970
  }
672
971
  async updateItem(cartItemId, updates) {
673
- return safe2(
674
- this.client.call("cart.updateItem", {
972
+ if (typeof updates.quantity === "number") {
973
+ return this.updateQuantity(cartItemId, updates.quantity);
974
+ }
975
+ const encodedId = encodeURIComponent(cartItemId);
976
+ return safeWithFallback2(
977
+ () => this.client.patch(`/api/v1/cart/items/${encodedId}`, updates),
978
+ () => this.client.call("cart.updateItem", {
675
979
  cart_item_id: cartItemId,
676
980
  ...updates
677
981
  })
678
982
  );
679
983
  }
680
984
  async updateQuantity(cartItemId, quantity) {
681
- return safe2(
682
- this.client.call("cart.updateItemQuantity", {
985
+ const encodedId = encodeURIComponent(cartItemId);
986
+ return safeWithFallback2(
987
+ () => this.client.patch(`/api/v1/cart/items/${encodedId}`, {
988
+ quantity
989
+ }),
990
+ () => this.client.call("cart.updateItemQuantity", {
683
991
  cart_item_id: cartItemId,
684
992
  quantity
685
993
  })
686
994
  );
687
995
  }
688
996
  async removeItem(cartItemId) {
689
- return safe2(
690
- this.client.call("cart.removeItem", {
997
+ const encodedId = encodeURIComponent(cartItemId);
998
+ return safeWithFallback2(
999
+ () => this.client.delete(`/api/v1/cart/items/${encodedId}`),
1000
+ () => this.client.call("cart.removeItem", {
691
1001
  cart_item_id: cartItemId
692
1002
  })
693
1003
  );
694
1004
  }
695
1005
  async clear() {
696
- return safe2(this.client.call("cart.clearCart"));
1006
+ return safeWithFallback2(
1007
+ () => this.client.delete("/api/v1/cart"),
1008
+ () => this.client.call("cart.clearCart")
1009
+ );
697
1010
  }
698
1011
  async applyCoupon(code) {
699
- return safe2(
700
- this.client.call("cart.applyCoupon", {
1012
+ return safeWithFallback2(
1013
+ () => this.client.post("/api/v1/cart/coupons", {
1014
+ coupon_code: code
1015
+ }),
1016
+ () => this.client.call("cart.applyCoupon", {
701
1017
  coupon_code: code
702
1018
  })
703
1019
  );
704
1020
  }
705
1021
  async removeCoupon() {
706
- return safe2(this.client.call("cart.removeCoupon"));
1022
+ return safeWithFallback2(
1023
+ () => this.client.delete("/api/v1/cart/coupons/current"),
1024
+ () => this.client.call("cart.removeCoupon")
1025
+ );
707
1026
  }
708
1027
  async isEmpty() {
709
1028
  const countResult = await this.getCount();
@@ -984,6 +1303,25 @@ function parsePrice(value) {
984
1303
  const parsed = parseFloat(cleaned);
985
1304
  return isNaN(parsed) ? 0 : parsed;
986
1305
  }
1306
+ function hasTaxInfo(priceInfo) {
1307
+ return priceInfo.tax_info !== void 0 && priceInfo.tax_info !== null;
1308
+ }
1309
+ function getTaxAmount(priceInfo) {
1310
+ return parsePrice(priceInfo.tax_info?.tax_amount);
1311
+ }
1312
+ function isTaxInclusive(priceInfo) {
1313
+ return priceInfo.tax_info?.is_inclusive === true;
1314
+ }
1315
+ function formatPriceWithTax(priceInfo, currency = "GHS") {
1316
+ const finalPrice = formatPrice(priceInfo.final_price, currency);
1317
+ if (!hasTaxInfo(priceInfo)) {
1318
+ return finalPrice;
1319
+ }
1320
+ if (isTaxInclusive(priceInfo)) {
1321
+ return `${finalPrice} (incl. tax)`;
1322
+ }
1323
+ return `${finalPrice} + ${formatPrice(getTaxAmount(priceInfo), currency)} tax`;
1324
+ }
987
1325
  function getDisplayPrice(product) {
988
1326
  if (product.price_info) {
989
1327
  return parsePrice(product.price_info.final_price);
@@ -1846,6 +2184,14 @@ async function safe3(promise) {
1846
2184
  return err(toCimplifyError3(error));
1847
2185
  }
1848
2186
  }
2187
+ async function safeWithFallback3(primary, fallback) {
2188
+ const primaryResult = await safe3(primary());
2189
+ if (primaryResult.ok) return primaryResult;
2190
+ if (primaryResult.error.code !== "HTTP_404" && primaryResult.error.code !== "API_ERROR") {
2191
+ return primaryResult;
2192
+ }
2193
+ return safe3(fallback());
2194
+ }
1849
2195
  function toTerminalFailure(code, message, recoverable) {
1850
2196
  return {
1851
2197
  success: false,
@@ -1873,8 +2219,11 @@ var CheckoutService = class {
1873
2219
  ...data,
1874
2220
  idempotency_key: data.idempotency_key || generateIdempotencyKey()
1875
2221
  };
1876
- return safe3(
1877
- this.client.call(CHECKOUT_MUTATION.PROCESS, {
2222
+ return safeWithFallback3(
2223
+ () => this.client.post("/api/v1/checkout", {
2224
+ checkout_data: checkoutData
2225
+ }),
2226
+ () => this.client.call(CHECKOUT_MUTATION.PROCESS, {
1878
2227
  checkout_data: checkoutData
1879
2228
  })
1880
2229
  );
@@ -1888,18 +2237,23 @@ var CheckoutService = class {
1888
2237
  );
1889
2238
  }
1890
2239
  async submitAuthorization(input) {
1891
- return safe3(
1892
- this.client.call(PAYMENT_MUTATION.SUBMIT_AUTHORIZATION, input)
2240
+ return safeWithFallback3(
2241
+ () => this.client.post("/api/v1/payments/authorization", input),
2242
+ () => this.client.call(PAYMENT_MUTATION.SUBMIT_AUTHORIZATION, input)
1893
2243
  );
1894
2244
  }
1895
2245
  async pollPaymentStatus(orderId) {
1896
- return safe3(
1897
- this.client.call(PAYMENT_MUTATION.CHECK_STATUS, orderId)
2246
+ const encodedId = encodeURIComponent(orderId);
2247
+ return safeWithFallback3(
2248
+ () => this.client.get(`/api/v1/orders/${encodedId}/payment-status`),
2249
+ () => this.client.call(PAYMENT_MUTATION.CHECK_STATUS, orderId)
1898
2250
  );
1899
2251
  }
1900
2252
  async updateOrderCustomer(orderId, customer) {
1901
- return safe3(
1902
- this.client.call(ORDER_MUTATION.UPDATE_CUSTOMER, {
2253
+ const encodedId = encodeURIComponent(orderId);
2254
+ return safeWithFallback3(
2255
+ () => this.client.post(`/api/v1/orders/${encodedId}/customer`, customer),
2256
+ () => this.client.call(ORDER_MUTATION.UPDATE_CUSTOMER, {
1903
2257
  order_id: orderId,
1904
2258
  ...customer
1905
2259
  })
@@ -2029,6 +2383,14 @@ async function safe4(promise) {
2029
2383
  return err(toCimplifyError4(error));
2030
2384
  }
2031
2385
  }
2386
+ async function safeWithFallback4(primary, fallback) {
2387
+ const primaryResult = await safe4(primary());
2388
+ if (primaryResult.ok) return primaryResult;
2389
+ if (primaryResult.error.code !== "HTTP_404" && primaryResult.error.code !== "API_ERROR") {
2390
+ return primaryResult;
2391
+ }
2392
+ return safe4(fallback());
2393
+ }
2032
2394
  var OrderQueries = class {
2033
2395
  constructor(client) {
2034
2396
  this.client = client;
@@ -2045,20 +2407,36 @@ var OrderQueries = class {
2045
2407
  if (options?.offset) {
2046
2408
  query2 += `#offset(${options.offset})`;
2047
2409
  }
2048
- return safe4(this.client.query(query2));
2410
+ const params = new URLSearchParams();
2411
+ if (options?.status) params.set("status", options.status);
2412
+ if (options?.limit) params.set("limit", String(options.limit));
2413
+ if (options?.offset) params.set("offset", String(options.offset));
2414
+ const path = params.toString() ? `/api/v1/orders?${params.toString()}` : "/api/v1/orders";
2415
+ return safeWithFallback4(
2416
+ () => this.client.get(path),
2417
+ () => this.client.query(query2)
2418
+ );
2049
2419
  }
2050
2420
  async get(orderId) {
2051
- return safe4(this.client.query(`orders.${orderId}`));
2421
+ const encodedId = encodeURIComponent(orderId);
2422
+ return safeWithFallback4(
2423
+ () => this.client.get(`/api/v1/orders/${encodedId}`),
2424
+ () => this.client.query(`orders.${orderId}`)
2425
+ );
2052
2426
  }
2053
2427
  async getRecent(limit = 5) {
2054
2428
  return safe4(this.client.query(`orders#sort(created_at,desc)#limit(${limit})`));
2055
2429
  }
2056
2430
  async getByStatus(status) {
2057
- return safe4(this.client.query(`orders[?(@.status=='${status}')]`));
2431
+ return this.list({ status });
2058
2432
  }
2059
2433
  async cancel(orderId, reason) {
2060
- return safe4(
2061
- this.client.call("order.cancelOrder", {
2434
+ const encodedId = encodeURIComponent(orderId);
2435
+ return safeWithFallback4(
2436
+ () => this.client.post(`/api/v1/orders/${encodedId}/cancel`, {
2437
+ reason
2438
+ }),
2439
+ () => this.client.call("order.cancelOrder", {
2062
2440
  order_id: orderId,
2063
2441
  reason
2064
2442
  })
@@ -2233,12 +2611,23 @@ async function safe6(promise) {
2233
2611
  return err(toCimplifyError6(error));
2234
2612
  }
2235
2613
  }
2614
+ async function safeWithFallback5(primary, fallback) {
2615
+ const primaryResult = await safe6(primary());
2616
+ if (primaryResult.ok) return primaryResult;
2617
+ if (primaryResult.error.code !== "HTTP_404" && primaryResult.error.code !== "API_ERROR") {
2618
+ return primaryResult;
2619
+ }
2620
+ return safe6(fallback());
2621
+ }
2236
2622
  var AuthService = class {
2237
2623
  constructor(client) {
2238
2624
  this.client = client;
2239
2625
  }
2240
2626
  async getStatus() {
2241
- return safe6(this.client.query("auth"));
2627
+ return safeWithFallback5(
2628
+ () => this.client.get("/api/v1/auth/status"),
2629
+ () => this.client.query("auth")
2630
+ );
2242
2631
  }
2243
2632
  async getCurrentUser() {
2244
2633
  const result = await this.getStatus();
@@ -2251,23 +2640,34 @@ var AuthService = class {
2251
2640
  return ok(result.value.is_authenticated);
2252
2641
  }
2253
2642
  async requestOtp(contact, contactType) {
2254
- return safe6(
2255
- this.client.call(AUTH_MUTATION.REQUEST_OTP, {
2643
+ return safeWithFallback5(
2644
+ () => this.client.post("/api/v1/auth/request-otp", {
2645
+ contact,
2646
+ contact_type: contactType
2647
+ }),
2648
+ () => this.client.call(AUTH_MUTATION.REQUEST_OTP, {
2256
2649
  contact,
2257
2650
  contact_type: contactType
2258
2651
  })
2259
2652
  );
2260
2653
  }
2261
2654
  async verifyOtp(code, contact) {
2262
- return safe6(
2263
- this.client.call(AUTH_MUTATION.VERIFY_OTP, {
2655
+ return safeWithFallback5(
2656
+ () => this.client.post("/api/v1/auth/verify-otp", {
2657
+ otp_code: code,
2658
+ contact
2659
+ }),
2660
+ () => this.client.call(AUTH_MUTATION.VERIFY_OTP, {
2264
2661
  otp_code: code,
2265
2662
  contact
2266
2663
  })
2267
2664
  );
2268
2665
  }
2269
2666
  async logout() {
2270
- return safe6(this.client.call("auth.logout"));
2667
+ return safeWithFallback5(
2668
+ () => this.client.post("/api/v1/auth/logout"),
2669
+ () => this.client.call("auth.logout")
2670
+ );
2271
2671
  }
2272
2672
  async updateProfile(input) {
2273
2673
  return safe6(this.client.call("auth.update_profile", input));
@@ -2295,12 +2695,23 @@ async function safe7(promise) {
2295
2695
  return err(toCimplifyError7(error));
2296
2696
  }
2297
2697
  }
2698
+ async function safeWithFallback6(primary, fallback) {
2699
+ const primaryResult = await safe7(primary());
2700
+ if (primaryResult.ok) return primaryResult;
2701
+ if (primaryResult.error.code !== "HTTP_404" && primaryResult.error.code !== "API_ERROR") {
2702
+ return primaryResult;
2703
+ }
2704
+ return safe7(fallback());
2705
+ }
2298
2706
  var BusinessService = class {
2299
2707
  constructor(client) {
2300
2708
  this.client = client;
2301
2709
  }
2302
2710
  async getInfo() {
2303
- return safe7(this.client.query("business.info"));
2711
+ return safeWithFallback6(
2712
+ () => this.client.get("/api/v1/business"),
2713
+ () => this.client.query("business.info")
2714
+ );
2304
2715
  }
2305
2716
  async getByHandle(handle) {
2306
2717
  return safe7(this.client.query(`business.handle.${handle}`));
@@ -2309,24 +2720,48 @@ var BusinessService = class {
2309
2720
  return safe7(this.client.query("business.domain", { domain }));
2310
2721
  }
2311
2722
  async getSettings() {
2312
- return safe7(this.client.query("business.settings"));
2723
+ return safeWithFallback6(
2724
+ () => this.client.get("/api/v1/business/settings"),
2725
+ () => this.client.query("business.settings")
2726
+ );
2313
2727
  }
2314
2728
  async getTheme() {
2315
- return safe7(this.client.query("business.theme"));
2729
+ return safeWithFallback6(
2730
+ () => this.client.get("/api/v1/business/theme"),
2731
+ () => this.client.query("business.theme")
2732
+ );
2316
2733
  }
2317
2734
  async getLocations() {
2318
- return safe7(this.client.query("business.locations"));
2735
+ return safeWithFallback6(
2736
+ () => this.client.get("/api/v1/business/locations"),
2737
+ () => this.client.query("business.locations")
2738
+ );
2319
2739
  }
2320
2740
  async getLocation(locationId) {
2321
- return safe7(this.client.query(`business.locations.${locationId}`));
2741
+ const result = await this.getLocations();
2742
+ if (!result.ok) return err(result.error);
2743
+ const location = result.value.find((item) => item.id === locationId);
2744
+ if (!location) {
2745
+ return err(new CimplifyError(ErrorCode.NOT_FOUND, `Location not found: ${locationId}`, false));
2746
+ }
2747
+ return ok(location);
2322
2748
  }
2323
2749
  async getHours() {
2324
- return safe7(this.client.query("business.hours"));
2750
+ return safeWithFallback6(
2751
+ () => this.client.get("/api/v1/business/hours"),
2752
+ () => this.client.query("business.hours")
2753
+ );
2325
2754
  }
2326
2755
  async getLocationHours(locationId) {
2327
- return safe7(this.client.query(`business.locations.${locationId}.hours`));
2756
+ const result = await this.getHours();
2757
+ if (!result.ok) return result;
2758
+ return ok(result.value.filter((hour) => hour.location_id === locationId));
2328
2759
  }
2329
2760
  async getBootstrap() {
2761
+ const restBootstrap = await safe7(this.client.get("/api/v1/bootstrap"));
2762
+ if (restBootstrap.ok) {
2763
+ return restBootstrap;
2764
+ }
2330
2765
  const [businessResult, locationsResult, categoriesResult] = await Promise.all([
2331
2766
  this.getInfo(),
2332
2767
  this.getLocations(),
@@ -2619,15 +3054,30 @@ async function safe11(promise) {
2619
3054
  return err(toCimplifyError11(error));
2620
3055
  }
2621
3056
  }
3057
+ async function safeWithFallback7(primary, fallback) {
3058
+ const primaryResult = await safe11(primary());
3059
+ if (primaryResult.ok) return primaryResult;
3060
+ if (primaryResult.error.code !== "HTTP_404" && primaryResult.error.code !== "API_ERROR") {
3061
+ return primaryResult;
3062
+ }
3063
+ return safe11(fallback());
3064
+ }
2622
3065
  var FxService = class {
2623
3066
  constructor(client) {
2624
3067
  this.client = client;
2625
3068
  }
2626
3069
  async getRate(from, to) {
2627
- return safe11(this.client.call("fx.getRate", { from, to }));
3070
+ const path = `/api/v1/fx/rate?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`;
3071
+ return safeWithFallback7(
3072
+ () => this.client.get(path),
3073
+ () => this.client.call("fx.getRate", { from, to })
3074
+ );
2628
3075
  }
2629
3076
  async lockQuote(request) {
2630
- return safe11(this.client.call("fx.lockQuote", request));
3077
+ return safeWithFallback7(
3078
+ () => this.client.post("/api/v1/fx/quotes", request),
3079
+ () => this.client.call("fx.lockQuote", request)
3080
+ );
2631
3081
  }
2632
3082
  };
2633
3083
 
@@ -3635,6 +4085,15 @@ var CimplifyClient = class {
3635
4085
  });
3636
4086
  return this.handleRestResponse(response);
3637
4087
  }
4088
+ async patch(path, body) {
4089
+ const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
4090
+ method: "PATCH",
4091
+ credentials: this.credentials,
4092
+ headers: this.getHeaders(),
4093
+ body: body ? JSON.stringify(body) : void 0
4094
+ });
4095
+ return this.handleRestResponse(response);
4096
+ }
3638
4097
  async delete(path) {
3639
4098
  const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
3640
4099
  method: "DELETE",
@@ -3674,11 +4133,14 @@ var CimplifyClient = class {
3674
4133
  async handleRestResponse(response) {
3675
4134
  const json = await response.json();
3676
4135
  if (!response.ok) {
4136
+ const errorCode = typeof json.error === "object" && json.error?.error_code || typeof json.error === "object" && json.error?.code || "API_ERROR";
4137
+ const errorMessage = typeof json.error === "object" && json.error?.error_message || typeof json.error === "object" && json.error?.message || typeof json.error === "string" && json.error || typeof json.message === "string" && json.message || "An error occurred";
4138
+ const retryable = typeof json.error === "object" && typeof json.error?.retryable === "boolean" ? json.error.retryable : false;
3677
4139
  const error = enrichError(
3678
4140
  new CimplifyError(
3679
- json.error?.error_code || "API_ERROR",
3680
- json.error?.error_message || "An error occurred",
3681
- false
4141
+ errorCode,
4142
+ errorMessage,
4143
+ retryable
3682
4144
  ),
3683
4145
  { isTestMode: this.isTestMode() }
3684
4146
  );
@@ -3689,7 +4151,21 @@ var CimplifyClient = class {
3689
4151
  }
3690
4152
  throw error;
3691
4153
  }
3692
- return json.data;
4154
+ if (json?.success === false || json?.error?.code || json?.error?.message) {
4155
+ const error = enrichError(
4156
+ new CimplifyError(
4157
+ json.error?.code || "API_ERROR",
4158
+ json.error?.message || "An error occurred",
4159
+ json.error?.retryable || false
4160
+ ),
4161
+ { isTestMode: this.isTestMode() }
4162
+ );
4163
+ throw error;
4164
+ }
4165
+ if (json?.data !== void 0) {
4166
+ return json.data;
4167
+ }
4168
+ return json;
3693
4169
  }
3694
4170
  async handleResponse(response) {
3695
4171
  const json = await response.json();
@@ -3860,6 +4336,7 @@ exports.formatNumberCompact = formatNumberCompact;
3860
4336
  exports.formatPrice = formatPrice;
3861
4337
  exports.formatPriceAdjustment = formatPriceAdjustment;
3862
4338
  exports.formatPriceCompact = formatPriceCompact;
4339
+ exports.formatPriceWithTax = formatPriceWithTax;
3863
4340
  exports.formatProductPrice = formatProductPrice;
3864
4341
  exports.fromPromise = fromPromise;
3865
4342
  exports.generateIdempotencyKey = generateIdempotencyKey;
@@ -3871,6 +4348,8 @@ exports.getErrorHint = getErrorHint;
3871
4348
  exports.getMarkupPercentage = getMarkupPercentage;
3872
4349
  exports.getOrElse = getOrElse;
3873
4350
  exports.getProductCurrency = getProductCurrency;
4351
+ exports.getTaxAmount = getTaxAmount;
4352
+ exports.hasTaxInfo = hasTaxInfo;
3874
4353
  exports.isCimplifyError = isCimplifyError;
3875
4354
  exports.isErr = isErr;
3876
4355
  exports.isOk = isOk;
@@ -3879,6 +4358,7 @@ exports.isPaymentStatusFailure = isPaymentStatusFailure;
3879
4358
  exports.isPaymentStatusRequiresAction = isPaymentStatusRequiresAction;
3880
4359
  exports.isPaymentStatusSuccess = isPaymentStatusSuccess;
3881
4360
  exports.isRetryableError = isRetryableError;
4361
+ exports.isTaxInclusive = isTaxInclusive;
3882
4362
  exports.mapError = mapError;
3883
4363
  exports.mapResult = mapResult;
3884
4364
  exports.money = money;