json-server 0.13.0 → 0.15.0
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.
- package/.babelrc +2 -1
- package/.eslintrc.js +2 -2
- package/.travis.yml +1 -1
- package/CHANGELOG.md +19 -0
- package/README.md +57 -23
- package/dist/index.html +74 -45
- package/dist/main.css +110 -8
- package/dist/main.js +1 -1
- package/lib/cli/bin.js +4 -1
- package/lib/cli/index.js +8 -3
- package/lib/cli/run.js +59 -75
- package/lib/cli/utils/is.js +3 -4
- package/lib/cli/utils/load.js +65 -32
- package/lib/front/index.js +58 -102
- package/lib/server/body-parser.js +7 -2
- package/lib/server/defaults.js +29 -20
- package/lib/server/index.js +1 -1
- package/lib/server/mixins.js +24 -13
- package/lib/server/rewriter.js +2 -4
- package/lib/server/router/delay.js +2 -1
- package/lib/server/router/get-full-url.js +1 -2
- package/lib/server/router/index.js +39 -37
- package/lib/server/router/nested.js +6 -5
- package/lib/server/router/plural.js +87 -59
- package/lib/server/router/singular.js +29 -11
- package/lib/server/router/validate-data.js +1 -1
- package/lib/server/utils.js +1 -1
- package/package.json +62 -62
- package/postinstall.js +4 -0
- package/webpack.config.js +1 -1
- package/bin/index.js +0 -3
package/lib/server/mixins.js
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
const nanoid = require('nanoid');
|
|
4
|
+
|
|
4
5
|
const pluralize = require('pluralize');
|
|
5
6
|
|
|
6
7
|
module.exports = {
|
|
7
8
|
getRemovable,
|
|
8
9
|
createId,
|
|
9
|
-
deepQuery
|
|
10
|
-
|
|
11
|
-
// Returns document ids that have unsatisfied relations
|
|
10
|
+
deepQuery // Returns document ids that have unsatisfied relations
|
|
12
11
|
// Example: a comment that references a post that doesn't exist
|
|
13
|
-
|
|
12
|
+
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function getRemovable(db, opts) {
|
|
14
16
|
const _ = this;
|
|
17
|
+
|
|
15
18
|
const removable = [];
|
|
19
|
+
|
|
16
20
|
_.each(db, (coll, collName) => {
|
|
17
21
|
_.each(coll, doc => {
|
|
18
22
|
_.each(doc, (value, key) => {
|
|
19
23
|
if (new RegExp(`${opts.foreignKeySuffix}$`).test(key)) {
|
|
20
24
|
// Remove foreign key suffix and pluralize it
|
|
21
25
|
// Example postId -> posts
|
|
22
|
-
const refName = pluralize.plural(key.replace(new RegExp(`${opts.foreignKeySuffix}$`), ''));
|
|
23
|
-
|
|
26
|
+
const refName = pluralize.plural(key.replace(new RegExp(`${opts.foreignKeySuffix}$`), '')); // Test if table exists
|
|
27
|
+
|
|
24
28
|
if (db[refName]) {
|
|
25
29
|
// Test if references is defined in table
|
|
26
30
|
const ref = _.getById(db[refName], value);
|
|
31
|
+
|
|
27
32
|
if (_.isUndefined(ref)) {
|
|
28
|
-
removable.push({
|
|
33
|
+
removable.push({
|
|
34
|
+
name: collName,
|
|
35
|
+
id: doc.id
|
|
36
|
+
});
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
}
|
|
@@ -34,25 +42,28 @@ module.exports = {
|
|
|
34
42
|
});
|
|
35
43
|
|
|
36
44
|
return removable;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Return incremented id or uuid
|
|
45
|
+
} // Return incremented id or uuid
|
|
40
46
|
// Used to override lodash-id's createId with utils.createId
|
|
47
|
+
|
|
48
|
+
|
|
41
49
|
function createId(coll) {
|
|
42
50
|
const _ = this;
|
|
51
|
+
|
|
43
52
|
const idProperty = _.__id();
|
|
53
|
+
|
|
44
54
|
if (_.isEmpty(coll)) {
|
|
45
55
|
return 1;
|
|
46
56
|
} else {
|
|
47
|
-
let id = _(coll).maxBy(idProperty)[idProperty];
|
|
57
|
+
let id = _(coll).maxBy(idProperty)[idProperty]; // Increment integer id or generate string id
|
|
58
|
+
|
|
48
59
|
|
|
49
|
-
// Increment integer id or generate string id
|
|
50
60
|
return _.isFinite(id) ? ++id : nanoid(7);
|
|
51
61
|
}
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
function deepQuery(value, q) {
|
|
55
65
|
const _ = this;
|
|
66
|
+
|
|
56
67
|
if (value && q) {
|
|
57
68
|
if (_.isArray(value)) {
|
|
58
69
|
for (let i = 0; i < value.length; i++) {
|
package/lib/server/rewriter.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
const express = require('express');
|
|
4
|
+
|
|
4
5
|
const rewrite = require('express-urlrewrite');
|
|
5
6
|
|
|
6
7
|
module.exports = routes => {
|
|
7
8
|
const router = express.Router();
|
|
8
|
-
|
|
9
9
|
router.get('/__rules', (req, res) => {
|
|
10
10
|
res.json(routes);
|
|
11
11
|
});
|
|
12
|
-
|
|
13
12
|
Object.keys(routes).forEach(key => {
|
|
14
13
|
router.use(rewrite(key, routes[key]));
|
|
15
14
|
});
|
|
16
|
-
|
|
17
15
|
return router;
|
|
18
16
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
const pause = require('connect-pause');
|
|
4
4
|
|
|
@@ -6,6 +6,7 @@ module.exports = function delay(req, res, next) {
|
|
|
6
6
|
// NOTE: for some reason unknown to me, if the default is 0, the tests seems to add 2 seconds
|
|
7
7
|
// NOTE: to each test, a default value of 1 does not seem to be effected by that issue
|
|
8
8
|
const _delay = !isNaN(parseFloat(req.query._delay)) ? parseFloat(req.query._delay) : 1;
|
|
9
|
+
|
|
9
10
|
delete req.query._delay;
|
|
10
11
|
pause(_delay)(req, res, next);
|
|
11
12
|
};
|
|
@@ -1,63 +1,70 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
const express = require('express');
|
|
4
|
+
|
|
4
5
|
const methodOverride = require('method-override');
|
|
6
|
+
|
|
5
7
|
const _ = require('lodash');
|
|
8
|
+
|
|
6
9
|
const lodashId = require('lodash-id');
|
|
10
|
+
|
|
7
11
|
const low = require('lowdb');
|
|
8
|
-
|
|
12
|
+
|
|
13
|
+
const Memory = require('lowdb/adapters/Memory');
|
|
14
|
+
|
|
15
|
+
const FileSync = require('lowdb/adapters/FileSync');
|
|
16
|
+
|
|
9
17
|
const bodyParser = require('../body-parser');
|
|
18
|
+
|
|
10
19
|
const validateData = require('./validate-data');
|
|
20
|
+
|
|
11
21
|
const plural = require('./plural');
|
|
22
|
+
|
|
12
23
|
const nested = require('./nested');
|
|
24
|
+
|
|
13
25
|
const singular = require('./singular');
|
|
26
|
+
|
|
14
27
|
const mixins = require('../mixins');
|
|
15
28
|
|
|
16
|
-
module.exports = (
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
module.exports = (db, opts = {
|
|
30
|
+
foreignKeySuffix: 'Id',
|
|
31
|
+
_isFake: false
|
|
32
|
+
}) => {
|
|
33
|
+
if (typeof db === 'string') {
|
|
34
|
+
db = low(new FileSync(db));
|
|
35
|
+
} else if (!_.has(db, '__chain__') || !_.has(db, '__wrapped__')) {
|
|
36
|
+
db = low(new Memory()).setState(db);
|
|
37
|
+
} // Create router
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const router = express.Router(); // Add middlewares
|
|
19
41
|
|
|
20
|
-
// Add middlewares
|
|
21
42
|
router.use(methodOverride());
|
|
22
43
|
router.use(bodyParser);
|
|
44
|
+
validateData(db.getState()); // Add lodash-id methods to db
|
|
23
45
|
|
|
24
|
-
//
|
|
25
|
-
let db;
|
|
26
|
-
if (_.isObject(source)) {
|
|
27
|
-
db = low();
|
|
28
|
-
db.setState(source);
|
|
29
|
-
} else {
|
|
30
|
-
db = low(source, { storage: fileAsync });
|
|
31
|
-
}
|
|
46
|
+
db._.mixin(lodashId); // Add specific mixins
|
|
32
47
|
|
|
33
|
-
validateData(db.getState());
|
|
34
48
|
|
|
35
|
-
//
|
|
36
|
-
db._.mixin(lodashId);
|
|
49
|
+
db._.mixin(mixins); // Expose database
|
|
37
50
|
|
|
38
|
-
// Add specific mixins
|
|
39
|
-
db._.mixin(mixins);
|
|
40
51
|
|
|
41
|
-
// Expose
|
|
42
|
-
router.db = db;
|
|
52
|
+
router.db = db; // Expose render
|
|
43
53
|
|
|
44
|
-
// Expose render
|
|
45
54
|
router.render = (req, res) => {
|
|
46
55
|
res.jsonp(res.locals.data);
|
|
47
|
-
};
|
|
56
|
+
}; // GET /db
|
|
57
|
+
|
|
48
58
|
|
|
49
|
-
// GET /db
|
|
50
59
|
router.get('/db', (req, res) => {
|
|
51
60
|
res.jsonp(db.getState());
|
|
52
|
-
});
|
|
61
|
+
}); // Handle /:parent/:parentId/:resource
|
|
53
62
|
|
|
54
|
-
//
|
|
55
|
-
router.use(nested(opts));
|
|
63
|
+
router.use(nested(opts)); // Create routes
|
|
56
64
|
|
|
57
|
-
// Create routes
|
|
58
65
|
db.forEach((value, key) => {
|
|
59
66
|
if (_.isPlainObject(value)) {
|
|
60
|
-
router.use(`/${key}`, singular(db, key));
|
|
67
|
+
router.use(`/${key}`, singular(db, key, opts));
|
|
61
68
|
return;
|
|
62
69
|
}
|
|
63
70
|
|
|
@@ -66,16 +73,13 @@ module.exports = (source, opts = { foreignKeySuffix: 'Id' }) => {
|
|
|
66
73
|
return;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
var sourceMessage = '';
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
76
|
+
var sourceMessage = ''; // if (!_.isObject(source)) {
|
|
77
|
+
// sourceMessage = `in ${source}`
|
|
78
|
+
// }
|
|
73
79
|
|
|
74
80
|
const msg = `Type of "${key}" (${typeof value}) ${sourceMessage} is not supported. ` + `Use objects or arrays of objects.`;
|
|
75
|
-
|
|
76
81
|
throw new Error(msg);
|
|
77
82
|
}).value();
|
|
78
|
-
|
|
79
83
|
router.use((req, res) => {
|
|
80
84
|
if (!res.locals.data) {
|
|
81
85
|
res.status(404);
|
|
@@ -84,11 +88,9 @@ module.exports = (source, opts = { foreignKeySuffix: 'Id' }) => {
|
|
|
84
88
|
|
|
85
89
|
router.render(req, res);
|
|
86
90
|
});
|
|
87
|
-
|
|
88
91
|
router.use((err, req, res, next) => {
|
|
89
92
|
console.error(err.stack);
|
|
90
93
|
res.status(500).send(err.stack);
|
|
91
94
|
});
|
|
92
|
-
|
|
93
95
|
return router;
|
|
94
96
|
};
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
const express = require('express');
|
|
4
|
+
|
|
4
5
|
const pluralize = require('pluralize');
|
|
6
|
+
|
|
5
7
|
const delay = require('./delay');
|
|
6
8
|
|
|
7
9
|
module.exports = opts => {
|
|
8
10
|
const router = express.Router();
|
|
9
|
-
router.use(delay);
|
|
11
|
+
router.use(delay); // Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
|
|
10
12
|
|
|
11
|
-
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
|
|
12
13
|
function get(req, res, next) {
|
|
13
14
|
const prop = pluralize.singular(req.params.resource);
|
|
14
15
|
req.query[`${prop}${opts.foreignKeySuffix}`] = req.params.id;
|
|
15
16
|
req.url = `/${req.params.nested}`;
|
|
16
17
|
next();
|
|
17
|
-
}
|
|
18
|
+
} // Rewrite URL (/:resource/:id/:nested -> /:nested) and request body
|
|
19
|
+
|
|
18
20
|
|
|
19
|
-
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request body
|
|
20
21
|
function post(req, res, next) {
|
|
21
22
|
const prop = pluralize.singular(req.params.resource);
|
|
22
23
|
req.body[`${prop}${opts.foreignKeySuffix}`] = req.params.id;
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
4
|
+
|
|
5
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
6
|
|
|
3
7
|
const express = require('express');
|
|
8
|
+
|
|
4
9
|
const _ = require('lodash');
|
|
10
|
+
|
|
5
11
|
const pluralize = require('pluralize');
|
|
12
|
+
|
|
6
13
|
const write = require('./write');
|
|
14
|
+
|
|
7
15
|
const getFullURL = require('./get-full-url');
|
|
16
|
+
|
|
8
17
|
const utils = require('../utils');
|
|
18
|
+
|
|
9
19
|
const delay = require('./delay');
|
|
10
20
|
|
|
11
21
|
module.exports = (db, name, opts) => {
|
|
12
22
|
// Create router
|
|
13
23
|
const router = express.Router();
|
|
14
|
-
router.use(delay);
|
|
24
|
+
router.use(delay); // Embed function used in GET /name and GET /name/id
|
|
15
25
|
|
|
16
|
-
// Embed function used in GET /name and GET /name/id
|
|
17
26
|
function embed(resource, e) {
|
|
18
27
|
e && [].concat(e).forEach(externalResource => {
|
|
19
28
|
if (db.get(externalResource).value) {
|
|
@@ -23,31 +32,31 @@ module.exports = (db, name, opts) => {
|
|
|
23
32
|
resource[externalResource] = db.get(externalResource).filter(query).value();
|
|
24
33
|
}
|
|
25
34
|
});
|
|
26
|
-
}
|
|
35
|
+
} // Expand function used in GET /name and GET /name/id
|
|
36
|
+
|
|
27
37
|
|
|
28
|
-
// Expand function used in GET /name and GET /name/id
|
|
29
38
|
function expand(resource, e) {
|
|
30
39
|
e && [].concat(e).forEach(innerResource => {
|
|
31
40
|
const plural = pluralize(innerResource);
|
|
41
|
+
|
|
32
42
|
if (db.get(plural).value()) {
|
|
33
43
|
const prop = `${innerResource}${opts.foreignKeySuffix}`;
|
|
34
44
|
resource[innerResource] = db.get(plural).getById(resource[prop]).value();
|
|
35
45
|
}
|
|
36
46
|
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// GET /name
|
|
47
|
+
} // GET /name
|
|
40
48
|
// GET /name?q=
|
|
41
49
|
// GET /name?attr=&attr=
|
|
42
50
|
// GET /name?_end=&
|
|
43
51
|
// GET /name?_start=&_end=&
|
|
44
52
|
// GET /name?_embed=&_expand=
|
|
53
|
+
|
|
54
|
+
|
|
45
55
|
function list(req, res, next) {
|
|
46
56
|
// Resource chain
|
|
47
|
-
let chain = db.get(name);
|
|
48
|
-
|
|
49
|
-
// Remove q, _start, _end, ... from req.query to avoid filtering using those
|
|
57
|
+
let chain = db.get(name); // Remove q, _start, _end, ... from req.query to avoid filtering using those
|
|
50
58
|
// parameters
|
|
59
|
+
|
|
51
60
|
let q = req.query.q;
|
|
52
61
|
let _start = req.query._start;
|
|
53
62
|
let _end = req.query._end;
|
|
@@ -64,15 +73,16 @@ module.exports = (db, name, opts) => {
|
|
|
64
73
|
delete req.query._order;
|
|
65
74
|
delete req.query._limit;
|
|
66
75
|
delete req.query._embed;
|
|
67
|
-
delete req.query._expand;
|
|
68
|
-
|
|
69
|
-
// Automatically delete query parameters that can't be found
|
|
76
|
+
delete req.query._expand; // Automatically delete query parameters that can't be found
|
|
70
77
|
// in the database
|
|
78
|
+
|
|
71
79
|
Object.keys(req.query).forEach(query => {
|
|
72
80
|
const arr = db.get(name).value();
|
|
81
|
+
|
|
73
82
|
for (let i in arr) {
|
|
74
83
|
if (_.has(arr[i], query) || query === 'callback' || query === '_' || /_lte$/.test(query) || /_gte$/.test(query) || /_ne$/.test(query) || /_like$/.test(query)) return;
|
|
75
84
|
}
|
|
85
|
+
|
|
76
86
|
delete req.query[query];
|
|
77
87
|
});
|
|
78
88
|
|
|
@@ -83,10 +93,10 @@ module.exports = (db, name, opts) => {
|
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
q = q.toLowerCase();
|
|
86
|
-
|
|
87
96
|
chain = chain.filter(obj => {
|
|
88
97
|
for (let key in obj) {
|
|
89
98
|
const value = obj[key];
|
|
99
|
+
|
|
90
100
|
if (db._.deepQuery(value, q)) {
|
|
91
101
|
return true;
|
|
92
102
|
}
|
|
@@ -100,25 +110,23 @@ module.exports = (db, name, opts) => {
|
|
|
100
110
|
if (key !== 'callback' && key !== '_') {
|
|
101
111
|
// Always use an array, in case req.query is an array
|
|
102
112
|
const arr = [].concat(req.query[key]);
|
|
103
|
-
|
|
104
113
|
chain = chain.filter(element => {
|
|
105
114
|
return arr.map(function (value) {
|
|
106
115
|
const isDifferent = /_ne$/.test(key);
|
|
107
116
|
const isRange = /_lte$/.test(key) || /_gte$/.test(key);
|
|
108
117
|
const isLike = /_like$/.test(key);
|
|
109
|
-
const path = key.replace(/(_lte|_gte|_ne|_like)$/, '');
|
|
110
|
-
// get item value based on path
|
|
118
|
+
const path = key.replace(/(_lte|_gte|_ne|_like)$/, ''); // get item value based on path
|
|
111
119
|
// i.e post.title -> 'foo'
|
|
112
|
-
const elementValue = _.get(element, path);
|
|
113
120
|
|
|
114
|
-
// Prevent toString() failing on undefined or null values
|
|
121
|
+
const elementValue = _.get(element, path); // Prevent toString() failing on undefined or null values
|
|
122
|
+
|
|
123
|
+
|
|
115
124
|
if (elementValue === undefined || elementValue === null) {
|
|
116
125
|
return;
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
if (isRange) {
|
|
120
129
|
const isLowerThan = /_gte$/.test(key);
|
|
121
|
-
|
|
122
130
|
return isLowerThan ? value <= elementValue : value >= elementValue;
|
|
123
131
|
} else if (isDifferent) {
|
|
124
132
|
return value !== elementValue.toString();
|
|
@@ -130,16 +138,17 @@ module.exports = (db, name, opts) => {
|
|
|
130
138
|
}).reduce((a, b) => a || b);
|
|
131
139
|
});
|
|
132
140
|
}
|
|
133
|
-
});
|
|
141
|
+
}); // Sort
|
|
134
142
|
|
|
135
|
-
// Sort
|
|
136
143
|
if (_sort) {
|
|
137
144
|
const _sortSet = _sort.split(',');
|
|
145
|
+
|
|
138
146
|
const _orderSet = (_order || '').split(',').map(s => s.toLowerCase());
|
|
147
|
+
|
|
139
148
|
chain = chain.orderBy(_sortSet, _orderSet);
|
|
140
|
-
}
|
|
149
|
+
} // Slice result
|
|
150
|
+
|
|
141
151
|
|
|
142
|
-
// Slice result
|
|
143
152
|
if (_end || _limit || _page) {
|
|
144
153
|
res.setHeader('X-Total-Count', chain.size());
|
|
145
154
|
res.setHeader('Access-Control-Expose-Headers', `X-Total-Count${_page ? ', Link' : ''}`);
|
|
@@ -179,20 +188,19 @@ module.exports = (db, name, opts) => {
|
|
|
179
188
|
_start = parseInt(_start, 10) || 0;
|
|
180
189
|
_limit = parseInt(_limit, 10);
|
|
181
190
|
chain = chain.slice(_start, _start + _limit);
|
|
182
|
-
}
|
|
191
|
+
} // embed and expand
|
|
192
|
+
|
|
183
193
|
|
|
184
|
-
// embed and expand
|
|
185
194
|
chain = chain.cloneDeep().forEach(function (element) {
|
|
186
195
|
embed(element, _embed);
|
|
187
196
|
expand(element, _expand);
|
|
188
197
|
});
|
|
189
|
-
|
|
190
198
|
res.locals.data = chain.value();
|
|
191
199
|
next();
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// GET /name/:id
|
|
200
|
+
} // GET /name/:id
|
|
195
201
|
// GET /name/:id?_embed=&_expand
|
|
202
|
+
|
|
203
|
+
|
|
196
204
|
function show(req, res, next) {
|
|
197
205
|
const _embed = req.query._embed;
|
|
198
206
|
const _expand = req.query._expand;
|
|
@@ -200,61 +208,84 @@ module.exports = (db, name, opts) => {
|
|
|
200
208
|
|
|
201
209
|
if (resource) {
|
|
202
210
|
// Clone resource to avoid making changes to the underlying object
|
|
203
|
-
const clone = _.cloneDeep(resource);
|
|
204
|
-
|
|
205
|
-
// Embed other resources based on resource id
|
|
211
|
+
const clone = _.cloneDeep(resource); // Embed other resources based on resource id
|
|
206
212
|
// /posts/1?_embed=comments
|
|
207
|
-
embed(clone, _embed);
|
|
208
213
|
|
|
209
|
-
|
|
214
|
+
|
|
215
|
+
embed(clone, _embed); // Expand inner resources based on id
|
|
210
216
|
// /posts/1?_expand=user
|
|
211
|
-
expand(clone, _expand);
|
|
212
217
|
|
|
218
|
+
expand(clone, _expand);
|
|
213
219
|
res.locals.data = clone;
|
|
214
220
|
}
|
|
215
221
|
|
|
216
222
|
next();
|
|
217
|
-
}
|
|
223
|
+
} // POST /name
|
|
224
|
+
|
|
218
225
|
|
|
219
|
-
// POST /name
|
|
220
226
|
function create(req, res, next) {
|
|
221
|
-
|
|
227
|
+
let resource;
|
|
228
|
+
|
|
229
|
+
if (opts._isFake) {
|
|
230
|
+
const id = db.get(name).createId().value();
|
|
231
|
+
resource = _objectSpread({}, req.body, {
|
|
232
|
+
id
|
|
233
|
+
});
|
|
234
|
+
} else {
|
|
235
|
+
resource = db.get(name).insert(req.body).value();
|
|
236
|
+
}
|
|
222
237
|
|
|
223
238
|
res.setHeader('Access-Control-Expose-Headers', 'Location');
|
|
224
239
|
res.location(`${getFullURL(req)}/${resource.id}`);
|
|
225
|
-
|
|
226
240
|
res.status(201);
|
|
227
241
|
res.locals.data = resource;
|
|
228
|
-
|
|
229
242
|
next();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// PUT /name/:id
|
|
243
|
+
} // PUT /name/:id
|
|
233
244
|
// PATCH /name/:id
|
|
245
|
+
|
|
246
|
+
|
|
234
247
|
function update(req, res, next) {
|
|
235
248
|
const id = req.params.id;
|
|
236
|
-
let
|
|
249
|
+
let resource;
|
|
237
250
|
|
|
238
|
-
|
|
251
|
+
if (opts._isFake) {
|
|
252
|
+
resource = db.get(name).getById(id).value();
|
|
239
253
|
|
|
240
|
-
|
|
254
|
+
if (req.method === 'PATCH') {
|
|
255
|
+
resource = _objectSpread({}, resource, req.body);
|
|
256
|
+
} else {
|
|
257
|
+
resource = _objectSpread({}, req.body, {
|
|
258
|
+
id: resource.id
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
} else {
|
|
262
|
+
let chain = db.get(name);
|
|
263
|
+
chain = req.method === 'PATCH' ? chain.updateById(id, req.body) : chain.replaceById(id, req.body);
|
|
264
|
+
resource = chain.value();
|
|
265
|
+
}
|
|
241
266
|
|
|
242
267
|
if (resource) {
|
|
243
268
|
res.locals.data = resource;
|
|
244
269
|
}
|
|
245
270
|
|
|
246
271
|
next();
|
|
247
|
-
}
|
|
272
|
+
} // DELETE /name/:id
|
|
273
|
+
|
|
248
274
|
|
|
249
|
-
// DELETE /name/:id
|
|
250
275
|
function destroy(req, res, next) {
|
|
251
|
-
|
|
276
|
+
let resource;
|
|
252
277
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
db.get(
|
|
257
|
-
|
|
278
|
+
if (opts._isFake) {
|
|
279
|
+
resource = db.get(name).value();
|
|
280
|
+
} else {
|
|
281
|
+
resource = db.get(name).removeById(req.params.id).value(); // Remove dependents documents
|
|
282
|
+
|
|
283
|
+
const removable = db._.getRemovable(db.getState(), opts);
|
|
284
|
+
|
|
285
|
+
removable.forEach(item => {
|
|
286
|
+
db.get(item.name).removeById(item.id).value();
|
|
287
|
+
});
|
|
288
|
+
}
|
|
258
289
|
|
|
259
290
|
if (resource) {
|
|
260
291
|
res.locals.data = {};
|
|
@@ -264,10 +295,7 @@ module.exports = (db, name, opts) => {
|
|
|
264
295
|
}
|
|
265
296
|
|
|
266
297
|
const w = write(db);
|
|
267
|
-
|
|
268
298
|
router.route('/').get(list).post(create, w);
|
|
269
|
-
|
|
270
299
|
router.route('/:id').get(show).put(update, w).patch(update, w).delete(destroy, w);
|
|
271
|
-
|
|
272
300
|
return router;
|
|
273
301
|
};
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
4
|
+
|
|
5
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
6
|
|
|
3
7
|
const express = require('express');
|
|
8
|
+
|
|
4
9
|
const write = require('./write');
|
|
10
|
+
|
|
5
11
|
const getFullURL = require('./get-full-url');
|
|
12
|
+
|
|
6
13
|
const delay = require('./delay');
|
|
7
14
|
|
|
8
|
-
module.exports = (db, name) => {
|
|
15
|
+
module.exports = (db, name, opts) => {
|
|
9
16
|
const router = express.Router();
|
|
10
17
|
router.use(delay);
|
|
11
18
|
|
|
@@ -15,30 +22,41 @@ module.exports = (db, name) => {
|
|
|
15
22
|
}
|
|
16
23
|
|
|
17
24
|
function create(req, res, next) {
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
if (opts._isFake) {
|
|
26
|
+
res.locals.data = req.body;
|
|
27
|
+
} else {
|
|
28
|
+
db.set(name, req.body).value();
|
|
29
|
+
res.locals.data = db.get(name).value();
|
|
30
|
+
}
|
|
20
31
|
|
|
21
32
|
res.setHeader('Access-Control-Expose-Headers', 'Location');
|
|
22
33
|
res.location(`${getFullURL(req)}`);
|
|
23
|
-
|
|
24
34
|
res.status(201);
|
|
25
35
|
next();
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
function update(req, res, next) {
|
|
29
|
-
if (
|
|
30
|
-
|
|
39
|
+
if (opts._isFake) {
|
|
40
|
+
if (req.method === 'PUT') {
|
|
41
|
+
res.locals.data = req.body;
|
|
42
|
+
} else {
|
|
43
|
+
const resource = db.get(name).value();
|
|
44
|
+
res.locals.data = _objectSpread({}, resource, req.body);
|
|
45
|
+
}
|
|
31
46
|
} else {
|
|
32
|
-
|
|
47
|
+
if (req.method === 'PUT') {
|
|
48
|
+
db.set(name, req.body).value();
|
|
49
|
+
} else {
|
|
50
|
+
db.get(name).assign(req.body).value();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
res.locals.data = db.get(name).value();
|
|
33
54
|
}
|
|
34
55
|
|
|
35
|
-
res.locals.data = db.get(name).value();
|
|
36
56
|
next();
|
|
37
57
|
}
|
|
38
58
|
|
|
39
59
|
const w = write(db);
|
|
40
|
-
|
|
41
60
|
router.route('/').get(show).post(create, w).put(update, w).patch(update, w);
|
|
42
|
-
|
|
43
61
|
return router;
|
|
44
62
|
};
|