@behio/storefront-sdk 0.4.0 → 0.6.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/README.md CHANGED
@@ -84,6 +84,7 @@ function ProductList() {
84
84
  | `wishlist` | Add, remove, check |
85
85
  | `reviews` | Submit, list, vote helpful |
86
86
  | `addresses` | Address autocomplete with debounce hook |
87
+ | `shipping` | List shipping methods and fetch live carrier quotes (Zaslat.cz + extensible) |
87
88
  | `returns` | Submit return requests |
88
89
  | `consent` | Cookie consent (GDPR) |
89
90
  | `quotes` | B2B quote requests |
@@ -142,6 +142,7 @@ var BehioStorefront = class {
142
142
  this.consent = new ConsentModule(this);
143
143
  this.quotes = new QuotesModule(this);
144
144
  this.addresses = new AddressModule(this);
145
+ this.shipping = new ShippingModule(this);
145
146
  }
146
147
  // --- Public methods ---
147
148
  /** Get basic shop info */
@@ -493,6 +494,12 @@ var CatalogModule = class {
493
494
  async checkGiftCard(code) {
494
495
  return this.client.request("GET", `/catalog/gift-cards/${encodeURIComponent(code)}/check`);
495
496
  }
497
+ /** List configured payment methods (filtered by currency). */
498
+ async listPaymentMethods(opts) {
499
+ const query = {};
500
+ if (_optionalChain([opts, 'optionalAccess', _23 => _23.currency])) query.currency = opts.currency;
501
+ return this.client.request("GET", "/catalog/payment-methods", { query });
502
+ }
496
503
  };
497
504
  var AuthModule = class {
498
505
  constructor(client) {
@@ -637,11 +644,33 @@ var CartModule = class {
637
644
  this.client.emit("cart:updated", res.data);
638
645
  return res;
639
646
  }
640
- /** Add a bundle to the cart (price is locked at the bundle's current price) */
641
- async addBundle(bundleId, quantity = 1) {
642
- const res = await this.client.request("POST", "/cart/bundles", {
643
- body: { bundleId, quantity }
644
- });
647
+ /**
648
+ * Add a bundle to the cart. Price is snapshotted at the bundle's current
649
+ * price. Pass either the bundle id or its slug — slug is more ergonomic
650
+ * for static storefront wiring (`behio.cart.addBundle({slug: "morning-set"})`).
651
+ *
652
+ * Respects the bundle's `minQuantity`, `maxQuantity`, and `stockLimit`:
653
+ * the request rejects with HTTP 400 if the resulting cart line would
654
+ * violate any of them. The returned error includes the relevant field
655
+ * (`minQuantity`, `maxQuantity`, or `remaining`) so the storefront can
656
+ * surface a meaningful message.
657
+ *
658
+ * @param identifier Either `{id: bundleId}` or `{slug: bundleSlug}`. As a
659
+ * convenience, passing a plain string is treated as the
660
+ * bundle id for backwards compatibility.
661
+ * @param quantity How many bundles to add (defaults to 1). Capped by
662
+ * the bundle's `maxQuantity` if set.
663
+ */
664
+ async addBundle(identifier, quantity = 1) {
665
+ const body = { quantity };
666
+ if (typeof identifier === "string") {
667
+ body.bundleId = identifier;
668
+ } else if ("id" in identifier) {
669
+ body.bundleId = identifier.id;
670
+ } else {
671
+ body.bundleSlug = identifier.slug;
672
+ }
673
+ const res = await this.client.request("POST", "/cart/bundles", { body });
645
674
  if (res.error) return res;
646
675
  this.client.emit("cart:updated", res.data);
647
676
  return res;
@@ -709,7 +738,7 @@ var OrdersModule = class {
709
738
  /** List customer orders (requires auth) */
710
739
  async list(options) {
711
740
  return this.client.request("GET", "/orders", {
712
- query: { page: _optionalChain([options, 'optionalAccess', _23 => _23.page]), limit: _optionalChain([options, 'optionalAccess', _24 => _24.limit]) }
741
+ query: { page: _optionalChain([options, 'optionalAccess', _24 => _24.page]), limit: _optionalChain([options, 'optionalAccess', _25 => _25.limit]) }
713
742
  });
714
743
  }
715
744
  /** Get order detail (requires auth) */
@@ -810,6 +839,16 @@ var ReturnsModule = class {
810
839
  constructor(client) {
811
840
  this.client = client;
812
841
  }
842
+ /**
843
+ * Guest order lookup for the EU withdrawal form: order number + the email
844
+ * used on the order resolve to the order id and per-item returnable
845
+ * quantities. POST so the email never appears in a URL.
846
+ */
847
+ async lookupOrder(orderNumber, email) {
848
+ return this.client.request("POST", "/returns/lookup-order", {
849
+ body: { orderNumber, email }
850
+ });
851
+ }
813
852
  async submit(input) {
814
853
  return this.client.request("POST", "/returns", { body: input });
815
854
  }
@@ -863,6 +902,49 @@ var AddressModule = class {
863
902
  });
864
903
  }
865
904
  };
905
+ var ShippingModule = class {
906
+ constructor(client) {
907
+ this.client = client;
908
+ }
909
+ /**
910
+ * Return the configured shipping methods that pass the current
911
+ * currency + country filter. Fixed-price methods come back with
912
+ * their `pricing[]` row resolved; live-quote methods come back with
913
+ * `price` 0 here — call `quote()` to get the real live price.
914
+ */
915
+ async listMethods(opts) {
916
+ const query = {};
917
+ if (_optionalChain([opts, 'optionalAccess', _26 => _26.currency])) query.currency = opts.currency;
918
+ if (_optionalChain([opts, 'optionalAccess', _27 => _27.country])) query.country = opts.country;
919
+ if (_optionalChain([opts, 'optionalAccess', _28 => _28.cartTotal]) != null) query.cartTotal = String(opts.cartTotal);
920
+ if (_optionalChain([opts, 'optionalAccess', _29 => _29.cartWeightKg]) != null) query.cartWeightKg = String(opts.cartWeightKg);
921
+ return this.client.request(
922
+ "GET",
923
+ "/catalog/shipping-methods",
924
+ { query }
925
+ );
926
+ }
927
+ /**
928
+ * Quote shipping for a destination address + cart contents. Each
929
+ * configured method is evaluated:
930
+ * - `priceStrategy="fixed"` → resolved from the merchant's per-currency
931
+ * `pricing[]` rows + free-shipping threshold check.
932
+ * - `priceStrategy="live_quote"` → dispatched to the upstream
933
+ * meta-provider (Zaslat, future Shippo / Sendcloud / …) and run
934
+ * through the merchant's markup/rounding rules.
935
+ *
936
+ * Filter `available: true` for the checkout picker; `available: false`
937
+ * rows carry a `reason` (`"no_rate_returned"`, `"live_quote_not_implemented"`,
938
+ * …) you can log but should not display.
939
+ */
940
+ async quote(input) {
941
+ return this.client.request(
942
+ "POST",
943
+ "/catalog/shipping/quote",
944
+ { body: input }
945
+ );
946
+ }
947
+ };
866
948
 
867
949
 
868
950
 
@@ -142,6 +142,7 @@ var BehioStorefront = class {
142
142
  this.consent = new ConsentModule(this);
143
143
  this.quotes = new QuotesModule(this);
144
144
  this.addresses = new AddressModule(this);
145
+ this.shipping = new ShippingModule(this);
145
146
  }
146
147
  // --- Public methods ---
147
148
  /** Get basic shop info */
@@ -493,6 +494,12 @@ var CatalogModule = class {
493
494
  async checkGiftCard(code) {
494
495
  return this.client.request("GET", `/catalog/gift-cards/${encodeURIComponent(code)}/check`);
495
496
  }
497
+ /** List configured payment methods (filtered by currency). */
498
+ async listPaymentMethods(opts) {
499
+ const query = {};
500
+ if (opts?.currency) query.currency = opts.currency;
501
+ return this.client.request("GET", "/catalog/payment-methods", { query });
502
+ }
496
503
  };
497
504
  var AuthModule = class {
498
505
  constructor(client) {
@@ -637,11 +644,33 @@ var CartModule = class {
637
644
  this.client.emit("cart:updated", res.data);
638
645
  return res;
639
646
  }
640
- /** Add a bundle to the cart (price is locked at the bundle's current price) */
641
- async addBundle(bundleId, quantity = 1) {
642
- const res = await this.client.request("POST", "/cart/bundles", {
643
- body: { bundleId, quantity }
644
- });
647
+ /**
648
+ * Add a bundle to the cart. Price is snapshotted at the bundle's current
649
+ * price. Pass either the bundle id or its slug — slug is more ergonomic
650
+ * for static storefront wiring (`behio.cart.addBundle({slug: "morning-set"})`).
651
+ *
652
+ * Respects the bundle's `minQuantity`, `maxQuantity`, and `stockLimit`:
653
+ * the request rejects with HTTP 400 if the resulting cart line would
654
+ * violate any of them. The returned error includes the relevant field
655
+ * (`minQuantity`, `maxQuantity`, or `remaining`) so the storefront can
656
+ * surface a meaningful message.
657
+ *
658
+ * @param identifier Either `{id: bundleId}` or `{slug: bundleSlug}`. As a
659
+ * convenience, passing a plain string is treated as the
660
+ * bundle id for backwards compatibility.
661
+ * @param quantity How many bundles to add (defaults to 1). Capped by
662
+ * the bundle's `maxQuantity` if set.
663
+ */
664
+ async addBundle(identifier, quantity = 1) {
665
+ const body = { quantity };
666
+ if (typeof identifier === "string") {
667
+ body.bundleId = identifier;
668
+ } else if ("id" in identifier) {
669
+ body.bundleId = identifier.id;
670
+ } else {
671
+ body.bundleSlug = identifier.slug;
672
+ }
673
+ const res = await this.client.request("POST", "/cart/bundles", { body });
645
674
  if (res.error) return res;
646
675
  this.client.emit("cart:updated", res.data);
647
676
  return res;
@@ -810,6 +839,16 @@ var ReturnsModule = class {
810
839
  constructor(client) {
811
840
  this.client = client;
812
841
  }
842
+ /**
843
+ * Guest order lookup for the EU withdrawal form: order number + the email
844
+ * used on the order resolve to the order id and per-item returnable
845
+ * quantities. POST so the email never appears in a URL.
846
+ */
847
+ async lookupOrder(orderNumber, email) {
848
+ return this.client.request("POST", "/returns/lookup-order", {
849
+ body: { orderNumber, email }
850
+ });
851
+ }
813
852
  async submit(input) {
814
853
  return this.client.request("POST", "/returns", { body: input });
815
854
  }
@@ -863,6 +902,49 @@ var AddressModule = class {
863
902
  });
864
903
  }
865
904
  };
905
+ var ShippingModule = class {
906
+ constructor(client) {
907
+ this.client = client;
908
+ }
909
+ /**
910
+ * Return the configured shipping methods that pass the current
911
+ * currency + country filter. Fixed-price methods come back with
912
+ * their `pricing[]` row resolved; live-quote methods come back with
913
+ * `price` 0 here — call `quote()` to get the real live price.
914
+ */
915
+ async listMethods(opts) {
916
+ const query = {};
917
+ if (opts?.currency) query.currency = opts.currency;
918
+ if (opts?.country) query.country = opts.country;
919
+ if (opts?.cartTotal != null) query.cartTotal = String(opts.cartTotal);
920
+ if (opts?.cartWeightKg != null) query.cartWeightKg = String(opts.cartWeightKg);
921
+ return this.client.request(
922
+ "GET",
923
+ "/catalog/shipping-methods",
924
+ { query }
925
+ );
926
+ }
927
+ /**
928
+ * Quote shipping for a destination address + cart contents. Each
929
+ * configured method is evaluated:
930
+ * - `priceStrategy="fixed"` → resolved from the merchant's per-currency
931
+ * `pricing[]` rows + free-shipping threshold check.
932
+ * - `priceStrategy="live_quote"` → dispatched to the upstream
933
+ * meta-provider (Zaslat, future Shippo / Sendcloud / …) and run
934
+ * through the merchant's markup/rounding rules.
935
+ *
936
+ * Filter `available: true` for the checkout picker; `available: false`
937
+ * rows carry a `reason` (`"no_rate_returned"`, `"live_quote_not_implemented"`,
938
+ * …) you can log but should not display.
939
+ */
940
+ async quote(input) {
941
+ return this.client.request(
942
+ "POST",
943
+ "/catalog/shipping/quote",
944
+ { body: input }
945
+ );
946
+ }
947
+ };
866
948
 
867
949
  export {
868
950
  ProductSort,