import { Transaction } from 'sequelize'; type DatabaseTransactionProps = { transaction?: Transaction; isolationLevel?: string; autocommit?: boolean; }; type TransactionActionCallback = (transaction: Transaction) => Promise; const logger = console; // Here should be some custom logger (like pino, winston, etc) async function wrapInTransaction(action: TransactionActionCallback, opts?: DatabaseTransactionProps) { const { isolationLevel, autocommit = false } = opts || {}; // If no parent transaction has been passed inside "opts" // init new transaction const transaction = opts?.transaction || (await connection.transaction({ isolationLevel: Transaction.ISOLATION_LEVELS[isolationLevel], autocommit, })); try { const result = await action(transaction); // If no parent transaction has been passed inside "opts" // commit inner transaction if (!opts?.transaction) { await transaction.commit(); } return result; } catch (error) { // If no parent transaction has been passed inside "opts" // rollback inner transaction if (!opts?.transaction) { try { await transaction.rollback(); } catch (err) { logger.error('Failed to rollback failed transaction', err); } } throw error; } }