@behio/storefront-sdk 1.9.0 → 1.18.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);
@@ -574,6 +613,7 @@ var CatalogModule = class {
574
613
  if (query.priceMin) q.priceMin = query.priceMin;
575
614
  if (query.priceMax) q.priceMax = query.priceMax;
576
615
  if (query.currency) q.currency = query.currency;
616
+ if (query.country) q.country = query.country;
577
617
  if (query.locale) q.locale = query.locale;
578
618
  if (query.sort) q.sort = query.sort;
579
619
  if (query.inStock !== void 0) q.inStock = query.inStock;
@@ -606,7 +646,7 @@ var CatalogModule = class {
606
646
  "GET",
607
647
  `/catalog/products/${slug}`,
608
648
  {
609
- query: { locale: options?.locale, currency: options?.currency }
649
+ query: { locale: options?.locale, currency: options?.currency, country: options?.country }
610
650
  }
611
651
  );
612
652
  }
@@ -828,16 +868,27 @@ var CatalogModule = class {
828
868
  { body: input }
829
869
  );
830
870
  }
831
- /** List configured payment methods (filtered by currency). */
871
+ /**
872
+ * List configured payment methods (filtered by currency). `locale` picks the
873
+ * language of `instruments[].label` / `swifts[].label` (SDK 1.14.0); pass the
874
+ * locale of the page so the instrument tiles read in the shopper's language.
875
+ */
832
876
  async listPaymentMethods(opts) {
833
877
  const query = {};
834
878
  if (opts?.currency) query.currency = opts.currency;
879
+ if (opts?.locale) query.locale = opts.locale;
880
+ if (opts?.country) query.country = opts.country;
881
+ if (opts?.shippingMethodId) query.shippingMethodId = opts.shippingMethodId;
835
882
  return this.client.request(
836
883
  "GET",
837
884
  "/catalog/payment-methods",
838
885
  { query }
839
886
  );
840
887
  }
888
+ /** Alias of `listPaymentMethods` (SDK 1.14.0). */
889
+ paymentMethods(opts) {
890
+ return this.listPaymentMethods(opts);
891
+ }
841
892
  };
842
893
  var AuthModule = class {
843
894
  constructor(client) {
@@ -991,6 +1042,26 @@ var CartModule = class {
991
1042
  this.client.emit("cart:updated", res.data);
992
1043
  return res;
993
1044
  }
1045
+ /**
1046
+ * Tell the cart where the order will ship (and, for B2B, the buyer's VAT
1047
+ * ID) so the VAT breakdown matches the checkout before the address form:
1048
+ * destination-country rate (OSS), 0 % export outside the EU, or reverse
1049
+ * charge for an EU business with a VIES-valid VAT ID. `cart.vatMode` says
1050
+ * which rule applied. SDK 1.17.0.
1051
+ *
1052
+ * ```ts
1053
+ * await client.cart.setDestination({ country: "SK" });
1054
+ * await client.cart.setDestination({ vatId: "SK2020000001" }); // "" clears
1055
+ * ```
1056
+ */
1057
+ async setDestination(input) {
1058
+ const res = await this.client.request("PUT", "/cart/destination", {
1059
+ body: input
1060
+ });
1061
+ if (res.error) return res;
1062
+ this.client.emit("cart:updated", res.data);
1063
+ return res;
1064
+ }
994
1065
  /** Update item quantity */
995
1066
  async updateQuantity(itemId, quantity) {
996
1067
  const res = await this.client.request(
@@ -1142,6 +1213,30 @@ var OrdersModule = class {
1142
1213
  constructor(client) {
1143
1214
  this.client = client;
1144
1215
  }
1216
+ /**
1217
+ * Ask the backend to re-check this order's payment with the gateway.
1218
+ *
1219
+ * Call it on the thank-you page the customer lands on after paying, BEFORE
1220
+ * you read the order. Some gateways (Tatrapay+) have no server-to-server
1221
+ * notification at all, so the customer's return is the only fast way the
1222
+ * payment gets confirmed; for the others it is a safety net for a lost
1223
+ * notification.
1224
+ *
1225
+ * The response is deliberately opaque (`{ok: true}` every time, even for an
1226
+ * order number that does not exist): order numbers are sequential, so
1227
+ * anything else would turn this into a probe for other people's orders.
1228
+ * Read the actual state afterwards through a path that proves entitlement
1229
+ * ({@link get}, {@link track} or the guest access-code flow).
1230
+ *
1231
+ * Never throws for a missing order and never blocks the page: treat a
1232
+ * failure as "not confirmed yet", the backend poller catches up on its own.
1233
+ */
1234
+ async syncPaymentOnReturn(orderNumber) {
1235
+ return this.client.request(
1236
+ "POST",
1237
+ `/payments/return/${orderNumber}`
1238
+ );
1239
+ }
1145
1240
  /** List customer orders (requires auth) */
1146
1241
  async list(options) {
1147
1242
  return this.client.request(
@@ -1268,7 +1363,10 @@ var CustomerModule = class {
1268
1363
  body: address
1269
1364
  });
1270
1365
  }
1271
- /** Update address */
1366
+ /**
1367
+ * Update address. Partial: `{isDefault: true}` alone is a valid body. A
1368
+ * changed `vatId` or `country` re-runs the VIES check on the server.
1369
+ */
1272
1370
  async updateAddress(addressId, data) {
1273
1371
  return this.client.request(
1274
1372
  "PATCH",
@@ -1494,6 +1592,59 @@ var PagesModule = class {
1494
1592
  });
1495
1593
  }
1496
1594
  };
1595
+ var BlogModule = class {
1596
+ constructor(client) {
1597
+ this.client = client;
1598
+ }
1599
+ /** List the site's blogs (active only). */
1600
+ async list(locale) {
1601
+ return this.client.request("GET", "/blogs", {
1602
+ query: { locale }
1603
+ });
1604
+ }
1605
+ /** Published posts of one blog, newest first (featured first), paginated. */
1606
+ async posts(handle, query = {}) {
1607
+ return this.client.request("GET", `/blogs/${handle}/posts`, {
1608
+ query: {
1609
+ locale: query.locale,
1610
+ page: query.page,
1611
+ limit: query.limit,
1612
+ tag: query.tag
1613
+ }
1614
+ });
1615
+ }
1616
+ /** One published post with sanitised HTML content and related posts. */
1617
+ async post(handle, slug, locale) {
1618
+ return this.client.request("GET", `/blogs/${handle}/posts/${slug}`, {
1619
+ query: { locale }
1620
+ });
1621
+ }
1622
+ };
1623
+ var FormsModule = class {
1624
+ constructor(client) {
1625
+ this.client = client;
1626
+ }
1627
+ /** Public definition of one form (fields + settings). 404 for an unknown or inactive slug. */
1628
+ async get(slug) {
1629
+ return this.client.request(
1630
+ "GET",
1631
+ `/forms/${encodeURIComponent(slug)}`
1632
+ );
1633
+ }
1634
+ /**
1635
+ * Submit a response. On `be.forms.validationFailed` the returned error
1636
+ * carries per-field codes: read them with `formFieldErrors(error)`. Other
1637
+ * rejections: `be.forms.consentRequired`, `be.forms.tooLarge`,
1638
+ * `be.forms.formNotFound`; rate limit 10 submits per minute per visitor.
1639
+ */
1640
+ async submit(slug, input) {
1641
+ return this.client.request(
1642
+ "POST",
1643
+ `/forms/${encodeURIComponent(slug)}/submit`,
1644
+ { body: input, auth: false }
1645
+ );
1646
+ }
1647
+ };
1497
1648
  var WishlistModule = class {
1498
1649
  constructor(client) {
1499
1650
  this.client = client;
@@ -3081,9 +3232,10 @@ import { useQuery as useQuery25 } from "@tanstack/react-query";
3081
3232
  function usePaymentMethods(options) {
3082
3233
  const { client, currency: activeCurrency } = useBehio();
3083
3234
  const currency = options?.currency ?? activeCurrency;
3235
+ const locale = options?.locale;
3084
3236
  const { data, isLoading, error, refetch } = useQuery25({
3085
- queryKey: ["behio", "payment-methods", currency ?? ""],
3086
- queryFn: () => unwrap(client.catalog.listPaymentMethods({ currency })),
3237
+ queryKey: ["behio", "payment-methods", currency ?? "", locale ?? ""],
3238
+ queryFn: () => unwrap(client.catalog.listPaymentMethods({ currency, ...locale ? { locale } : {} })),
3087
3239
  enabled: options?.enabled !== false
3088
3240
  });
3089
3241
  return { methods: data?.items ?? [], isLoading, error, refetch };
@@ -3461,11 +3613,134 @@ function usePage(slug, locale, options) {
3461
3613
  });
3462
3614
  }
3463
3615
 
3464
- // src/react/hooks/use-shop-info.ts
3616
+ // src/react/hooks/use-blog.ts
3465
3617
  import { useQuery as useQuery30 } from "@tanstack/react-query";
3466
- function useShopInfo(options) {
3618
+ function useBlogs(locale, options) {
3467
3619
  const { client } = useBehio();
3468
3620
  return useQuery30({
3621
+ queryKey: ["behio", "blogs", locale],
3622
+ queryFn: async () => {
3623
+ const result = await unwrap(client.blog.list(locale));
3624
+ return result.blogs;
3625
+ },
3626
+ enabled: options?.enabled !== false
3627
+ });
3628
+ }
3629
+ function useBlogPosts(handle, query, options) {
3630
+ const { client } = useBehio();
3631
+ return useQuery30({
3632
+ queryKey: ["behio", "blog", handle, "posts", query?.locale, query?.page, query?.limit, query?.tag],
3633
+ queryFn: () => unwrap(client.blog.posts(handle, query)),
3634
+ enabled: options?.enabled !== false && !!handle
3635
+ });
3636
+ }
3637
+ function useBlogPost(handle, slug, locale, options) {
3638
+ const { client } = useBehio();
3639
+ return useQuery30({
3640
+ queryKey: ["behio", "blog", handle, "post", slug, locale],
3641
+ queryFn: () => unwrap(client.blog.post(handle, slug, locale)),
3642
+ enabled: options?.enabled !== false && !!handle && !!slug
3643
+ });
3644
+ }
3645
+
3646
+ // src/react/hooks/use-site-form.ts
3647
+ import { useCallback as useCallback15, useMemo as useMemo4 } from "react";
3648
+ import { useMutation as useMutation15, useQuery as useQuery31 } from "@tanstack/react-query";
3649
+
3650
+ // src/errors.ts
3651
+ function bodyOf(err) {
3652
+ const body = err instanceof BehioApiError ? err.body : err && typeof err === "object" && "body" in err ? err.body : err;
3653
+ return body && typeof body === "object" ? body : null;
3654
+ }
3655
+ function errorCode(err) {
3656
+ const body = bodyOf(err);
3657
+ if (!body) return null;
3658
+ const code = body.code ?? body.key;
3659
+ return typeof code === "string" && code.startsWith("be.") ? code : null;
3660
+ }
3661
+ function errorParams(err) {
3662
+ const body = bodyOf(err);
3663
+ const params = body?.params;
3664
+ return params && typeof params === "object" && !Array.isArray(params) ? params : {};
3665
+ }
3666
+ var FORM_FIELD_ERROR_CODES = /* @__PURE__ */ new Set([
3667
+ "required",
3668
+ "invalid",
3669
+ "tooShort",
3670
+ "tooLong",
3671
+ "min",
3672
+ "max",
3673
+ "notOption",
3674
+ "pattern"
3675
+ ]);
3676
+ function formFieldErrors(err) {
3677
+ if (errorCode(err) !== "be.forms.validationFailed") return [];
3678
+ const raw = errorParams(err).errors;
3679
+ if (!Array.isArray(raw)) return [];
3680
+ const out = [];
3681
+ for (const entry of raw) {
3682
+ if (typeof entry !== "string") continue;
3683
+ const idx = entry.lastIndexOf(":");
3684
+ if (idx <= 0) continue;
3685
+ const key = entry.slice(0, idx);
3686
+ const code = entry.slice(idx + 1);
3687
+ if (!FORM_FIELD_ERROR_CODES.has(code)) continue;
3688
+ out.push({ key, code });
3689
+ }
3690
+ return out;
3691
+ }
3692
+
3693
+ // src/react/hooks/use-site-form.ts
3694
+ function useSiteForm(slug, options) {
3695
+ const { client } = useBehio();
3696
+ return useQuery31({
3697
+ queryKey: ["behio", "form", slug],
3698
+ queryFn: () => unwrap(client.forms.get(slug)),
3699
+ enabled: options?.enabled !== false && !!slug
3700
+ });
3701
+ }
3702
+ function useSiteFormSubmit(slug) {
3703
+ const { client } = useBehio();
3704
+ const mutation = useMutation15({
3705
+ mutationFn: (input) => unwrap(client.forms.submit(slug, input))
3706
+ });
3707
+ const sdkError = mutation.error instanceof UnwrappedError ? mutation.error.sdkError : null;
3708
+ const fieldErrors = useMemo4(() => {
3709
+ const out = {};
3710
+ for (const e of formFieldErrors(sdkError)) out[e.key] = e.code;
3711
+ return out;
3712
+ }, [sdkError]);
3713
+ const errorCode2 = useMemo4(() => {
3714
+ const body = sdkError?.body;
3715
+ const code = body?.code ?? body?.key;
3716
+ return typeof code === "string" ? code : sdkError ? sdkError.code : null;
3717
+ }, [sdkError]);
3718
+ const submit = useCallback15(
3719
+ (input) => mutation.mutateAsync(input).catch(() => null),
3720
+ [mutation]
3721
+ );
3722
+ return {
3723
+ /** Resolves to the result, or null when the submit was rejected (see `fieldErrors` / `errorCode`). */
3724
+ submit,
3725
+ isSubmitting: mutation.isPending,
3726
+ isSuccess: mutation.isSuccess,
3727
+ /** `{ok, id, message, redirectUrl}` after a successful submit. */
3728
+ result: mutation.data ?? null,
3729
+ /** Field key -> validation code after a rejected submit. */
3730
+ fieldErrors,
3731
+ /** Backend error key (`be.forms.*`) or SDK code when the rejection is not per field. */
3732
+ errorCode: errorCode2,
3733
+ /** Raw SDK error (pass to `errorMessage(error, locale)` for a sentence). */
3734
+ error: sdkError,
3735
+ reset: mutation.reset
3736
+ };
3737
+ }
3738
+
3739
+ // src/react/hooks/use-shop-info.ts
3740
+ import { useQuery as useQuery32 } from "@tanstack/react-query";
3741
+ function useShopInfo(options) {
3742
+ const { client } = useBehio();
3743
+ return useQuery32({
3469
3744
  queryKey: ["behio", "shop-info"],
3470
3745
  queryFn: () => unwrap(client.getShopInfo()),
3471
3746
  enabled: options?.enabled !== false
@@ -3473,10 +3748,10 @@ function useShopInfo(options) {
3473
3748
  }
3474
3749
 
3475
3750
  // src/react/hooks/use-shop-scripts.ts
3476
- import { useQuery as useQuery31 } from "@tanstack/react-query";
3751
+ import { useQuery as useQuery33 } from "@tanstack/react-query";
3477
3752
  function useShopScripts(options) {
3478
3753
  const { client } = useBehio();
3479
- return useQuery31({
3754
+ return useQuery33({
3480
3755
  queryKey: ["behio", "shop-scripts"],
3481
3756
  queryFn: () => unwrap(client.getShopScripts()),
3482
3757
  enabled: options?.enabled !== false
@@ -3484,11 +3759,11 @@ function useShopScripts(options) {
3484
3759
  }
3485
3760
 
3486
3761
  // src/react/hooks/use-shop-seo.ts
3487
- import { useQuery as useQuery32 } from "@tanstack/react-query";
3762
+ import { useQuery as useQuery34 } from "@tanstack/react-query";
3488
3763
  function useShopSeo(options) {
3489
3764
  const { client } = useBehio();
3490
3765
  const { locale, initialData, enabled = true } = options ?? {};
3491
- return useQuery32({
3766
+ return useQuery34({
3492
3767
  queryKey: ["behio", "shop-seo", locale ?? "_default"],
3493
3768
  queryFn: () => unwrap(client.getShopSeo(locale)),
3494
3769
  initialData,
@@ -3548,23 +3823,23 @@ function CurrencySwitcher({
3548
3823
  }
3549
3824
 
3550
3825
  // src/react/components/storefront-scripts.tsx
3551
- import { useEffect as useEffect6, useMemo as useMemo4, useState as useState10 } from "react";
3826
+ import { useEffect as useEffect6, useMemo as useMemo5, useState as useState10 } from "react";
3552
3827
 
3553
3828
  // src/react/hooks/use-consent.ts
3554
- import { useQuery as useQuery33, useMutation as useMutation15, useQueryClient as useQueryClient16 } from "@tanstack/react-query";
3829
+ import { useQuery as useQuery35, useMutation as useMutation16, useQueryClient as useQueryClient16 } from "@tanstack/react-query";
3555
3830
  function useCookieConsent(visitorId) {
3556
3831
  const { client } = useBehio();
3557
3832
  const qc = useQueryClient16();
3558
- const query = useQuery33({
3833
+ const query = useQuery35({
3559
3834
  queryKey: ["behio", "consent", visitorId],
3560
3835
  queryFn: () => unwrap(client.consent.get(visitorId)),
3561
3836
  enabled: Boolean(visitorId)
3562
3837
  });
3563
- const recordMutation = useMutation15({
3838
+ const recordMutation = useMutation16({
3564
3839
  mutationFn: (input) => unwrap(client.consent.record(input)),
3565
3840
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "consent"] })
3566
3841
  });
3567
- const revokeMutation = useMutation15({
3842
+ const revokeMutation = useMutation16({
3568
3843
  mutationFn: () => unwrap(client.consent.revoke(visitorId)),
3569
3844
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "consent"] })
3570
3845
  });
@@ -3649,11 +3924,11 @@ function StorefrontScripts({ visitorId: visitorIdProp } = {}) {
3649
3924
  }, [visitorIdProp]);
3650
3925
  const { data: consent } = useCookieConsent(visitorId || void 0);
3651
3926
  const analyticsOk = Boolean(consent?.analytics);
3652
- const scripts = useMemo4(
3927
+ const scripts = useMemo5(
3653
3928
  () => (data?.scripts ?? []).filter((s) => !s.consentRequired || analyticsOk),
3654
3929
  [data, analyticsOk]
3655
3930
  );
3656
- const signature = useMemo4(
3931
+ const signature = useMemo5(
3657
3932
  () => JSON.stringify(scripts.map((s) => [s.id, s.type, s.placement, s.value])),
3658
3933
  [scripts]
3659
3934
  );
@@ -3923,10 +4198,10 @@ function utmFromSearch(search) {
3923
4198
  }
3924
4199
 
3925
4200
  // src/react/hooks/use-bundles.ts
3926
- import { useQuery as useQuery34 } from "@tanstack/react-query";
4201
+ import { useQuery as useQuery36 } from "@tanstack/react-query";
3927
4202
  function useBundles(options) {
3928
4203
  const { client } = useBehio();
3929
- return useQuery34({
4204
+ return useQuery36({
3930
4205
  queryKey: ["behio", "bundles"],
3931
4206
  queryFn: () => unwrap(client.catalog.getBundles()),
3932
4207
  enabled: options?.enabled ?? true,
@@ -3935,7 +4210,7 @@ function useBundles(options) {
3935
4210
  }
3936
4211
  function useBundle(slug, options) {
3937
4212
  const { client } = useBehio();
3938
- return useQuery34({
4213
+ return useQuery36({
3939
4214
  queryKey: ["behio", "bundle", slug],
3940
4215
  queryFn: () => unwrap(client.catalog.getBundle(slug)),
3941
4216
  enabled: Boolean(slug) && (options?.enabled ?? true),
@@ -3944,10 +4219,10 @@ function useBundle(slug, options) {
3944
4219
  }
3945
4220
 
3946
4221
  // src/react/hooks/use-product-group.ts
3947
- import { useQuery as useQuery35 } from "@tanstack/react-query";
4222
+ import { useQuery as useQuery37 } from "@tanstack/react-query";
3948
4223
  function useProductGroup(slug, options) {
3949
4224
  const { client } = useBehio();
3950
- return useQuery35({
4225
+ return useQuery37({
3951
4226
  queryKey: ["behio", "product-group", slug, options?.locale, options?.currency],
3952
4227
  queryFn: () => unwrap(
3953
4228
  client.catalog.getProductGroup(slug, {
@@ -3961,10 +4236,10 @@ function useProductGroup(slug, options) {
3961
4236
  }
3962
4237
 
3963
4238
  // src/react/hooks/use-cross-sell.ts
3964
- import { useQuery as useQuery36 } from "@tanstack/react-query";
4239
+ import { useQuery as useQuery38 } from "@tanstack/react-query";
3965
4240
  function useCrossSell(productSlug, options) {
3966
4241
  const { client } = useBehio();
3967
- return useQuery36({
4242
+ return useQuery38({
3968
4243
  queryKey: ["behio", "cross-sell", productSlug, options?.locale, options?.currency],
3969
4244
  queryFn: () => unwrap(
3970
4245
  client.catalog.getCrossSell(productSlug, {
@@ -3978,10 +4253,10 @@ function useCrossSell(productSlug, options) {
3978
4253
  }
3979
4254
 
3980
4255
  // src/react/hooks/use-product-promotions.ts
3981
- import { useQuery as useQuery37 } from "@tanstack/react-query";
4256
+ import { useQuery as useQuery39 } from "@tanstack/react-query";
3982
4257
  function useProductPromotions(productSlug, options) {
3983
4258
  const { client } = useBehio();
3984
- return useQuery37({
4259
+ return useQuery39({
3985
4260
  queryKey: ["behio", "product-promotions", productSlug],
3986
4261
  queryFn: () => unwrap(client.catalog.getProductPromotions(productSlug)),
3987
4262
  enabled: Boolean(productSlug) && (options?.enabled ?? true),
@@ -3990,11 +4265,11 @@ function useProductPromotions(productSlug, options) {
3990
4265
  }
3991
4266
 
3992
4267
  // src/react/hooks/use-gift-card.ts
3993
- import { useQuery as useQuery38 } from "@tanstack/react-query";
4268
+ import { useQuery as useQuery40 } from "@tanstack/react-query";
3994
4269
  function useGiftCardBalance(code, options) {
3995
4270
  const { client } = useBehio();
3996
4271
  const trimmed = code?.trim();
3997
- return useQuery38({
4272
+ return useQuery40({
3998
4273
  queryKey: ["behio", "gift-card-balance", trimmed],
3999
4274
  queryFn: () => unwrap(client.catalog.checkGiftCard(trimmed)),
4000
4275
  enabled: Boolean(trimmed && trimmed.length >= 6) && (options?.enabled ?? true)
@@ -4002,20 +4277,20 @@ function useGiftCardBalance(code, options) {
4002
4277
  }
4003
4278
 
4004
4279
  // src/react/hooks/use-wishlist.ts
4005
- import { useQuery as useQuery39, useMutation as useMutation16, useQueryClient as useQueryClient17 } from "@tanstack/react-query";
4280
+ import { useQuery as useQuery41, useMutation as useMutation17, useQueryClient as useQueryClient17 } from "@tanstack/react-query";
4006
4281
  function useWishlist(options) {
4007
4282
  const { client } = useBehio();
4008
4283
  const qc = useQueryClient17();
4009
- const query = useQuery39({
4284
+ const query = useQuery41({
4010
4285
  queryKey: ["behio", "wishlist"],
4011
4286
  queryFn: () => unwrap(client.wishlist.get()),
4012
4287
  enabled: options?.enabled ?? true
4013
4288
  });
4014
- const addMutation = useMutation16({
4289
+ const addMutation = useMutation17({
4015
4290
  mutationFn: (productId) => unwrap(client.wishlist.add(productId)),
4016
4291
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "wishlist"] })
4017
4292
  });
4018
- const removeMutation = useMutation16({
4293
+ const removeMutation = useMutation17({
4019
4294
  mutationFn: (productId) => unwrap(client.wishlist.remove(productId)),
4020
4295
  onSuccess: () => qc.invalidateQueries({ queryKey: ["behio", "wishlist"] })
4021
4296
  });
@@ -4029,7 +4304,7 @@ function useWishlist(options) {
4029
4304
  }
4030
4305
  function useIsInWishlist(productId) {
4031
4306
  const { client } = useBehio();
4032
- return useQuery39({
4307
+ return useQuery41({
4033
4308
  queryKey: ["behio", "wishlist-check", productId],
4034
4309
  queryFn: () => unwrap(client.wishlist.isInWishlist(productId)),
4035
4310
  enabled: Boolean(productId)
@@ -4037,10 +4312,10 @@ function useIsInWishlist(productId) {
4037
4312
  }
4038
4313
 
4039
4314
  // src/react/hooks/use-reviews.ts
4040
- import { useQuery as useQuery40, useMutation as useMutation17, useQueryClient as useQueryClient18 } from "@tanstack/react-query";
4315
+ import { useQuery as useQuery42, useMutation as useMutation18, useQueryClient as useQueryClient18 } from "@tanstack/react-query";
4041
4316
  function useProductReviews(productId, options) {
4042
4317
  const { client } = useBehio();
4043
- return useQuery40({
4318
+ return useQuery42({
4044
4319
  queryKey: ["behio", "reviews", productId, options?.page ?? 1],
4045
4320
  queryFn: () => unwrap(client.reviews.getProductReviews(productId, options?.page, options?.limit)),
4046
4321
  enabled: Boolean(productId) && (options?.enabled ?? true)
@@ -4049,29 +4324,29 @@ function useProductReviews(productId, options) {
4049
4324
  function useSubmitReview() {
4050
4325
  const { client } = useBehio();
4051
4326
  const qc = useQueryClient18();
4052
- return useMutation17({
4327
+ return useMutation18({
4053
4328
  mutationFn: (input) => unwrap(client.reviews.submit(input)),
4054
4329
  onSuccess: (_, input) => qc.invalidateQueries({ queryKey: ["behio", "reviews", input.productId] })
4055
4330
  });
4056
4331
  }
4057
4332
 
4058
4333
  // src/react/hooks/use-returns.ts
4059
- import { useQuery as useQuery41, useMutation as useMutation18 } from "@tanstack/react-query";
4334
+ import { useQuery as useQuery43, useMutation as useMutation19 } from "@tanstack/react-query";
4060
4335
  function useLookupReturnableOrder() {
4061
4336
  const { client } = useBehio();
4062
- return useMutation18({
4337
+ return useMutation19({
4063
4338
  mutationFn: ({ orderNumber, email }) => unwrap(client.returns.lookupOrder(orderNumber, email))
4064
4339
  });
4065
4340
  }
4066
4341
  function useSubmitReturn() {
4067
4342
  const { client } = useBehio();
4068
- return useMutation18({
4343
+ return useMutation19({
4069
4344
  mutationFn: (input) => unwrap(client.returns.submit(input))
4070
4345
  });
4071
4346
  }
4072
4347
  function useReturnStatus(returnId, email) {
4073
4348
  const { client } = useBehio();
4074
- return useQuery41({
4349
+ return useQuery43({
4075
4350
  queryKey: ["behio", "return-status", returnId],
4076
4351
  queryFn: () => unwrap(client.returns.getStatus(returnId, email)),
4077
4352
  enabled: Boolean(returnId && email)
@@ -4079,16 +4354,16 @@ function useReturnStatus(returnId, email) {
4079
4354
  }
4080
4355
 
4081
4356
  // src/react/hooks/use-quotes.ts
4082
- import { useMutation as useMutation19, useQuery as useQuery42 } from "@tanstack/react-query";
4357
+ import { useMutation as useMutation20, useQuery as useQuery44 } from "@tanstack/react-query";
4083
4358
  function useSubmitQuote() {
4084
4359
  const { client } = useBehio();
4085
- return useMutation19({
4360
+ return useMutation20({
4086
4361
  mutationFn: (input) => unwrap(client.quotes.submit(input))
4087
4362
  });
4088
4363
  }
4089
4364
  function useQuoteStatus(quoteId, email) {
4090
4365
  const { client } = useBehio();
4091
- return useQuery42({
4366
+ return useQuery44({
4092
4367
  queryKey: ["behio", "quote-status", quoteId],
4093
4368
  queryFn: () => unwrap(client.quotes.getStatus(quoteId, email)),
4094
4369
  enabled: Boolean(quoteId && email)
@@ -4096,10 +4371,10 @@ function useQuoteStatus(quoteId, email) {
4096
4371
  }
4097
4372
 
4098
4373
  // src/react/hooks/use-back-in-stock.ts
4099
- import { useMutation as useMutation20 } from "@tanstack/react-query";
4374
+ import { useMutation as useMutation21 } from "@tanstack/react-query";
4100
4375
  function useNotifyWhenAvailable() {
4101
4376
  const { client } = useBehio();
4102
- return useMutation20({
4377
+ return useMutation21({
4103
4378
  mutationFn: ({ productId, email }) => unwrap(client.catalog.notifyWhenAvailable(productId, email))
4104
4379
  });
4105
4380
  }
@@ -4235,6 +4510,9 @@ export {
4235
4510
  useAuth,
4236
4511
  useBehio,
4237
4512
  useBehioClient,
4513
+ useBlogPost,
4514
+ useBlogPosts,
4515
+ useBlogs,
4238
4516
  useBundle,
4239
4517
  useBundles,
4240
4518
  useCart,
@@ -4288,6 +4566,8 @@ export {
4288
4566
  useShopInfo,
4289
4567
  useShopScripts,
4290
4568
  useShopSeo,
4569
+ useSiteForm,
4570
+ useSiteFormSubmit,
4291
4571
  useSubmitQuote,
4292
4572
  useSubmitReturn,
4293
4573
  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.18.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",