@optave/codegraph 3.1.4 → 3.2.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 (210) hide show
  1. package/README.md +29 -72
  2. package/package.json +10 -8
  3. package/src/ast-analysis/engine.js +260 -246
  4. package/src/ast-analysis/shared.js +2 -14
  5. package/src/ast-analysis/visitors/cfg-visitor.js +635 -649
  6. package/src/ast-analysis/visitors/complexity-visitor.js +135 -139
  7. package/src/ast-analysis/visitors/dataflow-visitor.js +230 -224
  8. package/src/cli/commands/ast.js +4 -7
  9. package/src/cli/commands/audit.js +11 -11
  10. package/src/cli/commands/batch.js +6 -5
  11. package/src/cli/commands/branch-compare.js +1 -1
  12. package/src/cli/commands/brief.js +12 -0
  13. package/src/cli/commands/build.js +1 -1
  14. package/src/cli/commands/cfg.js +5 -8
  15. package/src/cli/commands/check.js +28 -36
  16. package/src/cli/commands/children.js +9 -7
  17. package/src/cli/commands/co-change.js +5 -3
  18. package/src/cli/commands/communities.js +2 -6
  19. package/src/cli/commands/complexity.js +5 -3
  20. package/src/cli/commands/context.js +9 -8
  21. package/src/cli/commands/cycles.js +12 -8
  22. package/src/cli/commands/dataflow.js +5 -8
  23. package/src/cli/commands/deps.js +9 -8
  24. package/src/cli/commands/diff-impact.js +2 -6
  25. package/src/cli/commands/embed.js +1 -1
  26. package/src/cli/commands/export.js +34 -31
  27. package/src/cli/commands/exports.js +2 -6
  28. package/src/cli/commands/flow.js +5 -8
  29. package/src/cli/commands/fn-impact.js +9 -8
  30. package/src/cli/commands/impact.js +2 -6
  31. package/src/cli/commands/info.js +2 -2
  32. package/src/cli/commands/map.js +1 -1
  33. package/src/cli/commands/mcp.js +1 -1
  34. package/src/cli/commands/models.js +1 -1
  35. package/src/cli/commands/owners.js +5 -3
  36. package/src/cli/commands/path.js +2 -2
  37. package/src/cli/commands/plot.js +40 -31
  38. package/src/cli/commands/query.js +9 -8
  39. package/src/cli/commands/registry.js +2 -2
  40. package/src/cli/commands/roles.js +5 -8
  41. package/src/cli/commands/search.js +9 -3
  42. package/src/cli/commands/sequence.js +5 -8
  43. package/src/cli/commands/snapshot.js +6 -1
  44. package/src/cli/commands/stats.js +1 -1
  45. package/src/cli/commands/structure.js +5 -4
  46. package/src/cli/commands/triage.js +41 -30
  47. package/src/cli/commands/watch.js +1 -1
  48. package/src/cli/commands/where.js +2 -6
  49. package/src/cli/index.js +11 -5
  50. package/src/cli/shared/open-graph.js +13 -0
  51. package/src/cli/shared/options.js +22 -2
  52. package/src/cli.js +1 -1
  53. package/src/db/connection.js +140 -11
  54. package/src/{db.js → db/index.js} +12 -5
  55. package/src/db/migrations.js +42 -65
  56. package/src/db/query-builder.js +72 -9
  57. package/src/db/repository/base.js +1 -1
  58. package/src/db/repository/graph-read.js +3 -3
  59. package/src/db/repository/in-memory-repository.js +30 -28
  60. package/src/db/repository/nodes.js +10 -17
  61. package/src/domain/analysis/brief.js +155 -0
  62. package/src/domain/analysis/context.js +392 -0
  63. package/src/domain/analysis/dependencies.js +395 -0
  64. package/src/{analysis → domain/analysis}/exports.js +11 -6
  65. package/src/domain/analysis/impact.js +581 -0
  66. package/src/domain/analysis/module-map.js +348 -0
  67. package/src/{analysis → domain/analysis}/roles.js +12 -9
  68. package/src/{analysis → domain/analysis}/symbol-lookup.js +19 -11
  69. package/src/{builder → domain/graph/builder}/helpers.js +4 -4
  70. package/src/{builder → domain/graph/builder}/incremental.js +119 -93
  71. package/src/domain/graph/builder/pipeline.js +156 -0
  72. package/src/domain/graph/builder/stages/build-edges.js +376 -0
  73. package/src/{builder → domain/graph/builder}/stages/build-structure.js +4 -4
  74. package/src/{builder → domain/graph/builder}/stages/collect-files.js +2 -2
  75. package/src/{builder → domain/graph/builder}/stages/detect-changes.js +204 -183
  76. package/src/{builder → domain/graph/builder}/stages/finalize.js +4 -4
  77. package/src/domain/graph/builder/stages/insert-nodes.js +203 -0
  78. package/src/{builder → domain/graph/builder}/stages/parse-files.js +2 -2
  79. package/src/{builder → domain/graph/builder}/stages/resolve-imports.js +1 -1
  80. package/src/{builder → domain/graph/builder}/stages/run-analyses.js +2 -2
  81. package/src/{change-journal.js → domain/graph/change-journal.js} +1 -1
  82. package/src/{cycles.js → domain/graph/cycles.js} +4 -4
  83. package/src/{journal.js → domain/graph/journal.js} +1 -1
  84. package/src/{resolve.js → domain/graph/resolve.js} +2 -2
  85. package/src/{watcher.js → domain/graph/watcher.js} +7 -7
  86. package/src/{parser.js → domain/parser.js} +24 -15
  87. package/src/{queries.js → domain/queries.js} +17 -16
  88. package/src/{embeddings → domain/search}/generator.js +3 -3
  89. package/src/{embeddings → domain/search}/models.js +2 -2
  90. package/src/{embeddings → domain/search}/search/cli-formatter.js +1 -1
  91. package/src/{embeddings → domain/search}/search/filters.js +9 -5
  92. package/src/{embeddings → domain/search}/search/hybrid.js +1 -1
  93. package/src/{embeddings → domain/search}/search/keyword.js +13 -6
  94. package/src/{embeddings → domain/search}/search/prepare.js +15 -7
  95. package/src/{embeddings → domain/search}/search/semantic.js +1 -1
  96. package/src/{embeddings → domain/search}/strategies/structured.js +1 -1
  97. package/src/extractors/csharp.js +224 -207
  98. package/src/extractors/go.js +176 -172
  99. package/src/extractors/hcl.js +94 -78
  100. package/src/extractors/java.js +213 -207
  101. package/src/extractors/javascript.js +275 -305
  102. package/src/extractors/php.js +234 -221
  103. package/src/extractors/python.js +252 -250
  104. package/src/extractors/ruby.js +192 -185
  105. package/src/extractors/rust.js +182 -167
  106. package/src/{ast.js → features/ast.js} +13 -11
  107. package/src/{audit.js → features/audit.js} +20 -46
  108. package/src/{batch.js → features/batch.js} +5 -5
  109. package/src/{boundaries.js → features/boundaries.js} +100 -85
  110. package/src/{branch-compare.js → features/branch-compare.js} +3 -3
  111. package/src/{cfg.js → features/cfg.js} +141 -150
  112. package/src/{check.js → features/check.js} +13 -30
  113. package/src/{cochange.js → features/cochange.js} +5 -5
  114. package/src/{communities.js → features/communities.js} +72 -57
  115. package/src/{complexity.js → features/complexity.js} +154 -143
  116. package/src/{dataflow.js → features/dataflow.js} +155 -158
  117. package/src/{export.js → features/export.js} +6 -6
  118. package/src/{flow.js → features/flow.js} +4 -4
  119. package/src/{viewer.js → features/graph-enrichment.js} +8 -8
  120. package/src/{manifesto.js → features/manifesto.js} +15 -12
  121. package/src/{owners.js → features/owners.js} +6 -5
  122. package/src/features/sequence.js +300 -0
  123. package/src/features/shared/find-nodes.js +31 -0
  124. package/src/{snapshot.js → features/snapshot.js} +3 -3
  125. package/src/{structure.js → features/structure.js} +139 -108
  126. package/src/features/triage.js +141 -0
  127. package/src/graph/builders/dependency.js +33 -14
  128. package/src/graph/classifiers/risk.js +3 -2
  129. package/src/graph/classifiers/roles.js +6 -3
  130. package/src/index.cjs +16 -0
  131. package/src/index.js +40 -39
  132. package/src/{native.js → infrastructure/native.js} +1 -1
  133. package/src/mcp/middleware.js +1 -1
  134. package/src/mcp/server.js +68 -59
  135. package/src/mcp/tool-registry.js +15 -2
  136. package/src/mcp/tools/ast-query.js +1 -1
  137. package/src/mcp/tools/audit.js +1 -1
  138. package/src/mcp/tools/batch-query.js +1 -1
  139. package/src/mcp/tools/branch-compare.js +3 -1
  140. package/src/mcp/tools/brief.js +8 -0
  141. package/src/mcp/tools/cfg.js +1 -1
  142. package/src/mcp/tools/check.js +3 -3
  143. package/src/mcp/tools/co-changes.js +1 -1
  144. package/src/mcp/tools/code-owners.js +1 -1
  145. package/src/mcp/tools/communities.js +1 -1
  146. package/src/mcp/tools/complexity.js +1 -1
  147. package/src/mcp/tools/dataflow.js +2 -2
  148. package/src/mcp/tools/execution-flow.js +2 -2
  149. package/src/mcp/tools/export-graph.js +2 -2
  150. package/src/mcp/tools/find-cycles.js +2 -2
  151. package/src/mcp/tools/index.js +2 -0
  152. package/src/mcp/tools/list-repos.js +1 -1
  153. package/src/mcp/tools/sequence.js +1 -1
  154. package/src/mcp/tools/structure.js +1 -1
  155. package/src/mcp/tools/triage.js +2 -2
  156. package/src/{commands → presentation}/audit.js +2 -2
  157. package/src/{commands → presentation}/batch.js +1 -1
  158. package/src/{commands → presentation}/branch-compare.js +2 -2
  159. package/src/presentation/brief.js +51 -0
  160. package/src/{commands → presentation}/cfg.js +1 -1
  161. package/src/{commands → presentation}/check.js +2 -2
  162. package/src/{commands → presentation}/communities.js +1 -1
  163. package/src/{commands → presentation}/complexity.js +1 -1
  164. package/src/{commands → presentation}/dataflow.js +1 -1
  165. package/src/{commands → presentation}/flow.js +2 -2
  166. package/src/{commands → presentation}/manifesto.js +1 -1
  167. package/src/{commands → presentation}/owners.js +1 -1
  168. package/src/presentation/queries-cli/exports.js +53 -0
  169. package/src/presentation/queries-cli/impact.js +214 -0
  170. package/src/presentation/queries-cli/index.js +5 -0
  171. package/src/presentation/queries-cli/inspect.js +329 -0
  172. package/src/presentation/queries-cli/overview.js +196 -0
  173. package/src/presentation/queries-cli/path.js +65 -0
  174. package/src/presentation/queries-cli.js +27 -0
  175. package/src/{commands → presentation}/query.js +1 -1
  176. package/src/presentation/result-formatter.js +126 -3
  177. package/src/{commands → presentation}/sequence.js +2 -2
  178. package/src/{commands → presentation}/structure.js +1 -1
  179. package/src/presentation/table.js +0 -8
  180. package/src/{commands → presentation}/triage.js +1 -1
  181. package/src/{constants.js → shared/constants.js} +1 -1
  182. package/src/shared/file-utils.js +2 -2
  183. package/src/shared/generators.js +9 -5
  184. package/src/shared/hierarchy.js +1 -1
  185. package/src/{kinds.js → shared/kinds.js} +1 -1
  186. package/src/analysis/context.js +0 -408
  187. package/src/analysis/dependencies.js +0 -341
  188. package/src/analysis/impact.js +0 -463
  189. package/src/analysis/module-map.js +0 -322
  190. package/src/builder/pipeline.js +0 -130
  191. package/src/builder/stages/build-edges.js +0 -297
  192. package/src/builder/stages/insert-nodes.js +0 -195
  193. package/src/mcp.js +0 -2
  194. package/src/queries-cli.js +0 -866
  195. package/src/sequence.js +0 -289
  196. package/src/triage.js +0 -126
  197. /package/src/{builder → domain/graph/builder}/context.js +0 -0
  198. /package/src/{builder.js → domain/graph/builder.js} +0 -0
  199. /package/src/{embeddings → domain/search}/index.js +0 -0
  200. /package/src/{embeddings → domain/search}/stores/fts5.js +0 -0
  201. /package/src/{embeddings → domain/search}/stores/sqlite-blob.js +0 -0
  202. /package/src/{embeddings → domain/search}/strategies/source.js +0 -0
  203. /package/src/{embeddings → domain/search}/strategies/text-utils.js +0 -0
  204. /package/src/{config.js → infrastructure/config.js} +0 -0
  205. /package/src/{logger.js → infrastructure/logger.js} +0 -0
  206. /package/src/{registry.js → infrastructure/registry.js} +0 -0
  207. /package/src/{update-check.js → infrastructure/update-check.js} +0 -0
  208. /package/src/{commands → presentation}/cochange.js +0 -0
  209. /package/src/{errors.js → shared/errors.js} +0 -0
  210. /package/src/{paginate.js → shared/paginate.js} +0 -0
@@ -1,341 +0,0 @@
1
- import {
2
- findCallees,
3
- findCallers,
4
- findFileNodes,
5
- findImportSources,
6
- findImportTargets,
7
- findNodesByFile,
8
- openReadonlyOrFail,
9
- } from '../db.js';
10
- import { isTestFile } from '../infrastructure/test-filter.js';
11
- import { paginateResult } from '../paginate.js';
12
- import { resolveMethodViaHierarchy } from '../shared/hierarchy.js';
13
- import { normalizeSymbol } from '../shared/normalize.js';
14
- import { findMatchingNodes } from './symbol-lookup.js';
15
-
16
- export function fileDepsData(file, customDbPath, opts = {}) {
17
- const db = openReadonlyOrFail(customDbPath);
18
- try {
19
- const noTests = opts.noTests || false;
20
- const fileNodes = findFileNodes(db, `%${file}%`);
21
- if (fileNodes.length === 0) {
22
- return { file, results: [] };
23
- }
24
-
25
- const results = fileNodes.map((fn) => {
26
- let importsTo = findImportTargets(db, fn.id);
27
- if (noTests) importsTo = importsTo.filter((i) => !isTestFile(i.file));
28
-
29
- let importedBy = findImportSources(db, fn.id);
30
- if (noTests) importedBy = importedBy.filter((i) => !isTestFile(i.file));
31
-
32
- const defs = findNodesByFile(db, fn.file);
33
-
34
- return {
35
- file: fn.file,
36
- imports: importsTo.map((i) => ({ file: i.file, typeOnly: i.edge_kind === 'imports-type' })),
37
- importedBy: importedBy.map((i) => ({ file: i.file })),
38
- definitions: defs.map((d) => ({ name: d.name, kind: d.kind, line: d.line })),
39
- };
40
- });
41
-
42
- const base = { file, results };
43
- return paginateResult(base, 'results', { limit: opts.limit, offset: opts.offset });
44
- } finally {
45
- db.close();
46
- }
47
- }
48
-
49
- export function fnDepsData(name, customDbPath, opts = {}) {
50
- const db = openReadonlyOrFail(customDbPath);
51
- try {
52
- const depth = opts.depth || 3;
53
- const noTests = opts.noTests || false;
54
- const hc = new Map();
55
-
56
- const nodes = findMatchingNodes(db, name, { noTests, file: opts.file, kind: opts.kind });
57
- if (nodes.length === 0) {
58
- return { name, results: [] };
59
- }
60
-
61
- const results = nodes.map((node) => {
62
- const callees = findCallees(db, node.id);
63
- const filteredCallees = noTests ? callees.filter((c) => !isTestFile(c.file)) : callees;
64
-
65
- let callers = findCallers(db, node.id);
66
-
67
- if (node.kind === 'method' && node.name.includes('.')) {
68
- const methodName = node.name.split('.').pop();
69
- const relatedMethods = resolveMethodViaHierarchy(db, methodName);
70
- for (const rm of relatedMethods) {
71
- if (rm.id === node.id) continue;
72
- const extraCallers = findCallers(db, rm.id);
73
- callers.push(...extraCallers.map((c) => ({ ...c, viaHierarchy: rm.name })));
74
- }
75
- }
76
- if (noTests) callers = callers.filter((c) => !isTestFile(c.file));
77
-
78
- // Transitive callers
79
- const transitiveCallers = {};
80
- if (depth > 1) {
81
- const visited = new Set([node.id]);
82
- let frontier = callers
83
- .map((c) => {
84
- const row = db
85
- .prepare('SELECT id FROM nodes WHERE name = ? AND kind = ? AND file = ? AND line = ?')
86
- .get(c.name, c.kind, c.file, c.line);
87
- return row ? { ...c, id: row.id } : null;
88
- })
89
- .filter(Boolean);
90
-
91
- for (let d = 2; d <= depth; d++) {
92
- const nextFrontier = [];
93
- for (const f of frontier) {
94
- if (visited.has(f.id)) continue;
95
- visited.add(f.id);
96
- const upstream = db
97
- .prepare(`
98
- SELECT n.name, n.kind, n.file, n.line
99
- FROM edges e JOIN nodes n ON e.source_id = n.id
100
- WHERE e.target_id = ? AND e.kind = 'calls'
101
- `)
102
- .all(f.id);
103
- for (const u of upstream) {
104
- if (noTests && isTestFile(u.file)) continue;
105
- const uid = db
106
- .prepare(
107
- 'SELECT id FROM nodes WHERE name = ? AND kind = ? AND file = ? AND line = ?',
108
- )
109
- .get(u.name, u.kind, u.file, u.line)?.id;
110
- if (uid && !visited.has(uid)) {
111
- nextFrontier.push({ ...u, id: uid });
112
- }
113
- }
114
- }
115
- if (nextFrontier.length > 0) {
116
- transitiveCallers[d] = nextFrontier.map((n) => ({
117
- name: n.name,
118
- kind: n.kind,
119
- file: n.file,
120
- line: n.line,
121
- }));
122
- }
123
- frontier = nextFrontier;
124
- if (frontier.length === 0) break;
125
- }
126
- }
127
-
128
- return {
129
- ...normalizeSymbol(node, db, hc),
130
- callees: filteredCallees.map((c) => ({
131
- name: c.name,
132
- kind: c.kind,
133
- file: c.file,
134
- line: c.line,
135
- })),
136
- callers: callers.map((c) => ({
137
- name: c.name,
138
- kind: c.kind,
139
- file: c.file,
140
- line: c.line,
141
- viaHierarchy: c.viaHierarchy || undefined,
142
- })),
143
- transitiveCallers,
144
- };
145
- });
146
-
147
- const base = { name, results };
148
- return paginateResult(base, 'results', { limit: opts.limit, offset: opts.offset });
149
- } finally {
150
- db.close();
151
- }
152
- }
153
-
154
- export function pathData(from, to, customDbPath, opts = {}) {
155
- const db = openReadonlyOrFail(customDbPath);
156
- try {
157
- const noTests = opts.noTests || false;
158
- const maxDepth = opts.maxDepth || 10;
159
- const edgeKinds = opts.edgeKinds || ['calls'];
160
- const reverse = opts.reverse || false;
161
-
162
- const fromNodes = findMatchingNodes(db, from, {
163
- noTests,
164
- file: opts.fromFile,
165
- kind: opts.kind,
166
- });
167
- if (fromNodes.length === 0) {
168
- return {
169
- from,
170
- to,
171
- found: false,
172
- error: `No symbol matching "${from}"`,
173
- fromCandidates: [],
174
- toCandidates: [],
175
- };
176
- }
177
-
178
- const toNodes = findMatchingNodes(db, to, {
179
- noTests,
180
- file: opts.toFile,
181
- kind: opts.kind,
182
- });
183
- if (toNodes.length === 0) {
184
- return {
185
- from,
186
- to,
187
- found: false,
188
- error: `No symbol matching "${to}"`,
189
- fromCandidates: fromNodes
190
- .slice(0, 5)
191
- .map((n) => ({ name: n.name, kind: n.kind, file: n.file, line: n.line })),
192
- toCandidates: [],
193
- };
194
- }
195
-
196
- const sourceNode = fromNodes[0];
197
- const targetNode = toNodes[0];
198
-
199
- const fromCandidates = fromNodes
200
- .slice(0, 5)
201
- .map((n) => ({ name: n.name, kind: n.kind, file: n.file, line: n.line }));
202
- const toCandidates = toNodes
203
- .slice(0, 5)
204
- .map((n) => ({ name: n.name, kind: n.kind, file: n.file, line: n.line }));
205
-
206
- // Self-path
207
- if (sourceNode.id === targetNode.id) {
208
- return {
209
- from,
210
- to,
211
- fromCandidates,
212
- toCandidates,
213
- found: true,
214
- hops: 0,
215
- path: [
216
- {
217
- name: sourceNode.name,
218
- kind: sourceNode.kind,
219
- file: sourceNode.file,
220
- line: sourceNode.line,
221
- edgeKind: null,
222
- },
223
- ],
224
- alternateCount: 0,
225
- edgeKinds,
226
- reverse,
227
- maxDepth,
228
- };
229
- }
230
-
231
- // Build edge kind filter
232
- const kindPlaceholders = edgeKinds.map(() => '?').join(', ');
233
-
234
- // BFS — direction depends on `reverse` flag
235
- // Forward: source_id → target_id (A calls... calls B)
236
- // Reverse: target_id → source_id (B is called by... called by A)
237
- const neighborQuery = reverse
238
- ? `SELECT n.id, n.name, n.kind, n.file, n.line, e.kind AS edge_kind
239
- FROM edges e JOIN nodes n ON e.source_id = n.id
240
- WHERE e.target_id = ? AND e.kind IN (${kindPlaceholders})`
241
- : `SELECT n.id, n.name, n.kind, n.file, n.line, e.kind AS edge_kind
242
- FROM edges e JOIN nodes n ON e.target_id = n.id
243
- WHERE e.source_id = ? AND e.kind IN (${kindPlaceholders})`;
244
- const neighborStmt = db.prepare(neighborQuery);
245
-
246
- const visited = new Set([sourceNode.id]);
247
- // parent map: nodeId → { parentId, edgeKind }
248
- const parent = new Map();
249
- let queue = [sourceNode.id];
250
- let found = false;
251
- let alternateCount = 0;
252
- let foundDepth = -1;
253
-
254
- for (let depth = 1; depth <= maxDepth; depth++) {
255
- const nextQueue = [];
256
- for (const currentId of queue) {
257
- const neighbors = neighborStmt.all(currentId, ...edgeKinds);
258
- for (const n of neighbors) {
259
- if (noTests && isTestFile(n.file)) continue;
260
- if (n.id === targetNode.id) {
261
- if (!found) {
262
- found = true;
263
- foundDepth = depth;
264
- parent.set(n.id, { parentId: currentId, edgeKind: n.edge_kind });
265
- }
266
- alternateCount++;
267
- continue;
268
- }
269
- if (!visited.has(n.id)) {
270
- visited.add(n.id);
271
- parent.set(n.id, { parentId: currentId, edgeKind: n.edge_kind });
272
- nextQueue.push(n.id);
273
- }
274
- }
275
- }
276
- if (found) break;
277
- queue = nextQueue;
278
- if (queue.length === 0) break;
279
- }
280
-
281
- if (!found) {
282
- return {
283
- from,
284
- to,
285
- fromCandidates,
286
- toCandidates,
287
- found: false,
288
- hops: null,
289
- path: [],
290
- alternateCount: 0,
291
- edgeKinds,
292
- reverse,
293
- maxDepth,
294
- };
295
- }
296
-
297
- // alternateCount includes the one we kept; subtract 1 for "alternates"
298
- alternateCount = Math.max(0, alternateCount - 1);
299
-
300
- // Reconstruct path from target back to source
301
- const pathIds = [targetNode.id];
302
- let cur = targetNode.id;
303
- while (cur !== sourceNode.id) {
304
- const p = parent.get(cur);
305
- pathIds.push(p.parentId);
306
- cur = p.parentId;
307
- }
308
- pathIds.reverse();
309
-
310
- // Build path with node info
311
- const nodeCache = new Map();
312
- const getNode = (id) => {
313
- if (nodeCache.has(id)) return nodeCache.get(id);
314
- const row = db.prepare('SELECT name, kind, file, line FROM nodes WHERE id = ?').get(id);
315
- nodeCache.set(id, row);
316
- return row;
317
- };
318
-
319
- const resultPath = pathIds.map((id, idx) => {
320
- const node = getNode(id);
321
- const edgeKind = idx === 0 ? null : parent.get(id).edgeKind;
322
- return { name: node.name, kind: node.kind, file: node.file, line: node.line, edgeKind };
323
- });
324
-
325
- return {
326
- from,
327
- to,
328
- fromCandidates,
329
- toCandidates,
330
- found: true,
331
- hops: foundDepth,
332
- path: resultPath,
333
- alternateCount,
334
- edgeKinds,
335
- reverse,
336
- maxDepth,
337
- };
338
- } finally {
339
- db.close();
340
- }
341
- }