workspace-tools
Version:
A collection of tools that are useful in a git-controlled monorepo that is managed by one of these software:
106 lines (105 loc) • 3.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const graphCache = new Map();
function memoizedKey(packages, scope = []) {
return JSON.stringify({ packages, scope });
}
function getPackageGraph(packages, scope = []) {
const key = memoizedKey(packages, scope);
if (graphCache.has(key)) {
return graphCache.get(key);
}
const edges = [];
const visited = new Set();
const stack = scope.length > 0 ? [...scope] : Object.keys(packages);
while (stack.length > 0) {
const pkg = stack.pop();
if (visited.has(pkg)) {
continue;
}
visited.add(pkg);
const info = packages[pkg];
const deps = getInternalDeps(info, packages);
if (deps.length > 0) {
for (const dep of deps) {
stack.push(dep);
edges.push([dep, pkg]);
}
}
else {
edges.push([null, pkg]);
}
}
graphCache.set(key, edges);
return edges;
}
function getDependentMap(packages) {
const graph = getPackageGraph(packages);
const map = new Map();
for (const [from, to] of graph) {
if (!map.has(to)) {
map.set(to, new Set());
}
if (from) {
map.get(to).add(from);
}
}
return map;
}
exports.getDependentMap = getDependentMap;
/**
* for a package graph of a->b->c (where b depends on a), transitive consumers of a are b & c and their consumers (or what are the consequences of a)
* @param targets
* @param packages
* @param scope
*/
function getTransitiveConsumers(targets, packages, scope = []) {
const graph = getPackageGraph(packages, scope);
const pkgQueue = [...targets];
const visited = new Set();
while (pkgQueue.length > 0) {
const pkg = pkgQueue.shift();
if (!visited.has(pkg)) {
visited.add(pkg);
for (const [from, to] of graph) {
if (from === pkg) {
pkgQueue.push(to);
}
}
}
}
return [...visited].filter((pkg) => !targets.includes(pkg));
}
exports.getTransitiveConsumers = getTransitiveConsumers;
/**
* for a package graph of a->b->c (where b depends on a), transitive providers of c are a & b and their providers (or what is needed to satisfy c)
* @param targets
* @param packages
*/
function getTransitiveProviders(targets, packages) {
const graph = getPackageGraph(packages);
const pkgQueue = [...targets];
const visited = new Set();
while (pkgQueue.length > 0) {
const pkg = pkgQueue.shift();
if (!visited.has(pkg)) {
visited.add(pkg);
for (const [from, to] of graph) {
if (to === pkg && from) {
pkgQueue.push(from);
}
}
}
}
return [...visited].filter((pkg) => !targets.includes(pkg));
}
exports.getTransitiveProviders = getTransitiveProviders;
// package dependencies = getting transitive providers
exports.getTransitiveDependencies = getTransitiveProviders;
// package dependents = getting transitive consumers
exports.getTransitiveDependents = getTransitiveConsumers;
function getInternalDeps(info, packages) {
const deps = Object.keys(Object.assign(Object.assign({}, info.dependencies), info.devDependencies));
return Object.keys(packages).filter((pkg) => deps.includes(pkg));
}
exports.getInternalDeps = getInternalDeps;