rho-graph 0.1.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.
- package/README.md +277 -0
- package/bin/rho-graph.js +2 -0
- package/dist/cli/commands/index-cmd.d.ts +2 -0
- package/dist/cli/commands/index-cmd.js +45 -0
- package/dist/cli/commands/index-cmd.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.js +55 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install-hook.d.ts +3 -0
- package/dist/cli/commands/install-hook.js +37 -0
- package/dist/cli/commands/install-hook.js.map +1 -0
- package/dist/cli/commands/install-mcp.d.ts +3 -0
- package/dist/cli/commands/install-mcp.js +32 -0
- package/dist/cli/commands/install-mcp.js.map +1 -0
- package/dist/cli/commands/query.d.ts +2 -0
- package/dist/cli/commands/query.js +92 -0
- package/dist/cli/commands/query.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/commands/setup.js +15 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +40 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/visualize.d.ts +2 -0
- package/dist/cli/commands/visualize.js +45 -0
- package/dist/cli/commands/visualize.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +32 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +95 -0
- package/dist/config.js.map +1 -0
- package/dist/db/connection.d.ts +13 -0
- package/dist/db/connection.js +25 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/queries.d.ts +106 -0
- package/dist/db/queries.js +247 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.d.ts +2 -0
- package/dist/db/schema.js +22 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/docker/neo4j.d.ts +5 -0
- package/dist/docker/neo4j.js +85 -0
- package/dist/docker/neo4j.js.map +1 -0
- package/dist/indexer/batch-writer.d.ts +35 -0
- package/dist/indexer/batch-writer.js +202 -0
- package/dist/indexer/batch-writer.js.map +1 -0
- package/dist/indexer/extractor.d.ts +35 -0
- package/dist/indexer/extractor.js +141 -0
- package/dist/indexer/extractor.js.map +1 -0
- package/dist/indexer/graph-writer.d.ts +12 -0
- package/dist/indexer/graph-writer.js +75 -0
- package/dist/indexer/graph-writer.js.map +1 -0
- package/dist/indexer/import-resolver.d.ts +8 -0
- package/dist/indexer/import-resolver.js +80 -0
- package/dist/indexer/import-resolver.js.map +1 -0
- package/dist/indexer/index.d.ts +21 -0
- package/dist/indexer/index.js +262 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/language-map.json +101 -0
- package/dist/indexer/parallel-pipeline.d.ts +41 -0
- package/dist/indexer/parallel-pipeline.js +82 -0
- package/dist/indexer/parallel-pipeline.js.map +1 -0
- package/dist/indexer/parser.d.ts +9 -0
- package/dist/indexer/parser.js +85 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/staleness.d.ts +12 -0
- package/dist/indexer/staleness.js +60 -0
- package/dist/indexer/staleness.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +38 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/staleness-check.d.ts +7 -0
- package/dist/mcp/staleness-check.js +31 -0
- package/dist/mcp/staleness-check.js.map +1 -0
- package/dist/mcp/tools/get-callees.d.ts +3 -0
- package/dist/mcp/tools/get-callees.js +34 -0
- package/dist/mcp/tools/get-callees.js.map +1 -0
- package/dist/mcp/tools/get-callers.d.ts +3 -0
- package/dist/mcp/tools/get-callers.js +34 -0
- package/dist/mcp/tools/get-callers.js.map +1 -0
- package/dist/mcp/tools/get-class.d.ts +3 -0
- package/dist/mcp/tools/get-class.js +42 -0
- package/dist/mcp/tools/get-class.js.map +1 -0
- package/dist/mcp/tools/get-dependencies.d.ts +3 -0
- package/dist/mcp/tools/get-dependencies.js +26 -0
- package/dist/mcp/tools/get-dependencies.js.map +1 -0
- package/dist/mcp/tools/get-dependents.d.ts +3 -0
- package/dist/mcp/tools/get-dependents.js +26 -0
- package/dist/mcp/tools/get-dependents.js.map +1 -0
- package/dist/mcp/tools/get-file-structure.d.ts +3 -0
- package/dist/mcp/tools/get-file-structure.js +33 -0
- package/dist/mcp/tools/get-file-structure.js.map +1 -0
- package/dist/mcp/tools/get-function.d.ts +3 -0
- package/dist/mcp/tools/get-function.js +34 -0
- package/dist/mcp/tools/get-function.js.map +1 -0
- package/dist/mcp/tools/get-repo-structure.d.ts +3 -0
- package/dist/mcp/tools/get-repo-structure.js +39 -0
- package/dist/mcp/tools/get-repo-structure.js.map +1 -0
- package/dist/mcp/tools/reindex.d.ts +4 -0
- package/dist/mcp/tools/reindex.js +27 -0
- package/dist/mcp/tools/reindex.js.map +1 -0
- package/dist/mcp/tools/search-code.d.ts +3 -0
- package/dist/mcp/tools/search-code.js +43 -0
- package/dist/mcp/tools/search-code.js.map +1 -0
- package/dist/visualize/public/graph.js +445 -0
- package/dist/visualize/public/index.html +88 -0
- package/dist/visualize/queries.d.ts +14 -0
- package/dist/visualize/queries.js +84 -0
- package/dist/visualize/queries.js.map +1 -0
- package/dist/visualize/server.d.ts +19 -0
- package/dist/visualize/server.js +293 -0
- package/dist/visualize/server.js.map +1 -0
- package/docker-compose.yml +16 -0
- package/package.json +69 -0
- package/src/indexer/language-map.json +128 -0
- package/src/visualize/public/graph.js +445 -0
- package/src/visualize/public/index.html +88 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempt to resolve a raw import source string (as extracted from the AST)
|
|
3
|
+
* to an absolute file path that exists in the indexed file set.
|
|
4
|
+
*
|
|
5
|
+
* Returns null if the import cannot be resolved (e.g., stdlib, third-party,
|
|
6
|
+
* or a language we don't know how to resolve).
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveImport(source: string, fromFilePath: string, language: string, filePathSet: Set<string>): string | null;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { dirname, join, resolve } from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Attempt to resolve a raw import source string (as extracted from the AST)
|
|
4
|
+
* to an absolute file path that exists in the indexed file set.
|
|
5
|
+
*
|
|
6
|
+
* Returns null if the import cannot be resolved (e.g., stdlib, third-party,
|
|
7
|
+
* or a language we don't know how to resolve).
|
|
8
|
+
*/
|
|
9
|
+
export function resolveImport(source, fromFilePath, language, filePathSet) {
|
|
10
|
+
if (language === "python") {
|
|
11
|
+
return resolvePythonImport(source, fromFilePath, filePathSet);
|
|
12
|
+
}
|
|
13
|
+
if (language === "typescript" || language === "tsx" || language === "javascript") {
|
|
14
|
+
return resolveJsImport(source, fromFilePath, filePathSet);
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
function resolvePythonImport(source, fromFilePath, filePathSet) {
|
|
19
|
+
// Count leading dots (relative import markers)
|
|
20
|
+
let dots = 0;
|
|
21
|
+
let rest = source;
|
|
22
|
+
while (rest.startsWith(".")) {
|
|
23
|
+
dots++;
|
|
24
|
+
rest = rest.slice(1);
|
|
25
|
+
}
|
|
26
|
+
const relPath = rest ? rest.split(".").join("/") : "";
|
|
27
|
+
if (dots > 0) {
|
|
28
|
+
// Relative import: 1 dot = same package dir, 2 dots = parent, etc.
|
|
29
|
+
let base = dirname(fromFilePath);
|
|
30
|
+
for (let i = 1; i < dots; i++) {
|
|
31
|
+
base = dirname(base);
|
|
32
|
+
}
|
|
33
|
+
return tryPythonCandidates(base, relPath, filePathSet);
|
|
34
|
+
}
|
|
35
|
+
// Absolute import: try file's directory first, then walk up toward repo root.
|
|
36
|
+
// filePathSet is scoped to the repo so no false matches outside it.
|
|
37
|
+
let dir = dirname(fromFilePath);
|
|
38
|
+
while (true) {
|
|
39
|
+
const result = tryPythonCandidates(dir, relPath, filePathSet);
|
|
40
|
+
if (result !== null)
|
|
41
|
+
return result;
|
|
42
|
+
const parent = dirname(dir);
|
|
43
|
+
if (parent === dir)
|
|
44
|
+
break; // reached filesystem root
|
|
45
|
+
dir = parent;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
function tryPythonCandidates(base, relPath, filePathSet) {
|
|
50
|
+
const candidates = relPath
|
|
51
|
+
? [join(base, relPath + ".py"), join(base, relPath, "__init__.py")]
|
|
52
|
+
: [join(base, "__init__.py")];
|
|
53
|
+
for (const candidate of candidates) {
|
|
54
|
+
if (filePathSet.has(candidate))
|
|
55
|
+
return candidate;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
function resolveJsImport(source, fromFilePath, filePathSet) {
|
|
60
|
+
if (!source.startsWith("./") && !source.startsWith("../"))
|
|
61
|
+
return null;
|
|
62
|
+
const base = resolve(dirname(fromFilePath), source);
|
|
63
|
+
// Try the path as-is (already has extension)
|
|
64
|
+
if (filePathSet.has(base))
|
|
65
|
+
return base;
|
|
66
|
+
// Try common extensions
|
|
67
|
+
for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
|
|
68
|
+
const candidate = base + ext;
|
|
69
|
+
if (filePathSet.has(candidate))
|
|
70
|
+
return candidate;
|
|
71
|
+
}
|
|
72
|
+
// Try as a directory index file
|
|
73
|
+
for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
|
|
74
|
+
const candidate = join(base, "index" + ext);
|
|
75
|
+
if (filePathSet.has(candidate))
|
|
76
|
+
return candidate;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=import-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-resolver.js","sourceRoot":"","sources":["../../src/indexer/import-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DbConnection } from "../db/connection.js";
|
|
2
|
+
import type { IndexConfig } from "../config.js";
|
|
3
|
+
export declare function discoverFiles(rootPath: string, config: IndexConfig): Promise<string[]>;
|
|
4
|
+
export interface IndexResult {
|
|
5
|
+
filesIndexed: number;
|
|
6
|
+
functionsFound: number;
|
|
7
|
+
classesFound: number;
|
|
8
|
+
orphansRemoved: number;
|
|
9
|
+
errors: Array<{
|
|
10
|
+
file: string;
|
|
11
|
+
error: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare function indexRepository(db: DbConnection, repoPath: string, config: IndexConfig, options?: {
|
|
15
|
+
changedOnly?: boolean;
|
|
16
|
+
specificPath?: string;
|
|
17
|
+
concurrency?: number;
|
|
18
|
+
maxMemoryMB?: number;
|
|
19
|
+
onProgress?: (current: number, total: number, file: string) => void;
|
|
20
|
+
onFlushProgress?: (completed: number, total: number) => void;
|
|
21
|
+
}): Promise<IndexResult>;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { resolve, relative } from "node:path";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { glob } from "glob";
|
|
4
|
+
import { minimatch } from "minimatch";
|
|
5
|
+
import { initParser, parseFile, detectLanguage } from "./parser.js";
|
|
6
|
+
import { extractGraphEntities } from "./extractor.js";
|
|
7
|
+
import { writeRepoOnce } from "./graph-writer.js";
|
|
8
|
+
import { BatchGraphWriter } from "./batch-writer.js";
|
|
9
|
+
import { getRepositoryCommit, upsertRepositoryWithCommit, deleteFileAndRelationships, getAllFilePathsUnderPrefix, batchDeleteOrphanFiles, } from "../db/queries.js";
|
|
10
|
+
import { computeFileHash, getFileMtime, isFileStale, getChangedFilesSinceCommit, getCurrentCommitSha } from "./staleness.js";
|
|
11
|
+
import { runParallelPipeline } from "./parallel-pipeline.js";
|
|
12
|
+
/**
|
|
13
|
+
* Attempt to list files via git, which natively respects .gitignore.
|
|
14
|
+
* Returns null if not a git repo or git is unavailable.
|
|
15
|
+
*/
|
|
16
|
+
function getGitFiles(absRoot) {
|
|
17
|
+
try {
|
|
18
|
+
const output = execFileSync("git", ["ls-files", "--cached", "--others", "--exclude-standard", "-z"], { cwd: absRoot, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
19
|
+
return output.split("\0").filter(Boolean).map((f) => resolve(absRoot, f));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function discoverFiles(rootPath, config) {
|
|
26
|
+
const absRoot = resolve(rootPath);
|
|
27
|
+
const excludePatterns = config.exclude.map((e) => e.includes("/") ? e : `**/${e}/**`);
|
|
28
|
+
// Prefer git ls-files: it natively respects .gitignore, so node_modules
|
|
29
|
+
// and virtual environments are excluded without needing explicit config.
|
|
30
|
+
const gitFiles = getGitFiles(absRoot);
|
|
31
|
+
if (gitFiles !== null) {
|
|
32
|
+
return gitFiles.filter((absPath) => {
|
|
33
|
+
const rel = relative(absRoot, absPath);
|
|
34
|
+
const matchesInclude = config.include.some((p) => minimatch(rel, p, { dot: true }));
|
|
35
|
+
const matchesExclude = excludePatterns.some((p) => minimatch(rel, p, { dot: true }));
|
|
36
|
+
return matchesInclude && !matchesExclude;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// Fallback for non-git directories: use glob with manual exclude patterns.
|
|
40
|
+
const allFiles = [];
|
|
41
|
+
for (const pattern of config.include) {
|
|
42
|
+
const matches = await glob(pattern, {
|
|
43
|
+
cwd: absRoot,
|
|
44
|
+
absolute: true,
|
|
45
|
+
ignore: excludePatterns,
|
|
46
|
+
nodir: true,
|
|
47
|
+
});
|
|
48
|
+
allFiles.push(...matches);
|
|
49
|
+
}
|
|
50
|
+
return [...new Set(allFiles)];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Remove File nodes (and their child Function/Class nodes) that exist in the
|
|
54
|
+
* graph under `pathPrefix` but are no longer in the discovered file set.
|
|
55
|
+
*
|
|
56
|
+
* This is the "self-healing" pass: if a previous index run wrote files that
|
|
57
|
+
* shouldn't have been indexed (e.g., venv contents written before .gitignore
|
|
58
|
+
* was respected, or a file that was deleted on disk), this removes them on
|
|
59
|
+
* the next full re-index.
|
|
60
|
+
*
|
|
61
|
+
* Safety: if discovery returned zero files but the graph has files indexed
|
|
62
|
+
* under this prefix, we refuse to delete. That guards against a botched
|
|
63
|
+
* discovery (wrong path, broken git, transient I/O failure) silently
|
|
64
|
+
* nuking the entire repo's graph.
|
|
65
|
+
*/
|
|
66
|
+
const ORPHAN_DELETE_CHUNK_SIZE = 500;
|
|
67
|
+
async function cleanOrphanedFiles(db, pathPrefix, discoveredFiles) {
|
|
68
|
+
const session = db.session();
|
|
69
|
+
try {
|
|
70
|
+
const listQ = getAllFilePathsUnderPrefix({ pathPrefix });
|
|
71
|
+
const result = await session.run(listQ.cypher, listQ.params);
|
|
72
|
+
const indexedPaths = result.records.map((r) => r.get("path"));
|
|
73
|
+
const orphans = indexedPaths.filter((p) => !discoveredFiles.has(p));
|
|
74
|
+
if (orphans.length === 0)
|
|
75
|
+
return 0;
|
|
76
|
+
if (discoveredFiles.size === 0) {
|
|
77
|
+
console.warn(`[indexer] orphan cleanup skipped: discovery returned 0 files but ${indexedPaths.length} are indexed under ${pathPrefix}. ` +
|
|
78
|
+
`Refusing to delete to avoid wiping the graph on a botched discovery. ` +
|
|
79
|
+
`If this is intentional, remove the repo manually.`);
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
// Chunk the deletes: a single UNWIND of thousands of DETACH DELETEs can
|
|
83
|
+
// exceed Neo4j's per-transaction memory budget (MemoryPoolOutOfMemoryError).
|
|
84
|
+
// 500 per chunk keeps each tx small while still cutting round-trips ~500x
|
|
85
|
+
// vs. one-by-one. The trade-off: a partial run leaves some orphans, which
|
|
86
|
+
// the next index will pick up — acceptable for an idempotent cleanup.
|
|
87
|
+
let deleted = 0;
|
|
88
|
+
for (let i = 0; i < orphans.length; i += ORPHAN_DELETE_CHUNK_SIZE) {
|
|
89
|
+
const chunk = orphans.slice(i, i + ORPHAN_DELETE_CHUNK_SIZE);
|
|
90
|
+
const deleteQ = batchDeleteOrphanFiles(chunk);
|
|
91
|
+
await session.run(deleteQ.cypher, deleteQ.params);
|
|
92
|
+
deleted += chunk.length;
|
|
93
|
+
}
|
|
94
|
+
return deleted;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
await session.close();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export async function indexRepository(db, repoPath, config, options = {}) {
|
|
101
|
+
const absRoot = resolve(repoPath);
|
|
102
|
+
await initParser();
|
|
103
|
+
let files;
|
|
104
|
+
if (options.specificPath) {
|
|
105
|
+
files = await discoverFiles(resolve(absRoot, options.specificPath), config);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
files = await discoverFiles(absRoot, config);
|
|
109
|
+
}
|
|
110
|
+
// Filter to supported languages
|
|
111
|
+
files = files.filter((f) => detectLanguage(f) !== null);
|
|
112
|
+
// Build the full set of discovered file paths for import resolution
|
|
113
|
+
const filePathSet = new Set(files);
|
|
114
|
+
// If changedOnly, check staleness against existing graph
|
|
115
|
+
if (options.changedOnly) {
|
|
116
|
+
// Try git-based incremental first
|
|
117
|
+
const session = db.session();
|
|
118
|
+
let usedGitBased = false;
|
|
119
|
+
try {
|
|
120
|
+
const commitQ = getRepositoryCommit({ path: absRoot });
|
|
121
|
+
const result = await session.run(commitQ.cypher, commitQ.params);
|
|
122
|
+
const lastCommit = result.records[0]?.get("lastIndexedCommit") ?? null;
|
|
123
|
+
if (lastCommit) {
|
|
124
|
+
const diff = getChangedFilesSinceCommit(absRoot, lastCommit, { includeDeleted: true });
|
|
125
|
+
if (diff.error) {
|
|
126
|
+
// Git failed (invalid SHA, shallow clone, etc.) — fall through to hash/mtime
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Remove deleted files from the index
|
|
130
|
+
for (const relPath of diff.deleted) {
|
|
131
|
+
const absPath = resolve(absRoot, relPath);
|
|
132
|
+
const deleteQ = deleteFileAndRelationships({ filePath: absPath });
|
|
133
|
+
await session.run(deleteQ.cypher, deleteQ.params); // let errors propagate
|
|
134
|
+
}
|
|
135
|
+
// Filter files to only changed ones
|
|
136
|
+
const changedAbsPaths = new Set(diff.changed.map((f) => resolve(absRoot, f)));
|
|
137
|
+
files = files.filter((f) => changedAbsPaths.has(f));
|
|
138
|
+
usedGitBased = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await session.close();
|
|
144
|
+
}
|
|
145
|
+
// Fall back to mtime/hash-based staleness if git-based wasn't used
|
|
146
|
+
if (!usedGitBased) {
|
|
147
|
+
const session2 = db.session();
|
|
148
|
+
try {
|
|
149
|
+
const result = await session2.run("MATCH (f:File) WHERE f.path STARTS WITH $repoPath RETURN f.path AS path, f.hash AS hash, f.lastModified AS lastModified", { repoPath: absRoot });
|
|
150
|
+
const indexed = new Map(result.records.map((r) => [
|
|
151
|
+
r.get("path"),
|
|
152
|
+
{ hash: r.get("hash"), lastModified: r.get("lastModified") },
|
|
153
|
+
]));
|
|
154
|
+
files = files.filter((f) => {
|
|
155
|
+
const existing = indexed.get(f);
|
|
156
|
+
if (!existing)
|
|
157
|
+
return true;
|
|
158
|
+
return isFileStale(f, existing.hash, existing.lastModified);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
await session2.close();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const result = {
|
|
167
|
+
filesIndexed: 0,
|
|
168
|
+
functionsFound: 0,
|
|
169
|
+
classesFound: 0,
|
|
170
|
+
orphansRemoved: 0,
|
|
171
|
+
errors: [],
|
|
172
|
+
};
|
|
173
|
+
// Snapshot of what discovery returned, for orphan cleanup later. We capture
|
|
174
|
+
// this before any post-discovery filtering so the cleanup compares against
|
|
175
|
+
// the full set of files we *intend* to manage on this run.
|
|
176
|
+
const discoveredSet = options.changedOnly ? null : new Set(files);
|
|
177
|
+
await writeRepoOnce(db, absRoot);
|
|
178
|
+
const concurrency = options.concurrency ?? 8;
|
|
179
|
+
const maxMemoryBytes = (options.maxMemoryMB ?? 8192) * 1024 * 1024;
|
|
180
|
+
if (concurrency > 1) {
|
|
181
|
+
const batchWriter = new BatchGraphWriter(db, { filePathSet });
|
|
182
|
+
const pipelineResult = await runParallelPipeline({
|
|
183
|
+
files,
|
|
184
|
+
absRoot,
|
|
185
|
+
concurrency,
|
|
186
|
+
maxMemoryBytes,
|
|
187
|
+
parseFn: parseFile,
|
|
188
|
+
extractFn: extractGraphEntities,
|
|
189
|
+
batchWriter,
|
|
190
|
+
computeHashFn: computeFileHash,
|
|
191
|
+
getMtimeFn: getFileMtime,
|
|
192
|
+
onProgress: options.onProgress,
|
|
193
|
+
onFlushProgress: options.onFlushProgress,
|
|
194
|
+
});
|
|
195
|
+
result.filesIndexed = pipelineResult.filesIndexed;
|
|
196
|
+
result.functionsFound = pipelineResult.functionsFound;
|
|
197
|
+
result.classesFound = pipelineResult.classesFound;
|
|
198
|
+
result.errors = pipelineResult.errors;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Sequential fallback
|
|
202
|
+
const batchWriter = new BatchGraphWriter(db, { filePathSet });
|
|
203
|
+
for (let i = 0; i < files.length; i++) {
|
|
204
|
+
const file = files[i];
|
|
205
|
+
options.onProgress?.(i + 1, files.length, file);
|
|
206
|
+
try {
|
|
207
|
+
const parseResult = await parseFile(file);
|
|
208
|
+
if (!parseResult)
|
|
209
|
+
continue;
|
|
210
|
+
let entities;
|
|
211
|
+
try {
|
|
212
|
+
entities = extractGraphEntities(parseResult.tree, parseResult.language, parseResult.source, file);
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
parseResult.tree.delete();
|
|
216
|
+
}
|
|
217
|
+
batchWriter.add(entities, {
|
|
218
|
+
filePath: file, relativePath: relative(absRoot, file), repoPath: absRoot,
|
|
219
|
+
language: parseResult.language,
|
|
220
|
+
hash: computeFileHash(file, parseResult.source),
|
|
221
|
+
lastModified: getFileMtime(file),
|
|
222
|
+
});
|
|
223
|
+
result.filesIndexed++;
|
|
224
|
+
result.functionsFound += entities.functions.length;
|
|
225
|
+
result.classesFound += entities.classes.length;
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
result.errors.push({ file, error: error instanceof Error ? error.message : String(error) });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
await batchWriter.waitForPendingFlush();
|
|
232
|
+
await batchWriter.flush();
|
|
233
|
+
}
|
|
234
|
+
// Orphan cleanup: remove File nodes that exist in the graph under our scope
|
|
235
|
+
// but weren't in this run's discovered set. Skipped for changedOnly because
|
|
236
|
+
// the git-diff path above already handles deletions for the incremental case.
|
|
237
|
+
if (discoveredSet !== null) {
|
|
238
|
+
const cleanupRoot = options.specificPath
|
|
239
|
+
? resolve(absRoot, options.specificPath)
|
|
240
|
+
: absRoot;
|
|
241
|
+
result.orphansRemoved = await cleanOrphanedFiles(db, cleanupRoot, discoveredSet);
|
|
242
|
+
}
|
|
243
|
+
if (result.errors.length === 0) {
|
|
244
|
+
const commitSha = getCurrentCommitSha(absRoot);
|
|
245
|
+
if (commitSha) {
|
|
246
|
+
const session = db.session();
|
|
247
|
+
try {
|
|
248
|
+
const q = upsertRepositoryWithCommit({
|
|
249
|
+
path: absRoot,
|
|
250
|
+
name: absRoot.split("/").pop() || absRoot,
|
|
251
|
+
lastIndexedCommit: commitSha,
|
|
252
|
+
});
|
|
253
|
+
await session.run(q.cypher, q.params);
|
|
254
|
+
}
|
|
255
|
+
finally {
|
|
256
|
+
await session.close();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"typescript": {
|
|
3
|
+
"function": ["function_declaration", "arrow_function", "method_definition"],
|
|
4
|
+
"class": ["class_declaration"],
|
|
5
|
+
"import": ["import_statement"],
|
|
6
|
+
"call": ["call_expression"],
|
|
7
|
+
"name_field": "name",
|
|
8
|
+
"body_field": "body",
|
|
9
|
+
"parameters_field": "parameters"
|
|
10
|
+
},
|
|
11
|
+
"tsx": {
|
|
12
|
+
"function": ["function_declaration", "arrow_function", "method_definition"],
|
|
13
|
+
"class": ["class_declaration"],
|
|
14
|
+
"import": ["import_statement"],
|
|
15
|
+
"call": ["call_expression"],
|
|
16
|
+
"name_field": "name",
|
|
17
|
+
"body_field": "body",
|
|
18
|
+
"parameters_field": "parameters"
|
|
19
|
+
},
|
|
20
|
+
"javascript": {
|
|
21
|
+
"function": ["function_declaration", "arrow_function", "method_definition"],
|
|
22
|
+
"class": ["class_declaration"],
|
|
23
|
+
"import": ["import_statement"],
|
|
24
|
+
"call": ["call_expression"],
|
|
25
|
+
"name_field": "name",
|
|
26
|
+
"body_field": "body",
|
|
27
|
+
"parameters_field": "parameters"
|
|
28
|
+
},
|
|
29
|
+
"python": {
|
|
30
|
+
"function": ["function_definition"],
|
|
31
|
+
"class": ["class_definition"],
|
|
32
|
+
"import": ["import_from_statement", "import_statement"],
|
|
33
|
+
"call": ["call"],
|
|
34
|
+
"name_field": "name",
|
|
35
|
+
"body_field": "body",
|
|
36
|
+
"parameters_field": "parameters"
|
|
37
|
+
},
|
|
38
|
+
"go": {
|
|
39
|
+
"function": ["function_declaration", "method_declaration"],
|
|
40
|
+
"class": ["type_declaration"],
|
|
41
|
+
"import": ["import_declaration", "import_spec"],
|
|
42
|
+
"call": ["call_expression"],
|
|
43
|
+
"name_field": "name",
|
|
44
|
+
"body_field": "body",
|
|
45
|
+
"parameters_field": "parameters"
|
|
46
|
+
},
|
|
47
|
+
"java": {
|
|
48
|
+
"function": ["method_declaration", "constructor_declaration"],
|
|
49
|
+
"class": ["class_declaration", "interface_declaration", "enum_declaration"],
|
|
50
|
+
"import": ["import_declaration"],
|
|
51
|
+
"call": ["method_invocation"],
|
|
52
|
+
"name_field": "name",
|
|
53
|
+
"body_field": "body",
|
|
54
|
+
"parameters_field": "parameters"
|
|
55
|
+
},
|
|
56
|
+
"rust": {
|
|
57
|
+
"function": ["function_item"],
|
|
58
|
+
"class": ["struct_item", "enum_item", "trait_item", "impl_item"],
|
|
59
|
+
"import": ["use_declaration"],
|
|
60
|
+
"call": ["call_expression"],
|
|
61
|
+
"name_field": "name",
|
|
62
|
+
"body_field": "body",
|
|
63
|
+
"parameters_field": "parameters"
|
|
64
|
+
},
|
|
65
|
+
"c": {
|
|
66
|
+
"function": ["function_definition"],
|
|
67
|
+
"class": ["struct_specifier"],
|
|
68
|
+
"import": ["preproc_include"],
|
|
69
|
+
"call": ["call_expression"],
|
|
70
|
+
"name_field": "declarator",
|
|
71
|
+
"body_field": "body",
|
|
72
|
+
"parameters_field": "parameters"
|
|
73
|
+
},
|
|
74
|
+
"cpp": {
|
|
75
|
+
"function": ["function_definition"],
|
|
76
|
+
"class": ["class_specifier", "struct_specifier"],
|
|
77
|
+
"import": ["preproc_include"],
|
|
78
|
+
"call": ["call_expression"],
|
|
79
|
+
"name_field": "declarator",
|
|
80
|
+
"body_field": "body",
|
|
81
|
+
"parameters_field": "parameters"
|
|
82
|
+
},
|
|
83
|
+
"ruby": {
|
|
84
|
+
"function": ["method", "singleton_method"],
|
|
85
|
+
"class": ["class", "module"],
|
|
86
|
+
"import": ["call"],
|
|
87
|
+
"call": ["call", "method_call"],
|
|
88
|
+
"name_field": "name",
|
|
89
|
+
"body_field": "body",
|
|
90
|
+
"parameters_field": "parameters"
|
|
91
|
+
},
|
|
92
|
+
"graphql": {
|
|
93
|
+
"function": ["operation_definition", "fragment_definition"],
|
|
94
|
+
"class": ["object_type_definition", "input_object_type_definition", "interface_type_definition", "enum_type_definition"],
|
|
95
|
+
"import": [],
|
|
96
|
+
"call": [],
|
|
97
|
+
"name_field": "name",
|
|
98
|
+
"body_field": "body",
|
|
99
|
+
"parameters_field": "arguments_definition"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { BatchGraphWriter } from "./batch-writer.js";
|
|
2
|
+
export declare class Semaphore {
|
|
3
|
+
private readonly maxConcurrency;
|
|
4
|
+
private queue;
|
|
5
|
+
private running;
|
|
6
|
+
constructor(maxConcurrency: number);
|
|
7
|
+
acquire(): Promise<() => void>;
|
|
8
|
+
private release;
|
|
9
|
+
}
|
|
10
|
+
export interface PipelineOptions {
|
|
11
|
+
files: string[];
|
|
12
|
+
absRoot: string;
|
|
13
|
+
concurrency: number;
|
|
14
|
+
maxMemoryBytes: number;
|
|
15
|
+
parseFn: (filePath: string) => Promise<{
|
|
16
|
+
tree: any;
|
|
17
|
+
language: string;
|
|
18
|
+
source: string;
|
|
19
|
+
} | null>;
|
|
20
|
+
extractFn: (tree: any, language: string, source: string, filePath: string) => {
|
|
21
|
+
functions: any[];
|
|
22
|
+
classes: any[];
|
|
23
|
+
imports: any[];
|
|
24
|
+
calls: any[];
|
|
25
|
+
};
|
|
26
|
+
batchWriter: BatchGraphWriter;
|
|
27
|
+
computeHashFn: (filePath: string, content?: string) => string;
|
|
28
|
+
getMtimeFn: (filePath: string) => number;
|
|
29
|
+
onProgress?: (current: number, total: number, file: string) => void;
|
|
30
|
+
onFlushProgress?: (completed: number, total: number) => void;
|
|
31
|
+
}
|
|
32
|
+
export interface PipelineResult {
|
|
33
|
+
filesIndexed: number;
|
|
34
|
+
functionsFound: number;
|
|
35
|
+
classesFound: number;
|
|
36
|
+
errors: Array<{
|
|
37
|
+
file: string;
|
|
38
|
+
error: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
export declare function runParallelPipeline(options: PipelineOptions): Promise<PipelineResult>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
export class Semaphore {
|
|
3
|
+
maxConcurrency;
|
|
4
|
+
queue = [];
|
|
5
|
+
running = 0;
|
|
6
|
+
constructor(maxConcurrency) {
|
|
7
|
+
this.maxConcurrency = maxConcurrency;
|
|
8
|
+
}
|
|
9
|
+
async acquire() {
|
|
10
|
+
if (this.running < this.maxConcurrency) {
|
|
11
|
+
this.running++;
|
|
12
|
+
return () => this.release();
|
|
13
|
+
}
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
this.queue.push(() => {
|
|
16
|
+
this.running++;
|
|
17
|
+
resolve(() => this.release());
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
release() {
|
|
22
|
+
this.running--;
|
|
23
|
+
const next = this.queue.shift();
|
|
24
|
+
if (next)
|
|
25
|
+
next();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function runParallelPipeline(options) {
|
|
29
|
+
const { files, absRoot, concurrency, maxMemoryBytes, parseFn, extractFn, batchWriter, computeHashFn, getMtimeFn, onProgress, onFlushProgress } = options;
|
|
30
|
+
if (onFlushProgress)
|
|
31
|
+
batchWriter.onFlushProgress = onFlushProgress;
|
|
32
|
+
const sem = new Semaphore(concurrency);
|
|
33
|
+
const result = { filesIndexed: 0, functionsFound: 0, classesFound: 0, errors: [] };
|
|
34
|
+
let progressCounter = 0;
|
|
35
|
+
const tasks = files.map((file) => async () => {
|
|
36
|
+
// Backpressure: flush BEFORE acquiring slot — fatal errors propagate out
|
|
37
|
+
while (batchWriter.estimatedMemoryBytes >= maxMemoryBytes) {
|
|
38
|
+
await batchWriter.flush();
|
|
39
|
+
}
|
|
40
|
+
const release = await sem.acquire();
|
|
41
|
+
try {
|
|
42
|
+
const parseResult = await parseFn(file);
|
|
43
|
+
if (parseResult) {
|
|
44
|
+
let entities;
|
|
45
|
+
try {
|
|
46
|
+
entities = extractFn(parseResult.tree, parseResult.language, parseResult.source, file);
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
parseResult.tree.delete();
|
|
50
|
+
}
|
|
51
|
+
batchWriter.add(entities, {
|
|
52
|
+
filePath: file,
|
|
53
|
+
relativePath: relative(absRoot, file),
|
|
54
|
+
repoPath: absRoot,
|
|
55
|
+
language: parseResult.language,
|
|
56
|
+
hash: computeHashFn(file, parseResult.source),
|
|
57
|
+
lastModified: getMtimeFn(file),
|
|
58
|
+
});
|
|
59
|
+
// Backpressure: flush if memory limit exceeded after add
|
|
60
|
+
if (batchWriter.estimatedMemoryBytes >= maxMemoryBytes) {
|
|
61
|
+
await batchWriter.flush();
|
|
62
|
+
}
|
|
63
|
+
result.filesIndexed++;
|
|
64
|
+
result.functionsFound += entities.functions.length;
|
|
65
|
+
result.classesFound += entities.classes.length;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
result.errors.push({ file, error: error instanceof Error ? error.message : String(error) });
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
progressCounter++;
|
|
73
|
+
onProgress?.(progressCounter, files.length, file);
|
|
74
|
+
release();
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await Promise.all(tasks.map((t) => t()));
|
|
78
|
+
await batchWriter.waitForPendingFlush();
|
|
79
|
+
await batchWriter.flush();
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=parallel-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-pipeline.js","sourceRoot":"","sources":["../../src/indexer/parallel-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import Parser from "web-tree-sitter";
|
|
2
|
+
export declare function detectLanguage(filePath: string): string | null;
|
|
3
|
+
export declare function initParser(): Promise<void>;
|
|
4
|
+
export interface ParseResult {
|
|
5
|
+
tree: Parser.Tree;
|
|
6
|
+
language: string;
|
|
7
|
+
source: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseFile(filePath: string): Promise<ParseResult | null>;
|