Build a fake backend by providing the content of files or JavaScript objects through configurable routes. This service allows the developer to work on a new feature or an existing one using fake data while the real service is in development.
Start by adding the service as a development dependency.
yarn add --dev the-fake-backend
or
npm install --save-dev the-fake-backend
After installing, create a new file that will be responsible for configuring and starting the service.
const { createServer } = require('the-fake-backend');
const server = createServer();
server.routes([
{
path: '/example',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
data: 'your-response-data-here',
// data: (req) => 'your-response-data-here-based-in-request'
},
],
},
]);
server.listen(8080);
This will create the http://localhost:8080/example endpoint.
You can also use files content as response instead of using the data
property.
const { createServer } = require('the-fake-backend');
const server = createServer();
server.routes([
{
path: '/cats',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
},
],
},
{
path: '/dogs',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
file: 'data/my/custom/path/to/dogs.txt',
// file: req => `data/my/custom/path/to/dogs-${req.query.type}.txt`
},
],
},
]);
server.listen(8080);
The script above generates the following two endpoints.
Method | Path | Response |
---|---|---|
GET | http://localhost:8080/cats | The data/cats.json file content |
GET | http://localhost:8080/dogs | The data/my/custom/path/to/dogs.txt file content |
Property | Required | Description |
---|---|---|
basePath | no | An API context prefix (e.g. /v1 ) |
middlewares | no | An array of express's middlewares |
proxies | no | The server proxies |
throttlings | no | The server throttlings |
pagination | no | The server pagination setup |
This property allows to proxy requests.
Property | Required | Default | Description |
---|---|---|---|
proxies[].name | yes | The proxy name | |
proxies[].host | yes | The proxy host (e.g.: http://api.dev.com/api ) |
|
proxies[].appendBasePath | No | false |
Whether basePath should be appended in target |
This property allows responses to be throttled.
Property | Required | Description |
---|---|---|
throttlings[].name | yes | Custom throttling name |
throttlings[].values | yes | Custom throttling range (array of numbers, in ms) |
This property allows routes to be paginated. Response attributes may be printed in response payload (wrapping the given fixture) or headers. Request parameters are read from URL query string.
Property | Required | Default | Type | Description |
---|---|---|---|---|
count | no | 'count' |
Response attribute | Current page items count |
data | no | 'data' |
Response attribute | Current page data |
empty | no | 'empty' |
Response attribute | Whether if current page is empty |
first | no | 'first' |
Response attribute | Whether if current page is the first one |
headers | no | false |
Configuration | Whether response attributes will be present in headers |
last | no | 'last' |
Response attribute | Whether if current page is the last one |
next | no | 'next' |
Response attribute | Whether if there is a next page |
offsetParameter | no | 'offset' |
Request parameter | Requested offset |
page | no | 'page' |
Response attribute | Current page |
pageParameter | no | 'page' |
Request parameter | Requested page |
pages | no | 'pages' |
Response attribute | Pages count |
sizeParameter | no | 'size' |
Request parameter | Requested page size |
total | no | 'total' |
Response attribute | Total items count |
Property | Required | Description |
---|---|---|
routes[].path | yes | The endpoint address (URI). |
routes[].methods | yes | The route methods, check the method's properties table below. |
Property | Type | Required | Default | Description |
---|---|---|---|---|
methods[].type | string | yes | HTTP request type | |
methods[].code | number | no | 200 |
HTTP response status code |
methods[].data | any | (req) => any | no | HTTP response data. May also be a function with request | |
methods[].file | string | (req) => string | no | /data/${req.path} |
HTTP response data fixture file (when data is not given). May also be a function with request |
methods[].headers | object | (req) => object | no | HTTP response headers. May also be a function with request | |
methods[].delay | number | no | HTTP response delay/timeout, in milliseconds | |
methods[].search | object | no | Search parameters | |
methods[].pagination | boolean | object | no | false |
Whether data is paginated or not. May also be a pagination object |
methods[].overrides | object[] | no | Custom response scenarios (switchable in CLI) | |
methods[].overrideContent | (req, content) => any | no | A function to override response content before send |
This property allows routes to be searchable.
Property | Type | Required | Default | Description |
---|---|---|---|---|
parameter | string | yes | 'search' |
Query string parameter name |
properties | string[] | yes | An array of properties to apply the search |
This property allows you to create an array of options that will override the current method
option.
Property | Type | Required | Default | Description |
---|---|---|---|---|
overrides[].name | string | yes | Scenario name | |
overrides[].code | number | no | 200 |
Described above |
overrides[].data | any | (req) => any | no | Described above | |
overrides[].file | string | (req) => string | no | Described above | |
overrides[].headers | object | (req) => object | no | Described above | |
overrides[].delay | number | no | Described above | |
overrides[].search | object | no | Described above | |
overrides[].pagination | boolean | object | no | false |
Described above |
overrides[].overrideContent | (req, content) => any | no | Described above | |
overrides[].selected | boolean | no | false |
Described above |
When a request is made the server will check if the method
object contains the overrides
property and if there is one override
selected through the property selected
. If there is an override
selected it will be merged with the method
object.
const server = createServer({ ... })
server.routes([
{
path: '/user',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
file: 'data/my/custom/path/to/client-user.json',
overrides: [
{
name: 'Staff',
file: 'data/my/custom/path/to/staff-user.json'
},
{
name: 'Super Admin',
file: 'data/my/custom/path/to/super-admin-user.json'
},
{
name: 'Error 500',
code: 500
}
]
}
]
}
]);
// curl -XGET http://localhost:8080/user
// Returns `data/my/custom/path/to/client-user.json` file content.
Press 'o' on terminal and change the URL '/user' with method 'get' with override 'Super Admin'
// curl -XGET http://localhost:8080/user
// Returns `data/my/custom/path/to/super-admin-user.json` file content.
You can override the response content after all the processing (file/data content, pagination, search, etc.).
// /data/dogs.json
[
{ "id": 1, "name": "Doogo" },
{ "id": 2, "name": "Dogger" },
{ "id": 3, "name": "Dog" },
{ "id": 4, "name": "Doggernaut" },
{ "id": 5, "name": "Dogging" }
]
const { createServer } = require('the-fake-backend');
const server = createServer();
server.routes([
{
path: '/dogs',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
overrideContent: (req, content) => ({
...content,
{ id: 6, name: 'Bulldog' }
})
},
],
},
]);
server.listen(8080);
You can make an endpoint searchable by declaring the search property in a route.
// /data/dogs.json
[
{ "id": 1, "name": "Doogo" },
{ "id": 2, "name": "Dogger" },
{ "id": 3, "name": "Dog" },
{ "id": 4, "name": "Doggernaut" },
{ "id": 5, "name": "Dogging" }
]
const { createServer } = require('the-fake-backend');
const server = createServer();
server.routes([
{
path: '/dogs',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
search: {
parameter: 'search',
properties: ['name'],
},
},
],
},
]);
server.listen(8080);
You can now make requests to the http://localhost:8080/dogs?search=dogg
endpoint. The response will be the data/dogs.json
file content filtered.
[
{ "id": 2, "name": "Dogger" },
{ "id": 4, "name": "Doggernaut" },
{ "id": 5, "name": "Dogging" }
]
You can make an endpoint paginated by declaring the pagination options in the server (just in case of overriding default values), adding pagination parameter in a route and visiting it with pagination query string parameters.
Route pagination parameter may be a boolean (true) to use global pagination options, or pagination object parts to override global ones.
Note: The pagination is zero-based, so 0 is the first page.
// /data/dogs.json
[
{ "id": 1, "name": "Doogo" },
{ "id": 2, "name": "Dogger" },
{ "id": 3, "name": "Dog" },
{ "id": 4, "name": "Doggernaut" },
{ "id": 5, "name": "Dogging" }
];
const { createServer } = require('the-fake-backend');
const server = createServer(); // if pagination isn't given, default values will be applied
server.routes([
{
path: '/dogs',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
pagination: true,
// pagination: { headers: true } // only this request will have pagination parameters in response headers
},
],
},
]);
server.listen(8080);
Then, given a http://localhost:8080/dogs?page=1&size=2
request, the following payload will be returned:
{
"count": 2,
"empty": false,
"first": true,
"last": false,
"next": true,
"page": 1,
"pages": 3,
"total": 5,
"data": [
{ "id": 3, "name": "Dog" },
{ "id": 4, "name": "Doggernaut" }
]
}
Note: given
http://localhost:8080/dogs?offset=2&size=2
the payload would be the same. Offset attribute has precedence over page.
If headers attribute was set to true in server options (or route pagination options):
const server = createServer({
pagination: {
headers: true,
},
});
Then the metadata attributes would be printed in response headers and the response payload would be the following:
[
{ "id": 3, "name": "Dog" },
{ "id": 4, "name": "Doggernaut" }
]
Just like in Express, route requests may have dynamic params:
const { createServer } = require('the-fake-backend');
const server = createServer();
server.routes([
{
path: '/dogs/:id/details',
methods: [
{
type: 'get', // or MethodType.GET with Typescript
},
],
},
]);
Given a matching HTTP request, e.g. http://localhost:8080/dogs/3/details
, the server will search the following fixtures, sorted by precedence:
data/dogs/3/details.json
data/dogs/:id/details.json
If the request has multiple dynamic params, the precedence is the same, searching the fullly specific fixture, and the fully generic one otherwise.