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.
@@ -2,41 +2,47 @@
2
2
  * Upgrade CLI command - Updates Package Installer CLI to the latest version
3
3
  */
4
4
  import chalk from 'chalk';
5
- import gradient from 'gradient-string';
6
5
  import boxen from 'boxen';
7
6
  import ora from 'ora';
8
7
  import inquirer from 'inquirer';
9
8
  import { exec } from 'child_process';
10
9
  import { promisify } from 'util';
11
10
  import semver from 'semver';
11
+ import { createStandardHelp } from '../utils/helpFormatter.js';
12
12
  const execAsync = promisify(exec);
13
13
  /**
14
14
  * Display help for upgrade-cli command
15
15
  */
16
16
  export function showUpgradeHelp() {
17
- const piGradient = gradient(['#00c6ff', '#0072ff']);
18
- const headerGradient = gradient(['#4facfe', '#00f2fe']);
19
- console.log('\n' + boxen(headerGradient('🚀 Package Installer CLI - Upgrade Command Help') + '\n\n' +
20
- chalk.white('Update Package Installer CLI to the latest version with intelligent upgrade management.') + '\n' +
21
- chalk.white('Includes breaking change detection and version compatibility checks!') + '\n\n' +
22
- chalk.cyan('Usage:') + '\n' +
23
- chalk.white(` ${piGradient('pi')} ${chalk.hex('#10ac84')('upgrade-cli')}`) + '\n\n' +
24
- chalk.cyan('Options:') + '\n' +
25
- chalk.gray(' -h, --help Display help for this command') + '\n\n' +
26
- chalk.cyan('Examples:') + '\n' +
27
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#10ac84')('upgrade-cli')} # Smart upgrade with breaking change detection`) + '\n' +
28
- chalk.gray(` ${piGradient('pi')} ${chalk.hex('#10ac84')('upgrade-cli')} ${chalk.hex('#ff6b6b')('--help')} # Show this help message`) + '\n\n' +
29
- chalk.hex('#00d2d3')('💡 Enhanced Features:') + '\n' +
30
- chalk.hex('#95afc0')(' • Semantic version analysis and breaking change detection') + '\n' +
31
- chalk.hex('#95afc0')(' Interactive confirmation for major version upgrades') + '\n' +
32
- chalk.hex('#95afc0')(' Automatic @latest tag installation for maximum compatibility') + '\n' +
33
- chalk.hex('#95afc0')(' Package size and release date information') + '\n' +
34
- chalk.hex('#95afc0')(' Comprehensive upgrade verification and rollback guidance'), {
35
- padding: 1,
36
- borderStyle: 'round',
37
- borderColor: 'cyan',
38
- backgroundColor: '#0a0a0a'
39
- }));
17
+ const helpConfig = {
18
+ commandName: 'upgrade-cli',
19
+ emoji: '🚀',
20
+ description: 'Update Package Installer CLI to the latest version with intelligent upgrade management.\nIncludes breaking change detection and version compatibility checks!',
21
+ usage: ['pi upgrade-cli'],
22
+ options: [],
23
+ examples: [
24
+ { command: 'pi upgrade-cli', description: 'Smart upgrade with breaking change detection' },
25
+ { command: 'pi upgrade-cli --help', description: 'Show this help message' }
26
+ ],
27
+ additionalSections: [
28
+ {
29
+ title: '💡 Enhanced Features',
30
+ items: [
31
+ '• Semantic version analysis and breaking change detection',
32
+ '• Interactive confirmation for major version upgrades',
33
+ '• Automatic @latest tag installation for maximum compatibility',
34
+ '• Package size and release date information',
35
+ '• Comprehensive upgrade verification and rollback guidance'
36
+ ]
37
+ }
38
+ ],
39
+ tips: [
40
+ 'CLI will prompt for confirmation on major version upgrades',
41
+ 'Breaking changes are automatically detected and explained',
42
+ 'Use npm install -g package-installer-cli@<version> to rollback'
43
+ ]
44
+ };
45
+ createStandardHelp(helpConfig);
40
46
  }
41
47
  /**
42
48
  * Get current CLI version
data/dist/index.js CHANGED
@@ -14,10 +14,12 @@ import { addCommand, showAddHelp } from './commands/add.js';
14
14
  import { showUpgradeHelp, upgradeCliCommand } from './commands/upgrade-cli.js';
15
15
  import { updateCommand, showUpdateHelp } from './commands/update.js';
16
16
  import { analyzeCommand, showAnalyzeHelp } from './commands/analyze.js';
17
- import { deployCommand } from './commands/deploy.js';
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';
@@ -93,12 +95,18 @@ program
93
95
  .command('check')
94
96
  .description(chalk.hex('#f39c12')('🔍 ') + chalk.hex('#ffa500')('Check package versions and get update suggestions'))
95
97
  .argument('[package-name]', chalk.hex('#95afc0')('Specific package to check (optional)'))
98
+ .option('-v, --verbose', 'Show detailed information for all packages')
99
+ .option('-h, --help', 'Display help for this command')
96
100
  .on('--help', () => {
97
101
  showCheckHelp();
98
102
  })
99
- .action(async (packageName) => {
103
+ .action(async (packageName, options) => {
100
104
  try {
101
- await checkCommand(packageName);
105
+ if (options.help) {
106
+ showCheckHelp();
107
+ return;
108
+ }
109
+ await checkCommand(packageName, options);
102
110
  }
103
111
  catch (error) {
104
112
  handleCommandError('check packages', error);
@@ -110,10 +118,21 @@ program
110
118
  .description(chalk.hex('#00d2d3')('📥 ') + chalk.hex('#00cec9')('Clone repositories from GitHub, GitLab, BitBucket & SourceHut'))
111
119
  .argument('[user/repo]', chalk.hex('#95afc0')('Repository in format "user/repo" or "provider:user/repo"'))
112
120
  .argument('[project-name]', chalk.hex('#95afc0')('Custom project name (defaults to repo name)'))
121
+ .option('-h, --help', 'Display help for this command')
122
+ .option('--offline', 'Use cached templates if available')
123
+ .option('--no-deps', 'Skip dependency installation')
124
+ .option('--no-git', 'Skip git initialization')
125
+ .option('--shallow', 'Create shallow clone (faster)')
126
+ .option('--branch <name>', 'Clone specific branch')
127
+ .option('--template', 'Treat as template repository')
113
128
  .on('--help', () => {
114
129
  showCloneHelp();
115
130
  })
116
- .action(async (userRepo, projectName) => {
131
+ .action(async (userRepo, projectName, options) => {
132
+ if (options.help) {
133
+ showCloneHelp();
134
+ return;
135
+ }
117
136
  if (!userRepo) {
118
137
  console.log('\n' + chalk.hex('#ff4757')('❌ Error: Repository is required'));
119
138
  console.log(chalk.hex('#95afc0')(' Format: user/repo or provider:user/repo'));
@@ -124,7 +143,7 @@ program
124
143
  return;
125
144
  }
126
145
  try {
127
- await cloneRepo(userRepo, projectName);
146
+ await cloneRepo(userRepo, projectName, options);
128
147
  }
129
148
  catch (error) {
130
149
  handleCommandError('clone repository', error);
@@ -138,11 +157,16 @@ program
138
157
  .argument('[provider]', chalk.hex('#95afc0')('Provider for the feature (optional)'))
139
158
  .option('-l, --list', chalk.hex('#95afc0')('List all available features'))
140
159
  .option('-v, --verbose', chalk.hex('#95afc0')('Show detailed output'))
160
+ .option('-h, --help', chalk.hex('#95afc0')('Display help for this command'))
141
161
  .on('--help', () => {
142
162
  showAddHelp();
143
163
  })
144
164
  .action(async (feature, provider, options) => {
145
165
  try {
166
+ if (options.help) {
167
+ showAddHelp();
168
+ return;
169
+ }
146
170
  await addCommand(feature, provider, options);
147
171
  }
148
172
  catch (error) {
@@ -152,6 +176,7 @@ program
152
176
  // UPGRADE-CLI COMMAND - Update CLI to latest version
153
177
  program
154
178
  .command('upgrade-cli')
179
+ .alias('upgrade')
155
180
  .description(chalk.hex('#ff6b6b')('🚀 ') + chalk.hex('#fd79a8')('Update Package Installer CLI to the latest version'))
156
181
  .on('--help', () => {
157
182
  showUpgradeHelp();
@@ -167,13 +192,18 @@ program
167
192
  // ANALYZE COMMAND - Terminal dashboard with analytics
168
193
  program
169
194
  .command('analyze')
195
+ .alias('stats')
170
196
  .description(chalk.hex('#667eea')('📊 ') + chalk.hex('#4facfe')('Show CLI usage analytics and framework statistics'))
197
+ .option('--export', 'Export analytics data to JSON file')
198
+ .option('--reset', 'Reset analytics history')
199
+ .option('--detailed', 'Show detailed analytics breakdown')
200
+ .option('-h, --help', 'Show this help message')
171
201
  .on('--help', () => {
172
202
  showAnalyzeHelp();
173
203
  })
174
- .action(async () => {
204
+ .action(async (options) => {
175
205
  try {
176
- await analyzeCommand();
206
+ await analyzeCommand(options);
177
207
  }
178
208
  catch (error) {
179
209
  handleCommandError('show analytics', error);
@@ -183,14 +213,16 @@ program
183
213
  program
184
214
  .command('update')
185
215
  .alias('u')
186
- .description(chalk.hex('#ff6b6b')('🔄 ') + chalk.hex('#fd79a8')('Update CLI, dependencies, and cache'))
216
+ .description(chalk.hex('#ff6b6b')('🔄 ') + chalk.hex('#fd79a8')('Update project dependencies with breaking change detection'))
217
+ .argument('[packages]', chalk.hex('#95afc0')('Comma-separated list of packages to update (optional)'))
218
+ .option('--latest', 'Update to latest versions (may include breaking changes)')
187
219
  .option('-h, --help', 'Show help for update command')
188
220
  .on('--help', () => {
189
221
  showUpdateHelp();
190
222
  })
191
- .action(async (options) => {
223
+ .action(async (packages, options) => {
192
224
  try {
193
- await updateCommand(options);
225
+ await updateCommand(packages, options);
194
226
  }
195
227
  catch (error) {
196
228
  handleCommandError('update', error);
@@ -204,15 +236,20 @@ program
204
236
  .option('--node-modules', 'Clean node_modules directories')
205
237
  .option('--build', 'Clean build/dist directories')
206
238
  .option('--cache', 'Clean package manager caches')
207
- .option('--logs', 'Clean log files')
208
- .option('--all', 'Clean everything (safe)')
239
+ .option('--logs', 'Clean log files and debug outputs')
240
+ .option('--all', 'Clean everything (safe operation)')
209
241
  .option('--deep', 'Deep clean (includes lock files)')
210
242
  .option('--dry-run', 'Preview what would be cleaned')
243
+ .option('-h, --help', 'Show help for clean command')
211
244
  .on("--help", () => {
212
245
  showCleanHelp();
213
246
  })
214
247
  .action(async (options) => {
215
248
  try {
249
+ if (options.help) {
250
+ showCleanHelp();
251
+ return;
252
+ }
216
253
  displayCommandBanner('clean', 'Clean development artifacts and caches');
217
254
  await cleanCommand(options);
218
255
  }
@@ -270,10 +307,18 @@ program
270
307
  .description(chalk.hex('#00d2d3')('🗄️ ') + chalk.hex('#0084ff')('Manage CLI cache system'))
271
308
  .argument('[subcommand]', 'Cache subcommand (stats, clear, info, optimize)')
272
309
  .argument('[type]', 'Type for clear command (projects, analysis, packages, templates, system, all)')
273
- .action(async (subcommand, type) => {
310
+ .option('--stats', 'Show cache statistics')
311
+ .option('--clear [type]', 'Clear cache (optionally specify type)')
312
+ .option('--info', 'Show cache configuration')
313
+ .option('--optimize', 'Optimize cache performance')
314
+ .option('--size', 'Show cache size information')
315
+ .option('-h, --help', 'Show help for cache command')
316
+ .on('--help', async () => {
317
+ showCacheHelp();
318
+ })
319
+ .action(async (subcommand, type, options) => {
274
320
  try {
275
- const { cacheCommand } = await import('./commands/cache.js');
276
- await cacheCommand(subcommand, type);
321
+ await cacheCommand(subcommand, type, options);
277
322
  }
278
323
  catch (error) {
279
324
  handleCommandError('cache', error);
@@ -284,7 +329,7 @@ program
284
329
  .command('deploy')
285
330
  .description(chalk.hex('#ff9a9e')('🚀 ') + chalk.hex('#fd79a8')('Deploy your project (Coming Soon)'))
286
331
  .on('--help', () => {
287
- // Help is handled in the command file
332
+ showDeployHelp();
288
333
  })
289
334
  .action(async () => {
290
335
  try {
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' +
@@ -66,7 +66,7 @@ export function displayCommandBanner(commandName, description) {
66
66
  const commandGradient = gradient(['#4facfe', '#00f2fe']);
67
67
  console.log('\n' + boxen(commandGradient(`🚀 ${commandName.toUpperCase()} COMMAND`) + '\n\n' +
68
68
  chalk.white(description) + '\n\n' +
69
- chalk.hex('#00d2d3')('💡 Package Installer CLI v3.2.0') + ' • ' +
69
+ chalk.hex('#00d2d3')(`💡 Package Installer CLI v${getPackageVersion()}`) + ' • ' +
70
70
  chalk.hex('#95afc0')('Fast • Smart • Feature-Rich'), {
71
71
  padding: 1,
72
72
  borderStyle: 'round',
@@ -1,77 +1,50 @@
1
1
  /**
2
2
  * Cache Manager - Centralized caching operations for Package Installer CLI
3
+ * Simplified version focusing on essential caching functionality only
3
4
  */
4
5
  import { cacheManager as cacheManagerInstance } from './cacheUtils.js';
5
6
  import fs from 'fs-extra';
6
7
  import path from 'path';
7
- import chalk from 'chalk';
8
8
  // Export the cache manager instance
9
9
  export const cacheManager = cacheManagerInstance;
10
10
  /**
11
11
  * Initialize cache system on CLI startup
12
12
  */
13
13
  export async function initializeCache() {
14
- await cacheManagerInstance.init();
15
- }
16
- /**
17
- * Get cached project
18
- */
19
- export async function getCachedProject(projectPath) {
20
14
  try {
21
- const cache = cacheManagerInstance.getCache();
22
- const cached = cache.projects.find((p) => p.path === projectPath);
23
- return cached || null;
15
+ await cacheManagerInstance.init();
24
16
  }
25
17
  catch (error) {
26
- return null;
18
+ // Silent fail - cache will work in memory mode
27
19
  }
28
20
  }
29
21
  /**
30
- * Cache project data (simplified)
22
+ * Get cached template files (simplified - returns null for now)
31
23
  */
32
- export async function cacheProjectData(projectPath, name, language, framework, dependencies, size) {
33
- try {
34
- // For now, just cache basic project info without complex dependencies
35
- console.log(chalk.gray(`📊 Caching project data for ${name}`));
36
- }
37
- catch (error) {
38
- console.warn('Failed to cache project data:', error);
39
- }
24
+ export async function getCachedTemplateFiles(templateName) {
25
+ // Simplified implementation - just return null for now
26
+ return null;
40
27
  }
41
28
  /**
42
- * Get cached template files (simplified)
29
+ * Cache template files (simplified - no-op for now)
43
30
  */
44
- export async function getCachedTemplateFiles(templateName) {
45
- try {
46
- const cache = cacheManagerInstance.getCache();
47
- const template = cache.templateFiles.find((t) => t.templateName === templateName);
48
- return template || null;
49
- }
50
- catch (error) {
51
- return null;
52
- }
31
+ export async function cacheTemplateFiles(templateName, templatePath, files) {
32
+ // Simplified implementation - no-op for now
33
+ // This reduces complexity and memory usage
53
34
  }
54
35
  /**
55
- * Cache template files (simplified)
36
+ * Update template usage statistics (simplified - no-op for now)
56
37
  */
57
- export async function cacheTemplateFiles(templateName, templatePath, files, size) {
58
- try {
59
- console.log(chalk.gray(`📊 Caching template files for ${templateName}`));
60
- }
61
- catch (error) {
62
- console.warn('Failed to cache template files:', error);
63
- }
38
+ export async function updateTemplateUsage(templateName, framework, language) {
39
+ // Simplified implementation - no-op for now
40
+ // This reduces complexity and memory usage
64
41
  }
65
42
  /**
66
- * Update template usage statistics (simplified)
43
+ * Cache project data (simplified - no-op for now)
67
44
  */
68
- export async function updateTemplateUsage(templateName, framework, language, features) {
69
- try {
70
- console.log(chalk.gray(`📊 Recording template usage: ${templateName}`));
71
- }
72
- catch (error) {
73
- console.warn('Failed to update template usage:', error);
74
- }
45
+ export async function cacheProjectData(projectPath, name, type) {
46
+ // Simplified implementation - no-op for now
47
+ // This reduces complexity and memory usage
75
48
  }
76
49
  /**
77
50
  * Get directory size utility function
@@ -80,18 +53,24 @@ export async function getDirectorySize(dirPath) {
80
53
  try {
81
54
  let totalSize = 0;
82
55
  async function calculateSize(currentPath) {
83
- const stats = await fs.stat(currentPath);
84
- if (stats.isFile()) {
85
- totalSize += stats.size;
86
- }
87
- else if (stats.isDirectory()) {
88
- const items = await fs.readdir(currentPath);
89
- for (const item of items) {
90
- if (!['node_modules', '.git', 'dist', 'build'].includes(item)) {
91
- await calculateSize(path.join(currentPath, item));
56
+ try {
57
+ const stats = await fs.stat(currentPath);
58
+ if (stats.isFile()) {
59
+ totalSize += stats.size;
60
+ }
61
+ else if (stats.isDirectory()) {
62
+ const items = await fs.readdir(currentPath);
63
+ for (const item of items) {
64
+ // Skip large directories to avoid performance issues
65
+ if (!['node_modules', '.git', 'dist', 'build', 'target', '.cache'].includes(item)) {
66
+ await calculateSize(path.join(currentPath, item));
67
+ }
92
68
  }
93
69
  }
94
70
  }
71
+ catch (error) {
72
+ // Skip files/directories that can't be accessed
73
+ }
95
74
  }
96
75
  await calculateSize(dirPath);
97
76
  return totalSize;
@@ -101,98 +80,52 @@ export async function getDirectorySize(dirPath) {
101
80
  }
102
81
  }
103
82
  /**
104
- * Read template files for caching
105
- */
106
- export async function readTemplateFiles(templatePath) {
107
- const files = {};
108
- async function readFiles(currentPath, relativePath = '') {
109
- try {
110
- const items = await fs.readdir(currentPath, { withFileTypes: true });
111
- for (const item of items) {
112
- const fullPath = path.join(currentPath, item.name);
113
- const relativeItemPath = path.join(relativePath, item.name);
114
- if (item.isFile()) {
115
- // Skip binary files and large files
116
- const stats = await fs.stat(fullPath);
117
- if (stats.size < 1024 * 1024) { // Skip files larger than 1MB
118
- const content = await fs.readFile(fullPath, 'utf-8').catch(() => null);
119
- if (content !== null) {
120
- files[relativeItemPath] = content;
121
- }
122
- }
123
- }
124
- else if (item.isDirectory() && !['node_modules', '.git', 'dist', 'build'].includes(item.name)) {
125
- await readFiles(fullPath, relativeItemPath);
126
- }
127
- }
128
- }
129
- catch (error) {
130
- // Skip directories that can't be read
131
- }
132
- }
133
- await readFiles(templatePath);
134
- return files;
135
- }
136
- /**
137
- * Create project from cached template
138
- */
139
- export async function createProjectFromCachedTemplate(projectName, cachedTemplate) {
140
- const projectPath = path.resolve(process.cwd(), projectName);
141
- // Create project directory
142
- await fs.ensureDir(projectPath);
143
- // Write cached files
144
- if (cachedTemplate.files) {
145
- for (const [filePath, content] of Object.entries(cachedTemplate.files)) {
146
- const fullPath = path.join(projectPath, filePath);
147
- await fs.ensureDir(path.dirname(fullPath));
148
- await fs.writeFile(fullPath, content);
149
- }
150
- }
151
- return projectPath;
152
- }
153
- /**
154
- * Get cache statistics
83
+ * Get cache statistics (simplified)
155
84
  */
156
85
  export function getCacheStats() {
157
86
  try {
158
- return cacheManagerInstance.getAdvancedStats();
87
+ const cache = cacheManagerInstance.getCache();
88
+ return {
89
+ projects: cache.projects || [],
90
+ templates: cache.templates || [],
91
+ templateFiles: cache.templateFiles || [],
92
+ features: cache.features || [],
93
+ hits: 0,
94
+ misses: 0
95
+ };
159
96
  }
160
97
  catch (error) {
161
98
  return {
162
- cache: { hitRate: '0%', size: 0 },
163
- health: { status: 'Unknown' },
164
- performance: {}
99
+ projects: [],
100
+ templates: [],
101
+ templateFiles: [],
102
+ features: [],
103
+ hits: 0,
104
+ misses: 0
165
105
  };
166
106
  }
167
107
  }
168
108
  /**
169
- * Get cache status
109
+ * Get cache status (simplified)
170
110
  */
171
111
  export function getCacheStatus() {
172
112
  try {
173
- const stats = getCacheStats();
174
113
  const cache = cacheManagerInstance.getCache();
175
114
  return {
176
- isHealthy: stats.health?.status === 'Healthy',
177
- hitRate: 0,
115
+ initialized: true,
116
+ version: cache.version || '1.0.0',
178
117
  totalProjects: cache.projects?.length || 0,
179
118
  totalTemplates: cache.templates?.length || 0,
180
- totalFeatures: cache.features?.length || 0,
181
- recentProjects: [],
182
- performance: stats.performance || {},
183
- size: stats.cache?.size || 0
119
+ totalFeatures: cache.features?.length || 0
184
120
  };
185
121
  }
186
122
  catch (error) {
187
123
  return {
188
- isHealthy: false,
189
- hitRate: 0,
124
+ initialized: false,
125
+ version: '1.0.0',
190
126
  totalProjects: 0,
191
127
  totalTemplates: 0,
192
- totalFeatures: 0,
193
- recentProjects: [],
194
- performance: {},
195
- size: 0
128
+ totalFeatures: 0
196
129
  };
197
130
  }
198
131
  }
@@ -292,7 +292,6 @@ function extractInstalledPackages(output, language) {
292
292
  switch (language) {
293
293
  case 'javascript':
294
294
  case 'typescript':
295
- case 'nodejs':
296
295
  // Parse npm/yarn/pnpm/bun output
297
296
  const jsMatches = output.match(/(?:added|installed)\s+(.+?)(?:\s|$)/gi);
298
297
  if (jsMatches) {
@@ -387,7 +386,6 @@ export async function installPackages(projectPath, language, packages, options =
387
386
  switch (language) {
388
387
  case 'javascript':
389
388
  case 'typescript':
390
- case 'nodejs':
391
389
  const flags = [
392
390
  isDev ? (packageManager.name === 'npm' ? '--save-dev' : packageManager.name === 'yarn' ? '--dev' : '--save-dev') : '',
393
391
  exact ? '--save-exact' : '',