Using middleware

Getting started

So we have our two commands, but we're repeating a lot of code. Wouldn't it be nice if we could re-use the code that parses the list of numbers? That's where middleware comes in.

Creating the middleware

Let's create a standalone middleware function that parses the numbers for us and adds the result to context state. Create it like this:

const numberMiddleware = (context, next) => {
  const { content, state } = context

  const numbers = content.split(" ").map(n => Number(n))
  state.numbers = numbers

  return next()
}

Now, we can add this middleware to our commands:

const sumCommand = new Command()
  .match(matchPrefixes("sum "))
  .use(numberMiddleware)
  .use(context => {
    const { numbers } = context.state
    const summed = numbers.reduce((a, b) => a + b)

    console.log(summed)
  })

const multiplyCommand = new Command()
  .match(matchPrefixes("multiply "))
  .use(numberMiddleware)
  .use(context => {
    const { numbers } = context.state
    const multiplied = numbers.reduce((a, b) => a * b)

    console.log(multiplied)
  })

The advantage of using middleware is that we can re-use code for specific situations like this one. Let's make our middleware even better by validating that the numbers passed are actual numbers:

const numberMiddleware = (context, next) => {
  const { content, state } = context

  const numbers = content.split(" ").map(n => Number(n))

  if (numbers.some(n => isNaN(n))) {
    console.log("Please specify a list of numbers separated by space.")
    return
  }

  state.numbers = numbers
  return next()
}

If you run your code again and input sum i am a number you should get the message "Please specify a list of numbers separated by space."

Adding commands
Adding command groups