1import { DependencyKind } from '../Packages';
2import PackagesGraphNode from './PackagesGraphNode';
3
4/**
5 * A graph edge that refers to the relation between two packages.
6 */
7export default class PackagesGraphEdge {
8  /**
9   * The graph node that depends on the destination node.
10   */
11  origin: PackagesGraphNode;
12
13  /**
14   * The graph node that is dependent of the origin node.
15   */
16  destination: PackagesGraphNode;
17
18  /**
19   * Version range that the origin node package requires on the destination node package.
20   */
21  versionRange: string;
22
23  /**
24   * A set of dependency kinds that connect these two nodes. Usually it's just one kind,
25   * but in theory it's possible that the package is both a dependency and dev or peer dependency.
26   */
27  kinds = new Set<DependencyKind>();
28
29  /**
30   * Determines whether the edge is part of the cycle.
31   */
32  isCyclic: boolean = false;
33
34  constructor(origin: PackagesGraphNode, destination: PackagesGraphNode, versionRange: string) {
35    this.origin = origin;
36    this.destination = destination;
37    this.versionRange = versionRange;
38  }
39
40  addKind(kind: DependencyKind) {
41    this.kinds.add(kind);
42  }
43
44  isOfKind(kind: DependencyKind): boolean {
45    return this.kinds.has(kind);
46  }
47
48  getDominantKind(): DependencyKind {
49    const kindsInImportanceOrder: DependencyKind[] = [
50      DependencyKind.Normal,
51      DependencyKind.Dev,
52      DependencyKind.Peer,
53      DependencyKind.Optional,
54    ];
55    const dominant = kindsInImportanceOrder.find((kind) => this.kinds.has(kind));
56
57    if (!dominant) {
58      throw new Error(
59        `Cannot find a dominant edge kind between ${this.origin.name} and ${this.destination.name}`
60      );
61    }
62    return dominant;
63  }
64}
65