@behio/storefront-sdk 0.8.0 → 0.12.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.
@@ -123,6 +123,7 @@ var BehioStorefront = class {
123
123
  this.rateLimitReset = null;
124
124
  this.baseUrl = (config.baseUrl || "https://api.behio.com").replace(/\/$/, "");
125
125
  this.apiKey = config.apiKey;
126
+ this.shopDomain = config.shopDomain;
126
127
  this.defaultLocale = config.locale;
127
128
  this.defaultCurrency = config.currency;
128
129
  this.fetchFn = config.fetch || globalThis.fetch.bind(globalThis);
@@ -185,6 +186,28 @@ var BehioStorefront = class {
185
186
  clearCartSession() {
186
187
  this.cartSession = void 0;
187
188
  }
189
+ // --- Default currency / locale (runtime-switchable) ---
190
+ /**
191
+ * Set the default currency sent on every catalog request (unless a per-call
192
+ * `currency` overrides it). Read live at request time, so changing it takes
193
+ * effect immediately without rebuilding the client. Pass undefined to clear
194
+ * (falls back to the shop's default currency server-side).
195
+ */
196
+ setCurrency(currency) {
197
+ this.defaultCurrency = currency || void 0;
198
+ }
199
+ /** Get the current default currency, if any. */
200
+ getCurrency() {
201
+ return this.defaultCurrency;
202
+ }
203
+ /** Set the default locale sent on every catalog request (per-call wins). */
204
+ setLocale(locale) {
205
+ this.defaultLocale = locale || void 0;
206
+ }
207
+ /** Get the current default locale, if any. */
208
+ getLocale() {
209
+ return this.defaultLocale;
210
+ }
188
211
  // --- Event emitter ---
189
212
  /** Subscribe to SDK events. Returns an unsubscribe function. */
190
213
  on(event, handler) {
@@ -301,13 +324,19 @@ var BehioStorefront = class {
301
324
  "X-Api-Key": this.apiKey,
302
325
  "Content-Type": "application/json"
303
326
  };
327
+ if (this.shopDomain) {
328
+ headers["X-Shop-Domain"] = this.shopDomain;
329
+ }
304
330
  if (this.accessToken && _optionalChain([options, 'optionalAccess', _13 => _13.auth]) !== false) {
305
331
  headers["Authorization"] = `Bearer ${this.accessToken}`;
306
332
  }
307
333
  if (this.cartSession) {
308
334
  headers["X-Cart-Session"] = this.cartSession;
309
335
  }
310
- const bodyStr = _optionalChain([options, 'optionalAccess', _14 => _14.body]) ? JSON.stringify(options.body) : void 0;
336
+ if (_optionalChain([options, 'optionalAccess', _14 => _14.headers])) {
337
+ Object.assign(headers, options.headers);
338
+ }
339
+ const bodyStr = _optionalChain([options, 'optionalAccess', _15 => _15.body]) ? JSON.stringify(options.body) : void 0;
311
340
  let interceptedConfig = {
312
341
  url,
313
342
  method,
@@ -321,7 +350,7 @@ var BehioStorefront = class {
321
350
  for (let attempt = 0; attempt <= this.retries; attempt++) {
322
351
  const controller = new AbortController();
323
352
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
324
- if (_optionalChain([options, 'optionalAccess', _15 => _15.signal])) {
353
+ if (_optionalChain([options, 'optionalAccess', _16 => _16.signal])) {
325
354
  if (options.signal.aborted) {
326
355
  clearTimeout(timeoutId);
327
356
  throw new BehioNetworkError("Request aborted", false);
@@ -362,8 +391,8 @@ var BehioStorefront = class {
362
391
  this.emit("response", { method, path, status: res.status });
363
392
  if (!res.ok) {
364
393
  const body = await res.json().catch(() => null);
365
- const apiError = new BehioApiError(res.status, body, _optionalChain([body, 'optionalAccess', _16 => _16.message]) || `API Error ${res.status}`);
366
- if (res.status === 401 && this.refreshToken && _optionalChain([options, 'optionalAccess', _17 => _17.auth]) !== false && !_optionalChain([options, 'optionalAccess', _18 => _18._isRetryAfterRefresh])) {
394
+ const apiError = new BehioApiError(res.status, body, _optionalChain([body, 'optionalAccess', _17 => _17.message]) || `API Error ${res.status}`);
395
+ if (res.status === 401 && this.refreshToken && _optionalChain([options, 'optionalAccess', _18 => _18.auth]) !== false && !_optionalChain([options, 'optionalAccess', _19 => _19._isRetryAfterRefresh])) {
367
396
  try {
368
397
  await this.handleTokenRefresh();
369
398
  return this.rawRequest(method, path, { ...options, _isRetryAfterRefresh: true });
@@ -426,7 +455,7 @@ var CatalogModule = class {
426
455
  /** Get product detail by slug */
427
456
  async getProduct(slug, options) {
428
457
  return this.client.request("GET", `/catalog/products/${slug}`, {
429
- query: { locale: _optionalChain([options, 'optionalAccess', _19 => _19.locale]), currency: _optionalChain([options, 'optionalAccess', _20 => _20.currency]) }
458
+ query: { locale: _optionalChain([options, 'optionalAccess', _20 => _20.locale]), currency: _optionalChain([options, 'optionalAccess', _21 => _21.currency]) }
430
459
  });
431
460
  }
432
461
  /** Get category tree */
@@ -460,7 +489,7 @@ var CatalogModule = class {
460
489
  /** Get featured products */
461
490
  async getFeatured(options) {
462
491
  return this.client.request("GET", "/catalog/featured", {
463
- query: { locale: _optionalChain([options, 'optionalAccess', _21 => _21.locale]), currency: _optionalChain([options, 'optionalAccess', _22 => _22.currency]) }
492
+ query: { locale: _optionalChain([options, 'optionalAccess', _22 => _22.locale]), currency: _optionalChain([options, 'optionalAccess', _23 => _23.currency]) }
464
493
  });
465
494
  }
466
495
  /** Get available filter fields for dynamic filter UI */
@@ -505,7 +534,7 @@ var CatalogModule = class {
505
534
  /** List configured payment methods (filtered by currency). */
506
535
  async listPaymentMethods(opts) {
507
536
  const query = {};
508
- if (_optionalChain([opts, 'optionalAccess', _23 => _23.currency])) query.currency = opts.currency;
537
+ if (_optionalChain([opts, 'optionalAccess', _24 => _24.currency])) query.currency = opts.currency;
509
538
  return this.client.request("GET", "/catalog/payment-methods", { query });
510
539
  }
511
540
  };
@@ -746,7 +775,7 @@ var OrdersModule = class {
746
775
  /** List customer orders (requires auth) */
747
776
  async list(options) {
748
777
  return this.client.request("GET", "/orders", {
749
- query: { page: _optionalChain([options, 'optionalAccess', _24 => _24.page]), limit: _optionalChain([options, 'optionalAccess', _25 => _25.limit]) }
778
+ query: { page: _optionalChain([options, 'optionalAccess', _25 => _25.page]), limit: _optionalChain([options, 'optionalAccess', _26 => _26.limit]) }
750
779
  });
751
780
  }
752
781
  /** Get order detail (requires auth) */
@@ -757,10 +786,50 @@ var OrdersModule = class {
757
786
  async cancel(orderNumber) {
758
787
  return this.client.request("POST", `/orders/${orderNumber}/cancel`);
759
788
  }
760
- /** Track order by tracking token (no customer login required, only API key) */
789
+ /**
790
+ * Track an order by tracking token (no login, only API key). Returns a
791
+ * PII-minimized view: order status + items + masked email + destination
792
+ * city, never full address / phone / billing — the token travels in URLs
793
+ * and e-mails so it must not expose full personal data.
794
+ */
761
795
  async track(trackingToken) {
762
796
  return this.client.request("GET", `/orders/track/${trackingToken}`, { auth: false });
763
797
  }
798
+ /**
799
+ * Step 1 of guest order-access: request a 6-digit code e-mailed to the
800
+ * address on the order. The response is always generic (success) regardless
801
+ * of whether the order number + e-mail match, so order numbers can't be
802
+ * enumerated. No login, only API key.
803
+ */
804
+ async requestAccessCode(orderNumber, email) {
805
+ return this.client.request("POST", "/orders/access/request", {
806
+ auth: false,
807
+ body: { orderNumber, email }
808
+ });
809
+ }
810
+ /**
811
+ * Step 2 of guest order-access: verify the e-mailed code. On success returns
812
+ * the FULL order detail plus a short-lived `accessToken` you can pass to
813
+ * {@link getByAccessToken} to re-fetch the detail without re-entering the
814
+ * code. No login, only API key.
815
+ */
816
+ async verifyAccessCode(orderNumber, email, code) {
817
+ return this.client.request("POST", "/orders/access/verify", {
818
+ auth: false,
819
+ body: { orderNumber, email, code }
820
+ });
821
+ }
822
+ /**
823
+ * Re-fetch a guest order's full detail using the `accessToken` returned by
824
+ * {@link verifyAccessCode}. The token is scoped to that single order and
825
+ * expires after 30 minutes.
826
+ */
827
+ async getByAccessToken(accessToken) {
828
+ return this.client.request("GET", "/orders/access/detail", {
829
+ auth: false,
830
+ headers: { "X-Order-Access": accessToken }
831
+ });
832
+ }
764
833
  };
765
834
  var CustomerModule = class {
766
835
  constructor(client) {
@@ -860,8 +929,9 @@ var ReturnsModule = class {
860
929
  async submit(input) {
861
930
  return this.client.request("POST", "/returns", { body: input });
862
931
  }
932
+ /** Email is the ownership gate; POST so it never lands in a URL / log. */
863
933
  async getStatus(returnId, email) {
864
- return this.client.request("GET", `/returns/${returnId}/status`, { query: { email } });
934
+ return this.client.request("POST", `/returns/${returnId}/status`, { body: { email } });
865
935
  }
866
936
  };
867
937
  var ConsentModule = class {
@@ -928,10 +998,10 @@ var ShippingModule = class {
928
998
  */
929
999
  async listMethods(opts) {
930
1000
  const query = {};
931
- if (_optionalChain([opts, 'optionalAccess', _26 => _26.currency])) query.currency = opts.currency;
932
- if (_optionalChain([opts, 'optionalAccess', _27 => _27.country])) query.country = opts.country;
933
- if (_optionalChain([opts, 'optionalAccess', _28 => _28.cartTotal]) != null) query.cartTotal = String(opts.cartTotal);
934
- if (_optionalChain([opts, 'optionalAccess', _29 => _29.cartWeightKg]) != null) query.cartWeightKg = String(opts.cartWeightKg);
1001
+ if (_optionalChain([opts, 'optionalAccess', _27 => _27.currency])) query.currency = opts.currency;
1002
+ if (_optionalChain([opts, 'optionalAccess', _28 => _28.country])) query.country = opts.country;
1003
+ if (_optionalChain([opts, 'optionalAccess', _29 => _29.cartTotal]) != null) query.cartTotal = String(opts.cartTotal);
1004
+ if (_optionalChain([opts, 'optionalAccess', _30 => _30.cartWeightKg]) != null) query.cartWeightKg = String(opts.cartWeightKg);
935
1005
  return this.client.request(
936
1006
  "GET",
937
1007
  "/catalog/shipping-methods",
@@ -123,6 +123,7 @@ var BehioStorefront = class {
123
123
  this.rateLimitReset = null;
124
124
  this.baseUrl = (config.baseUrl || "https://api.behio.com").replace(/\/$/, "");
125
125
  this.apiKey = config.apiKey;
126
+ this.shopDomain = config.shopDomain;
126
127
  this.defaultLocale = config.locale;
127
128
  this.defaultCurrency = config.currency;
128
129
  this.fetchFn = config.fetch || globalThis.fetch.bind(globalThis);
@@ -185,6 +186,28 @@ var BehioStorefront = class {
185
186
  clearCartSession() {
186
187
  this.cartSession = void 0;
187
188
  }
189
+ // --- Default currency / locale (runtime-switchable) ---
190
+ /**
191
+ * Set the default currency sent on every catalog request (unless a per-call
192
+ * `currency` overrides it). Read live at request time, so changing it takes
193
+ * effect immediately without rebuilding the client. Pass undefined to clear
194
+ * (falls back to the shop's default currency server-side).
195
+ */
196
+ setCurrency(currency) {
197
+ this.defaultCurrency = currency || void 0;
198
+ }
199
+ /** Get the current default currency, if any. */
200
+ getCurrency() {
201
+ return this.defaultCurrency;
202
+ }
203
+ /** Set the default locale sent on every catalog request (per-call wins). */
204
+ setLocale(locale) {
205
+ this.defaultLocale = locale || void 0;
206
+ }
207
+ /** Get the current default locale, if any. */
208
+ getLocale() {
209
+ return this.defaultLocale;
210
+ }
188
211
  // --- Event emitter ---
189
212
  /** Subscribe to SDK events. Returns an unsubscribe function. */
190
213
  on(event, handler) {
@@ -301,12 +324,18 @@ var BehioStorefront = class {
301
324
  "X-Api-Key": this.apiKey,
302
325
  "Content-Type": "application/json"
303
326
  };
327
+ if (this.shopDomain) {
328
+ headers["X-Shop-Domain"] = this.shopDomain;
329
+ }
304
330
  if (this.accessToken && options?.auth !== false) {
305
331
  headers["Authorization"] = `Bearer ${this.accessToken}`;
306
332
  }
307
333
  if (this.cartSession) {
308
334
  headers["X-Cart-Session"] = this.cartSession;
309
335
  }
336
+ if (options?.headers) {
337
+ Object.assign(headers, options.headers);
338
+ }
310
339
  const bodyStr = options?.body ? JSON.stringify(options.body) : void 0;
311
340
  let interceptedConfig = {
312
341
  url,
@@ -757,10 +786,50 @@ var OrdersModule = class {
757
786
  async cancel(orderNumber) {
758
787
  return this.client.request("POST", `/orders/${orderNumber}/cancel`);
759
788
  }
760
- /** Track order by tracking token (no customer login required, only API key) */
789
+ /**
790
+ * Track an order by tracking token (no login, only API key). Returns a
791
+ * PII-minimized view: order status + items + masked email + destination
792
+ * city, never full address / phone / billing — the token travels in URLs
793
+ * and e-mails so it must not expose full personal data.
794
+ */
761
795
  async track(trackingToken) {
762
796
  return this.client.request("GET", `/orders/track/${trackingToken}`, { auth: false });
763
797
  }
798
+ /**
799
+ * Step 1 of guest order-access: request a 6-digit code e-mailed to the
800
+ * address on the order. The response is always generic (success) regardless
801
+ * of whether the order number + e-mail match, so order numbers can't be
802
+ * enumerated. No login, only API key.
803
+ */
804
+ async requestAccessCode(orderNumber, email) {
805
+ return this.client.request("POST", "/orders/access/request", {
806
+ auth: false,
807
+ body: { orderNumber, email }
808
+ });
809
+ }
810
+ /**
811
+ * Step 2 of guest order-access: verify the e-mailed code. On success returns
812
+ * the FULL order detail plus a short-lived `accessToken` you can pass to
813
+ * {@link getByAccessToken} to re-fetch the detail without re-entering the
814
+ * code. No login, only API key.
815
+ */
816
+ async verifyAccessCode(orderNumber, email, code) {
817
+ return this.client.request("POST", "/orders/access/verify", {
818
+ auth: false,
819
+ body: { orderNumber, email, code }
820
+ });
821
+ }
822
+ /**
823
+ * Re-fetch a guest order's full detail using the `accessToken` returned by
824
+ * {@link verifyAccessCode}. The token is scoped to that single order and
825
+ * expires after 30 minutes.
826
+ */
827
+ async getByAccessToken(accessToken) {
828
+ return this.client.request("GET", "/orders/access/detail", {
829
+ auth: false,
830
+ headers: { "X-Order-Access": accessToken }
831
+ });
832
+ }
764
833
  };
765
834
  var CustomerModule = class {
766
835
  constructor(client) {
@@ -860,8 +929,9 @@ var ReturnsModule = class {
860
929
  async submit(input) {
861
930
  return this.client.request("POST", "/returns", { body: input });
862
931
  }
932
+ /** Email is the ownership gate; POST so it never lands in a URL / log. */
863
933
  async getStatus(returnId, email) {
864
- return this.client.request("GET", `/returns/${returnId}/status`, { query: { email } });
934
+ return this.client.request("POST", `/returns/${returnId}/status`, { body: { email } });
865
935
  }
866
936
  };
867
937
  var ConsentModule = class {
package/dist/index.d.mts CHANGED
@@ -3,6 +3,14 @@ interface BehioStorefrontConfig {
3
3
  apiKey: string;
4
4
  /** Backend base URL. Default: https://api.behio.com */
5
5
  baseUrl?: string;
6
+ /**
7
+ * The domain this storefront is served on (e.g. "mujshop.cz"), sent as
8
+ * X-Shop-Domain. Only needed when ONE deployment serves several domains with
9
+ * a single "all domains" API key (e.g. a Vercel app behind mujshop.cz +
10
+ * mujshop.sk) AND there's no Origin header (server-side rendering). A
11
+ * domain-bound key, or a browser request (Origin), doesn't need it.
12
+ */
13
+ shopDomain?: string;
6
14
  /** Default locale for catalog requests. Default: none (uses shop default) */
7
15
  locale?: string;
8
16
  /** Default currency for price resolution. Default: none (uses shop default) */
@@ -392,6 +400,25 @@ interface OrderItem {
392
400
  totalPrice: number;
393
401
  totalPriceWithTax: number;
394
402
  }
403
+ /**
404
+ * PII-minimized order view returned by `orders.track(token)`. The tracking
405
+ * token is shared in URLs and e-mails, so this deliberately omits full
406
+ * address, phone, billing and customer note, and masks the email.
407
+ */
408
+ interface OrderTracking {
409
+ orderNumber: string;
410
+ status: OrderStatus;
411
+ paymentStatus: PaymentStatus;
412
+ fulfillmentStatus: FulfillmentStatus;
413
+ currency: string;
414
+ grandTotal: number;
415
+ /** Masked, e.g. "j***@e***.cz" */
416
+ emailMasked: string;
417
+ shippingCity: string | null;
418
+ shippingCountry: string | null;
419
+ items: OrderItem[];
420
+ createdAt: number;
421
+ }
395
422
  interface OrderStatusHistory {
396
423
  fromStatus?: OrderStatus;
397
424
  toStatus: OrderStatus;
@@ -421,6 +448,19 @@ interface OrderDetail extends OrderListItem {
421
448
  */
422
449
  paymentRedirectUrl?: string | null;
423
450
  }
451
+ /** Generic response to `orders.requestAccessCode` — never reveals existence. */
452
+ interface OrderAccessRequestResponse {
453
+ success: boolean;
454
+ message: string;
455
+ }
456
+ /** Response to a successful `orders.verifyAccessCode`. */
457
+ interface OrderAccessVerifyResponse {
458
+ /** Short-lived JWT scoped to this single order (use with `getByAccessToken`). */
459
+ accessToken: string;
460
+ /** Token lifetime in seconds. */
461
+ expiresIn: number;
462
+ order: OrderDetail;
463
+ }
424
464
  interface CustomerProfile {
425
465
  id: string;
426
466
  email: string;
@@ -854,6 +894,7 @@ interface SubmitQuoteInput {
854
894
  declare class BehioStorefront {
855
895
  private baseUrl;
856
896
  private apiKey;
897
+ private shopDomain?;
857
898
  private defaultLocale?;
858
899
  private defaultCurrency?;
859
900
  private fetchFn;
@@ -906,6 +947,19 @@ declare class BehioStorefront {
906
947
  getCartSession(): string | undefined;
907
948
  /** Clear cart session */
908
949
  clearCartSession(): void;
950
+ /**
951
+ * Set the default currency sent on every catalog request (unless a per-call
952
+ * `currency` overrides it). Read live at request time, so changing it takes
953
+ * effect immediately without rebuilding the client. Pass undefined to clear
954
+ * (falls back to the shop's default currency server-side).
955
+ */
956
+ setCurrency(currency: string | undefined): void;
957
+ /** Get the current default currency, if any. */
958
+ getCurrency(): string | undefined;
959
+ /** Set the default locale sent on every catalog request (per-call wins). */
960
+ setLocale(locale: string | undefined): void;
961
+ /** Get the current default locale, if any. */
962
+ getLocale(): string | undefined;
909
963
  /** Subscribe to SDK events. Returns an unsubscribe function. */
910
964
  on(event: BehioEventType, handler: BehioEventHandler): () => void;
911
965
  /** @internal Emit an event (fire-and-forget, handler errors are swallowed) */
@@ -933,6 +987,7 @@ declare class BehioStorefront {
933
987
  query?: Record<string, string | number | boolean | undefined | string[] | number[]>;
934
988
  auth?: boolean;
935
989
  signal?: AbortSignal;
990
+ headers?: Record<string, string>;
936
991
  }): Promise<SdkResult<T>>;
937
992
  /**
938
993
  * Throws on failure (API error / network / timeout). Kept private so
@@ -1094,8 +1149,33 @@ declare class OrdersModule {
1094
1149
  get(orderNumber: string): Promise<SdkResult<OrderDetail>>;
1095
1150
  /** Cancel a PENDING order (requires auth) */
1096
1151
  cancel(orderNumber: string): Promise<SdkResult<OrderDetail>>;
1097
- /** Track order by tracking token (no customer login required, only API key) */
1098
- track(trackingToken: string): Promise<SdkResult<OrderDetail>>;
1152
+ /**
1153
+ * Track an order by tracking token (no login, only API key). Returns a
1154
+ * PII-minimized view: order status + items + masked email + destination
1155
+ * city, never full address / phone / billing — the token travels in URLs
1156
+ * and e-mails so it must not expose full personal data.
1157
+ */
1158
+ track(trackingToken: string): Promise<SdkResult<OrderTracking>>;
1159
+ /**
1160
+ * Step 1 of guest order-access: request a 6-digit code e-mailed to the
1161
+ * address on the order. The response is always generic (success) regardless
1162
+ * of whether the order number + e-mail match, so order numbers can't be
1163
+ * enumerated. No login, only API key.
1164
+ */
1165
+ requestAccessCode(orderNumber: string, email: string): Promise<SdkResult<OrderAccessRequestResponse>>;
1166
+ /**
1167
+ * Step 2 of guest order-access: verify the e-mailed code. On success returns
1168
+ * the FULL order detail plus a short-lived `accessToken` you can pass to
1169
+ * {@link getByAccessToken} to re-fetch the detail without re-entering the
1170
+ * code. No login, only API key.
1171
+ */
1172
+ verifyAccessCode(orderNumber: string, email: string, code: string): Promise<SdkResult<OrderAccessVerifyResponse>>;
1173
+ /**
1174
+ * Re-fetch a guest order's full detail using the `accessToken` returned by
1175
+ * {@link verifyAccessCode}. The token is scoped to that single order and
1176
+ * expires after 30 minutes.
1177
+ */
1178
+ getByAccessToken(accessToken: string): Promise<SdkResult<OrderDetail>>;
1099
1179
  }
1100
1180
  declare class CustomerModule {
1101
1181
  private client;
@@ -1164,6 +1244,7 @@ declare class ReturnsModule {
1164
1244
  */
1165
1245
  lookupOrder(orderNumber: string, email: string): Promise<SdkResult<ReturnableOrder>>;
1166
1246
  submit(input: SubmitReturnInput): Promise<SdkResult<ReturnRequest>>;
1247
+ /** Email is the ownership gate; POST so it never lands in a URL / log. */
1167
1248
  getStatus(returnId: string, email: string): Promise<SdkResult<ReturnStatus>>;
1168
1249
  }
1169
1250
  declare class ConsentModule {
@@ -1256,4 +1337,4 @@ declare class ShippingModule {
1256
1337
  }>>;
1257
1338
  }
1258
1339
 
1259
- export { type ActivePromotion, type AddToCartInput, type AddressDetail, type AddressSuggestion, type AddressType, AddressTypes, type AuthTokens, type BackInStockSubscription, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Bundle, type BundleItem, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CheckoutPaymentMethod, type CookieConsent, type CookieConsentInput, type CrossSellItem, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type GiftCardBalance, type LoginInput, type MessageResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type Page, type PageAttachment, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductMedia, type ProductMediaVariant, type ProductPrice, type ProductReview, type ProductReviewsResponse, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type QuoteItem, type QuoteRequest, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ReturnRequest, type ReturnRequestItem, type ReturnStatus, type ReturnStatusItem, type ReturnableOrder, type ReturnableOrderItem, type SdkError, type SdkResult, type ShippingMethodSummary, type ShippingQuote, type ShippingQuoteInput, type ShopInfo, type ShopSeo, type SubmitQuoteInput, type SubmitReturnInput, type SubmitReviewInput, type WishlistItem, err, ok, toSdkError };
1340
+ export { type ActivePromotion, type AddToCartInput, type AddressDetail, type AddressSuggestion, type AddressType, AddressTypes, type AuthTokens, type BackInStockSubscription, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Bundle, type BundleItem, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CheckoutPaymentMethod, type CookieConsent, type CookieConsentInput, type CrossSellItem, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type GiftCardBalance, type LoginInput, type MessageResponse, type OrderAccessRequestResponse, type OrderAccessVerifyResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type OrderTracking, type Page, type PageAttachment, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductMedia, type ProductMediaVariant, type ProductPrice, type ProductReview, type ProductReviewsResponse, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type QuoteItem, type QuoteRequest, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ReturnRequest, type ReturnRequestItem, type ReturnStatus, type ReturnStatusItem, type ReturnableOrder, type ReturnableOrderItem, type SdkError, type SdkResult, type ShippingMethodSummary, type ShippingQuote, type ShippingQuoteInput, type ShopInfo, type ShopSeo, type SubmitQuoteInput, type SubmitReturnInput, type SubmitReviewInput, type WishlistItem, err, ok, toSdkError };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,14 @@ interface BehioStorefrontConfig {
3
3
  apiKey: string;
4
4
  /** Backend base URL. Default: https://api.behio.com */
5
5
  baseUrl?: string;
6
+ /**
7
+ * The domain this storefront is served on (e.g. "mujshop.cz"), sent as
8
+ * X-Shop-Domain. Only needed when ONE deployment serves several domains with
9
+ * a single "all domains" API key (e.g. a Vercel app behind mujshop.cz +
10
+ * mujshop.sk) AND there's no Origin header (server-side rendering). A
11
+ * domain-bound key, or a browser request (Origin), doesn't need it.
12
+ */
13
+ shopDomain?: string;
6
14
  /** Default locale for catalog requests. Default: none (uses shop default) */
7
15
  locale?: string;
8
16
  /** Default currency for price resolution. Default: none (uses shop default) */
@@ -392,6 +400,25 @@ interface OrderItem {
392
400
  totalPrice: number;
393
401
  totalPriceWithTax: number;
394
402
  }
403
+ /**
404
+ * PII-minimized order view returned by `orders.track(token)`. The tracking
405
+ * token is shared in URLs and e-mails, so this deliberately omits full
406
+ * address, phone, billing and customer note, and masks the email.
407
+ */
408
+ interface OrderTracking {
409
+ orderNumber: string;
410
+ status: OrderStatus;
411
+ paymentStatus: PaymentStatus;
412
+ fulfillmentStatus: FulfillmentStatus;
413
+ currency: string;
414
+ grandTotal: number;
415
+ /** Masked, e.g. "j***@e***.cz" */
416
+ emailMasked: string;
417
+ shippingCity: string | null;
418
+ shippingCountry: string | null;
419
+ items: OrderItem[];
420
+ createdAt: number;
421
+ }
395
422
  interface OrderStatusHistory {
396
423
  fromStatus?: OrderStatus;
397
424
  toStatus: OrderStatus;
@@ -421,6 +448,19 @@ interface OrderDetail extends OrderListItem {
421
448
  */
422
449
  paymentRedirectUrl?: string | null;
423
450
  }
451
+ /** Generic response to `orders.requestAccessCode` — never reveals existence. */
452
+ interface OrderAccessRequestResponse {
453
+ success: boolean;
454
+ message: string;
455
+ }
456
+ /** Response to a successful `orders.verifyAccessCode`. */
457
+ interface OrderAccessVerifyResponse {
458
+ /** Short-lived JWT scoped to this single order (use with `getByAccessToken`). */
459
+ accessToken: string;
460
+ /** Token lifetime in seconds. */
461
+ expiresIn: number;
462
+ order: OrderDetail;
463
+ }
424
464
  interface CustomerProfile {
425
465
  id: string;
426
466
  email: string;
@@ -854,6 +894,7 @@ interface SubmitQuoteInput {
854
894
  declare class BehioStorefront {
855
895
  private baseUrl;
856
896
  private apiKey;
897
+ private shopDomain?;
857
898
  private defaultLocale?;
858
899
  private defaultCurrency?;
859
900
  private fetchFn;
@@ -906,6 +947,19 @@ declare class BehioStorefront {
906
947
  getCartSession(): string | undefined;
907
948
  /** Clear cart session */
908
949
  clearCartSession(): void;
950
+ /**
951
+ * Set the default currency sent on every catalog request (unless a per-call
952
+ * `currency` overrides it). Read live at request time, so changing it takes
953
+ * effect immediately without rebuilding the client. Pass undefined to clear
954
+ * (falls back to the shop's default currency server-side).
955
+ */
956
+ setCurrency(currency: string | undefined): void;
957
+ /** Get the current default currency, if any. */
958
+ getCurrency(): string | undefined;
959
+ /** Set the default locale sent on every catalog request (per-call wins). */
960
+ setLocale(locale: string | undefined): void;
961
+ /** Get the current default locale, if any. */
962
+ getLocale(): string | undefined;
909
963
  /** Subscribe to SDK events. Returns an unsubscribe function. */
910
964
  on(event: BehioEventType, handler: BehioEventHandler): () => void;
911
965
  /** @internal Emit an event (fire-and-forget, handler errors are swallowed) */
@@ -933,6 +987,7 @@ declare class BehioStorefront {
933
987
  query?: Record<string, string | number | boolean | undefined | string[] | number[]>;
934
988
  auth?: boolean;
935
989
  signal?: AbortSignal;
990
+ headers?: Record<string, string>;
936
991
  }): Promise<SdkResult<T>>;
937
992
  /**
938
993
  * Throws on failure (API error / network / timeout). Kept private so
@@ -1094,8 +1149,33 @@ declare class OrdersModule {
1094
1149
  get(orderNumber: string): Promise<SdkResult<OrderDetail>>;
1095
1150
  /** Cancel a PENDING order (requires auth) */
1096
1151
  cancel(orderNumber: string): Promise<SdkResult<OrderDetail>>;
1097
- /** Track order by tracking token (no customer login required, only API key) */
1098
- track(trackingToken: string): Promise<SdkResult<OrderDetail>>;
1152
+ /**
1153
+ * Track an order by tracking token (no login, only API key). Returns a
1154
+ * PII-minimized view: order status + items + masked email + destination
1155
+ * city, never full address / phone / billing — the token travels in URLs
1156
+ * and e-mails so it must not expose full personal data.
1157
+ */
1158
+ track(trackingToken: string): Promise<SdkResult<OrderTracking>>;
1159
+ /**
1160
+ * Step 1 of guest order-access: request a 6-digit code e-mailed to the
1161
+ * address on the order. The response is always generic (success) regardless
1162
+ * of whether the order number + e-mail match, so order numbers can't be
1163
+ * enumerated. No login, only API key.
1164
+ */
1165
+ requestAccessCode(orderNumber: string, email: string): Promise<SdkResult<OrderAccessRequestResponse>>;
1166
+ /**
1167
+ * Step 2 of guest order-access: verify the e-mailed code. On success returns
1168
+ * the FULL order detail plus a short-lived `accessToken` you can pass to
1169
+ * {@link getByAccessToken} to re-fetch the detail without re-entering the
1170
+ * code. No login, only API key.
1171
+ */
1172
+ verifyAccessCode(orderNumber: string, email: string, code: string): Promise<SdkResult<OrderAccessVerifyResponse>>;
1173
+ /**
1174
+ * Re-fetch a guest order's full detail using the `accessToken` returned by
1175
+ * {@link verifyAccessCode}. The token is scoped to that single order and
1176
+ * expires after 30 minutes.
1177
+ */
1178
+ getByAccessToken(accessToken: string): Promise<SdkResult<OrderDetail>>;
1099
1179
  }
1100
1180
  declare class CustomerModule {
1101
1181
  private client;
@@ -1164,6 +1244,7 @@ declare class ReturnsModule {
1164
1244
  */
1165
1245
  lookupOrder(orderNumber: string, email: string): Promise<SdkResult<ReturnableOrder>>;
1166
1246
  submit(input: SubmitReturnInput): Promise<SdkResult<ReturnRequest>>;
1247
+ /** Email is the ownership gate; POST so it never lands in a URL / log. */
1167
1248
  getStatus(returnId: string, email: string): Promise<SdkResult<ReturnStatus>>;
1168
1249
  }
1169
1250
  declare class ConsentModule {
@@ -1256,4 +1337,4 @@ declare class ShippingModule {
1256
1337
  }>>;
1257
1338
  }
1258
1339
 
1259
- export { type ActivePromotion, type AddToCartInput, type AddressDetail, type AddressSuggestion, type AddressType, AddressTypes, type AuthTokens, type BackInStockSubscription, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Bundle, type BundleItem, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CheckoutPaymentMethod, type CookieConsent, type CookieConsentInput, type CrossSellItem, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type GiftCardBalance, type LoginInput, type MessageResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type Page, type PageAttachment, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductMedia, type ProductMediaVariant, type ProductPrice, type ProductReview, type ProductReviewsResponse, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type QuoteItem, type QuoteRequest, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ReturnRequest, type ReturnRequestItem, type ReturnStatus, type ReturnStatusItem, type ReturnableOrder, type ReturnableOrderItem, type SdkError, type SdkResult, type ShippingMethodSummary, type ShippingQuote, type ShippingQuoteInput, type ShopInfo, type ShopSeo, type SubmitQuoteInput, type SubmitReturnInput, type SubmitReviewInput, type WishlistItem, err, ok, toSdkError };
1340
+ export { type ActivePromotion, type AddToCartInput, type AddressDetail, type AddressSuggestion, type AddressType, AddressTypes, type AuthTokens, type BackInStockSubscription, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Bundle, type BundleItem, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CheckoutPaymentMethod, type CookieConsent, type CookieConsentInput, type CrossSellItem, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type GiftCardBalance, type LoginInput, type MessageResponse, type OrderAccessRequestResponse, type OrderAccessVerifyResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type OrderTracking, type Page, type PageAttachment, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductMedia, type ProductMediaVariant, type ProductPrice, type ProductReview, type ProductReviewsResponse, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type QuoteItem, type QuoteRequest, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ReturnRequest, type ReturnRequestItem, type ReturnStatus, type ReturnStatusItem, type ReturnableOrder, type ReturnableOrderItem, type SdkError, type SdkResult, type ShippingMethodSummary, type ShippingQuote, type ShippingQuoteInput, type ShopInfo, type ShopSeo, type SubmitQuoteInput, type SubmitReturnInput, type SubmitReviewInput, type WishlistItem, err, ok, toSdkError };
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkDMTMGPUZjs = require('./chunk-DMTMGPUZ.js');
13
+ var _chunkGGUHYQNFjs = require('./chunk-GGUHYQNF.js');
14
14
 
15
15
 
16
16
 
@@ -23,4 +23,4 @@ var _chunkDMTMGPUZjs = require('./chunk-DMTMGPUZ.js');
23
23
 
24
24
 
25
25
 
26
- exports.AddressTypes = _chunkDMTMGPUZjs.AddressTypes; exports.BehioApiError = _chunkDMTMGPUZjs.BehioApiError; exports.BehioNetworkError = _chunkDMTMGPUZjs.BehioNetworkError; exports.BehioStorefront = _chunkDMTMGPUZjs.BehioStorefront; exports.FulfillmentStatuses = _chunkDMTMGPUZjs.FulfillmentStatuses; exports.OrderStatuses = _chunkDMTMGPUZjs.OrderStatuses; exports.PaymentStatuses = _chunkDMTMGPUZjs.PaymentStatuses; exports.ProductSort = _chunkDMTMGPUZjs.ProductSort; exports.err = _chunkDMTMGPUZjs.err; exports.ok = _chunkDMTMGPUZjs.ok; exports.toSdkError = _chunkDMTMGPUZjs.toSdkError;
26
+ exports.AddressTypes = _chunkGGUHYQNFjs.AddressTypes; exports.BehioApiError = _chunkGGUHYQNFjs.BehioApiError; exports.BehioNetworkError = _chunkGGUHYQNFjs.BehioNetworkError; exports.BehioStorefront = _chunkGGUHYQNFjs.BehioStorefront; exports.FulfillmentStatuses = _chunkGGUHYQNFjs.FulfillmentStatuses; exports.OrderStatuses = _chunkGGUHYQNFjs.OrderStatuses; exports.PaymentStatuses = _chunkGGUHYQNFjs.PaymentStatuses; exports.ProductSort = _chunkGGUHYQNFjs.ProductSort; exports.err = _chunkGGUHYQNFjs.err; exports.ok = _chunkGGUHYQNFjs.ok; exports.toSdkError = _chunkGGUHYQNFjs.toSdkError;
package/dist/index.mjs CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  err,
11
11
  ok,
12
12
  toSdkError
13
- } from "./chunk-EZEZUV2B.mjs";
13
+ } from "./chunk-XITY2WQN.mjs";
14
14
  export {
15
15
  AddressTypes,
16
16
  BehioApiError,
package/dist/next.d.mts CHANGED
@@ -3,6 +3,8 @@ import { BehioStorefrontConfig, BehioStorefront } from './index.mjs';
3
3
  interface GetBehioOptions extends Partial<BehioStorefrontConfig> {
4
4
  /** Override the cart session cookie name (default: "behio_cart_session"). */
5
5
  cartCookieName?: string;
6
+ /** Override the currency cookie name (default: "behio_currency"). */
7
+ currencyCookieName?: string;
6
8
  }
7
9
  /**
8
10
  * Returns a per-request bound BehioStorefront instance. Reads the cart
package/dist/next.d.ts CHANGED
@@ -3,6 +3,8 @@ import { BehioStorefrontConfig, BehioStorefront } from './index.js';
3
3
  interface GetBehioOptions extends Partial<BehioStorefrontConfig> {
4
4
  /** Override the cart session cookie name (default: "behio_cart_session"). */
5
5
  cartCookieName?: string;
6
+ /** Override the currency cookie name (default: "behio_currency"). */
7
+ currencyCookieName?: string;
6
8
  }
7
9
  /**
8
10
  * Returns a per-request bound BehioStorefront instance. Reads the cart