Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save drochgenius/68b08ac9b4b04324ea3a667905d8fe7b to your computer and use it in GitHub Desktop.
Save drochgenius/68b08ac9b4b04324ea3a667905d8fe7b to your computer and use it in GitHub Desktop.
Use lerna graph to build packages in topological order in parallel
/* eslint-disable @typescript-eslint/no-var-requires */
/**
* this script will list packages in topological order (dependencies before dependents)
* and execute the given command in sequence
* it will substitute any {package} found on the command by the actual package of the current cursor.
* We no longer trust lerna to build in topological order.
*/
const { exec, execSync } = require('child_process');
const colors = require('colors');
const rawCommand = process.argv[2];
const dry = process.argv[3] === '--dry';
dry && process.stdout.write(colors.yellow('Running script in dry mode'));
let _exec = !dry
? exec
: (command, callback) =>
setTimeout(() => {
process.stdout.write(colors.grey(`Dry Run... ${command}\n`)) && callback(false, '', '');
}, 200);
try {
process.on('beforeExit', () => {
console.timeEnd(module.filename);
});
console.time(module.filename);
const buffer = execSync(`npx lerna list --graph -a`);
const unformattedGraph = JSON.parse(buffer.toString());
let graph = Object.keys(unformattedGraph).map((name) => ({
name,
dependencies: unformattedGraph[name].filter((dep) => Object.keys(unformattedGraph).includes(dep)),
}));
const processedList = [];
function processed(name) {
processedList.push(name);
process.stdout.write(colors.grey(`-> done with #${processedList.length} - `));
console.timeEnd(name);
}
function recursiveTreeProcessing(graph, node) {
if (node && !node['dependencies'].length) {
graph.splice(graph.indexOf(node), 1);
const name = node['name'];
const command = rawCommand.replace('{package}', name);
process.stdout.write(colors.green(`running ${command}\n`));
console.time(name);
_exec(command, (error, stdout, stderr) => {
if (error) {
process.stdout.write(stdout);
process.stderr.write(colors.red(`error with ${name}\n\n${stderr}`));
process.exit(1);
}
processed(name);
const parentNodes = graph.filter((n) => n && n['dependencies'].includes(name));
for (let parentNode of parentNodes) {
if (!parentNode) {
continue;
}
parentNode['dependencies'].splice(parentNode['dependencies'].indexOf(name), 1);
recursiveTreeProcessing(graph, parentNode);
}
});
}
}
for (let i = graph.length - 1; i >= 0; i--) {
recursiveTreeProcessing(graph, graph[i]);
}
} catch (error) {
console.error(error);
process.exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment