UNPKG

expeditavoluptas

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.

124 lines (109 loc) 6.6 kB
import { MikroORM } from '@mikro-orm/mongodb'; import type { Options, PrimaryProperty, Cast, IsUnknown, EntityMetadata } from '@mikro-orm/core'; import { Collection as Collection_, Reference as Reference_, ReferenceType, EnumArrayType } from '@mikro-orm/core'; import { TsMorphMetadataProvider } from '@mikro-orm/reflection'; import { Author, Book, Publisher, BaseEntity, BaseEntity3, BookTagSchema, Test, FooBaz } from './entities'; import FooBar from './entities/FooBar'; // we need to define those to get around typescript issues with reflection (ts-morph would return `any` for the type otherwise) export class Collection<T extends object> extends Collection_<T> { } export class Reference<T extends object> extends Reference_<T> { } export type IdentifiedReference<T extends object, PK extends keyof T | unknown = PrimaryProperty<T>> = true extends IsUnknown<PK> ? Reference<T> : ({ [K in Cast<PK, keyof T>]?: T[K] } & Reference<T>); describe('TsMorphMetadataProvider', () => { test('should load TS files directly', async () => { const orm = await MikroORM.init({ entities: [Author, Book, Publisher, BaseEntity, BaseEntity3, BookTagSchema, Test, FooBaz, FooBar], baseDir: __dirname, clientUrl: 'mongodb://localhost:27017/mikro-orm-test', cache: { enabled: false }, discovery: { alwaysAnalyseProperties: false }, metadataProvider: TsMorphMetadataProvider, }); expect(Object.keys(orm.getMetadata().getAll()).sort()).toEqual(['Author', 'Book', 'BookTag', 'FooBar', 'FooBaz', 'Publisher', 'Test']); await orm.close(); }); test('should load entities based on .d.ts files', async () => { const orm = await MikroORM.init({ entities: ['./entities-compiled'], tsNode: false, baseDir: __dirname, clientUrl: 'mongodb://localhost:27017/mikro-orm-test', cache: { enabled: false }, discovery: { alwaysAnalyseProperties: false }, metadataProvider: TsMorphMetadataProvider, }); expect(Object.keys(orm.getMetadata().getAll()).sort()).toEqual(['Author', 'Book', 'BookTag', 'FooBar', 'FooBaz', 'Publisher', 'Test']); await orm.close(); }); test('should throw when .d.ts files missing', async () => { const options: Options = { entities: ['./entities-compiled-error'], entitiesTs: ['./entities-compiled-error'], tsNode: false, baseDir: __dirname, clientUrl: 'mongodb://localhost:27017/mikro-orm-test', cache: { enabled: false }, metadataProvider: TsMorphMetadataProvider, }; const error = `Source file './entities-compiled-error/FooBar.ts' not found. Check your 'entitiesTs' option and verify you have 'compilerOptions.declaration' enabled in your 'tsconfig.json'. If you are using webpack, see https://bit.ly/35pPDNn`; await expect(MikroORM.init(options, false)).rejects.toThrowError(error); }); test('should load entities', async () => { const orm = await MikroORM.init({ entities: ['entities'], baseDir: __dirname, clientUrl: 'mongodb://localhost:27017/mikro-orm-test', cache: { pretty: true }, metadataProvider: TsMorphMetadataProvider, }); const metadata = orm.getMetadata().getAll(); expect(metadata).toBeInstanceOf(Object); expect(metadata[Author.name]).toBeInstanceOf(Object); expect(metadata[Author.name].path).toBe('./entities/Author.ts'); expect(metadata[Author.name].properties).toBeInstanceOf(Object); expect(metadata[Author.name].properties.books.type).toBe(Book.name); expect(metadata[Author.name].properties.books.reference).toBe(ReferenceType.ONE_TO_MANY); expect(metadata[Author.name].properties.identities.array).toBe(true); expect(metadata[Author.name].properties.identities.type).toBe('string[]'); expect(metadata[Author.name].properties.foo.type).toBe('string'); expect(metadata[Author.name].properties.age.type).toBe('number'); expect(metadata[Author.name].properties.age.optional).toBe(true); expect(metadata[Author.name].properties.age.nullable).toBe(true); // nullable is sniffed via ts-morph too expect(metadata[Book.name].properties.author.type).toBe(Author.name); expect(metadata[Book.name].properties.author.reference).toBe(ReferenceType.MANY_TO_ONE); expect(metadata[Book.name].properties.metaArray.type).toBe('any[]'); expect(metadata[Book.name].properties.metaArray.array).toBe(true); expect(metadata[Book.name].properties.metaArrayOfStrings.type).toBe('string[]'); expect(metadata[Book.name].properties.metaArrayOfStrings.array).toBe(true); expect(metadata[Publisher.name].properties.tests.owner).toBe(true); expect(metadata[Publisher.name].properties.types.customType).toBeInstanceOf(EnumArrayType); expect(metadata[Publisher.name].properties.types2.customType).toBeInstanceOf(EnumArrayType); // customType should be re-hydrated when loading metadata from cache const provider = new TsMorphMetadataProvider(orm.config); const cacheAdapter = orm.config.getCacheAdapter(); const cache = await cacheAdapter.get('Publisher.ts'); const meta = { properties: { types: { name: 'types', customType: new EnumArrayType('Publisher.types') }, types2: { name: 'types2', customType: new EnumArrayType('Publisher.types2') }, } } as unknown as EntityMetadata; provider.loadFromCache(meta, cache); expect(meta.properties.types.array).toBe(true); expect(meta.properties.types.enum).toBe(false); expect(meta.properties.types.customType).toBeInstanceOf(EnumArrayType); expect(meta.properties.types2.customType).toBeInstanceOf(EnumArrayType); expect(meta.properties.types2.array).toBe(true); expect(meta.properties.types2.enum).toBe(false); await orm.close(true); }); test('should ignore entity without path', async () => { const provider = new TsMorphMetadataProvider({} as any); const initProperties = jest.spyOn(TsMorphMetadataProvider.prototype, 'initProperties' as any); expect(initProperties).toBeCalledTimes(0); await provider.loadEntityMetadata({} as any, 'name'); expect(initProperties).toBeCalledTimes(0); }); test('should throw when source file not found', async () => { const provider = new TsMorphMetadataProvider({} as any); const error = `Source file './path/to/entity.ts' not found. Check your 'entitiesTs' option and verify you have 'compilerOptions.declaration' enabled in your 'tsconfig.json'. If you are using webpack, see https://bit.ly/35pPDNn`; await expect(provider.getExistingSourceFile('./path/to/entity.js')).rejects.toThrowError(error); }); });