@reactionary/medusa 0.10.49 → 0.10.51

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.
@@ -28,6 +28,7 @@ import {
28
28
  Reactionary,
29
29
  success
30
30
  } from "@reactionary/core";
31
+ import { FetchError } from "@medusajs/js-sdk";
31
32
  import {} from "@medusajs/types";
32
33
  import createDebug from "debug";
33
34
  import {
@@ -233,6 +234,30 @@ class MedusaCartCapability extends CartCapability {
233
234
  }
234
235
  this.medusaApi.setSessionData(sessionData);
235
236
  }
237
+ /**
238
+ * Removes every trace of a cart from the session: the active cart marker
239
+ * (when it points at this cart) and the entry in every owned-carts
240
+ * collection. Used when a cart turns out to be deleted or stale upstream.
241
+ */
242
+ pruneCartFromSession(cartKey) {
243
+ const sessionData = this.medusaApi.getSessionData();
244
+ if (sessionData.activeCartId?.key === cartKey) {
245
+ delete sessionData.activeCartId;
246
+ this.medusaApi.setSessionData({ activeCartId: void 0 });
247
+ }
248
+ if (sessionData.allOwnedCarts) {
249
+ const prunedCollections = Object.fromEntries(
250
+ Object.entries(sessionData.allOwnedCarts).map(([collection, carts]) => [
251
+ collection,
252
+ carts.filter((cart) => cart.key !== cartKey)
253
+ ])
254
+ );
255
+ this.medusaApi.setSessionData({ allOwnedCarts: prunedCollections });
256
+ }
257
+ }
258
+ isNotFoundError(err) {
259
+ return err instanceof FetchError && err.status === 404;
260
+ }
236
261
  removeCartFromOwnedList(cartIdentifier, company) {
237
262
  const sessionData = this.medusaApi.getSessionData();
238
263
  const companyIdToUse = company ? company.taxIdentifier : "_me";
@@ -329,18 +354,23 @@ class MedusaCartCapability extends CartCapability {
329
354
  }
330
355
  }
331
356
  if (activeCartId) {
332
- const response = await client.store.cart.retrieve(activeCartId.key, { fields: "id,region_id" });
333
- if (!response.cart) {
334
- delete sessionData.activeCartId;
335
- this.medusaApi.setSessionData({
336
- activeCartId: void 0
337
- });
357
+ let remoteCart;
358
+ try {
359
+ const response = await client.store.cart.retrieve(activeCartId.key, { fields: "id,region_id" });
360
+ remoteCart = response.cart;
361
+ } catch (retrieveError) {
362
+ if (!this.isNotFoundError(retrieveError)) {
363
+ throw retrieveError;
364
+ }
365
+ }
366
+ if (!remoteCart) {
367
+ this.pruneCartFromSession(activeCartId.key);
338
368
  return error({
339
369
  type: "NotFound",
340
370
  identifier: activeCartId
341
371
  });
342
372
  }
343
- return success(this.factory.parseCartIdentifier(this.context, response.cart));
373
+ return success(this.factory.parseCartIdentifier(this.context, remoteCart));
344
374
  }
345
375
  return error({
346
376
  type: "NotFound",
@@ -359,13 +389,7 @@ class MedusaCartCapability extends CartCapability {
359
389
  const client = await this.getClient();
360
390
  const medusaId = payload.cart;
361
391
  if (medusaId.key) {
362
- const sessionData = this.medusaApi.getSessionData();
363
- if (sessionData.activeCartId) {
364
- delete sessionData.activeCartId;
365
- this.medusaApi.setSessionData({
366
- activeCartId: void 0
367
- });
368
- }
392
+ this.pruneCartFromSession(medusaId.key);
369
393
  }
370
394
  const cartResponse = await client.store.cart.retrieve(medusaId.key);
371
395
  if (cartResponse.cart) {
@@ -374,9 +398,11 @@ class MedusaCartCapability extends CartCapability {
374
398
  }
375
399
  }
376
400
  return success(void 0);
377
- } catch (error2) {
378
- debug("Failed to delete cart:", error2);
379
- return success(void 0);
401
+ } catch (err) {
402
+ if (this.isNotFoundError(err)) {
403
+ return success(void 0);
404
+ }
405
+ handleProviderError("delete cart", err);
380
406
  }
381
407
  }
382
408
  /**
@@ -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
- const response = await client.store.cart.retrieve(payload.identifier.key, {
92
- fields: this.includedFields
93
- });
94
- return success(this.factory.parseCheckout(this.context, response.cart));
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 (error) {
244
- debug("Failed to add payment instruction: {0}", [error]);
254
+ } catch (error2) {
255
+ debug("Failed to add payment instruction: {0}", [error2]);
245
256
  throw new Error(
246
- `Failed to add payment instruction: ${error instanceof Error ? error.message : "Unknown error"}`
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 (error) {
284
- handleProviderError("set shipping method", error);
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 || !checkout.value.readyForFinalization) {
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;
@@ -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"] !== void 0 ? data.metadata?.["instructions"] + "" : void 0;
107
- const backupPickupPoint = data.metadata?.["pickup_point"] !== void 0 ? data.metadata?.["pickup_point"] + "" : void 0;
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.49",
3
+ "version": "0.10.51",
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.49",
13
+ "@reactionary/core": "0.10.51",
14
14
  "debug": "^4.4.3",
15
15
  "@medusajs/types": "^2.13.3",
16
16
  "zod": "4.1.9"
@@ -36,6 +36,13 @@ export declare class MedusaCartCapability<TFactory extends CartFactory = MedusaC
36
36
  */
37
37
  protected createCartPayload(payload: CartMutationCreateCart): Promise<StoreCreateCart>;
38
38
  protected addCartToOwnedList(cartIdentifier: MedusaCartIdentifier, companyId?: CompanyIdentifier): void;
39
+ /**
40
+ * Removes every trace of a cart from the session: the active cart marker
41
+ * (when it points at this cart) and the entry in every owned-carts
42
+ * collection. Used when a cart turns out to be deleted or stale upstream.
43
+ */
44
+ protected pruneCartFromSession(cartKey: string): void;
45
+ protected isNotFoundError(err: unknown): boolean;
39
46
  protected removeCartFromOwnedList(cartIdentifier: MedusaCartIdentifier, company?: CompanyIdentifier): void;
40
47
  createCart(payload: CartMutationCreateCart): Promise<Result<CartFactoryCartOutput<TFactory>>>;
41
48
  remove(payload: CartMutationItemRemove): Promise<Result<CartFactoryCartOutput<TFactory>>>;
@@ -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,
@@ -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,