This commit is contained in:
--list
2021-06-28 12:42:26 +02:00
parent b62d4a7038
commit e86f4656a9
19 changed files with 174 additions and 63 deletions

View File

@@ -155,7 +155,7 @@ export default async (req, res) => {
draftOrder = await draftOrderService.retrieve(draftOrder.id, {
relations: defaultRelations,
select: defaultFields,
})
}) //
res.status(200).json({ draft_order: draftOrder })
} catch (err) {

View File

@@ -65,7 +65,7 @@ export default (app, container, config) => {
returnRoutes(route)
variantRoutes(route)
draftOrderRoutes(route)
collectionRoutes(route)
collectionRoutes(route) //test
notificationRoutes(route)
returnReasonRoutes(route)

View File

@@ -110,7 +110,7 @@ import { defaultRelations, defaultFields } from "./"
* $ref: "#/components/schemas/order"
*/
export default async (req, res) => {
const { id } = req.params
const { id } = req.params
const schema = Validator.object().keys({
type: Validator.string()
@@ -165,7 +165,7 @@ export default async (req, res) => {
const { value, error } = schema.validate(req.body)
if (error) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
}
const idempotencyKeyService = req.scope.resolve("idempotencyKeyService")

View File

@@ -64,7 +64,10 @@ export default async (req, res) => {
try {
const orderService = req.scope.resolve("orderService")
await orderService.createFulfillment(id, value.items, value.no_notification, value.metadata)
await orderService.createFulfillment(id, value.items, {
metadata: value.metadata,
noNotification: value.no_notification
})
const order = await orderService.retrieve(id, {
select: defaultFields,

View File

@@ -44,7 +44,7 @@ export default async (req, res) => {
tracking_numbers: Validator.array()
.items(Validator.string())
.optional(),
no_notification: Validator.boolean().optional(),
no_notification: Validator.boolean().optional(),
})
const { value, error } = schema.validate(req.body)
@@ -59,7 +59,7 @@ export default async (req, res) => {
id,
value.fulfillment_id,
value.tracking_numbers.map(n => ({ tracking_number: n })),
value.no_notification,
{noNotification: value.no_notification},
)
const order = await orderService.retrieve(id, {

View File

@@ -22,6 +22,9 @@ import { defaultFields, defaultRelations } from "./"
* type: array
* items:
* type: string
* no_notification:
* description: If set to true no notification will be send related to this Claim.
* type: boolean
* tags:
* - Order
* responses:
@@ -42,6 +45,7 @@ export default async (req, res) => {
tracking_numbers: Validator.array()
.items(Validator.string())
.optional(),
no_notification: Validator.boolean().optional(),
})
const { value, error } = schema.validate(req.body)
@@ -56,7 +60,8 @@ export default async (req, res) => {
await swapService.createShipment(
swap_id,
value.fulfillment_id,
value.tracking_numbers.map(n => ({ tracking_number: n }))
value.tracking_numbers.map(n => ({ tracking_number: n })),
{noNotification: value.no_notification},
)
const order = await orderService.retrieve(id, {

View File

@@ -90,6 +90,8 @@ export default async (req, res) => {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
console.log("..>")
const idempotencyKeyService = req.scope.resolve("idempotencyKeyService")
const headerKey = req.get("Idempotency-Key") || ""
@@ -138,8 +140,7 @@ export default async (req, res) => {
value.return_items,
value.additional_items,
value.return_shipping,
value.no_notification,
{ idempotency_key: idempotencyKey.idempotency_key }
{ idempotency_key: idempotencyKey.idempotency_key, noNotification: value.no_notification }
)
await swapService.withTransaction(manager).createCart(swap.id)

View File

@@ -17,6 +17,9 @@ import { defaultRelations, defaultFields } from "./"
* metadata:
* description: An optional set of key-value pairs to hold additional information.
* type: object
* no_notification:
* description: If set to true no notification will be send related to this Claim.
* type: boolean
* tags:
* - Order
* responses:
@@ -34,6 +37,7 @@ export default async (req, res) => {
const schema = Validator.object().keys({
metadata: Validator.object().optional(),
no_notification: Validator.boolean().optional(),
})
const { value, error } = schema.validate(req.body)
@@ -49,7 +53,10 @@ export default async (req, res) => {
await entityManager.transaction(async manager => {
await claimService
.withTransaction(manager)
.createFulfillment(claim_id, value.metadata)
.createFulfillment(claim_id, {
metadata: value.metadata,
noNotification: value.no_notification,
})
})
const order = await orderService.retrieve(id, {

View File

@@ -17,6 +17,9 @@ import { defaultRelations, defaultFields } from "./"
* metadata:
* description: An optional set of key-value pairs to hold additional information.
* type: object
* no_notification:
* description: If set to true no notification will be send related to this Claim.
* type: boolean
* tags:
* - Order
* responses:
@@ -34,6 +37,7 @@ export default async (req, res) => {
const schema = Validator.object().keys({
metadata: Validator.object().optional(),
no_notification: Validator.boolean().optional,
})
const { value, error } = schema.validate(req.body)
@@ -49,7 +53,10 @@ export default async (req, res) => {
await entityManager.transaction(async manager => {
await swapService
.withTransaction(manager)
.createFulfillment(swap_id, value.metadata)
.createFulfillment(swap_id, {
metadata: value.metadata,
noNotification: value.no_notification,
})
const order = await orderService.withTransaction(manager).retrieve(id, {
select: defaultFields,

View File

@@ -62,7 +62,7 @@ export default async (req, res) => {
try {
const orderService = req.scope.resolve("orderService")
await orderService.createRefund(id, value.amount, value.reason, value.note, value.no_notification)
await orderService.createRefund(id, value.amount, value.reason, value.note, {noNotification: value.no_notification})
const order = await orderService.retrieve(id, {
select: defaultFields,

View File

@@ -43,3 +43,4 @@ export { Swap } from "./models/swap"
export { User } from "./models/user"
export { DraftOrder } from "./models/draft-order"
export { ReturnReason } from "./models/return-reason"

View File

@@ -9,9 +9,11 @@ export class noNotification1623231564533 implements MigrationInterface {
await queryRunner.query(`ALTER TABLE "swap" ADD "no_notification" boolean`);
await queryRunner.query(`ALTER TABLE "order" ADD "no_notification" boolean`);
await queryRunner.query(`ALTER TABLE "draft_order" ADD "no_notification_order" boolean`);
await queryRunner.query(`ALTER TABLE "fulfillment" ADD "no_notification" boolean`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "fulfillment" DROP COLUMN "no_notification"`);
await queryRunner.query(`ALTER TABLE "draft_order" DROP COLUMN "no_notification_order"`);
await queryRunner.query(`ALTER TABLE "order" DROP COLUMN "no_notification"`);
await queryRunner.query(`ALTER TABLE "swap" DROP COLUMN "no_notification"`);

View File

@@ -62,6 +62,9 @@ export class Fulfillment {
@JoinColumn({ name: "order_id" })
order: Order
@Column({ type: "boolean", nullable: true})
no_notification: Boolean
@Index()
@Column()
provider_id: string
@@ -157,6 +160,9 @@ export class Fulfillment {
* description: "The date with timezone at which the Fulfillment was shipped."
* type: string
* format: date-time
* no_notification:
* description: "Flag for describing whether or not notifications related to this should be send."
* type: boolean
* canceled_at:
* description: "The date with timezone at which the Fulfillment was canceled."
* type: string

View File

@@ -135,7 +135,7 @@ class ClaimService extends BaseService {
}
}
if(no_notification !== undefined){
if( no_notification !== undefined ){
claim.no_notification = no_notification
await claimRepo.save(claim)
}
@@ -306,7 +306,12 @@ class ClaimService extends BaseService {
})
}
createFulfillment(id, metadata = {}) {
createFulfillment(id, config = {
metadata: {},
noNotification: undefined,
}) {
const { metadata, noNotification } = config
return this.atomicPhase_(async manager => {
const claim = await this.retrieve(id, {
relations: [
@@ -343,6 +348,8 @@ class ClaimService extends BaseService {
)
}
const evaluatedNoNotification = noNotification !== undefined ? noNotification : claim.no_notification
const fulfillments = await this.fulfillmentService_
.withTransaction(manager)
.createFulfillment(
@@ -359,6 +366,7 @@ class ClaimService extends BaseService {
items: claim.additional_items,
shipping_methods: claim.shipping_methods,
is_claim: true,
no_notification: evaluatedNoNotification,
},
claim.additional_items.map(i => ({
item_id: i.id,
@@ -450,15 +458,22 @@ class ClaimService extends BaseService {
})
}
async createShipment(id, fulfillmentId, trackingLinks, metadata = []) {
async createShipment(id, fulfillmentId, trackingLinks, config = {
metadata: [],
noNotification: undefined,
}) {
const { metadata, noNotification } = config
return this.atomicPhase_(async manager => {
const claim = await this.retrieve(id, {
relations: ["additional_items"],
})
const evaluatedNoNotification = noNotification !== undefined ? noNotification : claim.no_notification
const shipment = await this.fulfillmentService_
.withTransaction(manager)
.createShipment(fulfillmentId, trackingLinks, metadata)
.createShipment(fulfillmentId, trackingLinks, {metadata, noNotification: evaluatedNoNotification})
claim.fulfillment_status = "shipped"

View File

@@ -165,10 +165,15 @@ class FulfillmentService extends BaseService {
* those partitions.
* @param {Order} order - order to create fulfillment for
* @param {{ item_id: string, quantity: number}[]} itemsToFulfill - the items in the order to fulfill
* @param {object} metadata - potential metadata to add
* @param {object} config - potential configurations, including metadata to add
* @return {Fulfillment[]} the created fulfillments
*/
async createFulfillment(order, itemsToFulfill, custom = {}) {
async createFulfillment(order, itemsToFulfill, config = {
noNotification: undefined,
custom: {},
}) {
const {custom, noNotification} = config
return this.atomicPhase_(async manager => {
const fulfillmentRepository = manager.getCustomRepository(
this.fulfillmentRepository_
@@ -180,6 +185,8 @@ class FulfillmentService extends BaseService {
this.validateFulfillmentLineItem_
)
const evaluatedNoNotification = noNotification !== undefined ? noNotification : order.no_notification
const { shipping_methods } = order
// partition order items to their dedicated shipping method
@@ -191,6 +198,7 @@ class FulfillmentService extends BaseService {
...custom,
provider_id: shipping_method.shipping_option.provider_id,
items: items.map(i => ({ item_id: i.id, quantity: i.quantity })),
no_notification: evaluatedNoNotification,
data: {},
})

View File

@@ -28,7 +28,7 @@ class NotificationService extends BaseService {
this.notificationProviderRepository_ = notificationProviderRepository
this.subscribers_ = {}
this.attachmentGenerator_ = null
this.attachmentGenerator_ = null
}
/**

View File

@@ -1,3 +1,4 @@
import { metadata } from "core-js/fn/reflect"
import _ from "lodash"
import { Validator, MedusaError } from "medusa-core-utils"
import { BaseService } from "medusa-interfaces"
@@ -572,7 +573,12 @@ class OrderService extends BaseService {
* the fulfillment
* @return {order} the resulting order following the update.
*/
async createShipment(orderId, fulfillmentId, trackingLinks, noNotification = undefined, metadata = {}) {
async createShipment(orderId, fulfillmentId, trackingLinks, config = {
metadata: {},
noNotification: undefined,
}) {
const { metadata, noNotification } = config
return this.atomicPhase_(async manager => {
const order = await this.retrieve(orderId, { relations: ["items"] })
const shipment = await this.fulfillmentService_.retrieve(fulfillmentId)
@@ -584,9 +590,11 @@ class OrderService extends BaseService {
)
}
const evaluatedNoNotification = noNotification !== undefined ? noNotification : shipment.no_notification
const shipmentRes = await this.fulfillmentService_
.withTransaction(manager)
.createShipment(fulfillmentId, trackingLinks, metadata)
.createShipment(fulfillmentId, trackingLinks, {metadata, noNotification: evaluatedNoNotification})
order.fulfillment_status = "shipped"
for (const item of order.items) {
@@ -610,8 +618,6 @@ class OrderService extends BaseService {
const orderRepo = manager.getCustomRepository(this.orderRepository_)
const result = await orderRepo.save(order)
const evaluatedNoNotification = noNotification !== undefined ? noNotification : order.no_notification
await this.eventBus_
.withTransaction(manager)
.emit(OrderService.Events.SHIPMENT_CREATED, {
@@ -983,7 +989,12 @@ class OrderService extends BaseService {
* @param {string} orderId - id of order to cancel.
* @return {Promise} result of the update operation.
*/
async createFulfillment(orderId, itemsToFulfill, noNotification = undefined, metadata = {}) {
async createFulfillment(orderId, itemsToFulfill, config = {
noNotification: undefined,
metadata: {},
}) {
const { metadata, noNotification } = config
return this.atomicPhase_(async manager => {
const order = await this.retrieve(orderId, {
select: [
@@ -1011,18 +1022,23 @@ class OrderService extends BaseService {
],
})
console.log("metadata:" + metadata)
if (!order.shipping_methods?.length) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Cannot fulfill an order that lacks shipping methods"
)
}
const fulfillments = await this.fulfillmentService_
.withTransaction(manager)
.createFulfillment(order, itemsToFulfill, {
metadata,
order_id: orderId,
no_notification: noNotification
})
let successfullyFulfilled = []
for (const f of fulfillments) {
@@ -1125,7 +1141,11 @@ class OrderService extends BaseService {
/**
* Refunds a given amount back to the customer.
*/
async createRefund(orderId, refundAmount, reason, note, noNotification = undefined) {
async createRefund(orderId, refundAmount, reason, note, config = {
noNotification: undefined,
}) {
const { noNotification } = config
return this.atomicPhase_(async manager => {
const order = await this.retrieve(orderId, {
select: ["refundable_amount", "total", "refunded_total"],

View File

@@ -16,6 +16,7 @@ class SwapService extends BaseService {
PAYMENT_CAPTURE_FAILED: "swap.payment_capture_failed",
PROCESS_REFUND_FAILED: "swap.process_refund_failed",
REFUND_PROCESSED: "swap.refund_processed",
FULFILLMENT_CREATED: "swap.fulfillment_created",
}
constructor({
@@ -214,9 +215,13 @@ class SwapService extends BaseService {
returnItems,
additionalItems,
returnShipping,
noNotification,
custom = {}
config = {
custom: {},
noNotification: undefined,
}
) {
const { noNotification, custom } = config
return this.atomicPhase_(async manager => {
if (
order.fulfillment_status === "not_fulfilled" ||
@@ -302,10 +307,12 @@ class SwapService extends BaseService {
swap.payment_status = "requires_action"
const result = await swapRepo.save(swap)
// TODO: event payload should not contain full result but just { id: result.id ... }
await this.eventBus_
.withTransaction(manager)
.emit(SwapService.Events.PROCESS_REFUND_FAILED, result)
.emit(SwapService.Events.PROCESS_REFUND_FAILED, {
id: result.id,
no_notification: swap.no_notification,
})
return result
}
@@ -314,10 +321,12 @@ class SwapService extends BaseService {
const result = await swapRepo.save(swap)
// TODO: event payload should not contain full result but just { id: result.id ... }
await this.eventBus_
.withTransaction(manager)
.emit(SwapService.Events.REFUND_PROCESSED, result)
.emit(SwapService.Events.REFUND_PROCESSED, {
id: result.id,
no_notification: swap.no_notification,
})
return result
} else if (swap.difference_due === 0) {
@@ -329,10 +338,12 @@ class SwapService extends BaseService {
const result = await swapRepo.save(swap)
// TODO: event payload should not contain full result but just { id: result.id ... }
await this.eventBus_
.withTransaction(manager)
.emit(SwapService.Events.REFUND_PROCESSED, result)
.emit(SwapService.Events.REFUND_PROCESSED, {
id: result.id,
no_notification: swap.no_notification,
})
return result
}
@@ -349,10 +360,12 @@ class SwapService extends BaseService {
swap.payment_status = "requires_action"
const result = await swapRepo.save(swap)
// TODO: event payload should not contain full result but just { id: result.id ... }
await this.eventBus_
.withTransaction(manager)
.emit(SwapService.Events.PAYMENT_CAPTURE_FAILED, result)
.emit(SwapService.Events.PAYMENT_CAPTURE_FAILED, {
id: swap.id,
no_notification: swap.no_notification,
})
return result
}
@@ -361,10 +374,12 @@ class SwapService extends BaseService {
const result = await swapRepo.save(swap)
// TODO: event payload should not contain full result but just { id: result.id ... }
await this.eventBus_
.withTransaction(manager)
.emit(SwapService.Events.PAYMENT_CAPTURED, result)
.emit(SwapService.Events.PAYMENT_CAPTURED, {
id: result.id,
no_notification: swap.no_notification,
})
return result
})
@@ -374,15 +389,15 @@ class SwapService extends BaseService {
return this.atomicPhase_(async manager => {
const swap = await this.retrieve(swapId)
if ("metadata" in update) {
if ( "metadata" in update ) {
swap.metadata = this.setMetadata_(swap, update.metadata)
}
if("no_notification" in update){
if( "no_notification" in update ){
swap.no_notification = update.no_notification
}
if ("shipping_address" in update) {
if ( "shipping_address" in update ) {
await this.updateShippingAddress_(swap, update.shipping_address)
}
@@ -634,7 +649,12 @@ class SwapService extends BaseService {
* @param {object} metadata - optional metadata to attach to the fulfillment.
* @returns {Promise<Swap>} the updated swap with new status and fulfillments.
*/
async createFulfillment(swapId, metadata = {}) {
async createFulfillment(swapId, config = {
metadata: {},
noNotification: undefined
}) {
const { metadata, noNotification } = config
return this.atomicPhase_(async manager => {
const swap = await this.retrieve(swapId, {
relations: [
@@ -664,6 +684,8 @@ class SwapService extends BaseService {
)
}
const evaluatedNoNotification = noNotification !== undefined ? noNotification : swap.no_notification
swap.fulfillments = await this.fulfillmentService_
.withTransaction(manager)
.createFulfillment(
@@ -680,6 +702,7 @@ class SwapService extends BaseService {
items: swap.additional_items,
shipping_methods: swap.shipping_methods,
is_swap: true,
no_notification: evaluatedNoNotification,
},
swap.additional_items.map(i => ({
item_id: i.id,
@@ -723,7 +746,13 @@ class SwapService extends BaseService {
const swapRepo = manager.getCustomRepository(this.swapRepository_)
const result = await swapRepo.save(swap)
// TODO: EMIT swap.fulfillment_created
await this.eventBus_
.withTransaction(manager)
.emit(SwapService.Events.FULFILLMENT_CREATED, {
id: swapId,
fulfillment_id: shipment.id,
no_notification: evaluatedNoNotification
})
return result
})
@@ -739,16 +768,23 @@ class SwapService extends BaseService {
* @param {object} metadata - optional metadata to attach to the shipment.
* @returns {Promise<Swap>} the updated swap with new fulfillments and status.
*/
async createShipment(swapId, fulfillmentId, trackingLinks, metadata = {}) {
async createShipment(swapId, fulfillmentId, trackingLinks, config = {
metadata: {},
noNotification: undefined,
} ) {
const { metadata, noNotification } = config
return this.atomicPhase_(async manager => {
const swap = await this.retrieve(swapId, {
relations: ["additional_items"],
})
const evaluatedNoNotification = noNotification !== undefined ? noNotification : swap.no_notification
// Update the fulfillment to register
const shipment = await this.fulfillmentService_
.withTransaction(manager)
.createShipment(fulfillmentId, trackingLinks, metadata)
.createShipment(fulfillmentId, trackingLinks, {metadata, noNotification: evaluatedNoNotification})
swap.fulfillment_status = "shipped"

View File

@@ -1673,10 +1673,10 @@ babel-preset-jest@^25.5.0:
babel-plugin-jest-hoist "^25.5.0"
babel-preset-current-node-syntax "^0.1.2"
babel-preset-medusa-package@^1.1.5-next.0:
version "1.1.5-next.0"
resolved "https://registry.yarnpkg.com/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.5-next.0.tgz#3ab62092742ae4976f80e2d0f9ff887866d7f032"
integrity sha512-M+DDbIi2VLZdir+svQIpWhUACHTE/1Cx2aQ8zU/n+0kb29yxMVNWqZto9m4Uh3c9PkoSnZfOYpu1AG/5RPByjw==
babel-preset-medusa-package@^1.1.8:
version "1.1.9"
resolved "https://registry.yarnpkg.com/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.9.tgz#4bd3f588e9d84d5888279a82dd69559965326cdc"
integrity sha512-U+5QM2N2kQ0Rxy8/8tUXzCbckrkju7E+bvPitFLctAR9V6RAWrJuZ11joZ+tE8upIkS1/b4uEbrVnoM0pq+nNA==
dependencies:
"@babel/plugin-proposal-class-properties" "^7.12.1"
"@babel/plugin-proposal-decorators" "^7.12.1"
@@ -4545,28 +4545,28 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
medusa-core-utils@^1.1.11-next.0, medusa-core-utils@^1.1.11-next.0+60da043:
version "1.1.11-next.0"
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.11-next.0.tgz#c65ec751f48a3abf530bea598793fbbb96b84796"
integrity sha512-v4qqsRAOBvueJcKeMD8uL2Qb9dvR+qh3sDvW8C+1bpbnjuTbIq2D+d/xT+963mx3+e445XRoePjXNLltUcSicw==
medusa-core-utils@^1.1.14, medusa-core-utils@^1.1.15:
version "1.1.15"
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.15.tgz#0fe98e1a451b5554b03421d241c973b67f00ff9b"
integrity sha512-sK1+Q0k68Rsz0XDAYLVDJ9hshQssMTxceUk+9umXxZgZlPhrPcHMMi8BwwrKOEaSk+nxmN38/h0XiHJ92Pts8g==
dependencies:
joi "^17.3.0"
joi-objectid "^3.0.1"
medusa-interfaces@^1.1.12-next.0:
version "1.1.12-next.0"
resolved "https://registry.yarnpkg.com/medusa-interfaces/-/medusa-interfaces-1.1.12-next.0.tgz#12f0b6eb068c729b10a66b693462e765a7661954"
integrity sha512-55CrFN4QHtUo32XQ88qKw1/CfqwikQxNnR2u05Xyyc63efoxlk6tlGg5o8PH74rA3kwQgmztjfG859GtwBRoOg==
medusa-interfaces@^1.1.15:
version "1.1.16"
resolved "https://registry.yarnpkg.com/medusa-interfaces/-/medusa-interfaces-1.1.16.tgz#1b693759359faa2811966c9420f20f865591cf05"
integrity sha512-ghy4radBy1RIrkRThXIQ2q86htxPPnIFA1LMNyxViPKVZ+QPv350NNow6gSXsm6diTV5lWH0Bvl/hH6AbjA8vA==
dependencies:
medusa-core-utils "^1.1.11-next.0+60da043"
medusa-core-utils "^1.1.15"
medusa-test-utils@^1.1.14-next.0:
version "1.1.14-next.0"
resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.1.14-next.0.tgz#29a85e7f08da811e3f2c735de5a906522de23948"
integrity sha512-NMUP7d1HH91piXLZGeF6ifEiyI4cA8jp7OTrD8+i/miS0HwilGxsXxqfzolzgsB/2AWiDrLdWg+pFF8JREQT2Q==
medusa-test-utils@^1.1.17:
version "1.1.18"
resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.1.18.tgz#4660f1cbec47abf5f17fc9469bb7ec5543b93c85"
integrity sha512-M25eFBvxlBzKu4dHQFz2ijMqjQIYgG5eNIxo1NE+3CLrgRNl+nrG+LwUBE0ouVDa9fi1TMSXXeTD17/7o7UOAA==
dependencies:
"@babel/plugin-transform-classes" "^7.9.5"
medusa-core-utils "^1.1.11-next.0+60da043"
medusa-core-utils "^1.1.15"
randomatic "^3.1.1"
merge-descriptors@1.0.1: