1
1
import { writeFile } from 'node:fs/promises' ;
2
- import { dirname , join } from 'node:path' ;
3
- import type { AuditOutput , RunnerConfig } from '@code-pushup/models' ;
2
+ import { dirname } from 'node:path' ;
3
+ import type {
4
+ AuditOutput ,
5
+ IssueSeverity ,
6
+ RunnerConfig ,
7
+ } from '@code-pushup/models' ;
4
8
import {
5
9
ensureDirectoryExists ,
6
10
executeProcess ,
7
11
readJsonFile ,
8
12
} from '@code-pushup/utils' ;
9
13
import {
10
14
FinalJSPackagesPluginConfig ,
11
- PackageCommand ,
15
+ PackageAuditLevel ,
12
16
PackageDependency ,
17
+ PackageManager ,
13
18
packageDependencies ,
14
19
} from '../config' ;
15
20
import { auditResultToAuditOutput } from './audit/transform' ;
@@ -18,55 +23,6 @@ import { PLUGIN_CONFIG_PATH, RUNNER_OUTPUT_PATH } from './constants';
18
23
import { outdatedResultToAuditOutput } from './outdated/transform' ;
19
24
import { NpmOutdatedResultJson } from './outdated/types' ;
20
25
21
- export async function executeRunner ( ) : Promise < void > {
22
- const outputPath = join (
23
- process . cwd ( ) ,
24
- 'node_modules' ,
25
- '.code-pushup' ,
26
- 'js-packages' ,
27
- ) ;
28
-
29
- const { packageManager, checks, auditLevelMapping } =
30
- await readJsonFile < FinalJSPackagesPluginConfig > ( PLUGIN_CONFIG_PATH ) ;
31
-
32
- const results = await Promise . allSettled (
33
- checks . flatMap ( check =>
34
- packageDependencies . map < Promise < AuditOutput > > ( async dep => {
35
- const outputFilename = `${ packageManager } -${ check } -${ dep } .json` ;
36
-
37
- await executeProcess ( {
38
- command : 'npm' ,
39
- args : [
40
- check ,
41
- ...getCommandArgs ( check , dep , join ( outputPath , outputFilename ) ) ,
42
- ] ,
43
- alwaysResolve : true , // npm outdated returns exit code 1 when outdated dependencies are found
44
- } ) ;
45
-
46
- if ( check === 'audit' ) {
47
- const auditResult = await readJsonFile < NpmAuditResultJson > (
48
- join ( outputPath , outputFilename ) ,
49
- ) ;
50
- return auditResultToAuditOutput ( auditResult , dep , auditLevelMapping ) ;
51
- } else {
52
- const outdatedResult = await readJsonFile < NpmOutdatedResultJson > (
53
- join ( outputPath , outputFilename ) ,
54
- ) ;
55
- return outdatedResultToAuditOutput ( outdatedResult , dep ) ;
56
- }
57
- } ) ,
58
- ) ,
59
- ) ;
60
- const auditOutputs = results
61
- . filter (
62
- ( x ) : x is PromiseFulfilledResult < AuditOutput > => x . status === 'fulfilled' ,
63
- )
64
- . map ( x => x . value ) ;
65
-
66
- await ensureDirectoryExists ( dirname ( RUNNER_OUTPUT_PATH ) ) ;
67
- await writeFile ( RUNNER_OUTPUT_PATH , JSON . stringify ( auditOutputs ) ) ;
68
- }
69
-
70
26
export async function createRunnerConfig (
71
27
scriptPath : string ,
72
28
config : FinalJSPackagesPluginConfig ,
@@ -81,27 +37,64 @@ export async function createRunnerConfig(
81
37
} ;
82
38
}
83
39
84
- function getCommandArgs (
85
- check : PackageCommand ,
86
- dep : PackageDependency ,
87
- outputPath : string ,
40
+ export async function executeRunner ( ) : Promise < void > {
41
+ const { packageManager, checks, auditLevelMapping } =
42
+ await readJsonFile < FinalJSPackagesPluginConfig > ( PLUGIN_CONFIG_PATH ) ;
43
+
44
+ const auditResults = checks . includes ( 'audit' )
45
+ ? await processAudit ( packageManager , auditLevelMapping )
46
+ : [ ] ;
47
+
48
+ const outdatedResults = checks . includes ( 'outdated' )
49
+ ? await processOutdated ( packageManager )
50
+ : [ ] ;
51
+ const checkResults = [ ...auditResults , ...outdatedResults ] ;
52
+
53
+ await ensureDirectoryExists ( dirname ( RUNNER_OUTPUT_PATH ) ) ;
54
+ await writeFile ( RUNNER_OUTPUT_PATH , JSON . stringify ( checkResults ) ) ;
55
+ }
56
+
57
+ async function processOutdated ( packageManager : PackageManager ) {
58
+ const { stdout } = await executeProcess ( {
59
+ command : packageManager ,
60
+ args : [ 'outdated' , '--json' , '--long' ] ,
61
+ alwaysResolve : true , // npm outdated returns exit code 1 when outdated dependencies are found
62
+ } ) ;
63
+
64
+ const outdatedResult = JSON . parse ( stdout ) as NpmOutdatedResultJson ;
65
+ return packageDependencies . map ( dep =>
66
+ outdatedResultToAuditOutput ( outdatedResult , dep ) ,
67
+ ) ;
68
+ }
69
+
70
+ async function processAudit (
71
+ packageManager : PackageManager ,
72
+ auditLevelMapping : Record < PackageAuditLevel , IssueSeverity > ,
88
73
) {
89
- return check === 'audit'
90
- ? [
91
- ...createAuditFlags ( dep ) ,
92
- '--json' ,
93
- '--audit-level=none' ,
94
- '>' ,
95
- outputPath ,
96
- ]
97
- : [ '--json' , '--long' , '>' , outputPath ] ;
74
+ const auditResults = await Promise . allSettled (
75
+ packageDependencies . map < Promise < AuditOutput > > ( async dep => {
76
+ const { stdout } = await executeProcess ( {
77
+ command : packageManager ,
78
+ args : [ 'audit' , ...getNpmAuditOptions ( dep ) ] ,
79
+ } ) ;
80
+
81
+ const auditResult = JSON . parse ( stdout ) as NpmAuditResultJson ;
82
+ return auditResultToAuditOutput ( auditResult , dep , auditLevelMapping ) ;
83
+ } ) ,
84
+ ) ;
85
+ return auditResults
86
+ . filter (
87
+ ( x ) : x is PromiseFulfilledResult < AuditOutput > => x . status === 'fulfilled' ,
88
+ )
89
+ . map ( x => x . value ) ;
98
90
}
99
91
100
- function createAuditFlags ( currentDep : PackageDependency ) {
101
- return [
92
+ function getNpmAuditOptions ( currentDep : PackageDependency ) {
93
+ const flags = [
102
94
`--include=${ currentDep } ` ,
103
95
...packageDependencies
104
96
. filter ( dep => dep !== currentDep )
105
97
. map ( dep => `--omit=${ dep } ` ) ,
106
98
] ;
99
+ return [ ...flags , '--json' , '--audit-level=none' ] ;
107
100
}
0 commit comments