package-installer-cli 1.1.0 → 1.2.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/dist/utils/dependencyInstaller.js +0 -44
  3. data/dist/utils/featureInstaller.js +149 -89
  4. data/dist/utils/languageConfig.js +167 -298
  5. data/dist/utils/templateResolver.js +3 -4
  6. data/dist/utils/utils.js +1 -1
  7. data/lib/package_installer_cli.rb +1 -1
  8. data/templates/django/django-full-stack-template/django-project-template/deployment/docker/build.sh +0 -0
  9. data/templates/django/django-full-stack-template/django-project-template/deployment/docker/manage.py +0 -0
  10. data/templates/django/django-full-stack-template/django-project-template/src/compile-locale.sh +0 -0
  11. data/templates/django/django-full-stack-template/django-project-template/src/compile-sass.sh +0 -0
  12. data/templates/django/django-full-stack-template/django-project-template/src/manage.py +0 -0
  13. data/templates/django/django-inertia-svelte-template/django-inertia-svelte-template-starter/manage.py +0 -0
  14. data/templates/flask/flask-cookiecutter-advance-template/cookiecutter-docker.sh +0 -0
  15. data/templates/flask/flask-cookiecutter-advance-template/{{cookiecutter.app_name}}/autoapp.py +0 -0
  16. data/templates/flask/flask-project-template/apply.sh +0 -0
  17. data/templates/react-native/typescript/template/android/gradlew +0 -0
  18. data/templates/ruby/rails_7_esbuild_hotwire_tailwindcss_starter/bin/bundle +0 -0
  19. data/templates/ruby/rails_7_esbuild_hotwire_tailwindcss_starter/bin/dev +0 -0
  20. data/templates/ruby/rails_7_esbuild_hotwire_tailwindcss_starter/bin/docker-entrypoint +0 -0
  21. data/templates/ruby/rails_7_esbuild_hotwire_tailwindcss_starter/bin/rails +0 -0
  22. data/templates/ruby/rails_7_esbuild_hotwire_tailwindcss_starter/bin/rake +0 -0
  23. data/templates/ruby/rails_7_esbuild_hotwire_tailwindcss_starter/bin/setup +0 -0
  24. data/templates/ruby/ruby-on-rails-apis-template/bin/bundle +0 -0
  25. data/templates/ruby/ruby-on-rails-apis-template/bin/rails +0 -0
  26. data/templates/ruby/ruby-on-rails-apis-template/bin/rake +0 -0
  27. data/templates/ruby/ruby-on-rails-apis-template/bin/setup +0 -0
  28. data/templates/ruby/ruby-on-rails-apis-template/bin/spring +0 -0
  29. data/templates/ruby/ruby-on-rails-apis-template/bin/update +0 -0
  30. data/templates/ruby/ruby-on-rails-boilerplate-template/bin/bundle +0 -0
  31. data/templates/ruby/ruby-on-rails-boilerplate-template/bin/dev +0 -0
  32. data/templates/ruby/ruby-on-rails-boilerplate-template/bin/importmap +0 -0
  33. data/templates/ruby/ruby-on-rails-boilerplate-template/bin/rails +0 -0
  34. data/templates/ruby/ruby-on-rails-boilerplate-template/bin/rake +0 -0
  35. data/templates/ruby/ruby-on-rails-boilerplate-template/bin/setup +0 -0
  36. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 67f8a4e5d268f24f01d493f27c9cf688d7e909fb0ec7f67906c0955e4d022ee9
4
- data.tar.gz: 52f196b68f262f313be40bac842f592d32c1a8c3310247bd7cc386cc5298103a
3
+ metadata.gz: 7f432378951e281eb37210295d7894abbf072093bd9a2e6099f1d3219ad45eb0
4
+ data.tar.gz: 0e9edf8310281ce583765615d8d41f1897b7e0fab8e6cc3dbbfa405d39a63cc9
5
5
  SHA512:
6
- metadata.gz: b9cbbdb378e2bff40893095c025e5b02802080e1e06a25c471d0e096beadbe4ff40bd3b377959dc9e4a4a7d946f805ffa491ee8194315dd8cd93cc6af2680d86
7
- data.tar.gz: 45b213c38590a89247580f3ccf78ca0d4d714aafdc67f30effe08c45efebdd9ad1d7022857c82fc897f20087d03b6c0f14157d5544f58e6536c16e67db972e8c
6
+ metadata.gz: b0490199b16d2f27b1513fc9360895c02cb9a1a2fc58a4cddc5611c20afa21c8ef6e609d99b4dc7271a19de0ea21c1275127839d4b56b26b91e0554cff66c296
7
+ data.tar.gz: 6e7cec10cae328695c8fb9328797f5efc46ced7e04b0bb99dffe40ccbb887bc9ee495277b2ac49e5196e88f98e6a71a2cec823ad4ec692ee78424ce5cc3b5d53
@@ -332,28 +332,6 @@ function extractInstalledPackages(output, language) {
332
332
  });
333
333
  }
334
334
  break;
335
- case 'php':
336
- // Parse composer output
337
- const phpMatches = output.match(/Installing (.+?) \(/gi);
338
- if (phpMatches) {
339
- phpMatches.forEach(match => {
340
- const pkg = match.replace(/Installing\s+/, '').replace(/\s+\(.*/, '');
341
- if (pkg)
342
- packages.push(pkg);
343
- });
344
- }
345
- break;
346
- case 'java':
347
- // Parse maven output
348
- const javaMatches = output.match(/Downloaded from .+?: (.+?) \(/gi);
349
- if (javaMatches) {
350
- javaMatches.forEach(match => {
351
- const pkg = match.match(/: (.+?) \(/)?.[1];
352
- if (pkg)
353
- packages.push(pkg);
354
- });
355
- }
356
- break;
357
335
  case 'ruby':
358
336
  // Parse bundler output
359
337
  const rubyMatches = output.match(/Installing (.+?) \(/gi);
@@ -365,17 +343,6 @@ function extractInstalledPackages(output, language) {
365
343
  });
366
344
  }
367
345
  break;
368
- case 'dotnet':
369
- // Parse dotnet output
370
- const dotnetMatches = output.match(/PackageReference for package '(.+?)'/gi);
371
- if (dotnetMatches) {
372
- dotnetMatches.forEach(match => {
373
- const pkg = match.match(/'(.+?)'/)?.[1];
374
- if (pkg)
375
- packages.push(pkg);
376
- });
377
- }
378
- break;
379
346
  default:
380
347
  // Generic extraction
381
348
  packages.push('dependencies');
@@ -443,20 +410,9 @@ export async function installPackages(projectPath, language, packages, options =
443
410
  case 'go':
444
411
  command = `go get ${packages.join(' ')}`;
445
412
  break;
446
- case 'php':
447
- const composerFlags = isDev ? '--dev' : '';
448
- command = `composer require ${composerFlags} ${packages.join(' ')}`;
449
- break;
450
- case 'java':
451
- // For Maven, we'd typically need to edit pom.xml, but for simplicity:
452
- command = `mvn dependency:get -Dartifact=${packages[0]}`;
453
- break;
454
413
  case 'ruby':
455
414
  command = `bundle add ${packages.join(' ')}`;
456
415
  break;
457
- case 'dotnet':
458
- command = `dotnet add package ${packages.join(' ')}`;
459
- break;
460
416
  default:
461
417
  throw new Error(`Unsupported language: ${language}`);
462
418
  }
@@ -45,7 +45,7 @@ export { getCliRootPath } from './pathResolver.js';
45
45
  * Detect the current project's framework and language with improved logic
46
46
  */
47
47
  /**
48
- * Detect if a Next.js project uses src folder structure
48
+ * Detect if a Next.js project uses src folder structure (Next.js only)
49
49
  */
50
50
  async function detectNextjsSrcStructure(projectPath) {
51
51
  try {
@@ -54,17 +54,17 @@ async function detectNextjsSrcStructure(projectPath) {
54
54
  if (!await fs.pathExists(srcPath)) {
55
55
  return false;
56
56
  }
57
- // Check for app directory in src (App Router)
57
+ // Check for Next.js App Router (app directory in src)
58
58
  const srcAppPath = path.join(srcPath, 'app');
59
59
  if (await fs.pathExists(srcAppPath)) {
60
60
  return true;
61
61
  }
62
- // Check for pages directory in src (Pages Router)
62
+ // Check for Next.js Pages Router (pages directory in src)
63
63
  const srcPagesPath = path.join(srcPath, 'pages');
64
64
  if (await fs.pathExists(srcPagesPath)) {
65
65
  return true;
66
66
  }
67
- // Check for components directory in src
67
+ // Check for components directory in src (common pattern)
68
68
  const srcComponentsPath = path.join(srcPath, 'components');
69
69
  if (await fs.pathExists(srcComponentsPath)) {
70
70
  return true;
@@ -76,45 +76,35 @@ async function detectNextjsSrcStructure(projectPath) {
76
76
  }
77
77
  }
78
78
  /**
79
- * Adjust file path for Next.js src folder structure
79
+ * Adjust file path for Next.js src folder structure (Next.js only)
80
+ * Dynamically places files in src/ folder based on their path structure
80
81
  */
81
- function adjustNextjsFilePath(filePath, hasSrcFolder, projectPath) {
82
- // Files that should be placed in src folder when src structure is used
83
- const srcFolderFiles = [
84
- 'app/',
85
- 'pages/',
86
- 'components/',
87
- 'lib/',
88
- 'utils/',
89
- 'hooks/',
90
- 'context/',
91
- 'types/',
92
- 'styles/' // Only component-specific styles, not global ones
93
- ];
94
- // Files that should always be in root regardless of src folder
82
+ function adjustNextjsSrcFilePath(filePath, hasSrcFolder, projectPath) {
83
+ // If project doesn't use src folder, return original path
84
+ if (!hasSrcFolder) {
85
+ return path.join(projectPath, filePath);
86
+ }
87
+ // Files that should ALWAYS be in root regardless of src folder
95
88
  const rootOnlyFiles = [
96
- 'middleware.ts',
97
- 'middleware.js',
98
- 'next.config.js',
99
- 'next.config.mjs',
100
89
  '.env',
101
90
  '.env.local',
102
91
  '.env.example',
103
92
  'package.json',
93
+ 'next.config.js',
94
+ 'next.config.mjs',
104
95
  'tailwind.config.js',
105
96
  'tailwind.config.ts',
106
- 'postcss.config.js'
97
+ 'postcss.config.js',
98
+ 'middleware.ts',
99
+ 'middleware.js'
107
100
  ];
108
- // Check if this file should always be in root
109
101
  const fileName = path.basename(filePath);
110
- if (rootOnlyFiles.includes(fileName) || filePath.includes('public/')) {
111
- return filePath;
112
- }
113
- // If project has src folder and this file should be in src
114
- if (hasSrcFolder && srcFolderFiles.some(prefix => filePath.startsWith(prefix))) {
115
- return path.join('src', filePath);
102
+ // Check if this file should always be in root
103
+ if (rootOnlyFiles.includes(fileName) || filePath.startsWith('public/')) {
104
+ return path.join(projectPath, filePath);
116
105
  }
117
- return filePath;
106
+ // For all other files, place them in src/ folder if src structure is used
107
+ return path.join(projectPath, 'src', filePath);
118
108
  }
119
109
  export async function detectProjectStack(projectPath) {
120
110
  try {
@@ -183,7 +173,7 @@ export async function detectProjectStack(projectPath) {
183
173
  else if (dependencies['@remix-run/react']) {
184
174
  framework = 'remixjs';
185
175
  }
186
- // For non-Next.js projects, simple src folder check
176
+ // For other frameworks, simple src folder check
187
177
  if (framework !== 'nextjs' && !hasSrcFolder) {
188
178
  hasSrcFolder = await fs.pathExists(path.join(projectPath, 'src'));
189
179
  }
@@ -321,9 +311,9 @@ async function processFeatureFile(filePath, fileConfig, featureName, provider, p
321
311
  }
322
312
  // Handle file path adjustment based on project structure
323
313
  let targetFilePath = path.join(projectPath, filePath);
324
- // For Next.js projects, adjust file paths based on src folder structure
325
- if (projectInfo.framework === 'nextjs') {
326
- targetFilePath = adjustNextjsFilePath(filePath, projectInfo.hasSrcFolder || false, projectPath);
314
+ // For Next.js projects with src folder structure, adjust file paths accordingly
315
+ if (projectInfo.framework === 'nextjs' && projectInfo.hasSrcFolder) {
316
+ targetFilePath = adjustNextjsSrcFilePath(filePath, projectInfo.hasSrcFolder, projectPath);
327
317
  }
328
318
  // Ensure all parent directories exist before processing
329
319
  await fs.ensureDir(path.dirname(targetFilePath));
@@ -385,85 +375,155 @@ async function handleFileCreation(sourceFilePath, targetFilePath, cachedContent)
385
375
  console.log(chalk.green(`✅ Created: ${path.relative(process.cwd(), targetFilePath)}`));
386
376
  }
387
377
  /**
388
- * Handle file overwrite (replace existing content)
378
+ * Handle file overwrite (replace existing content or create if doesn't exist)
389
379
  */
390
380
  async function handleFileOverwrite(sourceFilePath, targetFilePath, cachedContent) {
391
- if (cachedContent) {
392
- await fs.outputFile(targetFilePath, cachedContent);
381
+ // Ensure target directory exists
382
+ await fs.ensureDir(path.dirname(targetFilePath));
383
+ const fileExists = await fs.pathExists(targetFilePath);
384
+ try {
385
+ if (cachedContent) {
386
+ await fs.outputFile(targetFilePath, cachedContent);
387
+ }
388
+ else {
389
+ // Check if source template exists
390
+ if (await fs.pathExists(sourceFilePath)) {
391
+ await copyTemplateFile(sourceFilePath, targetFilePath);
392
+ }
393
+ else {
394
+ console.log(chalk.yellow(`⚠️ Template file not found, skipping: ${path.relative(process.cwd(), sourceFilePath)}`));
395
+ console.log(chalk.gray(` This might be due to running a globally installed CLI. Consider using 'npx' or installing locally.`));
396
+ return;
397
+ }
398
+ }
399
+ if (fileExists) {
400
+ console.log(chalk.green(`✅ Updated: ${path.relative(process.cwd(), targetFilePath)}`));
401
+ }
402
+ else {
403
+ console.log(chalk.green(`✅ Created: ${path.relative(process.cwd(), targetFilePath)}`));
404
+ }
393
405
  }
394
- else {
395
- await copyTemplateFile(sourceFilePath, targetFilePath);
406
+ catch (error) {
407
+ console.error(chalk.red(`❌ Failed to overwrite/create ${path.relative(process.cwd(), targetFilePath)}: ${error}`));
408
+ throw error;
396
409
  }
397
- console.log(chalk.green(`✅ Updated: ${path.relative(process.cwd(), targetFilePath)}`));
398
410
  }
399
411
  /**
400
- * Handle file append (add content to end of file)
412
+ * Handle file append (add content to end of file, create if doesn't exist)
401
413
  */
402
414
  async function handleFileAppend(sourceFilePath, targetFilePath, cachedContent) {
415
+ // Ensure target directory exists
416
+ await fs.ensureDir(path.dirname(targetFilePath));
417
+ const fileExists = await fs.pathExists(targetFilePath);
403
418
  let existingContent = '';
404
- if (await fs.pathExists(targetFilePath)) {
405
- existingContent = await fs.readFile(targetFilePath, 'utf-8');
406
- }
407
- let templateContent;
408
- if (cachedContent) {
409
- templateContent = cachedContent;
419
+ try {
420
+ if (fileExists) {
421
+ existingContent = await fs.readFile(targetFilePath, 'utf8');
422
+ }
423
+ let contentToAppend = '';
424
+ if (cachedContent) {
425
+ contentToAppend = cachedContent;
426
+ }
427
+ else {
428
+ // Check if source template exists
429
+ if (await fs.pathExists(sourceFilePath)) {
430
+ contentToAppend = await fs.readFile(sourceFilePath, 'utf8');
431
+ }
432
+ else {
433
+ console.log(chalk.yellow(`⚠️ Template file not found, skipping append: ${path.relative(process.cwd(), sourceFilePath)}`));
434
+ console.log(chalk.gray(` This might be due to running a globally installed CLI. Consider using 'npx' or installing locally.`));
435
+ return;
436
+ }
437
+ }
438
+ const newContent = existingContent + contentToAppend;
439
+ await fs.outputFile(targetFilePath, newContent);
440
+ if (fileExists) {
441
+ console.log(chalk.green(`✅ Appended to: ${path.relative(process.cwd(), targetFilePath)}`));
442
+ }
443
+ else {
444
+ console.log(chalk.green(`✅ Created with content: ${path.relative(process.cwd(), targetFilePath)}`));
445
+ }
410
446
  }
411
- else {
412
- templateContent = await fs.readFile(sourceFilePath, 'utf-8');
447
+ catch (error) {
448
+ console.error(chalk.red(`❌ Failed to append/create ${path.relative(process.cwd(), targetFilePath)}: ${error}`));
449
+ throw error;
413
450
  }
414
- const separator = existingContent && !existingContent.endsWith('\n') ? '\n\n' : '\n';
415
- const newContent = existingContent + separator + templateContent;
416
- // Ensure target directory exists
417
- await fs.ensureDir(path.dirname(targetFilePath));
418
- await fs.outputFile(targetFilePath, newContent);
419
- console.log(chalk.green(`✅ Appended to: ${path.relative(process.cwd(), targetFilePath)}`));
420
451
  }
421
452
  /**
422
- * Handle file prepend (add content to beginning of file)
453
+ * Handle file prepend (add content to beginning of file, create if doesn't exist)
423
454
  */
424
455
  async function handleFilePrepend(sourceFilePath, targetFilePath, cachedContent) {
456
+ // Ensure target directory exists
457
+ await fs.ensureDir(path.dirname(targetFilePath));
458
+ const fileExists = await fs.pathExists(targetFilePath);
425
459
  let existingContent = '';
426
- if (await fs.pathExists(targetFilePath)) {
427
- existingContent = await fs.readFile(targetFilePath, 'utf-8');
428
- }
429
- let templateContent;
430
- if (cachedContent) {
431
- templateContent = cachedContent;
460
+ try {
461
+ if (fileExists) {
462
+ existingContent = await fs.readFile(targetFilePath, 'utf-8');
463
+ }
464
+ let templateContent;
465
+ if (cachedContent) {
466
+ templateContent = cachedContent;
467
+ }
468
+ else {
469
+ // Check if source template exists
470
+ if (await fs.pathExists(sourceFilePath)) {
471
+ templateContent = await fs.readFile(sourceFilePath, 'utf-8');
472
+ }
473
+ else {
474
+ console.log(chalk.yellow(`⚠️ Template file not found, skipping prepend: ${path.relative(process.cwd(), sourceFilePath)}`));
475
+ console.log(chalk.gray(` This might be due to running a globally installed CLI. Consider using 'npx' or installing locally.`));
476
+ return;
477
+ }
478
+ }
479
+ const separator = templateContent.endsWith('\n') ? '' : '\n';
480
+ const newContent = templateContent + separator + existingContent;
481
+ await fs.outputFile(targetFilePath, newContent);
482
+ if (fileExists) {
483
+ console.log(chalk.green(`✅ Prepended to: ${path.relative(process.cwd(), targetFilePath)}`));
484
+ }
485
+ else {
486
+ console.log(chalk.green(`✅ Created with content: ${path.relative(process.cwd(), targetFilePath)}`));
487
+ }
432
488
  }
433
- else {
434
- templateContent = await fs.readFile(sourceFilePath, 'utf-8');
489
+ catch (error) {
490
+ console.error(chalk.red(`❌ Failed to prepend/create ${path.relative(process.cwd(), targetFilePath)}: ${error}`));
491
+ throw error;
435
492
  }
436
- const separator = templateContent.endsWith('\n') ? '' : '\n';
437
- const newContent = templateContent + separator + existingContent;
438
- // Ensure target directory exists
439
- await fs.ensureDir(path.dirname(targetFilePath));
440
- await fs.outputFile(targetFilePath, newContent);
441
- console.log(chalk.green(`✅ Prepended to: ${path.relative(process.cwd(), targetFilePath)}`));
442
493
  }
443
494
  /**
444
- * Copy template file to target location with Next.js content processing
495
+ * Copy template file to target location with framework-agnostic content processing
445
496
  */
446
497
  async function copyTemplateFile(sourceFilePath, targetFilePath) {
447
498
  if (!await fs.pathExists(sourceFilePath)) {
499
+ const relativePath = path.relative(process.cwd(), sourceFilePath);
500
+ console.error(chalk.red(`❌ Template file not found: ${relativePath}`));
501
+ console.error(chalk.yellow(`💡 This might be due to running a globally installed CLI. Consider using 'npx' or installing locally.`));
448
502
  throw new Error(`Template file not found: ${sourceFilePath}`);
449
503
  }
450
- // Ensure target directory exists
451
- await fs.ensureDir(path.dirname(targetFilePath));
452
- // For Next.js projects, we might need to adjust import paths in template files
453
- if (path.extname(sourceFilePath).match(/\.(js|jsx|ts|tsx)$/)) {
454
- const templateContent = await fs.readFile(sourceFilePath, 'utf-8');
455
- // Process content for Next.js src folder structure
456
- let processedContent = templateContent;
457
- // Adjust import paths if needed (this is basic - you might want to make it more sophisticated)
458
- if (targetFilePath.includes('/src/')) {
459
- processedContent = processedContent.replace(/from ['"]@\//g, 'from "@/');
460
- processedContent = processedContent.replace(/from ['"]\.\.\//g, 'from "../');
461
- }
462
- await fs.writeFile(targetFilePath, processedContent);
504
+ try {
505
+ // Ensure target directory exists
506
+ await fs.ensureDir(path.dirname(targetFilePath));
507
+ // For code files, we might need to adjust import paths based on project structure
508
+ if (path.extname(sourceFilePath).match(/\.(js|jsx|ts|tsx)$/)) {
509
+ const templateContent = await fs.readFile(sourceFilePath, 'utf-8');
510
+ // Process content based on project structure (framework-agnostic)
511
+ let processedContent = templateContent;
512
+ // Adjust import paths for src-based project structures
513
+ if (targetFilePath.includes('/src/')) {
514
+ processedContent = processedContent.replace(/from ['"]@\//g, 'from "@/');
515
+ processedContent = processedContent.replace(/from ['"]\.\.\//g, 'from "../');
516
+ }
517
+ await fs.writeFile(targetFilePath, processedContent);
518
+ }
519
+ else {
520
+ // For non-code files, just copy directly
521
+ await fs.copy(sourceFilePath, targetFilePath);
522
+ }
463
523
  }
464
- else {
465
- // For non-code files, just copy directly
466
- await fs.copy(sourceFilePath, targetFilePath);
524
+ catch (error) {
525
+ console.error(chalk.red(`❌ Failed to copy template file: ${error}`));
526
+ throw error;
467
527
  }
468
528
  }
469
529
  /**
@@ -12,39 +12,6 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
12
12
  category: 'web',
13
13
  maturity: 'stable',
14
14
  packageManagers: [
15
- {
16
- name: 'bun',
17
- displayName: 'Bun',
18
- description: 'Fast all-in-one JavaScript runtime & toolkit',
19
- installCommand: 'bun install',
20
- updateCommand: 'bun update',
21
- addCommand: 'bun add',
22
- removeCommand: 'bun remove',
23
- listCommand: 'bun pm ls',
24
- lockFiles: ['bun.lockb'],
25
- configFiles: ['bunfig.toml'],
26
- detectCommand: 'bun --version',
27
- versionCommand: 'bun --version',
28
- priority: 1,
29
- features: [
30
- { name: 'Native bundling', description: 'Built-in bundler and transpiler', supported: true },
31
- { name: 'TypeScript support', description: 'Native TypeScript execution', supported: true },
32
- { name: 'JSX support', description: 'Native JSX transpilation', supported: true },
33
- { name: 'Hot reloading', description: 'Development server with hot reload', supported: true }
34
- ],
35
- performance: {
36
- installSpeed: 'fast',
37
- diskUsage: 'low',
38
- networkEfficiency: 'excellent',
39
- caching: 'global'
40
- },
41
- security: {
42
- checksums: true,
43
- signatures: true,
44
- vulnerabilityScanning: true,
45
- lockFileValidation: true
46
- }
47
- },
48
15
  {
49
16
  name: 'pnpm',
50
17
  displayName: 'pnpm',
@@ -59,7 +26,7 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
59
26
  configFiles: ['pnpm-workspace.yaml', '.pnpmrc'],
60
27
  detectCommand: 'pnpm --version',
61
28
  versionCommand: 'pnpm --version',
62
- priority: 2,
29
+ priority: 1,
63
30
  globalFlag: '-g',
64
31
  features: [
65
32
  { name: 'Workspace support', description: 'Monorepo and workspace management', supported: true },
@@ -80,6 +47,41 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
80
47
  lockFileValidation: true
81
48
  }
82
49
  },
50
+ {
51
+ name: 'npm',
52
+ displayName: 'npm',
53
+ description: 'Node.js package manager',
54
+ installCommand: 'npm install',
55
+ updateCommand: 'npm update',
56
+ addCommand: 'npm install',
57
+ removeCommand: 'npm uninstall',
58
+ listCommand: 'npm list',
59
+ searchCommand: 'npm search',
60
+ lockFiles: ['package-lock.json'],
61
+ configFiles: ['.npmrc'],
62
+ detectCommand: 'npm --version',
63
+ versionCommand: 'npm --version',
64
+ priority: 2,
65
+ globalFlag: '-g',
66
+ features: [
67
+ { name: 'Package scripts', description: 'Custom script execution', supported: true },
68
+ { name: 'Version management', description: 'Semantic versioning support', supported: true },
69
+ { name: 'Workspaces', description: 'Monorepo support', supported: true }
70
+ ],
71
+ performance: {
72
+ installSpeed: 'medium',
73
+ diskUsage: 'high',
74
+ networkEfficiency: 'good',
75
+ caching: 'local'
76
+ },
77
+ security: {
78
+ checksums: true,
79
+ signatures: false,
80
+ auditCommand: 'npm audit',
81
+ vulnerabilityScanning: true,
82
+ lockFileValidation: true
83
+ }
84
+ },
83
85
  {
84
86
  name: 'yarn',
85
87
  displayName: 'Yarn',
@@ -115,36 +117,34 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
115
117
  }
116
118
  },
117
119
  {
118
- name: 'npm',
119
- displayName: 'npm',
120
- description: 'Node.js package manager',
121
- installCommand: 'npm install',
122
- updateCommand: 'npm update',
123
- addCommand: 'npm install',
124
- removeCommand: 'npm uninstall',
125
- listCommand: 'npm list',
126
- searchCommand: 'npm search',
127
- lockFiles: ['package-lock.json'],
128
- configFiles: ['.npmrc'],
129
- detectCommand: 'npm --version',
130
- versionCommand: 'npm --version',
120
+ name: 'bun',
121
+ displayName: 'Bun',
122
+ description: 'Fast all-in-one JavaScript runtime & toolkit',
123
+ installCommand: 'bun install',
124
+ updateCommand: 'bun update',
125
+ addCommand: 'bun add',
126
+ removeCommand: 'bun remove',
127
+ listCommand: 'bun pm ls',
128
+ lockFiles: ['bun.lockb'],
129
+ configFiles: ['bunfig.toml'],
130
+ detectCommand: 'bun --version',
131
+ versionCommand: 'bun --version',
131
132
  priority: 4,
132
- globalFlag: '-g',
133
133
  features: [
134
- { name: 'Package scripts', description: 'Custom script execution', supported: true },
135
- { name: 'Version management', description: 'Semantic versioning support', supported: true },
136
- { name: 'Workspaces', description: 'Monorepo support', supported: true }
134
+ { name: 'Native bundling', description: 'Built-in bundler and transpiler', supported: true },
135
+ { name: 'TypeScript support', description: 'Native TypeScript execution', supported: true },
136
+ { name: 'JSX support', description: 'Native JSX transpilation', supported: true },
137
+ { name: 'Hot reloading', description: 'Development server with hot reload', supported: true }
137
138
  ],
138
139
  performance: {
139
- installSpeed: 'medium',
140
- diskUsage: 'high',
141
- networkEfficiency: 'good',
142
- caching: 'local'
140
+ installSpeed: 'fast',
141
+ diskUsage: 'low',
142
+ networkEfficiency: 'excellent',
143
+ caching: 'global'
143
144
  },
144
145
  security: {
145
146
  checksums: true,
146
- signatures: false,
147
- auditCommand: 'npm audit',
147
+ signatures: true,
148
148
  vulnerabilityScanning: true,
149
149
  lockFileValidation: true
150
150
  }
@@ -304,7 +304,111 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
304
304
  category: 'web',
305
305
  maturity: 'stable',
306
306
  packageManagers: [
307
- // Inherits from JavaScript but with TypeScript-specific tooling
307
+ // Inherits from JavaScript with same priority order: pnpm > npm > yarn > bun
308
+ {
309
+ name: 'pnpm',
310
+ displayName: 'pnpm',
311
+ description: 'Fast, disk space efficient package manager',
312
+ installCommand: 'pnpm install',
313
+ updateCommand: 'pnpm update',
314
+ addCommand: 'pnpm add',
315
+ removeCommand: 'pnpm remove',
316
+ listCommand: 'pnpm list',
317
+ searchCommand: 'pnpm search',
318
+ lockFiles: ['pnpm-lock.yaml'],
319
+ configFiles: ['pnpm-workspace.yaml', '.pnpmrc'],
320
+ detectCommand: 'pnpm --version',
321
+ versionCommand: 'pnpm --version',
322
+ priority: 1,
323
+ globalFlag: '-g',
324
+ features: [
325
+ { name: 'TypeScript support', description: 'Excellent TypeScript integration', supported: true },
326
+ { name: 'Workspace support', description: 'Monorepo and workspace management', supported: true },
327
+ { name: 'Content-addressed storage', description: 'Efficient disk space usage', supported: true }
328
+ ],
329
+ performance: {
330
+ installSpeed: 'fast',
331
+ diskUsage: 'low',
332
+ networkEfficiency: 'excellent',
333
+ caching: 'global'
334
+ },
335
+ security: {
336
+ checksums: true,
337
+ signatures: false,
338
+ auditCommand: 'pnpm audit',
339
+ vulnerabilityScanning: true,
340
+ lockFileValidation: true
341
+ }
342
+ },
343
+ {
344
+ name: 'npm',
345
+ displayName: 'npm',
346
+ description: 'Node.js package manager with TypeScript support',
347
+ installCommand: 'npm install',
348
+ updateCommand: 'npm update',
349
+ addCommand: 'npm install',
350
+ removeCommand: 'npm uninstall',
351
+ listCommand: 'npm list',
352
+ searchCommand: 'npm search',
353
+ lockFiles: ['package-lock.json'],
354
+ configFiles: ['.npmrc'],
355
+ detectCommand: 'npm --version',
356
+ versionCommand: 'npm --version',
357
+ priority: 2,
358
+ globalFlag: '-g',
359
+ features: [
360
+ { name: 'TypeScript support', description: 'Official TypeScript support', supported: true },
361
+ { name: 'Package scripts', description: 'Custom script execution', supported: true },
362
+ { name: 'Version management', description: 'Semantic versioning support', supported: true }
363
+ ],
364
+ performance: {
365
+ installSpeed: 'medium',
366
+ diskUsage: 'high',
367
+ networkEfficiency: 'good',
368
+ caching: 'local'
369
+ },
370
+ security: {
371
+ checksums: true,
372
+ signatures: false,
373
+ auditCommand: 'npm audit',
374
+ vulnerabilityScanning: true,
375
+ lockFileValidation: true
376
+ }
377
+ },
378
+ {
379
+ name: 'yarn',
380
+ displayName: 'Yarn',
381
+ description: 'Reliable, secure, fast package manager with TypeScript support',
382
+ installCommand: 'yarn install',
383
+ updateCommand: 'yarn upgrade',
384
+ addCommand: 'yarn add',
385
+ removeCommand: 'yarn remove',
386
+ listCommand: 'yarn list',
387
+ lockFiles: ['yarn.lock'],
388
+ configFiles: ['.yarnrc.yml', '.yarnrc'],
389
+ detectCommand: 'yarn --version',
390
+ versionCommand: 'yarn --version',
391
+ priority: 3,
392
+ globalFlag: 'global',
393
+ features: [
394
+ { name: 'TypeScript support', description: 'Excellent TypeScript integration', supported: true },
395
+ { name: 'Zero-installs', description: 'Offline installation support', supported: true },
396
+ { name: 'Plug\'n\'Play', description: 'Fast module resolution', supported: true }
397
+ ],
398
+ performance: {
399
+ installSpeed: 'fast',
400
+ diskUsage: 'medium',
401
+ networkEfficiency: 'good',
402
+ caching: 'global'
403
+ },
404
+ security: {
405
+ checksums: true,
406
+ signatures: false,
407
+ auditCommand: 'yarn npm audit',
408
+ vulnerabilityScanning: true,
409
+ lockFileValidation: true
410
+ }
411
+ },
308
412
  {
309
413
  name: 'bun',
310
414
  displayName: 'Bun',
@@ -312,14 +416,17 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
312
416
  installCommand: 'bun install',
313
417
  updateCommand: 'bun update',
314
418
  addCommand: 'bun add',
419
+ removeCommand: 'bun remove',
420
+ listCommand: 'bun pm ls',
315
421
  lockFiles: ['bun.lockb'],
316
422
  configFiles: ['bunfig.toml'],
317
423
  detectCommand: 'bun --version',
318
424
  versionCommand: 'bun --version',
319
- priority: 1,
425
+ priority: 4,
320
426
  features: [
321
427
  { name: 'Native TypeScript', description: 'No transpilation needed', supported: true },
322
- { name: 'Type checking', description: 'Built-in type checking', supported: true }
428
+ { name: 'Type checking', description: 'Built-in type checking', supported: true },
429
+ { name: 'Hot reloading', description: 'Development server with hot reload', supported: true }
323
430
  ],
324
431
  performance: {
325
432
  installSpeed: 'fast',
@@ -880,164 +987,6 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
880
987
  ]
881
988
  }
882
989
  },
883
- php: {
884
- name: 'php',
885
- displayName: 'PHP',
886
- description: 'Server-side scripting language for web development',
887
- icon: '🐘',
888
- category: 'web',
889
- maturity: 'stable',
890
- packageManagers: [
891
- {
892
- name: 'composer',
893
- displayName: 'Composer',
894
- description: 'Dependency Manager for PHP',
895
- installCommand: 'composer install',
896
- updateCommand: 'composer update',
897
- addCommand: 'composer require',
898
- removeCommand: 'composer remove',
899
- listCommand: 'composer show',
900
- lockFiles: ['composer.lock'],
901
- configFiles: ['composer.json'],
902
- detectCommand: 'composer --version',
903
- versionCommand: 'composer --version',
904
- priority: 1,
905
- features: [
906
- { name: 'Autoloading', description: 'PSR-4 autoloading support', supported: true },
907
- { name: 'Version constraints', description: 'Semantic versioning', supported: true }
908
- ],
909
- performance: {
910
- installSpeed: 'medium',
911
- diskUsage: 'medium',
912
- networkEfficiency: 'good',
913
- caching: 'global'
914
- },
915
- security: {
916
- checksums: true,
917
- signatures: false,
918
- vulnerabilityScanning: true,
919
- lockFileValidation: true
920
- }
921
- }
922
- ],
923
- configFiles: [
924
- {
925
- filename: 'composer.json',
926
- description: 'PHP dependency configuration',
927
- required: true,
928
- type: 'dependency',
929
- parser: 'json'
930
- }
931
- ],
932
- buildFiles: ['vendor'],
933
- sourceFileExtensions: ['.php'],
934
- frameworkDetection: [
935
- {
936
- framework: 'laravel',
937
- displayName: 'Laravel',
938
- patterns: ['artisan'],
939
- dependencies: ['laravel/framework'],
940
- popularity: 90,
941
- category: 'backend'
942
- }
943
- ],
944
- toolchain: {
945
- interpreter: { name: 'PHP', command: 'php', optional: false, description: 'PHP interpreter' }
946
- },
947
- ecosystem: {
948
- registry: { name: 'Packagist', url: 'packagist.org' },
949
- community: { github: { repos: 300000, stars: 1000000 }, stackoverflow: { questions: 300000, activity: 'high' } },
950
- learning: [],
951
- trends: { githubStars: 1000000, stackoverflowQuestions: 300000, jobPostings: 120000, trendDirection: 'stable' }
952
- },
953
- compatibility: {
954
- operatingSystems: ['windows', 'macos', 'linux'],
955
- architectures: ['x64', 'arm64'],
956
- containers: true,
957
- cloud: [
958
- { name: 'AWS', supported: true, deployment: ['Lambda', 'EC2'] }
959
- ]
960
- }
961
- },
962
- java: {
963
- name: 'java',
964
- displayName: 'Java',
965
- description: 'Enterprise-grade, platform-independent programming language',
966
- icon: '☕',
967
- category: 'enterprise',
968
- maturity: 'stable',
969
- packageManagers: [
970
- {
971
- name: 'maven',
972
- displayName: 'Maven',
973
- description: 'Build automation and dependency management',
974
- installCommand: 'mvn install',
975
- updateCommand: 'mvn versions:use-latest-versions',
976
- addCommand: 'mvn dependency:get',
977
- listCommand: 'mvn dependency:list',
978
- lockFiles: [],
979
- configFiles: ['pom.xml'],
980
- detectCommand: 'mvn --version',
981
- versionCommand: 'mvn --version',
982
- priority: 1,
983
- features: [
984
- { name: 'Central repository', description: 'Maven Central repository', supported: true },
985
- { name: 'Build lifecycle', description: 'Standardized build process', supported: true }
986
- ],
987
- performance: {
988
- installSpeed: 'medium',
989
- diskUsage: 'high',
990
- networkEfficiency: 'good',
991
- caching: 'local'
992
- },
993
- security: {
994
- checksums: true,
995
- signatures: true,
996
- vulnerabilityScanning: true,
997
- lockFileValidation: false
998
- }
999
- }
1000
- ],
1001
- configFiles: [
1002
- {
1003
- filename: 'pom.xml',
1004
- description: 'Maven project configuration',
1005
- required: true,
1006
- type: 'dependency',
1007
- parser: 'xml'
1008
- }
1009
- ],
1010
- buildFiles: ['target', '.m2'],
1011
- sourceFileExtensions: ['.java'],
1012
- frameworkDetection: [
1013
- {
1014
- framework: 'spring',
1015
- displayName: 'Spring Boot',
1016
- patterns: ['src/main/java/**/*Application.java'],
1017
- dependencies: ['org.springframework.boot:spring-boot-starter'],
1018
- popularity: 95,
1019
- category: 'backend'
1020
- }
1021
- ],
1022
- toolchain: {
1023
- interpreter: { name: 'Java', command: 'java', optional: false, description: 'Java runtime' }
1024
- },
1025
- ecosystem: {
1026
- registry: { name: 'Maven Central', url: 'mvnrepository.com' },
1027
- community: { github: { repos: 800000, stars: 3000000 }, stackoverflow: { questions: 1500000, activity: 'high' } },
1028
- learning: [],
1029
- trends: { githubStars: 3000000, stackoverflowQuestions: 1500000, jobPostings: 200000, trendDirection: 'stable' }
1030
- },
1031
- compatibility: {
1032
- operatingSystems: ['windows', 'macos', 'linux'],
1033
- architectures: ['x64', 'arm64'],
1034
- containers: true,
1035
- cloud: [
1036
- { name: 'AWS', supported: true },
1037
- { name: 'Google Cloud', supported: true }
1038
- ]
1039
- }
1040
- },
1041
990
  ruby: {
1042
991
  name: 'ruby',
1043
992
  displayName: 'Ruby',
@@ -1115,86 +1064,6 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
1115
1064
  { name: 'Heroku', supported: true }
1116
1065
  ]
1117
1066
  }
1118
- },
1119
- dotnet: {
1120
- name: 'dotnet',
1121
- displayName: '.NET',
1122
- description: 'Cross-platform framework for modern applications',
1123
- icon: '🟣',
1124
- category: 'enterprise',
1125
- maturity: 'stable',
1126
- packageManagers: [
1127
- {
1128
- name: 'dotnet',
1129
- displayName: 'NuGet',
1130
- description: '.NET package manager',
1131
- installCommand: 'dotnet restore',
1132
- updateCommand: 'dotnet outdated --upgrade',
1133
- addCommand: 'dotnet add package',
1134
- removeCommand: 'dotnet remove package',
1135
- listCommand: 'dotnet list package',
1136
- lockFiles: ['packages.lock.json'],
1137
- configFiles: ['*.csproj', '*.fsproj', '*.vbproj'],
1138
- detectCommand: 'dotnet --version',
1139
- versionCommand: 'dotnet --version',
1140
- priority: 1,
1141
- features: [
1142
- { name: 'Package references', description: 'Modern package management', supported: true },
1143
- { name: 'Central package management', description: 'Centralized version control', supported: true }
1144
- ],
1145
- performance: {
1146
- installSpeed: 'fast',
1147
- diskUsage: 'medium',
1148
- networkEfficiency: 'excellent',
1149
- caching: 'global'
1150
- },
1151
- security: {
1152
- checksums: true,
1153
- signatures: true,
1154
- vulnerabilityScanning: true,
1155
- lockFileValidation: true
1156
- }
1157
- }
1158
- ],
1159
- configFiles: [
1160
- {
1161
- filename: '*.csproj',
1162
- description: 'C# project file',
1163
- required: true,
1164
- type: 'dependency',
1165
- parser: 'xml'
1166
- }
1167
- ],
1168
- buildFiles: ['bin', 'obj'],
1169
- sourceFileExtensions: ['.cs', '.fs', '.vb'],
1170
- frameworkDetection: [
1171
- {
1172
- framework: 'aspnet',
1173
- displayName: 'ASP.NET Core',
1174
- patterns: ['Program.cs', 'Startup.cs'],
1175
- dependencies: ['Microsoft.AspNetCore'],
1176
- popularity: 85,
1177
- category: 'backend'
1178
- }
1179
- ],
1180
- toolchain: {
1181
- interpreter: { name: '.NET', command: 'dotnet', optional: false, description: '.NET CLI' }
1182
- },
1183
- ecosystem: {
1184
- registry: { name: 'NuGet', url: 'nuget.org' },
1185
- community: { github: { repos: 600000, stars: 2500000 }, stackoverflow: { questions: 800000, activity: 'high' } },
1186
- learning: [],
1187
- trends: { githubStars: 2500000, stackoverflowQuestions: 800000, jobPostings: 150000, trendDirection: 'rising' }
1188
- },
1189
- compatibility: {
1190
- operatingSystems: ['windows', 'macos', 'linux'],
1191
- architectures: ['x64', 'arm64'],
1192
- containers: true,
1193
- cloud: [
1194
- { name: 'Azure', supported: true },
1195
- { name: 'AWS', supported: true }
1196
- ]
1197
- }
1198
1067
  }
1199
1068
  // Additional languages would be added here with full configuration...
1200
1069
  // For brevity, I'm showing the structure with key languages implemented
@@ -43,14 +43,13 @@ export function generateTemplateName(framework, options) {
43
43
  parts.push('no-src');
44
44
  }
45
45
  }
46
- // Handle UI library
46
+ // Handle UI library - only add if actually selected (not "none")
47
+ // When UI is "none", templates simply omit the UI part from their names
47
48
  if (config.ui && config.ui.length > 0) {
48
49
  if (options.ui && options.ui !== 'none') {
49
50
  parts.push(options.ui);
50
51
  }
51
- else {
52
- parts.push('no-' + config.ui[0]);
53
- }
52
+ // For "none" selection, don't add any UI part to the template name
54
53
  }
55
54
  // Handle tailwind option
56
55
  if (config.options?.includes('tailwind')) {
data/dist/utils/utils.js CHANGED
@@ -21,7 +21,7 @@ export function getPackageVersion() {
21
21
  const packageJsonPath = getPackageJsonPath();
22
22
  const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8');
23
23
  const packageJson = JSON.parse(packageJsonContent);
24
- return packageJson.version || '3.2.0';
24
+ return packageJson.version || '3.4.0';
25
25
  }
26
26
  catch (error) {
27
27
  console.warn('Warning: Could not read version from package.json, using fallback version');
@@ -4,7 +4,7 @@ require 'open3'
4
4
  require 'json'
5
5
 
6
6
  module PackageInstallerCli
7
- VERSION = "1.1.0"
7
+ VERSION = "1.2.0"
8
8
 
9
9
  class << self
10
10
  def run(args = ARGV)
File without changes
File without changes
File without changes
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: package-installer-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sharique
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-23 00:00:00.000000000 Z
11
+ date: 2025-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -2985,8 +2985,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
2985
2985
  - !ruby/object:Gem::Version
2986
2986
  version: '0'
2987
2987
  requirements: []
2988
- rubygems_version: 3.1.2
2989
- signing_key:
2988
+ rubygems_version: 3.4.20
2989
+ signing_key:
2990
2990
  specification_version: 4
2991
2991
  summary: A cross-platform, interactive CLI to scaffold modern web app templates
2992
2992
  test_files: []