diff --git a/packages/reflection/src/TsMorphMetadataProvider.ts b/packages/reflection/src/TsMorphMetadataProvider.ts index 377c89eefd41..7343a266af96 100644 --- a/packages/reflection/src/TsMorphMetadataProvider.ts +++ b/packages/reflection/src/TsMorphMetadataProvider.ts @@ -1,7 +1,7 @@ import type { PropertyDeclaration, SourceFile } from 'ts-morph'; -import { Project, ModuleKind } from 'ts-morph'; +import { ModuleKind, Project } from 'ts-morph'; import type { EntityMetadata, EntityProperty } from '@mikro-orm/core'; -import { MetadataError, MetadataProvider, MetadataStorage, Utils } from '@mikro-orm/core'; +import { MetadataError, MetadataProvider, MetadataStorage, ReferenceType, Utils } from '@mikro-orm/core'; export class TsMorphMetadataProvider extends MetadataProvider { @@ -123,7 +123,7 @@ export class TsMorphMetadataProvider extends MetadataProvider { .replace(/\((.*)\)/, '$1'); // unwrap union types // keep the array suffix in the type, it is needed in few places in discovery and comparator (`prop.array` is used only for enum arrays) - if (prop.array && !type.includes(' | ')) { + if (prop.array && !type.includes(' | ') && prop.reference === ReferenceType.SCALAR) { type += '[]'; } diff --git a/tests/features/embeddables/GH3690.test.ts b/tests/features/embeddables/GH3690.test.ts new file mode 100644 index 000000000000..8645d0ab6de2 --- /dev/null +++ b/tests/features/embeddables/GH3690.test.ts @@ -0,0 +1,68 @@ +import { Embeddable, Embedded, Entity, PrimaryKey, Property, OneToOne, Ref } from '@mikro-orm/core'; +import { MikroORM } from '@mikro-orm/sqlite'; +import { TsMorphMetadataProvider } from '@mikro-orm/reflection'; + +@Embeddable() +export class PTE { + + @Property() + name!: string; + +} + +@Entity() +export class BPE { + + @PrimaryKey() + id!: number; + + @Embedded({ object: true }) + titles!: PTE[]; + + @OneToOne(() => P, p => p.bp, { orphanRemoval: true }) + p!: Ref

| null; + +} + +@Entity() +export class P { + + @PrimaryKey() + id!: number; + + @OneToOne(() => BPE, { orphanRemoval: true }) + bp!: Ref | null; + +} + +let orm: MikroORM; + +beforeAll(async () => { + orm = await MikroORM.init({ + entities: [P, PTE], + dbName: ':memory:', + metadataProvider: TsMorphMetadataProvider, + cache: { enabled: false }, + }); + await orm.schema.createSchema(); +}); + +afterAll(async () => { + await orm.close(true); +}); + +test('GH issue 3690', async () => { + const e = orm.em.create(P, { + bp: { + titles: [{ name: 't1' }, { name: 't2' }], + }, + }); + await orm.em.flush(); + orm.em.clear(); + + const e1 = await orm.em.findOneOrFail(P, e, { populate: ['bp'] }); + expect(e1.bp?.$.titles).toEqual([ + { name: 't1' }, + { name: 't2' }, + ]); +});