package-installer-cli 1.3.1 → 1.3.3
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 +4 -4
- data/dist/commands/check.js +157 -133
- data/dist/utils/languageConfig.js +0 -29
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 87cf10ca48c5f33ea24bb36427427bdf709be32b8b654e295b2768bd3077d940
|
|
4
|
+
data.tar.gz: f93337632294f53991e374fd94d42c4c66409292b523370e4de687a2de0f48e3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3be6855632ef33fd77e69488336a2d276b1c446cea2f422d0b8d02de30cd7dc687141067b864fc10babccd6c86294e43481d2d55bd4bf52db17a82b69ec15415
|
|
7
|
+
data.tar.gz: 73a4b812134e0a256d9bb9c9735da36531c549c672b967f09950645cc72438138b698b90ca5b83a687664a56be1be73301c6e4a989b9064675c39379370856ff
|
data/dist/commands/check.js
CHANGED
|
@@ -2,7 +2,6 @@ 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';
|
|
@@ -32,6 +31,14 @@ const PROJECT_TYPES = getSupportedLanguages().map(lang => {
|
|
|
32
31
|
registryUrl = 'https://pypi.org';
|
|
33
32
|
packageInfoUrl = (packageName) => `https://pypi.org/pypi/${packageName}/json`;
|
|
34
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;
|
|
35
42
|
default:
|
|
36
43
|
// For unsupported languages, we'll try npm registry as fallback
|
|
37
44
|
registryUrl = 'https://registry.npmjs.org';
|
|
@@ -394,11 +401,11 @@ export function showCheckHelp() {
|
|
|
394
401
|
{
|
|
395
402
|
title: 'Supported Package Managers',
|
|
396
403
|
items: [
|
|
397
|
-
'npm, pnpm, yarn (
|
|
404
|
+
'npm, pnpm, yarn (JavaScript/TypeScript)',
|
|
398
405
|
'pip, pipenv, poetry (Python)',
|
|
399
406
|
'cargo (Rust)',
|
|
400
407
|
'go modules (Go)',
|
|
401
|
-
'
|
|
408
|
+
'gem, bundler (Ruby)'
|
|
402
409
|
]
|
|
403
410
|
}
|
|
404
411
|
],
|
|
@@ -461,7 +468,36 @@ async function checkSinglePackage(packageName, verbose = false) {
|
|
|
461
468
|
async function checkProjectPackages(verbose = false) {
|
|
462
469
|
const spinner = ora('Analyzing project dependencies...').start();
|
|
463
470
|
try {
|
|
464
|
-
|
|
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 {
|
|
465
501
|
let dependencies = {};
|
|
466
502
|
if (!projectType) {
|
|
467
503
|
spinner.warn('No supported project files found in current directory');
|
|
@@ -472,10 +508,8 @@ async function checkProjectPackages(verbose = false) {
|
|
|
472
508
|
console.log(chalk.gray('\n Or specify a package name: pi check <package-name>'));
|
|
473
509
|
return;
|
|
474
510
|
}
|
|
475
|
-
// Get fresh dependencies
|
|
476
|
-
|
|
477
|
-
dependencies = await getDependenciesForProject(projectType);
|
|
478
|
-
}
|
|
511
|
+
// Get fresh dependencies
|
|
512
|
+
dependencies = await getDependenciesForProject(projectType);
|
|
479
513
|
if (Object.keys(dependencies).length === 0) {
|
|
480
514
|
spinner.warn(`No dependencies found in ${projectType.name} project`);
|
|
481
515
|
return;
|
|
@@ -486,77 +520,73 @@ async function checkProjectPackages(verbose = false) {
|
|
|
486
520
|
try {
|
|
487
521
|
const info = await getEnhancedPackageInfo(name, version, projectType);
|
|
488
522
|
packageInfos.push(info);
|
|
523
|
+
spinner.text = `✔ Retrieved info for ${name}`;
|
|
489
524
|
}
|
|
490
525
|
catch (error) {
|
|
491
526
|
console.warn(`⚠️ Could not check ${name}`);
|
|
492
527
|
}
|
|
493
528
|
}
|
|
494
|
-
spinner.succeed(
|
|
495
|
-
// Cache the package check results
|
|
496
|
-
|
|
497
|
-
|
|
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);
|
|
498
538
|
}
|
|
499
539
|
catch (error) {
|
|
500
|
-
spinner.fail(
|
|
540
|
+
spinner.fail(`Failed to analyze ${projectType.name} dependencies`);
|
|
501
541
|
throw error;
|
|
502
542
|
}
|
|
503
543
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const
|
|
508
|
-
|
|
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
|
|
509
552
|
for (const priorityFile of priorityFiles) {
|
|
510
553
|
const filePath = path.join(process.cwd(), priorityFile);
|
|
511
|
-
console.log(chalk.gray(` Checking
|
|
554
|
+
console.log(chalk.gray(` Checking: ${filePath}`));
|
|
512
555
|
if (await fs.pathExists(filePath)) {
|
|
513
556
|
console.log(chalk.green(` ✅ Found: ${priorityFile}`));
|
|
557
|
+
foundFiles.push(priorityFile);
|
|
514
558
|
// Find the project type that matches this file
|
|
515
559
|
const matchingType = PROJECT_TYPES.find(type => type.files.includes(priorityFile));
|
|
516
|
-
if (matchingType) {
|
|
560
|
+
if (matchingType && !foundTypes.find(t => t.name === matchingType.name)) {
|
|
517
561
|
console.log(chalk.green(` 📦 Detected: ${matchingType.name}`));
|
|
518
|
-
|
|
562
|
+
foundTypes.push(matchingType);
|
|
519
563
|
}
|
|
520
564
|
}
|
|
521
565
|
}
|
|
522
|
-
//
|
|
566
|
+
// Check for additional files in each detected project type
|
|
523
567
|
for (const projectType of PROJECT_TYPES) {
|
|
524
|
-
|
|
568
|
+
if (foundTypes.find(t => t.name === projectType.name))
|
|
569
|
+
continue; // Already found
|
|
525
570
|
for (const file of projectType.files) {
|
|
526
571
|
if (priorityFiles.includes(file))
|
|
527
572
|
continue; // Already checked
|
|
528
|
-
// Check in current directory first
|
|
529
573
|
const filePath = path.join(process.cwd(), file);
|
|
530
574
|
if (await fs.pathExists(filePath)) {
|
|
531
|
-
console.log(chalk.green(` ✅ Found: ${file}`));
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
// Third pass: check subdirectories
|
|
537
|
-
try {
|
|
538
|
-
const currentDirContents = await fs.readdir(process.cwd());
|
|
539
|
-
for (const item of currentDirContents) {
|
|
540
|
-
const itemPath = path.join(process.cwd(), item);
|
|
541
|
-
const stats = await fs.stat(itemPath);
|
|
542
|
-
if (stats.isDirectory()) {
|
|
543
|
-
for (const priorityFile of priorityFiles) {
|
|
544
|
-
const configPath = path.join(itemPath, priorityFile);
|
|
545
|
-
if (await fs.pathExists(configPath)) {
|
|
546
|
-
console.log(chalk.green(` ✅ Found in subdirectory: ${item}/${priorityFile}`));
|
|
547
|
-
const matchingType = PROJECT_TYPES.find(type => type.files.includes(priorityFile));
|
|
548
|
-
if (matchingType)
|
|
549
|
-
return matchingType;
|
|
550
|
-
}
|
|
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);
|
|
551
580
|
}
|
|
552
581
|
}
|
|
553
582
|
}
|
|
554
583
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
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;
|
|
560
590
|
}
|
|
561
591
|
async function getDependenciesForProject(projectType) {
|
|
562
592
|
console.log(chalk.gray(`📋 Looking for dependencies in ${projectType.name} project...`));
|
|
@@ -691,8 +721,8 @@ async function getPackageInfo(packageName, currentVersion, projectType) {
|
|
|
691
721
|
try {
|
|
692
722
|
// Clean up version string (remove ^ ~ and similar prefixes)
|
|
693
723
|
const cleanCurrentVersion = currentVersion?.replace(/[\^~>=<]/, '') || 'unknown';
|
|
694
|
-
// Enhanced NPM registry support
|
|
695
|
-
if (type.name === '
|
|
724
|
+
// Enhanced NPM registry support
|
|
725
|
+
if (type.name === 'JavaScript' || type.name === 'TypeScript') {
|
|
696
726
|
const response = await fetch(`https://registry.npmjs.org/${packageName}`);
|
|
697
727
|
if (!response.ok) {
|
|
698
728
|
throw new Error(`Package ${packageName} not found in NPM registry`);
|
|
@@ -801,101 +831,95 @@ async function getPackageInfo(packageName, currentVersion, projectType) {
|
|
|
801
831
|
throw new Error(`Failed to fetch info for ${packageName}: ${error.message}`);
|
|
802
832
|
}
|
|
803
833
|
}
|
|
804
|
-
function displayPackageInfo(packages, projectType, verbose = false) {
|
|
834
|
+
function displayPackageInfo(packages, projectType, verbose = false, isMultiProject = false) {
|
|
805
835
|
if (packages.length === 0) {
|
|
806
836
|
console.log(chalk.yellow('📦 No packages to display'));
|
|
807
837
|
return;
|
|
808
838
|
}
|
|
809
|
-
console.log('\n' + chalk.hex('#00d2d3')('📊 Package Analysis Results'));
|
|
810
|
-
console.log(chalk.gray('─'.repeat(60)));
|
|
811
839
|
const outdatedPackages = packages.filter(pkg => pkg.needsUpdate);
|
|
812
840
|
const deprecatedPackages = packages.filter(pkg => pkg.isDeprecated);
|
|
813
841
|
const upToDatePackages = packages.filter(pkg => !pkg.needsUpdate && !pkg.isDeprecated);
|
|
814
|
-
//
|
|
815
|
-
console.log(
|
|
816
|
-
console.log(
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
}
|
|
823
|
-
// 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}`);
|
|
824
851
|
if (projectType) {
|
|
825
|
-
console.log(
|
|
826
|
-
}
|
|
827
|
-
// Determine how many packages to show
|
|
828
|
-
const packagesToShow = verbose ? packages : packages.slice(0,
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
})
|
|
856
|
-
}
|
|
857
|
-
// Show remaining packages
|
|
858
|
-
if (!verbose && packages.length >
|
|
859
|
-
const remaining = packages.length -
|
|
860
|
-
const remainingOutdated = packages.
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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}`);
|
|
867
896
|
}
|
|
897
|
+
// Show sample of remaining package names
|
|
868
898
|
if (remainingOutdated > 0) {
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
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 ? '...' : ''}`);
|
|
873
902
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
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`);
|
|
879
920
|
}
|
|
880
|
-
console.log(`\n ${chalk.cyan('💡 Tip:')} Use ${chalk.bold('--verbose')} to see detailed info for all ${packages.length} packages`);
|
|
881
|
-
}
|
|
882
|
-
// Enhanced recommendations section
|
|
883
|
-
console.log('\n' + chalk.hex('#00d2d3')('💡 Recommendations:'));
|
|
884
|
-
console.log(chalk.gray('─'.repeat(30)));
|
|
885
|
-
if (deprecatedPackages.length > 0) {
|
|
886
|
-
console.log(`${chalk.hex('#ff4757')('🚨 URGENT:')} Replace ${deprecatedPackages.length} deprecated package(s) immediately`);
|
|
887
|
-
deprecatedPackages.slice(0, 3).forEach(pkg => {
|
|
888
|
-
console.log(` • ${chalk.red(pkg.name)} ${chalk.gray(pkg.deprecatedMessage ? '- ' + pkg.deprecatedMessage.slice(0, 50) + '...' : '')}`);
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
|
-
if (outdatedPackages.length > 0 && projectType) {
|
|
892
|
-
console.log(`${chalk.hex('#f39c12')('⚠️ UPDATE:')} ${outdatedPackages.length} package(s) need updating`);
|
|
893
|
-
console.log(` Run: ${chalk.cyan(projectType.getUpdateCommand())}`);
|
|
894
|
-
}
|
|
895
|
-
if (packages.length > 50) {
|
|
896
|
-
console.log(`${chalk.hex('#95afc0')('📦 INFO:')} Large dependency count (${packages.length}) - consider reviewing for optimization`);
|
|
897
921
|
}
|
|
898
|
-
console.log(chalk.gray(`\
|
|
922
|
+
console.log(chalk.gray(`\nLast checked: ${new Date().toLocaleString()}`));
|
|
899
923
|
}
|
|
900
924
|
/**
|
|
901
925
|
* Cache package check results for performance
|
|
@@ -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,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.3.
|
|
4
|
+
version: 1.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- sharique
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-10-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|