@reactionary/medusa 0.6.3

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.
Files changed (72) hide show
  1. package/README.md +11 -0
  2. package/capabilities/cart.capability.js +517 -0
  3. package/capabilities/category.capability.js +216 -0
  4. package/capabilities/checkout.capability.js +533 -0
  5. package/capabilities/identity.capability.js +128 -0
  6. package/capabilities/inventory.capability.js +142 -0
  7. package/capabilities/order-search.capability.js +161 -0
  8. package/capabilities/order.capability.js +179 -0
  9. package/capabilities/price.capability.js +120 -0
  10. package/capabilities/product-associations.capability.js +148 -0
  11. package/capabilities/product-recommendations.capability.js +116 -0
  12. package/capabilities/product-search.capability.js +177 -0
  13. package/capabilities/product.capability.js +252 -0
  14. package/capabilities/profile.capability.js +333 -0
  15. package/core/client.js +269 -0
  16. package/core/initialize.js +290 -0
  17. package/core/initialize.types.js +13 -0
  18. package/factories/cart/cart.factory.js +17 -0
  19. package/factories/category/category.factory.js +17 -0
  20. package/factories/checkout/checkout.factory.js +22 -0
  21. package/factories/identity/identity.factory.js +12 -0
  22. package/factories/index.js +12 -0
  23. package/factories/inventory/inventory.factory.js +12 -0
  24. package/factories/order/order.factory.js +12 -0
  25. package/factories/order-search/order-search.factory.js +12 -0
  26. package/factories/price/price.factory.js +12 -0
  27. package/factories/product/product.factory.js +12 -0
  28. package/factories/product-associations/product-associations.factory.js +12 -0
  29. package/factories/product-search/product-search.factory.js +12 -0
  30. package/factories/profile/profile.factory.js +12 -0
  31. package/index.js +17 -0
  32. package/package.json +17 -0
  33. package/schema/capabilities.schema.js +43 -0
  34. package/schema/configuration.schema.js +11 -0
  35. package/schema/medusa.schema.js +26 -0
  36. package/src/capabilities/cart.capability.d.ts +100 -0
  37. package/src/capabilities/category.capability.d.ts +36 -0
  38. package/src/capabilities/checkout.capability.d.ts +88 -0
  39. package/src/capabilities/identity.capability.d.ts +13 -0
  40. package/src/capabilities/inventory.capability.d.ts +21 -0
  41. package/src/capabilities/order-search.capability.d.ts +53 -0
  42. package/src/capabilities/order.capability.d.ts +49 -0
  43. package/src/capabilities/price.capability.d.ts +16 -0
  44. package/src/capabilities/product-associations.capability.d.ts +19 -0
  45. package/src/capabilities/product-recommendations.capability.d.ts +41 -0
  46. package/src/capabilities/product-search.capability.d.ts +45 -0
  47. package/src/capabilities/product.capability.d.ts +32 -0
  48. package/src/capabilities/profile.capability.d.ts +39 -0
  49. package/src/core/client.d.ts +81 -0
  50. package/src/core/initialize.d.ts +5 -0
  51. package/src/core/initialize.types.d.ts +108 -0
  52. package/src/factories/cart/cart.factory.d.ts +9 -0
  53. package/src/factories/category/category.factory.d.ts +9 -0
  54. package/src/factories/checkout/checkout.factory.d.ts +11 -0
  55. package/src/factories/identity/identity.factory.d.ts +7 -0
  56. package/src/factories/index.d.ts +12 -0
  57. package/src/factories/inventory/inventory.factory.d.ts +7 -0
  58. package/src/factories/order/order.factory.d.ts +7 -0
  59. package/src/factories/order-search/order-search.factory.d.ts +7 -0
  60. package/src/factories/price/price.factory.d.ts +9 -0
  61. package/src/factories/product/product.factory.d.ts +7 -0
  62. package/src/factories/product-associations/product-associations.factory.d.ts +7 -0
  63. package/src/factories/product-search/product-search.factory.d.ts +7 -0
  64. package/src/factories/profile/profile.factory.d.ts +7 -0
  65. package/src/index.d.ts +17 -0
  66. package/src/schema/capabilities.schema.d.ts +116 -0
  67. package/src/schema/configuration.schema.d.ts +9 -0
  68. package/src/schema/medusa.schema.d.ts +33 -0
  69. package/src/test/test-utils.d.ts +2 -0
  70. package/src/utils/medusa-helpers.d.ts +35 -0
  71. package/test/test-utils.js +12 -0
  72. package/utils/medusa-helpers.js +72 -0
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # medusa
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Building
6
+
7
+ Run `nx build medusa` to build the library.
8
+
9
+ ## Running unit tests
10
+
11
+ Run `nx test medusa` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,517 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result)
9
+ __defProp(target, key, result);
10
+ return result;
11
+ };
12
+ import {
13
+ CartIdentifierSchema,
14
+ CartMutationApplyCouponSchema,
15
+ CartMutationChangeCurrencySchema,
16
+ CartMutationDeleteCartSchema,
17
+ CartMutationItemAddSchema,
18
+ CartMutationItemQuantityChangeSchema,
19
+ CartMutationItemRemoveSchema,
20
+ CartMutationRemoveCouponSchema,
21
+ CartCapability,
22
+ CartQueryByIdSchema,
23
+ CartSchema,
24
+ error,
25
+ ProductVariantIdentifierSchema,
26
+ Reactionary,
27
+ success
28
+ } from "@reactionary/core";
29
+ import createDebug from "debug";
30
+ import { MedusaCartIdentifierSchema } from "../schema/medusa.schema.js";
31
+ import {
32
+ handleProviderError,
33
+ parseMedusaCostBreakdown,
34
+ parseMedusaItemPrice
35
+ } from "../utils/medusa-helpers.js";
36
+ const debug = createDebug("reactionary:medusa:cart");
37
+ class MedusaCartCapability extends CartCapability {
38
+ constructor(config, cache, context, medusaApi, factory) {
39
+ super(cache, context);
40
+ this.medusaApi = medusaApi;
41
+ this.config = config;
42
+ this.factory = factory;
43
+ }
44
+ config;
45
+ factory;
46
+ /**
47
+ * This controls which fields are always included when fetching a cart
48
+ * You can override this in a subclass to add more fields as needed.
49
+ *
50
+ * example: this.includedFields = [includedFields, '+discounts.*'].join(',');
51
+ */
52
+ includedFields = ["+items.*"].join(",");
53
+ async getById(payload) {
54
+ try {
55
+ const client = await this.getClient();
56
+ const medusaId = payload.cart;
57
+ if (debug.enabled) {
58
+ debug("Fetching cart by ID:", medusaId.key);
59
+ }
60
+ const cartResponse = await client.store.cart.retrieve(medusaId.key, { fields: this.includedFields });
61
+ if (debug.enabled) {
62
+ debug("Received cart response:", cartResponse);
63
+ }
64
+ if (cartResponse.cart) {
65
+ return success(this.parseSingle(cartResponse.cart));
66
+ }
67
+ return error({
68
+ type: "NotFound",
69
+ identifier: payload
70
+ });
71
+ } catch (err) {
72
+ debug("Failed to get cart by ID:", error);
73
+ return error({
74
+ type: "NotFound",
75
+ identifier: payload
76
+ });
77
+ }
78
+ }
79
+ /**
80
+ * Extension point for the `add` operation to control the payload sent to Medusa when adding an item to the cart. By default, it only includes the variant ID and quantity, but you can override it to include more fields as needed.
81
+ *
82
+ * @param payload
83
+ * @param variantId
84
+ * @returns
85
+ */
86
+ addPayload(payload, variantId) {
87
+ return {
88
+ variant_id: variantId,
89
+ quantity: payload.quantity
90
+ };
91
+ }
92
+ async add(payload) {
93
+ try {
94
+ const client = await this.getClient();
95
+ let cartIdentifier = payload.cart;
96
+ if (!cartIdentifier) {
97
+ cartIdentifier = await this.createCart();
98
+ }
99
+ const medusaId = cartIdentifier;
100
+ if (debug.enabled) {
101
+ debug(
102
+ "Adding item to cart ID:",
103
+ medusaId.key,
104
+ "SKU:",
105
+ payload.variant.sku,
106
+ "Quantity:",
107
+ payload.quantity
108
+ );
109
+ }
110
+ const variantId = await this.medusaApi.resolveVariantId(payload.variant.sku);
111
+ const response = await client.store.cart.createLineItem(
112
+ medusaId.key,
113
+ this.addPayload(payload, variantId),
114
+ {
115
+ fields: this.includedFields
116
+ }
117
+ );
118
+ if (debug.enabled) {
119
+ debug("Received add item response:", response);
120
+ }
121
+ if (response.cart) {
122
+ return success(this.parseSingle(response.cart));
123
+ }
124
+ throw new Error("Failed to add item to cart");
125
+ } catch (error2) {
126
+ handleProviderError("add item to cart", error2);
127
+ }
128
+ }
129
+ async remove(payload) {
130
+ try {
131
+ const client = await this.getClient();
132
+ const medusaId = payload.cart;
133
+ const response = await client.store.cart.deleteLineItem(
134
+ medusaId.key,
135
+ payload.item.key,
136
+ {
137
+ fields: this.includedFields
138
+ }
139
+ );
140
+ if (response.parent) {
141
+ return success(this.parseSingle(response.parent));
142
+ }
143
+ throw new Error("Failed to remove item from cart");
144
+ } catch (error2) {
145
+ handleProviderError("remove item from cart", error2);
146
+ }
147
+ }
148
+ /**
149
+ * Extension point for the `changeQuantity` operation to control the payload sent to Medusa when changing the quantity of an item in the cart. By default, it only includes the new quantity, but you can override it to include more fields as needed.
150
+ * @param payload
151
+ * @returns
152
+ */
153
+ changeQuantityPayload(payload) {
154
+ return {
155
+ quantity: payload.quantity
156
+ };
157
+ }
158
+ async changeQuantity(payload) {
159
+ if (payload.quantity < 1) {
160
+ throw new Error(
161
+ "Changing quantity to 0 is not allowed. Use the remove call instead."
162
+ );
163
+ }
164
+ try {
165
+ const client = await this.getClient();
166
+ const medusaId = payload.cart;
167
+ const response = await client.store.cart.updateLineItem(
168
+ medusaId.key,
169
+ payload.item.key,
170
+ this.changeQuantityPayload(payload),
171
+ {
172
+ fields: this.includedFields
173
+ }
174
+ );
175
+ if (response.cart) {
176
+ return success(this.parseSingle(response.cart));
177
+ }
178
+ throw new Error("Failed to change item quantity");
179
+ } catch (error2) {
180
+ handleProviderError("change item quantity", error2);
181
+ }
182
+ }
183
+ async getActiveCartId() {
184
+ try {
185
+ const client = await this.getClient();
186
+ const sessionData = this.medusaApi.getSessionData();
187
+ const activeCartId = sessionData.activeCartId;
188
+ if (activeCartId) {
189
+ try {
190
+ await client.store.cart.retrieve(activeCartId);
191
+ return success(this.factory.parseCartIdentifier(this.context, {
192
+ key: activeCartId,
193
+ region_id: (await this.medusaApi.getActiveRegion()).id
194
+ }));
195
+ } catch {
196
+ }
197
+ }
198
+ return error({
199
+ type: "NotFound",
200
+ identifier: void 0
201
+ });
202
+ } catch (err) {
203
+ debug("Failed to get active cart ID:", err);
204
+ return error({
205
+ type: "NotFound",
206
+ identifier: void 0
207
+ });
208
+ }
209
+ }
210
+ async deleteCart(payload) {
211
+ try {
212
+ const client = await this.getClient();
213
+ const medusaId = payload.cart;
214
+ if (medusaId.key) {
215
+ const sessionData = this.medusaApi.getSessionData();
216
+ if (sessionData.activeCartId) {
217
+ delete sessionData.activeCartId;
218
+ this.medusaApi.setSessionData({
219
+ activeCartId: void 0
220
+ });
221
+ }
222
+ }
223
+ const cartResponse = await client.store.cart.retrieve(medusaId.key);
224
+ if (cartResponse.cart) {
225
+ for (const item of cartResponse.cart.items || []) {
226
+ await client.store.cart.deleteLineItem(medusaId.key, item.id);
227
+ }
228
+ }
229
+ return success(void 0);
230
+ } catch (error2) {
231
+ debug("Failed to delete cart:", error2);
232
+ return success(void 0);
233
+ }
234
+ }
235
+ /**
236
+ * Extension point to apply a coupon code to the cart. By default, it only includes the coupon code, but you can override it to include more fields as needed.
237
+ * @param payload
238
+ * @returns
239
+ */
240
+ applyCouponCodePayload(payload) {
241
+ return {
242
+ promo_codes: [payload.couponCode]
243
+ };
244
+ }
245
+ async applyCouponCode(payload) {
246
+ try {
247
+ const client = await this.getClient();
248
+ const medusaId = payload.cart;
249
+ const response = await client.client.fetch(
250
+ `/store/carts/${medusaId.key}/promotions`,
251
+ {
252
+ method: "POST",
253
+ body: this.applyCouponCodePayload(payload),
254
+ query: {
255
+ fields: this.includedFields
256
+ }
257
+ }
258
+ );
259
+ if (response.cart) {
260
+ return success(this.parseSingle(response.cart));
261
+ }
262
+ throw new Error("Failed to apply coupon code");
263
+ } catch (error2) {
264
+ handleProviderError("apply coupon code", error2);
265
+ }
266
+ }
267
+ /**
268
+ * Extension point to remove a coupon code from the cart. By default, it only includes the coupon code to be removed, but you can override it to include more fields as needed.
269
+ * @param payload
270
+ * @returns
271
+ */
272
+ removeCouponCodePayload(payload) {
273
+ return {
274
+ promo_codes: [payload.couponCode]
275
+ };
276
+ }
277
+ async removeCouponCode(payload) {
278
+ try {
279
+ const client = await this.getClient();
280
+ const medusaId = payload.cart;
281
+ const response = await client.client.fetch(
282
+ `/store/carts/${medusaId.key}/promotions`,
283
+ {
284
+ method: "DELETE",
285
+ body: this.removeCouponCodePayload(payload),
286
+ query: {
287
+ fields: this.includedFields
288
+ }
289
+ }
290
+ );
291
+ if (response.cart) {
292
+ return success(this.parseSingle(response.cart));
293
+ }
294
+ throw new Error("Failed to remove coupon code");
295
+ } catch (error2) {
296
+ handleProviderError("remove coupon code", error2);
297
+ }
298
+ }
299
+ /**
300
+ * Extension point to control the payload sent to Medusa when changing the currency of the cart. By default, it only includes the new region ID, but you can override it to include more fields as needed.
301
+ * @param payload
302
+ * @param newRegionId
303
+ * @returns
304
+ */
305
+ changeCurrencyPayload(payload, newRegionId) {
306
+ return {
307
+ region_id: newRegionId
308
+ };
309
+ }
310
+ async changeCurrency(payload) {
311
+ try {
312
+ const client = await this.getClient();
313
+ const newRegionId = (await this.medusaApi.getActiveRegion()).id;
314
+ const updatedCartResponse = await client.store.cart.update(
315
+ payload.cart.key,
316
+ this.changeCurrencyPayload(payload, newRegionId),
317
+ {
318
+ fields: this.includedFields
319
+ }
320
+ );
321
+ if (updatedCartResponse.cart) {
322
+ this.medusaApi.setSessionData({
323
+ activeCartId: updatedCartResponse.cart.id
324
+ });
325
+ return success(this.parseSingle(updatedCartResponse.cart));
326
+ }
327
+ throw new Error("Failed to change currency");
328
+ } catch (error2) {
329
+ handleProviderError("change currency", error2);
330
+ }
331
+ }
332
+ /**
333
+ * Extension point to control the payload sent to Medusa when creating a cart. By default, it only includes the currency code, but you can override it to include more fields as needed.
334
+ * @param currency
335
+ * @returns
336
+ */
337
+ createCartPayload(currency) {
338
+ return {
339
+ currency_code: (currency || this.context.languageContext.currencyCode || "").toLowerCase()
340
+ };
341
+ }
342
+ async createCart(currency) {
343
+ try {
344
+ const client = await this.getClient();
345
+ const response = await client.store.cart.create(
346
+ this.createCartPayload(currency),
347
+ {
348
+ fields: this.includedFields
349
+ }
350
+ );
351
+ if (response.cart) {
352
+ const cartIdentifier = this.factory.parseCartIdentifier(this.context, {
353
+ key: response.cart.id,
354
+ region_id: response.cart.region_id
355
+ });
356
+ this.medusaApi.setSessionData({
357
+ activeCartId: cartIdentifier.key
358
+ });
359
+ return cartIdentifier;
360
+ }
361
+ throw new Error("Failed to create cart");
362
+ } catch (error2) {
363
+ handleProviderError("create cart", error2);
364
+ }
365
+ }
366
+ async getClient() {
367
+ return this.medusaApi.getClient();
368
+ }
369
+ /**
370
+ * Extension point to control the parsing of a single cart item price
371
+ * @param remoteItem
372
+ * @param currency
373
+ * @returns
374
+ */
375
+ parseItemPrice(remoteItem, currency) {
376
+ return parseMedusaItemPrice(remoteItem, currency);
377
+ }
378
+ /**
379
+ * Extension point to control the parsing of the cost breakdown of a cart
380
+ * @param remote
381
+ * @returns
382
+ */
383
+ parseCostBreakdown(remote) {
384
+ return parseMedusaCostBreakdown(remote);
385
+ }
386
+ /**
387
+ * Extension point to control the parsing of a single cart item
388
+ * @param remoteItem
389
+ * @param currency
390
+ * @returns
391
+ */
392
+ parseCartItem(remoteItem, currency) {
393
+ const item = {
394
+ identifier: {
395
+ key: remoteItem.id
396
+ },
397
+ product: {
398
+ key: remoteItem.product_id || ""
399
+ },
400
+ variant: ProductVariantIdentifierSchema.parse({
401
+ sku: remoteItem.variant_sku || ""
402
+ }),
403
+ quantity: remoteItem.quantity || 1,
404
+ price: parseMedusaItemPrice(remoteItem, currency)
405
+ };
406
+ return item;
407
+ }
408
+ /**
409
+ * Extension point to control the parsing of a single cart
410
+ * @param remote
411
+ * @returns
412
+ */
413
+ parseSingle(remote) {
414
+ const identifier = MedusaCartIdentifierSchema.parse({
415
+ key: remote.id,
416
+ region_id: remote.region_id
417
+ });
418
+ const name = "" + (remote.metadata?.["name"] || "");
419
+ const description = "" + (remote.metadata?.["description"] || "");
420
+ const price = this.parseCostBreakdown(remote);
421
+ const items = new Array();
422
+ const allItems = remote.items || [];
423
+ allItems.sort(
424
+ (a, b) => a.created_at && b.created_at ? new Date(a.created_at).getTime() - new Date(b.created_at).getTime() : 0
425
+ );
426
+ for (const remoteItem of allItems) {
427
+ items.push(this.parseCartItem(remoteItem, price.grandTotal.currency));
428
+ }
429
+ const appliedPromotions = [];
430
+ if (remote.promotions) {
431
+ for (const promo of remote.promotions) {
432
+ const promotionName = promo.code;
433
+ let promoDescription = "";
434
+ if (promo.application_method?.type === "percentage") {
435
+ promoDescription = `-${promo.application_method.value}%`;
436
+ }
437
+ if (promo.application_method?.type === "fixed") {
438
+ promoDescription = `-${promo.application_method.value} ${price.grandTotal.currency}`;
439
+ }
440
+ appliedPromotions.push({
441
+ code: promo.code || "",
442
+ isCouponCode: promo.is_automatic ? false : true,
443
+ name: promotionName || promoDescription,
444
+ description: promoDescription
445
+ });
446
+ }
447
+ }
448
+ const result = {
449
+ identifier,
450
+ name,
451
+ description,
452
+ price,
453
+ items,
454
+ appliedPromotions,
455
+ userId: {
456
+ userId: "???"
457
+ }
458
+ };
459
+ return this.factory.parseCart(this.context, result);
460
+ }
461
+ }
462
+ __decorateClass([
463
+ Reactionary({
464
+ inputSchema: CartQueryByIdSchema,
465
+ outputSchema: CartSchema
466
+ })
467
+ ], MedusaCartCapability.prototype, "getById", 1);
468
+ __decorateClass([
469
+ Reactionary({
470
+ inputSchema: CartMutationItemAddSchema,
471
+ outputSchema: CartSchema
472
+ })
473
+ ], MedusaCartCapability.prototype, "add", 1);
474
+ __decorateClass([
475
+ Reactionary({
476
+ inputSchema: CartMutationItemRemoveSchema,
477
+ outputSchema: CartSchema
478
+ })
479
+ ], MedusaCartCapability.prototype, "remove", 1);
480
+ __decorateClass([
481
+ Reactionary({
482
+ inputSchema: CartMutationItemQuantityChangeSchema,
483
+ outputSchema: CartSchema
484
+ })
485
+ ], MedusaCartCapability.prototype, "changeQuantity", 1);
486
+ __decorateClass([
487
+ Reactionary({
488
+ outputSchema: CartIdentifierSchema
489
+ })
490
+ ], MedusaCartCapability.prototype, "getActiveCartId", 1);
491
+ __decorateClass([
492
+ Reactionary({
493
+ cache: false,
494
+ inputSchema: CartMutationDeleteCartSchema
495
+ })
496
+ ], MedusaCartCapability.prototype, "deleteCart", 1);
497
+ __decorateClass([
498
+ Reactionary({
499
+ inputSchema: CartMutationApplyCouponSchema,
500
+ outputSchema: CartSchema
501
+ })
502
+ ], MedusaCartCapability.prototype, "applyCouponCode", 1);
503
+ __decorateClass([
504
+ Reactionary({
505
+ inputSchema: CartMutationRemoveCouponSchema,
506
+ outputSchema: CartSchema
507
+ })
508
+ ], MedusaCartCapability.prototype, "removeCouponCode", 1);
509
+ __decorateClass([
510
+ Reactionary({
511
+ inputSchema: CartMutationChangeCurrencySchema,
512
+ outputSchema: CartSchema
513
+ })
514
+ ], MedusaCartCapability.prototype, "changeCurrency", 1);
515
+ export {
516
+ MedusaCartCapability
517
+ };