json-server 0.9.4 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,73 @@
1
+ html {
2
+ font-size: 70%;
3
+ }
4
+
5
+ body {
6
+ display: flex;
7
+ min-height: 100vh;
8
+ flex-direction: column;
9
+ padding:0;
10
+ margin: 0;
11
+ color: #333;
12
+ letter-spacing: 0;
13
+ }
14
+
15
+ header {
16
+ padding-top: 2.0rem;
17
+ border-bottom: 1px solid #EEE;
18
+ }
19
+
20
+ header a, header a:hover {
21
+ text-decoration: none;
22
+ }
23
+
24
+ main {
25
+ flex: 1;
26
+ }
27
+
28
+ footer {
29
+ padding-top: 2.5rem;
30
+ border-top: 1px solid #EEE;
31
+ }
32
+
33
+ h4 {
34
+ margin-top: 4rem;
35
+ }
36
+
37
+ a {
38
+ color: #0275d8;
39
+ }
40
+
41
+ a:hover {
42
+ color: #014c8c;
43
+ text-decoration: underline;
44
+ }
45
+
46
+ table {
47
+ margin-left: 0;
48
+ }
49
+
50
+ td {
51
+ border: 0;
52
+ padding: 0 1em .5em 0;
53
+ color: #014c8c;
54
+ }
55
+
56
+ td:first-child {
57
+ width: 1%;
58
+ white-space: nowrap;
59
+ }
60
+
61
+ ul {
62
+ list-style-position: inside;
63
+ padding-left: 0;
64
+ }
65
+
66
+ li {
67
+ list-style-type: none;
68
+ margin-bottom: .2rem;
69
+ }
70
+
71
+ code {
72
+ border-radius: 0;
73
+ }
@@ -9,6 +9,10 @@ function updateQueryString(target, sourceUrl) {
9
9
  module.exports = function (routes) {
10
10
  var router = express.Router();
11
11
 
12
+ router.get('/__rules', function (req, res) {
13
+ res.json(routes);
14
+ });
15
+
12
16
  Object.keys(routes).forEach(function (route) {
13
17
  if (route.indexOf(':') !== -1) {
14
18
  router.all(route, function (req, res, next) {
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ var url = require('url');
4
+
5
+ module.exports = function getFullURL(req) {
6
+ var root = url.format({
7
+ protocol: req.protocol,
8
+ host: req.get('host')
9
+ });
10
+
11
+ return `${root}${req.originalUrl}`;
12
+ };
@@ -1,13 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
4
-
5
3
  var express = require('express');
6
4
  var methodOverride = require('method-override');
7
5
  var _ = require('lodash');
8
- var _db = require('underscore-db');
6
+ var lodashId = require('lodash-id');
9
7
  var low = require('lowdb');
10
- var fileAsync = require('lowdb/lib/file-async');
8
+ var fileAsync = require('lowdb/lib/storages/file-async');
11
9
  var bodyParser = require('../body-parser');
12
10
  var validateData = require('./validate-data');
13
11
  var plural = require('./plural');
@@ -34,8 +32,8 @@ module.exports = function (source) {
34
32
 
35
33
  validateData(db.getState());
36
34
 
37
- // Add underscore-db methods to db
38
- db._.mixin(_db);
35
+ // Add lodash-id methods to db
36
+ db._.mixin(lodashId);
39
37
 
40
38
  // Add specific mixins
41
39
  db._.mixin(mixins);
@@ -59,16 +57,16 @@ module.exports = function (source) {
59
57
  // Create routes
60
58
  db.forEach(function (value, key) {
61
59
  if (_.isPlainObject(value)) {
62
- router.use('/' + key, singular(db, key));
60
+ router.use(`/${key}`, singular(db, key));
63
61
  return;
64
62
  }
65
63
 
66
64
  if (_.isArray(value)) {
67
- router.use('/' + key, plural(db, key));
65
+ router.use(`/${key}`, plural(db, key));
68
66
  return;
69
67
  }
70
68
 
71
- var msg = 'Type of "' + key + '" (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + (_.isObject(source) ? '' : 'in ' + source) + ' is not supported. ' + 'Use objects or arrays of objects.';
69
+ var msg = `Type of "${key}" (${typeof value}) ` + (_.isObject(source) ? '' : `in ${source}`) + ' is not supported. ' + 'Use objects or arrays of objects.';
72
70
 
73
71
  throw new Error(msg);
74
72
  }).value();
@@ -9,16 +9,16 @@ module.exports = function () {
9
9
  // Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
10
10
  function get(req, res, next) {
11
11
  var prop = pluralize.singular(req.params.resource);
12
- req.query[prop + 'Id'] = req.params.id;
13
- req.url = '/' + req.params.nested;
12
+ req.query[`${prop}Id`] = req.params.id;
13
+ req.url = `/${req.params.nested}`;
14
14
  next();
15
15
  }
16
16
 
17
17
  // Rewrite URL (/:resource/:id/:nested -> /:nested) and request body
18
18
  function post(req, res, next) {
19
19
  var prop = pluralize.singular(req.params.resource);
20
- req.body[prop + 'Id'] = req.params.id;
21
- req.url = '/' + req.params.nested;
20
+ req.body[`${prop}Id`] = req.params.id;
21
+ req.url = `/${req.params.nested}`;
22
22
  next();
23
23
  }
24
24
 
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var url = require('url');
4
3
  var express = require('express');
5
4
  var _ = require('lodash');
6
5
  var pluralize = require('pluralize');
6
+ var write = require('./write');
7
+ var getFullURL = require('./get-full-url');
7
8
  var utils = require('../utils');
8
9
 
9
10
  module.exports = function (db, name) {
@@ -16,7 +17,7 @@ module.exports = function (db, name) {
16
17
  if (db.get(externalResource).value) {
17
18
  var query = {};
18
19
  var singularResource = pluralize.singular(name);
19
- query[singularResource + 'Id'] = resource.id;
20
+ query[`${singularResource}Id`] = resource.id;
20
21
  resource[externalResource] = db.get(externalResource).filter(query).value();
21
22
  }
22
23
  });
@@ -27,21 +28,12 @@ module.exports = function (db, name) {
27
28
  e && [].concat(e).forEach(function (innerResource) {
28
29
  var plural = pluralize(innerResource);
29
30
  if (db.get(plural).value()) {
30
- var prop = innerResource + 'Id';
31
+ var prop = `${innerResource}Id`;
31
32
  resource[innerResource] = db.get(plural).getById(resource[prop]).value();
32
33
  }
33
34
  });
34
35
  }
35
36
 
36
- function getFullURL(req) {
37
- var root = url.format({
38
- protocol: req.protocol,
39
- host: req.get('host')
40
- });
41
-
42
- return '' + root + req.originalUrl;
43
- }
44
-
45
37
  // GET /name
46
38
  // GET /name?q=
47
39
  // GET /name?attr=&attr=
@@ -84,6 +76,10 @@ module.exports = function (db, name) {
84
76
 
85
77
  if (q) {
86
78
  // Full-text search
79
+ if (Array.isArray(q)) {
80
+ q = q[0];
81
+ }
82
+
87
83
  q = q.toLowerCase();
88
84
 
89
85
  chain = chain.filter(function (obj) {
@@ -100,52 +96,49 @@ module.exports = function (db, name) {
100
96
  // Don't take into account JSONP query parameters
101
97
  // jQuery adds a '_' query parameter too
102
98
  if (key !== 'callback' && key !== '_') {
103
- (function () {
104
- // Always use an array, in case req.query is an array
105
- var arr = [].concat(req.query[key]);
106
-
107
- chain = chain.filter(function (element) {
108
- return arr.map(function (value) {
109
- var isDifferent = /_ne$/.test(key);
110
- var isRange = /_lte$/.test(key) || /_gte$/.test(key);
111
- var isLike = /_like$/.test(key);
112
- var path = key.replace(/(_lte|_gte|_ne|_like)$/, '');
113
- var elementValue = _.get(element, path);
114
-
115
- if (elementValue === undefined) {
116
- return;
117
- }
118
-
119
- if (isRange) {
120
- var isLowerThan = /_gte$/.test(key);
121
-
122
- return isLowerThan ? value <= elementValue : value >= elementValue;
123
- } else if (isDifferent) {
124
- return value !== elementValue.toString();
125
- } else if (isLike) {
126
- return new RegExp(value, 'i').test(elementValue.toString());
127
- } else {
128
- return value === elementValue.toString();
129
- }
130
- }).reduce(function (a, b) {
131
- return a || b;
132
- });
99
+ // Always use an array, in case req.query is an array
100
+ var arr = [].concat(req.query[key]);
101
+
102
+ chain = chain.filter(function (element) {
103
+ return arr.map(function (value) {
104
+ var isDifferent = /_ne$/.test(key);
105
+ var isRange = /_lte$/.test(key) || /_gte$/.test(key);
106
+ var isLike = /_like$/.test(key);
107
+ var path = key.replace(/(_lte|_gte|_ne|_like)$/, '');
108
+ // get item value based on path
109
+ // i.e post.title -> 'foo'
110
+ var elementValue = _.get(element, path);
111
+
112
+ // Prevent toString() failing on undefined or null values
113
+ if (elementValue === undefined || elementValue === null) {
114
+ return;
115
+ }
116
+
117
+ if (isRange) {
118
+ var isLowerThan = /_gte$/.test(key);
119
+
120
+ return isLowerThan ? value <= elementValue : value >= elementValue;
121
+ } else if (isDifferent) {
122
+ return value !== elementValue.toString();
123
+ } else if (isLike) {
124
+ return new RegExp(value, 'i').test(elementValue.toString());
125
+ } else {
126
+ return value === elementValue.toString();
127
+ }
128
+ }).reduce(function (a, b) {
129
+ return a || b;
133
130
  });
134
- })();
131
+ });
135
132
  }
136
133
  });
137
134
 
138
135
  // Sort
139
136
  if (_sort) {
140
- _order = _order || 'ASC';
141
-
142
- chain = chain.sortBy(function (element) {
143
- return _.get(element, _sort);
137
+ var _sortSet = _sort.split(',');
138
+ var _orderSet = (_order || '').split(',').map(function (s) {
139
+ return s.toLowerCase();
144
140
  });
145
-
146
- if (_order === 'DESC') {
147
- chain = chain.reverse();
148
- }
141
+ chain = chain.orderBy(_sortSet, _orderSet);
149
142
  }
150
143
 
151
144
  // Slice result
@@ -229,8 +222,12 @@ module.exports = function (db, name) {
229
222
  function create(req, res, next) {
230
223
  var resource = db.get(name).insert(req.body).value();
231
224
 
225
+ res.setHeader('Access-Control-Expose-Headers', 'Location');
226
+ res.location(`${getFullURL(req)}/${resource.id}`);
227
+
232
228
  res.status(201);
233
229
  res.locals.data = resource;
230
+
234
231
  next();
235
232
  }
236
233
 
@@ -269,9 +266,11 @@ module.exports = function (db, name) {
269
266
  next();
270
267
  }
271
268
 
272
- router.route('/').get(list).post(create);
269
+ var w = write(db);
270
+
271
+ router.route('/').get(list).post(create, w);
273
272
 
274
- router.route('/:id').get(show).put(update).patch(update).delete(destroy);
273
+ router.route('/:id').get(show).put(update, w).patch(update, w).delete(destroy, w);
275
274
 
276
275
  return router;
277
276
  };
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var express = require('express');
4
+ var write = require('./write');
5
+ var getFullURL = require('./get-full-url');
4
6
 
5
7
  module.exports = function (db, name) {
6
8
  var router = express.Router();
@@ -13,6 +15,10 @@ module.exports = function (db, name) {
13
15
  function create(req, res, next) {
14
16
  db.set(name, req.body).value();
15
17
  res.locals.data = db.get(name).value();
18
+
19
+ res.setHeader('Access-Control-Expose-Headers', 'Location');
20
+ res.location(`${getFullURL(req)}`);
21
+
16
22
  res.status(201);
17
23
  next();
18
24
  }
@@ -28,7 +34,9 @@ module.exports = function (db, name) {
28
34
  next();
29
35
  }
30
36
 
31
- router.route('/').get(show).post(create).put(update).patch(update);
37
+ var w = write(db);
38
+
39
+ router.route('/').get(show).post(create, w).put(update, w).patch(update, w);
32
40
 
33
41
  return router;
34
42
  };
@@ -1,12 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
4
-
5
3
  var _ = require('lodash');
6
4
 
7
5
  function validateKey(key) {
8
6
  if (key.indexOf('/') !== -1) {
9
- var msg = ['Oops, found / character in database property \'' + key + '\'.', '', '/ aren\'t supported, if you want to tweak default routes, see', 'https://github.com/typicode/json-server/tree/next#add-custom-routes'].join('\n');
7
+ var msg = [`Oops, found / character in database property '${key}'.`, '', '/ aren\'t supported, if you want to tweak default routes, see', 'https://github.com/typicode/json-server/#add-custom-routes'].join('\n');
10
8
  throw new Error(msg);
11
9
  }
12
10
  }
@@ -15,6 +13,6 @@ module.exports = function (obj) {
15
13
  if (_.isPlainObject(obj)) {
16
14
  Object.keys(obj).forEach(validateKey);
17
15
  } else {
18
- throw new Error('Data must be an object. Found ' + (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) + '.' + 'See https://github.com/typicode/json-server for example.');
16
+ throw new Error(`Data must be an object. Found ${typeof obj}.` + 'See https://github.com/typicode/json-server for example.');
19
17
  }
20
18
  };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ module.exports = function write(db) {
4
+ return function (req, res, next) {
5
+ db.write();
6
+ next();
7
+ };
8
+ };
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  module.exports = {
4
- getPage: getPage
4
+ getPage
5
5
  };
6
6
 
7
7
  function getPage(array, page, perPage) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-server",
3
- "version": "0.9.4",
3
+ "version": "0.10.1",
4
4
  "description": "Serves JSON files through REST routes.",
5
5
  "main": "./lib/server/index.js",
6
6
  "bin": "./bin/index.js",
@@ -17,7 +17,8 @@
17
17
  "express": "^4.9.5",
18
18
  "json-parse-helpfulerror": "^1.0.3",
19
19
  "lodash": "^4.11.2",
20
- "lowdb": "^0.14.0",
20
+ "lodash-id": "^0.13.0",
21
+ "lowdb": "^0.15.0",
21
22
  "method-override": "^2.1.2",
22
23
  "morgan": "^1.3.1",
23
24
  "object-assign": "^4.0.1",
@@ -25,35 +26,35 @@
25
26
  "request": "^2.72.0",
26
27
  "server-destroy": "^1.0.1",
27
28
  "shortid": "^2.2.6",
28
- "underscore-db": "^0.12.2",
29
29
  "update-notifier": "^1.0.2",
30
30
  "yargs": "^6.0.0"
31
31
  },
32
32
  "devDependencies": {
33
- "babel-cli": "^6.10.1",
34
- "babel-preset-es2015": "^6.16.0",
33
+ "babel-cli": "^6.24.0",
34
+ "babel-preset-env": "^1.3.2",
35
35
  "babel-register": "^6.16.3",
36
36
  "cross-env": "^2.0.1",
37
- "husky": "^0.11.4",
37
+ "husky": "^0.13.0",
38
38
  "markdown-toc": "^0.13.0",
39
39
  "mkdirp": "^0.5.1",
40
- "mocha": "^3.1.2",
40
+ "mocha": "^3.2.0",
41
41
  "os-tmpdir": "^1.0.1",
42
+ "pkg-ok": "^1.0.1",
42
43
  "rimraf": "^2.5.2",
43
44
  "server-ready": "^0.3.1",
44
45
  "standard": "^8.3.0",
45
- "supertest": "^2.0.0",
46
+ "supertest": "^3.0.0",
46
47
  "temp-write": "^2.1.0"
47
48
  },
48
49
  "scripts": {
49
- "test": "npm run test:cli && npm run test:server && standard --fix",
50
+ "test": "npm run test:cli && npm run test:server && standard",
50
51
  "test:cli": "npm run build && cross-env NODE_ENV=test mocha test/cli/*.js",
51
52
  "test:server": "cross-env NODE_ENV=test mocha test/server/*.js",
52
- "start": "node bin",
53
- "prepush": "npm t",
53
+ "start": "babel-node src/cli/bin",
54
+ "precommit": "npm test",
54
55
  "build": "babel src -d lib --copy-files",
55
56
  "toc": "markdown-toc -i README.md",
56
- "prepublish": "npm run build"
57
+ "prepublish": "npm run build && pkg-ok"
57
58
  },
58
59
  "repository": {
59
60
  "type": "git",
@@ -88,6 +89,6 @@
88
89
  }
89
90
  },
90
91
  "engines": {
91
- "node": ">= 0.12"
92
+ "node": ">= 4"
92
93
  }
93
94
  }
package/routes.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "/api/": "/",
3
+ "/blog/:resource/:id/show": "/:resource/:id",
4
+ "/blog/:category": "/posts?category=:category"
5
+ }
package/test/mocha.opts CHANGED
@@ -1,3 +1,3 @@
1
- --compilers js:babel-register
1
+ --require babel-register
2
2
  --reporter spec
3
- --timeout 5000
3
+ --timeout 5000
@@ -1,13 +1,13 @@
1
1
  const assert = require('assert')
2
2
  const _ = require('lodash')
3
- const _db = require('underscore-db')
3
+ const lodashId = require('lodash-id')
4
4
  const mixins = require('../../src/server/mixins')
5
5
 
6
6
  describe('mixins', () => {
7
7
  let db
8
8
 
9
9
  before(() => {
10
- _.mixin(_db)
10
+ _.mixin(lodashId)
11
11
  _.mixin(mixins)
12
12
  })
13
13