chore: add yarn-lock-diff helper
This commit is contained in:
parent
594718c542
commit
6892345e24
1 changed files with 105 additions and 0 deletions
105
scripts/yarn-lock-diff.mjs
Normal file
105
scripts/yarn-lock-diff.mjs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import { exec } from 'child_process';
|
||||
import fs from 'fs';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import lockfile from '@yarnpkg/lockfile';
|
||||
|
||||
/**
|
||||
* === Generic Helpers ===
|
||||
*/
|
||||
|
||||
const execPromise = cmd =>
|
||||
new Promise(resolve => exec(cmd, { maxBuffer: 200000000 }, (err, stdout) => resolve(stdout)));
|
||||
|
||||
const arrDiff = (arrA, arrB, eq = (a, b) => a === b) =>
|
||||
arrA.filter(a => arrB.every(b => !eq(a, b)));
|
||||
|
||||
/**
|
||||
* === yarn-lock-diff ===
|
||||
*/
|
||||
|
||||
function groupByPackageName(obj) {
|
||||
const packages = [];
|
||||
Object.keys(obj.object).forEach(key => {
|
||||
const names = key.split('@');
|
||||
let name = names[0];
|
||||
if (name === '') {
|
||||
// handle scoped packages
|
||||
name = `@${names[1]}`;
|
||||
}
|
||||
const { version } = obj.object[key];
|
||||
const found = packages.find(p => p.name === name);
|
||||
if (found) {
|
||||
found.versions.push(version);
|
||||
} else {
|
||||
packages.push({
|
||||
name,
|
||||
versions: [version],
|
||||
});
|
||||
}
|
||||
});
|
||||
return packages;
|
||||
}
|
||||
|
||||
function yarnLockDiff(prevLockContents, curLockContents) {
|
||||
const previous = lockfile.parse(prevLockContents);
|
||||
const current = lockfile.parse(curLockContents);
|
||||
|
||||
const previousPackages = groupByPackageName(previous);
|
||||
const currentPackages = groupByPackageName(current);
|
||||
|
||||
const removedResult = [];
|
||||
const changedResult = [];
|
||||
|
||||
previousPackages.forEach(prevPkg => {
|
||||
const foundCurPkg = currentPackages.find(curPkg => curPkg.name === prevPkg.name);
|
||||
if (!foundCurPkg) {
|
||||
removedResult.push(prevPkg);
|
||||
} else {
|
||||
const diff = arrDiff(foundCurPkg.versions, prevPkg.versions);
|
||||
if (diff.length) {
|
||||
changedResult.push({
|
||||
name: prevPkg.name,
|
||||
previousVersions: Array.from(new Set(prevPkg.versions)),
|
||||
currentVersions: Array.from(new Set(foundCurPkg.versions)),
|
||||
diff,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return { removed: removedResult, changed: changedResult };
|
||||
}
|
||||
|
||||
/**
|
||||
* === cli ===
|
||||
*/
|
||||
|
||||
function getArgs() {
|
||||
const idx = process.argv.findIndex(a => a === '--versions-back');
|
||||
let versionsBack;
|
||||
if (idx > 0) {
|
||||
versionsBack = Number(process.argv[idx + 1]);
|
||||
if (Number.isNaN(versionsBack)) {
|
||||
throw new Error('Please provide a number for --versions-back');
|
||||
}
|
||||
} else {
|
||||
versionsBack = 1;
|
||||
}
|
||||
return { versionsBack };
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { versionsBack } = getArgs();
|
||||
const changeHistory = await execPromise(`git log yarn.lock`);
|
||||
const commits = changeHistory
|
||||
.match(/commit (.*)\n/g)
|
||||
.map(c => c.replace('commit ', '').replace('\n', ''));
|
||||
|
||||
// For now, we pick latest commit. When needed in the future, allow '--age 2-months' or smth
|
||||
const prevLockContents = await execPromise(`git show ${commits[versionsBack - 1]}:yarn.lock`);
|
||||
const curLockContents = await fs.promises.readFile('yarn.lock', 'utf8');
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(JSON.stringify(yarnLockDiff(prevLockContents, curLockContents), null, 2));
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Reference in a new issue