@nithin554/code-crawler 0.0.0 → 0.1.2

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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +221 -45
  3. package/dist/config.d.ts +13 -0
  4. package/dist/config.js +32 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/crawler.d.ts +46 -0
  7. package/dist/crawler.js +303 -0
  8. package/dist/crawler.js.map +1 -0
  9. package/dist/graph/queries.d.ts +111 -0
  10. package/dist/graph/queries.js +265 -0
  11. package/dist/graph/queries.js.map +1 -0
  12. package/dist/graph/schema.d.ts +63 -0
  13. package/dist/graph/schema.js +54 -0
  14. package/dist/graph/schema.js.map +1 -0
  15. package/dist/graph/store.d.ts +66 -0
  16. package/dist/graph/store.js +251 -0
  17. package/dist/graph/store.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +133 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/parser/language.d.ts +111 -0
  22. package/dist/parser/language.js +13 -0
  23. package/dist/parser/language.js.map +1 -0
  24. package/dist/parser/languages/index.d.ts +5 -0
  25. package/dist/parser/languages/index.js +31 -0
  26. package/dist/parser/languages/index.js.map +1 -0
  27. package/dist/parser/languages/java.d.ts +10 -0
  28. package/dist/parser/languages/java.js +334 -0
  29. package/dist/parser/languages/java.js.map +1 -0
  30. package/dist/parser/treeSitter.d.ts +28 -0
  31. package/dist/parser/treeSitter.js +114 -0
  32. package/dist/parser/treeSitter.js.map +1 -0
  33. package/dist/resolver/javaResolver.d.ts +20 -0
  34. package/dist/resolver/javaResolver.js +253 -0
  35. package/dist/resolver/javaResolver.js.map +1 -0
  36. package/dist/resolver/types.d.ts +45 -0
  37. package/dist/resolver/types.js +80 -0
  38. package/dist/resolver/types.js.map +1 -0
  39. package/dist/server.d.ts +15 -0
  40. package/dist/server.js +282 -0
  41. package/dist/server.js.map +1 -0
  42. package/package.json +44 -7
@@ -0,0 +1,265 @@
1
+ function nodeToRef(node) {
2
+ return {
3
+ id: node.id,
4
+ qualifiedName: node.qualifiedName,
5
+ name: node.properties.name,
6
+ kind: node.kind,
7
+ filePath: node.filePath,
8
+ };
9
+ }
10
+ /** Resolve a node by exact id or by qualified name, favoring id. */
11
+ function resolveNode(store, symbol) {
12
+ return store.getNode(symbol) ?? store.getNodeByQualifiedName(symbol);
13
+ }
14
+ /**
15
+ * Find every symbol that calls the given symbol, directly or transitively.
16
+ * Each row includes the edge chain depth so clients can render a call tree.
17
+ */
18
+ export function getCallers(store, symbol, opts = {}) {
19
+ const target = resolveNode(store, symbol);
20
+ if (!target)
21
+ return null;
22
+ const transitive = opts.transitive ?? true;
23
+ const maxDepth = Math.max(1, opts.maxDepth ?? store.maxDepth ?? 10);
24
+ const limit = opts.limit ?? 100;
25
+ if (!transitive) {
26
+ const rows = store.raw(`SELECT n.id, n.qualified_name, n.kind, n.file_path, n.properties, e.properties AS edge_props
27
+ FROM edges e
28
+ JOIN nodes n ON n.id = e.source
29
+ WHERE e.target = ? AND e.kind = 'CALLS'
30
+ ORDER BY e.source
31
+ LIMIT ?`, symbol, limit);
32
+ return {
33
+ target: nodeToRef(target),
34
+ callers: rows.map((r) => ({
35
+ caller: rowToRef(r),
36
+ depth: 1,
37
+ callSiteLine: edgeLine(r.edge_props),
38
+ })),
39
+ };
40
+ }
41
+ const rows = store.raw(`WITH RECURSIVE callers(id, depth, path) AS (
42
+ SELECT e.source, 1, e.source || '/' || e.target
43
+ FROM edges e
44
+ WHERE e.target = ? AND e.kind = 'CALLS'
45
+ UNION ALL
46
+ SELECT e.source, c.depth + 1, c.path || '/' || e.source
47
+ FROM edges e
48
+ JOIN callers c ON e.target = c.id
49
+ WHERE e.kind = 'CALLS'
50
+ AND c.depth < ?
51
+ AND e.source || '/' || e.target NOT LIKE c.path || '/%'
52
+ )
53
+ SELECT n.id, n.qualified_name, n.kind, n.file_path, n.properties, c.depth
54
+ FROM callers c
55
+ JOIN nodes n ON n.id = c.id
56
+ ORDER BY c.depth, n.id
57
+ LIMIT ?`, symbol, maxDepth, limit);
58
+ return {
59
+ target: nodeToRef(target),
60
+ callers: rows.map((r) => ({ caller: rowToRef(r), depth: r.depth })),
61
+ };
62
+ }
63
+ /**
64
+ * Find every symbol the given symbol calls, directly or transitively.
65
+ */
66
+ export function getCallees(store, symbol, opts = {}) {
67
+ const source = resolveNode(store, symbol);
68
+ if (!source)
69
+ return null;
70
+ const transitive = opts.transitive ?? true;
71
+ const maxDepth = Math.max(1, opts.maxDepth ?? store.maxDepth ?? 10);
72
+ const limit = opts.limit ?? 100;
73
+ if (!transitive) {
74
+ const rows = store.raw(`SELECT n.id, n.qualified_name, n.kind, n.file_path, n.properties, e.properties AS edge_props
75
+ FROM edges e
76
+ JOIN nodes n ON n.id = e.target
77
+ WHERE e.source = ? AND e.kind = 'CALLS'
78
+ ORDER BY e.target
79
+ LIMIT ?`, symbol, limit);
80
+ return {
81
+ source: nodeToRef(source),
82
+ callees: rows.map((r) => ({
83
+ callee: rowToRef(r),
84
+ depth: 1,
85
+ callSiteLine: edgeLine(r.edge_props),
86
+ })),
87
+ };
88
+ }
89
+ const rows = store.raw(`WITH RECURSIVE callees(id, depth, path) AS (
90
+ SELECT e.target, 1, e.source || '/' || e.target
91
+ FROM edges e
92
+ WHERE e.source = ? AND e.kind = 'CALLS'
93
+ UNION ALL
94
+ SELECT e.target, c.depth + 1, c.path || '/' || e.target
95
+ FROM edges e
96
+ JOIN callees c ON e.source = c.id
97
+ WHERE e.kind = 'CALLS'
98
+ AND c.depth < ?
99
+ AND e.source || '/' || e.target NOT LIKE c.path || '/%'
100
+ )
101
+ SELECT n.id, n.qualified_name, n.kind, n.file_path, n.properties, c.depth
102
+ FROM callees c
103
+ JOIN nodes n ON n.id = c.id
104
+ ORDER BY c.depth, n.id
105
+ LIMIT ?`, symbol, maxDepth, limit);
106
+ return {
107
+ source: nodeToRef(source),
108
+ callees: rows.map((r) => ({ callee: rowToRef(r), depth: r.depth })),
109
+ };
110
+ }
111
+ /**
112
+ * Find up to `limit` static call paths between two symbols.
113
+ * BFS over CALLS edges so the shortest paths come first.
114
+ */
115
+ export function tracePath(store, from, to, opts = {}) {
116
+ const start = resolveNode(store, from);
117
+ const goal = resolveNode(store, to);
118
+ if (!start || !goal)
119
+ return null;
120
+ const maxDepth = Math.max(1, opts.maxDepth ?? store.maxDepth ?? 10);
121
+ const limit = opts.limit ?? 10;
122
+ // BFS in SQL via recursive CTE that accumulates the path taken.
123
+ const rows = store.raw(`WITH RECURSIVE paths(id, depth, path, edge_path) AS (
124
+ SELECT e.target, 1, e.source || '/' || e.target, e.source || '/' || e.target
125
+ FROM edges e
126
+ WHERE e.source = ? AND e.kind = 'CALLS'
127
+ UNION ALL
128
+ SELECT e.target, p.depth + 1, p.path || '/' || e.target, p.edge_path || '|' || e.source || '/' || e.target
129
+ FROM edges e
130
+ JOIN paths p ON e.source = p.id
131
+ WHERE e.kind = 'CALLS'
132
+ AND p.depth < ?
133
+ AND instr('|' || p.path || '|', '|' || e.target || '|') = 0
134
+ )
135
+ SELECT path, edge_path, depth
136
+ FROM paths
137
+ WHERE id = ?
138
+ ORDER BY depth
139
+ LIMIT ?`, from, maxDepth, to, limit);
140
+ return rows.map((r) => {
141
+ const ids = r.path.split("/");
142
+ const edges = r.edge_path.split("|").map((pair) => {
143
+ const [src, tgt] = pair.split("/");
144
+ return { source: src ?? "", target: tgt ?? "" };
145
+ });
146
+ return { path: ids, length: r.depth, edges };
147
+ });
148
+ }
149
+ /**
150
+ * Extract the neighborhood around a symbol (any edge kinds), useful for
151
+ * visualization and for letting an LLM see the local shape of the graph.
152
+ */
153
+ export function getSubgraph(store, symbol, opts = {}) {
154
+ const center = resolveNode(store, symbol);
155
+ if (!center)
156
+ return { center: null, nodes: [], edges: [] };
157
+ const radius = Math.max(1, opts.radius ?? 2);
158
+ const edgeKinds = opts.edgeKinds ?? ["CALLS", "DECLARED_IN", "CONTAINS", "EXTENDS", "IMPLEMENTS", "REFERENCES", "IMPORTS"];
159
+ const limit = opts.limit ?? 500;
160
+ const kinds = edgeKinds.map((k) => `'${k}'`).join(",");
161
+ const rows = store.raw(`WITH RECURSIVE reach(id, depth) AS (
162
+ SELECT ? , 0
163
+ UNION
164
+ SELECT e.target, r.depth + 1
165
+ FROM edges e
166
+ JOIN reach r ON e.source = r.id
167
+ WHERE e.kind IN (${kinds}) AND r.depth < ?
168
+ UNION
169
+ SELECT e.source, r.depth + 1
170
+ FROM edges e
171
+ JOIN reach r ON e.target = r.id
172
+ WHERE e.kind IN (${kinds}) AND r.depth < ?
173
+ )
174
+ SELECT n.id, n.qualified_name, n.kind, n.file_path, n.properties, r.depth
175
+ FROM reach r
176
+ JOIN nodes n ON n.id = r.id
177
+ ORDER BY r.depth, n.id
178
+ LIMIT ?`, symbol, radius, radius, limit);
179
+ const nodes = rows.map(rowToRef);
180
+ const ids = nodes.map((n) => n.id);
181
+ if (ids.length === 0)
182
+ return { center: nodeToRef(center), nodes, edges: [] };
183
+ const placeholders = ids.map(() => "?").join(",");
184
+ const edgeRows = store.raw(`SELECT source, target, kind, properties
185
+ FROM edges
186
+ WHERE kind IN (${kinds})
187
+ AND source IN (${placeholders}) AND target IN (${placeholders})
188
+ LIMIT ?`, ...ids, ...ids, limit);
189
+ return {
190
+ center: nodeToRef(center),
191
+ nodes,
192
+ edges: edgeRows.map((r) => ({
193
+ source: r.source,
194
+ target: r.target,
195
+ kind: r.kind,
196
+ callSiteLine: edgeLine(r.properties),
197
+ })),
198
+ };
199
+ }
200
+ /**
201
+ * Fuzzy symbol lookup by short name or FQN. Matches substring of either the
202
+ * id, the qualified name, or the display name.
203
+ */
204
+ export function searchSymbols(store, query, opts = {}) {
205
+ const q = query.trim().toLowerCase();
206
+ if (!q)
207
+ return [];
208
+ const limit = opts.limit ?? store.defaultLimit ?? 50;
209
+ const like = `%${q}%`;
210
+ const kindClause = opts.kind ? "AND n.kind = ?" : "";
211
+ const params = [like, like, like];
212
+ if (opts.kind)
213
+ params.push(opts.kind);
214
+ // ORDER BY CASE params: exact-qualified-name, then prefix/name match
215
+ params.push(q, like, limit);
216
+ const rows = store.raw(`SELECT n.id, n.qualified_name, n.kind, n.file_path, n.properties
217
+ FROM nodes n
218
+ WHERE LOWER(n.id) LIKE ? OR LOWER(n.qualified_name) LIKE ? OR LOWER(n.properties) LIKE ?
219
+ ${kindClause}
220
+ ORDER BY
221
+ CASE WHEN LOWER(n.qualified_name) = ? THEN 0
222
+ WHEN LOWER(n.id) LIKE ? THEN 1
223
+ ELSE 2 END,
224
+ n.qualified_name
225
+ LIMIT ?`, ...params);
226
+ // Re-rank: exact-qualified-name matches first.
227
+ return rows
228
+ .map((r) => rowToRef(r))
229
+ .sort((a, b) => rank(a, q) - rank(b, q));
230
+ }
231
+ function rank(ref, q) {
232
+ if (ref.qualifiedName.toLowerCase() === q)
233
+ return 0;
234
+ const name = ref.name?.toLowerCase() ?? "";
235
+ if (name === q)
236
+ return 1;
237
+ if (ref.qualifiedName.toLowerCase().startsWith(q))
238
+ return 2;
239
+ return 3;
240
+ }
241
+ /** Suggest similar symbols when an exact lookup fails. */
242
+ export function suggestSymbols(store, symbol, limit = 8) {
243
+ const tokens = symbol
244
+ .split(/[.#$<>]/)
245
+ .filter((t) => t.length > 1)
246
+ .slice(-1);
247
+ const best = tokens[0] ?? symbol.slice(-20);
248
+ return searchSymbols(store, best, { limit });
249
+ }
250
+ function rowToRef(r) {
251
+ return {
252
+ id: r.id,
253
+ qualifiedName: r.qualified_name,
254
+ kind: r.kind,
255
+ filePath: r.file_path,
256
+ name: JSON.parse(r.properties).name,
257
+ };
258
+ }
259
+ function edgeLine(props) {
260
+ if (!props)
261
+ return undefined;
262
+ const line = JSON.parse(props).line;
263
+ return typeof line === "number" ? line : undefined;
264
+ }
265
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/graph/queries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Graph schema for the code-crawler property graph.
3
+ *
4
+ * The graph is a labelled property graph stored in SQLite:
5
+ * - Nodes represent source-level symbols (files, classes, methods, fields, ...)
6
+ * - Directed edges represent relationships between symbols (calls, contains, ...)
7
+ *
8
+ * Both nodes and edges carry an arbitrary `properties` JSON blob so languages
9
+ * can attach extra metadata (signatures, modifiers, confidence scores) without
10
+ * schema migrations.
11
+ */
12
+ export declare const NODE_KINDS: readonly ["file", "package", "class", "interface", "enum", "method", "constructor", "field", "import", "unknown_symbol"];
13
+ export type NodeKind = (typeof NODE_KINDS)[number];
14
+ export declare const EDGE_KINDS: readonly ["CALLS", "DECLARED_IN", "CONTAINS", "IMPLEMENTS", "EXTENDS", "IMPORTS", "REFERENCES"];
15
+ export type EdgeKind = (typeof EDGE_KINDS)[number];
16
+ /** Kinds that may appear as call *targets* (nodes at the arrow end of CALLS). */
17
+ export declare const CALLABLE_KINDS: readonly NodeKind[];
18
+ export interface NodeProperties {
19
+ /** Zero-based line of the declaration start. */
20
+ startLine?: number;
21
+ /** Zero-based line of the declaration end. */
22
+ endLine?: number;
23
+ /** Short display name (method/field/class simple name). */
24
+ name?: string;
25
+ /** Fully-qualified name when distinct from the node id. */
26
+ qualifiedName?: string;
27
+ /** Free-form language-specific metadata. */
28
+ [key: string]: string | number | boolean | (string | number)[] | undefined;
29
+ }
30
+ export interface GraphNode {
31
+ id: string;
32
+ kind: NodeKind;
33
+ /** Globally unique fully-qualified name, e.g. `com.acme.Foo#run`. */
34
+ qualifiedName: string;
35
+ /** Absolute path of the source file that declares this symbol. */
36
+ filePath: string | null;
37
+ properties: NodeProperties;
38
+ }
39
+ export interface EdgeProperties {
40
+ /** Zero-based line number of the call site / reference. */
41
+ line?: number;
42
+ /** For CALLS edges: whether the target was statically resolved. */
43
+ resolved?: boolean;
44
+ /** For CALLS edges: heuristic confidence 0..1 when resolved. */
45
+ confidence?: number;
46
+ /** Free-form language-specific metadata. */
47
+ [key: string]: string | number | boolean | undefined;
48
+ }
49
+ export interface GraphEdge {
50
+ source: string;
51
+ target: string;
52
+ kind: EdgeKind;
53
+ properties: EdgeProperties;
54
+ }
55
+ /** Node id scheme. `#` separates type from member so FQNs stay readable. */
56
+ export declare function methodNodeId(qualifiedType: string, methodName: string): string;
57
+ export declare function constructorNodeId(qualifiedType: string): string;
58
+ /** Field ids use `$` so they never collide with nested-type FQNs (`.`). */
59
+ export declare function fieldNodeId(qualifiedType: string, fieldName: string): string;
60
+ /** Import nodes represent external (or unindexed) dependencies. */
61
+ export declare function importNodeId(fqn: string): string;
62
+ /** Fallback id for calls that could not be statically resolved. */
63
+ export declare function unknownNodeId(qualifiedName: string): string;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Graph schema for the code-crawler property graph.
3
+ *
4
+ * The graph is a labelled property graph stored in SQLite:
5
+ * - Nodes represent source-level symbols (files, classes, methods, fields, ...)
6
+ * - Directed edges represent relationships between symbols (calls, contains, ...)
7
+ *
8
+ * Both nodes and edges carry an arbitrary `properties` JSON blob so languages
9
+ * can attach extra metadata (signatures, modifiers, confidence scores) without
10
+ * schema migrations.
11
+ */
12
+ export const NODE_KINDS = [
13
+ "file",
14
+ "package",
15
+ "class",
16
+ "interface",
17
+ "enum",
18
+ "method",
19
+ "constructor",
20
+ "field",
21
+ "import",
22
+ "unknown_symbol",
23
+ ];
24
+ export const EDGE_KINDS = [
25
+ "CALLS",
26
+ "DECLARED_IN",
27
+ "CONTAINS",
28
+ "IMPLEMENTS",
29
+ "EXTENDS",
30
+ "IMPORTS",
31
+ "REFERENCES",
32
+ ];
33
+ /** Kinds that may appear as call *targets* (nodes at the arrow end of CALLS). */
34
+ export const CALLABLE_KINDS = ["method", "constructor"];
35
+ /** Node id scheme. `#` separates type from member so FQNs stay readable. */
36
+ export function methodNodeId(qualifiedType, methodName) {
37
+ return `${qualifiedType}#${methodName}`;
38
+ }
39
+ export function constructorNodeId(qualifiedType) {
40
+ return `${qualifiedType}#<init>`;
41
+ }
42
+ /** Field ids use `$` so they never collide with nested-type FQNs (`.`). */
43
+ export function fieldNodeId(qualifiedType, fieldName) {
44
+ return `${qualifiedType}$${fieldName}`;
45
+ }
46
+ /** Import nodes represent external (or unindexed) dependencies. */
47
+ export function importNodeId(fqn) {
48
+ return `__import__:${fqn}`;
49
+ }
50
+ /** Fallback id for calls that could not be statically resolved. */
51
+ export function unknownNodeId(qualifiedName) {
52
+ return `__unknown__:${qualifiedName}`;
53
+ }
54
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/graph/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM;IACN,SAAS;IACT,OAAO;IACP,WAAW;IACX,MAAM;IACN,QAAQ;IACR,aAAa;IACb,OAAO;IACP,QAAQ;IACR,gBAAgB;CACR,CAAC;AAGX,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO;IACP,aAAa;IACb,UAAU;IACV,YAAY;IACZ,SAAS;IACT,SAAS;IACT,YAAY;CACJ,CAAC;AAGX,iFAAiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAwB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AA2C7E,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,aAAqB,EAAE,UAAkB;IACpE,OAAO,GAAG,aAAa,IAAI,UAAU,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,aAAqB;IACrD,OAAO,GAAG,aAAa,SAAS,CAAC;AACnC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,WAAW,CAAC,aAAqB,EAAE,SAAiB;IAClE,OAAO,GAAG,aAAa,IAAI,SAAS,EAAE,CAAC;AACzC,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,cAAc,GAAG,EAAE,CAAC;AAC7B,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,aAAa,CAAC,aAAqB;IACjD,OAAO,eAAe,aAAa,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import Database from "better-sqlite3";
2
+ import type { EdgeKind, GraphEdge, GraphNode, EdgeProperties } from "./schema.js";
3
+ export interface StoreStats {
4
+ nodes: number;
5
+ edges: number;
6
+ files: number;
7
+ lastCrawl: string | null;
8
+ }
9
+ export declare class GraphStore {
10
+ readonly db: Database.Database;
11
+ /** Default cap on transitive traversal depth (config override). */
12
+ readonly maxDepth: number;
13
+ /** Default result cap for list queries (config override). */
14
+ readonly defaultLimit: number;
15
+ private insertNodeStmt;
16
+ private insertEdgeStmt;
17
+ private deleteFileNodesStmt;
18
+ private updateMetaStmt;
19
+ constructor(dbPath: string, options?: {
20
+ maxDepth?: number;
21
+ defaultLimit?: number;
22
+ });
23
+ close(): void;
24
+ /**
25
+ * Persist a node. Idempotent: re-indexing an existing symbol just updates it.
26
+ */
27
+ upsertNode(node: GraphNode): void;
28
+ /**
29
+ * Persist multiple nodes in a single transaction for batch ingestion.
30
+ */
31
+ upsertNodes(nodes: GraphNode[]): void;
32
+ /**
33
+ * Persist an edge. Both endpoints must exist (FK enforced).
34
+ */
35
+ upsertEdge(edge: GraphEdge): void;
36
+ upsertEdges(edges: GraphEdge[]): void;
37
+ getNode(id: string): GraphNode | null;
38
+ getNodeByQualifiedName(qn: string): GraphNode | null;
39
+ /** All nodes originating from one source file (for reindex + stats). */
40
+ getFileNodes(filePath: string): GraphNode[];
41
+ /**
42
+ * Remove every node declared in a file, plus their incident edges
43
+ * (cascade). Nodes referenced by the file but declared elsewhere survive.
44
+ */
45
+ removeFile(filePath: string): void;
46
+ /**
47
+ * Rebuild the graph for a single file: drop its symbols and edges, then
48
+ * re-ingest. Call inside a caller-supplied transaction when batching.
49
+ */
50
+ replaceFile(filePath: string, nodes: GraphNode[], edges: GraphEdge[]): void;
51
+ /** Ensure every CALLS edge endpoint exists (e.g. phantom unknown symbols). */
52
+ ensureNode(node: GraphNode): void;
53
+ setMeta(key: string, value: string): void;
54
+ getMeta(key: string): string | null;
55
+ stats(): StoreStats;
56
+ clearAll(): void;
57
+ /** Run a function inside a transaction. */
58
+ withTransaction<T>(fn: () => T): T;
59
+ /**
60
+ * SQLite uses 0-based row/col; tree-sitter uses 0-based row but 1-based col.
61
+ * Store and expose tree-sitter-compatible positions (0-based line) and let
62
+ * the presentation layer add +1 where humans expect 1-based lines.
63
+ */
64
+ raw(sql: string, ...params: unknown[]): unknown;
65
+ }
66
+ export type { EdgeKind, EdgeProperties };