11import { 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' ;
48import {
59 ensureDirectoryExists ,
610 executeProcess ,
711 readJsonFile ,
812} from '@code-pushup/utils' ;
913import {
1014 FinalJSPackagesPluginConfig ,
11- PackageCommand ,
15+ PackageAuditLevel ,
1216 PackageDependency ,
17+ PackageManager ,
1318 packageDependencies ,
1419} from '../config' ;
1520import { auditResultToAuditOutput } from './audit/transform' ;
@@ -18,55 +23,6 @@ import { PLUGIN_CONFIG_PATH, RUNNER_OUTPUT_PATH } from './constants';
1823import { outdatedResultToAuditOutput } from './outdated/transform' ;
1924import { NpmOutdatedResultJson } from './outdated/types' ;
2025
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-
7026export async function createRunnerConfig (
7127 scriptPath : string ,
7228 config : FinalJSPackagesPluginConfig ,
@@ -81,27 +37,64 @@ export async function createRunnerConfig(
8137 } ;
8238}
8339
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 > ,
8873) {
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 ) ;
9890}
9991
100- function createAuditFlags ( currentDep : PackageDependency ) {
101- return [
92+ function getNpmAuditOptions ( currentDep : PackageDependency ) {
93+ const flags = [
10294 `--include=${ currentDep } ` ,
10395 ...packageDependencies
10496 . filter ( dep => dep !== currentDep )
10597 . map ( dep => `--omit=${ dep } ` ) ,
10698 ] ;
99+ return [ ...flags , '--json' , '--audit-level=none' ] ;
107100}
0 commit comments