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
package/src/commands/create.js
CHANGED
|
@@ -3,42 +3,42 @@ import path from 'path';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import { generateTemplate } from '../utils/templateGenerator.js';
|
|
6
|
-
import { installDependencies } from '../utils/packageManager.js';
|
|
7
6
|
import { initGit } from '../utils/git.js';
|
|
7
|
+
import { bootstrapWithOfficialCLI } from '../utils/frameworkBootstrap.js';
|
|
8
|
+
import { installAddons, hasAddons } from '../utils/addonInstaller.js';
|
|
8
9
|
import {
|
|
9
10
|
CLIError,
|
|
10
11
|
ERROR_CODES,
|
|
11
12
|
withErrorHandling,
|
|
12
13
|
rollbackProject,
|
|
13
|
-
safeFileOperation,
|
|
14
14
|
} from '../utils/errorHandler.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Create a new project based on user configuration
|
|
18
|
-
*
|
|
18
|
+
*
|
|
19
19
|
* This is the main orchestration function that:
|
|
20
20
|
* 1. Creates the project directory
|
|
21
21
|
* 2. Generates template files
|
|
22
22
|
* 3. Installs dependencies
|
|
23
23
|
* 4. Initializes Git repository
|
|
24
24
|
* 5. Handles errors with automatic rollback
|
|
25
|
-
*
|
|
25
|
+
*
|
|
26
26
|
* @param {Object} answers - User's configuration from interactive prompts
|
|
27
27
|
* @param {string} answers.projectName - Name of the project (used for directory)
|
|
28
|
-
* @param {string} answers.projectType - Type of project ('frontend'|'backend'|'
|
|
28
|
+
* @param {string} answers.projectType - Type of project ('frontend'|'backend'|'library')
|
|
29
29
|
* @param {string} [answers.frontend] - Frontend framework choice
|
|
30
30
|
* @param {string} [answers.backend] - Backend framework choice
|
|
31
31
|
* @param {string} answers.language - Programming language ('typescript'|'javascript')
|
|
32
32
|
* @param {string} answers.packageManager - Package manager ('npm'|'yarn'|'pnpm')
|
|
33
33
|
* @param {boolean} [answers.gitInit] - Whether to initialize Git repository
|
|
34
|
-
*
|
|
34
|
+
*
|
|
35
35
|
* @param {Object} [options={}] - Additional command-line options
|
|
36
36
|
* @param {boolean} [options.verbose=false] - Show detailed output during creation
|
|
37
37
|
* @param {string} [options.projectPath] - Custom path for project (overrides answers.projectName)
|
|
38
|
-
*
|
|
38
|
+
*
|
|
39
39
|
* @returns {Promise<void>}
|
|
40
40
|
* @throws {CLIError} If project creation fails at any step (automatic rollback triggered)
|
|
41
|
-
*
|
|
41
|
+
*
|
|
42
42
|
* @example
|
|
43
43
|
* // Basic usage
|
|
44
44
|
* await createProject({
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
* packageManager: 'npm',
|
|
50
50
|
* gitInit: true
|
|
51
51
|
* });
|
|
52
|
-
*
|
|
52
|
+
*
|
|
53
53
|
* @example
|
|
54
54
|
* // With verbose output
|
|
55
55
|
* await createProject(answers, { verbose: true });
|
|
@@ -57,10 +57,18 @@ import {
|
|
|
57
57
|
async function createProject(answers, options = {}) {
|
|
58
58
|
const { verbose = false, projectPath: customProjectPath } = options;
|
|
59
59
|
const projectPath = customProjectPath || path.join(process.cwd(), answers.projectName);
|
|
60
|
-
let spinner;
|
|
60
|
+
let spinner = ora();
|
|
61
61
|
|
|
62
62
|
try {
|
|
63
|
-
//
|
|
63
|
+
// ============================================
|
|
64
|
+
// STEP 1: Bootstrap with Official Framework CLI
|
|
65
|
+
// ============================================
|
|
66
|
+
spinner = ora({
|
|
67
|
+
text: 'Bootstrapping project with official CLI...',
|
|
68
|
+
color: 'cyan',
|
|
69
|
+
}).start();
|
|
70
|
+
|
|
71
|
+
// Check if directory already exists
|
|
64
72
|
if (await fs.pathExists(projectPath)) {
|
|
65
73
|
throw new CLIError(
|
|
66
74
|
`Directory "${answers.projectName}" already exists!`,
|
|
@@ -69,103 +77,180 @@ async function createProject(answers, options = {}) {
|
|
|
69
77
|
);
|
|
70
78
|
}
|
|
71
79
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
await withErrorHandling(() => bootstrapWithOfficialCLI(projectPath, answers), {
|
|
81
|
+
projectPath,
|
|
82
|
+
rollback: true,
|
|
83
|
+
errorCode: ERROR_CODES.CREATION_FAILED,
|
|
84
|
+
context: { step: 'CLI bootstrapping' },
|
|
85
|
+
});
|
|
77
86
|
|
|
78
|
-
|
|
79
|
-
() => fs.ensureDir(projectPath),
|
|
80
|
-
'Creating project directory'
|
|
81
|
-
);
|
|
87
|
+
spinner.succeed(chalk.green('✓ Base project created'));
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
// ============================================
|
|
90
|
+
// STEP 2: Install Add-ons with Official CLIs/Commands
|
|
91
|
+
// ============================================
|
|
92
|
+
if (hasAddons(answers)) {
|
|
93
|
+
spinner = ora({
|
|
94
|
+
text: 'Installing selected libraries and add-ons...',
|
|
95
|
+
color: 'cyan',
|
|
96
|
+
}).start();
|
|
87
97
|
|
|
88
|
-
|
|
89
|
-
await withErrorHandling(
|
|
90
|
-
() => generateTemplate(projectPath, answers),
|
|
91
|
-
{
|
|
98
|
+
await withErrorHandling(() => installAddons(projectPath, answers), {
|
|
92
99
|
projectPath,
|
|
93
100
|
rollback: true,
|
|
94
101
|
errorCode: ERROR_CODES.CREATION_FAILED,
|
|
95
|
-
context: { step: '
|
|
96
|
-
}
|
|
97
|
-
|
|
102
|
+
context: { step: 'add-on installation' },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
spinner.succeed(chalk.green('✓ Add-ons installed'));
|
|
106
|
+
}
|
|
98
107
|
|
|
99
|
-
|
|
108
|
+
// ============================================
|
|
109
|
+
// STEP 3: Enhance with Custom Folder Structure
|
|
110
|
+
// ============================================
|
|
111
|
+
spinner = ora({
|
|
112
|
+
text: 'Creating custom folder structure...',
|
|
113
|
+
color: 'cyan',
|
|
114
|
+
}).start();
|
|
100
115
|
|
|
101
|
-
|
|
116
|
+
await withErrorHandling(() => generateTemplate(projectPath, answers), {
|
|
117
|
+
projectPath,
|
|
118
|
+
rollback: true,
|
|
119
|
+
errorCode: ERROR_CODES.CREATION_FAILED,
|
|
120
|
+
context: { step: 'folder structure enhancement' },
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
spinner.succeed(chalk.green('✓ Folder structure configured'));
|
|
124
|
+
|
|
125
|
+
// ============================================
|
|
126
|
+
// STEP 4: Install Dependencies
|
|
127
|
+
// ============================================
|
|
128
|
+
spinner = ora({
|
|
129
|
+
text: `Installing dependencies with ${answers.packageManager}...`,
|
|
130
|
+
color: 'cyan',
|
|
131
|
+
}).start();
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const installCmd = getInstallCommand(answers.packageManager);
|
|
135
|
+
const { execCommand } = await import('../utils/cliRunner.js');
|
|
136
|
+
await execCommand(installCmd, { cwd: projectPath });
|
|
137
|
+
spinner.succeed(chalk.green('✓ Dependencies installed'));
|
|
138
|
+
} catch (error) {
|
|
139
|
+
spinner.warn(chalk.yellow('⚠ Dependency installation had issues'));
|
|
140
|
+
console.log(chalk.gray(` You can run '${answers.packageManager} install' manually\\n`));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ============================================
|
|
144
|
+
// STEP 5: Initialize Git Repository
|
|
145
|
+
// ============================================
|
|
102
146
|
if (answers.useGit) {
|
|
103
|
-
|
|
104
|
-
|
|
147
|
+
spinner = ora({
|
|
148
|
+
text: 'Initializing Git repository...',
|
|
149
|
+
color: 'cyan',
|
|
150
|
+
}).start();
|
|
151
|
+
|
|
105
152
|
try {
|
|
106
153
|
await initGit(projectPath);
|
|
107
|
-
|
|
154
|
+
spinner.succeed(chalk.green('✓ Git initialized'));
|
|
108
155
|
} catch (error) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (verbose) {
|
|
112
|
-
console.log(chalk.gray(` Reason: ${error.message}`));
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
156
|
+
spinner.warn(chalk.yellow('⚠ Git initialization skipped'));
|
|
116
157
|
|
|
117
|
-
// Step 5: Install dependencies
|
|
118
|
-
if (answers.installDependencies !== false) {
|
|
119
|
-
try {
|
|
120
|
-
await installDependencies(projectPath, answers.packageManager, {
|
|
121
|
-
verbose,
|
|
122
|
-
});
|
|
123
|
-
} catch (error) {
|
|
124
|
-
// Don't fail the entire process if install fails
|
|
125
|
-
console.log(chalk.yellow('\nDependency installation failed'));
|
|
126
|
-
console.log(chalk.gray(' You can install them manually later\n'));
|
|
127
|
-
|
|
128
158
|
if (verbose) {
|
|
129
|
-
console.log(chalk.gray(`
|
|
159
|
+
console.log(chalk.gray(` Reason: ${error.message}`));
|
|
130
160
|
}
|
|
131
161
|
}
|
|
132
|
-
} else {
|
|
133
|
-
console.log(chalk.gray('\n Skipping dependency installation (--no-install)'));
|
|
134
162
|
}
|
|
135
163
|
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
164
|
+
// ============================================
|
|
165
|
+
// SUCCESS!
|
|
166
|
+
// ============================================
|
|
167
|
+
console.log('\n');
|
|
168
|
+
displaySuccessMessage(answers, projectPath);
|
|
139
169
|
} catch (error) {
|
|
140
170
|
// Stop any running spinners
|
|
141
171
|
if (spinner && spinner.isSpinning) {
|
|
142
|
-
spinner.fail(chalk.red('Project creation failed'));
|
|
172
|
+
spinner.fail(chalk.red('✗ Project creation failed'));
|
|
143
173
|
}
|
|
144
174
|
|
|
175
|
+
console.log(chalk.red('\n✗ Error: ' + error.message));
|
|
176
|
+
|
|
177
|
+
// Rollback project directory
|
|
178
|
+
await rollbackProject(projectPath);
|
|
179
|
+
|
|
145
180
|
// If it's already a CLIError, just re-throw it
|
|
146
181
|
if (error instanceof CLIError) {
|
|
147
182
|
throw error;
|
|
148
183
|
}
|
|
149
184
|
|
|
150
185
|
// Wrap unexpected errors
|
|
151
|
-
throw new CLIError(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
);
|
|
186
|
+
throw new CLIError(`Failed to create project: ${error.message}`, ERROR_CODES.CREATION_FAILED, {
|
|
187
|
+
originalError: error.name,
|
|
188
|
+
path: projectPath,
|
|
189
|
+
});
|
|
156
190
|
}
|
|
157
191
|
}
|
|
158
192
|
|
|
159
193
|
/**
|
|
160
|
-
* Display
|
|
194
|
+
* Display success message after project creation
|
|
161
195
|
* @param {Object} answers - Project configuration
|
|
162
196
|
* @param {string} projectPath - Path to the project
|
|
163
|
-
* @param {boolean} verbose - Show detailed information
|
|
164
197
|
*/
|
|
165
|
-
function
|
|
198
|
+
function displaySuccessMessage(answers, projectPath) {
|
|
199
|
+
const projectName = path.basename(projectPath);
|
|
200
|
+
|
|
201
|
+
console.log(chalk.green.bold('🎉 Project created successfully!\n'));
|
|
202
|
+
console.log(chalk.cyan('Next steps:'));
|
|
203
|
+
console.log(chalk.white(` cd ${projectName}`));
|
|
204
|
+
console.log(chalk.white(` ${answers.packageManager} run dev\n`));
|
|
205
|
+
|
|
206
|
+
// Show installed add-ons
|
|
207
|
+
if (hasAddons(answers)) {
|
|
208
|
+
console.log(chalk.cyan('Installed add-ons:'));
|
|
209
|
+
if (answers.stateManagement && answers.stateManagement !== 'none') {
|
|
210
|
+
console.log(chalk.white(` ✓ State management: ${answers.stateManagement}`));
|
|
211
|
+
}
|
|
212
|
+
if (answers.uiLibrary && answers.uiLibrary !== 'none') {
|
|
213
|
+
console.log(chalk.white(` ✓ UI library: ${answers.uiLibrary}`));
|
|
214
|
+
}
|
|
215
|
+
if (answers.orm && answers.orm !== 'none') {
|
|
216
|
+
console.log(chalk.white(` ✓ ORM: ${answers.orm}`));
|
|
217
|
+
}
|
|
218
|
+
if (answers.authentication && answers.authentication !== 'none') {
|
|
219
|
+
console.log(chalk.white(` ✓ Authentication: ${answers.authentication}`));
|
|
220
|
+
}
|
|
221
|
+
if (answers.testing && answers.testing.length > 0) {
|
|
222
|
+
console.log(chalk.white(` ✓ Testing: ${answers.testing.join(', ')}`));
|
|
223
|
+
}
|
|
224
|
+
console.log();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
console.log(chalk.gray('Happy coding! 🚀\n'));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** * Get install command for package manager
|
|
231
|
+
*/
|
|
232
|
+
function getInstallCommand(packageManager) {
|
|
233
|
+
const commands = {
|
|
234
|
+
npm: 'npm install',
|
|
235
|
+
yarn: 'yarn install',
|
|
236
|
+
pnpm: 'pnpm install',
|
|
237
|
+
bun: 'bun install',
|
|
238
|
+
};
|
|
239
|
+
return commands[packageManager] || 'npm install';
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** * Display comprehensive success summary after project creation (LEGACY - DEPRECATED)
|
|
243
|
+
* This function is kept for backward compatibility but is no longer used
|
|
244
|
+
* @deprecated Use displaySuccessMessage instead
|
|
245
|
+
*/
|
|
246
|
+
function displaySuccessSummary(answers, projectPath, _verbose = false) {
|
|
166
247
|
console.log('');
|
|
167
248
|
console.log(chalk.green('╔════════════════════════════════════════════════════════════╗'));
|
|
168
|
-
console.log(
|
|
249
|
+
console.log(
|
|
250
|
+
chalk.green('║') +
|
|
251
|
+
chalk.green.bold(' ✨ Project Created Successfully! ✨ ') +
|
|
252
|
+
chalk.green('║')
|
|
253
|
+
);
|
|
169
254
|
console.log(chalk.green('╚════════════════════════════════════════════════════════════╝'));
|
|
170
255
|
console.log('');
|
|
171
256
|
|
|
@@ -173,20 +258,18 @@ function displaySuccessSummary(answers, projectPath, verbose = false) {
|
|
|
173
258
|
console.log(chalk.cyan.bold(' 📦 Project Information'));
|
|
174
259
|
console.log(chalk.white(` ${chalk.gray('Name:')} ${chalk.bold(answers.projectName)}`));
|
|
175
260
|
console.log(chalk.white(` ${chalk.gray('Type:')} ${answers.projectType}`));
|
|
176
|
-
console.log(
|
|
177
|
-
|
|
261
|
+
console.log(
|
|
262
|
+
chalk.white(` ${chalk.gray('Language:')} ${answers.language || 'JavaScript'}`)
|
|
263
|
+
);
|
|
264
|
+
|
|
178
265
|
if (answers.frontend) {
|
|
179
266
|
console.log(chalk.white(` ${chalk.gray('Frontend:')} ${answers.frontend}`));
|
|
180
267
|
}
|
|
181
|
-
|
|
268
|
+
|
|
182
269
|
if (answers.backend) {
|
|
183
270
|
console.log(chalk.white(` ${chalk.gray('Backend:')} ${answers.backend}`));
|
|
184
271
|
}
|
|
185
272
|
|
|
186
|
-
if (answers.fullstackType) {
|
|
187
|
-
console.log(chalk.white(` ${chalk.gray('Architecture:')} ${answers.fullstackType}`));
|
|
188
|
-
}
|
|
189
|
-
|
|
190
273
|
if (answers.database && answers.database !== 'none') {
|
|
191
274
|
console.log(chalk.white(` ${chalk.gray('Database:')} ${answers.database}`));
|
|
192
275
|
}
|
|
@@ -200,7 +283,7 @@ function displaySuccessSummary(answers, projectPath, verbose = false) {
|
|
|
200
283
|
// Features section
|
|
201
284
|
if (answers.features && answers.features.length > 0) {
|
|
202
285
|
console.log(chalk.cyan.bold(' ⚙️ Configured Features'));
|
|
203
|
-
answers.features.forEach(feature => {
|
|
286
|
+
answers.features.forEach((feature) => {
|
|
204
287
|
console.log(chalk.white(` ${chalk.green('✓')} ${feature}`));
|
|
205
288
|
});
|
|
206
289
|
console.log('');
|
|
@@ -209,7 +292,7 @@ function displaySuccessSummary(answers, projectPath, verbose = false) {
|
|
|
209
292
|
// Additional libraries
|
|
210
293
|
if (answers.additionalLibraries && answers.additionalLibraries.length > 0) {
|
|
211
294
|
console.log(chalk.cyan.bold(' 📚 Additional Libraries'));
|
|
212
|
-
answers.additionalLibraries.slice(0, 5).forEach(lib => {
|
|
295
|
+
answers.additionalLibraries.slice(0, 5).forEach((lib) => {
|
|
213
296
|
console.log(chalk.white(` ${chalk.green('✓')} ${lib}`));
|
|
214
297
|
});
|
|
215
298
|
if (answers.additionalLibraries.length > 5) {
|
|
@@ -232,19 +315,25 @@ function displaySuccessSummary(answers, projectPath, verbose = false) {
|
|
|
232
315
|
console.log(chalk.white(` ${chalk.yellow('1.')} Navigate to your project:`));
|
|
233
316
|
console.log(chalk.gray(` cd ${answers.projectName}`));
|
|
234
317
|
console.log('');
|
|
235
|
-
|
|
318
|
+
|
|
236
319
|
if (!packagesInstalled) {
|
|
237
320
|
console.log(chalk.white(` ${chalk.yellow('2.')} Install dependencies:`));
|
|
238
321
|
console.log(chalk.gray(` ${answers.packageManager} install`));
|
|
239
322
|
console.log('');
|
|
240
323
|
}
|
|
241
|
-
|
|
324
|
+
|
|
242
325
|
const stepNum = packagesInstalled ? 2 : 3;
|
|
243
326
|
console.log(chalk.white(` ${chalk.yellow(stepNum + '.')} Start development server:`));
|
|
244
|
-
console.log(
|
|
327
|
+
console.log(
|
|
328
|
+
chalk.gray(
|
|
329
|
+
` ${answers.packageManager} ${answers.packageManager === 'npm' ? 'run ' : ''}dev`
|
|
330
|
+
)
|
|
331
|
+
);
|
|
245
332
|
console.log('');
|
|
246
|
-
|
|
247
|
-
console.log(
|
|
333
|
+
|
|
334
|
+
console.log(
|
|
335
|
+
chalk.white(` ${chalk.yellow(stepNum + 1 + '.')} Read the README for more info:`)
|
|
336
|
+
);
|
|
248
337
|
console.log(chalk.gray(` cat README.md`));
|
|
249
338
|
console.log('');
|
|
250
339
|
|
package/src/prompts/questions.js
CHANGED
|
@@ -54,7 +54,6 @@ function getQuestions(initialProjectName) {
|
|
|
54
54
|
choices: [
|
|
55
55
|
{ name: 'Frontend Only', value: 'frontend' },
|
|
56
56
|
{ name: 'Backend Only', value: 'backend' },
|
|
57
|
-
{ name: 'Full Stack', value: 'fullstack' },
|
|
58
57
|
{ name: 'Node.js Library/Package', value: 'library' },
|
|
59
58
|
],
|
|
60
59
|
},
|
|
@@ -68,7 +67,6 @@ function getQuestions(initialProjectName) {
|
|
|
68
67
|
const typeDefaults = {
|
|
69
68
|
frontend: 'my-frontend-app',
|
|
70
69
|
backend: 'my-backend-api',
|
|
71
|
-
fullstack: 'my-fullstack-app',
|
|
72
70
|
library: 'my-package',
|
|
73
71
|
};
|
|
74
72
|
return typeDefaults[answers.projectType] || 'my-awesome-project';
|
|
@@ -119,41 +117,7 @@ function getQuestions(initialProjectName) {
|
|
|
119
117
|
{ name: 'Next.js (React)', value: 'nextjs' },
|
|
120
118
|
{ name: 'Vue.js + Vite', value: 'vue' },
|
|
121
119
|
],
|
|
122
|
-
when: (answers) =>
|
|
123
|
-
},
|
|
124
|
-
// Full-stack architecture type
|
|
125
|
-
{
|
|
126
|
-
type: 'list',
|
|
127
|
-
name: 'fullstackType',
|
|
128
|
-
message: 'Choose your full-stack architecture:',
|
|
129
|
-
choices: [
|
|
130
|
-
{ name: 'Monorepo (apps/ + packages/)', value: 'monorepo' },
|
|
131
|
-
{ name: 'Traditional (separate client/ + server/)', value: 'traditional' },
|
|
132
|
-
],
|
|
133
|
-
when: (answers) => answers.projectType === 'fullstack',
|
|
134
|
-
},
|
|
135
|
-
// Full-stack stack selection
|
|
136
|
-
{
|
|
137
|
-
type: 'list',
|
|
138
|
-
name: 'stack',
|
|
139
|
-
message: 'Choose your full-stack:',
|
|
140
|
-
choices: (answers) => {
|
|
141
|
-
if (answers.fullstackType === 'monorepo') {
|
|
142
|
-
return [
|
|
143
|
-
{ name: 'Next.js + Express + MongoDB', value: 'Next.js + Express + MongoDB' },
|
|
144
|
-
{ name: 'Next.js + Express + PostgreSQL', value: 'Next.js + Express + PostgreSQL' },
|
|
145
|
-
{ name: 'React + Express + MongoDB', value: 'React + Express + MongoDB' },
|
|
146
|
-
{ name: 'React + Express + PostgreSQL', value: 'React + Express + PostgreSQL' },
|
|
147
|
-
];
|
|
148
|
-
}
|
|
149
|
-
return [
|
|
150
|
-
{ name: 'MERN (MongoDB + Express + React + Node)', value: 'MERN' },
|
|
151
|
-
{ name: 'PERN (PostgreSQL + Express + React + Node)', value: 'PERN' },
|
|
152
|
-
{ name: 'Next.js + Express', value: 'Next.js + Express' },
|
|
153
|
-
{ name: 'Laravel + React', value: 'Laravel + React' },
|
|
154
|
-
];
|
|
155
|
-
},
|
|
156
|
-
when: (answers) => answers.projectType === 'fullstack',
|
|
120
|
+
when: (answers) => answers.projectType === 'frontend',
|
|
157
121
|
},
|
|
158
122
|
// Backend framework selection
|
|
159
123
|
{
|
|
@@ -264,6 +228,98 @@ function getQuestions(initialProjectName) {
|
|
|
264
228
|
],
|
|
265
229
|
when: (answers) => answers.projectType === 'frontend',
|
|
266
230
|
},
|
|
231
|
+
// State Management (Frontend)
|
|
232
|
+
{
|
|
233
|
+
type: 'list',
|
|
234
|
+
name: 'stateManagement',
|
|
235
|
+
message: 'Choose your state management solution:',
|
|
236
|
+
choices: [
|
|
237
|
+
{ name: 'None (React Context API only)', value: 'none' },
|
|
238
|
+
{ name: 'Redux Toolkit (Official Redux)', value: 'redux-toolkit' },
|
|
239
|
+
{ name: 'Zustand (Lightweight)', value: 'zustand' },
|
|
240
|
+
{ name: 'Jotai (Atomic)', value: 'jotai' },
|
|
241
|
+
{ name: 'Recoil (Atomic)', value: 'recoil' },
|
|
242
|
+
{ name: 'Pinia (Vue)', value: 'pinia' },
|
|
243
|
+
],
|
|
244
|
+
default: 'none',
|
|
245
|
+
when: (answers) => answers.projectType === 'frontend' && answers.frontend !== 'nextjs',
|
|
246
|
+
},
|
|
247
|
+
// UI Component Library (Frontend)
|
|
248
|
+
{
|
|
249
|
+
type: 'list',
|
|
250
|
+
name: 'uiLibrary',
|
|
251
|
+
message: 'Choose a UI component library (optional):',
|
|
252
|
+
choices: [
|
|
253
|
+
{ name: 'None', value: 'none' },
|
|
254
|
+
{ name: 'shadcn/ui (Radix + Tailwind)', value: 'shadcn' },
|
|
255
|
+
{ name: 'Material-UI (MUI)', value: 'mui' },
|
|
256
|
+
{ name: 'Ant Design', value: 'antd' },
|
|
257
|
+
{ name: 'Chakra UI', value: 'chakra' },
|
|
258
|
+
{ name: 'Mantine', value: 'mantine' },
|
|
259
|
+
{ name: 'DaisyUI (Tailwind)', value: 'daisyui' },
|
|
260
|
+
],
|
|
261
|
+
default: 'none',
|
|
262
|
+
when: (answers) => answers.projectType === 'frontend',
|
|
263
|
+
},
|
|
264
|
+
// ORM/Database Tool (Backend)
|
|
265
|
+
{
|
|
266
|
+
type: 'list',
|
|
267
|
+
name: 'orm',
|
|
268
|
+
message: 'Choose an ORM/database tool:',
|
|
269
|
+
choices: [
|
|
270
|
+
{ name: 'None', value: 'none' },
|
|
271
|
+
{ name: 'Prisma (Type-safe ORM)', value: 'prisma' },
|
|
272
|
+
{ name: 'Drizzle (Lightweight ORM)', value: 'drizzle' },
|
|
273
|
+
{ name: 'TypeORM', value: 'typeorm' },
|
|
274
|
+
{ name: 'Mongoose (MongoDB)', value: 'mongoose' },
|
|
275
|
+
],
|
|
276
|
+
default: 'none',
|
|
277
|
+
when: (answers) => answers.projectType === 'backend',
|
|
278
|
+
},
|
|
279
|
+
// Database Selection (if ORM selected)
|
|
280
|
+
{
|
|
281
|
+
type: 'list',
|
|
282
|
+
name: 'database',
|
|
283
|
+
message: 'Choose your database:',
|
|
284
|
+
choices: [
|
|
285
|
+
{ name: 'PostgreSQL', value: 'postgresql' },
|
|
286
|
+
{ name: 'MySQL', value: 'mysql' },
|
|
287
|
+
{ name: 'SQLite', value: 'sqlite' },
|
|
288
|
+
{ name: 'MongoDB', value: 'mongodb' },
|
|
289
|
+
],
|
|
290
|
+
default: 'postgresql',
|
|
291
|
+
when: (answers) => answers.orm && answers.orm !== 'none' && answers.orm !== 'mongoose',
|
|
292
|
+
},
|
|
293
|
+
// Authentication (Frontend/Backend)
|
|
294
|
+
{
|
|
295
|
+
type: 'list',
|
|
296
|
+
name: 'authentication',
|
|
297
|
+
message: 'Choose an authentication solution:',
|
|
298
|
+
choices: [
|
|
299
|
+
{ name: 'None', value: 'none' },
|
|
300
|
+
{ name: 'NextAuth.js', value: 'nextauth' },
|
|
301
|
+
{ name: 'Clerk', value: 'clerk' },
|
|
302
|
+
{ name: 'Supabase Auth', value: 'supabase' },
|
|
303
|
+
{ name: 'Auth0', value: 'auth0' },
|
|
304
|
+
{ name: 'Lucia', value: 'lucia' },
|
|
305
|
+
],
|
|
306
|
+
default: 'none',
|
|
307
|
+
when: (answers) => ['frontend', 'backend'].includes(answers.projectType),
|
|
308
|
+
},
|
|
309
|
+
// Testing Frameworks
|
|
310
|
+
{
|
|
311
|
+
type: 'checkbox',
|
|
312
|
+
name: 'testing',
|
|
313
|
+
message: 'Select testing frameworks:',
|
|
314
|
+
choices: [
|
|
315
|
+
{ name: 'Vitest (Unit/Integration)', value: 'vitest', checked: false },
|
|
316
|
+
{ name: 'Jest (Unit/Integration)', value: 'jest', checked: false },
|
|
317
|
+
{ name: 'Playwright (E2E)', value: 'playwright', checked: false },
|
|
318
|
+
{ name: 'Cypress (E2E)', value: 'cypress', checked: false },
|
|
319
|
+
{ name: 'React Testing Library', value: 'testing-library', checked: false },
|
|
320
|
+
],
|
|
321
|
+
when: (answers) => ['frontend', 'backend'].includes(answers.projectType),
|
|
322
|
+
},
|
|
267
323
|
// Additional Libraries (Multi-select)
|
|
268
324
|
{
|
|
269
325
|
type: 'checkbox',
|
|
@@ -301,11 +357,11 @@ function getQuestions(initialProjectName) {
|
|
|
301
357
|
|
|
302
358
|
let choices = [...commonChoices];
|
|
303
359
|
|
|
304
|
-
if (
|
|
360
|
+
if (answers.projectType === 'frontend') {
|
|
305
361
|
choices = [...choices, ...frontendChoices];
|
|
306
362
|
}
|
|
307
363
|
|
|
308
|
-
if (
|
|
364
|
+
if (answers.projectType === 'backend') {
|
|
309
365
|
choices = [...choices, ...backendChoices];
|
|
310
366
|
}
|
|
311
367
|
|