From ec00a0d54855d542585413134eaf49dcb6c28b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C6=B0=C6=A1ng=20T=E1=BA=A5n=20Hu=E1=BB=B3nh=20Phong?= Date: Mon, 22 Jan 2024 19:27:35 +0700 Subject: [PATCH] fix(mikro): infinite loop when using OneToOne eager loading (#546) * fix(mikro): infinite loop when using OneToOne eager loading * fix(mikro): mapping custom property of mikro entity to automapper --- packages/mikro/src/lib/serialize-entity.ts | 30 ++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/packages/mikro/src/lib/serialize-entity.ts b/packages/mikro/src/lib/serialize-entity.ts index c76e576b5..ed7f78bcc 100644 --- a/packages/mikro/src/lib/serialize-entity.ts +++ b/packages/mikro/src/lib/serialize-entity.ts @@ -1,6 +1,7 @@ import { isEmpty } from '@automapper/core'; import type { AnyEntity } from '@mikro-orm/core'; import { Reference, Utils, wrap } from '@mikro-orm/core'; +import type { IWrappedEntityInternal } from '@mikro-orm/core/typings'; const excluded = [ '__gettersDefined', @@ -14,13 +15,16 @@ const excluded = [ export function serializeEntity( item: AnyEntity, itemMetadata: Record | undefined, - toPojo = false + toPojo = false, + memorized = new Map>, + skipCheckExisting = false ) { if (!Utils.isEntity(item)) return item; if (toPojo) return wrap(item).toPOJO(); const result = {} as Record; - for (const key of Reflect.ownKeys(item)) { + const keys = Object.keys((wrap(item) as IWrappedEntityInternal).__meta.properties); + for (const key of keys) { if (typeof key === 'symbol' || excluded.includes(key)) { continue; } @@ -33,6 +37,8 @@ export function serializeEntity( return serializeEntity( snapshot as AnyEntity, keyMetadata, + true, + memorized, true ); }); @@ -40,23 +46,37 @@ export function serializeEntity( } if (Reference.isReference(value)) { + const isExisting = memorized.has(value); + + if (!skipCheckExisting && isExisting) { + result[key] = memorized.get(value); + continue; + } + if (!value.isInitialized()) { + memorized.set(value, wrap(value).toPOJO()); result[key] = serializeEntity( wrap(value).toPOJO(), - keyMetadata + keyMetadata, + false, + memorized, + !isExisting ); continue; } + memorized.set(value, value.getEntity() as Record); result[key] = serializeEntity( value.getEntity(), keyMetadata, - typeof keyMetadata === 'object' && isEmpty(keyMetadata) + typeof keyMetadata === 'object' && isEmpty(keyMetadata), + memorized, + !isExisting ); continue; } - result[key] = serializeEntity(value, keyMetadata); + result[key] = serializeEntity(value, keyMetadata, false, memorized, false); } if (result['id'] == null && item['id'] != null) {