UNPKG

ionic-orm-x

Version:

Data-mapper ORM for Ionic WebSQL and SQLite

276 lines 12.9 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { QueryBuilder } from "../query-builder/QueryBuilder"; import { PlainObjectToNewEntityTransformer } from "../query-builder/transformer/PlainObjectToNewEntityTransformer"; import { PlainObjectToDatabaseEntityTransformer } from "../query-builder/transformer/PlainObjectToDatabaseEntityTransformer"; import { FindOptionsUtils } from "../find-options/FindOptionsUtils"; import { QueryRunnerProvider } from "../query-runner/QueryRunnerProvider"; import { EntityPersister } from "../persistment/EntityPersister"; /** * Repository is supposed to work with your entity objects. Find entities, insert, update, delete, etc. */ export class Repository { // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- constructor(connection, metadata, queryRunnerProvider) { this.connection = connection; this.metadata = metadata; this.queryRunnerProvider = queryRunnerProvider; } // ------------------------------------------------------------------------- // Public Methods // ------------------------------------------------------------------------- /** * Returns object that is managed by this repository. * If this repository manages entity from schema, * then it returns a name of that schema instead. */ get target() { return this.metadata.target; } /** * Checks if entity has an id. * If entity contains compose ids, then it checks them all. */ hasId(entity) { // if (this.metadata.parentEntityMetadata) { // return this.metadata.parentEntityMetadata.parentIdColumns.every(parentIdColumn => { // const columnName = parentIdColumn.propertyName; // return !!entity && // entity.hasOwnProperty(columnName) && // entity[columnName] !== null && // entity[columnName] !== undefined && // entity[columnName] !== ""; // }); // } else { return this.metadata.primaryColumns.every(primaryColumn => { const columnName = primaryColumn.propertyName; return !!entity && entity.hasOwnProperty(columnName) && entity[columnName] !== null && entity[columnName] !== undefined && entity[columnName] !== ""; }); // } } /** * Creates a new query builder that can be used to build a sql query. */ createQueryBuilder(alias) { return new QueryBuilder(this.connection /*, dbConnection*/) .select(alias) .from(this.metadata.target, alias); } /** * Creates a new entity instance or instances. * Can copy properties from the given object into new entities. */ create(plainObjectOrObjects) { if (plainObjectOrObjects instanceof Array) return plainObjectOrObjects.map(object => this.create(object)); const newEntity = this.metadata.create(); if (plainObjectOrObjects) { const plainObjectToEntityTransformer = new PlainObjectToNewEntityTransformer(); plainObjectToEntityTransformer.transform(newEntity, plainObjectOrObjects, this.metadata); } return newEntity; } /** * Creates a new entity from the given plan javascript object. If entity already exist in the database, then * it loads it (and everything related to it), replaces all values with the new ones from the given object * and returns this new entity. This new entity is actually a loaded from the db entity with all properties * replaced from the new object. */ preload(object) { const queryBuilder = this.createQueryBuilder(this.metadata.table.name); const plainObjectToDatabaseEntityTransformer = new PlainObjectToDatabaseEntityTransformer(); return plainObjectToDatabaseEntityTransformer.transform(object, this.metadata, queryBuilder); } /** * Merges multiple entities (or entity-like objects) into a one new entity. */ merge(...objects) { const newEntity = this.metadata.create(); const plainObjectToEntityTransformer = new PlainObjectToNewEntityTransformer(); objects.forEach(object => plainObjectToEntityTransformer.transform(newEntity, object, this.metadata)); return newEntity; } /** * Persists one or many given entities. */ persist(entityOrEntities) { return __awaiter(this, void 0, void 0, function* () { // if multiple entities given then go throw all of them and save them if (entityOrEntities instanceof Array) return Promise.all(entityOrEntities.map(entity => this.persist(entity))); const queryRunnerProvider = this.queryRunnerProvider || new QueryRunnerProvider(this.connection.driver); const queryRunner = yield queryRunnerProvider.provide(); try { const entityPersister = new EntityPersister(this.connection, this.metadata, queryRunner); return yield entityPersister.persist(entityOrEntities); // await is needed here because we are using finally // if (this.hasId(entityOrEntities)) { // return await entityPersister.update(entityOrEntities); // await is needed here because we are using finally // } else { // return await entityPersister.insert(entityOrEntities); // await is needed here because we are using finally // } } finally { yield queryRunnerProvider.release(queryRunner); } }); } /** * Removes one or many given entities. */ remove(entityOrEntities) { return __awaiter(this, void 0, void 0, function* () { // if multiple entities given then go throw all of them and save them if (entityOrEntities instanceof Array) return Promise.all(entityOrEntities.map(entity => this.remove(entity))); const queryRunnerProvider = this.queryRunnerProvider || new QueryRunnerProvider(this.connection.driver, true); const queryRunner = yield queryRunnerProvider.provide(); try { const entityPersister = new EntityPersister(this.connection, this.metadata, queryRunner); return yield entityPersister.remove(entityOrEntities); // await is needed here because we are using finally } finally { yield queryRunnerProvider.release(queryRunner); } }); } /** * Finds entities that match given conditions and/or find options. */ find(conditionsOrFindOptions, options) { return __awaiter(this, void 0, void 0, function* () { return this.createFindQueryBuilder(conditionsOrFindOptions, options) .getResults(); }); } /** * Finds entities that match given conditions. * Also counts all entities that match given conditions, * but ignores pagination settings (maxResults, firstResult) options. */ findAndCount(conditionsOrFindOptions, options) { return __awaiter(this, void 0, void 0, function* () { return this.createFindQueryBuilder(conditionsOrFindOptions, options) .getResultsAndCount(); }); } /** * Finds first entity that matches given conditions and/or find options. */ findOne(conditionsOrFindOptions, options) { return __awaiter(this, void 0, void 0, function* () { return this.createFindQueryBuilder(conditionsOrFindOptions, options) .getSingleResult(); }); } /** * Finds entity with given id. * Optionally find options can be applied. */ findOneById(id, options) { return __awaiter(this, void 0, void 0, function* () { const conditions = {}; if (this.metadata.hasMultiplePrimaryKeys) { this.metadata.primaryColumns.forEach(primaryColumn => { conditions[primaryColumn.name] = id[primaryColumn.name]; }); this.metadata.parentIdColumns.forEach(primaryColumn => { conditions[primaryColumn.name] = id[primaryColumn.propertyName]; }); } else { if (this.metadata.primaryColumns.length > 0) { conditions[this.metadata.firstPrimaryColumn.name] = id; } else if (this.metadata.parentIdColumns.length > 0) { conditions[this.metadata.parentIdColumns[0].name] = id; } } return this.createFindQueryBuilder(conditions, options) .getSingleResult(); }); } /** * Executes a raw SQL query and returns a raw database results. */ query(query) { return __awaiter(this, void 0, void 0, function* () { const queryRunnerProvider = this.queryRunnerProvider || new QueryRunnerProvider(this.connection.driver); const queryRunner = yield queryRunnerProvider.provide(); try { return yield queryRunner.query(query); // await is needed here because we are using finally } finally { yield queryRunnerProvider.release(queryRunner); } }); } /** * Wraps given function execution (and all operations made there) in a transaction. * All database operations must be executed using provided repository. */ transaction(runInTransaction) { return __awaiter(this, void 0, void 0, function* () { const queryRunnerProvider = this.queryRunnerProvider || new QueryRunnerProvider(this.connection.driver, true); const queryRunner = yield queryRunnerProvider.provide(); const transactionRepository = new Repository(this.connection, this.metadata, queryRunnerProvider); try { yield queryRunner.beginTransaction(); const result = yield runInTransaction(transactionRepository); yield queryRunner.commitTransaction(); return result; } catch (err) { yield queryRunner.rollbackTransaction(); throw err; } finally { yield queryRunnerProvider.release(queryRunner); if (!this.queryRunnerProvider) yield queryRunnerProvider.releaseReused(); } }); } // ------------------------------------------------------------------------- // Protected Methods // ------------------------------------------------------------------------- /** * Creates a query builder from the given conditions or find options. * Used to create a query builder for find* methods. */ createFindQueryBuilder(conditionsOrFindOptions, options) { const findOptions = FindOptionsUtils.isFindOptions(conditionsOrFindOptions) ? conditionsOrFindOptions : options; const conditions = FindOptionsUtils.isFindOptions(conditionsOrFindOptions) ? undefined : conditionsOrFindOptions; const alias = findOptions ? findOptions.alias : this.metadata.table.name; const qb = this.createQueryBuilder(alias); // if find options are given then apply them to query builder if (findOptions) FindOptionsUtils.applyOptionsToQueryBuilder(qb, findOptions); // if conditions are given then apply them to query builder if (conditions) { Object.keys(conditions).forEach(key => { const name = key.indexOf(".") === -1 ? alias + "." + key : key; if (conditions[key]) { qb.andWhere(name + "=:" + key); } else { qb.andWhere(name + " IS NULL"); } }); qb.addParameters(conditions); } return qb; } } //# sourceMappingURL=Repository.js.map