vako 1.3.12 → 1.3.14
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/bin/commands/setup-executor.js +368 -3
- package/bin/commands/setup.js +53 -1
- package/bin/vako.js +38 -6
- package/package.json +1 -1
|
@@ -154,7 +154,21 @@ class SetupExecutor {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
generateFiles() {
|
|
157
|
-
const { projectName, description, author, license, template, features, database, auth, styling } = this.config;
|
|
157
|
+
const { projectName, description, author, license, template, features, database, auth, styling, codeType } = this.config;
|
|
158
|
+
const files = {};
|
|
159
|
+
|
|
160
|
+
// Générer les fichiers selon le type de code
|
|
161
|
+
if (codeType === 'nextjs') {
|
|
162
|
+
return this.generateNextJsFiles();
|
|
163
|
+
} else if (codeType === 'typescript') {
|
|
164
|
+
return this.generateTypeScriptFiles();
|
|
165
|
+
} else {
|
|
166
|
+
return this.generateEjsFiles();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
generateEjsFiles() {
|
|
171
|
+
const { projectName, description, author, license } = this.config;
|
|
158
172
|
const files = {};
|
|
159
173
|
|
|
160
174
|
// package.json
|
|
@@ -168,11 +182,11 @@ class SetupExecutor {
|
|
|
168
182
|
start: 'vako start',
|
|
169
183
|
build: 'vako build'
|
|
170
184
|
},
|
|
171
|
-
keywords: ['vako', 'framework', 'web'],
|
|
185
|
+
keywords: ['vako', 'framework', 'web', 'ejs'],
|
|
172
186
|
author: author || '',
|
|
173
187
|
license: license || 'MIT',
|
|
174
188
|
dependencies: {
|
|
175
|
-
vako: '^1.3.
|
|
189
|
+
vako: '^1.3.13'
|
|
176
190
|
}
|
|
177
191
|
}, null, 2);
|
|
178
192
|
|
|
@@ -265,6 +279,357 @@ h1 {
|
|
|
265
279
|
return files;
|
|
266
280
|
}
|
|
267
281
|
|
|
282
|
+
generateTypeScriptFiles() {
|
|
283
|
+
const { projectName, description, author, license } = this.config;
|
|
284
|
+
const files = {};
|
|
285
|
+
|
|
286
|
+
// package.json
|
|
287
|
+
files['package.json'] = JSON.stringify({
|
|
288
|
+
name: projectName,
|
|
289
|
+
version: '1.0.0',
|
|
290
|
+
description: description || 'A modern web application built with Vako and TypeScript',
|
|
291
|
+
main: 'dist/app.js',
|
|
292
|
+
scripts: {
|
|
293
|
+
dev: 'ts-node src/app.ts',
|
|
294
|
+
build: 'tsc',
|
|
295
|
+
start: 'node dist/app.js',
|
|
296
|
+
'type-check': 'tsc --noEmit'
|
|
297
|
+
},
|
|
298
|
+
keywords: ['vako', 'framework', 'web', 'typescript'],
|
|
299
|
+
author: author || '',
|
|
300
|
+
license: license || 'MIT',
|
|
301
|
+
dependencies: {
|
|
302
|
+
vako: '^1.3.13'
|
|
303
|
+
},
|
|
304
|
+
devDependencies: {
|
|
305
|
+
'@types/node': '^20.10.5',
|
|
306
|
+
'@types/express': '^4.17.21',
|
|
307
|
+
'ts-node': '^10.9.2',
|
|
308
|
+
'typescript': '^5.3.3'
|
|
309
|
+
}
|
|
310
|
+
}, null, 2);
|
|
311
|
+
|
|
312
|
+
// tsconfig.json
|
|
313
|
+
files['tsconfig.json'] = JSON.stringify({
|
|
314
|
+
compilerOptions: {
|
|
315
|
+
target: 'ES2020',
|
|
316
|
+
module: 'commonjs',
|
|
317
|
+
lib: ['ES2020'],
|
|
318
|
+
outDir: './dist',
|
|
319
|
+
rootDir: './src',
|
|
320
|
+
strict: true,
|
|
321
|
+
esModuleInterop: true,
|
|
322
|
+
skipLibCheck: true,
|
|
323
|
+
forceConsistentCasingInFileNames: true,
|
|
324
|
+
resolveJsonModule: true,
|
|
325
|
+
declaration: true,
|
|
326
|
+
declarationMap: true,
|
|
327
|
+
sourceMap: true
|
|
328
|
+
},
|
|
329
|
+
include: ['src/**/*'],
|
|
330
|
+
exclude: ['node_modules', 'dist']
|
|
331
|
+
}, null, 2);
|
|
332
|
+
|
|
333
|
+
// src/app.ts
|
|
334
|
+
files['src/app.ts'] = `import { App } from 'vako';
|
|
335
|
+
|
|
336
|
+
const app = new App({
|
|
337
|
+
port: 3000,
|
|
338
|
+
isDev: true,
|
|
339
|
+
viewsDir: 'views',
|
|
340
|
+
staticDir: 'public',
|
|
341
|
+
routesDir: 'src/routes'
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
app.loadRoutes();
|
|
345
|
+
app.listen();
|
|
346
|
+
`;
|
|
347
|
+
|
|
348
|
+
// src/routes/index.ts
|
|
349
|
+
files['src/routes/index.ts'] = `import { Router, Request, Response } from 'express';
|
|
350
|
+
|
|
351
|
+
const router = Router();
|
|
352
|
+
|
|
353
|
+
router.get('/', (req: Request, res: Response) => {
|
|
354
|
+
res.render('index', {
|
|
355
|
+
title: 'Welcome to ${projectName}'
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
export default router;
|
|
360
|
+
`;
|
|
361
|
+
|
|
362
|
+
// README.md
|
|
363
|
+
files['README.md'] = `# ${projectName}
|
|
364
|
+
|
|
365
|
+
${description || 'A modern web application built with Vako and TypeScript'}
|
|
366
|
+
|
|
367
|
+
## Getting Started
|
|
368
|
+
|
|
369
|
+
\`\`\`bash
|
|
370
|
+
npm install
|
|
371
|
+
npm run dev
|
|
372
|
+
\`\`\`
|
|
373
|
+
|
|
374
|
+
## Building for Production
|
|
375
|
+
|
|
376
|
+
\`\`\`bash
|
|
377
|
+
npm run build
|
|
378
|
+
npm start
|
|
379
|
+
\`\`\`
|
|
380
|
+
|
|
381
|
+
## Documentation
|
|
382
|
+
|
|
383
|
+
Visit [https://vako.js.org](https://vako.js.org) for more information.
|
|
384
|
+
`;
|
|
385
|
+
|
|
386
|
+
// .gitignore
|
|
387
|
+
files['.gitignore'] = `node_modules/
|
|
388
|
+
.env
|
|
389
|
+
*.log
|
|
390
|
+
.DS_Store
|
|
391
|
+
dist/
|
|
392
|
+
coverage/
|
|
393
|
+
*.tsbuildinfo
|
|
394
|
+
`;
|
|
395
|
+
|
|
396
|
+
// views/index.ejs
|
|
397
|
+
files['views/index.ejs'] = `<!DOCTYPE html>
|
|
398
|
+
<html lang="en">
|
|
399
|
+
<head>
|
|
400
|
+
<meta charset="UTF-8">
|
|
401
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
402
|
+
<title><%= title %></title>
|
|
403
|
+
</head>
|
|
404
|
+
<body>
|
|
405
|
+
<h1><%= title %></h1>
|
|
406
|
+
<p>Welcome to your Vako TypeScript application!</p>
|
|
407
|
+
</body>
|
|
408
|
+
</html>
|
|
409
|
+
`;
|
|
410
|
+
|
|
411
|
+
return files;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
generateNextJsFiles() {
|
|
415
|
+
const { projectName, description, author, license } = this.config;
|
|
416
|
+
const files = {};
|
|
417
|
+
|
|
418
|
+
// package.json
|
|
419
|
+
files['package.json'] = JSON.stringify({
|
|
420
|
+
name: projectName,
|
|
421
|
+
version: '1.0.0',
|
|
422
|
+
description: description || 'A modern web application built with Vako and Next.js',
|
|
423
|
+
scripts: {
|
|
424
|
+
dev: 'next dev',
|
|
425
|
+
build: 'next build',
|
|
426
|
+
start: 'next start',
|
|
427
|
+
lint: 'next lint'
|
|
428
|
+
},
|
|
429
|
+
keywords: ['vako', 'framework', 'web', 'nextjs', 'react'],
|
|
430
|
+
author: author || '',
|
|
431
|
+
license: license || 'MIT',
|
|
432
|
+
dependencies: {
|
|
433
|
+
vako: '^1.3.13',
|
|
434
|
+
next: '^14.0.0',
|
|
435
|
+
react: '^18.2.0',
|
|
436
|
+
'react-dom': '^18.2.0'
|
|
437
|
+
},
|
|
438
|
+
devDependencies: {
|
|
439
|
+
'@types/node': '^20.10.5',
|
|
440
|
+
'@types/react': '^18.2.0',
|
|
441
|
+
'@types/react-dom': '^18.2.0',
|
|
442
|
+
typescript: '^5.3.3',
|
|
443
|
+
eslint: '^8.56.0',
|
|
444
|
+
'eslint-config-next': '^14.0.0'
|
|
445
|
+
}
|
|
446
|
+
}, null, 2);
|
|
447
|
+
|
|
448
|
+
// next.config.js
|
|
449
|
+
files['next.config.js'] = `/** @type {import('next').NextConfig} */
|
|
450
|
+
const { NextJsAdapter } = require('vako');
|
|
451
|
+
const { App } = require('vako');
|
|
452
|
+
|
|
453
|
+
const nextConfig = {
|
|
454
|
+
reactStrictMode: true,
|
|
455
|
+
// Configuration Vako
|
|
456
|
+
webpack: (config, { isServer }) => {
|
|
457
|
+
if (!isServer) {
|
|
458
|
+
// Configuration pour le client
|
|
459
|
+
}
|
|
460
|
+
return config;
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
module.exports = nextConfig;
|
|
465
|
+
`;
|
|
466
|
+
|
|
467
|
+
// tsconfig.json (pour Next.js)
|
|
468
|
+
files['tsconfig.json'] = JSON.stringify({
|
|
469
|
+
compilerOptions: {
|
|
470
|
+
target: 'ES2020',
|
|
471
|
+
lib: ['dom', 'dom.iterable', 'esnext'],
|
|
472
|
+
allowJs: true,
|
|
473
|
+
skipLibCheck: true,
|
|
474
|
+
strict: true,
|
|
475
|
+
forceConsistentCasingInFileNames: true,
|
|
476
|
+
noEmit: true,
|
|
477
|
+
esModuleInterop: true,
|
|
478
|
+
module: 'esnext',
|
|
479
|
+
moduleResolution: 'bundler',
|
|
480
|
+
resolveJsonModule: true,
|
|
481
|
+
isolatedModules: true,
|
|
482
|
+
jsx: 'preserve',
|
|
483
|
+
incremental: true,
|
|
484
|
+
plugins: [
|
|
485
|
+
{
|
|
486
|
+
name: 'next'
|
|
487
|
+
}
|
|
488
|
+
],
|
|
489
|
+
paths: {
|
|
490
|
+
'@/*': ['./src/*']
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
include: ['next-env.d.ts', '**/*.ts', '**/*.tsx', '.next/types/**/*.ts'],
|
|
494
|
+
exclude: ['node_modules']
|
|
495
|
+
}, null, 2);
|
|
496
|
+
|
|
497
|
+
// server.js (serveur personnalisé avec Vako)
|
|
498
|
+
files['server.js'] = `const { createServer } = require('http');
|
|
499
|
+
const { parse } = require('url');
|
|
500
|
+
const next = require('next');
|
|
501
|
+
const { App } = require('vako');
|
|
502
|
+
const { NextJsAdapter } = require('vako');
|
|
503
|
+
|
|
504
|
+
const dev = process.env.NODE_ENV !== 'production';
|
|
505
|
+
const hostname = 'localhost';
|
|
506
|
+
const port = parseInt(process.env.PORT || '3000', 10);
|
|
507
|
+
|
|
508
|
+
const app = next({ dev, hostname, port });
|
|
509
|
+
const handle = app.getRequestHandler();
|
|
510
|
+
|
|
511
|
+
app.prepare().then(() => {
|
|
512
|
+
// Créer l'instance Vako
|
|
513
|
+
const vakoApp = new App({
|
|
514
|
+
port: port + 1, // Port différent pour Vako
|
|
515
|
+
isDev: dev
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
// Intégrer Vako avec Next.js
|
|
519
|
+
const adapter = new NextJsAdapter({
|
|
520
|
+
nextApp: app,
|
|
521
|
+
enableVakoRoutes: true,
|
|
522
|
+
enableVakoPlugins: true,
|
|
523
|
+
routePrefix: '/api/vako'
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
adapter.integrateRoutes(vakoApp);
|
|
527
|
+
adapter.usePlugins(vakoApp);
|
|
528
|
+
|
|
529
|
+
// Créer le serveur HTTP
|
|
530
|
+
createServer(async (req, res) => {
|
|
531
|
+
try {
|
|
532
|
+
const parsedUrl = parse(req.url, true);
|
|
533
|
+
await handle(req, res, parsedUrl);
|
|
534
|
+
} catch (err) {
|
|
535
|
+
console.error('Error occurred handling', req.url, err);
|
|
536
|
+
res.statusCode = 500;
|
|
537
|
+
res.end('internal server error');
|
|
538
|
+
}
|
|
539
|
+
}).listen(port, (err) => {
|
|
540
|
+
if (err) throw err;
|
|
541
|
+
console.log(\`> Ready on http://\${hostname}:\${port}\`);
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
`;
|
|
545
|
+
|
|
546
|
+
// src/app/layout.tsx
|
|
547
|
+
files['src/app/layout.tsx'] = `import type { Metadata } from 'next';
|
|
548
|
+
import './globals.css';
|
|
549
|
+
|
|
550
|
+
export const metadata: Metadata = {
|
|
551
|
+
title: '${projectName}',
|
|
552
|
+
description: '${description || 'A modern web application built with Vako and Next.js'}'
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
export default function RootLayout({
|
|
556
|
+
children
|
|
557
|
+
}: {
|
|
558
|
+
children: React.ReactNode;
|
|
559
|
+
}) {
|
|
560
|
+
return (
|
|
561
|
+
<html lang="en">
|
|
562
|
+
<body>{children}</body>
|
|
563
|
+
</html>
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
`;
|
|
567
|
+
|
|
568
|
+
// src/app/page.tsx
|
|
569
|
+
files['src/app/page.tsx'] = `export default function Home() {
|
|
570
|
+
return (
|
|
571
|
+
<main>
|
|
572
|
+
<h1>Welcome to ${projectName}</h1>
|
|
573
|
+
<p>Welcome to your Vako Next.js application!</p>
|
|
574
|
+
</main>
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
`;
|
|
578
|
+
|
|
579
|
+
// src/app/globals.css
|
|
580
|
+
files['src/app/globals.css'] = `body {
|
|
581
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
582
|
+
margin: 0;
|
|
583
|
+
padding: 20px;
|
|
584
|
+
background-color: #f5f5f5;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
h1 {
|
|
588
|
+
color: #333;
|
|
589
|
+
}
|
|
590
|
+
`;
|
|
591
|
+
|
|
592
|
+
// README.md
|
|
593
|
+
files['README.md'] = `# ${projectName}
|
|
594
|
+
|
|
595
|
+
${description || 'A modern web application built with Vako and Next.js'}
|
|
596
|
+
|
|
597
|
+
## Getting Started
|
|
598
|
+
|
|
599
|
+
\`\`\`bash
|
|
600
|
+
npm install
|
|
601
|
+
npm run dev
|
|
602
|
+
\`\`\`
|
|
603
|
+
|
|
604
|
+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
605
|
+
|
|
606
|
+
## Building for Production
|
|
607
|
+
|
|
608
|
+
\`\`\`bash
|
|
609
|
+
npm run build
|
|
610
|
+
npm start
|
|
611
|
+
\`\`\`
|
|
612
|
+
|
|
613
|
+
## Documentation
|
|
614
|
+
|
|
615
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|
|
616
|
+
- [Vako Documentation](https://vako.js.org)
|
|
617
|
+
`;
|
|
618
|
+
|
|
619
|
+
// .gitignore
|
|
620
|
+
files['.gitignore'] = `node_modules/
|
|
621
|
+
.env
|
|
622
|
+
*.log
|
|
623
|
+
.DS_Store
|
|
624
|
+
.next/
|
|
625
|
+
out/
|
|
626
|
+
dist/
|
|
627
|
+
coverage/
|
|
628
|
+
`;
|
|
629
|
+
|
|
630
|
+
return files;
|
|
631
|
+
}
|
|
632
|
+
|
|
268
633
|
async configureFeatures() {
|
|
269
634
|
// Configure features based on this.config.features
|
|
270
635
|
// This is a placeholder - features are already configured in generateFiles()
|
package/bin/commands/setup.js
CHANGED
|
@@ -17,6 +17,7 @@ class SetupWizard {
|
|
|
17
17
|
this.config = {
|
|
18
18
|
projectName: '',
|
|
19
19
|
template: 'default',
|
|
20
|
+
codeType: 'ejs', // 'ejs', 'typescript', 'nextjs'
|
|
20
21
|
features: [],
|
|
21
22
|
database: 'sqlite',
|
|
22
23
|
auth: { enabled: false },
|
|
@@ -206,13 +207,64 @@ class SetupWizard {
|
|
|
206
207
|
Object.assign(this.config, this.sanitizeProjectInfo(answers));
|
|
207
208
|
}
|
|
208
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Sélection du type de code (EJS, TypeScript, Next.js)
|
|
212
|
+
*/
|
|
213
|
+
async selectCodeType() {
|
|
214
|
+
console.log(chalk.blue.bold('\n💻 Choose Your Code Type\n'));
|
|
215
|
+
|
|
216
|
+
const codeTypeChoices = [
|
|
217
|
+
{
|
|
218
|
+
name: '📄 EJS - Traditional server-side rendering with EJS templates',
|
|
219
|
+
value: 'ejs',
|
|
220
|
+
description: 'Classic Vako.js with EJS views, perfect for traditional web apps'
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: '📘 TypeScript - Type-safe JavaScript with TypeScript',
|
|
224
|
+
value: 'typescript',
|
|
225
|
+
description: 'Modern TypeScript support with type definitions and IntelliSense'
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: '⚛️ Next.js - React framework with SSR and SSG',
|
|
229
|
+
value: 'nextjs',
|
|
230
|
+
description: 'Next.js integration with React, Server-Side Rendering, and Static Generation'
|
|
231
|
+
}
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
const { codeType } = await inquirer.prompt([{
|
|
235
|
+
type: 'list',
|
|
236
|
+
name: 'codeType',
|
|
237
|
+
message: '🎯 Select your preferred code type:',
|
|
238
|
+
choices: codeTypeChoices.map(choice => ({
|
|
239
|
+
name: choice.name,
|
|
240
|
+
value: choice.value
|
|
241
|
+
})),
|
|
242
|
+
pageSize: 10
|
|
243
|
+
}]);
|
|
244
|
+
|
|
245
|
+
this.config.codeType = codeType;
|
|
246
|
+
|
|
247
|
+
const selectedChoice = codeTypeChoices.find(c => c.value === codeType);
|
|
248
|
+
console.log(chalk.gray(`\n✓ Selected: ${selectedChoice.description}\n`));
|
|
249
|
+
}
|
|
250
|
+
|
|
209
251
|
/**
|
|
210
252
|
* Sélection du template de projet
|
|
211
253
|
*/
|
|
212
254
|
async selectTemplate() {
|
|
213
255
|
console.log(chalk.blue.bold('\n🎨 Choose Your Template\n'));
|
|
214
256
|
|
|
215
|
-
|
|
257
|
+
// Filtrer les templates selon le type de code
|
|
258
|
+
let availableTemplates = Array.from(this.templates.entries());
|
|
259
|
+
|
|
260
|
+
// Si Next.js est sélectionné, limiter les options
|
|
261
|
+
if (this.config.codeType === 'nextjs') {
|
|
262
|
+
availableTemplates = availableTemplates.filter(([key]) =>
|
|
263
|
+
['default', 'api', 'blog', 'portfolio'].includes(key)
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const templateChoices = availableTemplates.map(([value, template]) => ({
|
|
216
268
|
name: template.name,
|
|
217
269
|
value
|
|
218
270
|
}));
|
package/bin/vako.js
CHANGED
|
@@ -21,7 +21,7 @@ const program = new Command();
|
|
|
21
21
|
program
|
|
22
22
|
.name('vako')
|
|
23
23
|
.description('Vako Framework CLI')
|
|
24
|
-
.version('1.3.
|
|
24
|
+
.version('1.3.14');
|
|
25
25
|
|
|
26
26
|
// ============= DEV COMMAND =============
|
|
27
27
|
program
|
|
@@ -32,15 +32,47 @@ program
|
|
|
32
32
|
.option('-w, --watch <dirs>', 'Watch directories', 'views,routes,public')
|
|
33
33
|
.action(async (options) => {
|
|
34
34
|
try {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
const { App } = require('../index');
|
|
36
|
+
const path = require('path');
|
|
37
|
+
const fs = require('fs');
|
|
38
|
+
|
|
39
|
+
// Vérifier si le fichier d'entrée existe
|
|
40
|
+
const entryFile = path.resolve(process.cwd(), options.file);
|
|
41
|
+
if (fs.existsSync(entryFile)) {
|
|
42
|
+
// Charger le fichier d'entrée de l'utilisateur s'il existe
|
|
43
|
+
try {
|
|
44
|
+
require(entryFile);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.warn(chalk.yellow(`⚠️ Warning: Could not load ${options.file}: ${err.message}`));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Créer l'application en mode développement
|
|
51
|
+
const port = parseInt(options.port);
|
|
52
|
+
const wsPort = port + 8;
|
|
53
|
+
|
|
54
|
+
const app = new App({
|
|
55
|
+
port: port,
|
|
56
|
+
wsPort: wsPort,
|
|
57
|
+
isDev: true,
|
|
58
|
+
watchDirs: options.watch.split(',').map(dir => dir.trim()),
|
|
59
|
+
routesDir: 'routes',
|
|
60
|
+
viewsDir: 'views',
|
|
61
|
+
staticDir: 'public'
|
|
39
62
|
});
|
|
40
63
|
|
|
41
|
-
|
|
64
|
+
// Utiliser la méthode startDev qui configure automatiquement le devServer
|
|
65
|
+
app.startDev(port);
|
|
66
|
+
|
|
67
|
+
console.log(chalk.green(`\n🚀 Vako dev server running on http://localhost:${port}`));
|
|
68
|
+
console.log(chalk.cyan(`📡 WebSocket server on ws://localhost:${wsPort}`));
|
|
69
|
+
console.log(chalk.gray(`\n👀 Watching: ${options.watch}\n`));
|
|
70
|
+
|
|
42
71
|
} catch (error) {
|
|
43
72
|
console.error(chalk.red('❌ Error starting dev server:'), error.message);
|
|
73
|
+
if (error.stack) {
|
|
74
|
+
console.error(chalk.gray(error.stack));
|
|
75
|
+
}
|
|
44
76
|
process.exit(1);
|
|
45
77
|
}
|
|
46
78
|
});
|
package/package.json
CHANGED