UNPKG

yarn-audit-fix

Version:
142 lines (126 loc) 3.17 kB
import { TAuditReport, TFlags, TLockfileEntry, TLockfileObject, } from '../ifaces' import { addHiddenProp, formatFlags, formatYaml, invoke, mapFlags, parseYaml, sortObject } from '../util' export const parse = (raw: string): TLockfileObject => { const data = parseYaml(raw) const {__metadata} = data delete data.__metadata return Object.entries(data).reduce<Record<string, any>>( (m, [key, value]: [string, any]) => { key.split(', ').forEach((k) => { m[k] = value }) return m }, addHiddenProp({}, '__metadata', __metadata), ) } export const patchEntry = ( entry: TLockfileEntry, name: string, newVersion: string, npmBin: string, ): TLockfileEntry => { entry.version = newVersion entry.resolution = `${name}@npm:${newVersion}` // NOTE seems like deps are not updated by `yarn mode='--update-lockfile'`, only checksums entry.dependencies = sortObject(JSON.parse( invoke( npmBin, ['view', `${name}@${newVersion}`, 'dependencies', '--json'], process.cwd(), true, false, ) || 'null', ) || undefined) delete entry.checksum return entry } export const format = (lockfile: TLockfileObject): string => { const keymap = Object.entries(lockfile).reduce<Record<string, any>>( (m, [k, { resolution }]) => { const entry = m[resolution] || (m[resolution] = []) entry.push(k) return m }, {}, ) const data = Object.values(lockfile).reduce<Record<string, any>>( (m, value) => { const key = keymap[value.resolution].join(', ') m[key] = value return m }, { __metadata: lockfile.__metadata || { version: 5, cacheKey: 8, }, }, ) return `# This file is generated by running "yarn install" inside your project. # Manual changes might be lost - proceed with caution! ${formatYaml(data, { quotingType: '"', flowLevel: -1, lineWidth: -1, }) .replace(/\n([^\s"].+):\n/g, '\n"$1":\n') .replace(/\n(\S)/g, '\n\n$1') .replace(/resolution: ([^\n"]+)/g, 'resolution: "$1"')}` } export const audit = ( flags: TFlags, temp: string, bins: Record<string, string>, ): TAuditReport => { const mapping = { 'audit-level': 'severity', level: 'severity', groups: { key: 'environment', values: { dependencies: 'production', }, }, only: { key: 'environment', values: { prod: 'production', }, }, } const _flags = formatFlags( mapFlags(flags, mapping), 'exclude', 'ignore', 'groups', 'verbose', ) const report = invoke( bins.yarn, ['npm', 'audit', '--all', '--json', '--recursive', ..._flags], temp, !!flags.silent, false, false, ) return parseAuditReport(report) } export const parseAuditReport = (data: string): TAuditReport => Object.values(JSON.parse(data).advisories).reduce<TAuditReport>( (m, { vulnerable_versions, module_name, patched_versions }: any) => { m[module_name] = { patched_versions, vulnerable_versions, module_name, } return m }, {}, )