DEV Community

Lucas Aragno
Lucas Aragno

Posted on

Performpal a service object library for Javascript/NodeJS

This week I've published Performpal a service object library for JavaScript.

This library is inspired by the principles of clean code architecture and Trailblazer.

Operations are a nice and clean way to abstract out all the business logic from other layers of your application. This useful specially for backend apps in which we often end up having business logic on the controller/model layer.

With performpal we can create an Operation for each "use case" of our application and perform each step necessary in order in a react-ish way:

For example:

const { Operation } = require('performpal')
const pug = require('pug')
const emailService = require('../emailService')
const registeredUserEmail = pug.compileFile('../templates/users/register')


class SendEmail extends Operation {
  constructor () {
    super()
    this.steps = [
      this.createEmailBody,
      this.sendEmail
    ]

    this.failures = [
      this.handleSubmitEmailError
    ]
  }

  // on constructor handle this, like react does with this.state

  createEmailBody ({params, options}) {
    let { email } = params
    options['emailBody'] = registeredUserEmail({email})
  }


  sendEmail ({params, options}) {
    const { emailBody } = options
    const { email } = params
    return emailService.send({ email, emailBody })
  }

  handleSubmitEmailError ({params}) {
    const { email } = params
    throw new Error(`Error sending email to ${email}`)
  }
}

module.exports = SendEmail

Operations are framework agnostic so you can use them wherever you want.

This is how an express route would look like:

const SendEmail = require('../operations/SendEmail')

app.post('/sendEmail', async (req) => {
  try {
    let { email } = req.body
    let result = await (new SendEmail()).run({params: {email}})
    res.send(200).json({result})
  } catch (error) {
    res.send(500).json({error})
  }
})

This way our route will be just and HTTP endpoint for our app that only cares about getting the request, taking the parameters, dispatching the operation and communicate the result.

You can also use Operation to write up GraphQL resolvers, Callbacks or anything you want.

This pattern has helped me a lot to keep things clean on big applications so I decided to move it over a library, feedback is welcomed!

Top comments (0)