pnpm-catalog-updates 0.7.19 → 1.0.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.
@@ -5,64 +5,64 @@
5
5
  * Integrates with npm audit and snyk for comprehensive security analysis.
6
6
  */
7
7
 
8
- import { spawnSync } from 'child_process';
9
- import * as fs from 'fs-extra';
10
- import * as path from 'path';
11
- import { OutputFormat, OutputFormatter } from '../formatters/outputFormatter.js';
12
- import { ProgressBar } from '../formatters/progressBar.js';
13
- import { StyledText, ThemeManager } from '../themes/colorTheme.js';
8
+ import { spawnSync } from 'node:child_process'
9
+ import * as path from 'node:path'
10
+ import * as fs from 'fs-extra'
11
+ import type { OutputFormat, OutputFormatter } from '../formatters/outputFormatter.js'
12
+ import { ProgressBar } from '../formatters/progressBar.js'
13
+ import { StyledText, ThemeManager } from '../themes/colorTheme.js'
14
14
 
15
15
  export interface SecurityCommandOptions {
16
- workspace?: string;
17
- format?: OutputFormat;
18
- audit?: boolean;
19
- fixVulns?: boolean;
20
- severity?: 'low' | 'moderate' | 'high' | 'critical';
21
- includeDev?: boolean;
22
- snyk?: boolean;
23
- verbose?: boolean;
24
- color?: boolean;
16
+ workspace?: string
17
+ format?: OutputFormat
18
+ audit?: boolean
19
+ fixVulns?: boolean
20
+ severity?: 'low' | 'moderate' | 'high' | 'critical'
21
+ includeDev?: boolean
22
+ snyk?: boolean
23
+ verbose?: boolean
24
+ color?: boolean
25
25
  }
26
26
 
27
27
  export interface SecurityReport {
28
28
  summary: {
29
- totalVulnerabilities: number;
30
- critical: number;
31
- high: number;
32
- moderate: number;
33
- low: number;
34
- info: number;
35
- };
36
- vulnerabilities: Vulnerability[];
37
- recommendations: SecurityRecommendation[];
29
+ totalVulnerabilities: number
30
+ critical: number
31
+ high: number
32
+ moderate: number
33
+ low: number
34
+ info: number
35
+ }
36
+ vulnerabilities: Vulnerability[]
37
+ recommendations: SecurityRecommendation[]
38
38
  metadata: {
39
- scanDate: string;
40
- scanTools: string[];
41
- workspacePath: string;
42
- };
39
+ scanDate: string
40
+ scanTools: string[]
41
+ workspacePath: string
42
+ }
43
43
  }
44
44
 
45
45
  export interface Vulnerability {
46
- id: string;
47
- package: string;
48
- severity: 'low' | 'moderate' | 'high' | 'critical';
49
- title: string;
50
- url: string;
51
- range: string;
52
- fixAvailable: boolean | string;
53
- fixVersion?: string;
54
- paths: string[];
55
- cwe?: string[];
56
- cve?: string[];
46
+ id: string
47
+ package: string
48
+ severity: 'low' | 'moderate' | 'high' | 'critical'
49
+ title: string
50
+ url: string
51
+ range: string
52
+ fixAvailable: boolean | string
53
+ fixVersion?: string
54
+ paths: string[]
55
+ cwe?: string[]
56
+ cve?: string[]
57
57
  }
58
58
 
59
59
  export interface SecurityRecommendation {
60
- package: string;
61
- currentVersion: string;
62
- recommendedVersion: string;
63
- type: 'update' | 'remove' | 'replace';
64
- reason: string;
65
- impact: string;
60
+ package: string
61
+ currentVersion: string
62
+ recommendedVersion: string
63
+ type: 'update' | 'remove' | 'replace'
64
+ reason: string
65
+ impact: string
66
66
  }
67
67
 
68
68
  export class SecurityCommand {
@@ -72,61 +72,61 @@ export class SecurityCommand {
72
72
  * Execute the security command
73
73
  */
74
74
  async execute(options: SecurityCommandOptions = {}): Promise<void> {
75
- let progressBar: ProgressBar | undefined;
75
+ let progressBar: ProgressBar | undefined
76
76
 
77
77
  try {
78
78
  // Initialize theme
79
- ThemeManager.setTheme('default');
79
+ ThemeManager.setTheme('default')
80
80
 
81
81
  // Show loading with progress bar
82
82
  progressBar = new ProgressBar({
83
83
  text: 'Performing security analysis...',
84
- });
85
- progressBar.start();
84
+ })
85
+ progressBar.start()
86
86
 
87
87
  if (options.verbose) {
88
- console.log(StyledText.iconAnalysis('Security vulnerability scanning'));
89
- console.log(StyledText.muted(`Workspace: ${options.workspace || process.cwd()}`));
90
- console.log(StyledText.muted(`Severity filter: ${options.severity || 'all'}`));
91
- console.log('');
88
+ console.log(StyledText.iconAnalysis('Security vulnerability scanning'))
89
+ console.log(StyledText.muted(`Workspace: ${options.workspace || process.cwd()}`))
90
+ console.log(StyledText.muted(`Severity filter: ${options.severity || 'all'}`))
91
+ console.log('')
92
92
  }
93
93
 
94
94
  // Execute security scan
95
- const report = await this.performSecurityScan(options);
95
+ const report = await this.performSecurityScan(options)
96
96
 
97
- progressBar.succeed('Security analysis completed');
97
+ progressBar.succeed('Security analysis completed')
98
98
 
99
99
  // Format and display results
100
- const formattedOutput = this.outputFormatter.formatSecurityReport(report);
101
- console.log(formattedOutput);
100
+ const formattedOutput = this.outputFormatter.formatSecurityReport(report)
101
+ console.log(formattedOutput)
102
102
 
103
103
  // Show recommendations if available
104
104
  if (report.recommendations.length > 0) {
105
- this.showRecommendations(report);
105
+ this.showRecommendations(report)
106
106
  }
107
107
 
108
108
  // Auto-fix vulnerabilities if requested
109
109
  if (options.fixVulns) {
110
- await this.autoFixVulnerabilities(report, options);
110
+ await this.autoFixVulnerabilities(report, options)
111
111
  }
112
112
 
113
113
  // Exit with appropriate code based on findings
114
- const exitCode = report.summary.critical > 0 ? 1 : 0;
115
- process.exit(exitCode);
114
+ const exitCode = report.summary.critical > 0 ? 1 : 0
115
+ process.exit(exitCode)
116
116
  } catch (error) {
117
117
  if (progressBar) {
118
- progressBar.fail('Security analysis failed');
118
+ progressBar.fail('Security analysis failed')
119
119
  }
120
120
 
121
- console.error(StyledText.iconError('Error performing security scan:'));
122
- console.error(StyledText.error(String(error)));
121
+ console.error(StyledText.iconError('Error performing security scan:'))
122
+ console.error(StyledText.error(String(error)))
123
123
 
124
124
  if (options.verbose && error instanceof Error) {
125
- console.error(StyledText.muted('Stack trace:'));
126
- console.error(StyledText.muted(error.stack || 'No stack trace available'));
125
+ console.error(StyledText.muted('Stack trace:'))
126
+ console.error(StyledText.muted(error.stack || 'No stack trace available'))
127
127
  }
128
128
 
129
- process.exit(1);
129
+ process.exit(1)
130
130
  }
131
131
  }
132
132
 
@@ -134,37 +134,37 @@ export class SecurityCommand {
134
134
  * Perform comprehensive security scan
135
135
  */
136
136
  private async performSecurityScan(options: SecurityCommandOptions): Promise<SecurityReport> {
137
- const workspacePath = options.workspace || process.cwd();
138
- const vulnerabilities: Vulnerability[] = [];
139
- const recommendations: SecurityRecommendation[] = [];
137
+ const workspacePath = options.workspace || process.cwd()
138
+ const vulnerabilities: Vulnerability[] = []
139
+ const recommendations: SecurityRecommendation[] = []
140
140
 
141
141
  // Check if package.json exists
142
- const packageJsonPath = path.join(workspacePath, 'package.json');
142
+ const packageJsonPath = path.join(workspacePath, 'package.json')
143
143
  if (!(await fs.pathExists(packageJsonPath))) {
144
- throw new Error(`No package.json found in ${workspacePath}`);
144
+ throw new Error(`No package.json found in ${workspacePath}`)
145
145
  }
146
146
 
147
147
  // Run npm audit
148
148
  if (options.audit !== false) {
149
- const npmVulns = await this.runNpmAudit(workspacePath, options);
150
- vulnerabilities.push(...npmVulns);
149
+ const npmVulns = await this.runNpmAudit(workspacePath, options)
150
+ vulnerabilities.push(...npmVulns)
151
151
  }
152
152
 
153
153
  // Run snyk scan if available
154
154
  if (options.snyk) {
155
- const snykVulns = await this.runSnykScan(workspacePath, options);
156
- vulnerabilities.push(...snykVulns);
155
+ const snykVulns = await this.runSnykScan(workspacePath, options)
156
+ vulnerabilities.push(...snykVulns)
157
157
  }
158
158
 
159
159
  // Generate recommendations
160
- recommendations.push(...this.generateRecommendations(vulnerabilities));
160
+ recommendations.push(...this.generateRecommendations(vulnerabilities))
161
161
 
162
162
  // Filter by severity if specified
163
163
  const filteredVulnerabilities = options.severity
164
164
  ? vulnerabilities.filter(
165
165
  (v) => this.severityToNumber(v.severity) >= this.severityToNumber(options.severity!)
166
166
  )
167
- : vulnerabilities;
167
+ : vulnerabilities
168
168
 
169
169
  return {
170
170
  summary: this.generateSummary(filteredVulnerabilities),
@@ -175,7 +175,7 @@ export class SecurityCommand {
175
175
  scanTools: ['npm-audit', ...(options.snyk ? ['snyk'] : [])],
176
176
  workspacePath: workspacePath,
177
177
  },
178
- };
178
+ }
179
179
  }
180
180
 
181
181
  /**
@@ -185,39 +185,39 @@ export class SecurityCommand {
185
185
  workspacePath: string,
186
186
  options: SecurityCommandOptions
187
187
  ): Promise<Vulnerability[]> {
188
- const auditArgs = ['audit', '--json'];
188
+ const auditArgs = ['audit', '--json']
189
189
 
190
190
  if (!options.includeDev) {
191
- auditArgs.push('--omit=dev');
191
+ auditArgs.push('--omit=dev')
192
192
  }
193
193
 
194
194
  const result = spawnSync('npm', auditArgs, {
195
195
  cwd: workspacePath,
196
196
  encoding: 'utf8',
197
197
  stdio: ['pipe', 'pipe', 'pipe'],
198
- });
198
+ })
199
199
 
200
200
  if (result.error) {
201
- throw new Error(`npm audit failed: ${result.error.message}`);
201
+ throw new Error(`npm audit failed: ${result.error.message}`)
202
202
  }
203
203
 
204
204
  if (result.status === 1) {
205
205
  // npm audit returns 1 when vulnerabilities are found
206
206
  try {
207
- const auditData = JSON.parse(result.stdout);
208
- return this.parseNpmAuditResults(auditData);
207
+ const auditData = JSON.parse(result.stdout)
208
+ return this.parseNpmAuditResults(auditData)
209
209
  } catch (parseError) {
210
- throw new Error(`Failed to parse npm audit output: ${parseError}`);
210
+ throw new Error(`Failed to parse npm audit output: ${parseError}`)
211
211
  }
212
212
  } else if (result.status === 0) {
213
213
  try {
214
- const auditData = JSON.parse(result.stdout);
215
- return this.parseNpmAuditResults(auditData);
214
+ const auditData = JSON.parse(result.stdout)
215
+ return this.parseNpmAuditResults(auditData)
216
216
  } catch (parseError) {
217
- throw new Error(`Failed to parse npm audit output: ${parseError}`);
217
+ throw new Error(`Failed to parse npm audit output: ${parseError}`)
218
218
  }
219
219
  } else {
220
- throw new Error(`npm audit failed with status ${result.status}: ${result.stderr}`);
220
+ throw new Error(`npm audit failed with status ${result.status}: ${result.stderr}`)
221
221
  }
222
222
  }
223
223
 
@@ -230,39 +230,39 @@ export class SecurityCommand {
230
230
  ): Promise<Vulnerability[]> {
231
231
  try {
232
232
  // Check if snyk is installed
233
- const versionResult = spawnSync('snyk', ['--version'], { stdio: 'pipe' });
233
+ const versionResult = spawnSync('snyk', ['--version'], { stdio: 'pipe' })
234
234
  if (versionResult.error) {
235
- throw versionResult.error;
235
+ throw versionResult.error
236
236
  }
237
237
 
238
- const snykArgs = ['test', '--json'];
238
+ const snykArgs = ['test', '--json']
239
239
 
240
240
  if (!options.includeDev) {
241
- snykArgs.push('--dev');
241
+ snykArgs.push('--dev')
242
242
  }
243
243
 
244
244
  const result = spawnSync('snyk', snykArgs, {
245
245
  cwd: workspacePath,
246
246
  encoding: 'utf8',
247
247
  stdio: ['pipe', 'pipe', 'pipe'],
248
- });
248
+ })
249
249
 
250
250
  if (result.error) {
251
- throw result.error;
251
+ throw result.error
252
252
  }
253
253
 
254
254
  if (result.status !== 0 && result.status !== 1) {
255
- throw new Error(`Snyk scan failed with status ${result.status}: ${result.stderr}`);
255
+ throw new Error(`Snyk scan failed with status ${result.status}: ${result.stderr}`)
256
256
  }
257
257
 
258
- const snykData = JSON.parse(result.stdout);
259
- return this.parseSnykResults(snykData);
258
+ const snykData = JSON.parse(result.stdout)
259
+ return this.parseSnykResults(snykData)
260
260
  } catch (error: any) {
261
261
  if (error.code === 'ENOENT') {
262
- console.warn(StyledText.iconWarning('Snyk not found. Install with: npm install -g snyk'));
263
- return [];
262
+ console.warn(StyledText.iconWarning('Snyk not found. Install with: npm install -g snyk'))
263
+ return []
264
264
  }
265
- throw new Error(`Snyk scan failed: ${error.message}`);
265
+ throw new Error(`Snyk scan failed: ${error.message}`)
266
266
  }
267
267
  }
268
268
 
@@ -270,14 +270,14 @@ export class SecurityCommand {
270
270
  * Parse npm audit results
271
271
  */
272
272
  private parseNpmAuditResults(auditData: any): Vulnerability[] {
273
- const vulnerabilities: Vulnerability[] = [];
273
+ const vulnerabilities: Vulnerability[] = []
274
274
 
275
275
  if (!auditData.vulnerabilities) {
276
- return vulnerabilities;
276
+ return vulnerabilities
277
277
  }
278
278
 
279
279
  for (const [id, vuln] of Object.entries(auditData.vulnerabilities)) {
280
- const vulnerability = vuln as any;
280
+ const vulnerability = vuln as any
281
281
 
282
282
  vulnerabilities.push({
283
283
  id: id,
@@ -291,20 +291,20 @@ export class SecurityCommand {
291
291
  paths: vulnerability.via?.map((v: any) => v.source || v.name) || [vulnerability.name],
292
292
  cwe: vulnerability.cwe,
293
293
  cve: vulnerability.cve,
294
- });
294
+ })
295
295
  }
296
296
 
297
- return vulnerabilities;
297
+ return vulnerabilities
298
298
  }
299
299
 
300
300
  /**
301
301
  * Parse snyk results
302
302
  */
303
303
  private parseSnykResults(snykData: any): Vulnerability[] {
304
- const vulnerabilities: Vulnerability[] = [];
304
+ const vulnerabilities: Vulnerability[] = []
305
305
 
306
306
  if (!snykData.vulnerabilities) {
307
- return vulnerabilities;
307
+ return vulnerabilities
308
308
  }
309
309
 
310
310
  for (const vuln of snykData.vulnerabilities) {
@@ -320,35 +320,35 @@ export class SecurityCommand {
320
320
  paths: vuln.from || [vuln.packageName],
321
321
  cwe: vuln.identifiers?.CWE || [],
322
322
  cve: vuln.identifiers?.CVE || [],
323
- });
323
+ })
324
324
  }
325
325
 
326
- return vulnerabilities;
326
+ return vulnerabilities
327
327
  }
328
328
 
329
329
  /**
330
330
  * Generate security recommendations
331
331
  */
332
332
  private generateRecommendations(vulnerabilities: Vulnerability[]): SecurityRecommendation[] {
333
- const recommendations: SecurityRecommendation[] = [];
334
- const packages = new Set(vulnerabilities.map((v) => v.package));
333
+ const recommendations: SecurityRecommendation[] = []
334
+ const packages = new Set(vulnerabilities.map((v) => v.package))
335
335
 
336
336
  for (const pkg of packages) {
337
- const pkgVulns = vulnerabilities.filter((v) => v.package === pkg);
337
+ const pkgVulns = vulnerabilities.filter((v) => v.package === pkg)
338
338
  const criticalVulns = pkgVulns.filter(
339
339
  (v) => v.severity === 'critical' || v.severity === 'high'
340
- );
340
+ )
341
341
 
342
342
  if (criticalVulns.length > 0) {
343
343
  const fixVersions = [
344
344
  ...new Set(
345
345
  criticalVulns.map((v) => v.fixVersion).filter((v) => v && typeof v === 'string')
346
346
  ),
347
- ];
347
+ ]
348
348
 
349
349
  if (fixVersions.length > 0) {
350
- const currentVersion = pkgVulns[0]?.range?.split(' ')[0] || 'unknown';
351
- const recommendedVersion = fixVersions[0] || 'unknown';
350
+ const currentVersion = pkgVulns[0]?.range?.split(' ')[0] || 'unknown'
351
+ const recommendedVersion = fixVersions[0] || 'unknown'
352
352
 
353
353
  recommendations.push({
354
354
  package: pkg,
@@ -357,12 +357,12 @@ export class SecurityCommand {
357
357
  type: 'update',
358
358
  reason: `${criticalVulns.length} critical vulnerabilities found`,
359
359
  impact: 'High - Security vulnerability fix',
360
- });
360
+ })
361
361
  }
362
362
  }
363
363
  }
364
364
 
365
- return recommendations;
365
+ return recommendations
366
366
  }
367
367
 
368
368
  /**
@@ -376,33 +376,33 @@ export class SecurityCommand {
376
376
  moderate: 0,
377
377
  low: 0,
378
378
  info: 0,
379
- };
379
+ }
380
380
 
381
381
  for (const vuln of vulnerabilities) {
382
- const severity = vuln.severity as string;
382
+ const severity = vuln.severity as string
383
383
  switch (severity) {
384
384
  case 'critical':
385
- summary.critical++;
386
- break;
385
+ summary.critical++
386
+ break
387
387
  case 'high':
388
- summary.high++;
389
- break;
388
+ summary.high++
389
+ break
390
390
  case 'moderate':
391
- summary.moderate++;
392
- break;
391
+ summary.moderate++
392
+ break
393
393
  case 'low':
394
- summary.low++;
395
- break;
394
+ summary.low++
395
+ break
396
396
  case 'info':
397
- summary.info++;
398
- break;
397
+ summary.info++
398
+ break
399
399
  default:
400
- summary.info++;
401
- break;
400
+ summary.info++
401
+ break
402
402
  }
403
403
  }
404
404
 
405
- return summary;
405
+ return summary
406
406
  }
407
407
 
408
408
  /**
@@ -411,17 +411,17 @@ export class SecurityCommand {
411
411
  private severityToNumber(severity: string): number {
412
412
  switch (severity) {
413
413
  case 'critical':
414
- return 4;
414
+ return 4
415
415
  case 'high':
416
- return 3;
416
+ return 3
417
417
  case 'moderate':
418
- return 2;
418
+ return 2
419
419
  case 'low':
420
- return 1;
420
+ return 1
421
421
  case 'info':
422
- return 0;
422
+ return 0
423
423
  default:
424
- return 0;
424
+ return 0
425
425
  }
426
426
  }
427
427
 
@@ -430,21 +430,21 @@ export class SecurityCommand {
430
430
  */
431
431
  private showRecommendations(report: SecurityReport): void {
432
432
  if (report.recommendations.length === 0) {
433
- return;
433
+ return
434
434
  }
435
435
 
436
- console.log('\n' + StyledText.iconInfo('Security Recommendations:'));
436
+ console.log(`\n${StyledText.iconInfo('Security Recommendations:')}`)
437
437
 
438
438
  for (const rec of report.recommendations) {
439
439
  console.log(
440
440
  ` ${StyledText.iconWarning()} ${rec.package}: ${rec.currentVersion} → ${rec.recommendedVersion}`
441
- );
442
- console.log(` ${StyledText.muted(rec.reason)}`);
443
- console.log(` ${StyledText.muted(rec.impact)}`);
441
+ )
442
+ console.log(` ${StyledText.muted(rec.reason)}`)
443
+ console.log(` ${StyledText.muted(rec.impact)}`)
444
444
  }
445
445
 
446
- console.log('');
447
- console.log(StyledText.iconUpdate('Run with --fix-vulns to apply automatic fixes'));
446
+ console.log('')
447
+ console.log(StyledText.iconUpdate('Run with --fix-vulns to apply automatic fixes'))
448
448
  }
449
449
 
450
450
  /**
@@ -455,61 +455,61 @@ export class SecurityCommand {
455
455
  options: SecurityCommandOptions
456
456
  ): Promise<void> {
457
457
  if (report.recommendations.length === 0) {
458
- console.log(StyledText.iconSuccess('No security fixes available'));
459
- return;
458
+ console.log(StyledText.iconSuccess('No security fixes available'))
459
+ return
460
460
  }
461
461
 
462
- console.log('\n' + StyledText.iconUpdate('Applying security fixes...'));
462
+ console.log(`\n${StyledText.iconUpdate('Applying security fixes...')}`)
463
463
 
464
- const workspacePath = options.workspace || process.cwd();
465
- const fixableVulns = report.recommendations.filter((r) => r.type === 'update');
464
+ const workspacePath = options.workspace || process.cwd()
465
+ const fixableVulns = report.recommendations.filter((r) => r.type === 'update')
466
466
 
467
467
  if (fixableVulns.length === 0) {
468
- console.log(StyledText.iconInfo('No automatic fixes available'));
469
- return;
468
+ console.log(StyledText.iconInfo('No automatic fixes available'))
469
+ return
470
470
  }
471
471
 
472
472
  try {
473
473
  // Run npm audit fix
474
- const fixArgs = ['audit', 'fix'];
474
+ const fixArgs = ['audit', 'fix']
475
475
  if (!options.includeDev) {
476
- fixArgs.push('--omit=dev');
476
+ fixArgs.push('--omit=dev')
477
477
  }
478
478
 
479
479
  const result = spawnSync('npm', fixArgs, {
480
480
  cwd: workspacePath,
481
481
  encoding: 'utf8',
482
482
  stdio: 'inherit',
483
- });
483
+ })
484
484
 
485
485
  if (result.error) {
486
- throw result.error;
486
+ throw result.error
487
487
  }
488
488
 
489
489
  if (result.status !== 0) {
490
- throw new Error(`npm audit fix failed with status ${result.status}`);
490
+ throw new Error(`npm audit fix failed with status ${result.status}`)
491
491
  }
492
492
 
493
- console.log(StyledText.iconSuccess('Security fixes applied successfully'));
493
+ console.log(StyledText.iconSuccess('Security fixes applied successfully'))
494
494
 
495
495
  // Re-run scan to verify fixes
496
- console.log(StyledText.iconInfo('Re-running security scan to verify fixes...'));
497
- const newReport = await this.performSecurityScan({ ...options, fixVulns: false });
496
+ console.log(StyledText.iconInfo('Re-running security scan to verify fixes...'))
497
+ const newReport = await this.performSecurityScan({ ...options, fixVulns: false })
498
498
 
499
499
  if (newReport.summary.critical === 0 && newReport.summary.high === 0) {
500
500
  console.log(
501
501
  StyledText.iconSuccess('All critical and high severity vulnerabilities have been fixed!')
502
- );
502
+ )
503
503
  } else {
504
504
  console.log(
505
505
  StyledText.iconWarning(
506
506
  `${newReport.summary.critical} critical and ${newReport.summary.high} high severity vulnerabilities remain`
507
507
  )
508
- );
508
+ )
509
509
  }
510
510
  } catch (error: any) {
511
- console.error(StyledText.iconError('Failed to apply security fixes:'));
512
- console.error(StyledText.error(error.message));
511
+ console.error(StyledText.iconError('Failed to apply security fixes:'))
512
+ console.error(StyledText.error(error.message))
513
513
  }
514
514
  }
515
515
 
@@ -517,19 +517,19 @@ export class SecurityCommand {
517
517
  * Validate command options
518
518
  */
519
519
  static validateOptions(options: SecurityCommandOptions): string[] {
520
- const errors: string[] = [];
520
+ const errors: string[] = []
521
521
 
522
522
  // Validate format
523
523
  if (options.format && !['table', 'json', 'yaml', 'minimal'].includes(options.format)) {
524
- errors.push('Invalid format. Must be one of: table, json, yaml, minimal');
524
+ errors.push('Invalid format. Must be one of: table, json, yaml, minimal')
525
525
  }
526
526
 
527
527
  // Validate severity
528
528
  if (options.severity && !['low', 'moderate', 'high', 'critical'].includes(options.severity)) {
529
- errors.push('Invalid severity. Must be one of: low, moderate, high, critical');
529
+ errors.push('Invalid severity. Must be one of: low, moderate, high, critical')
530
530
  }
531
531
 
532
- return errors;
532
+ return errors
533
533
  }
534
534
 
535
535
  /**
@@ -564,6 +564,6 @@ Exit Codes:
564
564
  0 No vulnerabilities found
565
565
  1 Vulnerabilities found
566
566
  2 Error occurred
567
- `;
567
+ `
568
568
  }
569
569
  }