@behio/storefront-sdk 0.41.0 → 1.0.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.
@@ -566,8 +566,7 @@ var CatalogModule = class {
566
566
  if (query.inStock !== void 0) q.inStock = query.inStock;
567
567
  if (query.ratingMin !== void 0) q.ratingMin = query.ratingMin;
568
568
  if (query.search) q.search = query.search;
569
- if (query.customFields)
570
- q.customFields = JSON.stringify(query.customFields);
569
+ if (query.parameters) q.parameters = JSON.stringify(query.parameters);
571
570
  if (query.facets) q.facets = JSON.stringify(query.facets);
572
571
  if (query.ids && query.ids.length > 0) q.ids = query.ids;
573
572
  if (query.slugs && query.slugs.length > 0) q.slugs = query.slugs;
@@ -659,18 +658,52 @@ var CatalogModule = class {
659
658
  }
660
659
  );
661
660
  }
662
- /** Get available filter fields for dynamic filter UI */
663
- async getFilters() {
661
+ /**
662
+ * Available filters for a dynamic filter UI.
663
+ *
664
+ * Derived from curated PARAMETERS the merchant marked filterable, so a
665
+ * visitor can never filter by something that does not appear in the
666
+ * product's parameters. Labels are per language, hence `locale`.
667
+ */
668
+ async getFilters(options) {
669
+ return this.client.request(
670
+ "GET",
671
+ "/catalog/filters",
672
+ { query: { locale: _optionalChain([options, 'optionalAccess', _25 => _25.locale]) } }
673
+ );
674
+ }
675
+ /**
676
+ * Curated parameter groups of a product, already resolved (label, value,
677
+ * unit, order). Returns an ARRAY of groups so a template can lay them out
678
+ * however it likes: one group as a spec table, another as badges.
679
+ *
680
+ * A variant's own parameters ride along on `ProductDetail.variants[]`, so
681
+ * this call is for the parent product.
682
+ */
683
+ async getProductParameters(slug, options) {
684
+ return this.client.request(
685
+ "GET",
686
+ `/catalog/products/${slug}/parameters`,
687
+ { query: { locale: _optionalChain([options, 'optionalAccess', _26 => _26.locale]) } }
688
+ );
689
+ }
690
+ /**
691
+ * One specific parameter group of a product, by its slug. 404 when the
692
+ * product does not have that group, which is deliberate: the caller asked
693
+ * for a named thing, so an empty array would hide a wrong slug.
694
+ */
695
+ async getProductParameterGroup(slug, groupSlug, options) {
664
696
  return this.client.request(
665
697
  "GET",
666
- "/catalog/filters"
698
+ `/catalog/products/${slug}/parameters/${groupSlug}`,
699
+ { query: { locale: _optionalChain([options, 'optionalAccess', _27 => _27.locale]) } }
667
700
  );
668
701
  }
669
702
  /**
670
- * Facet groups + selection-aware counts for the current filter set (custom
671
- * fields, labels, price, availability, rating, subcategories). Pass the SAME
672
- * query you pass to `getProducts` (category, search, price, inStock, ratingMin,
673
- * customFields, facets slugs, labels): counts for each facet are computed with
703
+ * Facet groups + selection-aware counts for the current filter set
704
+ * (parameters, labels, price, availability, rating, subcategories). Pass the
705
+ * SAME query you pass to `getProducts` (category, search, price, inStock,
706
+ * ratingMin, parameters, facets slugs, labels): counts are computed with
674
707
  * that facet excluded, and values that drop to 0 are still returned (render
675
708
  * them disabled). Use this to build an Alza-style filter sidebar.
676
709
  */
@@ -686,8 +719,7 @@ var CatalogModule = class {
686
719
  if (query.inStock !== void 0) q.inStock = query.inStock;
687
720
  if (query.ratingMin !== void 0) q.ratingMin = query.ratingMin;
688
721
  if (query.search) q.search = query.search;
689
- if (query.customFields)
690
- q.customFields = JSON.stringify(query.customFields);
722
+ if (query.parameters) q.parameters = JSON.stringify(query.parameters);
691
723
  if (query.facets) q.facets = JSON.stringify(query.facets);
692
724
  if (query.labels && query.labels.length > 0) q.labels = query.labels;
693
725
  if (query.categories && query.categories.length > 0)
@@ -722,7 +754,7 @@ var CatalogModule = class {
722
754
  "GET",
723
755
  `/catalog/product-groups/${encodeURIComponent(slug)}`,
724
756
  {
725
- query: { locale: _optionalChain([options, 'optionalAccess', _25 => _25.locale]), currency: _optionalChain([options, 'optionalAccess', _26 => _26.currency]) }
757
+ query: { locale: _optionalChain([options, 'optionalAccess', _28 => _28.locale]), currency: _optionalChain([options, 'optionalAccess', _29 => _29.currency]) }
726
758
  }
727
759
  );
728
760
  }
@@ -737,7 +769,7 @@ var CatalogModule = class {
737
769
  return this.client.request(
738
770
  "GET",
739
771
  `/catalog/products/${encodeURIComponent(productSlug)}/cross-sell`,
740
- { query: { locale: _optionalChain([options, 'optionalAccess', _27 => _27.locale]), currency: _optionalChain([options, 'optionalAccess', _28 => _28.currency]) } }
772
+ { query: { locale: _optionalChain([options, 'optionalAccess', _30 => _30.locale]), currency: _optionalChain([options, 'optionalAccess', _31 => _31.currency]) } }
741
773
  );
742
774
  }
743
775
  /** Active promotions applicable to a product (with countdown end time) */
@@ -777,7 +809,7 @@ var CatalogModule = class {
777
809
  /** List configured payment methods (filtered by currency). */
778
810
  async listPaymentMethods(opts) {
779
811
  const query = {};
780
- if (_optionalChain([opts, 'optionalAccess', _29 => _29.currency])) query.currency = opts.currency;
812
+ if (_optionalChain([opts, 'optionalAccess', _32 => _32.currency])) query.currency = opts.currency;
781
813
  return this.client.request(
782
814
  "GET",
783
815
  "/catalog/payment-methods",
@@ -1071,7 +1103,7 @@ var OrdersModule = class {
1071
1103
  "GET",
1072
1104
  "/orders",
1073
1105
  {
1074
- query: { page: _optionalChain([options, 'optionalAccess', _30 => _30.page]), limit: _optionalChain([options, 'optionalAccess', _31 => _31.limit]) }
1106
+ query: { page: _optionalChain([options, 'optionalAccess', _33 => _33.page]), limit: _optionalChain([options, 'optionalAccess', _34 => _34.limit]) }
1075
1107
  }
1076
1108
  );
1077
1109
  }
@@ -1566,7 +1598,7 @@ var ConsentModule = class {
1566
1598
  }
1567
1599
  if (result.error) return { data: null, error: result.error };
1568
1600
  return {
1569
- data: _optionalChain([result, 'access', _32 => _32.data, 'optionalAccess', _33 => _33.consented]) ? result.data.consent : null,
1601
+ data: _optionalChain([result, 'access', _35 => _35.data, 'optionalAccess', _36 => _36.consented]) ? result.data.consent : null,
1570
1602
  error: null
1571
1603
  };
1572
1604
  }
@@ -1653,10 +1685,10 @@ var ShippingModule = class {
1653
1685
  */
1654
1686
  async listMethods(opts) {
1655
1687
  const query = {};
1656
- if (_optionalChain([opts, 'optionalAccess', _34 => _34.currency])) query.currency = opts.currency;
1657
- if (_optionalChain([opts, 'optionalAccess', _35 => _35.country])) query.country = opts.country;
1658
- if (_optionalChain([opts, 'optionalAccess', _36 => _36.cartTotal]) != null) query.cartTotal = String(opts.cartTotal);
1659
- if (_optionalChain([opts, 'optionalAccess', _37 => _37.cartWeightKg]) != null)
1688
+ if (_optionalChain([opts, 'optionalAccess', _37 => _37.currency])) query.currency = opts.currency;
1689
+ if (_optionalChain([opts, 'optionalAccess', _38 => _38.country])) query.country = opts.country;
1690
+ if (_optionalChain([opts, 'optionalAccess', _39 => _39.cartTotal]) != null) query.cartTotal = String(opts.cartTotal);
1691
+ if (_optionalChain([opts, 'optionalAccess', _40 => _40.cartWeightKg]) != null)
1660
1692
  query.cartWeightKg = String(opts.cartWeightKg);
1661
1693
  return this.client.request(
1662
1694
  "GET",
@@ -566,8 +566,7 @@ var CatalogModule = class {
566
566
  if (query.inStock !== void 0) q.inStock = query.inStock;
567
567
  if (query.ratingMin !== void 0) q.ratingMin = query.ratingMin;
568
568
  if (query.search) q.search = query.search;
569
- if (query.customFields)
570
- q.customFields = JSON.stringify(query.customFields);
569
+ if (query.parameters) q.parameters = JSON.stringify(query.parameters);
571
570
  if (query.facets) q.facets = JSON.stringify(query.facets);
572
571
  if (query.ids && query.ids.length > 0) q.ids = query.ids;
573
572
  if (query.slugs && query.slugs.length > 0) q.slugs = query.slugs;
@@ -659,18 +658,52 @@ var CatalogModule = class {
659
658
  }
660
659
  );
661
660
  }
662
- /** Get available filter fields for dynamic filter UI */
663
- async getFilters() {
661
+ /**
662
+ * Available filters for a dynamic filter UI.
663
+ *
664
+ * Derived from curated PARAMETERS the merchant marked filterable, so a
665
+ * visitor can never filter by something that does not appear in the
666
+ * product's parameters. Labels are per language, hence `locale`.
667
+ */
668
+ async getFilters(options) {
669
+ return this.client.request(
670
+ "GET",
671
+ "/catalog/filters",
672
+ { query: { locale: options?.locale } }
673
+ );
674
+ }
675
+ /**
676
+ * Curated parameter groups of a product, already resolved (label, value,
677
+ * unit, order). Returns an ARRAY of groups so a template can lay them out
678
+ * however it likes: one group as a spec table, another as badges.
679
+ *
680
+ * A variant's own parameters ride along on `ProductDetail.variants[]`, so
681
+ * this call is for the parent product.
682
+ */
683
+ async getProductParameters(slug, options) {
684
+ return this.client.request(
685
+ "GET",
686
+ `/catalog/products/${slug}/parameters`,
687
+ { query: { locale: options?.locale } }
688
+ );
689
+ }
690
+ /**
691
+ * One specific parameter group of a product, by its slug. 404 when the
692
+ * product does not have that group, which is deliberate: the caller asked
693
+ * for a named thing, so an empty array would hide a wrong slug.
694
+ */
695
+ async getProductParameterGroup(slug, groupSlug, options) {
664
696
  return this.client.request(
665
697
  "GET",
666
- "/catalog/filters"
698
+ `/catalog/products/${slug}/parameters/${groupSlug}`,
699
+ { query: { locale: options?.locale } }
667
700
  );
668
701
  }
669
702
  /**
670
- * Facet groups + selection-aware counts for the current filter set (custom
671
- * fields, labels, price, availability, rating, subcategories). Pass the SAME
672
- * query you pass to `getProducts` (category, search, price, inStock, ratingMin,
673
- * customFields, facets slugs, labels): counts for each facet are computed with
703
+ * Facet groups + selection-aware counts for the current filter set
704
+ * (parameters, labels, price, availability, rating, subcategories). Pass the
705
+ * SAME query you pass to `getProducts` (category, search, price, inStock,
706
+ * ratingMin, parameters, facets slugs, labels): counts are computed with
674
707
  * that facet excluded, and values that drop to 0 are still returned (render
675
708
  * them disabled). Use this to build an Alza-style filter sidebar.
676
709
  */
@@ -686,8 +719,7 @@ var CatalogModule = class {
686
719
  if (query.inStock !== void 0) q.inStock = query.inStock;
687
720
  if (query.ratingMin !== void 0) q.ratingMin = query.ratingMin;
688
721
  if (query.search) q.search = query.search;
689
- if (query.customFields)
690
- q.customFields = JSON.stringify(query.customFields);
722
+ if (query.parameters) q.parameters = JSON.stringify(query.parameters);
691
723
  if (query.facets) q.facets = JSON.stringify(query.facets);
692
724
  if (query.labels && query.labels.length > 0) q.labels = query.labels;
693
725
  if (query.categories && query.categories.length > 0)
@@ -300,6 +300,14 @@ interface ProductVariant {
300
300
  * "default photo" or to render the picture in a subtler style.
301
301
  */
302
302
  imageIsInherited: boolean;
303
+ /**
304
+ * Parameters of this variant. A variant carries its own value where it has
305
+ * one and inherits the parent's everywhere else, so you can render the rows
306
+ * that actually differ under each variant. Empty when nothing is assigned.
307
+ *
308
+ * Added in SDK 1.0.0.
309
+ */
310
+ parameterGroups: ProductParameterGroup[];
303
311
  }
304
312
  interface ProductLabel {
305
313
  id: string;
@@ -355,6 +363,36 @@ interface ProductListItem {
355
363
  * disable the buy button, never re-derive the rule client-side.
356
364
  */
357
365
  isPurchasable: boolean;
366
+ /**
367
+ * The merchant sells this product ONLY through its variants: "Tričko" on its
368
+ * own means nothing, the shop sells the red one and the yellow one.
369
+ *
370
+ * The product keeps its card, its PDP and its search presence — it simply is
371
+ * not a sellable unit. `isPurchasable` is false and the cart/checkout reject
372
+ * its `id` with a 400, so the shopper must pick a variant first.
373
+ *
374
+ * When this is true, render the headline price as **"od {priceFrom}"** and
375
+ * keep the buy button disabled until a variant is chosen; then switch to that
376
+ * variant's own `price` and add `variant.id` to the cart. `price` still
377
+ * carries the parent's own number for backwards compatibility, but showing it
378
+ * as *the* price would quote 990 and charge 1990 — always label it "od".
379
+ *
380
+ * False for every product without variants, so nothing changes for shops that
381
+ * never turn it on.
382
+ */
383
+ variantsOnly: boolean;
384
+ /**
385
+ * "From" price: the CHEAPEST variant price, in the requested currency, or
386
+ * null when the product has no variants (or prices are gated behind login in
387
+ * B2B mode). Populated for EVERY variant parent, not only `variantsOnly`
388
+ * ones, so a card can render "od 990 Kč" whenever the template wants to.
389
+ *
390
+ * Computed over the same variant set the PDP lists (published, enabled
391
+ * variants) and deliberately IGNORING stock — a size selling out must not
392
+ * make the advertised price jump. `compareAtPrice` carries that same
393
+ * variant's strike-through price when it has one.
394
+ */
395
+ priceFrom?: ProductPrice | null;
358
396
  /**
359
397
  * Early bird (time-based launch price) is active: `price.amount` already IS
360
398
  * the discounted early-bird amount and the regular price sits in
@@ -483,25 +521,41 @@ interface VariantAxis {
483
521
  values: VariantAxisValue[];
484
522
  }
485
523
  /**
486
- * One custom-field (data-group value) rendered as a spec-table row. BOOLEAN
487
- * carries a typed `booleanValue` (value is null) so the storefront can localize
488
- * Ano/Ne; MONEY carries its currency in `unit`; PERCENTAGE carries "%" in
489
- * `unit`.
524
+ * One row of a curated parameter group.
525
+ *
526
+ * A parameter is something the merchant explicitly published: a label they
527
+ * wrote, a value resolved from a fixed string, a product field, or ONE named
528
+ * field of one warehouse data group. Nothing here reveals warehouse structure:
529
+ * no ids, no field keys, no internal types.
530
+ *
531
+ * `value` is null only for boolean parameters, where `booleanValue` carries the
532
+ * typed value so the storefront localizes Ano/Ne itself. A parameter with no
533
+ * value is omitted from the array rather than rendered as an empty row.
490
534
  */
491
- interface ProductCustomField {
492
- key: string;
493
- name: string;
494
- /** TEXT | NUMBER | DECIMAL | BOOLEAN | DATE | TIME | DATETIME | PERCENTAGE | MONEY | ITEM_LIST | ... */
495
- type: string;
535
+ interface ProductParameter {
536
+ label: string;
496
537
  value: string | null;
497
538
  booleanValue: boolean | null;
539
+ /** "cm", "g", a currency code, "%"; null when the parameter has none. */
498
540
  unit: string | null;
499
541
  }
500
- /** A spec-table section (one inventory data group) with its fields. */
501
- interface ProductCustomFieldGroup {
502
- key: string;
542
+ /**
543
+ * One curated parameter group. A product can carry several, so a template can
544
+ * render one as a spec table and another as badges. Ordering is array order,
545
+ * both for the groups and for the parameters inside them.
546
+ */
547
+ interface ProductParameterGroup {
548
+ /**
549
+ * Stable public identifier derived from the merchant's own group name
550
+ * ("Parametry oblečení" -> "parametry-obleceni"). Pass it to
551
+ * `catalog.getProductParameterGroup` to fetch just this group.
552
+ */
553
+ slug: string;
503
554
  name: string;
504
- fields: ProductCustomField[];
555
+ parameters: ProductParameter[];
556
+ }
557
+ interface ProductParametersResponse {
558
+ groups: ProductParameterGroup[];
505
559
  }
506
560
  interface ProductDetail extends ProductListItem {
507
561
  longDescription?: string;
@@ -531,14 +585,15 @@ interface ProductDetail extends ProductListItem {
531
585
  variantAxes: VariantAxis[];
532
586
  volumePricing: ProductVolumePrice[];
533
587
  /**
534
- * Structured product parameters from custom fields (inventory data groups),
535
- * grouped into spec-table sections (GAP-12). Empty when the product has no
536
- * data-group values. Distinct from `longDescription` (free HTML): this is
537
- * machine-readable key/value data for a "Parametry" table + comparison
538
- * engines. (Corrected from the old untyped `Record<string, unknown>` — the
539
- * API never populated that; it now sends this structured shape.)
588
+ * Curated parameter groups, already resolved. Empty when the merchant
589
+ * assigned none. Distinct from `longDescription` (free HTML): this is
590
+ * machine-readable key/value data for a "Parametry" table, comparison
591
+ * engines and AEO.
592
+ *
593
+ * Replaced `customFields` in SDK 1.0.0. The old field returned raw warehouse
594
+ * data groups, which published internal bookkeeping nobody curated.
540
595
  */
541
- customFields: ProductCustomFieldGroup[];
596
+ parameterGroups: ProductParameterGroup[];
542
597
  seo: {
543
598
  title?: string | null;
544
599
  description?: string | null;
@@ -645,13 +700,22 @@ interface CategoryDetail extends Category {
645
700
  ogImage?: string | null;
646
701
  };
647
702
  }
648
- type DataGroupFieldType = "TEXT" | "NUMBER" | "DECIMAL" | "BOOLEAN" | "DATE" | "TIME" | "DATETIME" | "PERCENTAGE" | "MONEY" | "ASSET" | "ITEM_LIST" | "DYNAMIC_NUMBER_CALCULATION_FROM_OTHERS";
703
+ /**
704
+ * One available filter, derived from a curated parameter the merchant marked
705
+ * filterable. A visitor can therefore never filter by a field that does not
706
+ * appear in the product's parameters.
707
+ */
649
708
  interface FilterField {
709
+ /** Parameter slug. Pass it back in `ProductsQuery.parameters` or `facets`. */
650
710
  key: string;
711
+ /** Parameter label in the requested language. */
651
712
  name: string;
652
- type: DataGroupFieldType | string;
653
- groupKey: string;
713
+ /** How to render it: value list, numeric range, or yes/no. */
714
+ type: "enum" | "range" | "boolean" | string;
715
+ /** Slug of the parameter group this filter belongs to. */
716
+ groupSlug: string;
654
717
  groupName: string;
718
+ unit?: string | null;
655
719
  values?: string[];
656
720
  }
657
721
  interface FacetValue {
@@ -671,14 +735,14 @@ interface FacetRange {
671
735
  max: number | null;
672
736
  }
673
737
  interface Facet {
738
+ /** Parameter slug. Never a warehouse field key. */
674
739
  key: string;
675
740
  name: string;
676
741
  /** "enum" (checkboxes), "range" (slider) or "boolean". */
677
742
  type: "enum" | "range" | "boolean" | string;
678
- groupKey: string;
743
+ /** Slug of the parameter group this facet belongs to. */
744
+ groupSlug: string;
679
745
  groupName: string;
680
- /** Underlying data-group field type (TEXT, NUMBER, MONEY, ...). */
681
- fieldType: string;
682
746
  /** enum/boolean facets: selectable values with counts. */
683
747
  values?: FacetValue[];
684
748
  /** range facets: numeric bounds within the current context. */
@@ -773,11 +837,17 @@ interface ProductsQuery {
773
837
  /** Minimum aggregate rating, e.g. 4 for "4 and up". */
774
838
  ratingMin?: number;
775
839
  search?: string;
776
- /** Custom-field filters. A value may be an array = multi-select (OR within
777
- * the key), e.g. {"barva": ["cerna", "bila"]}. */
778
- customFields?: Record<string, string | number | boolean | string[] | unknown>;
779
- /** Slug-based facet selection for SEO URLs: facet key -> value slugs, e.g.
780
- * {"barva": ["cerna"]}. Resolved server-side to the underlying values. */
840
+ /**
841
+ * Parameter filters, keyed by PARAMETER SLUG. A value may be an array =
842
+ * multi-select (OR within the key), e.g. {"barva": ["cerna", "bila"]}.
843
+ * Range filters use the `_min` / `_max` suffix, e.g. {"hmotnost_min": 100}.
844
+ *
845
+ * Replaced `customFields` in SDK 1.0.0, which was keyed by a warehouse
846
+ * data-group field key.
847
+ */
848
+ parameters?: Record<string, string | number | boolean | string[] | unknown>;
849
+ /** Slug-based facet selection for SEO URLs: parameter slug -> value slugs,
850
+ * e.g. {"barva": ["cerna"]}. Resolved server-side to the stored values. */
781
851
  facets?: Record<string, string[]>;
782
852
  /** Filter by specific product IDs (comma-separated in URL) */
783
853
  ids?: string[];
@@ -1116,7 +1186,10 @@ interface DigitalDownload {
1116
1186
  fileName: string;
1117
1187
  /** Localized product name the file belongs to (may be null). */
1118
1188
  productName: string | null;
1119
- /** Product slug for linking back to the PDP (may be null). */
1189
+ /**
1190
+ * Product slug for linking back to the PDP (may be null). Resolved the same
1191
+ * way as everywhere else: per-locale slug first, then the product id.
1192
+ */
1120
1193
  productSlug: string | null;
1121
1194
  fileSize: number;
1122
1195
  mimeType: string;
@@ -1138,7 +1211,10 @@ interface CourseListItem {
1138
1211
  courseId: string;
1139
1212
  /** Localized course (product) name, best-effort. */
1140
1213
  name: string | null;
1141
- /** Product slug for linking to the PDP. */
1214
+ /**
1215
+ * Product slug for linking to the PDP. Resolved the same way as in the
1216
+ * catalog: per-locale slug first, then the product id.
1217
+ */
1142
1218
  slug: string;
1143
1219
  imageUrl: string | null;
1144
1220
  totalLessons: number;
@@ -1190,6 +1266,7 @@ interface CourseModule {
1190
1266
  interface CourseDetail {
1191
1267
  courseId: string;
1192
1268
  name: string | null;
1269
+ /** Product slug for linking to the PDP (resolved per-locale slug, else id). */
1193
1270
  slug: string;
1194
1271
  imageUrl: string | null;
1195
1272
  /** Welcome text shown at the top of the member area (markdown). */
@@ -1542,15 +1619,17 @@ interface Bundle {
1542
1619
  slug: string;
1543
1620
  name: string;
1544
1621
  description: string | null;
1545
- bundlePrice: number;
1622
+ /** `null` when the eshop hides prices from guests and this visitor has no price entitlement. */
1623
+ bundlePrice: number | null;
1546
1624
  currency: string;
1547
1625
  coverImage: string | null;
1548
1626
  endsAt: number | null;
1549
- itemsSum: number;
1550
- /** Absolute saving vs buying the components separately, in `currency`. */
1551
- savings: number;
1552
- /** Percentage saving, 0–100. 0 when `itemsSum` is zero. */
1553
- savingsPercent: number;
1627
+ /** `null` when prices are hidden (see `bundlePrice`). */
1628
+ itemsSum: number | null;
1629
+ /** Absolute saving vs buying the components separately, in `currency`. `null` when prices are hidden. */
1630
+ savings: number | null;
1631
+ /** Percentage saving, 0–100. 0 when `itemsSum` is zero. `null` when prices are hidden. */
1632
+ savingsPercent: number | null;
1554
1633
  /** Minimum bundles per order. Default 1. */
1555
1634
  minQuantity: number;
1556
1635
  /** Maximum bundles per order. `null` = uncapped. */
@@ -2254,15 +2333,42 @@ declare class CatalogModule {
2254
2333
  locale?: string;
2255
2334
  currency?: string;
2256
2335
  }): Promise<SdkResult<PaginatedResponse<ProductListItem>>>;
2257
- /** Get available filter fields for dynamic filter UI */
2258
- getFilters(): Promise<SdkResult<{
2336
+ /**
2337
+ * Available filters for a dynamic filter UI.
2338
+ *
2339
+ * Derived from curated PARAMETERS the merchant marked filterable, so a
2340
+ * visitor can never filter by something that does not appear in the
2341
+ * product's parameters. Labels are per language, hence `locale`.
2342
+ */
2343
+ getFilters(options?: {
2344
+ locale?: string;
2345
+ }): Promise<SdkResult<{
2259
2346
  filters: FilterField[];
2260
2347
  }>>;
2261
2348
  /**
2262
- * Facet groups + selection-aware counts for the current filter set (custom
2263
- * fields, labels, price, availability, rating, subcategories). Pass the SAME
2264
- * query you pass to `getProducts` (category, search, price, inStock, ratingMin,
2265
- * customFields, facets slugs, labels): counts for each facet are computed with
2349
+ * Curated parameter groups of a product, already resolved (label, value,
2350
+ * unit, order). Returns an ARRAY of groups so a template can lay them out
2351
+ * however it likes: one group as a spec table, another as badges.
2352
+ *
2353
+ * A variant's own parameters ride along on `ProductDetail.variants[]`, so
2354
+ * this call is for the parent product.
2355
+ */
2356
+ getProductParameters(slug: string, options?: {
2357
+ locale?: string;
2358
+ }): Promise<SdkResult<ProductParametersResponse>>;
2359
+ /**
2360
+ * One specific parameter group of a product, by its slug. 404 when the
2361
+ * product does not have that group, which is deliberate: the caller asked
2362
+ * for a named thing, so an empty array would hide a wrong slug.
2363
+ */
2364
+ getProductParameterGroup(slug: string, groupSlug: string, options?: {
2365
+ locale?: string;
2366
+ }): Promise<SdkResult<ProductParameterGroup>>;
2367
+ /**
2368
+ * Facet groups + selection-aware counts for the current filter set
2369
+ * (parameters, labels, price, availability, rating, subcategories). Pass the
2370
+ * SAME query you pass to `getProducts` (category, search, price, inStock,
2371
+ * ratingMin, parameters, facets slugs, labels): counts are computed with
2266
2372
  * that facet excluded, and values that drop to 0 are still returned (render
2267
2373
  * them disabled). Use this to build an Alza-style filter sidebar.
2268
2374
  */
@@ -2764,4 +2870,4 @@ declare class NewsletterModule {
2764
2870
  unsubscribe(email: string): Promise<SdkResult<NewsletterUnsubscribeResult>>;
2765
2871
  }
2766
2872
 
2767
- export { type DownloadUrl as $, type ActivePromotion as A, BehioStorefront as B, type CookieConsent as C, type CheckoutAddress as D, type CheckoutInput as E, type CheckoutPaymentMethod as F, type CheckoutSettings as G, type CookieConsentInput as H, type CourseAttachment as I, type CourseCertificate as J, type CourseComment as K, type CourseCommentReply as L, type CourseCommentsList as M, type CourseDetail as N, type CourseLesson as O, type CourseListItem as P, type CourseModule as Q, type CoursePostedComment as R, type SdkResult as S, type CourseProgress as T, type CourseTutorMessage as U, type CourseTutorThread as V, type CrossSellItem as W, type CustomerAddress as X, type CustomerProfile as Y, type DataGroupFieldType as Z, type DigitalDownload as _, type AddToCartInput as a, type ProductPrice as a$, type Facet as a0, type FacetAvailability as a1, type FacetCategory as a2, type FacetLabel as a3, type FacetPriceRange as a4, type FacetRange as a5, type FacetRatingBucket as a6, type FacetValue as a7, type FacetsResponse as a8, type FilterField as a9, type OrderAccessVerifyResponse as aA, type OrderDetail as aB, type OrderItem as aC, type OrderListItem as aD, type OrderStatus as aE, type OrderStatusHistory as aF, OrderStatuses as aG, type OrderTracking as aH, type Page as aI, type PageAttachment as aJ, type PageDetail as aK, type PaginatedResponse as aL, type PaymentStatus as aM, PaymentStatuses as aN, type PickupPoint as aO, type PickupPointHours as aP, type PickupPointsInput as aQ, type PriceDisplay as aR, type ProductAvailability as aS, type ProductCustomField as aT, type ProductCustomFieldGroup as aU, type ProductDetail as aV, type ProductGroup as aW, type ProductLabel as aX, type ProductListItem as aY, type ProductMedia as aZ, type ProductMediaVariant as a_, type FulfillmentStatus as aa, FulfillmentStatuses as ab, type GiftCardBalance as ac, type GiftCardPurchaseInput as ad, type GiftCardPurchaseResult as ae, type GiftCardSummary as af, type LessonNote as ag, type LessonQuiz as ah, type LoginInput as ai, type LoyaltyBalance as aj, type LoyaltyNextTier as ak, type LoyaltyProgram as al, type LoyaltySummary as am, type LoyaltyTier as an, type LoyaltyTierPerks as ao, type LoyaltyTransaction as ap, type Menu as aq, type MenuItem as ar, type MenuItemRef as as, type MenuItemType as at, type MessageResponse as au, type NewsletterOptInDefault as av, type NewsletterSubscribeInput as aw, type NewsletterSubscribeResult as ax, type NewsletterUnsubscribeResult as ay, type OrderAccessRequestResponse as az, type AddressDetail as b, type ProductPromotionSummary as b0, type ProductReview as b1, type ProductReviewsResponse as b2, ProductSort as b3, type ProductSortValue as b4, type ProductVariant as b5, type ProductVolumePrice as b6, type ProductsQuery as b7, type QuizAnswerInput as b8, type QuizAnswerResult as b9, type ShopSeoIdentity as bA, type StockBehavior as bB, type StockMode as bC, type SubmitQuoteInput as bD, type SubmitReturnInput as bE, type SubmitReviewInput as bF, type Subscription as bG, type SubscriptionAction as bH, type SubscriptionFrequency as bI, type SubscriptionItem as bJ, type SubscriptionStatus as bK, type TaxBreakdownLine as bL, type VariantAxis as bM, type VariantAxisValue as bN, type WishlistItem as bO, err as bP, ok as bQ, toSdkError as bR, type QuizQuestion as ba, type QuizResult as bb, type QuoteItem as bc, type QuoteRequest as bd, type RegisterInput as be, type RegisterResult as bf, type RequestInterceptor as bg, type RequestInterceptorConfig as bh, type ResponseInterceptor as bi, type ResponseInterceptorData as bj, type ReturnRequest as bk, type ReturnRequestItem as bl, type ReturnStatus as bm, type ReturnStatusItem as bn, type ReturnableOrder as bo, type ReturnableOrderItem as bp, type SdkError as bq, type ShippingMethodSummary as br, type ShippingQuote as bs, type ShippingQuoteInput as bt, type ShopInfo as bu, type ShopScript as bv, type ShopScriptPlacement as bw, type ShopScriptType as bx, type ShopScripts as by, type ShopSeo as bz, type AddressSuggestion as c, type AddressType as d, AddressTypes as e, type AuthTokens as f, type BackInStockSubscription as g, type BadgeTone as h, BehioApiError as i, type BehioErrorCode as j, type BehioEventHandler as k, type BehioEventType as l, BehioNetworkError as m, type BehioStorefrontConfig as n, type Bundle as o, type BundleItem as p, type Cart as q, type CartBundleLine as r, type CartBundleLineItem as s, type CartDiscount as t, type CartItem as u, type CartItemProduct as v, type CartPromotion as w, type Category as x, type CategoryDetail as y, type CertificateVerification as z };
2873
+ export { type Facet as $, type ActivePromotion as A, BehioStorefront as B, type CookieConsent as C, type CheckoutAddress as D, type CheckoutInput as E, type CheckoutPaymentMethod as F, type CheckoutSettings as G, type CookieConsentInput as H, type CourseAttachment as I, type CourseCertificate as J, type CourseComment as K, type CourseCommentReply as L, type CourseCommentsList as M, type CourseDetail as N, type CourseLesson as O, type CourseListItem as P, type CourseModule as Q, type CoursePostedComment as R, type SdkResult as S, type CourseProgress as T, type CourseTutorMessage as U, type CourseTutorThread as V, type CrossSellItem as W, type CustomerAddress as X, type CustomerProfile as Y, type DigitalDownload as Z, type DownloadUrl as _, type AddToCartInput as a, type ProductPrice as a$, type FacetAvailability as a0, type FacetCategory as a1, type FacetLabel as a2, type FacetPriceRange as a3, type FacetRange as a4, type FacetRatingBucket as a5, type FacetValue as a6, type FacetsResponse as a7, type FilterField as a8, type FulfillmentStatus as a9, type OrderDetail as aA, type OrderItem as aB, type OrderListItem as aC, type OrderStatus as aD, type OrderStatusHistory as aE, OrderStatuses as aF, type OrderTracking as aG, type Page as aH, type PageAttachment as aI, type PageDetail as aJ, type PaginatedResponse as aK, type PaymentStatus as aL, PaymentStatuses as aM, type PickupPoint as aN, type PickupPointHours as aO, type PickupPointsInput as aP, type PriceDisplay as aQ, type ProductAvailability as aR, type ProductDetail as aS, type ProductGroup as aT, type ProductLabel as aU, type ProductListItem as aV, type ProductMedia as aW, type ProductMediaVariant as aX, type ProductParameter as aY, type ProductParameterGroup as aZ, type ProductParametersResponse as a_, FulfillmentStatuses as aa, type GiftCardBalance as ab, type GiftCardPurchaseInput as ac, type GiftCardPurchaseResult as ad, type GiftCardSummary as ae, type LessonNote as af, type LessonQuiz as ag, type LoginInput as ah, type LoyaltyBalance as ai, type LoyaltyNextTier as aj, type LoyaltyProgram as ak, type LoyaltySummary as al, type LoyaltyTier as am, type LoyaltyTierPerks as an, type LoyaltyTransaction as ao, type Menu as ap, type MenuItem as aq, type MenuItemRef as ar, type MenuItemType as as, type MessageResponse as at, type NewsletterOptInDefault as au, type NewsletterSubscribeInput as av, type NewsletterSubscribeResult as aw, type NewsletterUnsubscribeResult as ax, type OrderAccessRequestResponse as ay, type OrderAccessVerifyResponse as az, type AddressDetail as b, type ProductPromotionSummary as b0, type ProductReview as b1, type ProductReviewsResponse as b2, ProductSort as b3, type ProductSortValue as b4, type ProductVariant as b5, type ProductVolumePrice as b6, type ProductsQuery as b7, type QuizAnswerInput as b8, type QuizAnswerResult as b9, type ShopSeoIdentity as bA, type StockBehavior as bB, type StockMode as bC, type SubmitQuoteInput as bD, type SubmitReturnInput as bE, type SubmitReviewInput as bF, type Subscription as bG, type SubscriptionAction as bH, type SubscriptionFrequency as bI, type SubscriptionItem as bJ, type SubscriptionStatus as bK, type TaxBreakdownLine as bL, type VariantAxis as bM, type VariantAxisValue as bN, type WishlistItem as bO, err as bP, ok as bQ, toSdkError as bR, type QuizQuestion as ba, type QuizResult as bb, type QuoteItem as bc, type QuoteRequest as bd, type RegisterInput as be, type RegisterResult as bf, type RequestInterceptor as bg, type RequestInterceptorConfig as bh, type ResponseInterceptor as bi, type ResponseInterceptorData as bj, type ReturnRequest as bk, type ReturnRequestItem as bl, type ReturnStatus as bm, type ReturnStatusItem as bn, type ReturnableOrder as bo, type ReturnableOrderItem as bp, type SdkError as bq, type ShippingMethodSummary as br, type ShippingQuote as bs, type ShippingQuoteInput as bt, type ShopInfo as bu, type ShopScript as bv, type ShopScriptPlacement as bw, type ShopScriptType as bx, type ShopScripts as by, type ShopSeo as bz, type AddressSuggestion as c, type AddressType as d, AddressTypes as e, type AuthTokens as f, type BackInStockSubscription as g, type BadgeTone as h, BehioApiError as i, type BehioErrorCode as j, type BehioEventHandler as k, type BehioEventType as l, BehioNetworkError as m, type BehioStorefrontConfig as n, type Bundle as o, type BundleItem as p, type Cart as q, type CartBundleLine as r, type CartBundleLineItem as s, type CartDiscount as t, type CartItem as u, type CartItemProduct as v, type CartPromotion as w, type Category as x, type CategoryDetail as y, type CertificateVerification as z };