@@ -24,6 +24,14 @@ import fs from 'fs';
24
24
import { createServer } from '../lib' ;
25
25
import { CliArgs , ServerOptions } from '../types' ;
26
26
import { fileExists } from '../utils/utils' ;
27
+ import {
28
+ styles ,
29
+ createHeader ,
30
+ createBox ,
31
+ formatList ,
32
+ formatHelp ,
33
+ formatError ,
34
+ } from '../utils/cli-styles' ;
27
35
28
36
// Default server configuration
29
37
const DEFAULT_PORT = 3000 ;
@@ -80,10 +88,22 @@ function showVersion(): void {
80
88
const packageJsonPath = path . join ( __dirname , '../../package.json' ) ;
81
89
const packageJson = JSON . parse ( fs . readFileSync ( packageJsonPath , 'utf8' ) ) ;
82
90
83
- console . log ( `@webmasterdevlin/json-server v${ packageJson . version } ` ) ;
91
+ console . log (
92
+ createBox (
93
+ '⚡️ @webmasterdevlin/json-server' ,
94
+ [
95
+ '' ,
96
+ `${ styles . primary ( 'Version:' ) } ${ styles . highlight ( packageJson . version ) } ` ,
97
+ '' ,
98
+ `${ styles . secondary ( 'TypeScript-powered REST API mock server' ) } ` ,
99
+ '' ,
100
+ ] ,
101
+ 'default'
102
+ )
103
+ ) ;
84
104
} catch ( error ) {
85
105
const errorMessage = error instanceof Error ? error . message : String ( error ) ;
86
- console . error ( ' Error reading package version:' , errorMessage ) ;
106
+ console . error ( formatError ( 'Version Error' , `Error reading package version: ${ errorMessage } ` ) ) ;
87
107
process . exit ( 1 ) ;
88
108
}
89
109
}
@@ -92,50 +112,46 @@ function showVersion(): void {
92
112
* Display help information with usage examples
93
113
*/
94
114
function showHelp ( ) : void {
95
- console . log ( `
96
- ╭───────────────────────────────────────────────────────────────────────────╮
97
- │ │
98
- │ @webmasterdevlin/json-server CLI │
99
- │ │
100
- ╰───────────────────────────────────────────────────────────────────────────╯
101
-
102
- A TypeScript implementation of json-server with additional features.
103
-
104
- Usage:
105
- json-server [options] <source>
106
-
107
- Options:
108
- --port, -p Set port [default: 3000]
109
- --host, -H Set host [default: "localhost"]
110
- --watch, -w Watch for changes [default: false]
111
- --routes, -r Path to routes file [string]
112
- --middlewares, -m Path to middlewares files [array]
113
- --static, -s Path to static files [array]
114
- --read-only, --ro Allow only GET requests [default: false]
115
- --no-cors, --nc Disable CORS [default: false]
116
- --no-gzip, --ng Disable GZIP compression [default: false]
117
- --enable-api-prefix, --api Enable /api/* prefix [default: false]
118
- --delay, -d Add delay to responses (ms) [number]
119
- --id, -i Set database id field [default: "id"]
120
- --foreignKeySuffix Set foreign key suffix [default: "_id"]
121
- --quiet, -q Suppress log messages [default: false]
122
- --help, -h Show help [boolean]
123
- --version, -v Show version [boolean]
124
-
125
- Examples:
126
- json-server db.json
127
- json-server db.json --port 3001
128
- json-server db.json --watch
129
- json-server db.json --routes routes.json
130
- json-server db.json --routes routes.js
131
- json-server db.json --delay 1000
132
- json-server db.json --id _id
133
- json-server db.json --enable-api-prefix # Enable /api/* routes
134
- json-server http://example.com/db.json
135
-
136
- For more information, visit:
137
- https://github.com/webmasterdevlin/json-server
138
- ` ) ;
115
+ // Create sections for the help display
116
+ const sections : Record < string , string > = {
117
+ Usage : `${ styles . command ( 'json-server' ) } ${ styles . info ( '[options]' ) } ${ styles . highlight ( '<source>' ) } ` ,
118
+
119
+ Options : formatList ( [
120
+ `${ styles . key ( '--port, -p' ) } ${ styles . value ( 'Set port' ) } ${ styles . muted ( ' [default: 3000]' ) } ` ,
121
+ `${ styles . key ( '--host, -H' ) } ${ styles . value ( 'Set host' ) } ${ styles . muted ( ' [default: "localhost"]' ) } ` ,
122
+ `${ styles . key ( '--watch, -w' ) } ${ styles . value ( 'Watch for changes' ) } ${ styles . muted ( ' [default: false]' ) } ` ,
123
+ `${ styles . key ( '--routes, -r' ) } ${ styles . value ( 'Path to routes file' ) } ${ styles . muted ( ' [string]' ) } ` ,
124
+ `${ styles . key ( '--middlewares, -m' ) } ${ styles . value ( 'Path to middlewares files' ) } ${ styles . muted ( ' [array]' ) } ` ,
125
+ `${ styles . key ( '--static, -s' ) } ${ styles . value ( 'Path to static files' ) } ${ styles . muted ( ' [array]' ) } ` ,
126
+ `${ styles . key ( '--read-only, --ro' ) } ${ styles . value ( 'Allow only GET requests' ) } ${ styles . muted ( ' [default: false]' ) } ` ,
127
+ `${ styles . key ( '--no-cors, --nc' ) } ${ styles . value ( 'Disable CORS' ) } ${ styles . muted ( ' [default: false]' ) } ` ,
128
+ `${ styles . key ( '--no-gzip, --ng' ) } ${ styles . value ( 'Disable GZIP compression' ) } ${ styles . muted ( ' [default: false]' ) } ` ,
129
+ `${ styles . key ( '--enable-api-prefix, --api' ) } ${ styles . value ( 'Enable /api/* prefix' ) } ${ styles . muted ( ' [default: false]' ) } ` ,
130
+ `${ styles . key ( '--delay, -d' ) } ${ styles . value ( 'Add delay to responses (ms)' ) } ${ styles . muted ( ' [number]' ) } ` ,
131
+ `${ styles . key ( '--id, -i' ) } ${ styles . value ( 'Set database id field' ) } ${ styles . muted ( ' [default: "id"]' ) } ` ,
132
+ `${ styles . key ( '--foreignKeySuffix' ) } ${ styles . value ( 'Set foreign key suffix' ) } ${ styles . muted ( ' [default: "_id"]' ) } ` ,
133
+ `${ styles . key ( '--quiet, -q' ) } ${ styles . value ( 'Suppress log messages' ) } ${ styles . muted ( ' [default: false]' ) } ` ,
134
+ `${ styles . key ( '--help, -h' ) } ${ styles . value ( 'Show help' ) } ${ styles . muted ( ' [boolean]' ) } ` ,
135
+ `${ styles . key ( '--version, -v' ) } ${ styles . value ( 'Show version' ) } ${ styles . muted ( ' [boolean]' ) } ` ,
136
+ ] ) ,
137
+
138
+ Examples : formatList ( [
139
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ` ,
140
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ${ styles . info ( '--port 3001' ) } ` ,
141
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ${ styles . info ( '--watch' ) } ` ,
142
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ${ styles . info ( '--routes routes.json' ) } ` ,
143
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ${ styles . info ( '--routes routes.js' ) } ` ,
144
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ${ styles . info ( '--delay 1000' ) } ` ,
145
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ${ styles . info ( '--id _id' ) } ` ,
146
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'db.json' ) } ${ styles . info ( '--enable-api-prefix' ) } ${ styles . muted ( '# Enable /api/* routes' ) } ` ,
147
+ `${ styles . command ( 'json-server' ) } ${ styles . highlight ( 'http://example.com/db.json' ) } ` ,
148
+ ] ) ,
149
+
150
+ 'More Information' : `${ styles . url ( 'https://github.com/webmasterdevlin/json-server' ) } ` ,
151
+ } ;
152
+
153
+ // Display the help sections
154
+ console . log ( formatHelp ( sections ) ) ;
139
155
}
140
156
141
157
/**
@@ -158,19 +174,39 @@ async function main(): Promise<void> {
158
174
const cliArgs = parseArgs ( ) ;
159
175
const args = process . argv . slice ( 2 ) ;
160
176
177
+ // Show welcome banner
178
+ if ( ! cliArgs . quiet ) {
179
+ console . log ( createHeader ( ) ) ;
180
+ }
181
+
161
182
// Get database source
162
183
const source = getSourcePath ( args ) ;
163
184
if ( ! source ) {
164
- console . error ( 'Error: No database source provided' ) ;
185
+ console . error (
186
+ formatError (
187
+ 'Missing Source' ,
188
+ 'No database source provided.' ,
189
+ 'Please specify a JSON file or URL to use as database.'
190
+ )
191
+ ) ;
165
192
showHelp ( ) ;
166
193
process . exit ( 1 ) ;
167
194
}
168
195
169
196
// Check if source file exists (if it's a local file)
170
197
if ( source . startsWith ( 'http://' ) || source . startsWith ( 'https://' ) ) {
171
- console . log ( `Using remote database: ${ source } ` ) ;
198
+ console . log (
199
+ styles . icons . database ,
200
+ styles . info ( `Using remote database: ${ styles . url ( source ) } ` )
201
+ ) ;
172
202
} else if ( ! fileExists ( source ) ) {
173
- console . error ( `Error: Database file not found: ${ source } ` ) ;
203
+ console . error (
204
+ formatError (
205
+ 'Database Error' ,
206
+ `Database file not found: ${ source } ` ,
207
+ 'Make sure the file exists and you have permissions to read it.'
208
+ )
209
+ ) ;
174
210
process . exit ( 1 ) ;
175
211
}
176
212
@@ -201,9 +237,12 @@ async function main(): Promise<void> {
201
237
// Load custom routes if specified
202
238
if ( cliArgs . routes ) {
203
239
if ( ! fileExists ( cliArgs . routes ) ) {
204
- console . warn ( `Warning: Routes file not found: ${ cliArgs . routes } ` ) ;
240
+ console . warn (
241
+ styles . icons . warning ,
242
+ styles . warning ( `Routes file not found: ${ styles . highlight ( cliArgs . routes ) } ` )
243
+ ) ;
205
244
} else {
206
- server . loadRoutes ( cliArgs . routes ) ;
245
+ await server . loadRoutes ( cliArgs . routes ) ;
207
246
}
208
247
}
209
248
@@ -219,7 +258,7 @@ async function main(): Promise<void> {
219
258
}
220
259
} catch ( error ) {
221
260
const errorMessage = error instanceof Error ? error . message : String ( error ) ;
222
- console . error ( ' Error starting server:' , errorMessage ) ;
261
+ console . error ( formatError ( 'Server Error' , `Error starting server: ${ errorMessage } ` ) ) ;
223
262
process . exit ( 1 ) ;
224
263
}
225
264
}
@@ -235,37 +274,49 @@ function setupFileWatcher(dbPath: string, server: any): void {
235
274
// Use Node's fs.watch API to monitor file changes
236
275
fs . watch ( dbPath , ( eventType ) => {
237
276
if ( eventType === 'change' ) {
238
- console . log ( `Database file changed: ${ dbPath } ` ) ;
277
+ console . log (
278
+ styles . icons . watch ,
279
+ styles . info ( `${ styles . highlight ( dbPath ) } changed, reloading database...` )
280
+ ) ;
239
281
try {
240
282
server . loadDatabase ( dbPath ) ;
241
- console . log ( 'Database reloaded' ) ;
283
+ console . log ( styles . icons . success , styles . success ( 'Database reloaded successfully' ) ) ;
242
284
} catch ( error ) {
243
285
const errorMessage = error instanceof Error ? error . message : String ( error ) ;
244
- console . error ( 'Error reloading database:' , errorMessage ) ;
286
+ console . error (
287
+ styles . icons . error ,
288
+ styles . error ( `Error reloading database: ${ errorMessage } ` )
289
+ ) ;
245
290
}
246
291
}
247
292
} ) ;
248
293
249
- console . log ( `Watching for changes: ${ dbPath } ` ) ;
294
+ console . log (
295
+ styles . icons . watch ,
296
+ styles . info ( `Watching for changes: ${ styles . highlight ( dbPath ) } ` )
297
+ ) ;
250
298
} catch ( error ) {
251
299
const errorMessage = error instanceof Error ? error . message : String ( error ) ;
252
- console . error ( 'Error setting up file watcher:' , errorMessage ) ;
300
+ console . error (
301
+ styles . icons . error ,
302
+ styles . error ( `Error setting up file watcher: ${ errorMessage } ` )
303
+ ) ;
253
304
}
254
305
}
255
306
256
307
// Handle process termination gracefully
257
308
process . on ( 'SIGINT' , ( ) => {
258
- console . log ( '\nReceived SIGINT. Shutting down...' ) ;
309
+ console . log ( '\n' + styles . icons . stop , styles . info ( 'Received SIGINT. Shutting down...') ) ;
259
310
process . exit ( 0 ) ;
260
311
} ) ;
261
312
262
313
process . on ( 'SIGTERM' , ( ) => {
263
- console . log ( '\nReceived SIGTERM. Shutting down...' ) ;
314
+ console . log ( '\n' + styles . icons . stop , styles . info ( 'Received SIGTERM. Shutting down...') ) ;
264
315
process . exit ( 0 ) ;
265
316
} ) ;
266
317
267
318
// Start the application
268
319
main ( ) . catch ( ( error ) => {
269
- console . error ( 'Fatal error: ' , error . message ) ;
320
+ console . error ( formatError ( 'Fatal Error ' , error . message ) ) ;
270
321
process . exit ( 1 ) ;
271
322
} ) ;
0 commit comments