typeorm-transactional-async-callbacks
Version:
A Transactional Method Decorator for typeorm that uses cls-hooked to handle and propagate transactions between different repositories and service methods. Inpired by Spring Trasnactional Annotation and Sequelize CLS
180 lines • 7.98 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setHookInContext = exports.getHookInContext = exports.deleteDataSourceByName = exports.getDataSourceByName = exports.addTransactionalDataSource = exports.initializeTransactionalContext = exports.getTransactionalOptions = exports.setEntityManagerByDataSourceName = exports.getEntityManagerByDataSourceName = exports.getTransactionalContext = void 0;
var typeorm_1 = require("typeorm");
var constants_1 = require("./constants");
var storage_driver_1 = require("../enums/storage-driver");
var typeorm_updated_patch_1 = require("../errors/typeorm-updated-patch");
var utils_1 = require("../utils");
var storage_1 = require("../storage");
/**
* Map of added data sources.
*
* The property "name" in the `DataSource` is deprecated, so we add own names to distinguish data sources.
*/
var dataSources = new Map();
/**
* Default library's state
*/
var data = {
options: {
maxHookHandlers: 10,
storageDriver: storage_driver_1.StorageDriver.CLS_HOOKED,
},
};
var getTransactionalContext = function () { return storage_1.storage.get(); };
exports.getTransactionalContext = getTransactionalContext;
var getEntityManagerByDataSourceName = function (context, name) {
if (!dataSources.has(name))
return null;
return context.get(constants_1.TYPEORM_DATA_SOURCE_NAME_PREFIX + name) || null;
};
exports.getEntityManagerByDataSourceName = getEntityManagerByDataSourceName;
var setEntityManagerByDataSourceName = function (context, name, entityManager) {
if (!dataSources.has(name))
return;
context.set(constants_1.TYPEORM_DATA_SOURCE_NAME_PREFIX + name, entityManager);
};
exports.setEntityManagerByDataSourceName = setEntityManagerByDataSourceName;
var getEntityManagerInContext = function (dataSourceName) {
var context = (0, exports.getTransactionalContext)();
if (!context || !context.active)
return null;
return (0, exports.getEntityManagerByDataSourceName)(context, dataSourceName);
};
var patchDataSource = function (dataSource) {
var originalManager = dataSource.manager;
Object.defineProperty(dataSource, 'manager', {
configurable: true,
get: function () {
return (getEntityManagerInContext(this[constants_1.TYPEORM_DATA_SOURCE_NAME]) ||
originalManager);
},
set: function (manager) {
originalManager = manager;
},
});
var originalQuery = typeorm_1.DataSource.prototype.query;
if (originalQuery.length !== 3) {
throw new typeorm_updated_patch_1.TypeOrmUpdatedPatchError();
}
dataSource.query = function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
args[2] = args[2] || ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.queryRunner);
return originalQuery.apply(this, args);
};
var originalCreateQueryBuilder = typeorm_1.DataSource.prototype.createQueryBuilder;
if (originalCreateQueryBuilder.length !== 3) {
throw new typeorm_updated_patch_1.TypeOrmUpdatedPatchError();
}
dataSource.createQueryBuilder = function () {
var _a, _b;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args.length === 0) {
return originalCreateQueryBuilder.apply(this, [(_a = this.manager) === null || _a === void 0 ? void 0 : _a.queryRunner]);
}
args[2] = args[2] || ((_b = this.manager) === null || _b === void 0 ? void 0 : _b.queryRunner);
return originalCreateQueryBuilder.apply(this, args);
};
dataSource.transaction = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return originalManager.transaction.apply(originalManager, args);
};
};
var setTransactionalOptions = function (options) {
data.options = __assign(__assign({}, data.options), (options || {}));
};
var getTransactionalOptions = function () { return data.options; };
exports.getTransactionalOptions = getTransactionalOptions;
var initializeTransactionalContext = function (options) {
setTransactionalOptions(options);
var patchManager = function (repositoryType) {
Object.defineProperty(repositoryType, 'manager', {
configurable: true,
get: function () {
return (getEntityManagerInContext(this[constants_1.TYPEORM_ENTITY_MANAGER_NAME].connection[constants_1.TYPEORM_DATA_SOURCE_NAME]) || this[constants_1.TYPEORM_ENTITY_MANAGER_NAME]);
},
set: function (manager) {
this[constants_1.TYPEORM_ENTITY_MANAGER_NAME] = manager;
},
});
};
var getRepository = function (originalFn) {
return function patchRepository() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var repository = originalFn.apply(this, args);
if (!(constants_1.TYPEORM_ENTITY_MANAGER_NAME in repository)) {
/**
* Store current manager
*/
repository[constants_1.TYPEORM_ENTITY_MANAGER_NAME] = repository.manager;
}
return repository;
};
};
var originalGetRepository = typeorm_1.EntityManager.prototype.getRepository;
var originalExtend = typeorm_1.Repository.prototype.extend;
typeorm_1.EntityManager.prototype.getRepository = getRepository(originalGetRepository);
typeorm_1.Repository.prototype.extend = getRepository(originalExtend);
patchManager(typeorm_1.Repository.prototype);
var storageDriver = (0, exports.getTransactionalOptions)().storageDriver;
return storage_1.storage.create(storageDriver);
};
exports.initializeTransactionalContext = initializeTransactionalContext;
var addTransactionalDataSource = function (input) {
if ((0, utils_1.isDataSource)(input)) {
input = { name: 'default', dataSource: input, patch: true };
}
var _a = input.name, name = _a === void 0 ? 'default' : _a, dataSource = input.dataSource, _b = input.patch, patch = _b === void 0 ? true : _b;
if (dataSources.has(name)) {
throw new Error("DataSource with name \"".concat(name, "\" has already added."));
}
if (patch) {
patchDataSource(dataSource);
}
dataSources.set(name, dataSource);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dataSource[constants_1.TYPEORM_DATA_SOURCE_NAME] = name;
return input.dataSource;
};
exports.addTransactionalDataSource = addTransactionalDataSource;
var getDataSourceByName = function (name) { return dataSources.get(name); };
exports.getDataSourceByName = getDataSourceByName;
var deleteDataSourceByName = function (name) { return dataSources.delete(name); };
exports.deleteDataSourceByName = deleteDataSourceByName;
var getHookInContext = function (context) {
return context === null || context === void 0 ? void 0 : context.get(constants_1.TYPEORM_HOOK_NAME);
};
exports.getHookInContext = getHookInContext;
var setHookInContext = function (context, emitter) {
return context.set(constants_1.TYPEORM_HOOK_NAME, emitter);
};
exports.setHookInContext = setHookInContext;
//# sourceMappingURL=index.js.map
;