@reactionary/feeds 0.10.54 → 0.10.56

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.
Files changed (2) hide show
  1. package/cli.cjs +151 -20
  2. package/package.json +9 -9
package/cli.cjs CHANGED
@@ -37222,6 +37222,9 @@ var init_product_model = __esm({
37222
37222
  weee_symbol: boolean2().default(false).meta({ description: "Indicates whether the WEEE symbol can be shown on the product" }),
37223
37223
  energy_class: string2().optional().meta({ description: "The energy class of the product, as required by EU regulations. A,B,C,D,E,F,G, etc" }),
37224
37224
  garan_duration: number2().optional().meta({ description: "The duration of the guarantee in months as by the EU Garan scheme. Only set if above 24." }),
37225
+ energy_class_range: string2().optional().meta({ description: 'The scale the energy class belongs to, e.g. "A-G", "A++-G" or "A+++-D". Needed to render the EU class arrow, because the same class letter is drawn differently on different scales.' }),
37226
+ eprel_registration_number: string2().optional().meta({ description: "The EPREL registration number of the product model (digits only, up to 19). Together with eprel_product_group it identifies the official EU energy label and class arrow." }),
37227
+ eprel_product_group: string2().optional().meta({ description: 'The EPREL product group URL code the model is registered under, e.g. "spaceheaters" or "localspaceheaters".' }),
37225
37228
  safety_warnings: string2().optional().meta({ description: "Any safety warnings associated with the product as required by EU regulations." }),
37226
37229
  composition: string2().optional().meta({ description: "The composition of the product as required by EU regulations." }),
37227
37230
  additional_disclosures: string2().optional().meta({ description: "Any additional disclosures associated with the product as required by EU regulations." }),
@@ -37314,6 +37317,9 @@ var init_product_search_model = __esm({
37314
37317
  weee_symbol: boolean2().default(false).meta({ description: "Indicates whether the WEEE symbol can be shown on the product" }),
37315
37318
  energy_class: string2().optional().meta({ description: "The energy class of the product, as required by EU regulations. A,B,C,D,E,F,G, etc" }),
37316
37319
  garan_duration: number2().optional().meta({ description: "The duration of the guarantee in months as by the EU Garan scheme. Only set if above 24." }),
37320
+ energy_class_range: string2().optional().meta({ description: 'The scale the energy class belongs to, e.g. "A-G", "A++-G" or "A+++-D". Needed to render the EU class arrow, because the same class letter is drawn differently on different scales.' }),
37321
+ eprel_registration_number: string2().optional().meta({ description: "The EPREL registration number of the product model (digits only, up to 19). Together with eprel_product_group it identifies the official EU energy label and class arrow." }),
37322
+ eprel_product_group: string2().optional().meta({ description: 'The EPREL product group URL code the model is registered under, e.g. "spaceheaters" or "localspaceheaters".' }),
37317
37323
  is_organic: boolean2().optional().meta({ description: "Indicates whether the product is organic" }),
37318
37324
  organic_certification_type: string2().optional().meta({ description: "The type of organic certification, e.g., EU_ORGANIC_LEAF, GOTS, ECOCERT." })
37319
37325
  });
@@ -37422,7 +37428,7 @@ var init_profile_model = __esm({
37422
37428
  });
37423
37429
 
37424
37430
  // packages/core/src/schemas/models/shipping-method.model.ts
37425
- var ShippingFulfillmentTypeSchema, ShippingProtocolDataSchema, PickupPointSchema, ShippingMethodSchema, ShippingInstructionSchema;
37431
+ var ShippingFulfillmentTypeSchema, ShippingProtocolDataSchema, SHIPPING_PROTOCOL_DATA_KEYS, PickupPointSchema, ShippingMethodSchema, ShippingInstructionSchema;
37426
37432
  var init_shipping_method_model = __esm({
37427
37433
  "packages/core/src/schemas/models/shipping-method.model.ts"() {
37428
37434
  "use strict";
@@ -37436,6 +37442,13 @@ var init_shipping_method_model = __esm({
37436
37442
  key: string2().meta({ description: 'The protocol-specific key, e.g. "timeSlotId".' }),
37437
37443
  value: union([string2(), record(string2(), json())]).meta({ description: "The protocol-specific value: either a plain string, or a JSON-serializable object for richer structures." })
37438
37444
  });
37445
+ SHIPPING_PROTOCOL_DATA_KEYS = {
37446
+ /**
37447
+ * The identifier (Store.identifier.key) of the brand's own store an
37448
+ * in-store pickup (BOPIS) shipping method is fulfilled from.
37449
+ */
37450
+ pickupStore: "pickup_store"
37451
+ };
37439
37452
  PickupPointSchema = looseObject({
37440
37453
  identifier: object({
37441
37454
  key: string2()
@@ -37457,7 +37470,7 @@ var init_shipping_method_model = __esm({
37457
37470
  deliveryTime: string2(),
37458
37471
  carrier: string2().optional(),
37459
37472
  fulfillmentType: ShippingFulfillmentTypeSchema.optional().meta({ description: `How this shipping method fulfills the order: "delivery" for shipment to an address (including third-party carrier service points selected via the shipping instruction's pickupPoint), "pickup" for collection at one of the brand's own stores (BOPIS). When absent, "delivery" can be assumed.` }),
37460
- protocolData: array(ShippingProtocolDataSchema).optional().meta({ description: "Additional provider-populated, protocol-specific data for this shipping method, e.g. available pickup time slots." })
37473
+ protocolData: array(ShippingProtocolDataSchema).optional().meta({ description: `Additional provider-populated, protocol-specific data for this shipping method, e.g. available pickup time slots. Conventional keys (see SHIPPING_PROTOCOL_DATA_KEYS) include "pickup_store": the identifier of the brand's own store a pickup method is fulfilled from.` })
37461
37474
  });
37462
37475
  ShippingInstructionSchema = BaseModelSchema.extend({
37463
37476
  shippingMethod: ShippingMethodIdentifierSchema,
@@ -159542,17 +159555,17 @@ var init_checkout_capability5 = __esm({
159542
159555
  *
159543
159556
  * example: this.includedFields = [includedFields, '+discounts.*'].join(',');
159544
159557
  */
159545
- includedFields = ["+items.*", "+order.id", "+order.display_id", "+order.custom_display_id"].join(",");
159558
+ includedFields = ["+items.*", "+order.id", "+order.display_id", "+order.custom_display_id", "+shipping_methods.data"].join(",");
159546
159559
  /**
159547
159560
  * This controls which fields are requested for the cart's shipping options.
159548
159561
  * You can override this in a subclass to add more fields as needed.
159549
159562
  *
159550
159563
  * The service zone's fulfillment set tells us whether an option is in-store
159551
- * pickup (BOPIS) or a delivery, and the option metadata lets medusa-side
159552
- * providers push additional data that is mapped to the shipping method's
159553
- * protocolData.
159564
+ * pickup (BOPIS) or a delivery, and the option data is the fulfillment
159565
+ * provider's payload (e.g. nShift option/carrier ids) that is mapped to the
159566
+ * shipping method's protocolData.
159554
159567
  */
159555
- shippingOptionFields = ["*service_zone.fulfillment_set", "+metadata"].join(",");
159568
+ shippingOptionFields = ["*service_zone.fulfillment_set", "+data"].join(",");
159556
159569
  initiateCheckoutForCartPayload(payload) {
159557
159570
  return {
159558
159571
  billing_address: payload.billingAddress ? this.mapAddressToStoreAddress(payload.billingAddress) : void 0,
@@ -159757,12 +159770,19 @@ var init_checkout_capability5 = __esm({
159757
159770
  throw new Error("Method not implemented.");
159758
159771
  }
159759
159772
  setShippingInstructionPayload(payload) {
159773
+ const data = {
159774
+ consent_for_unattended_delivery: payload.shippingInstruction.consentForUnattendedDelivery + "",
159775
+ instructions: payload.shippingInstruction.instructions || ""
159776
+ };
159777
+ for (const entry of payload.shippingInstruction.protocolData ?? []) {
159778
+ data[entry.key] = entry.value;
159779
+ }
159780
+ if (payload.shippingInstruction.pickupPoint) {
159781
+ data["pickup_point"] = payload.shippingInstruction.pickupPoint;
159782
+ }
159760
159783
  return {
159761
159784
  option_id: payload.shippingInstruction.shippingMethod.key,
159762
- data: {
159763
- consent_for_unattended_delivery: payload.shippingInstruction.consentForUnattendedDelivery + "",
159764
- instructions: payload.shippingInstruction.instructions || ""
159765
- }
159785
+ data
159766
159786
  };
159767
159787
  }
159768
159788
  /**
@@ -161428,6 +161448,18 @@ var init_product_search_capability6 = __esm({
161428
161448
  });
161429
161449
 
161430
161450
  // packages/medusa/src/utils/product-compliance.ts
161451
+ function parseEnergyClassRange(value) {
161452
+ const text2 = safeStringConvert(value)?.trim();
161453
+ return text2 && /^[A-Za-z0-9+\-–_ ]{1,20}$/.test(text2) ? text2 : void 0;
161454
+ }
161455
+ function parseEprelRegistrationNumber(value) {
161456
+ const text2 = safeStringConvert(value)?.trim();
161457
+ return text2 && /^\d{1,19}$/.test(text2) ? text2 : void 0;
161458
+ }
161459
+ function parseEprelProductGroup(value) {
161460
+ const text2 = safeStringConvert(value)?.trim().toLowerCase();
161461
+ return text2 && /^[a-z0-9]{1,64}$/.test(text2) ? text2 : void 0;
161462
+ }
161431
161463
  function parseProductSearchComplianceData(product) {
161432
161464
  if (!product.metadata) {
161433
161465
  return ProductSearchResultItemComplianceDataSchema.parse({});
@@ -161438,7 +161470,10 @@ function parseProductSearchComplianceData(product) {
161438
161470
  ce_marking: safeBoolConvert(metadata["compliance_data_ce_marking"]),
161439
161471
  weee_symbol: safeBoolConvert(metadata["compliance_data_weee_symbol"]),
161440
161472
  energy_class: safeStringConvert(metadata["compliance_data_energy_class"]),
161473
+ energy_class_range: parseEnergyClassRange(metadata["compliance_data_energy_class_range"]),
161441
161474
  garan_duration: duration3 === void 0 || !Number.isFinite(Number(duration3)) ? void 0 : Number(duration3),
161475
+ eprel_registration_number: parseEprelRegistrationNumber(metadata["compliance_data_eprel_registration_number"]),
161476
+ eprel_product_group: parseEprelProductGroup(metadata["compliance_data_eprel_product_group"]),
161442
161477
  is_organic: safeBoolConvert(metadata["compliance_data_organic_is_organic"]),
161443
161478
  organic_certification_type: safeStringConvert(metadata["compliance_data_organic_certification_type"])
161444
161479
  });
@@ -162658,7 +162693,7 @@ var init_checkout_factory5 = __esm({
162658
162693
  instructions = sm.data["instructions"] != null ? String(sm.data["instructions"]) : "";
162659
162694
  consentForUnattendedDelivery = sm.data["consent_for_unattended_delivery"] === "true";
162660
162695
  pickupStore = sm.data["pickup_store"] != null && sm.data["pickup_store"] !== "" ? String(sm.data["pickup_store"]) : void 0;
162661
- protocolData = this.parseShippingProtocolData(sm.data["shipping_protocol_data"]);
162696
+ protocolData = this.parseInstructionProtocolData(sm.data);
162662
162697
  }
162663
162698
  if (!pickupPoint) {
162664
162699
  pickupPoint = backupPickupPoint || "";
@@ -162746,11 +162781,46 @@ var init_checkout_factory5 = __esm({
162746
162781
  currency: data.calculated_price.currency_code?.toUpperCase() || _context.languageContext.currencyCode
162747
162782
  }),
162748
162783
  deliveryTime: "",
162784
+ carrier: this.parseShippingMethodCarrier(_context, data),
162749
162785
  fulfillmentType: this.parseFulfillmentType(_context, data),
162750
- protocolData: this.parseShippingMethodProtocolData(_context, data)
162786
+ protocolData: this.mergeShippingMethodProtocolData(
162787
+ this.parseShippingMethodProtocolData(_context, data),
162788
+ this.parseShippingMethodStoreReference(_context, data)
162789
+ )
162751
162790
  };
162752
162791
  return this.shippingMethodSchema.parse(sm);
162753
162792
  }
162793
+ /**
162794
+ * Appends a conventional entry to the provider-derived protocol data,
162795
+ * unless the provider data already carries the same key (explicit provider
162796
+ * data wins).
162797
+ */
162798
+ mergeShippingMethodProtocolData(protocolData, entry) {
162799
+ if (!entry) {
162800
+ return protocolData;
162801
+ }
162802
+ if ((protocolData ?? []).some((existing) => existing.key === entry.key)) {
162803
+ return protocolData;
162804
+ }
162805
+ return [...protocolData ?? [], entry];
162806
+ }
162807
+ /**
162808
+ * Extension point emitting the conventional "pickup_store" protocol data
162809
+ * entry for in-store pickup options: the stock location id of the service
162810
+ * zone's fulfillment set, which equals the store capability's
162811
+ * Store.identifier.key. Delivery options also carry a location (the
162812
+ * warehouse), so the entry is emitted for pickup options only.
162813
+ */
162814
+ parseShippingMethodStoreReference(_context, data) {
162815
+ if (this.parseFulfillmentType(_context, data) !== "pickup") {
162816
+ return void 0;
162817
+ }
162818
+ const locationId = data.service_zone?.fulfillment_set?.location?.id;
162819
+ if (!locationId) {
162820
+ return void 0;
162821
+ }
162822
+ return { key: SHIPPING_PROTOCOL_DATA_KEYS.pickupStore, value: locationId };
162823
+ }
162754
162824
  /**
162755
162825
  * Extension point to control how a Medusa shipping option maps to the core
162756
162826
  * fulfillment type. A shipping option belonging to a fulfillment set of type
@@ -162760,18 +162830,33 @@ var init_checkout_factory5 = __esm({
162760
162830
  return data.service_zone?.fulfillment_set?.type === "pickup" ? "pickup" : "delivery";
162761
162831
  }
162762
162832
  /**
162763
- * Extension point mapping a Medusa shipping option's metadata to the
162764
- * shipping method's protocolData, so medusa-side providers can push
162765
- * additional data (e.g. available pickup time slots) that reaches the
162766
- * client. String and JSON-object values are kept as-is, other primitives
162767
- * are stringified, and arrays/null entries are skipped.
162833
+ * Extension point mapping a Medusa shipping option's `data` - the payload
162834
+ * the fulfillment provider works with (e.g. nShift's option/carrier ids) -
162835
+ * to the shipping method's protocolData, so provider-protocol data reaches
162836
+ * the client. String and JSON-object values are kept as-is, other
162837
+ * primitives are stringified, and arrays/null entries are skipped.
162838
+ *
162839
+ * Option `metadata` is deliberately NOT mapped: it is merchant free-form
162840
+ * annotation, not protocol data. Override this hook to surface it.
162768
162841
  */
162769
162842
  parseShippingMethodProtocolData(_context, data) {
162770
- if (!data.metadata) {
162843
+ if (!data.data) {
162771
162844
  return void 0;
162772
162845
  }
162846
+ const entries = this.convertToProtocolDataEntries(data.data);
162847
+ return entries.length > 0 ? entries : void 0;
162848
+ }
162849
+ /**
162850
+ * Converts a Medusa key-value record into protocol data entries: string and
162851
+ * JSON-object values are kept as-is, other primitives are stringified, and
162852
+ * arrays/null entries are skipped. Keys listed in skipKeys are left out.
162853
+ */
162854
+ convertToProtocolDataEntries(record2, skipKeys = []) {
162773
162855
  const entries = [];
162774
- for (const [key, value] of Object.entries(data.metadata)) {
162856
+ for (const [key, value] of Object.entries(record2)) {
162857
+ if (skipKeys.includes(key)) {
162858
+ continue;
162859
+ }
162775
162860
  if (typeof value === "string") {
162776
162861
  entries.push({ key, value });
162777
162862
  } else if (typeof value === "number" || typeof value === "boolean") {
@@ -162780,6 +162865,49 @@ var init_checkout_factory5 = __esm({
162780
162865
  entries.push({ key, value });
162781
162866
  }
162782
162867
  }
162868
+ return entries;
162869
+ }
162870
+ /**
162871
+ * Extension point resolving the carrier of a shipping option from its
162872
+ * provider data (e.g. nShift's carrier_id), when present.
162873
+ */
162874
+ parseShippingMethodCarrier(_context, data) {
162875
+ const carrierId = data.data?.["carrier_id"];
162876
+ return typeof carrierId === "string" && carrierId.length > 0 ? carrierId : void 0;
162877
+ }
162878
+ /**
162879
+ * The persisted shipping method data keys that are NOT surfaced as
162880
+ * instruction protocol data: keys already represented as first-class
162881
+ * instruction fields, the legacy JSON blob, and provider-side values that
162882
+ * would mislead (nShift's data.price is not the charged amount).
162883
+ */
162884
+ instructionProtocolDataSkipKeys = [
162885
+ "pickup_store",
162886
+ "pickup_point",
162887
+ "instructions",
162888
+ "consent_for_unattended_delivery",
162889
+ "shipping_protocol_data",
162890
+ "price",
162891
+ "currency_code"
162892
+ ];
162893
+ /**
162894
+ * Builds the shipping instruction's protocolData from the persisted
162895
+ * shipping method data: the provider payload enriched by the backend (e.g.
162896
+ * nShift's session_id, carrier ids and optional delivery_time) merged with
162897
+ * whatever the client sent when setting the instruction. First-class and
162898
+ * misleading keys are skipped; the legacy shipping_protocol_data JSON blob
162899
+ * still contributes entries whose keys are not already present.
162900
+ */
162901
+ parseInstructionProtocolData(smData) {
162902
+ const entries = this.convertToProtocolDataEntries(
162903
+ smData,
162904
+ this.instructionProtocolDataSkipKeys
162905
+ );
162906
+ for (const legacyEntry of this.parseShippingProtocolData(smData["shipping_protocol_data"]) ?? []) {
162907
+ if (!entries.some((entry) => entry.key === legacyEntry.key)) {
162908
+ entries.push(legacyEntry);
162909
+ }
162910
+ }
162783
162911
  return entries.length > 0 ? entries : void 0;
162784
162912
  }
162785
162913
  /**
@@ -163528,7 +163656,10 @@ var init_product_factory5 = __esm({
163528
163656
  ce_marking: shared.ce_marking,
163529
163657
  weee_symbol: shared.weee_symbol,
163530
163658
  energy_class: shared.energy_class,
163659
+ energy_class_range: shared.energy_class_range,
163531
163660
  garan_duration: shared.garan_duration,
163661
+ eprel_registration_number: shared.eprel_registration_number,
163662
+ eprel_product_group: shared.eprel_product_group,
163532
163663
  safety_warnings: safeStringConvert(body.metadata?.["compliance_data_safety_warnings"]),
163533
163664
  composition: safeStringConvert(body.metadata?.["compliance_data_composition"]),
163534
163665
  additional_disclosures: safeStringConvert(body.metadata?.["compliance_data_additional_disclosures"]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactionary/feeds",
3
- "version": "0.10.54",
3
+ "version": "0.10.56",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./src/index.d.ts",
@@ -12,14 +12,14 @@
12
12
  "url": "git+https://github.com/Solteq/reactionary.git"
13
13
  },
14
14
  "dependencies": {
15
- "@reactionary/algolia": "0.10.54",
16
- "@reactionary/commercetools": "0.10.54",
17
- "@reactionary/core": "0.10.54",
18
- "@reactionary/fake": "0.10.54",
19
- "@reactionary/magento": "0.10.54",
20
- "@reactionary/medusa": "0.10.54",
21
- "@reactionary/meilisearch": "0.10.54",
22
- "@reactionary/unomi": "0.10.54",
15
+ "@reactionary/algolia": "0.10.56",
16
+ "@reactionary/commercetools": "0.10.56",
17
+ "@reactionary/core": "0.10.56",
18
+ "@reactionary/fake": "0.10.56",
19
+ "@reactionary/magento": "0.10.56",
20
+ "@reactionary/medusa": "0.10.56",
21
+ "@reactionary/meilisearch": "0.10.56",
22
+ "@reactionary/unomi": "0.10.56",
23
23
  "commander": "^15.0.0",
24
24
  "dotenv": "^17.2.2",
25
25
  "sitemap": "^9.0.1",