Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mikro-orm

Package Overview
Dependencies
Maintainers
1
Versions
3403
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mikro-orm - npm Package Compare versions

Comparing version 0.7.4 to 0.8.0

tests/EntityRepository.test.ts

2

dist/BaseEntity.js

@@ -17,3 +17,3 @@ "use strict";

if ([ReferenceType.ONE_TO_MANY, ReferenceType.MANY_TO_MANY].includes(props[prop].reference)) {
this[prop] = new Collection_1.Collection(props[prop], this, []);
this[prop] = new Collection_1.Collection(this, props[prop], []);
}

@@ -20,0 +20,0 @@ });

import { ObjectID } from 'bson';
import { BaseEntity, EntityProperty } from './BaseEntity';
export declare class Collection<T extends BaseEntity> {
readonly owner: BaseEntity;
private readonly property;
private readonly owner;
private initialized;
private dirty;
private readonly items;
constructor(property: EntityProperty, owner: BaseEntity, items?: T[]);
isInitialized(): boolean;
constructor(owner: BaseEntity, property: EntityProperty, items?: T[]);
isInitialized(fully?: boolean): boolean;
isDirty(): boolean;

@@ -16,3 +16,3 @@ init(): Promise<Collection<T>>;

add(...items: T[]): void;
set(items: T[]): void;
set(items: T[], initialize?: boolean): void;
remove(...items: T[]): void;

@@ -25,2 +25,3 @@ removeAll(): void;

private handleInverseSide;
private createCondition;
}

@@ -6,5 +6,5 @@ "use strict";

class Collection {
constructor(property, owner, items = null) {
constructor(owner, property, items = null) {
this.owner = owner;
this.property = property;
this.owner = owner;
this.initialized = false;

@@ -18,3 +18,6 @@ this.dirty = false;

}
isInitialized() {
isInitialized(fully = false) {
if (fully) {
return this.initialized && this.items.every(i => i.isInitialized());
}
return this.initialized;

@@ -26,16 +29,10 @@ }

async init() {
const cond = {};
const order = [];
if (this.property.reference === BaseEntity_1.ReferenceType.ONE_TO_MANY) {
cond[this.property.fk] = this.owner._id;
// do not make db call if we know we will get no results
if (this.property.reference === BaseEntity_1.ReferenceType.MANY_TO_MANY && this.property.owner && this.items.length === 0) {
this.initialized = true;
this.dirty = false;
return this;
}
else if (this.property.reference === BaseEntity_1.ReferenceType.MANY_TO_MANY) {
if (this.property.owner) {
const order = this.items.map(item => item._id);
cond._id = { $in: order };
}
else {
cond[this.property.mappedBy] = this.owner._id;
}
}
const cond = this.createCondition();
const order = this.items.map(item => item._id);
this.items.length = 0;

@@ -72,5 +69,11 @@ const em = MikroORM_1.getEntityManager();

}
set(items) {
set(items, initialize = false) {
if (initialize) {
this.initialized = true;
}
this.removeAll();
this.add(...items);
if (initialize) {
this.dirty = false;
}
}

@@ -119,3 +122,18 @@ remove(...items) {

}
createCondition() {
const cond = {};
if (this.property.reference === BaseEntity_1.ReferenceType.ONE_TO_MANY) {
cond[this.property.fk] = this.owner._id;
}
else if (this.property.reference === BaseEntity_1.ReferenceType.MANY_TO_MANY) {
if (this.property.owner) {
cond._id = { $in: this.items.map(item => item._id) };
}
else {
cond[this.property.mappedBy] = this.owner._id;
}
}
return cond;
}
}
exports.Collection = Collection;

@@ -22,3 +22,2 @@ "use strict";

const meta = this.metadata[entityName];
const exclude = [];
let entity;

@@ -34,4 +33,5 @@ data._id = new bson_1.ObjectID(data.id || data._id);

entity = Object.create(Entity.prototype);
this.em.identityMap[`${entityName}-${data._id}`] = entity;
}
this.initEntity(entity, meta.properties, data, exclude);
this.initEntity(entity, meta.properties, data);
if (initialized) {

@@ -51,3 +51,3 @@ delete entity['_initialized'];

}
initEntity(entity, properties, data, exclude = []) {
initEntity(entity, properties, data) {
// process base entity properties first

@@ -62,7 +62,4 @@ ['_id', 'createdAt', 'updatedAt'].forEach(k => {

const prop = properties[p];
if (exclude.includes(p)) {
return;
}
if (prop.reference === BaseEntity_1.ReferenceType.ONE_TO_MANY && !data[p]) {
return entity[p] = new Collection_1.Collection(prop, entity);
return entity[p] = new Collection_1.Collection(entity, prop);
}

@@ -72,6 +69,6 @@ if (prop.reference === BaseEntity_1.ReferenceType.MANY_TO_MANY) {

const items = data[p].map((id) => this.createReference(prop.type, id.toHexString()));
return entity[p] = new Collection_1.Collection(prop, entity, items);
return entity[p] = new Collection_1.Collection(entity, prop, items);
}
else if (!entity[p]) {
return entity[p] = new Collection_1.Collection(prop, entity, prop.owner ? [] : null);
return entity[p] = new Collection_1.Collection(entity, prop, prop.owner ? [] : null);
}

@@ -78,0 +75,0 @@ }

@@ -24,2 +24,5 @@ import { Collection as MongoCollection, Db, FilterQuery } from 'mongodb';

merge<T extends BaseEntity>(entityName: string, data: any): T;
/**
* gets a reference to the entity identified by the given type and identifier without actually loading it, if the entity is not yet loaded
*/
getReference<T extends BaseEntity>(entityName: string, id: string): T;

@@ -40,5 +43,9 @@ remove(entityName: string, where: BaseEntity | any): Promise<number>;

canPopulate(entityName: string, property: string): boolean;
private processPopulate;
private populateOne;
/**
* preload everything in one call (this will update already existing references in IM)
*/
private populateMany;
private buildQuery;
private runHooks;
}

@@ -39,20 +39,8 @@ "use strict";

async find(entityName, where = {}, populate = [], orderBy = {}, limit = null, offset = null) {
Utils_1.Utils.renameKey(where, 'id', '_id');
let query = `db.getCollection("${this.metadata[entityName].collection}").find(${JSON.stringify(where)})`;
where = Utils_1.Utils.convertObjectIds(where);
const resultSet = this.getCollection(entityName).find(where);
if (Object.keys(orderBy).length > 0) {
query += `.sort(${JSON.stringify(orderBy)})`;
resultSet.sort(orderBy);
}
if (limit !== null) {
query += `.limit(${limit})`;
resultSet.limit(limit);
}
if (offset !== null) {
query += `.skip(${offset})`;
resultSet.skip(offset);
}
const { query, resultSet } = this.buildQuery(entityName, where, orderBy, limit, offset);
this.options.logger(`[query-logger] ${query}.toArray();`);
const results = await resultSet.toArray();
if (results.length === 0) {
return [];
}
const ret = [];

@@ -63,3 +51,5 @@ for (const data of results) {

}
await this.processPopulate(ret, populate);
for (const field of populate) {
await this.populateMany(entityName, ret, field);
}
return ret;

@@ -69,3 +59,3 @@ }

if (!where || (typeof where === 'object' && Object.keys(where).length === 0)) {
return null;
throw new Error(`You cannot call 'EntityManager.findOne()' with empty 'where' parameter`);
}

@@ -76,2 +66,3 @@ if (where instanceof mongodb_1.ObjectID) {

if (Utils_1.Utils.isString(where) && this.identityMap[`${entityName}-${where}`] && this.identityMap[`${entityName}-${where}`].isInitialized()) {
await this.populateOne(entityName, this.identityMap[`${entityName}-${where}`], populate);
return this.identityMap[`${entityName}-${where}`];

@@ -91,3 +82,3 @@ }

const entity = this.merge(entityName, data);
await this.processPopulate(entity, populate);
await this.populateOne(entityName, entity, populate);
return entity;

@@ -102,6 +93,12 @@ }

entity.assign(data);
this.unitOfWork.addToIdentityMap(entity);
}
this.addToIdentityMap(entity);
else {
this.addToIdentityMap(entity);
}
return entity;
}
/**
* gets a reference to the entity identified by the given type and identifier without actually loading it, if the entity is not yet loaded
*/
getReference(entityName, id) {

@@ -173,25 +170,26 @@ if (this.identityMap[`${entityName}-${id}`]) {

}
async processPopulate(entity, populate) {
if (entity instanceof BaseEntity_1.BaseEntity) {
for (const field of populate) {
if (entity[field] instanceof Collection_1.Collection && !entity[field].isInitialized()) {
await entity[field].init();
}
if (entity[field] instanceof BaseEntity_1.BaseEntity && !entity[field].isInitialized()) {
await entity[field].init();
}
async populateOne(entityName, entity, populate) {
for (const field of populate) {
if (!this.canPopulate(entityName, field)) {
throw new Error(`Entity '${entityName}' does not have property '${field}'`);
}
return;
if (entity[field] instanceof Collection_1.Collection && !entity[field].isInitialized(true)) {
await entity[field].init();
}
if (entity[field] instanceof BaseEntity_1.BaseEntity && !entity[field].isInitialized()) {
await entity[field].init();
}
}
if (entity.length === 0) {
return;
}
/**
* preload everything in one call (this will update already existing references in IM)
*/
async populateMany(entityName, entities, field) {
if (!this.canPopulate(entityName, field)) {
throw new Error(`Entity '${entityName}' does not have property '${field}'`);
}
for (const field of populate) {
await this.populateMany(entity, field);
}
}
async populateMany(entities, field) {
if (entities[0][field] instanceof Collection_1.Collection) {
const meta = this.metadata[entityName].properties[field];
if (meta.reference === BaseEntity_1.ReferenceType.MANY_TO_MANY && !meta.owner) {
for (const entity of entities) {
if (entity[field] instanceof Collection_1.Collection && !entity[field].isInitialized()) {
if (!entity[field].isInitialized()) {
await entity[field].init();

@@ -202,11 +200,48 @@ }

}
const children = entities.filter(e => e[field] instanceof BaseEntity_1.BaseEntity && !e[field].isInitialized());
const children = [];
let fk = '_id';
if (meta.reference === BaseEntity_1.ReferenceType.ONE_TO_MANY) {
const filtered = entities.filter(e => e[field] instanceof Collection_1.Collection);
children.push(...filtered.map(e => e[field].owner));
fk = meta.fk;
}
else if (meta.reference === BaseEntity_1.ReferenceType.MANY_TO_MANY) {
const filtered = entities.filter(e => e[field] instanceof Collection_1.Collection && !e[field].isInitialized(true));
children.push(...filtered.reduce((a, b) => [...a, ...b[field].getItems()], []));
}
else {
children.push(...entities.filter(e => e[field] instanceof BaseEntity_1.BaseEntity && !e[field].isInitialized()).map(e => e[field]));
}
if (children.length === 0) {
return;
}
// preload everything in one call (this will update already existing references in IM)
const ids = Utils_1.Utils.unique(children.map(e => e[field].id));
const meta = this.metadata[entities[0].constructor.name].properties[field];
await this.find(meta.type, { _id: { $in: ids } });
const ids = Utils_1.Utils.unique(children.map(e => e.id));
const data = await this.find(meta.type, { [fk]: { $in: ids } });
// initialize collections for one to many
if (meta.reference === BaseEntity_1.ReferenceType.ONE_TO_MANY) {
for (const entity of entities) {
const items = data.filter(child => child[fk] === entity);
entity[field].set(items, true);
}
}
}
buildQuery(entityName, where, orderBy, limit, offset) {
Utils_1.Utils.renameKey(where, 'id', '_id');
let query = `db.getCollection("${this.metadata[entityName].collection}").find(${JSON.stringify(where)})`;
where = Utils_1.Utils.convertObjectIds(where);
const resultSet = this.getCollection(entityName).find(where);
if (Object.keys(orderBy).length > 0) {
query += `.sort(${JSON.stringify(orderBy)})`;
resultSet.sort(orderBy);
}
if (limit !== null) {
query += `.limit(${limit})`;
resultSet.limit(limit);
}
if (offset !== null) {
query += `.skip(${offset})`;
resultSet.skip(offset);
}
return { query, resultSet };
}
runHooks(type, entity) {

@@ -213,0 +248,0 @@ const hooks = this.metadata[entity.constructor.name].hooks;

@@ -8,2 +8,3 @@ import { FilterQuery } from 'mongodb';

constructor(em: EntityManager, entityName: string);
getReference<T extends BaseEntity>(id: string): T;
persist(entity: T, flush?: boolean): Promise<void>;

@@ -10,0 +11,0 @@ findOne(where: FilterQuery<T> | string, populate?: string[]): Promise<T>;

@@ -8,2 +8,5 @@ "use strict";

}
getReference(id) {
return this.em.getReference(this.entityName, id);
}
async persist(entity, flush = true) {

@@ -10,0 +13,0 @@ return this.em.persist(entity, flush);

@@ -22,3 +22,3 @@ import { getMetadataStorage, getEntityManager } from './MikroORM';

if ([ReferenceType.ONE_TO_MANY, ReferenceType.MANY_TO_MANY].includes(props[prop].reference)) {
this[prop] = new Collection(props[prop], this, []);
this[prop] = new Collection(this, props[prop], []);
}

@@ -25,0 +25,0 @@ });

@@ -11,4 +11,4 @@ import { ObjectID } from 'bson';

constructor(private readonly property: EntityProperty,
private readonly owner: BaseEntity,
constructor(public readonly owner: BaseEntity,
private readonly property: EntityProperty,
items: T[] = null) {

@@ -21,3 +21,7 @@ if (items) {

isInitialized(): boolean {
isInitialized(fully = false): boolean {
if (fully) {
return this.initialized && this.items.every(i => i.isInitialized());
}
return this.initialized;

@@ -31,16 +35,13 @@ }

async init(): Promise<Collection<T>> {
const cond = {} as any;
const order = [] as ObjectID[];
// do not make db call if we know we will get no results
if (this.property.reference === ReferenceType.MANY_TO_MANY && this.property.owner && this.items.length === 0) {
this.initialized = true;
this.dirty = false;
if (this.property.reference === ReferenceType.ONE_TO_MANY) {
cond[this.property.fk] = this.owner._id;
} else if (this.property.reference === ReferenceType.MANY_TO_MANY) {
if (this.property.owner) {
const order = this.items.map(item => item._id);
cond._id = { $in: order };
} else {
cond[this.property.mappedBy] = this.owner._id;
}
return this;
}
const cond = this.createCondition();
const order = this.items.map(item => item._id);
this.items.length = 0;

@@ -86,5 +87,13 @@ const em = getEntityManager();

set(items: T[]): void {
set(items: T[], initialize = false): void {
if (initialize) {
this.initialized = true;
}
this.removeAll();
this.add(...items);
if (initialize) {
this.dirty = false;
}
}

@@ -140,3 +149,3 @@

private handleInverseSide(item: T, method: string) {
private handleInverseSide(item: T, method: string): void {
if (this.property.owner && this.property.inversedBy && item[this.property.inversedBy].isInitialized()) {

@@ -147,3 +156,19 @@ item[this.property.inversedBy][method](this.owner);

private createCondition(): any {
const cond: any = {};
if (this.property.reference === ReferenceType.ONE_TO_MANY) {
cond[this.property.fk] = this.owner._id;
} else if (this.property.reference === ReferenceType.MANY_TO_MANY) {
if (this.property.owner) {
cond._id = { $in: this.items.map(item => item._id) };
} else {
cond[this.property.mappedBy] = this.owner._id;
}
}
return cond;
}
}

@@ -26,3 +26,2 @@ import { readdirSync } from 'fs';

const meta = this.metadata[entityName];
const exclude: string[] = [];
let entity: T;

@@ -39,5 +38,6 @@

entity = Object.create(Entity.prototype);
this.em.identityMap[`${entityName}-${data._id}`] = entity;
}
this.initEntity(entity, meta.properties, data, exclude);
this.initEntity(entity, meta.properties, data);

@@ -61,3 +61,3 @@ if (initialized) {

private initEntity<T extends BaseEntity>(entity: T, properties: any, data: any, exclude: string[] = []): void {
private initEntity<T extends BaseEntity>(entity: T, properties: any, data: any): void {
// process base entity properties first

@@ -74,8 +74,4 @@ ['_id', 'createdAt', 'updatedAt'].forEach(k => {

if (exclude.includes(p)) {
return;
}
if (prop.reference === ReferenceType.ONE_TO_MANY && !data[p]) {
return entity[p] = new Collection<T>(prop, entity);
return entity[p] = new Collection<T>(entity, prop);
}

@@ -86,5 +82,5 @@

const items = data[p].map((id: ObjectID) => this.createReference(prop.type, id.toHexString()));
return entity[p] = new Collection<T>(prop, entity, items);
return entity[p] = new Collection<T>(entity, prop, items);
} else if (!entity[p]) {
return entity[p] = new Collection<T>(prop, entity, prop.owner ? [] : null);
return entity[p] = new Collection<T>(entity, prop, prop.owner ? [] : null);
}

@@ -91,0 +87,0 @@ }

import { Collection as MongoCollection, Db, FilterQuery, ObjectID } from 'mongodb';
import { BaseEntity, EntityMetadata } from './BaseEntity';
import { BaseEntity, EntityMetadata, ReferenceType } from './BaseEntity';
import { EntityRepository } from './EntityRepository';

@@ -43,24 +43,10 @@ import { EntityFactory } from './EntityFactory';

async find<T extends BaseEntity>(entityName: string, where = {} as FilterQuery<T>, populate: string[] = [], orderBy: { [k: string]: 1 | -1 } = {}, limit: number = null, offset: number = null): Promise<T[]> {
Utils.renameKey(where, 'id', '_id');
let query = `db.getCollection("${this.metadata[entityName].collection}").find(${JSON.stringify(where)})`;
where = Utils.convertObjectIds(where);
const resultSet = this.getCollection(entityName).find(where);
const { query, resultSet } = this.buildQuery<T>(entityName, where, orderBy, limit, offset);
this.options.logger(`[query-logger] ${query}.toArray();`);
const results = await resultSet.toArray();
if (Object.keys(orderBy).length > 0) {
query += `.sort(${JSON.stringify(orderBy)})`;
resultSet.sort(orderBy);
if (results.length === 0) {
return [];
}
if (limit !== null) {
query += `.limit(${limit})`;
resultSet.limit(limit);
}
if (offset !== null) {
query += `.skip(${offset})`;
resultSet.skip(offset);
}
this.options.logger(`[query-logger] ${query}.toArray();`);
const results = await resultSet.toArray();
const ret: T[] = [];

@@ -73,3 +59,5 @@

await this.processPopulate(ret, populate);
for (const field of populate) {
await this.populateMany(entityName, ret, field);
}

@@ -81,3 +69,3 @@ return ret;

if (!where || (typeof where === 'object' && Object.keys(where).length === 0)) {
return null;
throw new Error(`You cannot call 'EntityManager.findOne()' with empty 'where' parameter`);
}

@@ -90,2 +78,3 @@

if (Utils.isString(where) && this.identityMap[`${entityName}-${where}`] && this.identityMap[`${entityName}-${where}`].isInitialized()) {
await this.populateOne(entityName, this.identityMap[`${entityName}-${where}`], populate);
return this.identityMap[`${entityName}-${where}`] as T;

@@ -109,3 +98,3 @@ }

const entity = this.merge(entityName, data) as T;
await this.processPopulate(entity, populate);
await this.populateOne(entityName, entity, populate);

@@ -124,9 +113,13 @@ return entity;

entity.assign(data);
this.unitOfWork.addToIdentityMap(entity);
} else {
this.addToIdentityMap(entity);
}
this.addToIdentityMap(entity);
return entity as T;
}
/**
* gets a reference to the entity identified by the given type and identifier without actually loading it, if the entity is not yet loaded
*/
getReference<T extends BaseEntity>(entityName: string, id: string): T {

@@ -212,30 +205,31 @@ if (this.identityMap[`${entityName}-${id}`]) {

private async processPopulate(entity: BaseEntity | BaseEntity[], populate: string[]): Promise<void> {
if (entity instanceof BaseEntity) {
for (const field of populate) {
if (entity[field] instanceof Collection && !entity[field].isInitialized()) {
await (entity[field] as Collection<BaseEntity>).init();
}
private async populateOne(entityName: string, entity: BaseEntity, populate: string[]): Promise<void> {
for (const field of populate) {
if (!this.canPopulate(entityName, field)) {
throw new Error(`Entity '${entityName}' does not have property '${field}'`);
}
if (entity[field] instanceof BaseEntity && !entity[field].isInitialized()) {
await (entity[field] as BaseEntity).init();
}
if (entity[field] instanceof Collection && !entity[field].isInitialized(true)) {
await (entity[field] as Collection<BaseEntity>).init();
}
return;
if (entity[field] instanceof BaseEntity && !entity[field].isInitialized()) {
await (entity[field] as BaseEntity).init();
}
}
}
if (entity.length === 0) {
return;
/**
* preload everything in one call (this will update already existing references in IM)
*/
private async populateMany(entityName: string, entities: BaseEntity[], field: string): Promise<void> {
if (!this.canPopulate(entityName, field)) {
throw new Error(`Entity '${entityName}' does not have property '${field}'`);
}
for (const field of populate) {
await this.populateMany(entity, field);
}
}
const meta = this.metadata[entityName].properties[field];
private async populateMany(entities: BaseEntity[], field: string): Promise<void> {
if (entities[0][field] instanceof Collection) {
if (meta.reference === ReferenceType.MANY_TO_MANY && !meta.owner) {
for (const entity of entities) {
if (entity[field] instanceof Collection && !entity[field].isInitialized()) {
if (!entity[field].isInitialized()) {
await (entity[field] as Collection<BaseEntity>).init();

@@ -248,4 +242,16 @@ }

const children = entities.filter(e => e[field] instanceof BaseEntity && !e[field].isInitialized());
const children: BaseEntity[] = [];
let fk = '_id';
if (meta.reference === ReferenceType.ONE_TO_MANY) {
const filtered = entities.filter(e => e[field] instanceof Collection);
children.push(...filtered.map(e => e[field].owner));
fk = meta.fk;
} else if (meta.reference === ReferenceType.MANY_TO_MANY) {
const filtered = entities.filter(e => e[field] instanceof Collection && !e[field].isInitialized(true));
children.push(...filtered.reduce((a, b) => [...a, ...b[field].getItems()], []));
} else {
children.push(...entities.filter(e => e[field] instanceof BaseEntity && !e[field].isInitialized()).map(e => e[field]));
}
if (children.length === 0) {

@@ -255,8 +261,38 @@ return;

// preload everything in one call (this will update already existing references in IM)
const ids = Utils.unique(children.map(e => e[field].id));
const meta = this.metadata[entities[0].constructor.name].properties[field];
await this.find<BaseEntity>(meta.type, { _id: { $in: ids } });
const ids = Utils.unique(children.map(e => e.id));
const data = await this.find<BaseEntity>(meta.type, { [fk]: { $in: ids } });
// initialize collections for one to many
if (meta.reference === ReferenceType.ONE_TO_MANY) {
for (const entity of entities) {
const items = data.filter(child => child[fk] === entity);
(entity[field] as Collection<BaseEntity>).set(items, true);
}
}
}
private buildQuery<T extends BaseEntity>(entityName: string, where: FilterQuery<T>, orderBy: { [p: string]: 1 | -1 }, limit: number, offset: number): { query: string; resultSet: any } {
Utils.renameKey(where, 'id', '_id');
let query = `db.getCollection("${this.metadata[entityName].collection}").find(${JSON.stringify(where)})`;
where = Utils.convertObjectIds(where);
const resultSet = this.getCollection(entityName).find(where);
if (Object.keys(orderBy).length > 0) {
query += `.sort(${JSON.stringify(orderBy)})`;
resultSet.sort(orderBy);
}
if (limit !== null) {
query += `.limit(${limit})`;
resultSet.limit(limit);
}
if (offset !== null) {
query += `.skip(${offset})`;
resultSet.skip(offset);
}
return { query, resultSet };
}
private runHooks(type: string, entity: BaseEntity) {

@@ -263,0 +299,0 @@ const hooks = this.metadata[entity.constructor.name].hooks;

@@ -10,2 +10,6 @@ import { FilterQuery } from 'mongodb';

getReference<T extends BaseEntity>(id: string): T {
return this.em.getReference(this.entityName, id);
}
async persist(entity: T, flush = true): Promise<void> {

@@ -12,0 +16,0 @@ return this.em.persist(entity, flush);

{
"name": "mikro-orm",
"version": "0.7.4",
"version": "0.8.0",
"description": "Simple typescript mongo ORM for node.js based on data-mapper, unit-of-work and identity-map patterns",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -34,3 +34,2 @@ import { EntityFactory } from '../lib/EntityFactory';

const metadata = factory.getMetadata();
// console.log(require('util').inspect(metadata, true, 5, true));
expect(metadata).toBeInstanceOf(Object);

@@ -37,0 +36,0 @@ expect(metadata[Author.name]).toBeInstanceOf(Object);

@@ -9,2 +9,3 @@ import { ObjectID } from 'bson';

import { initORM, wipeDatabase } from './bootstrap';
import { Test } from './entities/Test';

@@ -103,2 +104,4 @@ /**

expect(jon.books.getIdentifiers()[0]).toBeInstanceOf(ObjectID);
expect(jon.books.getIdentifiers('id')).toBeInstanceOf(Array);
expect(typeof jon.books.getIdentifiers('id')[0]).toBe('string');

@@ -155,8 +158,8 @@ for (const author of authors) {

test('findOne with empty where will return null', async () => {
expect(await orm.em.findOne<Author>(Author.name, '')).toBeNull();
expect(await orm.em.findOne<Author>(Author.name, {})).toBeNull();
expect(await orm.em.findOne<Author>(Author.name, [])).toBeNull();
expect(await orm.em.findOne<Author>(Author.name, undefined)).toBeNull();
expect(await orm.em.findOne<Author>(Author.name, null)).toBeNull();
test('findOne with empty where will throw', async () => {
await expect(orm.em.findOne<Author>(Author.name, '')).rejects.toThrowError(`You cannot call 'EntityManager.findOne()' with empty 'where' parameter`);
await expect(orm.em.findOne<Author>(Author.name, {})).rejects.toThrowError(`You cannot call 'EntityManager.findOne()' with empty 'where' parameter`);
await expect(orm.em.findOne<Author>(Author.name, [])).rejects.toThrowError(`You cannot call 'EntityManager.findOne()' with empty 'where' parameter`);
await expect(orm.em.findOne<Author>(Author.name, undefined)).rejects.toThrowError(`You cannot call 'EntityManager.findOne()' with empty 'where' parameter`);
await expect(orm.em.findOne<Author>(Author.name, null)).rejects.toThrowError(`You cannot call 'EntityManager.findOne()' with empty 'where' parameter`);
});

@@ -328,2 +331,54 @@

test('populating many to many relation', async () => {
const p1 = new Publisher('foo');
expect(p1.tests).toBeInstanceOf(Collection);
expect(p1.tests.isInitialized()).toBe(true);
expect(p1.tests.isDirty()).toBe(false);
expect(p1.tests.count()).toBe(0);
const p2 = new Publisher('bar');
p2.tests.add(new Test(), new Test());
await orm.em.persist([p1, p2]);
const repo = orm.em.getRepository<Publisher>(Publisher.name);
orm.em.clear();
const publishers = await repo.findAll(['tests']);
expect(publishers).toBeInstanceOf(Array);
expect(publishers.length).toBe(2);
expect(publishers[0]).toBeInstanceOf(Publisher);
expect(publishers[0].tests).toBeInstanceOf(Collection);
expect(publishers[0].tests.isInitialized()).toBe(true);
expect(publishers[0].tests.isDirty()).toBe(false);
expect(publishers[0].tests.count()).toBe(0);
await publishers[0].tests.init(); // empty many to many on owning side should not make db calls
expect(publishers[1].tests.getItems()[0].isInitialized()).toBe(true);
});
test('populating many to many relation on inverse side', async () => {
const author = new Author('Jon Snow', 'snow@wall.st');
const book1 = new Book('My Life on The Wall, part 1', author);
const book2 = new Book('My Life on The Wall, part 2', author);
const book3 = new Book('My Life on The Wall, part 3', author);
const tag1 = new BookTag('silly');
const tag2 = new BookTag('funny');
const tag3 = new BookTag('sick');
const tag4 = new BookTag('strange');
const tag5 = new BookTag('sexy');
book1.tags.add(tag1, tag3);
book2.tags.add(tag1, tag2, tag5);
book3.tags.add(tag2, tag4, tag5);
await orm.em.persist([book1, book2, book3]);
const repo = orm.em.getRepository<BookTag>(BookTag.name);
orm.em.clear();
const tags = await repo.findAll(['books']);
expect(tags).toBeInstanceOf(Array);
expect(tags.length).toBe(5);
expect(tags[0]).toBeInstanceOf(BookTag);
expect(tags[0].books).toBeInstanceOf(Collection);
expect(tags[0].books.isInitialized()).toBe(true);
expect(tags[0].books.isDirty()).toBe(false);
expect(tags[0].books.count()).toBe(2);
expect(tags[0].books.getItems()[0].isInitialized()).toBe(true);
});
test('hooks', async () => {

@@ -368,2 +423,12 @@ Author.beforeDestroyCalled = 0;

});
test('trying to populate non-existing or non-reference property will throw', async () => {
const repo = orm.em.getRepository<Author>(Author.name);
const author = new Author('Johny Cash', 'johny@cash.com');
await repo.persist(author);
orm.em.clear();
await expect(repo.findAll(['tests'])).rejects.toThrowError(`Entity 'Author' does not have property 'tests'`);
await expect(repo.findOne(author.id, ['tests'])).rejects.toThrowError(`Entity 'Author' does not have property 'tests'`);
});
});

@@ -370,0 +435,0 @@

@@ -1,2 +0,2 @@

import { MikroORM, Options, EntityManager } from '../lib';
import { MikroORM, Options, EntityManager, getEntityManager } from '../lib';

@@ -8,2 +8,6 @@ /**

test('should throw when trying to get EM before initialisation', async () => {
await expect(() => getEntityManager()).toThrowError('Call MikroORM.init() first!');
});
test('should throw when not enough options provided', async () => {

@@ -10,0 +14,0 @@ await expect(() => new MikroORM({ entitiesDirs: ['entities'] } as Options)).toThrowError('No database specified, please fill in `dbName` option');

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc