@zuvia-software-solutions/code-mapper 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/README.md +215 -0
  2. package/dist/cli/ai-context.d.ts +19 -0
  3. package/dist/cli/ai-context.js +168 -0
  4. package/dist/cli/analyze.d.ts +7 -0
  5. package/dist/cli/analyze.js +325 -0
  6. package/dist/cli/augment.d.ts +7 -0
  7. package/dist/cli/augment.js +27 -0
  8. package/dist/cli/clean.d.ts +5 -0
  9. package/dist/cli/clean.js +56 -0
  10. package/dist/cli/eval-server.d.ts +25 -0
  11. package/dist/cli/eval-server.js +365 -0
  12. package/dist/cli/index.d.ts +6 -0
  13. package/dist/cli/index.js +102 -0
  14. package/dist/cli/lazy-action.d.ts +6 -0
  15. package/dist/cli/lazy-action.js +19 -0
  16. package/dist/cli/list.d.ts +2 -0
  17. package/dist/cli/list.js +27 -0
  18. package/dist/cli/mcp.d.ts +8 -0
  19. package/dist/cli/mcp.js +35 -0
  20. package/dist/cli/refresh.d.ts +12 -0
  21. package/dist/cli/refresh.js +165 -0
  22. package/dist/cli/serve.d.ts +5 -0
  23. package/dist/cli/serve.js +8 -0
  24. package/dist/cli/setup.d.ts +6 -0
  25. package/dist/cli/setup.js +218 -0
  26. package/dist/cli/status.d.ts +2 -0
  27. package/dist/cli/status.js +33 -0
  28. package/dist/cli/tool.d.ts +28 -0
  29. package/dist/cli/tool.js +87 -0
  30. package/dist/config/ignore-service.d.ts +32 -0
  31. package/dist/config/ignore-service.js +282 -0
  32. package/dist/config/supported-languages.d.ts +23 -0
  33. package/dist/config/supported-languages.js +52 -0
  34. package/dist/core/augmentation/engine.d.ts +22 -0
  35. package/dist/core/augmentation/engine.js +232 -0
  36. package/dist/core/embeddings/embedder.d.ts +35 -0
  37. package/dist/core/embeddings/embedder.js +171 -0
  38. package/dist/core/embeddings/embedding-pipeline.d.ts +41 -0
  39. package/dist/core/embeddings/embedding-pipeline.js +402 -0
  40. package/dist/core/embeddings/index.d.ts +5 -0
  41. package/dist/core/embeddings/index.js +6 -0
  42. package/dist/core/embeddings/text-generator.d.ts +20 -0
  43. package/dist/core/embeddings/text-generator.js +159 -0
  44. package/dist/core/embeddings/types.d.ts +60 -0
  45. package/dist/core/embeddings/types.js +23 -0
  46. package/dist/core/graph/graph.d.ts +4 -0
  47. package/dist/core/graph/graph.js +65 -0
  48. package/dist/core/graph/types.d.ts +69 -0
  49. package/dist/core/graph/types.js +3 -0
  50. package/dist/core/incremental/child-process.d.ts +8 -0
  51. package/dist/core/incremental/child-process.js +649 -0
  52. package/dist/core/incremental/refresh-coordinator.d.ts +32 -0
  53. package/dist/core/incremental/refresh-coordinator.js +147 -0
  54. package/dist/core/incremental/types.d.ts +78 -0
  55. package/dist/core/incremental/types.js +153 -0
  56. package/dist/core/incremental/watcher.d.ts +63 -0
  57. package/dist/core/incremental/watcher.js +338 -0
  58. package/dist/core/ingestion/ast-cache.d.ts +12 -0
  59. package/dist/core/ingestion/ast-cache.js +34 -0
  60. package/dist/core/ingestion/call-processor.d.ts +34 -0
  61. package/dist/core/ingestion/call-processor.js +937 -0
  62. package/dist/core/ingestion/call-routing.d.ts +40 -0
  63. package/dist/core/ingestion/call-routing.js +97 -0
  64. package/dist/core/ingestion/cluster-enricher.d.ts +30 -0
  65. package/dist/core/ingestion/cluster-enricher.js +151 -0
  66. package/dist/core/ingestion/community-processor.d.ts +26 -0
  67. package/dist/core/ingestion/community-processor.js +272 -0
  68. package/dist/core/ingestion/constants.d.ts +5 -0
  69. package/dist/core/ingestion/constants.js +8 -0
  70. package/dist/core/ingestion/entry-point-scoring.d.ts +23 -0
  71. package/dist/core/ingestion/entry-point-scoring.js +317 -0
  72. package/dist/core/ingestion/export-detection.d.ts +11 -0
  73. package/dist/core/ingestion/export-detection.js +203 -0
  74. package/dist/core/ingestion/filesystem-walker.d.ts +18 -0
  75. package/dist/core/ingestion/filesystem-walker.js +64 -0
  76. package/dist/core/ingestion/framework-detection.d.ts +42 -0
  77. package/dist/core/ingestion/framework-detection.js +405 -0
  78. package/dist/core/ingestion/heritage-processor.d.ts +15 -0
  79. package/dist/core/ingestion/heritage-processor.js +237 -0
  80. package/dist/core/ingestion/import-processor.d.ts +31 -0
  81. package/dist/core/ingestion/import-processor.js +416 -0
  82. package/dist/core/ingestion/language-config.d.ts +32 -0
  83. package/dist/core/ingestion/language-config.js +161 -0
  84. package/dist/core/ingestion/mro-processor.d.ts +32 -0
  85. package/dist/core/ingestion/mro-processor.js +343 -0
  86. package/dist/core/ingestion/named-binding-extraction.d.ts +51 -0
  87. package/dist/core/ingestion/named-binding-extraction.js +343 -0
  88. package/dist/core/ingestion/parsing-processor.d.ts +20 -0
  89. package/dist/core/ingestion/parsing-processor.js +282 -0
  90. package/dist/core/ingestion/pipeline.d.ts +3 -0
  91. package/dist/core/ingestion/pipeline.js +416 -0
  92. package/dist/core/ingestion/process-processor.d.ts +42 -0
  93. package/dist/core/ingestion/process-processor.js +357 -0
  94. package/dist/core/ingestion/resolution-context.d.ts +40 -0
  95. package/dist/core/ingestion/resolution-context.js +171 -0
  96. package/dist/core/ingestion/resolvers/csharp.d.ts +10 -0
  97. package/dist/core/ingestion/resolvers/csharp.js +101 -0
  98. package/dist/core/ingestion/resolvers/go.d.ts +8 -0
  99. package/dist/core/ingestion/resolvers/go.js +33 -0
  100. package/dist/core/ingestion/resolvers/index.d.ts +14 -0
  101. package/dist/core/ingestion/resolvers/index.js +10 -0
  102. package/dist/core/ingestion/resolvers/jvm.d.ts +9 -0
  103. package/dist/core/ingestion/resolvers/jvm.js +74 -0
  104. package/dist/core/ingestion/resolvers/php.d.ts +7 -0
  105. package/dist/core/ingestion/resolvers/php.js +30 -0
  106. package/dist/core/ingestion/resolvers/ruby.d.ts +9 -0
  107. package/dist/core/ingestion/resolvers/ruby.js +13 -0
  108. package/dist/core/ingestion/resolvers/rust.d.ts +5 -0
  109. package/dist/core/ingestion/resolvers/rust.js +62 -0
  110. package/dist/core/ingestion/resolvers/standard.d.ts +16 -0
  111. package/dist/core/ingestion/resolvers/standard.js +144 -0
  112. package/dist/core/ingestion/resolvers/utils.d.ts +18 -0
  113. package/dist/core/ingestion/resolvers/utils.js +113 -0
  114. package/dist/core/ingestion/structure-processor.d.ts +4 -0
  115. package/dist/core/ingestion/structure-processor.js +39 -0
  116. package/dist/core/ingestion/symbol-table.d.ts +34 -0
  117. package/dist/core/ingestion/symbol-table.js +48 -0
  118. package/dist/core/ingestion/tree-sitter-queries.d.ts +20 -0
  119. package/dist/core/ingestion/tree-sitter-queries.js +691 -0
  120. package/dist/core/ingestion/type-env.d.ts +52 -0
  121. package/dist/core/ingestion/type-env.js +349 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +4 -0
  123. package/dist/core/ingestion/type-extractors/c-cpp.js +214 -0
  124. package/dist/core/ingestion/type-extractors/csharp.d.ts +4 -0
  125. package/dist/core/ingestion/type-extractors/csharp.js +224 -0
  126. package/dist/core/ingestion/type-extractors/go.d.ts +4 -0
  127. package/dist/core/ingestion/type-extractors/go.js +261 -0
  128. package/dist/core/ingestion/type-extractors/index.d.ts +20 -0
  129. package/dist/core/ingestion/type-extractors/index.js +30 -0
  130. package/dist/core/ingestion/type-extractors/jvm.d.ts +5 -0
  131. package/dist/core/ingestion/type-extractors/jvm.js +386 -0
  132. package/dist/core/ingestion/type-extractors/php.d.ts +4 -0
  133. package/dist/core/ingestion/type-extractors/php.js +280 -0
  134. package/dist/core/ingestion/type-extractors/python.d.ts +4 -0
  135. package/dist/core/ingestion/type-extractors/python.js +175 -0
  136. package/dist/core/ingestion/type-extractors/ruby.d.ts +12 -0
  137. package/dist/core/ingestion/type-extractors/ruby.js +218 -0
  138. package/dist/core/ingestion/type-extractors/rust.d.ts +4 -0
  139. package/dist/core/ingestion/type-extractors/rust.js +290 -0
  140. package/dist/core/ingestion/type-extractors/shared.d.ts +81 -0
  141. package/dist/core/ingestion/type-extractors/shared.js +322 -0
  142. package/dist/core/ingestion/type-extractors/swift.d.ts +4 -0
  143. package/dist/core/ingestion/type-extractors/swift.js +140 -0
  144. package/dist/core/ingestion/type-extractors/types.d.ts +111 -0
  145. package/dist/core/ingestion/type-extractors/types.js +4 -0
  146. package/dist/core/ingestion/type-extractors/typescript.d.ts +4 -0
  147. package/dist/core/ingestion/type-extractors/typescript.js +227 -0
  148. package/dist/core/ingestion/utils.d.ts +73 -0
  149. package/dist/core/ingestion/utils.js +992 -0
  150. package/dist/core/ingestion/workers/parse-worker.d.ts +99 -0
  151. package/dist/core/ingestion/workers/parse-worker.js +1055 -0
  152. package/dist/core/ingestion/workers/worker-pool.d.ts +15 -0
  153. package/dist/core/ingestion/workers/worker-pool.js +123 -0
  154. package/dist/core/lbug/csv-generator.d.ts +28 -0
  155. package/dist/core/lbug/csv-generator.js +355 -0
  156. package/dist/core/lbug/lbug-adapter.d.ts +96 -0
  157. package/dist/core/lbug/lbug-adapter.js +753 -0
  158. package/dist/core/lbug/schema.d.ts +46 -0
  159. package/dist/core/lbug/schema.js +402 -0
  160. package/dist/core/search/bm25-index.d.ts +20 -0
  161. package/dist/core/search/bm25-index.js +123 -0
  162. package/dist/core/search/hybrid-search.d.ts +32 -0
  163. package/dist/core/search/hybrid-search.js +131 -0
  164. package/dist/core/search/query-cache.d.ts +18 -0
  165. package/dist/core/search/query-cache.js +47 -0
  166. package/dist/core/search/query-expansion.d.ts +19 -0
  167. package/dist/core/search/query-expansion.js +75 -0
  168. package/dist/core/search/reranker.d.ts +29 -0
  169. package/dist/core/search/reranker.js +122 -0
  170. package/dist/core/search/types.d.ts +154 -0
  171. package/dist/core/search/types.js +51 -0
  172. package/dist/core/semantic/tsgo-service.d.ts +67 -0
  173. package/dist/core/semantic/tsgo-service.js +355 -0
  174. package/dist/core/tree-sitter/parser-loader.d.ts +12 -0
  175. package/dist/core/tree-sitter/parser-loader.js +71 -0
  176. package/dist/lib/memory-guard.d.ts +35 -0
  177. package/dist/lib/memory-guard.js +70 -0
  178. package/dist/lib/utils.d.ts +3 -0
  179. package/dist/lib/utils.js +6 -0
  180. package/dist/mcp/compatible-stdio-transport.d.ts +32 -0
  181. package/dist/mcp/compatible-stdio-transport.js +209 -0
  182. package/dist/mcp/core/embedder.d.ts +24 -0
  183. package/dist/mcp/core/embedder.js +168 -0
  184. package/dist/mcp/core/lbug-adapter.d.ts +29 -0
  185. package/dist/mcp/core/lbug-adapter.js +330 -0
  186. package/dist/mcp/local/local-backend.d.ts +188 -0
  187. package/dist/mcp/local/local-backend.js +2759 -0
  188. package/dist/mcp/resources.d.ts +22 -0
  189. package/dist/mcp/resources.js +379 -0
  190. package/dist/mcp/server.d.ts +10 -0
  191. package/dist/mcp/server.js +217 -0
  192. package/dist/mcp/staleness.d.ts +10 -0
  193. package/dist/mcp/staleness.js +25 -0
  194. package/dist/mcp/tools.d.ts +21 -0
  195. package/dist/mcp/tools.js +202 -0
  196. package/dist/server/api.d.ts +5 -0
  197. package/dist/server/api.js +340 -0
  198. package/dist/server/mcp-http.d.ts +7 -0
  199. package/dist/server/mcp-http.js +95 -0
  200. package/dist/storage/git.d.ts +6 -0
  201. package/dist/storage/git.js +35 -0
  202. package/dist/storage/repo-manager.d.ts +87 -0
  203. package/dist/storage/repo-manager.js +249 -0
  204. package/dist/types/pipeline.d.ts +35 -0
  205. package/dist/types/pipeline.js +20 -0
  206. package/hooks/claude/code-mapper-hook.cjs +238 -0
  207. package/hooks/claude/pre-tool-use.sh +79 -0
  208. package/hooks/claude/session-start.sh +42 -0
  209. package/models/mlx-embedder.py +185 -0
  210. package/package.json +100 -0
  211. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  212. package/vendor/leiden/index.cjs +355 -0
  213. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,8 @@
1
+ /** @file Go package import resolution using go.mod module paths */
2
+ export interface GoModuleConfig {
3
+ modulePath: string;
4
+ }
5
+ /** Extract the package directory suffix from a Go import path (e.g., "/internal/auth/") */
6
+ export declare function resolveGoPackageDir(importPath: string, goModule: GoModuleConfig): string | null;
7
+ /** Resolve a Go package import to all .go files in the package directory */
8
+ export declare function resolveGoPackage(importPath: string, goModule: GoModuleConfig, normalizedFileList: string[], allFileList: string[]): string[];
@@ -0,0 +1,33 @@
1
+ // code-mapper/src/core/ingestion/resolvers/go.ts
2
+ /** @file Go package import resolution using go.mod module paths */
3
+ /** Extract the package directory suffix from a Go import path (e.g., "/internal/auth/") */
4
+ export function resolveGoPackageDir(importPath, goModule) {
5
+ if (!importPath.startsWith(goModule.modulePath))
6
+ return null;
7
+ const relativePkg = importPath.slice(goModule.modulePath.length + 1);
8
+ if (!relativePkg)
9
+ return null;
10
+ return '/' + relativePkg + '/';
11
+ }
12
+ /** Resolve a Go package import to all .go files in the package directory */
13
+ export function resolveGoPackage(importPath, goModule, normalizedFileList, allFileList) {
14
+ if (!importPath.startsWith(goModule.modulePath))
15
+ return [];
16
+ const relativePkg = importPath.slice(goModule.modulePath.length + 1); // e.g., "internal/auth"
17
+ if (!relativePkg)
18
+ return [];
19
+ const pkgSuffix = '/' + relativePkg + '/';
20
+ const matches = [];
21
+ for (let i = 0; i < normalizedFileList.length; i++) {
22
+ // Prepend '/' so "internal/auth/service.go" matches suffix "/internal/auth/"
23
+ const normalized = '/' + normalizedFileList[i];
24
+ // Must be directly in the package directory (not a subdirectory)
25
+ if (normalized.includes(pkgSuffix) && normalized.endsWith('.go') && !normalized.endsWith('_test.go')) {
26
+ const afterPkg = normalized.substring(normalized.indexOf(pkgSuffix) + pkgSuffix.length);
27
+ if (!afterPkg.includes('/')) {
28
+ matches.push(allFileList[i]);
29
+ }
30
+ }
31
+ }
32
+ return matches;
33
+ }
@@ -0,0 +1,14 @@
1
+ /** @file Barrel export for language-specific import resolvers */
2
+ export { EXTENSIONS, tryResolveWithExtensions, buildSuffixIndex, suffixResolve } from './utils.js';
3
+ export type { SuffixIndex } from './utils.js';
4
+ export { KOTLIN_EXTENSIONS, appendKotlinWildcard, resolveJvmWildcard, resolveJvmMemberImport } from './jvm.js';
5
+ export { resolveGoPackageDir, resolveGoPackage } from './go.js';
6
+ export type { GoModuleConfig } from './go.js';
7
+ export { resolveCSharpImport, resolveCSharpNamespaceDir } from './csharp.js';
8
+ export type { CSharpProjectConfig } from './csharp.js';
9
+ export { resolvePhpImport } from './php.js';
10
+ export type { ComposerConfig } from './php.js';
11
+ export { resolveRustImport, tryRustModulePath } from './rust.js';
12
+ export { resolveRubyImport } from './ruby.js';
13
+ export { resolveImportPath, RESOLVE_CACHE_CAP } from './standard.js';
14
+ export type { TsconfigPaths } from './standard.js';
@@ -0,0 +1,10 @@
1
+ // code-mapper/src/core/ingestion/resolvers/index.ts
2
+ /** @file Barrel export for language-specific import resolvers */
3
+ export { EXTENSIONS, tryResolveWithExtensions, buildSuffixIndex, suffixResolve } from './utils.js';
4
+ export { KOTLIN_EXTENSIONS, appendKotlinWildcard, resolveJvmWildcard, resolveJvmMemberImport } from './jvm.js';
5
+ export { resolveGoPackageDir, resolveGoPackage } from './go.js';
6
+ export { resolveCSharpImport, resolveCSharpNamespaceDir } from './csharp.js';
7
+ export { resolvePhpImport } from './php.js';
8
+ export { resolveRustImport, tryRustModulePath } from './rust.js';
9
+ export { resolveRubyImport } from './ruby.js';
10
+ export { resolveImportPath, RESOLVE_CACHE_CAP } from './standard.js';
@@ -0,0 +1,9 @@
1
+ /** @file JVM import resolution for Java and Kotlin (wildcards, member/static imports) */
2
+ import type { SuffixIndex } from './utils.js';
3
+ export declare const KOTLIN_EXTENSIONS: readonly string[];
4
+ /** Append .* to a Kotlin import path if a wildcard_import sibling node exists */
5
+ export declare const appendKotlinWildcard: (importPath: string, importNode: any) => string;
6
+ /** Resolve a JVM wildcard import (com.example.*) to all matching files */
7
+ export declare function resolveJvmWildcard(importPath: string, normalizedFileList: string[], allFileList: string[], extensions: readonly string[], index?: SuffixIndex): string[];
8
+ /** Resolve a JVM member/static import by stripping the member name */
9
+ export declare function resolveJvmMemberImport(importPath: string, normalizedFileList: string[], allFileList: string[], extensions: readonly string[], index?: SuffixIndex): string | null;
@@ -0,0 +1,74 @@
1
+ // code-mapper/src/core/ingestion/resolvers/jvm.ts
2
+ /** @file JVM import resolution for Java and Kotlin (wildcards, member/static imports) */
3
+ // Kotlin file extensions for JVM resolver reuse
4
+ export const KOTLIN_EXTENSIONS = ['.kt', '.kts'];
5
+ /** Append .* to a Kotlin import path if a wildcard_import sibling node exists */
6
+ export const appendKotlinWildcard = (importPath, importNode) => {
7
+ for (let i = 0; i < importNode.childCount; i++) {
8
+ if (importNode.child(i)?.type === 'wildcard_import') {
9
+ return importPath.endsWith('.*') ? importPath : `${importPath}.*`;
10
+ }
11
+ }
12
+ return importPath;
13
+ };
14
+ /** Resolve a JVM wildcard import (com.example.*) to all matching files */
15
+ export function resolveJvmWildcard(importPath, normalizedFileList, allFileList, extensions, index) {
16
+ // "com.example.util.*" -> "com/example/util"
17
+ const packagePath = importPath.slice(0, -2).replace(/\./g, '/');
18
+ if (index) {
19
+ const candidates = extensions.flatMap(ext => index.getFilesInDir(packagePath, ext));
20
+ // Filter to only direct children (no subdirectories)
21
+ const packageSuffix = '/' + packagePath + '/';
22
+ return candidates.filter(f => {
23
+ const normalized = f.replace(/\\/g, '/');
24
+ const idx = normalized.indexOf(packageSuffix);
25
+ if (idx < 0)
26
+ return false;
27
+ const afterPkg = normalized.substring(idx + packageSuffix.length);
28
+ return !afterPkg.includes('/');
29
+ });
30
+ }
31
+ // Fallback: linear scan
32
+ const packageSuffix = '/' + packagePath + '/';
33
+ const matches = [];
34
+ for (let i = 0; i < normalizedFileList.length; i++) {
35
+ const normalized = normalizedFileList[i];
36
+ if (normalized.includes(packageSuffix) &&
37
+ extensions.some(ext => normalized.endsWith(ext))) {
38
+ const afterPackage = normalized.substring(normalized.indexOf(packageSuffix) + packageSuffix.length);
39
+ if (!afterPackage.includes('/')) {
40
+ matches.push(allFileList[i]);
41
+ }
42
+ }
43
+ }
44
+ return matches;
45
+ }
46
+ /** Resolve a JVM member/static import by stripping the member name */
47
+ export function resolveJvmMemberImport(importPath, normalizedFileList, allFileList, extensions, index) {
48
+ // Last segment is a member if it starts with lowercase, is ALL_CAPS, or is a wildcard
49
+ const segments = importPath.split('.');
50
+ if (segments.length < 3)
51
+ return null;
52
+ const lastSeg = segments[segments.length - 1];
53
+ if (lastSeg === '*' || /^[a-z]/.test(lastSeg) || /^[A-Z_]+$/.test(lastSeg)) {
54
+ const classPath = segments.slice(0, -1).join('/');
55
+ for (const ext of extensions) {
56
+ const classSuffix = classPath + ext;
57
+ if (index) {
58
+ const result = index.get(classSuffix) || index.getInsensitive(classSuffix);
59
+ if (result)
60
+ return result;
61
+ }
62
+ else {
63
+ const fullSuffix = '/' + classSuffix;
64
+ for (let i = 0; i < normalizedFileList.length; i++) {
65
+ if (normalizedFileList[i].endsWith(fullSuffix) ||
66
+ normalizedFileList[i].toLowerCase().endsWith(fullSuffix.toLowerCase())) {
67
+ return allFileList[i];
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ return null;
74
+ }
@@ -0,0 +1,7 @@
1
+ /** @file PHP PSR-4 import resolution via composer.json autoload mappings */
2
+ import type { SuffixIndex } from './utils.js';
3
+ export interface ComposerConfig {
4
+ psr4: Map<string, string>;
5
+ }
6
+ /** Resolve a PHP use-statement via PSR-4 mappings, falling back to suffix matching */
7
+ export declare function resolvePhpImport(importPath: string, composerConfig: ComposerConfig | null, allFiles: Set<string>, normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;
@@ -0,0 +1,30 @@
1
+ // code-mapper/src/core/ingestion/resolvers/php.ts
2
+ /** @file PHP PSR-4 import resolution via composer.json autoload mappings */
3
+ import { suffixResolve } from './utils.js';
4
+ /** Resolve a PHP use-statement via PSR-4 mappings, falling back to suffix matching */
5
+ export function resolvePhpImport(importPath, composerConfig, allFiles, normalizedFileList, allFileList, index) {
6
+ // Normalize backslashes to forward slashes
7
+ const normalized = importPath.replace(/\\/g, '/');
8
+ // Try PSR-4 resolution if composer.json is available
9
+ if (composerConfig) {
10
+ // Longest match wins
11
+ const sorted = [...composerConfig.psr4.entries()].sort((a, b) => b[0].length - a[0].length);
12
+ for (const [nsPrefix, dirPrefix] of sorted) {
13
+ const nsPrefixSlash = nsPrefix.replace(/\\/g, '/');
14
+ if (normalized.startsWith(nsPrefixSlash + '/') || normalized === nsPrefixSlash) {
15
+ const remainder = normalized.slice(nsPrefixSlash.length).replace(/^\//, '');
16
+ const filePath = dirPrefix + (remainder ? '/' + remainder : '') + '.php';
17
+ if (allFiles.has(filePath))
18
+ return filePath;
19
+ if (index) {
20
+ const result = index.getInsensitive(filePath);
21
+ if (result)
22
+ return result;
23
+ }
24
+ }
25
+ }
26
+ }
27
+ // Fallback: suffix matching (works without composer.json)
28
+ const pathParts = normalized.split('/').filter(Boolean);
29
+ return suffixResolve(pathParts, normalizedFileList, allFileList, index);
30
+ }
@@ -0,0 +1,9 @@
1
+ /** @file Ruby require/require_relative import resolution via suffix matching */
2
+ import type { SuffixIndex } from './utils.js';
3
+ /**
4
+ * Resolve a Ruby require/require_relative path to a matching .rb file
5
+ *
6
+ * require_relative paths are pre-normalized to './' prefix by the caller;
7
+ * require paths use suffix matching (gem-style paths like 'json', 'net/http')
8
+ */
9
+ export declare function resolveRubyImport(importPath: string, normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;
@@ -0,0 +1,13 @@
1
+ // code-mapper/src/core/ingestion/resolvers/ruby.ts
2
+ /** @file Ruby require/require_relative import resolution via suffix matching */
3
+ import { suffixResolve } from './utils.js';
4
+ /**
5
+ * Resolve a Ruby require/require_relative path to a matching .rb file
6
+ *
7
+ * require_relative paths are pre-normalized to './' prefix by the caller;
8
+ * require paths use suffix matching (gem-style paths like 'json', 'net/http')
9
+ */
10
+ export function resolveRubyImport(importPath, normalizedFileList, allFileList, index) {
11
+ const pathParts = importPath.replace(/^\.\//, '').split('/').filter(Boolean);
12
+ return suffixResolve(pathParts, normalizedFileList, allFileList, index);
13
+ }
@@ -0,0 +1,5 @@
1
+ /** @file Rust module import resolution for crate::, super::, self:: paths */
2
+ /** Resolve a Rust use-path to a file, handling crate::, super::, self:: prefixes */
3
+ export declare function resolveRustImport(currentFile: string, importPath: string, allFiles: Set<string>): string | null;
4
+ /** Try to resolve a Rust module path to a file (path.rs, path/mod.rs, or symbol-stripped) */
5
+ export declare function tryRustModulePath(modulePath: string, allFiles: Set<string>): string | null;
@@ -0,0 +1,62 @@
1
+ // code-mapper/src/core/ingestion/resolvers/rust.ts
2
+ /** @file Rust module import resolution for crate::, super::, self:: paths */
3
+ /** Resolve a Rust use-path to a file, handling crate::, super::, self:: prefixes */
4
+ export function resolveRustImport(currentFile, importPath, allFiles) {
5
+ let rustPath;
6
+ if (importPath.startsWith('crate::')) {
7
+ // crate:: resolves from src/ (standard Rust layout)
8
+ rustPath = importPath.slice(7).replace(/::/g, '/');
9
+ // Try from src/ (standard layout)
10
+ const fromSrc = tryRustModulePath('src/' + rustPath, allFiles);
11
+ if (fromSrc)
12
+ return fromSrc;
13
+ // Try from repo root (non-standard)
14
+ const fromRoot = tryRustModulePath(rustPath, allFiles);
15
+ if (fromRoot)
16
+ return fromRoot;
17
+ return null;
18
+ }
19
+ if (importPath.startsWith('super::')) {
20
+ // super:: = parent directory of current file's module
21
+ const currentDir = currentFile.split('/').slice(0, -1);
22
+ currentDir.pop(); // Go up one level for super::
23
+ rustPath = importPath.slice(7).replace(/::/g, '/');
24
+ const fullPath = [...currentDir, rustPath].join('/');
25
+ return tryRustModulePath(fullPath, allFiles);
26
+ }
27
+ if (importPath.startsWith('self::')) {
28
+ // self:: = current module's directory
29
+ const currentDir = currentFile.split('/').slice(0, -1);
30
+ rustPath = importPath.slice(6).replace(/::/g, '/');
31
+ const fullPath = [...currentDir, rustPath].join('/');
32
+ return tryRustModulePath(fullPath, allFiles);
33
+ }
34
+ // Bare path without prefix — convert :: to / and try suffix matching
35
+ if (importPath.includes('::')) {
36
+ rustPath = importPath.replace(/::/g, '/');
37
+ return tryRustModulePath(rustPath, allFiles);
38
+ }
39
+ return null;
40
+ }
41
+ /** Try to resolve a Rust module path to a file (path.rs, path/mod.rs, or symbol-stripped) */
42
+ export function tryRustModulePath(modulePath, allFiles) {
43
+ // Try direct: path.rs
44
+ if (allFiles.has(modulePath + '.rs'))
45
+ return modulePath + '.rs';
46
+ // Try directory: path/mod.rs
47
+ if (allFiles.has(modulePath + '/mod.rs'))
48
+ return modulePath + '/mod.rs';
49
+ // Try path/lib.rs (for crate root)
50
+ if (allFiles.has(modulePath + '/lib.rs'))
51
+ return modulePath + '/lib.rs';
52
+ // Last segment might be a symbol name, not a module — strip and retry
53
+ const lastSlash = modulePath.lastIndexOf('/');
54
+ if (lastSlash > 0) {
55
+ const parentPath = modulePath.substring(0, lastSlash);
56
+ if (allFiles.has(parentPath + '.rs'))
57
+ return parentPath + '.rs';
58
+ if (allFiles.has(parentPath + '/mod.rs'))
59
+ return parentPath + '/mod.rs';
60
+ }
61
+ return null;
62
+ }
@@ -0,0 +1,16 @@
1
+ /** @file Standard import path resolution with relative imports, path alias rewriting, and suffix matching */
2
+ import type { SuffixIndex } from './utils.js';
3
+ import { SupportedLanguages } from '../../../config/supported-languages.js';
4
+ export interface TsconfigPaths {
5
+ aliases: Map<string, string>;
6
+ baseUrl: string;
7
+ }
8
+ export declare const RESOLVE_CACHE_CAP = 100000;
9
+ /**
10
+ * Resolve an import path to a file path in the repository
11
+ *
12
+ * Applies language-specific preprocessing (TS/JS path aliases, Rust module paths)
13
+ * before generic resolution. Java wildcards and Go packages are handled separately
14
+ * in processImports because they resolve to multiple files.
15
+ */
16
+ export declare const resolveImportPath: (currentFile: string, importPath: string, allFiles: Set<string>, allFileList: string[], normalizedFileList: string[], resolveCache: Map<string, string | null>, language: SupportedLanguages, tsconfigPaths: TsconfigPaths | null, index?: SuffixIndex) => string | null;
@@ -0,0 +1,144 @@
1
+ // code-mapper/src/core/ingestion/resolvers/standard.ts
2
+ /** @file Standard import path resolution with relative imports, path alias rewriting, and suffix matching */
3
+ import { tryResolveWithExtensions, suffixResolve } from './utils.js';
4
+ import { resolveRustImport } from './rust.js';
5
+ import { SupportedLanguages } from '../../../config/supported-languages.js';
6
+ // Max entries in the resolve cache (100K entries ≈ 15MB)
7
+ export const RESOLVE_CACHE_CAP = 100_000;
8
+ /**
9
+ * Resolve an import path to a file path in the repository
10
+ *
11
+ * Applies language-specific preprocessing (TS/JS path aliases, Rust module paths)
12
+ * before generic resolution. Java wildcards and Go packages are handled separately
13
+ * in processImports because they resolve to multiple files.
14
+ */
15
+ export const resolveImportPath = (currentFile, importPath, allFiles, allFileList, normalizedFileList, resolveCache, language, tsconfigPaths, index) => {
16
+ const cacheKey = `${currentFile}::${importPath}`;
17
+ if (resolveCache.has(cacheKey))
18
+ return resolveCache.get(cacheKey) ?? null;
19
+ const cache = (result) => {
20
+ // Evict oldest 20% when cap is reached
21
+ if (resolveCache.size >= RESOLVE_CACHE_CAP) {
22
+ const evictCount = Math.floor(RESOLVE_CACHE_CAP * 0.2);
23
+ const iter = resolveCache.keys();
24
+ for (let i = 0; i < evictCount; i++) {
25
+ const key = iter.next().value;
26
+ if (key !== undefined)
27
+ resolveCache.delete(key);
28
+ }
29
+ }
30
+ resolveCache.set(cacheKey, result);
31
+ return result;
32
+ };
33
+ // TypeScript/JavaScript: rewrite path aliases
34
+ if ((language === SupportedLanguages.TypeScript || language === SupportedLanguages.JavaScript) &&
35
+ tsconfigPaths &&
36
+ !importPath.startsWith('.')) {
37
+ for (const [aliasPrefix, targetPrefix] of tsconfigPaths.aliases) {
38
+ if (importPath.startsWith(aliasPrefix)) {
39
+ const remainder = importPath.slice(aliasPrefix.length);
40
+ // Rewrite path relative to baseUrl
41
+ const rewritten = tsconfigPaths.baseUrl === '.'
42
+ ? targetPrefix + remainder
43
+ : tsconfigPaths.baseUrl + '/' + targetPrefix + remainder;
44
+ // Try direct resolution from repo root first
45
+ const resolved = tryResolveWithExtensions(rewritten, allFiles);
46
+ if (resolved)
47
+ return cache(resolved);
48
+ // Try suffix matching as fallback
49
+ const parts = rewritten.split('/').filter(Boolean);
50
+ const suffixResult = suffixResolve(parts, normalizedFileList, allFileList, index);
51
+ if (suffixResult)
52
+ return cache(suffixResult);
53
+ }
54
+ }
55
+ }
56
+ // Rust: convert module path syntax to file paths
57
+ if (language === SupportedLanguages.Rust) {
58
+ // Grouped imports: extract prefix path before ::{...} and resolve the module
59
+ let rustImportPath = importPath;
60
+ const braceIdx = importPath.indexOf('::{');
61
+ if (braceIdx !== -1) {
62
+ rustImportPath = importPath.substring(0, braceIdx);
63
+ }
64
+ else if (importPath.startsWith('{') && importPath.endsWith('}')) {
65
+ // Top-level grouped imports: use {crate::a, crate::b}
66
+ // Returns first resolving part; callers needing ALL edges intercept earlier
67
+ const inner = importPath.slice(1, -1);
68
+ const parts = inner.split(',').map(p => p.trim()).filter(Boolean);
69
+ for (const part of parts) {
70
+ const partResult = resolveRustImport(currentFile, part, allFiles);
71
+ if (partResult)
72
+ return cache(partResult);
73
+ }
74
+ return cache(null);
75
+ }
76
+ const rustResult = resolveRustImport(currentFile, rustImportPath, allFiles);
77
+ if (rustResult)
78
+ return cache(rustResult);
79
+ // Fall through to generic resolution if Rust-specific resolver missed
80
+ }
81
+ // Python relative imports (PEP 328): .module, ..module, ...
82
+ if (language === SupportedLanguages.Python && importPath.startsWith('.')) {
83
+ const dotMatch = importPath.match(/^(\.+)(.*)/);
84
+ if (dotMatch) {
85
+ const dotCount = dotMatch[1].length;
86
+ const modulePart = dotMatch[2]; // e.g., "models" from ".models"
87
+ const dirParts = currentFile.split('/').slice(0, -1);
88
+ // 1 dot = same package, each additional dot goes up one level
89
+ for (let i = 1; i < dotCount; i++) {
90
+ dirParts.pop();
91
+ }
92
+ if (modulePart) {
93
+ // from .models import User → resolve "models" relative to current package
94
+ const modulePath = modulePart.replace(/\./g, '/');
95
+ dirParts.push(...modulePath.split('/'));
96
+ }
97
+ const basePath = dirParts.join('/');
98
+ const resolved = tryResolveWithExtensions(basePath, allFiles);
99
+ return cache(resolved);
100
+ }
101
+ }
102
+ // Generic relative import resolution (./ and ../)
103
+ const currentDir = currentFile.split('/').slice(0, -1);
104
+ const parts = importPath.split('/');
105
+ for (const part of parts) {
106
+ if (part === '.')
107
+ continue;
108
+ if (part === '..') {
109
+ currentDir.pop();
110
+ }
111
+ else {
112
+ currentDir.push(part);
113
+ }
114
+ }
115
+ const basePath = currentDir.join('/');
116
+ if (importPath.startsWith('.')) {
117
+ const resolved = tryResolveWithExtensions(basePath, allFiles);
118
+ if (resolved)
119
+ return cache(resolved);
120
+ // ESM TypeScript: import from './foo.js' refers to './foo.ts'
121
+ // Strip .js/.jsx/.mjs/.cjs extension and retry with TS/native extensions
122
+ const jsExtMatch = basePath.match(/\.(js|jsx|mjs|cjs)$/);
123
+ if (jsExtMatch) {
124
+ const stripped = basePath.slice(0, -jsExtMatch[0].length);
125
+ const retried = tryResolveWithExtensions(stripped, allFiles);
126
+ if (retried)
127
+ return cache(retried);
128
+ }
129
+ return cache(null);
130
+ }
131
+ // Generic package/absolute import resolution (suffix matching)
132
+ // Java wildcards are handled in processImports, not here
133
+ if (importPath.endsWith('.*')) {
134
+ return cache(null);
135
+ }
136
+ // C/C++ includes use actual file paths (e.g. "animal.h") — don't convert dots to slashes
137
+ const isCpp = language === SupportedLanguages.C || language === SupportedLanguages.CPlusPlus;
138
+ const pathLike = importPath.includes('/') || isCpp
139
+ ? importPath
140
+ : importPath.replace(/\./g, '/');
141
+ const pathParts = pathLike.split('/').filter(Boolean);
142
+ const resolved = suffixResolve(pathParts, normalizedFileList, allFileList, index);
143
+ return cache(resolved);
144
+ };
@@ -0,0 +1,18 @@
1
+ /** @file Shared utilities for import path resolution including extension matching and suffix indexing */
2
+ export declare const EXTENSIONS: string[];
3
+ /** Try to match a path (with extensions) against the known file set */
4
+ export declare function tryResolveWithExtensions(basePath: string, allFiles: Set<string>): string | null;
5
+ /**
6
+ * O(1) suffix index mapping every possible path suffix to its original file path
7
+ *
8
+ * For "src/com/example/Foo.java", indexes: "Foo.java", "example/Foo.java", etc
9
+ */
10
+ export interface SuffixIndex {
11
+ get(suffix: string): string | undefined;
12
+ getInsensitive(suffix: string): string | undefined;
13
+ getFilesInDir(dirSuffix: string, extension: string): string[];
14
+ }
15
+ /** Build a suffix index from normalized and original file lists */
16
+ export declare function buildSuffixIndex(normalizedFileList: string[], allFileList: string[]): SuffixIndex;
17
+ /** Suffix-based resolution using index (O(1) per lookup, falls back to linear scan) */
18
+ export declare function suffixResolve(pathParts: string[], normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;
@@ -0,0 +1,113 @@
1
+ // code-mapper/src/core/ingestion/resolvers/utils.ts
2
+ /** @file Shared utilities for import path resolution including extension matching and suffix indexing */
3
+ // All file extensions to try during resolution
4
+ export const EXTENSIONS = [
5
+ '',
6
+ // TypeScript/JavaScript
7
+ '.tsx', '.ts', '.jsx', '.js', '/index.tsx', '/index.ts', '/index.jsx', '/index.js',
8
+ // Python
9
+ '.py', '/__init__.py',
10
+ // Java
11
+ '.java',
12
+ // Kotlin
13
+ '.kt', '.kts',
14
+ // C/C++
15
+ '.c', '.h', '.cpp', '.hpp', '.cc', '.cxx', '.hxx', '.hh',
16
+ // C#
17
+ '.cs',
18
+ // Go
19
+ '.go',
20
+ // Rust
21
+ '.rs', '/mod.rs',
22
+ // PHP
23
+ '.php', '.phtml',
24
+ // Swift
25
+ '.swift',
26
+ // Ruby
27
+ '.rb',
28
+ ];
29
+ /** Try to match a path (with extensions) against the known file set */
30
+ export function tryResolveWithExtensions(basePath, allFiles) {
31
+ for (const ext of EXTENSIONS) {
32
+ const candidate = basePath + ext;
33
+ if (allFiles.has(candidate))
34
+ return candidate;
35
+ }
36
+ return null;
37
+ }
38
+ /** Build a suffix index from normalized and original file lists */
39
+ export function buildSuffixIndex(normalizedFileList, allFileList) {
40
+ const exactMap = new Map(); // normalized suffix -> original path
41
+ const lowerMap = new Map(); // lowercase suffix -> original path
42
+ const dirMap = new Map(); // dir suffix -> file paths in that dir
43
+ for (let i = 0; i < normalizedFileList.length; i++) {
44
+ const normalized = normalizedFileList[i];
45
+ const original = allFileList[i];
46
+ const parts = normalized.split('/');
47
+ // Index all suffixes: "a/b/c.java" -> "c.java", "b/c.java", "a/b/c.java"
48
+ for (let j = parts.length - 1; j >= 0; j--) {
49
+ const suffix = parts.slice(j).join('/');
50
+ // First match wins for ambiguous suffixes
51
+ if (!exactMap.has(suffix)) {
52
+ exactMap.set(suffix, original);
53
+ }
54
+ const lower = suffix.toLowerCase();
55
+ if (!lowerMap.has(lower)) {
56
+ lowerMap.set(lower, original);
57
+ }
58
+ }
59
+ // Index directory membership for getFilesInDir lookups
60
+ const lastSlash = normalized.lastIndexOf('/');
61
+ if (lastSlash >= 0) {
62
+ // Build all directory suffix variants
63
+ const dirParts = parts.slice(0, -1);
64
+ const fileName = parts[parts.length - 1];
65
+ const ext = fileName.substring(fileName.lastIndexOf('.'));
66
+ for (let j = dirParts.length - 1; j >= 0; j--) {
67
+ const dirSuffix = dirParts.slice(j).join('/');
68
+ const key = `${dirSuffix}:${ext}`;
69
+ let list = dirMap.get(key);
70
+ if (!list) {
71
+ list = [];
72
+ dirMap.set(key, list);
73
+ }
74
+ list.push(original);
75
+ }
76
+ }
77
+ }
78
+ return {
79
+ get: (suffix) => exactMap.get(suffix),
80
+ getInsensitive: (suffix) => lowerMap.get(suffix.toLowerCase()),
81
+ getFilesInDir: (dirSuffix, extension) => {
82
+ return dirMap.get(`${dirSuffix}:${extension}`) || [];
83
+ },
84
+ };
85
+ }
86
+ /** Suffix-based resolution using index (O(1) per lookup, falls back to linear scan) */
87
+ export function suffixResolve(pathParts, normalizedFileList, allFileList, index) {
88
+ if (index) {
89
+ for (let i = 0; i < pathParts.length; i++) {
90
+ const suffix = pathParts.slice(i).join('/');
91
+ for (const ext of EXTENSIONS) {
92
+ const suffixWithExt = suffix + ext;
93
+ const result = index.get(suffixWithExt) || index.getInsensitive(suffixWithExt);
94
+ if (result)
95
+ return result;
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ // Fallback: linear scan (for backward compatibility)
101
+ for (let i = 0; i < pathParts.length; i++) {
102
+ const suffix = pathParts.slice(i).join('/');
103
+ for (const ext of EXTENSIONS) {
104
+ const suffixWithExt = suffix + ext;
105
+ const suffixPattern = '/' + suffixWithExt;
106
+ const matchIdx = normalizedFileList.findIndex(filePath => filePath.endsWith(suffixPattern) || filePath.toLowerCase().endsWith(suffixPattern.toLowerCase()));
107
+ if (matchIdx !== -1) {
108
+ return allFileList[matchIdx];
109
+ }
110
+ }
111
+ }
112
+ return null;
113
+ }
@@ -0,0 +1,4 @@
1
+ /** @file structure-processor.ts @description Builds the file/folder tree structure in the knowledge graph by creating File and Folder nodes with CONTAINS relationships */
2
+ import { KnowledgeGraph } from "../graph/types.js";
3
+ /** Build File/Folder nodes and CONTAINS edges from a list of file paths */
4
+ export declare const processStructure: (graph: KnowledgeGraph, paths: string[]) => void;
@@ -0,0 +1,39 @@
1
+ // code-mapper/src/core/ingestion/structure-processor.ts
2
+ /** @file structure-processor.ts @description Builds the file/folder tree structure in the knowledge graph by creating File and Folder nodes with CONTAINS relationships */
3
+ import { generateId } from "../../lib/utils.js";
4
+ /** Build File/Folder nodes and CONTAINS edges from a list of file paths */
5
+ export const processStructure = (graph, paths) => {
6
+ paths.forEach(path => {
7
+ const parts = path.split('/');
8
+ let currentPath = '';
9
+ let parentId = '';
10
+ parts.forEach((part, index) => {
11
+ const isFile = index === parts.length - 1;
12
+ const label = isFile ? 'File' : 'Folder';
13
+ currentPath = currentPath ? `${currentPath}/${part}` : part;
14
+ const nodeId = generateId(label, currentPath);
15
+ const node = {
16
+ id: nodeId,
17
+ label: label,
18
+ properties: {
19
+ name: part,
20
+ filePath: currentPath
21
+ }
22
+ };
23
+ graph.addNode(node);
24
+ if (parentId) {
25
+ const relId = generateId('CONTAINS', `${parentId}->${nodeId}`);
26
+ const relationship = {
27
+ id: relId,
28
+ type: 'CONTAINS',
29
+ sourceId: parentId,
30
+ targetId: nodeId,
31
+ confidence: 1.0,
32
+ reason: '',
33
+ };
34
+ graph.addRelationship(relationship);
35
+ }
36
+ parentId = nodeId;
37
+ });
38
+ });
39
+ };