UNPKG

nestjs-typeorm-transactions

Version:

A NestJS module to make transaction management easier across different services

249 lines 9.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TransactionalRepository = void 0; const datasource_storage_1 = require("./common/datasource-storage"); const async_local_storage_1 = require("./common/async-local-storage"); class TransactionalRepository { constructor(dataSource, EntityClass, connection = datasource_storage_1.DEFAULT_DATASOURCE_NAME) { this.dataSource = dataSource; this.EntityClass = EntityClass; this.connection = connection; } /** Execute a raw query */ static async executeRawQuery(options) { let manager; const connection = options.connection ?? datasource_storage_1.DEFAULT_DATASOURCE_NAME; if (async_local_storage_1.asyncLocalStorage.getStore() && async_local_storage_1.asyncLocalStorage.getStore()[connection]) { manager = async_local_storage_1.asyncLocalStorage.getStore()[connection]; } else { manager = datasource_storage_1.DataSourceStorage.getDataSource(connection).manager; } return await manager.query(options.query, options.parameters); } /** Retrieve the transactional entity manager optionally specifying a connection name. If no connection name is specified, the default connection's entity manager is returned */ static getEntityManager(connection = datasource_storage_1.DEFAULT_DATASOURCE_NAME) { let manager; if (async_local_storage_1.asyncLocalStorage.getStore() && async_local_storage_1.asyncLocalStorage.getStore()[connection]) { manager = async_local_storage_1.asyncLocalStorage.getStore()[connection]; } else { manager = datasource_storage_1.DataSourceStorage.getDataSource(connection).manager; } return manager; } /** Get native typeorm repository */ getTypeOrmRepository() { let manager; if (async_local_storage_1.asyncLocalStorage.getStore() && async_local_storage_1.asyncLocalStorage.getStore()[this.connection]) { manager = async_local_storage_1.asyncLocalStorage.getStore()[this.connection]; } else { manager = this.dataSource.manager; } return manager.getRepository(this.EntityClass); } /** Create query builder */ createQueryBuilder(alias, queryRunner) { return this.getTypeOrmRepository().createQueryBuilder(alias, queryRunner); } /** Return multiple records */ async find(options) { return await this.getTypeOrmRepository() .createQueryBuilder() .setFindOptions(options ?? {}) .getMany(); } /** Return multiple records */ async findBy(where) { return await this.find({ where, }); } /** Return multiple records with pagination */ async findWithPagination(limit, page, options) { const data = await this.getTypeOrmRepository() .createQueryBuilder() .setFindOptions(options ?? {}) .skip((page - 1) * limit) .take(limit) .getMany(); const count = await this.getTypeOrmRepository() .createQueryBuilder() .setFindOptions(options ?? {}) .getCount(); return { count, pageCount: Math.ceil(count / limit), currentPage: page, limit, data, }; } /** Find one record */ async findOne(options) { return await this.getTypeOrmRepository() .createQueryBuilder() .setFindOptions(options) .getOne(); } /** Find one record */ async findOneBy(where) { return await this.findOne({ where, }); } /** Preload an entity using typeorm preload method */ async preload(entity) { return await this.getTypeOrmRepository().preload(entity); } async insert(entity) { if (entity instanceof Array) { await this.getTypeOrmRepository().insert(entity); return entity; } else { await this.getTypeOrmRepository().insert(entity); return entity; } } create(entity) { if (entity instanceof Array) { return this.getTypeOrmRepository().create(entity); } else { return this.getTypeOrmRepository().create(entity); } } async save(entity, saveOptions) { if (!saveOptions) { saveOptions = { transaction: false }; } else { saveOptions.transaction = false; } if (entity instanceof Array) { return await this.getTypeOrmRepository().save(entity, saveOptions); } else { return await this.getTypeOrmRepository().save(entity, saveOptions); } } /** Updates given entity/entities */ async update(id, entity) { await this.getTypeOrmRepository().update(id, entity); } /** Upserts record(s) */ async upsert(entity, conflictPaths) { await this.getTypeOrmRepository().upsert(entity, conflictPaths); } /** Deletes record(s) */ async delete(id) { await this.getTypeOrmRepository().delete(id); } /** Disassociate all child entities in many to many relationships */ async disassociateAll(entityId, relation) { const relations = this.getTypeOrmRepository().metadata.relations; let found = false; let columnName = ''; for (let r of relations) { if (r.propertyName === relation.toString()) { if (!r.isManyToMany || !r.junctionEntityMetadata) { throw new Error('Not a many to many relationship or no junction metadata found'); } r.junctionEntityMetadata.columns.forEach((column) => { if (column.referencedColumn.target === this.EntityClass) { columnName = column.databaseName; } }); if (!columnName) { throw new Error('No column found in junction table for the given entity'); } await this.getTypeOrmRepository() .createQueryBuilder() .delete() .from(r.joinTableName) .where(`${columnName} = :id`, { id: entityId, }) .execute(); found = true; } } if (!found) { throw new Error(`Relation ${relation.toString()} not found in ${this.EntityClass instanceof Function ? this.EntityClass.name : this.EntityClass.options.name}`); } } /** Disassociate child entities by ids in many to many relationships */ async disassociate(entityId, relatedEntityId, relation) { const relations = this.getTypeOrmRepository().metadata.relations; let found = false; for (let r of relations) if (r.propertyName === relation.toString()) { if (!r.isManyToMany) { throw new Error('Not a many to many relationship'); } await this.getTypeOrmRepository() .createQueryBuilder() .relation(this.EntityClass, relation.toString()) .of(entityId) .remove(relatedEntityId); found = true; } if (!found) { throw new Error(`Relation ${relation.toString()} not found in ${this.EntityClass instanceof Function ? this.EntityClass.name : this.EntityClass.options.name}`); } } /** Associate child entities by ids in many to many relationships */ async associate(entityId, relatedEntityId, relation) { const relations = this.getTypeOrmRepository().metadata.relations; let found = false; for (let r of relations) if (r.propertyName === relation.toString()) { if (!r.isManyToMany) { throw new Error('Not a many to many relationship'); } await this.getTypeOrmRepository() .createQueryBuilder() .relation(this.EntityClass, relation.toString()) .of(entityId) .add(relatedEntityId); found = true; } if (!found) { throw new Error(`Relation ${relation.toString()} not found in ${this.EntityClass instanceof Function ? this.EntityClass.name : this.EntityClass.options.name}`); } } /** Count entities */ async count(options) { return await this.getTypeOrmRepository().count(options); } /** Get the average of a culumn */ async average(columnName, where) { return await this.getTypeOrmRepository().average(columnName, where); } /** Get the sum of a column */ async sum(columnName, where) { return await this.getTypeOrmRepository().sum(columnName, where); } /** Get the max value of a column */ async max(columnName, where) { return await this.getTypeOrmRepository().maximum(columnName, where); } /** Get the min value of a column */ async min(columnName, where) { return await this.getTypeOrmRepository().minimum(columnName, where); } /** Merge multiple entity like objects into a single entity */ merge(mergeIntoEntity, ...entityLikes) { return this.getTypeOrmRepository().merge(mergeIntoEntity, ...entityLikes); } } exports.TransactionalRepository = TransactionalRepository; //# sourceMappingURL=transactional.repository.js.map