package-installer-cli 1.2.0 → 1.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f432378951e281eb37210295d7894abbf072093bd9a2e6099f1d3219ad45eb0
4
- data.tar.gz: 0e9edf8310281ce583765615d8d41f1897b7e0fab8e6cc3dbbfa405d39a63cc9
3
+ metadata.gz: de2baf8d0677e75c1471a523c2c8b581bde9c5187f0cecb4a5a4c79a6d03022a
4
+ data.tar.gz: c3e5ee669f095c1537ba2bf505367da009999c907b6814fb907e5b569eebcc2a
5
5
  SHA512:
6
- metadata.gz: b0490199b16d2f27b1513fc9360895c02cb9a1a2fc58a4cddc5611c20afa21c8ef6e609d99b4dc7271a19de0ea21c1275127839d4b56b26b91e0554cff66c296
7
- data.tar.gz: 6e7cec10cae328695c8fb9328797f5efc46ced7e04b0bb99dffe40ccbb887bc9ee495277b2ac49e5196e88f98e6a71a2cec823ad4ec692ee78424ce5cc3b5d53
6
+ metadata.gz: 3f593de7edcf4ec3b60397cf4de415d7e2703debb4a49c7f85d1911d2c2c64b9c644e637d259187dd965d43b23906985795cb5ed5fbc5eece7bf6af45b33c4fb
7
+ data.tar.gz: c9f3538f2430caa503d7bbe21f52bd2592b689e80c1f08763b4afd2268a1cffd9ba4d1bd4dcf6a855aebacc0b2f59a1ca750ec296ad96aa57344b6cfdf40e043
data/CHANGELOG.md CHANGED
@@ -5,7 +5,7 @@ All notable changes to the Package Installer CLI Ruby gem will be documented in
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [1.1.0] - 2025-09-23
8
+ ## [1.3.0] - 2025-09-23
9
9
 
10
10
  ### Updated
11
11
  - Version bump to 1.1.0
data/dist/commands/add.js CHANGED
@@ -4,9 +4,10 @@ import gradient from 'gradient-string';
4
4
  import boxen from 'boxen';
5
5
  import path from 'path';
6
6
  import fs from 'fs-extra';
7
+ import { createStandardHelp } from '../utils/helpFormatter.js';
7
8
  import { addFeature, detectProjectStack, SUPPORTED_FEATURES } from '../utils/featureInstaller.js';
8
9
  import { historyManager } from '../utils/historyManager.js';
9
- import { getCachedProject, cacheProjectData } from '../utils/cacheManager.js';
10
+ import { cacheProjectData } from '../utils/cacheManager.js';
10
11
  import { getFeaturesJsonPath, getFeaturesPath } from '../utils/pathResolver.js';
11
12
  /**
12
13
  * Helper function to capitalize strings
@@ -15,14 +16,47 @@ function capitalize(str) {
15
16
  return str.charAt(0).toUpperCase() + str.slice(1);
16
17
  }
17
18
  /**
18
- * Get features.json configuration
19
+ * Get features.json configuration with new jsonPath structure
19
20
  */
20
- function getFeaturesConfig() {
21
+ async function getFeaturesConfig() {
21
22
  try {
22
23
  // Use the centralized path resolver
23
24
  const featuresPath = getFeaturesJsonPath();
24
25
  if (fs.existsSync(featuresPath)) {
25
- return JSON.parse(fs.readFileSync(featuresPath, 'utf-8'));
26
+ const baseConfig = JSON.parse(fs.readFileSync(featuresPath, 'utf-8'));
27
+ const processedConfig = {};
28
+ // Process each feature to load individual JSON files
29
+ for (const [featureName, config] of Object.entries(baseConfig.features || baseConfig)) {
30
+ const featureConfig = config;
31
+ if (featureConfig.jsonPath) {
32
+ try {
33
+ // Load the individual feature JSON file
34
+ const individualFeaturePath = path.resolve(path.dirname(featuresPath), featureConfig.jsonPath);
35
+ if (fs.existsSync(individualFeaturePath)) {
36
+ const individualFeatureData = JSON.parse(fs.readFileSync(individualFeaturePath, 'utf-8'));
37
+ // Merge the base config with the individual feature data
38
+ processedConfig[featureName] = {
39
+ ...featureConfig,
40
+ files: individualFeatureData.files || individualFeatureData,
41
+ ...individualFeatureData
42
+ };
43
+ }
44
+ else {
45
+ console.warn(chalk.yellow(`⚠️ Individual feature file not found: ${individualFeaturePath}`));
46
+ processedConfig[featureName] = featureConfig;
47
+ }
48
+ }
49
+ catch (error) {
50
+ console.warn(chalk.yellow(`⚠️ Could not load individual feature file for ${featureName}`));
51
+ processedConfig[featureName] = featureConfig;
52
+ }
53
+ }
54
+ else {
55
+ // Legacy format
56
+ processedConfig[featureName] = featureConfig;
57
+ }
58
+ }
59
+ return { features: processedConfig };
26
60
  }
27
61
  console.warn(chalk.yellow(`⚠️ features.json not found at: ${featuresPath}`));
28
62
  return { features: {} };
@@ -35,32 +69,32 @@ function getFeaturesConfig() {
35
69
  /**
36
70
  * Get available feature categories
37
71
  */
38
- function getAvailableFeatures() {
39
- const config = getFeaturesConfig();
40
- return Object.keys(config);
72
+ export async function getAvailableFeatures() {
73
+ const config = await getFeaturesConfig();
74
+ return Object.keys(config.features || {});
41
75
  }
42
76
  /**
43
77
  * Get sub-features for a category
44
78
  */
45
- function getSubFeatures(category) {
46
- const config = getFeaturesConfig();
47
- const categoryConfig = config[category];
79
+ async function getSubFeatures(category) {
80
+ const config = await getFeaturesConfig();
81
+ const categoryConfig = config.features?.[category];
48
82
  if (!categoryConfig || typeof categoryConfig !== 'object') {
49
83
  return [];
50
84
  }
51
- return Object.keys(categoryConfig);
85
+ return Object.keys(categoryConfig.files || {});
52
86
  }
53
87
  /**
54
88
  * List available features from features.json with descriptions
55
89
  */
56
- function listAvailableFeatures() {
57
- const featuresConfig = getFeaturesConfig();
90
+ async function listAvailableFeatures() {
91
+ const featuresConfig = await getFeaturesConfig();
58
92
  if (!featuresConfig.features || Object.keys(featuresConfig.features).length === 0) {
59
93
  console.log(chalk.yellow('⚠️ No features found in configuration'));
60
94
  return;
61
95
  }
62
96
  const featuresData = Object.entries(featuresConfig.features).map(([key, config]) => {
63
- const providers = Object.keys(config).filter(k => k !== 'description' && k !== 'supportedFrameworks');
97
+ const providers = config.files ? Object.keys(config.files) : [];
64
98
  const description = config.description || 'No description available';
65
99
  const frameworks = config.supportedFrameworks ? config.supportedFrameworks.join(', ') : 'All frameworks';
66
100
  return {
@@ -234,61 +268,60 @@ function showEnhancedSetupInstructions(feature, provider) {
234
268
  /**
235
269
  * Show help for add command
236
270
  */
237
- export function showAddHelp() {
238
- const piGradient = gradient(['#00c6ff', '#0072ff']);
239
- const featuresConfig = getFeaturesConfig();
271
+ export async function showAddHelp() {
272
+ const featuresConfig = await getFeaturesConfig();
240
273
  const availableFeatures = Object.keys(featuresConfig.features || {});
241
- console.log('\n' + boxen(piGradient.multiline([
242
- '📦 Package Installer CLI - Add Features',
243
- '',
244
- 'USAGE:',
245
- ' pi add # Interactive feature selection',
246
- ' pi add <feature> # Add feature with provider selection',
247
- ' pi add <feature> <provider> # Add specific feature provider',
248
- ' pi add --list # List all available features',
249
- ' pi add --help # Show this help message',
250
- '',
251
- 'EXAMPLES:',
252
- ' pi add # Show all features in dropdown',
253
- ' pi add auth # Show auth providers dropdown',
254
- ' pi add auth clerk # Add Clerk authentication',
255
- ' pi add aws # Show AWS services dropdown',
256
- ' pi add aws ec2 # Add AWS EC2 integration',
257
- ' pi add ai openai # Add OpenAI integration',
258
- ' pi add database postgres # Add PostgreSQL integration',
259
- ' pi add payment stripe # Add Stripe payment integration',
260
- '',
261
- 'OPTIONS:',
262
- ' -l, --list List all available features',
263
- ' -v, --verbose Show detailed output',
264
- ' -h, --help Show this help message',
265
- '',
266
- `AVAILABLE FEATURES (${availableFeatures.length}):`,
267
- availableFeatures.length > 0
268
- ? availableFeatures.map(feature => ` • ${feature}`).join('\n')
269
- : ' No features configured',
270
- '',
271
- 'SUPPORTED FRAMEWORKS:',
272
- ' Next.js App Router & Pages Router',
273
- ' • React Create React App & Vite',
274
- ' • Express.js Node.js backend framework',
275
- ' NestJS TypeScript backend framework',
276
- ' • Vue.js Vue 3 with Composition API',
277
- ' Angular Angular 15+',
278
- ' Remix Full-stack React framework',
279
- ' And more coming soon...',
280
- '',
281
- 'NOTES:',
282
- ' • Features are automatically configured for your framework',
283
- ' • Environment variables are added to .env files',
284
- ' • TypeScript and JavaScript are both supported',
285
- ' Use "pi add --list" to see detailed feature information'
286
- ].join('\n')), {
287
- padding: 1,
288
- margin: 1,
289
- borderStyle: 'round',
290
- borderColor: 'blue'
291
- }));
274
+ const helpConfig = {
275
+ commandName: 'Add',
276
+ emoji: '',
277
+ description: 'Add new features to your project with automatic framework integration.\nSupports authentication, databases, AI, payments, AWS services, and more.',
278
+ usage: [
279
+ 'add [options]',
280
+ 'add <feature> [provider] [options]'
281
+ ],
282
+ options: [
283
+ { 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' }
286
+ ],
287
+ examples: [
288
+ { command: 'add', description: 'Interactive feature selection' },
289
+ { command: 'add auth', description: 'Show auth providers dropdown' },
290
+ { command: 'add auth clerk', description: 'Add Clerk authentication' },
291
+ { command: 'add aws ec2', description: 'Add AWS EC2 integration' },
292
+ { command: 'add ai openai', description: 'Add OpenAI integration' },
293
+ { command: 'add database postgres', description: 'Add PostgreSQL integration' },
294
+ { command: 'add payment stripe', description: 'Add Stripe payment integration' },
295
+ { command: 'add --list', description: 'List all available features' }
296
+ ],
297
+ additionalSections: [
298
+ {
299
+ title: `Available Features (${availableFeatures.length})`,
300
+ items: availableFeatures.length > 0
301
+ ? availableFeatures
302
+ : ['No features configured']
303
+ },
304
+ {
305
+ title: 'Supported Frameworks',
306
+ items: [
307
+ 'Next.js - App Router & Pages Router',
308
+ 'React - Create React App & Vite',
309
+ 'Express.js - Node.js backend framework',
310
+ 'NestJS - TypeScript backend framework',
311
+ 'Vue.js - Vue 3 with Composition API',
312
+ 'Angular - Angular 15+',
313
+ 'Remix - Full-stack React framework'
314
+ ]
315
+ }
316
+ ],
317
+ tips: [
318
+ 'Features are automatically configured for your framework',
319
+ 'Environment variables are added to .env files',
320
+ 'TypeScript and JavaScript are both supported',
321
+ 'Use "pi add --list" to see detailed feature information'
322
+ ]
323
+ };
324
+ createStandardHelp(helpConfig);
292
325
  }
293
326
  /**
294
327
  * Main add command handler with enhanced syntax support
@@ -303,12 +336,12 @@ export async function addCommand(feature, provider, options = {}) {
303
336
  try {
304
337
  // Handle help flag
305
338
  if (options.help || feature === '--help' || feature === '-h') {
306
- showAddHelp();
339
+ await showAddHelp();
307
340
  return;
308
341
  }
309
342
  // Handle list flag
310
343
  if (options.list || feature === '--list' || feature === '-l') {
311
- listAvailableFeatures();
344
+ await listAvailableFeatures();
312
345
  return;
313
346
  }
314
347
  // Initialize history manager
@@ -330,7 +363,8 @@ export async function addCommand(feature, provider, options = {}) {
330
363
  }
331
364
  else {
332
365
  // Standalone add command - detect framework from project files
333
- projectInfo = await getCachedProject(projectPath);
366
+ // Get cached project info or detect it (simplified)
367
+ projectInfo = null; // Simplified - always detect fresh
334
368
  if (!projectInfo) {
335
369
  console.log(chalk.yellow('🔍 Analyzing project structure...'));
336
370
  projectInfo = await detectProjectStack(projectPath);
@@ -341,7 +375,7 @@ export async function addCommand(feature, provider, options = {}) {
341
375
  const projectName = await fs.pathExists(packageJsonPath)
342
376
  ? (await fs.readJson(packageJsonPath)).name || path.basename(projectPath)
343
377
  : path.basename(projectPath);
344
- await cacheProjectData(projectPath, projectName, projectInfo.projectLanguage || 'unknown', projectInfo.framework, [], 0);
378
+ await cacheProjectData(projectPath, projectName, projectInfo.projectLanguage || 'unknown');
345
379
  }
346
380
  catch (error) {
347
381
  console.warn(chalk.yellow('⚠️ Could not cache project info'));
@@ -375,8 +409,8 @@ export async function addCommand(feature, provider, options = {}) {
375
409
  console.log(chalk.red('❌ Features configuration not found'));
376
410
  return;
377
411
  }
378
- const featuresConfig = JSON.parse(await fs.readFile(featuresConfigPath, 'utf-8'));
379
- const availableFeatures = Object.keys(featuresConfig.features);
412
+ const featuresConfig = await getFeaturesConfig();
413
+ const availableFeatures = Object.keys(featuresConfig.features || {});
380
414
  // Handle different command syntax cases
381
415
  if (!feature) {
382
416
  // Case 1: "pi add" - Show interactive dropdown for all features
@@ -511,7 +545,7 @@ export async function addCommand(feature, provider, options = {}) {
511
545
  return;
512
546
  }
513
547
  // Get available sub-features/providers
514
- const subFeatures = getSubFeatures(selectedFeature);
548
+ const subFeatures = await getSubFeatures(selectedFeature);
515
549
  // If no provider specified and multiple providers available, show selection
516
550
  if (!selectedProvider && subFeatures.length > 1) {
517
551
  const providerChoices = subFeatures.map((subFeature) => {
@@ -7,46 +7,54 @@ import path from 'path';
7
7
  import os from 'os';
8
8
  import gradientString from 'gradient-string';
9
9
  import boxen from 'boxen';
10
+ import { createStandardHelp } from '../utils/helpFormatter.js';
10
11
  import { createBanner, displaySystemInfo, displaySuccessMessage } from '../utils/dashboard.js';
11
12
  import { HistoryManager } from '../utils/historyManager.js';
12
13
  /**
13
- * Display help for analyze command
14
+ * Display help for analyze command using standardized format
14
15
  */
15
16
  export function showAnalyzeHelp() {
16
- console.clear();
17
- const helpContent = boxen(gradientString(['#667eea', '#764ba2'])('📊 Package Installer CLI Analytics Help') + '\n\n' +
18
- chalk.white('Display comprehensive CLI usage analytics and project dashboard') + '\n\n' +
19
- chalk.cyan('Usage:') + '\n' +
20
- chalk.white(' pi analyze [options]') + '\n' +
21
- chalk.white(' pi stats [options]') + chalk.gray(' (alias)') + '\n\n' +
22
- chalk.cyan('Description:') + '\n' +
23
- chalk.white(' Interactive dashboard showing Package Installer CLI usage statistics,') + '\n' +
24
- chalk.white(' project analytics, recent activities, and development environment info.') + '\n\n' +
25
- chalk.cyan('Options:') + '\n' +
26
- chalk.white(' --export') + chalk.gray(' Export analytics data to JSON file') + '\n' +
27
- chalk.white(' --reset') + chalk.gray(' Reset analytics history') + '\n' +
28
- chalk.white(' --detailed') + chalk.gray(' Show detailed analytics breakdown') + '\n' +
29
- chalk.white(' -h, --help') + chalk.gray(' Show this help message') + '\n\n' +
30
- chalk.cyan('Features:') + '\n' +
31
- chalk.green(' 📈 Command Usage Stats') + chalk.gray(' Frequency and trends of CLI commands') + '\n' +
32
- chalk.green(' 🚀 Project Analytics') + chalk.gray(' Created projects and framework breakdown') + '\n' +
33
- chalk.green(' 📁 Recent Activity') + chalk.gray(' Last created/modified projects timeline') + '\n' +
34
- chalk.green(' 🎯 Feature Usage') + chalk.gray(' Most used features and integrations') + '\n' +
35
- chalk.green(' ⚙️ Environment Info') + chalk.gray(' Development environment overview') + '\n' +
36
- chalk.green(' 📊 Performance') + chalk.gray(' CLI performance metrics and insights') + '\n\n' +
37
- chalk.cyan('Examples:') + '\n' +
38
- chalk.white(' pi analyze') + chalk.gray(' Show complete analytics dashboard') + '\n' +
39
- chalk.white(' pi analyze --detailed') + chalk.gray(' Show detailed breakdown with more metrics') + '\n' +
40
- chalk.white(' pi analyze --export') + chalk.gray(' Export analytics data to JSON file') + '\n' +
41
- chalk.white(' pi analyze --reset') + chalk.gray(' Clear all analytics history') + '\n\n' +
42
- chalk.yellow('💡 Tip: Analytics data is collected from ~/.package-installer-cli/history.json'), {
43
- padding: 1,
44
- margin: { top: 1, bottom: 1, left: 2, right: 2 },
45
- borderStyle: 'round',
46
- borderColor: 'magenta',
47
- backgroundColor: '#000000'
48
- });
49
- console.log(helpContent);
17
+ const helpConfig = {
18
+ commandName: 'Analyze',
19
+ emoji: '📊',
20
+ description: 'Display comprehensive CLI usage analytics and project dashboard.\nInteractive dashboard showing Package Installer CLI usage statistics, project analytics, recent activities, and development environment info.',
21
+ usage: [
22
+ 'analyze [options]',
23
+ 'stats [options] # alias'
24
+ ],
25
+ options: [
26
+ { flag: '--export', description: 'Export analytics data to JSON file' },
27
+ { flag: '--reset', description: 'Reset analytics history' },
28
+ { flag: '--detailed', description: 'Show detailed analytics breakdown' },
29
+ { flag: '-h, --help', description: 'Show this help message' }
30
+ ],
31
+ examples: [
32
+ { command: 'analyze', description: 'Show complete analytics dashboard' },
33
+ { command: 'analyze --detailed', description: 'Show detailed breakdown with more metrics' },
34
+ { command: 'analyze --export', description: 'Export analytics data to JSON file' },
35
+ { command: 'analyze --reset', description: 'Clear all analytics history' },
36
+ { command: 'stats', description: 'Use alias command' }
37
+ ],
38
+ additionalSections: [
39
+ {
40
+ title: 'Features',
41
+ items: [
42
+ '📈 Command Usage Stats - Frequency and trends of CLI commands',
43
+ '🚀 Project Analytics - Created projects and framework breakdown',
44
+ '📁 Recent Activity - Last created/modified projects timeline',
45
+ '🎯 Feature Usage - Most used features and integrations',
46
+ '⚙️ Environment Info - Development environment overview',
47
+ '📊 Performance - CLI performance metrics and insights'
48
+ ]
49
+ }
50
+ ],
51
+ tips: [
52
+ 'Analytics data is collected from ~/.package-installer-cli/history.json',
53
+ 'Use --export to backup your analytics data',
54
+ 'Use --reset to start fresh analytics tracking'
55
+ ]
56
+ };
57
+ createStandardHelp(helpConfig);
50
58
  }
51
59
  /**
52
60
  * Main analyze command function
@@ -7,11 +7,98 @@ import fs from 'fs-extra';
7
7
  import path from 'path';
8
8
  import os from 'os';
9
9
  import ora from 'ora';
10
+ import { createStandardHelp } from '../utils/helpFormatter.js';
10
11
  import { getDirectorySize, getCacheStats, getCacheStatus } from '../utils/cacheManager.js';
12
+ /**
13
+ * Display help for cache command
14
+ */
15
+ export function showCacheHelp() {
16
+ const helpConfig = {
17
+ commandName: 'Cache',
18
+ emoji: '🗄️',
19
+ description: 'Manage CLI cache system for improved performance.\nAutomatically manages cached data for faster operations.',
20
+ usage: [
21
+ 'cache [subcommand] [type]',
22
+ 'cache [options]'
23
+ ],
24
+ options: [
25
+ { flag: '--stats', description: 'Show cache statistics' },
26
+ { flag: '--clear [type]', description: 'Clear cache (optional type)' },
27
+ { flag: '--info', description: 'Show cache information' },
28
+ { flag: '--optimize', description: 'Optimize cache' },
29
+ { flag: '--size', description: 'Show cache size only' },
30
+ { flag: '-h, --help', description: 'Show this help message' }
31
+ ],
32
+ examples: [
33
+ { command: 'cache stats', description: 'Show cache statistics' },
34
+ { command: 'cache --stats', description: 'Show cache statistics (flag)' },
35
+ { command: 'cache clear', description: 'Clear all cache' },
36
+ { command: 'cache clear projects', description: 'Clear specific cache type' },
37
+ { command: 'cache info', description: 'Show cache information' },
38
+ { command: 'cache optimize', description: 'Optimize cache performance' },
39
+ { command: 'cache --size', description: 'Show cache size only' }
40
+ ],
41
+ additionalSections: [
42
+ {
43
+ title: 'Subcommands',
44
+ items: [
45
+ 'stats - Show cache statistics and usage info',
46
+ 'clear [type] - Clear cache (all or specific type)',
47
+ 'info - Show cache configuration and paths',
48
+ 'optimize - Optimize cache performance'
49
+ ]
50
+ },
51
+ {
52
+ title: 'Cache Types',
53
+ items: [
54
+ 'projects - Project metadata and analysis',
55
+ 'analysis - Analysis results and reports',
56
+ 'packages - Package version information',
57
+ 'templates - Template usage statistics',
58
+ 'system - System environment information',
59
+ 'all - Clear all cache types'
60
+ ]
61
+ }
62
+ ],
63
+ tips: [
64
+ 'Cache improves CLI performance by storing frequently used data',
65
+ 'Cache is automatically managed but you can manually optimize it',
66
+ 'Use --size to check cache disk usage before clearing'
67
+ ]
68
+ };
69
+ createStandardHelp(helpConfig);
70
+ }
11
71
  /**
12
72
  * Main cache command function
13
73
  */
14
- export async function cacheCommand(subcommand, type) {
74
+ export async function cacheCommand(subcommand, type, options = {}) {
75
+ // Handle help flag
76
+ if (options.help || options['--help'] || options['-h'] || subcommand === '--help' || subcommand === '-h') {
77
+ showCacheHelp();
78
+ return;
79
+ }
80
+ // Handle option flags
81
+ if (options.stats || subcommand === 'stats') {
82
+ await cacheStatsCommand();
83
+ return;
84
+ }
85
+ if (options.clear !== undefined || subcommand === 'clear') {
86
+ const clearType = options.clear || type;
87
+ await cacheClearCommand(clearType);
88
+ return;
89
+ }
90
+ if (options.info || subcommand === 'info') {
91
+ await cacheInfoCommand();
92
+ return;
93
+ }
94
+ if (options.optimize || subcommand === 'optimize') {
95
+ await cacheOptimizeCommand();
96
+ return;
97
+ }
98
+ if (options.size) {
99
+ await cacheSizeCommand();
100
+ return;
101
+ }
15
102
  // Handle subcommands
16
103
  if (subcommand === 'stats') {
17
104
  await cacheStatsCommand();
@@ -27,26 +114,35 @@ export async function cacheCommand(subcommand, type) {
27
114
  }
28
115
  else {
29
116
  // Default cache command - show help and quick stats
117
+ console.clear();
30
118
  console.log(gradientString(['#00d2d3', '#0084ff'])('🗄️ Cache Manager\n'));
31
119
  console.log(chalk.cyan('Available commands:'));
32
- console.log(chalk.gray(' pi cache stats - Show cache statistics'));
33
- console.log(chalk.gray(' pi cache clear - Clear all cache'));
120
+ console.log(chalk.gray(' pi cache stats - Show cache statistics'));
121
+ console.log(chalk.gray(' pi cache clear - Clear all cache'));
34
122
  console.log(chalk.gray(' pi cache clear <type> - Clear specific cache type'));
35
- console.log(chalk.gray(' pi cache info - Show cache configuration'));
36
- console.log(chalk.gray(' pi cache optimize - Optimize cache performance'));
123
+ console.log(chalk.gray(' pi cache info - Show cache configuration'));
124
+ console.log(chalk.gray(' pi cache optimize - Optimize cache performance'));
125
+ console.log(chalk.gray(' pi cache --help - Show detailed help'));
37
126
  console.log(chalk.cyan('\nCache types:'));
38
- console.log(chalk.gray(' projects, templates, analysis, packages'));
127
+ console.log(chalk.gray(' projects, templates, analysis, packages, system, all'));
39
128
  // Show quick stats
40
129
  try {
41
130
  const stats = getCacheStats();
42
131
  console.log(chalk.cyan('\nQuick Stats:'));
43
132
  console.log(chalk.gray(` Cached Projects: ${stats.projects?.length || 0}`));
44
133
  console.log(chalk.gray(` Template Files: ${stats.templateFiles?.size || Object.keys(stats.templateFiles || {}).length || 0}`));
134
+ // Show cache size
135
+ const cacheDir = path.join(os.homedir(), '.pi-cache');
136
+ if (await fs.pathExists(cacheDir)) {
137
+ const size = await getDirectorySize(cacheDir);
138
+ console.log(chalk.gray(` Cache Size: ${(size / 1024 / 1024).toFixed(2)} MB`));
139
+ }
45
140
  }
46
141
  catch (error) {
47
142
  console.log(chalk.yellow('\n⚠️ Cache not initialized yet'));
48
143
  }
49
144
  console.log(chalk.green('\n✅ Cache system ready'));
145
+ console.log(chalk.gray('💡 Use --help for detailed options'));
50
146
  }
51
147
  }
52
148
  /**
@@ -174,6 +270,46 @@ async function cacheInfoCommand() {
174
270
  console.log(chalk.gray(' • templateFiles - Cached template file contents'));
175
271
  console.log(chalk.gray(' • system - System environment info'));
176
272
  }
273
+ /**
274
+ * Cache size subcommand
275
+ */
276
+ async function cacheSizeCommand() {
277
+ console.log(gradientString(['#00d2d3', '#0084ff'])('\n📊 Cache Size Information\n'));
278
+ const spinner = ora('Calculating cache size...').start();
279
+ try {
280
+ const cacheDir = path.join(os.homedir(), '.pi-cache');
281
+ if (!await fs.pathExists(cacheDir)) {
282
+ spinner.warn('Cache directory not found');
283
+ console.log(chalk.yellow('⚠️ Cache has not been initialized yet'));
284
+ return;
285
+ }
286
+ const totalSize = await getDirectorySize(cacheDir);
287
+ const cacheFile = path.join(cacheDir, 'cache.json');
288
+ spinner.succeed('Cache size calculated');
289
+ console.log(chalk.cyan('📁 Cache Size Breakdown:'));
290
+ console.log(chalk.gray(` Total Cache Size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`));
291
+ if (await fs.pathExists(cacheFile)) {
292
+ const cacheFileStats = await fs.stat(cacheFile);
293
+ console.log(chalk.gray(` Cache Data File: ${(cacheFileStats.size / 1024).toFixed(2)} KB`));
294
+ }
295
+ // Show cache efficiency
296
+ if (totalSize > 50 * 1024 * 1024) { // 50MB
297
+ console.log(chalk.yellow('\n⚠️ Cache is quite large (>50MB)'));
298
+ console.log(chalk.gray('💡 Consider running "pi cache optimize" or "pi cache clear"'));
299
+ }
300
+ else if (totalSize > 10 * 1024 * 1024) { // 10MB
301
+ console.log(chalk.cyan('\n💡 Cache size is reasonable'));
302
+ console.log(chalk.gray('Consider optimizing if performance is slow'));
303
+ }
304
+ else {
305
+ console.log(chalk.green('\n✅ Cache size is optimal'));
306
+ }
307
+ }
308
+ catch (error) {
309
+ spinner.fail('Failed to calculate cache size');
310
+ console.error(chalk.red(`❌ Error: ${error.message}`));
311
+ }
312
+ }
177
313
  /**
178
314
  * Cache optimize subcommand
179
315
  */