json-server 0.17.3 → 1.0.0-alpha.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.
- package/LICENSE +44 -20
- package/README.md +52 -589
- package/package.json +39 -92
- package/lib/cli/bin.js +0 -6
- package/lib/cli/index.js +0 -81
- package/lib/cli/run.js +0 -235
- package/lib/cli/utils/is.js +0 -19
- package/lib/cli/utils/load.js +0 -82
- package/lib/server/body-parser.js +0 -10
- package/lib/server/defaults.js +0 -80
- package/lib/server/index.js +0 -11
- package/lib/server/mixins.js +0 -85
- package/lib/server/rewriter.js +0 -16
- package/lib/server/router/delay.js +0 -12
- package/lib/server/router/get-full-url.js +0 -11
- package/lib/server/router/index.js +0 -103
- package/lib/server/router/nested.js +0 -29
- package/lib/server/router/plural.js +0 -305
- package/lib/server/router/singular.js +0 -64
- package/lib/server/router/validate-data.js +0 -19
- package/lib/server/router/write.js +0 -8
- package/lib/server/utils.js +0 -32
- package/public/favicon.ico +0 -0
- package/public/index.html +0 -85
- package/public/script.js +0 -76
- package/public/style.css +0 -113
package/package.json
CHANGED
|
@@ -1,102 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": "./lib/index.js",
|
|
7
|
+
"types": "lib",
|
|
7
8
|
"files": [
|
|
8
|
-
"lib"
|
|
9
|
-
"public"
|
|
9
|
+
"lib"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"postversion": "git push && git push --tags",
|
|
20
|
-
"prepublish": "npm test && npm run build"
|
|
21
|
-
},
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"body-parser": "^1.19.0",
|
|
24
|
-
"chalk": "^4.1.2",
|
|
25
|
-
"compression": "^1.7.4",
|
|
26
|
-
"connect-pause": "^0.1.1",
|
|
27
|
-
"cors": "^2.8.5",
|
|
28
|
-
"errorhandler": "^1.5.1",
|
|
29
|
-
"express": "^4.17.1",
|
|
30
|
-
"express-urlrewrite": "^1.4.0",
|
|
31
|
-
"json-parse-helpfulerror": "^1.0.3",
|
|
32
|
-
"lodash": "^4.17.21",
|
|
33
|
-
"lodash-id": "^0.14.1",
|
|
34
|
-
"lowdb": "^1.0.0",
|
|
35
|
-
"method-override": "^3.0.0",
|
|
36
|
-
"morgan": "^1.10.0",
|
|
37
|
-
"nanoid": "^3.1.23",
|
|
38
|
-
"please-upgrade-node": "^3.2.0",
|
|
39
|
-
"pluralize": "^8.0.0",
|
|
40
|
-
"server-destroy": "^1.0.1",
|
|
41
|
-
"standard": "^17.0.0",
|
|
42
|
-
"yargs": "^17.0.1"
|
|
12
|
+
"css": "tailwindcss -i ./views/input.css -o ./public/output.css",
|
|
13
|
+
"watch-ts": "tsx watch src/bin.ts db.json",
|
|
14
|
+
"watch-css": "npm run css -- --watch",
|
|
15
|
+
"dev": "concurrently npm:watch-*",
|
|
16
|
+
"build": "rm -rf lib && tsc && npm run css",
|
|
17
|
+
"test": "node --import tsx/esm --test src/**/*.test.ts",
|
|
18
|
+
"prepare": "husky install"
|
|
43
19
|
},
|
|
20
|
+
"keywords": [],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "SEE LICENSE IN ./LICENSE",
|
|
44
23
|
"devDependencies": {
|
|
45
|
-
"@
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"eslint-plugin-standard": "^4.1.0",
|
|
58
|
-
"husky": "^6.0.0",
|
|
59
|
-
"jest": "^26.6.3",
|
|
60
|
-
"markdown-toc": "^1.2.0",
|
|
61
|
-
"mkdirp": "^1.0.4",
|
|
62
|
-
"npm-run-all": "^4.1.5",
|
|
63
|
-
"os-tmpdir": "^2.0.0",
|
|
64
|
-
"prettier": "^2.3.2",
|
|
65
|
-
"rimraf": "^3.0.2",
|
|
66
|
-
"server-ready": "^0.3.1",
|
|
67
|
-
"supertest": "^6.0.1",
|
|
68
|
-
"temp-write": "^4.0.0"
|
|
24
|
+
"@sindresorhus/tsconfig": "^5.0.0",
|
|
25
|
+
"@tailwindcss/typography": "^0.5.10",
|
|
26
|
+
"@types/node": "^20.10.0",
|
|
27
|
+
"@typicode/eslint-config": "^1.2.0",
|
|
28
|
+
"concurrently": "^8.2.2",
|
|
29
|
+
"get-port": "^7.0.0",
|
|
30
|
+
"husky": "^8.0.3",
|
|
31
|
+
"tailwindcss": "^3.3.5",
|
|
32
|
+
"tempy": "^3.1.0",
|
|
33
|
+
"tsx": "^4.5.0",
|
|
34
|
+
"type-fest": "^4.8.2",
|
|
35
|
+
"typescript": "^5.3.2"
|
|
69
36
|
},
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"mock",
|
|
82
|
-
"mocking",
|
|
83
|
-
"test",
|
|
84
|
-
"testing",
|
|
85
|
-
"rest",
|
|
86
|
-
"data",
|
|
87
|
-
"dummy",
|
|
88
|
-
"sandbox"
|
|
89
|
-
],
|
|
90
|
-
"author": "Typicode <typicode@gmail.com>",
|
|
91
|
-
"license": "MIT",
|
|
92
|
-
"bugs": {
|
|
93
|
-
"url": "https://github.com/typicode/json-server/issues"
|
|
94
|
-
},
|
|
95
|
-
"homepage": "https://github.com/typicode/json-server",
|
|
96
|
-
"engines": {
|
|
97
|
-
"node": ">=12"
|
|
98
|
-
},
|
|
99
|
-
"jest": {
|
|
100
|
-
"testURL": "http://localhost/"
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@tinyhttp/app": "^2.2.1",
|
|
39
|
+
"chokidar": "^3.5.3",
|
|
40
|
+
"dot-prop": "^8.0.2",
|
|
41
|
+
"eta": "^3.1.1",
|
|
42
|
+
"inflection": "^3.0.0",
|
|
43
|
+
"lowdb": "^6.1.1",
|
|
44
|
+
"milliparsec": "^2.3.0",
|
|
45
|
+
"sirv": "^2.0.3",
|
|
46
|
+
"sort-on": "^6.0.0",
|
|
47
|
+
"zod": "^3.22.4"
|
|
101
48
|
}
|
|
102
49
|
}
|
package/lib/cli/bin.js
DELETED
package/lib/cli/index.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const yargs = require('yargs');
|
|
4
|
-
|
|
5
|
-
const run = require('./run');
|
|
6
|
-
|
|
7
|
-
const pkg = require('../../package.json');
|
|
8
|
-
|
|
9
|
-
module.exports = function () {
|
|
10
|
-
const argv = yargs.config('config').usage('$0 [options] <source>').options({
|
|
11
|
-
port: {
|
|
12
|
-
alias: 'p',
|
|
13
|
-
description: 'Set port',
|
|
14
|
-
default: 3000
|
|
15
|
-
},
|
|
16
|
-
host: {
|
|
17
|
-
alias: 'H',
|
|
18
|
-
description: 'Set host',
|
|
19
|
-
default: 'localhost'
|
|
20
|
-
},
|
|
21
|
-
watch: {
|
|
22
|
-
alias: 'w',
|
|
23
|
-
description: 'Watch file(s)'
|
|
24
|
-
},
|
|
25
|
-
routes: {
|
|
26
|
-
alias: 'r',
|
|
27
|
-
description: 'Path to routes file'
|
|
28
|
-
},
|
|
29
|
-
middlewares: {
|
|
30
|
-
alias: 'm',
|
|
31
|
-
array: true,
|
|
32
|
-
description: 'Paths to middleware files'
|
|
33
|
-
},
|
|
34
|
-
static: {
|
|
35
|
-
alias: 's',
|
|
36
|
-
description: 'Set static files directory'
|
|
37
|
-
},
|
|
38
|
-
'read-only': {
|
|
39
|
-
alias: 'ro',
|
|
40
|
-
description: 'Allow only GET requests'
|
|
41
|
-
},
|
|
42
|
-
'no-cors': {
|
|
43
|
-
alias: 'nc',
|
|
44
|
-
description: 'Disable Cross-Origin Resource Sharing'
|
|
45
|
-
},
|
|
46
|
-
'no-gzip': {
|
|
47
|
-
alias: 'ng',
|
|
48
|
-
description: 'Disable GZIP Content-Encoding'
|
|
49
|
-
},
|
|
50
|
-
snapshots: {
|
|
51
|
-
alias: 'S',
|
|
52
|
-
description: 'Set snapshots directory',
|
|
53
|
-
default: '.'
|
|
54
|
-
},
|
|
55
|
-
delay: {
|
|
56
|
-
alias: 'd',
|
|
57
|
-
description: 'Add delay to responses (ms)'
|
|
58
|
-
},
|
|
59
|
-
id: {
|
|
60
|
-
alias: 'i',
|
|
61
|
-
description: 'Set database id property (e.g. _id)',
|
|
62
|
-
default: 'id'
|
|
63
|
-
},
|
|
64
|
-
foreignKeySuffix: {
|
|
65
|
-
alias: 'fks',
|
|
66
|
-
description: 'Set foreign key suffix (e.g. _id as in post_id)',
|
|
67
|
-
default: 'Id'
|
|
68
|
-
},
|
|
69
|
-
quiet: {
|
|
70
|
-
alias: 'q',
|
|
71
|
-
description: 'Suppress log messages from output'
|
|
72
|
-
},
|
|
73
|
-
config: {
|
|
74
|
-
alias: 'c',
|
|
75
|
-
description: 'Path to config file',
|
|
76
|
-
default: 'json-server.json'
|
|
77
|
-
}
|
|
78
|
-
}).boolean('watch').boolean('read-only').boolean('quiet').boolean('no-cors').boolean('no-gzip').help('help').alias('help', 'h').version(pkg.version).alias('version', 'v').example('$0 db.json', '').example('$0 file.js', '').example('$0 http://example.com/db.json', '').epilog('https://github.com/typicode/json-server').require(1, 'Missing <source> argument').argv;
|
|
79
|
-
|
|
80
|
-
run(argv);
|
|
81
|
-
};
|
package/lib/cli/run.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
const jph = require('json-parse-helpfulerror');
|
|
8
|
-
|
|
9
|
-
const _ = require('lodash');
|
|
10
|
-
|
|
11
|
-
const chalk = require('chalk');
|
|
12
|
-
|
|
13
|
-
const enableDestroy = require('server-destroy');
|
|
14
|
-
|
|
15
|
-
const pause = require('connect-pause');
|
|
16
|
-
|
|
17
|
-
const is = require('./utils/is');
|
|
18
|
-
|
|
19
|
-
const load = require('./utils/load');
|
|
20
|
-
|
|
21
|
-
const jsonServer = require('../server');
|
|
22
|
-
|
|
23
|
-
function prettyPrint(argv, object, rules) {
|
|
24
|
-
const root = `http://${argv.host}:${argv.port}`;
|
|
25
|
-
console.log();
|
|
26
|
-
console.log(chalk.bold(' Resources'));
|
|
27
|
-
|
|
28
|
-
for (const prop in object) {
|
|
29
|
-
// skip printing $schema nodes
|
|
30
|
-
if (prop === '$schema') continue;
|
|
31
|
-
console.log(` ${root}/${prop}`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (rules) {
|
|
35
|
-
console.log();
|
|
36
|
-
console.log(chalk.bold(' Other routes'));
|
|
37
|
-
|
|
38
|
-
for (const rule in rules) {
|
|
39
|
-
console.log(` ${rule} -> ${rules[rule]}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.log();
|
|
44
|
-
console.log(chalk.bold(' Home'));
|
|
45
|
-
console.log(` ${root}`);
|
|
46
|
-
console.log();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function createApp(db, routes, middlewares, argv) {
|
|
50
|
-
const app = jsonServer.create();
|
|
51
|
-
const {
|
|
52
|
-
foreignKeySuffix
|
|
53
|
-
} = argv;
|
|
54
|
-
const router = jsonServer.router(db, foreignKeySuffix ? {
|
|
55
|
-
foreignKeySuffix
|
|
56
|
-
} : undefined);
|
|
57
|
-
const defaultsOpts = {
|
|
58
|
-
logger: !argv.quiet,
|
|
59
|
-
readOnly: argv.readOnly,
|
|
60
|
-
noCors: argv.noCors,
|
|
61
|
-
noGzip: argv.noGzip,
|
|
62
|
-
bodyParser: true
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
if (argv.static) {
|
|
66
|
-
defaultsOpts.static = path.join(process.cwd(), argv.static);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const defaults = jsonServer.defaults(defaultsOpts);
|
|
70
|
-
app.use(defaults);
|
|
71
|
-
|
|
72
|
-
if (routes) {
|
|
73
|
-
const rewriter = jsonServer.rewriter(routes);
|
|
74
|
-
app.use(rewriter);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (middlewares) {
|
|
78
|
-
app.use(middlewares);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (argv.delay) {
|
|
82
|
-
app.use(pause(argv.delay));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
router.db._.id = argv.id;
|
|
86
|
-
app.db = router.db;
|
|
87
|
-
app.use(router);
|
|
88
|
-
return app;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
module.exports = function (argv) {
|
|
92
|
-
const source = argv._[0];
|
|
93
|
-
let app;
|
|
94
|
-
let server;
|
|
95
|
-
|
|
96
|
-
if (!fs.existsSync(argv.snapshots)) {
|
|
97
|
-
console.log(`Error: snapshots directory ${argv.snapshots} doesn't exist`);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
} // noop log fn
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (argv.quiet) {
|
|
103
|
-
console.log = () => {};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
console.log();
|
|
107
|
-
console.log(chalk.cyan(' \\{^_^}/ hi!'));
|
|
108
|
-
|
|
109
|
-
function start(cb) {
|
|
110
|
-
console.log();
|
|
111
|
-
console.log(chalk.gray(' Loading', source));
|
|
112
|
-
server = undefined; // create db and load object, JSON file, JS or HTTP database
|
|
113
|
-
|
|
114
|
-
return load(source).then(db => {
|
|
115
|
-
// Load additional routes
|
|
116
|
-
let routes;
|
|
117
|
-
|
|
118
|
-
if (argv.routes) {
|
|
119
|
-
console.log(chalk.gray(' Loading', argv.routes));
|
|
120
|
-
routes = JSON.parse(fs.readFileSync(argv.routes));
|
|
121
|
-
} // Load middlewares
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
let middlewares;
|
|
125
|
-
|
|
126
|
-
if (argv.middlewares) {
|
|
127
|
-
middlewares = argv.middlewares.map(function (m) {
|
|
128
|
-
console.log(chalk.gray(' Loading', m));
|
|
129
|
-
return require(path.resolve(m));
|
|
130
|
-
});
|
|
131
|
-
} // Done
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
console.log(chalk.gray(' Done')); // Create app and server
|
|
135
|
-
|
|
136
|
-
app = createApp(db, routes, middlewares, argv);
|
|
137
|
-
server = app.listen(argv.port, argv.host); // Enhance with a destroy function
|
|
138
|
-
|
|
139
|
-
enableDestroy(server); // Display server informations
|
|
140
|
-
|
|
141
|
-
prettyPrint(argv, db.getState(), routes); // Catch and handle any error occurring in the server process
|
|
142
|
-
|
|
143
|
-
process.on('uncaughtException', error => {
|
|
144
|
-
if (error.errno === 'EADDRINUSE') console.log(chalk.red(`Cannot bind to the port ${error.port}. Please specify another port number either through --port argument or through the json-server.json configuration file`));else console.log('Some error occurred', error);
|
|
145
|
-
process.exit(1);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
} // Start server
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
start().then(() => {
|
|
152
|
-
// Snapshot
|
|
153
|
-
console.log(chalk.gray(' Type s + enter at any time to create a snapshot of the database')); // Support nohup
|
|
154
|
-
// https://github.com/typicode/json-server/issues/221
|
|
155
|
-
|
|
156
|
-
process.stdin.on('error', () => {
|
|
157
|
-
console.log(` Error, can't read from stdin`);
|
|
158
|
-
console.log(` Creating a snapshot from the CLI won't be possible`);
|
|
159
|
-
});
|
|
160
|
-
process.stdin.setEncoding('utf8');
|
|
161
|
-
process.stdin.on('data', chunk => {
|
|
162
|
-
if (chunk.trim().toLowerCase() === 's') {
|
|
163
|
-
const filename = `db-${Date.now()}.json`;
|
|
164
|
-
const file = path.join(argv.snapshots, filename);
|
|
165
|
-
const state = app.db.getState();
|
|
166
|
-
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8');
|
|
167
|
-
console.log(` Saved snapshot to ${path.relative(process.cwd(), file)}\n`);
|
|
168
|
-
}
|
|
169
|
-
}); // Watch files
|
|
170
|
-
|
|
171
|
-
if (argv.watch) {
|
|
172
|
-
console.log(chalk.gray(' Watching...'));
|
|
173
|
-
console.log();
|
|
174
|
-
const source = argv._[0]; // Can't watch URL
|
|
175
|
-
|
|
176
|
-
if (is.URL(source)) throw new Error("Can't watch URL"); // Watch .js or .json file
|
|
177
|
-
// Since lowdb uses atomic writing, directory is watched instead of file
|
|
178
|
-
|
|
179
|
-
const watchedDir = path.dirname(source);
|
|
180
|
-
let readError = false;
|
|
181
|
-
fs.watch(watchedDir, (event, file) => {
|
|
182
|
-
// https://github.com/typicode/json-server/issues/420
|
|
183
|
-
// file can be null
|
|
184
|
-
if (file) {
|
|
185
|
-
const watchedFile = path.resolve(watchedDir, file);
|
|
186
|
-
|
|
187
|
-
if (watchedFile === path.resolve(source)) {
|
|
188
|
-
if (is.FILE(watchedFile)) {
|
|
189
|
-
let obj;
|
|
190
|
-
|
|
191
|
-
try {
|
|
192
|
-
obj = jph.parse(fs.readFileSync(watchedFile));
|
|
193
|
-
|
|
194
|
-
if (readError) {
|
|
195
|
-
console.log(chalk.green(` Read error has been fixed :)`));
|
|
196
|
-
readError = false;
|
|
197
|
-
}
|
|
198
|
-
} catch (e) {
|
|
199
|
-
readError = true;
|
|
200
|
-
console.log(chalk.red(` Error reading ${watchedFile}`));
|
|
201
|
-
console.error(e.message);
|
|
202
|
-
return;
|
|
203
|
-
} // Compare .json file content with in memory database
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const isDatabaseDifferent = !_.isEqual(obj, app.db.getState());
|
|
207
|
-
|
|
208
|
-
if (isDatabaseDifferent) {
|
|
209
|
-
console.log(chalk.gray(` ${source} has changed, reloading...`));
|
|
210
|
-
server && server.destroy(() => start());
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}); // Watch routes
|
|
216
|
-
|
|
217
|
-
if (argv.routes) {
|
|
218
|
-
const watchedDir = path.dirname(argv.routes);
|
|
219
|
-
fs.watch(watchedDir, (event, file) => {
|
|
220
|
-
if (file) {
|
|
221
|
-
const watchedFile = path.resolve(watchedDir, file);
|
|
222
|
-
|
|
223
|
-
if (watchedFile === path.resolve(argv.routes)) {
|
|
224
|
-
console.log(chalk.gray(` ${argv.routes} has changed, reloading...`));
|
|
225
|
-
server && server.destroy(() => start());
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}).catch(err => {
|
|
232
|
-
console.log(err);
|
|
233
|
-
process.exit(1);
|
|
234
|
-
});
|
|
235
|
-
};
|
package/lib/cli/utils/is.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
FILE,
|
|
5
|
-
JS,
|
|
6
|
-
URL
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
function FILE(s) {
|
|
10
|
-
return !URL(s) && /\.json$/.test(s);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function JS(s) {
|
|
14
|
-
return !URL(s) && /\.c?js$/.test(s);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function URL(s) {
|
|
18
|
-
return /^(http|https):/.test(s);
|
|
19
|
-
}
|
package/lib/cli/utils/load.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
const http = require('http');
|
|
8
|
-
|
|
9
|
-
const https = require('https');
|
|
10
|
-
|
|
11
|
-
const low = require('lowdb');
|
|
12
|
-
|
|
13
|
-
const FileAsync = require('lowdb/adapters/FileAsync');
|
|
14
|
-
|
|
15
|
-
const Memory = require('lowdb/adapters/Memory');
|
|
16
|
-
|
|
17
|
-
const is = require('./is');
|
|
18
|
-
|
|
19
|
-
const chalk = require('chalk');
|
|
20
|
-
|
|
21
|
-
const example = {
|
|
22
|
-
posts: [{
|
|
23
|
-
id: 1,
|
|
24
|
-
title: 'json-server',
|
|
25
|
-
author: 'typicode'
|
|
26
|
-
}],
|
|
27
|
-
comments: [{
|
|
28
|
-
id: 1,
|
|
29
|
-
body: 'some comment',
|
|
30
|
-
postId: 1
|
|
31
|
-
}],
|
|
32
|
-
profile: {
|
|
33
|
-
name: 'typicode'
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
module.exports = function (source) {
|
|
38
|
-
return new Promise((resolve, reject) => {
|
|
39
|
-
if (is.FILE(source)) {
|
|
40
|
-
if (!fs.existsSync(source)) {
|
|
41
|
-
console.log(chalk.yellow(` Oops, ${source} doesn't seem to exist`));
|
|
42
|
-
console.log(chalk.yellow(` Creating ${source} with some default data`));
|
|
43
|
-
console.log();
|
|
44
|
-
fs.writeFileSync(source, JSON.stringify(example, null, 2));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
resolve(low(new FileAsync(source)));
|
|
48
|
-
} else if (is.URL(source)) {
|
|
49
|
-
// Normalize the source into a URL object.
|
|
50
|
-
const sourceUrl = new URL(source); // Pick the client based on the protocol scheme
|
|
51
|
-
|
|
52
|
-
const client = sourceUrl.protocol === 'https:' ? https : http;
|
|
53
|
-
client.get(sourceUrl, res => {
|
|
54
|
-
let dbData = '';
|
|
55
|
-
res.on('data', data => {
|
|
56
|
-
dbData += data;
|
|
57
|
-
});
|
|
58
|
-
res.on('end', () => {
|
|
59
|
-
resolve(low(new Memory()).setState(JSON.parse(dbData)));
|
|
60
|
-
});
|
|
61
|
-
}).on('error', error => {
|
|
62
|
-
return reject(error);
|
|
63
|
-
});
|
|
64
|
-
} else if (is.JS(source)) {
|
|
65
|
-
// Clear cache
|
|
66
|
-
const filename = path.resolve(source);
|
|
67
|
-
delete require.cache[filename];
|
|
68
|
-
|
|
69
|
-
const dataFn = require(filename);
|
|
70
|
-
|
|
71
|
-
if (typeof dataFn !== 'function') {
|
|
72
|
-
throw new Error('The database is a JavaScript file but the export is not a function.');
|
|
73
|
-
} // Run dataFn to generate data
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const data = dataFn();
|
|
77
|
-
resolve(low(new Memory()).setState(data));
|
|
78
|
-
} else {
|
|
79
|
-
throw new Error(`Unsupported source ${source}`);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
};
|
package/lib/server/defaults.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
const express = require('express');
|
|
8
|
-
|
|
9
|
-
const logger = require('morgan');
|
|
10
|
-
|
|
11
|
-
const cors = require('cors');
|
|
12
|
-
|
|
13
|
-
const compression = require('compression');
|
|
14
|
-
|
|
15
|
-
const errorhandler = require('errorhandler');
|
|
16
|
-
|
|
17
|
-
const bodyParser = require('./body-parser');
|
|
18
|
-
|
|
19
|
-
module.exports = function (opts) {
|
|
20
|
-
const userDir = path.join(process.cwd(), 'public');
|
|
21
|
-
const defaultDir = path.join(__dirname, '../../public');
|
|
22
|
-
const staticDir = fs.existsSync(userDir) ? userDir : defaultDir;
|
|
23
|
-
opts = Object.assign({
|
|
24
|
-
logger: true,
|
|
25
|
-
static: staticDir
|
|
26
|
-
}, opts);
|
|
27
|
-
const arr = []; // Compress all requests
|
|
28
|
-
|
|
29
|
-
if (!opts.noGzip) {
|
|
30
|
-
arr.push(compression());
|
|
31
|
-
} // Enable CORS for all the requests, including static files
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!opts.noCors) {
|
|
35
|
-
arr.push(cors({
|
|
36
|
-
origin: true,
|
|
37
|
-
credentials: true
|
|
38
|
-
}));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (process.env.NODE_ENV === 'development') {
|
|
42
|
-
// only use in development
|
|
43
|
-
arr.push(errorhandler());
|
|
44
|
-
} // Serve static files
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
arr.push(express.static(opts.static)); // Logger
|
|
48
|
-
|
|
49
|
-
if (opts.logger) {
|
|
50
|
-
arr.push(logger('dev', {
|
|
51
|
-
skip: req => process.env.NODE_ENV === 'test' || req.path === '/favicon.ico'
|
|
52
|
-
}));
|
|
53
|
-
} // No cache for IE
|
|
54
|
-
// https://support.microsoft.com/en-us/kb/234067
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
arr.push((req, res, next) => {
|
|
58
|
-
res.header('Cache-Control', 'no-cache');
|
|
59
|
-
res.header('Pragma', 'no-cache');
|
|
60
|
-
res.header('Expires', '-1');
|
|
61
|
-
next();
|
|
62
|
-
}); // Read-only
|
|
63
|
-
|
|
64
|
-
if (opts.readOnly) {
|
|
65
|
-
arr.push((req, res, next) => {
|
|
66
|
-
if (req.method === 'GET') {
|
|
67
|
-
next(); // Continue
|
|
68
|
-
} else {
|
|
69
|
-
res.sendStatus(403); // Forbidden
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
} // Add middlewares
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (opts.bodyParser) {
|
|
76
|
-
arr.push(bodyParser);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return arr;
|
|
80
|
-
};
|
package/lib/server/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const express = require('express');
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
create: () => express().set('json spaces', 2),
|
|
7
|
-
defaults: require('./defaults'),
|
|
8
|
-
router: require('./router'),
|
|
9
|
-
rewriter: require('./rewriter'),
|
|
10
|
-
bodyParser: require('./body-parser')
|
|
11
|
-
};
|