zerostart-cli 0.0.35 → 0.0.37
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 +270 -248
- package/out/cli.js +532 -28
- package/out/managers/ProjectManager.js +83 -31
- package/out/managers/TemplateManager.js +227 -212
- package/out/types.js +1 -1
- package/package.json +47 -54
package/out/cli.js
CHANGED
|
@@ -132,24 +132,23 @@ async function initializeProject(name, language, type, options) {
|
|
|
132
132
|
console.log(chalk_1.default.bold.green(' Success! Your project is ready!'));
|
|
133
133
|
console.log(chalk_1.default.gray(' Location: ') + chalk_1.default.cyan(projectPath));
|
|
134
134
|
console.log();
|
|
135
|
-
|
|
136
|
-
const isPractice = type === types_1.ProjectType.DSAPractice;
|
|
137
|
-
if (!isWeb || isPractice) {
|
|
135
|
+
if ([types_1.ProjectLanguage.Python, types_1.ProjectLanguage.Java, types_1.ProjectLanguage.CPP].includes(language)) {
|
|
138
136
|
const gdbLinks = {
|
|
139
137
|
[types_1.ProjectLanguage.Python]: 'https://www.onlinegdb.com/online_python_compiler',
|
|
140
138
|
[types_1.ProjectLanguage.Java]: 'https://www.onlinegdb.com/online_java_compiler',
|
|
141
|
-
[types_1.ProjectLanguage.CPP]: 'https://www.onlinegdb.com/online_c++_compiler'
|
|
142
|
-
[types_1.ProjectLanguage.NodeJS]: 'https://www.onlinegdb.com/online_node.js_compiler',
|
|
143
|
-
[types_1.ProjectLanguage.React]: 'https://www.onlinegdb.com/'
|
|
139
|
+
[types_1.ProjectLanguage.CPP]: 'https://www.onlinegdb.com/online_c++_compiler'
|
|
144
140
|
};
|
|
145
|
-
const link = gdbLinks[language]
|
|
141
|
+
const link = gdbLinks[language];
|
|
146
142
|
console.log(chalk_1.default.bold.yellow(' Practice Online:'));
|
|
147
143
|
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan(link));
|
|
148
144
|
console.log(chalk_1.default.gray(' (Opening in your browser...)'));
|
|
149
145
|
openUrl(link);
|
|
150
|
-
return;
|
|
151
146
|
}
|
|
152
|
-
|
|
147
|
+
if (language === types_1.ProjectLanguage.HTMLCSS) {
|
|
148
|
+
console.log(chalk_1.default.bold.cyan('\n Deployment:'));
|
|
149
|
+
console.log(chalk_1.default.gray(' To deploy to Vercel, run: ') + chalk_1.default.white('zerostart deploy-vercel'));
|
|
150
|
+
}
|
|
151
|
+
console.log(chalk_1.default.bold('\n Get started:'));
|
|
153
152
|
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan(`cd ${name}`));
|
|
154
153
|
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan('code .') + chalk_1.default.gray(' (or your favorite editor)'));
|
|
155
154
|
console.log();
|
|
@@ -161,7 +160,410 @@ async function initializeProject(name, language, type, options) {
|
|
|
161
160
|
program
|
|
162
161
|
.name('zerostart')
|
|
163
162
|
.description('Create and deploy a complete project with one command')
|
|
164
|
-
.version('0.0.
|
|
163
|
+
.version('0.0.37');
|
|
164
|
+
// zerostart init [project-name]
|
|
165
|
+
program
|
|
166
|
+
.command('init [project-name]')
|
|
167
|
+
.description('Initialize a new project with interactive prompts')
|
|
168
|
+
.action(async (projectName) => {
|
|
169
|
+
showBanner();
|
|
170
|
+
const answers = await inquirer_1.default.prompt([
|
|
171
|
+
{ type: 'input', name: 'name', message: 'Project Name:', when: !projectName, default: 'my-project' },
|
|
172
|
+
{
|
|
173
|
+
type: 'list',
|
|
174
|
+
name: 'language',
|
|
175
|
+
message: 'Select Template:',
|
|
176
|
+
choices: [
|
|
177
|
+
types_1.ProjectLanguage.React,
|
|
178
|
+
types_1.ProjectLanguage.TypeScript,
|
|
179
|
+
types_1.ProjectLanguage.HTMLCSS,
|
|
180
|
+
types_1.ProjectLanguage.CPP,
|
|
181
|
+
types_1.ProjectLanguage.Java,
|
|
182
|
+
types_1.ProjectLanguage.Python
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
]);
|
|
186
|
+
const selectedLang = answers.language;
|
|
187
|
+
let createRemote = false;
|
|
188
|
+
let githubToken = null;
|
|
189
|
+
if (selectedLang === types_1.ProjectLanguage.React || selectedLang === types_1.ProjectLanguage.TypeScript) {
|
|
190
|
+
const { github } = await inquirer_1.default.prompt([
|
|
191
|
+
{ type: 'confirm', name: 'github', message: 'Do you want to add this to GitHub?', default: true }
|
|
192
|
+
]);
|
|
193
|
+
if (github) {
|
|
194
|
+
createRemote = true;
|
|
195
|
+
showGitHubTokenHelp();
|
|
196
|
+
const { token } = await inquirer_1.default.prompt([
|
|
197
|
+
{ type: 'password', name: 'token', message: 'Enter your GitHub Personal Access Token:', validate: (input) => input.length > 0 || 'Token is required' }
|
|
198
|
+
]);
|
|
199
|
+
githubToken = token;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
let type = types_1.ProjectType.WebApp;
|
|
203
|
+
if (selectedLang === types_1.ProjectLanguage.TypeScript)
|
|
204
|
+
type = types_1.ProjectType.CLITool;
|
|
205
|
+
if ([types_1.ProjectLanguage.CPP, types_1.ProjectLanguage.Java, types_1.ProjectLanguage.Python].includes(selectedLang))
|
|
206
|
+
type = types_1.ProjectType.DSAPractice;
|
|
207
|
+
await initializeProject(projectName || answers.name, selectedLang, type, {
|
|
208
|
+
isPublic: false,
|
|
209
|
+
createRemote: createRemote,
|
|
210
|
+
githubToken: githubToken,
|
|
211
|
+
authMethod: 'none'
|
|
212
|
+
});
|
|
213
|
+
if (selectedLang === types_1.ProjectLanguage.HTMLCSS) {
|
|
214
|
+
const { deploy } = await inquirer_1.default.prompt([
|
|
215
|
+
{ type: 'confirm', name: 'deploy', message: 'Do you want to deploy to Vercel right now?', default: true }
|
|
216
|
+
]);
|
|
217
|
+
if (deploy) {
|
|
218
|
+
const vercelManager = new VercelManager_1.VercelManager();
|
|
219
|
+
const projectPath = path.join(process.cwd(), projectName || answers.name);
|
|
220
|
+
if (await vercelManager.checkAuth()) {
|
|
221
|
+
await vercelManager.deploy(projectPath, projectName || answers.name);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
// zerostart deploy
|
|
227
|
+
program
|
|
228
|
+
.command('deploy')
|
|
229
|
+
.description('Deploy your project to a hosting provider')
|
|
230
|
+
.action(async () => {
|
|
231
|
+
showBanner();
|
|
232
|
+
const { provider } = await inquirer_1.default.prompt([{
|
|
233
|
+
type: 'list',
|
|
234
|
+
name: 'provider',
|
|
235
|
+
message: 'Choose deployment provider:',
|
|
236
|
+
choices: ['Vercel', 'Netlify', 'GitHub Pages']
|
|
237
|
+
}]);
|
|
238
|
+
const cwd = process.cwd();
|
|
239
|
+
const projectName = path.basename(cwd);
|
|
240
|
+
if (provider === 'Vercel') {
|
|
241
|
+
const vercelManager = new VercelManager_1.VercelManager();
|
|
242
|
+
if (await vercelManager.checkAuth()) {
|
|
243
|
+
const { vName } = await inquirer_1.default.prompt([{ type: 'input', name: 'vName', message: 'Vercel Project Name:', default: projectName }]);
|
|
244
|
+
const url = await vercelManager.deploy(cwd, vName);
|
|
245
|
+
if (url)
|
|
246
|
+
console.log(chalk_1.default.green(' ✔ Deployed! URL: ') + chalk_1.default.cyan(url));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else if (provider === 'Netlify') {
|
|
250
|
+
const netlifyManager = new NetlifyManager_1.NetlifyManager();
|
|
251
|
+
if (await netlifyManager.checkAuth()) {
|
|
252
|
+
const { nName } = await inquirer_1.default.prompt([{ type: 'input', name: 'nName', message: 'Netlify Project Name:', default: projectName }]);
|
|
253
|
+
const res = await netlifyManager.createSite(nName, cwd);
|
|
254
|
+
const success = await netlifyManager.deploy(cwd, res.siteId);
|
|
255
|
+
if (success)
|
|
256
|
+
console.log(chalk_1.default.green(' ✔ Deployed to Netlify!'));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else if (provider === 'GitHub Pages') {
|
|
260
|
+
console.log(chalk_1.default.yellow(' GitHub Pages deployment coming soon!'));
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
// zerostart git
|
|
264
|
+
program
|
|
265
|
+
.command('git')
|
|
266
|
+
.description('Initialize Git repository and optionally create GitHub repo')
|
|
267
|
+
.action(async () => {
|
|
268
|
+
showBanner();
|
|
269
|
+
const cwd = process.cwd();
|
|
270
|
+
const gitManager = new GitManager_1.GitManager();
|
|
271
|
+
const spinner = (0, ora_1.default)({ text: 'Checking Git...', color: 'cyan' }).start();
|
|
272
|
+
if (!await gitManager.checkGitInstalled()) {
|
|
273
|
+
spinner.fail(chalk_1.default.red('Git is not installed!'));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
spinner.text = 'Initializing Git repository...';
|
|
277
|
+
await gitManager.init(cwd);
|
|
278
|
+
spinner.succeed(chalk_1.default.green('Git repository initialized'));
|
|
279
|
+
const { createGitHub } = await inquirer_1.default.prompt([{
|
|
280
|
+
type: 'list',
|
|
281
|
+
name: 'createGitHub',
|
|
282
|
+
message: 'Create GitHub repository?',
|
|
283
|
+
choices: ['Yes', 'No'],
|
|
284
|
+
default: 'No'
|
|
285
|
+
}]);
|
|
286
|
+
if (createGitHub === 'Yes') {
|
|
287
|
+
const { isPublic } = await inquirer_1.default.prompt([{
|
|
288
|
+
type: 'list',
|
|
289
|
+
name: 'isPublic',
|
|
290
|
+
message: 'Repository visibility:',
|
|
291
|
+
choices: ['Public', 'Private'],
|
|
292
|
+
default: 'Private'
|
|
293
|
+
}]);
|
|
294
|
+
spinner.start('Creating GitHub repository...');
|
|
295
|
+
const repoName = path.basename(cwd);
|
|
296
|
+
const repoUrl = await gitManager.createRepoWithGh(cwd, repoName, isPublic === 'Public');
|
|
297
|
+
if (repoUrl) {
|
|
298
|
+
spinner.succeed(chalk_1.default.green('GitHub repository created'));
|
|
299
|
+
spinner.start('Pushing to GitHub...');
|
|
300
|
+
await gitManager.commit(cwd, 'Initial commit');
|
|
301
|
+
await gitManager.push(cwd);
|
|
302
|
+
spinner.succeed(chalk_1.default.green('Pushed to GitHub'));
|
|
303
|
+
console.log(chalk_1.default.cyan(` Repository: ${repoUrl}`));
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
spinner.fail(chalk_1.default.red('Failed to create GitHub repository'));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
await gitManager.commit(cwd, 'Initial commit');
|
|
311
|
+
console.log(chalk_1.default.green(' ✔ Git initialized with initial commit'));
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
// zerostart add [feature]
|
|
315
|
+
program
|
|
316
|
+
.command('add [feature]')
|
|
317
|
+
.description('Add features to your existing project')
|
|
318
|
+
.action(async (feature) => {
|
|
319
|
+
showBanner();
|
|
320
|
+
const features = ['auth', 'database', 'api', 'ui-components', 'testing', 'docker'];
|
|
321
|
+
let selectedFeature = feature;
|
|
322
|
+
if (!feature) {
|
|
323
|
+
const { feat } = await inquirer_1.default.prompt([{
|
|
324
|
+
type: 'list',
|
|
325
|
+
name: 'feat',
|
|
326
|
+
message: 'Select feature to add:',
|
|
327
|
+
choices: features
|
|
328
|
+
}]);
|
|
329
|
+
selectedFeature = feat;
|
|
330
|
+
}
|
|
331
|
+
const spinner = (0, ora_1.default)({ text: `Adding ${selectedFeature}...`, color: 'cyan' }).start();
|
|
332
|
+
// Placeholder implementation - would need actual feature templates
|
|
333
|
+
setTimeout(() => {
|
|
334
|
+
spinner.succeed(chalk_1.default.green(`${selectedFeature} feature added successfully!`));
|
|
335
|
+
console.log(chalk_1.default.gray(` Note: Feature templates are being developed`));
|
|
336
|
+
}, 1000);
|
|
337
|
+
});
|
|
338
|
+
// zerostart env
|
|
339
|
+
program
|
|
340
|
+
.command('env')
|
|
341
|
+
.description('Manage environment variables interactively')
|
|
342
|
+
.action(async () => {
|
|
343
|
+
showBanner();
|
|
344
|
+
const cwd = process.cwd();
|
|
345
|
+
const envPath = path.join(cwd, '.env');
|
|
346
|
+
const { action } = await inquirer_1.default.prompt([{
|
|
347
|
+
type: 'list',
|
|
348
|
+
name: 'action',
|
|
349
|
+
message: 'Environment variable action:',
|
|
350
|
+
choices: ['Add/Edit', 'View', 'Remove']
|
|
351
|
+
}]);
|
|
352
|
+
if (action === 'Add/Edit') {
|
|
353
|
+
const { key, value } = await inquirer_1.default.prompt([
|
|
354
|
+
{ type: 'input', name: 'key', message: 'Variable name:' },
|
|
355
|
+
{ type: 'input', name: 'value', message: 'Variable value:' }
|
|
356
|
+
]);
|
|
357
|
+
let envContent = '';
|
|
358
|
+
if (fs.existsSync(envPath)) {
|
|
359
|
+
envContent = fs.readFileSync(envPath, 'utf-8');
|
|
360
|
+
}
|
|
361
|
+
const lines = envContent.split('\n').filter(line => !line.startsWith(`${key}=`));
|
|
362
|
+
lines.push(`${key}=${value}`);
|
|
363
|
+
fs.writeFileSync(envPath, lines.join('\n'));
|
|
364
|
+
console.log(chalk_1.default.green(` ✔ ${key} added to .env`));
|
|
365
|
+
}
|
|
366
|
+
else if (action === 'View') {
|
|
367
|
+
if (fs.existsSync(envPath)) {
|
|
368
|
+
const content = fs.readFileSync(envPath, 'utf-8');
|
|
369
|
+
console.log(chalk_1.default.cyan('\n Environment variables:'));
|
|
370
|
+
console.log(chalk_1.default.gray(content));
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
console.log(chalk_1.default.yellow(' No .env file found'));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else if (action === 'Remove') {
|
|
377
|
+
if (fs.existsSync(envPath)) {
|
|
378
|
+
const content = fs.readFileSync(envPath, 'utf-8');
|
|
379
|
+
const vars = content.split('\n').filter(l => l.includes('=')).map(l => l.split('=')[0]);
|
|
380
|
+
const { varToRemove } = await inquirer_1.default.prompt([{
|
|
381
|
+
type: 'list',
|
|
382
|
+
name: 'varToRemove',
|
|
383
|
+
message: 'Select variable to remove:',
|
|
384
|
+
choices: vars
|
|
385
|
+
}]);
|
|
386
|
+
const newContent = content.split('\n').filter(l => !l.startsWith(`${varToRemove}=`)).join('\n');
|
|
387
|
+
fs.writeFileSync(envPath, newContent);
|
|
388
|
+
console.log(chalk_1.default.green(` ✔ ${varToRemove} removed`));
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
// zerostart test
|
|
393
|
+
program
|
|
394
|
+
.command('test')
|
|
395
|
+
.description('Set up testing framework with sample tests')
|
|
396
|
+
.action(async () => {
|
|
397
|
+
showBanner();
|
|
398
|
+
const { framework } = await inquirer_1.default.prompt([{
|
|
399
|
+
type: 'list',
|
|
400
|
+
name: 'framework',
|
|
401
|
+
message: 'Choose testing framework:',
|
|
402
|
+
choices: ['Jest', 'Vitest', 'Cypress', 'Mocha']
|
|
403
|
+
}]);
|
|
404
|
+
const spinner = (0, ora_1.default)({ text: `Setting up ${framework}...`, color: 'cyan' }).start();
|
|
405
|
+
// Placeholder - would install actual dependencies
|
|
406
|
+
setTimeout(() => {
|
|
407
|
+
spinner.succeed(chalk_1.default.green(`${framework} configured successfully!`));
|
|
408
|
+
console.log(chalk_1.default.gray(` Run tests with: npm test`));
|
|
409
|
+
}, 1500);
|
|
410
|
+
});
|
|
411
|
+
// zerostart build
|
|
412
|
+
program
|
|
413
|
+
.command('build')
|
|
414
|
+
.description('Build your project for production')
|
|
415
|
+
.action(async () => {
|
|
416
|
+
showBanner();
|
|
417
|
+
const cwd = process.cwd();
|
|
418
|
+
const spinner = (0, ora_1.default)({ text: 'Building for production...', color: 'cyan' }).start();
|
|
419
|
+
try {
|
|
420
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
421
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
422
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
423
|
+
if (packageJson.scripts && packageJson.scripts.build) {
|
|
424
|
+
(0, child_process_1.exec)('npm run build', { cwd }, (error, stdout, stderr) => {
|
|
425
|
+
if (error) {
|
|
426
|
+
spinner.fail(chalk_1.default.red('Build failed!'));
|
|
427
|
+
console.error(stderr);
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
spinner.succeed(chalk_1.default.green('Build completed successfully!'));
|
|
431
|
+
console.log(chalk_1.default.gray(stdout));
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
spinner.warn(chalk_1.default.yellow('No build script found in package.json'));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
spinner.warn(chalk_1.default.yellow('No package.json found'));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
catch (error) {
|
|
444
|
+
spinner.fail(chalk_1.default.red('Build failed: ' + error.message));
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
// zerostart dev
|
|
448
|
+
program
|
|
449
|
+
.command('dev')
|
|
450
|
+
.description('Start development server with hot reload')
|
|
451
|
+
.action(async () => {
|
|
452
|
+
showBanner();
|
|
453
|
+
const cwd = process.cwd();
|
|
454
|
+
console.log(chalk_1.default.cyan(' Starting development server...\n'));
|
|
455
|
+
try {
|
|
456
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
457
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
458
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
459
|
+
if (packageJson.scripts && packageJson.scripts.dev) {
|
|
460
|
+
(0, child_process_1.exec)('npm run dev', { cwd }, (error, stdout, stderr) => {
|
|
461
|
+
if (error) {
|
|
462
|
+
console.error(chalk_1.default.red('Failed to start dev server:'), stderr);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
else if (packageJson.scripts && packageJson.scripts.start) {
|
|
467
|
+
(0, child_process_1.exec)('npm start', { cwd }, (error, stdout, stderr) => {
|
|
468
|
+
if (error) {
|
|
469
|
+
console.error(chalk_1.default.red('Failed to start dev server:'), stderr);
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
console.log(chalk_1.default.yellow(' No dev or start script found in package.json'));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
console.log(chalk_1.default.yellow(' No package.json found'));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
console.error(chalk_1.default.red('Error: ' + error.message));
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
// zerostart clean
|
|
486
|
+
program
|
|
487
|
+
.command('clean')
|
|
488
|
+
.description('Clean build artifacts and cache files')
|
|
489
|
+
.action(async () => {
|
|
490
|
+
showBanner();
|
|
491
|
+
const cwd = process.cwd();
|
|
492
|
+
const { confirm, reinstall } = await inquirer_1.default.prompt([
|
|
493
|
+
{
|
|
494
|
+
type: 'confirm',
|
|
495
|
+
name: 'confirm',
|
|
496
|
+
message: 'This will delete node_modules, dist, build, and cache files. Continue?',
|
|
497
|
+
default: false
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
type: 'confirm',
|
|
501
|
+
name: 'reinstall',
|
|
502
|
+
message: 'Reinstall dependencies after cleaning?',
|
|
503
|
+
default: true,
|
|
504
|
+
when: (ans) => ans.confirm
|
|
505
|
+
}
|
|
506
|
+
]);
|
|
507
|
+
if (!confirm) {
|
|
508
|
+
console.log(chalk_1.default.yellow(' Cancelled'));
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
const spinner = (0, ora_1.default)({ text: 'Cleaning...', color: 'cyan' }).start();
|
|
512
|
+
const dirsToClean = ['node_modules', 'dist', 'build', 'out', '.next', '.cache'];
|
|
513
|
+
for (const dir of dirsToClean) {
|
|
514
|
+
const dirPath = path.join(cwd, dir);
|
|
515
|
+
if (fs.existsSync(dirPath)) {
|
|
516
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
517
|
+
spinner.text = `Removed ${dir}`;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
spinner.succeed(chalk_1.default.green('Cleaned successfully!'));
|
|
521
|
+
if (reinstall) {
|
|
522
|
+
spinner.start('Reinstalling dependencies...');
|
|
523
|
+
(0, child_process_1.exec)('npm install', { cwd }, (error, stdout, stderr) => {
|
|
524
|
+
if (error) {
|
|
525
|
+
spinner.fail(chalk_1.default.red('Failed to reinstall dependencies'));
|
|
526
|
+
console.error(stderr);
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
spinner.succeed(chalk_1.default.green('Dependencies reinstalled!'));
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
// zerostart update
|
|
535
|
+
program
|
|
536
|
+
.command('update')
|
|
537
|
+
.description('Update ZeroStart CLI to the latest version')
|
|
538
|
+
.action(async () => {
|
|
539
|
+
showBanner();
|
|
540
|
+
const spinner = (0, ora_1.default)({ text: 'Checking for updates...', color: 'cyan' }).start();
|
|
541
|
+
(0, child_process_1.exec)('npm view zerostart-cli version', (error, stdout, stderr) => {
|
|
542
|
+
if (error) {
|
|
543
|
+
spinner.fail(chalk_1.default.red('Failed to check for updates'));
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
const latestVersion = stdout.trim();
|
|
547
|
+
const currentVersion = '0.0.37';
|
|
548
|
+
if (latestVersion === currentVersion) {
|
|
549
|
+
spinner.succeed(chalk_1.default.green('You are using the latest version!'));
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
spinner.info(chalk_1.default.yellow(`Update available: ${currentVersion} → ${latestVersion}`));
|
|
553
|
+
console.log(chalk_1.default.cyan(' Run: npm install -g zerostart-cli@latest'));
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
// zerostart docs
|
|
558
|
+
program
|
|
559
|
+
.command('docs')
|
|
560
|
+
.description('Open comprehensive documentation in your browser')
|
|
561
|
+
.action(() => {
|
|
562
|
+
showBanner();
|
|
563
|
+
const docsUrl = 'https://github.com/yourusername/zerostart-cli#readme';
|
|
564
|
+
console.log(chalk_1.default.cyan(' Opening documentation...'));
|
|
565
|
+
openUrl(docsUrl);
|
|
566
|
+
});
|
|
165
567
|
// Standalone deployment commands
|
|
166
568
|
program
|
|
167
569
|
.command('deploy-vercel')
|
|
@@ -192,24 +594,20 @@ program
|
|
|
192
594
|
console.log(chalk_1.default.green(' ✔ Deployed to Netlify!'));
|
|
193
595
|
}
|
|
194
596
|
});
|
|
195
|
-
// Shortcut commands (
|
|
597
|
+
// Shortcut commands (Removed Node.js shortcuts)
|
|
196
598
|
const shortcuts = [
|
|
197
599
|
{ cmd: 'dsa-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.DSAPractice },
|
|
198
600
|
{ cmd: 'dsa-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.DSAPractice },
|
|
199
601
|
{ cmd: 'dsa-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.DSAPractice },
|
|
200
|
-
{ cmd: 'dsa-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.DSAPractice },
|
|
201
602
|
{ cmd: 'web-react', lang: types_1.ProjectLanguage.React, type: types_1.ProjectType.WebApp },
|
|
202
603
|
{ cmd: 'web-html', lang: types_1.ProjectLanguage.HTMLCSS, type: types_1.ProjectType.WebApp },
|
|
203
|
-
{ cmd: 'web-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.WebApp },
|
|
204
604
|
{ cmd: 'web-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.WebApp },
|
|
205
605
|
{ cmd: 'web-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.WebApp },
|
|
206
606
|
{ cmd: 'web-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.WebApp },
|
|
207
607
|
{ cmd: 'cli-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.CLITool },
|
|
208
|
-
{ cmd: 'cli-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.CLITool },
|
|
209
608
|
{ cmd: 'cli-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.CLITool },
|
|
210
609
|
{ cmd: 'cli-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.CLITool },
|
|
211
610
|
{ cmd: 'ml-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.MLProject },
|
|
212
|
-
{ cmd: 'ml-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.MLProject },
|
|
213
611
|
{ cmd: 'ml-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.MLProject },
|
|
214
612
|
{ cmd: 'ml-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.MLProject },
|
|
215
613
|
];
|
|
@@ -219,21 +617,127 @@ shortcuts.forEach(s => {
|
|
|
219
617
|
initializeProject(n, s.lang, s.type, { isPublic: false, createRemote: false, githubToken: null, authMethod: 'none' });
|
|
220
618
|
});
|
|
221
619
|
});
|
|
620
|
+
async function startWizard(initialName) {
|
|
621
|
+
let step = 1;
|
|
622
|
+
let name = initialName;
|
|
623
|
+
let language;
|
|
624
|
+
let github = false;
|
|
625
|
+
let githubToken = null;
|
|
626
|
+
const BACK = '< Back';
|
|
627
|
+
while (step > 0 && step <= 4) {
|
|
628
|
+
if (step === 1) {
|
|
629
|
+
if (!name) {
|
|
630
|
+
const ans = await inquirer_1.default.prompt([{
|
|
631
|
+
type: 'input',
|
|
632
|
+
name: 'name',
|
|
633
|
+
message: 'Project Name:',
|
|
634
|
+
default: 'my-project'
|
|
635
|
+
}]);
|
|
636
|
+
name = ans.name;
|
|
637
|
+
}
|
|
638
|
+
step++;
|
|
639
|
+
}
|
|
640
|
+
else if (step === 2) {
|
|
641
|
+
const choices = [
|
|
642
|
+
types_1.ProjectLanguage.React,
|
|
643
|
+
types_1.ProjectLanguage.TypeScript,
|
|
644
|
+
types_1.ProjectLanguage.HTMLCSS,
|
|
645
|
+
types_1.ProjectLanguage.CPP,
|
|
646
|
+
types_1.ProjectLanguage.Java,
|
|
647
|
+
types_1.ProjectLanguage.Python
|
|
648
|
+
];
|
|
649
|
+
if (!initialName)
|
|
650
|
+
choices.push(new inquirer_1.default.Separator(), BACK);
|
|
651
|
+
const ans = await inquirer_1.default.prompt([{
|
|
652
|
+
type: 'list',
|
|
653
|
+
name: 'language',
|
|
654
|
+
message: 'Select Template:',
|
|
655
|
+
choices: choices
|
|
656
|
+
}]);
|
|
657
|
+
if (ans.language === BACK) {
|
|
658
|
+
name = undefined;
|
|
659
|
+
step--;
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
language = ans.language;
|
|
663
|
+
step++;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
else if (step === 3) {
|
|
667
|
+
if (language === types_1.ProjectLanguage.React || language === types_1.ProjectLanguage.TypeScript) {
|
|
668
|
+
const ans = await inquirer_1.default.prompt([{
|
|
669
|
+
type: 'list',
|
|
670
|
+
name: 'github',
|
|
671
|
+
message: 'Do you want to add this to GitHub?',
|
|
672
|
+
choices: ['Yes', 'No', BACK],
|
|
673
|
+
default: 'Yes'
|
|
674
|
+
}]);
|
|
675
|
+
if (ans.github === BACK) {
|
|
676
|
+
step--;
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
github = ans.github === 'Yes';
|
|
680
|
+
step++;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
github = false;
|
|
685
|
+
step++; // Skip to creation
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
else if (step === 4) {
|
|
689
|
+
if (github) {
|
|
690
|
+
showGitHubTokenHelp();
|
|
691
|
+
const ans = await inquirer_1.default.prompt([
|
|
692
|
+
{
|
|
693
|
+
type: 'password',
|
|
694
|
+
name: 'token',
|
|
695
|
+
message: 'Enter your GitHub Personal Access Token (or type "back" to return):',
|
|
696
|
+
validate: (input) => input.length > 0 || 'Token is required'
|
|
697
|
+
}
|
|
698
|
+
]);
|
|
699
|
+
if (ans.token.toLowerCase() === 'back') {
|
|
700
|
+
step--;
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
githubToken = ans.token;
|
|
704
|
+
step++;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
else {
|
|
708
|
+
step++;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if (step > 4 && name && language) {
|
|
713
|
+
let type = types_1.ProjectType.WebApp;
|
|
714
|
+
if (language === types_1.ProjectLanguage.TypeScript)
|
|
715
|
+
type = types_1.ProjectType.CLITool;
|
|
716
|
+
if ([types_1.ProjectLanguage.CPP, types_1.ProjectLanguage.Java, types_1.ProjectLanguage.Python].includes(language))
|
|
717
|
+
type = types_1.ProjectType.DSAPractice;
|
|
718
|
+
await initializeProject(name, language, type, {
|
|
719
|
+
isPublic: false,
|
|
720
|
+
createRemote: !!githubToken,
|
|
721
|
+
githubToken: githubToken,
|
|
722
|
+
authMethod: 'none'
|
|
723
|
+
});
|
|
724
|
+
if (language === types_1.ProjectLanguage.HTMLCSS) {
|
|
725
|
+
const { deploy } = await inquirer_1.default.prompt([
|
|
726
|
+
{ type: 'confirm', name: 'deploy', message: 'Do you want to deploy to Vercel right now?', default: true }
|
|
727
|
+
]);
|
|
728
|
+
if (deploy) {
|
|
729
|
+
const vercelManager = new VercelManager_1.VercelManager();
|
|
730
|
+
const projectPath = path.join(process.cwd(), name);
|
|
731
|
+
if (await vercelManager.checkAuth()) {
|
|
732
|
+
await vercelManager.deploy(projectPath, name);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
222
738
|
// Main wizard
|
|
223
739
|
program.argument('[projectName]').action(async (projectName) => {
|
|
224
740
|
showBanner();
|
|
225
|
-
|
|
226
|
-
const answers = await inquirer_1.default.prompt([
|
|
227
|
-
{ type: 'input', name: 'name', message: 'Project Name:', skip: !!projectName, when: !projectName },
|
|
228
|
-
{ type: 'list', name: 'language', message: 'Language:', choices: Object.values(types_1.ProjectLanguage) },
|
|
229
|
-
{ type: 'list', name: 'type', message: 'Type:', choices: Object.values(types_1.ProjectType) },
|
|
230
|
-
{ type: 'list', name: 'createRemote', message: 'Push to GitHub?', choices: ['Yes', 'No'], default: 'No', when: (ans) => ans.type !== types_1.ProjectType.DSAPractice }
|
|
231
|
-
]);
|
|
232
|
-
await initializeProject(projectName || answers.name, answers.language, answers.type, {
|
|
233
|
-
isPublic: false,
|
|
234
|
-
createRemote: answers.createRemote === 'Yes',
|
|
235
|
-
githubToken: null,
|
|
236
|
-
authMethod: 'none'
|
|
237
|
-
});
|
|
741
|
+
await startWizard(projectName);
|
|
238
742
|
});
|
|
239
743
|
program.parse(process.argv);
|