It seems that you understand how to send an email, you also understand how to attach an image to the email. What you do not really understand is how to use this in the scope of a promise?
To help you to better understand the flow of the code and how it would be laid out, I have created an example that you can customise by adding your own content and mail options, you can also convert this to typescript where neccessary:
send.js:
const nodemailer = require('nodemailer')
const config = {
  port: 'your smtp port',
  host: 'your smtp host',
  user: 'your username',
  pass: 'your password',
  from: {
    name: 'Sender Name',
    email: 'Sender Email Address'
  }
}
module.exports = {
  send(payload) {
    return new Promise(async (resolve, reject) => {
      try {
        const { subject, name, email } = payload
        // The plaintext version
        const text = 'Hello World!'
        // The html version
        const html = '<p>Hello World!</p>'
        // create reusable transporter object using the default SMTP transport
        const transporter = nodemailer.createTransport({
          port: config.port,
          host: config.host,
          auth: {
            user: config.user,
            pass: config.pass
          },
          secure: true
        })
        // setup email options here
        const mailOptions = {
          from: `"${config.from.name}" <${config.from.email}>`, // sender address
          to: `"${name}" <${email}>`, // comma seperated list of receivers
          subject, // Subject line
          text, // plain text body
          html // html body
        }
        // send mail with defined transport object
        const info = await transporter.sendMail(mailOptions)
        // Success
        return resolve(info)
      } catch (err) {
        return reject(err)
      }
    })
  },
};
main.js:
const { send } = require('./send.js');
(async () => {
  try {
    const payload = {
      subject: 'Test Email',
      name: 'Some Person',
      email: 'Their Email Address'
    }
    const info = await send(payload)
    console.log('successfully sent the email:')
    console.log(info)
  } catch (err) {
    console.log('failed to send the email:')
    console.log(err)
  }
})();
In the case of a successful outcome:
{ accepted: [ 'name@domain.tld' ],
  rejected: [],
  envelopeTime: 605,
  messageTime: 596,
  messageSize: 620,
  response:
   '250 Ok someidortheother',
  envelope:
   { from: 'sender@senderdomain.tld',
     to: [ 'name@domain.tld' ] },
  messageId: '<messageidblah@senderdomain.tld>' }
I can suggest too that you always include a plaintext version of the email so that it can be rendered in email clients which do not support or have been configured not to display the html body content.