json-server 0.17.4 → 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/package.json CHANGED
@@ -1,102 +1,49 @@
1
1
  {
2
2
  "name": "json-server",
3
- "version": "0.17.4",
4
- "description": "Get a full fake REST API with zero coding in less than 30 seconds",
5
- "main": "./lib/server/index.js",
6
- "bin": "./lib/cli/bin.js",
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
- "prepare": "husky install",
13
- "test": "npm run build && cross-env NODE_ENV=test jest",
14
- "start": "babel-node -- src/cli/bin db.json -r routes.json",
15
- "lint": "eslint . --ignore-path .gitignore",
16
- "fix": "npm run lint -- --fix",
17
- "build": "babel src -d lib",
18
- "toc": "markdown-toc -i README.md",
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
- "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"
42
19
  },
20
+ "keywords": [],
21
+ "author": "",
22
+ "license": "SEE LICENSE IN ./LICENSE",
43
23
  "devDependencies": {
44
- "@babel/cli": "^7.12.1",
45
- "@babel/core": "^7.12.3",
46
- "@babel/node": "^7.12.6",
47
- "@babel/preset-env": "^7.12.1",
48
- "cross-env": "^7.0.2",
49
- "eslint": "^7.13.0",
50
- "eslint-config-prettier": "^8.3.0",
51
- "eslint-config-standard": "^16.0.1",
52
- "eslint-plugin-import": "^2.22.1",
53
- "eslint-plugin-node": "^11.1.0",
54
- "eslint-plugin-prettier": "^3.1.4",
55
- "eslint-plugin-promise": "^4.2.1",
56
- "eslint-plugin-standard": "^4.1.0",
57
- "husky": "^6.0.0",
58
- "jest": "^26.6.3",
59
- "markdown-toc": "^1.2.0",
60
- "mkdirp": "^1.0.4",
61
- "npm-run-all": "^4.1.5",
62
- "os-tmpdir": "^2.0.0",
63
- "prettier": "^2.3.2",
64
- "rimraf": "^3.0.2",
65
- "server-ready": "^0.3.1",
66
- "standard": "^17.1.0",
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
- "repository": {
71
- "type": "git",
72
- "url": "git://github.com/typicode/json-server.git"
73
- },
74
- "keywords": [
75
- "JSON",
76
- "server",
77
- "fake",
78
- "REST",
79
- "API",
80
- "prototyping",
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
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
-
4
- require('please-upgrade-node')(require('../../package.json'));
5
- require('./')();
package/lib/cli/index.js DELETED
@@ -1,77 +0,0 @@
1
- "use strict";
2
-
3
- const yargs = require('yargs');
4
- const run = require('./run');
5
- const pkg = require('../../package.json');
6
- module.exports = function () {
7
- const argv = yargs.config('config').usage('$0 [options] <source>').options({
8
- port: {
9
- alias: 'p',
10
- description: 'Set port',
11
- default: 3000
12
- },
13
- host: {
14
- alias: 'H',
15
- description: 'Set host',
16
- default: 'localhost'
17
- },
18
- watch: {
19
- alias: 'w',
20
- description: 'Watch file(s)'
21
- },
22
- routes: {
23
- alias: 'r',
24
- description: 'Path to routes file'
25
- },
26
- middlewares: {
27
- alias: 'm',
28
- array: true,
29
- description: 'Paths to middleware files'
30
- },
31
- static: {
32
- alias: 's',
33
- description: 'Set static files directory'
34
- },
35
- 'read-only': {
36
- alias: 'ro',
37
- description: 'Allow only GET requests'
38
- },
39
- 'no-cors': {
40
- alias: 'nc',
41
- description: 'Disable Cross-Origin Resource Sharing'
42
- },
43
- 'no-gzip': {
44
- alias: 'ng',
45
- description: 'Disable GZIP Content-Encoding'
46
- },
47
- snapshots: {
48
- alias: 'S',
49
- description: 'Set snapshots directory',
50
- default: '.'
51
- },
52
- delay: {
53
- alias: 'd',
54
- description: 'Add delay to responses (ms)'
55
- },
56
- id: {
57
- alias: 'i',
58
- description: 'Set database id property (e.g. _id)',
59
- default: 'id'
60
- },
61
- foreignKeySuffix: {
62
- alias: 'fks',
63
- description: 'Set foreign key suffix (e.g. _id as in post_id)',
64
- default: 'Id'
65
- },
66
- quiet: {
67
- alias: 'q',
68
- description: 'Suppress log messages from output'
69
- },
70
- config: {
71
- alias: 'c',
72
- description: 'Path to config file',
73
- default: 'json-server.json'
74
- }
75
- }).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;
76
- run(argv);
77
- };
package/lib/cli/run.js DELETED
@@ -1,213 +0,0 @@
1
- "use strict";
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const jph = require('json-parse-helpfulerror');
6
- const _ = require('lodash');
7
- const chalk = require('chalk');
8
- const enableDestroy = require('server-destroy');
9
- const pause = require('connect-pause');
10
- const is = require('./utils/is');
11
- const load = require('./utils/load');
12
- const jsonServer = require('../server');
13
- function prettyPrint(argv, object, rules) {
14
- const root = `http://${argv.host}:${argv.port}`;
15
- console.log();
16
- console.log(chalk.bold(' Resources'));
17
- for (const prop in object) {
18
- // skip printing $schema nodes
19
- if (prop === '$schema') continue;
20
- console.log(` ${root}/${prop}`);
21
- }
22
- if (rules) {
23
- console.log();
24
- console.log(chalk.bold(' Other routes'));
25
- for (const rule in rules) {
26
- console.log(` ${rule} -> ${rules[rule]}`);
27
- }
28
- }
29
- console.log();
30
- console.log(chalk.bold(' Home'));
31
- console.log(` ${root}`);
32
- console.log();
33
- }
34
- function createApp(db, routes, middlewares, argv) {
35
- const app = jsonServer.create();
36
- const {
37
- foreignKeySuffix
38
- } = argv;
39
- const router = jsonServer.router(db, foreignKeySuffix ? {
40
- foreignKeySuffix
41
- } : undefined);
42
- const defaultsOpts = {
43
- logger: !argv.quiet,
44
- readOnly: argv.readOnly,
45
- noCors: argv.noCors,
46
- noGzip: argv.noGzip,
47
- bodyParser: true
48
- };
49
- if (argv.static) {
50
- defaultsOpts.static = path.join(process.cwd(), argv.static);
51
- }
52
- const defaults = jsonServer.defaults(defaultsOpts);
53
- app.use(defaults);
54
- if (routes) {
55
- const rewriter = jsonServer.rewriter(routes);
56
- app.use(rewriter);
57
- }
58
- if (middlewares) {
59
- app.use(middlewares);
60
- }
61
- if (argv.delay) {
62
- app.use(pause(argv.delay));
63
- }
64
- router.db._.id = argv.id;
65
- app.db = router.db;
66
- app.use(router);
67
- return app;
68
- }
69
- module.exports = function (argv) {
70
- const source = argv._[0];
71
- let app;
72
- let server;
73
- if (!fs.existsSync(argv.snapshots)) {
74
- console.log(`Error: snapshots directory ${argv.snapshots} doesn't exist`);
75
- process.exit(1);
76
- }
77
-
78
- // noop log fn
79
- if (argv.quiet) {
80
- console.log = () => {};
81
- }
82
- console.log();
83
- console.log(chalk.cyan(' \\{^_^}/ hi!'));
84
- function start(cb) {
85
- console.log();
86
- console.log(chalk.gray(' Loading', source));
87
- server = undefined;
88
-
89
- // create db and load object, JSON file, JS or HTTP database
90
- return load(source).then(db => {
91
- // Load additional routes
92
- let routes;
93
- if (argv.routes) {
94
- console.log(chalk.gray(' Loading', argv.routes));
95
- routes = JSON.parse(fs.readFileSync(argv.routes));
96
- }
97
-
98
- // Load middlewares
99
- let middlewares;
100
- if (argv.middlewares) {
101
- middlewares = argv.middlewares.map(function (m) {
102
- console.log(chalk.gray(' Loading', m));
103
- return require(path.resolve(m));
104
- });
105
- }
106
-
107
- // Done
108
- console.log(chalk.gray(' Done'));
109
-
110
- // Create app and server
111
- app = createApp(db, routes, middlewares, argv);
112
- server = app.listen(argv.port, argv.host);
113
-
114
- // Enhance with a destroy function
115
- enableDestroy(server);
116
-
117
- // Display server informations
118
- prettyPrint(argv, db.getState(), routes);
119
-
120
- // Catch and handle any error occurring in the server process
121
- process.on('uncaughtException', error => {
122
- 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);
123
- process.exit(1);
124
- });
125
- });
126
- }
127
-
128
- // Start server
129
- start().then(() => {
130
- // Snapshot
131
- console.log(chalk.gray(' Type s + enter at any time to create a snapshot of the database'));
132
-
133
- // Support nohup
134
- // https://github.com/typicode/json-server/issues/221
135
- process.stdin.on('error', () => {
136
- console.log(` Error, can't read from stdin`);
137
- console.log(` Creating a snapshot from the CLI won't be possible`);
138
- });
139
- process.stdin.setEncoding('utf8');
140
- process.stdin.on('data', chunk => {
141
- if (chunk.trim().toLowerCase() === 's') {
142
- const filename = `db-${Date.now()}.json`;
143
- const file = path.join(argv.snapshots, filename);
144
- const state = app.db.getState();
145
- fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8');
146
- console.log(` Saved snapshot to ${path.relative(process.cwd(), file)}\n`);
147
- }
148
- });
149
-
150
- // Watch files
151
- if (argv.watch) {
152
- console.log(chalk.gray(' Watching...'));
153
- console.log();
154
- const source = argv._[0];
155
-
156
- // Can't watch URL
157
- if (is.URL(source)) throw new Error("Can't watch URL");
158
-
159
- // Watch .js or .json file
160
- // Since lowdb uses atomic writing, directory is watched instead of file
161
- const watchedDir = path.dirname(source);
162
- let readError = false;
163
- fs.watch(watchedDir, (event, file) => {
164
- // https://github.com/typicode/json-server/issues/420
165
- // file can be null
166
- if (file) {
167
- const watchedFile = path.resolve(watchedDir, file);
168
- if (watchedFile === path.resolve(source)) {
169
- if (is.FILE(watchedFile)) {
170
- let obj;
171
- try {
172
- obj = jph.parse(fs.readFileSync(watchedFile));
173
- if (readError) {
174
- console.log(chalk.green(` Read error has been fixed :)`));
175
- readError = false;
176
- }
177
- } catch (e) {
178
- readError = true;
179
- console.log(chalk.red(` Error reading ${watchedFile}`));
180
- console.error(e.message);
181
- return;
182
- }
183
-
184
- // Compare .json file content with in memory database
185
- const isDatabaseDifferent = !_.isEqual(obj, app.db.getState());
186
- if (isDatabaseDifferent) {
187
- console.log(chalk.gray(` ${source} has changed, reloading...`));
188
- server && server.destroy(() => start());
189
- }
190
- }
191
- }
192
- }
193
- });
194
-
195
- // Watch routes
196
- if (argv.routes) {
197
- const watchedDir = path.dirname(argv.routes);
198
- fs.watch(watchedDir, (event, file) => {
199
- if (file) {
200
- const watchedFile = path.resolve(watchedDir, file);
201
- if (watchedFile === path.resolve(argv.routes)) {
202
- console.log(chalk.gray(` ${argv.routes} has changed, reloading...`));
203
- server && server.destroy(() => start());
204
- }
205
- }
206
- });
207
- }
208
- }
209
- }).catch(err => {
210
- console.log(err);
211
- process.exit(1);
212
- });
213
- };
@@ -1,16 +0,0 @@
1
- "use strict";
2
-
3
- module.exports = {
4
- FILE,
5
- JS,
6
- URL
7
- };
8
- function FILE(s) {
9
- return !URL(s) && /\.json$/.test(s);
10
- }
11
- function JS(s) {
12
- return !URL(s) && /\.c?js$/.test(s);
13
- }
14
- function URL(s) {
15
- return /^(http|https):/.test(s);
16
- }
@@ -1,69 +0,0 @@
1
- "use strict";
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const http = require('http');
6
- const https = require('https');
7
- const low = require('lowdb');
8
- const FileAsync = require('lowdb/adapters/FileAsync');
9
- const Memory = require('lowdb/adapters/Memory');
10
- const is = require('./is');
11
- const chalk = require('chalk');
12
- const example = {
13
- posts: [{
14
- id: 1,
15
- title: 'json-server',
16
- author: 'typicode'
17
- }],
18
- comments: [{
19
- id: 1,
20
- body: 'some comment',
21
- postId: 1
22
- }],
23
- profile: {
24
- name: 'typicode'
25
- }
26
- };
27
- module.exports = function (source) {
28
- return new Promise((resolve, reject) => {
29
- if (is.FILE(source)) {
30
- if (!fs.existsSync(source)) {
31
- console.log(chalk.yellow(` Oops, ${source} doesn't seem to exist`));
32
- console.log(chalk.yellow(` Creating ${source} with some default data`));
33
- console.log();
34
- fs.writeFileSync(source, JSON.stringify(example, null, 2));
35
- }
36
- resolve(low(new FileAsync(source)));
37
- } else if (is.URL(source)) {
38
- // Normalize the source into a URL object.
39
- const sourceUrl = new URL(source);
40
- // Pick the client based on the protocol scheme
41
- const client = sourceUrl.protocol === 'https:' ? https : http;
42
- client.get(sourceUrl, res => {
43
- let dbData = '';
44
- res.on('data', data => {
45
- dbData += data;
46
- });
47
- res.on('end', () => {
48
- resolve(low(new Memory()).setState(JSON.parse(dbData)));
49
- });
50
- }).on('error', error => {
51
- return reject(error);
52
- });
53
- } else if (is.JS(source)) {
54
- // Clear cache
55
- const filename = path.resolve(source);
56
- delete require.cache[filename];
57
- const dataFn = require(filename);
58
- if (typeof dataFn !== 'function') {
59
- throw new Error('The database is a JavaScript file but the export is not a function.');
60
- }
61
-
62
- // Run dataFn to generate data
63
- const data = dataFn();
64
- resolve(low(new Memory()).setState(data));
65
- } else {
66
- throw new Error(`Unsupported source ${source}`);
67
- }
68
- });
69
- };
@@ -1,9 +0,0 @@
1
- "use strict";
2
-
3
- const bodyParser = require('body-parser');
4
- module.exports = [bodyParser.json({
5
- limit: '10mb',
6
- extended: false
7
- }), bodyParser.urlencoded({
8
- extended: false
9
- })];
@@ -1,73 +0,0 @@
1
- "use strict";
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const express = require('express');
6
- const logger = require('morgan');
7
- const cors = require('cors');
8
- const compression = require('compression');
9
- const errorhandler = require('errorhandler');
10
- const bodyParser = require('./body-parser');
11
- module.exports = function (opts) {
12
- const userDir = path.join(process.cwd(), 'public');
13
- const defaultDir = path.join(__dirname, '../../public');
14
- const staticDir = fs.existsSync(userDir) ? userDir : defaultDir;
15
- opts = Object.assign({
16
- logger: true,
17
- static: staticDir
18
- }, opts);
19
- const arr = [];
20
-
21
- // Compress all requests
22
- if (!opts.noGzip) {
23
- arr.push(compression());
24
- }
25
-
26
- // Enable CORS for all the requests, including static files
27
- if (!opts.noCors) {
28
- arr.push(cors({
29
- origin: true,
30
- credentials: true
31
- }));
32
- }
33
- if (process.env.NODE_ENV === 'development') {
34
- // only use in development
35
- arr.push(errorhandler());
36
- }
37
-
38
- // Serve static files
39
- arr.push(express.static(opts.static));
40
-
41
- // Logger
42
- if (opts.logger) {
43
- arr.push(logger('dev', {
44
- skip: req => process.env.NODE_ENV === 'test' || req.path === '/favicon.ico'
45
- }));
46
- }
47
-
48
- // No cache for IE
49
- // https://support.microsoft.com/en-us/kb/234067
50
- arr.push((req, res, next) => {
51
- res.header('Cache-Control', 'no-cache');
52
- res.header('Pragma', 'no-cache');
53
- res.header('Expires', '-1');
54
- next();
55
- });
56
-
57
- // Read-only
58
- if (opts.readOnly) {
59
- arr.push((req, res, next) => {
60
- if (req.method === 'GET') {
61
- next(); // Continue
62
- } else {
63
- res.sendStatus(403); // Forbidden
64
- }
65
- });
66
- }
67
-
68
- // Add middlewares
69
- if (opts.bodyParser) {
70
- arr.push(bodyParser);
71
- }
72
- return arr;
73
- };
@@ -1,10 +0,0 @@
1
- "use strict";
2
-
3
- const express = require('express');
4
- module.exports = {
5
- create: () => express().set('json spaces', 2),
6
- defaults: require('./defaults'),
7
- router: require('./router'),
8
- rewriter: require('./rewriter'),
9
- bodyParser: require('./body-parser')
10
- };