gitnexus 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +181 -0
  2. package/dist/cli/ai-context.d.ts +21 -0
  3. package/dist/cli/ai-context.js +219 -0
  4. package/dist/cli/analyze.d.ts +10 -0
  5. package/dist/cli/analyze.js +118 -0
  6. package/dist/cli/clean.d.ts +8 -0
  7. package/dist/cli/clean.js +29 -0
  8. package/dist/cli/index.d.ts +2 -0
  9. package/dist/cli/index.js +42 -0
  10. package/dist/cli/list.d.ts +6 -0
  11. package/dist/cli/list.js +27 -0
  12. package/dist/cli/mcp.d.ts +7 -0
  13. package/dist/cli/mcp.js +85 -0
  14. package/dist/cli/serve.d.ts +3 -0
  15. package/dist/cli/serve.js +5 -0
  16. package/dist/cli/status.d.ts +6 -0
  17. package/dist/cli/status.js +27 -0
  18. package/dist/config/ignore-service.d.ts +1 -0
  19. package/dist/config/ignore-service.js +208 -0
  20. package/dist/config/supported-languages.d.ts +11 -0
  21. package/dist/config/supported-languages.js +15 -0
  22. package/dist/core/embeddings/embedder.d.ts +60 -0
  23. package/dist/core/embeddings/embedder.js +205 -0
  24. package/dist/core/embeddings/embedding-pipeline.d.ts +50 -0
  25. package/dist/core/embeddings/embedding-pipeline.js +321 -0
  26. package/dist/core/embeddings/index.d.ts +9 -0
  27. package/dist/core/embeddings/index.js +9 -0
  28. package/dist/core/embeddings/text-generator.d.ts +24 -0
  29. package/dist/core/embeddings/text-generator.js +182 -0
  30. package/dist/core/embeddings/types.d.ts +87 -0
  31. package/dist/core/embeddings/types.js +32 -0
  32. package/dist/core/graph/graph.d.ts +2 -0
  33. package/dist/core/graph/graph.js +61 -0
  34. package/dist/core/graph/types.d.ts +50 -0
  35. package/dist/core/graph/types.js +1 -0
  36. package/dist/core/ingestion/ast-cache.d.ts +11 -0
  37. package/dist/core/ingestion/ast-cache.js +34 -0
  38. package/dist/core/ingestion/call-processor.d.ts +8 -0
  39. package/dist/core/ingestion/call-processor.js +269 -0
  40. package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
  41. package/dist/core/ingestion/cluster-enricher.js +170 -0
  42. package/dist/core/ingestion/community-processor.d.ts +39 -0
  43. package/dist/core/ingestion/community-processor.js +269 -0
  44. package/dist/core/ingestion/entry-point-scoring.d.ts +39 -0
  45. package/dist/core/ingestion/entry-point-scoring.js +235 -0
  46. package/dist/core/ingestion/filesystem-walker.d.ts +5 -0
  47. package/dist/core/ingestion/filesystem-walker.js +26 -0
  48. package/dist/core/ingestion/framework-detection.d.ts +38 -0
  49. package/dist/core/ingestion/framework-detection.js +183 -0
  50. package/dist/core/ingestion/heritage-processor.d.ts +14 -0
  51. package/dist/core/ingestion/heritage-processor.js +134 -0
  52. package/dist/core/ingestion/import-processor.d.ts +8 -0
  53. package/dist/core/ingestion/import-processor.js +490 -0
  54. package/dist/core/ingestion/parsing-processor.d.ts +8 -0
  55. package/dist/core/ingestion/parsing-processor.js +249 -0
  56. package/dist/core/ingestion/pipeline.d.ts +2 -0
  57. package/dist/core/ingestion/pipeline.js +228 -0
  58. package/dist/core/ingestion/process-processor.d.ts +51 -0
  59. package/dist/core/ingestion/process-processor.js +278 -0
  60. package/dist/core/ingestion/structure-processor.d.ts +2 -0
  61. package/dist/core/ingestion/structure-processor.js +36 -0
  62. package/dist/core/ingestion/symbol-table.d.ts +33 -0
  63. package/dist/core/ingestion/symbol-table.js +38 -0
  64. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -0
  65. package/dist/core/ingestion/tree-sitter-queries.js +319 -0
  66. package/dist/core/ingestion/utils.d.ts +10 -0
  67. package/dist/core/ingestion/utils.js +44 -0
  68. package/dist/core/kuzu/csv-generator.d.ts +22 -0
  69. package/dist/core/kuzu/csv-generator.js +272 -0
  70. package/dist/core/kuzu/kuzu-adapter.d.ts +81 -0
  71. package/dist/core/kuzu/kuzu-adapter.js +568 -0
  72. package/dist/core/kuzu/schema.d.ts +53 -0
  73. package/dist/core/kuzu/schema.js +380 -0
  74. package/dist/core/search/bm25-index.d.ts +22 -0
  75. package/dist/core/search/bm25-index.js +52 -0
  76. package/dist/core/search/hybrid-search.d.ts +49 -0
  77. package/dist/core/search/hybrid-search.js +118 -0
  78. package/dist/core/tree-sitter/parser-loader.d.ts +4 -0
  79. package/dist/core/tree-sitter/parser-loader.js +42 -0
  80. package/dist/lib/utils.d.ts +1 -0
  81. package/dist/lib/utils.js +3 -0
  82. package/dist/mcp/core/embedder.d.ts +27 -0
  83. package/dist/mcp/core/embedder.js +93 -0
  84. package/dist/mcp/core/kuzu-adapter.d.ts +23 -0
  85. package/dist/mcp/core/kuzu-adapter.js +62 -0
  86. package/dist/mcp/local/local-backend.d.ts +73 -0
  87. package/dist/mcp/local/local-backend.js +752 -0
  88. package/dist/mcp/resources.d.ts +31 -0
  89. package/dist/mcp/resources.js +279 -0
  90. package/dist/mcp/server.d.ts +12 -0
  91. package/dist/mcp/server.js +130 -0
  92. package/dist/mcp/staleness.d.ts +15 -0
  93. package/dist/mcp/staleness.js +29 -0
  94. package/dist/mcp/tools.d.ts +24 -0
  95. package/dist/mcp/tools.js +160 -0
  96. package/dist/server/api.d.ts +6 -0
  97. package/dist/server/api.js +156 -0
  98. package/dist/storage/git.d.ts +7 -0
  99. package/dist/storage/git.js +39 -0
  100. package/dist/storage/repo-manager.d.ts +61 -0
  101. package/dist/storage/repo-manager.js +106 -0
  102. package/dist/types/pipeline.d.ts +28 -0
  103. package/dist/types/pipeline.js +16 -0
  104. package/package.json +80 -0
  105. package/skills/debugging.md +104 -0
  106. package/skills/exploring.md +112 -0
  107. package/skills/impact-analysis.md +114 -0
  108. package/skills/refactoring.md +119 -0
  109. package/vendor/leiden/index.cjs +355 -0
  110. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: gitnexus-exploring
3
+ description: Navigate unfamiliar code using GitNexus knowledge graph
4
+ ---
5
+
6
+ # Exploring Codebases
7
+
8
+ ## Quick Start
9
+ ```
10
+ 0. If "Index is stale" → gitnexus_analyze({})
11
+ 1. READ gitnexus://context → Get codebase overview (~150 tokens)
12
+ 2. READ gitnexus://clusters → See all functional clusters
13
+ 3. READ gitnexus://cluster/{name} → Deep dive on specific cluster
14
+ ```
15
+
16
+ ## When to Use
17
+ - "How does authentication work?"
18
+ - "What's the project structure?"
19
+ - "Show me the main components"
20
+ - "Where is the database logic?"
21
+
22
+ ## Workflow Checklist
23
+ ```
24
+ Exploration Progress:
25
+ - [ ] READ gitnexus://context for codebase overview
26
+ - [ ] READ gitnexus://clusters to list all clusters
27
+ - [ ] Identify the relevant cluster by name
28
+ - [ ] READ gitnexus://cluster/{name} for cluster details
29
+ - [ ] Use gitnexus_explore for specific symbols
30
+ ```
31
+
32
+ ## Resource Reference
33
+
34
+ ### gitnexus://context
35
+ Codebase overview. **Read first.**
36
+ ```yaml
37
+ project: my-app
38
+ stats:
39
+ files: 42
40
+ symbols: 918
41
+ clusters: 12
42
+ processes: 45
43
+ tools_available: [search, explore, impact, overview, cypher]
44
+ resources_available: [clusters, processes, cluster/{name}, process/{name}]
45
+ ```
46
+
47
+ ### gitnexus://clusters
48
+ All functional clusters with cohesion scores.
49
+ ```yaml
50
+ clusters:
51
+ - name: "Auth"
52
+ symbols: 47
53
+ cohesion: 92%
54
+ - name: "Database"
55
+ symbols: 32
56
+ cohesion: 88%
57
+ ```
58
+
59
+ ### gitnexus://cluster/{name}
60
+ Members of a specific cluster.
61
+ ```yaml
62
+ name: Auth
63
+ symbols: 47
64
+ cohesion: 92%
65
+ members:
66
+ - name: validateUser
67
+ type: Function
68
+ file: src/auth/validator.ts
69
+ ```
70
+
71
+ ### gitnexus://process/{name}
72
+ Full execution trace.
73
+ ```yaml
74
+ name: LoginFlow
75
+ type: cross_community
76
+ steps:
77
+ 1: handleLogin (src/auth/handler.ts)
78
+ 2: validateUser (src/auth/validator.ts)
79
+ 3: createSession (src/auth/session.ts)
80
+ ```
81
+
82
+ ## Tool Reference (When Resources Aren't Enough)
83
+
84
+ ### gitnexus_explore
85
+ For detailed symbol context with callers/callees:
86
+ ```
87
+ gitnexus_explore({name: "validateUser", type: "symbol"})
88
+ → Callers: loginHandler, apiMiddleware
89
+ → Callees: checkToken, getUserById
90
+ ```
91
+
92
+ ### gitnexus_search
93
+ For finding code by query:
94
+ ```
95
+ gitnexus_search({query: "payment validation", depth: "full"})
96
+ ```
97
+
98
+ ## Example: "How does payment processing work?"
99
+
100
+ ```
101
+ 1. READ gitnexus://context
102
+ → 918 symbols, 12 clusters
103
+
104
+ 2. READ gitnexus://clusters
105
+ → Clusters: Auth, Payment, Database, API...
106
+
107
+ 3. READ gitnexus://cluster/Payment
108
+ → Members: processPayment, validateCard, PaymentService
109
+
110
+ 4. READ gitnexus://process/CheckoutFlow
111
+ → handleCheckout → validateCart → processPayment → sendConfirmation
112
+ ```
@@ -0,0 +1,114 @@
1
+ ---
2
+ name: gitnexus-impact-analysis
3
+ description: Analyze blast radius before making code changes
4
+ ---
5
+
6
+ # Impact Analysis
7
+
8
+ ## Quick Start
9
+ ```
10
+ 0. If "Index is stale" → gitnexus_analyze({})
11
+ 1. gitnexus_impact({target, direction: "upstream"}) → What depends on this
12
+ 2. READ gitnexus://clusters → Check affected areas
13
+ 3. READ gitnexus://processes → Affected execution flows
14
+ ```
15
+
16
+ ## When to Use
17
+ - "Is it safe to change this function?"
18
+ - "What will break if I modify X?"
19
+ - "Show me the blast radius"
20
+ - "Who uses this code?"
21
+
22
+ ## Understanding Output
23
+
24
+ | Depth | Risk Level | Meaning |
25
+ |-------|-----------|---------|
26
+ | d=1 | WILL BREAK | Direct callers/importers |
27
+ | d=2 | LIKELY AFFECTED | Indirect dependencies |
28
+ | d=3 | MAY NEED TESTING | Transitive effects |
29
+
30
+ ## Workflow Checklist
31
+ ```
32
+ Impact Analysis:
33
+ - [ ] gitnexus_impact(target, "upstream") to find dependents
34
+ - [ ] READ gitnexus://clusters to understand affected areas
35
+ - [ ] Check high-confidence (>0.8) dependencies first
36
+ - [ ] Count affected clusters (cross-cutting = higher risk)
37
+ - [ ] If >10 processes affected, consider splitting change
38
+ ```
39
+
40
+ ## Resource Reference
41
+
42
+ ### gitnexus://clusters
43
+ Check which clusters might be affected:
44
+ ```yaml
45
+ clusters:
46
+ - name: Auth
47
+ symbols: 47
48
+ - name: API
49
+ symbols: 32
50
+ ```
51
+
52
+ ### gitnexus://processes
53
+ Find which processes touch the target:
54
+ ```yaml
55
+ processes:
56
+ - name: LoginFlow
57
+ type: cross_community
58
+ steps: 5
59
+ ```
60
+
61
+ ## Tool Reference
62
+
63
+ ### gitnexus_impact
64
+ Analyze blast radius:
65
+ ```
66
+ gitnexus_impact({
67
+ target: "validateUser",
68
+ direction: "upstream",
69
+ minConfidence: 0.8,
70
+ maxDepth: 3
71
+ })
72
+
73
+ → d=1 (WILL BREAK):
74
+ - loginHandler (src/auth/login.ts:42) [CALLS, 100%]
75
+ - apiMiddleware (src/api/middleware.ts:15) [CALLS, 100%]
76
+
77
+ → d=2 (LIKELY AFFECTED):
78
+ - authRouter (src/routes/auth.ts:22) [CALLS, 95%]
79
+
80
+ → Affected Processes: LoginFlow, TokenRefresh
81
+ → Risk: MEDIUM (3 processes)
82
+ ```
83
+
84
+ ## Risk Assessment
85
+
86
+ | Affected | Risk |
87
+ |----------|------|
88
+ | <5 symbols, 1 cluster | LOW |
89
+ | 5-15 symbols, 1-2 clusters | MEDIUM |
90
+ | >15 symbols or 3+ clusters | HIGH |
91
+ | Critical path (auth, payments) | CRITICAL |
92
+
93
+ ## Pre-Change Checklist
94
+ ```
95
+ Before Committing:
96
+ - [ ] Run impact analysis
97
+ - [ ] Review all d=1 (WILL BREAK) items
98
+ - [ ] Verify test coverage for affected processes
99
+ - [ ] If risk > MEDIUM, get code review
100
+ - [ ] If cross-cluster, coordinate with other teams
101
+ ```
102
+
103
+ ## Example: "What breaks if I change validateUser?"
104
+
105
+ ```
106
+ 1. gitnexus_impact({target: "validateUser", direction: "upstream"})
107
+ → d=1: loginHandler, apiMiddleware
108
+ → d=2: authRouter, sessionManager
109
+
110
+ 2. READ gitnexus://clusters
111
+ → Auth and API clusters affected
112
+
113
+ 3. Decision: 2 direct callers, 2 clusters = MEDIUM risk
114
+ ```
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: gitnexus-refactoring
3
+ description: Plan safe refactors using blast radius and dependency mapping
4
+ ---
5
+
6
+ # Refactoring with GitNexus
7
+
8
+ ## Quick Start
9
+ ```
10
+ 0. If "Index is stale" → gitnexus_analyze({})
11
+ 1. gitnexus_impact({target, direction: "upstream"}) → Map all dependents
12
+ 2. READ gitnexus://schema → Understand graph structure
13
+ 3. gitnexus_cypher → Find all references
14
+ ```
15
+
16
+ ## When to Use
17
+ - "Rename this function safely"
18
+ - "Extract this into a module"
19
+ - "Split this service"
20
+ - "Refactor without breaking things"
21
+
22
+ ## Checklists
23
+
24
+ ### Rename Symbol
25
+ ```
26
+ Rename Refactoring:
27
+ - [ ] gitnexus_impact(oldName, "upstream") — find all callers
28
+ - [ ] gitnexus_search(oldName) — find string literals
29
+ - [ ] Check for reflection/dynamic references
30
+ - [ ] Update in order: interface → implementation → usages
31
+ - [ ] Run tests for affected processes
32
+ ```
33
+
34
+ ### Extract Module
35
+ ```
36
+ Extract Module:
37
+ - [ ] gitnexus_explore(target, "symbol") — map dependencies
38
+ - [ ] gitnexus_impact(target, "upstream") — find callers
39
+ - [ ] READ gitnexus://cluster/{name} — check cohesion
40
+ - [ ] Define new module interface
41
+ - [ ] Update imports across affected files
42
+ ```
43
+
44
+ ### Split Function
45
+ ```
46
+ Split Function:
47
+ - [ ] gitnexus_explore(target, "symbol") — understand callees
48
+ - [ ] Group related logic
49
+ - [ ] gitnexus_impact — verify callers won't break
50
+ - [ ] Create new functions
51
+ - [ ] Update callers
52
+ ```
53
+
54
+ ## Resource Reference
55
+
56
+ ### gitnexus://schema
57
+ Graph structure for Cypher queries:
58
+ ```yaml
59
+ nodes: [Function, Class, Method, Community, Process]
60
+ relationships: [CALLS, IMPORTS, EXTENDS, MEMBER_OF]
61
+
62
+ example_queries:
63
+ find_callers: |
64
+ MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "X"})
65
+ RETURN caller.name
66
+ ```
67
+
68
+ ### gitnexus://cluster/{name}
69
+ Check if extraction preserves cohesion:
70
+ ```yaml
71
+ name: Payment
72
+ cohesion: 92%
73
+ members: [processPayment, validateCard, PaymentService]
74
+ ```
75
+
76
+ ## Tool Reference
77
+
78
+ ### Finding all references
79
+ ```cypher
80
+ MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "validateUser"})
81
+ RETURN caller.name, caller.filePath
82
+ ORDER BY caller.filePath
83
+ ```
84
+
85
+ ### Finding imports of a module
86
+ ```cypher
87
+ MATCH (importer)-[:CodeRelation {type: 'IMPORTS'}]->(f:File {name: "utils.ts"})
88
+ RETURN importer.name, importer.filePath
89
+ ```
90
+
91
+ ## Example: Safely Rename `validateUser` to `authenticateUser`
92
+
93
+ ```
94
+ 1. gitnexus_impact({target: "validateUser", direction: "upstream"})
95
+ → loginHandler, apiMiddleware, testUtils
96
+
97
+ 2. gitnexus_search({query: "validateUser"})
98
+ → Found in: config.json (dynamic reference!)
99
+
100
+ 3. READ gitnexus://processes
101
+ → LoginFlow, TokenRefresh, APIGateway
102
+
103
+ 4. Plan update order:
104
+ 1. Update declaration in auth.ts
105
+ 2. Update config.json string reference
106
+ 3. Update loginHandler
107
+ 4. Update apiMiddleware
108
+ 5. Run tests for LoginFlow, TokenRefresh
109
+ ```
110
+
111
+ ## Refactoring Safety Rules
112
+
113
+ | Risk Factor | Mitigation |
114
+ |-------------|------------|
115
+ | Many callers (>5) | Update in small batches |
116
+ | Cross-cluster | Coordinate with other teams |
117
+ | String references | Search for dynamic usage |
118
+ | Reflection | Check for dynamic invocation |
119
+ | External exports | May break downstream repos |
@@ -0,0 +1,355 @@
1
+ /**
2
+ * Graphology Leiden Algorithm
3
+ * ============================
4
+ *
5
+ * JavaScript implementation of the Leiden community detection
6
+ * algorithm for graphology.
7
+ *
8
+ * Vendored from: https://github.com/graphology/graphology/tree/master/src/communities-leiden
9
+ * License: MIT
10
+ *
11
+ * [Reference]
12
+ * Traag, V. A., et al. "From Louvain to Leiden: Guaranteeing Well-Connected
13
+ * Communities". Scientific Reports, vol. 9, no 1, 2019, p. 5233.
14
+ * https://arxiv.org/abs/1810.08473
15
+ */
16
+ var resolveDefaults = require('graphology-utils/defaults');
17
+ var isGraph = require('graphology-utils/is-graph');
18
+ var inferType = require('graphology-utils/infer-type');
19
+ var SparseMap = require('mnemonist/sparse-map');
20
+ var SparseQueueSet = require('mnemonist/sparse-queue-set');
21
+ var createRandomIndex = require('pandemonium/random-index').createRandomIndex;
22
+ var utils = require('./utils.cjs');
23
+
24
+ var indices = require('graphology-indices/louvain');
25
+ var addWeightToCommunity = utils.addWeightToCommunity;
26
+
27
+ var UndirectedLouvainIndex = indices.UndirectedLouvainIndex;
28
+
29
+ var UndirectedLeidenAddenda = utils.UndirectedLeidenAddenda;
30
+
31
+ var DEFAULTS = {
32
+ attributes: {
33
+ community: 'community',
34
+ weight: 'weight'
35
+ },
36
+ randomness: 0.01,
37
+ randomWalk: true,
38
+ resolution: 1,
39
+ rng: Math.random,
40
+ weighted: false
41
+ };
42
+
43
+ var EPSILON = 1e-10;
44
+
45
+ function tieBreaker(
46
+ bestCommunity,
47
+ currentCommunity,
48
+ targetCommunity,
49
+ delta,
50
+ bestDelta
51
+ ) {
52
+ if (Math.abs(delta - bestDelta) < EPSILON) {
53
+ if (bestCommunity === currentCommunity) {
54
+ return false;
55
+ } else {
56
+ return targetCommunity > bestCommunity;
57
+ }
58
+ } else if (delta > bestDelta) {
59
+ return true;
60
+ }
61
+
62
+ return false;
63
+ }
64
+
65
+ function undirectedLeiden(detailed, graph, options) {
66
+ var index = new UndirectedLouvainIndex(graph, {
67
+ attributes: {
68
+ weight: options.attributes.weight
69
+ },
70
+ keepDendrogram: detailed,
71
+ resolution: options.resolution,
72
+ weighted: options.weighted
73
+ });
74
+
75
+ var addenda = new UndirectedLeidenAddenda(index, {
76
+ randomness: options.randomness,
77
+ rng: options.rng
78
+ });
79
+
80
+ var randomIndex = createRandomIndex(options.rng);
81
+
82
+ // Communities
83
+ var currentCommunity, targetCommunity;
84
+ var communities = new SparseMap(Float64Array, index.C);
85
+
86
+ // Traversal
87
+ var queue = new SparseQueueSet(index.C),
88
+ start,
89
+ end,
90
+ weight,
91
+ ci,
92
+ ri,
93
+ s,
94
+ i,
95
+ j,
96
+ l;
97
+
98
+ // Metrics
99
+ var degree, targetCommunityDegree;
100
+
101
+ // Moves
102
+ var bestCommunity, bestDelta, deltaIsBetter, delta;
103
+
104
+ // Details
105
+ var deltaComputations = 0,
106
+ nodesVisited = 0,
107
+ moves = [],
108
+ currentMoves;
109
+
110
+ while (true) {
111
+ l = index.C;
112
+
113
+ currentMoves = 0;
114
+
115
+ // Traversal of the graph
116
+ ri = options.randomWalk ? randomIndex(l) : 0;
117
+
118
+ for (s = 0; s < l; s++, ri++) {
119
+ i = ri % l;
120
+ queue.enqueue(i);
121
+ }
122
+
123
+ while (queue.size !== 0) {
124
+ i = queue.dequeue();
125
+ nodesVisited++;
126
+
127
+ degree = 0;
128
+ communities.clear();
129
+
130
+ currentCommunity = index.belongings[i];
131
+
132
+ start = index.starts[i];
133
+ end = index.starts[i + 1];
134
+
135
+ // Traversing neighbors
136
+ for (; start < end; start++) {
137
+ j = index.neighborhood[start];
138
+ weight = index.weights[start];
139
+
140
+ targetCommunity = index.belongings[j];
141
+
142
+ // Incrementing metrics
143
+ degree += weight;
144
+ addWeightToCommunity(communities, targetCommunity, weight);
145
+ }
146
+
147
+ // Finding best community to move to
148
+ bestDelta = index.fastDeltaWithOwnCommunity(
149
+ i,
150
+ degree,
151
+ communities.get(currentCommunity) || 0,
152
+ currentCommunity
153
+ );
154
+ bestCommunity = currentCommunity;
155
+
156
+ for (ci = 0; ci < communities.size; ci++) {
157
+ targetCommunity = communities.dense[ci];
158
+
159
+ if (targetCommunity === currentCommunity) continue;
160
+
161
+ targetCommunityDegree = communities.vals[ci];
162
+
163
+ deltaComputations++;
164
+
165
+ delta = index.fastDelta(
166
+ i,
167
+ degree,
168
+ targetCommunityDegree,
169
+ targetCommunity
170
+ );
171
+
172
+ deltaIsBetter = tieBreaker(
173
+ bestCommunity,
174
+ currentCommunity,
175
+ targetCommunity,
176
+ delta,
177
+ bestDelta
178
+ );
179
+
180
+ if (deltaIsBetter) {
181
+ bestDelta = delta;
182
+ bestCommunity = targetCommunity;
183
+ }
184
+ }
185
+
186
+ if (bestDelta < 0) {
187
+ bestCommunity = index.isolate(i, degree);
188
+
189
+ if (bestCommunity === currentCommunity) continue;
190
+ } else {
191
+ if (bestCommunity === currentCommunity) {
192
+ continue;
193
+ } else {
194
+ index.move(i, degree, bestCommunity);
195
+ }
196
+ }
197
+
198
+ currentMoves++;
199
+
200
+ // Adding neighbors from other communities to the queue
201
+ start = index.starts[i];
202
+ end = index.starts[i + 1];
203
+
204
+ for (; start < end; start++) {
205
+ j = index.neighborhood[start];
206
+ targetCommunity = index.belongings[j];
207
+
208
+ if (targetCommunity !== bestCommunity) queue.enqueue(j);
209
+ }
210
+ }
211
+
212
+ moves.push(currentMoves);
213
+
214
+ if (currentMoves === 0) {
215
+ index.zoomOut();
216
+ break;
217
+ }
218
+
219
+ if (!addenda.onlySingletons()) {
220
+ // We continue working on the induced graph
221
+ addenda.zoomOut();
222
+ continue;
223
+ }
224
+
225
+ break;
226
+ }
227
+
228
+ var results = {
229
+ index: index,
230
+ deltaComputations: deltaComputations,
231
+ nodesVisited: nodesVisited,
232
+ moves: moves
233
+ };
234
+
235
+ return results;
236
+ }
237
+
238
+ /**
239
+ * Function returning the communities mapping of the graph.
240
+ *
241
+ * @param {boolean} assign - Assign communities to nodes attributes?
242
+ * @param {boolean} detailed - Whether to return detailed information.
243
+ * @param {Graph} graph - Target graph.
244
+ * @param {object} options - Options:
245
+ * @param {object} attributes - Attribute names:
246
+ * @param {string} community - Community node attribute name.
247
+ * @param {string} weight - Weight edge attribute name.
248
+ * @param {number} randomness - Randomness parameter.
249
+ * @param {boolean} randomWalk - Whether to traverse the graph in random order.
250
+ * @param {number} resolution - Resolution parameter.
251
+ * @param {function} rng - RNG function to use.
252
+ * @param {boolean} weighted - Whether to compute the weighted version.
253
+ * @return {object}
254
+ */
255
+ function leiden(assign, detailed, graph, options) {
256
+ if (!isGraph(graph))
257
+ throw new Error(
258
+ 'graphology-communities-leiden: the given graph is not a valid graphology instance.'
259
+ );
260
+
261
+ var type = inferType(graph);
262
+
263
+ if (type === 'mixed')
264
+ throw new Error(
265
+ 'graphology-communities-leiden: cannot run the algorithm on a true mixed graph.'
266
+ );
267
+
268
+ if (type === 'directed')
269
+ throw new Error(
270
+ 'graphology-communities-leiden: not yet implemented for directed graphs.'
271
+ );
272
+
273
+ // Attributes name
274
+ options = resolveDefaults(options, DEFAULTS);
275
+
276
+ // Empty graph case
277
+ var c = 0;
278
+
279
+ if (graph.size === 0) {
280
+ if (assign) {
281
+ graph.forEachNode(function (node) {
282
+ graph.setNodeAttribute(node, options.attributes.communities, c++);
283
+ });
284
+
285
+ return;
286
+ }
287
+
288
+ var communities = {};
289
+
290
+ graph.forEachNode(function (node) {
291
+ communities[node] = c++;
292
+ });
293
+
294
+ if (!detailed) return communities;
295
+
296
+ return {
297
+ communities: communities,
298
+ count: graph.order,
299
+ deltaComputations: 0,
300
+ dendrogram: null,
301
+ level: 0,
302
+ modularity: NaN,
303
+ moves: null,
304
+ nodesVisited: 0,
305
+ resolution: options.resolution
306
+ };
307
+ }
308
+
309
+ var fn = undirectedLeiden;
310
+
311
+ var results = fn(detailed, graph, options);
312
+
313
+ var index = results.index;
314
+
315
+ // Standard output
316
+ if (!detailed) {
317
+ if (assign) {
318
+ index.assign(options.attributes.community);
319
+ return;
320
+ }
321
+
322
+ return index.collect();
323
+ }
324
+
325
+ // Detailed output
326
+ var output = {
327
+ count: index.C,
328
+ deltaComputations: results.deltaComputations,
329
+ dendrogram: index.dendrogram,
330
+ level: index.level,
331
+ modularity: index.modularity(),
332
+ moves: results.moves,
333
+ nodesVisited: results.nodesVisited,
334
+ resolution: options.resolution
335
+ };
336
+
337
+ if (assign) {
338
+ index.assign(options.attributes.community);
339
+ return output;
340
+ }
341
+
342
+ output.communities = index.collect();
343
+
344
+ return output;
345
+ }
346
+
347
+ /**
348
+ * Exporting.
349
+ */
350
+ var fn = leiden.bind(null, false, false);
351
+ fn.assign = leiden.bind(null, true, false);
352
+ fn.detailed = leiden.bind(null, false, true);
353
+ fn.defaults = DEFAULTS;
354
+
355
+ module.exports = fn;