feat: Improve how options are defined and handled for product (#7007)
* feat: Improve how options are defined and handled for product * fix: Updating option values supports passing without id
This commit is contained in:
@@ -13,7 +13,10 @@ export const dbErrorMapper = (err: Error) => {
|
||||
throw new MedusaError(MedusaError.Types.NOT_FOUND, err.message)
|
||||
}
|
||||
|
||||
if (err instanceof UniqueConstraintViolationException) {
|
||||
if (
|
||||
err instanceof UniqueConstraintViolationException ||
|
||||
(err as any).code === "23505"
|
||||
) {
|
||||
const info = getConstraintInfo(err)
|
||||
if (!info) {
|
||||
throw err
|
||||
@@ -27,7 +30,10 @@ export const dbErrorMapper = (err: Error) => {
|
||||
)
|
||||
}
|
||||
|
||||
if (err instanceof NotNullConstraintViolationException) {
|
||||
if (
|
||||
err instanceof NotNullConstraintViolationException ||
|
||||
(err as any).code === "23502"
|
||||
) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Cannot set field '${(err as any).column}' of ${upperCaseFirst(
|
||||
@@ -36,7 +42,10 @@ export const dbErrorMapper = (err: Error) => {
|
||||
)
|
||||
}
|
||||
|
||||
if (err instanceof InvalidFieldNameException) {
|
||||
if (
|
||||
err instanceof InvalidFieldNameException ||
|
||||
(err as any).code === "42703"
|
||||
) {
|
||||
const userFriendlyMessage = err.message.match(/(column.*)/)?.[0]
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
@@ -44,7 +53,10 @@ export const dbErrorMapper = (err: Error) => {
|
||||
)
|
||||
}
|
||||
|
||||
if (err instanceof ForeignKeyConstraintViolationException) {
|
||||
if (
|
||||
err instanceof ForeignKeyConstraintViolationException ||
|
||||
(err as any).code === "23503"
|
||||
) {
|
||||
const info = getConstraintInfo(err)
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
|
||||
@@ -656,8 +656,7 @@ describe("mikroOrmRepository", () => {
|
||||
expect(listedEntities[0].entity3.getItems()).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
// title: "en3-1",
|
||||
title: "newen3-1",
|
||||
title: "en3-1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "en3-4",
|
||||
@@ -744,8 +743,7 @@ describe("mikroOrmRepository", () => {
|
||||
expect(listedEntities[0].entity3.getItems()).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
// title: "en3-1",
|
||||
title: "newen3-1",
|
||||
title: "en3-1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: "en3-4",
|
||||
@@ -817,31 +815,34 @@ describe("mikroOrmRepository", () => {
|
||||
)
|
||||
})
|
||||
|
||||
// it("should correctly handle many-to-many upserts with a uniqueness constriant on a non-primary key", async () => {
|
||||
// const entity1 = {
|
||||
// id: "1",
|
||||
// title: "en1",
|
||||
// entity3: [{ title: "en3-1" }, { title: "en3-2" }] as any,
|
||||
// }
|
||||
it("should correctly handle many-to-many upserts with a uniqueness constriant on a non-primary key", async () => {
|
||||
const entity1 = {
|
||||
id: "1",
|
||||
title: "en1",
|
||||
entity3: [
|
||||
{ id: "4", title: "en3-1" },
|
||||
{ id: "5", title: "en3-2" },
|
||||
] as any,
|
||||
}
|
||||
|
||||
// await manager1().upsertWithReplace([entity1], {
|
||||
// relations: ["entity3"],
|
||||
// })
|
||||
await manager1().upsertWithReplace([entity1], {
|
||||
relations: ["entity3"],
|
||||
})
|
||||
|
||||
// await manager1().upsertWithReplace([{ ...entity1, id: "2" }], {
|
||||
// relations: ["entity3"],
|
||||
// })
|
||||
await manager1().upsertWithReplace([{ ...entity1, id: "2" }], {
|
||||
relations: ["entity3"],
|
||||
})
|
||||
|
||||
// const listedEntities = await manager1().find({
|
||||
// where: {},
|
||||
// options: { populate: ["entity3"] },
|
||||
// })
|
||||
const listedEntities = await manager1().find({
|
||||
where: {},
|
||||
options: { populate: ["entity3"] },
|
||||
})
|
||||
|
||||
// expect(listedEntities).toHaveLength(2)
|
||||
// expect(listedEntities[0].entity3.getItems()).toEqual(
|
||||
// listedEntities[1].entity3.getItems()
|
||||
// )
|
||||
// })
|
||||
expect(listedEntities).toHaveLength(2)
|
||||
expect(listedEntities[0].entity3.getItems()).toEqual(
|
||||
listedEntities[1].entity3.getItems()
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("error mapping", () => {
|
||||
|
||||
@@ -602,8 +602,7 @@ export function mikroOrmBaseRepositoryFactory<T extends object = object>(
|
||||
return normalizedData
|
||||
}
|
||||
|
||||
// TODO: Currently we will also do an update of the data on the other side of the many-to-many relationship. Reevaluate if we should avoid that.
|
||||
await this.upsertMany_(manager, relation.type, normalizedData)
|
||||
await this.upsertMany_(manager, relation.type, normalizedData, true)
|
||||
|
||||
const pivotData = normalizedData.map((currModel) => {
|
||||
return {
|
||||
@@ -721,39 +720,17 @@ export function mikroOrmBaseRepositoryFactory<T extends object = object>(
|
||||
return { id: (created as any).id, ...data }
|
||||
}
|
||||
|
||||
protected async upsertManyToOneRelations_(
|
||||
manager: SqlEntityManager,
|
||||
upsertsPerType: Record<string, any[]>
|
||||
) {
|
||||
const typesToUpsert = Object.entries(upsertsPerType)
|
||||
if (!typesToUpsert.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
return (
|
||||
await promiseAll(
|
||||
typesToUpsert.map(([type, data]) => {
|
||||
return this.upsertMany_(manager, type, data)
|
||||
})
|
||||
)
|
||||
).flat()
|
||||
}
|
||||
|
||||
protected async upsertMany_(
|
||||
manager: SqlEntityManager,
|
||||
entityName: string,
|
||||
entries: any[]
|
||||
entries: any[],
|
||||
skipUpdate: boolean = false
|
||||
) {
|
||||
const existingEntities: any[] = await manager.find(
|
||||
entityName,
|
||||
{
|
||||
id: { $in: entries.map((d) => d.id) },
|
||||
},
|
||||
{
|
||||
populate: [],
|
||||
disableIdentityMap: true,
|
||||
}
|
||||
)
|
||||
const selectQb = manager.qb(entityName)
|
||||
const existingEntities: any[] = await selectQb.select("*").where({
|
||||
id: { $in: entries.map((d) => d.id) },
|
||||
})
|
||||
|
||||
const existingEntitiesMap = new Map(
|
||||
existingEntities.map((e) => [e.id, e])
|
||||
)
|
||||
@@ -762,12 +739,21 @@ export function mikroOrmBaseRepositoryFactory<T extends object = object>(
|
||||
|
||||
await promiseAll(
|
||||
entries.map(async (data) => {
|
||||
orderedEntities.push(data)
|
||||
const existingEntity = existingEntitiesMap.get(data.id)
|
||||
orderedEntities.push(data)
|
||||
if (existingEntity) {
|
||||
if (skipUpdate) {
|
||||
return
|
||||
}
|
||||
await manager.nativeUpdate(entityName, { id: data.id }, data)
|
||||
} else {
|
||||
await manager.insert(entityName, data)
|
||||
const qb = manager.qb(entityName)
|
||||
if (skipUpdate) {
|
||||
await qb.insert(data).onConflict().ignore().execute()
|
||||
} else {
|
||||
await manager.insert(entityName, data)
|
||||
// await manager.insert(entityName, data)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user