@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.
- package/capabilities/product-recommendations.capability.js +6 -1
- package/factories/product/product.factory.js +46 -2
- package/factories/product-associations/product-associations.factory.js +6 -1
- package/factories/product-search/product-search.factory.js +6 -0
- package/package.json +2 -2
- package/src/capabilities/product-recommendations.capability.d.ts +3 -1
- package/src/factories/product/product.factory.d.ts +2 -1
- package/src/factories/product-associations/product-associations.factory.d.ts +2 -1
- package/src/factories/product-search/product-search.factory.d.ts +2 -1
- package/src/utils/medusa-helpers.d.ts +2 -0
- package/src/utils/product-compliance.d.ts +3 -0
- package/utils/medusa-helpers.js +15 -1
- package/utils/product-compliance.js +22 -0
|
@@ -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.
|
|
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.
|
|
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;
|
package/utils/medusa-helpers.js
CHANGED
|
@@ -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
|
+
};
|