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.
@@ -0,0 +1,304 @@
1
+ import path from 'path';
2
+ import { execCommand } from './cliRunner.js';
3
+ import chalk from 'chalk';
4
+
5
+ /**
6
+ * Bootstrap a project using official framework CLIs
7
+ *
8
+ * This function delegates project creation to official framework CLIs
9
+ * instead of manually creating files. This ensures we always use the
10
+ * latest best practices and configurations from framework maintainers.
11
+ *
12
+ * @param {string} projectPath - Absolute path to the project directory
13
+ * @param {Object} config - User configuration object
14
+ * @returns {Promise<void>}
15
+ */
16
+ export async function bootstrapWithOfficialCLI(projectPath, config) {
17
+ const { projectType, frontend, backend } = config;
18
+
19
+ switch (projectType) {
20
+ case 'frontend':
21
+ return bootstrapFrontend(projectPath, config);
22
+
23
+ case 'backend':
24
+ return bootstrapBackend(projectPath, config);
25
+
26
+ default:
27
+ throw new Error(`Unsupported project type: ${projectType}`);
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Bootstrap a frontend project
33
+ */
34
+ async function bootstrapFrontend(projectPath, config) {
35
+ const { frontend } = config;
36
+
37
+ switch (frontend) {
38
+ case 'nextjs':
39
+ return bootstrapNextjs(projectPath, config);
40
+
41
+ case 'react':
42
+ return bootstrapReact(projectPath, config);
43
+
44
+ case 'vue':
45
+ return bootstrapVue(projectPath, config);
46
+
47
+ case 'nuxt':
48
+ return bootstrapNuxt(projectPath, config);
49
+
50
+ case 'svelte':
51
+ return bootstrapSvelte(projectPath, config);
52
+
53
+ default:
54
+ throw new Error(`Unsupported frontend framework: ${frontend}`);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Bootstrap a backend project
60
+ */
61
+ async function bootstrapBackend(projectPath, config) {
62
+ const { backend } = config;
63
+
64
+ switch (backend) {
65
+ case 'express':
66
+ return bootstrapExpress(projectPath, config);
67
+
68
+ case 'nestjs':
69
+ return bootstrapNestJS(projectPath, config);
70
+
71
+ case 'fastify':
72
+ return bootstrapFastify(projectPath, config);
73
+
74
+ default:
75
+ throw new Error(`Unsupported backend framework: ${backend}`);
76
+ }
77
+ }
78
+
79
+ // ============================================
80
+ // Frontend Framework Bootstrappers
81
+ // ============================================
82
+
83
+ /**
84
+ * Bootstrap Next.js project using create-next-app
85
+ *
86
+ * @param {string} projectPath - Absolute path to project
87
+ * @param {Object} config - Configuration object
88
+ */
89
+ export async function bootstrapNextjs(projectPath, config) {
90
+ const { language, styling, packageManager = 'npm' } = config;
91
+ const projectName = path.basename(projectPath);
92
+ const parentDir = path.dirname(projectPath);
93
+
94
+ console.log(chalk.cyan(`\nšŸ“¦ Creating Next.js project...`));
95
+ console.log(
96
+ chalk.gray(` Language: ${language === 'typescript' ? 'TypeScript' : 'JavaScript'}`)
97
+ );
98
+ console.log(chalk.gray(` Styling: ${styling || 'CSS'}`));
99
+ console.log(chalk.gray(` Package Manager: ${packageManager}\n`));
100
+
101
+ const args = ['create-next-app@latest', projectName];
102
+
103
+ // Language
104
+ if (language === 'typescript') {
105
+ args.push('--typescript');
106
+ } else {
107
+ args.push('--javascript');
108
+ }
109
+
110
+ // Styling - check if user wants Tailwind
111
+ if (styling === 'tailwind' || styling === 'tailwindcss') {
112
+ args.push('--tailwind');
113
+ } else {
114
+ args.push('--no-tailwind');
115
+ }
116
+
117
+ // Default options
118
+ args.push('--eslint'); // Always include ESLint
119
+ args.push('--app'); // Use App Router
120
+ args.push('--src-dir'); // Use src directory
121
+ args.push('--import-alias', '@/*'); // Set import alias
122
+ args.push('--no-git'); // We handle git separately
123
+
124
+ // Package manager
125
+ args.push(`--use-${packageManager}`);
126
+
127
+ // Skip installation - we'll install add-ons after
128
+ args.push('--skip-install');
129
+
130
+ console.log(chalk.dim(` Command: npx ${args.join(' ')}\n`));
131
+
132
+ await execCommand(`npx ${args.join(' ')}`, {
133
+ cwd: parentDir,
134
+ });
135
+ }
136
+
137
+ /**
138
+ * Bootstrap React project using Vite
139
+ *
140
+ * @param {string} projectPath - Absolute path to project
141
+ * @param {Object} config - Configuration object
142
+ */
143
+ export async function bootstrapReact(projectPath, config) {
144
+ const { language = 'typescript', packageManager = 'npm' } = config;
145
+ const projectName = path.basename(projectPath);
146
+ const parentDir = path.dirname(projectPath);
147
+ const template = language === 'typescript' ? 'react-ts' : 'react';
148
+
149
+ console.log(chalk.cyan(`\nšŸ“¦ Creating React project with Vite...`));
150
+ console.log(
151
+ chalk.gray(` Language: ${language === 'typescript' ? 'TypeScript' : 'JavaScript'}`)
152
+ );
153
+ console.log(chalk.gray(` Template: ${template}`));
154
+ console.log(chalk.gray(` Package Manager: ${packageManager}\n`));
155
+
156
+ // Use create-vite 5.1.0 which is more stable and doesn't auto-start dev server
157
+ // The --template flag should make it non-interactive
158
+ const command = `npx create-vite@5.1.0 ${projectName} --template ${template}`;
159
+ console.log(chalk.dim(` Command: ${command}\n`));
160
+
161
+ await execCommand(command, {
162
+ cwd: parentDir,
163
+ });
164
+ }
165
+
166
+ /**
167
+ * Bootstrap Vue project
168
+ *
169
+ * @param {string} projectPath - Absolute path to project
170
+ * @param {Object} config - Configuration object
171
+ */
172
+ export async function bootstrapVue(projectPath, config) {
173
+ const { language = 'typescript', packageManager = 'npm' } = config;
174
+ const projectName = path.basename(projectPath);
175
+ const parentDir = path.dirname(projectPath);
176
+
177
+ console.log(chalk.cyan(`\nšŸ“¦ Creating Vue project...`));
178
+ console.log(
179
+ chalk.gray(` Language: ${language === 'typescript' ? 'TypeScript' : 'JavaScript'}`)
180
+ );
181
+ console.log(chalk.gray(` Package Manager: ${packageManager}\n`));
182
+
183
+ // Use --typescript and --default flags to create non-interactive TypeScript project
184
+ const flags = language === 'typescript' ? '--typescript --default' : '--default';
185
+ const command = `npm create vue@latest ${projectName} -- ${flags}`;
186
+ console.log(chalk.dim(` Command: ${command}\n`));
187
+
188
+ await execCommand(command, { cwd: parentDir });
189
+ }
190
+
191
+ /**
192
+ * Bootstrap Nuxt project
193
+ *
194
+ * @param {string} projectPath - Absolute path to project
195
+ * @param {Object} config - Configuration object
196
+ */
197
+ export async function bootstrapNuxt(projectPath, config) {
198
+ const { packageManager = 'npm' } = config;
199
+ const projectName = path.basename(projectPath);
200
+ const parentDir = path.dirname(projectPath);
201
+
202
+ console.log(chalk.cyan(`\nšŸ“¦ Creating Nuxt project...`));
203
+ console.log(chalk.gray(` Package Manager: ${packageManager}\n`));
204
+
205
+ const command = `npx nuxi@latest init ${projectName} --packageManager ${packageManager}`;
206
+ console.log(chalk.dim(` Command: ${command}\n`));
207
+
208
+ await execCommand(command, { cwd: parentDir });
209
+ }
210
+
211
+ /**
212
+ * Bootstrap Svelte project
213
+ *
214
+ * @param {string} projectPath - Absolute path to project
215
+ * @param {Object} config - Configuration object
216
+ */
217
+ export async function bootstrapSvelte(projectPath, config) {
218
+ const { packageManager = 'npm' } = config;
219
+ const projectName = path.basename(projectPath);
220
+ const parentDir = path.dirname(projectPath);
221
+
222
+ console.log(chalk.cyan(`\nšŸ“¦ Creating Svelte project...`));
223
+ console.log(chalk.gray(` Package Manager: ${packageManager}\n`));
224
+
225
+ const command = `npm create svelte@latest ${projectName} -y`;
226
+ console.log(chalk.dim(` Command: ${command}\n`));
227
+
228
+ await execCommand(command, { cwd: parentDir });
229
+ }
230
+
231
+ // ============================================
232
+ // Backend Framework Bootstrappers
233
+ // ============================================
234
+
235
+ /**
236
+ * Bootstrap Express project
237
+ *
238
+ * @param {string} projectPath - Absolute path to project
239
+ * @param {Object} config - Configuration object
240
+ */
241
+ export async function bootstrapExpress(projectPath, config) {
242
+ const { language, packageManager = 'npm' } = config;
243
+ const projectName = path.basename(projectPath);
244
+ const parentDir = path.dirname(projectPath);
245
+
246
+ console.log(chalk.cyan(`\nšŸ“¦ Creating Express project...`));
247
+ console.log(
248
+ chalk.gray(` Language: ${language === 'typescript' ? 'TypeScript' : 'JavaScript'}\n`)
249
+ );
250
+
251
+ // Express doesn't have a modern CLI, so we'll use express-generator
252
+ const command = `npx express-generator --no-view --git ${projectName}`;
253
+ console.log(chalk.dim(` Command: ${command}\n`));
254
+
255
+ await execCommand(command, { cwd: parentDir });
256
+
257
+ // If TypeScript, we'll need to convert it later in the template generator
258
+ if (language === 'typescript') {
259
+ console.log(chalk.yellow(' TypeScript setup will be added in the next step...\n'));
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Bootstrap NestJS project
265
+ *
266
+ * @param {string} projectPath - Absolute path to project
267
+ * @param {Object} config - Configuration object
268
+ */
269
+ export async function bootstrapNestJS(projectPath, config) {
270
+ const { packageManager = 'npm' } = config;
271
+ const projectName = path.basename(projectPath);
272
+ const parentDir = path.dirname(projectPath);
273
+
274
+ console.log(chalk.cyan(`\nšŸ“¦ Creating NestJS project...`));
275
+ console.log(chalk.gray(` Language: TypeScript (NestJS default)`));
276
+ console.log(chalk.gray(` Package Manager: ${packageManager}\n`));
277
+
278
+ const command = `npx @nestjs/cli new ${projectName} --package-manager ${packageManager} --skip-git --skip-install`;
279
+ console.log(chalk.dim(` Command: ${command}\n`));
280
+
281
+ await execCommand(command, { cwd: parentDir });
282
+ }
283
+
284
+ /**
285
+ * Bootstrap Fastify project
286
+ *
287
+ * @param {string} projectPath - Absolute path to project
288
+ * @param {Object} config - Configuration object
289
+ */
290
+ export async function bootstrapFastify(projectPath, config) {
291
+ const { language = 'javascript' } = config;
292
+ const projectName = path.basename(projectPath);
293
+ const parentDir = path.dirname(projectPath);
294
+
295
+ console.log(chalk.cyan(`\nšŸ“¦ Creating Fastify project...`));
296
+ console.log(
297
+ chalk.gray(` Language: ${language === 'typescript' ? 'TypeScript' : 'JavaScript'}\n`)
298
+ );
299
+
300
+ const command = `npx fastify-cli generate ${projectName}`;
301
+ console.log(chalk.dim(` Command: ${command}\n`));
302
+
303
+ await execCommand(command, { cwd: parentDir });
304
+ }