package-installer-cli 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/dist/commands/add.js +127 -84
- data/dist/commands/analyze.js +45 -37
- data/dist/commands/cache.js +141 -6
- data/dist/commands/check.js +121 -72
- data/dist/commands/clean.js +232 -93
- data/dist/commands/clone.js +65 -44
- data/dist/commands/create.js +76 -53
- data/dist/commands/deploy.js +28 -22
- data/dist/commands/doctor.js +26 -28
- data/dist/commands/env.js +44 -32
- data/dist/commands/update.js +598 -113
- data/dist/commands/upgrade-cli.js +30 -24
- data/dist/index.js +61 -16
- data/dist/utils/banner.js +3 -3
- data/dist/utils/cacheManager.js +57 -124
- data/dist/utils/dependencyInstaller.js +0 -2
- data/dist/utils/featureInstaller.js +404 -122
- data/dist/utils/helpFormatter.js +117 -0
- data/dist/utils/pathResolver.js +34 -72
- data/dist/utils/utils.js +20 -5
- metadata +3 -2
data/dist/commands/check.js
CHANGED
|
@@ -3,11 +3,12 @@ import { promisify } from 'util';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import boxen from 'boxen';
|
|
6
|
-
import gradient from 'gradient-string';
|
|
7
6
|
import fs from 'fs-extra';
|
|
8
7
|
import path from 'path';
|
|
9
8
|
import semver from 'semver';
|
|
10
9
|
import https from 'https';
|
|
10
|
+
import { createStandardHelp } from '../utils/helpFormatter.js';
|
|
11
|
+
import { displayCommandBanner } from '../utils/banner.js';
|
|
11
12
|
import { getSupportedLanguages, getLanguageConfig } from '../utils/languageConfig.js';
|
|
12
13
|
const execAsync = promisify(exec);
|
|
13
14
|
// Generate PROJECT_TYPES from shared language configuration with enhanced registry support
|
|
@@ -18,7 +19,6 @@ const PROJECT_TYPES = getSupportedLanguages().map(lang => {
|
|
|
18
19
|
let registryUrl;
|
|
19
20
|
let packageInfoUrl;
|
|
20
21
|
switch (lang) {
|
|
21
|
-
case 'nodejs':
|
|
22
22
|
case 'javascript':
|
|
23
23
|
case 'typescript':
|
|
24
24
|
registryUrl = 'https://registry.npmjs.org';
|
|
@@ -48,7 +48,8 @@ const PROJECT_TYPES = getSupportedLanguages().map(lang => {
|
|
|
48
48
|
const deps = {};
|
|
49
49
|
// Language-specific dependency parsing
|
|
50
50
|
switch (lang) {
|
|
51
|
-
case '
|
|
51
|
+
case 'javascript':
|
|
52
|
+
case 'typescript':
|
|
52
53
|
if (filename === 'package.json' || filename === 'package-lock.json' || filename === 'pnpm-lock.yml') {
|
|
53
54
|
return {
|
|
54
55
|
...content.dependencies,
|
|
@@ -104,14 +105,6 @@ const PROJECT_TYPES = getSupportedLanguages().map(lang => {
|
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
break;
|
|
107
|
-
case 'php':
|
|
108
|
-
if (filename === 'composer.json') {
|
|
109
|
-
return {
|
|
110
|
-
...content.require,
|
|
111
|
-
...content['require-dev']
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
break;
|
|
115
108
|
case 'ruby':
|
|
116
109
|
if (filename === 'Gemfile') {
|
|
117
110
|
const lines = content.toString().split('\n');
|
|
@@ -159,16 +152,13 @@ const PROJECT_TYPES = getSupportedLanguages().map(lang => {
|
|
|
159
152
|
});
|
|
160
153
|
function getRegistryUrl(lang) {
|
|
161
154
|
switch (lang) {
|
|
162
|
-
case '
|
|
155
|
+
case 'javascript':
|
|
156
|
+
case 'typescript':
|
|
157
|
+
return 'https://registry.npmjs.org';
|
|
163
158
|
case 'rust': return 'https://crates.io/api/v1/crates';
|
|
164
159
|
case 'python': return 'https://pypi.org/pypi';
|
|
165
160
|
case 'go': return 'https://proxy.golang.org';
|
|
166
161
|
case 'ruby': return 'https://rubygems.org/api/v1/gems';
|
|
167
|
-
case 'php': return 'https://packagist.org/packages';
|
|
168
|
-
case 'java': return 'https://repo1.maven.org/maven2';
|
|
169
|
-
case 'csharp': return 'https://api.nuget.org/v3-flatcontainer';
|
|
170
|
-
case 'swift': return 'https://packagecatalog.com';
|
|
171
|
-
case 'dart': return 'https://pub.dev/api/packages';
|
|
172
162
|
default: return '';
|
|
173
163
|
}
|
|
174
164
|
}
|
|
@@ -191,7 +181,8 @@ async function fetchPackageFromRegistry(packageName, projectType) {
|
|
|
191
181
|
const parsed = JSON.parse(data);
|
|
192
182
|
// Handle different registry response formats
|
|
193
183
|
switch (projectType.name) {
|
|
194
|
-
case '
|
|
184
|
+
case 'JavaScript':
|
|
185
|
+
case 'Typescript':
|
|
195
186
|
resolve(parseNpmRegistryResponse(parsed, packageName));
|
|
196
187
|
break;
|
|
197
188
|
case 'Rust':
|
|
@@ -293,7 +284,8 @@ function parseGenericResponse(data, packageName) {
|
|
|
293
284
|
async function getLatestVersion(packageName, projectType) {
|
|
294
285
|
try {
|
|
295
286
|
switch (projectType.name) {
|
|
296
|
-
case '
|
|
287
|
+
case 'JavaScript':
|
|
288
|
+
case 'TypeScript':
|
|
297
289
|
const { stdout } = await execAsync(`npm view ${packageName} version`);
|
|
298
290
|
return stdout.trim();
|
|
299
291
|
case 'Rust':
|
|
@@ -380,33 +372,42 @@ async function getEnhancedPackageInfo(name, currentVersion, projectType) {
|
|
|
380
372
|
* Display help for check command
|
|
381
373
|
*/
|
|
382
374
|
export function showCheckHelp() {
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
375
|
+
const helpConfig = {
|
|
376
|
+
commandName: 'Check',
|
|
377
|
+
emoji: '🔍',
|
|
378
|
+
description: 'Check package versions in your project and get suggestions for updates.\nHelps you keep your dependencies up-to-date and secure.',
|
|
379
|
+
usage: [
|
|
380
|
+
'check [package-name] [options]',
|
|
381
|
+
'check [options]'
|
|
382
|
+
],
|
|
383
|
+
options: [
|
|
384
|
+
{ flag: '-v, --verbose', description: 'Show detailed information for all packages' }
|
|
385
|
+
],
|
|
386
|
+
examples: [
|
|
387
|
+
{ command: 'check', description: 'Check all packages in current project' },
|
|
388
|
+
{ command: 'check --verbose', description: 'Check all packages with detailed info' },
|
|
389
|
+
{ command: 'check react', description: 'Check specific package version' },
|
|
390
|
+
{ command: 'check @types/node', description: 'Check scoped packages' },
|
|
391
|
+
{ command: 'check --help', description: 'Show this help message' }
|
|
392
|
+
],
|
|
393
|
+
additionalSections: [
|
|
394
|
+
{
|
|
395
|
+
title: 'Supported Package Managers',
|
|
396
|
+
items: [
|
|
397
|
+
'npm, pnpm, yarn (Node.js)',
|
|
398
|
+
'pip, pipenv, poetry (Python)',
|
|
399
|
+
'cargo (Rust)',
|
|
400
|
+
'go modules (Go)',
|
|
401
|
+
'composer (PHP)'
|
|
402
|
+
]
|
|
403
|
+
}
|
|
404
|
+
],
|
|
405
|
+
tips: [
|
|
406
|
+
'Use --verbose for detailed package information including security vulnerabilities',
|
|
407
|
+
'Check specific packages by name for targeted updates'
|
|
408
|
+
]
|
|
409
|
+
};
|
|
410
|
+
createStandardHelp(helpConfig);
|
|
410
411
|
}
|
|
411
412
|
export async function checkCommand(packageName, options) {
|
|
412
413
|
// Check for help flag
|
|
@@ -426,6 +427,8 @@ export async function checkCommand(packageName, options) {
|
|
|
426
427
|
packageName = undefined;
|
|
427
428
|
}
|
|
428
429
|
try {
|
|
430
|
+
// Display command banner
|
|
431
|
+
displayCommandBanner('Check', 'Check package versions and updates for your project dependencies');
|
|
429
432
|
console.log('\n' + chalk.hex('#f39c12')('🔍 Starting package check...'));
|
|
430
433
|
if (packageName && packageName !== '--verbose' && packageName !== '-v') {
|
|
431
434
|
await checkSinglePackage(packageName, isVerbose);
|
|
@@ -500,61 +503,100 @@ async function checkProjectPackages(verbose = false) {
|
|
|
500
503
|
}
|
|
501
504
|
async function detectProjectType() {
|
|
502
505
|
console.log(chalk.gray('🔍 Detecting project type...'));
|
|
506
|
+
// Priority order for detection - check most common files first
|
|
507
|
+
const priorityFiles = ['package.json', 'Cargo.toml', 'requirements.txt', 'composer.json', 'go.mod'];
|
|
508
|
+
// First pass: check priority files in current directory
|
|
509
|
+
for (const priorityFile of priorityFiles) {
|
|
510
|
+
const filePath = path.join(process.cwd(), priorityFile);
|
|
511
|
+
console.log(chalk.gray(` Checking priority file: ${filePath}`));
|
|
512
|
+
if (await fs.pathExists(filePath)) {
|
|
513
|
+
console.log(chalk.green(` ✅ Found: ${priorityFile}`));
|
|
514
|
+
// Find the project type that matches this file
|
|
515
|
+
const matchingType = PROJECT_TYPES.find(type => type.files.includes(priorityFile));
|
|
516
|
+
if (matchingType) {
|
|
517
|
+
console.log(chalk.green(` 📦 Detected: ${matchingType.name}`));
|
|
518
|
+
return matchingType;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
// Second pass: check all other files
|
|
503
523
|
for (const projectType of PROJECT_TYPES) {
|
|
504
524
|
console.log(chalk.gray(` Checking ${projectType.name}: ${projectType.files.join(', ')}`));
|
|
505
525
|
for (const file of projectType.files) {
|
|
526
|
+
if (priorityFiles.includes(file))
|
|
527
|
+
continue; // Already checked
|
|
506
528
|
// Check in current directory first
|
|
507
529
|
const filePath = path.join(process.cwd(), file);
|
|
508
|
-
console.log(chalk.gray(` Looking for: ${filePath}`));
|
|
509
530
|
if (await fs.pathExists(filePath)) {
|
|
510
|
-
console.log(chalk.green(`
|
|
531
|
+
console.log(chalk.green(` ✅ Found: ${file}`));
|
|
511
532
|
return projectType;
|
|
512
533
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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;
|
|
525
550
|
}
|
|
526
551
|
}
|
|
527
552
|
}
|
|
528
|
-
catch (error) {
|
|
529
|
-
// Ignore directory read errors
|
|
530
|
-
}
|
|
531
553
|
}
|
|
532
554
|
}
|
|
555
|
+
catch (error) {
|
|
556
|
+
console.log(chalk.yellow(' Warning: Could not read directory contents'));
|
|
557
|
+
}
|
|
533
558
|
console.log(chalk.yellow(' No project type detected'));
|
|
534
|
-
return
|
|
559
|
+
return null;
|
|
535
560
|
}
|
|
536
561
|
async function getDependenciesForProject(projectType) {
|
|
537
|
-
|
|
538
|
-
|
|
562
|
+
console.log(chalk.gray(`📋 Looking for dependencies in ${projectType.name} project...`));
|
|
563
|
+
// Priority order for dependency files
|
|
564
|
+
const priorityFiles = projectType.files.slice().sort((a, b) => {
|
|
565
|
+
const priority = ['package.json', 'Cargo.toml', 'requirements.txt', 'composer.json', 'go.mod'];
|
|
566
|
+
return priority.indexOf(a) - priority.indexOf(b);
|
|
567
|
+
});
|
|
568
|
+
// First check current directory with priority files
|
|
569
|
+
for (const file of priorityFiles) {
|
|
539
570
|
const filePath = path.join(process.cwd(), file);
|
|
571
|
+
console.log(chalk.gray(` Checking: ${filePath}`));
|
|
540
572
|
if (await fs.pathExists(filePath)) {
|
|
573
|
+
console.log(chalk.green(` ✅ Found: ${file}`));
|
|
541
574
|
try {
|
|
542
575
|
let content;
|
|
543
576
|
if (file.endsWith('.json')) {
|
|
544
577
|
content = await fs.readJson(filePath);
|
|
578
|
+
console.log(chalk.gray(` 📦 Loaded JSON config from ${file}`));
|
|
545
579
|
}
|
|
546
580
|
else if (file.endsWith('.toml')) {
|
|
547
581
|
// Simple TOML parser for basic cases
|
|
548
582
|
const tomlContent = await fs.readFile(filePath, 'utf-8');
|
|
549
583
|
content = parseSimpleToml(tomlContent);
|
|
584
|
+
console.log(chalk.gray(` 📦 Loaded TOML config from ${file}`));
|
|
550
585
|
}
|
|
551
586
|
else {
|
|
552
587
|
content = await fs.readFile(filePath, 'utf-8');
|
|
588
|
+
console.log(chalk.gray(` 📦 Loaded text config from ${file}`));
|
|
589
|
+
}
|
|
590
|
+
const dependencies = projectType.getDependencies(content, file);
|
|
591
|
+
const depCount = Object.keys(dependencies).length;
|
|
592
|
+
console.log(chalk.green(` 📊 Found ${depCount} dependencies`));
|
|
593
|
+
if (depCount > 0) {
|
|
594
|
+
console.log(chalk.gray(` Dependencies: ${Object.keys(dependencies).slice(0, 5).join(', ')}${depCount > 5 ? '...' : ''}`));
|
|
595
|
+
return dependencies;
|
|
553
596
|
}
|
|
554
|
-
return projectType.getDependencies(content, file);
|
|
555
597
|
}
|
|
556
598
|
catch (error) {
|
|
557
|
-
console.warn(
|
|
599
|
+
console.warn(chalk.yellow(` ⚠️ Could not parse ${file}: ${error}`));
|
|
558
600
|
}
|
|
559
601
|
}
|
|
560
602
|
}
|
|
@@ -565,9 +607,10 @@ async function getDependenciesForProject(projectType) {
|
|
|
565
607
|
const itemPath = path.join(process.cwd(), item);
|
|
566
608
|
const stats = await fs.stat(itemPath);
|
|
567
609
|
if (stats.isDirectory()) {
|
|
568
|
-
for (const file of
|
|
610
|
+
for (const file of priorityFiles) {
|
|
569
611
|
const configPath = path.join(itemPath, file);
|
|
570
612
|
if (await fs.pathExists(configPath)) {
|
|
613
|
+
console.log(chalk.green(` ✅ Found in subdirectory: ${item}/${file}`));
|
|
571
614
|
try {
|
|
572
615
|
let content;
|
|
573
616
|
if (file.endsWith('.json')) {
|
|
@@ -580,10 +623,15 @@ async function getDependenciesForProject(projectType) {
|
|
|
580
623
|
else {
|
|
581
624
|
content = await fs.readFile(configPath, 'utf-8');
|
|
582
625
|
}
|
|
583
|
-
|
|
626
|
+
const dependencies = projectType.getDependencies(content, file);
|
|
627
|
+
const depCount = Object.keys(dependencies).length;
|
|
628
|
+
if (depCount > 0) {
|
|
629
|
+
console.log(chalk.green(` 📊 Found ${depCount} dependencies in ${configPath}`));
|
|
630
|
+
return dependencies;
|
|
631
|
+
}
|
|
584
632
|
}
|
|
585
633
|
catch (error) {
|
|
586
|
-
console.warn(
|
|
634
|
+
console.warn(chalk.yellow(` ⚠️ Could not parse ${configPath}`));
|
|
587
635
|
}
|
|
588
636
|
}
|
|
589
637
|
}
|
|
@@ -591,8 +639,9 @@ async function getDependenciesForProject(projectType) {
|
|
|
591
639
|
}
|
|
592
640
|
}
|
|
593
641
|
catch (error) {
|
|
594
|
-
|
|
642
|
+
console.warn(chalk.yellow(' ⚠️ Could not read directory contents'));
|
|
595
643
|
}
|
|
644
|
+
console.log(chalk.yellow(' 📦 No dependencies found'));
|
|
596
645
|
return {};
|
|
597
646
|
}
|
|
598
647
|
function parseSimpleToml(content) {
|