initkit 1.1.0 → 1.2.1
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/README.md +109 -117
- package/package.json +2 -5
- package/src/cli.js +77 -34
- package/src/commands/create.js +173 -84
- package/src/prompts/questions.js +95 -39
- package/src/utils/addonInstaller.js +402 -0
- package/src/utils/cliRunner.js +146 -0
- package/src/utils/frameworkBootstrap.js +304 -0
- package/src/utils/templateGenerator.js +191 -171
- package/src/templates/express.js +0 -915
- package/src/templates/fullstack.js +0 -1236
- package/src/templates/nextjs.js +0 -620
- package/src/templates/react.js +0 -586
- package/src/templates/vue.js +0 -545
|
@@ -1,1236 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import ora from 'ora';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import { getLatestVersion } from '../utils/versionFetcher.js';
|
|
6
|
-
import { generateNextjsTemplate } from './nextjs.js';
|
|
7
|
-
import { generateReactTemplate } from './react.js';
|
|
8
|
-
import { generateExpressTemplate } from './express.js';
|
|
9
|
-
|
|
10
|
-
async function fetchVersion(packageName, fallback = 'latest') {
|
|
11
|
-
try {
|
|
12
|
-
const version = await getLatestVersion(packageName);
|
|
13
|
-
return `^${version}`;
|
|
14
|
-
} catch {
|
|
15
|
-
return fallback;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Generate Full-Stack project with integrated frontend and backend
|
|
21
|
-
*
|
|
22
|
-
* Creates a complete full-stack application supporting:
|
|
23
|
-
* - **Monorepo Structure**: Turborepo with apps/ and packages/ workspaces
|
|
24
|
-
* - **Traditional Structure**: Separate client/ and server/ directories
|
|
25
|
-
* - **Popular Stacks**: MERN, PERN, T3 Stack, Next.js + Express, etc.
|
|
26
|
-
* - **Shared Packages**: Common types, UI components, utilities
|
|
27
|
-
* - **API Integration**: Pre-configured frontend-backend communication
|
|
28
|
-
* - **Database Setup**: Models, migrations, seeders
|
|
29
|
-
* - **Docker Compose**: Complete orchestration for all services
|
|
30
|
-
*
|
|
31
|
-
* Generated project includes:
|
|
32
|
-
* - Frontend application (React, Next.js, Vue, etc.)
|
|
33
|
-
* - Backend API (Express, NestJS, etc.)
|
|
34
|
-
* - Shared TypeScript types package
|
|
35
|
-
* - UI components library (optional)
|
|
36
|
-
* - Root configuration (Turborepo, Docker Compose, etc.)
|
|
37
|
-
* - Environment configuration for all services
|
|
38
|
-
* - Comprehensive README with setup instructions
|
|
39
|
-
*
|
|
40
|
-
* @param {string} projectPath - Absolute path to the project directory
|
|
41
|
-
* @param {Object} config - User configuration object
|
|
42
|
-
* @param {string} config.projectName - Name of the project
|
|
43
|
-
* @param {string} config.language - Programming language ('typescript'|'javascript')
|
|
44
|
-
* @param {string} config.fullstackType - Project structure type
|
|
45
|
-
* - 'monorepo': Turborepo with workspaces (recommended for large projects)
|
|
46
|
-
* - 'traditional': Separate client/ and server/ folders
|
|
47
|
-
* @param {string} config.stack - Technology stack selection
|
|
48
|
-
* - 'MERN': MongoDB + Express + React + Node.js
|
|
49
|
-
* - 'PERN': PostgreSQL + Express + React + Node.js
|
|
50
|
-
* - 'T3': Next.js + tRPC + Prisma + NextAuth
|
|
51
|
-
* - 'Next.js + Express': Next.js frontend with Express backend
|
|
52
|
-
* - 'Vue + Express': Vue.js frontend with Express backend
|
|
53
|
-
* @param {string} [config.frontend] - Frontend framework (derived from stack)
|
|
54
|
-
* @param {string} [config.backend] - Backend framework (derived from stack)
|
|
55
|
-
* @param {string} [config.database] - Database choice (derived from stack)
|
|
56
|
-
* @param {string} config.packageManager - Package manager to use
|
|
57
|
-
*
|
|
58
|
-
* @returns {Promise<void>}
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* // Create MERN stack monorepo with Turborepo
|
|
62
|
-
* await generateFullStackTemplate('/path/to/project', {
|
|
63
|
-
* projectName: 'my-fullstack-app',
|
|
64
|
-
* language: 'typescript',
|
|
65
|
-
* fullstackType: 'monorepo',
|
|
66
|
-
* stack: 'MERN',
|
|
67
|
-
* packageManager: 'pnpm'
|
|
68
|
-
* });
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* // Create T3 Stack (Next.js + tRPC + Prisma)
|
|
72
|
-
* await generateFullStackTemplate('/path/to/project', {
|
|
73
|
-
* projectName: 'my-t3-app',
|
|
74
|
-
* language: 'typescript',
|
|
75
|
-
* fullstackType: 'monorepo',
|
|
76
|
-
* stack: 'T3',
|
|
77
|
-
* packageManager: 'pnpm'
|
|
78
|
-
* });
|
|
79
|
-
*/
|
|
80
|
-
export async function generateFullStackTemplate(projectPath, config) {
|
|
81
|
-
const { fullstackType, stack } = config;
|
|
82
|
-
|
|
83
|
-
if (fullstackType === 'monorepo') {
|
|
84
|
-
await generateMonorepoStructure(projectPath, config);
|
|
85
|
-
} else {
|
|
86
|
-
await generateTraditionalFullStack(projectPath, config);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Generate Monorepo Structure with Turborepo
|
|
92
|
-
*/
|
|
93
|
-
async function generateMonorepoStructure(projectPath, config) {
|
|
94
|
-
const { stack } = config;
|
|
95
|
-
|
|
96
|
-
// Create monorepo folder structure
|
|
97
|
-
await fs.ensureDir(path.join(projectPath, 'apps', 'frontend'));
|
|
98
|
-
await fs.ensureDir(path.join(projectPath, 'apps', 'backend'));
|
|
99
|
-
await fs.ensureDir(path.join(projectPath, 'packages', 'shared-types'));
|
|
100
|
-
await fs.ensureDir(path.join(projectPath, 'packages', 'ui-components'));
|
|
101
|
-
|
|
102
|
-
// Generate root package.json with workspaces
|
|
103
|
-
await fs.writeFile(
|
|
104
|
-
path.join(projectPath, 'package.json'),
|
|
105
|
-
await generateMonorepoPackageJson(config)
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
// Generate turbo.json
|
|
109
|
-
await fs.writeFile(path.join(projectPath, 'turbo.json'), generateTurboConfig());
|
|
110
|
-
|
|
111
|
-
// Generate frontend in apps/frontend
|
|
112
|
-
const frontendPath = path.join(projectPath, 'apps', 'frontend');
|
|
113
|
-
const frontendConfig = {
|
|
114
|
-
...config,
|
|
115
|
-
projectName: 'frontend',
|
|
116
|
-
frontend: stack.includes('Next.js') ? 'nextjs' : 'react',
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
if (stack.includes('Next.js')) {
|
|
120
|
-
await generateNextjsTemplate(frontendPath, frontendConfig);
|
|
121
|
-
} else {
|
|
122
|
-
await generateReactTemplate(frontendPath, frontendConfig);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Generate backend in apps/backend
|
|
126
|
-
const backendPath = path.join(projectPath, 'apps', 'backend');
|
|
127
|
-
const backendConfig = {
|
|
128
|
-
...config,
|
|
129
|
-
projectName: 'backend',
|
|
130
|
-
backend: 'express',
|
|
131
|
-
database: stack.includes('MongoDB')
|
|
132
|
-
? 'mongodb'
|
|
133
|
-
: stack.includes('PostgreSQL')
|
|
134
|
-
? 'prisma'
|
|
135
|
-
: 'none',
|
|
136
|
-
};
|
|
137
|
-
await generateExpressTemplate(backendPath, backendConfig);
|
|
138
|
-
|
|
139
|
-
// Generate shared packages
|
|
140
|
-
await generateSharedTypes(path.join(projectPath, 'packages', 'shared-types'));
|
|
141
|
-
await generateUIComponents(path.join(projectPath, 'packages', 'ui-components'), config);
|
|
142
|
-
|
|
143
|
-
// Generate root-level configs
|
|
144
|
-
await generateMonorepoRootFiles(projectPath, config);
|
|
145
|
-
|
|
146
|
-
// Generate Docker setup for monorepo
|
|
147
|
-
await generateMonorepoDockerSetup(projectPath, config);
|
|
148
|
-
|
|
149
|
-
// Generate README
|
|
150
|
-
await generateMonorepoReadme(projectPath, config);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Generate Traditional Full-Stack Structure
|
|
155
|
-
*/
|
|
156
|
-
async function generateTraditionalFullStack(projectPath, config) {
|
|
157
|
-
const { stack } = config;
|
|
158
|
-
|
|
159
|
-
if (stack === 'MERN') {
|
|
160
|
-
await generateMERNStack(projectPath, config);
|
|
161
|
-
} else if (stack === 'PERN') {
|
|
162
|
-
await generatePERNStack(projectPath, config);
|
|
163
|
-
} else if (stack === 'Next.js + Express') {
|
|
164
|
-
await generateNextExpressStack(projectPath, config);
|
|
165
|
-
} else if (stack === 'Laravel + React') {
|
|
166
|
-
await generateLaravelReactStack(projectPath, config);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* MERN Stack (MongoDB, Express, React, Node)
|
|
172
|
-
*/
|
|
173
|
-
async function generateMERNStack(projectPath, config) {
|
|
174
|
-
// Create folder structure
|
|
175
|
-
await fs.ensureDir(path.join(projectPath, 'client'));
|
|
176
|
-
await fs.ensureDir(path.join(projectPath, 'server'));
|
|
177
|
-
|
|
178
|
-
// Generate React frontend in client/
|
|
179
|
-
const clientConfig = {
|
|
180
|
-
...config,
|
|
181
|
-
projectName: 'client',
|
|
182
|
-
frontend: 'react',
|
|
183
|
-
additionalLibraries: ['react-router', 'axios'],
|
|
184
|
-
};
|
|
185
|
-
await generateReactTemplate(path.join(projectPath, 'client'), clientConfig);
|
|
186
|
-
|
|
187
|
-
// Generate Express backend in server/
|
|
188
|
-
const serverConfig = {
|
|
189
|
-
...config,
|
|
190
|
-
projectName: 'server',
|
|
191
|
-
backend: 'express',
|
|
192
|
-
database: 'mongodb',
|
|
193
|
-
folderStructure: 'mvc',
|
|
194
|
-
};
|
|
195
|
-
await generateExpressTemplate(path.join(projectPath, 'server'), serverConfig);
|
|
196
|
-
|
|
197
|
-
// Generate root package.json
|
|
198
|
-
await fs.writeFile(
|
|
199
|
-
path.join(projectPath, 'package.json'),
|
|
200
|
-
await generateRootPackageJson(config, 'MERN')
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
// Generate Docker setup
|
|
204
|
-
await generateDockerSetup(projectPath, config, 'MERN');
|
|
205
|
-
|
|
206
|
-
// Generate API proxy config
|
|
207
|
-
await generateAPIConfig(projectPath, config, 'MERN');
|
|
208
|
-
|
|
209
|
-
// Generate environment files
|
|
210
|
-
await generateFullStackEnv(projectPath, config, 'MERN');
|
|
211
|
-
|
|
212
|
-
// Generate README
|
|
213
|
-
await generateFullStackReadme(projectPath, config, 'MERN');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* PERN Stack (PostgreSQL, Express, React, Node)
|
|
218
|
-
*/
|
|
219
|
-
async function generatePERNStack(projectPath, config) {
|
|
220
|
-
// Create folder structure
|
|
221
|
-
await fs.ensureDir(path.join(projectPath, 'client'));
|
|
222
|
-
await fs.ensureDir(path.join(projectPath, 'server'));
|
|
223
|
-
|
|
224
|
-
// Generate React frontend
|
|
225
|
-
const clientConfig = {
|
|
226
|
-
...config,
|
|
227
|
-
projectName: 'client',
|
|
228
|
-
frontend: 'react',
|
|
229
|
-
additionalLibraries: ['react-router', 'axios'],
|
|
230
|
-
};
|
|
231
|
-
await generateReactTemplate(path.join(projectPath, 'client'), clientConfig);
|
|
232
|
-
|
|
233
|
-
// Generate Express backend with Prisma
|
|
234
|
-
const serverConfig = {
|
|
235
|
-
...config,
|
|
236
|
-
projectName: 'server',
|
|
237
|
-
backend: 'express',
|
|
238
|
-
database: 'prisma',
|
|
239
|
-
folderStructure: 'layered',
|
|
240
|
-
};
|
|
241
|
-
await generateExpressTemplate(path.join(projectPath, 'server'), serverConfig);
|
|
242
|
-
|
|
243
|
-
// Generate root package.json
|
|
244
|
-
await fs.writeFile(
|
|
245
|
-
path.join(projectPath, 'package.json'),
|
|
246
|
-
await generateRootPackageJson(config, 'PERN')
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
// Generate Docker setup with PostgreSQL
|
|
250
|
-
await generateDockerSetup(projectPath, config, 'PERN');
|
|
251
|
-
|
|
252
|
-
// Generate API config
|
|
253
|
-
await generateAPIConfig(projectPath, config, 'PERN');
|
|
254
|
-
|
|
255
|
-
// Generate environment files
|
|
256
|
-
await generateFullStackEnv(projectPath, config, 'PERN');
|
|
257
|
-
|
|
258
|
-
// Generate README
|
|
259
|
-
await generateFullStackReadme(projectPath, config, 'PERN');
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Next.js + Express Stack
|
|
264
|
-
*/
|
|
265
|
-
async function generateNextExpressStack(projectPath, config) {
|
|
266
|
-
// Create folder structure
|
|
267
|
-
await fs.ensureDir(path.join(projectPath, 'frontend'));
|
|
268
|
-
await fs.ensureDir(path.join(projectPath, 'backend'));
|
|
269
|
-
|
|
270
|
-
// Generate Next.js frontend
|
|
271
|
-
const frontendConfig = {
|
|
272
|
-
...config,
|
|
273
|
-
projectName: 'frontend',
|
|
274
|
-
frontend: 'nextjs',
|
|
275
|
-
};
|
|
276
|
-
await generateNextjsTemplate(path.join(projectPath, 'frontend'), frontendConfig);
|
|
277
|
-
|
|
278
|
-
// Generate Express backend
|
|
279
|
-
const backendConfig = {
|
|
280
|
-
...config,
|
|
281
|
-
projectName: 'backend',
|
|
282
|
-
backend: 'express',
|
|
283
|
-
database: config.database || 'prisma',
|
|
284
|
-
folderStructure: 'clean-architecture',
|
|
285
|
-
};
|
|
286
|
-
await generateExpressTemplate(path.join(projectPath, 'backend'), backendConfig);
|
|
287
|
-
|
|
288
|
-
// Generate root package.json
|
|
289
|
-
await fs.writeFile(
|
|
290
|
-
path.join(projectPath, 'package.json'),
|
|
291
|
-
await generateRootPackageJson(config, 'Next.js + Express')
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
// Generate Docker setup
|
|
295
|
-
await generateDockerSetup(projectPath, config, 'Next.js + Express');
|
|
296
|
-
|
|
297
|
-
// Generate Next.js API proxy config
|
|
298
|
-
await generateNextjsProxyConfig(path.join(projectPath, 'frontend'));
|
|
299
|
-
|
|
300
|
-
// Generate environment files
|
|
301
|
-
await generateFullStackEnv(projectPath, config, 'Next.js + Express');
|
|
302
|
-
|
|
303
|
-
// Generate README
|
|
304
|
-
await generateFullStackReadme(projectPath, config, 'Next.js + Express');
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Laravel + React Stack (Scaffolding only)
|
|
309
|
-
*/
|
|
310
|
-
async function generateLaravelReactStack(projectPath, config) {
|
|
311
|
-
// Create folder structure
|
|
312
|
-
await fs.ensureDir(path.join(projectPath, 'client'));
|
|
313
|
-
|
|
314
|
-
// Generate React frontend
|
|
315
|
-
const clientConfig = {
|
|
316
|
-
...config,
|
|
317
|
-
projectName: 'client',
|
|
318
|
-
frontend: 'react',
|
|
319
|
-
additionalLibraries: ['react-router', 'axios'],
|
|
320
|
-
};
|
|
321
|
-
await generateReactTemplate(path.join(projectPath, 'client'), clientConfig);
|
|
322
|
-
|
|
323
|
-
// Create Laravel backend placeholder
|
|
324
|
-
await fs.ensureDir(path.join(projectPath, 'server'));
|
|
325
|
-
await fs.writeFile(
|
|
326
|
-
path.join(projectPath, 'server', 'README.md'),
|
|
327
|
-
`# Laravel Backend
|
|
328
|
-
|
|
329
|
-
## Setup Instructions
|
|
330
|
-
|
|
331
|
-
1. Install Laravel:
|
|
332
|
-
\`\`\`bash
|
|
333
|
-
composer create-project laravel/laravel .
|
|
334
|
-
\`\`\`
|
|
335
|
-
|
|
336
|
-
2. Configure database in \`.env\`
|
|
337
|
-
|
|
338
|
-
3. Run migrations:
|
|
339
|
-
\`\`\`bash
|
|
340
|
-
php artisan migrate
|
|
341
|
-
\`\`\`
|
|
342
|
-
|
|
343
|
-
4. Start server:
|
|
344
|
-
\`\`\`bash
|
|
345
|
-
php artisan serve
|
|
346
|
-
\`\`\`
|
|
347
|
-
|
|
348
|
-
## API Routes
|
|
349
|
-
|
|
350
|
-
Add your API routes in \`routes/api.php\`
|
|
351
|
-
`
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
// Generate root README
|
|
355
|
-
await fs.writeFile(path.join(projectPath, 'README.md'), generateLaravelReactReadme(config));
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// ==================== Helper Functions ====================
|
|
359
|
-
|
|
360
|
-
async function generateMonorepoPackageJson(config) {
|
|
361
|
-
const spinner = ora('Fetching latest package versions...').start();
|
|
362
|
-
|
|
363
|
-
try {
|
|
364
|
-
const turboVer = await fetchVersion('turbo');
|
|
365
|
-
spinner.succeed(chalk.green('Fetched latest versions'));
|
|
366
|
-
|
|
367
|
-
return JSON.stringify(
|
|
368
|
-
{
|
|
369
|
-
name: config.projectName || 'my-monorepo',
|
|
370
|
-
version: '1.0.0',
|
|
371
|
-
private: true,
|
|
372
|
-
workspaces: ['apps/*', 'packages/*'],
|
|
373
|
-
scripts: {
|
|
374
|
-
dev: 'turbo run dev',
|
|
375
|
-
build: 'turbo run build',
|
|
376
|
-
lint: 'turbo run lint',
|
|
377
|
-
clean: 'turbo run clean',
|
|
378
|
-
'dev:frontend': 'turbo run dev --filter=frontend',
|
|
379
|
-
'dev:backend': 'turbo run dev --filter=backend',
|
|
380
|
-
},
|
|
381
|
-
devDependencies: {
|
|
382
|
-
turbo: turboVer,
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
null,
|
|
386
|
-
2
|
|
387
|
-
);
|
|
388
|
-
} catch (error) {
|
|
389
|
-
spinner.fail(chalk.yellow('Could not fetch versions, using fallbacks'));
|
|
390
|
-
return JSON.stringify(
|
|
391
|
-
{
|
|
392
|
-
name: config.projectName || 'my-monorepo',
|
|
393
|
-
version: '1.0.0',
|
|
394
|
-
private: true,
|
|
395
|
-
workspaces: ['apps/*', 'packages/*'],
|
|
396
|
-
scripts: {
|
|
397
|
-
dev: 'turbo run dev',
|
|
398
|
-
build: 'turbo run build',
|
|
399
|
-
lint: 'turbo run lint',
|
|
400
|
-
clean: 'turbo run clean',
|
|
401
|
-
'dev:frontend': 'turbo run dev --filter=frontend',
|
|
402
|
-
'dev:backend': 'turbo run dev --filter=backend',
|
|
403
|
-
},
|
|
404
|
-
devDependencies: { turbo: 'latest' },
|
|
405
|
-
},
|
|
406
|
-
null,
|
|
407
|
-
2
|
|
408
|
-
);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function generateTurboConfig() {
|
|
413
|
-
return JSON.stringify(
|
|
414
|
-
{
|
|
415
|
-
$schema: 'https://turbo.build/schema.json',
|
|
416
|
-
pipeline: {
|
|
417
|
-
build: {
|
|
418
|
-
dependsOn: ['^build'],
|
|
419
|
-
outputs: ['dist/**', '.next/**'],
|
|
420
|
-
},
|
|
421
|
-
dev: {
|
|
422
|
-
cache: false,
|
|
423
|
-
persistent: true,
|
|
424
|
-
},
|
|
425
|
-
lint: {},
|
|
426
|
-
clean: {
|
|
427
|
-
cache: false,
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
|
-
},
|
|
431
|
-
null,
|
|
432
|
-
2
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
async function generateSharedTypes(typesPath) {
|
|
437
|
-
await fs.writeFile(
|
|
438
|
-
path.join(typesPath, 'package.json'),
|
|
439
|
-
JSON.stringify(
|
|
440
|
-
{
|
|
441
|
-
name: 'shared-types',
|
|
442
|
-
version: '1.0.0',
|
|
443
|
-
main: './src/index.ts',
|
|
444
|
-
types: './src/index.ts',
|
|
445
|
-
},
|
|
446
|
-
null,
|
|
447
|
-
2
|
|
448
|
-
)
|
|
449
|
-
);
|
|
450
|
-
|
|
451
|
-
await fs.ensureDir(path.join(typesPath, 'src'));
|
|
452
|
-
await fs.writeFile(
|
|
453
|
-
path.join(typesPath, 'src', 'index.ts'),
|
|
454
|
-
`// Shared TypeScript types and interfaces
|
|
455
|
-
|
|
456
|
-
export interface User {
|
|
457
|
-
id: string;
|
|
458
|
-
email: string;
|
|
459
|
-
name: string;
|
|
460
|
-
createdAt: Date;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
export interface ApiResponse<T = any> {
|
|
464
|
-
success: boolean;
|
|
465
|
-
data?: T;
|
|
466
|
-
message?: string;
|
|
467
|
-
error?: string;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// Add your shared types here
|
|
471
|
-
`
|
|
472
|
-
);
|
|
473
|
-
|
|
474
|
-
await fs.writeFile(
|
|
475
|
-
path.join(typesPath, 'tsconfig.json'),
|
|
476
|
-
JSON.stringify(
|
|
477
|
-
{
|
|
478
|
-
compilerOptions: {
|
|
479
|
-
target: 'ES2020',
|
|
480
|
-
module: 'ESNext',
|
|
481
|
-
moduleResolution: 'node',
|
|
482
|
-
declaration: true,
|
|
483
|
-
outDir: './dist',
|
|
484
|
-
strict: true,
|
|
485
|
-
esModuleInterop: true,
|
|
486
|
-
},
|
|
487
|
-
include: ['src/**/*'],
|
|
488
|
-
exclude: ['node_modules', 'dist'],
|
|
489
|
-
},
|
|
490
|
-
null,
|
|
491
|
-
2
|
|
492
|
-
)
|
|
493
|
-
);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
async function generateUIComponents(uiPath, config) {
|
|
497
|
-
const isNextjs = config.stack?.includes('Next.js');
|
|
498
|
-
|
|
499
|
-
await fs.writeFile(
|
|
500
|
-
path.join(uiPath, 'package.json'),
|
|
501
|
-
JSON.stringify(
|
|
502
|
-
{
|
|
503
|
-
name: 'ui-components',
|
|
504
|
-
version: '1.0.0',
|
|
505
|
-
main: './src/index.ts',
|
|
506
|
-
dependencies: {
|
|
507
|
-
react: '^19.0.0',
|
|
508
|
-
...(isNextjs && { next: '^15.1.4' }),
|
|
509
|
-
},
|
|
510
|
-
},
|
|
511
|
-
null,
|
|
512
|
-
2
|
|
513
|
-
)
|
|
514
|
-
);
|
|
515
|
-
|
|
516
|
-
await fs.ensureDir(path.join(uiPath, 'src'));
|
|
517
|
-
await fs.writeFile(
|
|
518
|
-
path.join(uiPath, 'src', 'Button.tsx'),
|
|
519
|
-
`import React from 'react';
|
|
520
|
-
|
|
521
|
-
interface ButtonProps {
|
|
522
|
-
children: React.ReactNode;
|
|
523
|
-
onClick?: () => void;
|
|
524
|
-
variant?: 'primary' | 'secondary';
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
export const Button: React.FC<ButtonProps> = ({
|
|
528
|
-
children,
|
|
529
|
-
onClick,
|
|
530
|
-
variant = 'primary'
|
|
531
|
-
}) => {
|
|
532
|
-
return (
|
|
533
|
-
<button
|
|
534
|
-
onClick={onClick}
|
|
535
|
-
className={\`btn btn-\${variant}\`}
|
|
536
|
-
>
|
|
537
|
-
{children}
|
|
538
|
-
</button>
|
|
539
|
-
);
|
|
540
|
-
};
|
|
541
|
-
`
|
|
542
|
-
);
|
|
543
|
-
|
|
544
|
-
await fs.writeFile(
|
|
545
|
-
path.join(uiPath, 'src', 'index.ts'),
|
|
546
|
-
`export { Button } from './Button';
|
|
547
|
-
// Export more components here
|
|
548
|
-
`
|
|
549
|
-
);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
async function generateMonorepoRootFiles(projectPath, config) {
|
|
553
|
-
// Root .gitignore
|
|
554
|
-
await fs.writeFile(
|
|
555
|
-
path.join(projectPath, '.gitignore'),
|
|
556
|
-
`# Dependencies
|
|
557
|
-
node_modules/
|
|
558
|
-
.pnp
|
|
559
|
-
.pnp.js
|
|
560
|
-
|
|
561
|
-
# Build outputs
|
|
562
|
-
dist/
|
|
563
|
-
.next/
|
|
564
|
-
build/
|
|
565
|
-
|
|
566
|
-
# Environment
|
|
567
|
-
.env
|
|
568
|
-
.env*.local
|
|
569
|
-
|
|
570
|
-
# Logs
|
|
571
|
-
*.log
|
|
572
|
-
|
|
573
|
-
# OS
|
|
574
|
-
.DS_Store
|
|
575
|
-
Thumbs.db
|
|
576
|
-
|
|
577
|
-
# IDE
|
|
578
|
-
.vscode/
|
|
579
|
-
.idea/
|
|
580
|
-
*.swp
|
|
581
|
-
*.swo
|
|
582
|
-
`
|
|
583
|
-
);
|
|
584
|
-
|
|
585
|
-
// Root .env.example
|
|
586
|
-
await fs.writeFile(
|
|
587
|
-
path.join(projectPath, '.env.example'),
|
|
588
|
-
`# Environment Configuration
|
|
589
|
-
|
|
590
|
-
# Frontend
|
|
591
|
-
NEXT_PUBLIC_API_URL=http://localhost:3001/api
|
|
592
|
-
|
|
593
|
-
# Backend
|
|
594
|
-
PORT=3001
|
|
595
|
-
NODE_ENV=development
|
|
596
|
-
DATABASE_URL=
|
|
597
|
-
|
|
598
|
-
# Add your environment variables here
|
|
599
|
-
`
|
|
600
|
-
);
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
async function generateMonorepoDockerSetup(projectPath, config) {
|
|
604
|
-
// Docker Compose for monorepo
|
|
605
|
-
await fs.writeFile(
|
|
606
|
-
path.join(projectPath, 'docker-compose.yml'),
|
|
607
|
-
`version: '3.8'
|
|
608
|
-
|
|
609
|
-
services:
|
|
610
|
-
frontend:
|
|
611
|
-
build:
|
|
612
|
-
context: ./apps/frontend
|
|
613
|
-
dockerfile: Dockerfile
|
|
614
|
-
ports:
|
|
615
|
-
- "3000:3000"
|
|
616
|
-
environment:
|
|
617
|
-
- NEXT_PUBLIC_API_URL=http://backend:3001/api
|
|
618
|
-
depends_on:
|
|
619
|
-
- backend
|
|
620
|
-
volumes:
|
|
621
|
-
- ./apps/frontend:/app
|
|
622
|
-
- /app/node_modules
|
|
623
|
-
|
|
624
|
-
backend:
|
|
625
|
-
build:
|
|
626
|
-
context: ./apps/backend
|
|
627
|
-
dockerfile: Dockerfile
|
|
628
|
-
ports:
|
|
629
|
-
- "3001:3001"
|
|
630
|
-
environment:
|
|
631
|
-
- NODE_ENV=development
|
|
632
|
-
- PORT=3001
|
|
633
|
-
volumes:
|
|
634
|
-
- ./apps/backend:/app
|
|
635
|
-
- /app/node_modules
|
|
636
|
-
|
|
637
|
-
${
|
|
638
|
-
config.stack?.includes('MongoDB')
|
|
639
|
-
? `mongo:
|
|
640
|
-
image: mongo:7
|
|
641
|
-
ports:
|
|
642
|
-
- "27017:27017"
|
|
643
|
-
volumes:
|
|
644
|
-
- mongo_data:/data/db`
|
|
645
|
-
: ''
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
${
|
|
649
|
-
config.stack?.includes('PostgreSQL')
|
|
650
|
-
? `postgres:
|
|
651
|
-
image: postgres:15-alpine
|
|
652
|
-
ports:
|
|
653
|
-
- "5432:5432"
|
|
654
|
-
environment:
|
|
655
|
-
- POSTGRES_USER=postgres
|
|
656
|
-
- POSTGRES_PASSWORD=postgres
|
|
657
|
-
- POSTGRES_DB=mydb
|
|
658
|
-
volumes:
|
|
659
|
-
- postgres_data:/var/lib/postgresql/data`
|
|
660
|
-
: ''
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
${
|
|
664
|
-
config.stack?.includes('MongoDB') || config.stack?.includes('PostgreSQL')
|
|
665
|
-
? `volumes:
|
|
666
|
-
${config.stack?.includes('MongoDB') ? 'mongo_data:' : ''}
|
|
667
|
-
${config.stack?.includes('PostgreSQL') ? 'postgres_data:' : ''}`
|
|
668
|
-
: ''
|
|
669
|
-
}
|
|
670
|
-
`
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
function generateMonorepoReadme(projectPath, config) {
|
|
675
|
-
return fs.writeFile(
|
|
676
|
-
path.join(projectPath, 'README.md'),
|
|
677
|
-
`# ${config.projectName || 'My Monorepo'}
|
|
678
|
-
|
|
679
|
-
Full-stack monorepo with ${config.stack}
|
|
680
|
-
|
|
681
|
-
## 📁 Structure
|
|
682
|
-
|
|
683
|
-
\`\`\`
|
|
684
|
-
${config.projectName}/
|
|
685
|
-
├── apps/
|
|
686
|
-
│ ├── frontend/ # ${config.stack?.includes('Next.js') ? 'Next.js' : 'React'} application
|
|
687
|
-
│ └── backend/ # Express.js API
|
|
688
|
-
├── packages/
|
|
689
|
-
│ ├── shared-types/ # Shared TypeScript types
|
|
690
|
-
│ └── ui-components/# Shared UI components
|
|
691
|
-
├── package.json # Root workspace config
|
|
692
|
-
└── turbo.json # Turborepo configuration
|
|
693
|
-
\`\`\`
|
|
694
|
-
|
|
695
|
-
## 🚀 Getting Started
|
|
696
|
-
|
|
697
|
-
### Prerequisites
|
|
698
|
-
|
|
699
|
-
- Node.js 18+
|
|
700
|
-
- pnpm (recommended) or npm
|
|
701
|
-
|
|
702
|
-
### Installation
|
|
703
|
-
|
|
704
|
-
\`\`\`bash
|
|
705
|
-
# Install dependencies
|
|
706
|
-
npm install
|
|
707
|
-
|
|
708
|
-
# Or with pnpm
|
|
709
|
-
pnpm install
|
|
710
|
-
\`\`\`
|
|
711
|
-
|
|
712
|
-
### Development
|
|
713
|
-
|
|
714
|
-
\`\`\`bash
|
|
715
|
-
# Run all apps
|
|
716
|
-
npm run dev
|
|
717
|
-
|
|
718
|
-
# Run frontend only
|
|
719
|
-
npm run dev:frontend
|
|
720
|
-
|
|
721
|
-
# Run backend only
|
|
722
|
-
npm run dev:backend
|
|
723
|
-
\`\`\`
|
|
724
|
-
|
|
725
|
-
### Build
|
|
726
|
-
|
|
727
|
-
\`\`\`bash
|
|
728
|
-
npm run build
|
|
729
|
-
\`\`\`
|
|
730
|
-
|
|
731
|
-
## 🐳 Docker
|
|
732
|
-
|
|
733
|
-
\`\`\`bash
|
|
734
|
-
# Start all services
|
|
735
|
-
docker-compose up
|
|
736
|
-
|
|
737
|
-
# Build and start
|
|
738
|
-
docker-compose up --build
|
|
739
|
-
\`\`\`
|
|
740
|
-
|
|
741
|
-
## 📦 Packages
|
|
742
|
-
|
|
743
|
-
- **shared-types**: Common TypeScript interfaces
|
|
744
|
-
- **ui-components**: Reusable UI components
|
|
745
|
-
|
|
746
|
-
## 📝 License
|
|
747
|
-
|
|
748
|
-
MIT
|
|
749
|
-
`
|
|
750
|
-
);
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
async function generateRootPackageJson(config, stackType) {
|
|
754
|
-
const spinner = ora('Fetching latest package versions...').start();
|
|
755
|
-
|
|
756
|
-
try {
|
|
757
|
-
const concurrentlyVer = await fetchVersion('concurrently');
|
|
758
|
-
spinner.succeed(chalk.green('Fetched latest versions'));
|
|
759
|
-
|
|
760
|
-
const scripts = {
|
|
761
|
-
dev: 'concurrently "npm run dev:client" "npm run dev:server"',
|
|
762
|
-
'dev:client':
|
|
763
|
-
stackType === 'Next.js + Express'
|
|
764
|
-
? 'cd frontend && npm run dev'
|
|
765
|
-
: 'cd client && npm run dev',
|
|
766
|
-
'dev:server':
|
|
767
|
-
stackType === 'Next.js + Express'
|
|
768
|
-
? 'cd backend && npm run dev'
|
|
769
|
-
: 'cd server && npm run dev',
|
|
770
|
-
build: 'npm run build:client && npm run build:server',
|
|
771
|
-
'build:client':
|
|
772
|
-
stackType === 'Next.js + Express'
|
|
773
|
-
? 'cd frontend && npm run build'
|
|
774
|
-
: 'cd client && npm run build',
|
|
775
|
-
'build:server':
|
|
776
|
-
stackType === 'Next.js + Express'
|
|
777
|
-
? 'cd backend && npm run build'
|
|
778
|
-
: 'cd server && npm run build',
|
|
779
|
-
'install:all':
|
|
780
|
-
stackType === 'Next.js + Express'
|
|
781
|
-
? 'npm install && cd frontend && npm install && cd ../backend && npm install'
|
|
782
|
-
: 'npm install && cd client && npm install && cd ../server && npm install',
|
|
783
|
-
};
|
|
784
|
-
|
|
785
|
-
return JSON.stringify(
|
|
786
|
-
{
|
|
787
|
-
name: config.projectName || 'my-fullstack-app',
|
|
788
|
-
version: '1.0.0',
|
|
789
|
-
description: `${stackType} full-stack application`,
|
|
790
|
-
scripts,
|
|
791
|
-
devDependencies: {
|
|
792
|
-
concurrently: concurrentlyVer,
|
|
793
|
-
},
|
|
794
|
-
},
|
|
795
|
-
null,
|
|
796
|
-
2
|
|
797
|
-
);
|
|
798
|
-
} catch (error) {
|
|
799
|
-
spinner.fail(chalk.yellow('Could not fetch versions, using fallbacks'));
|
|
800
|
-
const scripts = {
|
|
801
|
-
dev: 'concurrently "npm run dev:client" "npm run dev:server"',
|
|
802
|
-
'dev:client':
|
|
803
|
-
stackType === 'Next.js + Express'
|
|
804
|
-
? 'cd frontend && npm run dev'
|
|
805
|
-
: 'cd client && npm run dev',
|
|
806
|
-
'dev:server':
|
|
807
|
-
stackType === 'Next.js + Express'
|
|
808
|
-
? 'cd backend && npm run dev'
|
|
809
|
-
: 'cd server && npm run dev',
|
|
810
|
-
build: 'npm run build:client && npm run build:server',
|
|
811
|
-
'build:client':
|
|
812
|
-
stackType === 'Next.js + Express'
|
|
813
|
-
? 'cd frontend && npm run build'
|
|
814
|
-
: 'cd client && npm run build',
|
|
815
|
-
'build:server':
|
|
816
|
-
stackType === 'Next.js + Express'
|
|
817
|
-
? 'cd backend && npm run build'
|
|
818
|
-
: 'cd server && npm run build',
|
|
819
|
-
'install:all':
|
|
820
|
-
stackType === 'Next.js + Express'
|
|
821
|
-
? 'npm install && cd frontend && npm install && cd ../backend && npm install'
|
|
822
|
-
: 'npm install && cd client && npm install && cd ../server && npm install',
|
|
823
|
-
};
|
|
824
|
-
return JSON.stringify(
|
|
825
|
-
{
|
|
826
|
-
name: config.projectName || 'my-fullstack-app',
|
|
827
|
-
version: '1.0.0',
|
|
828
|
-
description: `${stackType} full-stack application`,
|
|
829
|
-
scripts,
|
|
830
|
-
devDependencies: { concurrently: 'latest' },
|
|
831
|
-
},
|
|
832
|
-
null,
|
|
833
|
-
2
|
|
834
|
-
);
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
async function generateDockerSetup(projectPath, config, stackType) {
|
|
839
|
-
const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
|
|
840
|
-
const backendDir = stackType === 'Next.js + Express' ? 'backend' : 'server';
|
|
841
|
-
|
|
842
|
-
// Docker Compose
|
|
843
|
-
const dbService =
|
|
844
|
-
stackType === 'MERN'
|
|
845
|
-
? ` mongo:
|
|
846
|
-
image: mongo:7
|
|
847
|
-
ports:
|
|
848
|
-
- "27017:27017"
|
|
849
|
-
volumes:
|
|
850
|
-
- mongo_data:/data/db
|
|
851
|
-
environment:
|
|
852
|
-
- MONGO_INITDB_DATABASE=mydb`
|
|
853
|
-
: stackType === 'PERN' || stackType === 'Next.js + Express'
|
|
854
|
-
? ` postgres:
|
|
855
|
-
image: postgres:15-alpine
|
|
856
|
-
ports:
|
|
857
|
-
- "5432:5432"
|
|
858
|
-
environment:
|
|
859
|
-
- POSTGRES_USER=postgres
|
|
860
|
-
- POSTGRES_PASSWORD=postgres
|
|
861
|
-
- POSTGRES_DB=mydb
|
|
862
|
-
volumes:
|
|
863
|
-
- postgres_data:/var/lib/postgresql/data`
|
|
864
|
-
: '';
|
|
865
|
-
|
|
866
|
-
await fs.writeFile(
|
|
867
|
-
path.join(projectPath, 'docker-compose.yml'),
|
|
868
|
-
`version: '3.8'
|
|
869
|
-
|
|
870
|
-
services:
|
|
871
|
-
frontend:
|
|
872
|
-
build:
|
|
873
|
-
context: ./${frontendDir}
|
|
874
|
-
dockerfile: Dockerfile
|
|
875
|
-
ports:
|
|
876
|
-
- "${stackType.includes('Next.js') ? '3000:3000' : '5173:5173'}"
|
|
877
|
-
environment:
|
|
878
|
-
- ${stackType.includes('Next.js') ? 'NEXT_PUBLIC_API_URL' : 'VITE_API_URL'}=http://backend:3001/api
|
|
879
|
-
depends_on:
|
|
880
|
-
- backend
|
|
881
|
-
volumes:
|
|
882
|
-
- ./${frontendDir}:/app
|
|
883
|
-
- /app/node_modules
|
|
884
|
-
|
|
885
|
-
backend:
|
|
886
|
-
build:
|
|
887
|
-
context: ./${backendDir}
|
|
888
|
-
dockerfile: Dockerfile
|
|
889
|
-
ports:
|
|
890
|
-
- "3001:3001"
|
|
891
|
-
environment:
|
|
892
|
-
- NODE_ENV=development
|
|
893
|
-
- PORT=3001
|
|
894
|
-
${stackType === 'MERN' ? '- MONGODB_URI=mongodb://mongo:27017/mydb' : ''}
|
|
895
|
-
${stackType === 'PERN' || stackType === 'Next.js + Express' ? '- DATABASE_URL=postgresql://postgres:postgres@postgres:5432/mydb' : ''}
|
|
896
|
-
depends_on:
|
|
897
|
-
${stackType !== 'MERN' && stackType !== 'PERN' && !stackType.includes('Next.js') ? '' : '- ' + (stackType === 'MERN' ? 'mongo' : 'postgres')}
|
|
898
|
-
volumes:
|
|
899
|
-
- ./${backendDir}:/app
|
|
900
|
-
- /app/node_modules
|
|
901
|
-
|
|
902
|
-
${dbService}
|
|
903
|
-
|
|
904
|
-
${
|
|
905
|
-
dbService
|
|
906
|
-
? `volumes:
|
|
907
|
-
${stackType === 'MERN' ? 'mongo_data:' : 'postgres_data:'}`
|
|
908
|
-
: ''
|
|
909
|
-
}
|
|
910
|
-
`
|
|
911
|
-
);
|
|
912
|
-
|
|
913
|
-
// Frontend Dockerfile
|
|
914
|
-
const frontendDockerfile = stackType.includes('Next.js')
|
|
915
|
-
? `FROM node:18-alpine AS base
|
|
916
|
-
|
|
917
|
-
FROM base AS deps
|
|
918
|
-
WORKDIR /app
|
|
919
|
-
COPY package*.json ./
|
|
920
|
-
RUN npm ci
|
|
921
|
-
|
|
922
|
-
FROM base AS builder
|
|
923
|
-
WORKDIR /app
|
|
924
|
-
COPY --from=deps /app/node_modules ./node_modules
|
|
925
|
-
COPY . .
|
|
926
|
-
RUN npm run build
|
|
927
|
-
|
|
928
|
-
FROM base AS runner
|
|
929
|
-
WORKDIR /app
|
|
930
|
-
ENV NODE_ENV production
|
|
931
|
-
COPY --from=builder /app/public ./public
|
|
932
|
-
COPY --from=builder /app/.next/standalone ./
|
|
933
|
-
COPY --from=builder /app/.next/static ./.next/static
|
|
934
|
-
|
|
935
|
-
EXPOSE 3000
|
|
936
|
-
CMD ["node", "server.js"]`
|
|
937
|
-
: `FROM node:18-alpine
|
|
938
|
-
WORKDIR /app
|
|
939
|
-
COPY package*.json ./
|
|
940
|
-
RUN npm install
|
|
941
|
-
COPY . .
|
|
942
|
-
EXPOSE 5173
|
|
943
|
-
CMD ["npm", "run", "dev", "--", "--host"]`;
|
|
944
|
-
|
|
945
|
-
await fs.writeFile(path.join(projectPath, frontendDir, 'Dockerfile'), frontendDockerfile);
|
|
946
|
-
|
|
947
|
-
// Backend Dockerfile
|
|
948
|
-
await fs.writeFile(
|
|
949
|
-
path.join(projectPath, backendDir, 'Dockerfile'),
|
|
950
|
-
`FROM node:18-alpine
|
|
951
|
-
WORKDIR /app
|
|
952
|
-
COPY package*.json ./
|
|
953
|
-
RUN npm install
|
|
954
|
-
COPY . .
|
|
955
|
-
${config.language === 'typescript' ? 'RUN npm run build' : ''}
|
|
956
|
-
EXPOSE 3001
|
|
957
|
-
CMD ["npm", "start"]`
|
|
958
|
-
);
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
async function generateAPIConfig(projectPath, config, stackType) {
|
|
962
|
-
const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
|
|
963
|
-
|
|
964
|
-
if (stackType.includes('Next.js')) {
|
|
965
|
-
return; // Next.js uses rewrites in next.config.js
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
// Vite proxy config for React
|
|
969
|
-
const viteConfig = `import { defineConfig } from 'vite';
|
|
970
|
-
import react from '@vitejs/plugin-react';
|
|
971
|
-
|
|
972
|
-
export default defineConfig({
|
|
973
|
-
plugins: [react()],
|
|
974
|
-
server: {
|
|
975
|
-
proxy: {
|
|
976
|
-
'/api': {
|
|
977
|
-
target: 'http://localhost:3001',
|
|
978
|
-
changeOrigin: true,
|
|
979
|
-
},
|
|
980
|
-
},
|
|
981
|
-
},
|
|
982
|
-
});
|
|
983
|
-
`;
|
|
984
|
-
|
|
985
|
-
await fs.writeFile(path.join(projectPath, frontendDir, 'vite.config.js'), viteConfig);
|
|
986
|
-
|
|
987
|
-
// API client wrapper
|
|
988
|
-
await fs.ensureDir(path.join(projectPath, frontendDir, 'src', 'lib'));
|
|
989
|
-
await fs.writeFile(
|
|
990
|
-
path.join(projectPath, frontendDir, 'src', 'lib', 'api.js'),
|
|
991
|
-
`import axios from 'axios';
|
|
992
|
-
|
|
993
|
-
const api = axios.create({
|
|
994
|
-
baseURL: import.meta.env.VITE_API_URL || '/api',
|
|
995
|
-
headers: {
|
|
996
|
-
'Content-Type': 'application/json',
|
|
997
|
-
},
|
|
998
|
-
});
|
|
999
|
-
|
|
1000
|
-
// Add interceptors for auth tokens if needed
|
|
1001
|
-
api.interceptors.request.use((config) => {
|
|
1002
|
-
const token = localStorage.getItem('token');
|
|
1003
|
-
if (token) {
|
|
1004
|
-
config.headers.Authorization = \`Bearer \${token}\`;
|
|
1005
|
-
}
|
|
1006
|
-
return config;
|
|
1007
|
-
});
|
|
1008
|
-
|
|
1009
|
-
export default api;
|
|
1010
|
-
`
|
|
1011
|
-
);
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
async function generateNextjsProxyConfig(frontendPath) {
|
|
1015
|
-
// Add API rewrite to next.config.js
|
|
1016
|
-
const nextConfigPath = path.join(frontendPath, 'next.config.js');
|
|
1017
|
-
|
|
1018
|
-
// Read existing config or create new one
|
|
1019
|
-
let configContent = `/** @type {import('next').NextConfig} */
|
|
1020
|
-
const nextConfig = {
|
|
1021
|
-
async rewrites() {
|
|
1022
|
-
return [
|
|
1023
|
-
{
|
|
1024
|
-
source: '/api/:path*',
|
|
1025
|
-
destination: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api/:path*',
|
|
1026
|
-
},
|
|
1027
|
-
];
|
|
1028
|
-
},
|
|
1029
|
-
};
|
|
1030
|
-
|
|
1031
|
-
export default nextConfig;
|
|
1032
|
-
`;
|
|
1033
|
-
|
|
1034
|
-
await fs.writeFile(nextConfigPath, configContent);
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
async function generateFullStackEnv(projectPath, config, stackType) {
|
|
1038
|
-
const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
|
|
1039
|
-
const backendDir = stackType === 'Next.js + Express' ? 'backend' : 'server';
|
|
1040
|
-
|
|
1041
|
-
// Root .env.example
|
|
1042
|
-
await fs.writeFile(
|
|
1043
|
-
path.join(projectPath, '.env.example'),
|
|
1044
|
-
`# Full Stack Environment Variables
|
|
1045
|
-
|
|
1046
|
-
# Frontend
|
|
1047
|
-
${stackType.includes('Next.js') ? 'NEXT_PUBLIC_API_URL' : 'VITE_API_URL'}=http://localhost:3001/api
|
|
1048
|
-
|
|
1049
|
-
# Backend
|
|
1050
|
-
PORT=3001
|
|
1051
|
-
NODE_ENV=development
|
|
1052
|
-
${stackType === 'MERN' ? 'MONGODB_URI=mongodb://localhost:27017/mydb' : ''}
|
|
1053
|
-
${stackType === 'PERN' || stackType === 'Next.js + Express' ? 'DATABASE_URL=postgresql://postgres:postgres@localhost:5432/mydb' : ''}
|
|
1054
|
-
`
|
|
1055
|
-
);
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
function generateFullStackReadme(projectPath, config, stackType) {
|
|
1059
|
-
const frontendDir = stackType === 'Next.js + Express' ? 'frontend' : 'client';
|
|
1060
|
-
const backendDir = stackType === 'Next.js + Express' ? 'backend' : 'server';
|
|
1061
|
-
|
|
1062
|
-
const frontend = stackType.includes('Next.js') ? 'Next.js' : 'React';
|
|
1063
|
-
const backend = 'Express.js';
|
|
1064
|
-
const database =
|
|
1065
|
-
stackType === 'MERN' ? 'MongoDB' : stackType === 'PERN' ? 'PostgreSQL' : 'PostgreSQL';
|
|
1066
|
-
|
|
1067
|
-
return fs.writeFile(
|
|
1068
|
-
path.join(projectPath, 'README.md'),
|
|
1069
|
-
`# ${config.projectName || 'Full Stack Application'}
|
|
1070
|
-
|
|
1071
|
-
${stackType} full-stack application
|
|
1072
|
-
|
|
1073
|
-
## 🛠️ Tech Stack
|
|
1074
|
-
|
|
1075
|
-
- **Frontend**: ${frontend}
|
|
1076
|
-
- **Backend**: ${backend}
|
|
1077
|
-
- **Database**: ${database}
|
|
1078
|
-
|
|
1079
|
-
## 📁 Project Structure
|
|
1080
|
-
|
|
1081
|
-
\`\`\`
|
|
1082
|
-
${config.projectName}/
|
|
1083
|
-
├── ${frontendDir}/ # Frontend application
|
|
1084
|
-
├── ${backendDir}/ # Backend API
|
|
1085
|
-
├── docker-compose.yml # Docker setup
|
|
1086
|
-
└── package.json # Root scripts
|
|
1087
|
-
\`\`\`
|
|
1088
|
-
|
|
1089
|
-
## 🚀 Getting Started
|
|
1090
|
-
|
|
1091
|
-
### Prerequisites
|
|
1092
|
-
|
|
1093
|
-
- Node.js 18+
|
|
1094
|
-
${stackType === 'MERN' ? '- MongoDB' : ''}
|
|
1095
|
-
${stackType === 'PERN' || stackType === 'Next.js + Express' ? '- PostgreSQL' : ''}
|
|
1096
|
-
|
|
1097
|
-
### Installation
|
|
1098
|
-
|
|
1099
|
-
\`\`\`bash
|
|
1100
|
-
# Install all dependencies
|
|
1101
|
-
npm run install:all
|
|
1102
|
-
\`\`\`
|
|
1103
|
-
|
|
1104
|
-
### Environment Variables
|
|
1105
|
-
|
|
1106
|
-
Copy \`.env.example\` to \`.env\` in both frontend and backend directories and configure:
|
|
1107
|
-
|
|
1108
|
-
\`\`\`bash
|
|
1109
|
-
cp .env.example .env
|
|
1110
|
-
\`\`\`
|
|
1111
|
-
|
|
1112
|
-
### Development
|
|
1113
|
-
|
|
1114
|
-
\`\`\`bash
|
|
1115
|
-
# Run both frontend and backend
|
|
1116
|
-
npm run dev
|
|
1117
|
-
|
|
1118
|
-
# Or run separately:
|
|
1119
|
-
npm run dev:client # Frontend only
|
|
1120
|
-
npm run dev:server # Backend only
|
|
1121
|
-
\`\`\`
|
|
1122
|
-
|
|
1123
|
-
Frontend: http://localhost:${stackType.includes('Next.js') ? '3000' : '5173'}
|
|
1124
|
-
Backend: http://localhost:3001
|
|
1125
|
-
|
|
1126
|
-
### Build
|
|
1127
|
-
|
|
1128
|
-
\`\`\`bash
|
|
1129
|
-
npm run build
|
|
1130
|
-
\`\`\`
|
|
1131
|
-
|
|
1132
|
-
## 🐳 Docker
|
|
1133
|
-
|
|
1134
|
-
\`\`\`bash
|
|
1135
|
-
# Start all services with Docker
|
|
1136
|
-
docker-compose up
|
|
1137
|
-
|
|
1138
|
-
# Build and start
|
|
1139
|
-
docker-compose up --build
|
|
1140
|
-
|
|
1141
|
-
# Stop services
|
|
1142
|
-
docker-compose down
|
|
1143
|
-
\`\`\`
|
|
1144
|
-
|
|
1145
|
-
## 📡 API Integration
|
|
1146
|
-
|
|
1147
|
-
The frontend is configured to proxy API requests to the backend:
|
|
1148
|
-
- **Endpoint**: \`/api/*\`
|
|
1149
|
-
- **Target**: \`http://localhost:3001/api\`
|
|
1150
|
-
|
|
1151
|
-
## 📝 License
|
|
1152
|
-
|
|
1153
|
-
MIT
|
|
1154
|
-
`
|
|
1155
|
-
);
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
function generateLaravelReactReadme(config) {
|
|
1159
|
-
return `# ${config.projectName || 'Laravel + React Application'}
|
|
1160
|
-
|
|
1161
|
-
Full-stack application with Laravel backend and React frontend
|
|
1162
|
-
|
|
1163
|
-
## 🛠️ Tech Stack
|
|
1164
|
-
|
|
1165
|
-
- **Frontend**: React + Vite
|
|
1166
|
-
- **Backend**: Laravel
|
|
1167
|
-
- **Database**: MySQL/PostgreSQL
|
|
1168
|
-
|
|
1169
|
-
## 📁 Project Structure
|
|
1170
|
-
|
|
1171
|
-
\`\`\`
|
|
1172
|
-
${config.projectName}/
|
|
1173
|
-
├── client/ # React frontend
|
|
1174
|
-
└── server/ # Laravel backend
|
|
1175
|
-
\`\`\`
|
|
1176
|
-
|
|
1177
|
-
## 🚀 Getting Started
|
|
1178
|
-
|
|
1179
|
-
### Prerequisites
|
|
1180
|
-
|
|
1181
|
-
- Node.js 18+
|
|
1182
|
-
- PHP 8.1+
|
|
1183
|
-
- Composer
|
|
1184
|
-
- MySQL or PostgreSQL
|
|
1185
|
-
|
|
1186
|
-
### Backend Setup
|
|
1187
|
-
|
|
1188
|
-
\`\`\`bash
|
|
1189
|
-
cd server
|
|
1190
|
-
|
|
1191
|
-
# Install Laravel
|
|
1192
|
-
composer create-project laravel/laravel .
|
|
1193
|
-
|
|
1194
|
-
# Configure .env file
|
|
1195
|
-
cp .env.example .env
|
|
1196
|
-
|
|
1197
|
-
# Generate application key
|
|
1198
|
-
php artisan key:generate
|
|
1199
|
-
|
|
1200
|
-
# Run migrations
|
|
1201
|
-
php artisan migrate
|
|
1202
|
-
|
|
1203
|
-
# Start server
|
|
1204
|
-
php artisan serve
|
|
1205
|
-
\`\`\`
|
|
1206
|
-
|
|
1207
|
-
### Frontend Setup
|
|
1208
|
-
|
|
1209
|
-
\`\`\`bash
|
|
1210
|
-
cd client
|
|
1211
|
-
|
|
1212
|
-
# Install dependencies
|
|
1213
|
-
npm install
|
|
1214
|
-
|
|
1215
|
-
# Start development server
|
|
1216
|
-
npm run dev
|
|
1217
|
-
\`\`\`
|
|
1218
|
-
|
|
1219
|
-
Frontend: http://localhost:5173
|
|
1220
|
-
Backend: http://localhost:8000
|
|
1221
|
-
|
|
1222
|
-
## 📡 API Integration
|
|
1223
|
-
|
|
1224
|
-
Configure API URL in \`client/.env\`:
|
|
1225
|
-
|
|
1226
|
-
\`\`\`
|
|
1227
|
-
VITE_API_URL=http://localhost:8000/api
|
|
1228
|
-
\`\`\`
|
|
1229
|
-
|
|
1230
|
-
## 📝 License
|
|
1231
|
-
|
|
1232
|
-
MIT
|
|
1233
|
-
`;
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
export default generateFullStackTemplate;
|