backend-scaffold-cli 1.0.2 → 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 +217 -141
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -8,132 +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
- ...(answers.useAuth && { jsonwebtoken: '^9.0.0' }),
123
- ...(answers.useValidation && { joi: '^17.9.0' })
124
- },
125
- devDependencies: {
126
- nodemon: '^2.0.22',
127
- }
128
114
 
129
- };
130
115
 
131
- fs.writeFileSync(
132
- path.join(projectPath, 'package.json'),
133
- JSON.stringify(packageJson, null, 2)
134
- );
135
116
 
136
- 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
137
158
  PORT=5000
138
159
  NODE_ENV=development
139
160
 
@@ -157,10 +178,12 @@ CORS_ORIGIN=http://localhost:3000
157
178
  LOG_LEVEL=debug
158
179
  `;
159
180
 
160
- fs.writeFileSync(path.join(projectPath, '.env.example'), env);
181
+ fs.writeFileSync(path.join(projectPath, '.env.example'), env);
182
+
161
183
 
162
184
 
163
- const gitignore = `node_modules/
185
+
186
+ const gitignore = `node_modules/
164
187
  .env
165
188
  .env.local
166
189
  .env.*.local
@@ -174,9 +197,9 @@ yarn-debug.log*
174
197
  .vscode/
175
198
  `;
176
199
 
177
- fs.writeFileSync(path.join(projectPath, '.gitignore'), gitignore);
200
+ fs.writeFileSync(path.join(projectPath, '.gitignore'), gitignore);
178
201
 
179
- console.log(chalk.green(' Config files created'));
202
+ console.log(chalk.green(' Config files created'));
180
203
 
181
204
 
182
205
  };
@@ -184,6 +207,8 @@ yarn-debug.log*
184
207
 
185
208
 
186
209
 
210
+
211
+
187
212
  function createMiddlewareFiles(projectPath, answers) {
188
213
  const errorHandler = `// Middleware for handling errors
189
214
  class ErrorHandler extends Error {
@@ -222,13 +247,16 @@ const errorMiddleware = (err, req, res, next) => {
222
247
  module.exports = { errorMiddleware, ErrorHandler };
223
248
  `;
224
249
 
225
- fs.writeFileSync(
226
- path.join(projectPath, 'src/middleware/errorHandler.js'),
227
- errorHandler
228
- );
250
+ fs.writeFileSync(
251
+ path.join(projectPath, 'src/middleware/errorHandler.js'),
252
+ errorHandler
253
+ );
254
+
255
+
256
+
229
257
 
230
258
 
231
- const logger = `// Simple logging middleware
259
+ const logger = `// Simple logging middleware
232
260
  const loggerMiddleware = (req, res, next) => {
233
261
  const start = Date.now();
234
262
 
@@ -243,14 +271,48 @@ const loggerMiddleware = (req, res, next) => {
243
271
  };
244
272
 
245
273
  module.exports = loggerMiddleware;
274
+ `;
275
+
276
+ fs.writeFileSync(
277
+ path.join(projectPath, 'src/middleware/logger.js'),
278
+ logger
279
+ );
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+ if (answers.useRateLimit) {
288
+ const rateLimiter = `const ratelimit= require('express-rate-limit');
289
+
290
+ const limiter=ratelimit({
291
+ windowMs: 15 * 60 * 1000,
292
+ max: 100,
293
+ message: 'Too many requests from this IP, please try again after 15 minutes',
294
+ standardHeaders: true,
295
+ legacyHeaders: false,
296
+ });
297
+
298
+ module.exports=limiter;
299
+
300
+
246
301
  `;
247
302
 
248
303
  fs.writeFileSync(
249
- path.join(projectPath, 'src/middleware/logger.js'),
250
- logger
304
+ path.join(projectPath, 'src/middleware/rateLimiter.js'),
305
+ rateLimiter
251
306
  );
252
307
 
253
- if (answers.useAuth) {
308
+ }
309
+
310
+
311
+
312
+
313
+
314
+
315
+ if (answers.useAuth) {
254
316
  const auth = `const jwt = require('jsonwebtoken');
255
317
  const { ErrorHandler } = require('./errorHandler');
256
318
 
@@ -274,11 +336,14 @@ module.exports = authenticateToken;
274
336
  `;
275
337
 
276
338
  fs.writeFileSync(
277
- path.join(projectPath, 'src/middleware/auth.js'),
278
- auth
339
+ path.join(projectPath, 'src/middleware/auth.js'),
340
+ auth
279
341
  );
280
342
  }
281
343
 
344
+
345
+
346
+
282
347
  if (answers.useValidation) {
283
348
  const validation = `const Joi = require('joi');
284
349
 
@@ -306,8 +371,8 @@ module.exports = validateRequest;
306
371
  `;
307
372
 
308
373
  fs.writeFileSync(
309
- path.join(projectPath, 'src/middleware/validation.js'),
310
- validation
374
+ path.join(projectPath, 'src/middleware/validation.js'),
375
+ validation
311
376
  );
312
377
  }
313
378
 
@@ -315,8 +380,11 @@ module.exports = validateRequest;
315
380
  }
316
381
 
317
382
 
383
+
384
+
385
+
318
386
  const createRouteFiles = (projectPath, answers) => {
319
- const routes = `const express = require('express');
387
+ const routes = `const express = require('express');
320
388
  const router = express.Router();
321
389
  ${answers.useAuth ? "const authenticateToken = require('../middleware/auth');" : ''}
322
390
 
@@ -334,14 +402,16 @@ router.get('/protected', authenticateToken, (req, res) => {
334
402
 
335
403
  module.exports = router;
336
404
  `;
337
- fs.writeFileSync(
338
- path.join(projectPath, 'src/routes/index.js'),
339
- routes
340
- );
405
+ fs.writeFileSync(
406
+ path.join(projectPath, 'src/routes/index.js'),
407
+ routes
408
+ );
409
+
410
+
341
411
 
342
-
343
412
 
344
- const dbConfig = `const mongoose = require('mongoose');
413
+
414
+ const dbConfig = `const mongoose = require('mongoose');
345
415
  const dns = require('dns');
346
416
 
347
417
  // Set DNS servers
@@ -375,12 +445,16 @@ const connectDB = async () => {
375
445
  module.exports = connectDB;
376
446
  `;
377
447
 
378
- fs.writeFileSync(
379
- path.join(projectPath, 'src/config/db.js'),
380
- dbConfig
381
- );
448
+ fs.writeFileSync(
449
+ path.join(projectPath, 'src/config/db.js'),
450
+ dbConfig
451
+ );
452
+
453
+
454
+
455
+
382
456
 
383
- const server = `require('dotenv').config();
457
+ const server = `require('dotenv').config();
384
458
  const express = require('express');
385
459
  const cors = require('cors');
386
460
  const connectDB = require('./config/db');
@@ -389,6 +463,7 @@ const loggerMiddleware = require('./middleware/logger');
389
463
  const { errorMiddleware } = require('./middleware/errorHandler');
390
464
 
391
465
  const app = express();
466
+ ${answers.useRateLimit ? "const limiter = require('./middleware/rateLimiter');" : ''}
392
467
  const PORT = process.env.PORT || 5000;
393
468
 
394
469
  // Connect to MongoDB
@@ -402,6 +477,7 @@ app.use(cors({
402
477
  app.use(express.json());
403
478
  app.use(express.urlencoded({ extended: true }));
404
479
  app.use(loggerMiddleware);
480
+ ${answers.useRateLimit ? 'app.use(limiter);' : ''}
405
481
 
406
482
 
407
483
  // Routes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-scaffold-cli",
3
- "version": "1.0.2",
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": {