@moonbase.sh/storefront-api 2.3.1 → 2.4.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/index.js CHANGED
@@ -20,6 +20,7 @@ __export(schemas_exports2, {
20
20
  offerConditionSchema: () => offerConditionSchema,
21
21
  storefrontBundleSchema: () => storefrontBundleSchema,
22
22
  storefrontOfferSchema: () => storefrontOfferSchema,
23
+ storefrontOfferTargetSchema: () => storefrontOfferTargetSchema,
23
24
  storefrontProductSchema: () => storefrontProductSchema,
24
25
  storefrontSchema: () => storefrontSchema,
25
26
  taxEstimateSchema: () => taxEstimateSchema
@@ -236,13 +237,36 @@ var cartContainsItemsConditionSchema = z3.object({
236
237
  relevantItemVariations: z3.record(z3.string(), z3.string().array())
237
238
  });
238
239
  var offerConditionSchema = z3.discriminatedUnion("type", [cartContainsItemsConditionSchema]);
240
+ var offerTargetItemSchema = z3.union([storefrontProductSchema, storefrontBundleSchema]);
241
+ var storefrontOfferTargetSchema = z3.object({
242
+ // The product or bundle the offer applies to.
243
+ item: offerTargetItemSchema,
244
+ // The pricing variation IDs the offer is restricted to; an empty list means all variations.
245
+ variations: z3.string().array()
246
+ });
247
+ function legacyOfferTargets(target, targetVariations) {
248
+ if (!target)
249
+ return [];
250
+ const items = Array.isArray(target) ? target : [target];
251
+ return items.map((item) => ({ item, variations: items.length === 1 ? targetVariations != null ? targetVariations : [] : [] }));
252
+ }
239
253
  var storefrontOfferSchema = z3.object({
240
254
  id: z3.string(),
241
- target: singleOrMultiple(z3.union([storefrontProductSchema, storefrontBundleSchema])),
242
- targetVariations: z3.string().array(),
255
+ // Each target pairs a product/bundle with the pricing variations the offer applies to (an empty
256
+ // list means all variations). This is the model to consume.
257
+ targets: z3.array(storefrontOfferTargetSchema).optional(),
258
+ // Legacy fields, kept optional only so old cached storefront responses still parse. The API now
259
+ // exposes the unified `targets` model; we derive `targets` from these when a response predates it.
260
+ // `.catch` guards against the deprecated shape drifting: a malformed legacy field is ignored
261
+ // rather than failing the whole response (newer responses carry `targets` anyway).
262
+ target: singleOrMultiple(offerTargetItemSchema).optional().catch(void 0),
263
+ targetVariations: z3.string().array().optional().catch(void 0),
243
264
  condition: offerConditionSchema,
244
265
  discount: discountSchema
245
- });
266
+ }).transform(({ target, targetVariations, targets, ...rest }) => ({
267
+ ...rest,
268
+ targets: targets != null ? targets : legacyOfferTargets(target, targetVariations)
269
+ }));
246
270
  var taxEstimateSchema = z3.object({
247
271
  rate: z3.number(),
248
272
  mode: z3.enum(["Exclusive", "Inclusive"]),
@@ -1642,11 +1666,27 @@ var OfferUtils = class _OfferUtils {
1642
1666
  // a. Not be owned, or all targets need to be owned
1643
1667
  // b. Not already in the cart
1644
1668
  static relevantTargets(offer, cartItems) {
1645
- if (Array.isArray(offer.target)) {
1646
- const allOwned = offer.target.every((i) => i.owned);
1647
- return offer.target.filter((i) => (allOwned || !i.owned) && !cartItems.some((l) => l.type === i.type && i.id === (l.type === "Product" ? l.productId : l.bundleId)));
1669
+ if (offer.targets.length > 1) {
1670
+ const allOwned = offer.targets.every((t) => t.item.owned);
1671
+ return offer.targets.filter((t) => (allOwned || !t.item.owned) && !cartItems.some((l) => l.type === t.item.type && t.item.id === (l.type === "Product" ? l.productId : l.bundleId)));
1648
1672
  }
1649
- return [offer.target];
1673
+ return offer.targets;
1674
+ }
1675
+ // The pricing variations a target restricts the offer to. An empty (or missing) variation list
1676
+ // means the offer is not narrowed to specific variations, in which case we keep the established
1677
+ // single default-variation upsell.
1678
+ static targetedVariations(target) {
1679
+ var _a;
1680
+ const { item, variations } = target;
1681
+ if (variations.length === 0)
1682
+ return item.defaultVariation ? [item.defaultVariation] : [];
1683
+ const itemVariations = (_a = item.variations) != null ? _a : item.defaultVariation ? [item.defaultVariation] : [];
1684
+ return itemVariations.filter((v) => variations.includes(v.id));
1685
+ }
1686
+ // Expands the relevant targets into one `{ target, variation }` entry per targeted variation, so
1687
+ // an offer targeting several variations (or several products) surfaces each as its own upsell row.
1688
+ static relevantTargetVariations(offer, cartItems) {
1689
+ return _OfferUtils.relevantTargets(offer, cartItems).flatMap((target) => _OfferUtils.targetedVariations(target).map((variation) => ({ target: target.item, variation })));
1650
1690
  }
1651
1691
  static applyToVariation(offer, variation) {
1652
1692
  const discount = DiscountUtils.apply(offer.discount, variation.price);
@@ -1657,8 +1697,7 @@ var OfferUtils = class _OfferUtils {
1657
1697
  };
1658
1698
  }
1659
1699
  static targetContainsBundle(offer, bundleId) {
1660
- if (Array.isArray(offer.target))
1661
- return offer.target.some((i) => i.type === "Bundle" && i.id === bundleId);
1700
+ return offer.targets.some((t) => t.item.type === "Bundle" && t.item.id === bundleId);
1662
1701
  }
1663
1702
  };
1664
1703
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moonbase.sh/storefront-api",
3
3
  "type": "module",
4
- "version": "2.3.1",
4
+ "version": "2.4.0",
5
5
  "description": "Package to let you build storefronts with Moonbase.sh as payment and delivery provider",
6
6
  "author": "Tobias Lønnerød Madsen <m@dsen.tv>",
7
7
  "license": "MIT",