function create() {
return express().set('json spaces', 2);
}...
```sh
$ npm install json-server --save-dev
```
```js
// server.js
var jsonServer = require('json-server')
var server = jsonServer.create()
var router = jsonServer.router('db.json')
var middlewares = jsonServer.defaults()
server.use(middlewares)
server.use(router)
server.listen(3000, function () {
console.log('JSON Server is running')
...defaults = function (opts) {
var userDir = path.join(process.cwd(), 'public');
var defaultDir = path.join(__dirname, 'public');
var staticDir = fs.existsSync(userDir) ? userDir : defaultDir;
opts = objectAssign({ logger: true, static: staticDir }, opts);
var arr = [];
// Compress all requests
if (!opts.noGzip) {
arr.push(compression());
}
// Logger
if (opts.logger) {
arr.push(logger('dev', {
skip: function skip(req) {
return process.env.NODE_ENV === 'test' || req.path === '/favicon.ico';
}
}));
}
// Enable CORS for all the requests, including static files
if (!opts.noCors) {
arr.push(cors({ origin: true, credentials: true }));
}
if (process.env.NODE_ENV === 'development') {
// only use in development
arr.push(errorhandler());
}
// Serve static files
arr.push(express.static(opts.static));
// No cache for IE
// https://support.microsoft.com/en-us/kb/234067
arr.push(function (req, res, next) {
res.header('Cache-Control', 'no-cache');
res.header('Pragma', 'no-cache');
res.header('Expires', '-1');
next();
});
// Read-only
if (opts.readOnly) {
arr.push(function (req, res, next) {
if (req.method === 'GET') {
next(); // Continue
} else {
res.sendStatus(403); // Forbidden
}
});
}
return arr;
}...
```
```js
// server.js
var jsonServer = require('json-server')
var server = jsonServer.create()
var router = jsonServer.router('db.json')
var middlewares = jsonServer.defaults()
server.use(middlewares)
server.use(router)
server.listen(3000, function () {
console.log('JSON Server is running')
})
```
...rewriter = function (routes) {
var router = express.Router();
router.get('/__rules', function (req, res) {
res.json(routes);
});
Object.keys(routes).forEach(function (route) {
if (route.indexOf(':') !== -1) {
router.all(route, function (req, res, next) {
// Rewrite target url using params
var target = routes[route];
for (var param in req.params) {
target = target.replace(':' + param, req.params[param]);
}
req.url = target;
req.query = updateQueryString(req.query, req.url);
next();
});
} else {
router.all(route + '*', function (req, res, next) {
// Rewrite url by replacing prefix
req.url = req.url.replace(route, routes[route]);
req.query = updateQueryString(req.query, req.url);
next();
});
}
});
return router;
}...
body: res.locals.data
})
}
```
#### Rewriter example
To add rewrite rules, use `jsonServer.rewriter()`:
```javascript
// Add this before server.use(router)
server.use(jsonServer.rewriter({
'/api/': '/',
'/blog/:resource/:id/show': '/:resource/:id'
}))
...router = function (source) {
// Create router
var router = express.Router();
// Add middlewares
router.use(methodOverride());
router.use(bodyParser);
// Create database
var db = void 0;
if (_.isObject(source)) {
db = low();
db.setState(source);
} else {
db = low(source, { storage: fileAsync });
}
validateData(db.getState());
// Add lodash-id methods to db
db._.mixin(lodashId);
// Add specific mixins
db._.mixin(mixins);
// Expose database
router.db = db;
// Expose render
router.render = function (req, res) {
res.jsonp(res.locals.data);
};
// GET /db
router.get('/db', function (req, res) {
res.jsonp(db.getState());
});
// Handle /:parent/:parentId/:resource
router.use(nested());
// Create routes
db.forEach(function (value, key) {
if (_.isPlainObject(value)) {
router.use('/' + key, singular(db, key));
return;
}
if (_.isArray(value)) {
router.use('/' + key, plural(db, key));
return;
}
var msg = 'Type of "' + key + '" (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + (_.isObject(source
) ? '' : 'in ' + source) + ' is not supported. ' + 'Use objects or arrays of objects.';
throw new Error(msg);
}).value();
router.use(function (req, res) {
if (!res.locals.data) {
res.status(404);
res.locals.data = {};
}
router.render(req, res);
});
router.use(function (err, req, res, next) {
console.error(err.stack);
res.status(500).send(err.stack);
});
return router;
}...
$ npm install json-server --save-dev
```
```js
// server.js
var jsonServer = require('json-server')
var server = jsonServer.create()
var router = jsonServer.router('db.json')
var middlewares = jsonServer.defaults()
server.use(middlewares)
server.use(router)
server.listen(3000, function () {
console.log('JSON Server is running')
})
...function jsonParser(req, res, next) {
if (req._body) {
debug('body already parsed')
next()
return
}
req.body = req.body || {}
// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}
debug('content-type %j', req.headers['content-type'])
// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}
// assert charset per RFC 7159 sec 8.1
var charset = getCharset(req) || 'utf-8'
if (charset.substr(0, 4) !== 'utf-') {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
charset: charset
}))
return
}
// read
read(req, res, next, parse, debug, {
encoding: charset,
inflate: inflate,
limit: limit,
verify: verify
})
}n/a
function urlencodedParser(req, res, next) {
if (req._body) {
debug('body already parsed')
next()
return
}
req.body = req.body || {}
// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}
debug('content-type %j', req.headers['content-type'])
// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}
// assert charset
var charset = getCharset(req) || 'utf-8'
if (charset !== 'utf-8') {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
charset: charset
}))
return
}
// read
read(req, res, next, parse, debug, {
debug: debug,
encoding: charset,
inflate: inflate,
limit: limit,
verify: verify
})
}n/a
function JS(s) {
return !URL(s) && /\.js$/.test(s);
}...
json: true
};
request(opts, function (err, response) {
if (err) return cb(err);
cb(null, response.body);
});
} else if (is.JS(source)) {
// Clear cache
var filename = path.resolve(source);
delete require.cache[filename];
var dataFn = require(filename);
if (typeof dataFn !== 'function') {
throw new Error('The database is a JavaScript file but the export is not a function.');
...function JSON(s) {
return !URL(s) && /\.json$/.test(s);
}...
function createApp(source, object, routes, middlewares, argv) {
var app = jsonServer.create();
var router = void 0;
try {
router = jsonServer.router(is.JSON(source) ? source : object);
} catch (e) {
console.log();
console.error(chalk.red(e.message.replace(/^/gm, ' ')));
process.exit(1);
}
var defaultsOpts = {
...function URL(s) {
return (/^(http|https):/.test(s)
);
}...
if (argv.watch) {
(function () {
console.log(chalk.gray(' Watching...'));
console.log();
var source = argv._[0];
// Can't watch URL
if (is.URL(source)) throw new Error('Can\'t watch URL');
// Watch .js or .json file
// Since lowdb uses atomic writing, directory is watched instead of file
var watchedDir = path.dirname(source);
var readError = false;
fs.watch(watchedDir, function (event, file) {
// https://github.com/typicode/json-server/issues/420
...function createId(coll) {
var _ = this;
var idProperty = _.__id();
if (_.isEmpty(coll)) {
return 1;
} else {
var id = _(coll).maxBy(idProperty)[idProperty];
// Increment integer id or generate string id
return _.isFinite(id) ? ++id : shortid.generate();
}
}n/a
function deepQuery(value, q) {
var _ = this;
if (value && q) {
if (_.isArray(value)) {
for (var i = 0; i < value.length; i++) {
if (_.deepQuery(value[i], q)) {
return true;
}
}
} else if (_.isObject(value) && !_.isArray(value)) {
for (var k in value) {
if (_.deepQuery(value[k], q)) {
return true;
}
}
} else if (value.toString().toLowerCase().indexOf(q) !== -1) {
return true;
}
}
}...
}
function deepQuery(value, q) {
var _ = this;
if (value && q) {
if (_.isArray(value)) {
for (var i = 0; i < value.length; i++) {
if (_.deepQuery(value[i], q)) {
return true;
}
}
} else if (_.isObject(value) && !_.isArray(value)) {
for (var k in value) {
if (_.deepQuery(value[k], q)) {
return true;
...function getRemovable(db) {
var _ = this;
var removable = [];
_.each(db, function (coll, collName) {
_.each(coll, function (doc) {
_.each(doc, function (value, key) {
if (/Id$/.test(key)) {
var refName = pluralize.plural(key.slice(0, -2));
// Test if table exists
if (db[refName]) {
// Test if references is defined in table
var ref = _.getById(db[refName], value);
if (_.isUndefined(ref)) {
removable.push({ name: collName, id: doc.id });
}
}
}
});
});
});
return removable;
}...
}
// DELETE /name/:id
function destroy(req, res, next) {
var resource = db.get(name).removeById(req.params.id).value();
// Remove dependents documents
var removable = db._.getRemovable(db.getState());
removable.forEach(function (item) {
db.get(item.name).removeById(item.id).value();
});
if (resource) {
res.locals.data = {};
...function getPage(array, page, perPage) {
var obj = {};
var start = (page - 1) * perPage;
var end = page * perPage;
obj.items = array.slice(start, end);
if (obj.items.length === 0) {
return obj;
}
if (page > 1) {
obj.prev = page - 1;
}
if (end < array.length) {
obj.next = page + 1;
}
if (obj.items.length !== array.length) {
obj.current = page;
obj.first = 1;
obj.last = Math.ceil(array.length / perPage);
}
return obj;
}...
res.setHeader('Access-Control-Expose-Headers', 'X-Total-Count' + (_page ? ', Link' : ''));
}
if (_page) {
_page = parseInt(_page, 10);
_page = _page >= 1 ? _page : 1;
_limit = parseInt(_limit, 10) || 10;
var page = utils.getPage(chain.value(), _page, _limit);
var links = {};
var fullURL = getFullURL(req);
if (page.first) {
links.first = fullURL.replace('page=' + page.current, 'page=' + page.first);
}
...