DEV Community

Cover image for Validating/transforming input data in an express server is no more a headache task.
Sang
Sang

Posted on

Validating/transforming input data in an express server is no more a headache task.

Preface

One of the most critical tasks when writing a backend code is to validate the input data passed by the clients. However, as I know, currently, there is no library for this purpose which is good enough to use.

Then, I decided to write one. I called it express-transformer.

The NPM document is well-prepared in terms of the API specification details. In this post, I will only introduce several use cases with sample codes, to share with you my motivation to write and publish this package.

Use cases

import {transformer} from 'express-transformer'

Check for a value existence

app.use(transformer('id').exists())
Enter fullscreen mode Exit fullscreen mode

Customize the error message

app.use(transformer('id').exists().message('id is required'))
Enter fullscreen mode Exit fullscreen mode

Convert the page parameter in req.query

Convert the page parameter in req.query from string to number format, decrease the value by 1, ensure that the number is positive, and also set the default value 0 if it does not exist.

app.use(
  transformer('page', {location: 'query'})
    .defaultValue('1')
    .toInt({min: 1})
    .transform(page => page - 1)
)
Enter fullscreen mode Exit fullscreen mode

Check password fields

app.use(
  transformer('password')
    .exists().message('password is required')
    .isLength({min: 8}).message('password is too short'),
  transformer(['password', 'passswordConfirm'])
    .transform(([p, pc]) => {
      if (p !== pc) throw new Error('dump string')
    }, {validateOnly: true})
    .message('Passwords do not match')
)
Enter fullscreen mode Exit fullscreen mode

Convert user id to a user object, throw an error if not found.

transformer('id')
  .exists()
  .transform(async id => User.findById(id).exec())
  .exists().message('User does not exist')
// in the next middleware, req.body.id is a non-null User object.
Enter fullscreen mode Exit fullscreen mode

Array elements iteration

The following transformation chain iterates all values in req.body.messages[<index>].stars[<index>] and carry out the transformation .toInt.

transformer('user.messages[].stars[]')
  .toInt({min: 0, max: 5})
Enter fullscreen mode Exit fullscreen mode

More advanced cases with array iteration

This transformation chain iterate all available values at req.body.me.favorite[<index>], req.body.posts[<index>].meta.comments[<index>].likes[<index>], req.body.credits, pairs them one by one and pass to the callback in .transform(callback).

transformer(['me.favorites[]', 'posts[].meta.comments[].likes[]', 'credits'])
  .transform(([favorite, like, credits]) => {
    // perform the check here
    // because validateOnly is true, the returned value is ignored
  }, {validateOnly: true})
Enter fullscreen mode Exit fullscreen mode

Conclusion

Besides the above-mentioned validations, the library also supports various methods, such as:

  • .exists()
  • .is()
  • .isArray()
  • .isEmail()
  • .isIn(list)
  • .isLength() (check string length or array's length)
  • .matches(regex)
  • .defaultValue(value)
  • .toDate()
  • .toFloat()
  • .toInt()
  • .trim()

Please refer to the NPM package for more details.

Indeed, it is possible (and very easy) to add more methods via plugins. You can add your own methods, like: .isPostalCode(), .isMongodbID(), .isNewUsername ...

Top comments (0)