chore(medusa): Move formatException to the errorHandler to be always applied and not have to apply it manually (#2467)
**What** Move the usage of the formatException to the errorHandler level in order to not have to try catch here and there to apply it. Also make our error handling uniformed and avoid forgetting to apply it. FIXES CORE-721
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { NextFunction, Request, Response } from "express"
|
import { NextFunction, Request, Response } from "express"
|
||||||
import { MedusaError } from "medusa-core-utils"
|
import { MedusaError } from "medusa-core-utils"
|
||||||
import { Logger } from "../../types/global"
|
import { Logger } from "../../types/global"
|
||||||
|
import { formatException } from "../../utils";
|
||||||
|
|
||||||
const QUERY_RUNNER_RELEASED = "QueryRunnerAlreadyReleasedError"
|
const QUERY_RUNNER_RELEASED = "QueryRunnerAlreadyReleasedError"
|
||||||
const TRANSACTION_STARTED = "TransactionAlreadyStartedError"
|
const TRANSACTION_STARTED = "TransactionAlreadyStartedError"
|
||||||
@@ -18,6 +19,9 @@ export default () => {
|
|||||||
next: NextFunction
|
next: NextFunction
|
||||||
) => {
|
) => {
|
||||||
const logger: Logger = req.scope.resolve("logger")
|
const logger: Logger = req.scope.resolve("logger")
|
||||||
|
|
||||||
|
err = formatException(err)
|
||||||
|
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
|
|
||||||
const errorType = err.type || err.name
|
const errorType = err.type || err.name
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { FindConfig, Selector } from "../types/common"
|
|||||||
import { CustomerGroupUpdate } from "../types/customer-groups"
|
import { CustomerGroupUpdate } from "../types/customer-groups"
|
||||||
import {
|
import {
|
||||||
buildQuery,
|
buildQuery,
|
||||||
formatException,
|
|
||||||
isDefined,
|
isDefined,
|
||||||
isString,
|
isString,
|
||||||
PostgresError,
|
PostgresError,
|
||||||
@@ -108,26 +107,8 @@ class CustomerGroupService extends TransactionBaseService {
|
|||||||
)
|
)
|
||||||
return await cgRepo.addCustomers(id, ids)
|
return await cgRepo.addCustomers(id, ids)
|
||||||
},
|
},
|
||||||
async (error: any) => {
|
async (e: any) => {
|
||||||
if (error.code === PostgresError.FOREIGN_KEY_ERROR) {
|
await this.handleCreationFail(id, ids, e)
|
||||||
await this.retrieve(id)
|
|
||||||
|
|
||||||
const existingCustomers = await this.customerService_.list({
|
|
||||||
id: ids,
|
|
||||||
})
|
|
||||||
|
|
||||||
const nonExistingCustomers = ids.filter(
|
|
||||||
(cId) => existingCustomers.findIndex((el) => el.id === cId) === -1
|
|
||||||
)
|
|
||||||
|
|
||||||
throw new MedusaError(
|
|
||||||
MedusaError.Types.NOT_FOUND,
|
|
||||||
`The following customer ids do not exist: ${JSON.stringify(
|
|
||||||
nonExistingCustomers.join(", ")
|
|
||||||
)}`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
throw formatException(error)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -274,6 +255,32 @@ class CustomerGroupService extends TransactionBaseService {
|
|||||||
|
|
||||||
return customerGroup
|
return customerGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async handleCreationFail(
|
||||||
|
id: string,
|
||||||
|
ids: string[],
|
||||||
|
error: any
|
||||||
|
): Promise<never> {
|
||||||
|
if (error.code === PostgresError.FOREIGN_KEY_ERROR) {
|
||||||
|
await this.retrieve(id)
|
||||||
|
|
||||||
|
const existingCustomers = await this.customerService_.list({
|
||||||
|
id: ids,
|
||||||
|
})
|
||||||
|
|
||||||
|
const nonExistingCustomers = ids.filter(
|
||||||
|
(cId) => existingCustomers.findIndex((el) => el.id === cId) === -1
|
||||||
|
)
|
||||||
|
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`The following customer ids do not exist: ${JSON.stringify(
|
||||||
|
nonExistingCustomers.join(", ")
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CustomerGroupService
|
export default CustomerGroupService
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { CustomerRepository } from "../repositories/customer"
|
|||||||
import { AddressCreatePayload, FindConfig, Selector } from "../types/common"
|
import { AddressCreatePayload, FindConfig, Selector } from "../types/common"
|
||||||
import { CreateCustomerInput, UpdateCustomerInput } from "../types/customers"
|
import { CreateCustomerInput, UpdateCustomerInput } from "../types/customers"
|
||||||
import { buildQuery, isDefined, setMetadata } from "../utils"
|
import { buildQuery, isDefined, setMetadata } from "../utils"
|
||||||
import { formatException } from "../utils/exception-formatter"
|
|
||||||
import EventBusService from "./event-bus"
|
import EventBusService from "./event-bus"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -19,6 +18,7 @@ type InjectedDependencies = {
|
|||||||
customerRepository: typeof CustomerRepository
|
customerRepository: typeof CustomerRepository
|
||||||
addressRepository: typeof AddressRepository
|
addressRepository: typeof AddressRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides layer to manipulate customers.
|
* Provides layer to manipulate customers.
|
||||||
*/
|
*/
|
||||||
@@ -301,57 +301,53 @@ class CustomerService extends TransactionBaseService {
|
|||||||
customerId: string,
|
customerId: string,
|
||||||
update: UpdateCustomerInput
|
update: UpdateCustomerInput
|
||||||
): Promise<Customer> {
|
): Promise<Customer> {
|
||||||
return await this.atomicPhase_(
|
return await this.atomicPhase_(async (manager) => {
|
||||||
async (manager) => {
|
const customerRepository = manager.getCustomRepository(
|
||||||
const customerRepository = manager.getCustomRepository(
|
this.customerRepository_
|
||||||
this.customerRepository_
|
)
|
||||||
)
|
|
||||||
|
|
||||||
const customer = await this.retrieve(customerId)
|
const customer = await this.retrieve(customerId)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
password,
|
password,
|
||||||
metadata,
|
metadata,
|
||||||
billing_address,
|
billing_address,
|
||||||
billing_address_id,
|
billing_address_id,
|
||||||
groups,
|
groups,
|
||||||
...rest
|
...rest
|
||||||
} = update
|
} = update
|
||||||
|
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
customer.metadata = setMetadata(customer, metadata)
|
customer.metadata = setMetadata(customer, metadata)
|
||||||
}
|
|
||||||
|
|
||||||
if ("billing_address_id" in update || "billing_address" in update) {
|
|
||||||
const address = billing_address_id || billing_address
|
|
||||||
if (isDefined(address)) {
|
|
||||||
await this.updateBillingAddress_(customer, address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(rest)) {
|
|
||||||
customer[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
if (password) {
|
|
||||||
customer.password_hash = await this.hashPassword_(password)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groups) {
|
|
||||||
customer.groups = groups as CustomerGroup[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const updated = await customerRepository.save(customer)
|
|
||||||
|
|
||||||
await this.eventBusService_
|
|
||||||
.withTransaction(manager)
|
|
||||||
.emit(CustomerService.Events.UPDATED, updated)
|
|
||||||
return updated
|
|
||||||
},
|
|
||||||
async (error) => {
|
|
||||||
throw formatException(error)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
if ("billing_address_id" in update || "billing_address" in update) {
|
||||||
|
const address = billing_address_id || billing_address
|
||||||
|
if (isDefined(address)) {
|
||||||
|
await this.updateBillingAddress_(customer, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(rest)) {
|
||||||
|
customer[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password) {
|
||||||
|
customer.password_hash = await this.hashPassword_(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groups) {
|
||||||
|
customer.groups = groups as CustomerGroup[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const updated = await customerRepository.save(customer)
|
||||||
|
|
||||||
|
await this.eventBusService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.emit(CustomerService.Events.UPDATED, updated)
|
||||||
|
|
||||||
|
return updated
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ import {
|
|||||||
} from "../types/discount"
|
} from "../types/discount"
|
||||||
import { buildQuery, setMetadata } from "../utils"
|
import { buildQuery, setMetadata } from "../utils"
|
||||||
import { isFuture, isPast } from "../utils/date-helpers"
|
import { isFuture, isPast } from "../utils/date-helpers"
|
||||||
import { formatException } from "../utils/exception-formatter"
|
|
||||||
import { FlagRouter } from "../utils/flag-router"
|
import { FlagRouter } from "../utils/flag-router"
|
||||||
import CustomerService from "./customer"
|
import CustomerService from "./customer"
|
||||||
import DiscountConditionService from "./discount-condition"
|
import DiscountConditionService from "./discount-condition"
|
||||||
@@ -200,39 +199,35 @@ class DiscountService extends TransactionBaseService {
|
|||||||
"Fixed discounts can have one region"
|
"Fixed discounts can have one region"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
try {
|
if (discount.regions) {
|
||||||
if (discount.regions) {
|
discount.regions = (await Promise.all(
|
||||||
discount.regions = (await Promise.all(
|
discount.regions.map(async (regionId) =>
|
||||||
discount.regions.map(async (regionId) =>
|
this.regionService_.withTransaction(manager).retrieve(regionId)
|
||||||
this.regionService_.withTransaction(manager).retrieve(regionId)
|
|
||||||
)
|
|
||||||
)) as Region[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const discountRule = ruleRepo.create(validatedRule)
|
|
||||||
const createdDiscountRule = await ruleRepo.save(discountRule)
|
|
||||||
|
|
||||||
const created: Discount = discountRepo.create(
|
|
||||||
discount as DeepPartial<Discount>
|
|
||||||
)
|
|
||||||
created.rule = createdDiscountRule
|
|
||||||
|
|
||||||
const result = await discountRepo.save(created)
|
|
||||||
|
|
||||||
if (conditions?.length) {
|
|
||||||
await Promise.all(
|
|
||||||
conditions.map(async (cond) => {
|
|
||||||
await this.discountConditionService_
|
|
||||||
.withTransaction(manager)
|
|
||||||
.upsertCondition({ rule_id: result.rule_id, ...cond })
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
}
|
)) as Region[]
|
||||||
|
|
||||||
return result
|
|
||||||
} catch (error) {
|
|
||||||
throw formatException(error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const discountRule = ruleRepo.create(validatedRule)
|
||||||
|
const createdDiscountRule = await ruleRepo.save(discountRule)
|
||||||
|
|
||||||
|
const created: Discount = discountRepo.create(
|
||||||
|
discount as DeepPartial<Discount>
|
||||||
|
)
|
||||||
|
created.rule = createdDiscountRule
|
||||||
|
|
||||||
|
const result = await discountRepo.save(created)
|
||||||
|
|
||||||
|
if (conditions?.length) {
|
||||||
|
await Promise.all(
|
||||||
|
conditions.map(async (cond) => {
|
||||||
|
await this.discountConditionService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.upsertCondition({ rule_id: result.rule_id, ...cond })
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
PriceListPriceUpdateInput,
|
PriceListPriceUpdateInput,
|
||||||
UpdatePriceListInput,
|
UpdatePriceListInput,
|
||||||
} from "../types/price-list"
|
} from "../types/price-list"
|
||||||
import { formatException } from "../utils/exception-formatter"
|
|
||||||
import ProductService from "./product"
|
import ProductService from "./product"
|
||||||
import RegionService from "./region"
|
import RegionService from "./region"
|
||||||
import { TransactionBaseService } from "../interfaces"
|
import { TransactionBaseService } from "../interfaces"
|
||||||
@@ -119,40 +118,36 @@ class PriceListService extends TransactionBaseService {
|
|||||||
|
|
||||||
const { prices, customer_groups, includes_tax, ...rest } = priceListObject
|
const { prices, customer_groups, includes_tax, ...rest } = priceListObject
|
||||||
|
|
||||||
try {
|
const rawPriceList: DeepPartial<PriceList> = {
|
||||||
const rawPriceList: DeepPartial<PriceList> = {
|
...rest,
|
||||||
...rest,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
this.featureFlagRouter_.isFeatureEnabled(
|
|
||||||
TaxInclusivePricingFeatureFlag.key
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (typeof includes_tax !== "undefined") {
|
|
||||||
rawPriceList.includes_tax = includes_tax
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const entity = priceListRepo.create(rawPriceList)
|
|
||||||
|
|
||||||
const priceList = await priceListRepo.save(entity)
|
|
||||||
|
|
||||||
if (prices) {
|
|
||||||
const prices_ = await this.addCurrencyFromRegion(prices)
|
|
||||||
await moneyAmountRepo.addPriceListPrices(priceList.id, prices_)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (customer_groups) {
|
|
||||||
await this.upsertCustomerGroups_(priceList.id, customer_groups)
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.retrieve(priceList.id, {
|
|
||||||
relations: ["prices", "customer_groups"],
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
throw formatException(error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.featureFlagRouter_.isFeatureEnabled(
|
||||||
|
TaxInclusivePricingFeatureFlag.key
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (typeof includes_tax !== "undefined") {
|
||||||
|
rawPriceList.includes_tax = includes_tax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const entity = priceListRepo.create(rawPriceList)
|
||||||
|
|
||||||
|
const priceList = await priceListRepo.save(entity)
|
||||||
|
|
||||||
|
if (prices) {
|
||||||
|
const prices_ = await this.addCurrencyFromRegion(prices)
|
||||||
|
await moneyAmountRepo.addPriceListPrices(priceList.id, prices_)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customer_groups) {
|
||||||
|
await this.upsertCustomerGroups_(priceList.id, customer_groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.retrieve(priceList.id, {
|
||||||
|
relations: ["prices", "customer_groups"],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
UpdateProductCollection,
|
UpdateProductCollection,
|
||||||
} from "../types/product-collection"
|
} from "../types/product-collection"
|
||||||
import { buildQuery, isString, setMetadata } from "../utils"
|
import { buildQuery, isString, setMetadata } from "../utils"
|
||||||
import { formatException } from "../utils/exception-formatter"
|
|
||||||
import EventBusService from "./event-bus"
|
import EventBusService from "./event-bus"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -113,12 +112,8 @@ class ProductCollectionService extends TransactionBaseService {
|
|||||||
this.productCollectionRepository_
|
this.productCollectionRepository_
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
const productCollection = collectionRepo.create(collection)
|
||||||
const productCollection = collectionRepo.create(collection)
|
return await collectionRepo.save(productCollection)
|
||||||
return await collectionRepo.save(productCollection)
|
|
||||||
} catch (error) {
|
|
||||||
throw formatException(error)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,17 +178,13 @@ class ProductCollectionService extends TransactionBaseService {
|
|||||||
return await this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const productRepo = manager.getCustomRepository(this.productRepository_)
|
const productRepo = manager.getCustomRepository(this.productRepository_)
|
||||||
|
|
||||||
try {
|
const { id } = await this.retrieve(collectionId, { select: ["id"] })
|
||||||
const { id } = await this.retrieve(collectionId, { select: ["id"] })
|
|
||||||
|
|
||||||
await productRepo.bulkAddToCollection(productIds, id)
|
await productRepo.bulkAddToCollection(productIds, id)
|
||||||
|
|
||||||
return await this.retrieve(id, {
|
return await this.retrieve(id, {
|
||||||
relations: ["products"],
|
relations: ["products"],
|
||||||
})
|
})
|
||||||
} catch (error) {
|
|
||||||
throw formatException(error)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import {
|
|||||||
UpdateProductInput,
|
UpdateProductInput,
|
||||||
} from "../types/product"
|
} from "../types/product"
|
||||||
import { buildQuery, isDefined, setMetadata } from "../utils"
|
import { buildQuery, isDefined, setMetadata } from "../utils"
|
||||||
import { formatException } from "../utils/exception-formatter"
|
|
||||||
import EventBusService from "./event-bus"
|
import EventBusService from "./event-bus"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -362,61 +361,57 @@ class ProductService extends TransactionBaseService {
|
|||||||
rest.discountable = false
|
rest.discountable = false
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
let product = productRepo.create(rest)
|
||||||
let product = productRepo.create(rest)
|
|
||||||
|
|
||||||
if (images?.length) {
|
if (images?.length) {
|
||||||
product.images = await imageRepo.upsertImages(images)
|
product.images = await imageRepo.upsertImages(images)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tags?.length) {
|
if (tags?.length) {
|
||||||
product.tags = await productTagRepo.upsertTags(tags)
|
product.tags = await productTagRepo.upsertTags(tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof type !== `undefined`) {
|
if (typeof type !== `undefined`) {
|
||||||
product.type_id = (await productTypeRepo.upsertType(type))?.id || null
|
product.type_id = (await productTypeRepo.upsertType(type))?.id || null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.featureFlagRouter_.isFeatureEnabled(SalesChannelFeatureFlag.key)
|
this.featureFlagRouter_.isFeatureEnabled(SalesChannelFeatureFlag.key)
|
||||||
) {
|
) {
|
||||||
if (isDefined(salesChannels)) {
|
if (isDefined(salesChannels)) {
|
||||||
product.sales_channels = []
|
product.sales_channels = []
|
||||||
if (salesChannels?.length) {
|
if (salesChannels?.length) {
|
||||||
const salesChannelIds = salesChannels?.map((sc) => sc.id)
|
const salesChannelIds = salesChannels?.map((sc) => sc.id)
|
||||||
product.sales_channels = salesChannelIds?.map(
|
product.sales_channels = salesChannelIds?.map(
|
||||||
(id) => ({ id } as SalesChannel)
|
(id) => ({ id } as SalesChannel)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
product = await productRepo.save(product)
|
|
||||||
|
|
||||||
product.options = await Promise.all(
|
|
||||||
(options ?? []).map(async (option) => {
|
|
||||||
const res = optionRepo.create({
|
|
||||||
...option,
|
|
||||||
product_id: product.id,
|
|
||||||
})
|
|
||||||
await optionRepo.save(res)
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const result = await this.retrieve(product.id, {
|
|
||||||
relations: ["options"],
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.eventBus_
|
|
||||||
.withTransaction(manager)
|
|
||||||
.emit(ProductService.Events.CREATED, {
|
|
||||||
id: result.id,
|
|
||||||
})
|
|
||||||
return result
|
|
||||||
} catch (error) {
|
|
||||||
throw formatException(error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
product = await productRepo.save(product)
|
||||||
|
|
||||||
|
product.options = await Promise.all(
|
||||||
|
(options ?? []).map(async (option) => {
|
||||||
|
const res = optionRepo.create({
|
||||||
|
...option,
|
||||||
|
product_id: product.id,
|
||||||
|
})
|
||||||
|
await optionRepo.save(res)
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const result = await this.retrieve(product.id, {
|
||||||
|
relations: ["options"],
|
||||||
|
})
|
||||||
|
|
||||||
|
await this.eventBus_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.emit(ProductService.Events.CREATED, {
|
||||||
|
id: result.id,
|
||||||
|
})
|
||||||
|
return result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export enum PostgresError {
|
|||||||
DUPLICATE_ERROR = "23505",
|
DUPLICATE_ERROR = "23505",
|
||||||
FOREIGN_KEY_ERROR = "23503",
|
FOREIGN_KEY_ERROR = "23503",
|
||||||
}
|
}
|
||||||
export const formatException = (err): Error => {
|
export const formatException = (err): MedusaError => {
|
||||||
switch (err.code) {
|
switch (err.code) {
|
||||||
case PostgresError.DUPLICATE_ERROR:
|
case PostgresError.DUPLICATE_ERROR:
|
||||||
return new MedusaError(
|
return new MedusaError(
|
||||||
|
|||||||
Reference in New Issue
Block a user