pnpm
65 строк · 2.3 Кб
1import { graphSequencer } from '@pnpm/deps.graph-sequencer'
2import { type PackageManifest, type PatchFile } from '@pnpm/types'
3import filter from 'ramda/src/filter'
4
5export interface DependenciesGraphNode {
6children: Record<string, string>
7depPath: string
8name: string
9dir: string
10fetchingBundledManifest?: () => Promise<PackageManifest | undefined>
11filesIndexFile?: string
12hasBin: boolean
13hasBundledDependencies: boolean
14installable?: boolean
15isBuilt?: boolean
16optional: boolean
17optionalDependencies: Set<string>
18// eslint-disable-next-line @typescript-eslint/no-explicit-any
19requiresBuild?: boolean | any // this is a dirty workaround added in https://github.com/pnpm/pnpm/pull/4898
20patchFile?: PatchFile
21}
22
23export interface DependenciesGraph {
24[depPath: string]: DependenciesGraphNode
25}
26
27export function buildSequence (
28depGraph: Record<string, Pick<DependenciesGraphNode, 'children' | 'requiresBuild'>>,
29rootDepPaths: string[]
30): string[][] {
31const nodesToBuild = new Set<string>()
32getSubgraphToBuild(depGraph, rootDepPaths, nodesToBuild, new Set<string>())
33const onlyFromBuildGraph = filter((depPath: string) => nodesToBuild.has(depPath))
34const nodesToBuildArray = Array.from(nodesToBuild)
35const graph = new Map(
36nodesToBuildArray
37.map((depPath) => [depPath, onlyFromBuildGraph(Object.values(depGraph[depPath].children))])
38)
39const graphSequencerResult = graphSequencer(graph, nodesToBuildArray)
40const chunks = graphSequencerResult.chunks as string[][]
41return chunks
42}
43
44function getSubgraphToBuild (
45graph: Record<string, Pick<DependenciesGraphNode, 'children' | 'requiresBuild' | 'patchFile'>>,
46entryNodes: string[],
47nodesToBuild: Set<string>,
48walked: Set<string>
49): boolean {
50let currentShouldBeBuilt = false
51for (const depPath of entryNodes) {
52const node = graph[depPath]
53if (!node) continue // packages that are already in node_modules are skipped
54if (walked.has(depPath)) continue
55walked.add(depPath)
56const childShouldBeBuilt = getSubgraphToBuild(graph, Object.values(node.children), nodesToBuild, walked) ||
57node.requiresBuild ||
58node.patchFile != null
59if (childShouldBeBuilt) {
60nodesToBuild.add(depPath)
61currentShouldBeBuilt = true
62}
63}
64return currentShouldBeBuilt
65}
66