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,179 @@
1
+ /**
2
+ * Generate main Fastify app.js file
3
+ */
4
+
5
+ import { FEATURES, DATABASES } from '../../../types/index.js';
6
+ import { hasFeature } from '../../../utils/answer-helpers.js';
7
+
8
+ export function generateAppJs(projectPath, answers) {
9
+ let content = `import Fastify from 'fastify';
10
+ import cors from '@fastify/cors';
11
+ import helmet from '@fastify/helmet';
12
+ import rateLimit from '@fastify/rate-limit';
13
+ import env from '@fastify/env';
14
+ import { logger } from './utils/logger.js';
15
+ import { errorHandler } from './plugins/errorHandler.js';
16
+ import { notFound } from './plugins/notFound.js';
17
+
18
+ // Environment schema
19
+ const envSchema = {
20
+ type: 'object',
21
+ required: ['PORT'],
22
+ properties: {
23
+ PORT: {
24
+ type: 'string',
25
+ default: '3000'
26
+ },
27
+ NODE_ENV: {
28
+ type: 'string',
29
+ default: 'development'
30
+ },
31
+ HOST: {
32
+ type: 'string',
33
+ default: '0.0.0.0'
34
+ }
35
+ `;
36
+
37
+ // Add database environment variables
38
+ if (answers.database === DATABASES.MONGODB) {
39
+ content += ` MONGODB_URI: {
40
+ type: 'string',
41
+ default: 'mongodb://localhost:27017/${answers.projectName}'
42
+ }
43
+ `;
44
+ } else if (answers.database === DATABASES.POSTGRESQL || answers.database === DATABASES.SQLITE) {
45
+ content += ` DATABASE_URL: {
46
+ type: 'string',
47
+ default: '${answers.database === DATABASES.POSTGRESQL ? 'postgresql://username:password@localhost:5432/' : 'file:./dev.db'}${answers.projectName}'
48
+ }
49
+ `;
50
+ } else if (answers.database === DATABASES.MYSQL) {
51
+ content += ` DB_HOST: {
52
+ type: 'string',
53
+ default: 'localhost'
54
+ },
55
+ DB_PORT: {
56
+ type: 'string',
57
+ default: '3306'
58
+ },
59
+ DB_NAME: {
60
+ type: 'string',
61
+ default: '${answers.projectName}'
62
+ },
63
+ DB_USER: {
64
+ type: 'string',
65
+ default: 'root'
66
+ },
67
+ DB_PASSWORD: {
68
+ type: 'string',
69
+ default: 'password'
70
+ }
71
+ `;
72
+ }
73
+
74
+ // Add authentication environment variables
75
+ if (answers.authStrategy && answers.authStrategy !== 'none') {
76
+ content += ` JWT_SECRET: {
77
+ type: 'string',
78
+ default: 'your-super-secret-jwt-key'
79
+ },
80
+ JWT_EXPIRES_IN: {
81
+ type: 'string',
82
+ default: '7d'
83
+ }
84
+ `;
85
+ }
86
+
87
+ // Add CORS environment variables
88
+ if (answers.features && answers.features.includes(FEATURES.CORS)) {
89
+ content += ` CORS_ORIGIN: {
90
+ type: 'string',
91
+ default: 'http://localhost:3000'
92
+ }
93
+ `;
94
+ }
95
+
96
+ // Add rate limiting environment variables
97
+ if (hasFeature(answers, 'rate-limit')) {
98
+ content += ` RATE_LIMIT_MAX: {
99
+ type: 'string',
100
+ default: '100'
101
+ },
102
+ RATE_LIMIT_TIME_WINDOW: {
103
+ type: 'string',
104
+ default: '60000'
105
+ }
106
+ `;
107
+ }
108
+
109
+ content += ` }
110
+ };
111
+
112
+ export async function buildApp() {
113
+ const fastify = Fastify({
114
+ logger: {
115
+ level: process.env.LOG_LEVEL || 'info',
116
+ transport: process.env.NODE_ENV === 'development' ? {
117
+ target: 'pino-pretty',
118
+ options: {
119
+ colorize: true
120
+ }
121
+ } : undefined
122
+ }
123
+ });
124
+
125
+ // Register environment plugin
126
+ await fastify.register(env, { schema: envSchema });
127
+
128
+ // Register security plugins
129
+ await fastify.register(helmet);
130
+
131
+ // Register CORS plugin
132
+ if (hasFeature(answers, 'cors')) {
133
+ await fastify.register(cors, {
134
+ origin: fastify.config.CORS_ORIGIN || 'http://localhost:3000',
135
+ credentials: true
136
+ });
137
+ }
138
+
139
+ // Register rate limiting plugin
140
+ if (answers.features.includes('rate-limit')) {
141
+ await fastify.register(rateLimit, {
142
+ max: parseInt(fastify.config.RATE_LIMIT_MAX) || 100,
143
+ timeWindow: parseInt(fastify.config.RATE_LIMIT_TIME_WINDOW) || 60000
144
+ });
145
+ }
146
+
147
+ // Register custom plugins
148
+ await fastify.register(errorHandler);
149
+ await fastify.register(notFound);
150
+
151
+ // Health check endpoint
152
+ fastify.get('/health', async (request, reply) => {
153
+ return {
154
+ status: 'OK',
155
+ timestamp: new Date().toISOString(),
156
+ uptime: process.uptime(),
157
+ environment: fastify.config.NODE_ENV,
158
+ version: '1.0.0'
159
+ };
160
+ });
161
+
162
+ // API routes
163
+ fastify.get('/api', async (request, reply) => {
164
+ return {
165
+ message: 'Welcome to ${answers.projectName} API',
166
+ version: '1.0.0',
167
+ endpoints: {
168
+ health: '/health',
169
+ api: '/api'
170
+ }
171
+ };
172
+ });
173
+
174
+ return fastify;
175
+ }
176
+ `;
177
+
178
+ return content;
179
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Generate Fastify config template
3
+ */
4
+
5
+ export function generateConfig(projectPath, answers) {
6
+ const configContent = `export const config = {
7
+ port: process.env.PORT || 3000,
8
+ host: process.env.HOST || '0.0.0.0',
9
+ nodeEnv: process.env.NODE_ENV || 'development',
10
+ corsOrigin: process.env.CORS_ORIGIN || 'http://localhost:3000',
11
+ database: {
12
+ url: process.env.DATABASE_URL || process.env.MONGODB_URI,
13
+ host: process.env.DB_HOST || 'localhost',
14
+ port: process.env.DB_PORT || 3306,
15
+ name: process.env.DB_NAME || '${answers.projectName}',
16
+ user: process.env.DB_USER || 'root',
17
+ password: process.env.DB_PASSWORD || 'password'
18
+ },
19
+ auth: {
20
+ jwtSecret: process.env.JWT_SECRET || 'your-secret-key',
21
+ jwtExpiresIn: process.env.JWT_EXPIRES_IN || '7d'
22
+ },
23
+ rateLimit: {
24
+ max: parseInt(process.env.RATE_LIMIT_MAX) || 100,
25
+ timeWindow: parseInt(process.env.RATE_LIMIT_TIME_WINDOW) || 60000
26
+ }
27
+ };
28
+
29
+ export default config;
30
+ `;
31
+
32
+ return configContent;
33
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Generate Fastify Docker template
3
+ */
4
+
5
+ export function generateDocker(projectPath, answers) {
6
+ const dockerfile = `# Use Node.js LTS version
7
+ FROM node:18-alpine
8
+
9
+ # Set working directory
10
+ WORKDIR /app
11
+
12
+ # Copy package files
13
+ COPY package*.json ./
14
+
15
+ # Install dependencies
16
+ RUN npm ci --only=production
17
+
18
+ # Copy source code
19
+ COPY . .
20
+
21
+ # Create non-root user
22
+ RUN addgroup -g 1001 -S nodejs
23
+ RUN adduser -S nextjs -u 1001
24
+
25
+ # Change ownership
26
+ RUN chown -R nextjs:nodejs /app
27
+ USER nextjs
28
+
29
+ # Expose port
30
+ EXPOSE 3000
31
+
32
+ # Health check
33
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
34
+ CMD curl -f http://localhost:3000/health || exit 1
35
+
36
+ # Start the application
37
+ CMD ["npm", "start"]
38
+ `;
39
+
40
+ const dockerCompose = `version: '3.8'
41
+
42
+ services:
43
+ app:
44
+ build: .
45
+ ports:
46
+ - "3000:3000"
47
+ environment:
48
+ - NODE_ENV=production
49
+ - PORT=3000
50
+ - HOST=0.0.0.0
51
+ depends_on:
52
+ - db
53
+ restart: unless-stopped
54
+
55
+ db:
56
+ image: ${answers.database === 'mongodb' ? 'mongo:latest' : 'postgres:15-alpine'}
57
+ environment:
58
+ ${answers.database === 'mongodb'
59
+ ? 'MONGO_INITDB_DATABASE=myapp'
60
+ : 'POSTGRES_DB=myapp\n POSTGRES_USER=postgres\n POSTGRES_PASSWORD=password'
61
+ }
62
+ volumes:
63
+ - db_data:/data/db
64
+ ports:
65
+ - "${answers.database === 'mongodb' ? '27017:27017' : '5432:5432'}"
66
+ restart: unless-stopped
67
+
68
+ volumes:
69
+ db_data:
70
+ `;
71
+
72
+ return { dockerfile, dockerCompose };
73
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Generate Fastify 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,57 @@
1
+ /**
2
+ * Generate package.json for Fastify 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 Fastify 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
+ 'test:tap': answers.includeTests ? 'tap test/**/*.test.js' : undefined
21
+ },
22
+ keywords: [
23
+ 'fastify',
24
+ 'nodejs',
25
+ 'api',
26
+ 'backend',
27
+ 'server',
28
+ 'rest',
29
+ 'production-ready',
30
+ 'high-performance'
31
+ ],
32
+ author: 'Generated by build-app-with',
33
+ license: 'MIT',
34
+ engines: {
35
+ node: '>=18.0.0'
36
+ },
37
+ dependencies: {},
38
+ devDependencies: {}
39
+ };
40
+
41
+ // Add database-specific scripts
42
+ if (answers.database === DATABASES.POSTGRESQL || answers.database === DATABASES.SQLITE) {
43
+ basePackage.scripts['db:generate'] = 'prisma generate';
44
+ basePackage.scripts['db:push'] = 'prisma db push';
45
+ basePackage.scripts['db:migrate'] = 'prisma migrate dev';
46
+ basePackage.scripts['db:studio'] = 'prisma studio';
47
+ }
48
+
49
+ // Remove undefined scripts
50
+ Object.keys(basePackage.scripts).forEach(key => {
51
+ if (basePackage.scripts[key] === undefined) {
52
+ delete basePackage.scripts[key];
53
+ }
54
+ });
55
+
56
+ return basePackage;
57
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Generate Fastify plugins template
3
+ */
4
+
5
+ export function generatePlugins(projectPath, answers) {
6
+ const pluginsContent = `import fp from 'fastify-plugin';
7
+
8
+ // Error handler plugin
9
+ export default fp(async function (fastify, opts) {
10
+ fastify.setErrorHandler(async (error, request, reply) => {
11
+ fastify.log.error(error);
12
+
13
+ const statusCode = error.statusCode || 500;
14
+ const message = error.message || 'Internal Server Error';
15
+
16
+ reply.status(statusCode).send({
17
+ error: true,
18
+ message,
19
+ statusCode,
20
+ ...(process.env.NODE_ENV === 'development' && { stack: error.stack })
21
+ });
22
+ });
23
+
24
+ // Not found handler
25
+ fastify.setNotFoundHandler(async (request, reply) => {
26
+ reply.status(404).send({
27
+ error: true,
28
+ message: \`Route \${request.method}:\${request.url} not found\`,
29
+ statusCode: 404
30
+ });
31
+ });
32
+ }, {
33
+ name: 'error-handler'
34
+ });
35
+ `;
36
+
37
+ return pluginsContent;
38
+ }