create-node-advance-app 2.0.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.
@@ -0,0 +1,2138 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ // Helper to write files
5
+ function writeFile(filePath, content) {
6
+ const dir = path.dirname(filePath);
7
+ if (!fs.existsSync(dir)) {
8
+ fs.mkdirSync(dir, { recursive: true });
9
+ }
10
+ fs.writeFileSync(filePath, content.trim() + '\n');
11
+ }
12
+
13
+ async function createProject(config) {
14
+ const {
15
+ projectPath,
16
+ projectName,
17
+ language,
18
+ database,
19
+ auth,
20
+ validation,
21
+ logger,
22
+ errorHandling,
23
+ docker
24
+ } = config;
25
+
26
+ const isTS = language === 'TypeScript';
27
+ const ext = isTS ? 'ts' : 'js';
28
+
29
+ // Create directories
30
+ const dirs = [
31
+ 'src',
32
+ 'src/config',
33
+ 'src/routes',
34
+ 'src/middlewares',
35
+ 'src/controllers',
36
+ 'src/services',
37
+ 'src/utils'
38
+ ];
39
+
40
+ if (isTS) dirs.push('src/types');
41
+ if (database !== 'none') dirs.push('src/models');
42
+ if (validation !== 'none') dirs.push('src/validators');
43
+ if (database === 'postgresql' || database === 'mysql') {
44
+ dirs.push('src/migrations');
45
+ dirs.push('src/seeders');
46
+ }
47
+
48
+ dirs.forEach(dir => {
49
+ fs.mkdirSync(path.join(projectPath, dir), { recursive: true });
50
+ });
51
+
52
+ // ============================================================
53
+ // 1. PACKAGE.JSON
54
+ // ============================================================
55
+ const dependencies = {
56
+ express: '^4.18.2',
57
+ dotenv: '^16.3.1',
58
+ cors: '^2.8.5',
59
+ helmet: '^7.1.0'
60
+ };
61
+
62
+ const devDependencies = {
63
+ nodemon: '^3.0.2'
64
+ };
65
+
66
+ if (isTS) {
67
+ devDependencies.typescript = '^5.3.3';
68
+ devDependencies['@types/node'] = '^20.10.6';
69
+ devDependencies['@types/express'] = '^4.17.21';
70
+ devDependencies['@types/cors'] = '^2.8.17';
71
+ devDependencies['ts-node'] = '^10.9.2';
72
+ }
73
+
74
+ // Database dependencies
75
+ if (database === 'mongodb') {
76
+ dependencies.mongoose = '^8.0.3';
77
+ } else if (database === 'postgresql' || database === 'mysql') {
78
+ dependencies.sequelize = '^6.35.2';
79
+ devDependencies['sequelize-cli'] = '^6.6.2';
80
+
81
+ if (database === 'postgresql') {
82
+ dependencies.pg = '^8.11.3';
83
+ dependencies['pg-hstore'] = '^2.3.4';
84
+ } else {
85
+ dependencies.mysql2 = '^3.6.5';
86
+ }
87
+ }
88
+
89
+ // Auth dependencies
90
+ if (auth) {
91
+ dependencies.jsonwebtoken = '^9.0.2';
92
+ dependencies.bcryptjs = '^2.4.3';
93
+ if (isTS) {
94
+ devDependencies['@types/jsonwebtoken'] = '^9.0.5';
95
+ devDependencies['@types/bcryptjs'] = '^2.4.6';
96
+ }
97
+ }
98
+
99
+ // Validation dependencies
100
+ if (validation === 'zod') {
101
+ dependencies.zod = '^3.22.4';
102
+ } else if (validation === 'joi') {
103
+ dependencies.joi = '^17.11.0';
104
+ }
105
+
106
+ // Logger dependencies
107
+ if (logger === 'Winston') {
108
+ dependencies.winston = '^3.11.0';
109
+ } else if (logger === 'Pino') {
110
+ dependencies.pino = '^8.17.2';
111
+ dependencies['pino-pretty'] = '^10.3.1';
112
+ }
113
+
114
+ const scripts = {
115
+ start: isTS ? 'node dist/server.js' : 'node src/server.js',
116
+ dev: isTS ? 'nodemon --exec ts-node src/server.ts' : 'nodemon src/server.js'
117
+ };
118
+
119
+ if (isTS) {
120
+ scripts.build = 'tsc';
121
+ }
122
+
123
+ if (database === 'postgresql' || database === 'mysql') {
124
+ scripts['db:migrate'] = 'npx sequelize-cli db:migrate';
125
+ scripts['db:migrate:undo'] = 'npx sequelize-cli db:migrate:undo';
126
+ scripts['db:seed'] = 'npx sequelize-cli db:seed:all';
127
+ }
128
+
129
+ writeFile(path.join(projectPath, 'package.json'), JSON.stringify({
130
+ name: projectName,
131
+ version: '1.0.0',
132
+ description: 'Backend API',
133
+ main: isTS ? 'dist/server.js' : 'src/server.js',
134
+ scripts,
135
+ dependencies,
136
+ devDependencies
137
+ }, null, 2));
138
+
139
+ // ============================================================
140
+ // 2. ENVIRONMENT FILES
141
+ // ============================================================
142
+ let envContent = `NODE_ENV=development
143
+ PORT=5000
144
+ `;
145
+
146
+ if (database === 'mongodb') {
147
+ envContent += `\n# Database
148
+ MONGODB_URI=mongodb://localhost:27017/${projectName}
149
+ `;
150
+ } else if (database === 'postgresql') {
151
+ envContent += `\n# Database
152
+ DATABASE_URL=postgresql://postgres:root@localhost:5432/my-back
153
+ DB_HOST=localhost
154
+ DB_PORT=5432
155
+ DB_NAME=my-back
156
+ DB_USER=postgres
157
+ DB_PASSWORD=root
158
+ `;
159
+ } else if (database === 'mysql') {
160
+ envContent += `\n# Database
161
+ DATABASE_URL=mysql://root:password@localhost:3306/${projectName}
162
+ DB_HOST=localhost
163
+ DB_PORT=3306
164
+ DB_NAME=${projectName}
165
+ DB_USER=root
166
+ DB_PASSWORD=password
167
+ `;
168
+ }
169
+
170
+ if (auth) {
171
+ envContent += `\n# JWT
172
+ JWT_SECRET=your-super-secret-jwt-key-change-in-production
173
+ JWT_EXPIRES_IN=7d
174
+ `;
175
+ }
176
+
177
+ envContent += `\n# CORS
178
+ CORS_ORIGIN=http://localhost:3000
179
+ `;
180
+
181
+ writeFile(path.join(projectPath, '.env'), envContent);
182
+ writeFile(path.join(projectPath, '.env.example'), envContent);
183
+
184
+ // ============================================================
185
+ // 3. GITIGNORE
186
+ // ============================================================
187
+ writeFile(path.join(projectPath, '.gitignore'), `node_modules/
188
+ .env
189
+ .env.local
190
+ ${isTS ? 'dist/\n' : ''}logs/
191
+ *.log
192
+ .DS_Store
193
+ coverage/
194
+ `);
195
+
196
+ // ============================================================
197
+ // 4. TYPESCRIPT CONFIG (if TypeScript)
198
+ // ============================================================
199
+ if (isTS) {
200
+ writeFile(path.join(projectPath, 'tsconfig.json'), JSON.stringify({
201
+ compilerOptions: {
202
+ target: 'ES2020',
203
+ module: 'commonjs',
204
+ lib: ['ES2020'],
205
+ outDir: './dist',
206
+ rootDir: './src',
207
+ strict: true,
208
+ esModuleInterop: true,
209
+ skipLibCheck: true,
210
+ forceConsistentCasingInFileNames: true,
211
+ resolveJsonModule: true,
212
+ moduleResolution: 'node',
213
+ types: ['node']
214
+ },
215
+ include: ['src/**/*'],
216
+ exclude: ['node_modules', 'dist']
217
+ }, null, 2));
218
+ }
219
+
220
+ // ============================================================
221
+ // 5. src/config/env.ts/js - CENTRALIZED ENVIRONMENT CONSTANTS
222
+ // ============================================================
223
+ const envConfigContent = isTS ? `interface Environment {
224
+ NODE_ENV: string;
225
+ PORT: number;
226
+ ${database === 'mongodb' ? 'MONGODB_URI: string;' : ''}
227
+ ${database === 'postgresql' || database === 'mysql' ? `DATABASE_URL: string;
228
+ DB_HOST: string;
229
+ DB_PORT: number;
230
+ DB_NAME: string;
231
+ DB_USER: string;
232
+ DB_PASSWORD: string;` : ''}
233
+ ${auth ? `JWT_SECRET: string;
234
+ JWT_EXPIRES_IN: string;` : ''}
235
+ CORS_ORIGIN: string;
236
+ }
237
+
238
+ export const ENV: Environment = {
239
+ NODE_ENV: process.env.NODE_ENV || 'development',
240
+ PORT: parseInt(process.env.PORT || '5000', 10),
241
+ ${database === 'mongodb' ? "MONGODB_URI: process.env.MONGODB_URI || 'mongodb://localhost:27017/app'," : ''}
242
+ ${database === 'postgresql' || database === 'mysql' ? `DATABASE_URL: process.env.DATABASE_URL || '',
243
+ DB_HOST: process.env.DB_HOST || 'localhost',
244
+ DB_PORT: parseInt(process.env.DB_PORT || '${database === 'postgresql' ? '5432' : '3306'}', 10),
245
+ DB_NAME: process.env.DB_NAME || 'my-back',
246
+ DB_USER: process.env.DB_USER || '${database === 'postgresql' ? 'postgres' : 'root'}',
247
+ DB_PASSWORD: process.env.DB_PASSWORD || 'root',` : ''}
248
+ ${auth ? `JWT_SECRET: process.env.JWT_SECRET || 'change-this-secret',
249
+ JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '7d',` : ''}
250
+ CORS_ORIGIN: process.env.CORS_ORIGIN || 'http://localhost:3000'
251
+ };
252
+ ` : `const ENV = {
253
+ NODE_ENV: process.env.NODE_ENV || 'development',
254
+ PORT: parseInt(process.env.PORT || '5000', 10),
255
+ ${database === 'mongodb' ? "MONGODB_URI: process.env.MONGODB_URI || 'mongodb://localhost:27017/app'," : ''}
256
+ ${database === 'postgresql' || database === 'mysql' ? `DATABASE_URL: process.env.DATABASE_URL || '',
257
+ DB_HOST: process.env.DB_HOST || 'localhost',
258
+ DB_PORT: parseInt(process.env.DB_PORT || '${database === 'postgresql' ? '5432' : '3306'}', 10),
259
+ DB_NAME: process.env.DB_NAME || 'my-back',
260
+ DB_USER: process.env.DB_USER || '${database === 'postgresql' ? 'postgres' : 'root'}',
261
+ DB_PASSWORD: process.env.DB_PASSWORD || 'root',` : ''}
262
+ ${auth ? `JWT_SECRET: process.env.JWT_SECRET || 'change-this-secret',
263
+ JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '7d',` : ''}
264
+ CORS_ORIGIN: process.env.CORS_ORIGIN || 'http://localhost:3000'
265
+ };
266
+
267
+ module.exports = { ENV };
268
+ `;
269
+
270
+ writeFile(path.join(projectPath, `src/config/env.${ext}`), envConfigContent);
271
+
272
+ // ============================================================
273
+ // 6. src/utils/AppError.ts/js - CUSTOM ERROR CLASS
274
+ // ============================================================
275
+ if (errorHandling) {
276
+ const appErrorContent = isTS ? `export class AppError extends Error {
277
+ public statusCode: number;
278
+ public isOperational: boolean;
279
+
280
+ constructor(message: string, statusCode: number = 500) {
281
+ super(message);
282
+ this.statusCode = statusCode;
283
+ this.isOperational = true;
284
+
285
+ Error.captureStackTrace(this, this.constructor);
286
+ }
287
+ }
288
+ ` : `class AppError extends Error {
289
+ constructor(message, statusCode = 500) {
290
+ super(message);
291
+ this.statusCode = statusCode;
292
+ this.isOperational = true;
293
+
294
+ Error.captureStackTrace(this, this.constructor);
295
+ }
296
+ }
297
+
298
+ module.exports = { AppError };
299
+ `;
300
+
301
+ writeFile(path.join(projectPath, `src/utils/AppError.${ext}`), appErrorContent);
302
+ }
303
+
304
+ // ============================================================
305
+ // 7. src/utils/response.ts/js - RESPONSE HELPERS
306
+ // ============================================================
307
+ if (errorHandling) {
308
+ const responseContent = isTS ? `import { Response } from 'express';
309
+
310
+ export const successResponse = (
311
+ res: Response,
312
+ data: any,
313
+ message: string = 'Success',
314
+ statusCode: number = 200
315
+ ) => {
316
+ return res.status(statusCode).json({
317
+ success: true,
318
+ message,
319
+ data
320
+ });
321
+ };
322
+
323
+ export const errorResponse = (
324
+ res: Response,
325
+ message: string = 'Error occurred',
326
+ statusCode: number = 500,
327
+ errors?: any
328
+ ) => {
329
+ const response: any = {
330
+ success: false,
331
+ message
332
+ };
333
+
334
+ if (errors) {
335
+ response.errors = errors;
336
+ }
337
+
338
+ return res.status(statusCode).json(response);
339
+ };
340
+ ` : `const successResponse = (res, data, message = 'Success', statusCode = 200) => {
341
+ return res.status(statusCode).json({
342
+ success: true,
343
+ message,
344
+ data
345
+ });
346
+ };
347
+
348
+ const errorResponse = (res, message = 'Error occurred', statusCode = 500, errors = null) => {
349
+ const response = {
350
+ success: false,
351
+ message
352
+ };
353
+
354
+ if (errors) {
355
+ response.errors = errors;
356
+ }
357
+
358
+ return res.status(statusCode).json(response);
359
+ };
360
+
361
+ module.exports = { successResponse, errorResponse };
362
+ `;
363
+
364
+ writeFile(path.join(projectPath, `src/utils/response.${ext}`), responseContent);
365
+ }
366
+
367
+ // ============================================================
368
+ // 8. src/server.ts/js
369
+ // ============================================================
370
+ const serverContent = isTS ? `import dotenv from 'dotenv';
371
+ import app from './app';
372
+ import { ENV } from './config/env';
373
+ ${database === 'mongodb' ? "import connectDB from './config/database';" : ''}
374
+ ${database === 'postgresql' || database === 'mysql' ? "import { connectDatabase } from './config/database';" : ''}
375
+ ${logger !== 'None' ? "import logger from './config/logger';" : ''}
376
+
377
+ dotenv.config();
378
+
379
+ ${database === 'mongodb' ? `// Connect to MongoDB
380
+ connectDB();
381
+ ` : ''}
382
+ ${database === 'postgresql' || database === 'mysql' ? `// Connect to database
383
+ connectDatabase();
384
+ ` : ''}
385
+ const server = app.listen(ENV.PORT, () => {
386
+ ${logger !== 'None'
387
+ ? "logger.info(`Server running on port ${ENV.PORT}`);"
388
+ : "console.log(`🚀 Server running on port ${ENV.PORT}`);"}
389
+ });
390
+
391
+ // Graceful shutdown
392
+ process.on('SIGTERM', () => {
393
+ ${logger !== 'None' ? "logger.info('SIGTERM received, closing server...');" : "console.log('SIGTERM received');"}
394
+ server.close(() => {
395
+ ${logger !== 'None' ? "logger.info('Server closed');" : "console.log('Server closed');"}
396
+ process.exit(0);
397
+ });
398
+ });
399
+ ` : `require('dotenv').config();
400
+ const app = require('./app');
401
+ const { ENV } = require('./config/env');
402
+ ${database === 'mongodb' ? "const connectDB = require('./config/database');" : ''}
403
+ ${database === 'postgresql' || database === 'mysql' ? "const { connectDatabase } = require('./config/database');" : ''}
404
+ ${logger !== 'None' ? "const logger = require('./config/logger');" : ''}
405
+
406
+ ${database === 'mongodb' ? `// Connect to MongoDB
407
+ connectDB();
408
+ ` : ''}
409
+ ${database === 'postgresql' || database === 'mysql' ? `// Connect to database
410
+ connectDatabase();
411
+ ` : ''}
412
+ const server = app.listen(ENV.PORT, () => {
413
+ ${logger !== 'None'
414
+ ? "logger.info(`Server running on port ${ENV.PORT}`);"
415
+ : "console.log(`🚀 Server running on port ${ENV.PORT}`);"}
416
+ });
417
+
418
+ // Graceful shutdown
419
+ process.on('SIGTERM', () => {
420
+ ${logger !== 'None' ? "logger.info('SIGTERM received, closing server...');" : "console.log('SIGTERM received');"}
421
+ server.close(() => {
422
+ ${logger !== 'None' ? "logger.info('Server closed');" : "console.log('Server closed');"}
423
+ process.exit(0);
424
+ });
425
+ });
426
+ `;
427
+
428
+ writeFile(path.join(projectPath, `src/server.${ext}`), serverContent);
429
+
430
+ // ============================================================
431
+ // 9. src/app.ts/js
432
+ // ============================================================
433
+ const appContent = isTS ? `import express, { Application, Request, Response, NextFunction } from 'express';
434
+ import cors from 'cors';
435
+ import helmet from 'helmet';
436
+ import { ENV } from './config/env';
437
+ ${errorHandling ? "import { AppError } from './utils/AppError';\nimport { errorResponse } from './utils/response';" : ''}
438
+
439
+ const app: Application = express();
440
+
441
+ // Security middleware
442
+ app.use(helmet());
443
+ app.use(cors({ origin: ENV.CORS_ORIGIN, credentials: true }));
444
+
445
+ // Body parser
446
+ app.use(express.json());
447
+ app.use(express.urlencoded({ extended: true }));
448
+
449
+ // Health check
450
+ app.get('/', (req: Request, res: Response) => {
451
+ res.json({
452
+ success: true,
453
+ message: 'Server is healthy',
454
+ timestamp: new Date().toISOString()
455
+ });
456
+ });
457
+
458
+ // API Routes
459
+ // app.use('/api', routes);
460
+
461
+ ${errorHandling ? `// 404 handler
462
+ app.use((req: Request, res: Response, next: NextFunction) => {
463
+ next(new AppError(\`Route \${req.originalUrl} not found\`, 404));
464
+ });
465
+
466
+ // Global error handler
467
+ app.use((err: any, req: Request, res: Response, next: NextFunction) => {
468
+ const statusCode = err.statusCode || 500;
469
+ const message = err.message || 'Internal Server Error';
470
+
471
+ if (ENV.NODE_ENV === 'development') {
472
+ return res.status(statusCode).json({
473
+ success: false,
474
+ message,
475
+ stack: err.stack,
476
+ error: err
477
+ });
478
+ }
479
+
480
+ return errorResponse(res, message, statusCode);
481
+ });
482
+ ` : ''}
483
+ export default app;
484
+ ` : `const express = require('express');
485
+ const cors = require('cors');
486
+ const helmet = require('helmet');
487
+ const { ENV } = require('./config/env');
488
+ ${errorHandling ? "const { AppError } = require('./utils/AppError');\nconst { errorResponse } = require('./utils/response');" : ''}
489
+
490
+ const app = express();
491
+
492
+ // Security middleware
493
+ app.use(helmet());
494
+ app.use(cors({ origin: ENV.CORS_ORIGIN, credentials: true }));
495
+
496
+ // Body parser
497
+ app.use(express.json());
498
+ app.use(express.urlencoded({ extended: true }));
499
+
500
+ // Health check
501
+ app.get('/', (req, res) => {
502
+ res.json({
503
+ success: true,
504
+ message: 'Server is healthy',
505
+ timestamp: new Date().toISOString()
506
+ });
507
+ });
508
+
509
+ // API Routes
510
+ // app.use('/api', routes);
511
+
512
+ ${errorHandling ? `// 404 handler
513
+ app.use((req, res, next) => {
514
+ next(new AppError(\`Route \${req.originalUrl} not found\`, 404));
515
+ });
516
+
517
+ // Global error handler
518
+ app.use((err, req, res, next) => {
519
+ const statusCode = err.statusCode || 500;
520
+ const message = err.message || 'Internal Server Error';
521
+
522
+ if (ENV.NODE_ENV === 'development') {
523
+ return res.status(statusCode).json({
524
+ success: false,
525
+ message,
526
+ stack: err.stack,
527
+ error: err
528
+ });
529
+ }
530
+
531
+ return errorResponse(res, message, statusCode);
532
+ });
533
+ ` : ''}
534
+ module.exports = app;
535
+ `;
536
+
537
+ writeFile(path.join(projectPath, `src/app.${ext}`), appContent);
538
+
539
+ // ============================================================
540
+ // 10. DATABASE CONFIG
541
+ // ============================================================
542
+ if (database === 'mongodb') {
543
+ const mongoContent = isTS ? `import mongoose from 'mongoose';
544
+ import { ENV } from './env';
545
+ ${logger !== 'None' ? "import logger from './logger';" : ''}
546
+
547
+ const connectDB = async (): Promise<void> => {
548
+ try {
549
+ await mongoose.connect(ENV.MONGODB_URI);
550
+ ${logger !== 'None' ? "logger.info('MongoDB connected successfully');" : "console.log('✅ MongoDB connected');"}
551
+ } catch (error) {
552
+ ${logger !== 'None' ? "logger.error('MongoDB connection error:', error);" : "console.error('❌ MongoDB error:', error);"}
553
+ process.exit(1);
554
+ }
555
+ };
556
+
557
+ export default connectDB;
558
+ ` : `const mongoose = require('mongoose');
559
+ const { ENV } = require('./env');
560
+ ${logger !== 'None' ? "const logger = require('./logger');" : ''}
561
+
562
+ const connectDB = async () => {
563
+ try {
564
+ await mongoose.connect(ENV.MONGODB_URI);
565
+ ${logger !== 'None' ? "logger.info('MongoDB connected successfully');" : "console.log('✅ MongoDB connected');"}
566
+ } catch (error) {
567
+ ${logger !== 'None' ? "logger.error('MongoDB connection error:', error);" : "console.error('❌ MongoDB error:', error);"}
568
+ process.exit(1);
569
+ }
570
+ };
571
+
572
+ module.exports = connectDB;
573
+ `;
574
+
575
+ writeFile(path.join(projectPath, `src/config/database.${ext}`), mongoContent);
576
+
577
+ // Info file for models folder
578
+ const mongooseInfoContent = isTS ? `import mongoose, { Document, Schema } from 'mongoose';
579
+
580
+ /**
581
+ * MODELS FOLDER
582
+ *
583
+ * This folder contains Mongoose schemas and models for MongoDB.
584
+ *
585
+ * Purpose:
586
+ * - Define data structure and validation rules
587
+ * - Create database models for collections
588
+ * - Add instance and static methods
589
+ * - Set up hooks (pre/post save, etc.)
590
+ *
591
+ * How to create a model:
592
+ *
593
+ * 1. Define interface:
594
+ * export interface IUser extends Document {
595
+ * name: string;
596
+ * email: string;
597
+ * password: string;
598
+ * createdAt: Date;
599
+ * updatedAt: Date;
600
+ * }
601
+ *
602
+ * 2. Create schema:
603
+ * const userSchema = new Schema<IUser>({
604
+ * name: { type: String, required: true, trim: true },
605
+ * email: {
606
+ * type: String,
607
+ * required: true,
608
+ * unique: true,
609
+ * lowercase: true
610
+ * },
611
+ * password: { type: String, required: true, minlength: 6 }
612
+ * }, {
613
+ * timestamps: true // Auto-creates createdAt, updatedAt
614
+ * });
615
+ *
616
+ * 3. Add methods (optional):
617
+ * userSchema.methods.comparePassword = async function(password: string) {
618
+ * return bcrypt.compare(password, this.password);
619
+ * };
620
+ *
621
+ * 4. Export model:
622
+ * export const User = mongoose.model<IUser>('User', userSchema);
623
+ *
624
+ * 5. Use in controllers:
625
+ * import { User } from '../models/user.model';
626
+ *
627
+ * const users = await User.find();
628
+ * const user = await User.create({ name, email, password });
629
+ * const user = await User.findById(id);
630
+ * await User.findByIdAndUpdate(id, updates);
631
+ * await User.findByIdAndDelete(id);
632
+ *
633
+ * Common model files:
634
+ * - user.model.ts - User authentication and profile
635
+ * - product.model.ts - Product catalog
636
+ * - order.model.ts - Customer orders
637
+ */
638
+
639
+ // Example: Uncomment to use
640
+ // export interface IExample extends Document {
641
+ // field: string;
642
+ // }
643
+ //
644
+ // const exampleSchema = new Schema<IExample>({
645
+ // field: { type: String, required: true }
646
+ // });
647
+ //
648
+ // export const Example = mongoose.model<IExample>('Example', exampleSchema);
649
+ ` : `const mongoose = require('mongoose');
650
+
651
+ /**
652
+ * MODELS FOLDER
653
+ *
654
+ * This folder contains Mongoose schemas and models for MongoDB.
655
+ *
656
+ * Purpose:
657
+ * - Define data structure and validation rules
658
+ * - Create database models for collections
659
+ * - Add instance and static methods
660
+ * - Set up hooks (pre/post save, etc.)
661
+ *
662
+ * How to create a model:
663
+ *
664
+ * 1. Create schema:
665
+ * const userSchema = new mongoose.Schema({
666
+ * name: { type: String, required: true, trim: true },
667
+ * email: {
668
+ * type: String,
669
+ * required: true,
670
+ * unique: true,
671
+ * lowercase: true
672
+ * },
673
+ * password: { type: String, required: true, minlength: 6 }
674
+ * }, {
675
+ * timestamps: true // Auto-creates createdAt, updatedAt
676
+ * });
677
+ *
678
+ * 2. Add methods (optional):
679
+ * userSchema.methods.comparePassword = async function(password) {
680
+ * return bcrypt.compare(password, this.password);
681
+ * };
682
+ *
683
+ * 3. Export model:
684
+ * module.exports = mongoose.model('User', userSchema);
685
+ *
686
+ * 4. Use in controllers:
687
+ * const User = require('../models/user.model');
688
+ *
689
+ * const users = await User.find();
690
+ * const user = await User.create({ name, email, password });
691
+ * const user = await User.findById(id);
692
+ * await User.findByIdAndUpdate(id, updates);
693
+ * await User.findByIdAndDelete(id);
694
+ *
695
+ * Common model files:
696
+ * - user.model.js - User authentication and profile
697
+ * - product.model.js - Product catalog
698
+ * - order.model.js - Customer orders
699
+ */
700
+
701
+ // Example: Uncomment to use
702
+ // const exampleSchema = new mongoose.Schema({
703
+ // field: { type: String, required: true }
704
+ // });
705
+ //
706
+ // module.exports = mongoose.model('Example', exampleSchema);
707
+ `;
708
+
709
+ writeFile(path.join(projectPath, `src/models/info.${ext}`), mongooseInfoContent);
710
+
711
+ } else if (database === 'postgresql' || database === 'mysql') {
712
+ const sequelizeContent = isTS ? `import { Sequelize } from 'sequelize';
713
+ import { ENV } from './env';
714
+ ${logger !== 'None' ? "import logger from './logger';" : ''}
715
+
716
+ export const sequelize = new Sequelize({
717
+ dialect: '${database === 'postgresql' ? 'postgres' : 'mysql'}',
718
+ host: ENV.DB_HOST,
719
+ port: ENV.DB_PORT,
720
+ database: ENV.DB_NAME,
721
+ username: ENV.DB_USER,
722
+ password: ENV.DB_PASSWORD,
723
+ logging: false, // Disable SQL query logging
724
+ pool: {
725
+ max: 5,
726
+ min: 0,
727
+ acquire: 30000,
728
+ idle: 10000
729
+ }
730
+ });
731
+
732
+ export const connectDatabase = async (): Promise<void> => {
733
+ try {
734
+ await sequelize.authenticate();
735
+ ${logger !== 'None' ? "logger.info('Database connected successfully');" : "console.log('✅ Database connected');"}
736
+ } catch (error) {
737
+ ${logger !== 'None' ? "logger.error('Database connection failed:', error);" : "console.error('❌ Database connection failed:', error);"}
738
+ process.exit(1);
739
+ }
740
+ };
741
+ ` : `const { Sequelize } = require('sequelize');
742
+ const { ENV } = require('./env');
743
+ ${logger !== 'None' ? "const logger = require('./logger');" : ''}
744
+
745
+ const sequelize = new Sequelize({
746
+ dialect: '${database === 'postgresql' ? 'postgres' : 'mysql'}',
747
+ host: ENV.DB_HOST,
748
+ port: ENV.DB_PORT,
749
+ database: ENV.DB_NAME,
750
+ username: ENV.DB_USER,
751
+ password: ENV.DB_PASSWORD,
752
+ logging: false, // Disable SQL query logging
753
+ pool: {
754
+ max: 5,
755
+ min: 0,
756
+ acquire: 30000,
757
+ idle: 10000
758
+ }
759
+ });
760
+
761
+ const connectDatabase = async () => {
762
+ try {
763
+ await sequelize.authenticate();
764
+ ${logger !== 'None' ? "logger.info('Database connected successfully');" : "console.log('✅ Database connected');"}
765
+ } catch (error) {
766
+ ${logger !== 'None' ? "logger.error('Database connection failed:', error);" : "console.error('❌ Database connection failed:', error);"}
767
+ process.exit(1);
768
+ }
769
+ };
770
+
771
+ module.exports = { sequelize, connectDatabase };
772
+ `;
773
+
774
+ writeFile(path.join(projectPath, `src/config/database.${ext}`), sequelizeContent);
775
+
776
+ // Sequelize config file for CLI
777
+ const sequelizeConfigContent = `module.exports = {
778
+ development: {
779
+ username: process.env.DB_USER || '${database === 'postgresql' ? 'postgres' : 'root'}',
780
+ password: process.env.DB_PASSWORD || '${database === 'postgresql' ? 'root' : 'password'}',
781
+ database: process.env.DB_NAME || 'my-back',
782
+ host: process.env.DB_HOST || 'localhost',
783
+ port: process.env.DB_PORT || ${database === 'postgresql' ? '5432' : '3306'},
784
+ dialect: '${database === 'postgresql' ? 'postgres' : 'mysql'}'
785
+ },
786
+ test: {
787
+ username: process.env.DB_USER || '${database === 'postgresql' ? 'postgres' : 'root'}',
788
+ password: process.env.DB_PASSWORD || '${database === 'postgresql' ? 'root' : 'password'}',
789
+ database: \`\${process.env.DB_NAME || 'my-back'}_test\`,
790
+ host: process.env.DB_HOST || 'localhost',
791
+ port: process.env.DB_PORT || ${database === 'postgresql' ? '5432' : '3306'},
792
+ dialect: '${database === 'postgresql' ? 'postgres' : 'mysql'}'
793
+ },
794
+ production: {
795
+ use_env_variable: 'DATABASE_URL',
796
+ dialect: '${database === 'postgresql' ? 'postgres' : 'mysql'}',
797
+ dialectOptions: {
798
+ ssl: {
799
+ require: true,
800
+ rejectUnauthorized: false
801
+ }
802
+ }
803
+ }
804
+ };
805
+ `;
806
+
807
+ writeFile(path.join(projectPath, '.sequelizerc'), `const path = require('path');
808
+
809
+ module.exports = {
810
+ 'config': path.resolve('config', 'database.js'),
811
+ 'models-path': path.resolve('src', 'models'),
812
+ 'seeders-path': path.resolve('src', 'seeders'),
813
+ 'migrations-path': path.resolve('src', 'migrations')
814
+ };
815
+ `);
816
+
817
+ fs.mkdirSync(path.join(projectPath, 'config'), { recursive: true });
818
+ writeFile(path.join(projectPath, 'config/database.js'), sequelizeConfigContent);
819
+
820
+ // Info file for models folder
821
+ const sequelizeInfoContent = isTS ? `import { DataTypes, Model, Optional } from 'sequelize';
822
+ import { sequelize } from '../config/database';
823
+
824
+ /**
825
+ * MODELS FOLDER
826
+ *
827
+ * This folder contains Sequelize models for ${database === 'postgresql' ? 'PostgreSQL' : 'MySQL'}.
828
+ *
829
+ * Purpose:
830
+ * - Define table structure and data types
831
+ * - Set up relationships between tables
832
+ * - Add validations and constraints
833
+ * - Create model methods and hooks
834
+ *
835
+ * How to create a model:
836
+ *
837
+ * 1. Define interfaces:
838
+ * interface UserAttributes {
839
+ * id: number;
840
+ * name: string;
841
+ * email: string;
842
+ * createdAt?: Date;
843
+ * updatedAt?: Date;
844
+ * }
845
+ *
846
+ * interface UserCreationAttributes extends Optional<UserAttributes, 'id'> {}
847
+ *
848
+ * 2. Create model class:
849
+ * export class User extends Model<UserAttributes, UserCreationAttributes>
850
+ * implements UserAttributes {
851
+ * public id!: number;
852
+ * public name!: string;
853
+ * public email!: string;
854
+ * public readonly createdAt!: Date;
855
+ * public readonly updatedAt!: Date;
856
+ * }
857
+ *
858
+ * 3. Initialize model:
859
+ * User.init({
860
+ * id: {
861
+ * type: DataTypes.INTEGER,
862
+ * autoIncrement: true,
863
+ * primaryKey: true
864
+ * },
865
+ * name: {
866
+ * type: DataTypes.STRING,
867
+ * allowNull: false
868
+ * },
869
+ * email: {
870
+ * type: DataTypes.STRING,
871
+ * allowNull: false,
872
+ * unique: true,
873
+ * validate: { isEmail: true }
874
+ * }
875
+ * }, {
876
+ * sequelize,
877
+ * tableName: 'users',
878
+ * timestamps: true // Auto-creates createdAt, updatedAt
879
+ * });
880
+ *
881
+ * 4. Add associations (optional):
882
+ * User.hasMany(Post, { foreignKey: 'userId' });
883
+ * Post.belongsTo(User, { foreignKey: 'userId' });
884
+ *
885
+ * 5. Use in controllers:
886
+ * import { User } from '../models/user.model';
887
+ *
888
+ * const users = await User.findAll();
889
+ * const user = await User.create({ name, email });
890
+ * const user = await User.findByPk(id);
891
+ * await User.update({ name }, { where: { id } });
892
+ * await User.destroy({ where: { id } });
893
+ *
894
+ * Generate migration:
895
+ * npx sequelize-cli migration:generate --name create-users
896
+ *
897
+ * Common model files:
898
+ * - user.model.ts - User authentication and profile
899
+ * - product.model.ts - Product catalog
900
+ * - order.model.ts - Customer orders
901
+ */
902
+
903
+ // Example: Uncomment to use
904
+ // interface ExampleAttributes {
905
+ // id: number;
906
+ // field: string;
907
+ // }
908
+ //
909
+ // interface ExampleCreationAttributes extends Optional<ExampleAttributes, 'id'> {}
910
+ //
911
+ // export class Example extends Model<ExampleAttributes, ExampleCreationAttributes> {
912
+ // public id!: number;
913
+ // public field!: string;
914
+ // }
915
+ //
916
+ // Example.init({
917
+ // id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
918
+ // field: { type: DataTypes.STRING, allowNull: false }
919
+ // }, { sequelize, tableName: 'examples' });
920
+ ` : `const { DataTypes, Model } = require('sequelize');
921
+ const { sequelize } = require('../config/database');
922
+
923
+ /**
924
+ * MODELS FOLDER
925
+ *
926
+ * This folder contains Sequelize models for ${database === 'postgresql' ? 'PostgreSQL' : 'MySQL'}.
927
+ *
928
+ * Purpose:
929
+ * - Define table structure and data types
930
+ * - Set up relationships between tables
931
+ * - Add validations and constraints
932
+ * - Create model methods and hooks
933
+ *
934
+ * How to create a model:
935
+ *
936
+ * 1. Create model class:
937
+ * class User extends Model {}
938
+ *
939
+ * 2. Initialize model:
940
+ * User.init({
941
+ * id: {
942
+ * type: DataTypes.INTEGER,
943
+ * autoIncrement: true,
944
+ * primaryKey: true
945
+ * },
946
+ * name: {
947
+ * type: DataTypes.STRING,
948
+ * allowNull: false
949
+ * },
950
+ * email: {
951
+ * type: DataTypes.STRING,
952
+ * allowNull: false,
953
+ * unique: true,
954
+ * validate: { isEmail: true }
955
+ * }
956
+ * }, {
957
+ * sequelize,
958
+ * tableName: 'users',
959
+ * timestamps: true // Auto-creates createdAt, updatedAt
960
+ * });
961
+ *
962
+ * 3. Add associations (optional):
963
+ * User.hasMany(Post, { foreignKey: 'userId' });
964
+ * Post.belongsTo(User, { foreignKey: 'userId' });
965
+ *
966
+ * 4. Use in controllers:
967
+ * const User = require('../models/user.model');
968
+ *
969
+ * const users = await User.findAll();
970
+ * const user = await User.create({ name, email });
971
+ * const user = await User.findByPk(id);
972
+ * await User.update({ name }, { where: { id } });
973
+ * await User.destroy({ where: { id } });
974
+ *
975
+ * Generate migration:
976
+ * npx sequelize-cli migration:generate --name create-users
977
+ *
978
+ * Common model files:
979
+ * - user.model.js - User authentication and profile
980
+ * - product.model.js - Product catalog
981
+ * - order.model.js - Customer orders
982
+ */
983
+
984
+ // Example: Uncomment to use
985
+ // class Example extends Model {}
986
+ //
987
+ // Example.init({
988
+ // id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
989
+ // field: { type: DataTypes.STRING, allowNull: false }
990
+ // }, { sequelize, tableName: 'examples' });
991
+ //
992
+ // module.exports = { Example };
993
+ `;
994
+
995
+ writeFile(path.join(projectPath, `src/models/info.${ext}`), sequelizeInfoContent);
996
+ }
997
+
998
+ // ============================================================
999
+ // 11. LOGGER CONFIG - UPDATED WITH CLEAN OUTPUT
1000
+ // ============================================================
1001
+ if (logger === 'Winston') {
1002
+ const winstonContent = isTS ? `import winston from 'winston';
1003
+
1004
+ const logger = winston.createLogger({
1005
+ level: process.env.LOG_LEVEL || 'info',
1006
+ format: winston.format.combine(
1007
+ winston.format.errors({ stack: true }),
1008
+ winston.format.splat(),
1009
+ winston.format.printf(({ level, message }) => {
1010
+ const emoji = level === 'info' ? '✅' : level === 'error' ? '❌' : 'ℹ️';
1011
+ return \`\${emoji} \${message}\`;
1012
+ })
1013
+ ),
1014
+ transports: [
1015
+ new winston.transports.Console({
1016
+ format: winston.format.combine(
1017
+ winston.format.colorize(),
1018
+ winston.format.printf(({ level, message }) => {
1019
+ const emoji = level.includes('info') ? '✅' : level.includes('error') ? '❌' : 'ℹ️';
1020
+ return \`\${emoji} \${message}\`;
1021
+ })
1022
+ ),
1023
+ }),
1024
+ ],
1025
+ });
1026
+
1027
+ export default logger;
1028
+ ` : `const winston = require('winston');
1029
+
1030
+ const logger = winston.createLogger({
1031
+ level: process.env.LOG_LEVEL || 'info',
1032
+ format: winston.format.combine(
1033
+ winston.format.errors({ stack: true }),
1034
+ winston.format.splat(),
1035
+ winston.format.printf(({ level, message }) => {
1036
+ const emoji = level === 'info' ? '✅' : level === 'error' ? '❌' : 'ℹ️';
1037
+ return \`\${emoji} \${message}\`;
1038
+ })
1039
+ ),
1040
+ transports: [
1041
+ new winston.transports.Console({
1042
+ format: winston.format.combine(
1043
+ winston.format.colorize(),
1044
+ winston.format.printf(({ level, message }) => {
1045
+ const emoji = level.includes('info') ? '✅' : level.includes('error') ? '❌' : 'ℹ️';
1046
+ return \`\${emoji} \${message}\`;
1047
+ })
1048
+ ),
1049
+ }),
1050
+ ],
1051
+ });
1052
+
1053
+ module.exports = logger;
1054
+ `;
1055
+
1056
+ writeFile(path.join(projectPath, `src/config/logger.${ext}`), winstonContent);
1057
+ } else if (logger === 'Pino') {
1058
+ const pinoContent = isTS ? `import pino from 'pino';
1059
+ import { ENV } from './env';
1060
+
1061
+ const logger = pino({
1062
+ level: ENV.NODE_ENV === 'production' ? 'info' : 'debug',
1063
+ transport: ENV.NODE_ENV === 'development' ? {
1064
+ target: 'pino-pretty',
1065
+ options: {
1066
+ colorize: true,
1067
+ translateTime: 'SYS:standard',
1068
+ ignore: 'pid,hostname'
1069
+ }
1070
+ } : undefined
1071
+ });
1072
+
1073
+ export default logger;
1074
+ ` : `const pino = require('pino');
1075
+ const { ENV } = require('./env');
1076
+
1077
+ const logger = pino({
1078
+ level: ENV.NODE_ENV === 'production' ? 'info' : 'debug',
1079
+ transport: ENV.NODE_ENV === 'development' ? {
1080
+ target: 'pino-pretty',
1081
+ options: {
1082
+ colorize: true,
1083
+ translateTime: 'SYS:standard',
1084
+ ignore: 'pid,hostname'
1085
+ }
1086
+ } : undefined
1087
+ });
1088
+
1089
+ module.exports = logger;
1090
+ `;
1091
+
1092
+ writeFile(path.join(projectPath, `src/config/logger.${ext}`), pinoContent);
1093
+ }
1094
+
1095
+ // ============================================================
1096
+ // 12. VALIDATORS (if validation library chosen)
1097
+ // ============================================================
1098
+ if (validation === 'zod') {
1099
+ const zodValidatorContent = isTS ? `import { z } from 'zod';
1100
+
1101
+ /**
1102
+ * VALIDATORS FOLDER
1103
+ *
1104
+ * This folder contains request validation schemas using Zod.
1105
+ *
1106
+ * Purpose:
1107
+ * - Validate incoming request data (body, params, query)
1108
+ * - Ensure type safety with TypeScript inference
1109
+ * - Provide clear error messages for invalid data
1110
+ *
1111
+ * How to create a validator:
1112
+ *
1113
+ * 1. Define your schema:
1114
+ * export const createUserSchema = z.object({
1115
+ * name: z.string().min(1, 'Name is required'),
1116
+ * email: z.string().email('Invalid email'),
1117
+ * age: z.number().min(18).optional()
1118
+ * });
1119
+ *
1120
+ * 2. Infer TypeScript type:
1121
+ * export type CreateUserInput = z.infer<typeof createUserSchema>;
1122
+ *
1123
+ * 3. Use in middleware:
1124
+ * const validateRequest = (schema: z.ZodSchema) => {
1125
+ * return (req, res, next) => {
1126
+ * const result = schema.safeParse(req.body);
1127
+ * if (!result.success) {
1128
+ * return res.status(400).json({
1129
+ * success: false,
1130
+ * errors: result.error.errors
1131
+ * });
1132
+ * }
1133
+ * req.body = result.data;
1134
+ * next();
1135
+ * };
1136
+ * };
1137
+ *
1138
+ * Example validators for common use cases:
1139
+ * - user.validator.ts - User registration, login, update
1140
+ * - product.validator.ts - Product creation, update
1141
+ * - auth.validator.ts - Authentication requests
1142
+ */
1143
+
1144
+ // Example: Uncomment to use
1145
+ // export const exampleSchema = z.object({
1146
+ // field: z.string()
1147
+ // });
1148
+ ` : `const { z } = require('zod');
1149
+
1150
+ /**
1151
+ * VALIDATORS FOLDER
1152
+ *
1153
+ * This folder contains request validation schemas using Zod.
1154
+ *
1155
+ * Purpose:
1156
+ * - Validate incoming request data (body, params, query)
1157
+ * - Provide clear error messages for invalid data
1158
+ *
1159
+ * How to create a validator:
1160
+ *
1161
+ * 1. Define your schema:
1162
+ * const createUserSchema = z.object({
1163
+ * name: z.string().min(1, 'Name is required'),
1164
+ * email: z.string().email('Invalid email'),
1165
+ * age: z.number().min(18).optional()
1166
+ * });
1167
+ *
1168
+ * 2. Use in middleware:
1169
+ * const validateRequest = (schema) => {
1170
+ * return (req, res, next) => {
1171
+ * const result = schema.safeParse(req.body);
1172
+ * if (!result.success) {
1173
+ * return res.status(400).json({
1174
+ * success: false,
1175
+ * errors: result.error.errors
1176
+ * });
1177
+ * }
1178
+ * req.body = result.data;
1179
+ * next();
1180
+ * };
1181
+ * };
1182
+ *
1183
+ * Example validators for common use cases:
1184
+ * - user.validator.js - User registration, login, update
1185
+ * - product.validator.js - Product creation, update
1186
+ * - auth.validator.js - Authentication requests
1187
+ */
1188
+
1189
+ // Example: Uncomment to use
1190
+ // const exampleSchema = z.object({
1191
+ // field: z.string()
1192
+ // });
1193
+ //
1194
+ // module.exports = { exampleSchema };
1195
+ `;
1196
+
1197
+ writeFile(path.join(projectPath, `src/validators/info.${ext}`), zodValidatorContent);
1198
+ } else if (validation === 'joi') {
1199
+ const joiValidatorContent = isTS ? `import Joi from 'joi';
1200
+
1201
+ /**
1202
+ * VALIDATORS FOLDER
1203
+ *
1204
+ * This folder contains request validation schemas using Joi.
1205
+ *
1206
+ * Purpose:
1207
+ * - Validate incoming request data (body, params, query)
1208
+ * - Provide clear error messages for invalid data
1209
+ *
1210
+ * How to create a validator:
1211
+ *
1212
+ * 1. Define your schema:
1213
+ * export const createUserSchema = Joi.object({
1214
+ * name: Joi.string().required(),
1215
+ * email: Joi.string().email().required(),
1216
+ * age: Joi.number().min(18).optional()
1217
+ * });
1218
+ *
1219
+ * 2. Use in middleware:
1220
+ * const validateRequest = (schema: Joi.Schema) => {
1221
+ * return (req, res, next) => {
1222
+ * const { error, value } = schema.validate(req.body);
1223
+ * if (error) {
1224
+ * return res.status(400).json({
1225
+ * success: false,
1226
+ * errors: error.details
1227
+ * });
1228
+ * }
1229
+ * req.body = value;
1230
+ * next();
1231
+ * };
1232
+ * };
1233
+ *
1234
+ * Example validators for common use cases:
1235
+ * - user.validator.ts - User registration, login, update
1236
+ * - product.validator.ts - Product creation, update
1237
+ * - auth.validator.ts - Authentication requests
1238
+ */
1239
+
1240
+ // Example: Uncomment to use
1241
+ // export const exampleSchema = Joi.object({
1242
+ // field: Joi.string().required()
1243
+ // });
1244
+ ` : `const Joi = require('joi');
1245
+
1246
+ /**
1247
+ * VALIDATORS FOLDER
1248
+ *
1249
+ * This folder contains request validation schemas using Joi.
1250
+ *
1251
+ * Purpose:
1252
+ * - Validate incoming request data (body, params, query)
1253
+ * - Provide clear error messages for invalid data
1254
+ *
1255
+ * How to create a validator:
1256
+ *
1257
+ * 1. Define your schema:
1258
+ * const createUserSchema = Joi.object({
1259
+ * name: Joi.string().required(),
1260
+ * email: Joi.string().email().required(),
1261
+ * age: Joi.number().min(18).optional()
1262
+ * });
1263
+ *
1264
+ * 2. Use in middleware:
1265
+ * const validateRequest = (schema) => {
1266
+ * return (req, res, next) => {
1267
+ * const { error, value } = schema.validate(req.body);
1268
+ * if (error) {
1269
+ * return res.status(400).json({
1270
+ * success: false,
1271
+ * errors: error.details
1272
+ * });
1273
+ * }
1274
+ * req.body = value;
1275
+ * next();
1276
+ * };
1277
+ * };
1278
+ *
1279
+ * Example validators for common use cases:
1280
+ * - user.validator.js - User registration, login, update
1281
+ * - product.validator.js - Product creation, update
1282
+ * - auth.validator.js - Authentication requests
1283
+ */
1284
+
1285
+ // Example: Uncomment to use
1286
+ // const exampleSchema = Joi.object({
1287
+ // field: Joi.string().required()
1288
+ // });
1289
+ //
1290
+ // module.exports = { exampleSchema };
1291
+ `;
1292
+
1293
+ writeFile(path.join(projectPath, `src/validators/info.${ext}`), joiValidatorContent);
1294
+ }
1295
+
1296
+ // ============================================================
1297
+ // 13. INFO FILES FOR FOLDER STRUCTURE
1298
+ // ============================================================
1299
+
1300
+ // Routes info
1301
+ writeFile(path.join(projectPath, `src/routes/info.${ext}`), isTS
1302
+ ? `import { Router } from 'express';
1303
+
1304
+ /**
1305
+ * ROUTES FOLDER
1306
+ *
1307
+ * This folder contains API route definitions.
1308
+ *
1309
+ * Purpose:
1310
+ * - Define API endpoints and HTTP methods
1311
+ * - Map routes to controller functions
1312
+ * - Apply middleware (auth, validation, etc.)
1313
+ * - Group related routes together
1314
+ *
1315
+ * How to create routes:
1316
+ *
1317
+ * 1. Create a router:
1318
+ * import { Router } from 'express';
1319
+ * const router = Router();
1320
+ *
1321
+ * 2. Define routes:
1322
+ * import { getUsers, createUser } from '../controllers/user.controller';
1323
+ * import { authenticate } from '../middlewares/auth.middleware';
1324
+ * import { validateRequest } from '../middlewares/validation.middleware';
1325
+ * import { createUserSchema } from '../validators/user.validator';
1326
+ *
1327
+ * router.get('/', authenticate, getUsers);
1328
+ * router.post('/',
1329
+ * authenticate,
1330
+ * validateRequest(createUserSchema),
1331
+ * createUser
1332
+ * );
1333
+ * router.get('/:id', authenticate, getUserById);
1334
+ * router.put('/:id', authenticate, updateUser);
1335
+ * router.delete('/:id', authenticate, deleteUser);
1336
+ *
1337
+ * 3. Export router:
1338
+ * export default router;
1339
+ *
1340
+ * 4. Register in main routes:
1341
+ * import userRoutes from './user.routes';
1342
+ * router.use('/users', userRoutes);
1343
+ *
1344
+ * Route naming conventions:
1345
+ * - user.routes.ts - User-related endpoints
1346
+ * - auth.routes.ts - Authentication endpoints
1347
+ * - product.routes.ts - Product endpoints
1348
+ *
1349
+ * Example structure:
1350
+ * GET /api/users - Get all users
1351
+ * POST /api/users - Create user
1352
+ * GET /api/users/:id - Get user by ID
1353
+ * PUT /api/users/:id - Update user
1354
+ * DELETE /api/users/:id - Delete user
1355
+ */
1356
+
1357
+ const router = Router();
1358
+
1359
+ // Example: Uncomment to use
1360
+ // import exampleRoutes from './example.routes';
1361
+ // router.use('/examples', exampleRoutes);
1362
+
1363
+ export default router;`
1364
+ : `const { Router } = require('express');
1365
+
1366
+ /**
1367
+ * ROUTES FOLDER
1368
+ *
1369
+ * This folder contains API route definitions.
1370
+ *
1371
+ * Purpose:
1372
+ * - Define API endpoints and HTTP methods
1373
+ * - Map routes to controller functions
1374
+ * - Apply middleware (auth, validation, etc.)
1375
+ * - Group related routes together
1376
+ *
1377
+ * How to create routes:
1378
+ *
1379
+ * 1. Create a router:
1380
+ * const { Router } = require('express');
1381
+ * const router = Router();
1382
+ *
1383
+ * 2. Define routes:
1384
+ * const { getUsers, createUser } = require('../controllers/user.controller');
1385
+ * const { authenticate } = require('../middlewares/auth.middleware');
1386
+ * const { validateRequest } = require('../middlewares/validation.middleware');
1387
+ * const { createUserSchema } = require('../validators/user.validator');
1388
+ *
1389
+ * router.get('/', authenticate, getUsers);
1390
+ * router.post('/',
1391
+ * authenticate,
1392
+ * validateRequest(createUserSchema),
1393
+ * createUser
1394
+ * );
1395
+ * router.get('/:id', authenticate, getUserById);
1396
+ * router.put('/:id', authenticate, updateUser);
1397
+ * router.delete('/:id', authenticate, deleteUser);
1398
+ *
1399
+ * 3. Export router:
1400
+ * module.exports = router;
1401
+ *
1402
+ * 4. Register in main routes:
1403
+ * const userRoutes = require('./user.routes');
1404
+ * router.use('/users', userRoutes);
1405
+ *
1406
+ * Route naming conventions:
1407
+ * - user.routes.js - User-related endpoints
1408
+ * - auth.routes.js - Authentication endpoints
1409
+ * - product.routes.js - Product endpoints
1410
+ *
1411
+ * Example structure:
1412
+ * GET /api/users - Get all users
1413
+ * POST /api/users - Create user
1414
+ * GET /api/users/:id - Get user by ID
1415
+ * PUT /api/users/:id - Update user
1416
+ * DELETE /api/users/:id - Delete user
1417
+ */
1418
+
1419
+ const router = Router();
1420
+
1421
+ // Example: Uncomment to use
1422
+ // const exampleRoutes = require('./example.routes');
1423
+ // router.use('/examples', exampleRoutes);
1424
+
1425
+ module.exports = router;`
1426
+ );
1427
+
1428
+ // Controllers info
1429
+ writeFile(path.join(projectPath, `src/controllers/info.${ext}`), isTS
1430
+ ? `import { Request, Response, NextFunction } from 'express';
1431
+ ${errorHandling ? "import { successResponse, errorResponse } from '../utils/response';\nimport { AppError } from '../utils/AppError';" : ''}
1432
+
1433
+ /**
1434
+ * CONTROLLERS FOLDER
1435
+ *
1436
+ * This folder contains controller functions that handle HTTP requests.
1437
+ *
1438
+ * Purpose:
1439
+ * - Process incoming requests
1440
+ * - Call service layer for business logic
1441
+ * - Return HTTP responses
1442
+ * - Handle errors appropriately
1443
+ *
1444
+ * How to create a controller:
1445
+ *
1446
+ * 1. Import dependencies:
1447
+ * import { Request, Response, NextFunction } from 'express';
1448
+ ${errorHandling ? "* import { successResponse, errorResponse } from '../utils/response';" : ''}
1449
+ * import { UserService } from '../services/user.service';
1450
+ *
1451
+ * 2. Create controller functions:
1452
+ * export const getUsers = async (
1453
+ * req: Request,
1454
+ * res: Response,
1455
+ * next: NextFunction
1456
+ * ) => {
1457
+ * try {
1458
+ * const users = await UserService.getAllUsers();
1459
+ ${errorHandling ? "* return successResponse(res, users, 'Users retrieved successfully');" : "* return res.json({ success: true, data: users });"}
1460
+ * } catch (error) {
1461
+ * next(error);
1462
+ * }
1463
+ * };
1464
+ *
1465
+ * export const createUser = async (
1466
+ * req: Request,
1467
+ * res: Response,
1468
+ * next: NextFunction
1469
+ * ) => {
1470
+ * try {
1471
+ * const user = await UserService.createUser(req.body);
1472
+ ${errorHandling ? "* return successResponse(res, user, 'User created', 201);" : "* return res.status(201).json({ success: true, data: user });"}
1473
+ * } catch (error) {
1474
+ * next(error);
1475
+ * }
1476
+ * };
1477
+ *
1478
+ * Controller best practices:
1479
+ * - Keep controllers thin - delegate logic to services
1480
+ * - Always use try-catch and pass errors to next()
1481
+ * - Use consistent response format
1482
+ * - Validate input (use validators + middleware)
1483
+ * - Return appropriate HTTP status codes
1484
+ *
1485
+ * Common controller files:
1486
+ * - user.controller.ts - User CRUD operations
1487
+ * - auth.controller.ts - Login, register, logout
1488
+ * - product.controller.ts - Product management
1489
+ */
1490
+
1491
+ // Example: Uncomment to use
1492
+ // export const exampleController = async (
1493
+ // req: Request,
1494
+ // res: Response,
1495
+ // next: NextFunction
1496
+ // ) => {
1497
+ // try {
1498
+ // // Your logic here
1499
+ ${errorHandling ? "// return successResponse(res, {}, 'Success');" : "// return res.json({ success: true });"}
1500
+ // } catch (error) {
1501
+ // next(error);
1502
+ // }
1503
+ // };`
1504
+ : `${errorHandling ? "const { successResponse, errorResponse } = require('../utils/response');\nconst { AppError } = require('../utils/AppError');" : ''}
1505
+
1506
+ /**
1507
+ * CONTROLLERS FOLDER
1508
+ *
1509
+ * This folder contains controller functions that handle HTTP requests.
1510
+ *
1511
+ * Purpose:
1512
+ * - Process incoming requests
1513
+ * - Call service layer for business logic
1514
+ * - Return HTTP responses
1515
+ * - Handle errors appropriately
1516
+ *
1517
+ * How to create a controller:
1518
+ *
1519
+ * 1. Import dependencies:
1520
+ ${errorHandling ? "* const { successResponse } = require('../utils/response');" : ''}
1521
+ * const UserService = require('../services/user.service');
1522
+ *
1523
+ * 2. Create controller functions:
1524
+ * const getUsers = async (req, res, next) => {
1525
+ * try {
1526
+ * const users = await UserService.getAllUsers();
1527
+ ${errorHandling ? "* return successResponse(res, users, 'Users retrieved successfully');" : "* return res.json({ success: true, data: users });"}
1528
+ * } catch (error) {
1529
+ * next(error);
1530
+ * }
1531
+ * };
1532
+ *
1533
+ * const createUser = async (req, res, next) => {
1534
+ * try {
1535
+ * const user = await UserService.createUser(req.body);
1536
+ ${errorHandling ? "* return successResponse(res, user, 'User created', 201);" : "* return res.status(201).json({ success: true, data: user });"}
1537
+ * } catch (error) {
1538
+ * next(error);
1539
+ * }
1540
+ * };
1541
+ *
1542
+ * 3. Export functions:
1543
+ * module.exports = { getUsers, createUser };
1544
+ *
1545
+ * Controller best practices:
1546
+ * - Keep controllers thin - delegate logic to services
1547
+ * - Always use try-catch and pass errors to next()
1548
+ * - Use consistent response format
1549
+ * - Validate input (use validators + middleware)
1550
+ * - Return appropriate HTTP status codes
1551
+ *
1552
+ * Common controller files:
1553
+ * - user.controller.js - User CRUD operations
1554
+ * - auth.controller.js - Login, register, logout
1555
+ * - product.controller.js - Product management
1556
+ */
1557
+
1558
+ // Example: Uncomment to use
1559
+ // const exampleController = async (req, res, next) => {
1560
+ // try {
1561
+ // // Your logic here
1562
+ ${errorHandling ? "// return successResponse(res, {}, 'Success');" : "// return res.json({ success: true });"}
1563
+ // } catch (error) {
1564
+ // next(error);
1565
+ // }
1566
+ // };
1567
+ //
1568
+ // module.exports = { exampleController };`
1569
+ );
1570
+
1571
+ // Services info
1572
+ writeFile(path.join(projectPath, `src/services/info.${ext}`), isTS
1573
+ ? `${database === 'mongodb' ? "// import { User } from '../models/user.model';" : database === 'postgresql' || database === 'mysql' ? "// import { User } from '../models/user.model';" : ''}
1574
+ ${errorHandling ? "import { AppError } from '../utils/AppError';" : ''}
1575
+
1576
+ /**
1577
+ * SERVICES FOLDER
1578
+ *
1579
+ * This folder contains business logic and data access layer.
1580
+ *
1581
+ * Purpose:
1582
+ * - Encapsulate business logic
1583
+ * - Interact with database models
1584
+ * - Handle data transformations
1585
+ * - Reusable functions across controllers
1586
+ *
1587
+ * How to create a service:
1588
+ *
1589
+ * 1. Import model and utilities:
1590
+ * import { User } from '../models/user.model';
1591
+ ${errorHandling ? "* import { AppError } from '../utils/AppError';" : ''}
1592
+ *
1593
+ * 2. Create service class or functions:
1594
+ * export class UserService {
1595
+ * static async getAllUsers() {
1596
+ ${database === 'mongodb' ? '* return await User.find().select(\'-password\');' : database === 'postgresql' || database === 'mysql' ? '* return await User.findAll({ attributes: { exclude: [\'password\'] } });' : '* // Database query here'}
1597
+ * }
1598
+ *
1599
+ * static async getUserById(id: string) {
1600
+ ${database === 'mongodb' ? '* const user = await User.findById(id).select(\'-password\');' : database === 'postgresql' || database === 'mysql' ? '* const user = await User.findByPk(id);' : '* // Database query here'}
1601
+ ${errorHandling ? "* if (!user) throw new AppError('User not found', 404);" : "* if (!user) throw new Error('User not found');"}
1602
+ * return user;
1603
+ * }
1604
+ *
1605
+ * static async createUser(data: any) {
1606
+ ${database === 'mongodb' ? '* return await User.create(data);' : database === 'postgresql' || database === 'mysql' ? '* return await User.create(data);' : '* // Create record'}
1607
+ * }
1608
+ *
1609
+ * static async updateUser(id: string, data: any) {
1610
+ ${database === 'mongodb' ? '* const user = await User.findByIdAndUpdate(id, data, { new: true });' : database === 'postgresql' || database === 'mysql' ? '* await User.update(data, { where: { id } });\n* return await User.findByPk(id);' : '* // Update record'}
1611
+ ${errorHandling ? "* if (!user) throw new AppError('User not found', 404);" : "* if (!user) throw new Error('User not found');"}
1612
+ * return user;
1613
+ * }
1614
+ *
1615
+ * static async deleteUser(id: string) {
1616
+ ${database === 'mongodb' ? '* const user = await User.findByIdAndDelete(id);' : database === 'postgresql' || database === 'mysql' ? '* const deleted = await User.destroy({ where: { id } });' : '* // Delete record'}
1617
+ ${errorHandling ? "* if (!user) throw new AppError('User not found', 404);" : "* if (!user) throw new Error('User not found');"}
1618
+ * return user;
1619
+ * }
1620
+ * }
1621
+ *
1622
+ * Service best practices:
1623
+ * - Keep business logic out of controllers
1624
+ * - Make services reusable
1625
+ * - Throw meaningful errors
1626
+ * - Use transactions for multiple database operations
1627
+ * - Keep services focused (Single Responsibility)
1628
+ *
1629
+ * Common service files:
1630
+ * - user.service.ts - User business logic
1631
+ * - auth.service.ts - Authentication logic
1632
+ * - email.service.ts - Email sending logic
1633
+ */
1634
+
1635
+ // Example: Uncomment to use
1636
+ // export class ExampleService {
1637
+ // static async exampleMethod() {
1638
+ // // Business logic here
1639
+ // }
1640
+ // }`
1641
+ : `${database === 'mongodb' ? "// const User = require('../models/user.model');" : database === 'postgresql' || database === 'mysql' ? "// const { User } = require('../models/user.model');" : ''}
1642
+ ${errorHandling ? "const { AppError } = require('../utils/AppError');" : ''}
1643
+
1644
+ /**
1645
+ * SERVICES FOLDER
1646
+ *
1647
+ * This folder contains business logic and data access layer.
1648
+ *
1649
+ * Purpose:
1650
+ * - Encapsulate business logic
1651
+ * - Interact with database models
1652
+ * - Handle data transformations
1653
+ * - Reusable functions across controllers
1654
+ *
1655
+ * How to create a service:
1656
+ *
1657
+ * 1. Import model and utilities:
1658
+ * const User = require('../models/user.model');
1659
+ ${errorHandling ? "* const { AppError } = require('../utils/AppError');" : ''}
1660
+ *
1661
+ * 2. Create service functions:
1662
+ * class UserService {
1663
+ * static async getAllUsers() {
1664
+ ${database === 'mongodb' ? '* return await User.find().select(\'-password\');' : database === 'postgresql' || database === 'mysql' ? '* return await User.findAll({ attributes: { exclude: [\'password\'] } });' : '* // Database query here'}
1665
+ * }
1666
+ *
1667
+ * static async getUserById(id) {
1668
+ ${database === 'mongodb' ? '* const user = await User.findById(id).select(\'-password\');' : database === 'postgresql' || database === 'mysql' ? '* const user = await User.findByPk(id);' : '* // Database query here'}
1669
+ ${errorHandling ? "* if (!user) throw new AppError('User not found', 404);" : "* if (!user) throw new Error('User not found');"}
1670
+ * return user;
1671
+ * }
1672
+ *
1673
+ * static async createUser(data) {
1674
+ ${database === 'mongodb' ? '* return await User.create(data);' : database === 'postgresql' || database === 'mysql' ? '* return await User.create(data);' : '* // Create record'}
1675
+ * }
1676
+ *
1677
+ * static async updateUser(id, data) {
1678
+ ${database === 'mongodb' ? '* const user = await User.findByIdAndUpdate(id, data, { new: true });' : database === 'postgresql' || database === 'mysql' ? '* await User.update(data, { where: { id } });\n* return await User.findByPk(id);' : '* // Update record'}
1679
+ ${errorHandling ? "* if (!user) throw new AppError('User not found', 404);" : "* if (!user) throw new Error('User not found');"}
1680
+ * return user;
1681
+ * }
1682
+ *
1683
+ * static async deleteUser(id) {
1684
+ ${database === 'mongodb' ? '* const user = await User.findByIdAndDelete(id);' : database === 'postgresql' || database === 'mysql' ? '* const deleted = await User.destroy({ where: { id } });' : '* // Delete record'}
1685
+ ${errorHandling ? "* if (!user) throw new AppError('User not found', 404);" : "* if (!user) throw new Error('User not found');"}
1686
+ * return user;
1687
+ * }
1688
+ * }
1689
+ *
1690
+ * 3. Export service:
1691
+ * module.exports = UserService;
1692
+ *
1693
+ * Service best practices:
1694
+ * - Keep business logic out of controllers
1695
+ * - Make services reusable
1696
+ * - Throw meaningful errors
1697
+ * - Use transactions for multiple database operations
1698
+ * - Keep services focused (Single Responsibility)
1699
+ *
1700
+ * Common service files:
1701
+ * - user.service.js - User business logic
1702
+ * - auth.service.js - Authentication logic
1703
+ * - email.service.js - Email sending logic
1704
+ */
1705
+
1706
+ // Example: Uncomment to use
1707
+ // class ExampleService {
1708
+ // static async exampleMethod() {
1709
+ // // Business logic here
1710
+ // }
1711
+ // }
1712
+ //
1713
+ // module.exports = ExampleService;`
1714
+ );
1715
+
1716
+ // Middlewares info
1717
+ writeFile(path.join(projectPath, `src/middlewares/info.${ext}`), isTS
1718
+ ? `import { Request, Response, NextFunction } from 'express';
1719
+ ${errorHandling ? "import { AppError } from '../utils/AppError';\nimport { errorResponse } from '../utils/response';" : ''}
1720
+
1721
+ /**
1722
+ * MIDDLEWARES FOLDER
1723
+ *
1724
+ * This folder contains Express middleware functions.
1725
+ *
1726
+ * Purpose:
1727
+ * - Intercept and process requests before reaching controllers
1728
+ * - Authentication and authorization
1729
+ * - Request validation
1730
+ * - Error handling
1731
+ * - Logging and monitoring
1732
+ *
1733
+ * How to create middleware:
1734
+ *
1735
+ * 1. Basic middleware:
1736
+ * export const logRequest = (
1737
+ * req: Request,
1738
+ * res: Response,
1739
+ * next: NextFunction
1740
+ * ) => {
1741
+ * console.log(\`\${req.method} \${req.path}\`);
1742
+ * next();
1743
+ * };
1744
+ *
1745
+ * 2. Authentication middleware:
1746
+ * import jwt from 'jsonwebtoken';
1747
+ *
1748
+ * export const authenticate = (
1749
+ * req: Request,
1750
+ * res: Response,
1751
+ * next: NextFunction
1752
+ * ) => {
1753
+ * try {
1754
+ * const token = req.headers.authorization?.split(' ')[1];
1755
+ ${errorHandling ? "* if (!token) throw new AppError('No token provided', 401);" : "* if (!token) return res.status(401).json({ error: 'No token' });"}
1756
+ *
1757
+ * const decoded = jwt.verify(token, process.env.JWT_SECRET!);
1758
+ * req.user = decoded;
1759
+ * next();
1760
+ * } catch (error) {
1761
+ * next(error);
1762
+ * }
1763
+ * };
1764
+ *
1765
+ * 3. Validation middleware:
1766
+ * import { z } from 'zod';
1767
+ *
1768
+ * export const validateRequest = (schema: z.ZodSchema) => {
1769
+ * return (req: Request, res: Response, next: NextFunction) => {
1770
+ * const result = schema.safeParse(req.body);
1771
+ * if (!result.success) {
1772
+ ${errorHandling ? "* return errorResponse(res, 'Validation failed', 400, result.error.errors);" : "* return res.status(400).json({ errors: result.error.errors });"}
1773
+ * }
1774
+ * req.body = result.data;
1775
+ * next();
1776
+ * };
1777
+ * };
1778
+ *
1779
+ * 4. Error handling middleware:
1780
+ * export const errorHandler = (
1781
+ * err: any,
1782
+ * req: Request,
1783
+ * res: Response,
1784
+ * next: NextFunction
1785
+ * ) => {
1786
+ * const statusCode = err.statusCode || 500;
1787
+ * res.status(statusCode).json({
1788
+ * success: false,
1789
+ * message: err.message,
1790
+ * ...(process.env.NODE_ENV === 'development' && { stack: err.stack })
1791
+ * });
1792
+ * };
1793
+ *
1794
+ * Common middleware files:
1795
+ * - auth.middleware.ts - Authentication/authorization
1796
+ * - validation.middleware.ts - Request validation
1797
+ * - upload.middleware.ts - File uploads
1798
+ * - rateLimit.middleware.ts - Rate limiting
1799
+ */
1800
+
1801
+ // Example: Uncomment to use
1802
+ // export const exampleMiddleware = (
1803
+ // req: Request,
1804
+ // res: Response,
1805
+ // next: NextFunction
1806
+ // ) => {
1807
+ // // Middleware logic here
1808
+ // next();
1809
+ // };`
1810
+ : `${errorHandling ? "const { AppError } = require('../utils/AppError');\nconst { errorResponse } = require('../utils/response');" : ''}
1811
+
1812
+ /**
1813
+ * MIDDLEWARES FOLDER
1814
+ *
1815
+ * This folder contains Express middleware functions.
1816
+ *
1817
+ * Purpose:
1818
+ * - Intercept and process requests before reaching controllers
1819
+ * - Authentication and authorization
1820
+ * - Request validation
1821
+ * - Error handling
1822
+ * - Logging and monitoring
1823
+ *
1824
+ * How to create middleware:
1825
+ *
1826
+ * 1. Basic middleware:
1827
+ * const logRequest = (req, res, next) => {
1828
+ * console.log(\`\${req.method} \${req.path}\`);
1829
+ * next();
1830
+ * };
1831
+ *
1832
+ * 2. Authentication middleware:
1833
+ * const jwt = require('jsonwebtoken');
1834
+ *
1835
+ * const authenticate = (req, res, next) => {
1836
+ * try {
1837
+ * const token = req.headers.authorization?.split(' ')[1];
1838
+ ${errorHandling ? "* if (!token) throw new AppError('No token provided', 401);" : "* if (!token) return res.status(401).json({ error: 'No token' });"}
1839
+ *
1840
+ * const decoded = jwt.verify(token, process.env.JWT_SECRET);
1841
+ * req.user = decoded;
1842
+ * next();
1843
+ * } catch (error) {
1844
+ * next(error);
1845
+ * }
1846
+ * };
1847
+ *
1848
+ * 3. Validation middleware:
1849
+ * const { z } = require('zod');
1850
+ *
1851
+ * const validateRequest = (schema) => {
1852
+ * return (req, res, next) => {
1853
+ * const result = schema.safeParse(req.body);
1854
+ * if (!result.success) {
1855
+ ${errorHandling ? "* return errorResponse(res, 'Validation failed', 400, result.error.errors);" : "* return res.status(400).json({ errors: result.error.errors });"}
1856
+ * }
1857
+ * req.body = result.data;
1858
+ * next();
1859
+ * };
1860
+ * };
1861
+ *
1862
+ * 4. Error handling middleware:
1863
+ * const errorHandler = (err, req, res, next) => {
1864
+ * const statusCode = err.statusCode || 500;
1865
+ * res.status(statusCode).json({
1866
+ * success: false,
1867
+ * message: err.message,
1868
+ * ...(process.env.NODE_ENV === 'development' && { stack: err.stack })
1869
+ * });
1870
+ * };
1871
+ *
1872
+ * 5. Export middleware:
1873
+ * module.exports = { logRequest, authenticate, validateRequest };
1874
+ *
1875
+ * Common middleware files:
1876
+ * - auth.middleware.js - Authentication/authorization
1877
+ * - validation.middleware.js - Request validation
1878
+ * - upload.middleware.js - File uploads
1879
+ * - rateLimit.middleware.js - Rate limiting
1880
+ */
1881
+
1882
+ // Example: Uncomment to use
1883
+ // const exampleMiddleware = (req, res, next) => {
1884
+ // // Middleware logic here
1885
+ // next();
1886
+ // };
1887
+ //
1888
+ // module.exports = { exampleMiddleware };`
1889
+ );
1890
+
1891
+ // ============================================================
1892
+ // 14. DOCKER FILES (if enabled)
1893
+ // ============================================================
1894
+ if (docker) {
1895
+ writeFile(path.join(projectPath, 'Dockerfile'), `FROM node:18-alpine
1896
+
1897
+ WORKDIR /app
1898
+
1899
+ COPY package*.json ./
1900
+ RUN npm ci --only=production
1901
+
1902
+ COPY . .
1903
+ ${isTS ? 'RUN npm run build\n' : ''}
1904
+ EXPOSE 5000
1905
+
1906
+ CMD ["npm", "start"]
1907
+ `);
1908
+
1909
+ let composeContent = `version: '3.8'
1910
+
1911
+ services:
1912
+ app:
1913
+ build: .
1914
+ ports:
1915
+ - "\${PORT:-5000}:5000"
1916
+ env_file:
1917
+ - .env
1918
+ restart: unless-stopped
1919
+ `;
1920
+
1921
+ if (database === 'mongodb') {
1922
+ composeContent += ` depends_on:
1923
+ - mongodb
1924
+
1925
+ mongodb:
1926
+ image: mongo:7
1927
+ ports:
1928
+ - "27017:27017"
1929
+ volumes:
1930
+ - mongodb_data:/data/db
1931
+ restart: unless-stopped
1932
+
1933
+ volumes:
1934
+ mongodb_data:
1935
+ `;
1936
+ } else if (database === 'postgresql') {
1937
+ composeContent += ` depends_on:
1938
+ - postgres
1939
+
1940
+ postgres:
1941
+ image: postgres:16
1942
+ environment:
1943
+ POSTGRES_DB: \${DB_NAME:-my-back}
1944
+ POSTGRES_USER: \${DB_USER:-postgres}
1945
+ POSTGRES_PASSWORD: \${DB_PASSWORD:-root}
1946
+ ports:
1947
+ - "\${DB_PORT:-5432}:5432"
1948
+ volumes:
1949
+ - postgres_data:/var/lib/postgresql/data
1950
+ restart: unless-stopped
1951
+
1952
+ volumes:
1953
+ postgres_data:
1954
+ `;
1955
+ } else if (database === 'mysql') {
1956
+ composeContent += ` depends_on:
1957
+ - mysql
1958
+
1959
+ mysql:
1960
+ image: mysql:8
1961
+ environment:
1962
+ MYSQL_DATABASE: \${DB_NAME:-${projectName}}
1963
+ MYSQL_USER: \${DB_USER:-user}
1964
+ MYSQL_PASSWORD: \${DB_PASSWORD:-password}
1965
+ MYSQL_ROOT_PASSWORD: \${DB_PASSWORD:-password}
1966
+ ports:
1967
+ - "\${DB_PORT:-3306}:3306"
1968
+ volumes:
1969
+ - mysql_data:/var/lib/mysql
1970
+ restart: unless-stopped
1971
+
1972
+ volumes:
1973
+ mysql_data:
1974
+ `;
1975
+ }
1976
+
1977
+ writeFile(path.join(projectPath, 'docker-compose.yml'), composeContent);
1978
+
1979
+ writeFile(path.join(projectPath, '.dockerignore'), `node_modules
1980
+ npm-debug.log
1981
+ .env
1982
+ .git
1983
+ .gitignore
1984
+ README.md
1985
+ ${isTS ? 'dist\n' : ''}logs
1986
+ *.log
1987
+ `);
1988
+ }
1989
+
1990
+ // ============================================================
1991
+ // 15. README.md
1992
+ // ============================================================
1993
+ const readmeContent = `# ${projectName}
1994
+
1995
+ Backend API built with Backend Forge v2.0
1996
+
1997
+ ## Features
1998
+
1999
+ - ✅ ${language}
2000
+ - ✅ ${database === 'mongodb' ? 'MongoDB + Mongoose' : database === 'postgresql' ? 'PostgreSQL + Sequelize' : database === 'mysql' ? 'MySQL + Sequelize' : 'No Database'}
2001
+ ${auth ? '- ✅ JWT Authentication' : ''}
2002
+ ${validation !== 'none' ? `- ✅ ${validation === 'zod' ? 'Zod' : 'Joi'} Validation` : ''}
2003
+ ${logger !== 'None' ? `- ✅ ${logger} Logger` : ''}
2004
+ ${errorHandling ? '- ✅ Custom Error Handling & Response Utilities' : ''}
2005
+ ${docker ? '- ✅ Docker Support' : ''}
2006
+ - ✅ Environment Configuration
2007
+ - ✅ CORS & Security (Helmet)
2008
+
2009
+ ## Setup
2010
+
2011
+ \`\`\`bash
2012
+ # Install dependencies
2013
+ npm install
2014
+
2015
+ # Configure environment
2016
+ cp .env.example .env
2017
+ # Edit .env with your settings
2018
+
2019
+ ${database === 'postgresql' || database === 'mysql' ? `# Run database migrations
2020
+ npx sequelize-cli db:migrate
2021
+
2022
+ ` : ''}# Start development server
2023
+ npm run dev
2024
+ \`\`\`
2025
+
2026
+ ## Project Structure
2027
+
2028
+ \`\`\`
2029
+ src/
2030
+ ├── config/ # Configuration files
2031
+ │ ├── env.${ext} # Environment constants
2032
+ │ ├── database.${ext} # Database connection
2033
+ ${logger !== 'None' ? `│ └── logger.${ext} # Logger setup\n` : ''}├── routes/ # API routes
2034
+ ├── controllers/ # Route controllers
2035
+ ├── services/ # Business logic
2036
+ ├── models/ # Database models
2037
+ ${validation !== 'none' ? `├── validators/ # Request validators\n` : ''}├── middlewares/ # Custom middleware
2038
+ ├── utils/ # Utility functions
2039
+ ${errorHandling ? `│ ├── AppError.${ext} # Custom error class
2040
+ │ └── response.${ext} # Response helpers
2041
+ ` : ''}├── app.${ext} # Express app
2042
+ └── server.${ext} # Server entry point
2043
+ \`\`\`
2044
+
2045
+ ## Available Scripts
2046
+
2047
+ - \`npm run dev\` - Start development server
2048
+ - \`npm start\` - Start production server
2049
+ ${isTS ? '- `npm run build` - Build TypeScript\n' : ''}${database === 'postgresql' || database === 'mysql' ? `- \`npm run db:migrate\` - Run database migrations
2050
+ - \`npm run db:migrate:undo\` - Undo last migration
2051
+ - \`npm run db:seed\` - Run database seeders
2052
+ ` : ''}
2053
+ ## API Endpoints
2054
+
2055
+ ### Health Check
2056
+ \`\`\`
2057
+ GET /
2058
+ \`\`\`
2059
+
2060
+ Add your routes in \`src/routes/\`
2061
+
2062
+ ${errorHandling ? `## Error Handling
2063
+
2064
+ The project includes:
2065
+ - \`AppError\` class for consistent error handling
2066
+ - \`successResponse\` helper for success responses
2067
+ - \`errorResponse\` helper for error responses
2068
+
2069
+ Example usage:
2070
+
2071
+ \`\`\`${ext}
2072
+ import { AppError } from './utils/AppError';
2073
+ import { successResponse, errorResponse } from './utils/response';
2074
+
2075
+ // Throw custom error
2076
+ throw new AppError('User not found', 404);
2077
+
2078
+ // Success response
2079
+ successResponse(res, data, 'User created', 201);
2080
+
2081
+ // Error response
2082
+ errorResponse(res, 'Invalid input', 400);
2083
+ \`\`\`
2084
+
2085
+ ` : ''}${database === 'postgresql' || database === 'mysql' ? `## Database Migrations
2086
+
2087
+ Create a new migration:
2088
+
2089
+ \`\`\`bash
2090
+ npx sequelize-cli migration:generate --name create-users-table
2091
+ \`\`\`
2092
+
2093
+ Run migrations:
2094
+
2095
+ \`\`\`bash
2096
+ npm run db:migrate
2097
+ \`\`\`
2098
+
2099
+ ` : ''}${docker ? `## Docker
2100
+
2101
+ \`\`\`bash
2102
+ # Start all services
2103
+ docker-compose up
2104
+
2105
+ # Start in background
2106
+ docker-compose up -d
2107
+
2108
+ # Stop services
2109
+ docker-compose down
2110
+ \`\`\`
2111
+
2112
+ ` : ''}## Environment Variables
2113
+
2114
+ See \`.env.example\` for all available environment variables.
2115
+
2116
+ ## License
2117
+
2118
+ MIT
2119
+ `;
2120
+
2121
+ writeFile(path.join(projectPath, 'README.md'), readmeContent);
2122
+
2123
+ // ============================================================
2124
+ // 16. TYPES (if TypeScript)
2125
+ // ============================================================
2126
+ if (isTS) {
2127
+ writeFile(path.join(projectPath, 'src/types/index.ts'), `// Add your TypeScript types and interfaces here
2128
+
2129
+ export interface ApiResponse<T = any> {
2130
+ success: boolean;
2131
+ message: string;
2132
+ data?: T;
2133
+ }
2134
+ `);
2135
+ }
2136
+ }
2137
+
2138
+ module.exports = { createProject };