diff --git a/README.md b/README.md
index cdf3a55..8f59400 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
-[](https://travis-ci.org/typicode/json-server)
-[](http://badge.fury.io/js/json-server)
-
-
+
+
+
# JSON Server
@@ -9,36 +8,43 @@ Give it a JSON or JS seed file and it will serve it through REST routes.
Created with :heart: for front-end developers who need a flexible back-end for quick prototyping and mocking.
+[](https://travis-ci.org/typicode/json-server)
+[](http://badge.fury.io/js/json-server)
+
## Examples
### Command line interface
```bash
-$ cat db.json
+$ json-server --file db.json
+$ curl -i http://localhost:3000/posts/1
+```
+
+```javascript
+// db.json
{
"posts": [
{ "id": 1, "body": "foo" }
]
}
-$ json-server --file db.json
-$ curl -i http://localhost:3000/posts/1
```
-You can type 's' at any moment to save the current live JSON object to timestamped
-file.
-
### Node module
```javascript
var server = require('json-server');
-var db = {
+server.low.db = {
posts: [
{ id: 1, body: 'foo' }
]
}
-server.run(db);
+server.get('/another/route', function(req, res, next) {
+ // ...
+})
+
+server.listen(3000);
```
You can find a running demo here: http://jsonplaceholder.typicode.com.
@@ -58,38 +64,25 @@ You can find a running demo here: http://jsonplaceholder.typicode.com.
$ npm install -g json-server
```
-
## Usage
### Command line interface
```bash
-json-server --help
- Usage: json-server [options]
+ Usage: json-server [options]
Options:
- -h, --help output usage information
- -V, --version output the version number
- -f --file load db from a js or json file
- -u --url load db from a URL
- -p --port [port] server port
- --read-only read only mode
-```
+ --version output version
+ --port set port
-JSON Server can load JSON from multiple sources:
+ Exemples:
-```bash
-$ json-server --file db.json
-$ json-server --file seed.js
-$ json-server --url http://example.com/db.json
-```
-
-And be run in read-only mode (useful if deployed on a public server):
-
-```bash
-$ json-server --file db.json --read-only
+ json-server db.json
+ json-server seed.js
+ json-server http://example.com/db.json
+
```
#### Input
@@ -129,7 +122,6 @@ JSON Server expects JS files to export a ```run``` method that returns an object
Seed files are useful if you need to programmaticaly create a lot of data.
-
### Node module
#### run(db, [options])
@@ -149,7 +141,7 @@ By default, ```port``` is set to 3000 and ```readOnly``` to false.
```
GET /:resource
-GET /:resource?attr=&attr=&
+GET /:resource?filter=&filter=&
GET /:parent/:parentId/:resource
GET /:resource/:id
POST /:resource
@@ -189,4 +181,4 @@ $ npm test
## Articles
-[Fast prototyping using Restangular and Json-server](http://bahmutov.calepin.co/fast-prototyping-using-restangular-and-json-server.html)
+* [Fast prototyping using Restangular and Json-server](http://bahmutov.calepin.co/fast-prototyping-using-restangular-and-json-server.html)
diff --git a/bin/index.js b/bin/index.js
new file mode 100644
index 0000000..b4fd9a8
--- /dev/null
+++ b/bin/index.js
@@ -0,0 +1,11 @@
+#!/usr/bin/env node
+var minimist = require('minimist')
+var updateNotifier = require('update-notifier')
+var cli = require('../src/cli')
+
+var notifier = updateNotifier({packagePath: '../package'})
+if (notifier.update) notifier.notify()
+
+var argv = minimist(process.argv.slice(2))
+
+cli.run(argv)
\ No newline at end of file
diff --git a/db.json b/db.json
new file mode 100644
index 0000000..3641986
--- /dev/null
+++ b/db.json
@@ -0,0 +1,20 @@
+{
+ "posts": [
+ {
+ "id": 2,
+ "body": "bar"
+ }
+ ],
+ "comments": [
+ {
+ "id": 1,
+ "published": true,
+ "postId": 1
+ },
+ {
+ "id": 2,
+ "published": false,
+ "postId": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 455d54b..16895de 100644
--- a/package.json
+++ b/package.json
@@ -2,8 +2,8 @@
"name": "json-server",
"version": "0.2.0",
"description": "Serves JSON files through REST routes.",
- "main": "server.js",
- "bin": "./bin/cli.js",
+ "main": "./src/server.js",
+ "bin": "./bin/index.js",
"directories": {
"test": "test"
},
@@ -15,7 +15,9 @@
"underscore.inflections": "~0.2.1",
"low": "^0.4.2",
"yargs": "^1.2.1",
- "chalk": "^0.4.0"
+ "chalk": "^0.4.0",
+ "minimist": "0.0.8",
+ "update-notifier": "^0.1.8"
},
"devDependencies": {
"supertest": "~0.8.1",
diff --git a/src/command.js b/src/cli.js
similarity index 55%
rename from src/command.js
rename to src/cli.js
index 25d8573..b090fff 100644
--- a/src/command.js
+++ b/src/cli.js
@@ -1,66 +1,87 @@
-
+var fs = require('fs')
var chalk = require('chalk')
-var request = require('request')
+var minimist = require('minimist')
+var request = require('superagent')
var low = require('low')
var server = require('./server')
-function hello() {
- console.log(
- chalk.green('\n{^ ^} Heya!\n')
- )
+// Output version
+function version() {
+ var pkg = require('../package.json')
+ console.log(pkg.version)
}
+// Output help.txt with some colors
+function help() {
+ var txt = fs.readFileSync(__dirname + '/help.txt').toString()
+ txt = txt.replace(/json-server/g, chalk.green('json-server'))
+ console.log(txt)
+}
+
+// Start server
function start(port) {
for (var prop in low.db) {
console.log('http://localhost:' + port + '/' + chalk.green(prop))
}
- server.listen(port)
-}
-
-function run(argv) {
- hello();
-
- var source = argv._[0]
-
- console.log('Loading database from ' + source + '\n')
-
- if (/\.json$/.test(source)) {
- var path = process.cwd() + '/' + source
- low.path = path
- low.db = require(path);
- start(argv.port)
- }
-
- if (/\.js$/.test(source)) {
- var path = process.cwd() + '/' + source
- low.db = require(path).run();
- start(argv.port)
- }
-
- if (/^http/.test(source)) {
- request.get(source)
- .end(function(err, res) {
- if (err) {
- console.error(err)
- } else {
- low.db = JSON.parse(res.text)
- }
- })
- start(argv.port)
- }
-
console.log(
'\nEnter ' + chalk.green('`s`') + ' at any time to create a snapshot of the db\n'
)
process.stdin.resume()
process.stdin.setEncoding('utf8')
-
process.stdin.on('data', function (chunk) {
if (chunk.trim().toLowerCase() === 's') {
- low.save('db-' + Date.now() + '.json')
+ var file = 'db-' + Date.now() + '.json'
+ low.save(file)
+ console.log('\nSaved snapshot to ' + chalk.green(file) + '\n')
}
})
+
+ server.listen(port)
+}
+
+// Load source
+function load(source, port) {
+ console.log(chalk.green('\n{^ ^} Heya!\n'))
+
+ console.log('Loading database from ' + source + '\n')
+
+ if (/\.json$/.test(source)) {
+ var path = process.cwd() + '/' + source
+ low.path = path
+ low.db = require(path);
+ start(port)
+ }
+
+ if (/\.js$/.test(source)) {
+ var path = process.cwd() + '/' + source
+ low.db = require(path).run();
+ start(port)
+ }
+
+ if (/^http/.test(source)) {
+ request
+ .get(source)
+ .end(function(err, res) {
+ if (err) {
+ console.error(err)
+ } else {
+ low.db = JSON.parse(res.text)
+ start(port)
+ }
+ })
+ }
+}
+
+// Uses minimist parsed argv
+function run(argv) {
+ var source = argv._[0]
+ var port = argv.port || 3000
+
+ if (argv.version) return version()
+ if (source) return load(source, port)
+
+ help()
}
module.exports.run = run
diff --git a/src/help.txt b/src/help.txt
new file mode 100644
index 0000000..06fb12b
--- /dev/null
+++ b/src/help.txt
@@ -0,0 +1,14 @@
+
+ Usage: json-server [options]
+
+ Options:
+
+ --version output version
+ --port set port
+
+ Exemples:
+
+ json-server db.json
+ json-server seed.js
+ json-server http://example.com/db.json
+
\ No newline at end of file
diff --git a/src/routes.js b/src/routes.js
new file mode 100644
index 0000000..3546ba2
--- /dev/null
+++ b/src/routes.js
@@ -0,0 +1,81 @@
+var _ = require('underscore')
+var low = require('low')
+var utils = require('./utils')
+
+var routes = {}
+
+// GET /db
+routes.db = function(req, res, next) {
+ res.jsonp(low.db)
+}
+
+// GET /:resource?attr=&attr=
+// GET /:parent/:parentId/:resource
+routes.list = function(req, res, next) {
+ var props = {}
+ var resource
+
+ var _start = req.query._start
+ var _end = req.query._end
+
+ delete req.query._start
+ delete req.query._end
+
+ if (req.params.parent) {
+ props[req.params.parent.slice(0, - 1) + 'Id'] = +req.params.parentId
+ }
+
+ for (var key in req.query) {
+ props[key] = utils.toNative(req.query[key])
+ }
+
+ if (_(props).isEmpty()) {
+ resource = low(req.params.resource).value()
+ } else {
+ resource = low(req.params.resource).where(props).value()
+ }
+
+ if (_start) {
+ resource = resource.slice(_start, _end)
+ }
+
+ res.jsonp(resource)
+}
+
+// GET /:resource/:id
+routes.show = function(req, res, next) {
+ var resource = low(req.params.resource)
+ .get(+req.params.id)
+ .value()
+
+ res.jsonp(resource)
+}
+
+// POST /:resource
+routes.create = function(req, res, next) {
+ var resource = low(req.params.resource)
+ .insert(req.body)
+ .value()
+
+ res.jsonp(resource)
+}
+
+// PUT /:resource/:id
+// PATCH /:resource/:id
+routes.update = function(req, res, next) {
+ var resource = low(req.params.resource)
+ .update(+req.params.id, req.body)
+ .value()
+
+ res.jsonp(resource)
+}
+
+// DELETE /:resource/:id
+routes.destroy = function(req, res, next) {
+ low(req.params.resource).remove(+req.params.id)
+ utils.clean()
+
+ res.send(204)
+}
+
+module.exports = routes
\ No newline at end of file
diff --git a/src/server.js b/src/server.js
index 530900f..dcab263 100644
--- a/src/server.js
+++ b/src/server.js
@@ -1,9 +1,10 @@
var express = require('express')
+var cors = require('cors')
var http = require('http')
var path = require('path')
-var _ = require('underscore')
var low = require('low')
var utils = require('./utils')
+var routes = require('./routes')
low._.createId = utils.createId
@@ -15,104 +16,25 @@ server.use(express.json())
server.use(express.urlencoded())
server.use(express.methodOverride())
server.use(express.static(path.join(__dirname, '../public')))
+server.use(cors())
server.use(server.router)
if ('development' == server.get('env')) {
server.use(express.errorHandler());
}
-routes = {}
+server.get( '/db' , routes.db)
+server.get( '/:resource' , routes.list)
+server.get( '/:parent/:parentId/:resource' , routes.list)
+server.get( '/:resource/:id' , routes.show)
-// GET /db
-routes.db = function(req, res, next) {
- res.jsonp(low.db)
-}
+server.post( '/:resource' , routes.create)
-// GET /:resource?attr=&attr=
-routes.list = function(req, res, next) {
- var properties = {}
- var query
+server.put( '/:resource/:id' , routes.update)
+server.patch('/:resource/:id' , routes.update)
- Object.keys(req.query).forEach(function (key) {
- var value = req.query[key]
- properties[key] = utils.toNative(value)
- })
+server.del( '/:resource/:id' , routes.destroy)
- if (_(properties).isEmpty()) {
- query = low(req.params.resource)
- } else {
- query = low(req.params.resource).where(properties)
- }
-
- res.jsonp(query.value())
-}
-
-// GET /:parent/:parentId/:resource
-routes.nestedList = function(req, res, next) {
- var properties = {}
- var resource
-
- // Set parentID
- properties[req.params.parent.slice(0, - 1) + 'Id'] = +req.params.parentId
-
- // Filter using parentID
- resource = low(req.params.resource)
- .where(properties)
- .value()
-
- res.jsonp(resource)
-}
-
-// GET /:resource/:id
-routes.show = function(req, res, next) {
- var resource = low(req.params.resource)
- .get(+req.params.id)
- .value()
-
- res.jsonp(resource)
-}
-
-// POST /:resource
-routes.create = function(req, res, next) {
- var resource = low(req.params.resource)
- .insert(req.body)
- .value()
-
- res.jsonp(resource)
-}
-
-// PUT /:resource/:id
-// PATCH /:resource/:id
-routes.update = function(req, res, next) {
- var resource = low(req.params.resource)
- .update(+req.params.id, req.body)
- .value()
-
- res.jsonp(resource)
-}
-
-// DELETE /:resource/:id
-routes.destroy = function(req, res, next) {
- low(req.params.resource).remove(+req.params.id)
- utils.clean()
-
- res.send(204)
-}
-
-server.get('/db', routes.db)
-server.get('/:resource', routes.list)
-server.get('/:parent/:parentId/:resource', routes.nestedList)
-server.get('/:resource/:id', routes.show)
-server.post('/:resource', routes.create)
-server.put('/:resource/:id', routes.update)
-server.patch('/:resource/:id', routes.update)
-server.del('/:resource/:id', routes.destroy)
-
-server.on('after', function (req, res, route, err) {
- var latency = Date.now() - req.time()
- console.log('%s %s %s - %sms',
- req.method, req.url, res.statusCode, latency
- )
-})
+server.low = low
module.exports = server
\ No newline at end of file
diff --git a/test/server.js b/test/server.js
index 2a6100c..7c7e373 100644
--- a/test/server.js
+++ b/test/server.js
@@ -52,6 +52,16 @@ describe('Server', function() {
})
})
+ describe.only('GET /:resource?_start=&_end=', function() {
+ it('should respond with sliced array', function(done) {
+ request(server)
+ .get('/comments?_start=1&_end=2')
+ .expect('Content-Type', /json/)
+ .expect(low.db.comments.slice(1, 2))
+ .expect(200, done)
+ })
+ })
+
describe('GET /:parent/:parentId/:resource', function() {
it('should respond with json and corresponding nested resources', function(done) {
request(server)