@saluzi/codegraph 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/bin/codegraph.d.ts +25 -0
  2. package/dist/bin/node-version-check.d.ts +37 -0
  3. package/dist/bin/uninstall.d.ts +14 -0
  4. package/dist/context/formatter.d.ts +33 -0
  5. package/dist/context/formatter.js +244 -0
  6. package/dist/context/index.d.ts +117 -0
  7. package/dist/context/index.js +1050 -0
  8. package/dist/db/index.d.ts +101 -0
  9. package/dist/db/index.js +250 -0
  10. package/dist/db/migrations.d.ts +47 -0
  11. package/dist/db/migrations.js +131 -0
  12. package/dist/db/queries.d.ts +291 -0
  13. package/dist/db/queries.js +1349 -0
  14. package/dist/db/schema.sql +151 -0
  15. package/dist/db/sqlite-adapter.d.ts +49 -0
  16. package/dist/db/sqlite-adapter.js +141 -0
  17. package/dist/directory.d.ts +62 -0
  18. package/dist/directory.js +264 -0
  19. package/dist/errors.d.ts +149 -0
  20. package/dist/errors.js +219 -0
  21. package/dist/extraction/dfm-extractor.d.ts +31 -0
  22. package/dist/extraction/dfm-extractor.js +151 -0
  23. package/dist/extraction/grammars.d.ts +94 -0
  24. package/dist/extraction/grammars.js +357 -0
  25. package/dist/extraction/index.d.ts +148 -0
  26. package/dist/extraction/index.js +1286 -0
  27. package/dist/extraction/languages/c-cpp.d.ts +4 -0
  28. package/dist/extraction/languages/c-cpp.js +126 -0
  29. package/dist/extraction/languages/csharp.d.ts +3 -0
  30. package/dist/extraction/languages/csharp.js +72 -0
  31. package/dist/extraction/languages/dart.d.ts +3 -0
  32. package/dist/extraction/languages/dart.js +192 -0
  33. package/dist/extraction/languages/go.d.ts +3 -0
  34. package/dist/extraction/languages/go.js +58 -0
  35. package/dist/extraction/languages/index.d.ts +10 -0
  36. package/dist/extraction/languages/index.js +49 -0
  37. package/dist/extraction/languages/java.d.ts +3 -0
  38. package/dist/extraction/languages/java.js +64 -0
  39. package/dist/extraction/languages/javascript.d.ts +3 -0
  40. package/dist/extraction/languages/javascript.js +90 -0
  41. package/dist/extraction/languages/kotlin.d.ts +3 -0
  42. package/dist/extraction/languages/kotlin.js +253 -0
  43. package/dist/extraction/languages/lua.d.ts +3 -0
  44. package/dist/extraction/languages/lua.js +150 -0
  45. package/dist/extraction/languages/luau.d.ts +3 -0
  46. package/dist/extraction/languages/luau.js +37 -0
  47. package/dist/extraction/languages/pascal.d.ts +3 -0
  48. package/dist/extraction/languages/pascal.js +66 -0
  49. package/dist/extraction/languages/php.d.ts +3 -0
  50. package/dist/extraction/languages/php.js +107 -0
  51. package/dist/extraction/languages/python.d.ts +3 -0
  52. package/dist/extraction/languages/python.js +56 -0
  53. package/dist/extraction/languages/ruby.d.ts +3 -0
  54. package/dist/extraction/languages/ruby.js +114 -0
  55. package/dist/extraction/languages/rust.d.ts +3 -0
  56. package/dist/extraction/languages/rust.js +109 -0
  57. package/dist/extraction/languages/scala.d.ts +3 -0
  58. package/dist/extraction/languages/scala.js +139 -0
  59. package/dist/extraction/languages/swift.d.ts +3 -0
  60. package/dist/extraction/languages/swift.js +91 -0
  61. package/dist/extraction/languages/typescript.d.ts +3 -0
  62. package/dist/extraction/languages/typescript.js +129 -0
  63. package/dist/extraction/liquid-extractor.d.ts +52 -0
  64. package/dist/extraction/liquid-extractor.js +313 -0
  65. package/dist/extraction/parse-worker.d.ts +8 -0
  66. package/dist/extraction/parse-worker.js +94 -0
  67. package/dist/extraction/svelte-extractor.d.ts +56 -0
  68. package/dist/extraction/svelte-extractor.js +272 -0
  69. package/dist/extraction/tree-sitter-helpers.d.ts +39 -0
  70. package/dist/extraction/tree-sitter-helpers.js +103 -0
  71. package/dist/extraction/tree-sitter-types.d.ts +191 -0
  72. package/dist/extraction/tree-sitter-types.js +10 -0
  73. package/dist/extraction/tree-sitter.d.ts +238 -0
  74. package/dist/extraction/tree-sitter.js +2430 -0
  75. package/dist/extraction/vue-extractor.d.ts +36 -0
  76. package/dist/extraction/vue-extractor.js +163 -0
  77. package/dist/extraction/wasm/tree-sitter-c.wasm +0 -0
  78. package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  79. package/dist/extraction/wasm/tree-sitter-cpp.wasm +0 -0
  80. package/dist/extraction/wasm/tree-sitter-dart.wasm +0 -0
  81. package/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
  82. package/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
  83. package/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
  84. package/dist/extraction/wasm/tree-sitter-kotlin.wasm +0 -0
  85. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  86. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  87. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  88. package/dist/extraction/wasm/tree-sitter-php.wasm +0 -0
  89. package/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
  90. package/dist/extraction/wasm/tree-sitter-ruby.wasm +0 -0
  91. package/dist/extraction/wasm/tree-sitter-rust.wasm +0 -0
  92. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  93. package/dist/extraction/wasm/tree-sitter-swift.wasm +0 -0
  94. package/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
  95. package/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
  96. package/dist/extraction/wasm-runtime-flags.d.ts +46 -0
  97. package/dist/extraction/wasm-runtime-flags.js +105 -0
  98. package/dist/graph/index.d.ts +8 -0
  99. package/dist/graph/index.js +13 -0
  100. package/dist/graph/queries.d.ts +109 -0
  101. package/dist/graph/queries.js +366 -0
  102. package/dist/graph/traversal.d.ts +137 -0
  103. package/dist/graph/traversal.js +528 -0
  104. package/dist/index.d.ts +509 -0
  105. package/dist/index.js +800 -0
  106. package/dist/installer/claude-md-template.d.ts +19 -0
  107. package/dist/installer/config-writer.d.ts +29 -0
  108. package/dist/installer/index.d.ts +140 -0
  109. package/dist/installer/instructions-template.d.ts +30 -0
  110. package/dist/installer/targets/claude.d.ts +55 -0
  111. package/dist/installer/targets/codex.d.ts +18 -0
  112. package/dist/installer/targets/cursor.d.ts +35 -0
  113. package/dist/installer/targets/hermes.d.ts +18 -0
  114. package/dist/installer/targets/opencode.d.ts +30 -0
  115. package/dist/installer/targets/registry.d.ts +38 -0
  116. package/dist/installer/targets/shared.d.ts +92 -0
  117. package/dist/installer/targets/toml.d.ts +64 -0
  118. package/dist/installer/targets/types.d.ts +122 -0
  119. package/dist/mcp/index.d.ts +98 -0
  120. package/dist/mcp/server-instructions.d.ts +20 -0
  121. package/dist/mcp/tools.d.ts +269 -0
  122. package/dist/mcp/transport.d.ts +117 -0
  123. package/dist/resolution/frameworks/cargo-workspace.d.ts +20 -0
  124. package/dist/resolution/frameworks/cargo-workspace.js +225 -0
  125. package/dist/resolution/frameworks/csharp.d.ts +8 -0
  126. package/dist/resolution/frameworks/csharp.js +213 -0
  127. package/dist/resolution/frameworks/drupal.d.ts +51 -0
  128. package/dist/resolution/frameworks/drupal.js +335 -0
  129. package/dist/resolution/frameworks/express.d.ts +8 -0
  130. package/dist/resolution/frameworks/express.js +225 -0
  131. package/dist/resolution/frameworks/go.d.ts +8 -0
  132. package/dist/resolution/frameworks/go.js +158 -0
  133. package/dist/resolution/frameworks/index.d.ts +52 -0
  134. package/dist/resolution/frameworks/index.js +137 -0
  135. package/dist/resolution/frameworks/java.d.ts +8 -0
  136. package/dist/resolution/frameworks/java.js +177 -0
  137. package/dist/resolution/frameworks/laravel.d.ts +13 -0
  138. package/dist/resolution/frameworks/laravel.js +248 -0
  139. package/dist/resolution/frameworks/nestjs.d.ts +26 -0
  140. package/dist/resolution/frameworks/nestjs.js +374 -0
  141. package/dist/resolution/frameworks/python.d.ts +10 -0
  142. package/dist/resolution/frameworks/python.js +278 -0
  143. package/dist/resolution/frameworks/react.d.ts +8 -0
  144. package/dist/resolution/frameworks/react.js +272 -0
  145. package/dist/resolution/frameworks/ruby.d.ts +8 -0
  146. package/dist/resolution/frameworks/ruby.js +198 -0
  147. package/dist/resolution/frameworks/rust.d.ts +8 -0
  148. package/dist/resolution/frameworks/rust.js +207 -0
  149. package/dist/resolution/frameworks/svelte.d.ts +9 -0
  150. package/dist/resolution/frameworks/svelte.js +249 -0
  151. package/dist/resolution/frameworks/swift.d.ts +10 -0
  152. package/dist/resolution/frameworks/swift.js +376 -0
  153. package/dist/resolution/frameworks/vue.d.ts +9 -0
  154. package/dist/resolution/frameworks/vue.js +306 -0
  155. package/dist/resolution/import-resolver.d.ts +61 -0
  156. package/dist/resolution/import-resolver.js +663 -0
  157. package/dist/resolution/index.d.ts +118 -0
  158. package/dist/resolution/index.js +744 -0
  159. package/dist/resolution/lru-cache.d.ts +24 -0
  160. package/dist/resolution/lru-cache.js +62 -0
  161. package/dist/resolution/name-matcher.d.ts +50 -0
  162. package/dist/resolution/name-matcher.js +384 -0
  163. package/dist/resolution/path-aliases.d.ts +72 -0
  164. package/dist/resolution/path-aliases.js +238 -0
  165. package/dist/resolution/strip-comments.d.ts +40 -0
  166. package/dist/resolution/strip-comments.js +441 -0
  167. package/dist/resolution/types.d.ts +181 -0
  168. package/dist/resolution/types.js +8 -0
  169. package/dist/search/query-parser.d.ts +61 -0
  170. package/dist/search/query-parser.js +177 -0
  171. package/dist/search/query-utils.d.ts +59 -0
  172. package/dist/search/query-utils.js +383 -0
  173. package/dist/sync/git-hooks.d.ts +54 -0
  174. package/dist/sync/git-hooks.js +223 -0
  175. package/dist/sync/index.d.ts +25 -0
  176. package/dist/sync/index.js +28 -0
  177. package/dist/sync/watch-policy.d.ts +51 -0
  178. package/dist/sync/watch-policy.js +124 -0
  179. package/dist/sync/watcher.d.ts +83 -0
  180. package/dist/sync/watcher.js +192 -0
  181. package/dist/types.d.ts +433 -0
  182. package/dist/types.js +75 -0
  183. package/dist/ui/glyphs.d.ts +42 -0
  184. package/dist/ui/shimmer-progress.d.ts +11 -0
  185. package/dist/ui/shimmer-worker.d.ts +2 -0
  186. package/dist/ui/types.d.ts +20 -0
  187. package/dist/utils.d.ts +231 -0
  188. package/dist/utils.js +549 -0
  189. package/package.json +24 -0
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ /**
3
+ * Ruby Framework Resolver
4
+ *
5
+ * Handles Ruby on Rails patterns.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.railsResolver = void 0;
9
+ const strip_comments_1 = require("../strip-comments");
10
+ exports.railsResolver = {
11
+ name: 'rails',
12
+ languages: ['ruby'],
13
+ detect(context) {
14
+ // Check for Gemfile with rails
15
+ const gemfile = context.readFile('Gemfile');
16
+ if (gemfile && gemfile.includes("'rails'")) {
17
+ return true;
18
+ }
19
+ // Check for config/application.rb (Rails signature)
20
+ if (context.fileExists('config/application.rb')) {
21
+ return true;
22
+ }
23
+ // Check for typical Rails directory structure
24
+ return (context.fileExists('app/controllers/application_controller.rb') ||
25
+ context.fileExists('config/routes.rb'));
26
+ },
27
+ resolve(ref, context) {
28
+ // Pattern 1: Model references (ActiveRecord)
29
+ if (/^[A-Z][a-zA-Z]+$/.test(ref.referenceName)) {
30
+ const result = resolveModel(ref.referenceName, context);
31
+ if (result) {
32
+ return {
33
+ original: ref,
34
+ targetNodeId: result,
35
+ confidence: 0.8,
36
+ resolvedBy: 'framework',
37
+ };
38
+ }
39
+ }
40
+ // Pattern 2: Controller references
41
+ if (ref.referenceName.endsWith('Controller')) {
42
+ const result = resolveController(ref.referenceName, context);
43
+ if (result) {
44
+ return {
45
+ original: ref,
46
+ targetNodeId: result,
47
+ confidence: 0.85,
48
+ resolvedBy: 'framework',
49
+ };
50
+ }
51
+ }
52
+ // Pattern 3: Helper references
53
+ if (ref.referenceName.endsWith('Helper')) {
54
+ const result = resolveHelper(ref.referenceName, context);
55
+ if (result) {
56
+ return {
57
+ original: ref,
58
+ targetNodeId: result,
59
+ confidence: 0.8,
60
+ resolvedBy: 'framework',
61
+ };
62
+ }
63
+ }
64
+ // Pattern 4: Service/Job references
65
+ if (ref.referenceName.endsWith('Service') || ref.referenceName.endsWith('Job')) {
66
+ const result = resolveService(ref.referenceName, context);
67
+ if (result) {
68
+ return {
69
+ original: ref,
70
+ targetNodeId: result,
71
+ confidence: 0.8,
72
+ resolvedBy: 'framework',
73
+ };
74
+ }
75
+ }
76
+ return null;
77
+ },
78
+ extract(filePath, content) {
79
+ if (!filePath.endsWith('.rb'))
80
+ return { nodes: [], references: [] };
81
+ const nodes = [];
82
+ const references = [];
83
+ const now = Date.now();
84
+ const safe = (0, strip_comments_1.stripCommentsForRegex)(content, 'ruby');
85
+ // get/post/put/patch/delete/match '/path', to: 'controller#action'
86
+ // Also: get '/path' => 'controller#action'
87
+ const routeRegex = /\b(get|post|put|patch|delete|match)\s+['"]([^'"]+)['"]\s*(?:,\s*to:\s*|=>\s*)['"]([^#'"]+)#([^'"]+)['"]/g;
88
+ let match;
89
+ while ((match = routeRegex.exec(safe)) !== null) {
90
+ const [, method, routePath, _controller, action] = match;
91
+ const line = safe.slice(0, match.index).split('\n').length;
92
+ const upper = method.toUpperCase();
93
+ const routeNode = {
94
+ id: `route:${filePath}:${line}:${upper}:${routePath}`,
95
+ kind: 'route',
96
+ name: `${upper} ${routePath}`,
97
+ qualifiedName: `${filePath}::route:${routePath}`,
98
+ filePath,
99
+ startLine: line,
100
+ endLine: line,
101
+ startColumn: 0,
102
+ endColumn: match[0].length,
103
+ language: 'ruby',
104
+ updatedAt: now,
105
+ };
106
+ nodes.push(routeNode);
107
+ references.push({
108
+ fromNodeId: routeNode.id,
109
+ referenceName: action,
110
+ referenceKind: 'references',
111
+ line,
112
+ column: 0,
113
+ filePath,
114
+ language: 'ruby',
115
+ });
116
+ }
117
+ return { nodes, references };
118
+ },
119
+ };
120
+ // Helper functions
121
+ function resolveModel(name, context) {
122
+ // Try direct file path lookup first (Rails convention: CamelCase -> snake_case.rb)
123
+ const snakeName = name.replace(/([A-Z])/g, '_$1').toLowerCase().slice(1);
124
+ const possiblePaths = [
125
+ `app/models/${snakeName}.rb`,
126
+ `app/models/concerns/${snakeName}.rb`,
127
+ ];
128
+ for (const modelPath of possiblePaths) {
129
+ if (context.fileExists(modelPath)) {
130
+ const nodes = context.getNodesInFile(modelPath);
131
+ const modelNode = nodes.find((n) => n.kind === 'class' && n.name === name);
132
+ if (modelNode) {
133
+ return modelNode.id;
134
+ }
135
+ }
136
+ }
137
+ // Fall back to name-based lookup
138
+ const candidates = context.getNodesByName(name);
139
+ const modelNode = candidates.find((n) => n.kind === 'class' && n.filePath.includes('app/models/'));
140
+ if (modelNode)
141
+ return modelNode.id;
142
+ return null;
143
+ }
144
+ function resolveController(name, context) {
145
+ // Try direct file path lookup first
146
+ const snakeName = name.replace(/([A-Z])/g, '_$1').toLowerCase().slice(1);
147
+ const possiblePaths = [
148
+ `app/controllers/${snakeName}.rb`,
149
+ `app/controllers/api/${snakeName}.rb`,
150
+ `app/controllers/api/v1/${snakeName}.rb`,
151
+ ];
152
+ for (const controllerPath of possiblePaths) {
153
+ if (context.fileExists(controllerPath)) {
154
+ const nodes = context.getNodesInFile(controllerPath);
155
+ const controllerNode = nodes.find((n) => n.kind === 'class' && n.name === name);
156
+ if (controllerNode) {
157
+ return controllerNode.id;
158
+ }
159
+ }
160
+ }
161
+ // Fall back to name-based lookup
162
+ const candidates = context.getNodesByName(name);
163
+ const controllerNode = candidates.find((n) => n.kind === 'class' && n.filePath.includes('controllers/'));
164
+ if (controllerNode)
165
+ return controllerNode.id;
166
+ return null;
167
+ }
168
+ function resolveHelper(name, context) {
169
+ const snakeName = name.replace(/([A-Z])/g, '_$1').toLowerCase().slice(1);
170
+ const helperPath = `app/helpers/${snakeName}.rb`;
171
+ if (context.fileExists(helperPath)) {
172
+ const nodes = context.getNodesInFile(helperPath);
173
+ const helperNode = nodes.find((n) => n.kind === 'module' && n.name === name);
174
+ if (helperNode) {
175
+ return helperNode.id;
176
+ }
177
+ }
178
+ return null;
179
+ }
180
+ function resolveService(name, context) {
181
+ const snakeName = name.replace(/([A-Z])/g, '_$1').toLowerCase().slice(1);
182
+ const possiblePaths = [
183
+ `app/services/${snakeName}.rb`,
184
+ `app/jobs/${snakeName}.rb`,
185
+ `app/workers/${snakeName}.rb`,
186
+ ];
187
+ for (const servicePath of possiblePaths) {
188
+ if (context.fileExists(servicePath)) {
189
+ const nodes = context.getNodesInFile(servicePath);
190
+ const serviceNode = nodes.find((n) => n.kind === 'class' && n.name === name);
191
+ if (serviceNode) {
192
+ return serviceNode.id;
193
+ }
194
+ }
195
+ }
196
+ return null;
197
+ }
198
+ //# sourceMappingURL=ruby.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Rust Framework Resolver
3
+ *
4
+ * Handles Actix-web, Rocket, Axum, and common Rust patterns.
5
+ */
6
+ import { FrameworkResolver } from '../types'
7
+ export declare const rustResolver: FrameworkResolver
8
+ //# sourceMappingURL=rust.d.ts.map
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ /**
3
+ * Rust Framework Resolver
4
+ *
5
+ * Handles Actix-web, Rocket, Axum, and common Rust patterns.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.rustResolver = void 0;
9
+ const strip_comments_1 = require("../strip-comments");
10
+ const cargo_workspace_1 = require("./cargo-workspace");
11
+ const cargoWorkspaceMapCache = new WeakMap();
12
+ function getCachedCargoWorkspaceCrateMap(context) {
13
+ const cached = cargoWorkspaceMapCache.get(context);
14
+ if (cached)
15
+ return cached;
16
+ const map = (0, cargo_workspace_1.getCargoWorkspaceCrateMap)(context);
17
+ cargoWorkspaceMapCache.set(context, map);
18
+ return map;
19
+ }
20
+ exports.rustResolver = {
21
+ name: 'rust',
22
+ languages: ['rust'],
23
+ detect(context) {
24
+ // Check for Cargo.toml (Rust project signature)
25
+ return context.fileExists('Cargo.toml');
26
+ },
27
+ resolve(ref, context) {
28
+ // Pattern 1: Handler references
29
+ if (ref.referenceName.endsWith('_handler') || ref.referenceName.startsWith('handle_')) {
30
+ const result = resolveByNameAndKind(ref.referenceName, FUNCTION_KINDS, HANDLER_DIRS, context);
31
+ if (result) {
32
+ return {
33
+ original: ref,
34
+ targetNodeId: result,
35
+ confidence: 0.8,
36
+ resolvedBy: 'framework',
37
+ };
38
+ }
39
+ }
40
+ // Pattern 2: Service/Repository trait implementations
41
+ if (ref.referenceName.endsWith('Service') || ref.referenceName.endsWith('Repository')) {
42
+ const result = resolveByNameAndKind(ref.referenceName, SERVICE_KINDS, SERVICE_DIRS, context);
43
+ if (result) {
44
+ return {
45
+ original: ref,
46
+ targetNodeId: result,
47
+ confidence: 0.8,
48
+ resolvedBy: 'framework',
49
+ };
50
+ }
51
+ }
52
+ // Pattern 3: Struct references (PascalCase)
53
+ if (/^[A-Z][a-zA-Z]+$/.test(ref.referenceName)) {
54
+ const result = resolveByNameAndKind(ref.referenceName, STRUCT_KINDS, MODEL_DIRS, context);
55
+ if (result) {
56
+ return {
57
+ original: ref,
58
+ targetNodeId: result,
59
+ confidence: 0.7,
60
+ resolvedBy: 'framework',
61
+ };
62
+ }
63
+ }
64
+ // Pattern 4: Module references
65
+ if (/^[a-z_]+$/.test(ref.referenceName)) {
66
+ const result = resolveModule(ref.referenceName, context);
67
+ if (result) {
68
+ // Workspace-manifest hits are an exact crate-name -> crate-root
69
+ // mapping straight from Cargo.toml, so we trust them above
70
+ // name-matcher self-file matches (which otherwise win at 0.7
71
+ // because every file containing `use foo::...` has its own
72
+ // import node named `foo`).
73
+ return {
74
+ original: ref,
75
+ targetNodeId: result.targetId,
76
+ confidence: result.fromWorkspace ? 0.95 : 0.6,
77
+ resolvedBy: 'framework',
78
+ };
79
+ }
80
+ }
81
+ return null;
82
+ },
83
+ extract(filePath, content) {
84
+ if (!filePath.endsWith('.rs'))
85
+ return { nodes: [], references: [] };
86
+ const nodes = [];
87
+ const references = [];
88
+ const now = Date.now();
89
+ const safe = (0, strip_comments_1.stripCommentsForRegex)(content, 'rust');
90
+ // Actix-web / Rocket attribute: #[get("/path")] fn handler(..)
91
+ // Capture the method, path, and the fn identifier that follows.
92
+ const attrRegex = /#\[(get|post|put|patch|delete|head|options)\s*\(\s*["']([^"']+)["'][^\]]*\)\]/g;
93
+ let match;
94
+ while ((match = attrRegex.exec(safe)) !== null) {
95
+ const [, method, routePath] = match;
96
+ const line = safe.slice(0, match.index).split('\n').length;
97
+ const upper = method.toUpperCase();
98
+ const routeNode = {
99
+ id: `route:${filePath}:${line}:${upper}:${routePath}`,
100
+ kind: 'route',
101
+ name: `${upper} ${routePath}`,
102
+ qualifiedName: `${filePath}::route:${routePath}`,
103
+ filePath,
104
+ startLine: line,
105
+ endLine: line,
106
+ startColumn: 0,
107
+ endColumn: match[0].length,
108
+ language: 'rust',
109
+ updatedAt: now,
110
+ };
111
+ nodes.push(routeNode);
112
+ const tail = safe.slice(match.index + match[0].length);
113
+ const fnMatch = tail.match(/\n\s*(?:pub\s+)?(?:async\s+)?fn\s+(\w+)/);
114
+ if (fnMatch) {
115
+ references.push({
116
+ fromNodeId: routeNode.id,
117
+ referenceName: fnMatch[1],
118
+ referenceKind: 'references',
119
+ line,
120
+ column: 0,
121
+ filePath,
122
+ language: 'rust',
123
+ });
124
+ }
125
+ }
126
+ // Axum: .route("/path", get(handler))
127
+ const axumRegex = /\.route\s*\(\s*"([^"]+)"\s*,\s*(get|post|put|patch|delete)\s*\(\s*(\w+)/g;
128
+ while ((match = axumRegex.exec(safe)) !== null) {
129
+ const [, routePath, method, handler] = match;
130
+ const line = safe.slice(0, match.index).split('\n').length;
131
+ const upper = method.toUpperCase();
132
+ const routeNode = {
133
+ id: `route:${filePath}:${line}:${upper}:${routePath}`,
134
+ kind: 'route',
135
+ name: `${upper} ${routePath}`,
136
+ qualifiedName: `${filePath}::route:${routePath}`,
137
+ filePath,
138
+ startLine: line,
139
+ endLine: line,
140
+ startColumn: 0,
141
+ endColumn: match[0].length,
142
+ language: 'rust',
143
+ updatedAt: now,
144
+ };
145
+ nodes.push(routeNode);
146
+ references.push({
147
+ fromNodeId: routeNode.id,
148
+ referenceName: handler,
149
+ referenceKind: 'references',
150
+ line,
151
+ column: 0,
152
+ filePath,
153
+ language: 'rust',
154
+ });
155
+ }
156
+ return { nodes, references };
157
+ },
158
+ };
159
+ // Directory patterns
160
+ const HANDLER_DIRS = ['/handlers/', '/handler/', '/api/', '/routes/', '/controllers/'];
161
+ const SERVICE_DIRS = ['/services/', '/service/', '/repository/', '/domain/'];
162
+ const MODEL_DIRS = ['/models/', '/model/', '/entities/', '/entity/', '/domain/', '/types/'];
163
+ const FUNCTION_KINDS = new Set(['function']);
164
+ const SERVICE_KINDS = new Set(['struct', 'trait']);
165
+ const STRUCT_KINDS = new Set(['struct']);
166
+ /**
167
+ * Resolve a symbol by name using indexed queries instead of scanning all files.
168
+ */
169
+ function resolveByNameAndKind(name, kinds, preferredDirPatterns, context) {
170
+ const candidates = context.getNodesByName(name);
171
+ if (candidates.length === 0)
172
+ return null;
173
+ const kindFiltered = candidates.filter((n) => kinds.has(n.kind));
174
+ if (kindFiltered.length === 0)
175
+ return null;
176
+ // Prefer candidates in framework-conventional directories
177
+ const preferred = kindFiltered.filter((n) => preferredDirPatterns.some((d) => n.filePath.includes(d)));
178
+ if (preferred.length > 0)
179
+ return preferred[0].id;
180
+ // Fall back to any match
181
+ return kindFiltered[0].id;
182
+ }
183
+ function resolveModule(name, context) {
184
+ // Rust modules can be either mod.rs in a directory or name.rs
185
+ const localPaths = [`src/${name}.rs`, `src/${name}/mod.rs`];
186
+ const workspaceCrates = getCachedCargoWorkspaceCrateMap(context);
187
+ const cratePath = workspaceCrates.get(name);
188
+ const workspacePaths = cratePath
189
+ ? [`${cratePath}/src/lib.rs`, `${cratePath}/src/main.rs`]
190
+ : [];
191
+ const candidates = [
192
+ ...localPaths.map((path) => ({ path, fromWorkspace: false })),
193
+ ...workspacePaths.map((path) => ({ path, fromWorkspace: true })),
194
+ ];
195
+ for (const { path: modPath, fromWorkspace } of candidates) {
196
+ if (!context.fileExists(modPath))
197
+ continue;
198
+ const nodes = context.getNodesInFile(modPath);
199
+ const modNode = nodes.find((n) => n.kind === 'module');
200
+ if (modNode)
201
+ return { targetId: modNode.id, fromWorkspace };
202
+ if (nodes.length > 0)
203
+ return { targetId: nodes[0].id, fromWorkspace };
204
+ }
205
+ return null;
206
+ }
207
+ //# sourceMappingURL=rust.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Svelte / SvelteKit Framework Resolver
3
+ *
4
+ * Handles Svelte component references, Svelte 5 runes,
5
+ * store auto-subscriptions, and SvelteKit route/module patterns.
6
+ */
7
+ import { FrameworkResolver } from '../types'
8
+ export declare const svelteResolver: FrameworkResolver
9
+ //# sourceMappingURL=svelte.d.ts.map
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ /**
3
+ * Svelte / SvelteKit Framework Resolver
4
+ *
5
+ * Handles Svelte component references, Svelte 5 runes,
6
+ * store auto-subscriptions, and SvelteKit route/module patterns.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.svelteResolver = void 0;
10
+ /**
11
+ * Svelte 5 runes — compiler-provided, not user code
12
+ */
13
+ const SVELTE_RUNES = new Set([
14
+ '$state',
15
+ '$state.raw',
16
+ '$state.snapshot',
17
+ '$derived',
18
+ '$derived.by',
19
+ '$effect',
20
+ '$effect.pre',
21
+ '$effect.root',
22
+ '$effect.tracking',
23
+ '$props',
24
+ '$bindable',
25
+ '$inspect',
26
+ '$host',
27
+ ]);
28
+ /**
29
+ * SvelteKit framework-provided module prefixes
30
+ */
31
+ const SVELTEKIT_MODULE_PREFIXES = [
32
+ '$app/navigation',
33
+ '$app/stores',
34
+ '$app/environment',
35
+ '$app/forms',
36
+ '$app/paths',
37
+ '$env/static/private',
38
+ '$env/static/public',
39
+ '$env/dynamic/private',
40
+ '$env/dynamic/public',
41
+ ];
42
+ exports.svelteResolver = {
43
+ name: 'svelte',
44
+ languages: ['svelte'],
45
+ detect(context) {
46
+ // Check for svelte or @sveltejs/kit in package.json
47
+ const packageJson = context.readFile('package.json');
48
+ if (packageJson) {
49
+ try {
50
+ const pkg = JSON.parse(packageJson);
51
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
52
+ if (deps.svelte || deps['@sveltejs/kit']) {
53
+ return true;
54
+ }
55
+ }
56
+ catch {
57
+ // Invalid JSON
58
+ }
59
+ }
60
+ // Check for .svelte files in project
61
+ const allFiles = context.getAllFiles();
62
+ return allFiles.some((f) => f.endsWith('.svelte'));
63
+ },
64
+ resolve(ref, context) {
65
+ // Pattern 1: Svelte runes ($state, $derived, $effect, etc.)
66
+ if (isRuneReference(ref.referenceName)) {
67
+ // Runes are compiler-provided — return a high-confidence "framework" resolution
68
+ // so CodeGraph doesn't waste time searching for user-defined symbols.
69
+ // We use the fromNodeId as targetNodeId since runes don't have real targets.
70
+ return {
71
+ original: ref,
72
+ targetNodeId: ref.fromNodeId,
73
+ confidence: 1.0,
74
+ resolvedBy: 'framework',
75
+ };
76
+ }
77
+ // Pattern 2: Store auto-subscriptions ($storeName)
78
+ if (ref.referenceName.startsWith('$') && !ref.referenceName.startsWith('$$')) {
79
+ const storeName = ref.referenceName.substring(1);
80
+ const storeNode = context.getNodesByName(storeName).find((n) => n.kind === 'variable' || n.kind === 'constant');
81
+ if (storeNode) {
82
+ return {
83
+ original: ref,
84
+ targetNodeId: storeNode.id,
85
+ confidence: 0.85,
86
+ resolvedBy: 'framework',
87
+ };
88
+ }
89
+ }
90
+ // Pattern 3: SvelteKit module imports ($app/*, $env/*, $lib/*)
91
+ if (ref.referenceKind === 'imports' && ref.referenceName.startsWith('$')) {
92
+ // $lib/* resolves to src/lib/* — try to find the target file
93
+ if (ref.referenceName.startsWith('$lib/')) {
94
+ const libPath = ref.referenceName.replace('$lib/', 'src/lib/');
95
+ // Try common extensions
96
+ for (const ext of ['', '.ts', '.js', '.svelte', '/index.ts', '/index.js']) {
97
+ const fullPath = libPath + ext;
98
+ if (context.fileExists(fullPath)) {
99
+ const nodes = context.getNodesInFile(fullPath);
100
+ if (nodes.length > 0) {
101
+ return {
102
+ original: ref,
103
+ targetNodeId: nodes[0].id,
104
+ confidence: 0.9,
105
+ resolvedBy: 'framework',
106
+ };
107
+ }
108
+ }
109
+ }
110
+ }
111
+ // $app/* and $env/* are framework-provided
112
+ if (SVELTEKIT_MODULE_PREFIXES.some((prefix) => ref.referenceName.startsWith(prefix))) {
113
+ return {
114
+ original: ref,
115
+ targetNodeId: ref.fromNodeId,
116
+ confidence: 1.0,
117
+ resolvedBy: 'framework',
118
+ };
119
+ }
120
+ }
121
+ // Pattern 4: Component references (PascalCase) — resolve to .svelte files
122
+ if (isPascalCase(ref.referenceName) && ref.referenceKind === 'calls') {
123
+ const result = resolveComponent(ref.referenceName, ref.filePath, context);
124
+ if (result) {
125
+ return {
126
+ original: ref,
127
+ targetNodeId: result,
128
+ confidence: 0.8,
129
+ resolvedBy: 'framework',
130
+ };
131
+ }
132
+ }
133
+ return null;
134
+ },
135
+ extract(filePath, _content) {
136
+ const nodes = [];
137
+ const now = Date.now();
138
+ // Detect SvelteKit route files
139
+ const fileName = filePath.split(/[/\\]/).pop() || '';
140
+ const routeMatch = getSvelteKitRouteInfo(fileName);
141
+ if (routeMatch) {
142
+ // Extract route path from directory structure
143
+ // e.g., src/routes/blog/[slug]/+page.svelte -> /blog/:slug
144
+ const routePath = filePathToSvelteKitRoute(filePath);
145
+ if (routePath) {
146
+ nodes.push({
147
+ id: `route:${filePath}:${routePath}:1`,
148
+ kind: 'route',
149
+ name: routePath,
150
+ qualifiedName: `${filePath}::route:${routePath}`,
151
+ filePath,
152
+ startLine: 1,
153
+ endLine: 1,
154
+ startColumn: 0,
155
+ endColumn: 0,
156
+ language: filePath.endsWith('.svelte') ? 'svelte' : 'typescript',
157
+ updatedAt: now,
158
+ });
159
+ }
160
+ }
161
+ return { nodes, references: [] };
162
+ },
163
+ };
164
+ /**
165
+ * Check if a reference name is a Svelte rune
166
+ */
167
+ function isRuneReference(name) {
168
+ // Direct match (e.g. $state, $derived)
169
+ if (SVELTE_RUNES.has(name))
170
+ return true;
171
+ // Rune method calls come through as the base rune name
172
+ // e.g. $state.raw -> the call is to "$state" with ".raw" accessed as property
173
+ // Check if it's a base rune that has sub-methods
174
+ if (name === '$state' || name === '$derived' || name === '$effect')
175
+ return true;
176
+ return false;
177
+ }
178
+ /**
179
+ * Check if string is PascalCase
180
+ */
181
+ function isPascalCase(str) {
182
+ return /^[A-Z][a-zA-Z0-9]*$/.test(str);
183
+ }
184
+ /**
185
+ * Resolve a Svelte component reference using name-based lookup
186
+ */
187
+ function resolveComponent(name, fromFile, context) {
188
+ // Look for component nodes by name
189
+ const candidates = context.getNodesByName(name);
190
+ const components = candidates.filter((n) => n.kind === 'component');
191
+ if (components.length === 0)
192
+ return null;
193
+ // Prefer same directory
194
+ const fromDir = fromFile.substring(0, fromFile.lastIndexOf('/'));
195
+ const sameDir = components.filter((n) => n.filePath.startsWith(fromDir));
196
+ if (sameDir.length > 0)
197
+ return sameDir[0].id;
198
+ return components[0].id;
199
+ }
200
+ /**
201
+ * SvelteKit route file patterns
202
+ */
203
+ const SVELTEKIT_ROUTE_FILES = {
204
+ '+page.svelte': 'page',
205
+ '+page.ts': 'page-load',
206
+ '+page.js': 'page-load',
207
+ '+page.server.ts': 'page-server-load',
208
+ '+page.server.js': 'page-server-load',
209
+ '+layout.svelte': 'layout',
210
+ '+layout.ts': 'layout-load',
211
+ '+layout.js': 'layout-load',
212
+ '+layout.server.ts': 'layout-server-load',
213
+ '+layout.server.js': 'layout-server-load',
214
+ '+server.ts': 'api-endpoint',
215
+ '+server.js': 'api-endpoint',
216
+ '+error.svelte': 'error-page',
217
+ };
218
+ /**
219
+ * Check if filename is a SvelteKit route file
220
+ */
221
+ function getSvelteKitRouteInfo(fileName) {
222
+ return SVELTEKIT_ROUTE_FILES[fileName] || null;
223
+ }
224
+ /**
225
+ * Convert a file path to a SvelteKit route path
226
+ */
227
+ function filePathToSvelteKitRoute(filePath) {
228
+ // Normalize to forward slashes
229
+ const normalized = filePath.replace(/\\/g, '/');
230
+ // Find the routes directory
231
+ const routesIndex = normalized.indexOf('/routes/');
232
+ if (routesIndex === -1)
233
+ return null;
234
+ // Extract the path after routes/
235
+ const afterRoutes = normalized.substring(routesIndex + '/routes/'.length);
236
+ // Remove the file name
237
+ const lastSlash = afterRoutes.lastIndexOf('/');
238
+ const dirPath = lastSlash === -1 ? '' : afterRoutes.substring(0, lastSlash);
239
+ // Convert SvelteKit param syntax [param] to :param
240
+ let route = '/' + dirPath
241
+ .replace(/\[\.\.\.([^\]]+)\]/g, '*$1') // [...rest] -> *rest
242
+ .replace(/\[{2}([^\]]+)\]{2}/g, ':$1?') // [[optional]] -> :optional?
243
+ .replace(/\[([^\]]+)\]/g, ':$1'); // [param] -> :param
244
+ if (route === '/')
245
+ return '/';
246
+ // Remove trailing slash
247
+ return route.replace(/\/$/, '');
248
+ }
249
+ //# sourceMappingURL=svelte.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Swift Framework Resolver
3
+ *
4
+ * Handles SwiftUI, UIKit, and Vapor (server-side Swift) patterns.
5
+ */
6
+ import { FrameworkResolver } from '../types'
7
+ export declare const swiftUIResolver: FrameworkResolver
8
+ export declare const uikitResolver: FrameworkResolver
9
+ export declare const vaporResolver: FrameworkResolver
10
+ //# sourceMappingURL=swift.d.ts.map