UNPKG

undeexcepturi

Version:

TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.

180 lines (142 loc) 4.31 kB
import { v4, parse, stringify } from 'uuid'; import { Entity, LoadStrategy, ManyToOne, MikroORM, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Type, wrap, } from '@mikro-orm/core'; import { MySqlDriver } from '@mikro-orm/mysql'; import { mockLogger } from '../../helpers'; export class UuidBinaryType extends Type<string, Buffer> { override convertToDatabaseValue(value: string): Buffer { return Buffer.from(parse(value)); } override convertToJSValue(value: Buffer): string { return stringify(value); } override getColumnType(): string { return 'binary(16)'; } } @Entity() class A { @PrimaryKey({ type: UuidBinaryType }) id: string = v4(); @Property({ nullable: true }) name?: string; } @Entity() class B { @OneToOne({ primary: true }) a!: A; [PrimaryKeyProp]?: 'a'; } @Entity() class C { @OneToOne({ primary: true }) b!: B; [PrimaryKeyProp]?: 'b'; } @Entity() class D { @PrimaryKey({ type: UuidBinaryType }) id: string = v4(); @ManyToOne({ deleteRule: 'cascade' }) a!: A; } describe('GH issue 446', () => { let orm: MikroORM<MySqlDriver>; beforeAll(async () => { orm = await MikroORM.init({ entities: [A, B, C, D], dbName: `mikro_orm_test_gh_446`, driver: MySqlDriver, port: 3308, }); await orm.schema.refreshDatabase(); }); afterAll(async () => { await orm.close(true); }); afterEach(async () => { await orm.em.nativeDelete(A, {}); }); test(`chaining primary key column type`, async () => { const a = new A(); const b = new B(); b.a = a; const c = new C(); c.b = b; const d = new D(); d.a = a; await orm.em.persistAndFlush([c, d]); orm.em.clear(); const c1 = await orm.em.findOneOrFail(C, c.b.a.id, { populate: ['b.a'] }); const mock = mockLogger(orm); const c23 = await orm.em.findOneOrFail(C, c.b.a.id); expect(mock).not.toHaveBeenCalled(); expect(c1).toBe(c23); expect(c1).toBeInstanceOf(C); expect(c1.b).toBeInstanceOf(B); expect(wrap(c1.b).isInitialized()).toBe(true); expect(c1.b.a).toBeInstanceOf(A); expect(wrap(c1.b.a).isInitialized()).toBe(true); expect(c1.b.a.id).toBe(a.id); orm.em.clear(); const c2 = await orm.em.findOneOrFail(C, c.b.a.id, { populate: ['b.a'], strategy: LoadStrategy.JOINED }); expect(c2).toBeInstanceOf(C); expect(c2.b).toBeInstanceOf(B); expect(wrap(c2.b).isInitialized()).toBe(true); expect(c2.b.a).toBeInstanceOf(A); expect(wrap(c2.b.a).isInitialized()).toBe(true); expect(c2.b.a.id).toBe(a.id); }); test(`update entity with custom type PK (GH #1798)`, async () => { const a1 = orm.em.create(A, { name: 'a1' }); const a2 = orm.em.create(A, { name: 'a2' }); await orm.em.persist([a1, a2]).flush(); a1.name = 'a1 v2'; await orm.em.flush(); a1.name = 'a1 v3'; a2.name = 'a2 v3'; await orm.em.flush(); orm.em.clear(); const as = await orm.em.find(A, {}, { orderBy: { name: 1 } }); expect(as.map(a => a.name)).toEqual(['a1 v3', 'a2 v3']); as.forEach(a => orm.em.remove(a)); await orm.em.flush(); orm.em.clear(); const count = await orm.em.count(A, {}); expect(count).toBe(0); }); test(`assign with custom types`, async () => { const d = new D(); orm.em.assign(d, { id: Buffer.from(parse(v4())) as any, a: Buffer.from(parse(v4())) as any }, { convertCustomTypes: true }); expect(typeof d.id).toBe('string'); expect(typeof d.a.id).toBe('string'); orm.em.assign(d, { id: v4(), a: v4() }); expect(typeof d.id).toBe('string'); expect(typeof d.a.id).toBe('string'); orm.em.assign(d, { id: v4(), a: { id: v4(), name: 'abc' } }); expect(typeof d.id).toBe('string'); expect(typeof d.a.id).toBe('string'); expect(d.a.name).toBe('abc'); }); test('merging cached entity', async () => { const a1 = new A(); a1.name = 'test'; expect(typeof a1.id).toBe('string'); // simulate caching by converting to JSON and back to POJO const cache = JSON.parse(JSON.stringify(wrap(a1).toObject())); expect(typeof cache.id).toBe('string'); const a2 = orm.em.getRepository(A).merge(cache); expect(typeof a2.id).toBe('string'); expect(a2.name).toBe('test'); }); });