mirror of
https://github.com/typicode/json-server.git
synced 2025-08-02 11:32:47 +08:00
feat: better cli output
This commit is contained in:
74
package-lock.json
generated
74
package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@tinyhttp/app": "^2.2.1",
|
||||
"@tinyhttp/cors": "^2.0.0",
|
||||
"chalk": "^5.3.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"dot-prop": "^8.0.2",
|
||||
"eta": "^3.2.0",
|
||||
@ -1428,16 +1429,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
@ -1554,6 +1550,34 @@
|
||||
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently/node_modules/chalk/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently/node_modules/supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
@ -2006,6 +2030,23 @@
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
||||
@ -2905,9 +2946,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -3173,9 +3214,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.23",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
|
||||
"integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
|
||||
"version": "8.4.33",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
|
||||
"integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -3192,7 +3233,7 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.6",
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
@ -3822,6 +3863,7 @@
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
|
@ -39,6 +39,7 @@
|
||||
"dependencies": {
|
||||
"@tinyhttp/app": "^2.2.1",
|
||||
"@tinyhttp/cors": "^2.0.0",
|
||||
"chalk": "^5.3.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"dot-prop": "^8.0.2",
|
||||
"eta": "^3.2.0",
|
||||
|
79
src/bin.ts
79
src/bin.ts
@ -3,6 +3,7 @@ import { existsSync, readFileSync } from 'node:fs'
|
||||
import { extname, join } from 'node:path'
|
||||
import { parseArgs } from 'node:util'
|
||||
|
||||
import chalk from 'chalk'
|
||||
import { watch } from 'chokidar'
|
||||
import JSON5 from 'json5'
|
||||
import { Adapter, Low } from 'lowdb'
|
||||
@ -65,7 +66,7 @@ const port = parseInt(values.port ?? process.env['PORT'] ?? '3000')
|
||||
const host = values.host ?? process.env['HOST'] ?? 'localhost'
|
||||
|
||||
if (!existsSync(file)) {
|
||||
console.log(`File ${file} not found`)
|
||||
console.log(chalk.red(`File ${file} not found`))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@ -87,13 +88,45 @@ await db.read()
|
||||
// Create app
|
||||
const app = createApp(db, { logger: false, static: values.static })
|
||||
|
||||
function routes(db: Low<Data>): string[] {
|
||||
return Object.keys(db.data).map((key) => `http://${host}:${port}/${key}`)
|
||||
function logRoutes(data: Data) {
|
||||
console.log(
|
||||
[
|
||||
chalk.bold('Endpoints:'),
|
||||
...Object.keys(data).map(
|
||||
(key) => `${chalk.gray(`http://${host}:${port}/`)}${chalk.blue(key)}`,
|
||||
),
|
||||
].join('\n'),
|
||||
)
|
||||
}
|
||||
|
||||
const kaomojis = ['♡⸜(˶˃ ᵕ ˂˶)⸝♡', '♡( ◡‿◡ )', '( ˶ˆ ᗜ ˆ˵ )', '(˶ᵔ ᵕ ᵔ˶)']
|
||||
|
||||
// Get system current language
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(
|
||||
[
|
||||
chalk.bold(`JSON Server started on PORT :${port}`),
|
||||
chalk.gray('Press CTRL-C to stop'),
|
||||
chalk.gray(`Watching ${file}...`),
|
||||
'',
|
||||
chalk.magenta(kaomojis[Math.floor(Math.random() * kaomojis.length)]),
|
||||
'',
|
||||
chalk.bold('Index:'),
|
||||
chalk.gray(`http://localhost:${port}/`),
|
||||
'',
|
||||
chalk.bold('Static files:'),
|
||||
chalk.gray('Serving ./public directory if it exists'),
|
||||
'',
|
||||
].join('\n'),
|
||||
)
|
||||
logRoutes(db.data)
|
||||
})
|
||||
|
||||
// Watch file for changes
|
||||
if (process.env['NODE_ENV'] !== 'production') {
|
||||
let writing = false // true if the file is being written to by the app
|
||||
let prevEndpoints = ''
|
||||
|
||||
observer.onWriteStart = () => {
|
||||
writing = true
|
||||
@ -101,26 +134,32 @@ if (process.env['NODE_ENV'] !== 'production') {
|
||||
observer.onWriteEnd = () => {
|
||||
writing = false
|
||||
}
|
||||
observer.onReadStart = () => console.log(`Reloading ${file}...`)
|
||||
observer.onReadEnd = () => console.log('Reloaded')
|
||||
observer.onReadStart = () => {
|
||||
prevEndpoints = JSON.stringify(Object.keys(db.data).sort())
|
||||
}
|
||||
|
||||
observer.onReadEnd = (data) => {
|
||||
if (data === null) {
|
||||
return
|
||||
}
|
||||
|
||||
const nextEndpoints = JSON.stringify(Object.keys(data).sort())
|
||||
if (prevEndpoints !== nextEndpoints) {
|
||||
console.log()
|
||||
logRoutes(data)
|
||||
}
|
||||
}
|
||||
watch(file).on('change', () => {
|
||||
// Do no reload if the file is being written to by the app
|
||||
if (!writing) {
|
||||
db.read()
|
||||
.then(() => routes(db))
|
||||
.catch((e) => {
|
||||
if (e instanceof SyntaxError) {
|
||||
return console.log(e.message)
|
||||
}
|
||||
console.log(e)
|
||||
})
|
||||
db.read().catch((e) => {
|
||||
if (e instanceof SyntaxError) {
|
||||
return console.log(
|
||||
chalk.red(['', `Error parsing ${file}`, e.message].join('\n')),
|
||||
)
|
||||
}
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Started on :${port}`)
|
||||
console.log(`http://localhost:${port}/`)
|
||||
console.log(routes(db).join('\n'))
|
||||
console.log(`Watching ${file}...`)
|
||||
})
|
||||
|
@ -7,7 +7,7 @@ export class Observer<T> {
|
||||
onReadStart = function () {
|
||||
return
|
||||
}
|
||||
onReadEnd = function () {
|
||||
onReadEnd: (data: T | null) => void = function () {
|
||||
return
|
||||
}
|
||||
onWriteStart = function () {
|
||||
@ -24,7 +24,7 @@ export class Observer<T> {
|
||||
async read() {
|
||||
this.onReadStart()
|
||||
const data = await this.#adapter.read()
|
||||
this.onReadEnd()
|
||||
this.onReadEnd(data)
|
||||
return data
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user