@behio/storefront-sdk 1.9.0 → 1.17.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/react.mjs CHANGED
@@ -5,6 +5,38 @@ import { useRef, useEffect, useMemo, useState, useCallback } from "react";
5
5
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
6
6
 
7
7
  // src/types.ts
8
+ var BE_CODE_TO_ERROR = {
9
+ "be.storefront.cartIsEmpty": "CART_EMPTY",
10
+ "be.storefront.productNotFound": "PRODUCT_NOT_FOUND",
11
+ "be.storefront.productNotAvailable": "PRODUCT_NOT_FOUND",
12
+ "be.storefront.invalidEmailOrPassword": "INVALID_CREDENTIALS",
13
+ "be.storefront.currentPasswordIncorrect": "INVALID_CREDENTIALS",
14
+ "be.storefront.discountExpired": "DISCOUNT_EXPIRED",
15
+ "be.storefront.discountExpiredOrLimit": "DISCOUNT_EXPIRED",
16
+ "be.storefront.invalidDiscountCode": "INVALID_DISCOUNT",
17
+ "be.storefront.discountInvalid": "INVALID_DISCOUNT",
18
+ "be.storefront.discountInactive": "INVALID_DISCOUNT",
19
+ "be.storefront.discountWrongCurrency": "INVALID_DISCOUNT",
20
+ "be.storefront.discountNotApplicable": "INVALID_DISCOUNT",
21
+ "be.storefront.discountNotYetValid": "INVALID_DISCOUNT",
22
+ "be.storefront.discountUsageLimitReached": "INVALID_DISCOUNT",
23
+ "be.storefront.discountLimitedToGroups": "INVALID_DISCOUNT",
24
+ "be.storefront.tokenInvalid": "TOKEN_INVALID",
25
+ "be.storefront.orderAccessTokenInvalid": "TOKEN_INVALID",
26
+ "be.storefront.resetTokenInvalid": "TOKEN_INVALID",
27
+ "be.storefront.invalidVerificationToken": "TOKEN_INVALID",
28
+ "be.storefront.invalidRefreshToken": "TOKEN_INVALID",
29
+ "be.storefront.refreshTokenExpired": "TOKEN_EXPIRED",
30
+ "be.storefront.apiKeyExpired": "TOKEN_EXPIRED",
31
+ "be.storefront.customerEmailTaken": "EMAIL_ALREADY_EXISTS",
32
+ "be.storefront.orderNotCancellable": "ORDER_NOT_CANCELLABLE",
33
+ "be.storefront.orderCancelledNotReturnable": "ORDER_NOT_CANCELLABLE",
34
+ "be.validation.failed": "VALIDATION_ERROR",
35
+ "be.forms.formNotFound": "NOT_FOUND",
36
+ "be.forms.validationFailed": "VALIDATION_ERROR",
37
+ "be.forms.consentRequired": "VALIDATION_ERROR",
38
+ "be.forms.tooLarge": "VALIDATION_ERROR"
39
+ };
8
40
  var BehioApiError = class _BehioApiError extends Error {
9
41
  constructor(status, body, message) {
10
42
  super(message || `API Error ${status}`);
@@ -21,6 +53,11 @@ var BehioApiError = class _BehioApiError extends Error {
21
53
  if (status === 409) return "EMAIL_ALREADY_EXISTS";
22
54
  if (status === 429) return "RATE_LIMITED";
23
55
  if (status >= 500) return "INTERNAL_ERROR";
56
+ const rawCode = body?.code;
57
+ if (typeof rawCode === "string") {
58
+ const mapped = BE_CODE_TO_ERROR[rawCode];
59
+ if (mapped) return mapped;
60
+ }
24
61
  const msg = (body?.message || "").toLowerCase();
25
62
  if (msg.includes("invalid") && msg.includes("password"))
26
63
  return "INVALID_CREDENTIALS";
@@ -126,6 +163,8 @@ var BehioStorefront = class {
126
163
  this.orders = new OrdersModule(this);
127
164
  this.customer = new CustomerModule(this);
128
165
  this.pages = new PagesModule(this);
166
+ this.blog = new BlogModule(this);
167
+ this.forms = new FormsModule(this);
129
168
  this.wishlist = new WishlistModule(this);
130
169
  this.reviews = new ReviewsModule(this);
131
170
  this.returns = new ReturnsModule(this);
@@ -828,16 +867,27 @@ var CatalogModule = class {
828
867
  { body: input }
829
868
  );
830
869
  }
831
- /** List configured payment methods (filtered by currency). */
870
+ /**
871
+ * List configured payment methods (filtered by currency). `locale` picks the
872
+ * language of `instruments[].label` / `swifts[].label` (SDK 1.14.0); pass the
873
+ * locale of the page so the instrument tiles read in the shopper's language.
874
+ */
832
875
  async listPaymentMethods(opts) {
833
876
  const query = {};
834
877
  if (opts?.currency) query.currency = opts.currency;
878
+ if (opts?.locale) query.locale = opts.locale;
879
+ if (opts?.country) query.country = opts.country;
880
+ if (opts?.shippingMethodId) query.shippingMethodId = opts.shippingMethodId;
835
881
  return this.client.request(
836
882
  "GET",
837
883
  "/catalog/payment-methods",
838
884
  { query }
839
885
  );
840
886
  }
887
+ /** Alias of `listPaymentMethods` (SDK 1.14.0). */
888
+ paymentMethods(opts) {
889
+ return this.listPaymentMethods(opts);
890
+ }
841
891
  };
842
892
  var AuthModule = class {
843
893
  constructor(client) {
@@ -991,6 +1041,26 @@ var CartModule = class {
991
1041
  this.client.emit("cart:updated", res.data);
992
1042
  return res;
993
1043
  }
1044
+ /**
1045
+ * Tell the cart where the order will ship (and, for B2B, the buyer's VAT
1046
+ * ID) so the VAT breakdown matches the checkout before the address form:
1047
+ * destination-country rate (OSS), 0 % export outside the EU, or reverse
1048
+ * charge for an EU business with a VIES-valid VAT ID. `cart.vatMode` says
1049
+ * which rule applied. SDK 1.17.0.
1050
+ *
1051
+ * ```ts
1052
+ * await client.cart.setDestination({ country: "SK" });
1053
+ * await client.cart.setDestination({ vatId: "SK2020000001" }); // "" clears
1054
+ * ```
1055
+ */
1056
+ async setDestination(input) {
1057
+ const res = await this.client.request("PUT", "/cart/destination", {
1058
+ body: input
1059
+ });
1060
+ if (res.error) return res;
1061
+ this.client.emit("cart:updated", res.data);
1062
+ return res;
1063
+ }
994
1064
  /** Update item quantity */
995
1065
  async updateQuantity(itemId, quantity) {
996
1066
  const res = await this.client.request(
@@ -1142,6 +1212,30 @@ var OrdersModule = class {
1142
1212
  constructor(client) {
1143
1213
  this.client = client;
1144
1214
  }
1215
+ /**
1216
+ * Ask the backend to re-check this order's payment with the gateway.
1217
+ *
1218
+ * Call it on the thank-you page the customer lands on after paying, BEFORE
1219
+ * you read the order. Some gateways (Tatrapay+) have no server-to-server
1220
+ * notification at all, so the customer's return is the only fast way the
1221
+ * payment gets confirmed; for the others it is a safety net for a lost
1222
+ * notification.
1223
+ *
1224
+ * The response is deliberately opaque (`{ok: true}` every time, even for an
1225
+ * order number that does not exist): order numbers are sequential, so
1226
+ * anything else would turn this into a probe for other people's orders.
1227
+ * Read the actual state afterwards through a path that proves entitlement
1228
+ * ({@link get}, {@link track} or the guest access-code flow).
1229
+ *
1230
+ * Never throws for a missing order and never blocks the page: treat a
1231
+ * failure as "not confirmed yet", the backend poller catches up on its own.
1232
+ */
1233
+ async syncPaymentOnReturn(orderNumber) {
1234
+ return this.client.request(
1235
+ "POST",
1236
+ `/payments/return/${orderNumber}`
1237
+ );
1238
+ }
1145
1239
  /** List customer orders (requires auth) */
1146
1240
  async list(options) {
1147
1241
  return this.client.request(
@@ -1494,6 +1588,59 @@ var PagesModule = class {
1494
1588
  });
1495
1589
  }
1496
1590
  };
1591
+ var BlogModule = class {
1592
+ constructor(client) {
1593
+ this.client = client;
1594
+ }
1595
+ /** List the site's blogs (active only). */
1596
+ async list(locale) {
1597
+ return this.client.request("GET", "/blogs", {
1598
+ query: { locale }
1599
+ });
1600
+ }
1601
+ /** Published posts of one blog, newest first (featured first), paginated. */
1602
+ async posts(handle, query = {}) {
1603
+ return this.client.request("GET", `/blogs/${handle}/posts`, {
1604
+ query: {
1605
+ locale: query.locale,
1606
+ page: query.page,
1607
+ limit: query.limit,
1608
+ tag: query.tag
1609
+ }
1610
+ });
1611
+ }
1612
+ /** One published post with sanitised HTML content and related posts. */
1613
+ async post(handle, slug, locale) {
1614
+ return this.client.request("GET", `/blogs/${handle}/posts/${slug}`, {
1615
+ query: { locale }
1616
+ });
1617
+ }
1618
+ };
1619
+ var FormsModule = class {
1620
+ constructor(client) {
1621
+ this.client = client;
1622
+ }
1623
+ /** Public definition of one form (fields + settings). 404 for an unknown or inactive slug. */
1624
+ async get(slug) {
1625
+ return this.client.request(
1626
+ "GET",
1627
+ `/forms/${encodeURIComponent(slug)}`
1628
+ );
1629
+ }
1630
+ /**
1631
+ * Submit a response. On `be.forms.validationFailed` the returned error
1632
+ * carries per-field codes: read them with `formFieldErrors(error)`. Other
1633
+ * rejections: `be.forms.consentRequired`, `be.forms.tooLarge`,
1634
+ * `be.forms.formNotFound`; rate limit 10 submits per minute per visitor.
1635
+ */
1636
+ async submit(slug, input) {
1637
+ return this.client.request(
1638
+ "POST",
1639
+ `/forms/${encodeURIComponent(slug)}/submit`,
1640
+ { body: input, auth: false }
1641
+ );
1642
+ }
1643
+ };
1497
1644
  var WishlistModule = class {
1498
1645
  constructor(client) {
1499
1646
  this.client = client;
@@ -3081,9 +3228,10 @@ import { useQuery as useQuery25 } from "@tanstack/react-query";
3081
3228
  function usePaymentMethods(options) {
3082
3229
  const { client, currency: activeCurrency } = useBehio();
3083
3230
  const currency = options?.currency ?? activeCurrency;
3231
+ const locale = options?.locale;
3084
3232
  const { data, isLoading, error, refetch } = useQuery25({
3085
- queryKey: ["behio", "payment-methods", currency ?? ""],
3086
- queryFn: () => unwrap(client.catalog.listPaymentMethods({ currency })),
3233
+ queryKey: ["behio", "payment-methods", currency ?? "", locale ?? ""],
3234
+ queryFn: () => unwrap(client.catalog.listPaymentMethods({ currency, ...locale ? { locale } : {} })),
3087
3235
  enabled: options?.enabled !== false
3088
3236
  });
3089
3237
  return { methods: data?.items ?? [], isLoading, error, refetch };
@@ -3461,11 +3609,134 @@ function usePage(slug, locale, options) {
3461
3609
  });
3462
3610
  }
3463
3611
 
3464
- // src/react/hooks/use-shop-info.ts
3612
+ // src/react/hooks/use-blog.ts
3465
3613
  import { useQuery as useQuery30 } from "@tanstack/react-query";
3466
- function useShopInfo(options) {
3614
+ function useBlogs(locale, options) {
3615
+ const { client } = useBehio();
3616
+ return useQuery30({
3617
+ queryKey: ["behio", "blogs", locale],
3618
+ queryFn: async () => {
3619
+ const result = await unwrap(client.blog.list(locale));
3620
+ return result.blogs;
3621
+ },
3622
+ enabled: options?.enabled !== false
3623
+ });
3624
+ }
3625
+ function useBlogPosts(handle, query, options) {
3626
+ const { client } = useBehio();
3627
+ return useQuery30({
3628
+ queryKey: ["behio", "blog", handle, "posts", query?.locale, query?.page, query?.limit, query?.tag],
3629
+ queryFn: () => unwrap(client.blog.posts(handle, query)),
3630
+ enabled: options?.enabled !== false && !!handle
3631
+ });
3632
+ }
3633
+ function useBlogPost(handle, slug, locale, options) {
3467
3634
  const { client } = useBehio();
3468
3635
  return useQuery30({
3636
+ queryKey: ["behio", "blog", handle, "post", slug, locale],
3637
+ queryFn: () => unwrap(client.blog.post(handle, slug, locale)),
3638
+ enabled: options?.enabled !== false && !!handle && !!slug
3639
+ });
3640
+ }
3641
+
3642
+ // src/react/hooks/use-site-form.ts
3643
+ import { useCallback as useCallback15, useMemo as useMemo4 } from "react";
3644
+ import { useMutation as useMutation15, useQuery as useQuery31 } from "@tanstack/react-query";
3645
+
3646
+ // src/errors.ts
3647
+ function bodyOf(err) {
3648
+ const body = err instanceof BehioApiError ? err.body : err && typeof err === "object" && "body" in err ? err.body : err;
3649
+ return body && typeof body === "object" ? body : null;
3650
+ }
3651
+ function errorCode(err) {
3652
+ const body = bodyOf(err);
3653
+ if (!body) return null;
3654
+ const code = body.code ?? body.key;
3655
+ return typeof code === "string" && code.startsWith("be.") ? code : null;
3656
+ }
3657
+ function errorParams(err) {
3658
+ const body = bodyOf(err);
3659
+ const params = body?.params;
3660
+ return params && typeof params === "object" && !Array.isArray(params) ? params : {};
3661
+ }
3662
+ var FORM_FIELD_ERROR_CODES = /* @__PURE__ */ new Set([
3663
+ "required",
3664
+ "invalid",
3665
+ "tooShort",
3666
+ "tooLong",
3667
+ "min",
3668
+ "max",
3669
+ "notOption",
3670
+ "pattern"
3671
+ ]);
3672
+ function formFieldErrors(err) {
3673
+ if (errorCode(err) !== "be.forms.validationFailed") return [];
3674
+ const raw = errorParams(err).errors;
3675
+ if (!Array.isArray(raw)) return [];
3676
+ const out = [];
3677
+ for (const entry of raw) {
3678
+ if (typeof entry !== "string") continue;
3679
+ const idx = entry.lastIndexOf(":");
3680
+ if (idx <= 0) continue;
3681
+ const key = entry.slice(0, idx);
3682
+ const code = entry.slice(idx + 1);
3683
+ if (!FORM_FIELD_ERROR_CODES.has(code)) continue;
3684
+ out.push({ key, code });
3685
+ }
3686
+ return out;
3687
+ }
3688
+
3689
+ // src/react/hooks/use-site-form.ts
3690
+ function useSiteForm(slug, options) {
3691
+ const { client } = useBehio();
3692
+ return useQuery31({
3693
+ queryKey: ["behio", "form", slug],
3694
+ queryFn: () => unwrap(client.forms.get(slug)),
3695
+ enabled: options?.enabled !== false && !!slug
3696
+ });
3697
+ }
3698
+ function useSiteFormSubmit(slug) {
3699
+ const { client } = useBehio();
3700
+ const mutation = useMutation15({
3701
+ mutationFn: (input) => unwrap(client.forms.submit(slug, input))
3702
+ });
3703
+ const sdkError = mutation.error instanceof UnwrappedError ? mutation.error.sdkError : null;
3704
+ const fieldErrors = useMemo4(() => {
3705
+ const out = {};
3706
+ for (const e of formFieldErrors(sdkError)) out[e.key] = e.code;
3707
+ return out;
3708
+ }, [sdkError]);
3709
+ const errorCode2 = useMemo4(() => {
3710
+ const body = sdkError?.body;
3711
+ const code = body?.code ?? body?.key;
3712
+ return typeof code === "string" ? code : sdkError ? sdkError.code : null;
3713
+ }, [sdkError]);
3714
+ const submit = useCallback15(
3715
+ (input) => mutation.mutateAsync(input).catch(() => null),
3716
+ [mutation]
3717
+ );
3718
+ return {
3719
+ /** Resolves to the result, or null when the submit was rejected (see `fieldErrors` / `errorCode`). */
3720
+ submit,
3721
+ isSubmitting: mutation.isPending,
3722
+ isSuccess: mutation.isSuccess,
3723
+ /** `{ok, id, message, redirectUrl}` after a successful submit. */
3724
+ result: mutation.data ?? null,
3725
+ /** Field key -> validation code after a rejected submit. */
3726
+ fieldErrors,
3727
+ /** Backend error key (`be.forms.*`) or SDK code when the rejection is not per field. */
3728
+ errorCode: errorCode2,
3729
+ /** Raw SDK error (pass to `errorMessage(error, locale)` for a sentence). */
3730
+ error: sdkError,
3731
+ reset: mutation.reset
3732
+ };
3733
+ }
3734
+
3735
+ // src/react/hooks/use-shop-info.ts
3736
+ import { useQuery as useQuery32 } from "@tanstack/react-query";
3737
+ function useShopInfo(options) {
3738
+ const { client } = useBehio();
3739
+ return useQuery32({
3469
3740
  queryKey: ["behio", "shop-info"],
3470
3741
  queryFn: () => unwrap(client.getShopInfo()),
3471
3742
  enabled: options?.enabled !== false
@@ -3473,10 +3744,10 @@ function useShopInfo(options) {
3473
3744
  }
3474
3745
 
3475
3746
  // src/react/hooks/use-shop-scripts.ts
3476
- import { useQuery as useQuery31 } from "@tanstack/react-query";
3747
+ import { useQuery as useQuery33 } from "@tanstack/react-query";
3477
3748
  function useShopScripts(options) {
3478
3749
  const { client } = useBehio();
3479
- return useQuery31({
3750
+ return useQuery33({
3480
3751
  queryKey: ["behio", "shop-scripts"],
3481
3752
  queryFn: () => unwrap(client.getShopScripts()),
3482
3753
  enabled: options?.enabled !== false
@@ -3484,11 +3755,11 @@ function useShopScripts(options) {
3484
3755
  }
3485
3756
 
3486
3757
  // src/react/hooks/use-shop-seo.ts
3487
- import { useQuery as useQuery32 } from "@tanstack/react-query";
3758
+ import { useQuery as useQuery34 } from "@tanstack/react-query";
3488
3759
  function useShopSeo(options) {
3489
3760
  const { client } = useBehio();
3490
3761
  const { locale, initialData, enabled = true } = options ?? {};
3491
- return useQuery32({
3762
+ return useQuery34({
3492
3763
  queryKey: ["behio", "shop-seo", locale ?? "_default"],
3493
3764
  queryFn: () => unwrap(client.getShopSeo(locale)),
3494
3765
  initialData,
@@ -3548,23 +3819,23 @@ function CurrencySwitcher({
3548
3819
  }
3549
3820
 
3550
3821
  // src/react/components/storefront-scripts.tsx
3551
- import { useEffect as useEffect6, useMemo as useMemo4, useState as useState10 } from "react";
3822
+ import { useEffect as useEffect6, useMemo as useMemo5, useState as useState10 } from "react";
3552
3823
 
3553
3824
  // src/react/hooks/use-consent.ts
3554
- import { useQuery as useQuery33, useMutation as useMutation15, useQueryClient as useQueryClient16 } from "@tanstack/react-query";
3825
+ import { useQuery as useQuery35, useMutation as useMutation16, useQueryClient as useQueryClient16 } from "@tanstack/react-query";
3555
3826
  function useCookieConsent(visitorId) {
3556
3827
  const { client } = useBehio();
3557
3828
  const qc = useQueryClient16();
3558
- const query = useQuery33({
3829
+ const query = useQuery35({
3559
3830
  queryKey: ["behio", "consent", visitorId],
3560
3831
  queryFn: () => unwrap(client.consent.get(visitorId)),
3561
3832
  enabled: Boolean(visitorId)
3562
3833
  });
3563
- const recordMutation = useMutation15({
3834
+ const recordMutation = useMutation16({
3564
3835
  mutationFn: (input) => unwrap(client.consent.record(input)),
3565
3836
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "consent"] })
3566
3837
  });
3567
- const revokeMutation = useMutation15({
3838
+ const revokeMutation = useMutation16({
3568
3839
  mutationFn: () => unwrap(client.consent.revoke(visitorId)),
3569
3840
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "consent"] })
3570
3841
  });
@@ -3649,11 +3920,11 @@ function StorefrontScripts({ visitorId: visitorIdProp } = {}) {
3649
3920
  }, [visitorIdProp]);
3650
3921
  const { data: consent } = useCookieConsent(visitorId || void 0);
3651
3922
  const analyticsOk = Boolean(consent?.analytics);
3652
- const scripts = useMemo4(
3923
+ const scripts = useMemo5(
3653
3924
  () => (data?.scripts ?? []).filter((s) => !s.consentRequired || analyticsOk),
3654
3925
  [data, analyticsOk]
3655
3926
  );
3656
- const signature = useMemo4(
3927
+ const signature = useMemo5(
3657
3928
  () => JSON.stringify(scripts.map((s) => [s.id, s.type, s.placement, s.value])),
3658
3929
  [scripts]
3659
3930
  );
@@ -3923,10 +4194,10 @@ function utmFromSearch(search) {
3923
4194
  }
3924
4195
 
3925
4196
  // src/react/hooks/use-bundles.ts
3926
- import { useQuery as useQuery34 } from "@tanstack/react-query";
4197
+ import { useQuery as useQuery36 } from "@tanstack/react-query";
3927
4198
  function useBundles(options) {
3928
4199
  const { client } = useBehio();
3929
- return useQuery34({
4200
+ return useQuery36({
3930
4201
  queryKey: ["behio", "bundles"],
3931
4202
  queryFn: () => unwrap(client.catalog.getBundles()),
3932
4203
  enabled: options?.enabled ?? true,
@@ -3935,7 +4206,7 @@ function useBundles(options) {
3935
4206
  }
3936
4207
  function useBundle(slug, options) {
3937
4208
  const { client } = useBehio();
3938
- return useQuery34({
4209
+ return useQuery36({
3939
4210
  queryKey: ["behio", "bundle", slug],
3940
4211
  queryFn: () => unwrap(client.catalog.getBundle(slug)),
3941
4212
  enabled: Boolean(slug) && (options?.enabled ?? true),
@@ -3944,10 +4215,10 @@ function useBundle(slug, options) {
3944
4215
  }
3945
4216
 
3946
4217
  // src/react/hooks/use-product-group.ts
3947
- import { useQuery as useQuery35 } from "@tanstack/react-query";
4218
+ import { useQuery as useQuery37 } from "@tanstack/react-query";
3948
4219
  function useProductGroup(slug, options) {
3949
4220
  const { client } = useBehio();
3950
- return useQuery35({
4221
+ return useQuery37({
3951
4222
  queryKey: ["behio", "product-group", slug, options?.locale, options?.currency],
3952
4223
  queryFn: () => unwrap(
3953
4224
  client.catalog.getProductGroup(slug, {
@@ -3961,10 +4232,10 @@ function useProductGroup(slug, options) {
3961
4232
  }
3962
4233
 
3963
4234
  // src/react/hooks/use-cross-sell.ts
3964
- import { useQuery as useQuery36 } from "@tanstack/react-query";
4235
+ import { useQuery as useQuery38 } from "@tanstack/react-query";
3965
4236
  function useCrossSell(productSlug, options) {
3966
4237
  const { client } = useBehio();
3967
- return useQuery36({
4238
+ return useQuery38({
3968
4239
  queryKey: ["behio", "cross-sell", productSlug, options?.locale, options?.currency],
3969
4240
  queryFn: () => unwrap(
3970
4241
  client.catalog.getCrossSell(productSlug, {
@@ -3978,10 +4249,10 @@ function useCrossSell(productSlug, options) {
3978
4249
  }
3979
4250
 
3980
4251
  // src/react/hooks/use-product-promotions.ts
3981
- import { useQuery as useQuery37 } from "@tanstack/react-query";
4252
+ import { useQuery as useQuery39 } from "@tanstack/react-query";
3982
4253
  function useProductPromotions(productSlug, options) {
3983
4254
  const { client } = useBehio();
3984
- return useQuery37({
4255
+ return useQuery39({
3985
4256
  queryKey: ["behio", "product-promotions", productSlug],
3986
4257
  queryFn: () => unwrap(client.catalog.getProductPromotions(productSlug)),
3987
4258
  enabled: Boolean(productSlug) && (options?.enabled ?? true),
@@ -3990,11 +4261,11 @@ function useProductPromotions(productSlug, options) {
3990
4261
  }
3991
4262
 
3992
4263
  // src/react/hooks/use-gift-card.ts
3993
- import { useQuery as useQuery38 } from "@tanstack/react-query";
4264
+ import { useQuery as useQuery40 } from "@tanstack/react-query";
3994
4265
  function useGiftCardBalance(code, options) {
3995
4266
  const { client } = useBehio();
3996
4267
  const trimmed = code?.trim();
3997
- return useQuery38({
4268
+ return useQuery40({
3998
4269
  queryKey: ["behio", "gift-card-balance", trimmed],
3999
4270
  queryFn: () => unwrap(client.catalog.checkGiftCard(trimmed)),
4000
4271
  enabled: Boolean(trimmed && trimmed.length >= 6) && (options?.enabled ?? true)
@@ -4002,20 +4273,20 @@ function useGiftCardBalance(code, options) {
4002
4273
  }
4003
4274
 
4004
4275
  // src/react/hooks/use-wishlist.ts
4005
- import { useQuery as useQuery39, useMutation as useMutation16, useQueryClient as useQueryClient17 } from "@tanstack/react-query";
4276
+ import { useQuery as useQuery41, useMutation as useMutation17, useQueryClient as useQueryClient17 } from "@tanstack/react-query";
4006
4277
  function useWishlist(options) {
4007
4278
  const { client } = useBehio();
4008
4279
  const qc = useQueryClient17();
4009
- const query = useQuery39({
4280
+ const query = useQuery41({
4010
4281
  queryKey: ["behio", "wishlist"],
4011
4282
  queryFn: () => unwrap(client.wishlist.get()),
4012
4283
  enabled: options?.enabled ?? true
4013
4284
  });
4014
- const addMutation = useMutation16({
4285
+ const addMutation = useMutation17({
4015
4286
  mutationFn: (productId) => unwrap(client.wishlist.add(productId)),
4016
4287
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "wishlist"] })
4017
4288
  });
4018
- const removeMutation = useMutation16({
4289
+ const removeMutation = useMutation17({
4019
4290
  mutationFn: (productId) => unwrap(client.wishlist.remove(productId)),
4020
4291
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "wishlist"] })
4021
4292
  });
@@ -4029,7 +4300,7 @@ function useWishlist(options) {
4029
4300
  }
4030
4301
  function useIsInWishlist(productId) {
4031
4302
  const { client } = useBehio();
4032
- return useQuery39({
4303
+ return useQuery41({
4033
4304
  queryKey: ["behio", "wishlist-check", productId],
4034
4305
  queryFn: () => unwrap(client.wishlist.isInWishlist(productId)),
4035
4306
  enabled: Boolean(productId)
@@ -4037,10 +4308,10 @@ function useIsInWishlist(productId) {
4037
4308
  }
4038
4309
 
4039
4310
  // src/react/hooks/use-reviews.ts
4040
- import { useQuery as useQuery40, useMutation as useMutation17, useQueryClient as useQueryClient18 } from "@tanstack/react-query";
4311
+ import { useQuery as useQuery42, useMutation as useMutation18, useQueryClient as useQueryClient18 } from "@tanstack/react-query";
4041
4312
  function useProductReviews(productId, options) {
4042
4313
  const { client } = useBehio();
4043
- return useQuery40({
4314
+ return useQuery42({
4044
4315
  queryKey: ["behio", "reviews", productId, options?.page ?? 1],
4045
4316
  queryFn: () => unwrap(client.reviews.getProductReviews(productId, options?.page, options?.limit)),
4046
4317
  enabled: Boolean(productId) && (options?.enabled ?? true)
@@ -4049,29 +4320,29 @@ function useProductReviews(productId, options) {
4049
4320
  function useSubmitReview() {
4050
4321
  const { client } = useBehio();
4051
4322
  const qc = useQueryClient18();
4052
- return useMutation17({
4323
+ return useMutation18({
4053
4324
  mutationFn: (input) => unwrap(client.reviews.submit(input)),
4054
4325
  onSuccess: (_, input) => qc.invalidateQueries({ queryKey: ["behio", "reviews", input.productId] })
4055
4326
  });
4056
4327
  }
4057
4328
 
4058
4329
  // src/react/hooks/use-returns.ts
4059
- import { useQuery as useQuery41, useMutation as useMutation18 } from "@tanstack/react-query";
4330
+ import { useQuery as useQuery43, useMutation as useMutation19 } from "@tanstack/react-query";
4060
4331
  function useLookupReturnableOrder() {
4061
4332
  const { client } = useBehio();
4062
- return useMutation18({
4333
+ return useMutation19({
4063
4334
  mutationFn: ({ orderNumber, email }) => unwrap(client.returns.lookupOrder(orderNumber, email))
4064
4335
  });
4065
4336
  }
4066
4337
  function useSubmitReturn() {
4067
4338
  const { client } = useBehio();
4068
- return useMutation18({
4339
+ return useMutation19({
4069
4340
  mutationFn: (input) => unwrap(client.returns.submit(input))
4070
4341
  });
4071
4342
  }
4072
4343
  function useReturnStatus(returnId, email) {
4073
4344
  const { client } = useBehio();
4074
- return useQuery41({
4345
+ return useQuery43({
4075
4346
  queryKey: ["behio", "return-status", returnId],
4076
4347
  queryFn: () => unwrap(client.returns.getStatus(returnId, email)),
4077
4348
  enabled: Boolean(returnId && email)
@@ -4079,16 +4350,16 @@ function useReturnStatus(returnId, email) {
4079
4350
  }
4080
4351
 
4081
4352
  // src/react/hooks/use-quotes.ts
4082
- import { useMutation as useMutation19, useQuery as useQuery42 } from "@tanstack/react-query";
4353
+ import { useMutation as useMutation20, useQuery as useQuery44 } from "@tanstack/react-query";
4083
4354
  function useSubmitQuote() {
4084
4355
  const { client } = useBehio();
4085
- return useMutation19({
4356
+ return useMutation20({
4086
4357
  mutationFn: (input) => unwrap(client.quotes.submit(input))
4087
4358
  });
4088
4359
  }
4089
4360
  function useQuoteStatus(quoteId, email) {
4090
4361
  const { client } = useBehio();
4091
- return useQuery42({
4362
+ return useQuery44({
4092
4363
  queryKey: ["behio", "quote-status", quoteId],
4093
4364
  queryFn: () => unwrap(client.quotes.getStatus(quoteId, email)),
4094
4365
  enabled: Boolean(quoteId && email)
@@ -4096,10 +4367,10 @@ function useQuoteStatus(quoteId, email) {
4096
4367
  }
4097
4368
 
4098
4369
  // src/react/hooks/use-back-in-stock.ts
4099
- import { useMutation as useMutation20 } from "@tanstack/react-query";
4370
+ import { useMutation as useMutation21 } from "@tanstack/react-query";
4100
4371
  function useNotifyWhenAvailable() {
4101
4372
  const { client } = useBehio();
4102
- return useMutation20({
4373
+ return useMutation21({
4103
4374
  mutationFn: ({ productId, email }) => unwrap(client.catalog.notifyWhenAvailable(productId, email))
4104
4375
  });
4105
4376
  }
@@ -4235,6 +4506,9 @@ export {
4235
4506
  useAuth,
4236
4507
  useBehio,
4237
4508
  useBehioClient,
4509
+ useBlogPost,
4510
+ useBlogPosts,
4511
+ useBlogs,
4238
4512
  useBundle,
4239
4513
  useBundles,
4240
4514
  useCart,
@@ -4288,6 +4562,8 @@ export {
4288
4562
  useShopInfo,
4289
4563
  useShopScripts,
4290
4564
  useShopSeo,
4565
+ useSiteForm,
4566
+ useSiteFormSubmit,
4291
4567
  useSubmitQuote,
4292
4568
  useSubmitReturn,
4293
4569
  useSubmitReview,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@behio/storefront-sdk",
3
- "version": "1.9.0",
4
- "description": "TypeScript SDK for Behio Headless E-Shop \u2014 core client + React hooks",
3
+ "version": "1.17.0",
4
+ "description": "TypeScript SDK for Behio headless e-commerce: core client + React hooks",
5
5
  "author": "Behio",
6
6
  "license": "MIT",
7
7
  "main": "./dist/index.js",