@reactionary/medusa 0.6.4 → 0.6.6
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/cart.capability.js +7 -99
- package/capabilities/category.capability.js +29 -47
- package/capabilities/checkout.capability.js +19 -209
- package/capabilities/inventory.capability.js +10 -54
- package/capabilities/order-search.capability.js +2 -76
- package/capabilities/order.capability.js +2 -130
- package/capabilities/price.capability.js +3 -38
- package/capabilities/product-associations.capability.js +19 -54
- package/capabilities/product-search.capability.js +15 -67
- package/capabilities/product.capability.js +18 -131
- package/capabilities/profile.capability.js +14 -63
- package/factories/cart/cart.factory.js +91 -2
- package/factories/category/category.factory.js +33 -3
- package/factories/checkout/checkout.factory.js +187 -4
- package/factories/inventory/inventory.factory.js +19 -1
- package/factories/order/order.factory.js +128 -2
- package/factories/order-search/order-search.factory.js +75 -2
- package/factories/price/price.factory.js +31 -2
- package/factories/product/product.factory.js +155 -2
- package/factories/product-associations/product-associations.factory.js +38 -2
- package/factories/product-search/product-search.factory.js +51 -2
- package/factories/profile/profile.factory.js +54 -2
- package/package.json +2 -2
- package/src/capabilities/cart.capability.d.ts +2 -28
- package/src/capabilities/category.capability.d.ts +5 -7
- package/src/capabilities/checkout.capability.d.ts +3 -35
- package/src/capabilities/inventory.capability.d.ts +2 -12
- package/src/capabilities/order-search.capability.d.ts +2 -42
- package/src/capabilities/order.capability.d.ts +2 -39
- package/src/capabilities/price.capability.d.ts +1 -4
- package/src/capabilities/product-associations.capability.d.ts +3 -7
- package/src/capabilities/product-search.capability.d.ts +4 -34
- package/src/capabilities/product.capability.d.ts +1 -6
- package/src/capabilities/profile.capability.d.ts +3 -5
- package/src/factories/cart/cart.factory.d.ts +23 -2
- package/src/factories/category/category.factory.d.ts +4 -3
- package/src/factories/checkout/checkout.factory.d.ts +31 -4
- package/src/factories/inventory/inventory.factory.d.ts +7 -1
- package/src/factories/order/order.factory.d.ts +38 -2
- package/src/factories/order-search/order-search.factory.d.ts +20 -2
- package/src/factories/price/price.factory.d.ts +6 -1
- package/src/factories/product/product.factory.d.ts +6 -2
- package/src/factories/product-associations/product-associations.factory.d.ts +8 -2
- package/src/factories/product-search/product-search.factory.d.ts +5 -2
- package/src/factories/profile/profile.factory.d.ts +4 -2
|
@@ -10,16 +10,14 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
10
10
|
return result;
|
|
11
11
|
};
|
|
12
12
|
import {
|
|
13
|
-
|
|
14
|
-
ProductIdentifierSchema,
|
|
13
|
+
error,
|
|
15
14
|
ProductCapability,
|
|
16
15
|
ProductQueryByIdSchema,
|
|
17
16
|
ProductQueryBySKUSchema,
|
|
18
17
|
ProductQueryBySlugSchema,
|
|
19
18
|
ProductSchema,
|
|
20
19
|
Reactionary,
|
|
21
|
-
success
|
|
22
|
-
error
|
|
20
|
+
success
|
|
23
21
|
} from "@reactionary/core";
|
|
24
22
|
import createDebug from "debug";
|
|
25
23
|
const debug = createDebug("reactionary:medusa:product");
|
|
@@ -31,7 +29,11 @@ class MedusaProductCapability extends ProductCapability {
|
|
|
31
29
|
this.factory = factory;
|
|
32
30
|
}
|
|
33
31
|
config;
|
|
34
|
-
alwaysIncludedFields = [
|
|
32
|
+
alwaysIncludedFields = [
|
|
33
|
+
"+metadata.*",
|
|
34
|
+
"+categories.metadata.*",
|
|
35
|
+
"+external_id"
|
|
36
|
+
];
|
|
35
37
|
factory;
|
|
36
38
|
getByIdPayload(payload) {
|
|
37
39
|
return {
|
|
@@ -55,7 +57,7 @@ class MedusaProductCapability extends ProductCapability {
|
|
|
55
57
|
identifier: payload
|
|
56
58
|
});
|
|
57
59
|
}
|
|
58
|
-
return success(this.
|
|
60
|
+
return success(this.factory.parseProduct(this.context, response.products[0]));
|
|
59
61
|
}
|
|
60
62
|
getBySlugPayload(payload) {
|
|
61
63
|
return {
|
|
@@ -70,7 +72,9 @@ class MedusaProductCapability extends ProductCapability {
|
|
|
70
72
|
if (debug.enabled) {
|
|
71
73
|
debug(`Fetching product by slug: ${payload.slug}`);
|
|
72
74
|
}
|
|
73
|
-
const response = await client.store.product.list(
|
|
75
|
+
const response = await client.store.product.list(
|
|
76
|
+
this.getBySlugPayload(payload)
|
|
77
|
+
);
|
|
74
78
|
if (debug.enabled) {
|
|
75
79
|
debug(`Found ${response.count} products for slug: ${payload.slug}`);
|
|
76
80
|
}
|
|
@@ -80,11 +84,15 @@ class MedusaProductCapability extends ProductCapability {
|
|
|
80
84
|
identifier: payload
|
|
81
85
|
});
|
|
82
86
|
}
|
|
83
|
-
return success(
|
|
87
|
+
return success(
|
|
88
|
+
this.factory.parseProduct(this.context, response.products[0])
|
|
89
|
+
);
|
|
84
90
|
}
|
|
85
91
|
async getBySKU(payload) {
|
|
86
92
|
if (debug.enabled) {
|
|
87
|
-
debug(
|
|
93
|
+
debug(
|
|
94
|
+
`Fetching product by SKU: ${Array.isArray(payload) ? payload.join(", ") : payload}`
|
|
95
|
+
);
|
|
88
96
|
}
|
|
89
97
|
const sku = payload.variant.sku;
|
|
90
98
|
const product = await this.medusaApi.resolveProductForSKU(sku);
|
|
@@ -93,128 +101,7 @@ class MedusaProductCapability extends ProductCapability {
|
|
|
93
101
|
throw new Error(`Variant with SKU ${sku} not found`);
|
|
94
102
|
}
|
|
95
103
|
product.variants = product.variants?.filter((v) => v.sku === sku).concat(product.variants?.filter((v) => v.sku !== sku)) || [];
|
|
96
|
-
return success(this.
|
|
97
|
-
}
|
|
98
|
-
parseSingle(_body) {
|
|
99
|
-
const identifier = ProductIdentifierSchema.parse({ key: _body.external_id || _body.id });
|
|
100
|
-
const name = _body.title;
|
|
101
|
-
const slug = _body.handle;
|
|
102
|
-
const description = _body.description || "" || _body.subtitle || "";
|
|
103
|
-
const parentCategories = [];
|
|
104
|
-
parentCategories.push(
|
|
105
|
-
..._body.categories?.map((cat) => cat.metadata?.["external_id"]).map((id) => CategoryIdentifierSchema.parse({ key: id || "" })) || []
|
|
106
|
-
);
|
|
107
|
-
const sharedAttributes = this.parseAttributes(_body);
|
|
108
|
-
if (!_body.variants) {
|
|
109
|
-
debug("Product has no variants", _body);
|
|
110
|
-
throw new Error("Product has no variants " + _body.external_id);
|
|
111
|
-
}
|
|
112
|
-
const mainVariant = this.parseVariant(_body.variants[0], _body);
|
|
113
|
-
const otherVariants = [];
|
|
114
|
-
if (_body.variants.length > 1) {
|
|
115
|
-
otherVariants.push(
|
|
116
|
-
..._body.variants.slice(1).map((variant) => this.parseVariant(variant, _body))
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
const result = {
|
|
120
|
-
brand: "",
|
|
121
|
-
description,
|
|
122
|
-
identifier,
|
|
123
|
-
longDescription: "",
|
|
124
|
-
mainVariant,
|
|
125
|
-
manufacturer: "",
|
|
126
|
-
name,
|
|
127
|
-
options: [],
|
|
128
|
-
parentCategories,
|
|
129
|
-
published: true,
|
|
130
|
-
sharedAttributes,
|
|
131
|
-
slug,
|
|
132
|
-
variants: otherVariants
|
|
133
|
-
};
|
|
134
|
-
return this.factory.parseProduct(this.context, result);
|
|
135
|
-
}
|
|
136
|
-
parseVariant(variant, product) {
|
|
137
|
-
const options = (variant.options ?? []).map((option) => {
|
|
138
|
-
const optionId = { key: option.option_id || "" };
|
|
139
|
-
const title = option.option?.title || "?";
|
|
140
|
-
const valueIdentifier = { key: option.option_id || "", option: optionId };
|
|
141
|
-
const value = option.value || "";
|
|
142
|
-
const result2 = {
|
|
143
|
-
identifier: optionId,
|
|
144
|
-
name: title,
|
|
145
|
-
value: {
|
|
146
|
-
identifier: valueIdentifier,
|
|
147
|
-
label: value
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
return result2;
|
|
151
|
-
});
|
|
152
|
-
const result = {
|
|
153
|
-
identifier: {
|
|
154
|
-
sku: variant.sku || ""
|
|
155
|
-
},
|
|
156
|
-
name: variant.title || product.title,
|
|
157
|
-
upc: variant.upc || "",
|
|
158
|
-
ean: variant.ean || "",
|
|
159
|
-
images: (product.images || []).map((img) => {
|
|
160
|
-
return {
|
|
161
|
-
sourceUrl: img.url,
|
|
162
|
-
altText: variant.title || product.title || ""
|
|
163
|
-
};
|
|
164
|
-
}),
|
|
165
|
-
options,
|
|
166
|
-
gtin: variant.ean || "",
|
|
167
|
-
barcode: variant.ean || ""
|
|
168
|
-
};
|
|
169
|
-
return result;
|
|
170
|
-
}
|
|
171
|
-
createSynthAttribute(key, name, value) {
|
|
172
|
-
const attributeIdentifier = { key };
|
|
173
|
-
const valueIdentifier = { key: `${key}-${value}` };
|
|
174
|
-
const attribute = {
|
|
175
|
-
identifier: { key },
|
|
176
|
-
name,
|
|
177
|
-
group: "",
|
|
178
|
-
values: [
|
|
179
|
-
{
|
|
180
|
-
identifier: valueIdentifier,
|
|
181
|
-
label: String(value),
|
|
182
|
-
value
|
|
183
|
-
}
|
|
184
|
-
]
|
|
185
|
-
};
|
|
186
|
-
return attribute;
|
|
187
|
-
}
|
|
188
|
-
parseAttributes(_body) {
|
|
189
|
-
const sharedAttributes = [];
|
|
190
|
-
if (_body.origin_country) {
|
|
191
|
-
sharedAttributes.push(this.createSynthAttribute("origin_country", "Origin Country", _body.origin_country));
|
|
192
|
-
}
|
|
193
|
-
if (_body.height) {
|
|
194
|
-
sharedAttributes.push(this.createSynthAttribute("height", "Height", String(_body.height)));
|
|
195
|
-
}
|
|
196
|
-
if (_body.weight) {
|
|
197
|
-
sharedAttributes.push(this.createSynthAttribute("weight", "Weight", String(_body.weight)));
|
|
198
|
-
}
|
|
199
|
-
if (_body.length) {
|
|
200
|
-
sharedAttributes.push(this.createSynthAttribute("length", "Length", String(_body.length)));
|
|
201
|
-
}
|
|
202
|
-
if (_body.width) {
|
|
203
|
-
sharedAttributes.push(this.createSynthAttribute("width", "Width", String(_body.width)));
|
|
204
|
-
}
|
|
205
|
-
if (_body.material) {
|
|
206
|
-
sharedAttributes.push(this.createSynthAttribute("material", "Material", _body.material));
|
|
207
|
-
}
|
|
208
|
-
if (_body.metadata) {
|
|
209
|
-
const keysToExclude = ["reactionaryaccessories", "reactionaryreplacements", "reactionaryspareparts"];
|
|
210
|
-
for (const [key, value] of Object.entries(_body.metadata)) {
|
|
211
|
-
if (keysToExclude.includes(key)) {
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
sharedAttributes.push(this.createSynthAttribute(key, key, String(value)));
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return sharedAttributes;
|
|
104
|
+
return success(this.factory.parseProduct(this.context, product));
|
|
218
105
|
}
|
|
219
106
|
}
|
|
220
107
|
__decorateClass([
|
|
@@ -11,17 +11,17 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
11
11
|
};
|
|
12
12
|
import {
|
|
13
13
|
ProfileCapability,
|
|
14
|
-
Reactionary,
|
|
15
|
-
ProfileSchema,
|
|
16
|
-
ProfileMutationUpdateSchema,
|
|
17
14
|
ProfileMutationAddShippingAddressSchema,
|
|
18
|
-
ProfileMutationUpdateShippingAddressSchema,
|
|
19
|
-
ProfileMutationRemoveShippingAddressSchema,
|
|
20
15
|
ProfileMutationMakeShippingAddressDefaultSchema,
|
|
16
|
+
ProfileMutationRemoveShippingAddressSchema,
|
|
21
17
|
ProfileMutationSetBillingAddressSchema,
|
|
22
|
-
|
|
18
|
+
ProfileMutationUpdateSchema,
|
|
19
|
+
ProfileMutationUpdateShippingAddressSchema,
|
|
23
20
|
ProfileQueryByIdSchema,
|
|
24
|
-
|
|
21
|
+
ProfileSchema,
|
|
22
|
+
Reactionary,
|
|
23
|
+
error,
|
|
24
|
+
success
|
|
25
25
|
} from "@reactionary/core";
|
|
26
26
|
import createDebug from "debug";
|
|
27
27
|
const debug = createDebug("reactionary:medusa:profile");
|
|
@@ -45,7 +45,7 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
45
45
|
type: "NotFound"
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
const model = this.
|
|
48
|
+
const model = this.factory.parseProfile(this.context, customerResponse.customer);
|
|
49
49
|
return success(model);
|
|
50
50
|
}
|
|
51
51
|
updatePayload(payload) {
|
|
@@ -67,7 +67,7 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
67
67
|
}
|
|
68
68
|
const customer = customerResponse.customer;
|
|
69
69
|
const updatedResponse = await client.store.customer.update(this.updatePayload(payload), { fields: this.includedFields.join(",") });
|
|
70
|
-
const model = this.
|
|
70
|
+
const model = this.factory.parseProfile(this.context, updatedResponse.customer);
|
|
71
71
|
return success(model);
|
|
72
72
|
}
|
|
73
73
|
addShippingAddressPayload(payload) {
|
|
@@ -97,7 +97,7 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
97
97
|
error: "Failed to add shipping address"
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
|
-
const model = this.
|
|
100
|
+
const model = this.factory.parseProfile(this.context, response.customer);
|
|
101
101
|
return success(model);
|
|
102
102
|
}
|
|
103
103
|
updateShippingAddressPayload(payload) {
|
|
@@ -127,7 +127,7 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
127
127
|
error: "Failed to add shipping address"
|
|
128
128
|
});
|
|
129
129
|
}
|
|
130
|
-
const model = this.
|
|
130
|
+
const model = this.factory.parseProfile(this.context, response.customer);
|
|
131
131
|
return success(model);
|
|
132
132
|
}
|
|
133
133
|
async removeShippingAddress(payload) {
|
|
@@ -155,7 +155,7 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
155
155
|
});
|
|
156
156
|
}
|
|
157
157
|
const customerAfterDelete = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
158
|
-
const model = this.
|
|
158
|
+
const model = this.factory.parseProfile(this.context, customerAfterDelete.customer);
|
|
159
159
|
return success(model);
|
|
160
160
|
}
|
|
161
161
|
makeShippingAddressDefaultPayload(payload) {
|
|
@@ -185,7 +185,7 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
185
185
|
this.makeShippingAddressDefaultPayload(payload),
|
|
186
186
|
{ fields: this.includedFields.join(",") }
|
|
187
187
|
);
|
|
188
|
-
const model = this.
|
|
188
|
+
const model = this.factory.parseProfile(this.context, response.customer);
|
|
189
189
|
return success(model);
|
|
190
190
|
}
|
|
191
191
|
setBillingAddressPayload(payload) {
|
|
@@ -220,7 +220,7 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
220
220
|
const createAddressResponse = await client.store.customer.createAddress(newAddr, { fields: this.includedFields.join(",") });
|
|
221
221
|
customer = createAddressResponse.customer;
|
|
222
222
|
}
|
|
223
|
-
const model = this.
|
|
223
|
+
const model = this.factory.parseProfile(this.context, customer);
|
|
224
224
|
return success(model);
|
|
225
225
|
}
|
|
226
226
|
createMedusaAddress(address) {
|
|
@@ -236,55 +236,6 @@ class MedusaProfileCapability extends ProfileCapability {
|
|
|
236
236
|
country_code: address.countryCode
|
|
237
237
|
};
|
|
238
238
|
}
|
|
239
|
-
parseAddress(address) {
|
|
240
|
-
return {
|
|
241
|
-
identifier: {
|
|
242
|
-
nickName: address.address_name || ""
|
|
243
|
-
},
|
|
244
|
-
firstName: address.first_name || "",
|
|
245
|
-
lastName: address.last_name || "",
|
|
246
|
-
streetAddress: address.address_1 || "",
|
|
247
|
-
streetNumber: address.address_2 || "",
|
|
248
|
-
city: address.city || "",
|
|
249
|
-
region: address.province || "",
|
|
250
|
-
postalCode: address.postal_code || "",
|
|
251
|
-
countryCode: address.country_code || ""
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
parseSingle(customer) {
|
|
255
|
-
const email = customer.email;
|
|
256
|
-
const emailVerified = customer.metadata?.["email_verified"] === "true";
|
|
257
|
-
const phone = customer.phone || "";
|
|
258
|
-
const phoneVerified = customer.metadata?.["phone_verified"] === "true";
|
|
259
|
-
const addresses = customer.addresses || [];
|
|
260
|
-
let billingAddress = void 0;
|
|
261
|
-
let shippingAddress = void 0;
|
|
262
|
-
const existingBillingAddress = customer.addresses.find((addr) => addr.is_default_billing);
|
|
263
|
-
if (existingBillingAddress) {
|
|
264
|
-
billingAddress = this.parseAddress(existingBillingAddress);
|
|
265
|
-
}
|
|
266
|
-
const existingShippingAddress = customer.addresses.find((addr) => addr.is_default_shipping);
|
|
267
|
-
if (existingShippingAddress) {
|
|
268
|
-
shippingAddress = this.parseAddress(existingShippingAddress);
|
|
269
|
-
}
|
|
270
|
-
const alternateShippingAddresses = [];
|
|
271
|
-
alternateShippingAddresses.push(...addresses.filter((x) => !(x.is_default_billing || x.is_default_shipping)).map((addr) => this.parseAddress(addr)));
|
|
272
|
-
const result = {
|
|
273
|
-
identifier: {
|
|
274
|
-
userId: customer.id
|
|
275
|
-
},
|
|
276
|
-
email,
|
|
277
|
-
emailVerified,
|
|
278
|
-
phone,
|
|
279
|
-
phoneVerified,
|
|
280
|
-
billingAddress,
|
|
281
|
-
shippingAddress,
|
|
282
|
-
alternateShippingAddresses,
|
|
283
|
-
createdAt: new Date(customer.created_at || "").toISOString(),
|
|
284
|
-
updatedAt: new Date(customer.updated_at || "").toISOString()
|
|
285
|
-
};
|
|
286
|
-
return this.factory.parseProfile(this.context, result);
|
|
287
|
-
}
|
|
288
239
|
}
|
|
289
240
|
__decorateClass([
|
|
290
241
|
Reactionary({
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProductVariantIdentifierSchema
|
|
3
|
+
} from "@reactionary/core";
|
|
4
|
+
import { MedusaCartIdentifierSchema } from "../../schema/medusa.schema.js";
|
|
5
|
+
import { parseMedusaCostBreakdown, parseMedusaItemPrice } from "../../utils/medusa-helpers.js";
|
|
1
6
|
class MedusaCartFactory {
|
|
2
7
|
cartSchema;
|
|
3
8
|
cartIdentifierSchema;
|
|
@@ -5,12 +10,96 @@ class MedusaCartFactory {
|
|
|
5
10
|
this.cartSchema = cartSchema;
|
|
6
11
|
this.cartIdentifierSchema = cartIdentifierSchema;
|
|
7
12
|
}
|
|
8
|
-
parseCart(
|
|
9
|
-
|
|
13
|
+
parseCart(context, data) {
|
|
14
|
+
const identifier = MedusaCartIdentifierSchema.parse({
|
|
15
|
+
key: data.id,
|
|
16
|
+
region_id: data.region_id
|
|
17
|
+
});
|
|
18
|
+
const name = "" + (data.metadata?.["name"] || "");
|
|
19
|
+
const description = "" + (data.metadata?.["description"] || "");
|
|
20
|
+
const price = this.parseCostBreakdown(context, data);
|
|
21
|
+
const items = new Array();
|
|
22
|
+
const allItems = data.items || [];
|
|
23
|
+
allItems.sort(
|
|
24
|
+
(a, b) => a.created_at && b.created_at ? new Date(a.created_at).getTime() - new Date(b.created_at).getTime() : 0
|
|
25
|
+
);
|
|
26
|
+
for (const remoteItem of allItems) {
|
|
27
|
+
items.push(this.parseCartItem(context, remoteItem, price.grandTotal.currency));
|
|
28
|
+
}
|
|
29
|
+
const appliedPromotions = [];
|
|
30
|
+
if (data.promotions) {
|
|
31
|
+
for (const promo of data.promotions) {
|
|
32
|
+
const promotionName = promo.code;
|
|
33
|
+
let promoDescription = "";
|
|
34
|
+
if (promo.application_method?.type === "percentage") {
|
|
35
|
+
promoDescription = `-${promo.application_method.value}%`;
|
|
36
|
+
}
|
|
37
|
+
if (promo.application_method?.type === "fixed") {
|
|
38
|
+
promoDescription = `-${promo.application_method.value} ${price.grandTotal.currency}`;
|
|
39
|
+
}
|
|
40
|
+
appliedPromotions.push({
|
|
41
|
+
code: promo.code || "",
|
|
42
|
+
isCouponCode: promo.is_automatic ? false : true,
|
|
43
|
+
name: promotionName || promoDescription,
|
|
44
|
+
description: promoDescription
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const result = {
|
|
49
|
+
identifier,
|
|
50
|
+
name,
|
|
51
|
+
description,
|
|
52
|
+
price,
|
|
53
|
+
items,
|
|
54
|
+
appliedPromotions,
|
|
55
|
+
userId: {
|
|
56
|
+
userId: "???"
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return this.cartSchema.parse(result);
|
|
10
60
|
}
|
|
11
61
|
parseCartIdentifier(_context, data) {
|
|
12
62
|
return this.cartIdentifierSchema.parse(data);
|
|
13
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Extension point to control the parsing of a single cart item price
|
|
66
|
+
* @param remoteItem
|
|
67
|
+
* @param currency
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
parseItemPrice(_context, remoteItem, currency) {
|
|
71
|
+
return parseMedusaItemPrice(remoteItem, currency);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Extension point to control the parsing of the cost breakdown of a cart
|
|
75
|
+
* @param remote
|
|
76
|
+
* @returns
|
|
77
|
+
*/
|
|
78
|
+
parseCostBreakdown(_context, remote) {
|
|
79
|
+
return parseMedusaCostBreakdown(remote);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Extension point to control the parsing of a single cart item
|
|
83
|
+
* @param remoteItem
|
|
84
|
+
* @param currency
|
|
85
|
+
* @returns
|
|
86
|
+
*/
|
|
87
|
+
parseCartItem(context, remoteItem, currency) {
|
|
88
|
+
const item = {
|
|
89
|
+
identifier: {
|
|
90
|
+
key: remoteItem.id
|
|
91
|
+
},
|
|
92
|
+
product: {
|
|
93
|
+
key: remoteItem.product_id || ""
|
|
94
|
+
},
|
|
95
|
+
variant: ProductVariantIdentifierSchema.parse({
|
|
96
|
+
sku: remoteItem.variant_sku || ""
|
|
97
|
+
}),
|
|
98
|
+
quantity: remoteItem.quantity || 1,
|
|
99
|
+
price: this.parseItemPrice(context, remoteItem, currency)
|
|
100
|
+
};
|
|
101
|
+
return item;
|
|
102
|
+
}
|
|
14
103
|
}
|
|
15
104
|
export {
|
|
16
105
|
MedusaCartFactory
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CategoryIdentifierSchema
|
|
3
|
+
} from "@reactionary/core";
|
|
1
4
|
class MedusaCategoryFactory {
|
|
2
5
|
categorySchema;
|
|
3
6
|
categoryPaginatedResultSchema;
|
|
@@ -6,10 +9,37 @@ class MedusaCategoryFactory {
|
|
|
6
9
|
this.categoryPaginatedResultSchema = categoryPaginatedResultSchema;
|
|
7
10
|
}
|
|
8
11
|
parseCategory(_context, data) {
|
|
9
|
-
|
|
12
|
+
const identifier = CategoryIdentifierSchema.parse({
|
|
13
|
+
key: data.metadata?.["external_id"] || ""
|
|
14
|
+
});
|
|
15
|
+
const name = data.name;
|
|
16
|
+
const slug = data.handle;
|
|
17
|
+
const text = data.description || data.name || "";
|
|
18
|
+
const parentCategory = data.parent_category_id ? { key: data.parent_category?.metadata?.["external_id"] + "" || "" } : void 0;
|
|
19
|
+
const result = {
|
|
20
|
+
identifier,
|
|
21
|
+
name,
|
|
22
|
+
slug,
|
|
23
|
+
text,
|
|
24
|
+
parentCategory,
|
|
25
|
+
images: []
|
|
26
|
+
};
|
|
27
|
+
return this.categorySchema.parse(result);
|
|
10
28
|
}
|
|
11
|
-
parseCategoryPaginatedResult(
|
|
12
|
-
|
|
29
|
+
parseCategoryPaginatedResult(context, data) {
|
|
30
|
+
const items = data.product_categories.map((x) => this.parseCategory(context, x));
|
|
31
|
+
const totalPages = Math.ceil(
|
|
32
|
+
(data.count ?? 0) / Math.max(data.product_categories.length, 1)
|
|
33
|
+
);
|
|
34
|
+
const pageNumber = data.count === 0 ? 1 : Math.floor(data.offset / data.product_categories.length) + 1;
|
|
35
|
+
const result = {
|
|
36
|
+
pageNumber,
|
|
37
|
+
pageSize: Math.max(data.product_categories.length, 1),
|
|
38
|
+
totalCount: data.count,
|
|
39
|
+
totalPages,
|
|
40
|
+
items
|
|
41
|
+
};
|
|
42
|
+
return this.categoryPaginatedResultSchema.parse(result);
|
|
13
43
|
}
|
|
14
44
|
}
|
|
15
45
|
export {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AddressIdentifierSchema,
|
|
3
|
+
MonetaryAmountSchema,
|
|
4
|
+
ShippingMethodIdentifierSchema
|
|
5
|
+
} from "@reactionary/core";
|
|
6
|
+
import {
|
|
7
|
+
parseMedusaCostBreakdown,
|
|
8
|
+
parseMedusaItemPrice
|
|
9
|
+
} from "../../utils/medusa-helpers.js";
|
|
1
10
|
class MedusaCheckoutFactory {
|
|
2
11
|
checkoutSchema;
|
|
3
12
|
shippingMethodSchema;
|
|
@@ -7,14 +16,188 @@ class MedusaCheckoutFactory {
|
|
|
7
16
|
this.shippingMethodSchema = shippingMethodSchema;
|
|
8
17
|
this.paymentMethodSchema = paymentMethodSchema;
|
|
9
18
|
}
|
|
10
|
-
|
|
11
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Extension point to control the parsing of a single cart item price
|
|
21
|
+
* @param remoteItem
|
|
22
|
+
* @param currency
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
parseItemPrice(_context, remoteItem, currency) {
|
|
26
|
+
return parseMedusaItemPrice(remoteItem, currency);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extension point to control the parsing of the cost breakdown of a cart
|
|
30
|
+
* @param remote
|
|
31
|
+
* @returns
|
|
32
|
+
*/
|
|
33
|
+
parseCostBreakdown(_context, remote) {
|
|
34
|
+
return parseMedusaCostBreakdown(remote);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extension point to control the parsing of a single checkout item
|
|
38
|
+
* @param remoteItem
|
|
39
|
+
* @param currency
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
parseCheckoutItem(context, remoteItem, currency) {
|
|
43
|
+
const item = {
|
|
44
|
+
identifier: {
|
|
45
|
+
key: remoteItem.id
|
|
46
|
+
},
|
|
47
|
+
variant: {
|
|
48
|
+
sku: remoteItem.variant_sku || ""
|
|
49
|
+
},
|
|
50
|
+
quantity: remoteItem.quantity || 1,
|
|
51
|
+
price: this.parseItemPrice(context, remoteItem, currency)
|
|
52
|
+
};
|
|
53
|
+
return item;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extension point to control the parsing of an address from a store cart address
|
|
57
|
+
* @param storeAddress
|
|
58
|
+
* @returns
|
|
59
|
+
*/
|
|
60
|
+
parseAddress(_context, storeAddress) {
|
|
61
|
+
return {
|
|
62
|
+
identifier: AddressIdentifierSchema.parse({
|
|
63
|
+
nickName: storeAddress.id
|
|
64
|
+
}),
|
|
65
|
+
firstName: storeAddress.first_name || "",
|
|
66
|
+
lastName: storeAddress.last_name || "",
|
|
67
|
+
streetAddress: storeAddress.address_1 || "",
|
|
68
|
+
streetNumber: storeAddress.address_2 || "",
|
|
69
|
+
city: storeAddress.city || "",
|
|
70
|
+
postalCode: storeAddress.postal_code || "",
|
|
71
|
+
countryCode: storeAddress.country_code || "",
|
|
72
|
+
region: ""
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
parseCheckout(context, data) {
|
|
76
|
+
const identifier = {
|
|
77
|
+
key: data.id
|
|
78
|
+
// region_id: remote.region_id,
|
|
79
|
+
};
|
|
80
|
+
const name = "" + (data.metadata?.["name"] || "");
|
|
81
|
+
const description = "" + (data.metadata?.["description"] || "");
|
|
82
|
+
const price = this.parseCostBreakdown(context, data);
|
|
83
|
+
const items = new Array();
|
|
84
|
+
for (const remoteItem of data.items || []) {
|
|
85
|
+
items.push(
|
|
86
|
+
this.parseCheckoutItem(context, remoteItem, price.grandTotal.currency)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
const billingAddress = data.billing_address ? this.parseAddress(context, data.billing_address) : void 0;
|
|
90
|
+
const shippingAddress = data.shipping_address ? this.parseAddress(context, data.shipping_address) : void 0;
|
|
91
|
+
const backupUnattendedDelivery = data.metadata?.["consent_for_unattended_delivery"] !== void 0 ? data.metadata?.["consent_for_unattended_delivery"] === "true" : void 0;
|
|
92
|
+
const backupInstructions = data.metadata?.["instructions"] !== void 0 ? data.metadata?.["instructions"] + "" : void 0;
|
|
93
|
+
const backupPickupPoint = data.metadata?.["pickup_point"] !== void 0 ? data.metadata?.["pickup_point"] + "" : void 0;
|
|
94
|
+
let shippingInstruction;
|
|
95
|
+
data.shipping_methods?.forEach((sm) => {
|
|
96
|
+
let pickupPoint = "";
|
|
97
|
+
let instructions = "";
|
|
98
|
+
let consentForUnattendedDelivery = false;
|
|
99
|
+
if (sm.data) {
|
|
100
|
+
pickupPoint = sm.data["pickup_point"] + "" || "";
|
|
101
|
+
instructions = sm.data["instructions"] + "" || "";
|
|
102
|
+
consentForUnattendedDelivery = sm.data["consent_for_unattended_delivery"] === "true";
|
|
103
|
+
}
|
|
104
|
+
if (!pickupPoint) {
|
|
105
|
+
pickupPoint = backupPickupPoint || "";
|
|
106
|
+
}
|
|
107
|
+
if (!instructions) {
|
|
108
|
+
instructions = backupInstructions || "";
|
|
109
|
+
}
|
|
110
|
+
if (!consentForUnattendedDelivery) {
|
|
111
|
+
consentForUnattendedDelivery = backupUnattendedDelivery || false;
|
|
112
|
+
}
|
|
113
|
+
shippingInstruction = {
|
|
114
|
+
shippingMethod: { key: sm.shipping_option_id },
|
|
115
|
+
consentForUnattendedDelivery,
|
|
116
|
+
instructions,
|
|
117
|
+
pickupPoint
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
const paymentInstructions = new Array();
|
|
121
|
+
for (const remotePayment of data.payment_collection?.payment_sessions || []) {
|
|
122
|
+
if (remotePayment.status === "canceled" || remotePayment.status === "error") {
|
|
123
|
+
console.warn(
|
|
124
|
+
`Skipping payment session ${remotePayment.id} with status ${remotePayment.status}`
|
|
125
|
+
);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const paymentMethodIdentifier = {
|
|
129
|
+
method: remotePayment.provider_id,
|
|
130
|
+
name: remotePayment.provider_id,
|
|
131
|
+
paymentProcessor: remotePayment.provider_id
|
|
132
|
+
};
|
|
133
|
+
paymentInstructions.push({
|
|
134
|
+
identifier: {
|
|
135
|
+
key: remotePayment.id
|
|
136
|
+
},
|
|
137
|
+
amount: {
|
|
138
|
+
value: remotePayment.amount,
|
|
139
|
+
currency: remotePayment.currency_code?.toUpperCase()
|
|
140
|
+
},
|
|
141
|
+
paymentMethod: paymentMethodIdentifier,
|
|
142
|
+
protocolData: remotePayment.data ? Object.entries(remotePayment.data).map(([key, value]) => ({
|
|
143
|
+
key,
|
|
144
|
+
value: String(value)
|
|
145
|
+
})) : [],
|
|
146
|
+
status: "pending"
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const originalCartReference = {
|
|
150
|
+
key: data.id,
|
|
151
|
+
region: data.region_id
|
|
152
|
+
};
|
|
153
|
+
let resultingOrder = void 0;
|
|
154
|
+
if (data.metadata?.["order_id"]) {
|
|
155
|
+
resultingOrder = {
|
|
156
|
+
key: data.metadata?.["order_id"] + "" || "",
|
|
157
|
+
display_id: Number(data.metadata?.["order_display_id"] + "" || "0")
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const result = {
|
|
161
|
+
identifier,
|
|
162
|
+
name,
|
|
163
|
+
description,
|
|
164
|
+
price,
|
|
165
|
+
items,
|
|
166
|
+
originalCartReference,
|
|
167
|
+
paymentInstructions,
|
|
168
|
+
readyForFinalization: false,
|
|
169
|
+
billingAddress,
|
|
170
|
+
resultingOrder,
|
|
171
|
+
shippingAddress,
|
|
172
|
+
shippingInstruction
|
|
173
|
+
};
|
|
174
|
+
return this.checkoutSchema.parse(result);
|
|
12
175
|
}
|
|
13
176
|
parseShippingMethod(_context, data) {
|
|
14
|
-
|
|
177
|
+
const sm = {
|
|
178
|
+
identifier: ShippingMethodIdentifierSchema.parse({ key: data.id }),
|
|
179
|
+
name: data.name,
|
|
180
|
+
description: data.type.description || "",
|
|
181
|
+
price: MonetaryAmountSchema.parse({
|
|
182
|
+
value: data.calculated_price.calculated_amount || 0,
|
|
183
|
+
currency: data.calculated_price.currency_code?.toUpperCase()
|
|
184
|
+
}),
|
|
185
|
+
deliveryTime: ""
|
|
186
|
+
};
|
|
187
|
+
return this.shippingMethodSchema.parse(sm);
|
|
15
188
|
}
|
|
16
189
|
parsePaymentMethod(_context, data) {
|
|
17
|
-
|
|
190
|
+
const pm = {
|
|
191
|
+
identifier: {
|
|
192
|
+
method: data.id,
|
|
193
|
+
name: data.id,
|
|
194
|
+
paymentProcessor: data.id
|
|
195
|
+
},
|
|
196
|
+
logo: void 0,
|
|
197
|
+
description: data.id,
|
|
198
|
+
isPunchOut: true
|
|
199
|
+
};
|
|
200
|
+
return this.paymentMethodSchema.parse(pm);
|
|
18
201
|
}
|
|
19
202
|
}
|
|
20
203
|
export {
|