backend-scaffold-cli 1.3.0 → 1.5.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.
- package/bin/cli.js +173 -4
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -37,11 +37,23 @@ program
|
|
|
37
37
|
message: 'Include rate limiting?',
|
|
38
38
|
default: true
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
type: 'confirm',
|
|
42
|
+
name: 'useFileUpload',
|
|
43
|
+
message: 'Include file upload support (multer)?',
|
|
44
|
+
default: true
|
|
45
|
+
},
|
|
40
46
|
{
|
|
41
47
|
type: 'confirm',
|
|
42
48
|
name: 'installDeps',
|
|
43
49
|
message: 'Install dependencies now?',
|
|
44
50
|
default: true
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: 'confirm',
|
|
54
|
+
name: 'useAxios',
|
|
55
|
+
message: 'Include axios (for external API calls)?',
|
|
56
|
+
default: true
|
|
45
57
|
}
|
|
46
58
|
]);
|
|
47
59
|
|
|
@@ -61,13 +73,16 @@ program
|
|
|
61
73
|
console.log(chalk.blue(`Creating project in ${projectPath}\n`));
|
|
62
74
|
fs.ensureDirSync(projectPath);
|
|
63
75
|
|
|
64
|
-
createFolderStructure(projectPath);
|
|
76
|
+
createFolderStructure(projectPath, answers);
|
|
65
77
|
createConfigFiles(projectPath, answers);
|
|
66
78
|
createMiddlewareFiles(projectPath, answers);
|
|
67
79
|
createRouteFiles(projectPath, answers);
|
|
68
80
|
if (answers.useAuth) {
|
|
69
81
|
createUserModel(projectPath);
|
|
70
82
|
}
|
|
83
|
+
if(answers.useAxios){
|
|
84
|
+
createAxiosUtil(projectPath);
|
|
85
|
+
}
|
|
71
86
|
|
|
72
87
|
console.log(chalk.cyan(' Initializing git repository...'));
|
|
73
88
|
execSync('git init', { cwd: projectPath });
|
|
@@ -94,7 +109,7 @@ program.parse();
|
|
|
94
109
|
|
|
95
110
|
|
|
96
111
|
|
|
97
|
-
const createFolderStructure = (projectPath) => {
|
|
112
|
+
const createFolderStructure = (projectPath, answers) => {
|
|
98
113
|
const folders = [
|
|
99
114
|
'src/config',
|
|
100
115
|
'src/middleware',
|
|
@@ -105,12 +120,15 @@ const createFolderStructure = (projectPath) => {
|
|
|
105
120
|
'src/validation'
|
|
106
121
|
];
|
|
107
122
|
|
|
123
|
+
if (answers.useFileUpload) {
|
|
124
|
+
folders.push('uploads');
|
|
125
|
+
}
|
|
126
|
+
|
|
108
127
|
folders.forEach(folder => {
|
|
109
128
|
fs.ensureDirSync(path.join(projectPath, folder));
|
|
110
129
|
});
|
|
111
130
|
|
|
112
131
|
console.log(chalk.green(' Folder structure created'));
|
|
113
|
-
|
|
114
132
|
}
|
|
115
133
|
|
|
116
134
|
|
|
@@ -139,6 +157,8 @@ const createConfigFiles = (projectPath, answers) => {
|
|
|
139
157
|
...(answers.useAuth && { jsonwebtoken: '^9.0.0' , bcryptjs: '^2.4.3'}),
|
|
140
158
|
...(answers.useValidation && { joi: '^17.9.0' }),
|
|
141
159
|
...(answers.useRateLimit && { 'express-rate-limit': '^6.7.0' }),
|
|
160
|
+
...(answers.useFileUpload && { multer: '^2.0.0' }),
|
|
161
|
+
...(answers.useAxios && { axios: '^1.6.0' }),
|
|
142
162
|
|
|
143
163
|
},
|
|
144
164
|
devDependencies: {
|
|
@@ -185,7 +205,6 @@ LOG_LEVEL=debug
|
|
|
185
205
|
|
|
186
206
|
|
|
187
207
|
|
|
188
|
-
|
|
189
208
|
const gitignore = `node_modules/
|
|
190
209
|
.env
|
|
191
210
|
.env.local
|
|
@@ -198,10 +217,14 @@ npm-debug.log*
|
|
|
198
217
|
yarn-debug.log*
|
|
199
218
|
.idea/
|
|
200
219
|
.vscode/
|
|
220
|
+
${answers.useFileUpload ? 'uploads/*\n!uploads/.gitkeep' : ''}
|
|
201
221
|
`;
|
|
202
222
|
|
|
203
223
|
fs.writeFileSync(path.join(projectPath, '.gitignore'), gitignore);
|
|
204
224
|
|
|
225
|
+
if(answers.useFileUpload){
|
|
226
|
+
fs.writeFileSync(path.join(projectPath, 'uploads/.gitkeep'), '');
|
|
227
|
+
}
|
|
205
228
|
console.log(chalk.green(' Config files created'));
|
|
206
229
|
|
|
207
230
|
|
|
@@ -312,6 +335,57 @@ module.exports=limiter;
|
|
|
312
335
|
|
|
313
336
|
|
|
314
337
|
|
|
338
|
+
if(answers.useFileUpload){
|
|
339
|
+
const multerMiddleware= ` const multer = require('multer');
|
|
340
|
+
const path = require('path');
|
|
341
|
+
|
|
342
|
+
// Set storage engine
|
|
343
|
+
const storage = multer.diskStorage({
|
|
344
|
+
destination: function (req,file ,cb){
|
|
345
|
+
cb(null, 'uploads/');
|
|
346
|
+
},
|
|
347
|
+
filename: function (req, file, cb) {
|
|
348
|
+
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random()*1E9);
|
|
349
|
+
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname))
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
//file filter
|
|
356
|
+
const fileFilter = (req, file, cb) =>{
|
|
357
|
+
const allowedTypes = /jpeg|jpg|png|gif/;
|
|
358
|
+
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
|
|
359
|
+
const mimetype = allowedTypes.test(file.mimetype);
|
|
360
|
+
|
|
361
|
+
if(extname && mimetype){
|
|
362
|
+
return cb(null,true);
|
|
363
|
+
}else{
|
|
364
|
+
cb(new Error('Error: Images Only!'));
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const upload = multer({
|
|
369
|
+
storage: storage,
|
|
370
|
+
limits: { fileSize: 5 * 1024 * 1024 }, // 5MB limit
|
|
371
|
+
fileFilter: fileFilter
|
|
372
|
+
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
module.exports = upload;
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
`;
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
fs.writeFileSync(
|
|
382
|
+
path.join(projectPath, 'src/middleware/upload.js'),
|
|
383
|
+
multerMiddleware
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
315
389
|
|
|
316
390
|
|
|
317
391
|
|
|
@@ -390,6 +464,7 @@ const createRouteFiles = (projectPath, answers) => {
|
|
|
390
464
|
const routes = `const express = require('express');
|
|
391
465
|
const router = express.Router();
|
|
392
466
|
${answers.useAuth ? "const authenticateToken = require('../middleware/auth');" : ''}
|
|
467
|
+
${answers.useFileUpload ? "const upload = require('../middleware/upload');" : ''}
|
|
393
468
|
|
|
394
469
|
// Public routes
|
|
395
470
|
router.get('/health', (req, res) => {
|
|
@@ -403,6 +478,28 @@ router.get('/protected', authenticateToken, (req, res) => {
|
|
|
403
478
|
});
|
|
404
479
|
` : ''}
|
|
405
480
|
|
|
481
|
+
${answers.useFileUpload ? `
|
|
482
|
+
// File upload route
|
|
483
|
+
router.post('/upload', upload.single('file'), (req,res) =>{
|
|
484
|
+
if(!req.file){
|
|
485
|
+
return res.status(400).json({
|
|
486
|
+
success: false,
|
|
487
|
+
message: 'No file uploaded'
|
|
488
|
+
})
|
|
489
|
+
}
|
|
490
|
+
res.json({
|
|
491
|
+
success: true,
|
|
492
|
+
message: 'File uploaded successfully',
|
|
493
|
+
file: req.file
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
`: ''}
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
406
503
|
module.exports = router;
|
|
407
504
|
`;
|
|
408
505
|
fs.writeFileSync(
|
|
@@ -577,4 +674,76 @@ function createUserModel(projectPath) {
|
|
|
577
674
|
)
|
|
578
675
|
|
|
579
676
|
console.log(chalk.green('User model created'));
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
function createAxiosUtil(projectPath){
|
|
683
|
+
const axiosUtil = ` const axios = require('axios');
|
|
684
|
+
|
|
685
|
+
//create an axios instance with default config
|
|
686
|
+
const axiosInstance = axios.create({
|
|
687
|
+
baseURL: process.env.API_BASE_URL || '',
|
|
688
|
+
timeout: 10000,
|
|
689
|
+
headers:{
|
|
690
|
+
'Content-Type' : 'application/json',
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
//request interceptor
|
|
695
|
+
axiosInstance.interceptors.request.use(
|
|
696
|
+
(config) =>{
|
|
697
|
+
console.log(\`Making request to: \${config.url}\`);;
|
|
698
|
+
return config;
|
|
699
|
+
},
|
|
700
|
+
(error) => Promise.reject(error)
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
//response interceptor
|
|
704
|
+
axiosInstance.interceptors.response.use(
|
|
705
|
+
(response) => response,
|
|
706
|
+
(error) => {
|
|
707
|
+
console.error('API call error: ', error.response ? error.response.data : error.message);
|
|
708
|
+
return Promise.reject(error);
|
|
709
|
+
}
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
//fetch data function
|
|
713
|
+
const fetchData = async (url) => {
|
|
714
|
+
try{
|
|
715
|
+
const response = await axiosInstance.get(url);
|
|
716
|
+
return response.data;
|
|
717
|
+
}catch(error){
|
|
718
|
+
throw new Error(\`Failed to fetch data: \${error.message}\`);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
//post data function
|
|
723
|
+
const postData = async (url, data) => {
|
|
724
|
+
try{
|
|
725
|
+
const response = await axiosInstance.post(url, data);
|
|
726
|
+
return response.data;
|
|
727
|
+
}catch(error){
|
|
728
|
+
throw new Error(\`Failed to post data: \${error.message}\`);
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
module.exports = {
|
|
733
|
+
axiosInstance,
|
|
734
|
+
fetchData,
|
|
735
|
+
postData,
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
`;
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
fs.writeFileSync(
|
|
744
|
+
path.join(projectPath, 'src/utils/axiosUtil.js'),
|
|
745
|
+
axiosUtil
|
|
746
|
+
);
|
|
747
|
+
|
|
748
|
+
console.log(chalk.green('Axios utility created'));
|
|
580
749
|
}
|