@stupidloud/codegraph 0.8.1 → 0.9.9
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 +319 -152
- package/dist/bin/codegraph.d.ts +4 -0
- package/dist/bin/codegraph.d.ts.map +1 -1
- package/dist/bin/codegraph.js +354 -90
- package/dist/bin/codegraph.js.map +1 -1
- package/dist/bin/node-version-check.d.ts +17 -0
- package/dist/bin/node-version-check.d.ts.map +1 -1
- package/dist/bin/node-version-check.js +37 -0
- package/dist/bin/node-version-check.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -11
- package/dist/config.js.map +1 -1
- package/dist/context/formatter.d.ts.map +1 -1
- package/dist/context/formatter.js +25 -6
- package/dist/context/formatter.js.map +1 -1
- package/dist/context/index.d.ts +22 -0
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +257 -6
- package/dist/context/index.js.map +1 -1
- package/dist/context/markers.d.ts +19 -0
- package/dist/context/markers.d.ts.map +1 -0
- package/dist/context/markers.js +22 -0
- package/dist/context/markers.js.map +1 -0
- package/dist/db/index.d.ts +30 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +75 -25
- package/dist/db/index.js.map +1 -1
- package/dist/db/queries.d.ts +104 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +328 -31
- package/dist/db/queries.js.map +1 -1
- package/dist/db/sqlite-adapter.d.ts +24 -23
- package/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/dist/db/sqlite-adapter.js +54 -174
- package/dist/db/sqlite-adapter.js.map +1 -1
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +6 -20
- package/dist/directory.js.map +1 -1
- package/dist/extraction/generated-detection.d.ts +30 -0
- package/dist/extraction/generated-detection.d.ts.map +1 -0
- package/dist/extraction/generated-detection.js +80 -0
- package/dist/extraction/generated-detection.js.map +1 -0
- package/dist/extraction/grammars.d.ts +23 -1
- package/dist/extraction/grammars.d.ts.map +1 -1
- package/dist/extraction/grammars.js +107 -3
- package/dist/extraction/grammars.js.map +1 -1
- package/dist/extraction/index.d.ts +22 -14
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +272 -183
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/dist/extraction/languages/c-cpp.js +45 -0
- package/dist/extraction/languages/c-cpp.js.map +1 -1
- package/dist/extraction/languages/csharp.d.ts.map +1 -1
- package/dist/extraction/languages/csharp.js +2 -1
- package/dist/extraction/languages/csharp.js.map +1 -1
- package/dist/extraction/languages/go.d.ts.map +1 -1
- package/dist/extraction/languages/go.js +18 -2
- package/dist/extraction/languages/go.js.map +1 -1
- package/dist/extraction/languages/index.d.ts.map +1 -1
- package/dist/extraction/languages/index.js +6 -0
- package/dist/extraction/languages/index.js.map +1 -1
- package/dist/extraction/languages/java.d.ts.map +1 -1
- package/dist/extraction/languages/java.js +6 -0
- package/dist/extraction/languages/java.js.map +1 -1
- package/dist/extraction/languages/kotlin.d.ts.map +1 -1
- package/dist/extraction/languages/kotlin.js +6 -0
- package/dist/extraction/languages/kotlin.js.map +1 -1
- package/dist/extraction/languages/lua.d.ts +3 -0
- package/dist/extraction/languages/lua.d.ts.map +1 -0
- package/dist/extraction/languages/lua.js +150 -0
- package/dist/extraction/languages/lua.js.map +1 -0
- package/dist/extraction/languages/luau.d.ts +3 -0
- package/dist/extraction/languages/luau.d.ts.map +1 -0
- package/dist/extraction/languages/luau.js +37 -0
- package/dist/extraction/languages/luau.js.map +1 -0
- package/dist/extraction/languages/objc.d.ts +3 -0
- package/dist/extraction/languages/objc.d.ts.map +1 -0
- package/dist/extraction/languages/objc.js +133 -0
- package/dist/extraction/languages/objc.js.map +1 -0
- package/dist/extraction/mybatis-extractor.d.ts +48 -0
- package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
- package/dist/extraction/mybatis-extractor.js +198 -0
- package/dist/extraction/mybatis-extractor.js.map +1 -0
- package/dist/extraction/tree-sitter-types.d.ts +14 -0
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.d.ts +84 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +715 -16
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/extraction/vue-extractor.d.ts +15 -0
- package/dist/extraction/vue-extractor.d.ts.map +1 -1
- package/dist/extraction/vue-extractor.js +88 -0
- package/dist/extraction/vue-extractor.js.map +1 -1
- package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
- package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
- package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
- package/dist/extraction/wasm-runtime-flags.js +106 -0
- package/dist/extraction/wasm-runtime-flags.js.map +1 -0
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +76 -38
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +77 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +133 -19
- package/dist/index.js.map +1 -1
- package/dist/installer/config-writer.d.ts +7 -8
- package/dist/installer/config-writer.d.ts.map +1 -1
- package/dist/installer/config-writer.js +7 -27
- package/dist/installer/config-writer.js.map +1 -1
- package/dist/installer/index.d.ts +51 -16
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +120 -29
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/instructions-template.d.ts +11 -21
- package/dist/installer/instructions-template.d.ts.map +1 -1
- package/dist/installer/instructions-template.js +12 -56
- package/dist/installer/instructions-template.js.map +1 -1
- package/dist/installer/targets/antigravity.d.ts +57 -0
- package/dist/installer/targets/antigravity.d.ts.map +1 -0
- package/dist/installer/targets/antigravity.js +308 -0
- package/dist/installer/targets/antigravity.js.map +1 -0
- package/dist/installer/targets/claude.d.ts +26 -1
- package/dist/installer/targets/claude.d.ts.map +1 -1
- package/dist/installer/targets/claude.js +118 -40
- package/dist/installer/targets/claude.js.map +1 -1
- package/dist/installer/targets/codex.d.ts.map +1 -1
- package/dist/installer/targets/codex.js +15 -13
- package/dist/installer/targets/codex.js.map +1 -1
- package/dist/installer/targets/cursor.d.ts.map +1 -1
- package/dist/installer/targets/cursor.js +61 -36
- package/dist/installer/targets/cursor.js.map +1 -1
- package/dist/installer/targets/gemini.d.ts +26 -0
- package/dist/installer/targets/gemini.d.ts.map +1 -0
- package/dist/installer/targets/gemini.js +167 -0
- package/dist/installer/targets/gemini.js.map +1 -0
- package/dist/installer/targets/hermes.d.ts +18 -0
- package/dist/installer/targets/hermes.d.ts.map +1 -0
- package/dist/installer/targets/hermes.js +359 -0
- package/dist/installer/targets/hermes.js.map +1 -0
- package/dist/installer/targets/kiro.d.ts +27 -0
- package/dist/installer/targets/kiro.d.ts.map +1 -0
- package/dist/installer/targets/kiro.js +178 -0
- package/dist/installer/targets/kiro.js.map +1 -0
- package/dist/installer/targets/opencode.d.ts.map +1 -1
- package/dist/installer/targets/opencode.js +15 -13
- package/dist/installer/targets/opencode.js.map +1 -1
- package/dist/installer/targets/registry.d.ts.map +1 -1
- package/dist/installer/targets/registry.js +8 -0
- package/dist/installer/targets/registry.js.map +1 -1
- package/dist/installer/targets/shared.d.ts.map +1 -1
- package/dist/installer/targets/shared.js +3 -2
- package/dist/installer/targets/shared.js.map +1 -1
- package/dist/installer/targets/types.d.ts +1 -16
- package/dist/installer/targets/types.d.ts.map +1 -1
- package/dist/mcp/daemon-paths.d.ts +46 -0
- package/dist/mcp/daemon-paths.d.ts.map +1 -0
- package/dist/mcp/daemon-paths.js +125 -0
- package/dist/mcp/daemon-paths.js.map +1 -0
- package/dist/mcp/daemon.d.ts +161 -0
- package/dist/mcp/daemon.d.ts.map +1 -0
- package/dist/mcp/daemon.js +403 -0
- package/dist/mcp/daemon.js.map +1 -0
- package/dist/mcp/engine.d.ts +105 -0
- package/dist/mcp/engine.d.ts.map +1 -0
- package/dist/mcp/engine.js +270 -0
- package/dist/mcp/engine.js.map +1 -0
- package/dist/mcp/index.d.ts +70 -52
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +355 -331
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/proxy.d.ts +81 -0
- package/dist/mcp/proxy.d.ts.map +1 -0
- package/dist/mcp/proxy.js +510 -0
- package/dist/mcp/proxy.js.map +1 -0
- package/dist/mcp/server-instructions.d.ts +1 -1
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +21 -21
- package/dist/mcp/session.d.ts +77 -0
- package/dist/mcp/session.d.ts.map +1 -0
- package/dist/mcp/session.js +294 -0
- package/dist/mcp/session.js.map +1 -0
- package/dist/mcp/tools.d.ts +171 -15
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +1714 -298
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/transport.d.ts +111 -29
- package/dist/mcp/transport.d.ts.map +1 -1
- package/dist/mcp/transport.js +181 -71
- package/dist/mcp/transport.js.map +1 -1
- package/dist/mcp/version.d.ts +19 -0
- package/dist/mcp/version.d.ts.map +1 -0
- package/dist/mcp/version.js +71 -0
- package/dist/mcp/version.js.map +1 -0
- package/dist/resolution/callback-synthesizer.d.ts +10 -0
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
- package/dist/resolution/callback-synthesizer.js +1300 -0
- package/dist/resolution/callback-synthesizer.js.map +1 -0
- package/dist/resolution/frameworks/csharp.d.ts.map +1 -1
- package/dist/resolution/frameworks/csharp.js +36 -8
- package/dist/resolution/frameworks/csharp.js.map +1 -1
- package/dist/resolution/frameworks/drupal.d.ts +51 -0
- package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
- package/dist/resolution/frameworks/drupal.js +367 -0
- package/dist/resolution/frameworks/drupal.js.map +1 -0
- package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
- package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
- package/dist/resolution/frameworks/expo-modules.js +143 -0
- package/dist/resolution/frameworks/expo-modules.js.map +1 -0
- package/dist/resolution/frameworks/express.d.ts.map +1 -1
- package/dist/resolution/frameworks/express.js +102 -19
- package/dist/resolution/frameworks/express.js.map +1 -1
- package/dist/resolution/frameworks/fabric.d.ts +3 -0
- package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
- package/dist/resolution/frameworks/fabric.js +354 -0
- package/dist/resolution/frameworks/fabric.js.map +1 -0
- package/dist/resolution/frameworks/go.d.ts.map +1 -1
- package/dist/resolution/frameworks/go.js +6 -3
- package/dist/resolution/frameworks/go.js.map +1 -1
- package/dist/resolution/frameworks/index.d.ts +6 -0
- package/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/dist/resolution/frameworks/index.js +29 -1
- package/dist/resolution/frameworks/index.js.map +1 -1
- package/dist/resolution/frameworks/java.d.ts.map +1 -1
- package/dist/resolution/frameworks/java.js +339 -12
- package/dist/resolution/frameworks/java.js.map +1 -1
- package/dist/resolution/frameworks/laravel.d.ts.map +1 -1
- package/dist/resolution/frameworks/laravel.js +17 -8
- package/dist/resolution/frameworks/laravel.js.map +1 -1
- package/dist/resolution/frameworks/nestjs.d.ts.map +1 -1
- package/dist/resolution/frameworks/nestjs.js +324 -0
- package/dist/resolution/frameworks/nestjs.js.map +1 -1
- package/dist/resolution/frameworks/play.d.ts +19 -0
- package/dist/resolution/frameworks/play.d.ts.map +1 -0
- package/dist/resolution/frameworks/play.js +111 -0
- package/dist/resolution/frameworks/play.js.map +1 -0
- package/dist/resolution/frameworks/python.d.ts.map +1 -1
- package/dist/resolution/frameworks/python.js +134 -16
- package/dist/resolution/frameworks/python.js.map +1 -1
- package/dist/resolution/frameworks/react-native.d.ts +3 -0
- package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
- package/dist/resolution/frameworks/react-native.js +360 -0
- package/dist/resolution/frameworks/react-native.js.map +1 -0
- package/dist/resolution/frameworks/react.d.ts.map +1 -1
- package/dist/resolution/frameworks/react.js +96 -3
- package/dist/resolution/frameworks/react.js.map +1 -1
- package/dist/resolution/frameworks/ruby.d.ts.map +1 -1
- package/dist/resolution/frameworks/ruby.js +106 -2
- package/dist/resolution/frameworks/ruby.js.map +1 -1
- package/dist/resolution/frameworks/rust.d.ts.map +1 -1
- package/dist/resolution/frameworks/rust.js +102 -5
- package/dist/resolution/frameworks/rust.js.map +1 -1
- package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
- package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
- package/dist/resolution/frameworks/swift-objc.js +252 -0
- package/dist/resolution/frameworks/swift-objc.js.map +1 -0
- package/dist/resolution/frameworks/swift.d.ts.map +1 -1
- package/dist/resolution/frameworks/swift.js +30 -6
- package/dist/resolution/frameworks/swift.js.map +1 -1
- package/dist/resolution/go-module.d.ts +26 -0
- package/dist/resolution/go-module.d.ts.map +1 -0
- package/dist/resolution/go-module.js +78 -0
- package/dist/resolution/go-module.js.map +1 -0
- package/dist/resolution/import-resolver.d.ts +28 -0
- package/dist/resolution/import-resolver.d.ts.map +1 -1
- package/dist/resolution/import-resolver.js +617 -5
- package/dist/resolution/import-resolver.js.map +1 -1
- package/dist/resolution/index.d.ts +11 -0
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +196 -10
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/lru-cache.d.ts +24 -0
- package/dist/resolution/lru-cache.d.ts.map +1 -0
- package/dist/resolution/lru-cache.js +62 -0
- package/dist/resolution/lru-cache.js.map +1 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +212 -0
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/resolution/swift-objc-bridge.d.ts +134 -0
- package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
- package/dist/resolution/swift-objc-bridge.js +256 -0
- package/dist/resolution/swift-objc-bridge.js.map +1 -0
- package/dist/resolution/types.d.ts +44 -0
- package/dist/resolution/types.d.ts.map +1 -1
- package/dist/resolution/workspace-packages.d.ts +48 -0
- package/dist/resolution/workspace-packages.d.ts.map +1 -0
- package/dist/resolution/workspace-packages.js +208 -0
- package/dist/resolution/workspace-packages.js.map +1 -0
- package/dist/search/query-utils.d.ts +18 -0
- package/dist/search/query-utils.d.ts.map +1 -1
- package/dist/search/query-utils.js +30 -0
- package/dist/search/query-utils.js.map +1 -1
- package/dist/sync/git-hooks.d.ts.map +1 -1
- package/dist/sync/git-hooks.js +2 -0
- package/dist/sync/git-hooks.js.map +1 -1
- package/dist/sync/index.d.ts +3 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +8 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/watcher.d.ts +214 -12
- package/dist/sync/watcher.d.ts.map +1 -1
- package/dist/sync/watcher.js +467 -55
- package/dist/sync/watcher.js.map +1 -1
- package/dist/sync/worktree.d.ts +54 -0
- package/dist/sync/worktree.d.ts.map +1 -0
- package/dist/sync/worktree.js +137 -0
- package/dist/sync/worktree.js.map +1 -0
- package/dist/types.d.ts +9 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.js +1 -1
- package/package.json +2 -2
- package/scripts/add-lang/bench.sh +60 -0
- package/scripts/add-lang/check-grammar.mjs +75 -0
- package/scripts/add-lang/dump-ast.mjs +103 -0
- package/scripts/add-lang/verify-extraction.mjs +70 -0
- package/scripts/agent-eval/arms-F.sh +21 -0
- package/scripts/agent-eval/arms-matrix.sh +37 -0
- package/scripts/agent-eval/bench-readme.sh +28 -0
- package/scripts/agent-eval/bench-why-repo.sh +22 -0
- package/scripts/agent-eval/block-read-hook.sh +19 -0
- package/scripts/agent-eval/hook-settings.json +15 -0
- package/scripts/agent-eval/itrun.sh +24 -11
- package/scripts/agent-eval/parse-arms.mjs +116 -0
- package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
- package/scripts/agent-eval/probe-context.mjs +21 -0
- package/scripts/agent-eval/probe-explore.mjs +40 -0
- package/scripts/agent-eval/probe-node.mjs +20 -0
- package/scripts/agent-eval/probe-sweep.mjs +119 -0
- package/scripts/agent-eval/probe-trace.mjs +20 -0
- package/scripts/agent-eval/run-arms.sh +56 -0
- package/scripts/agent-eval/seq-matrix.mjs +137 -0
- package/scripts/build-bundle.sh +118 -0
- package/scripts/npm-sdk.js +75 -0
- package/scripts/npm-shim.js +246 -0
- package/scripts/pack-npm.sh +119 -0
- package/scripts/prepare-release.mjs +270 -0
- package/scripts/patch-tree-sitter-dart.js +0 -112
- package/scripts/release.sh +0 -68
package/dist/extraction/index.js
CHANGED
|
@@ -41,9 +41,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
41
41
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
42
|
};
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
-
exports.loadAllGrammars = exports.loadGrammarsForLanguages = exports.initGrammars = exports.getSupportedLanguages = exports.isGrammarLoaded = exports.isLanguageSupported = exports.detectLanguage = exports.extractFromSource = exports.ExtractionOrchestrator = void 0;
|
|
44
|
+
exports.loadAllGrammars = exports.loadGrammarsForLanguages = exports.initGrammars = exports.getSupportedLanguages = exports.isGrammarLoaded = exports.isLanguageSupported = exports.isSourceFile = exports.detectLanguage = exports.extractFromSource = exports.ExtractionOrchestrator = void 0;
|
|
45
45
|
exports.hashContent = hashContent;
|
|
46
|
-
exports.
|
|
46
|
+
exports.buildDefaultIgnore = buildDefaultIgnore;
|
|
47
47
|
exports.scanDirectory = scanDirectory;
|
|
48
48
|
exports.scanDirectoryAsync = scanDirectoryAsync;
|
|
49
49
|
const fs = __importStar(require("fs"));
|
|
@@ -55,7 +55,7 @@ const tree_sitter_1 = require("./tree-sitter");
|
|
|
55
55
|
const grammars_1 = require("./grammars");
|
|
56
56
|
const errors_1 = require("../errors");
|
|
57
57
|
const utils_1 = require("../utils");
|
|
58
|
-
const
|
|
58
|
+
const ignore_1 = __importDefault(require("ignore"));
|
|
59
59
|
const frameworks_1 = require("../resolution/frameworks");
|
|
60
60
|
/**
|
|
61
61
|
* Number of files to read in parallel during indexing.
|
|
@@ -84,29 +84,87 @@ function hashContent(content) {
|
|
|
84
84
|
return crypto.createHash('sha256').update(content).digest('hex');
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
|
-
*
|
|
87
|
+
* Skip files larger than this (bytes). Generated bundles, minified JS, and
|
|
88
|
+
* vendored blobs blow the WASM heap and the worker-recycle budget for no useful
|
|
89
|
+
* symbols. 1 MB covers essentially all hand-written source.
|
|
88
90
|
*/
|
|
89
|
-
|
|
90
|
-
filePath = (0, utils_1.normalizePath)(filePath);
|
|
91
|
-
return picomatch_1.default.isMatch(filePath, pattern, { dot: true });
|
|
92
|
-
}
|
|
91
|
+
const MAX_FILE_SIZE = 1024 * 1024;
|
|
93
92
|
/**
|
|
94
|
-
*
|
|
93
|
+
* Directory names that are dependency, build, cache, or tooling output across the
|
|
94
|
+
* languages/frameworks CodeGraph supports — curated from the canonical
|
|
95
|
+
* github/gitignore templates. Excluded by default so the graph reflects your code,
|
|
96
|
+
* not third-party noise, without requiring a `.gitignore` (issue #407). The
|
|
97
|
+
* exclusion applies uniformly (git or not, tracked or not); the only opt-in is an
|
|
98
|
+
* explicit `.gitignore` negation (e.g. `!vendor/`). First-party-prone or generic
|
|
99
|
+
* names (`packages`, `lib`, `app`, `bin`, `src`, `deps`, `env`, `tmp`, `storage`,
|
|
100
|
+
* `Library`) are deliberately NOT listed, to avoid ever hiding real source.
|
|
101
|
+
*
|
|
102
|
+
* Only dirs that actually contain *indexable source* (or are enormous) earn a slot
|
|
103
|
+
* — IDE/state dirs like `.idea`/`.vs` are omitted because CodeGraph indexes only
|
|
104
|
+
* recognized source extensions, so they produce no symbols regardless.
|
|
95
105
|
*/
|
|
96
|
-
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
const DEFAULT_IGNORE_DIRS = new Set([
|
|
107
|
+
// JS / TS — dependency directories
|
|
108
|
+
'node_modules', 'bower_components', 'jspm_packages', 'web_modules',
|
|
109
|
+
'.yarn', '.pnpm-store',
|
|
110
|
+
// JS / TS — framework & bundler build / cache / deploy output
|
|
111
|
+
'.next', '.nuxt', '.svelte-kit', '.turbo', '.vite', '.parcel-cache', '.angular',
|
|
112
|
+
'.docusaurus', 'storybook-static', '.vinxi', '.nitro', 'out-tsc',
|
|
113
|
+
'.vercel', '.netlify', '.wrangler',
|
|
114
|
+
// Build output (common across ecosystems)
|
|
115
|
+
'dist', 'build', 'out', '.output',
|
|
116
|
+
// Test / coverage
|
|
117
|
+
'coverage', '.nyc_output',
|
|
118
|
+
// Python
|
|
119
|
+
'__pycache__', '__pypackages__', '.venv', 'venv', '.pixi', '.pdm-build',
|
|
120
|
+
'.mypy_cache', '.pytest_cache', '.ruff_cache', '.tox', '.nox', '.hypothesis',
|
|
121
|
+
'.ipynb_checkpoints', '.eggs',
|
|
122
|
+
// Rust / JVM (Maven, Gradle, Scala)
|
|
123
|
+
'target', '.gradle',
|
|
124
|
+
// .NET
|
|
125
|
+
'obj',
|
|
126
|
+
// Vendored deps (Go, PHP/Composer, Ruby/Bundler)
|
|
127
|
+
'vendor',
|
|
128
|
+
// Swift / iOS
|
|
129
|
+
'.build', 'Pods', 'Carthage', 'DerivedData', '.swiftpm',
|
|
130
|
+
// Dart / Flutter
|
|
131
|
+
'.dart_tool', '.pub-cache',
|
|
132
|
+
// Native (Android NDK, C/C++ deps)
|
|
133
|
+
'.cxx', '.externalNativeBuild', 'vcpkg_installed',
|
|
134
|
+
// Scala tooling
|
|
135
|
+
'.bloop', '.metals',
|
|
136
|
+
// Lua / Luau (LuaRocks)
|
|
137
|
+
'lua_modules', '.luarocks',
|
|
138
|
+
// Delphi / RAD Studio IDE backups (duplicate .pas source — would double-count)
|
|
139
|
+
'__history', '__recovery',
|
|
140
|
+
// Generic cache
|
|
141
|
+
'.cache',
|
|
142
|
+
]);
|
|
143
|
+
/** Gitignore-style patterns for the `ignore` matcher: the dirs above plus a few globs. */
|
|
144
|
+
const DEFAULT_IGNORE_PATTERNS = [
|
|
145
|
+
...Array.from(DEFAULT_IGNORE_DIRS, (d) => `${d}/`),
|
|
146
|
+
'*.egg-info/', // Python packaging metadata
|
|
147
|
+
'cmake-build-*/', // CLion / CMake build trees
|
|
148
|
+
'bazel-*/', // Bazel output symlink trees
|
|
149
|
+
];
|
|
150
|
+
/**
|
|
151
|
+
* An `ignore` matcher seeded with the built-in defaults, merged with the project's
|
|
152
|
+
* root .gitignore so a negation there (e.g. `!vendor/`) overrides a default. Shared
|
|
153
|
+
* by both enumeration paths so behavior is identical with or without git — and so
|
|
154
|
+
* the defaults apply to tracked files too (committing a dependency dir doesn't make
|
|
155
|
+
* it project code; the explicit `.gitignore` negation is the only opt-in).
|
|
156
|
+
*/
|
|
157
|
+
function buildDefaultIgnore(rootDir) {
|
|
158
|
+
const ig = (0, ignore_1.default)().add(DEFAULT_IGNORE_PATTERNS);
|
|
159
|
+
try {
|
|
160
|
+
const rootGitignore = path.join(rootDir, '.gitignore');
|
|
161
|
+
if (fs.existsSync(rootGitignore))
|
|
162
|
+
ig.add(fs.readFileSync(rootGitignore, 'utf-8'));
|
|
102
163
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (matchesGlob(filePath, pattern)) {
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
164
|
+
catch {
|
|
165
|
+
// Unreadable root .gitignore — the built-in defaults still apply.
|
|
108
166
|
}
|
|
109
|
-
return
|
|
167
|
+
return ig;
|
|
110
168
|
}
|
|
111
169
|
/**
|
|
112
170
|
* Collect git-visible files (tracked + untracked, .gitignore-respected) from the
|
|
@@ -122,38 +180,39 @@ function shouldIncludeFile(filePath, config) {
|
|
|
122
180
|
* (See issue #193.)
|
|
123
181
|
*/
|
|
124
182
|
function collectGitFiles(repoDir, prefix, files) {
|
|
125
|
-
const gitOpts = { cwd: repoDir, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'] };
|
|
183
|
+
const gitOpts = { cwd: repoDir, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true };
|
|
126
184
|
// Tracked files. --recurse-submodules pulls in files from active submodules,
|
|
127
185
|
// which the index would otherwise represent only as a commit pointer.
|
|
128
186
|
// Without this, monorepos using submodules index 0 files. (See issue #147.)
|
|
129
187
|
// Note: --recurse-submodules only supports -c/--cached and --stage modes — it
|
|
130
188
|
// can't be combined with -o, so untracked files are gathered separately below.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
189
|
+
// -z gives NUL-separated, unquoted output so non-ASCII (e.g. CJK) paths
|
|
190
|
+
// survive verbatim. Without it git octal-escapes and double-quotes such paths
|
|
191
|
+
// (the core.quotepath default), and the quoted form never matches a real file
|
|
192
|
+
// on disk → those files are silently dropped from the index. (#541)
|
|
193
|
+
const tracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-c', '--recurse-submodules'], gitOpts);
|
|
194
|
+
for (const rel of tracked.split('\0')) {
|
|
195
|
+
if (rel)
|
|
196
|
+
files.add((0, utils_1.normalizePath)(prefix + rel));
|
|
137
197
|
}
|
|
138
198
|
// Untracked files (submodules manage their own untracked state). Embedded git
|
|
139
199
|
// repos surface here as a single "subdir/" entry that git refuses to descend
|
|
140
200
|
// into — recurse into those as their own repos so their source gets indexed.
|
|
141
|
-
const untracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-o', '--exclude-standard'], gitOpts);
|
|
142
|
-
for (const
|
|
143
|
-
|
|
144
|
-
if (!trimmed)
|
|
201
|
+
const untracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '--exclude-standard'], gitOpts);
|
|
202
|
+
for (const rel of untracked.split('\0')) {
|
|
203
|
+
if (!rel)
|
|
145
204
|
continue;
|
|
146
|
-
if (
|
|
205
|
+
if (rel.endsWith('/')) {
|
|
147
206
|
// git only emits a trailing-slash directory entry for an embedded repo.
|
|
148
207
|
// Guard with a .git check anyway, and skip anything else exactly as git
|
|
149
208
|
// itself skips it (we never descend into a non-repo opaque dir).
|
|
150
|
-
const childDir = path.join(repoDir,
|
|
209
|
+
const childDir = path.join(repoDir, rel);
|
|
151
210
|
if (fs.existsSync(path.join(childDir, '.git'))) {
|
|
152
|
-
collectGitFiles(childDir, prefix +
|
|
211
|
+
collectGitFiles(childDir, prefix + rel, files);
|
|
153
212
|
}
|
|
154
213
|
continue;
|
|
155
214
|
}
|
|
156
|
-
files.add((0, utils_1.normalizePath)(prefix +
|
|
215
|
+
files.add((0, utils_1.normalizePath)(prefix + rel));
|
|
157
216
|
}
|
|
158
217
|
}
|
|
159
218
|
/**
|
|
@@ -167,11 +226,11 @@ function getGitVisibleFiles(rootDir) {
|
|
|
167
226
|
// Check if the project directory is gitignored by a parent repo.
|
|
168
227
|
// When rootDir lives inside a parent git repo that ignores it,
|
|
169
228
|
// `git ls-files` returns nothing — fall back to filesystem walk.
|
|
170
|
-
const gitRoot = (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
229
|
+
const gitRoot = (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true }).trim();
|
|
171
230
|
if (path.resolve(gitRoot) !== path.resolve(rootDir)) {
|
|
172
231
|
try {
|
|
173
232
|
// git check-ignore exits 0 if the path IS ignored, 1 if not
|
|
174
|
-
(0, child_process_1.execFileSync)('git', ['check-ignore', '-q', path.resolve(rootDir)], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
233
|
+
(0, child_process_1.execFileSync)('git', ['check-ignore', '-q', path.resolve(rootDir)], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
|
|
175
234
|
// Directory is gitignored by parent repo — fall back to filesystem walk
|
|
176
235
|
return null;
|
|
177
236
|
}
|
|
@@ -181,7 +240,11 @@ function getGitVisibleFiles(rootDir) {
|
|
|
181
240
|
}
|
|
182
241
|
const files = new Set();
|
|
183
242
|
collectGitFiles(rootDir, '', files);
|
|
184
|
-
|
|
243
|
+
// Apply built-in default ignores uniformly — to tracked files too, since
|
|
244
|
+
// committing a dependency/build dir doesn't make it project code. A
|
|
245
|
+
// `.gitignore` negation (e.g. `!vendor/`) is the explicit opt-in. (issue #407)
|
|
246
|
+
const ig = buildDefaultIgnore(rootDir);
|
|
247
|
+
return new Set([...files].filter((f) => !ig.ignores(f)));
|
|
185
248
|
}
|
|
186
249
|
catch {
|
|
187
250
|
return null;
|
|
@@ -191,9 +254,9 @@ function getGitVisibleFiles(rootDir) {
|
|
|
191
254
|
* Use `git status` to detect changed files instead of scanning every file.
|
|
192
255
|
* Returns null on failure so callers fall back to full scan.
|
|
193
256
|
*/
|
|
194
|
-
function getGitChangedFiles(rootDir
|
|
257
|
+
function getGitChangedFiles(rootDir) {
|
|
195
258
|
try {
|
|
196
|
-
const output = (0, child_process_1.execFileSync)('git', ['status', '--porcelain', '--no-renames'], { cwd: rootDir, encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
259
|
+
const output = (0, child_process_1.execFileSync)('git', ['status', '--porcelain', '--no-renames'], { cwd: rootDir, encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
|
|
197
260
|
const modified = [];
|
|
198
261
|
const added = [];
|
|
199
262
|
const deleted = [];
|
|
@@ -202,8 +265,8 @@ function getGitChangedFiles(rootDir, config) {
|
|
|
202
265
|
continue; // Minimum: "XY file"
|
|
203
266
|
const statusCode = line.substring(0, 2);
|
|
204
267
|
const filePath = (0, utils_1.normalizePath)(line.substring(3));
|
|
205
|
-
// Skip files
|
|
206
|
-
if (!
|
|
268
|
+
// Skip non-source files (git status already omits .gitignored paths).
|
|
269
|
+
if (!(0, grammars_1.isSourceFile)(filePath))
|
|
207
270
|
continue;
|
|
208
271
|
if (statusCode === '??') {
|
|
209
272
|
added.push(filePath);
|
|
@@ -223,24 +286,20 @@ function getGitChangedFiles(rootDir, config) {
|
|
|
223
286
|
}
|
|
224
287
|
}
|
|
225
288
|
/**
|
|
226
|
-
*
|
|
227
|
-
*/
|
|
228
|
-
const CODEGRAPH_IGNORE_MARKER = '.codegraphignore';
|
|
229
|
-
/**
|
|
230
|
-
* Recursively scan directory for source files.
|
|
289
|
+
* Recursively scan a directory for source files.
|
|
231
290
|
*
|
|
232
|
-
* In git repos, uses `git ls-files`
|
|
233
|
-
*
|
|
234
|
-
*
|
|
291
|
+
* In git repos, uses `git ls-files` (inherently respects .gitignore at all
|
|
292
|
+
* levels), then keeps files with a supported source extension. For non-git
|
|
293
|
+
* projects, falls back to a filesystem walk that parses .gitignore itself.
|
|
235
294
|
*/
|
|
236
|
-
function scanDirectory(rootDir,
|
|
295
|
+
function scanDirectory(rootDir, onProgress) {
|
|
237
296
|
// Fast path: use git to get all visible files (respects .gitignore everywhere)
|
|
238
297
|
const gitFiles = getGitVisibleFiles(rootDir);
|
|
239
298
|
if (gitFiles) {
|
|
240
299
|
const files = [];
|
|
241
300
|
let count = 0;
|
|
242
301
|
for (const filePath of gitFiles) {
|
|
243
|
-
if (
|
|
302
|
+
if ((0, grammars_1.isSourceFile)(filePath)) {
|
|
244
303
|
files.push(filePath);
|
|
245
304
|
count++;
|
|
246
305
|
onProgress?.(count, filePath);
|
|
@@ -249,19 +308,19 @@ function scanDirectory(rootDir, config, onProgress) {
|
|
|
249
308
|
return files;
|
|
250
309
|
}
|
|
251
310
|
// Fallback: walk filesystem for non-git projects
|
|
252
|
-
return scanDirectoryWalk(rootDir,
|
|
311
|
+
return scanDirectoryWalk(rootDir, onProgress);
|
|
253
312
|
}
|
|
254
313
|
/**
|
|
255
314
|
* Async variant of scanDirectory that yields to the event loop periodically,
|
|
256
315
|
* allowing worker threads to receive and render progress messages.
|
|
257
316
|
*/
|
|
258
|
-
async function scanDirectoryAsync(rootDir,
|
|
317
|
+
async function scanDirectoryAsync(rootDir, onProgress) {
|
|
259
318
|
const gitFiles = getGitVisibleFiles(rootDir);
|
|
260
319
|
if (gitFiles) {
|
|
261
320
|
const files = [];
|
|
262
321
|
let count = 0;
|
|
263
322
|
for (const filePath of gitFiles) {
|
|
264
|
-
if (
|
|
323
|
+
if ((0, grammars_1.isSourceFile)(filePath)) {
|
|
265
324
|
files.push(filePath);
|
|
266
325
|
count++;
|
|
267
326
|
onProgress?.(count, filePath);
|
|
@@ -273,16 +332,40 @@ async function scanDirectoryAsync(rootDir, config, onProgress) {
|
|
|
273
332
|
}
|
|
274
333
|
return files;
|
|
275
334
|
}
|
|
276
|
-
return scanDirectoryWalk(rootDir,
|
|
335
|
+
return scanDirectoryWalk(rootDir, onProgress);
|
|
277
336
|
}
|
|
278
337
|
/**
|
|
279
338
|
* Filesystem walk fallback for non-git projects.
|
|
280
339
|
*/
|
|
281
|
-
function scanDirectoryWalk(rootDir,
|
|
340
|
+
function scanDirectoryWalk(rootDir, onProgress) {
|
|
282
341
|
const files = [];
|
|
283
342
|
let count = 0;
|
|
284
343
|
const visitedDirs = new Set();
|
|
285
|
-
|
|
344
|
+
const loadIgnore = (dir) => {
|
|
345
|
+
try {
|
|
346
|
+
const giPath = path.join(dir, '.gitignore');
|
|
347
|
+
if (fs.existsSync(giPath)) {
|
|
348
|
+
return { dir, ig: (0, ignore_1.default)().add(fs.readFileSync(giPath, 'utf-8')) };
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
// Unreadable .gitignore — treat as absent.
|
|
353
|
+
}
|
|
354
|
+
return null;
|
|
355
|
+
};
|
|
356
|
+
const isIgnored = (fullPath, isDir, matchers) => {
|
|
357
|
+
for (const { dir, ig } of matchers) {
|
|
358
|
+
let rel = (0, utils_1.normalizePath)(path.relative(dir, fullPath));
|
|
359
|
+
if (!rel || rel.startsWith('..'))
|
|
360
|
+
continue; // not under this matcher's dir
|
|
361
|
+
if (isDir)
|
|
362
|
+
rel += '/'; // dir-only rules (e.g. `build/`) only match with the slash
|
|
363
|
+
if (ig.ignores(rel))
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
367
|
+
};
|
|
368
|
+
function walk(dir, matchers) {
|
|
286
369
|
let realDir;
|
|
287
370
|
try {
|
|
288
371
|
realDir = fs.realpathSync(dir);
|
|
@@ -296,12 +379,11 @@ function scanDirectoryWalk(rootDir, config, onProgress) {
|
|
|
296
379
|
return;
|
|
297
380
|
}
|
|
298
381
|
visitedDirs.add(realDir);
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
382
|
+
// This directory's own .gitignore (if present) applies to everything below it.
|
|
383
|
+
// The root's .gitignore is already merged into the seeded base matcher (so a
|
|
384
|
+
// negation there can override a built-in default), so skip it here.
|
|
385
|
+
const own = dir === rootDir ? null : loadIgnore(dir);
|
|
386
|
+
const active = own ? [...matchers, own] : matchers;
|
|
305
387
|
let entries;
|
|
306
388
|
try {
|
|
307
389
|
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
@@ -311,6 +393,9 @@ function scanDirectoryWalk(rootDir, config, onProgress) {
|
|
|
311
393
|
return;
|
|
312
394
|
}
|
|
313
395
|
for (const entry of entries) {
|
|
396
|
+
// Never descend into git internals or our own data directory.
|
|
397
|
+
if (entry.name === '.git' || entry.name === '.codegraph')
|
|
398
|
+
continue;
|
|
314
399
|
const fullPath = path.join(dir, entry.name);
|
|
315
400
|
const relativePath = (0, utils_1.normalizePath)(path.relative(rootDir, fullPath));
|
|
316
401
|
if (entry.isSymbolicLink()) {
|
|
@@ -318,20 +403,12 @@ function scanDirectoryWalk(rootDir, config, onProgress) {
|
|
|
318
403
|
const realTarget = fs.realpathSync(fullPath);
|
|
319
404
|
const stat = fs.statSync(realTarget);
|
|
320
405
|
if (stat.isDirectory()) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
for (const pattern of config.exclude) {
|
|
324
|
-
if (matchesGlob(dirPattern, pattern) || matchesGlob(relativePath, pattern)) {
|
|
325
|
-
excluded = true;
|
|
326
|
-
break;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
if (!excluded) {
|
|
330
|
-
walk(fullPath);
|
|
406
|
+
if (!isIgnored(fullPath, true, active)) {
|
|
407
|
+
walk(fullPath, active);
|
|
331
408
|
}
|
|
332
409
|
}
|
|
333
410
|
else if (stat.isFile()) {
|
|
334
|
-
if (
|
|
411
|
+
if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath)) {
|
|
335
412
|
files.push(relativePath);
|
|
336
413
|
count++;
|
|
337
414
|
onProgress?.(count, relativePath);
|
|
@@ -344,20 +421,12 @@ function scanDirectoryWalk(rootDir, config, onProgress) {
|
|
|
344
421
|
continue;
|
|
345
422
|
}
|
|
346
423
|
if (entry.isDirectory()) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
for (const pattern of config.exclude) {
|
|
350
|
-
if (matchesGlob(dirPattern, pattern) || matchesGlob(relativePath, pattern)) {
|
|
351
|
-
excluded = true;
|
|
352
|
-
break;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
if (!excluded) {
|
|
356
|
-
walk(fullPath);
|
|
424
|
+
if (!isIgnored(fullPath, true, active)) {
|
|
425
|
+
walk(fullPath, active);
|
|
357
426
|
}
|
|
358
427
|
}
|
|
359
428
|
else if (entry.isFile()) {
|
|
360
|
-
if (
|
|
429
|
+
if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath)) {
|
|
361
430
|
files.push(relativePath);
|
|
362
431
|
count++;
|
|
363
432
|
onProgress?.(count, relativePath);
|
|
@@ -365,7 +434,9 @@ function scanDirectoryWalk(rootDir, config, onProgress) {
|
|
|
365
434
|
}
|
|
366
435
|
}
|
|
367
436
|
}
|
|
368
|
-
|
|
437
|
+
// Seed a base matcher with the built-in default ignores (merged with the root
|
|
438
|
+
// .gitignore so a negation can override). Nested .gitignores still layer per-dir.
|
|
439
|
+
walk(rootDir, [{ dir: rootDir, ig: buildDefaultIgnore(rootDir) }]);
|
|
369
440
|
return files;
|
|
370
441
|
}
|
|
371
442
|
/**
|
|
@@ -373,7 +444,6 @@ function scanDirectoryWalk(rootDir, config, onProgress) {
|
|
|
373
444
|
*/
|
|
374
445
|
class ExtractionOrchestrator {
|
|
375
446
|
rootDir;
|
|
376
|
-
config;
|
|
377
447
|
queries;
|
|
378
448
|
/**
|
|
379
449
|
* Names of frameworks detected for this project, populated by indexAll().
|
|
@@ -382,9 +452,8 @@ class ExtractionOrchestrator {
|
|
|
382
452
|
* hasn't run yet so single-file re-index paths can detect on the spot.
|
|
383
453
|
*/
|
|
384
454
|
detectedFrameworkNames = null;
|
|
385
|
-
constructor(rootDir,
|
|
455
|
+
constructor(rootDir, queries) {
|
|
386
456
|
this.rootDir = rootDir;
|
|
387
|
-
this.config = config;
|
|
388
457
|
this.queries = queries;
|
|
389
458
|
}
|
|
390
459
|
/**
|
|
@@ -426,6 +495,24 @@ class ExtractionOrchestrator {
|
|
|
426
495
|
return null;
|
|
427
496
|
}
|
|
428
497
|
},
|
|
498
|
+
// Monorepo support — needed by framework detect()s that probe
|
|
499
|
+
// subpackage manifests (e.g. fabric-view looking at
|
|
500
|
+
// packages/<sub>/package.json when the root manifest is just a
|
|
501
|
+
// workspace declaration). Matches the resolver-context shape.
|
|
502
|
+
listDirectories: (relativePath) => {
|
|
503
|
+
const target = relativePath === '.' || relativePath === ''
|
|
504
|
+
? rootDir
|
|
505
|
+
: path.join(rootDir, relativePath);
|
|
506
|
+
try {
|
|
507
|
+
return fs
|
|
508
|
+
.readdirSync(target, { withFileTypes: true })
|
|
509
|
+
.filter((entry) => entry.isDirectory())
|
|
510
|
+
.map((entry) => entry.name);
|
|
511
|
+
}
|
|
512
|
+
catch {
|
|
513
|
+
return [];
|
|
514
|
+
}
|
|
515
|
+
},
|
|
429
516
|
};
|
|
430
517
|
}
|
|
431
518
|
/**
|
|
@@ -436,7 +523,7 @@ class ExtractionOrchestrator {
|
|
|
436
523
|
ensureDetectedFrameworks(files) {
|
|
437
524
|
if (this.detectedFrameworkNames !== null)
|
|
438
525
|
return this.detectedFrameworkNames;
|
|
439
|
-
const fileList = files ?? scanDirectory(this.rootDir
|
|
526
|
+
const fileList = files ?? scanDirectory(this.rootDir);
|
|
440
527
|
const context = this.buildDetectionContext(fileList);
|
|
441
528
|
this.detectedFrameworkNames = (0, frameworks_1.detectFrameworks)(context).map((r) => r.name);
|
|
442
529
|
return this.detectedFrameworkNames;
|
|
@@ -462,7 +549,7 @@ class ExtractionOrchestrator {
|
|
|
462
549
|
current: 0,
|
|
463
550
|
total: 0,
|
|
464
551
|
});
|
|
465
|
-
const files = await scanDirectoryAsync(this.rootDir,
|
|
552
|
+
const files = await scanDirectoryAsync(this.rootDir, (current, file) => {
|
|
466
553
|
onProgress?.({
|
|
467
554
|
phase: 'scanning',
|
|
468
555
|
current,
|
|
@@ -697,18 +784,16 @@ class ExtractionOrchestrator {
|
|
|
697
784
|
});
|
|
698
785
|
continue;
|
|
699
786
|
}
|
|
700
|
-
// Honour
|
|
701
|
-
//
|
|
702
|
-
//
|
|
703
|
-
//
|
|
704
|
-
// the
|
|
705
|
-
|
|
706
|
-
// skip the check.
|
|
707
|
-
if (stats.size > this.config.maxFileSize) {
|
|
787
|
+
// Honour MAX_FILE_SIZE. Without this check, vendored generated
|
|
788
|
+
// headers, minified bundles, and other multi-MB files get indexed,
|
|
789
|
+
// wasting WASM heap and the worker recycle budget on inputs with no
|
|
790
|
+
// useful symbols. The single-file extractFile path already enforces
|
|
791
|
+
// this; the bulk path used to silently skip the check.
|
|
792
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
708
793
|
processed++;
|
|
709
794
|
filesSkipped++;
|
|
710
795
|
errors.push({
|
|
711
|
-
message: `File exceeds max size (${stats.size} > ${
|
|
796
|
+
message: `File exceeds max size (${stats.size} > ${MAX_FILE_SIZE})`,
|
|
712
797
|
filePath,
|
|
713
798
|
severity: 'warning',
|
|
714
799
|
code: 'size_exceeded',
|
|
@@ -755,7 +840,16 @@ class ExtractionOrchestrator {
|
|
|
755
840
|
filesErrored++;
|
|
756
841
|
}
|
|
757
842
|
else {
|
|
758
|
-
|
|
843
|
+
// Files with no symbols but no errors (yaml, twig, properties) are
|
|
844
|
+
// tracked at the file level — count them as indexed so the CLI
|
|
845
|
+
// doesn't misleadingly report "No files found to index".
|
|
846
|
+
const lang = (0, grammars_1.detectLanguage)(filePath, content);
|
|
847
|
+
if ((0, grammars_1.isFileLevelOnlyLanguage)(lang)) {
|
|
848
|
+
filesIndexed++;
|
|
849
|
+
}
|
|
850
|
+
else {
|
|
851
|
+
filesSkipped++;
|
|
852
|
+
}
|
|
759
853
|
}
|
|
760
854
|
}
|
|
761
855
|
}
|
|
@@ -906,7 +1000,13 @@ class ExtractionOrchestrator {
|
|
|
906
1000
|
filesErrored++;
|
|
907
1001
|
}
|
|
908
1002
|
else {
|
|
909
|
-
|
|
1003
|
+
const tracked = this.queries.getFileByPath(filePath);
|
|
1004
|
+
if (tracked && (0, grammars_1.isFileLevelOnlyLanguage)(tracked.language)) {
|
|
1005
|
+
filesIndexed++;
|
|
1006
|
+
}
|
|
1007
|
+
else {
|
|
1008
|
+
filesSkipped++;
|
|
1009
|
+
}
|
|
910
1010
|
}
|
|
911
1011
|
}
|
|
912
1012
|
return {
|
|
@@ -977,14 +1077,14 @@ class ExtractionOrchestrator {
|
|
|
977
1077
|
};
|
|
978
1078
|
}
|
|
979
1079
|
// Check file size
|
|
980
|
-
if (stats.size >
|
|
1080
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
981
1081
|
return {
|
|
982
1082
|
nodes: [],
|
|
983
1083
|
edges: [],
|
|
984
1084
|
unresolvedReferences: [],
|
|
985
1085
|
errors: [
|
|
986
1086
|
{
|
|
987
|
-
message: `File exceeds max size (${stats.size} > ${
|
|
1087
|
+
message: `File exceeds max size (${stats.size} > ${MAX_FILE_SIZE})`,
|
|
988
1088
|
filePath: relativePath,
|
|
989
1089
|
severity: 'warning',
|
|
990
1090
|
code: 'size_exceeded',
|
|
@@ -1073,8 +1173,12 @@ class ExtractionOrchestrator {
|
|
|
1073
1173
|
this.queries.upsertFile(fileRecord);
|
|
1074
1174
|
}
|
|
1075
1175
|
/**
|
|
1076
|
-
* Sync with current file state.
|
|
1077
|
-
*
|
|
1176
|
+
* Sync the index with the current file state.
|
|
1177
|
+
*
|
|
1178
|
+
* Change detection is filesystem-based, never git: a (size, mtime) stat
|
|
1179
|
+
* pre-filter skips unchanged files, then a content-hash compare confirms real
|
|
1180
|
+
* changes. This works in non-git projects and catches committed changes from
|
|
1181
|
+
* `git pull`/`checkout`/`merge`/`rebase` that `git status` cannot see.
|
|
1078
1182
|
*/
|
|
1079
1183
|
async sync(onProgress) {
|
|
1080
1184
|
await (0, grammars_1.initGrammars)(); // Initialize WASM runtime (grammars loaded lazily below)
|
|
@@ -1091,88 +1195,72 @@ class ExtractionOrchestrator {
|
|
|
1091
1195
|
total: 0,
|
|
1092
1196
|
});
|
|
1093
1197
|
const filesToIndex = [];
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1198
|
+
// === Filesystem reconcile (git-independent) ===
|
|
1199
|
+
// The source of truth for "what changed" is the filesystem vs the indexed
|
|
1200
|
+
// state — never git. We enumerate the current source files and reconcile
|
|
1201
|
+
// each against the DB. A cheap (size, mtime) stat pre-filter skips unchanged
|
|
1202
|
+
// files without reading or hashing them, so the expensive read+hash+parse
|
|
1203
|
+
// only runs for files that actually changed. This catches edits/adds/deletes
|
|
1204
|
+
// whether or not the project uses git, and crucially also catches committed
|
|
1205
|
+
// changes from `git pull`/`checkout`/`merge`/`rebase` — which `git status`
|
|
1206
|
+
// cannot see, because the working tree is clean afterward.
|
|
1207
|
+
const currentFiles = scanDirectory(this.rootDir);
|
|
1208
|
+
filesChecked = currentFiles.length;
|
|
1209
|
+
const currentSet = new Set(currentFiles);
|
|
1210
|
+
const trackedFiles = this.queries.getAllFiles();
|
|
1211
|
+
const trackedMap = new Map();
|
|
1212
|
+
for (const f of trackedFiles) {
|
|
1213
|
+
trackedMap.set(f.path, f);
|
|
1214
|
+
}
|
|
1215
|
+
// Removals: tracked in the DB but no longer a present source file. Check the
|
|
1216
|
+
// filesystem directly — `scanDirectory` (via `git ls-files`) still lists a
|
|
1217
|
+
// file deleted from disk but not yet staged, so set membership alone misses it.
|
|
1218
|
+
for (const tracked of trackedFiles) {
|
|
1219
|
+
if (!currentSet.has(tracked.path) || !fs.existsSync(path.join(this.rootDir, tracked.path))) {
|
|
1220
|
+
this.queries.deleteFile(tracked.path);
|
|
1221
|
+
filesRemoved++;
|
|
1106
1222
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1223
|
+
}
|
|
1224
|
+
// Adds / modifications.
|
|
1225
|
+
for (const filePath of currentFiles) {
|
|
1226
|
+
const fullPath = path.join(this.rootDir, filePath);
|
|
1227
|
+
const tracked = trackedMap.get(filePath);
|
|
1228
|
+
// Cheap pre-filter: an already-indexed file whose size AND mtime both match
|
|
1229
|
+
// the DB is unchanged — skip it without reading or hashing. (A content
|
|
1230
|
+
// change that preserves both exactly is the blind spot every mtime-based
|
|
1231
|
+
// incremental tool accepts; `index --force` is the escape hatch. Git bumps
|
|
1232
|
+
// mtime on every file it writes during checkout/merge, so pulls are caught.)
|
|
1233
|
+
if (tracked) {
|
|
1115
1234
|
try {
|
|
1116
|
-
|
|
1235
|
+
const stat = fs.statSync(fullPath);
|
|
1236
|
+
if (stat.size === tracked.size && Math.floor(stat.mtimeMs) === Math.floor(tracked.modifiedAt)) {
|
|
1237
|
+
continue;
|
|
1238
|
+
}
|
|
1117
1239
|
}
|
|
1118
1240
|
catch (error) {
|
|
1119
|
-
(0, errors_1.logDebug)('Skipping
|
|
1241
|
+
(0, errors_1.logDebug)('Skipping unstattable file during sync', { filePath, error: String(error) });
|
|
1120
1242
|
continue;
|
|
1121
1243
|
}
|
|
1122
|
-
const contentHash = hashContent(content);
|
|
1123
|
-
const tracked = this.queries.getFileByPath(filePath);
|
|
1124
|
-
if (!tracked) {
|
|
1125
|
-
filesToIndex.push(filePath);
|
|
1126
|
-
changedFilePaths.push(filePath);
|
|
1127
|
-
filesAdded++;
|
|
1128
|
-
}
|
|
1129
|
-
else if (tracked.contentHash !== contentHash) {
|
|
1130
|
-
filesToIndex.push(filePath);
|
|
1131
|
-
changedFilePaths.push(filePath);
|
|
1132
|
-
filesModified++;
|
|
1133
|
-
}
|
|
1134
1244
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
filesChecked = currentFiles.size;
|
|
1140
|
-
// Build Map for O(1) lookups instead of .find() per file
|
|
1141
|
-
const trackedFiles = this.queries.getAllFiles();
|
|
1142
|
-
const trackedMap = new Map();
|
|
1143
|
-
for (const f of trackedFiles) {
|
|
1144
|
-
trackedMap.set(f.path, f);
|
|
1245
|
+
// New, or size/mtime changed — read + hash to confirm a real content change.
|
|
1246
|
+
let content;
|
|
1247
|
+
try {
|
|
1248
|
+
content = fs.readFileSync(fullPath, 'utf-8');
|
|
1145
1249
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
this.queries.deleteFile(tracked.path);
|
|
1150
|
-
filesRemoved++;
|
|
1151
|
-
}
|
|
1250
|
+
catch (error) {
|
|
1251
|
+
(0, errors_1.logDebug)('Skipping unreadable file during sync', { filePath, error: String(error) });
|
|
1252
|
+
continue;
|
|
1152
1253
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
}
|
|
1164
|
-
const contentHash = hashContent(content);
|
|
1165
|
-
const tracked = trackedMap.get(filePath);
|
|
1166
|
-
if (!tracked) {
|
|
1167
|
-
filesToIndex.push(filePath);
|
|
1168
|
-
changedFilePaths.push(filePath);
|
|
1169
|
-
filesAdded++;
|
|
1170
|
-
}
|
|
1171
|
-
else if (tracked.contentHash !== contentHash) {
|
|
1172
|
-
filesToIndex.push(filePath);
|
|
1173
|
-
changedFilePaths.push(filePath);
|
|
1174
|
-
filesModified++;
|
|
1175
|
-
}
|
|
1254
|
+
const contentHash = hashContent(content);
|
|
1255
|
+
if (!tracked) {
|
|
1256
|
+
filesToIndex.push(filePath);
|
|
1257
|
+
changedFilePaths.push(filePath);
|
|
1258
|
+
filesAdded++;
|
|
1259
|
+
}
|
|
1260
|
+
else if (tracked.contentHash !== contentHash) {
|
|
1261
|
+
filesToIndex.push(filePath);
|
|
1262
|
+
changedFilePaths.push(filePath);
|
|
1263
|
+
filesModified++;
|
|
1176
1264
|
}
|
|
1177
1265
|
}
|
|
1178
1266
|
// Load only grammars needed for changed files
|
|
@@ -1212,7 +1300,7 @@ class ExtractionOrchestrator {
|
|
|
1212
1300
|
* Uses git status as a fast path when available, falling back to full scan.
|
|
1213
1301
|
*/
|
|
1214
1302
|
getChangedFiles() {
|
|
1215
|
-
const gitChanges = getGitChangedFiles(this.rootDir
|
|
1303
|
+
const gitChanges = getGitChangedFiles(this.rootDir);
|
|
1216
1304
|
if (gitChanges) {
|
|
1217
1305
|
// === Git fast path ===
|
|
1218
1306
|
const added = [];
|
|
@@ -1251,7 +1339,7 @@ class ExtractionOrchestrator {
|
|
|
1251
1339
|
return { added, modified, removed };
|
|
1252
1340
|
}
|
|
1253
1341
|
// === Fallback: full scan (non-git project or git failure) ===
|
|
1254
|
-
const currentFiles = new Set(scanDirectory(this.rootDir
|
|
1342
|
+
const currentFiles = new Set(scanDirectory(this.rootDir));
|
|
1255
1343
|
const trackedFiles = this.queries.getAllFiles();
|
|
1256
1344
|
// Build Map for O(1) lookups
|
|
1257
1345
|
const trackedMap = new Map();
|
|
@@ -1296,6 +1384,7 @@ var tree_sitter_2 = require("./tree-sitter");
|
|
|
1296
1384
|
Object.defineProperty(exports, "extractFromSource", { enumerable: true, get: function () { return tree_sitter_2.extractFromSource; } });
|
|
1297
1385
|
var grammars_2 = require("./grammars");
|
|
1298
1386
|
Object.defineProperty(exports, "detectLanguage", { enumerable: true, get: function () { return grammars_2.detectLanguage; } });
|
|
1387
|
+
Object.defineProperty(exports, "isSourceFile", { enumerable: true, get: function () { return grammars_2.isSourceFile; } });
|
|
1299
1388
|
Object.defineProperty(exports, "isLanguageSupported", { enumerable: true, get: function () { return grammars_2.isLanguageSupported; } });
|
|
1300
1389
|
Object.defineProperty(exports, "isGrammarLoaded", { enumerable: true, get: function () { return grammars_2.isGrammarLoaded; } });
|
|
1301
1390
|
Object.defineProperty(exports, "getSupportedLanguages", { enumerable: true, get: function () { return grammars_2.getSupportedLanguages; } });
|