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:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user