11

Type Checking for your API requests made simple

 3 years ago
source link: https://github.com/magna25/jebena
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Jebena

Lightweight ES6 promise based JSON validation library with 0 dependencies

Heavily inspired by https://github.com/lperrin/paperwork

Installation

npm i jebena

Usage

import jebena from 'jebena'


const spec = {
    name: String,
    age: Number,
    "phone?": Number // ? means optional prop
}

const data = {
    name: "Foo Bar",
    age: 34
}

jebena(spec, data)
.then( res => {
    console.log(res) //outputs cleaned and validated data
})
.catch(err => {
    console.log(err) //outputs array of errors
})

Express

import {jebenaExpress} from 'jebena'

const app = express()
app.use(express.json())

//catch json errors, not required (however, you must make sure req.body is a json data before you call jebenaExpress)
app.use((err,req,res,next) => {
    res.status(400).send({"error":"bad request"})
})

const spec = {
    email: isEmail(),
    password: all(String, minLength(8)),
}

app.post("/users", jebenaExpress(spec), () => {
    //req.body is validated and cleaned
})

jebenaExpress() by default runs the validation against req.body but you can change that by passing a second argument.

const spec = {
    page: Number,
    pageSize: Number
}

app.get("/products", jebenaExpress(spec, "query"), () => {
    //req.query is validated and cleaned
})

That's it. jebena returns a 400 response silently if there are any errors. Sample 400 response:

{
  "errors": [
    "password: must be at least 8 characters long"
  ]
}

Types

Supports Javascript primitive data types String, Number, Boolean + custom types

Arrays

const spec = {
    books: [] //array of any type
    books: [String] //array of strings
    books: [Number] //array of numbers
    books: [Boolean] //array of booleans
    books: [{
        id: String,
        title: String,
        year: Number
    }] //array of literal objects
}

Nested objects

const spec: [
    person: {
        id: Number,
        address: {
            street: String,
            ...
        },
        someProp: {
            anotherProp: {
                anotherProp: [
                    {
                        id: Number,
                        name: String
                    }
                ]
            }
        }

    }
]

Custom types

all(type1, type2, type3...) - validates each type

const spec = {
    phone: all(Number, length(10))
}

minLength(num) - validates minimum length

const spec = {
    password: all(String, minLength(8))
}

maxLength(num) - validates maximum length

const spec = {
    username: maxLength(25)
}

length(num) - checks if value is exactly n characters long

const spec = {
    phone: length(10)

match(regex, customErrorMsg) - tests regular expression against the value

const spec = {
    phone: match(/^\d+$/) //numbers only
}

isEmail() - check if string is in a valid email format

const spec = {
    email: isEmail()
}

equals(val) - verfies user value matches the defined value

const spec = {
    role: equals("ADMIN")
}

Custom validation

return true/false from your function

return [<boolean>, <customErrorMsg>] if you want to pass custom error msg

const spec = {
    fullName: (val) => {
        const fn = val.split(" ")
        if(fn.length < 2) return [false, "enter full name"] //return array for custom error message
        return true
    },
    age: (val) => {
        return val > 18
    }
}

Test

npm run jebena-test


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK