@reactionary/medusa 0.10.48 → 0.10.50
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 +1 -1
- package/capabilities/checkout.capability.js +25 -11
- package/capabilities/order.capability.js +8 -1
- package/core/client.js +1 -1
- package/factories/cart/cart.factory.js +34 -5
- package/factories/checkout/checkout.factory.js +4 -4
- package/package.json +2 -2
- package/src/factories/cart/cart.factory.d.ts +10 -4
- package/src/utils/medusa-helpers.d.ts +6 -0
- package/utils/medusa-helpers.js +5 -0
|
@@ -50,7 +50,7 @@ class MedusaCartCapability extends CartCapability {
|
|
|
50
50
|
*
|
|
51
51
|
* example: this.includedFields = [includedFields, '+discounts.*'].join(',');
|
|
52
52
|
*/
|
|
53
|
-
includedFields = ["+items.*"].join(",");
|
|
53
|
+
includedFields = ["+items.*", "+items.adjustments.*", "+shipping_methods.adjustments.*"].join(",");
|
|
54
54
|
async listCarts(payload) {
|
|
55
55
|
const client = await this.getClient();
|
|
56
56
|
const sessionData = this.medusaApi.getSessionData();
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
CheckoutSchema,
|
|
23
23
|
MonetaryAmountSchema,
|
|
24
24
|
PaymentMethodSchema,
|
|
25
|
+
error,
|
|
25
26
|
Reactionary,
|
|
26
27
|
ShippingMethodIdentifierSchema,
|
|
27
28
|
ShippingMethodSchema,
|
|
@@ -31,7 +32,7 @@ import createDebug from "debug";
|
|
|
31
32
|
import * as z from "zod";
|
|
32
33
|
import {
|
|
33
34
|
} from "../schema/medusa.schema.js";
|
|
34
|
-
import { handleProviderError } from "../utils/medusa-helpers.js";
|
|
35
|
+
import { handleProviderError, isNotFoundFetchError } from "../utils/medusa-helpers.js";
|
|
35
36
|
const debug = createDebug("reactionary:medusa:checkout");
|
|
36
37
|
class CheckoutNotReadyForFinalizationError extends Error {
|
|
37
38
|
constructor(checkoutIdentifier) {
|
|
@@ -88,10 +89,20 @@ class MedusaCheckoutCapability extends CheckoutCapability {
|
|
|
88
89
|
}
|
|
89
90
|
async getById(payload) {
|
|
90
91
|
const client = await this.medusaApi.getClient();
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
try {
|
|
93
|
+
const response = await client.store.cart.retrieve(payload.identifier.key, {
|
|
94
|
+
fields: this.includedFields
|
|
95
|
+
});
|
|
96
|
+
return success(this.factory.parseCheckout(this.context, response.cart));
|
|
97
|
+
} catch (err) {
|
|
98
|
+
if (isNotFoundFetchError(err)) {
|
|
99
|
+
return error({
|
|
100
|
+
type: "NotFound",
|
|
101
|
+
identifier: payload.identifier
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
handleProviderError("get checkout by id", err);
|
|
105
|
+
}
|
|
95
106
|
}
|
|
96
107
|
setShippingAddressPayload(payload) {
|
|
97
108
|
return {
|
|
@@ -240,10 +251,10 @@ class MedusaCheckoutCapability extends CheckoutCapability {
|
|
|
240
251
|
}
|
|
241
252
|
);
|
|
242
253
|
return success(this.factory.parseCheckout(this.context, updatedCartResponse.cart));
|
|
243
|
-
} catch (
|
|
244
|
-
debug("Failed to add payment instruction: {0}", [
|
|
254
|
+
} catch (error2) {
|
|
255
|
+
debug("Failed to add payment instruction: {0}", [error2]);
|
|
245
256
|
throw new Error(
|
|
246
|
-
`Failed to add payment instruction: ${
|
|
257
|
+
`Failed to add payment instruction: ${error2 instanceof Error ? error2.message : "Unknown error"}`
|
|
247
258
|
);
|
|
248
259
|
}
|
|
249
260
|
}
|
|
@@ -280,13 +291,16 @@ class MedusaCheckoutCapability extends CheckoutCapability {
|
|
|
280
291
|
return success(this.factory.parseCheckout(this.context, response.cart));
|
|
281
292
|
}
|
|
282
293
|
throw new Error("Failed to set shipping method");
|
|
283
|
-
} catch (
|
|
284
|
-
handleProviderError("set shipping method",
|
|
294
|
+
} catch (error2) {
|
|
295
|
+
handleProviderError("set shipping method", error2);
|
|
285
296
|
}
|
|
286
297
|
}
|
|
287
298
|
async finalizeCheckout(payload) {
|
|
288
299
|
let checkout = await this.getById({ identifier: payload.checkout });
|
|
289
|
-
if (!checkout.success
|
|
300
|
+
if (!checkout.success) {
|
|
301
|
+
return checkout;
|
|
302
|
+
}
|
|
303
|
+
if (!checkout.value.readyForFinalization) {
|
|
290
304
|
throw new CheckoutNotReadyForFinalizationError(payload.checkout);
|
|
291
305
|
}
|
|
292
306
|
if (!checkout.value.resultingOrder) {
|
|
@@ -9,6 +9,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
9
9
|
return result;
|
|
10
10
|
};
|
|
11
11
|
import {
|
|
12
|
+
error,
|
|
12
13
|
OrderCapability,
|
|
13
14
|
OrderQueryByIdSchema,
|
|
14
15
|
OrderSchema,
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
success
|
|
17
18
|
} from "@reactionary/core";
|
|
18
19
|
import createDebug from "debug";
|
|
19
|
-
import { handleProviderError } from "../utils/medusa-helpers.js";
|
|
20
|
+
import { handleProviderError, isNotFoundFetchError } from "../utils/medusa-helpers.js";
|
|
20
21
|
const debug = createDebug("reactionary:medusa:order");
|
|
21
22
|
class MedusaOrderCapability extends OrderCapability {
|
|
22
23
|
constructor(config, cache, context, medusaApi, factory) {
|
|
@@ -36,6 +37,12 @@ class MedusaOrderCapability extends OrderCapability {
|
|
|
36
37
|
const order = this.factory.parseOrder(this.context, response.order);
|
|
37
38
|
return success(order);
|
|
38
39
|
} catch (err) {
|
|
40
|
+
if (isNotFoundFetchError(err)) {
|
|
41
|
+
return error({
|
|
42
|
+
type: "NotFound",
|
|
43
|
+
identifier: payload.order
|
|
44
|
+
});
|
|
45
|
+
}
|
|
39
46
|
return handleProviderError("order", err);
|
|
40
47
|
}
|
|
41
48
|
}
|
package/core/client.js
CHANGED
|
@@ -36,7 +36,7 @@ class RequestContextTokenStore {
|
|
|
36
36
|
}
|
|
37
37
|
if (debug.enabled) {
|
|
38
38
|
debug(
|
|
39
|
-
`Setting token item for key: ${this.keyPrefix + "_" + key} - Value: ${value}
|
|
39
|
+
`Setting token item for key: ${this.keyPrefix + "_" + key} - Value: <redacted, ${value.length} chars>`
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
this.context.session[SESSION_KEY][this.keyPrefix + "_" + key] = value;
|
|
@@ -52,6 +52,7 @@ class MedusaCartFactory {
|
|
|
52
52
|
for (const remoteItem of allItems) {
|
|
53
53
|
items.push(this.parseCartItem(context, remoteItem, price.grandTotal.currency));
|
|
54
54
|
}
|
|
55
|
+
const adjustmentsByPromotionId = this.groupAdjustmentsByPromotionId(data);
|
|
55
56
|
const appliedPromotions = [];
|
|
56
57
|
if (data.promotions) {
|
|
57
58
|
for (const promo of data.promotions) {
|
|
@@ -63,11 +64,13 @@ class MedusaCartFactory {
|
|
|
63
64
|
if (promo.application_method?.type === "fixed") {
|
|
64
65
|
promoDescription = `-${promo.application_method.value} ${price.grandTotal.currency}`;
|
|
65
66
|
}
|
|
67
|
+
const discountedAmount = adjustmentsByPromotionId.get(promo.id);
|
|
66
68
|
appliedPromotions.push({
|
|
67
69
|
code: promo.code || "",
|
|
68
70
|
isCouponCode: promo.is_automatic ? false : true,
|
|
69
71
|
name: promotionName || promoDescription,
|
|
70
|
-
description: promoDescription
|
|
72
|
+
description: promoDescription,
|
|
73
|
+
...discountedAmount !== void 0 ? { amount: { value: Math.abs(discountedAmount), currency: price.grandTotal.currency } } : {}
|
|
71
74
|
});
|
|
72
75
|
}
|
|
73
76
|
}
|
|
@@ -92,11 +95,37 @@ class MedusaCartFactory {
|
|
|
92
95
|
return this.cartIdentifierSchema.parse(result);
|
|
93
96
|
}
|
|
94
97
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* @returns
|
|
98
|
+
* Sums each line item's and shipping method's adjustments by the promotion
|
|
99
|
+
* that caused them, so the resulting amount is the actual monetary total
|
|
100
|
+
* discounted by that promotion on this cart.
|
|
99
101
|
*/
|
|
102
|
+
groupAdjustmentsByPromotionId(data) {
|
|
103
|
+
const totals = /* @__PURE__ */ new Map();
|
|
104
|
+
const addAdjustments = (adjustments) => {
|
|
105
|
+
for (const adjustment of adjustments || []) {
|
|
106
|
+
if (!adjustment.promotion_id) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
totals.set(
|
|
110
|
+
adjustment.promotion_id,
|
|
111
|
+
(totals.get(adjustment.promotion_id) || 0) + adjustment.amount
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
for (const item of data.items || []) {
|
|
116
|
+
addAdjustments(item.adjustments);
|
|
117
|
+
}
|
|
118
|
+
for (const shippingMethod of data.shipping_methods || []) {
|
|
119
|
+
addAdjustments(shippingMethod.adjustments);
|
|
120
|
+
}
|
|
121
|
+
return totals;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Extension point to control the parsing of a single cart item price
|
|
125
|
+
* @param remoteItem
|
|
126
|
+
* @param currency
|
|
127
|
+
* @returns
|
|
128
|
+
*/
|
|
100
129
|
parseItemPrice(_context, remoteItem, currency) {
|
|
101
130
|
return parseMedusaItemPrice(remoteItem, currency);
|
|
102
131
|
}
|
|
@@ -103,16 +103,16 @@ class MedusaCheckoutFactory {
|
|
|
103
103
|
const billingAddress = data.billing_address ? this.parseAddress(context, data.billing_address) : void 0;
|
|
104
104
|
const shippingAddress = data.shipping_address ? this.parseAddress(context, data.shipping_address) : void 0;
|
|
105
105
|
const backupUnattendedDelivery = data.metadata?.["consent_for_unattended_delivery"] !== void 0 ? data.metadata?.["consent_for_unattended_delivery"] === "true" : void 0;
|
|
106
|
-
const backupInstructions = data.metadata?.["instructions"]
|
|
107
|
-
const backupPickupPoint = data.metadata?.["pickup_point"]
|
|
106
|
+
const backupInstructions = data.metadata?.["instructions"] != null ? String(data.metadata["instructions"]) : void 0;
|
|
107
|
+
const backupPickupPoint = data.metadata?.["pickup_point"] != null ? String(data.metadata["pickup_point"]) : void 0;
|
|
108
108
|
let shippingInstruction;
|
|
109
109
|
data.shipping_methods?.forEach((sm) => {
|
|
110
110
|
let pickupPoint = "";
|
|
111
111
|
let instructions = "";
|
|
112
112
|
let consentForUnattendedDelivery = false;
|
|
113
113
|
if (sm.data) {
|
|
114
|
-
pickupPoint = sm.data["pickup_point"]
|
|
115
|
-
instructions = sm.data["instructions"]
|
|
114
|
+
pickupPoint = sm.data["pickup_point"] != null ? String(sm.data["pickup_point"]) : "";
|
|
115
|
+
instructions = sm.data["instructions"] != null ? String(sm.data["instructions"]) : "";
|
|
116
116
|
consentForUnattendedDelivery = sm.data["consent_for_unattended_delivery"] === "true";
|
|
117
117
|
}
|
|
118
118
|
if (!pickupPoint) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/medusa",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.50",
|
|
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.50",
|
|
14
14
|
"debug": "^4.4.3",
|
|
15
15
|
"@medusajs/types": "^2.13.3",
|
|
16
16
|
"zod": "4.1.9"
|
|
@@ -15,11 +15,17 @@ export declare class MedusaCartFactory<TCartSchema extends AnyCartSchema = typeo
|
|
|
15
15
|
parseCart(context: RequestContext, data: StoreCart): z.output<TCartSchema>;
|
|
16
16
|
parseCartIdentifier(_context: RequestContext, data: StoreCart): z.output<TCartIdentifierSchema>;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @returns
|
|
18
|
+
* Sums each line item's and shipping method's adjustments by the promotion
|
|
19
|
+
* that caused them, so the resulting amount is the actual monetary total
|
|
20
|
+
* discounted by that promotion on this cart.
|
|
22
21
|
*/
|
|
22
|
+
protected groupAdjustmentsByPromotionId(data: StoreCart): Map<string, number>;
|
|
23
|
+
/**
|
|
24
|
+
* Extension point to control the parsing of a single cart item price
|
|
25
|
+
* @param remoteItem
|
|
26
|
+
* @param currency
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
23
29
|
protected parseItemPrice(_context: RequestContext, remoteItem: StoreCartLineItem, currency: Currency): ItemCostBreakdown;
|
|
24
30
|
/**
|
|
25
31
|
* Extension point to control the parsing of the cost breakdown of a cart
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { StoreCart } from '@medusajs/types';
|
|
2
2
|
import type { CostBreakDown, Currency } from '@reactionary/core';
|
|
3
|
+
/**
|
|
4
|
+
* The Medusa SDK throws a FetchError for every non-2xx response. Returns true
|
|
5
|
+
* when the error is the SDK's way of saying the resource does not exist, so
|
|
6
|
+
* capabilities can answer with a typed NotFound result instead of throwing.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isNotFoundFetchError(error: unknown): boolean;
|
|
3
9
|
/**
|
|
4
10
|
* The subset of StoreCart/StoreOrder fields parseMedusaCostBreakdown reads.
|
|
5
11
|
* Narrowed (rather than StoreCart | StoreOrder) so tests can build a minimal,
|
package/utils/medusa-helpers.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { FetchError } from "@medusajs/js-sdk";
|
|
1
2
|
import createDebug from "debug";
|
|
2
3
|
const debug = createDebug("reactionary:medusa:helpers");
|
|
4
|
+
function isNotFoundFetchError(error) {
|
|
5
|
+
return error instanceof FetchError && error.status === 404;
|
|
6
|
+
}
|
|
3
7
|
function parseMedusaCostBreakdown(remote) {
|
|
4
8
|
const grandTotal = remote.total || 0;
|
|
5
9
|
const shippingTotal = remote.shipping_total || 0;
|
|
@@ -79,6 +83,7 @@ function safeStringConvert(val, defaultValue) {
|
|
|
79
83
|
}
|
|
80
84
|
export {
|
|
81
85
|
handleProviderError,
|
|
86
|
+
isNotFoundFetchError,
|
|
82
87
|
parseMedusaCostBreakdown,
|
|
83
88
|
parseMedusaItemPrice,
|
|
84
89
|
safeBoolConvert,
|