jazelle/utils/report-mismatched-top-level-deps.js (71 lines of code) (raw):

// @flow const {check: checkDeps} = require('./lockfile.js'); /*:: import type {VersionPolicy, ExceptionMetadata} from './get-manifest.js'; export type ReportMismatchedTopLevelDepsArgs = { root: string, projects: Array<string>, versionPolicy: VersionPolicy | void, } export type ReportMismatchedTopLevelDeps = (ReportMismatchedTopLevelDepsArgs) => Promise<Report>; export type Report = { valid: boolean, policy: VersionPolicy, reported: DependencyReport, }; export type DependencyReport = { [string]: { [string]: Array<string>, }, }; */ const reportMismatchedTopLevelDeps /*: ReportMismatchedTopLevelDeps */ = async ({ root, projects, versionPolicy, }) => { const reported = await checkDeps({roots: projects.map(p => `${root}/${p}`)}); if (!versionPolicy) { return { valid: true, policy: { lockstep: false, exceptions: [], }, reported, }; } const policy = { lockstep: !!versionPolicy.lockstep, exceptions: versionPolicy.exceptions || [], }; let reportedFilter = Object.keys(reported) .filter((dep /*: string */) => policy.lockstep ? !policy.exceptions.includes(dep) : policy.exceptions.filter( // $FlowFixMe exception => exception === dep || exception.name === dep ).length > 0 ) .reduce((obj, dep /*: string */) => { const meta /*: ExceptionMetadata */ = (policy.exceptions /*: any */) .filter(meta => meta.name === dep)[0]; if (!meta) { // for blanket exemptions, include all reportedly mismatched versions obj[dep] = reported[dep]; } else { // otherwise, keep only versions that are not specifically exempt in the version policy for (let version of Object.keys(reported[dep])) { if (!meta.versions.includes(version)) { if (!obj[dep]) obj[dep] = {}; obj[dep][version] = reported[dep][version]; } } } return obj; }, {}); const valid = Object.keys(reportedFilter).length === 0; return {valid, policy, reported: reportedFilter}; }; /*:: export type GetErrorMessage = (Report, boolean) => string; */ const getErrorMessage /*: GetErrorMessage */ = (result, json = false) => { if (!result.valid) { const policy = result.policy; const exceptions = Object.keys(result.reported).filter(dep => policy.exceptions.includes(dep) ); const message = `Version policy violation. Use \`jazelle upgrade\` to ensure all projects use the same dependency version`; const positiveSpecifier = policy.exceptions.length > 0 ? ` for deps other than ${policy.exceptions .map(exception => exception.name || exception) .join(', ')}` : ''; const negativeSpecifier = exceptions.length > 0 ? ` for ${exceptions.join(', ')}` : ''; const modifier = policy.lockstep ? positiveSpecifier : negativeSpecifier; const report = JSON.stringify(result.reported, null, 2); const violations = `\nViolations:\n${report}`; return json ? report : message + modifier + violations; } else { return json ? '{}' : ''; } }; module.exports = {reportMismatchedTopLevelDeps, getErrorMessage};