fix: Remove extra saving on serialization which breaks the chain (#9465)
**What** The extra serialization check hapen to break the serialization chain by reusing already serialized entities when they have been serialized from a different parents sequence
This commit is contained in:
committed by
GitHub
parent
cc77ca1413
commit
ffc35f2b6e
@@ -1,6 +1,8 @@
|
||||
import {
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryKey,
|
||||
@@ -9,6 +11,104 @@ import {
|
||||
} from "@mikro-orm/core"
|
||||
import { Searchable } from "../decorators/searchable"
|
||||
|
||||
@Entity()
|
||||
class Product {
|
||||
@PrimaryKey()
|
||||
id: string
|
||||
|
||||
@Property()
|
||||
name: string
|
||||
|
||||
@OneToMany(() => ProductOption, (o) => o.product, {
|
||||
cascade: ["soft-remove"] as any,
|
||||
})
|
||||
options = new Collection<ProductOption>(this)
|
||||
|
||||
@OneToMany(() => ProductVariant, (variant) => variant.product, {
|
||||
cascade: ["soft-remove"] as any,
|
||||
})
|
||||
variants = new Collection<ProductVariant>(this)
|
||||
}
|
||||
|
||||
@Entity()
|
||||
class ProductOption {
|
||||
@PrimaryKey()
|
||||
id: string
|
||||
|
||||
@Property()
|
||||
name: string
|
||||
|
||||
@ManyToOne(() => Product, {
|
||||
persist: false,
|
||||
nullable: true,
|
||||
})
|
||||
product: Product | null
|
||||
|
||||
@OneToMany(() => ProductOptionValue, (value) => value.option, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove" as any],
|
||||
})
|
||||
values = new Collection<ProductOptionValue>(this)
|
||||
}
|
||||
|
||||
@Entity()
|
||||
class ProductOptionValue {
|
||||
@PrimaryKey()
|
||||
id: string
|
||||
|
||||
@Property()
|
||||
name: string
|
||||
|
||||
@ManyToOne(() => ProductOption, {
|
||||
columnType: "text",
|
||||
fieldName: "option_id",
|
||||
mapToPk: true,
|
||||
nullable: true,
|
||||
onDelete: "cascade",
|
||||
})
|
||||
option_id: string | null
|
||||
|
||||
@ManyToOne(() => ProductOption, {
|
||||
nullable: true,
|
||||
persist: false,
|
||||
})
|
||||
option: ProductOption | null
|
||||
|
||||
@ManyToMany(() => ProductVariant, (variant) => variant.options)
|
||||
variants = new Collection<ProductVariant>(this)
|
||||
}
|
||||
|
||||
@Entity()
|
||||
class ProductVariant {
|
||||
@PrimaryKey()
|
||||
id: string
|
||||
|
||||
@Property()
|
||||
name: string
|
||||
|
||||
@ManyToOne(() => Product, {
|
||||
columnType: "text",
|
||||
nullable: true,
|
||||
onDelete: "cascade",
|
||||
fieldName: "product_id",
|
||||
mapToPk: true,
|
||||
})
|
||||
product_id: string | null
|
||||
|
||||
@ManyToOne(() => Product, {
|
||||
persist: false,
|
||||
nullable: true,
|
||||
})
|
||||
product: Product | null
|
||||
|
||||
@ManyToMany(() => ProductOptionValue, "variants", {
|
||||
owner: true,
|
||||
pivotTable: "product_variant_option",
|
||||
joinColumn: "variant_id",
|
||||
inverseJoinColumn: "option_value_id",
|
||||
})
|
||||
options = new Collection<ProductOptionValue>(this)
|
||||
}
|
||||
|
||||
// Circular dependency one level
|
||||
@Entity()
|
||||
class RecursiveEntity1 {
|
||||
@@ -114,6 +214,11 @@ class DeepRecursiveEntity1 {
|
||||
@Property({ nullable: true })
|
||||
deleted_at: Date | null
|
||||
|
||||
@OneToMany(() => DeepRecursiveEntity3, (entity3) => entity3.entity1, {
|
||||
cascade: ["soft-remove"] as any,
|
||||
})
|
||||
entity3 = new Collection<DeepRecursiveEntity3>(this)
|
||||
|
||||
@OneToMany(() => DeepRecursiveEntity2, (entity2) => entity2.entity1, {
|
||||
cascade: ["soft-remove"] as any,
|
||||
})
|
||||
@@ -349,4 +454,8 @@ export {
|
||||
RecursiveEntity2,
|
||||
SearchableEntity1,
|
||||
SearchableEntity2,
|
||||
Product,
|
||||
ProductOption,
|
||||
ProductOptionValue,
|
||||
ProductVariant,
|
||||
}
|
||||
|
||||
@@ -2,13 +2,24 @@ import { MikroORM } from "@mikro-orm/core"
|
||||
import {
|
||||
Entity1WithUnDecoratedProp,
|
||||
Entity2WithUnDecoratedProp,
|
||||
Product,
|
||||
ProductOption,
|
||||
ProductOptionValue,
|
||||
ProductVariant,
|
||||
} from "../__fixtures__/utils"
|
||||
import { mikroOrmSerializer } from "../mikro-orm-serializer"
|
||||
|
||||
describe("mikroOrmSerializer", () => {
|
||||
beforeEach(async () => {
|
||||
await MikroORM.init({
|
||||
entities: [Entity1WithUnDecoratedProp, Entity2WithUnDecoratedProp],
|
||||
entities: [
|
||||
Entity1WithUnDecoratedProp,
|
||||
Entity2WithUnDecoratedProp,
|
||||
Product,
|
||||
ProductOption,
|
||||
ProductOptionValue,
|
||||
ProductVariant,
|
||||
],
|
||||
dbName: "test",
|
||||
type: "postgresql",
|
||||
})
|
||||
@@ -119,4 +130,70 @@ describe("mikroOrmSerializer", () => {
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it(`should properly serialize nested relations and sibling to not return parents into children`, async () => {
|
||||
const productOptionValue = new ProductOptionValue()
|
||||
productOptionValue.id = "1"
|
||||
productOptionValue.name = "Product option value 1"
|
||||
productOptionValue.option_id = "1"
|
||||
|
||||
const productOptions = new ProductOption()
|
||||
productOptions.id = "1"
|
||||
productOptions.name = "Product option 1"
|
||||
productOptions.values.add(productOptionValue)
|
||||
|
||||
const productVariant = new ProductVariant()
|
||||
productVariant.id = "1"
|
||||
productVariant.name = "Product variant 1"
|
||||
productVariant.options.add(productOptionValue)
|
||||
|
||||
const product = new Product()
|
||||
product.id = "1"
|
||||
product.name = "Product 1"
|
||||
product.options.add(productOptions)
|
||||
product.variants.add(productVariant)
|
||||
|
||||
const serialized = await mikroOrmSerializer(product)
|
||||
|
||||
expect(serialized).toEqual({
|
||||
id: "1",
|
||||
options: [
|
||||
{
|
||||
id: "1",
|
||||
values: [
|
||||
{
|
||||
id: "1",
|
||||
variants: [
|
||||
{
|
||||
id: "1",
|
||||
name: "Product variant 1",
|
||||
},
|
||||
],
|
||||
name: "Product option value 1",
|
||||
option_id: "1",
|
||||
},
|
||||
],
|
||||
name: "Product option 1",
|
||||
},
|
||||
],
|
||||
variants: [
|
||||
{
|
||||
id: "1",
|
||||
options: [
|
||||
{
|
||||
id: "1",
|
||||
name: "Product option value 1",
|
||||
option_id: "1",
|
||||
option: {
|
||||
id: "1",
|
||||
name: "Product option 1",
|
||||
},
|
||||
},
|
||||
],
|
||||
name: "Product variant 1",
|
||||
},
|
||||
],
|
||||
name: "Product 1",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -142,16 +142,6 @@ export class EntitySerializer {
|
||||
root.visited.add(entity)
|
||||
}
|
||||
|
||||
// Virtually augment the serialization context
|
||||
root.visitedSerialized ??= new Map()
|
||||
const primaryKeysValues = Array.from(keys)
|
||||
.map((key) => entity[key])
|
||||
.join("-")
|
||||
|
||||
if (root.visitedSerialized.has(primaryKeysValues)) {
|
||||
return root.visitedSerialized.get(primaryKeysValues)
|
||||
}
|
||||
|
||||
;[...keys]
|
||||
/** Medusa Custom properties filtering **/
|
||||
.filter((prop) =>
|
||||
@@ -242,7 +232,7 @@ export class EntitySerializer {
|
||||
parents_
|
||||
))
|
||||
)
|
||||
root.visitedSerialized.set(primaryKeysValues, ret)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user