WebPro

Fork me on GitHub
webpro/dyson dyson at GitHub
@webprolific WebPro at Twitter

dyson

Node server for dynamic, fake JSON.

npm install dyson

See installation notes. Check out some demo services.

Build Status npm package dependencies npm version

Introduction

Dyson allows you to define JSON endpoints based on a simple template object:

input-output

When developing client-side applications, for data usually either static JSON files are used, or an actual server, backend, datastore, API, you name it. Sometimes static files are too static, and sometimes an actual server is not available, not accessible, or too tedious to setup.

This is where dyson comes in. Get a full fake server for your application up and running in minutes.

Overview

Endpoint Configuration

Configure endpoints using simple objects:

module.exports = {
    path: '/user/:id',
    method: 'GET',
    template: {
        id: (params, query, body) =>params.id,
        name: g.name,
        address: {
            zip: g.zipUS,
            city: g.city
        }
    }
}

The path string is the usual argument provided to Express, as in app.get(path, callback);.

The template object may contain properties of the following types:

Note: the template can also be a function returning the actual data. The template function itself is also invoked with arguments (params, query, body, cookies, headers).

Images

In addition to configured endpoints, dyson registers a dummy image service at /image. E.g. requesting /image/300x200 serves an image with given dimensions.

This service is a proxy to Dynamic Dummy Image Generator by Russell Heimlich.

Defaults

The default values for the configuration objects:

module.exports = {
    cache: false,
    delay: false,
    proxy: false,
    size: () => _.random(2,10),
    collection: false,
    callback: response.generate,
    render: response.render
};

Fake data generators

You can use anything to generate data. Here are some suggestions:

Just install the generator(s) in your project to use them in your templates:

npm install dyson-generators --save-dev

Please refer to the project pages for usage and examples (here’s one using dyson-generators).

Containers

Containers can help if you need to send along some meta data, or wrap the response data in a specific way. Just use the container object, and return the data where you want it. Functions in the container object are invoked with arguments (params, query, data):

module.exports = {
    path: '/users',
    template: user.template,
    container: {
        meta: (params, query, data) => ({
            userCount: data.length
        }),
        data: {
            all: [],
            the: {
                way: {
                    here: (params, query, data) => data
                }
            }
        }
    }
}

And an example response:

{
  "meta": {
    "userCount": 2
  },
  "data": {
    "all": [],
    "the": {
      "way": {
        "here": [
          {
            "id": 412,
            "name": "John"
          },
          {
            "id": 218,
            "name": "Olivia"
          }
        ]
      }
    }
  }
}

Combined requests

Basic support for “combined” requests is available, by means of a comma separated path fragment.

For example, a request to /user/5,13 will result in an array of the responses from /user/5 and /user/13.

The , delimiter can be configured (or disabled).

Status codes

By default, all responses are sent with a status code 200 (and the Content-Type: application/json header).

This can be completely overridden with the status property, e.g.:

module.exports = {
    path: '/feature/:foo?',
    status: (req, res) => {
        if(req.params.foo === '999') {
            res.status(404).send('Feature not found');
        }
    }
}

Would result in a 404 when requesting /feature/999.

JSONP

Override the render method of the Express middleware in the endpoint definition. In the example below, depending on the existence of the callback parameter, either raw JSON response is returned or it is wrapped with the provided callback:

module.exports = {
    render: (req, res) => {
        const callback = req.query.callback;
        if (callback) {
            res.append('Content-Type', 'application/javascript');
            res.send(`${callback}(${JSON.stringify(res.body)});`);
        } else {
            res.send(res.body);
        }
    }
}

HTTPS

If you want to run dyson over https:// you have to provide a self-signed (or authority-signed) certificate into the options.https the same way it’s required for NodeJS HTTPS to work:

const fs = require('fs');

dyson.bootstrap({
    configDir: `${__dirname}/dummy`,
    port: 3001,
    https: {
        key: fs.readFileSync(`${__dirname}'/certs/sample.key`),
        crt: fs.readFileSync(`${__dirname}/certs/sample.crt`)
    }
});

Note: if running HTTPS on port 443, it will require sudo privileges.

Custom middleware

If you need some custom middleware before or after the endpoints are registered, dyson can be initialized programmatically. Then you can use appBefore or appAfter to install middleware before or after the dyson services are registered. An example:

const dyson = require('dyson'),
    path = require('path');

const options = {
    configDir: path.join(__dirname, 'services'),
    port: 8765
};

const configs = dyson.getConfigurations(options),
    appBefore = dyson.createServer(options),
    appAfter = dyson.registerServices(appBefore, options, configs);

console.log(`Dyson listening at port ${options.port}`);

Dyson configuration can also be installed into any Express server:

const express = require('express'),
    dyson = require('./lib/dyson'),
    path = require('path');

var options = {
    configDir: path.join(__dirname, 'services')
};

var myApp = express();
var configs = dyson.getConfigurations(options);
dyson.registerServices(myApp, options, configs);
myApp.listen(8765);

Installation

The recommended way to install dyson is to install it locally and put it in your package.json:

npm install dyson

Then you can use it from an npm-script in package.json using e.g. npm run mocks:

{
  "name": "my-package",
  "version": "1.0.0",
  "scripts": {
    "mocks": "dyson stubs"
  }
}

You can also install dyson globally to start it from anywhere:

npm install -g dyson

Project

You can put your configuration files anywhere, but either the configuration must have the method property set or the configuration file must be inside a directory representing the method (e.g. stubs/get/sub/endpoint.js). Then start the server:

dyson [dir]

This starts the services configured in [dir] at localhost:3000.

You can also provide an alternative port number by just adding it as a second argument (e.g. dyson path/ 8181).

Demo

For a demo project, see webpro/dyson-demo. This demo was also installed with now.sh to dyson-demo-npzwhgjdor.now.sh.

Project Configuration

Optionally, you can put a dyson.json file next to the configuration folders (inside [dir]). It enables to configure some behavior of dyson:

{
    "multiRequest": ",",
    "proxy": true,
    "proxyHost": "http://dyson.jit.su",
    "proxyPort": 8080,
    "proxyDelay": [200, 800]
}

Development & run tests

git clone git@github.com:webpro/dyson.git
cd dyson
npm install
npm test

Articles about dyson

License

MIT