forked from typicode/json-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
reworked scripts and added lib for direct git install
- Loading branch information
1 parent
a641111
commit e1e5e57
Showing
22 changed files
with
1,085 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
**/*.log | ||
node_modules | ||
tmp | ||
lib | ||
|
||
.DS_Store | ||
.idea | ||
db.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,2 @@ | ||
#!/bin/sh | ||
. "$(dirname $0)/_/husky.sh" | ||
|
||
npm test | ||
. "$(dirname $0)/_/husky.sh" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/usr/bin/env node | ||
"use strict"; | ||
|
||
require('please-upgrade-node')(require('../../package.json')); | ||
require('./')(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
"use strict"; | ||
|
||
const yargs = require('yargs'); | ||
const run = require('./run'); | ||
const pkg = require('../../package.json'); | ||
module.exports = function () { | ||
const argv = yargs.config('config').usage('$0 [options] <source>').options({ | ||
port: { | ||
alias: 'p', | ||
description: 'Set port', | ||
default: 3000 | ||
}, | ||
host: { | ||
alias: 'H', | ||
description: 'Set host', | ||
default: 'localhost' | ||
}, | ||
watch: { | ||
alias: 'w', | ||
description: 'Watch file(s)' | ||
}, | ||
routes: { | ||
alias: 'r', | ||
description: 'Path to routes file' | ||
}, | ||
middlewares: { | ||
alias: 'm', | ||
array: true, | ||
description: 'Paths to middleware files' | ||
}, | ||
static: { | ||
alias: 's', | ||
description: 'Set static files directory' | ||
}, | ||
'read-only': { | ||
alias: 'ro', | ||
description: 'Allow only GET requests' | ||
}, | ||
'no-cors': { | ||
alias: 'nc', | ||
description: 'Disable Cross-Origin Resource Sharing' | ||
}, | ||
'no-gzip': { | ||
alias: 'ng', | ||
description: 'Disable GZIP Content-Encoding' | ||
}, | ||
snapshots: { | ||
alias: 'S', | ||
description: 'Set snapshots directory', | ||
default: '.' | ||
}, | ||
delay: { | ||
alias: 'd', | ||
description: 'Add delay to responses (ms)' | ||
}, | ||
id: { | ||
alias: 'i', | ||
description: 'Set database id property (e.g. _id)', | ||
default: 'id' | ||
}, | ||
foreignKeySuffix: { | ||
alias: 'fks', | ||
description: 'Set foreign key suffix (e.g. _id as in post_id)', | ||
default: 'Id' | ||
}, | ||
quiet: { | ||
alias: 'q', | ||
description: 'Suppress log messages from output' | ||
}, | ||
config: { | ||
alias: 'c', | ||
description: 'Path to config file', | ||
default: 'json-server.json' | ||
} | ||
}).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; | ||
run(argv); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
"use strict"; | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
const jph = require('json-parse-helpfulerror'); | ||
const _ = require('lodash'); | ||
const chalk = require('chalk'); | ||
const enableDestroy = require('server-destroy'); | ||
const pause = require('connect-pause'); | ||
const is = require('./utils/is'); | ||
const load = require('./utils/load'); | ||
const jsonServer = require('../server'); | ||
function prettyPrint(argv, object, rules) { | ||
const root = `http://${argv.host}:${argv.port}`; | ||
console.log(); | ||
console.log(chalk.bold(' Resources')); | ||
for (const prop in object) { | ||
// skip printing $schema nodes | ||
if (prop === '$schema') continue; | ||
console.log(` ${root}/${prop}`); | ||
} | ||
if (rules) { | ||
console.log(); | ||
console.log(chalk.bold(' Other routes')); | ||
for (const rule in rules) { | ||
console.log(` ${rule} -> ${rules[rule]}`); | ||
} | ||
} | ||
console.log(); | ||
console.log(chalk.bold(' Home')); | ||
console.log(` ${root}`); | ||
console.log(); | ||
} | ||
function createApp(db, routes, middlewares, argv) { | ||
const app = jsonServer.create(); | ||
const { | ||
foreignKeySuffix | ||
} = argv; | ||
const router = jsonServer.router(db, foreignKeySuffix ? { | ||
foreignKeySuffix | ||
} : undefined); | ||
const defaultsOpts = { | ||
logger: !argv.quiet, | ||
readOnly: argv.readOnly, | ||
noCors: argv.noCors, | ||
noGzip: argv.noGzip, | ||
bodyParser: true | ||
}; | ||
if (argv.static) { | ||
defaultsOpts.static = path.join(process.cwd(), argv.static); | ||
} | ||
const defaults = jsonServer.defaults(defaultsOpts); | ||
app.use(defaults); | ||
if (routes) { | ||
const rewriter = jsonServer.rewriter(routes); | ||
app.use(rewriter); | ||
} | ||
if (middlewares) { | ||
app.use(middlewares); | ||
} | ||
if (argv.delay) { | ||
app.use(pause(argv.delay)); | ||
} | ||
router.db._.id = argv.id; | ||
app.db = router.db; | ||
app.use(router); | ||
return app; | ||
} | ||
module.exports = function (argv) { | ||
const source = argv._[0]; | ||
let app; | ||
let server; | ||
if (!fs.existsSync(argv.snapshots)) { | ||
console.log(`Error: snapshots directory ${argv.snapshots} doesn't exist`); | ||
process.exit(1); | ||
} | ||
|
||
// noop log fn | ||
if (argv.quiet) { | ||
console.log = () => {}; | ||
} | ||
console.log(); | ||
console.log(chalk.cyan(' \\{^_^}/ hi!')); | ||
function start(cb) { | ||
console.log(); | ||
console.log(chalk.gray(' Loading', source)); | ||
server = undefined; | ||
|
||
// create db and load object, JSON file, JS or HTTP database | ||
return load(source).then(db => { | ||
// Load additional routes | ||
let routes; | ||
if (argv.routes) { | ||
console.log(chalk.gray(' Loading', argv.routes)); | ||
routes = JSON.parse(fs.readFileSync(argv.routes)); | ||
} | ||
|
||
// Load middlewares | ||
let middlewares; | ||
if (argv.middlewares) { | ||
middlewares = argv.middlewares.map(function (m) { | ||
console.log(chalk.gray(' Loading', m)); | ||
return require(path.resolve(m)); | ||
}); | ||
} | ||
|
||
// Done | ||
console.log(chalk.gray(' Done')); | ||
|
||
// Create app and server | ||
app = createApp(db, routes, middlewares, argv); | ||
server = app.listen(argv.port, argv.host); | ||
|
||
// Enhance with a destroy function | ||
enableDestroy(server); | ||
|
||
// Display server informations | ||
prettyPrint(argv, db.getState(), routes); | ||
|
||
// Catch and handle any error occurring in the server process | ||
process.on('uncaughtException', error => { | ||
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); | ||
process.exit(1); | ||
}); | ||
}); | ||
} | ||
|
||
// Start server | ||
start().then(() => { | ||
// Snapshot | ||
console.log(chalk.gray(' Type s + enter at any time to create a snapshot of the database')); | ||
|
||
// Support nohup | ||
// https://github.com/typicode/json-server/issues/221 | ||
process.stdin.on('error', () => { | ||
console.log(` Error, can't read from stdin`); | ||
console.log(` Creating a snapshot from the CLI won't be possible`); | ||
}); | ||
process.stdin.setEncoding('utf8'); | ||
process.stdin.on('data', chunk => { | ||
if (chunk.trim().toLowerCase() === 's') { | ||
const filename = `db-${Date.now()}.json`; | ||
const file = path.join(argv.snapshots, filename); | ||
const state = app.db.getState(); | ||
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8'); | ||
console.log(` Saved snapshot to ${path.relative(process.cwd(), file)}\n`); | ||
} | ||
}); | ||
|
||
// Watch files | ||
if (argv.watch) { | ||
console.log(chalk.gray(' Watching...')); | ||
console.log(); | ||
const source = argv._[0]; | ||
|
||
// Can't watch URL | ||
if (is.URL(source)) throw new Error("Can't watch URL"); | ||
|
||
// Watch .js or .json file | ||
// Since lowdb uses atomic writing, directory is watched instead of file | ||
const watchedDir = path.dirname(source); | ||
let readError = false; | ||
fs.watch(watchedDir, (event, file) => { | ||
// https://github.com/typicode/json-server/issues/420 | ||
// file can be null | ||
if (file) { | ||
const watchedFile = path.resolve(watchedDir, file); | ||
if (watchedFile === path.resolve(source)) { | ||
if (is.FILE(watchedFile)) { | ||
let obj; | ||
try { | ||
obj = jph.parse(fs.readFileSync(watchedFile)); | ||
if (readError) { | ||
console.log(chalk.green(` Read error has been fixed :)`)); | ||
readError = false; | ||
} | ||
} catch (e) { | ||
readError = true; | ||
console.log(chalk.red(` Error reading ${watchedFile}`)); | ||
console.error(e.message); | ||
return; | ||
} | ||
|
||
// Compare .json file content with in memory database | ||
const isDatabaseDifferent = !_.isEqual(obj, app.db.getState()); | ||
if (isDatabaseDifferent) { | ||
console.log(chalk.gray(` ${source} has changed, reloading...`)); | ||
server && server.destroy(() => start()); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
|
||
// Watch routes | ||
if (argv.routes) { | ||
const watchedDir = path.dirname(argv.routes); | ||
fs.watch(watchedDir, (event, file) => { | ||
if (file) { | ||
const watchedFile = path.resolve(watchedDir, file); | ||
if (watchedFile === path.resolve(argv.routes)) { | ||
console.log(chalk.gray(` ${argv.routes} has changed, reloading...`)); | ||
server && server.destroy(() => start()); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
}).catch(err => { | ||
console.log(err); | ||
process.exit(1); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
"use strict"; | ||
|
||
module.exports = { | ||
FILE, | ||
JS, | ||
URL | ||
}; | ||
function FILE(s) { | ||
return !URL(s) && /\.json$/.test(s); | ||
} | ||
function JS(s) { | ||
return !URL(s) && /\.c?js$/.test(s); | ||
} | ||
function URL(s) { | ||
return /^(http|https):/.test(s); | ||
} |
Oops, something went wrong.