project-compass 4.2.1 → 4.3.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.
@@ -1,6 +1,7 @@
1
1
  import { dependencyMatches, hasProjectFile, resolveScriptCommand } from './utils.js';
2
2
 
3
3
  export const builtInFrameworks = [
4
+ // ==================== NODE.JS FRAMEWORKS ====================
4
5
  {
5
6
  id: 'next',
6
7
  name: 'Next.js',
@@ -16,9 +17,7 @@ export const builtInFrameworks = [
16
17
  const commands = {};
17
18
  const add = (key, label, fallback) => {
18
19
  const tokens = resolveScriptCommand(project, key, fallback);
19
- if (tokens) {
20
- commands[key] = { label, command: tokens, source: 'framework' };
21
- }
20
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
22
21
  };
23
22
  add('install', 'Next install', (pm) => [pm, 'install']);
24
23
  add('run', 'Next dev', (pm) => pm === 'npm' ? ['npx', 'next', 'dev'] : [pm, 'next', 'dev']);
@@ -28,6 +27,85 @@ export const builtInFrameworks = [
28
27
  return commands;
29
28
  }
30
29
  },
30
+ {
31
+ id: 'express',
32
+ name: 'Express',
33
+ icon: '🚂',
34
+ description: 'Express.js web framework',
35
+ languages: ['Node.js'],
36
+ priority: 108,
37
+ match(project) {
38
+ return dependencyMatches(project, 'express') && !dependencyMatches(project, 'next') && !dependencyMatches(project, '@nestjs/core');
39
+ },
40
+ commands(project) {
41
+ const pm = project.metadata?.packageManager || 'npm';
42
+ return {
43
+ install: { label: 'Express install', command: [pm, 'install'], source: 'framework' },
44
+ start: { label: 'Express start', command: [pm, 'run', 'start'], source: 'framework' },
45
+ dev: { label: 'Express dev', command: [pm, 'run', 'dev'], source: 'framework' }
46
+ };
47
+ }
48
+ },
49
+ {
50
+ id: 'fastify',
51
+ name: 'Fastify',
52
+ icon: '⚡',
53
+ description: 'Fast and low overhead web framework',
54
+ languages: ['Node.js'],
55
+ priority: 107,
56
+ match(project) {
57
+ return dependencyMatches(project, 'fastify');
58
+ },
59
+ commands(project) {
60
+ const pm = project.metadata?.packageManager || 'npm';
61
+ return {
62
+ install: { label: 'Fastify install', command: [pm, 'install'], source: 'framework' },
63
+ start: { label: 'Fastify start', command: [pm, 'run', 'start'], source: 'framework' },
64
+ dev: { label: 'Fastify dev', command: [pm, 'run', 'dev'], source: 'framework' }
65
+ };
66
+ }
67
+ },
68
+ {
69
+ id: 'koa',
70
+ name: 'Koa',
71
+ icon: '🎋',
72
+ description: 'Koa web framework by Express team',
73
+ languages: ['Node.js'],
74
+ priority: 106,
75
+ match(project) {
76
+ return dependencyMatches(project, 'koa') && !dependencyMatches(project, 'koa-router');
77
+ },
78
+ commands(project) {
79
+ const pm = project.metadata?.packageManager || 'npm';
80
+ return {
81
+ install: { label: 'Koa install', command: [pm, 'install'], source: 'framework' },
82
+ start: { label: 'Koa start', command: [pm, 'run', 'start'], source: 'framework' }
83
+ };
84
+ }
85
+ },
86
+ {
87
+ id: 'nest',
88
+ name: 'NestJS',
89
+ icon: '🛡️',
90
+ description: 'NestJS backend',
91
+ languages: ['Node.js'],
92
+ priority: 110,
93
+ match(project) {
94
+ return dependencyMatches(project, '@nestjs/cli') || dependencyMatches(project, '@nestjs/core') || hasProjectFile(project.path, 'nest-cli.json');
95
+ },
96
+ commands(project) {
97
+ const commands = {};
98
+ const add = (key, label, fallback) => {
99
+ const tokens = resolveScriptCommand(project, key, fallback);
100
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
101
+ };
102
+ add('install', 'Nest install', (pm) => [pm, 'install']);
103
+ add('run', 'Nest dev', (pm) => [pm, 'run', 'start:dev']);
104
+ add('build', 'Nest build', (pm) => [pm, 'run', 'build']);
105
+ add('test', 'Nest test', (pm) => [pm, 'run', 'test']);
106
+ return commands;
107
+ }
108
+ },
31
109
  {
32
110
  id: 'react',
33
111
  name: 'React',
@@ -42,9 +120,7 @@ export const builtInFrameworks = [
42
120
  const commands = {};
43
121
  const add = (key, label, fallback) => {
44
122
  const tokens = resolveScriptCommand(project, key, fallback);
45
- if (tokens) {
46
- commands[key] = { label, command: tokens, source: 'framework' };
47
- }
123
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
48
124
  };
49
125
  add('install', 'React install', (pm) => [pm, 'install']);
50
126
  add('run', 'React dev', (pm) => [pm, 'run', 'dev']);
@@ -67,9 +143,7 @@ export const builtInFrameworks = [
67
143
  const commands = {};
68
144
  const add = (key, label, fallback) => {
69
145
  const tokens = resolveScriptCommand(project, key, fallback);
70
- if (tokens) {
71
- commands[key] = { label, command: tokens, source: 'framework' };
72
- }
146
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
73
147
  };
74
148
  add('install', 'Vue install', (pm) => [pm, 'install']);
75
149
  add('run', 'Vue dev', (pm) => [pm, 'run', 'dev']);
@@ -79,50 +153,71 @@ export const builtInFrameworks = [
79
153
  }
80
154
  },
81
155
  {
82
- id: 'nest',
83
- name: 'NestJS',
84
- icon: '🛡️',
85
- description: 'NestJS backend',
156
+ id: 'svelte',
157
+ name: 'Svelte',
158
+ icon: '🧡',
159
+ description: 'SvelteKit or Svelte apps',
86
160
  languages: ['Node.js'],
87
- priority: 110,
161
+ priority: 109,
88
162
  match(project) {
89
- return dependencyMatches(project, '@nestjs/cli') || dependencyMatches(project, '@nestjs/core') || hasProjectFile(project.path, 'nest-cli.json');
163
+ return dependencyMatches(project, 'svelte') || dependencyMatches(project, '@sveltejs/kit') || hasProjectFile(project.path, 'svelte.config.js');
90
164
  },
91
165
  commands(project) {
92
166
  const commands = {};
93
167
  const add = (key, label, fallback) => {
94
168
  const tokens = resolveScriptCommand(project, key, fallback);
95
- if (tokens) {
96
- commands[key] = { label, command: tokens, source: 'framework' };
97
- }
169
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
98
170
  };
99
- add('install', 'Nest install', (pm) => [pm, 'install']);
100
- add('run', 'Nest dev', (pm) => [pm, 'run', 'start:dev']);
101
- add('build', 'Nest build', (pm) => [pm, 'run', 'build']);
102
- add('test', 'Nest test', (pm) => [pm, 'run', 'test']);
171
+ add('install', 'Svelte install', (pm) => [pm, 'install']);
172
+ add('run', 'Svelte dev', (pm) => [pm, 'run', 'dev']);
173
+ add('build', 'Svelte build', (pm) => [pm, 'run', 'build']);
174
+ add('test', 'Svelte test', (pm) => [pm, 'run', 'test']);
103
175
  return commands;
104
176
  }
105
177
  },
106
178
  {
107
- id: 'django',
108
- name: 'Django',
109
- icon: '🌿',
110
- description: 'Django web application',
111
- languages: ['Python'],
179
+ id: 'astro',
180
+ name: 'Astro',
181
+ icon: '🚀',
182
+ description: 'Astro SSR/SSG framework',
183
+ languages: ['Node.js'],
184
+ priority: 108,
185
+ match(project) {
186
+ return dependencyMatches(project, 'astro') || hasProjectFile(project.path, 'astro.config.mjs') || hasProjectFile(project.path, 'astro.config.ts');
187
+ },
188
+ commands(project) {
189
+ const commands = {};
190
+ const add = (key, label, fallback) => {
191
+ const tokens = resolveScriptCommand(project, key, fallback);
192
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
193
+ };
194
+ add('install', 'Astro install', (pm) => [pm, 'install']);
195
+ add('run', 'Astro dev', (pm) => [pm, 'run', 'dev']);
196
+ add('build', 'Astro build', (pm) => [pm, 'run', 'build']);
197
+ add('preview', 'Astro preview', (pm) => [pm, 'run', 'preview']);
198
+ return commands;
199
+ }
200
+ },
201
+ {
202
+ id: 'nuxt',
203
+ name: 'Nuxt',
204
+ icon: '🟢',
205
+ description: 'Nuxt.js Vue framework',
206
+ languages: ['Node.js'],
112
207
  priority: 110,
113
208
  match(project) {
114
- return dependencyMatches(project, 'django') || hasProjectFile(project.path, 'manage.py');
209
+ return dependencyMatches(project, 'nuxt') || dependencyMatches(project, '@nuxt/core') || hasProjectFile(project.path, 'nuxt.config.ts') || hasProjectFile(project.path, 'nuxt.config.js');
115
210
  },
116
211
  commands(project) {
117
- const commands = {};
118
- if (hasProjectFile(project.path, 'requirements.txt')) {
119
- commands.install = { label: 'Pip install', command: ['pip', 'install', '-r', 'requirements.txt'], source: 'framework' };
120
- }
121
- if (hasProjectFile(project.path, 'manage.py')) {
122
- commands.run = { label: 'Django runserver', command: ['python', 'manage.py', 'runserver'], source: 'framework' };
123
- commands.test = { label: 'Django test', command: ['python', 'manage.py', 'test'], source: 'framework' };
124
- commands.migrate = { label: 'Django migrate', command: ['python', 'manage.py', 'migrate'], source: 'framework' };
125
- }
212
+ const commands = {};
213
+ const add = (key, label, fallback) => {
214
+ const tokens = resolveScriptCommand(project, key, fallback);
215
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
216
+ };
217
+ add('install', 'Nuxt install', (pm) => [pm, 'install']);
218
+ add('run', 'Nuxt dev', (pm) => [pm, 'run', 'dev']);
219
+ add('build', 'Nuxt build', (pm) => [pm, 'run', 'build']);
220
+ add('generate', 'Nuxt generate', (pm) => [pm, 'run', 'generate']);
126
221
  return commands;
127
222
  }
128
223
  },
@@ -140,9 +235,7 @@ export const builtInFrameworks = [
140
235
  const commands = {};
141
236
  const add = (key, label, fallback) => {
142
237
  const tokens = resolveScriptCommand(project, key, fallback);
143
- if (tokens) {
144
- commands[key] = { label, command: tokens, source: 'framework' };
145
- }
238
+ if (tokens) commands[key] = { label, command: tokens, source: 'framework' };
146
239
  };
147
240
  add('install', 'Vite install', (pm) => [pm, 'install']);
148
241
  add('run', 'Vite dev', (pm) => pm === 'npm' ? ['npx', 'vite'] : [pm, 'vite']);
@@ -163,7 +256,6 @@ export const builtInFrameworks = [
163
256
  },
164
257
  commands(project) {
165
258
  const pm = project.metadata?.packageManager || 'npm';
166
- // Moved to 'setup' to avoid hijacking the primary 'install' (I) macro
167
259
  return { setup: { label: 'Tailwind Init', command: [pm, 'install', '-D', 'tailwindcss'], source: 'framework' } };
168
260
  }
169
261
  },
@@ -187,6 +279,212 @@ export const builtInFrameworks = [
187
279
  };
188
280
  }
189
281
  },
282
+ {
283
+ id: 'trpc',
284
+ name: 'tRPC',
285
+ icon: '🔌',
286
+ description: 'End-to-end typesafe APIs',
287
+ languages: ['Node.js'],
288
+ priority: 45,
289
+ match(project) {
290
+ return dependencyMatches(project, '@trpc/server') || dependencyMatches(project, '@trpc/client');
291
+ },
292
+ commands(project) {
293
+ const pm = project.metadata?.packageManager || 'npm';
294
+ return {
295
+ dev: { label: 'tRPC dev', command: [pm, 'run', 'dev'], source: 'framework' },
296
+ build: { label: 'tRPC build', command: [pm, 'run', 'build'], source: 'framework' }
297
+ };
298
+ }
299
+ },
300
+ {
301
+ id: 'graphql',
302
+ name: 'GraphQL',
303
+ icon: '◼️',
304
+ description: 'GraphQL API framework',
305
+ languages: ['Node.js'],
306
+ priority: 48,
307
+ match(project) {
308
+ return dependencyMatches(project, 'graphql') || dependencyMatches(project, 'apollo-server') || dependencyMatches(project, '@apollo/server');
309
+ },
310
+ commands(project) {
311
+ const pm = project.metadata?.packageManager || 'npm';
312
+ return {
313
+ start: { label: 'GraphQL start', command: [pm, 'run', 'start'], source: 'framework' },
314
+ dev: { label: 'GraphQL dev', command: [pm, 'run', 'dev'], source: 'framework' }
315
+ };
316
+ }
317
+ },
318
+
319
+ // ==================== PYTHON FRAMEWORKS ====================
320
+ {
321
+ id: 'fastapi',
322
+ name: 'FastAPI',
323
+ icon: '⚡',
324
+ description: 'Modern fast web framework for Python',
325
+ languages: ['Python'],
326
+ priority: 112,
327
+ match(project) {
328
+ return dependencyMatches(project, 'fastapi') || hasProjectFile(project.path, 'main.py');
329
+ },
330
+ commands(project) {
331
+ const pm = project.metadata?.packageManager || 'pip';
332
+ const isUV = pm === 'uv';
333
+ const base = isUV ? ['uv', 'run'] : pm === 'poetry' ? ['poetry', 'run'] : [];
334
+ return {
335
+ install: { label: 'FastAPI deps', command: isUV ? ['uv', 'sync'] : ['pip', 'install', '-r', 'requirements.txt'], source: 'framework' },
336
+ run: { label: 'FastAPI dev', command: [...base, 'uvicorn', 'main:app', '--reload'], source: 'framework' },
337
+ test: { label: 'FastAPI test', command: [...base, 'pytest'], source: 'framework' }
338
+ };
339
+ }
340
+ },
341
+ {
342
+ id: 'flask',
343
+ name: 'Flask',
344
+ icon: '🌶️',
345
+ description: 'Lightweight WSGI web framework',
346
+ languages: ['Python'],
347
+ priority: 111,
348
+ match(project) {
349
+ return dependencyMatches(project, 'flask') && !dependencyMatches(project, 'fastapi');
350
+ },
351
+ commands(project) {
352
+ const pm = project.metadata?.packageManager || 'pip';
353
+ const isUV = pm === 'uv';
354
+ const base = isUV ? ['uv', 'run'] : pm === 'poetry' ? ['poetry', 'run'] : ['python'];
355
+ return {
356
+ install: { label: 'Flask deps', command: isUV ? ['uv', 'sync'] : ['pip', 'install', '-r', 'requirements.txt'], source: 'framework' },
357
+ run: { label: 'Flask run', command: [...base, 'app.py'], source: 'framework' },
358
+ test: { label: 'Flask test', command: [...base, 'pytest'], source: 'framework' }
359
+ };
360
+ }
361
+ },
362
+ {
363
+ id: 'django',
364
+ name: 'Django',
365
+ icon: '🌿',
366
+ description: 'Django web application',
367
+ languages: ['Python'],
368
+ priority: 110,
369
+ match(project) {
370
+ return dependencyMatches(project, 'django') || hasProjectFile(project.path, 'manage.py');
371
+ },
372
+ commands(project) {
373
+ const pm = project.metadata?.packageManager || 'pip';
374
+ const isUV = pm === 'uv';
375
+ const base = isUV ? ['uv', 'run'] : pm === 'poetry' ? ['poetry', 'run'] : ['python'];
376
+ return {
377
+ install: { label: 'Django deps', command: isUV ? ['uv', 'sync'] : ['pip', 'install', '-r', 'requirements.txt'], source: 'framework' },
378
+ run: { label: 'Django runserver', command: [...base, 'manage.py', 'runserver'], source: 'framework' },
379
+ test: { label: 'Django test', command: [...base, 'manage.py', 'test'], source: 'framework' },
380
+ migrate: { label: 'Django migrate', command: [...base, 'manage.py', 'migrate'], source: 'framework' }
381
+ };
382
+ }
383
+ },
384
+ {
385
+ id: 'aiohttp',
386
+ name: 'AioHTTP',
387
+ icon: '🔄',
388
+ description: 'Async HTTP client/server for Python',
389
+ languages: ['Python'],
390
+ priority: 105,
391
+ match(project) {
392
+ return dependencyMatches(project, 'aiohttp');
393
+ },
394
+ commands() {
395
+ return {
396
+ test: { label: 'AioHTTP test', command: ['pytest'], source: 'framework' }
397
+ };
398
+ }
399
+ },
400
+ {
401
+ id: 'sanic',
402
+ name: 'Sanic',
403
+ icon: '🚀',
404
+ description: 'Async Python 3.7+ web server',
405
+ languages: ['Python'],
406
+ priority: 106,
407
+ match(project) {
408
+ return dependencyMatches(project, 'sanic');
409
+ },
410
+ commands() {
411
+ return {
412
+ run: { label: 'Sanic run', command: ['python', '-m', 'sanic', 'app.app'], source: 'framework' },
413
+ test: { label: 'Sanic test', command: ['pytest'], source: 'framework' }
414
+ };
415
+ }
416
+ },
417
+ {
418
+ id: 'tornado',
419
+ name: 'Tornado',
420
+ icon: '🌪️',
421
+ description: 'Python web framework and async networking',
422
+ languages: ['Python'],
423
+ priority: 104,
424
+ match(project) {
425
+ return dependencyMatches(project, 'tornado');
426
+ },
427
+ commands() {
428
+ return {
429
+ run: { label: 'Tornado run', command: ['python', 'app.py'], source: 'framework' },
430
+ test: { label: 'Tornado test', command: ['pytest'], source: 'framework' }
431
+ };
432
+ }
433
+ },
434
+ {
435
+ id: 'pytest',
436
+ name: 'Pytest',
437
+ icon: '✅',
438
+ description: 'Python testing framework',
439
+ languages: ['Python'],
440
+ priority: 50,
441
+ match(project) {
442
+ return dependencyMatches(project, 'pytest');
443
+ },
444
+ commands() {
445
+ return {
446
+ test: { label: 'Pytest run', command: ['pytest'], source: 'framework' },
447
+ coverage: { label: 'Pytest coverage', command: ['pytest', '--cov'], source: 'framework' }
448
+ };
449
+ }
450
+ },
451
+ {
452
+ id: 'sqlalchemy',
453
+ name: 'SQLAlchemy',
454
+ icon: '🗄️',
455
+ description: 'Python SQL toolkit and ORM',
456
+ languages: ['Python'],
457
+ priority: 48,
458
+ match(project) {
459
+ return dependencyMatches(project, 'sqlalchemy') || dependencyMatches(project, 'flask-sqlalchemy');
460
+ },
461
+ commands() {
462
+ return {
463
+ test: { label: 'SQLAlchemy test', command: ['pytest'], source: 'framework' }
464
+ };
465
+ }
466
+ },
467
+
468
+ // ==================== RUST FRAMEWORKS ====================
469
+ {
470
+ id: 'actix',
471
+ name: 'Actix Web',
472
+ icon: '🎭',
473
+ description: 'Powerful web framework for Rust',
474
+ languages: ['Rust'],
475
+ priority: 110,
476
+ match(project) {
477
+ return dependencyMatches(project, 'actix-web');
478
+ },
479
+ commands() {
480
+ return {
481
+ install: { label: 'Cargo Fetch', command: ['cargo', 'fetch'], source: 'framework' },
482
+ run: { label: 'Actix Run', command: ['cargo', 'run'], source: 'framework' },
483
+ test: { label: 'Actix Test', command: ['cargo', 'test'], source: 'framework' },
484
+ build: { label: 'Actix Build', command: ['cargo', 'build'], source: 'framework' }
485
+ };
486
+ }
487
+ },
190
488
  {
191
489
  id: 'rocket',
192
490
  name: 'Rocket',
@@ -205,13 +503,205 @@ export const builtInFrameworks = [
205
503
  };
206
504
  }
207
505
  },
506
+ {
507
+ id: 'axum',
508
+ name: 'Axum',
509
+ icon: '🗡️',
510
+ description: 'Ergonomic and modular web framework for Rust',
511
+ languages: ['Rust'],
512
+ priority: 108,
513
+ match(project) {
514
+ return dependencyMatches(project, 'axum');
515
+ },
516
+ commands() {
517
+ return {
518
+ install: { label: 'Cargo Fetch', command: ['cargo', 'fetch'], source: 'framework' },
519
+ run: { label: 'Axum Run', command: ['cargo', 'run'], source: 'framework' },
520
+ test: { label: 'Axum Test', command: ['cargo', 'test'], source: 'framework' }
521
+ };
522
+ }
523
+ },
524
+ {
525
+ id: 'warp',
526
+ name: 'Warp',
527
+ icon: '🌀',
528
+ description: 'Super-easy, composable web framework for Rust',
529
+ languages: ['Rust'],
530
+ priority: 104,
531
+ match(project) {
532
+ return dependencyMatches(project, 'warp');
533
+ },
534
+ commands() {
535
+ return {
536
+ run: { label: 'Warp Run', command: ['cargo', 'run'], source: 'framework' },
537
+ test: { label: 'Warp Test', command: ['cargo', 'test'], source: 'framework' }
538
+ };
539
+ }
540
+ },
541
+ {
542
+ id: 'tokio',
543
+ name: 'Tokio',
544
+ icon: '⚡',
545
+ description: 'Async runtime for Rust',
546
+ languages: ['Rust'],
547
+ priority: 50,
548
+ match(project) {
549
+ return dependencyMatches(project, 'tokio');
550
+ },
551
+ commands() {
552
+ return {
553
+ run: { label: 'Tokio Run', command: ['cargo', 'run'], source: 'framework' },
554
+ test: { label: 'Tokio Test', command: ['cargo', 'test'], source: 'framework' }
555
+ };
556
+ }
557
+ },
558
+
559
+ // ==================== GO FRAMEWORKS ====================
560
+ {
561
+ id: 'gin',
562
+ name: 'Gin',
563
+ icon: '🍸',
564
+ description: 'HTTP web framework for Go',
565
+ languages: ['Go'],
566
+ priority: 110,
567
+ match(project) {
568
+ return dependencyMatches(project, 'gin') || dependencyMatches(project, 'github.com/gin-gonic/gin');
569
+ },
570
+ commands() {
571
+ return {
572
+ install: { label: 'Go mod tidy', command: ['go', 'mod', 'tidy'], source: 'framework' },
573
+ run: { label: 'Gin Run', command: ['go', 'run', 'main.go'], source: 'framework' },
574
+ test: { label: 'Gin Test', command: ['go', 'test', './...'], source: 'framework' },
575
+ build: { label: 'Gin Build', command: ['go', 'build', '-o', 'app'], source: 'framework' }
576
+ };
577
+ }
578
+ },
579
+ {
580
+ id: 'echo',
581
+ name: 'Echo',
582
+ icon: '🔊',
583
+ description: 'High performance, minimalist Go web framework',
584
+ languages: ['Go'],
585
+ priority: 108,
586
+ match(project) {
587
+ return dependencyMatches(project, 'echo') || dependencyMatches(project, 'github.com/labstack/echo/v4');
588
+ },
589
+ commands() {
590
+ return {
591
+ run: { label: 'Echo Run', command: ['go', 'run', 'main.go'], source: 'framework' },
592
+ test: { label: 'Echo Test', command: ['go', 'test', './...'], source: 'framework' }
593
+ };
594
+ }
595
+ },
596
+ {
597
+ id: 'fiber',
598
+ name: 'Fiber',
599
+ icon: '🔥',
600
+ description: 'Express-inspired web framework for Go',
601
+ languages: ['Go'],
602
+ priority: 109,
603
+ match(project) {
604
+ return dependencyMatches(project, 'fiber') || dependencyMatches(project, 'github.com/gofiber/fiber/v2');
605
+ },
606
+ commands() {
607
+ return {
608
+ run: { label: 'Fiber Run', command: ['go', 'run', 'main.go'], source: 'framework' },
609
+ test: { label: 'Fiber Test', command: ['go', 'test', './...'], source: 'framework' }
610
+ };
611
+ }
612
+ },
613
+ {
614
+ id: 'chi',
615
+ name: 'Chi',
616
+ icon: '🤝',
617
+ description: 'Lightweight, idiomatic router for Go',
618
+ languages: ['Go'],
619
+ priority: 105,
620
+ match(project) {
621
+ return dependencyMatches(project, 'chi') || dependencyMatches(project, 'github.com/go-chi/chi/v5');
622
+ },
623
+ commands() {
624
+ return {
625
+ run: { label: 'Chi Run', command: ['go', 'run', 'main.go'], source: 'framework' },
626
+ test: { label: 'Chi Test', command: ['go', 'test', './...'], source: 'framework' }
627
+ };
628
+ }
629
+ },
630
+
631
+ // ==================== JAVA FRAMEWORKS ====================
632
+ {
633
+ id: 'spring-boot',
634
+ name: 'Spring Boot',
635
+ icon: '🍃',
636
+ description: 'Spring Boot Java framework',
637
+ languages: ['Java'],
638
+ priority: 115,
639
+ match(project) {
640
+ return dependencyMatches(project, 'spring-boot') || dependencyMatches(project, 'org.springframework.boot') || hasProjectFile(project.path, 'pom.xml') || hasProjectFile(project.path, 'build.gradle');
641
+ },
642
+ commands(project) {
643
+ if (hasProjectFile(project.path, 'pom.xml')) {
644
+ return {
645
+ install: { label: 'Maven Install', command: ['mvn', 'install'], source: 'framework' },
646
+ run: { label: 'Spring Boot Run', command: ['mvn', 'spring-boot:run'], source: 'framework' },
647
+ test: { label: 'Spring Boot Test', command: ['mvn', 'test'], source: 'framework' },
648
+ build: { label: 'Spring Boot Build', command: ['mvn', 'package'], source: 'framework' }
649
+ };
650
+ }
651
+ if (hasProjectFile(project.path, 'build.gradle') || hasProjectFile(project.path, 'build.gradle.kts')) {
652
+ return {
653
+ install: { label: 'Gradle Build', command: ['./gradlew', 'build'], source: 'framework' },
654
+ run: { label: 'Spring Boot Run', command: ['./gradlew', 'bootRun'], source: 'framework' },
655
+ test: { label: 'Spring Boot Test', command: ['./gradlew', 'test'], source: 'framework' }
656
+ };
657
+ }
658
+ return {};
659
+ }
660
+ },
661
+ {
662
+ id: 'quarkus',
663
+ name: 'Quarkus',
664
+ icon: '⚡',
665
+ description: 'Kubernetes Native Java stack',
666
+ languages: ['Java'],
667
+ priority: 108,
668
+ match(project) {
669
+ return dependencyMatches(project, 'quarkus') || hasProjectFile(project.path, 'pom.xml');
670
+ },
671
+ commands() {
672
+ return {
673
+ run: { label: 'Quarkus Dev', command: ['mvn', 'quarkus:dev'], source: 'framework' },
674
+ build: { label: 'Quarkus Build', command: ['mvn', 'package'], source: 'framework' },
675
+ test: { label: 'Quarkus Test', command: ['mvn', 'test'], source: 'framework' }
676
+ };
677
+ }
678
+ },
679
+ {
680
+ id: 'micronaut',
681
+ name: 'Micronaut',
682
+ icon: '🚀',
683
+ description: 'Modern JVM-based framework',
684
+ languages: ['Java'],
685
+ priority: 106,
686
+ match(project) {
687
+ return dependencyMatches(project, 'micronaut') || hasProjectFile(project.path, 'pom.xml');
688
+ },
689
+ commands() {
690
+ return {
691
+ run: { label: 'Micronaut Run', command: ['./mvnw', 'run'], source: 'framework' },
692
+ test: { label: 'Micronaut Test', command: ['./mvnw', 'test'], source: 'framework' }
693
+ };
694
+ }
695
+ },
696
+
697
+ // ==================== PHP FRAMEWORKS ====================
208
698
  {
209
699
  id: 'laravel',
210
700
  name: 'Laravel',
211
701
  icon: '🧡',
212
702
  description: 'Laravel PHP Framework',
213
703
  languages: ['PHP'],
214
- priority: 105,
704
+ priority: 110,
215
705
  match(project) {
216
706
  return hasProjectFile(project.path, 'artisan') || dependencyMatches(project, 'laravel/framework');
217
707
  },
@@ -223,5 +713,165 @@ export const builtInFrameworks = [
223
713
  migrate: { label: 'Artisan Migrate', command: ['php', 'artisan', 'migrate'], source: 'framework' }
224
714
  };
225
715
  }
716
+ },
717
+ {
718
+ id: 'symfony',
719
+ name: 'Symfony',
720
+ icon: '🎵',
721
+ description: 'Symfony PHP Framework',
722
+ languages: ['PHP'],
723
+ priority: 108,
724
+ match(project) {
725
+ return hasProjectFile(project.path, 'bin/console') || dependencyMatches(project, 'symfony/symfony') || hasProjectFile(project.path, 'symfony.lock');
726
+ },
727
+ commands() {
728
+ return {
729
+ install: { label: 'Composer install', command: ['composer', 'install'], source: 'framework' },
730
+ run: { label: 'Symfony Server', command: ['symfony', 'server:start'], source: 'framework' },
731
+ test: { label: 'Symfony Test', command: ['php', 'bin/phpunit'], source: 'framework' }
732
+ };
733
+ }
734
+ },
735
+ {
736
+ id: 'codeigniter',
737
+ name: 'CodeIgniter',
738
+ icon: '🔥',
739
+ description: 'CodeIgniter PHP Framework',
740
+ languages: ['PHP'],
741
+ priority: 104,
742
+ match(project) {
743
+ return hasProjectFile(project.path, 'application/config/config.php') || dependencyMatches(project, 'codeigniter4/framework');
744
+ },
745
+ commands() {
746
+ return {
747
+ test: { label: 'CI Test', command: ['php', 'vendor/bin/phpunit'], source: 'framework' }
748
+ };
749
+ }
750
+ },
751
+
752
+ // ==================== RUBY FRAMEWORKS ====================
753
+ {
754
+ id: 'rails',
755
+ name: 'Ruby on Rails',
756
+ icon: '🛤️',
757
+ description: 'Ruby on Rails framework',
758
+ languages: ['Ruby'],
759
+ priority: 110,
760
+ match(project) {
761
+ return hasProjectFile(project.path, 'bin/rails') || hasProjectFile(project.path, 'config/application.rb') || hasProjectFile(project.path, 'Gemfile.lock');
762
+ },
763
+ commands() {
764
+ return {
765
+ install: { label: 'Bundle install', command: ['bundle', 'install'], source: 'framework' },
766
+ run: { label: 'Rails server', command: ['bin/rails', 'server'], source: 'framework' },
767
+ test: { label: 'Rails test', command: ['bin/rails', 'test'], source: 'framework' },
768
+ migrate: { label: 'Rails migrate', command: ['bin/rails', 'db:migrate'], source: 'framework' }
769
+ };
770
+ }
771
+ },
772
+ {
773
+ id: 'sinatra',
774
+ name: 'Sinatra',
775
+ icon: '🎷',
776
+ description: 'Sinatra DSL for quickly creating web applications',
777
+ languages: ['Ruby'],
778
+ priority: 105,
779
+ match(project) {
780
+ return dependencyMatches(project, 'sinatra') || hasProjectFile(project.path, 'config.ru');
781
+ },
782
+ commands() {
783
+ return {
784
+ install: { label: 'Bundle install', command: ['bundle', 'install'], source: 'framework' },
785
+ run: { label: 'Rackup', command: ['rackup'], source: 'framework' }
786
+ };
787
+ }
788
+ },
789
+
790
+ // ==================== .NET FRAMEWORKS ====================
791
+ {
792
+ id: 'aspnet-core',
793
+ name: 'ASP.NET Core',
794
+ icon: '🔷',
795
+ description: 'ASP.NET Core web framework',
796
+ languages: ['.NET'],
797
+ priority: 110,
798
+ match(project) {
799
+ return hasProjectFile(project.path, 'Program.cs') && (hasProjectFile(project.path, '*.csproj') || hasProjectFile(project.path, '*.fsproj'));
800
+ },
801
+ commands() {
802
+ return {
803
+ install: { label: 'Dotnet restore', command: ['dotnet', 'restore'], source: 'framework' },
804
+ run: { label: 'Dotnet run', command: ['dotnet', 'run'], source: 'framework' },
805
+ test: { label: 'Dotnet test', command: ['dotnet', 'test'], source: 'framework' },
806
+ build: { label: 'Dotnet build', command: ['dotnet', 'build'], source: 'framework' }
807
+ };
808
+ }
809
+ },
810
+ {
811
+ id: 'blazor',
812
+ name: 'Blazor',
813
+ icon: '🌀',
814
+ description: 'Blazor interactive web UI with .NET',
815
+ languages: ['.NET'],
816
+ priority: 105,
817
+ match(project) {
818
+ return dependencyMatches(project, 'Microsoft.AspNetCore.Components.Web') || hasProjectFile(project.path, '*.csproj');
819
+ },
820
+ commands() {
821
+ return {
822
+ run: { label: 'Blazor Run', command: ['dotnet', 'run'], source: 'framework' },
823
+ build: { label: 'Blazor Build', command: ['dotnet', 'build'], source: 'framework' }
824
+ };
825
+ }
826
+ },
827
+
828
+ // ==================== DATA SCIENCE / ML ====================
829
+ {
830
+ id: 'pandas',
831
+ name: 'Pandas',
832
+ icon: '🐼',
833
+ description: 'Python data analysis library',
834
+ languages: ['Python'],
835
+ priority: 45,
836
+ match(project) {
837
+ return dependencyMatches(project, 'pandas');
838
+ },
839
+ commands() {
840
+ return {
841
+ test: { label: 'Pandas test', command: ['pytest'], source: 'framework' }
842
+ };
843
+ }
844
+ },
845
+ {
846
+ id: 'pytorch',
847
+ name: 'PyTorch',
848
+ icon: '🔥',
849
+ description: 'Machine learning framework for Python',
850
+ languages: ['Python'],
851
+ priority: 45,
852
+ match(project) {
853
+ return dependencyMatches(project, 'torch') || dependencyMatches(project, 'pytorch');
854
+ },
855
+ commands() {
856
+ return {
857
+ test: { label: 'PyTorch test', command: ['pytest'], source: 'framework' }
858
+ };
859
+ }
860
+ },
861
+ {
862
+ id: 'tensorflow',
863
+ name: 'TensorFlow',
864
+ icon: '🧠',
865
+ description: 'TensorFlow ML library',
866
+ languages: ['Python'],
867
+ priority: 45,
868
+ match(project) {
869
+ return dependencyMatches(project, 'tensorflow');
870
+ },
871
+ commands() {
872
+ return {
873
+ test: { label: 'TF test', command: ['pytest'], source: 'framework' }
874
+ };
875
+ }
226
876
  }
227
877
  ];