import fs from 'fs-extra' ; import { dirname , join , relative } from 'node:path' ; import { fileURLToPath } from 'node:url' ; import semver from 'semver' ; import synp from 'synp' ; import { TCallback } from './ifaces' ; import * as lf from './lockfile' ; import { format , getLockfileType } from './lockfile' ; import { formatFlags , getBinVersion , getNpm , getSymlinkType , getWorkspaces , getYarn , invoke , pkgDir , readJson , } from './util' ; const __dirname = dirname ( fileURLToPath ( import . meta . url ) ) ; /**
 * Resolve bins.
 */ export const resolveBins = ( { ctx , temp , flags } ) => { const yafManifest = readJson ( join ( pkgDir ( __dirname ) + '' , 'package.json' ) ) ; ctx . bins = { yarn : getYarn ( ) , npm : getNpm ( flags [ 'npm-path' ] ) , } ; ctx . versions = { node : getBinVersion ( 'node' ) , npm : getBinVersion ( ctx . bins . npm ) , yarn : getBinVersion ( ctx . bins . yarn ) , yaf : yafManifest . version , yafLatest : invoke ( ctx . bins . npm , [ 'view' , yafManifest . name , 'version' ] , temp , true , false ) as string , } ; } ; /**
 * Print runtime context digest.
 */ export const printRuntimeDigest = ( { temp , cwd , flags , bins , versions , manifest , } ) => { if ( flags . silent ) { return ; } const isMonorepo = ! ! manifest . workspaces ; if ( isMonorepo && ( semver . parse ( versions . npm as string ) ?. major as number ) < 7 ) { console . warn ( "This project looks like monorepo, so it's recommended to use `npm v7+` to process workspaces" ) ; } if ( semver . gt ( versions . yafLatest , versions . yaf ) ) { console . warn ( `yarn-audit-fix version ${ versions . yaf } is out of date. Install the latest ${ versions . yafLatest } for better results` ) ; } console . log ( JSON . stringify ( { isMonorepo , bins , versions , temp , cwd , flags , } , undefined , 2 ) . replace ( /[",:{}]/g , '' ) ) ; } ; param { TContext } cxt return { void } export const createTempAssets = ( { cwd , temp } ) => { fs . copyFileSync ( join ( cwd , 'yarn.lock' ) , join ( temp , 'yarn.lock' ) ) ; fs . copyFileSync ( join ( cwd , 'package.json' ) , join ( temp , 'package.json' ) ) ; fs . existsSync ( join ( cwd , '.npmrc' ) ) && fs . copyFileSync ( join ( cwd , '.npmrc' ) , join ( temp , '.npmrc' ) ) ; fs . existsSync ( join ( cwd , '.yarnrc' ) ) && fs . copyFileSync ( join ( cwd , '.yarnrc' ) , join ( temp , '.yarnrc' ) ) ; } ; param { TContext } cxt return { void } export const createSymlinks = ( { temp , flags , cwd , manifest } ) => { const symlinkType = getSymlinkType ( flags . symlink ) ; const workspaces = getWorkspaces ( cwd , manifest ) ; const links = [ join ( cwd , 'node_modules' ) , join ( cwd , '.yarn' ) , ... workspaces . map ( ( ws ) => dirname ( ws ) ) , ] ; links . forEach ( ( link ) => { const rel = relative ( cwd , link ) ; const from = join ( cwd , rel ) ; const to = join ( temp , rel ) ; fs . existsSync ( from ) && fs . createSymlinkSync ( from , to , symlinkType ) ; } ) ; } ; param { TContext } cxt return { void } export const yarnLockToPkgLock = ( { temp , flags } ) => { const pgkLockJsonData = synp . yarnToNpm ( temp , true ) ; fs . writeFileSync ( join ( temp , 'package-lock.json' ) , pgkLockJsonData ) ; if ( flags . flow !== 'patch' ) { fs . removeSync ( join ( temp , 'yarn.lock' ) ) ; } } ; param { TContext } cxt return { void } export const npmAuditFix = ( { temp , flags , bins } ) => { const defaultFlags = { 'package-lock-only' : true , } ; const auditFlags = formatFlags ( { ... defaultFlags , ... flags } , 'audit-level' , 'dry-run' , 'force' , 'loglevel' , 'legacy-peer-deps' , 'only' , 'package-lock-only' , 'registry' , 'silent' , 'verbose' ) ; const auditArgs = [ 'audit' , 'fix' , ... auditFlags , '--prefix' , temp ] ; invoke ( bins . npm , auditArgs , temp , flags . silent ) ; } ; param { TContext } cxt return { void } export const yarnImport = ( { temp } ) => { const yarnLockData = synp . npmToYarn ( temp , true ) ; fs . writeFileSync ( join ( temp , 'yarn.lock' ) , yarnLockData ) ; } ; export const syncLockfile = ( { temp , flags } ) => { if ( flags . dryRun ) { return ; } fs . copyFileSync ( join ( temp , 'yarn.lock' ) , 'yarn.lock' ) ; } ; param { TContext } cxt return { void } export const yarnInstall = ( { cwd , flags , versions , bins } ) => { if ( flags . dryRun ) { return ; } semver . gte ( versions . yarn , '2.0.0' ) ? invoke ( bins . yarn , [ 'install' , '--mode=update-lockfile' ] , cwd , flags . silent ) : invoke ( bins . yarn , [ 'install' , '--update-checksums' , ... formatFlags ( flags , 'verbose' , 'silent' , 'registry' , 'ignore-engines' ) , ] , cwd , flags . silent ) ; } ; param { TContext } cxt return { void } export const clear = ( { temp } ) => fs . emptyDirSync ( temp ) ; param { TContext } cxt return { void } export const exit = ( { flags , err } ) => { ! flags . silent && console . error ( err ) ; process . exitCode = err ?. status | 0 || 1 ; } ; export const patchLockfile = ( { temp , ctx } ) => { const lockfilePath = join ( temp , 'yarn.lock' ) ; const raw = fs . readFileSync ( lockfilePath , 'utf-8' ) ; const lockfileType = getLockfileType ( raw ) ; const lockfile = lf . parse ( raw , lockfileType ) ; const report = lf . audit ( ctx , lockfileType ) ; const patched = lf . patch ( lockfile , report , ctx , lockfileType ) ; fs . writeFileSync ( lockfilePath , format ( patched , lockfileType ) ) ; } ; param { TContext } cxt return { void } export const verify = ( { cwd , versions , flags } ) => { const required = [ 'yarn.lock' , 'package.json' ] ; if ( flags . flow === 'convert' || semver . lt ( versions . yarn , '2.0.0' ) ) { required . push ( 'node_modules' ) ; } required . forEach ( ( resource ) => { if ( ! fs . existsSync ( join ( cwd , resource ) ) ) { throw new Error ( `not found: ${ resource }` ) ; } } ) ; } ;