In multiple functions I'm running more than one database action. When one of these fails I want to revert the ran actions. Therefore I'm using a transaction session from Mongoose.
First I create a session with the startSession function. I've added the session to the different Model.create functions. At the end of the function I'm committing and ending the session.
Since I work with an asyncHandler wrapper on all my function I'm not retyping the try/catch pattern inside my function. Is there a way to get the session into the asyncHandler of a different wrapper to abort the transaction when one or more of these functions fail?
Register function example
import { startSession } from 'mongoose';
import Company from '../models/Company';
import Person from '../models/Person';
import User from '../models/User';
import Mandate from '../models/Mandate';
import asyncHandler from '../middleware/asyncHandler';
export const register = asyncHandler(async (req, res, next) => {    
    const session = await startSession();
    
    let entity;
    if(req.body.profile_type === 'company') {
        entity = await Company.create([{ ...req.body }], { session });
    } else {
        entity = await Person.create([{ ...req.body }], { session });
    }
    // Create user
    const user = await User.create([{ 
        entity,
        ...req.body
    }], { session });
    // Create mandate
    await Mandate.create([{
        entity,
        status: 'unsigned'
    }], { session });
    // Generate user account verification token
    const verification_token = user.generateVerificationToken();
    // Send verification mail
    await sendAccountVerificationMail(user.email, user.first_name, user.language, verification_token);
    await session.commitTransaction();
    session.endSession();
    res.json({
        message: 'User succesfully registered. Check your mailbox to verify your account and continue the onboarding.',
    })
});
asyncHandler helper
const asyncHandler = fn => ( req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
export default asyncHandler;
EDIT 1
Let me rephrase the question. I'm looking for a way (one or more wrapper functions or a different method) to avoid rewriting the lines with // ~ repetitive code behind it. A try/catch block and handling the start and abort function of a database transaction.
export const register = async (req, res, next) => {    
    const session = await startSession(); // ~ repetitive code
    session.startTransaction(); // ~ repetitive code
    try { // ~ repetitive code     
        let entity;
        if(req.body.profile_type === 'company') {
            entity = await Company.create([{ ...req.body }], { session });
        } else {
            entity = await Person.create([{ ...req.body }], { session });
        }
        const mandate = await Mandate.create([{ entity, status: 'unsigned' }], { session });
        const user = await User.create([{ entity, ...req.body }], { session });
        const verification_token = user.generateVerificationToken();
        
        await sendAccountVerificationMail(user.email, user.first_name, user.language, verification_token);
        await session.commitTransaction(); // ~ repetitive
        session.endSession(); // ~ repetitive
        res.json({
            message: 'User succesfully registered. Check your mailbox to verify your account and continue the onboarding.',
        });
    } catch(error) { // ~ repetitive
        session.abortTransaction(); // ~ repetitive
        next(error) // ~ repetitive
    } // ~ repetitive
};
 
     
    