package-installer-cli 1.3.0 → 1.3.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de2baf8d0677e75c1471a523c2c8b581bde9c5187f0cecb4a5a4c79a6d03022a
4
- data.tar.gz: c3e5ee669f095c1537ba2bf505367da009999c907b6814fb907e5b569eebcc2a
3
+ metadata.gz: cea62d79600dea627bd56027e3957cf9dcb9aea7714a42a1becad34f9206c73c
4
+ data.tar.gz: 5c81b035b59925817350c8ea8d69b43264ba0d6bc1ad88454768b4a102c3df6b
5
5
  SHA512:
6
- metadata.gz: 3f593de7edcf4ec3b60397cf4de415d7e2703debb4a49c7f85d1911d2c2c64b9c644e637d259187dd965d43b23906985795cb5ed5fbc5eece7bf6af45b33c4fb
7
- data.tar.gz: c9f3538f2430caa503d7bbe21f52bd2592b689e80c1f08763b4afd2268a1cffd9ba4d1bd4dcf6a855aebacc0b2f59a1ca750ec296ad96aa57344b6cfdf40e043
6
+ metadata.gz: c5648ee659a9fba908c339ea65bf798d4540d726427eaac63ac0fcf288ae8ce7bb1fba253883bcf24cbe369ded23614b64b282cceba5dc91acee89d8a305dfd7
7
+ data.tar.gz: 969feb40b0130d1a0a213084a5f8f8edb95a09b2fb530a69b4aee57329c4dc715a0d007a103dca22b02edd48d9ea3a29c30fa84afc0b5640f4f347119d78fa31
data/dist/commands/add.js CHANGED
@@ -5,10 +5,11 @@ import boxen from 'boxen';
5
5
  import path from 'path';
6
6
  import fs from 'fs-extra';
7
7
  import { createStandardHelp } from '../utils/helpFormatter.js';
8
- import { addFeature, detectProjectStack, SUPPORTED_FEATURES } from '../utils/featureInstaller.js';
8
+ import { addFeature, detectProjectStack, SUPPORTED_FEATURES, ensureFeaturesLoaded } from '../utils/featureInstaller.js';
9
9
  import { historyManager } from '../utils/historyManager.js';
10
10
  import { cacheProjectData } from '../utils/cacheManager.js';
11
11
  import { getFeaturesJsonPath, getFeaturesPath } from '../utils/pathResolver.js';
12
+ import { displayCommandBanner } from '../utils/banner.js';
12
13
  /**
13
14
  * Helper function to capitalize strings
14
15
  */
@@ -18,7 +19,13 @@ function capitalize(str) {
18
19
  /**
19
20
  * Get features.json configuration with new jsonPath structure
20
21
  */
22
+ // Cache for features config to avoid repeated file reads
23
+ let featuresConfigCache = null;
21
24
  async function getFeaturesConfig() {
25
+ // Return cached config if available
26
+ if (featuresConfigCache) {
27
+ return featuresConfigCache;
28
+ }
22
29
  try {
23
30
  // Use the centralized path resolver
24
31
  const featuresPath = getFeaturesJsonPath();
@@ -42,12 +49,12 @@ async function getFeaturesConfig() {
42
49
  };
43
50
  }
44
51
  else {
45
- console.warn(chalk.yellow(`⚠️ Individual feature file not found: ${individualFeaturePath}`));
52
+ // Silently skip missing files to avoid console spam
46
53
  processedConfig[featureName] = featureConfig;
47
54
  }
48
55
  }
49
56
  catch (error) {
50
- console.warn(chalk.yellow(`⚠️ Could not load individual feature file for ${featureName}`));
57
+ // Silently handle errors to avoid console spam
51
58
  processedConfig[featureName] = featureConfig;
52
59
  }
53
60
  }
@@ -56,13 +63,16 @@ async function getFeaturesConfig() {
56
63
  processedConfig[featureName] = featureConfig;
57
64
  }
58
65
  }
59
- return { features: processedConfig };
66
+ // Cache the processed config
67
+ featuresConfigCache = { features: processedConfig };
68
+ return featuresConfigCache;
60
69
  }
61
- console.warn(chalk.yellow(`⚠️ features.json not found at: ${featuresPath}`));
62
- return { features: {} };
70
+ // Return empty config without warning to avoid console spam
71
+ featuresConfigCache = { features: {} };
72
+ return featuresConfigCache;
63
73
  }
64
74
  catch (error) {
65
- console.warn(chalk.yellow('⚠️ Error reading features.json, using fallback'));
75
+ // Return fallback config without warning
66
76
  return { features: {} };
67
77
  }
68
78
  }
@@ -88,6 +98,7 @@ async function getSubFeatures(category) {
88
98
  * List available features from features.json with descriptions
89
99
  */
90
100
  async function listAvailableFeatures() {
101
+ await ensureFeaturesLoaded();
91
102
  const featuresConfig = await getFeaturesConfig();
92
103
  if (!featuresConfig.features || Object.keys(featuresConfig.features).length === 0) {
93
104
  console.log(chalk.yellow('⚠️ No features found in configuration'));
@@ -269,6 +280,7 @@ function showEnhancedSetupInstructions(feature, provider) {
269
280
  * Show help for add command
270
281
  */
271
282
  export async function showAddHelp() {
283
+ await ensureFeaturesLoaded();
272
284
  const featuresConfig = await getFeaturesConfig();
273
285
  const availableFeatures = Object.keys(featuresConfig.features || {});
274
286
  const helpConfig = {
@@ -281,8 +293,7 @@ export async function showAddHelp() {
281
293
  ],
282
294
  options: [
283
295
  { flag: '-l, --list', description: 'List all available features' },
284
- { flag: '-v, --verbose', description: 'Show detailed output' },
285
- { flag: '-h, --help', description: 'Show this help message' }
296
+ { flag: '-v, --verbose', description: 'Show detailed output' }
286
297
  ],
287
298
  examples: [
288
299
  { command: 'add', description: 'Interactive feature selection' },
@@ -334,21 +345,19 @@ export async function showAddHelp() {
334
345
  */
335
346
  export async function addCommand(feature, provider, options = {}) {
336
347
  try {
337
- // Handle help flag
338
- if (options.help || feature === '--help' || feature === '-h') {
339
- await showAddHelp();
340
- return;
341
- }
348
+ // Ensure features are loaded first
349
+ await ensureFeaturesLoaded();
342
350
  // Handle list flag
343
351
  if (options.list || feature === '--list' || feature === '-l') {
344
352
  await listAvailableFeatures();
345
353
  return;
346
354
  }
355
+ // Display command banner
356
+ displayCommandBanner('Add', 'Add new features to your project with integrated templates and configurations');
347
357
  // Initialize history manager
348
358
  await historyManager.init();
349
359
  // Show disclaimer
350
360
  showFeatureDisclaimer();
351
- console.log(chalk.hex('#9c88ff')('\n🔮 Adding features to your project...'));
352
361
  // Use provided project path or current directory
353
362
  const projectPath = options.projectPath || process.cwd();
354
363
  let projectInfo;
@@ -8,7 +8,8 @@ import os from 'os';
8
8
  import gradientString from 'gradient-string';
9
9
  import boxen from 'boxen';
10
10
  import { createStandardHelp } from '../utils/helpFormatter.js';
11
- import { createBanner, displaySystemInfo, displaySuccessMessage } from '../utils/dashboard.js';
11
+ import { displayCommandBanner } from '../utils/banner.js';
12
+ import { displaySystemInfo, displaySuccessMessage } from '../utils/dashboard.js';
12
13
  import { HistoryManager } from '../utils/historyManager.js';
13
14
  /**
14
15
  * Display help for analyze command using standardized format
@@ -25,8 +26,7 @@ export function showAnalyzeHelp() {
25
26
  options: [
26
27
  { flag: '--export', description: 'Export analytics data to JSON file' },
27
28
  { flag: '--reset', description: 'Reset analytics history' },
28
- { flag: '--detailed', description: 'Show detailed analytics breakdown' },
29
- { flag: '-h, --help', description: 'Show this help message' }
29
+ { flag: '--detailed', description: 'Show detailed analytics breakdown' }
30
30
  ],
31
31
  examples: [
32
32
  { command: 'analyze', description: 'Show complete analytics dashboard' },
@@ -65,7 +65,7 @@ export async function analyzeCommand(options = {}) {
65
65
  showAnalyzeHelp();
66
66
  return;
67
67
  }
68
- createBanner('Package Installer CLI Analytics');
68
+ displayCommandBanner('Analytics', 'Comprehensive project analytics and usage insights');
69
69
  const historyManager = new HistoryManager();
70
70
  try {
71
71
  // Load analytics data from history.json
@@ -26,8 +26,7 @@ export function showCacheHelp() {
26
26
  { flag: '--clear [type]', description: 'Clear cache (optional type)' },
27
27
  { flag: '--info', description: 'Show cache information' },
28
28
  { flag: '--optimize', description: 'Optimize cache' },
29
- { flag: '--size', description: 'Show cache size only' },
30
- { flag: '-h, --help', description: 'Show this help message' }
29
+ { flag: '--size', description: 'Show cache size only' }
31
30
  ],
32
31
  examples: [
33
32
  { command: 'cache stats', description: 'Show cache statistics' },
@@ -2,12 +2,12 @@ import { exec } from 'child_process';
2
2
  import { promisify } from 'util';
3
3
  import chalk from 'chalk';
4
4
  import ora from 'ora';
5
- import boxen from 'boxen';
6
5
  import fs from 'fs-extra';
7
6
  import path from 'path';
8
7
  import semver from 'semver';
9
8
  import https from 'https';
10
9
  import { createStandardHelp } from '../utils/helpFormatter.js';
10
+ import { displayCommandBanner } from '../utils/banner.js';
11
11
  import { getSupportedLanguages, getLanguageConfig } from '../utils/languageConfig.js';
12
12
  const execAsync = promisify(exec);
13
13
  // Generate PROJECT_TYPES from shared language configuration with enhanced registry support
@@ -31,6 +31,14 @@ const PROJECT_TYPES = getSupportedLanguages().map(lang => {
31
31
  registryUrl = 'https://pypi.org';
32
32
  packageInfoUrl = (packageName) => `https://pypi.org/pypi/${packageName}/json`;
33
33
  break;
34
+ case 'ruby':
35
+ registryUrl = 'https://rubygems.org';
36
+ packageInfoUrl = (packageName) => `https://rubygems.org/api/v1/gems/${packageName}.json`;
37
+ break;
38
+ case 'go':
39
+ registryUrl = 'https://proxy.golang.org';
40
+ packageInfoUrl = (packageName) => `https://proxy.golang.org/${packageName}/@v/list`;
41
+ break;
34
42
  default:
35
43
  // For unsupported languages, we'll try npm registry as fallback
36
44
  registryUrl = 'https://registry.npmjs.org';
@@ -380,7 +388,6 @@ export function showCheckHelp() {
380
388
  'check [options]'
381
389
  ],
382
390
  options: [
383
- { flag: '-h, --help', description: 'Display help for this command' },
384
391
  { flag: '-v, --verbose', description: 'Show detailed information for all packages' }
385
392
  ],
386
393
  examples: [
@@ -394,11 +401,11 @@ export function showCheckHelp() {
394
401
  {
395
402
  title: 'Supported Package Managers',
396
403
  items: [
397
- 'npm, pnpm, yarn (Node.js)',
404
+ 'npm, pnpm, yarn (JavaScript/TypeScript)',
398
405
  'pip, pipenv, poetry (Python)',
399
406
  'cargo (Rust)',
400
407
  'go modules (Go)',
401
- 'composer (PHP)'
408
+ 'gem, bundler (Ruby)'
402
409
  ]
403
410
  }
404
411
  ],
@@ -427,6 +434,8 @@ export async function checkCommand(packageName, options) {
427
434
  packageName = undefined;
428
435
  }
429
436
  try {
437
+ // Display command banner
438
+ displayCommandBanner('Check', 'Check package versions and updates for your project dependencies');
430
439
  console.log('\n' + chalk.hex('#f39c12')('🔍 Starting package check...'));
431
440
  if (packageName && packageName !== '--verbose' && packageName !== '-v') {
432
441
  await checkSinglePackage(packageName, isVerbose);
@@ -459,7 +468,36 @@ async function checkSinglePackage(packageName, verbose = false) {
459
468
  async function checkProjectPackages(verbose = false) {
460
469
  const spinner = ora('Analyzing project dependencies...').start();
461
470
  try {
462
- let projectType = await detectProjectType();
471
+ // Detect ALL project types instead of just one
472
+ const allProjectTypes = await detectAllProjectTypes();
473
+ if (allProjectTypes.length === 0) {
474
+ spinner.fail(chalk.hex('#ff4757')('❌ No supported project configuration files found'));
475
+ console.log(chalk.hex('#95afc0')('💡 Supported files: package.json, tsconfig.json, Cargo.toml, requirements.txt, pyproject.toml, go.mod, Gemfile'));
476
+ return;
477
+ }
478
+ spinner.succeed(chalk.hex('#10ac84')(`✅ Detected ${allProjectTypes.length} project type(s): ${allProjectTypes.map(pt => pt.name).join(', ')}`));
479
+ // Process each project type separately
480
+ for (let i = 0; i < allProjectTypes.length; i++) {
481
+ const projectType = allProjectTypes[i];
482
+ const isMultiProject = allProjectTypes.length > 1;
483
+ if (isMultiProject) {
484
+ console.log('\n' + chalk.hex('#667eea')('═'.repeat(80)));
485
+ console.log(chalk.hex('#667eea')(`📋 Analyzing ${projectType.name} Dependencies (${i + 1}/${allProjectTypes.length})`));
486
+ console.log(chalk.hex('#667eea')('═'.repeat(80)));
487
+ }
488
+ await analyzeSingleProjectType(projectType, verbose, isMultiProject);
489
+ }
490
+ return; // Exit early since we've processed all project types
491
+ }
492
+ catch (error) {
493
+ spinner.fail(chalk.hex('#ff4757')(`❌ Failed to analyze projects: ${error.message}`));
494
+ throw error;
495
+ }
496
+ }
497
+ // New function to analyze a single project type
498
+ async function analyzeSingleProjectType(projectType, verbose, isMultiProject = false) {
499
+ const spinner = ora(`Analyzing ${projectType.name} dependencies...`).start();
500
+ try {
463
501
  let dependencies = {};
464
502
  if (!projectType) {
465
503
  spinner.warn('No supported project files found in current directory');
@@ -470,10 +508,8 @@ async function checkProjectPackages(verbose = false) {
470
508
  console.log(chalk.gray('\n Or specify a package name: pi check <package-name>'));
471
509
  return;
472
510
  }
473
- // Get fresh dependencies if not cached or cache is incomplete
474
- if (Object.keys(dependencies).length === 0) {
475
- dependencies = await getDependenciesForProject(projectType);
476
- }
511
+ // Get fresh dependencies
512
+ dependencies = await getDependenciesForProject(projectType);
477
513
  if (Object.keys(dependencies).length === 0) {
478
514
  spinner.warn(`No dependencies found in ${projectType.name} project`);
479
515
  return;
@@ -484,77 +520,73 @@ async function checkProjectPackages(verbose = false) {
484
520
  try {
485
521
  const info = await getEnhancedPackageInfo(name, version, projectType);
486
522
  packageInfos.push(info);
523
+ spinner.text = `✔ Retrieved info for ${name}`;
487
524
  }
488
525
  catch (error) {
489
526
  console.warn(`⚠️ Could not check ${name}`);
490
527
  }
491
528
  }
492
- spinner.succeed(`Checked ${packageInfos.length} ${projectType.name} packages`);
493
- // Cache the package check results
494
- await cachePackageCheckResults(packageInfos, projectType);
495
- displayPackageInfo(packageInfos, projectType, verbose);
529
+ spinner.succeed(`✔ Checked ${packageInfos.length} ${projectType.name} packages`);
530
+ // Cache the package check results (optional)
531
+ try {
532
+ await cachePackageCheckResults?.(packageInfos, projectType);
533
+ }
534
+ catch (error) {
535
+ // Caching is optional, continue without it
536
+ }
537
+ displayPackageInfo(packageInfos, projectType, verbose, isMultiProject);
496
538
  }
497
539
  catch (error) {
498
- spinner.fail('Failed to analyze project dependencies');
540
+ spinner.fail(`Failed to analyze ${projectType.name} dependencies`);
499
541
  throw error;
500
542
  }
501
543
  }
502
- async function detectProjectType() {
503
- console.log(chalk.gray('🔍 Detecting project type...'));
504
- // Priority order for detection - check most common files first
505
- const priorityFiles = ['package.json', 'Cargo.toml', 'requirements.txt', 'composer.json', 'go.mod'];
506
- // First pass: check priority files in current directory
544
+ // New function to detect ALL project types in a directory
545
+ async function detectAllProjectTypes() {
546
+ console.log(chalk.gray('🔍 Detecting all project types...'));
547
+ const foundTypes = [];
548
+ const foundFiles = [];
549
+ // Priority order for detection - check most common files first (supported languages only)
550
+ const priorityFiles = ['package.json', 'tsconfig.json', 'Cargo.toml', 'requirements.txt', 'pyproject.toml', 'go.mod', 'Gemfile'];
551
+ // Check all priority files in current directory
507
552
  for (const priorityFile of priorityFiles) {
508
553
  const filePath = path.join(process.cwd(), priorityFile);
509
- console.log(chalk.gray(` Checking priority file: ${filePath}`));
554
+ console.log(chalk.gray(` Checking: ${filePath}`));
510
555
  if (await fs.pathExists(filePath)) {
511
556
  console.log(chalk.green(` ✅ Found: ${priorityFile}`));
557
+ foundFiles.push(priorityFile);
512
558
  // Find the project type that matches this file
513
559
  const matchingType = PROJECT_TYPES.find(type => type.files.includes(priorityFile));
514
- if (matchingType) {
560
+ if (matchingType && !foundTypes.find(t => t.name === matchingType.name)) {
515
561
  console.log(chalk.green(` 📦 Detected: ${matchingType.name}`));
516
- return matchingType;
562
+ foundTypes.push(matchingType);
517
563
  }
518
564
  }
519
565
  }
520
- // Second pass: check all other files
566
+ // Check for additional files in each detected project type
521
567
  for (const projectType of PROJECT_TYPES) {
522
- console.log(chalk.gray(` Checking ${projectType.name}: ${projectType.files.join(', ')}`));
568
+ if (foundTypes.find(t => t.name === projectType.name))
569
+ continue; // Already found
523
570
  for (const file of projectType.files) {
524
571
  if (priorityFiles.includes(file))
525
572
  continue; // Already checked
526
- // Check in current directory first
527
573
  const filePath = path.join(process.cwd(), file);
528
574
  if (await fs.pathExists(filePath)) {
529
- console.log(chalk.green(` ✅ Found: ${file}`));
530
- return projectType;
531
- }
532
- }
533
- }
534
- // Third pass: check subdirectories
535
- try {
536
- const currentDirContents = await fs.readdir(process.cwd());
537
- for (const item of currentDirContents) {
538
- const itemPath = path.join(process.cwd(), item);
539
- const stats = await fs.stat(itemPath);
540
- if (stats.isDirectory()) {
541
- for (const priorityFile of priorityFiles) {
542
- const configPath = path.join(itemPath, priorityFile);
543
- if (await fs.pathExists(configPath)) {
544
- console.log(chalk.green(` ✅ Found in subdirectory: ${item}/${priorityFile}`));
545
- const matchingType = PROJECT_TYPES.find(type => type.files.includes(priorityFile));
546
- if (matchingType)
547
- return matchingType;
548
- }
575
+ console.log(chalk.green(` ✅ Found additional: ${file}`));
576
+ foundFiles.push(file);
577
+ if (!foundTypes.find(t => t.name === projectType.name)) {
578
+ console.log(chalk.green(` 📦 Detected: ${projectType.name}`));
579
+ foundTypes.push(projectType);
549
580
  }
550
581
  }
551
582
  }
552
583
  }
553
- catch (error) {
554
- console.log(chalk.yellow(' Warning: Could not read directory contents'));
555
- }
556
- console.log(chalk.yellow(' No project type detected'));
557
- return null;
584
+ return foundTypes;
585
+ }
586
+ async function detectProjectType() {
587
+ // This function now uses detectAllProjectTypes and returns the first one for backward compatibility
588
+ const allTypes = await detectAllProjectTypes();
589
+ return allTypes.length > 0 ? allTypes[0] : null;
558
590
  }
559
591
  async function getDependenciesForProject(projectType) {
560
592
  console.log(chalk.gray(`📋 Looking for dependencies in ${projectType.name} project...`));
@@ -689,8 +721,8 @@ async function getPackageInfo(packageName, currentVersion, projectType) {
689
721
  try {
690
722
  // Clean up version string (remove ^ ~ and similar prefixes)
691
723
  const cleanCurrentVersion = currentVersion?.replace(/[\^~>=<]/, '') || 'unknown';
692
- // Enhanced NPM registry support
693
- if (type.name === 'Node.js') {
724
+ // Enhanced NPM registry support
725
+ if (type.name === 'JavaScript' || type.name === 'TypeScript') {
694
726
  const response = await fetch(`https://registry.npmjs.org/${packageName}`);
695
727
  if (!response.ok) {
696
728
  throw new Error(`Package ${packageName} not found in NPM registry`);
@@ -799,101 +831,95 @@ async function getPackageInfo(packageName, currentVersion, projectType) {
799
831
  throw new Error(`Failed to fetch info for ${packageName}: ${error.message}`);
800
832
  }
801
833
  }
802
- function displayPackageInfo(packages, projectType, verbose = false) {
834
+ function displayPackageInfo(packages, projectType, verbose = false, isMultiProject = false) {
803
835
  if (packages.length === 0) {
804
836
  console.log(chalk.yellow('📦 No packages to display'));
805
837
  return;
806
838
  }
807
- console.log('\n' + chalk.hex('#00d2d3')('📊 Package Analysis Results'));
808
- console.log(chalk.gray('─'.repeat(60)));
809
839
  const outdatedPackages = packages.filter(pkg => pkg.needsUpdate);
810
840
  const deprecatedPackages = packages.filter(pkg => pkg.isDeprecated);
811
841
  const upToDatePackages = packages.filter(pkg => !pkg.needsUpdate && !pkg.isDeprecated);
812
- // Enhanced Summary with statistics
813
- console.log(`\n${chalk.hex('#10ac84')(' Total packages checked:')} ${chalk.bold(packages.length.toString())}`);
814
- console.log(`${chalk.hex('#10ac84')('✅ Up to date:')} ${chalk.bold(upToDatePackages.length.toString())}`);
815
- if (outdatedPackages.length > 0) {
816
- console.log(`${chalk.hex('#f39c12')('⚠️ Packages needing updates:')} ${chalk.bold(outdatedPackages.length.toString())}`);
817
- }
818
- if (deprecatedPackages.length > 0) {
819
- console.log(`${chalk.hex('#ff4757')('🚨 Deprecated packages:')} ${chalk.bold(deprecatedPackages.length.toString())}`);
820
- }
821
- // Show severity breakdown
842
+ // Compact summary header
843
+ console.log('\n' + chalk.hex('#00d2d3')('📊 Package Analysis Results'));
844
+ console.log(chalk.gray(''.repeat(80)));
845
+ const summary = [
846
+ `${chalk.hex('#10ac84')('')} ${upToDatePackages.length} up-to-date`,
847
+ outdatedPackages.length > 0 ? `${chalk.hex('#f39c12')('⚠️')} ${outdatedPackages.length} need updates` : null,
848
+ deprecatedPackages.length > 0 ? `${chalk.hex('#ff4757')('🚨')} ${deprecatedPackages.length} deprecated` : null
849
+ ].filter(Boolean).join('');
850
+ console.log(`${chalk.bold(`Total: ${packages.length}`)} • ${summary}`);
822
851
  if (projectType) {
823
- console.log(`\n${chalk.hex('#00d2d3')('📋 Project Type:')} ${chalk.bold(projectType.name)} (${chalk.cyan(projectType.packageManager)})`);
824
- }
825
- // Determine how many packages to show based on verbose flag
826
- const packagesToShow = verbose ? packages : packages.slice(0, 8);
827
- if (verbose && packages.length > 8) {
828
- console.log(`\n${chalk.hex('#f39c12')('📋 Showing all')} ${chalk.bold(packages.length.toString())} ${chalk.hex('#f39c12')('packages (verbose mode)')}`);
829
- }
830
- else if (!verbose && packages.length > 8) {
831
- console.log(`\n${chalk.hex('#f39c12')('📋 Showing first')} ${chalk.bold('8')} ${chalk.hex('#f39c12')('packages (use --verbose to see all)')}`);
832
- }
833
- packagesToShow.forEach((pkg, index) => {
834
- const statusIcon = pkg.isDeprecated ? '🚨' : pkg.needsUpdate ? '⚠️' : '✅';
835
- const statusColor = pkg.isDeprecated ? '#ff4757' : pkg.needsUpdate ? '#f39c12' : '#10ac84';
836
- const statusText = pkg.isDeprecated ? 'DEPRECATED' : pkg.needsUpdate ? 'UPDATE AVAILABLE' : 'UP TO DATE';
837
- const versionComparison = pkg.currentVersion !== 'unknown' && pkg.latestVersion !== 'unknown'
838
- ? ` ${chalk.gray('')} ${chalk.hex('#10ac84')(pkg.latestVersion)}`
839
- : '';
840
- console.log('\n' + boxen(`${statusIcon} ${chalk.bold(pkg.name)} ${chalk.hex(statusColor)(`[${statusText}]`)}\n` +
841
- `${chalk.gray('Current:')} ${chalk.yellow(pkg.currentVersion)}${versionComparison}\n` +
842
- `${chalk.gray('Type:')} ${chalk.blue(pkg.projectType)} ${chalk.gray('via')} ${chalk.cyan(pkg.packageManager)}\n` +
843
- (pkg.description ? `${chalk.gray('Description:')} ${pkg.description.slice(0, 70)}${pkg.description.length > 70 ? '...' : ''}\n` : '') +
844
- (pkg.homepage ? `${chalk.gray('Homepage:')} ${chalk.blue(pkg.homepage)}\n` : '') +
845
- (pkg.isDeprecated ? `${chalk.hex('#ff4757')('⚠️ DEPRECATED:')} ${pkg.deprecatedMessage || 'This package is no longer maintained'}\n` : '') +
846
- (pkg.alternatives && pkg.alternatives.length > 0 ? `${chalk.gray('Alternatives:')} ${pkg.alternatives.join(', ')}\n` : ''), {
847
- padding: 1,
848
- margin: 0,
849
- borderStyle: 'round',
850
- borderColor: statusColor,
851
- title: `Package ${index + 1}/${packagesToShow.length}`,
852
- titleAlignment: 'left'
853
- }));
854
- });
855
- // Show remaining packages info when not in verbose mode
856
- if (!verbose && packages.length > 8) {
857
- const remaining = packages.length - 8;
858
- const remainingOutdated = packages.slice(8).filter(pkg => pkg.needsUpdate).length;
859
- const remainingDeprecated = packages.slice(8).filter(pkg => pkg.isDeprecated).length;
860
- const remainingUpToDate = packages.slice(8).filter(pkg => !pkg.needsUpdate && !pkg.isDeprecated).length;
861
- console.log('\n' + chalk.hex('#f39c12')(`📦 Remaining ${remaining} packages:`));
862
- console.log(chalk.gray(''.repeat(30)));
863
- if (remainingUpToDate > 0) {
864
- console.log(` ${chalk.hex('#10ac84')('✅')} ${remainingUpToDate} up to date`);
852
+ console.log(`${chalk.hex('#00d2d3')('📋')} ${projectType.name} (${chalk.cyan(projectType.packageManager)})`);
853
+ }
854
+ // Determine how many packages to show
855
+ const packagesToShow = verbose ? packages : packages.slice(0, 12);
856
+ // Group packages by status for better organization
857
+ const groupedPackages = [
858
+ ...deprecatedPackages.slice(0, verbose ? deprecatedPackages.length : 3),
859
+ ...outdatedPackages.slice(0, verbose ? outdatedPackages.length : 8),
860
+ ...upToDatePackages.slice(0, verbose ? upToDatePackages.length : 6)
861
+ ].slice(0, verbose ? packages.length : 12);
862
+ if (groupedPackages.length > 0) {
863
+ console.log('\n');
864
+ // Compact table format
865
+ groupedPackages.forEach((pkg, index) => {
866
+ const statusIcon = pkg.isDeprecated ? '🚨' : pkg.needsUpdate ? '⚠️' : '✅';
867
+ const statusColor = pkg.isDeprecated ? '#ff4757' : pkg.needsUpdate ? '#f39c12' : '#10ac84';
868
+ // Format version comparison compactly
869
+ const versionText = pkg.needsUpdate && pkg.latestVersion !== 'unknown'
870
+ ? `${chalk.dim(pkg.currentVersion)} ${chalk.hex(statusColor)(pkg.latestVersion)}`
871
+ : chalk.dim(pkg.currentVersion);
872
+ // Truncate name and description for compact view
873
+ const name = pkg.name.length > 25 ? pkg.name.slice(0, 22) + '...' : pkg.name;
874
+ const desc = pkg.description
875
+ ? (pkg.description.length > 50 ? pkg.description.slice(0, 47) + '...' : pkg.description)
876
+ : chalk.dim('No description');
877
+ console.log(`${statusIcon} ${chalk.bold(name.padEnd(25))} ${versionText.padEnd(20)} ${chalk.gray(desc)}`);
878
+ // Show deprecation warning inline
879
+ if (pkg.isDeprecated && pkg.deprecatedMessage) {
880
+ console.log(` ${chalk.hex('#ff4757')('⚠️')} ${chalk.dim(pkg.deprecatedMessage.slice(0, 80))}`);
881
+ }
882
+ });
883
+ }
884
+ // Show remaining packages summary when not in verbose mode
885
+ if (!verbose && packages.length > 12) {
886
+ const remaining = packages.length - groupedPackages.length;
887
+ const remainingOutdated = packages.filter(pkg => pkg.needsUpdate && !groupedPackages.includes(pkg)).length;
888
+ const remainingUpToDate = packages.filter(pkg => !pkg.needsUpdate && !pkg.isDeprecated && !groupedPackages.includes(pkg)).length;
889
+ console.log('\n' + chalk.gray('─'.repeat(80)));
890
+ const hiddenSummary = [
891
+ remainingUpToDate > 0 ? `${chalk.hex('#10ac84')('✅')} ${remainingUpToDate} more up-to-date` : null,
892
+ remainingOutdated > 0 ? `${chalk.hex('#f39c12')('⚠️')} ${remainingOutdated} more need updates` : null
893
+ ].filter(Boolean).join('');
894
+ if (hiddenSummary) {
895
+ console.log(`${chalk.dim(`+${remaining} hidden:`)} ${hiddenSummary}`);
865
896
  }
897
+ // Show sample of remaining package names
866
898
  if (remainingOutdated > 0) {
867
- console.log(` ${chalk.hex('#f39c12')('⚠️')} ${remainingOutdated} need updates`);
868
- // Show names of remaining outdated packages
869
- const outdatedNames = packages.slice(8).filter(pkg => pkg.needsUpdate).slice(0, 5).map(pkg => pkg.name);
870
- console.log(` ${chalk.gray('Packages:')} ${outdatedNames.join(', ')}${outdatedNames.length < remainingOutdated ? '...' : ''}`);
899
+ const sampleNames = packages.filter(pkg => pkg.needsUpdate && !groupedPackages.includes(pkg))
900
+ .slice(0, 4).map(pkg => pkg.name).join(', ');
901
+ console.log(`${chalk.dim('Outdated:')} ${sampleNames}${remainingOutdated > 4 ? '...' : ''}`);
871
902
  }
872
- if (remainingDeprecated > 0) {
873
- console.log(` ${chalk.hex('#ff4757')('🚨')} ${remainingDeprecated} deprecated`);
874
- // Show names of remaining deprecated packages
875
- const deprecatedNames = packages.slice(8).filter(pkg => pkg.isDeprecated).slice(0, 3).map(pkg => pkg.name);
876
- console.log(` ${chalk.gray('Packages:')} ${deprecatedNames.join(', ')}${deprecatedNames.length < remainingDeprecated ? '...' : ''}`);
903
+ console.log(`\n${chalk.cyan('💡')} Use ${chalk.bold('--verbose')} to see all ${packages.length} packages`);
904
+ }
905
+ // Compact recommendations section
906
+ if (outdatedPackages.length > 0 || deprecatedPackages.length > 0) {
907
+ console.log('\n' + chalk.hex('#667eea')('💡 Quick Actions:'));
908
+ console.log(chalk.gray('─'.repeat(40)));
909
+ if (deprecatedPackages.length > 0) {
910
+ console.log(`${chalk.hex('#ff4757')('🚨')} ${deprecatedPackages.length} deprecated - replace immediately`);
911
+ deprecatedPackages.slice(0, 3).forEach(pkg => {
912
+ console.log(` • ${chalk.red(pkg.name)} ${chalk.gray(pkg.deprecatedMessage ? '- ' + pkg.deprecatedMessage.slice(0, 50) + '...' : '')}`);
913
+ });
914
+ }
915
+ if (outdatedPackages.length > 0 && projectType) {
916
+ console.log(`${chalk.hex('#f39c12')('⚠️')} ${outdatedPackages.length} need updates - Run: ${chalk.cyan(projectType.getUpdateCommand())}`);
917
+ }
918
+ if (packages.length > 50) {
919
+ console.log(`${chalk.hex('#95afc0')('📦')} Large dependency count (${packages.length}) - consider optimization`);
877
920
  }
878
- console.log(`\n ${chalk.cyan('💡 Tip:')} Use ${chalk.bold('--verbose')} to see detailed info for all ${packages.length} packages`);
879
- }
880
- // Enhanced recommendations section
881
- console.log('\n' + chalk.hex('#00d2d3')('💡 Recommendations:'));
882
- console.log(chalk.gray('─'.repeat(30)));
883
- if (deprecatedPackages.length > 0) {
884
- console.log(`${chalk.hex('#ff4757')('🚨 URGENT:')} Replace ${deprecatedPackages.length} deprecated package(s) immediately`);
885
- deprecatedPackages.slice(0, 3).forEach(pkg => {
886
- console.log(` • ${chalk.red(pkg.name)} ${chalk.gray(pkg.deprecatedMessage ? '- ' + pkg.deprecatedMessage.slice(0, 50) + '...' : '')}`);
887
- });
888
- }
889
- if (outdatedPackages.length > 0 && projectType) {
890
- console.log(`${chalk.hex('#f39c12')('⚠️ UPDATE:')} ${outdatedPackages.length} package(s) need updating`);
891
- console.log(` Run: ${chalk.cyan(projectType.getUpdateCommand())}`);
892
- }
893
- if (packages.length > 50) {
894
- console.log(`${chalk.hex('#95afc0')('📦 INFO:')} Large dependency count (${packages.length}) - consider reviewing for optimization`);
895
921
  }
896
- console.log(chalk.gray(`\n Last checked: ${new Date().toLocaleString()}`));
922
+ console.log(chalk.gray(`\nLast checked: ${new Date().toLocaleString()}`));
897
923
  }
898
924
  /**
899
925
  * Cache package check results for performance
@@ -6,6 +6,7 @@ import ora from 'ora';
6
6
  import fs from 'fs-extra';
7
7
  import path from 'path';
8
8
  import { createStandardHelp } from '../utils/helpFormatter.js';
9
+ import { displayCommandBanner } from '../utils/banner.js';
9
10
  /**
10
11
  * Display help for clean command
11
12
  */
@@ -25,8 +26,7 @@ export function showCleanHelp() {
25
26
  { flag: '--logs', description: 'Clean log files and debug outputs' },
26
27
  { flag: '--all', description: 'Clean everything (safe operation)' },
27
28
  { flag: '--deep', description: 'Deep clean (includes lock files)' },
28
- { flag: '--dry-run', description: 'Preview what would be cleaned' },
29
- { flag: '-h, --help', description: 'Show this help message' }
29
+ { flag: '--dry-run', description: 'Preview what would be cleaned' }
30
30
  ],
31
31
  examples: [
32
32
  { command: 'clean --build', description: 'Clean build directories only' },
@@ -65,7 +65,8 @@ export async function cleanCommand(options = {}) {
65
65
  showCleanHelp();
66
66
  return;
67
67
  }
68
- console.clear();
68
+ // Display command banner
69
+ displayCommandBanner('Clean', 'Clean development artifacts, caches, and temporary files from your project');
69
70
  console.log(chalk.hex('#ffa502')('🧹 Project Cleaner\n'));
70
71
  const projectPath = process.cwd();
71
72
  const isDryRun = options['dryRun'] || options['dry-run'];
@@ -16,7 +16,6 @@ export function showCloneHelp() {
16
16
  'clone [options]'
17
17
  ],
18
18
  options: [
19
- { flag: '-h, --help', description: 'Display help for this command' },
20
19
  { flag: '--offline', description: 'Use cached templates if available' },
21
20
  { flag: '--no-deps', description: 'Skip dependency installation' },
22
21
  { flag: '--no-git', description: 'Skip git initialization' },
@@ -4,6 +4,7 @@
4
4
  import chalk from 'chalk';
5
5
  import path from 'path';
6
6
  import { createStandardHelp } from '../utils/helpFormatter.js';
7
+ import { displayCommandBanner } from '../utils/banner.js';
7
8
  import { promptProjectName, promptFrameworkSelection, promptLanguageSelection, promptTemplateSelection, promptFrameworkOptions, promptTemplateConfirmation, promptFeatureSelection, hasFrameworkOptions, hasUIOptions, hasBundlerOptions, shouldShowTemplates } from '../utils/prompts.js';
8
9
  import { resolveTemplatePath, generateTemplateName, templateExists, getFrameworkConfig } from '../utils/templateResolver.js';
9
10
  import { createProjectFromTemplate, installDependenciesForCreate } from '../utils/templateCreator.js';
@@ -22,7 +23,6 @@ export function showCreateHelp() {
22
23
  'create [options]'
23
24
  ],
24
25
  options: [
25
- { flag: '-h, --help', description: 'Display help for this command' },
26
26
  { flag: '--show-cache', description: 'Show cached preferences' },
27
27
  { flag: '--clear-cache', description: 'Clear cached preferences' }
28
28
  ],
@@ -79,6 +79,8 @@ export async function createProject(providedName, options) {
79
79
  return;
80
80
  }
81
81
  try {
82
+ // Display command banner
83
+ displayCommandBanner('Create', 'Create stunning web applications with integrated templates and features');
82
84
  console.log('\n' + chalk.hex('#10ac84')('🚀 Welcome to Package Installer CLI!'));
83
85
  console.log(chalk.hex('#95afc0')('Let\'s create something amazing together...'));
84
86
  // Step 1: Get project name (prompt if not provided)
@@ -14,9 +14,7 @@ export function showDeployHelp() {
14
14
  emoji: '🚀',
15
15
  description: 'Deploy your projects to various cloud platforms seamlessly.\nThis feature is currently under development!',
16
16
  usage: ['pi deploy'],
17
- options: [
18
- { flag: '-h, --help', description: 'Display help for this command' }
19
- ],
17
+ options: [],
20
18
  examples: [
21
19
  { command: 'pi deploy', description: 'Deploy current project' },
22
20
  { command: 'pi deploy --help', description: 'Show this help message' }
@@ -192,8 +192,7 @@ export function showDoctorHelp() {
192
192
  { flag: '--node', description: 'Check Node.js and npm setup only' },
193
193
  { flag: '--deps', description: 'Check project dependencies only' },
194
194
  { flag: '--tools', description: 'Check development tools only' },
195
- { flag: '--verbose', description: 'Show detailed diagnostic information' },
196
- { flag: '-h, --help', description: 'Show this help message' }
195
+ { flag: '--verbose', description: 'Show detailed diagnostic information' }
197
196
  ],
198
197
  examples: [
199
198
  { command: 'pi doctor', description: 'Complete health check' },
data/dist/commands/env.js CHANGED
@@ -106,7 +106,7 @@ function checkEnvironmentVariables() {
106
106
  async function generateEnvTemplate(projectPath) {
107
107
  try {
108
108
  const projectInfo = await detectProjectStack(projectPath);
109
- const envPath = path.join(projectPath, '.env.example');
109
+ const envPath = path.join(projectPath, '.env');
110
110
  let envContent = `# Environment Configuration
111
111
  # Generated by Package Installer CLI
112
112
 
@@ -222,8 +222,7 @@ export function showEnvironmentHelp() {
222
222
  { flag: '--generate', description: 'Generate .env template for project' },
223
223
  { flag: '--validate', description: 'Validate existing .env file' },
224
224
  { flag: '--export', description: 'Export environment info to file' },
225
- { flag: '--system', description: 'Show system information only' },
226
- { flag: '-h, --help', description: 'Show this help message' }
225
+ { flag: '--system', description: 'Show system information only' }
227
226
  ],
228
227
  examples: [
229
228
  { command: 'env', description: 'Interactive environment analysis' },
@@ -731,7 +731,6 @@ export function showUpdateHelp() {
731
731
  'u [options] # alias'
732
732
  ],
733
733
  options: [
734
- { flag: '-h, --help', description: 'Show this help message' },
735
734
  { flag: '--latest', description: 'Update to latest versions (breaking changes possible)' }
736
735
  ],
737
736
  examples: [
@@ -19,9 +19,7 @@ export function showUpgradeHelp() {
19
19
  emoji: '🚀',
20
20
  description: 'Update Package Installer CLI to the latest version with intelligent upgrade management.\nIncludes breaking change detection and version compatibility checks!',
21
21
  usage: ['pi upgrade-cli'],
22
- options: [
23
- { flag: '-h, --help', description: 'Display help for this command' }
24
- ],
22
+ options: [],
25
23
  examples: [
26
24
  { command: 'pi upgrade-cli', description: 'Smart upgrade with breaking change detection' },
27
25
  { command: 'pi upgrade-cli --help', description: 'Show this help message' }
data/dist/index.js CHANGED
@@ -16,8 +16,10 @@ import { updateCommand, showUpdateHelp } from './commands/update.js';
16
16
  import { analyzeCommand, showAnalyzeHelp } from './commands/analyze.js';
17
17
  import { deployCommand, showDeployHelp } from './commands/deploy.js';
18
18
  import { cleanCommand, showCleanHelp } from './commands/clean.js';
19
+ import { cacheCommand, showCacheHelp } from './commands/cache.js';
19
20
  import { environmentCommand, showEnvironmentHelp } from './commands/env.js';
20
21
  import { doctorCommand, showDoctorHelp } from './commands/doctor.js';
22
+ // Import utilities
21
23
  import { initializeCache } from './utils/cacheManager.js';
22
24
  import { displayBanner, displayCommandBanner } from './utils/banner.js';
23
25
  import { getPackageJsonPath } from './utils/pathResolver.js';
@@ -155,11 +157,16 @@ program
155
157
  .argument('[provider]', chalk.hex('#95afc0')('Provider for the feature (optional)'))
156
158
  .option('-l, --list', chalk.hex('#95afc0')('List all available features'))
157
159
  .option('-v, --verbose', chalk.hex('#95afc0')('Show detailed output'))
160
+ .option('-h, --help', chalk.hex('#95afc0')('Display help for this command'))
158
161
  .on('--help', () => {
159
162
  showAddHelp();
160
163
  })
161
164
  .action(async (feature, provider, options) => {
162
165
  try {
166
+ if (options.help) {
167
+ showAddHelp();
168
+ return;
169
+ }
163
170
  await addCommand(feature, provider, options);
164
171
  }
165
172
  catch (error) {
@@ -169,6 +176,7 @@ program
169
176
  // UPGRADE-CLI COMMAND - Update CLI to latest version
170
177
  program
171
178
  .command('upgrade-cli')
179
+ .alias('upgrade')
172
180
  .description(chalk.hex('#ff6b6b')('🚀 ') + chalk.hex('#fd79a8')('Update Package Installer CLI to the latest version'))
173
181
  .on('--help', () => {
174
182
  showUpgradeHelp();
@@ -195,10 +203,6 @@ program
195
203
  })
196
204
  .action(async (options) => {
197
205
  try {
198
- if (options.help) {
199
- showAnalyzeHelp();
200
- return;
201
- }
202
206
  await analyzeCommand(options);
203
207
  }
204
208
  catch (error) {
@@ -310,12 +314,10 @@ program
310
314
  .option('--size', 'Show cache size information')
311
315
  .option('-h, --help', 'Show help for cache command')
312
316
  .on('--help', async () => {
313
- const { showCacheHelp } = await import('./commands/cache.js');
314
317
  showCacheHelp();
315
318
  })
316
319
  .action(async (subcommand, type, options) => {
317
320
  try {
318
- const { cacheCommand } = await import('./commands/cache.js');
319
321
  await cacheCommand(subcommand, type, options);
320
322
  }
321
323
  catch (error) {
data/dist/utils/banner.js CHANGED
@@ -10,8 +10,8 @@ import { getPackageVersion } from './utils.js';
10
10
  * Generate the main CLI banner with gradient colors
11
11
  */
12
12
  export function generateBanner() {
13
- const packageGradient = gradient(['#00c6ff', '#4facfe', '#6c5ce7']);
14
- const installerGradient = gradient(['#fd79a8', '#e84393', '#fd79a8']);
13
+ const packageGradient = gradient(['#0072ff', '#00c6ff', '#4facfe']);
14
+ const installerGradient = gradient(['#00c6ff', '#0072ff', '#667eea']);
15
15
  return boxen(packageGradient(' ██████╗ █████╗ ██████╗██╗ ██╗ █████╗ ██████╗ ███████╗') + '\n' +
16
16
  packageGradient(' ██╔══██╗██╔══██╗██╔════╝██║ ██╔╝██╔══██╗██╔════╝ ██╔════╝') + '\n' +
17
17
  packageGradient(' ██████╔╝███████║██║ █████╔╝ ███████║██║ ███╗█████╗ ') + '\n' +
@@ -29,7 +29,6 @@ async function loadFeatures() {
29
29
  const featuresConfig = featuresData.features || featuresData;
30
30
  // Get available features using the centralized function
31
31
  const availableFeatures = await getAvailableFeatures();
32
- console.log(chalk.gray(`📦 Loading ${availableFeatures.length} available features...`));
33
32
  // Process each feature and load its individual JSON file
34
33
  for (const [featureName, config] of Object.entries(featuresConfig)) {
35
34
  const featureConfig = config;
@@ -89,10 +88,17 @@ async function loadFeatures() {
89
88
  console.warn(chalk.yellow('⚠️ Could not load features.json, using fallback configuration'));
90
89
  }
91
90
  }
92
- // Initialize features on module load
93
- await loadFeatures();
91
+ // Lazy loading flag
92
+ let featuresLoaded = false;
93
+ // Lazy load features when needed
94
+ async function ensureFeaturesLoaded() {
95
+ if (!featuresLoaded) {
96
+ await loadFeatures();
97
+ featuresLoaded = true;
98
+ }
99
+ }
94
100
  // Export for use in other modules
95
- export { SUPPORTED_FEATURES };
101
+ export { SUPPORTED_FEATURES, ensureFeaturesLoaded };
96
102
  // Re-export path utilities for backward compatibility
97
103
  export { getCliRootPath } from './pathResolver.js';
98
104
  /**
@@ -348,7 +354,7 @@ export async function addFeature(featureName, provider, projectPath = process.cw
348
354
  const spinner = ora(chalk.hex('#9c88ff')(`Adding ${featureName} feature...`)).start();
349
355
  try {
350
356
  // Ensure features are loaded
351
- await loadFeatures();
357
+ await ensureFeaturesLoaded();
352
358
  // Validate project path exists
353
359
  if (!await fs.pathExists(projectPath)) {
354
360
  throw new Error(`Project path does not exist: ${projectPath}`);
@@ -25,13 +25,20 @@ export function createStandardHelp(config) {
25
25
  });
26
26
  helpContent += '\n';
27
27
  // Options
28
+ helpContent += chalk.cyan('Options:') + '\n';
29
+ // Check if help flag already exists
30
+ const hasHelpFlag = config.options && config.options.some(option => option.flag.includes('-h') || option.flag.includes('--help'));
31
+ // Add custom options first
28
32
  if (config.options && config.options.length > 0) {
29
- helpContent += chalk.cyan('Options:') + '\n';
30
33
  config.options.forEach(option => {
31
34
  helpContent += chalk.gray(` ${option.flag.padEnd(20)} ${option.description}`) + '\n';
32
35
  });
33
- helpContent += '\n';
34
36
  }
37
+ // Add the global help flag only if it doesn't already exist
38
+ if (!hasHelpFlag) {
39
+ helpContent += chalk.gray(` -h, --help`.padEnd(20) + ' Show this help message') + '\n';
40
+ }
41
+ helpContent += '\n';
35
42
  // Examples
36
43
  if (config.examples && config.examples.length > 0) {
37
44
  helpContent += chalk.cyan('Examples:') + '\n';
@@ -872,35 +872,6 @@ export const ENHANCED_LANGUAGE_CONFIGS = {
872
872
  ]
873
873
  }
874
874
  },
875
- // Continue with other languages - abbreviated for space
876
- nodejs: {
877
- name: 'nodejs',
878
- displayName: 'Node.js',
879
- description: 'JavaScript runtime built on Chrome\'s V8 engine',
880
- icon: '💚',
881
- category: 'web',
882
- maturity: 'stable',
883
- packageManagers: [],
884
- configFiles: [],
885
- buildFiles: [],
886
- sourceFileExtensions: ['.js', '.mjs'],
887
- frameworkDetection: [],
888
- toolchain: {
889
- interpreter: { name: 'Node.js', command: 'node', optional: false, description: 'JavaScript runtime' }
890
- },
891
- ecosystem: {
892
- registry: { name: 'npm', url: 'https://npmjs.com' },
893
- community: { github: { repos: 0, stars: 0 }, stackoverflow: { questions: 0, activity: 'high' } },
894
- learning: [],
895
- trends: { githubStars: 0, stackoverflowQuestions: 0, jobPostings: 0, trendDirection: 'stable' }
896
- },
897
- compatibility: {
898
- operatingSystems: ['windows', 'macos', 'linux'],
899
- architectures: ['x64', 'arm64'],
900
- containers: true,
901
- cloud: []
902
- }
903
- },
904
875
  go: {
905
876
  name: 'go',
906
877
  displayName: 'Go',
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: package-installer-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - sharique