UNPKG

workspace-tools

Version:

A collection of utilities that are useful in a git-controlled monorepo managed by one of these tools:

115 lines 4.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createPackageGraph = void 0; const createDependencyMap_1 = require("./createDependencyMap"); const micromatch_1 = __importDefault(require("micromatch")); function createPackageGraph(packages, filters) { /** Set of packages being accumulated as the graph is filtered */ const packageSet = new Set(); /** Array of package names & its dependencies being accumulated as the graph is filtered */ const edges = []; const edgeKeys = new Set(); const dependencyMapCache = new Map(); function visitorForFilter(filter, pkg, dependencies, dependents) { packageSet.add(pkg); if (!filter || (filter.includeDependencies && dependencies)) { for (const dep of dependencies) { const key = edgeKey(pkg, dep); if (!edgeKeys.has(key)) { edgeKeys.add(key); edges.push({ name: pkg, dependency: dep }); } packageSet.add(dep); } } if (!filter || (filter.includeDependents && dependents)) { for (const dep of dependents) { const key = edgeKey(dep, pkg); if (!edgeKeys.has(key)) { edgeKeys.add(key); edges.push({ name: dep, dependency: pkg }); } packageSet.add(dep); } } } if (filters) { filters = Array.isArray(filters) ? filters : [filters]; for (const filter of filters) { const visitor = visitorForFilter.bind(undefined, filter); const dependencyMap = getDependencyMapForFilter(packages, filter); visitPackageGraph(packages, dependencyMap, visitor, filter); } } else { const visitor = visitorForFilter.bind(undefined, undefined); const dependencyMap = getDependencyMapForFilter(packages); visitPackageGraph(packages, dependencyMap, visitor); } return { packages: [...packageSet], dependencies: edges }; /** Calculates a key for checking if an edge is already added */ function edgeKey(name, dependency) { return `${name}->${dependency}`; } /** Gets the dependencyMap for a filter, using a cache based on filter options */ function getDependencyMapForFilter(packages, filter) { const cacheKey = getCacheKeyForFilter(filter); if (!dependencyMapCache.has(cacheKey)) { const dependencyMap = (0, createDependencyMap_1.createDependencyMap)(packages, filter); dependencyMapCache.set(cacheKey, dependencyMap); } return dependencyMapCache.get(cacheKey); } /** Generates a cache key based on the filter options */ function getCacheKeyForFilter(filter) { if (!filter) { return "default"; } const options = [ filter.withDevDependencies ? "dev" : "", filter.withPeerDependencies ? "peer" : "", filter.withOptionalDependencies ? "optional" : "", ] .filter(Boolean) .join("_"); return options || "prod"; } } exports.createPackageGraph = createPackageGraph; function visitPackageGraph(packages, dependencyMap, visitor, filter) { const visited = new Set(); const packageNames = Object.keys(packages); const stack = filter ? (0, micromatch_1.default)(packageNames, filter.namePatterns) : packageNames; while (stack.length > 0) { const pkg = stack.pop(); if (visited.has(pkg)) { continue; } const nextPkgs = new Set(); let dependencies = []; let dependents = []; if (!filter || filter.includeDependencies) { dependencies = [...(dependencyMap.dependencies.get(pkg) ?? [])]; for (const dep of dependencies) { nextPkgs.add(dep); } } if (!filter || filter.includeDependents) { dependents = [...(dependencyMap.dependents.get(pkg) ?? [])]; for (const dep of dependents) { nextPkgs.add(dep); } } visitor(pkg, dependencies, dependents); visited.add(pkg); if (nextPkgs.size > 0) { for (const nextPkg of nextPkgs) { stack.push(nextPkg); } } } } //# sourceMappingURL=createPackageGraph.js.map