@reactionary/medusa 0.10.25 → 0.10.27

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.
@@ -7,6 +7,7 @@ import {
7
7
  success
8
8
  } from "@reactionary/core";
9
9
  import createDebug from "debug";
10
+ import { parseProductSearchComplianceData } from "../utils/product-compliance.js";
10
11
  const debug = createDebug("reactionary:medusa:product-recommendations");
11
12
  class MedusaProductRecommendationsCapability extends ProductRecommendationsCapability {
12
13
  config;
@@ -94,10 +95,14 @@ class MedusaProductRecommendationsCapability extends ProductRecommendationsCapab
94
95
  identifier,
95
96
  name,
96
97
  slug,
97
- variants
98
+ variants,
99
+ complianceData: this.buildProductComplianceData(_body)
98
100
  };
99
101
  return result;
100
102
  }
103
+ buildProductComplianceData(product) {
104
+ return parseProductSearchComplianceData(product);
105
+ }
101
106
  parseVariant(variant, product) {
102
107
  const img = ImageSchema.parse({
103
108
  sourceUrl: product.images?.[0].url ?? "",
@@ -1,8 +1,11 @@
1
1
  import {
2
2
  CategoryIdentifierSchema,
3
- ProductIdentifierSchema
3
+ ProductIdentifierSchema,
4
+ ProductComplianceDataSchema
4
5
  } from "@reactionary/core";
5
6
  import createDebug from "debug";
7
+ import { safeStringConvert } from "../../utils/medusa-helpers.js";
8
+ import { parseProductSearchComplianceData } from "../../utils/product-compliance.js";
6
9
  const debug = createDebug("reactionary:medusa:product");
7
10
  class MedusaProductFactory {
8
11
  productSchema;
@@ -112,6 +115,9 @@ class MedusaProductFactory {
112
115
  if (keysToExclude.includes(key)) {
113
116
  continue;
114
117
  }
118
+ if (key.startsWith("compliance_data")) {
119
+ continue;
120
+ }
115
121
  sharedAttributes.push(
116
122
  this.createSynthAttribute(key, key, String(value))
117
123
  );
@@ -119,6 +125,42 @@ class MedusaProductFactory {
119
125
  }
120
126
  return sharedAttributes;
121
127
  }
128
+ parseComplianceData(context, body) {
129
+ if (!body.metadata) {
130
+ return ProductComplianceDataSchema.parse({});
131
+ }
132
+ const shared = parseProductSearchComplianceData(body);
133
+ const complianceData = {
134
+ ce_marking: shared.ce_marking,
135
+ weee_symbol: shared.weee_symbol,
136
+ energy_class: shared.energy_class,
137
+ garan_duration: shared.garan_duration,
138
+ safety_warnings: safeStringConvert(body.metadata?.["compliance_data_safety_warnings"]),
139
+ composition: safeStringConvert(body.metadata?.["compliance_data_composition"]),
140
+ additional_disclosures: safeStringConvert(body.metadata?.["compliance_data_additional_disclosures"]),
141
+ organic: {
142
+ is_organic: shared.is_organic ?? false,
143
+ certification_type: shared.organic_certification_type,
144
+ control_body_code: safeStringConvert(body.metadata?.["compliance_data_organic_control_body_code"]),
145
+ agriculture_origin: safeStringConvert(body.metadata?.["compliance_data_organic_agriculture_origin"]),
146
+ certificate_url: safeStringConvert(body.metadata?.["compliance_data_organic_certificate_url"])
147
+ },
148
+ traceability: {
149
+ product_identifier: safeStringConvert(body.metadata?.["compliance_data_traceability_product_identifier"]),
150
+ manufacturer: {
151
+ name: safeStringConvert(body.metadata?.["compliance_data_traceability_manufacturer_name"]),
152
+ postal_address: safeStringConvert(body.metadata?.["compliance_data_traceability_manufacturer_postal_address"]),
153
+ electronic_address: safeStringConvert(body.metadata?.["compliance_data_traceability_manufacturer_electronic_address"])
154
+ },
155
+ eu_responsible_person: {
156
+ name: safeStringConvert(body.metadata?.["compliance_data_traceability_eu_responsible_person_name"]),
157
+ postal_address: safeStringConvert(body.metadata?.["compliance_data_traceability_eu_responsible_person_postal_address"]),
158
+ electronic_address: safeStringConvert(body.metadata?.["compliance_data_traceability_eu_responsible_person_electronic_address"])
159
+ }
160
+ }
161
+ };
162
+ return complianceData;
163
+ }
122
164
  parseProduct(context, data) {
123
165
  const identifier = ProductIdentifierSchema.parse({
124
166
  key: data.external_id || data.id
@@ -131,6 +173,7 @@ class MedusaProductFactory {
131
173
  ...data.categories?.map((cat) => cat.external_id).map((id) => CategoryIdentifierSchema.parse({ key: id || "" })) || []
132
174
  );
133
175
  const sharedAttributes = this.parseAttributes(context, data);
176
+ const complianceData = this.parseComplianceData(context, data);
134
177
  if (!data.variants) {
135
178
  debug("Product has no variants", data);
136
179
  throw new Error("Product has no variants " + data.external_id);
@@ -155,7 +198,8 @@ class MedusaProductFactory {
155
198
  published: true,
156
199
  sharedAttributes,
157
200
  slug,
158
- variants: otherVariants
201
+ variants: otherVariants,
202
+ complianceData
159
203
  };
160
204
  return this.productSchema.parse(result);
161
205
  }
@@ -3,6 +3,7 @@ import {
3
3
  ProductSearchResultItemVariantSchema,
4
4
  ProductVariantIdentifierSchema
5
5
  } from "@reactionary/core";
6
+ import { parseProductSearchComplianceData } from "../../utils/product-compliance.js";
6
7
  class MedusaProductAssociationsFactory {
7
8
  productAssociationSchema;
8
9
  constructor(productAssociationSchema) {
@@ -21,7 +22,8 @@ class MedusaProductAssociationsFactory {
21
22
  identifier,
22
23
  name,
23
24
  slug,
24
- variants
25
+ variants,
26
+ complianceData: this.parseComplianceData(data.product)
25
27
  };
26
28
  const result = {
27
29
  associationIdentifier: data.identifier,
@@ -30,6 +32,9 @@ class MedusaProductAssociationsFactory {
30
32
  };
31
33
  return this.productAssociationSchema.parse(result);
32
34
  }
35
+ parseComplianceData(product) {
36
+ return parseProductSearchComplianceData(product);
37
+ }
33
38
  parseVariant(_context, variant, product) {
34
39
  const img = ImageSchema.parse({
35
40
  sourceUrl: product.images?.[0].url ?? "",
@@ -3,6 +3,7 @@ import {
3
3
  ProductSearchResultItemVariantSchema,
4
4
  ProductVariantIdentifierSchema
5
5
  } from "@reactionary/core";
6
+ import { parseProductSearchComplianceData } from "../../utils/product-compliance.js";
6
7
  class MedusaProductSearchFactory {
7
8
  productSearchResultSchema;
8
9
  constructor(productSearchResultSchema) {
@@ -26,6 +27,9 @@ class MedusaProductSearchFactory {
26
27
  result.facets = [];
27
28
  return this.productSearchResultSchema.parse(result);
28
29
  }
30
+ parseProductSearchComplianceData(context, data) {
31
+ return parseProductSearchComplianceData(data);
32
+ }
29
33
  parseProductSearchResultItem(context, data) {
30
34
  const heroVariant = data.variants?.[0];
31
35
  const identifier = { key: data.external_id || data.id };
@@ -35,10 +39,12 @@ class MedusaProductSearchFactory {
35
39
  if (heroVariant) {
36
40
  variants.push(this.parseVariant(context, heroVariant, data));
37
41
  }
42
+ const complianceData = this.parseProductSearchComplianceData(context, data);
38
43
  const result = {
39
44
  identifier,
40
45
  name,
41
46
  slug,
47
+ complianceData,
42
48
  variants
43
49
  };
44
50
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactionary/medusa",
3
- "version": "0.10.25",
3
+ "version": "0.10.27",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./src/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@medusajs/js-sdk": "^2.13.3",
13
- "@reactionary/core": "0.10.25",
13
+ "@reactionary/core": "0.10.27",
14
14
  "debug": "^4.4.3",
15
15
  "@medusajs/types": "^2.13.3",
16
16
  "zod": "4.1.9"
@@ -1,5 +1,5 @@
1
1
  import type { StoreCollection, StoreProduct, StoreProductVariant } from '@medusajs/types';
2
- import { ProductRecommendationsCapability, type Cache, type ProductRecommendation, type ProductRecommendationsByCollectionQuery, type ProductSearchResultItemVariant, type RequestContext, type Result } from '@reactionary/core';
2
+ import { ProductRecommendationsCapability, type Cache, type ProductRecommendation, type ProductRecommendationsByCollectionQuery, type ProductSearchResultItemComplianceData, type ProductSearchResultItemVariant, type RequestContext, type Result } from '@reactionary/core';
3
3
  import type { MedusaAPI } from '../core/client.js';
4
4
  import type { MedusaConfiguration } from '../schema/configuration.schema.js';
5
5
  /**
@@ -36,6 +36,8 @@ export declare class MedusaProductRecommendationsCapability extends ProductRecom
36
36
  name: string;
37
37
  slug: string;
38
38
  variants: ProductSearchResultItemVariant[];
39
+ complianceData: ProductSearchResultItemComplianceData;
39
40
  };
41
+ protected buildProductComplianceData(product: StoreProduct): ProductSearchResultItemComplianceData;
40
42
  protected parseVariant(variant: StoreProductVariant, product: StoreProduct): ProductSearchResultItemVariant;
41
43
  }
@@ -1,5 +1,5 @@
1
1
  import type { StoreProduct, StoreProductVariant } from '@medusajs/types';
2
- import { type AnyProductSchema, type ProductAttribute, type ProductFactory, type ProductSchema, type ProductVariant, type RequestContext } from '@reactionary/core';
2
+ import { type AnyProductSchema, type ProductComplianceData, type ProductAttribute, type ProductFactory, type ProductSchema, type ProductVariant, type RequestContext } from '@reactionary/core';
3
3
  import type * as z from 'zod';
4
4
  export declare class MedusaProductFactory<TProductSchema extends AnyProductSchema = typeof ProductSchema> implements ProductFactory<TProductSchema> {
5
5
  readonly productSchema: TProductSchema;
@@ -7,5 +7,6 @@ export declare class MedusaProductFactory<TProductSchema extends AnyProductSchem
7
7
  protected parseVariant(_context: RequestContext, variant: StoreProductVariant, product: StoreProduct): ProductVariant;
8
8
  protected createSynthAttribute(key: string, name: string, value: string): ProductAttribute;
9
9
  protected parseAttributes(_context: RequestContext, _body: StoreProduct): Array<ProductAttribute>;
10
+ parseComplianceData(context: RequestContext, body: StoreProduct): ProductComplianceData;
10
11
  parseProduct(context: RequestContext, data: StoreProduct): z.output<TProductSchema>;
11
12
  }
@@ -1,5 +1,5 @@
1
1
  import type { StoreProduct, StoreProductVariant } from '@medusajs/types';
2
- import { type AnyProductAssociationSchema, type ProductAssociationSchema, type ProductAssociationsFactory, type ProductAssociationsIdentifier, type ProductSearchResultItemVariant, type RequestContext } from '@reactionary/core';
2
+ import { type AnyProductAssociationSchema, type ProductAssociationSchema, type ProductAssociationsFactory, type ProductAssociationsIdentifier, type ProductSearchResultItemComplianceData, type ProductSearchResultItemVariant, type RequestContext } from '@reactionary/core';
3
3
  import type * as z from 'zod';
4
4
  export interface MedusaProductAssociationFactoryInput {
5
5
  product: StoreProduct;
@@ -9,5 +9,6 @@ export declare class MedusaProductAssociationsFactory<TProductAssociationSchema
9
9
  readonly productAssociationSchema: TProductAssociationSchema;
10
10
  constructor(productAssociationSchema: TProductAssociationSchema);
11
11
  parseAssociation(context: RequestContext, data: MedusaProductAssociationFactoryInput): z.output<TProductAssociationSchema>;
12
+ protected parseComplianceData(product: StoreProduct): ProductSearchResultItemComplianceData;
12
13
  protected parseVariant(_context: RequestContext, variant: StoreProductVariant, product: StoreProduct): ProductSearchResultItemVariant;
13
14
  }
@@ -1,10 +1,11 @@
1
1
  import type { StoreProduct, StoreProductListResponse, StoreProductVariant } from '@medusajs/types';
2
- import { type AnyProductSearchResultSchema, type ProductSearchFactory, type ProductSearchQueryByTerm, type ProductSearchResultItem, type ProductSearchResultItemVariant, type ProductSearchResultSchema, type RequestContext } from '@reactionary/core';
2
+ import { type AnyProductSearchResultSchema, type ProductSearchFactory, type ProductSearchQueryByTerm, type ProductSearchResultItem, type ProductSearchResultItemComplianceData, type ProductSearchResultItemVariant, type ProductSearchResultSchema, type RequestContext } from '@reactionary/core';
3
3
  import type * as z from 'zod';
4
4
  export declare class MedusaProductSearchFactory<TProductSearchResultSchema extends AnyProductSearchResultSchema = typeof ProductSearchResultSchema> implements ProductSearchFactory<TProductSearchResultSchema> {
5
5
  readonly productSearchResultSchema: TProductSearchResultSchema;
6
6
  constructor(productSearchResultSchema: TProductSearchResultSchema);
7
7
  parseSearchResult(context: RequestContext, remote: StoreProductListResponse, query: ProductSearchQueryByTerm): z.output<TProductSearchResultSchema>;
8
+ protected parseProductSearchComplianceData(context: RequestContext, data: StoreProduct): ProductSearchResultItemComplianceData;
8
9
  protected parseProductSearchResultItem(context: RequestContext, data: StoreProduct): ProductSearchResultItem;
9
10
  protected parseVariant(_context: RequestContext, variant: StoreProductVariant, product: StoreProduct): ProductSearchResultItemVariant;
10
11
  }
@@ -33,3 +33,5 @@ export declare function parseMedusaItemPrice(remoteItem: {
33
33
  * Handles capability implementation errors with consistent formatting
34
34
  */
35
35
  export declare function handleProviderError(action: string, error: unknown): never;
36
+ export declare function safeBoolConvert(val?: unknown): boolean;
37
+ export declare function safeStringConvert(val?: unknown, defaultValue?: string): string | undefined;
@@ -0,0 +1,3 @@
1
+ import type { StoreProduct } from '@medusajs/types';
2
+ import { type ProductSearchResultItemComplianceData } from '@reactionary/core';
3
+ export declare function parseProductSearchComplianceData(product: Pick<StoreProduct, 'metadata'>): ProductSearchResultItemComplianceData;
@@ -65,8 +65,22 @@ function handleProviderError(action, error) {
65
65
  `Failed to ${action}: ${error instanceof Error ? error.message : "Unknown error"}`
66
66
  );
67
67
  }
68
+ function safeBoolConvert(val) {
69
+ if (!val) {
70
+ return false;
71
+ }
72
+ return String(val).toLowerCase() === "true";
73
+ }
74
+ function safeStringConvert(val, defaultValue) {
75
+ if (!val) {
76
+ return defaultValue;
77
+ }
78
+ return String(val);
79
+ }
68
80
  export {
69
81
  handleProviderError,
70
82
  parseMedusaCostBreakdown,
71
- parseMedusaItemPrice
83
+ parseMedusaItemPrice,
84
+ safeBoolConvert,
85
+ safeStringConvert
72
86
  };
@@ -0,0 +1,22 @@
1
+ import {
2
+ ProductSearchResultItemComplianceDataSchema
3
+ } from "@reactionary/core";
4
+ import { safeBoolConvert, safeStringConvert } from "./medusa-helpers.js";
5
+ function parseProductSearchComplianceData(product) {
6
+ if (!product.metadata) {
7
+ return ProductSearchResultItemComplianceDataSchema.parse({});
8
+ }
9
+ const metadata = product.metadata;
10
+ const duration = safeStringConvert(metadata["compliance_data_garan_duration"]);
11
+ return ProductSearchResultItemComplianceDataSchema.parse({
12
+ ce_marking: safeBoolConvert(metadata["compliance_data_ce_marking"]),
13
+ weee_symbol: safeBoolConvert(metadata["compliance_data_weee_symbol"]),
14
+ energy_class: safeStringConvert(metadata["compliance_data_energy_class"]),
15
+ garan_duration: duration === void 0 || !Number.isFinite(Number(duration)) ? void 0 : Number(duration),
16
+ is_organic: safeBoolConvert(metadata["compliance_data_organic_is_organic"]),
17
+ organic_certification_type: safeStringConvert(metadata["compliance_data_organic_certification_type"])
18
+ });
19
+ }
20
+ export {
21
+ parseProductSearchComplianceData
22
+ };