1ffe4ee79STomasz Sapetaimport { DefaultDependencyKind, DependencyKind, Package } from '../Packages'; 2ffe4ee79STomasz Sapetaimport PackagesGraphEdge from './PackagesGraphEdge'; 3ffe4ee79STomasz Sapeta 4ffe4ee79STomasz Sapeta/** 5ffe4ee79STomasz Sapeta * A graph node that refers to the single package. 6ffe4ee79STomasz Sapeta */ 7ffe4ee79STomasz Sapetaexport default class PackagesGraphNode { 8ffe4ee79STomasz Sapeta /** 9ffe4ee79STomasz Sapeta * The package represented by the node. 10ffe4ee79STomasz Sapeta */ 11ffe4ee79STomasz Sapeta pkg: Package; 12ffe4ee79STomasz Sapeta 13ffe4ee79STomasz Sapeta /** 14ffe4ee79STomasz Sapeta * The package name. 15ffe4ee79STomasz Sapeta */ 16ffe4ee79STomasz Sapeta name: string; 17ffe4ee79STomasz Sapeta 18ffe4ee79STomasz Sapeta /** 19ffe4ee79STomasz Sapeta * Indicates how deep the node is placed in the graph. 20ffe4ee79STomasz Sapeta * Depth of nodes without incoming edges is equal to `0`. 21ffe4ee79STomasz Sapeta */ 22ffe4ee79STomasz Sapeta depth: number = 0; 23ffe4ee79STomasz Sapeta 24ffe4ee79STomasz Sapeta /** 25ffe4ee79STomasz Sapeta * Edges connecting this node with its dependencies. 26ffe4ee79STomasz Sapeta */ 27ffe4ee79STomasz Sapeta outgoingEdges: PackagesGraphEdge[] = []; 28ffe4ee79STomasz Sapeta 29ffe4ee79STomasz Sapeta /** 30ffe4ee79STomasz Sapeta * Edges connecting this node with its dependents. 31ffe4ee79STomasz Sapeta */ 32ffe4ee79STomasz Sapeta incomingEdges: PackagesGraphEdge[] = []; 33ffe4ee79STomasz Sapeta 34ffe4ee79STomasz Sapeta constructor(pkg: Package) { 35ffe4ee79STomasz Sapeta this.pkg = pkg; 36ffe4ee79STomasz Sapeta this.name = pkg.packageName; 37ffe4ee79STomasz Sapeta } 38ffe4ee79STomasz Sapeta 39ffe4ee79STomasz Sapeta getOutgoingEdgeForNode(node: PackagesGraphNode): PackagesGraphEdge | null { 40ffe4ee79STomasz Sapeta return this.outgoingEdges.find((edge) => edge.destination === node) ?? null; 41ffe4ee79STomasz Sapeta } 42ffe4ee79STomasz Sapeta 43ffe4ee79STomasz Sapeta getIncomingEdgeForNode(node: PackagesGraphNode): PackagesGraphEdge | null { 44ffe4ee79STomasz Sapeta return this.incomingEdges.find((edge) => edge.origin === node) ?? null; 45ffe4ee79STomasz Sapeta } 46ffe4ee79STomasz Sapeta 47ffe4ee79STomasz Sapeta getAllDependentEdges(kinds: DependencyKind[] = DefaultDependencyKind): PackagesGraphEdge[] { 48ffe4ee79STomasz Sapeta const allDependentEdges = this.incomingEdges 49ffe4ee79STomasz Sapeta .map((edge) => { 50ffe4ee79STomasz Sapeta if (!edge.isCyclic && kinds.includes(edge.getDominantKind())) { 51ffe4ee79STomasz Sapeta return [edge, ...edge.origin.getAllDependentEdges(kinds)]; 52ffe4ee79STomasz Sapeta } 53ffe4ee79STomasz Sapeta return []; 54ffe4ee79STomasz Sapeta }) 55ffe4ee79STomasz Sapeta .flat(); 56ffe4ee79STomasz Sapeta 57ffe4ee79STomasz Sapeta return [...new Set(allDependentEdges)]; 58ffe4ee79STomasz Sapeta } 59ffe4ee79STomasz Sapeta 60ffe4ee79STomasz Sapeta getAllDependents(kinds: DependencyKind[] = DefaultDependencyKind): PackagesGraphNode[] { 61ffe4ee79STomasz Sapeta return [...new Set(this.getAllDependentEdges(kinds).map((edge) => edge.origin))]; 62ffe4ee79STomasz Sapeta } 63ffe4ee79STomasz Sapeta 64*5dab530bSTomasz Sapeta getAllDependencyEdges(kinds: DependencyKind[] = DefaultDependencyKind): PackagesGraphEdge[] { 65*5dab530bSTomasz Sapeta const allDependencyEdges = this.outgoingEdges 66*5dab530bSTomasz Sapeta .map((edge) => { 67*5dab530bSTomasz Sapeta if (!edge.isCyclic && kinds.includes(edge.getDominantKind())) { 68*5dab530bSTomasz Sapeta return [edge, ...edge.destination.getAllDependencyEdges(kinds)]; 69*5dab530bSTomasz Sapeta } 70*5dab530bSTomasz Sapeta return []; 71*5dab530bSTomasz Sapeta }) 72*5dab530bSTomasz Sapeta .flat(); 73*5dab530bSTomasz Sapeta 74*5dab530bSTomasz Sapeta return [...new Set(allDependencyEdges)]; 75*5dab530bSTomasz Sapeta } 76*5dab530bSTomasz Sapeta 77*5dab530bSTomasz Sapeta getAllDependencies(kinds: DependencyKind[] = DefaultDependencyKind): PackagesGraphNode[] { 78*5dab530bSTomasz Sapeta return [...new Set(this.getAllDependencyEdges(kinds).map((edge) => edge.destination))]; 79*5dab530bSTomasz Sapeta } 80*5dab530bSTomasz Sapeta 81ffe4ee79STomasz Sapeta getOutgoingEdgesOfKinds(kinds: DependencyKind[]): PackagesGraphEdge[] { 82ffe4ee79STomasz Sapeta return this.outgoingEdges.filter((edge) => { 83ffe4ee79STomasz Sapeta return kinds.some((kind) => edge.isOfKind(kind)); 84ffe4ee79STomasz Sapeta }); 85ffe4ee79STomasz Sapeta } 86ffe4ee79STomasz Sapeta 87ffe4ee79STomasz Sapeta isDependentOf(node: PackagesGraphNode): boolean { 88ffe4ee79STomasz Sapeta return !!this.getOutgoingEdgeForNode(node); 89ffe4ee79STomasz Sapeta } 90ffe4ee79STomasz Sapeta 91ffe4ee79STomasz Sapeta isDependencyOf(node: PackagesGraphNode): boolean { 92ffe4ee79STomasz Sapeta return !!this.getIncomingEdgeForNode(node); 93ffe4ee79STomasz Sapeta } 94ffe4ee79STomasz Sapeta} 95