medusa-product-helper 0.0.13 → 0.0.18
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/.medusa/server/src/admin/index.js +59 -117
- package/.medusa/server/src/admin/index.mjs +59 -117
- package/.medusa/server/src/api/store/product-helper/products/route.js +112 -0
- package/.medusa/server/src/api/store/product-helper/products/validators.js +3 -1
- package/.medusa/server/src/config/product-helper-options.js +15 -1
- package/.medusa/server/src/index.js +101 -0
- package/.medusa/server/src/providers/filter-providers/availability-provider.js +82 -0
- package/.medusa/server/src/providers/filter-providers/base-filter-provider.js +14 -0
- package/.medusa/server/src/providers/filter-providers/base-product-provider.js +59 -0
- package/.medusa/server/src/providers/filter-providers/category-provider.js +36 -0
- package/.medusa/server/src/providers/filter-providers/collection-provider.js +36 -0
- package/.medusa/server/src/providers/filter-providers/index.js +58 -0
- package/.medusa/server/src/providers/filter-providers/metadata-provider.js +69 -0
- package/.medusa/server/src/providers/filter-providers/price-range-provider.js +95 -0
- package/.medusa/server/src/providers/filter-providers/promotion-provider.js +134 -0
- package/.medusa/server/src/providers/filter-providers/promotion-window-provider.js +85 -0
- package/.medusa/server/src/providers/filter-providers/rating-provider.js +69 -0
- package/.medusa/server/src/services/dynamic-filter-service.js +525 -0
- package/.medusa/server/src/services/filter-provider-loader.js +107 -0
- package/.medusa/server/src/services/filter-provider-registry.js +43 -0
- package/.medusa/server/src/services/product-filter-service.js +183 -0
- package/.medusa/server/src/shared/product-metadata/utils.js +66 -116
- package/.medusa/server/src/utils/query-builders/product-filters.js +89 -111
- package/.medusa/server/src/utils/query-parser.js +51 -0
- package/.medusa/server/src/workflows/add-to-wishlist.js +12 -26
- package/.medusa/server/src/workflows/get-wishlist.js +53 -51
- package/.medusa/server/src/workflows/remove-from-wishlist.js +3 -8
- package/README.md +89 -0
- package/package.json +3 -3
|
@@ -3,107 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.buildProductFilterPlan = buildProductFilterPlan;
|
|
4
4
|
exports.buildBestSellingPlan = buildBestSellingPlan;
|
|
5
5
|
function buildProductFilterPlan({ query, options, }) {
|
|
6
|
-
const baseFilters =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
if (query.collection_id?.length) {
|
|
14
|
-
baseFilters.collection_id = query.collection_id;
|
|
15
|
-
}
|
|
16
|
-
if (query.category_id?.length) {
|
|
17
|
-
baseFilters.categories = {
|
|
18
|
-
id: query.category_id,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
if (query.tags?.length) {
|
|
22
|
-
baseFilters.tags = {
|
|
23
|
-
value: query.tags,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
if (query.sales_channel_id?.length) {
|
|
27
|
-
baseFilters.sales_channels = {
|
|
28
|
-
id: query.sales_channel_id,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
const metadataAllowList = new Set(options.metadata.products.descriptors
|
|
32
|
-
.filter((descriptor) => descriptor.filterable)
|
|
33
|
-
.map((descriptor) => descriptor.key));
|
|
34
|
-
const metadataFilters = metadataAllowList.size === 0
|
|
35
|
-
? {}
|
|
36
|
-
: Object.entries(query.metadata ?? {}).reduce((acc, [key, value]) => {
|
|
37
|
-
if (metadataAllowList.has(key)) {
|
|
38
|
-
acc[key] = value;
|
|
39
|
-
}
|
|
40
|
-
return acc;
|
|
41
|
-
}, {});
|
|
42
|
-
const priceRange = typeof query.price_min !== "undefined" ||
|
|
43
|
-
typeof query.price_max !== "undefined"
|
|
44
|
-
? {
|
|
45
|
-
min: query.price_min,
|
|
46
|
-
max: query.price_max,
|
|
47
|
-
}
|
|
48
|
-
: options.default_price_range.min !== null ||
|
|
49
|
-
options.default_price_range.max !== null
|
|
50
|
-
? {
|
|
51
|
-
min: options.default_price_range.min ?? undefined,
|
|
52
|
-
max: options.default_price_range.max ?? undefined,
|
|
53
|
-
currency_code: options.default_price_range.currency_code,
|
|
54
|
-
}
|
|
55
|
-
: undefined;
|
|
56
|
-
const promotionWindow = {
|
|
57
|
-
startKey: options.promotion_window.start_metadata_key,
|
|
58
|
-
endKey: options.promotion_window.end_metadata_key,
|
|
59
|
-
range: query.promotion_start || query.promotion_end
|
|
60
|
-
? {
|
|
61
|
-
start: query.promotion_start,
|
|
62
|
-
end: query.promotion_end,
|
|
63
|
-
}
|
|
64
|
-
: undefined,
|
|
65
|
-
activeOn: query.promotion_active_on,
|
|
66
|
-
includeOpen: typeof query.include_open_promotions === "boolean"
|
|
67
|
-
? query.include_open_promotions
|
|
68
|
-
: options.promotion_window.treat_open_ended_as_active,
|
|
69
|
-
};
|
|
70
|
-
const availability = {
|
|
71
|
-
statuses: query.availability_status ?? [],
|
|
72
|
-
include_preorder: typeof query.include_preorder === "boolean"
|
|
73
|
-
? query.include_preorder
|
|
74
|
-
: options.availability.include_preorder,
|
|
75
|
-
include_backorder: typeof query.include_backorder === "boolean"
|
|
76
|
-
? query.include_backorder
|
|
77
|
-
: options.availability.include_backorder,
|
|
78
|
-
include_gift_cards: typeof query.include_gift_cards === "boolean"
|
|
79
|
-
? query.include_gift_cards
|
|
80
|
-
: options.availability.include_gift_cards,
|
|
81
|
-
publishable_only: typeof query.publishable_only === "boolean"
|
|
82
|
-
? query.publishable_only
|
|
83
|
-
: options.availability.publishable_only,
|
|
84
|
-
};
|
|
85
|
-
const rating = options.rating.enabled
|
|
86
|
-
? {
|
|
87
|
-
enabled: true,
|
|
88
|
-
min: typeof query.rating_min !== "undefined"
|
|
89
|
-
? query.rating_min
|
|
90
|
-
: options.rating.min,
|
|
91
|
-
max: typeof query.rating_max !== "undefined"
|
|
92
|
-
? query.rating_max
|
|
93
|
-
: options.rating.max,
|
|
94
|
-
require_reviews: typeof query.rating_required === "boolean"
|
|
95
|
-
? query.rating_required
|
|
96
|
-
: options.rating.require_reviews,
|
|
97
|
-
}
|
|
98
|
-
: {
|
|
99
|
-
enabled: false,
|
|
100
|
-
require_reviews: false,
|
|
101
|
-
};
|
|
6
|
+
const baseFilters = buildBaseFilters(query);
|
|
7
|
+
const metadataFilters = buildMetadataFilters(query, options);
|
|
8
|
+
const priceRange = buildPriceRange(query, options);
|
|
9
|
+
const promotionWindow = buildPromotionWindow(query, options);
|
|
10
|
+
const availability = buildAvailability(query, options);
|
|
11
|
+
const rating = buildRating(query, options);
|
|
102
12
|
return {
|
|
103
|
-
pagination: {
|
|
104
|
-
limit: query.limit,
|
|
105
|
-
offset: query.offset,
|
|
106
|
-
},
|
|
13
|
+
pagination: { limit: query.limit, offset: query.offset },
|
|
107
14
|
projection: {
|
|
108
15
|
fields: query.fields,
|
|
109
16
|
expand: query.expand,
|
|
@@ -118,22 +25,93 @@ function buildProductFilterPlan({ query, options, }) {
|
|
|
118
25
|
rating,
|
|
119
26
|
};
|
|
120
27
|
}
|
|
28
|
+
function buildBaseFilters(query) {
|
|
29
|
+
const filters = {};
|
|
30
|
+
if (query.id?.length)
|
|
31
|
+
filters.id = query.id;
|
|
32
|
+
if (query.handle?.length)
|
|
33
|
+
filters.handle = query.handle;
|
|
34
|
+
if (query.collection_id?.length)
|
|
35
|
+
filters.collection_id = query.collection_id;
|
|
36
|
+
if (query.tags?.length)
|
|
37
|
+
filters.tags = { value: query.tags };
|
|
38
|
+
if (query.sales_channel_id?.length)
|
|
39
|
+
filters.sales_channels = { id: query.sales_channel_id };
|
|
40
|
+
if (query.category_id?.length) {
|
|
41
|
+
filters.categories = { id: query.category_id };
|
|
42
|
+
}
|
|
43
|
+
return filters;
|
|
44
|
+
}
|
|
45
|
+
function buildMetadataFilters(query, options) {
|
|
46
|
+
const metadataAllowList = new Set(options.metadata.products.descriptors
|
|
47
|
+
.filter(descriptor => descriptor.filterable)
|
|
48
|
+
.map(descriptor => descriptor.key));
|
|
49
|
+
if (metadataAllowList.size === 0 || !query.metadata)
|
|
50
|
+
return {};
|
|
51
|
+
return Object.entries(query.metadata).reduce((acc, [key, value]) => {
|
|
52
|
+
if (metadataAllowList.has(key))
|
|
53
|
+
acc[key] = value;
|
|
54
|
+
return acc;
|
|
55
|
+
}, {});
|
|
56
|
+
}
|
|
57
|
+
function buildPriceRange(query, options) {
|
|
58
|
+
const hasQueryRange = query.price_min !== undefined || query.price_max !== undefined;
|
|
59
|
+
const hasDefaultRange = options.default_price_range.min !== null || options.default_price_range.max !== null;
|
|
60
|
+
if (hasQueryRange) {
|
|
61
|
+
return {
|
|
62
|
+
min: query.price_min,
|
|
63
|
+
max: query.price_max,
|
|
64
|
+
currency_code: options.default_price_range.currency_code
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (hasDefaultRange) {
|
|
68
|
+
return {
|
|
69
|
+
min: options.default_price_range.min ?? undefined,
|
|
70
|
+
max: options.default_price_range.max ?? undefined,
|
|
71
|
+
currency_code: options.default_price_range.currency_code
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
function buildPromotionWindow(query, options) {
|
|
77
|
+
const hasRange = query.promotion_start || query.promotion_end;
|
|
78
|
+
return {
|
|
79
|
+
startKey: options.promotion_window.start_metadata_key,
|
|
80
|
+
endKey: options.promotion_window.end_metadata_key,
|
|
81
|
+
range: hasRange ? { start: query.promotion_start, end: query.promotion_end } : undefined,
|
|
82
|
+
activeOn: query.promotion_active_on,
|
|
83
|
+
includeOpen: query.include_open_promotions ?? options.promotion_window.treat_open_ended_as_active
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function buildAvailability(query, options) {
|
|
87
|
+
return {
|
|
88
|
+
statuses: query.availability_status ?? [],
|
|
89
|
+
include_preorder: query.include_preorder ?? options.availability.include_preorder,
|
|
90
|
+
include_backorder: query.include_backorder ?? options.availability.include_backorder,
|
|
91
|
+
include_gift_cards: query.include_gift_cards ?? options.availability.include_gift_cards,
|
|
92
|
+
publishable_only: query.publishable_only ?? options.availability.publishable_only
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function buildRating(query, options) {
|
|
96
|
+
if (!options.rating.enabled) {
|
|
97
|
+
return { enabled: false, require_reviews: false };
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
enabled: true,
|
|
101
|
+
min: query.rating_min ?? options.rating.min,
|
|
102
|
+
max: query.rating_max ?? options.rating.max,
|
|
103
|
+
require_reviews: query.rating_required ?? options.rating.require_reviews
|
|
104
|
+
};
|
|
105
|
+
}
|
|
121
106
|
function buildBestSellingPlan(query) {
|
|
107
|
+
const hasTimeframe = query.timeframe_from || query.timeframe_to;
|
|
122
108
|
return {
|
|
123
|
-
pagination: {
|
|
124
|
-
|
|
125
|
-
offset: query.offset,
|
|
126
|
-
},
|
|
127
|
-
timeframe: query.timeframe_from || query.timeframe_to
|
|
128
|
-
? {
|
|
129
|
-
from: query.timeframe_from,
|
|
130
|
-
to: query.timeframe_to,
|
|
131
|
-
}
|
|
132
|
-
: undefined,
|
|
109
|
+
pagination: { limit: query.limit, offset: query.offset },
|
|
110
|
+
timeframe: hasTimeframe ? { from: query.timeframe_from, to: query.timeframe_to } : undefined,
|
|
133
111
|
sales_channel_id: query.sales_channel_id,
|
|
134
112
|
region_id: query.region_id,
|
|
135
113
|
product_id: query.product_id,
|
|
136
114
|
variant_id: query.variant_id,
|
|
137
115
|
};
|
|
138
116
|
}
|
|
139
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
117
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdC1maWx0ZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3F1ZXJ5LWJ1aWxkZXJzL3Byb2R1Y3QtZmlsdGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQXNDQSx3REE2QkM7QUEwR0Qsb0RBV0M7QUFsSkQsU0FBZ0Isc0JBQXNCLENBQUMsRUFDckMsS0FBSyxFQUNMLE9BQU8sR0FJUjtJQUNDLE1BQU0sV0FBVyxHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzNDLE1BQU0sZUFBZSxHQUFHLG9CQUFvQixDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUM1RCxNQUFNLFVBQVUsR0FBRyxlQUFlLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ2xELE1BQU0sZUFBZSxHQUFHLG9CQUFvQixDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUM1RCxNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDdEQsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUUxQyxPQUFPO1FBQ0wsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLEVBQUU7UUFDeEQsVUFBVSxFQUFFO1lBQ1YsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1lBQ3BCLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtZQUNwQixLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7WUFDbEIsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ1g7UUFDRCxXQUFXO1FBQ1gsZUFBZTtRQUNmLFVBQVU7UUFDVixlQUFlO1FBQ2YsWUFBWTtRQUNaLE1BQU07S0FDUCxDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQVMsZ0JBQWdCLENBQUMs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
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Query Parameter Parser Utility
|
|
4
|
+
*
|
|
5
|
+
* Normalizes query parameters from both formats:
|
|
6
|
+
* - Bracketed flat: `price_range[min]=10&price_range[max]=100`
|
|
7
|
+
* - Nested objects: `{ price_range: { min: 10, max: 100 } }`
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.normalizeQueryParams = normalizeQueryParams;
|
|
11
|
+
function parseBracketedKey(key) {
|
|
12
|
+
const match = key.match(/^([^[]+)\[([^\]]+)\]$/);
|
|
13
|
+
if (match) {
|
|
14
|
+
return { base: match[1], key: match[2] };
|
|
15
|
+
}
|
|
16
|
+
return { base: key, key: null };
|
|
17
|
+
}
|
|
18
|
+
function isPlainObject(value) {
|
|
19
|
+
return value !== null &&
|
|
20
|
+
typeof value === "object" &&
|
|
21
|
+
!Array.isArray(value) &&
|
|
22
|
+
Object.getPrototypeOf(value) === Object.prototype;
|
|
23
|
+
}
|
|
24
|
+
function normalizeQueryParams(query) {
|
|
25
|
+
const normalized = {};
|
|
26
|
+
const nestedKeys = {};
|
|
27
|
+
for (const [key, value] of Object.entries(query)) {
|
|
28
|
+
const { base, key: nestedKey } = parseBracketedKey(key);
|
|
29
|
+
if (nestedKey !== null) {
|
|
30
|
+
// Bracketed key: price_range[min]
|
|
31
|
+
if (!nestedKeys[base])
|
|
32
|
+
nestedKeys[base] = {};
|
|
33
|
+
nestedKeys[base][nestedKey] = value;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Flat key: category_id or already nested object
|
|
37
|
+
normalized[base] = isPlainObject(value) ? value : value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Merge bracketed keys into normalized result
|
|
41
|
+
for (const [base, nestedValues] of Object.entries(nestedKeys)) {
|
|
42
|
+
if (isPlainObject(normalized[base])) {
|
|
43
|
+
normalized[base] = { ...normalized[base], ...nestedValues };
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
normalized[base] = nestedValues;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktcGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3F1ZXJ5LXBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOztBQW1CSCxvREEyQkM7QUE1Q0QsU0FBUyxpQkFBaUIsQ0FBQyxHQUFXO0lBQ3BDLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQTtJQUVoRCxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1YsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFBO0lBQzFDLENBQUM7SUFFRCxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUE7QUFDakMsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLEtBQWM7SUFDbkMsT0FBTyxLQUFLLEtBQUssSUFBSTtRQUNkLE9BQU8sS0FBSyxLQUFLLFFBQVE7UUFDekIsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztRQUNyQixNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxLQUFLLE1BQU0sQ0FBQyxTQUFTLENBQUE7QUFDMUQsQ0FBQztBQUVELFNBQWdCLG9CQUFvQixDQUFDLEtBQThCO0lBQ2pFLE1BQU0sVUFBVSxHQUE0QixFQUFFLENBQUE7SUFDOUMsTUFBTSxVQUFVLEdBQTRDLEVBQUUsQ0FBQTtJQUU5RCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2pELE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxHQUFHLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBRXZELElBQUksU0FBUyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3ZCLGtDQUFrQztZQUNsQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztnQkFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFBO1lBQzVDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxLQUFLLENBQUE7UUFDckMsQ0FBQzthQUFNLENBQUM7WUFDTixpREFBaUQ7WUFDakQsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUE7UUFDekQsQ0FBQztJQUNILENBQUM7SUFFRCw4Q0FBOEM7SUFDOUMsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUM5RCxJQUFJLGFBQWEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3BDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBNEIsRUFBRSxHQUFHLFlBQVksRUFBRSxDQUFBO1FBQ3hGLENBQUM7YUFBTSxDQUFDO1lBQ04sVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLFlBQVksQ0FBQTtRQUNqQyxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sVUFBVSxDQUFBO0FBQ25CLENBQUMifQ==
|
|
@@ -5,37 +5,25 @@ const utils_1 = require("@medusajs/framework/utils");
|
|
|
5
5
|
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
6
6
|
const wishlist_1 = require("../modules/wishlist");
|
|
7
7
|
const validateCustomerAndProductStep = (0, workflows_sdk_1.createStep)("validate-customer-and-product", async (input, { container }) => {
|
|
8
|
-
// Validate customer exists using remote query
|
|
9
8
|
const remoteQuery = container.resolve(utils_1.ContainerRegistrationKeys.REMOTE_QUERY);
|
|
9
|
+
// Validate customer exists
|
|
10
10
|
const customerQuery = (0, utils_1.remoteQueryObjectFromString)({
|
|
11
11
|
entryPoint: "customer",
|
|
12
12
|
fields: ["id"],
|
|
13
|
-
|
|
14
|
-
filters: {
|
|
15
|
-
id: [input.customer_id],
|
|
16
|
-
},
|
|
17
|
-
},
|
|
13
|
+
filters: { id: [input.customer_id] },
|
|
18
14
|
});
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
// Validate product exists using remote query
|
|
15
|
+
const [customer] = await remoteQuery(customerQuery);
|
|
16
|
+
if (!customer)
|
|
17
|
+
throw new Error(`Customer ${input.customer_id} not found`);
|
|
18
|
+
// Validate product exists
|
|
25
19
|
const productQuery = (0, utils_1.remoteQueryObjectFromString)({
|
|
26
20
|
entryPoint: "product",
|
|
27
21
|
fields: ["id"],
|
|
28
|
-
|
|
29
|
-
filters: {
|
|
30
|
-
id: [input.product_id],
|
|
31
|
-
},
|
|
32
|
-
},
|
|
22
|
+
filters: { id: [input.product_id] },
|
|
33
23
|
});
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
throw new Error(`Product with id ${input.product_id} not found`);
|
|
38
|
-
}
|
|
24
|
+
const [product] = await remoteQuery(productQuery);
|
|
25
|
+
if (!product)
|
|
26
|
+
throw new Error(`Product ${input.product_id} not found`);
|
|
39
27
|
return new workflows_sdk_1.StepResponse({
|
|
40
28
|
customer_id: input.customer_id,
|
|
41
29
|
product_id: input.product_id,
|
|
@@ -49,9 +37,7 @@ const addToWishlistStep = (0, workflows_sdk_1.createStep)("add-to-wishlist", asy
|
|
|
49
37
|
exports.addToWishlistWorkflow = (0, workflows_sdk_1.createWorkflow)("add-to-wishlist", (input) => {
|
|
50
38
|
const validated = validateCustomerAndProductStep(input);
|
|
51
39
|
const wishlistItem = addToWishlistStep(validated);
|
|
52
|
-
return new workflows_sdk_1.WorkflowResponse({
|
|
53
|
-
wishlist_item: wishlistItem,
|
|
54
|
-
});
|
|
40
|
+
return new workflows_sdk_1.WorkflowResponse({ wishlist_item: wishlistItem });
|
|
55
41
|
});
|
|
56
42
|
exports.default = exports.addToWishlistWorkflow;
|
|
57
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRkLXRvLXdpc2hsaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9hZGQtdG8td2lzaGxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBR2tDO0FBRWxDLHFFQUswQztBQUMxQyxrREFBcUQ7QUFrQnJELE1BQU0sOEJBQThCLEdBQUcsSUFBQSwwQkFBVSxFQUMvQywrQkFBK0IsRUFDL0IsS0FBSyxFQUFFLEtBQXlCLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ2pELE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQXNCLGlDQUF5QixDQUFDLFlBQVksQ0FBQyxDQUFBO0lBRWxHLDJCQUEyQjtJQUMzQixNQUFNLGFBQWEsR0FBRyxJQUFBLG1DQUEyQixFQUFDO1FBQ2hELFVBQVUsRUFBRSxVQUFVO1FBQ3RCLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQztRQUNkLE9BQU8sRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRTtLQUNyQyxDQUFDLENBQUE7SUFFRixNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsTUFBTSxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUE7SUFDbkQsSUFBSSxDQUFDLFFBQVE7UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLFlBQVksS0FBSyxDQUFDLFdBQVcsWUFBWSxDQUFDLENBQUE7SUFFekUsMEJBQTBCO0lBQzFCLE1BQU0sWUFBWSxHQUFHLElBQUEsbUNBQTJCLEVBQUM7UUFDL0MsVUFBVSxFQUFFLFNBQVM7UUFDckIsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDO1FBQ2QsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxFQUFFO0tBQ3BDLENBQUMsQ0FBQTtJQUVGLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxNQUFNLFdBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUNqRCxJQUFJLENBQUMsT0FBTztRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLENBQUMsVUFBVSxZQUFZLENBQUMsQ0FBQTtJQUV0RSxPQUFPLElBQUksNEJBQVksQ0FBQztRQUN0QixXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVc7UUFDOUIsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO0tBQzdCLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FDRixDQUFBO0FBRUQsTUFBTSxpQkFBaUIsR0FBRyxJQUFBLDBCQUFVLEVBQ2xDLGlCQUFpQixFQUNqQixLQUFLLEVBQUUsS0FBa0QsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDMUUsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBd0IsMEJBQWUsQ0FBQyxDQUFBO0lBQ2pGLE1BQU0sWUFBWSxHQUFHLE1BQU0sZUFBZSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUU3RixPQUFPLElBQUksNEJBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUN2QyxDQUFDLENBQ0YsQ0FBQTtBQUVZLFFBQUEscUJBQXFCLEdBQUcsSUFBQSw4QkFBYyxFQUNqRCxpQkFBaUIsRUFDakIsQ0FBQyxLQUF5QixFQUF5QyxFQUFFO0lBQ25FLE1BQU0sU0FBUyxHQUFHLDhCQUE4QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ3ZELE1BQU0sWUFBWSxHQUFHLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBRWpELE9BQU8sSUFBSSxnQ0FBZ0IsQ0FBQyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFBO0FBQzlELENBQUMsQ0FDRixDQUFBO0FBRUQsa0JBQWUsNkJBQXFCLENBQUEifQ==
|
|
@@ -8,71 +8,73 @@ const fetchWishlistItemsStep = (0, workflows_sdk_1.createStep)("fetch-wishlist-i
|
|
|
8
8
|
const wishlistService = container.resolve(wishlist_1.WISHLIST_MODULE);
|
|
9
9
|
const wishlist = await wishlistService.getWishlist(input.customer_id, input.options);
|
|
10
10
|
const includeDetails = input.options?.includeDetails ?? false;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
let formattedWishlist = [];
|
|
12
|
+
if (includeDetails && Array.isArray(wishlist)) {
|
|
13
|
+
// When includeDetails is true, wishlist should be array of objects with id, product_id, etc.
|
|
14
|
+
const wishlistItems = wishlist;
|
|
15
|
+
formattedWishlist = wishlistItems.map((item) => ({
|
|
15
16
|
id: item.id,
|
|
16
17
|
product_id: item.product_id,
|
|
17
|
-
created_at: item.created_at
|
|
18
|
+
created_at: item.created_at
|
|
18
19
|
}));
|
|
19
20
|
}
|
|
20
|
-
else {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
else if (Array.isArray(wishlist)) {
|
|
22
|
+
// When includeDetails is false, wishlist should be array of product_id strings
|
|
23
|
+
const productIds = wishlist;
|
|
24
|
+
formattedWishlist = productIds
|
|
25
|
+
.filter((product_id) => typeof product_id === "string" && product_id.length > 0)
|
|
26
|
+
.map(product_id => ({
|
|
27
|
+
product_id: String(product_id)
|
|
23
28
|
}));
|
|
24
29
|
}
|
|
25
|
-
return new workflows_sdk_1.StepResponse({
|
|
26
|
-
wishlist: formattedWishlist,
|
|
27
|
-
includeDetails,
|
|
28
|
-
});
|
|
30
|
+
return new workflows_sdk_1.StepResponse({ wishlist: formattedWishlist, includeDetails });
|
|
29
31
|
});
|
|
30
32
|
const enrichWithProductDetailsStep = (0, workflows_sdk_1.createStep)("enrich-with-product-details", async (input, { container }) => {
|
|
31
33
|
if (!input.includeDetails || input.wishlist.length === 0) {
|
|
32
|
-
// Return as-is if no details needed or empty
|
|
33
34
|
return new workflows_sdk_1.StepResponse({ wishlist: input.wishlist });
|
|
34
35
|
}
|
|
35
|
-
//
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"thumbnail",
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
36
|
+
// Validate and extract product IDs
|
|
37
|
+
const productIds = input.wishlist
|
|
38
|
+
.map(item => item.product_id)
|
|
39
|
+
.filter((id) => typeof id === "string" && id.length > 0);
|
|
40
|
+
if (productIds.length === 0) {
|
|
41
|
+
// No valid product IDs, return wishlist as-is
|
|
42
|
+
return new workflows_sdk_1.StepResponse({ wishlist: input.wishlist });
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const remoteQuery = container.resolve(utils_1.ContainerRegistrationKeys.REMOTE_QUERY);
|
|
46
|
+
const queryObject = (0, utils_1.remoteQueryObjectFromString)({
|
|
47
|
+
entryPoint: "product",
|
|
48
|
+
fields: ["id", "title", "handle", "description", "thumbnail", "status", "created_at", "updated_at"],
|
|
49
|
+
filters: { id: productIds },
|
|
50
|
+
});
|
|
51
|
+
const products = await remoteQuery(queryObject);
|
|
52
|
+
// Type-safe product mapping
|
|
53
|
+
const productMap = new Map();
|
|
54
|
+
if (Array.isArray(products)) {
|
|
55
|
+
for (const product of products) {
|
|
56
|
+
if (product && typeof product === "object" && "id" in product && typeof product.id === "string") {
|
|
57
|
+
productMap.set(product.id, product);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const enrichedWishlist = input.wishlist.map(item => ({
|
|
62
|
+
...item,
|
|
63
|
+
product: item.product_id ? (productMap.get(item.product_id) || null) : null
|
|
64
|
+
}));
|
|
65
|
+
return new workflows_sdk_1.StepResponse({ wishlist: enrichedWishlist });
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// If product query fails, return wishlist without product details
|
|
69
|
+
// Log error but don't fail the workflow
|
|
70
|
+
console.warn("[getWishlistWorkflow] Failed to fetch product details:", error instanceof Error ? error.message : String(error));
|
|
71
|
+
return new workflows_sdk_1.StepResponse({ wishlist: input.wishlist });
|
|
72
|
+
}
|
|
69
73
|
});
|
|
70
74
|
exports.getWishlistWorkflow = (0, workflows_sdk_1.createWorkflow)("get-wishlist", (input) => {
|
|
71
75
|
const wishlistData = fetchWishlistItemsStep(input);
|
|
72
76
|
const enrichedWishlist = enrichWithProductDetailsStep(wishlistData);
|
|
73
|
-
return new workflows_sdk_1.WorkflowResponse({
|
|
74
|
-
wishlist: enrichedWishlist.wishlist,
|
|
75
|
-
});
|
|
77
|
+
return new workflows_sdk_1.WorkflowResponse({ wishlist: enrichedWishlist.wishlist });
|
|
76
78
|
});
|
|
77
79
|
exports.default = exports.getWishlistWorkflow;
|
|
78
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXdpc2hsaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9nZXQtd2lzaGxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBSzBDO0FBQzFDLHFEQUdrQztBQUVsQyxrREFBcUQ7QUFPckQsTUFBTSxzQkFBc0IsR0FBRyxJQUFBLDBCQUFVLEVBQ3ZDLHNCQUFzQixFQUN0QixLQUFLLEVBQUUsS0FBdUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDL0MsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBd0IsMEJBQWUsQ0FBQyxDQUFBO0lBQ2pGLE1BQU0sUUFBUSxHQUFHLE1BQU0sZUFBZSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUNwRixNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsT0FBTyxFQUFFLGNBQWMsSUFBSSxLQUFLLENBQUE7SUFFN0QsSUFBSSxpQkFBaUIsR0FBbUIsRUFBRSxDQUFBO0lBRTFDLElBQUksY0FBYyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUM5Qyw2RkFBNkY7UUFDN0YsTUFBTSxhQUFhLEdBQUcsUUFBaUMsQ0FBQTtRQUN2RCxpQkFBaUIsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQy9DLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtZQUNYLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtZQUMzQixVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7U0FDNUIsQ0FBQyxDQUFDLENBQUE7SUFDTCxDQUFDO1NBQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDbkMsK0VBQStFO1FBQy9FLE1BQU0sVUFBVSxHQUFHLFFB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
|
|
@@ -9,10 +9,7 @@ const validateWishlistItemExistsStep = (0, workflows_sdk_1.createStep)("validate
|
|
|
9
9
|
if (!exists) {
|
|
10
10
|
throw new Error(`Wishlist item not found for customer ${input.customer_id} and product ${input.product_id}`);
|
|
11
11
|
}
|
|
12
|
-
return new workflows_sdk_1.StepResponse(
|
|
13
|
-
customer_id: input.customer_id,
|
|
14
|
-
product_id: input.product_id,
|
|
15
|
-
});
|
|
12
|
+
return new workflows_sdk_1.StepResponse(input);
|
|
16
13
|
});
|
|
17
14
|
const removeFromWishlistStep = (0, workflows_sdk_1.createStep)("remove-from-wishlist", async (input, { container }) => {
|
|
18
15
|
const wishlistService = container.resolve(wishlist_1.WISHLIST_MODULE);
|
|
@@ -22,9 +19,7 @@ const removeFromWishlistStep = (0, workflows_sdk_1.createStep)("remove-from-wish
|
|
|
22
19
|
exports.removeFromWishlistWorkflow = (0, workflows_sdk_1.createWorkflow)("remove-from-wishlist", (input) => {
|
|
23
20
|
const validated = validateWishlistItemExistsStep(input);
|
|
24
21
|
const result = removeFromWishlistStep(validated);
|
|
25
|
-
return new workflows_sdk_1.WorkflowResponse({
|
|
26
|
-
success: result.success,
|
|
27
|
-
});
|
|
22
|
+
return new workflows_sdk_1.WorkflowResponse({ success: result.success });
|
|
28
23
|
});
|
|
29
24
|
exports.default = exports.removeFromWishlistWorkflow;
|
|
30
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3ZlLWZyb20td2lzaGxpc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3JlbW92ZS1mcm9tLXdpc2hsaXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUswQztBQUMxQyxrREFBcUQ7QUFNckQsTUFBTSw4QkFBOEIsR0FBRyxJQUFBLDBCQUFVLEVBQy9DLCtCQUErQixFQUMvQixLQUFLLEVBQUUsS0FBOEIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDdEQsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBd0IsMEJBQWUsQ0FBQyxDQUFBO0lBQ2pGLE1BQU0sTUFBTSxHQUFHLE1BQU0sZUFBZSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUV0RixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixNQUFNLElBQUksS0FBSyxDQUFDLHdDQUF3QyxLQUFLLENBQUMsV0FBVyxnQkFBZ0IsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUE7SUFDOUcsQ0FBQztJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQ2hDLENBQUMsQ0FDRixDQUFBO0FBRUQsTUFBTSxzQkFBc0IsR0FBRyxJQUFBLDBCQUFVLEVBQ3ZDLHNCQUFzQixFQUN0QixLQUFLLEVBQUUsS0FBOEIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDdEQsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBd0IsMEJBQWUsQ0FBQyxDQUFBO0lBQ2pGLE1BQU0sZUFBZSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0lBRTdFLE9BQU8sSUFBSSw0QkFBWSxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7QUFDNUMsQ0FBQyxDQUNGLENBQUE7QUFFWSxRQUFBLDBCQUEwQixHQUFHLElBQUEsOEJBQWMsRUFDdEQsc0JBQXNCLEVBQ3RCLENBQUMsS0FBOEIsRUFBOEMsRUFBRTtJQUM3RSxNQUFNLFNBQVMsR0FBRyw4QkFBOEIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUN2RCxNQUFNLE1BQU0sR0FBRyxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUVoRCxPQUFPLElBQUksZ0NBQWdCLENBQUMsRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7QUFDMUQsQ0FBQyxDQUNGLENBQUE7QUFFRCxrQkFBZSxrQ0FBMEIsQ0FBQSJ9
|
package/README.md
CHANGED
|
@@ -147,6 +147,17 @@ const plugins = [
|
|
|
147
147
|
// Require products to have at least one review
|
|
148
148
|
require_reviews: false,
|
|
149
149
|
},
|
|
150
|
+
// Custom filter providers (optional)
|
|
151
|
+
filterProviders: [
|
|
152
|
+
// File path (relative to project root)
|
|
153
|
+
"./src/providers/margin-provider.ts",
|
|
154
|
+
// Or module reference
|
|
155
|
+
"@my-org/custom-filters/brand-provider",
|
|
156
|
+
],
|
|
157
|
+
// Disable specific built-in providers (optional)
|
|
158
|
+
disableBuiltInProviders: [
|
|
159
|
+
// "rating", // Uncomment to disable rating filter provider
|
|
160
|
+
],
|
|
150
161
|
},
|
|
151
162
|
},
|
|
152
163
|
]
|
|
@@ -230,6 +241,84 @@ Configure rating-based filtering:
|
|
|
230
241
|
- `max`: Maximum rating (0-5)
|
|
231
242
|
- `require_reviews`: Require at least one review
|
|
232
243
|
|
|
244
|
+
#### Filter Providers
|
|
245
|
+
|
|
246
|
+
Configure custom filter providers:
|
|
247
|
+
- `filterProviders`: Array of file paths or module references to custom filter providers
|
|
248
|
+
- `disableBuiltInProviders`: Array of provider identifiers to disable (e.g., `["rating"]`)
|
|
249
|
+
|
|
250
|
+
See the [Provider Development Guide](./PROVIDER_DEVELOPMENT_GUIDE.md) for details on creating custom filter providers.
|
|
251
|
+
|
|
252
|
+
## Dynamic Filter Provider System
|
|
253
|
+
|
|
254
|
+
The plugin includes a provider-based dynamic filter system that allows you to extend product filtering capabilities without modifying the plugin code. All built-in filters (category, collection, metadata, price range, etc.) are implemented as filter providers, and you can add your own custom providers.
|
|
255
|
+
|
|
256
|
+
### Built-in Filter Providers
|
|
257
|
+
|
|
258
|
+
The plugin includes the following built-in filter providers:
|
|
259
|
+
|
|
260
|
+
- **Category Filter** (`category_id`): Filter products by category IDs
|
|
261
|
+
- **Collection Filter** (`collection_id`): Filter products by collection IDs
|
|
262
|
+
- **Metadata Filter** (`metadata`): Filter products by metadata with allowlist validation
|
|
263
|
+
- **Price Range Filter** (`price_range`): Filter products by price range (min/max)
|
|
264
|
+
- **Promotion Window Filter** (`promotion_window`): Filter products by promotion date windows
|
|
265
|
+
- **Availability Filter** (`availability`): Filter products by availability status
|
|
266
|
+
- **Rating Filter** (`rating`): Filter products by rating (min/max)
|
|
267
|
+
- **Base Product Filters** (`base_product`): Filter by ID, handle, tags, sales channel
|
|
268
|
+
|
|
269
|
+
### Using Filters
|
|
270
|
+
|
|
271
|
+
All filters are available through the `/store/product-helper/products` endpoint:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# Filter by category
|
|
275
|
+
GET /store/product-helper/products?category_id=cat_123,cat_456
|
|
276
|
+
|
|
277
|
+
# Filter by price range
|
|
278
|
+
GET /store/product-helper/products?price_min=10&price_max=100
|
|
279
|
+
|
|
280
|
+
# Filter by metadata (if filterable)
|
|
281
|
+
GET /store/product-helper/products?metadata[brand]=nike&metadata[color]=red
|
|
282
|
+
|
|
283
|
+
# Multiple filters
|
|
284
|
+
GET /store/product-helper/products?category_id=cat_123&price_min=10&rating_min=4
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Custom Filter Providers
|
|
288
|
+
|
|
289
|
+
You can create custom filter providers to add new filtering capabilities. See the [Provider Development Guide](./PROVIDER_DEVELOPMENT_GUIDE.md) for complete documentation.
|
|
290
|
+
|
|
291
|
+
**Quick Example:**
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
// src/providers/margin-provider.ts
|
|
295
|
+
import { BaseFilterProvider } from "medusa-product-helper/providers/filter-providers"
|
|
296
|
+
|
|
297
|
+
export class MarginFilterProvider extends BaseFilterProvider {
|
|
298
|
+
static readonly identifier = "margin"
|
|
299
|
+
static readonly displayName = "Margin Filter"
|
|
300
|
+
|
|
301
|
+
apply(filters: Record<string, unknown>, value: unknown): Record<string, unknown> {
|
|
302
|
+
if (!value || typeof value !== "object") return filters
|
|
303
|
+
|
|
304
|
+
const { min, max } = value as { min?: number; max?: number }
|
|
305
|
+
// Apply margin filter logic...
|
|
306
|
+
return filters
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Then register it in `medusa-config.ts`:
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
{
|
|
315
|
+
resolve: "medusa-product-helper",
|
|
316
|
+
options: {
|
|
317
|
+
filterProviders: ["./src/providers/margin-provider.ts"],
|
|
318
|
+
},
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
233
322
|
## Wishlist Feature
|
|
234
323
|
|
|
235
324
|
The plugin includes a comprehensive wishlist feature that allows customers to save products they're interested in and admins to view wishlist statistics.
|