/
buildSequence.ts
63 lines (59 loc) · 2 KB
/
buildSequence.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { PackageManifest } from '@pnpm/types'
import graphSequencer from 'graph-sequencer'
import filter from 'ramda/src/filter'
export interface DependenciesGraphNode {
children: {[alias: string]: string}
depPath: string
dir: string
fetchingBundledManifest?: () => Promise<PackageManifest | undefined>
filesIndexFile: string
hasBin: boolean
hasBundledDependencies: boolean
installable?: boolean
isBuilt?: boolean
optional: boolean
optionalDependencies: Set<string>
requiresBuild?: boolean
}
export interface DependenciesGraph {
[depPath: string]: DependenciesGraphNode
}
export default function buildSequence (
depGraph: Record<string, Pick<DependenciesGraphNode, 'children' | 'requiresBuild'>>,
rootDepPaths: string[]
) {
const nodesToBuild = new Set<string>()
getSubgraphToBuild(depGraph, rootDepPaths, nodesToBuild, new Set<string>())
const onlyFromBuildGraph = filter((depPath: string) => nodesToBuild.has(depPath))
const nodesToBuildArray = Array.from(nodesToBuild)
const graph = new Map(
nodesToBuildArray
.map((depPath) => [depPath, onlyFromBuildGraph(Object.values(depGraph[depPath].children))])
)
const graphSequencerResult = graphSequencer({
graph,
groups: [nodesToBuildArray],
})
const chunks = graphSequencerResult.chunks as string[][]
return chunks
}
function getSubgraphToBuild (
graph: Record<string, Pick<DependenciesGraphNode, 'children' | 'requiresBuild'>>,
entryNodes: string[],
nodesToBuild: Set<string>,
walked: Set<string>
) {
let currentShouldBeBuilt = false
for (const depPath of entryNodes) {
if (!graph[depPath]) continue // packages that are already in node_modules are skipped
if (walked.has(depPath)) continue
walked.add(depPath)
const childShouldBeBuilt = getSubgraphToBuild(graph, Object.values(graph[depPath].children), nodesToBuild, walked) ||
graph[depPath].requiresBuild
if (childShouldBeBuilt) {
nodesToBuild.add(depPath)
currentShouldBeBuilt = true
}
}
return currentShouldBeBuilt
}