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