Skip to content

Instantly share code, notes, and snippets.

@christianscott
Created July 1, 2021 08:13
Show Gist options
  • Save christianscott/ef1ea69262594bf9c6b31857c4a54845 to your computer and use it in GitHub Desktop.
Save christianscott/ef1ea69262594bf9c6b31857c4a54845 to your computer and use it in GitHub Desktop.
Count package versions across a JS monorepo
fd '**/package.json' | node count_versions_in_monorepo.js
const { strict: assert } = require('assert');
const fs = require('fs');
const readline = require('readline');
const depFields = ['dependencies', 'devDependencies', 'peerDependencies'];
function getAllDepVersions(pkgJsonObj) {
const allDepVersions = [];
}
async function main() {
const lines = await readLinesFromStdin();
const pkgVersions = new Map();
for (const line of lines) {
assert(
line.endsWith('package.json'),
`expected a path to a package.json file, got ${line}`,
);
const pkgJsonObj = maybeReadJson(line);
if (pkgJsonObj == null) {
console.error(`skipping ${line}`);
continue;
}
for (const depField of depFields) {
if (!(depField in pkgJsonObj)) continue;
for (const [name, version] of Object.entries(pkgJsonObj[depField])) {
if (isLocalDependency(version)) continue;
pushToKey(pkgVersions, name, version);
}
}
}
for (const [name, versions] of pkgVersions) {
const uniqVersions = unique(versions);
if (uniqVersions.length === 1) continue;
console.log(`${name}: ${uniqVersions.sort().join(', ')}`);
}
}
function isLocalDependency(version) {
return (
version.startsWith('file:')
|| version.startsWith('./')
|| version.startsWith('../')
);
}
function unique(values) {
return [...new Set(values)];
}
function pushToKey(map, key, value) {
let arr = map.get(key);
if (arr == null) {
arr = [];
map.set(key, arr);
}
arr.push(value);
}
function maybeReadJson(filepath) {
try {
return JSON.parse(fs.readFileSync(filepath, 'utf-8'));
} catch (err) {
return undefined;
}
}
function readLinesFromStdin() {
return new Promise((resolve, reject) => {
const lines = [];
const linereader = readline.createInterface({
input: process.stdin,
terminal: false,
});
linereader.on("line", (line) => lines.push(line));
linereader.on("close", () => resolve(lines));
});
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment