-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Nemanja Tesic
committed
Oct 15, 2024
1 parent
85643be
commit 98ae967
Showing
4 changed files
with
43 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { PackageInfos } from '../types/PackageInfo'; | ||
|
||
/** | ||
* @returns Each element is a tuple of [dependency, dependent] where `dependent` depends on `dependency`. | ||
* These are the edges of the dependency graph. | ||
*/ | ||
export function getPackageDependencyGraph(packages: string[], packageInfos: PackageInfos): [string | undefined, string][] { | ||
const packageSet = new Set(packages); | ||
const dependencyGraph: [string | undefined, string][] = []; | ||
|
||
for (const pkgName of packageSet) { | ||
const info = packageInfos[pkgName]; | ||
if (!info) { | ||
throw new Error(`Package info is missing for ${pkgName}.`); | ||
} | ||
|
||
const allDeps = new Set( | ||
[info.dependencies, info.devDependencies, info.peerDependencies, info.optionalDependencies] | ||
.flatMap(deps => Object.keys(deps || {})) | ||
.filter(pkg => packageSet.has(pkg)) | ||
); | ||
if (allDeps.size) { | ||
for (const depPkgName of allDeps) { | ||
dependencyGraph.push([depPkgName, pkgName]); | ||
} | ||
} else { | ||
dependencyGraph.push([undefined, pkgName]); | ||
} | ||
} | ||
|
||
return dependencyGraph; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,24 @@ | ||
import { createPackageGraph, PackageDependency, PackageGraph } from 'workspace-tools'; | ||
import { PackageInfo, PackageInfos } from '../types/PackageInfo'; | ||
import pGraph, { DependencyList, PGraphNodeMap } from 'p-graph'; | ||
import pGraph, { PGraphNodeMap } from 'p-graph'; | ||
import { getPackageDependencyGraph } from './getPackageDependencyGraph'; | ||
|
||
export function getPackageGraph( | ||
affectedPackages: Iterable<string>, | ||
packageInfos: PackageInfos, | ||
runHook: (packageInfo: PackageInfo) => Promise<void> | ||
) { | ||
const packageGraph: PackageGraph = createPackageGraphInternal(packageInfos, Array.from(affectedPackages)); | ||
|
||
const nodeMap: PGraphNodeMap = new Map(); | ||
for (const packageToBump of affectedPackages) { | ||
nodeMap.set(packageToBump, { | ||
run: async () => await runHook(packageInfos[packageToBump]), | ||
}); | ||
} | ||
|
||
return pGraph(nodeMap, createDependencyList(packageGraph.dependencies)); | ||
} | ||
|
||
function createDependencyList(dependencies: PackageDependency[]): DependencyList { | ||
return dependencies.map(dependency => [dependency.dependency, dependency.name]); | ||
const dependencyGraph: [string | undefined, string][] = getPackageDependencyGraph(Array.from(affectedPackages), packageInfos); | ||
const filteredDependencyGraph = filterDependencyGraph(dependencyGraph); | ||
return pGraph(nodeMap, filteredDependencyGraph); | ||
} | ||
|
||
/** | ||
* @returns A package graph that only contains the affected packages and their dependencies. This is done by filtering the | ||
* original package graph, which could contain more packages than the affected packages. This can happen if some scope is | ||
* provided to the command which filters some package. | ||
*/ | ||
function createPackageGraphInternal(packageInfos: PackageInfos, affectedPackages: string[]): PackageGraph { | ||
const packageGraph: PackageGraph = createPackageGraph(packageInfos, { | ||
namePatterns: affectedPackages, | ||
includeDependents: true, | ||
includeDependencies: true, | ||
withDevDependencies: true, | ||
withPeerDependencies: true, | ||
}); | ||
|
||
const filteredGraph: PackageGraph = { | ||
packages: packageGraph.packages.filter(pkg => affectedPackages.includes(pkg)), | ||
dependencies: packageGraph.dependencies.filter(dep => affectedPackages.includes(dep.name) && affectedPackages.includes(dep.dependency)), | ||
}; | ||
|
||
if (filteredGraph.packages.length !== affectedPackages.length) { | ||
throw new Error(`Failed to create the package graph. Affected packages size (${affectedPackages.length}) is different from the created graph size (${filteredGraph.packages.length}). Affected packages: ${affectedPackages.join(', ')}, created graph packages: ${filteredGraph.packages.join(', ')}`); | ||
} | ||
|
||
return filteredGraph; | ||
} | ||
function filterDependencyGraph(dependencyGraph: [string | undefined, string][]): [string, string][] { | ||
return dependencyGraph.filter(([dep, _]) => dep !== undefined) as [string, string][]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters