@abdul53245/create-dev-stack 1.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.
package/bin/index.js ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import('../dist/cli.js').catch((error) => {
3
+ const message = error instanceof Error ? error.message : String(error);
4
+ console.error(message);
5
+ process.exit(1);
6
+ });
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,107 @@
1
+ import { intro, outro, select, multiselect, text, spinner, isCancel, cancel } from '@clack/prompts';
2
+ import chalk from 'chalk';
3
+ import { generateFullStack } from './generator/index.js';
4
+ async function run() {
5
+ intro(chalk.bold.cyan('Welcome to the Create Dev Stack!'));
6
+ const projectName = await text({
7
+ message: 'What is the name of your project?',
8
+ placeholder: 'my-project',
9
+ defaultValue: 'my-dev-stack',
10
+ });
11
+ if (isCancel(projectName)) {
12
+ cancel('Operation cancelled.');
13
+ process.exit(0);
14
+ }
15
+ const frontEnd = await select({
16
+ message: 'Select a frontend framework:',
17
+ options: [
18
+ { value: 'nextjs', label: 'Next.js (App Router)', hint: 'React framework with SSR/SSG' },
19
+ { value: 'react', label: 'React (Vite)', hint: 'Single Page Application' },
20
+ { value: 'vue', label: 'Vue 3 (Vite)', hint: 'Progressive JavaScript Framework' },
21
+ { value: 'angular', label: 'Angular', hint: 'Full-featured enterprise platform' },
22
+ { value: 'none', label: 'None / API Only', hint: 'Backend/Microservice setup' },
23
+ ]
24
+ });
25
+ if (isCancel(frontEnd))
26
+ return handleCancel();
27
+ const backEnd = await select({
28
+ message: 'Select a backend framework:',
29
+ options: [
30
+ { value: 'nestjs', label: 'NestJS', hint: 'TypeScript framework with modular architecture' },
31
+ { value: 'express', label: 'Express.js', hint: 'Minimalist Node.js framework' },
32
+ { value: 'fastify', label: 'Fastify', hint: 'High-performance Node.js framework' },
33
+ { value: 'none', label: 'None / Jamstack', hint: 'Frontend only or Next.js API routes' },
34
+ ]
35
+ });
36
+ if (isCancel(backEnd))
37
+ return handleCancel();
38
+ const database = await select({
39
+ message: 'Select a database:',
40
+ options: [
41
+ { value: 'postgres', label: 'PostgreSQL', hint: 'Relational - Port 5432' },
42
+ { value: 'mysql', label: 'MySQL', hint: 'Relational - Port 3306' },
43
+ { value: 'mongodb', label: 'MongoDB', hint: 'Document - Port 27017' },
44
+ { value: 'none', label: 'None', hint: 'No persistent database needed' },
45
+ ]
46
+ });
47
+ if (isCancel(database))
48
+ return handleCancel();
49
+ let orm = 'none';
50
+ if (database !== 'none' && database !== 'mongodb') {
51
+ orm = await select({
52
+ message: 'Select an ORM (Object-Relational Mapping) tool:',
53
+ options: [
54
+ { value: 'prisma', label: 'Prisma', hint: 'Type-safe ORM with schema management' },
55
+ { value: 'drizzle', label: 'Drizzle ORM', hint: 'Lightweight SQL-like ORM' },
56
+ { value: 'typeorm', label: 'TypeORM', hint: 'Active Record / Data Mapper pattern' },
57
+ { value: 'none', label: 'Raw Drivers / None' },
58
+ ]
59
+ });
60
+ if (isCancel(orm))
61
+ return handleCancel();
62
+ }
63
+ const extras = await multiselect({
64
+ message: 'Select additional infrastructure services:',
65
+ options: [
66
+ { value: 'redis', label: 'Redis', hint: 'In-memory cache & pub/sub - Port 6379' },
67
+ { value: 'nginx', label: 'Nginx Reverse Proxy', hint: 'Routes frontend & backend traffic' },
68
+ { value: 'mailpit', label: 'Mailpit', hint: 'Local SMTP email testing interface' },
69
+ ],
70
+ required: false,
71
+ });
72
+ if (isCancel(extras))
73
+ return handleCancel();
74
+ const dockerStrategy = await select({
75
+ message: 'How would you like Docker configured?',
76
+ options: [
77
+ { value: 'full', label: 'Full Stack Docker', hint: 'Containers for Frontend, Backend, Database, and Cache' },
78
+ { value: 'infra-only', label: 'Infra Only (Recommended for Dev)', hint: 'Containers for DB/Redis; run apps locally with hot-reload' },
79
+ { value: 'none', label: 'No Docker', hint: 'Generate local code templates and config files only' },
80
+ ],
81
+ });
82
+ if (isCancel(dockerStrategy))
83
+ return handleCancel();
84
+ const projectConfig = {
85
+ projectName: projectName,
86
+ frontend: frontEnd !== 'none' ? frontEnd : undefined,
87
+ backend: backEnd !== 'none' ? backEnd : undefined,
88
+ database: database !== 'none' ? database : undefined,
89
+ orm: orm !== 'none' ? orm : undefined,
90
+ extras: extras,
91
+ dockerStrategy: dockerStrategy !== 'none' ? dockerStrategy : 'none',
92
+ };
93
+ const s = spinner();
94
+ s.start('Generating project structure...');
95
+ await generateFullStack(projectConfig);
96
+ s.stop('Project structure generated successfully!');
97
+ outro(chalk.green(`🎉 Success! Your stack is ready.\n\nNext steps:\n\n cd ${projectName}\n npm run api:dev\n npm run web:dev\n\nOr start both together:\n npm run dev\n\nIf you enabled Docker, you can also run:\n npm run docker:up\n`));
98
+ }
99
+ function handleCancel() {
100
+ cancel('Setup cancelled.');
101
+ process.exit(0);
102
+ }
103
+ run().catch((error) => {
104
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
105
+ process.exit(1);
106
+ });
107
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { StackConfig } from '../types.js';
2
+ export declare function generateBackend(config: StackConfig, appsDir: string): Promise<void>;
3
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/generator/backend.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,iBAmBzE"}
@@ -0,0 +1,211 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateBackend(config, appsDir) {
4
+ if (!config.backend || config.backend === 'none') {
5
+ return;
6
+ }
7
+ const targetDir = path.join(appsDir, 'api');
8
+ await fs.ensureDir(targetDir);
9
+ switch (config.backend) {
10
+ case 'nestjs':
11
+ await writeNestApp(targetDir);
12
+ break;
13
+ case 'fastify':
14
+ await writeFastifyApp(targetDir);
15
+ break;
16
+ case 'express':
17
+ await writeExpressApp(targetDir);
18
+ break;
19
+ }
20
+ }
21
+ async function writeExpressApp(targetDir) {
22
+ const packageJson = {
23
+ name: '@app/api',
24
+ version: '1.0.0',
25
+ private: true,
26
+ type: 'module',
27
+ scripts: {
28
+ dev: 'tsx watch src/index.ts',
29
+ build: 'tsc',
30
+ start: 'node dist/index.js',
31
+ },
32
+ dependencies: {
33
+ cors: '^2.8.5',
34
+ dotenv: '^16.4.1',
35
+ express: '^4.18.2',
36
+ },
37
+ devDependencies: {
38
+ '@types/cors': '^2.8.13',
39
+ '@types/express': '^4.17.17',
40
+ '@types/node': '^22.10.1',
41
+ tsx: '^4.19.2',
42
+ typescript: '^5.6.3',
43
+ },
44
+ };
45
+ const tsconfig = {
46
+ compilerOptions: {
47
+ target: 'ES2022',
48
+ module: 'NodeNext',
49
+ moduleResolution: 'NodeNext',
50
+ outDir: 'dist',
51
+ rootDir: 'src',
52
+ strict: true,
53
+ esModuleInterop: true,
54
+ resolveJsonModule: true,
55
+ skipLibCheck: true,
56
+ },
57
+ include: ['src/**/*.ts'],
58
+ };
59
+ const indexTs = `import cors from 'cors';
60
+ import express from 'express';
61
+ import dotenv from 'dotenv';
62
+
63
+ dotenv.config();
64
+
65
+ const app = express();
66
+ app.disable('x-powered-by');
67
+ app.use(cors({ origin: process.env.FRONTEND_URL ?? 'http://localhost:3000' }));
68
+ app.use(express.json());
69
+
70
+ app.get('/health', (_req, res) => {
71
+ res.status(200).json({ status: 'ok', service: 'api' });
72
+ });
73
+
74
+ app.get('/', (_req, res) => {
75
+ res.status(200).json({ message: 'API ready', service: 'api' });
76
+ });
77
+
78
+ const port = Number(process.env.PORT ?? '4000');
79
+ app.listen(port, '0.0.0.0', () => {
80
+ console.log(\`API listening on http://localhost:\${port}\`);
81
+ });
82
+ `;
83
+ await fs.writeFile(path.join(targetDir, 'package.json'), JSON.stringify(packageJson, null, 2) + '\n');
84
+ await fs.writeFile(path.join(targetDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2) + '\n');
85
+ await fs.ensureDir(path.join(targetDir, 'src'));
86
+ await fs.writeFile(path.join(targetDir, 'src', 'index.ts'), indexTs);
87
+ }
88
+ async function writeFastifyApp(targetDir) {
89
+ const packageJson = {
90
+ name: '@app/api',
91
+ version: '1.0.0',
92
+ private: true,
93
+ type: 'module',
94
+ scripts: {
95
+ dev: 'tsx watch src/index.ts',
96
+ build: 'tsc',
97
+ start: 'node dist/index.js',
98
+ },
99
+ dependencies: {
100
+ dotenv: '^16.4.1',
101
+ fastify: '^5.0.0',
102
+ },
103
+ devDependencies: {
104
+ '@types/node': '^22.10.1',
105
+ tsx: '^4.19.2',
106
+ typescript: '^5.6.3',
107
+ },
108
+ };
109
+ const tsconfig = {
110
+ compilerOptions: {
111
+ target: 'ES2022',
112
+ module: 'NodeNext',
113
+ moduleResolution: 'NodeNext',
114
+ outDir: 'dist',
115
+ rootDir: 'src',
116
+ strict: true,
117
+ esModuleInterop: true,
118
+ skipLibCheck: true,
119
+ },
120
+ include: ['src/**/*.ts'],
121
+ };
122
+ const indexTs = `import dotenv from 'dotenv';
123
+ import Fastify from 'fastify';
124
+
125
+ dotenv.config();
126
+
127
+ const app = Fastify({ logger: false });
128
+
129
+ app.get('/health', async () => ({ status: 'ok', service: 'api' }));
130
+ app.get('/', async () => ({ message: 'API ready', service: 'api' }));
131
+
132
+ const port = Number(process.env.PORT ?? '4000');
133
+ await app.listen({ port, host: '0.0.0.0' });
134
+ console.log(\`API listening on http://localhost:\${port}\`);
135
+ `;
136
+ await fs.writeFile(path.join(targetDir, 'package.json'), JSON.stringify(packageJson, null, 2) + '\n');
137
+ await fs.writeFile(path.join(targetDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2) + '\n');
138
+ await fs.ensureDir(path.join(targetDir, 'src'));
139
+ await fs.writeFile(path.join(targetDir, 'src', 'index.ts'), indexTs);
140
+ }
141
+ async function writeNestApp(targetDir) {
142
+ const packageJson = {
143
+ name: '@app/api',
144
+ version: '1.0.0',
145
+ private: true,
146
+ scripts: {
147
+ dev: 'nest start --watch',
148
+ build: 'nest build',
149
+ start: 'node dist/main.js',
150
+ },
151
+ dependencies: {
152
+ '@nestjs/common': '^10.4.5',
153
+ '@nestjs/core': '^10.4.5',
154
+ '@nestjs/platform-express': '^10.4.5',
155
+ 'class-transformer': '^0.5.1',
156
+ 'class-validator': '^0.15.1',
157
+ dotenv: '^16.4.1',
158
+ 'reflect-metadata': '^0.2.1',
159
+ rxjs: '^7.8.0',
160
+ },
161
+ devDependencies: {
162
+ '@nestjs/cli': '^10.4.5',
163
+ '@types/node': '^22.10.1',
164
+ 'ts-node': '^10.9.2',
165
+ typescript: '^5.6.3',
166
+ },
167
+ };
168
+ const tsconfig = {
169
+ compilerOptions: {
170
+ target: 'ES2022',
171
+ module: 'NodeNext',
172
+ moduleResolution: 'NodeNext',
173
+ outDir: 'dist',
174
+ rootDir: 'src',
175
+ strict: true,
176
+ experimentalDecorators: true,
177
+ emitDecoratorMetadata: true,
178
+ esModuleInterop: true,
179
+ skipLibCheck: true,
180
+ },
181
+ include: ['src/**/*.ts'],
182
+ };
183
+ const mainTs = `import 'reflect-metadata';
184
+ import dotenv from 'dotenv';
185
+ import { NestFactory } from '@nestjs/core';
186
+ import { AppModule } from './app.module.js';
187
+
188
+ dotenv.config();
189
+
190
+ async function bootstrap() {
191
+ const app = await NestFactory.create(AppModule);
192
+ app.enableCors({ origin: true });
193
+ const port = Number(process.env.PORT ?? '4000');
194
+ await app.listen(port, '0.0.0.0');
195
+ }
196
+
197
+ bootstrap();
198
+ `;
199
+ const appModule = `import { Module } from '@nestjs/common';
200
+
201
+ @Module({})
202
+ export class AppModule {}
203
+ `;
204
+ await fs.writeFile(path.join(targetDir, 'package.json'), JSON.stringify(packageJson, null, 2) + '\n');
205
+ await fs.writeFile(path.join(targetDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2) + '\n');
206
+ await fs.writeFile(path.join(targetDir, 'nest-cli.json'), JSON.stringify({ collection: '@nestjs/schematics', sourceRoot: 'src' }, null, 2) + '\n');
207
+ await fs.ensureDir(path.join(targetDir, 'src'));
208
+ await fs.writeFile(path.join(targetDir, 'src', 'main.ts'), mainTs);
209
+ await fs.writeFile(path.join(targetDir, 'src', 'app.module.ts'), appModule);
210
+ }
211
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/generator/backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { StackConfig } from '../types.js';
2
+ export declare function generateDockerConfig(config: StackConfig, rootDir: string): Promise<void>;
3
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/generator/docker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,iBAiB9E"}
@@ -0,0 +1,199 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateDockerConfig(config, rootDir) {
4
+ if (config.dockerStrategy === 'none') {
5
+ return;
6
+ }
7
+ const composeDir = path.join(rootDir, 'infra', 'docker');
8
+ await fs.ensureDir(composeDir);
9
+ await buildComposeFile(config, composeDir);
10
+ if (config.dockerStrategy === 'full') {
11
+ if (config.frontend && config.frontend !== 'none') {
12
+ await generateFrontendDockerfile(config, path.join(rootDir, 'apps', 'web'));
13
+ }
14
+ if (config.backend && config.backend !== 'none') {
15
+ await generateBackendDockerfile(config, path.join(rootDir, 'apps', 'api'));
16
+ }
17
+ }
18
+ }
19
+ async function buildComposeFile(config, composeDir) {
20
+ const services = {};
21
+ const volumes = {};
22
+ const dbService = config.database === 'postgres' ? 'postgres' : config.database === 'mysql' ? 'mysql' : config.database === 'mongodb' ? 'mongodb' : undefined;
23
+ if (config.database === 'postgres') {
24
+ services.postgres = {
25
+ image: 'postgres:16-alpine',
26
+ container_name: `${config.projectName}-postgres`,
27
+ restart: 'unless-stopped',
28
+ environment: {
29
+ POSTGRES_USER: 'devuser',
30
+ POSTGRES_PASSWORD: 'devpassword',
31
+ POSTGRES_DB: 'devdb',
32
+ },
33
+ ports: ['5432:5432'],
34
+ volumes: ['postgres_data:/var/lib/postgresql/data'],
35
+ healthcheck: {
36
+ test: ['CMD-SHELL', 'pg_isready -U devuser -d devdb'],
37
+ interval: '10s',
38
+ timeout: '5s',
39
+ retries: 5,
40
+ },
41
+ };
42
+ volumes.postgres_data = {};
43
+ }
44
+ else if (config.database === 'mysql') {
45
+ services.mysql = {
46
+ image: 'mysql:8.0',
47
+ container_name: `${config.projectName}-mysql`,
48
+ restart: 'unless-stopped',
49
+ environment: {
50
+ MYSQL_ROOT_PASSWORD: 'root',
51
+ MYSQL_DATABASE: 'devdb',
52
+ },
53
+ ports: ['3306:3306'],
54
+ volumes: ['mysql_data:/var/lib/mysql'],
55
+ };
56
+ volumes.mysql_data = {};
57
+ }
58
+ else if (config.database === 'mongodb') {
59
+ services.mongodb = {
60
+ image: 'mongo:7',
61
+ container_name: `${config.projectName}-mongodb`,
62
+ restart: 'unless-stopped',
63
+ ports: ['27017:27017'],
64
+ volumes: ['mongo_data:/data/db'],
65
+ };
66
+ volumes.mongo_data = {};
67
+ }
68
+ if (config.extras.includes('redis')) {
69
+ services.redis = {
70
+ image: 'redis:7-alpine',
71
+ container_name: `${config.projectName}-redis`,
72
+ restart: 'unless-stopped',
73
+ ports: ['6379:6379'],
74
+ };
75
+ }
76
+ if (config.extras.includes('mailpit')) {
77
+ services.mailpit = {
78
+ image: 'axllent/mailpit',
79
+ container_name: `${config.projectName}-mailpit`,
80
+ restart: 'unless-stopped',
81
+ ports: ['8025:8025', '1025:1025'],
82
+ };
83
+ }
84
+ if (config.dockerStrategy === 'full') {
85
+ if (config.backend && config.backend !== 'none') {
86
+ services.api = {
87
+ build: { context: '../../apps/api', dockerfile: 'Dockerfile' },
88
+ container_name: `${config.projectName}-api`,
89
+ restart: 'unless-stopped',
90
+ ports: ['4000:4000'],
91
+ env_file: ['../../.env'],
92
+ environment: {
93
+ PORT: '4000',
94
+ NODE_ENV: 'production',
95
+ DATABASE_URL: buildDatabaseUrl(config),
96
+ DB_HOST: dbService ?? 'localhost',
97
+ FRONTEND_URL: 'http://localhost:3000',
98
+ },
99
+ depends_on: dbService ? { [dbService]: { condition: 'service_started' } } : {},
100
+ };
101
+ }
102
+ if (config.frontend && config.frontend !== 'none') {
103
+ services.web = {
104
+ build: { context: '../../apps/web', dockerfile: 'Dockerfile' },
105
+ container_name: `${config.projectName}-web`,
106
+ restart: 'unless-stopped',
107
+ ports: ['3000:3000'],
108
+ env_file: ['../../.env'],
109
+ environment: {
110
+ NODE_ENV: 'production',
111
+ NEXT_PUBLIC_API_URL: 'http://api:4000',
112
+ VITE_API_URL: 'http://api:4000',
113
+ },
114
+ depends_on: config.backend && config.backend !== 'none' ? { api: { condition: 'service_started' } } : {},
115
+ };
116
+ }
117
+ }
118
+ const compose = {
119
+ name: config.projectName,
120
+ services,
121
+ volumes: Object.keys(volumes).length > 0 ? volumes : undefined,
122
+ };
123
+ await fs.writeFile(path.join(composeDir, 'docker-compose.yml'), JSON.stringify(compose, null, 2) + '\n');
124
+ await fs.writeFile(path.join(composeDir, 'nginx.conf'), ['server {', ' listen 3000;', ' location / {', ' root /usr/share/nginx/html;', ' index index.html;', ' try_files $uri $uri/ /index.html;', ' }', '}', ''].join('\n'));
125
+ }
126
+ function buildDatabaseUrl(config) {
127
+ if (config.database === 'postgres') {
128
+ return 'postgresql://devuser:devpassword@postgres:5432/devdb';
129
+ }
130
+ if (config.database === 'mysql') {
131
+ return 'mysql://root:root@mysql:3306/devdb';
132
+ }
133
+ if (config.database === 'mongodb') {
134
+ return 'mongodb://mongodb:27017/devdb';
135
+ }
136
+ return 'postgresql://devuser:devpassword@postgres:5432/devdb';
137
+ }
138
+ async function generateFrontendDockerfile(config, targetDir) {
139
+ let dockerfile = '';
140
+ if (config.frontend === 'nextjs') {
141
+ dockerfile = `FROM node:20-alpine AS builder
142
+ WORKDIR /app
143
+ COPY package.json package-lock.json* ./
144
+ RUN npm install
145
+ COPY . .
146
+ RUN npm run build
147
+
148
+ FROM node:20-alpine AS runner
149
+ WORKDIR /app
150
+ ENV NODE_ENV=production
151
+ COPY --from=builder /app/package.json ./package.json
152
+ COPY --from=builder /app/.next ./.next
153
+ COPY --from=builder /app/public ./public
154
+ COPY --from=builder /app/node_modules ./node_modules
155
+ EXPOSE 3000
156
+ CMD ["npm", "run", "start"]
157
+ `;
158
+ }
159
+ else {
160
+ const buildFolder = config.frontend === 'angular' ? 'dist/web' : 'dist';
161
+ dockerfile = `FROM node:20-alpine AS builder
162
+ WORKDIR /app
163
+ COPY package.json package-lock.json* ./
164
+ RUN npm install
165
+ COPY . .
166
+ RUN npm run build
167
+
168
+ FROM nginx:alpine AS runner
169
+ COPY --from=builder /app/${buildFolder} /usr/share/nginx/html
170
+ COPY ../../infra/docker/nginx.conf /etc/nginx/conf.d/default.conf
171
+ EXPOSE 3000
172
+ CMD ["nginx", "-g", "daemon off;"]
173
+ `;
174
+ }
175
+ await fs.writeFile(path.join(targetDir, 'Dockerfile'), dockerfile.trim() + '\n');
176
+ await fs.writeFile(path.join(targetDir, '.dockerignore'), ['node_modules', 'npm-debug.log', '.git', '.env', '.env.local', 'dist', 'build', '.next'].join('\n') + '\n');
177
+ }
178
+ async function generateBackendDockerfile(config, targetDir) {
179
+ const runCommand = config.backend === 'nestjs' ? 'dist/main.js' : 'dist/index.js';
180
+ const dockerfile = `FROM node:20-alpine AS builder
181
+ WORKDIR /app
182
+ COPY package.json package-lock.json* ./
183
+ RUN npm install
184
+ COPY . .
185
+ RUN npm run build
186
+
187
+ FROM node:20-alpine AS runner
188
+ WORKDIR /app
189
+ ENV NODE_ENV=production
190
+ COPY --from=builder /app/package.json ./package.json
191
+ COPY --from=builder /app/node_modules ./node_modules
192
+ COPY --from=builder /app/dist ./dist
193
+ EXPOSE 4000
194
+ CMD ["node", "${runCommand}"]
195
+ `;
196
+ await fs.writeFile(path.join(targetDir, 'Dockerfile'), dockerfile.trim() + '\n');
197
+ await fs.writeFile(path.join(targetDir, '.dockerignore'), ['node_modules', 'npm-debug.log', '.git', '.env', '.env.local', 'dist', 'build', '.next'].join('\n') + '\n');
198
+ }
199
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/generator/docker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { StackConfig } from '../types.js';
2
+ export declare function generateEnvFile(config: StackConfig, targetDir: string): Promise<void>;
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/generator/env.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAsD3E"}
@@ -0,0 +1,49 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateEnvFile(config, targetDir) {
4
+ const envVars = [];
5
+ envVars.push('NODE_ENV=development');
6
+ if (config.frontend && config.frontend !== 'none') {
7
+ envVars.push('FRONTEND_URL=http://localhost:3000');
8
+ envVars.push('NEXT_PUBLIC_API_URL=http://localhost:4000');
9
+ envVars.push('VITE_API_URL=http://localhost:4000');
10
+ }
11
+ if (config.backend && config.backend !== 'none') {
12
+ envVars.push('PORT=4000');
13
+ envVars.push('API_URL=http://localhost:4000');
14
+ }
15
+ if (config.database && config.database !== 'none') {
16
+ envVars.push('DB_HOST=localhost');
17
+ switch (config.database) {
18
+ case 'postgres':
19
+ envVars.push('POSTGRES_USER=devuser');
20
+ envVars.push('POSTGRES_PASSWORD=devpassword');
21
+ envVars.push('POSTGRES_DB=devdb');
22
+ envVars.push('DATABASE_URL=postgresql://devuser:devpassword@localhost:5432/devdb');
23
+ break;
24
+ case 'mysql':
25
+ envVars.push('MYSQL_ROOT_PASSWORD=root');
26
+ envVars.push('MYSQL_DATABASE=devdb');
27
+ envVars.push('DATABASE_URL=mysql://root:root@localhost:3306/devdb');
28
+ break;
29
+ case 'mongodb':
30
+ envVars.push('DATABASE_URL=mongodb://localhost:27017/devdb');
31
+ break;
32
+ }
33
+ }
34
+ if (config.extras.includes('redis')) {
35
+ envVars.push('REDIS_URL=redis://localhost:6379');
36
+ }
37
+ if (config.extras.includes('mailpit')) {
38
+ envVars.push('SMTP_HOST=localhost');
39
+ envVars.push('SMTP_PORT=1025');
40
+ }
41
+ const envContent = envVars.join('\n') + '\n';
42
+ await fs.writeFile(path.join(targetDir, '.env'), envContent);
43
+ await fs.writeFile(path.join(targetDir, '.env.example'), envContent);
44
+ const gitignorePath = path.join(targetDir, '.gitignore');
45
+ if (!(await fs.pathExists(gitignorePath))) {
46
+ await fs.writeFile(gitignorePath, 'node_modules\n.env\n.env.local\ndist\nbuild\n.next\n.DS_Store\n');
47
+ }
48
+ }
49
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/generator/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAmB,EAAE,SAAiB;IAC1E,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAErC,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAElC,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;YACxB,KAAK,UAAU;gBACb,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;gBACtC,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;gBAC9C,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBAClC,OAAO,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;gBACnF,MAAM;YACR,KAAK,OAAO;gBACV,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;gBACrC,OAAO,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;gBACpE,MAAM;YACR,KAAK,SAAS;gBACZ,OAAO,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;gBAC7D,MAAM;QACV,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,UAAU,CAAC,CAAC;IAErE,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACzD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC1C,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,iEAAiE,CAAC,CAAC;IACvG,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { StackConfig } from '../types.js';
2
+ export declare function generateFrontend(config: StackConfig, appsDir: string): Promise<void>;
3
+ //# sourceMappingURL=frontend.d.ts.map