build-app-with 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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/bin/cli.js +18 -0
  4. package/index.js +3 -0
  5. package/package.json +80 -0
  6. package/src/__tests__/core/error-handler.test.js +99 -0
  7. package/src/__tests__/core/logger.test.js +93 -0
  8. package/src/__tests__/e2e/cli-integration.test.js +220 -0
  9. package/src/__tests__/e2e/framework-generation.test.js +249 -0
  10. package/src/__tests__/setup.js +70 -0
  11. package/src/config/package-mappings.js +110 -0
  12. package/src/constants/index.js +42 -0
  13. package/src/core/error-handler.js +89 -0
  14. package/src/core/logger.js +89 -0
  15. package/src/core/package-manager.js +114 -0
  16. package/src/create-app.js +90 -0
  17. package/src/generators/express/index.js +52 -0
  18. package/src/generators/express/project-generator.js +367 -0
  19. package/src/generators/express/prompts.js +74 -0
  20. package/src/generators/express/simple-generator.js +275 -0
  21. package/src/generators/express/templates/app.js +73 -0
  22. package/src/generators/express/templates/config/database.js +122 -0
  23. package/src/generators/express/templates/config.js +37 -0
  24. package/src/generators/express/templates/controllers.js +49 -0
  25. package/src/generators/express/templates/docker.js +72 -0
  26. package/src/generators/express/templates/middleware/errorHandler.js +49 -0
  27. package/src/generators/express/templates/middleware.js +59 -0
  28. package/src/generators/express/templates/models.js +77 -0
  29. package/src/generators/express/templates/package-json.js +55 -0
  30. package/src/generators/express/templates/readme.js +310 -0
  31. package/src/generators/express/templates/routes.js +36 -0
  32. package/src/generators/express/templates/server.js +59 -0
  33. package/src/generators/express/templates/services.js +55 -0
  34. package/src/generators/express/templates/tests.js +46 -0
  35. package/src/generators/express/templates/utils/logger.js +54 -0
  36. package/src/generators/fastify/index.js +46 -0
  37. package/src/generators/fastify/project-generator.js +373 -0
  38. package/src/generators/fastify/prompts.js +76 -0
  39. package/src/generators/fastify/templates/app.js +179 -0
  40. package/src/generators/fastify/templates/config.js +33 -0
  41. package/src/generators/fastify/templates/docker.js +73 -0
  42. package/src/generators/fastify/templates/models.js +77 -0
  43. package/src/generators/fastify/templates/package-json.js +57 -0
  44. package/src/generators/fastify/templates/plugins.js +38 -0
  45. package/src/generators/fastify/templates/readme.js +328 -0
  46. package/src/generators/fastify/templates/routes.js +32 -0
  47. package/src/generators/fastify/templates/server.js +71 -0
  48. package/src/generators/fastify/templates/services.js +50 -0
  49. package/src/generators/fastify/templates/tests.js +60 -0
  50. package/src/generators/nextjs/dependency-manager.js +99 -0
  51. package/src/generators/nextjs/file-generator.js +256 -0
  52. package/src/generators/nextjs/nextjs-generator.js +177 -0
  53. package/src/generators/nextjs/nextjs-project-generator.js +896 -0
  54. package/src/generators/nextjs/package-mappings.js +51 -0
  55. package/src/generators/nextjs/templates.js +272 -0
  56. package/src/generators/package-json-generator.js +117 -0
  57. package/src/generators/vite/components/CreditComponent.jsx +41 -0
  58. package/src/generators/vite/components/app-component.js +359 -0
  59. package/src/generators/vite/components/main-file.js +88 -0
  60. package/src/generators/vite/eslint-config-generator.js +20 -0
  61. package/src/generators/vite/file-generator.js +796 -0
  62. package/src/generators/vite/prettier-config-generator.js +10 -0
  63. package/src/generators/vite/structures/domain-driven-structure.js +465 -0
  64. package/src/generators/vite/structures/feature-based-structure.js +342 -0
  65. package/src/generators/vite/structures/simple-structure.js +62 -0
  66. package/src/generators/vite/styles/index-css.js +130 -0
  67. package/src/generators/vite/tailwind-config-generator.js +14 -0
  68. package/src/generators/vite/vite-config-generator.js +22 -0
  69. package/src/generators/vite/vite-project-generator.js +263 -0
  70. package/src/generators/vite-project-generator.js +136 -0
  71. package/src/prompts/index.js +262 -0
  72. package/src/types/index.js +113 -0
  73. package/src/utils/answer-helpers.js +24 -0
  74. package/src/utils/credits.js +192 -0
  75. package/src/utils/dependencies.js +25 -0
  76. package/src/utils/messages.js +27 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Generate middleware template
3
+ */
4
+
5
+ export function generateMiddleware(projectPath, answers) {
6
+ const middlewareContent = `import { logger } from '../utils/logger.js';
7
+
8
+ export const requestLogger = (req, res, next) => {
9
+ const start = Date.now();
10
+
11
+ res.on('finish', () => {
12
+ const duration = Date.now() - start;
13
+ logger.info(\`\${req.method} \${req.url} - \${res.statusCode} - \${duration}ms\`);
14
+ });
15
+
16
+ next();
17
+ };
18
+
19
+ export const notFound = (req, res, next) => {
20
+ const error = new Error(\`Not found - \${req.originalUrl}\`);
21
+ res.status(404);
22
+ next(error);
23
+ };
24
+
25
+ export const errorHandler = (err, req, res, next) => {
26
+ let error = { ...err };
27
+ error.message = err.message;
28
+
29
+ // Log error
30
+ logger.error(err);
31
+
32
+ // Mongoose bad ObjectId
33
+ if (err.name === 'CastError') {
34
+ const message = 'Resource not found';
35
+ error = { message, statusCode: 404 };
36
+ }
37
+
38
+ // Mongoose duplicate key
39
+ if (err.code === 11000) {
40
+ const message = 'Duplicate field value entered';
41
+ error = { message, statusCode: 400 };
42
+ }
43
+
44
+ // Mongoose validation error
45
+ if (err.name === 'ValidationError') {
46
+ const message = Object.values(err.errors).map(val => val.message).join(', ');
47
+ error = { message, statusCode: 400 };
48
+ }
49
+
50
+ res.status(error.statusCode || 500).json({
51
+ success: false,
52
+ error: error.message || 'Server Error',
53
+ ...(process.env.NODE_ENV === 'development' && { stack: err.stack })
54
+ });
55
+ };
56
+ `;
57
+
58
+ return middlewareContent;
59
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Generate models template
3
+ */
4
+
5
+ import { DATABASES } from '../../../types/index.js';
6
+
7
+ export function generateModels(projectPath, answers) {
8
+ if (answers.database === DATABASES.MONGODB) {
9
+ return generateMongooseModels(answers);
10
+ } else if (answers.database === DATABASES.POSTGRESQL || answers.database === DATABASES.SQLITE) {
11
+ return generatePrismaModels(answers);
12
+ } else if (answers.database === DATABASES.MYSQL) {
13
+ return generateSequelizeModels(answers);
14
+ }
15
+ return '';
16
+ }
17
+
18
+ function generateMongooseModels(answers) {
19
+ return `import mongoose from 'mongoose';
20
+
21
+ const userSchema = new mongoose.Schema({
22
+ name: {
23
+ type: String,
24
+ required: true,
25
+ trim: true
26
+ },
27
+ email: {
28
+ type: String,
29
+ required: true,
30
+ unique: true,
31
+ lowercase: true,
32
+ trim: true
33
+ },
34
+ password: {
35
+ type: String,
36
+ required: true,
37
+ minlength: 6
38
+ }
39
+ }, {
40
+ timestamps: true
41
+ });
42
+
43
+ export const User = mongoose.model('User', userSchema);
44
+ `;
45
+ }
46
+
47
+ function generatePrismaModels(answers) {
48
+ return `// Prisma schema will be generated in schema.prisma
49
+ // This is a placeholder for Prisma models
50
+
51
+ export const prisma = new PrismaClient();
52
+ `;
53
+ }
54
+
55
+ function generateSequelizeModels(answers) {
56
+ return `import { DataTypes } from 'sequelize';
57
+ import { sequelize } from '../config/database.js';
58
+
59
+ export const User = sequelize.define('User', {
60
+ name: {
61
+ type: DataTypes.STRING,
62
+ allowNull: false
63
+ },
64
+ email: {
65
+ type: DataTypes.STRING,
66
+ allowNull: false,
67
+ unique: true
68
+ },
69
+ password: {
70
+ type: DataTypes.STRING,
71
+ allowNull: false
72
+ }
73
+ }, {
74
+ timestamps: true
75
+ });
76
+ `;
77
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Generate package.json for Express.js project
3
+ */
4
+
5
+ import { FRAMEWORKS, DATABASES, AUTH_STRATEGIES } from '../../../types/index.js';
6
+
7
+ export function generatePackageJson(answers) {
8
+ const basePackage = {
9
+ name: answers.projectName,
10
+ version: '1.0.0',
11
+ description: `A production-ready Express.js application - ${answers.projectName}`,
12
+ main: 'src/server.js',
13
+ type: 'module',
14
+ scripts: {
15
+ start: 'node src/server.js',
16
+ dev: 'nodemon src/server.js',
17
+ test: answers.includeTests ? 'jest' : undefined,
18
+ 'test:watch': answers.includeTests ? 'jest --watch' : undefined,
19
+ 'test:coverage': answers.includeTests ? 'jest --coverage' : undefined
20
+ },
21
+ keywords: [
22
+ 'express',
23
+ 'nodejs',
24
+ 'api',
25
+ 'backend',
26
+ 'server',
27
+ 'rest',
28
+ 'production-ready'
29
+ ],
30
+ author: 'Generated by build-app-with',
31
+ license: 'MIT',
32
+ engines: {
33
+ node: '>=18.0.0'
34
+ },
35
+ dependencies: {},
36
+ devDependencies: {}
37
+ };
38
+
39
+ // Add database-specific scripts
40
+ if (answers.database === DATABASES.POSTGRESQL || answers.database === DATABASES.SQLITE) {
41
+ basePackage.scripts['db:generate'] = 'prisma generate';
42
+ basePackage.scripts['db:push'] = 'prisma db push';
43
+ basePackage.scripts['db:migrate'] = 'prisma migrate dev';
44
+ basePackage.scripts['db:studio'] = 'prisma studio';
45
+ }
46
+
47
+ // Remove undefined scripts
48
+ Object.keys(basePackage.scripts).forEach(key => {
49
+ if (basePackage.scripts[key] === undefined) {
50
+ delete basePackage.scripts[key];
51
+ }
52
+ });
53
+
54
+ return basePackage;
55
+ }
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Generate README for Express.js project
3
+ */
4
+
5
+ import { DATABASES, AUTH_STRATEGIES } from '../../../types/index.js';
6
+ import { generateCreditsSection } from '../../../utils/credits.js';
7
+
8
+ export function generateReadme(projectPath, answers) {
9
+ const selectedFeatures = Array.isArray(answers.features) ? answers.features : [];
10
+ const allFeatures = [...selectedFeatures];
11
+ if (answers.database && answers.database !== 'none') {
12
+ allFeatures.push(answers.database);
13
+ }
14
+ if (answers.authStrategy && answers.authStrategy !== 'none') {
15
+ allFeatures.push(answers.authStrategy);
16
+ }
17
+ if (answers.includeTests) {
18
+ allFeatures.push('jest');
19
+ }
20
+ if (answers.includeDocker) {
21
+ allFeatures.push('docker');
22
+ }
23
+
24
+ const credits = generateCreditsSection('express', allFeatures);
25
+
26
+ const readme = `# ${answers.projectName}
27
+
28
+ A production-ready Express.js application built with modern best practices.
29
+
30
+ ## 🚀 Features
31
+
32
+ - ⚡ **Express.js** - Fast, unopinionated web framework
33
+ - 🔒 **Security** - Helmet, CORS, rate limiting
34
+ - 🗄️ **Database** - ${answers.database === 'none' ? 'No database' : answers.database} integration
35
+ - 🔐 **Authentication** - ${answers.authStrategy === 'none' ? 'No authentication' : answers.authStrategy} strategy
36
+ - 📝 **Logging** - Winston logger with structured logging
37
+ - ✅ **Validation** - Request validation and sanitization
38
+ - 🧪 **Testing** - Jest and Supertest setup
39
+ - 📚 **Documentation** - API documentation with Swagger
40
+ - 🐳 **Docker** - Production-ready containerization
41
+
42
+ ## 🛠️ Tech Stack
43
+
44
+ ${generateTechStack(answers)}
45
+
46
+ ## 📁 Project Structure
47
+
48
+ \`\`\`
49
+ ${answers.projectName}/
50
+ ├── src/
51
+ │ ├── controllers/ # Route controllers
52
+ │ ├── services/ # Business logic
53
+ │ ├── models/ # Database models
54
+ │ ├── routes/ # API routes
55
+ │ ├── middleware/ # Custom middleware
56
+ │ ├── config/ # Configuration files
57
+ │ ├── utils/ # Utility functions
58
+ │ ├── app.js # Express app setup
59
+ │ └── server.js # Server entry point
60
+ ├── tests/ # Test files
61
+ ├── logs/ # Log files
62
+ ├── .env.example # Environment variables example
63
+ ├── .gitignore # Git ignore rules
64
+ ├── package.json # Dependencies and scripts
65
+ └── README.md # This file
66
+ \`\`\`
67
+
68
+ ## 🚀 Getting Started
69
+
70
+ ### Prerequisites
71
+
72
+ - Node.js (v18 or higher)
73
+ - npm, yarn, or pnpm
74
+ ${answers.database !== 'none' ? `- ${answers.database} database` : ''}
75
+
76
+ ### Installation
77
+
78
+ 1. **Clone the repository**
79
+ \`\`\`bash
80
+ git clone <your-repo-url>
81
+ cd ${answers.projectName}
82
+ \`\`\`
83
+
84
+ 2. **Install dependencies**
85
+ \`\`\`bash
86
+ npm install
87
+ \`\`\`
88
+
89
+ 3. **Set up environment variables**
90
+ \`\`\`bash
91
+ cp .env.example .env
92
+ # Edit .env with your configuration
93
+ \`\`\`
94
+
95
+ 4. **Set up the database**
96
+ ${generateDatabaseSetup(answers)}
97
+
98
+ 5. **Start the development server**
99
+ \`\`\`bash
100
+ npm run dev
101
+ \`\`\`
102
+
103
+ The server will start on \`http://localhost:3000\`
104
+
105
+ ## 📚 API Documentation
106
+
107
+ Once the server is running, you can access:
108
+
109
+ - **API Base URL**: \`http://localhost:3000/api\`
110
+ - **Health Check**: \`http://localhost:3000/health\`
111
+ ${answers.features.includes('swagger') ? '- **API Documentation**: `http://localhost:3000/api-docs`' : ''}
112
+
113
+ ## 🧪 Testing
114
+
115
+ \`\`\`bash
116
+ # Run all tests
117
+ npm test
118
+
119
+ # Run tests in watch mode
120
+ npm run test:watch
121
+
122
+ # Run tests with coverage
123
+ npm run test:coverage
124
+ \`\`\`
125
+
126
+ ## 🐳 Docker
127
+
128
+ \`\`\`bash
129
+ # Build Docker image
130
+ docker build -t ${answers.projectName} .
131
+
132
+ # Run with Docker Compose
133
+ docker-compose up -d
134
+ \`\`\`
135
+
136
+ ## 📝 Available Scripts
137
+
138
+ - \`npm start\` - Start production server
139
+ - \`npm run dev\` - Start development server with nodemon
140
+ - \`npm test\` - Run tests
141
+ - \`npm run test:watch\` - Run tests in watch mode
142
+ - \`npm run test:coverage\` - Run tests with coverage report
143
+ ${answers.database === 'postgresql' || answers.database === 'sqlite' ? `
144
+ - \`npm run db:generate\` - Generate Prisma client
145
+ - \`npm run db:push\` - Push schema to database
146
+ - \`npm run db:migrate\` - Run database migrations
147
+ - \`npm run db:studio\` - Open Prisma Studio
148
+ ` : ''}
149
+
150
+ ## 🔧 Configuration
151
+
152
+ ### Environment Variables
153
+
154
+ | Variable | Description | Default |
155
+ |----------|-------------|---------|
156
+ | \`PORT\` | Server port | \`3000\` |
157
+ | \`NODE_ENV\` | Environment | \`development\` |
158
+ ${generateEnvVars(answers)}
159
+
160
+ ## 🚀 Deployment
161
+
162
+ ### Production Checklist
163
+
164
+ - [ ] Set \`NODE_ENV=production\`
165
+ - [ ] Configure proper database connection
166
+ - [ ] Set up logging and monitoring
167
+ - [ ] Configure reverse proxy (nginx)
168
+ - [ ] Set up SSL certificates
169
+ - [ ] Configure environment variables
170
+ - [ ] Set up process manager (PM2)
171
+ - [ ] Configure backup strategy
172
+
173
+ ### PM2 Configuration
174
+
175
+ \`\`\`bash
176
+ # Install PM2 globally
177
+ npm install -g pm2
178
+
179
+ # Start application with PM2
180
+ pm2 start src/server.js --name "${answers.projectName}"
181
+
182
+ # Save PM2 configuration
183
+ pm2 save
184
+ pm2 startup
185
+ \`\`\`
186
+
187
+ ## 🤝 Contributing
188
+
189
+ 1. Fork the repository
190
+ 2. Create your feature branch (\`git checkout -b feature/amazing-feature\`)
191
+ 3. Commit your changes (\`git commit -m 'Add some amazing feature'\`)
192
+ 4. Push to the branch (\`git push origin feature/amazing-feature\`)
193
+ 5. Open a Pull Request
194
+
195
+ ## 📄 License
196
+
197
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
198
+
199
+ ## 🙏 Acknowledgments
200
+
201
+ - **Express.js Team** - For the amazing web framework
202
+ - **Node.js Community** - For the incredible ecosystem
203
+ - **MongoDB/PostgreSQL/MySQL Teams** - For the robust databases
204
+ - **Jest Team** - For the testing framework
205
+ - **Winston Team** - For the logging library
206
+
207
+ ---
208
+
209
+ ${credits}
210
+ `;
211
+
212
+ return readme;
213
+ }
214
+
215
+ function generateTechStack(answers) {
216
+ const stack = ['- **Node.js** - JavaScript runtime'];
217
+
218
+ if (answers.database !== 'none') {
219
+ stack.push(`- **Database** - ${answers.database}`);
220
+ }
221
+
222
+ if (answers.authStrategy !== 'none') {
223
+ stack.push(`- **Authentication** - ${answers.authStrategy}`);
224
+ }
225
+
226
+ if (answers.features.includes('cors')) {
227
+ stack.push('- **CORS** - Cross-origin resource sharing');
228
+ }
229
+
230
+ if (answers.features.includes('helmet')) {
231
+ stack.push('- **Helmet** - Security headers');
232
+ }
233
+
234
+ if (answers.features.includes('morgan')) {
235
+ stack.push('- **Morgan** - HTTP request logger');
236
+ }
237
+
238
+ if (answers.features.includes('winston')) {
239
+ stack.push('- **Winston** - Logging library');
240
+ }
241
+
242
+ if (answers.features.includes('swagger')) {
243
+ stack.push('- **Swagger** - API documentation');
244
+ }
245
+
246
+ if (answers.includeTests) {
247
+ stack.push('- **Jest** - Testing framework');
248
+ stack.push('- **Supertest** - HTTP assertion library');
249
+ }
250
+
251
+ return stack.join('\n');
252
+ }
253
+
254
+ function generateDatabaseSetup(answers) {
255
+ if (answers.database === 'mongodb') {
256
+ return ` \`\`\`bash
257
+ # Start MongoDB (if using local instance)
258
+ mongod
259
+ \`\`\``;
260
+ } else if (answers.database === 'postgresql') {
261
+ return ` \`\`\`bash
262
+ # Generate Prisma client
263
+ npm run db:generate
264
+
265
+ # Push schema to database
266
+ npm run db:push
267
+ \`\`\``;
268
+ } else if (answers.database === 'mysql') {
269
+ return ` \`\`\`bash
270
+ # Create MySQL database
271
+ mysql -u root -p -e "CREATE DATABASE ${answers.projectName};"
272
+ \`\`\``;
273
+ } else if (answers.database === 'sqlite') {
274
+ return ` \`\`\`bash
275
+ # Generate Prisma client
276
+ npm run db:generate
277
+
278
+ # Push schema to database
279
+ npm run db:push
280
+ \`\`\``;
281
+ }
282
+ return '';
283
+ }
284
+
285
+ function generateEnvVars(answers) {
286
+ const vars = [];
287
+
288
+ if (answers.database === 'mongodb') {
289
+ vars.push(`| \`MONGODB_URI\` | MongoDB connection string | \`mongodb://localhost:27017/${answers.projectName}\` |`);
290
+ } else if (answers.database === 'postgresql' || answers.database === 'sqlite') {
291
+ vars.push('| `DATABASE_URL` | Database connection string | `postgresql://...` |');
292
+ } else if (answers.database === 'mysql') {
293
+ vars.push('| `DB_HOST` | MySQL host | `localhost` |');
294
+ vars.push('| `DB_PORT` | MySQL port | `3306` |');
295
+ vars.push(`| \`DB_NAME\` | MySQL database name | \`${answers.projectName}\` |`);
296
+ vars.push('| `DB_USER` | MySQL username | `root` |');
297
+ vars.push('| `DB_PASSWORD` | MySQL password | `password` |');
298
+ }
299
+
300
+ if (answers.authStrategy !== 'none') {
301
+ vars.push('| `JWT_SECRET` | JWT secret key | `your-secret-key` |');
302
+ vars.push('| `JWT_EXPIRES_IN` | JWT expiration time | `7d` |');
303
+ }
304
+
305
+ if (answers.features.includes('cors')) {
306
+ vars.push('| `CORS_ORIGIN` | CORS allowed origin | `http://localhost:3000` |');
307
+ }
308
+
309
+ return vars.join('\n');
310
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Generate routes template
3
+ */
4
+
5
+ export function generateRoutes(projectPath, answers) {
6
+ const routesContent = `import express from 'express';
7
+ import { logger } from '../utils/logger.js';
8
+
9
+ const router = express.Router();
10
+
11
+ // Health check route
12
+ router.get('/health', (req, res) => {
13
+ res.json({
14
+ status: 'OK',
15
+ timestamp: new Date().toISOString(),
16
+ service: '${answers.projectName}'
17
+ });
18
+ });
19
+
20
+ // API routes
21
+ router.get('/', (req, res) => {
22
+ res.json({
23
+ message: 'Welcome to ${answers.projectName} API',
24
+ version: '1.0.0',
25
+ endpoints: {
26
+ health: '/health',
27
+ api: '/api'
28
+ }
29
+ });
30
+ });
31
+
32
+ export default router;
33
+ `;
34
+
35
+ return routesContent;
36
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Generate server.js file
3
+ */
4
+
5
+ import { DATABASES } from '../../../types/index.js';
6
+
7
+ export function generateServerJs(projectPath, answers) {
8
+ let content = `import app from './app.js';
9
+ import { logger } from './utils/logger.js';
10
+ import { connectDatabase } from './config/database.js';
11
+
12
+ const PORT = process.env.PORT || 3000;
13
+ const NODE_ENV = process.env.NODE_ENV || 'development';
14
+
15
+ async function startServer() {
16
+ try {
17
+ // Connect to database
18
+ await connectDatabase();
19
+
20
+ // Start server
21
+ app.listen(PORT, () => {
22
+ logger.info(\`🚀 Server running on port \${PORT} in \${NODE_ENV} mode\`);
23
+ logger.info(\`📊 Health check: http://localhost:\${PORT}/health\`);
24
+ logger.info(\`🔗 API endpoint: http://localhost:\${PORT}/api\`);
25
+ });
26
+ } catch (error) {
27
+ logger.error('Failed to start server:', error);
28
+ process.exit(1);
29
+ }
30
+ }
31
+
32
+ // Handle uncaught exceptions
33
+ process.on('uncaughtException', (error) => {
34
+ logger.error('Uncaught Exception:', error);
35
+ process.exit(1);
36
+ });
37
+
38
+ // Handle unhandled promise rejections
39
+ process.on('unhandledRejection', (reason, promise) => {
40
+ logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
41
+ process.exit(1);
42
+ });
43
+
44
+ // Graceful shutdown
45
+ process.on('SIGTERM', () => {
46
+ logger.info('SIGTERM received, shutting down gracefully');
47
+ process.exit(0);
48
+ });
49
+
50
+ process.on('SIGINT', () => {
51
+ logger.info('SIGINT received, shutting down gracefully');
52
+ process.exit(0);
53
+ });
54
+
55
+ startServer();
56
+ `;
57
+
58
+ return content;
59
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Generate services template
3
+ */
4
+
5
+ export function generateServices(projectPath, answers) {
6
+ const servicesContent = `import { logger } from '../utils/logger.js';
7
+
8
+ export class BaseService {
9
+ static async handleServiceCall(serviceName, operation, data = null) {
10
+ try {
11
+ logger.info(\`Service: \${serviceName} - Operation: \${operation}\`);
12
+
13
+ // Add your business logic here
14
+ const result = await this.performOperation(operation, data);
15
+
16
+ return {
17
+ success: true,
18
+ data: result
19
+ };
20
+ } catch (error) {
21
+ logger.error(\`Service error in \${serviceName}:\`, error);
22
+ throw error;
23
+ }
24
+ }
25
+
26
+ static async performOperation(operation, data) {
27
+ // Implement your business logic here
28
+ return { operation, data };
29
+ }
30
+ }
31
+
32
+ export class HealthService extends BaseService {
33
+ static async getHealthStatus() {
34
+ return this.handleServiceCall('HealthService', 'getStatus', {
35
+ timestamp: new Date().toISOString(),
36
+ uptime: process.uptime(),
37
+ memory: process.memoryUsage(),
38
+ service: '${answers.projectName}'
39
+ });
40
+ }
41
+ }
42
+
43
+ export class ApiService extends BaseService {
44
+ static async getApiInfo() {
45
+ return this.handleServiceCall('ApiService', 'getInfo', {
46
+ message: 'Welcome to ${answers.projectName} API',
47
+ version: '1.0.0',
48
+ features: ['REST API', 'Health Check', 'Error Handling']
49
+ });
50
+ }
51
+ }
52
+ `;
53
+
54
+ return servicesContent;
55
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Generate tests template
3
+ */
4
+
5
+ export function generateTests(projectPath, answers) {
6
+ const testsContent = `import request from 'supertest';
7
+ import app from '../app.js';
8
+
9
+ describe('${answers.projectName} API', () => {
10
+ describe('GET /health', () => {
11
+ it('should return health status', async () => {
12
+ const response = await request(app)
13
+ .get('/health')
14
+ .expect(200);
15
+
16
+ expect(response.body).toHaveProperty('status', 'OK');
17
+ expect(response.body).toHaveProperty('timestamp');
18
+ });
19
+ });
20
+
21
+ describe('GET /api', () => {
22
+ it('should return API information', async () => {
23
+ const response = await request(app)
24
+ .get('/api')
25
+ .expect(200);
26
+
27
+ expect(response.body).toHaveProperty('message');
28
+ expect(response.body).toHaveProperty('version');
29
+ });
30
+ });
31
+
32
+ describe('404 handling', () => {
33
+ it('should return 404 for unknown routes', async () => {
34
+ const response = await request(app)
35
+ .get('/unknown-route')
36
+ .expect(404);
37
+
38
+ expect(response.body).toHaveProperty('success', false);
39
+ expect(response.body).toHaveProperty('error');
40
+ });
41
+ });
42
+ });
43
+ `;
44
+
45
+ return testsContent;
46
+ }