• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

graphty-org / graphty-element / 20390753610

20 Dec 2025 06:53AM UTC coverage: 82.423% (-1.2%) from 83.666%
20390753610

push

github

apowers313
Merge branch 'master' of https://github.com/graphty-org/graphty-element

5162 of 6088 branches covered (84.79%)

Branch coverage included in aggregate %.

24775 of 30233 relevant lines covered (81.95%)

6480.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.96
/src/algorithms/utils/graphConverter.ts
1
/**
2
 * @fileoverview Utility for converting graphty-element Graph to @graphty/algorithms Graph format
3
 */
4

5
import {Graph as AlgorithmGraph} from "@graphty/algorithms";
3✔
6

7
import type {Graph} from "../../Graph";
8

9
/**
10
 * Options for graph conversion
11
 */
12
export interface GraphConverterOptions {
13
    /** Whether to treat the graph as directed (default: false for undirected) */
14
    directed?: boolean;
15
    /** Weight attribute name on edges (default: "value") */
16
    weightAttribute?: string;
17
    /** Whether to allow parallel edges (default: true to handle real-world datasets) */
18
    allowParallelEdges?: boolean;
19
    /**
20
     * Whether to add reverse edges for bidirectional traversal in undirected mode.
21
     * When true (default), creates a directed graph internally with edges in both directions.
22
     * When false, creates a truly undirected graph (required for MST algorithms).
23
     * Only applies when directed=false.
24
     */
25
    addReverseEdges?: boolean;
26
}
27

28
/**
29
 * Convert a graphty-element Graph to @graphty/algorithms Graph format
30
 *
31
 * @param g - The graphty-element Graph instance
32
 * @param options - Conversion options
33
 * @returns A new AlgorithmGraph instance
34
 */
35
export function toAlgorithmGraph(g: Graph, options: GraphConverterOptions = {}): AlgorithmGraph {
3✔
36
    const {directed = false, weightAttribute = "value", allowParallelEdges = true, addReverseEdges = true} = options;
125✔
37

38
    // Determine the actual directedness of the created graph:
39
    // - If directed=true, create a directed graph (no reverse edges needed)
40
    // - If directed=false and addReverseEdges=true (default), create a directed graph internally
41
    //   with edges in both directions for algorithms that need bidirectional traversal
42
    // - If directed=false and addReverseEdges=false, create a truly undirected graph
43
    //   (required for MST algorithms like kruskal/prim)
44
    const useDirectedInternally = directed || addReverseEdges;
125✔
45
    const graph = new AlgorithmGraph({directed: useDirectedInternally, allowParallelEdges});
125✔
46

47
    // Add all nodes
48
    for (const node of g.getDataManager().nodes.values()) {
125✔
49
        graph.addNode(node.id);
3,839✔
50
    }
3,839✔
51

52
    // Add all edges with weights
53
    for (const edge of g.getDataManager().edges.values()) {
125✔
54
        // Get weight from edge data (weightAttribute already defaults to "value")
55
        // edge.data might be undefined in mock graphs used during testing
56
        // First try edge.data[weightAttribute], then fall back to edge[weightAttribute]
57
        const edgeData = edge.data as Record<string, unknown> | undefined;
9,712✔
58
        const edgeObject = edge as unknown as Record<string, unknown>;
9,712✔
59
        let rawWeight = edgeData?.[weightAttribute];
9,712✔
60

61
        if (rawWeight === undefined) {
9,712✔
62
            rawWeight = edgeObject[weightAttribute];
8,784✔
63
        }
8,784✔
64

65
        const weight: number = typeof rawWeight === "number" ? rawWeight : 1;
9,712✔
66

67
        graph.addEdge(edge.srcId, edge.dstId, weight);
9,712✔
68

69
        // For undirected graphs with reverse edges enabled, add reverse edge as well
70
        // This ensures algorithms like bellmanFord work correctly in both directions
71
        if (!directed && addReverseEdges) {
9,712✔
72
            graph.addEdge(edge.dstId, edge.srcId, weight);
7,480✔
73
        }
7,480✔
74
    }
9,712✔
75

76
    return graph;
125✔
77
}
125✔
78

79
/**
80
 * Convert a graphty-element Graph to adjacency map format
81
 * Used by algorithms like labelPropagation and leiden that expect Map<string, Map<string, number>>
82
 *
83
 * @param g - The graphty-element Graph instance
84
 * @param options - Conversion options
85
 * @returns An adjacency map where outer map keys are node IDs, inner maps are neighbor -> weight
86
 */
87
export function toAdjacencyMap(g: Graph, options: GraphConverterOptions = {}): Map<string, Map<string, number>> {
3✔
88
    const {weightAttribute = "value"} = options;
×
89

90
    const adjacencyMap = new Map<string, Map<string, number>>();
×
91

92
    // Initialize all nodes with empty neighbor maps
93
    for (const node of g.getDataManager().nodes.values()) {
×
94
        adjacencyMap.set(String(node.id), new Map<string, number>());
×
95
    }
×
96

97
    // Add edges (both directions for undirected graph)
98
    for (const edge of g.getDataManager().edges.values()) {
×
99
        const srcId = String(edge.srcId);
×
100
        const dstId = String(edge.dstId);
×
101

102
        // Get weight from edge data
103
        const edgeData = edge.data as Record<string, unknown> | undefined;
×
104
        const edgeObject = edge as unknown as Record<string, unknown>;
×
105
        let rawWeight = edgeData?.[weightAttribute];
×
106

107
        if (rawWeight === undefined) {
×
108
            rawWeight = edgeObject[weightAttribute];
×
109
        }
×
110

111
        const weight: number = typeof rawWeight === "number" ? rawWeight : 1;
×
112

113
        // Add edge in both directions (undirected)
114
        adjacencyMap.get(srcId)?.set(dstId, weight);
×
115
        adjacencyMap.get(dstId)?.set(srcId, weight);
×
116
    }
×
117

118
    return adjacencyMap;
×
119
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc