easybuild-nox 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,794 @@
1
+ const { Command } = require('commander');
2
+ const inquirer = require('inquirer');
3
+ const path = require('path');
4
+ const fs = require('fs-extra');
5
+ const logger = require('../utils/logger');
6
+
7
+ const TEMPLATES = {
8
+ 'express-api': {
9
+ name: 'Express API',
10
+ description: 'REST API with Express.js',
11
+ files: {
12
+ 'package.json': {
13
+ name: '{{name}}',
14
+ version: '1.0.0',
15
+ scripts: {
16
+ dev: 'nodemon src/index.js',
17
+ start: 'node src/index.js',
18
+ build: 'easy build',
19
+ },
20
+ dependencies: {
21
+ express: '^4.18.2',
22
+ cors: '^2.8.5',
23
+ dotenv: '^16.3.1',
24
+ },
25
+ devDependencies: {
26
+ nodemon: '^3.0.2',
27
+ },
28
+ },
29
+ 'src/index.js': `const express = require('express');
30
+ const cors = require('cors');
31
+ require('dotenv').config();
32
+
33
+ const app = express();
34
+ const PORT = process.env.PORT || 3000;
35
+
36
+ app.use(cors());
37
+ app.use(express.json());
38
+
39
+ app.get('/', (req, res) => {
40
+ res.json({ message: 'Hello from {{name}}!' });
41
+ });
42
+
43
+ app.listen(PORT, () => {
44
+ console.log(\`Server running on port \${PORT}\`);
45
+ });`,
46
+ '.env': 'PORT=3000',
47
+ '.gitignore': 'node_modules/\ndist/\n.env',
48
+ },
49
+ },
50
+
51
+ 'fastify-api': {
52
+ name: 'Fastify API',
53
+ description: 'High-performance API with Fastify',
54
+ files: {
55
+ 'package.json': {
56
+ name: '{{name}}',
57
+ version: '1.0.0',
58
+ scripts: {
59
+ dev: 'nodemon src/index.js',
60
+ start: 'node src/index.js',
61
+ build: 'easy build',
62
+ },
63
+ dependencies: {
64
+ fastify: '^4.25.0',
65
+ '@fastify/cors': '^8.5.0',
66
+ },
67
+ devDependencies: {
68
+ nodemon: '^3.0.2',
69
+ },
70
+ },
71
+ 'src/index.js': `const fastify = require('fastify')({ logger: true });
72
+
73
+ fastify.register(require('@fastify/cors'));
74
+
75
+ fastify.get('/', async (request, reply) => {
76
+ return { message: 'Hello from {{name}}!' };
77
+ });
78
+
79
+ const start = async () => {
80
+ try {
81
+ await fastify.listen({ port: process.env.PORT || 3000 });
82
+ } catch (err) {
83
+ fastify.log.error(err);
84
+ process.exit(1);
85
+ }
86
+ };
87
+
88
+ start();`,
89
+ '.gitignore': 'node_modules/\ndist/',
90
+ },
91
+ },
92
+
93
+ 'nest-api': {
94
+ name: 'NestJS API',
95
+ description: 'Enterprise-grade API with NestJS',
96
+ files: {
97
+ 'package.json': {
98
+ name: '{{name}}',
99
+ version: '1.0.0',
100
+ scripts: {
101
+ dev: 'nest start --watch',
102
+ start: 'nest start',
103
+ build: 'nest build',
104
+ 'start:prod': 'node dist/main',
105
+ },
106
+ dependencies: {
107
+ '@nestjs/common': '^10.3.0',
108
+ '@nestjs/core': '^10.3.0',
109
+ '@nestjs/platform-express': '^10.3.0',
110
+ 'reflect-metadata': '^0.1.14',
111
+ rxjs: '^7.8.1',
112
+ },
113
+ devDependencies: {
114
+ '@nestjs/cli': '^10.3.0',
115
+ '@nestjs/schematics': '^10.1.0',
116
+ typescript: '^5.3.3',
117
+ },
118
+ },
119
+ 'tsconfig.json': {
120
+ compilerOptions: {
121
+ module: 'commonjs',
122
+ declaration: true,
123
+ removeComments: true,
124
+ emitDecoratorMetadata: true,
125
+ experimentalDecorators: true,
126
+ allowSyntheticDefaultImports: true,
127
+ target: 'ES2021',
128
+ sourceMap: true,
129
+ outDir: './dist',
130
+ baseUrl: './',
131
+ incremental: true,
132
+ skipLibCheck: true,
133
+ strictNullChecks: false,
134
+ noImplicitAny: false,
135
+ strictBindCallApply: false,
136
+ forceConsistentCasingInFileNames: false,
137
+ noFallthroughCasesInSwitch: false,
138
+ },
139
+ },
140
+ 'src/main.ts': `import { NestFactory } from '@nestjs/core';
141
+ import { AppModule } from './app.module';
142
+
143
+ async function bootstrap() {
144
+ const app = await NestFactory.create(AppModule);
145
+ await app.listen(process.env.PORT || 3000);
146
+ }
147
+ bootstrap();`,
148
+ 'src/app.module.ts': `import { Module } from '@nestjs/common';
149
+ import { AppController } from './app.controller';
150
+ import { AppService } from './app.service';
151
+
152
+ @Module({
153
+ imports: [],
154
+ controllers: [AppController],
155
+ providers: [AppService],
156
+ })
157
+ export class AppModule {}`,
158
+ 'src/app.controller.ts': `import { Controller, Get } from '@nestjs/common';
159
+ import { AppService } from './app.service';
160
+
161
+ @Controller()
162
+ export class AppController {
163
+ constructor(private readonly appService: AppService) {}
164
+
165
+ @Get()
166
+ getData() {
167
+ return this.appService.getData();
168
+ }
169
+ }`,
170
+ 'src/app.service.ts': `import { Injectable } from '@nestjs/common';
171
+
172
+ @Injectable()
173
+ export class AppService {
174
+ getData(): { message: string } {
175
+ return { message: 'Hello from {{name}}!' };
176
+ }
177
+ }`,
178
+ },
179
+ },
180
+
181
+ 'react-app': {
182
+ name: 'React App',
183
+ description: 'React application with Vite',
184
+ files: {
185
+ 'package.json': {
186
+ name: '{{name}}',
187
+ version: '1.0.0',
188
+ scripts: {
189
+ dev: 'vite',
190
+ build: 'vite build',
191
+ preview: 'vite preview',
192
+ },
193
+ dependencies: {
194
+ react: '^18.2.0',
195
+ 'react-dom': '^18.2.0',
196
+ },
197
+ devDependencies: {
198
+ '@vitejs/plugin-react': '^4.2.1',
199
+ vite: '^5.0.12',
200
+ },
201
+ },
202
+ 'vite.config.js': `import { defineConfig } from 'vite';
203
+ import react from '@vitejs/plugin-react';
204
+
205
+ export default defineConfig({
206
+ plugins: [react()],
207
+ });`,
208
+ 'index.html': `<!DOCTYPE html>
209
+ <html lang="en">
210
+ <head>
211
+ <meta charset="UTF-8" />
212
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
213
+ <title>{{name}}</title>
214
+ </head>
215
+ <body>
216
+ <div id="root"></div>
217
+ <script type="module" src="/src/main.jsx"></script>
218
+ </body>
219
+ </html>`,
220
+ 'src/main.jsx': `import React from 'react';
221
+ import ReactDOM from 'react-dom/client';
222
+ import App from './App';
223
+
224
+ ReactDOM.createRoot(document.getElementById('root')).render(
225
+ <React.StrictMode>
226
+ <App />
227
+ </React.StrictMode>
228
+ );`,
229
+ 'src/App.jsx': `function App() {
230
+ return (
231
+ <div>
232
+ <h1>Hello from {{name}}!</h1>
233
+ </div>
234
+ );
235
+ }
236
+
237
+ export default App;`,
238
+ },
239
+ },
240
+
241
+ 'vue-app': {
242
+ name: 'Vue App',
243
+ description: 'Vue 3 application with Vite',
244
+ files: {
245
+ 'package.json': {
246
+ name: '{{name}}',
247
+ version: '1.0.0',
248
+ scripts: {
249
+ dev: 'vite',
250
+ build: 'vite build',
251
+ preview: 'vite preview',
252
+ },
253
+ dependencies: {
254
+ vue: '^3.4.15',
255
+ },
256
+ devDependencies: {
257
+ '@vitejs/plugin-vue': '^5.0.3',
258
+ vite: '^5.0.12',
259
+ },
260
+ },
261
+ 'vite.config.js': `import { defineConfig } from 'vite';
262
+ import vue from '@vitejs/plugin-vue';
263
+
264
+ export default defineConfig({
265
+ plugins: [vue()],
266
+ });`,
267
+ 'index.html': `<!DOCTYPE html>
268
+ <html lang="en">
269
+ <head>
270
+ <meta charset="UTF-8" />
271
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
272
+ <title>{{name}}</title>
273
+ </head>
274
+ <body>
275
+ <div id="app"></div>
276
+ <script type="module" src="/src/main.js"></script>
277
+ </body>
278
+ </html>`,
279
+ 'src/main.js': `import { createApp } from 'vue';
280
+ import App from './App.vue';
281
+
282
+ createApp(App).mount('#app');`,
283
+ 'src/App.vue': `<template>
284
+ <div>
285
+ <h1>Hello from {{name}}!</h1>
286
+ </div>
287
+ </template>
288
+
289
+ <script setup>
290
+ </script>`,
291
+ },
292
+ },
293
+
294
+ 'electron-app': {
295
+ name: 'Electron App',
296
+ description: 'Desktop application with Electron',
297
+ files: {
298
+ 'package.json': {
299
+ name: '{{name}}',
300
+ version: '1.0.0',
301
+ main: 'electron/main.js',
302
+ scripts: {
303
+ dev: 'electron .',
304
+ build: 'easy build --target electron',
305
+ 'build:win': 'easy build --target electron --platform win',
306
+ 'build:mac': 'easy build --target electron --platform mac',
307
+ 'build:linux': 'easy build --target electron --platform linux',
308
+ },
309
+ dependencies: {
310
+ electron: '^28.1.0',
311
+ },
312
+ },
313
+ 'electron/main.js': `const { app, BrowserWindow } = require('electron');
314
+ const path = require('path');
315
+
316
+ function createWindow() {
317
+ const mainWindow = new BrowserWindow({
318
+ width: 800,
319
+ height: 600,
320
+ webPreferences: {
321
+ preload: path.join(__dirname, 'preload.js'),
322
+ contextIsolation: true,
323
+ },
324
+ });
325
+
326
+ mainWindow.loadFile('index.html');
327
+ }
328
+
329
+ app.whenReady().then(createWindow);
330
+
331
+ app.on('window-all-closed', () => {
332
+ if (process.platform !== 'darwin') {
333
+ app.quit();
334
+ }
335
+ });`,
336
+ 'electron/preload.js': `const { contextBridge } = require('electron');
337
+
338
+ contextBridge.exposeInMainWorld('electronAPI', {
339
+ platform: process.platform,
340
+ });`,
341
+ 'index.html': `<!DOCTYPE html>
342
+ <html>
343
+ <head>
344
+ <meta charset="UTF-8" />
345
+ <title>{{name}}</title>
346
+ </head>
347
+ <body>
348
+ <h1>Hello from {{name}}!</h1>
349
+ </body>
350
+ </html>`,
351
+ },
352
+ },
353
+
354
+ 'typescript-lib': {
355
+ name: 'TypeScript Library',
356
+ description: 'Publishable TypeScript library',
357
+ files: {
358
+ 'package.json': {
359
+ name: '{{name}}',
360
+ version: '1.0.0',
361
+ main: 'dist/index.js',
362
+ types: 'dist/index.d.ts',
363
+ scripts: {
364
+ build: 'tsc',
365
+ dev: 'tsc --watch',
366
+ prepublishOnly: 'npm run build',
367
+ },
368
+ devDependencies: {
369
+ typescript: '^5.3.3',
370
+ },
371
+ },
372
+ 'tsconfig.json': {
373
+ compilerOptions: {
374
+ target: 'ES2020',
375
+ module: 'commonjs',
376
+ lib: ['ES2020'],
377
+ declaration: true,
378
+ strict: true,
379
+ noImplicitAny: true,
380
+ strictNullChecks: true,
381
+ noImplicitThis: true,
382
+ alwaysStrict: true,
383
+ outDir: './dist',
384
+ rootDir: './src',
385
+ },
386
+ include: ['src/**/*'],
387
+ exclude: ['node_modules', 'dist'],
388
+ },
389
+ 'src/index.ts': `export function hello(name: string): string {
390
+ return \`Hello, \${name}!\`;
391
+ }`,
392
+ },
393
+ },
394
+
395
+ 'cli-tool': {
396
+ name: 'CLI Tool',
397
+ description: 'Command-line interface tool',
398
+ files: {
399
+ 'package.json': {
400
+ name: '{{name}}',
401
+ version: '1.0.0',
402
+ bin: {
403
+ '{{name}}': './bin/index.js',
404
+ },
405
+ scripts: {
406
+ dev: 'node bin/index.js',
407
+ build: 'easy build --target library',
408
+ },
409
+ dependencies: {
410
+ commander: '^12.1.0',
411
+ chalk: '^5.3.0',
412
+ },
413
+ },
414
+ 'bin/index.js': `#!/usr/bin/env node
415
+
416
+ const { Command } = require('commander');
417
+ const chalk = require('chalk');
418
+
419
+ const program = new Command();
420
+
421
+ program
422
+ .name('{{name}}')
423
+ .description('A awesome CLI tool')
424
+ .version('1.0.0');
425
+
426
+ program
427
+ .command('hello')
428
+ .description('Say hello')
429
+ .action(() => {
430
+ console.log(chalk.green('Hello from {{name}}!'));
431
+ });
432
+
433
+ program.parse();`,
434
+ },
435
+ },
436
+
437
+ 'docker-app': {
438
+ name: 'Docker Application',
439
+ description: 'Application with Docker support',
440
+ files: {
441
+ 'package.json': {
442
+ name: '{{name}}',
443
+ version: '1.0.0',
444
+ scripts: {
445
+ dev: 'node src/index.js',
446
+ start: 'node src/index.js',
447
+ build: 'easy build',
448
+ docker: 'easy docker build',
449
+ 'docker:run': 'easy docker run',
450
+ },
451
+ dependencies: {
452
+ express: '^4.18.2',
453
+ },
454
+ },
455
+ 'Dockerfile': `FROM node:20-alpine
456
+
457
+ WORKDIR /app
458
+
459
+ COPY package*.json ./
460
+ RUN npm ci --only=production
461
+
462
+ COPY . .
463
+
464
+ EXPOSE 3000
465
+
466
+ CMD ["node", "src/index.js"]`,
467
+ '.dockerignore': 'node_modules\nnpm-debug.log\ndist\n.env',
468
+ 'docker-compose.yml': `version: '3.8'
469
+
470
+ services:
471
+ app:
472
+ build: .
473
+ ports:
474
+ - "3000:3000"
475
+ environment:
476
+ - NODE_ENV=production
477
+ restart: unless-stopped`,
478
+ 'src/index.js': `const express = require('express');
479
+ const app = express();
480
+ const PORT = process.env.PORT || 3000;
481
+
482
+ app.get('/', (req, res) => {
483
+ res.json({ message: 'Hello from {{name}}!' });
484
+ });
485
+
486
+ app.listen(PORT, () => {
487
+ console.log(\`Server running on port \${PORT}\`);
488
+ });`,
489
+ },
490
+ },
491
+
492
+ 'astro-app': {
493
+ name: 'Astro App',
494
+ description: 'Static site with Astro framework',
495
+ files: {
496
+ 'package.json': {
497
+ name: '{{name}}',
498
+ version: '1.0.0',
499
+ scripts: {
500
+ dev: 'astro dev',
501
+ build: 'astro build',
502
+ preview: 'astro preview',
503
+ },
504
+ dependencies: {
505
+ astro: '^4.0.0',
506
+ },
507
+ },
508
+ 'astro.config.mjs': `import { defineConfig } from 'astro/config';
509
+
510
+ export default defineConfig({
511
+ // Enable React if needed
512
+ // integrations: [react()],
513
+ });`,
514
+ 'src/pages/index.astro': `---
515
+ // Welcome to Astro!
516
+ ---
517
+
518
+ <html lang="en">
519
+ <head>
520
+ <meta charset="UTF-8" />
521
+ <meta name="viewport" content="width=device-width" />
522
+ <title>Welcome to {{name}}</title>
523
+ </head>
524
+ <body>
525
+ <h1>Hello from {{name}}!</h1>
526
+ <p>Welcome to your Astro project.</p>
527
+ </body>
528
+ </html>`,
529
+ 'src/layouts/Layout.astro': `---
530
+ const { title } = Astro.props;
531
+ ---
532
+
533
+ <html lang="en">
534
+ <head>
535
+ <meta charset="UTF-8" />
536
+ <meta name="viewport" content="width=device-width" />
537
+ <title>{title}</title>
538
+ </head>
539
+ <body>
540
+ <slot />
541
+ </body>
542
+ </html>`,
543
+ 'public/favicon.svg': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
544
+ <text y=".9em" font-size="90">🚀</text>
545
+ </svg>`,
546
+ },
547
+ },
548
+
549
+ 'astro-react': {
550
+ name: 'Astro + React',
551
+ description: 'Astro with React components',
552
+ files: {
553
+ 'package.json': {
554
+ name: '{{name}}',
555
+ version: '1.0.0',
556
+ scripts: {
557
+ dev: 'astro dev',
558
+ build: 'astro build',
559
+ preview: 'astro preview',
560
+ },
561
+ dependencies: {
562
+ astro: '^4.0.0',
563
+ '@astrojs/react': '^3.0.0',
564
+ react: '^18.2.0',
565
+ 'react-dom': '^18.2.0',
566
+ },
567
+ },
568
+ 'astro.config.mjs': `import { defineConfig } from 'astro/config';
569
+ import react from '@astrojs/react';
570
+
571
+ export default defineConfig({
572
+ integrations: [react()],
573
+ });`,
574
+ 'src/pages/index.astro': `---
575
+ import Counter from '../components/Counter.jsx';
576
+ ---
577
+
578
+ <html lang="en">
579
+ <head>
580
+ <meta charset="UTF-8" />
581
+ <meta name="viewport" content="width=device-width" />
582
+ <title>Welcome to {{name}}</title>
583
+ </head>
584
+ <body>
585
+ <h1>Hello from {{name}}!</h1>
586
+ <Counter client:visible />
587
+ </body>
588
+ </html>`,
589
+ 'src/components/Counter.jsx': `import { useState } from 'react';
590
+
591
+ export default function Counter() {
592
+ const [count, setCount] = useState(0);
593
+
594
+ return (
595
+ <div>
596
+ <p>Count: {count}</p>
597
+ <button onClick={() => setCount(c => c + 1)}>Increment</button>
598
+ </div>
599
+ );
600
+ }`,
601
+ },
602
+ },
603
+
604
+ 'astro-vue': {
605
+ name: 'Astro + Vue',
606
+ description: 'Astro with Vue components',
607
+ files: {
608
+ 'package.json': {
609
+ name: '{{name}}',
610
+ version: '1.0.0',
611
+ scripts: {
612
+ dev: 'astro dev',
613
+ build: 'astro build',
614
+ preview: 'astro preview',
615
+ },
616
+ dependencies: {
617
+ astro: '^4.0.0',
618
+ '@astrojs/vue': '^4.0.0',
619
+ vue: '^3.4.0',
620
+ },
621
+ },
622
+ 'astro.config.mjs': `import { defineConfig } from 'astro/config';
623
+ import vue from '@astrojs/vue';
624
+
625
+ export default defineConfig({
626
+ integrations: [vue()],
627
+ });`,
628
+ 'src/pages/index.astro': `---
629
+ import Counter from '../components/Counter.vue';
630
+ ---
631
+
632
+ <html lang="en">
633
+ <head>
634
+ <meta charset="UTF-8" />
635
+ <meta name="viewport" content="width=device-width" />
636
+ <title>Welcome to {{name}}</title>
637
+ </head>
638
+ <body>
639
+ <h1>Hello from {{name}}!</h1>
640
+ <Counter client:visible />
641
+ </body>
642
+ </html>`,
643
+ 'src/components/Counter.vue': `<template>
644
+ <div>
645
+ <p>Count: {{ count }}</p>
646
+ <button @click="count++">Increment</button>
647
+ </div>
648
+ </template>
649
+
650
+ <script setup>
651
+ import { ref } from 'vue';
652
+ const count = ref(0);
653
+ </script>`,
654
+ },
655
+ },
656
+
657
+ 'qwik-app': {
658
+ name: 'Qwik App',
659
+ description: 'Instant-loading web app with Qwik',
660
+ files: {
661
+ 'package.json': {
662
+ name: '{{name}}',
663
+ version: '1.0.0',
664
+ scripts: {
665
+ dev: 'vite',
666
+ build: 'tsc && vite build',
667
+ preview: 'vite preview',
668
+ },
669
+ dependencies: {
670
+ '@builder.io/qwik': '^1.0.0',
671
+ '@builder.io/qwik-city': '^1.0.0',
672
+ },
673
+ devDependencies: {
674
+ vite: '^5.0.0',
675
+ typescript: '^5.0.0',
676
+ },
677
+ },
678
+ 'src/routes/index.tsx': `import { component$ } from '@builder.io/qwik';
679
+
680
+ export default component$(() => {
681
+ return (
682
+ <div>
683
+ <h1>Hello from {{name}}!</h1>
684
+ <p>Welcome to your Qwik project.</p>
685
+ </div>
686
+ );
687
+ });`,
688
+ },
689
+ },
690
+
691
+ 'blank': {
692
+ name: 'Blank Project',
693
+ description: 'Empty project to start from scratch',
694
+ files: {
695
+ 'package.json': {
696
+ name: '{{name}}',
697
+ version: '1.0.0',
698
+ scripts: {
699
+ dev: 'node src/index.js',
700
+ build: 'easy build',
701
+ },
702
+ },
703
+ 'src/index.js': `console.log('Hello from {{name}}!');`,
704
+ },
705
+ },
706
+ };
707
+
708
+ const initCommand = new Command('init')
709
+ .description('Initialize a new project')
710
+ .argument('[name]', 'Project name')
711
+ .option('-t, --template <template>', 'Project template')
712
+ .action(async (name, options) => {
713
+ logger.header('🚀 Initialize New Project');
714
+
715
+ try {
716
+ // Get project name if not provided
717
+ if (!name) {
718
+ const nameAnswer = await inquirer.prompt([
719
+ {
720
+ type: 'input',
721
+ name: 'name',
722
+ message: 'Project name:',
723
+ validate: (input) => input.length > 0 || 'Project name is required',
724
+ },
725
+ ]);
726
+ name = nameAnswer.name;
727
+ }
728
+
729
+ // Get template if not provided
730
+ let template = options.template;
731
+ if (!template) {
732
+ const templateAnswer = await inquirer.prompt([
733
+ {
734
+ type: 'list',
735
+ name: 'template',
736
+ message: 'Select a template:',
737
+ choices: Object.entries(TEMPLATES).map(([key, value]) => ({
738
+ name: `${value.name} - ${value.description}`,
739
+ value: key,
740
+ })),
741
+ },
742
+ ]);
743
+ template = templateAnswer.template;
744
+ }
745
+
746
+ const templateData = TEMPLATES[template];
747
+ if (!templateData) {
748
+ logger.error(`Template "${template}" not found`);
749
+ process.exit(1);
750
+ }
751
+
752
+ const projectDir = path.join(process.cwd(), name);
753
+
754
+ // Check if directory exists
755
+ if (await fs.pathExists(projectDir)) {
756
+ logger.error(`Directory "${name}" already exists`);
757
+ process.exit(1);
758
+ }
759
+
760
+ // Create project directory
761
+ await fs.ensureDir(projectDir);
762
+
763
+ // Create files from template
764
+ for (const [filePath, content] of Object.entries(templateData.files)) {
765
+ const fullPath = path.join(projectDir, filePath);
766
+ await fs.ensureDir(path.dirname(fullPath));
767
+
768
+ let fileContent = content;
769
+ if (typeof content === 'object') {
770
+ fileContent = JSON.stringify(content, null, 2);
771
+ }
772
+
773
+ // Replace template variables
774
+ fileContent = fileContent.replace(/\{\{name\}\}/g, name);
775
+
776
+ await fs.writeFile(fullPath, fileContent);
777
+ }
778
+
779
+ logger.success(`Project "${name}" created successfully!`);
780
+ logger.info(`Template: ${templateData.name}`);
781
+ logger.info('');
782
+ logger.info('Next steps:');
783
+ logger.list([
784
+ `cd ${name}`,
785
+ 'npm install',
786
+ 'npm run dev',
787
+ ]);
788
+ } catch (error) {
789
+ logger.error(`Failed to initialize project: ${error.message}`);
790
+ process.exit(1);
791
+ }
792
+ });
793
+
794
+ module.exports = initCommand;