backend-scaffold-cli 1.1.0 → 1.2.0

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.
Files changed (2) hide show
  1. package/bin/cli.js +193 -153
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
 
4
4
  const { program } = require('commander');
@@ -8,133 +8,153 @@ const fs = require('fs-extra');
8
8
  const path = require('path');
9
9
  const { execSync } = require('child_process');
10
10
 
11
- const version= '1.0.0';
11
+ const version = '1.0.0';
12
12
 
13
13
  program
14
- .version(version)
15
- .description('Create a new Express.js backend application')
16
- .argument('<project-name>', 'Name of the project')
17
- .action(async (projectName) => {
18
- try{
19
- console.log(chalk.blue(`Creating a new Express.js backend application: ${projectName}`));
20
-
21
- const answers = await inquirer.prompt([
22
- {
23
- type: 'confirm',
24
- name: 'useAuth',
25
- message: 'Include JWT authentication?',
26
- default: true
27
- },
28
- {
29
- type:'confirm',
30
- name: 'useLogging',
31
- message: 'Include logging middleware?',
32
- default: true
33
- },
34
- {
35
- type: 'confirm',
36
- name: 'useValidation',
37
- message: 'Include input validation?',
38
- default: true
39
- },
40
- {
41
- type: 'confirm',
42
- name: 'installDeps',
43
- message: 'Install dependencies now?',
44
- default: true
45
- }
46
- ]);
47
-
48
- const projectPath = path.resolve(process.cwd(), projectName);
49
-
50
- if (fs.existsSync(projectPath)) {
51
- console.log(chalk.red(`Error: Directory ${projectName} already exists.`));
52
- process.exit(1);
53
- }
54
-
55
- console.log(chalk.blue(`Creating project in ${projectPath}\n`));
56
- fs.ensureDirSync(projectPath);
57
-
58
- createFolderStructure(projectPath);
59
- createConfigFiles(projectPath, answers);
60
- createMiddlewareFiles(projectPath, answers);
61
- createRouteFiles(projectPath, answers);
62
-
63
- console.log(chalk.cyan(' Initializing git repository...'));
64
- execSync('git init', { cwd: projectPath });
65
-
66
- if (answers.installDeps) {
67
- console.log(chalk.cyan(' Installing dependencies...\n'));
68
- execSync('npm install', { cwd: projectPath, stdio: 'inherit' });
69
- }
70
-
71
- console.log(chalk.green.bold('\n Project created successfully!\n'));
72
- console.log(chalk.cyan('Next steps:'));
73
- console.log(chalk.white(` cd ${projectName}`));
74
- console.log(chalk.white(' cp .env.example .env'));
75
- console.log(chalk.white(' npm start\n'));
76
- }catch (error) {
77
- console.error(chalk.red('\n Error creating project:'), error.message);
78
- process.exit(1);
14
+ .version(version)
15
+ .description('Create a new Express.js backend application')
16
+ .argument('<project-name>', 'Name of the project')
17
+ .action(async (projectName) => {
18
+ try {
19
+ console.log(chalk.blue(`Creating a new Express.js backend application: ${projectName}`));
20
+
21
+ const answers = await inquirer.prompt([
22
+ {
23
+ type: 'confirm',
24
+ name: 'useAuth',
25
+ message: 'Include JWT authentication?',
26
+ default: true
27
+ },
28
+ {
29
+ type: 'confirm',
30
+ name: 'useValidation',
31
+ message: 'Include input validation?',
32
+ default: true
33
+ },
34
+ {
35
+ type: 'confirm',
36
+ name: 'useRateLimit',
37
+ message: 'Include rate limiting?',
38
+ default: true
39
+ },
40
+ {
41
+ type: 'confirm',
42
+ name: 'installDeps',
43
+ message: 'Install dependencies now?',
44
+ default: true
79
45
  }
80
- });
46
+ ]);
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+ const projectPath = path.resolve(process.cwd(), projectName);
55
+
56
+ if (fs.existsSync(projectPath)) {
57
+ console.log(chalk.red(`Error: Directory ${projectName} already exists.`));
58
+ process.exit(1);
59
+ }
60
+
61
+ console.log(chalk.blue(`Creating project in ${projectPath}\n`));
62
+ fs.ensureDirSync(projectPath);
63
+
64
+ createFolderStructure(projectPath);
65
+ createConfigFiles(projectPath, answers);
66
+ createMiddlewareFiles(projectPath, answers);
67
+ createRouteFiles(projectPath, answers);
68
+
69
+ console.log(chalk.cyan(' Initializing git repository...'));
70
+ execSync('git init', { cwd: projectPath });
71
+
72
+ if (answers.installDeps) {
73
+ console.log(chalk.cyan(' Installing dependencies...\n'));
74
+ execSync('npm install', { cwd: projectPath, stdio: 'inherit' });
75
+ }
76
+
77
+ console.log(chalk.green.bold('\n Project created successfully!\n'));
78
+ console.log(chalk.cyan('Next steps:'));
79
+ console.log(chalk.white(` cd ${projectName}`));
80
+ console.log(chalk.white(' cp .env.example .env'));
81
+ console.log(chalk.white(' npm start\n'));
82
+ } catch (error) {
83
+ console.error(chalk.red('\n Error creating project:'), error.message);
84
+ process.exit(1);
85
+ }
86
+ });
81
87
 
82
88
  program.parse();
83
89
 
84
- const createFolderStructure=(projectPath) =>{
85
- const folders=[
86
- 'src/config',
87
- 'src/middleware',
88
- 'src/routes',
89
- 'src/controllers',
90
- 'src/models',
91
- 'src/utils',
92
- 'src/validation'
93
- ];
94
-
95
- folders.forEach(folder => {
96
- fs.ensureDirSync(path.join(projectPath, folder));
97
- });
98
-
99
- console.log(chalk.green(' Folder structure created'));
90
+
91
+
92
+
93
+
94
+ const createFolderStructure = (projectPath) => {
95
+ const folders = [
96
+ 'src/config',
97
+ 'src/middleware',
98
+ 'src/routes',
99
+ 'src/controllers',
100
+ 'src/models',
101
+ 'src/utils',
102
+ 'src/validation'
103
+ ];
104
+
105
+ folders.forEach(folder => {
106
+ fs.ensureDirSync(path.join(projectPath, folder));
107
+ });
108
+
109
+ console.log(chalk.green(' Folder structure created'));
100
110
 
101
111
  }
102
112
 
103
113
 
104
- const createConfigFiles= (projectPath,answers) =>{
105
- const packageJson={
106
- name: path.basename(projectPath),
107
- version: '1.0.0',
108
- main: 'src/server.js',
109
- scripts: {
110
- start: 'node src/server.js',
111
- dev: 'nodemon src/server.js',
112
- test: 'jest'
113
- },
114
- keywords: ['express', 'nodejs', 'backend'],
115
- author: '',
116
- license: 'MIT',
117
- dependencies: {
118
- express: '^4.18.2',
119
- mongoose: '^7.0.0',
120
- dotenv: '^16.0.3',
121
- cors: '^2.8.5',
122
- 'express-rate-limit': '^6.7.0',
123
- ...(answers.useAuth && { jsonwebtoken: '^9.0.0' }),
124
- ...(answers.useValidation && { joi: '^17.9.0' })
125
- },
126
- devDependencies: {
127
- nodemon: '^2.0.22',
128
- }
129
114
 
130
- };
131
115
 
132
- fs.writeFileSync(
133
- path.join(projectPath, 'package.json'),
134
- JSON.stringify(packageJson, null, 2)
135
- );
136
116
 
137
- const env = `# Server Configuration
117
+
118
+ const createConfigFiles = (projectPath, answers) => {
119
+ const packageJson = {
120
+ name: path.basename(projectPath),
121
+ version: '1.0.0',
122
+ main: 'src/server.js',
123
+ scripts: {
124
+ start: 'node src/server.js',
125
+ dev: 'nodemon src/server.js',
126
+ test: 'jest'
127
+ },
128
+ keywords: ['express', 'nodejs', 'backend'],
129
+ author: '',
130
+ license: 'MIT',
131
+ dependencies: {
132
+ express: '^4.18.2',
133
+ mongoose: '^7.0.0',
134
+ dotenv: '^16.0.3',
135
+ cors: '^2.8.5',
136
+ ...(answers.useAuth && { jsonwebtoken: '^9.0.0' }),
137
+ ...(answers.useValidation && { joi: '^17.9.0' }),
138
+ ...(answers.useRateLimit && { 'express-rate-limit': '^6.7.0' }),
139
+
140
+ },
141
+ devDependencies: {
142
+ nodemon: '^2.0.22',
143
+ }
144
+
145
+ };
146
+
147
+ fs.writeFileSync(
148
+ path.join(projectPath, 'package.json'),
149
+ JSON.stringify(packageJson, null, 2)
150
+ );
151
+
152
+
153
+
154
+
155
+
156
+
157
+ const env = `# Server Configuration
138
158
  PORT=5000
139
159
  NODE_ENV=development
140
160
 
@@ -158,10 +178,12 @@ CORS_ORIGIN=http://localhost:3000
158
178
  LOG_LEVEL=debug
159
179
  `;
160
180
 
161
- fs.writeFileSync(path.join(projectPath, '.env.example'), env);
181
+ fs.writeFileSync(path.join(projectPath, '.env.example'), env);
162
182
 
163
183
 
164
- const gitignore = `node_modules/
184
+
185
+
186
+ const gitignore = `node_modules/
165
187
  .env
166
188
  .env.local
167
189
  .env.*.local
@@ -175,9 +197,9 @@ yarn-debug.log*
175
197
  .vscode/
176
198
  `;
177
199
 
178
- fs.writeFileSync(path.join(projectPath, '.gitignore'), gitignore);
200
+ fs.writeFileSync(path.join(projectPath, '.gitignore'), gitignore);
179
201
 
180
- console.log(chalk.green(' Config files created'));
202
+ console.log(chalk.green(' Config files created'));
181
203
 
182
204
 
183
205
  };
@@ -185,6 +207,8 @@ yarn-debug.log*
185
207
 
186
208
 
187
209
 
210
+
211
+
188
212
  function createMiddlewareFiles(projectPath, answers) {
189
213
  const errorHandler = `// Middleware for handling errors
190
214
  class ErrorHandler extends Error {
@@ -223,15 +247,16 @@ const errorMiddleware = (err, req, res, next) => {
223
247
  module.exports = { errorMiddleware, ErrorHandler };
224
248
  `;
225
249
 
226
- fs.writeFileSync(
227
- path.join(projectPath, 'src/middleware/errorHandler.js'),
228
- errorHandler
229
- );
250
+ fs.writeFileSync(
251
+ path.join(projectPath, 'src/middleware/errorHandler.js'),
252
+ errorHandler
253
+ );
230
254
 
231
255
 
232
256
 
233
257
 
234
- const logger = `// Simple logging middleware
258
+
259
+ const logger = `// Simple logging middleware
235
260
  const loggerMiddleware = (req, res, next) => {
236
261
  const start = Date.now();
237
262
 
@@ -248,19 +273,24 @@ const loggerMiddleware = (req, res, next) => {
248
273
  module.exports = loggerMiddleware;
249
274
  `;
250
275
 
251
- fs.writeFileSync(
252
- path.join(projectPath, 'src/middleware/logger.js'),
253
- logger
254
- );
276
+ fs.writeFileSync(
277
+ path.join(projectPath, 'src/middleware/logger.js'),
278
+ logger
279
+ );
280
+
281
+
255
282
 
256
283
 
257
284
 
258
- const rateLimiter = `const ratelimit= require('express-rate-limit');
285
+
286
+
287
+ if (answers.useRateLimit) {
288
+ const rateLimiter = `const ratelimit= require('express-rate-limit');
259
289
 
260
290
  const limiter=ratelimit({
261
291
  windowMs: 15 * 60 * 1000,
262
292
  max: 100,
263
- message: 'Too many requests from this IP, please try again after 15 minutes'
293
+ message: 'Too many requests from this IP, please try again after 15 minutes',
264
294
  standardHeaders: true,
265
295
  legacyHeaders: false,
266
296
  });
@@ -271,13 +301,19 @@ module.exports=limiter;
271
301
  `;
272
302
 
273
303
  fs.writeFileSync(
274
- path.join(projectPath, 'src/middleware/rateLimiter.js'),
275
- rateLimiter
304
+ path.join(projectPath, 'src/middleware/rateLimiter.js'),
305
+ rateLimiter
276
306
  );
277
307
 
308
+ }
309
+
310
+
311
+
278
312
 
279
- if (answers.useAuth) {
280
- const auth = `const jwt = require('jsonwebtoken');
313
+
314
+
315
+ if (answers.useAuth) {
316
+ const auth = `const jwt = require('jsonwebtoken');
281
317
  const { ErrorHandler } = require('./errorHandler');
282
318
 
283
319
  const authenticateToken = (req, res, next) => {
@@ -300,15 +336,16 @@ module.exports = authenticateToken;
300
336
  `;
301
337
 
302
338
  fs.writeFileSync(
303
- path.join(projectPath, 'src/middleware/auth.js'),
304
- auth
339
+ path.join(projectPath, 'src/middleware/auth.js'),
340
+ auth
305
341
  );
306
342
  }
307
343
 
308
344
 
309
345
 
310
- if (answers.useValidation) {
311
- const validation = `const Joi = require('joi');
346
+
347
+ if (answers.useValidation) {
348
+ const validation = `const Joi = require('joi');
312
349
 
313
350
  const validateRequest = (schema) => {
314
351
  return (req, res, next) => {
@@ -334,8 +371,8 @@ module.exports = validateRequest;
334
371
  `;
335
372
 
336
373
  fs.writeFileSync(
337
- path.join(projectPath, 'src/middleware/validation.js'),
338
- validation
374
+ path.join(projectPath, 'src/middleware/validation.js'),
375
+ validation
339
376
  );
340
377
  }
341
378
 
@@ -365,14 +402,16 @@ router.get('/protected', authenticateToken, (req, res) => {
365
402
 
366
403
  module.exports = router;
367
404
  `;
368
- fs.writeFileSync(
369
- path.join(projectPath, 'src/routes/index.js'),
370
- routes
371
- );
405
+ fs.writeFileSync(
406
+ path.join(projectPath, 'src/routes/index.js'),
407
+ routes
408
+ );
409
+
410
+
411
+
372
412
 
373
-
374
413
 
375
- const dbConfig = `const mongoose = require('mongoose');
414
+ const dbConfig = `const mongoose = require('mongoose');
376
415
  const dns = require('dns');
377
416
 
378
417
  // Set DNS servers
@@ -406,15 +445,16 @@ const connectDB = async () => {
406
445
  module.exports = connectDB;
407
446
  `;
408
447
 
409
- fs.writeFileSync(
410
- path.join(projectPath, 'src/config/db.js'),
411
- dbConfig
412
- );
448
+ fs.writeFileSync(
449
+ path.join(projectPath, 'src/config/db.js'),
450
+ dbConfig
451
+ );
452
+
413
453
 
414
454
 
415
455
 
416
456
 
417
- const server = `require('dotenv').config();
457
+ const server = `require('dotenv').config();
418
458
  const express = require('express');
419
459
  const cors = require('cors');
420
460
  const connectDB = require('./config/db');
@@ -423,7 +463,7 @@ const loggerMiddleware = require('./middleware/logger');
423
463
  const { errorMiddleware } = require('./middleware/errorHandler');
424
464
 
425
465
  const app = express();
426
- const limiter = require('./middleware/rateLimiter');
466
+ ${answers.useRateLimit ? "const limiter = require('./middleware/rateLimiter');" : ''}
427
467
  const PORT = process.env.PORT || 5000;
428
468
 
429
469
  // Connect to MongoDB
@@ -437,7 +477,7 @@ app.use(cors({
437
477
  app.use(express.json());
438
478
  app.use(express.urlencoded({ extended: true }));
439
479
  app.use(loggerMiddleware);
440
- app.use(limiter);
480
+ ${answers.useRateLimit ? 'app.use(limiter);' : ''}
441
481
 
442
482
 
443
483
  // Routes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-scaffold-cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "CLI tool to scaffold Express.js backend projects with MongoDB, middleware, and common setup",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {