feat: better cli output

This commit is contained in:
typicode
2024-01-07 02:16:37 +01:00
parent 72a98336fa
commit ac42825be5
4 changed files with 120 additions and 38 deletions

74
package-lock.json generated
View File

@ -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"
},

View File

@ -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",

View File

@ -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}...`)
})

View 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
}