1.0.5 • Published 6 years ago

ejvm v1.0.5

Weekly downloads
59
License
ISC
Repository
github
Last release
6 years ago

EJVM

Express middleware written in Typescript for validating request-payloads against JSON schemas.

Build Status Coverage Status Greenkeeper badge

The motivation for building this library were these constraints: 1. It should be written in Typescript 2. It should use the current JSON schema standard 3. It should be as simple as possible 4. It should have reasonable defaults

Installation

yarn add ejvm

Note: EJVM supports draft-07 only!

Note: The middleware expects the req.body property to contain proper JSON. Use the body-parser middleware to handle this for you. Keep in mind that you must include the content-type header Content-Type: application/json in your requests.

Usage

Example application

This library includes a documented example application at src/example. To run it, clone the repository, install the dependencies and start the application:

$ git clone https://github.com/MrSchneepflug/ejvm
$ cd ejvm
$ yarn install
$ yarn example

Example request with curl:

curl \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"name": "some name"}' \
    http://localhost:3000/persons
{"success":true}

Simple Example

Lets say you want to build a CRUD interface for persons. To add a new person you would POST a JSON payload describing a person to a /persons endpoint.

First thing is to describe the desired schema for the person-payload. See http://json-schema.org/ for an in-depth explanation.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/schemas/person.json",
  "type": "object",
  "required": ["name"],
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "number"
    }
  }
}

Put this schema definition either in a separate .json file or directly in your code.

// load schema from separate file ...
const schema = JSON.parse(fs.readFileSync("/path/to/schema.json", "utf8"));

// ... or define schema directly in your code.
const schema = {
     "$schema": "http://json-schema.org/draft-07/schema#",
     "$id": "http://example.com/schemas/person.json",
     "type": "object",
     [...]
 };

You need to import the validate and isJsonSchemaValidationError functions. Also add the body-parser middleware.

import {validate, isJsonSchemaValidationError} from "ejvm";
import bodyParser from "body-parser";

Use the body-parser middleware before any route definition:

app.use(bodyParser.json());

Use the schema to create a new validation-middleware by calling the validate function.

app.post("/persons", validate(schema), (req: Request, res: Response): void => {
    // logic to store the person
});

Lastly, in order to catch the validation-errors you need to have an error-handler in place:

app.use((err: Error | JsonSchemaValidationError, req: Request, res: Response, next: NextFunction): void => {
    if (isJsonSchemaValidationError(err)) {
        // handle the error here, e.g.:
        res.status(400);
        res.json({
            statusText: "Bad Request",
            jsonSchemaValidation: true,
            validation: err.validationErrors,
        });
    } else {
        // this is not a JsonSchemaValidationError, so do not handle it here
        // and let the next middleware/finalhandler handle it
        next(err);
    }
});

To actually add a new person you need to include valid JSON with a name and optionally an age property. Example request with curl:

curl \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"name": "some name", "age": 65}' \
    http://localhost:3000/persons

Using multiple schemas

Sometimes it makes sense to use multiple schemas. For example if you want to reuse a specific schema several times.

Example

employee.json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/schemas/employee.json",
  "type": "object",
  "required": ["department", "person"],
  "properties": {
    "department": {
      "type": "string"
    },
    "person": {
      "$ref": "http://example.com/schemas/person.json"
    }
  }
}
person.json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/schemas/person.json",
  "type": "object",
  "required": ["name"],
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "number"
    }
  }
}

In this case you would pass an array with any additional schema as the second parameter to validate().

const employeeSchema = require("/path/to/employee.json");
const personSchema = require("/path/to/person.json");

app.post("/employees", validate(employeeSchema, [personSchema]), (req: Request, res: Response): void => {
    // ...
});

Note: Pass the configuration object for EJVM as third parameter to validate() if you want to use additional schemas.

Tests

$ yarn install
$ yarn test