fix(utils): Mikro orm prop filtering should check existence (#6842)

**What**
- Should return non decorated but visible properties.
- Should only prevent circular on non scalar fields
This commit is contained in:
Adrien de Peretti
2024-03-27 14:31:26 +00:00
committed by GitHub
parent e0b02a1012
commit 5d9aea053c
6 changed files with 108 additions and 23 deletions
@@ -229,6 +229,57 @@ class InternalCircularDependencyEntity1 {
parent: InternalCircularDependencyEntity1
}
// With un decorated prop
@Entity()
class Entity1WithUnDecoratedProp {
constructor(props: { id: string; deleted_at: Date | null }) {
this.id = props.id
this.deleted_at = props.deleted_at
}
unknownProp: string
@PrimaryKey()
id: string
@Property()
deleted_at: Date | null
@OneToMany(() => Entity2WithUnDecoratedProp, (entity2) => entity2.entity1, {
cascade: ["soft-remove"] as any,
})
entity2 = new Collection<Entity2WithUnDecoratedProp>(this)
}
@Entity()
class Entity2WithUnDecoratedProp {
constructor(props: {
id: string
deleted_at: Date | null
entity1: Entity1WithUnDecoratedProp
}) {
this.id = props.id
this.deleted_at = props.deleted_at
this.entity1 = props.entity1
this.entity1_id = props.entity1.id
}
unknownProp: string
@PrimaryKey()
id: string
@Property()
deleted_at: Date | null
@ManyToOne(() => Entity1WithUnDecoratedProp, { mapToPk: true })
entity1_id: string
@ManyToOne(() => Entity1WithUnDecoratedProp, { persist: false })
entity1: Entity1WithUnDecoratedProp
}
export {
RecursiveEntity1,
RecursiveEntity2,
@@ -239,4 +290,6 @@ export {
DeepRecursiveEntity3,
DeepRecursiveEntity4,
InternalCircularDependencyEntity1,
Entity1WithUnDecoratedProp,
Entity2WithUnDecoratedProp,
}
@@ -1,19 +1,27 @@
import { MikroORM } from "@mikro-orm/core"
import { Entity1, Entity2 } from "../__fixtures__/utils"
import {
Entity1WithUnDecoratedProp,
Entity2WithUnDecoratedProp,
} from "../__fixtures__/utils"
import { mikroOrmSerializer } from "../mikro-orm-serializer"
describe("mikroOrmSerializer", () => {
beforeEach(async () => {
await MikroORM.init({
entities: [Entity1, Entity2],
entities: [Entity1WithUnDecoratedProp, Entity2WithUnDecoratedProp],
dbName: "test",
type: "postgresql",
})
})
it("should serialize an entity", async () => {
const entity1 = new Entity1({ id: "1", deleted_at: null })
const entity2 = new Entity2({
const entity1 = new Entity1WithUnDecoratedProp({
id: "1",
deleted_at: null,
})
entity1.unknownProp = "calculated"
const entity2 = new Entity2WithUnDecoratedProp({
id: "2",
deleted_at: null,
entity1: entity1,
@@ -27,6 +35,7 @@ describe("mikroOrmSerializer", () => {
expect(serialized).toEqual({
id: "1",
deleted_at: null,
unknownProp: "calculated",
entity2: [
{
id: "2",
@@ -34,6 +43,7 @@ describe("mikroOrmSerializer", () => {
entity1: {
id: "1",
deleted_at: null,
unknownProp: "calculated",
},
entity1_id: "1",
},
@@ -42,8 +52,13 @@ describe("mikroOrmSerializer", () => {
})
it("should serialize an array of entities", async () => {
const entity1 = new Entity1({ id: "1", deleted_at: null })
const entity2 = new Entity2({
const entity1 = new Entity1WithUnDecoratedProp({
id: "1",
deleted_at: null,
})
entity1.unknownProp = "calculated"
const entity2 = new Entity2WithUnDecoratedProp({
id: "2",
deleted_at: null,
entity1: entity1,
@@ -57,6 +72,7 @@ describe("mikroOrmSerializer", () => {
const expectation = {
id: "1",
deleted_at: null,
unknownProp: "calculated",
entity2: [
{
id: "2",
@@ -64,6 +80,7 @@ describe("mikroOrmSerializer", () => {
entity1: {
id: "1",
deleted_at: null,
unknownProp: "calculated",
},
entity1_id: "1",
},
@@ -74,8 +91,13 @@ describe("mikroOrmSerializer", () => {
})
it("should serialize an entity preventing circular relation reference", async () => {
const entity1 = new Entity1({ id: "1", deleted_at: null })
const entity2 = new Entity2({
const entity1 = new Entity1WithUnDecoratedProp({
id: "1",
deleted_at: null,
})
entity1.unknownProp = "calculated"
const entity2 = new Entity2WithUnDecoratedProp({
id: "2",
deleted_at: null,
entity1: entity1,
@@ -87,6 +109,7 @@ describe("mikroOrmSerializer", () => {
expect(serialized).toEqual({
id: "1",
deleted_at: null,
unknownProp: "calculated",
entity2: [
{
id: "2",
@@ -65,26 +65,32 @@ function isPopulated<T extends object>(
/**
* Customer property filtering for the serialization which takes into account the parent entity to filter out circular references if configured for.
* @param prop
* @param propName
* @param meta
* @param options
* @param parent
*/
function filterEntityPropToSerialize(
prop: string,
propName: string,
meta: EntityMetadata,
options: SerializeOptions<object, any> & {
preventCircularRef?: boolean
} = {},
parent?: object
): boolean {
const isVisibleRes = isVisible(meta, prop, options)
if (options.preventCircularRef && isVisibleRes && parent) {
return (
// mapToPk would represent a foreign key and we want to keep them
meta.properties[prop].mapToPk ||
parent.constructor.name !== meta.properties[prop].type
)
const isVisibleRes = isVisible(meta, propName, options)
const prop = meta.properties[propName]
// Only prevent circular references if prop is a relation
if (
prop &&
options.preventCircularRef &&
isVisibleRes &&
parent &&
prop.reference !== ReferenceType.SCALAR
) {
// mapToPk would represent a foreign key and we want to keep them
return !!prop.mapToPk || parent.constructor.name !== prop.type
}
return isVisibleRes
}