code-auditor-mcp 2.6.2 → 3.0.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 (343) hide show
  1. package/README.md +319 -147
  2. package/dist/analyzers/analyzerUtils.d.ts +13 -11
  3. package/dist/analyzers/analyzerUtils.d.ts.map +1 -1
  4. package/dist/analyzers/analyzerUtils.js +22 -56
  5. package/dist/analyzers/analyzerUtils.js.map +1 -1
  6. package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts.map +1 -1
  7. package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.d.ts.map +1 -1
  8. package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.js.map +1 -1
  9. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
  10. package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
  11. package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
  12. package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
  13. package/dist/analyzers/dataAccessAnalyzer.d.ts.map +1 -1
  14. package/dist/analyzers/dataAccessAnalyzer.js +50 -24
  15. package/dist/analyzers/dataAccessAnalyzer.js.map +1 -1
  16. package/dist/analyzers/documentationAnalyzer.d.ts +4 -1
  17. package/dist/analyzers/documentationAnalyzer.d.ts.map +1 -1
  18. package/dist/analyzers/documentationAnalyzer.js +210 -111
  19. package/dist/analyzers/documentationAnalyzer.js.map +1 -1
  20. package/dist/analyzers/dryAnalyzer.d.ts.map +1 -1
  21. package/dist/analyzers/dryAnalyzer.js +190 -58
  22. package/dist/analyzers/dryAnalyzer.js.map +1 -1
  23. package/dist/analyzers/invariantsAnalyzer.d.ts +20 -0
  24. package/dist/analyzers/invariantsAnalyzer.d.ts.map +1 -0
  25. package/dist/analyzers/invariantsAnalyzer.js +148 -0
  26. package/dist/analyzers/invariantsAnalyzer.js.map +1 -0
  27. package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
  28. package/dist/analyzers/reactAnalyzer.js +2 -2
  29. package/dist/analyzers/reactAnalyzer.js.map +1 -1
  30. package/dist/analyzers/schemaAnalyzer.d.ts +2 -0
  31. package/dist/analyzers/schemaAnalyzer.d.ts.map +1 -1
  32. package/dist/analyzers/schemaAnalyzer.js +306 -147
  33. package/dist/analyzers/schemaAnalyzer.js.map +1 -1
  34. package/dist/analyzers/solidAnalyzer.d.ts.map +1 -1
  35. package/dist/analyzers/solidAnalyzer.js +145 -119
  36. package/dist/analyzers/solidAnalyzer.js.map +1 -1
  37. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +3 -1
  38. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
  39. package/dist/analyzers/universal/UniversalDRYAnalyzer.js +41 -1
  40. package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
  41. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
  42. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +8 -8
  43. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
  44. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts.map +1 -1
  45. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +6 -6
  46. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
  47. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
  48. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
  49. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +1 -1
  50. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
  51. package/dist/api/index.js +1 -0
  52. package/dist/api/index.js.map +1 -1
  53. package/dist/auditRunner.d.ts.map +1 -1
  54. package/dist/auditRunner.js +367 -24
  55. package/dist/auditRunner.js.map +1 -1
  56. package/dist/cli.d.ts +1 -1
  57. package/dist/cli.d.ts.map +1 -1
  58. package/dist/cli.js +740 -18
  59. package/dist/cli.js.map +1 -1
  60. package/dist/codeIndexDB-enhanced.d.ts +35 -13
  61. package/dist/codeIndexDB-enhanced.d.ts.map +1 -1
  62. package/dist/codeIndexDB-enhanced.js +311 -214
  63. package/dist/codeIndexDB-enhanced.js.map +1 -1
  64. package/dist/{codeIndexDb.d.ts → codeIndexDB.d.ts} +51 -224
  65. package/dist/codeIndexDB.d.ts.map +1 -0
  66. package/dist/codeIndexDB.js +2042 -0
  67. package/dist/codeIndexDB.js.map +1 -0
  68. package/dist/codeIndexService.d.ts.map +1 -1
  69. package/dist/codeIndexService.js.map +1 -1
  70. package/dist/componentScanner.d.ts +14 -8
  71. package/dist/componentScanner.d.ts.map +1 -1
  72. package/dist/componentScanner.js +136 -113
  73. package/dist/componentScanner.js.map +1 -1
  74. package/dist/config/configLoader.d.ts.map +1 -1
  75. package/dist/config/configLoader.js +10 -7
  76. package/dist/config/configLoader.js.map +1 -1
  77. package/dist/config/defaults.d.ts.map +1 -1
  78. package/dist/constants.js.map +1 -1
  79. package/dist/fingerprint.d.ts +15 -0
  80. package/dist/fingerprint.d.ts.map +1 -0
  81. package/dist/fingerprint.js +32 -0
  82. package/dist/fingerprint.js.map +1 -0
  83. package/dist/functionScanner.d.ts +5 -0
  84. package/dist/functionScanner.d.ts.map +1 -1
  85. package/dist/functionScanner.js +417 -341
  86. package/dist/functionScanner.js.map +1 -1
  87. package/dist/generators/AWSQConfigGenerator.d.ts.map +1 -1
  88. package/dist/generators/AiderConfigGenerator.d.ts.map +1 -1
  89. package/dist/generators/BaseConfigGenerator.d.ts.map +1 -1
  90. package/dist/generators/BaseConfigGenerator.js.map +1 -1
  91. package/dist/generators/ClaudeConfigGenerator.d.ts.map +1 -1
  92. package/dist/generators/ClineConfigGenerator.d.ts.map +1 -1
  93. package/dist/generators/CodeiumConfigGenerator.d.ts.map +1 -1
  94. package/dist/generators/ConfigGeneratorFactory.d.ts.map +1 -1
  95. package/dist/generators/ConfigGeneratorFactory.js.map +1 -1
  96. package/dist/generators/ContinueConfigGenerator.d.ts.map +1 -1
  97. package/dist/generators/CopilotConfigGenerator.d.ts.map +1 -1
  98. package/dist/generators/CursorConfigGenerator.d.ts.map +1 -1
  99. package/dist/generators/JetBrainsConfigGenerator.d.ts.map +1 -1
  100. package/dist/generators/VSCodeConfigGenerator.d.ts.map +1 -1
  101. package/dist/grammars/tree-sitter-go.wasm +0 -0
  102. package/dist/grammars/tree-sitter-javascript.wasm +0 -0
  103. package/dist/grammars/tree-sitter-tsx.wasm +0 -0
  104. package/dist/grammars/tree-sitter-typescript.wasm +0 -0
  105. package/dist/index.d.ts +1 -0
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +2 -1
  108. package/dist/index.js.map +1 -1
  109. package/dist/invariants/index.d.ts +9 -0
  110. package/dist/invariants/index.d.ts.map +1 -0
  111. package/dist/invariants/index.js +4 -0
  112. package/dist/invariants/index.js.map +1 -0
  113. package/dist/invariants/invariant-rules.schema.json +137 -0
  114. package/dist/invariants/ruleEngine.d.ts +32 -0
  115. package/dist/invariants/ruleEngine.d.ts.map +1 -0
  116. package/dist/invariants/ruleEngine.js +536 -0
  117. package/dist/invariants/ruleEngine.js.map +1 -0
  118. package/dist/invariants/ruleValidator.d.ts +17 -0
  119. package/dist/invariants/ruleValidator.d.ts.map +1 -0
  120. package/dist/invariants/ruleValidator.js +264 -0
  121. package/dist/invariants/ruleValidator.js.map +1 -0
  122. package/dist/invariants/types.d.ts +78 -0
  123. package/dist/invariants/types.d.ts.map +1 -0
  124. package/dist/invariants/types.js +5 -0
  125. package/dist/invariants/types.js.map +1 -0
  126. package/dist/languages/LanguageOrchestrator.d.ts.map +1 -1
  127. package/dist/languages/LanguageOrchestrator.js.map +1 -1
  128. package/dist/languages/LanguageRegistry.d.ts.map +1 -1
  129. package/dist/languages/RuntimeManager.d.ts.map +1 -1
  130. package/dist/languages/RuntimeManager.js +1 -1
  131. package/dist/languages/RuntimeManager.js.map +1 -1
  132. package/dist/languages/UniversalAnalyzer.d.ts.map +1 -1
  133. package/dist/languages/UniversalAnalyzer.js.map +1 -1
  134. package/dist/languages/adapterBridge.d.ts +102 -0
  135. package/dist/languages/adapterBridge.d.ts.map +1 -0
  136. package/dist/languages/adapterBridge.js +382 -0
  137. package/dist/languages/adapterBridge.js.map +1 -0
  138. package/dist/languages/go/GoAdapter.d.ts +37 -26
  139. package/dist/languages/go/GoAdapter.d.ts.map +1 -1
  140. package/dist/languages/go/GoAdapter.js +560 -281
  141. package/dist/languages/go/GoAdapter.js.map +1 -1
  142. package/dist/languages/index.d.ts +5 -2
  143. package/dist/languages/index.d.ts.map +1 -1
  144. package/dist/languages/index.js +11 -9
  145. package/dist/languages/index.js.map +1 -1
  146. package/dist/languages/tree-sitter/converter.d.ts +43 -0
  147. package/dist/languages/tree-sitter/converter.d.ts.map +1 -0
  148. package/dist/languages/tree-sitter/converter.js +150 -0
  149. package/dist/languages/tree-sitter/converter.js.map +1 -0
  150. package/dist/languages/tree-sitter/parser.d.ts +36 -0
  151. package/dist/languages/tree-sitter/parser.d.ts.map +1 -0
  152. package/dist/languages/tree-sitter/parser.js +114 -0
  153. package/dist/languages/tree-sitter/parser.js.map +1 -0
  154. package/dist/languages/types.d.ts +11 -0
  155. package/dist/languages/types.d.ts.map +1 -1
  156. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +92 -0
  157. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -0
  158. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +951 -0
  159. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -0
  160. package/dist/mcp-tools/projectTasks.d.ts +58 -22
  161. package/dist/mcp-tools/projectTasks.d.ts.map +1 -1
  162. package/dist/mcp-tools/projectTasks.js +172 -10
  163. package/dist/mcp-tools/projectTasks.js.map +1 -1
  164. package/dist/mcp-tools/whitelistTools.d.ts +21 -21
  165. package/dist/mcp-tools/whitelistTools.d.ts.map +1 -1
  166. package/dist/mcp-tools/workflowGuide.d.ts.map +1 -1
  167. package/dist/mcp-tools/workflowGuide.js +130 -126
  168. package/dist/mcp-tools/workflowGuide.js.map +1 -1
  169. package/dist/mcp-tools-shared.d.ts.map +1 -1
  170. package/dist/mcp-tools-shared.js.map +1 -1
  171. package/dist/mcp-ui-simple.js +1 -1
  172. package/dist/mcp-ui-simple.js.map +1 -1
  173. package/dist/mcp.d.ts +1 -1
  174. package/dist/mcp.d.ts.map +1 -1
  175. package/dist/mcp.js +1376 -1181
  176. package/dist/mcp.js.map +1 -1
  177. package/dist/mcpAuditJobs.d.ts +4 -0
  178. package/dist/mcpAuditJobs.d.ts.map +1 -1
  179. package/dist/mcpAuditJobs.js +49 -2
  180. package/dist/mcpAuditJobs.js.map +1 -1
  181. package/dist/mcpToolErrors.d.ts.map +1 -1
  182. package/dist/mcpToolErrors.js.map +1 -1
  183. package/dist/native/ast-grep-napi.darwin-arm64.node +0 -0
  184. package/dist/native/ast-grep-napi.darwin-x64.node +0 -0
  185. package/dist/native/ast-grep-napi.linux-arm64-gnu.node +0 -0
  186. package/dist/native/ast-grep-napi.linux-arm64-musl.node +0 -0
  187. package/dist/native/ast-grep-napi.linux-x64-gnu.node +0 -0
  188. package/dist/native/ast-grep-napi.linux-x64-musl.node +0 -0
  189. package/dist/native/ast-grep-napi.win32-x64-msvc.node +0 -0
  190. package/dist/native-bootstrap.d.ts +15 -0
  191. package/dist/native-bootstrap.d.ts.map +1 -0
  192. package/dist/native-bootstrap.js +75 -0
  193. package/dist/native-bootstrap.js.map +1 -0
  194. package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
  195. package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
  196. package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
  197. package/dist/reporting/reportGenerator.d.ts.map +1 -1
  198. package/dist/reporting/reportGenerator.js +4 -0
  199. package/dist/reporting/reportGenerator.js.map +1 -1
  200. package/dist/reporting/sarifReportGenerator.d.ts +39 -0
  201. package/dist/reporting/sarifReportGenerator.d.ts.map +1 -0
  202. package/dist/reporting/sarifReportGenerator.js +229 -0
  203. package/dist/reporting/sarifReportGenerator.js.map +1 -0
  204. package/dist/search/QueryParser.d.ts +41 -0
  205. package/dist/search/QueryParser.d.ts.map +1 -1
  206. package/dist/search/QueryParser.js +200 -19
  207. package/dist/search/QueryParser.js.map +1 -1
  208. package/dist/services/CodeMapGenerator.d.ts.map +1 -1
  209. package/dist/services/CodeMapGenerator.js +4 -4
  210. package/dist/services/CodeMapGenerator.js.map +1 -1
  211. package/dist/services/ProjectTaskRepository.d.ts +15 -2
  212. package/dist/services/ProjectTaskRepository.d.ts.map +1 -1
  213. package/dist/services/ProjectTaskRepository.js +16 -1
  214. package/dist/services/ProjectTaskRepository.js.map +1 -1
  215. package/dist/services/SchemaParser.d.ts.map +1 -1
  216. package/dist/services/SchemaParser.js +5 -8
  217. package/dist/services/SchemaParser.js.map +1 -1
  218. package/dist/services/auditJobService.d.ts +1 -1
  219. package/dist/services/projectTaskHelpers.js.map +1 -1
  220. package/dist/services/whitelistService.d.ts.map +1 -1
  221. package/dist/services/whitelistService.js +1 -1
  222. package/dist/services/whitelistService.js.map +1 -1
  223. package/dist/tool-registry.d.ts +79 -0
  224. package/dist/tool-registry.d.ts.map +1 -0
  225. package/dist/tool-registry.js +139 -0
  226. package/dist/tool-registry.js.map +1 -0
  227. package/dist/types/projectTask.d.ts +4 -0
  228. package/dist/types/projectTask.d.ts.map +1 -1
  229. package/dist/types.d.ts +26 -2
  230. package/dist/types.d.ts.map +1 -1
  231. package/dist/types.js.map +1 -1
  232. package/dist/ui/InteractivePrompts.d.ts.map +1 -1
  233. package/dist/ui/InteractivePrompts.js.map +1 -1
  234. package/dist/utils/astParser.d.ts +31 -38
  235. package/dist/utils/astParser.d.ts.map +1 -1
  236. package/dist/utils/astParser.js +138 -196
  237. package/dist/utils/astParser.js.map +1 -1
  238. package/dist/utils/astUtils.d.ts +87 -58
  239. package/dist/utils/astUtils.d.ts.map +1 -1
  240. package/dist/utils/astUtils.js +852 -581
  241. package/dist/utils/astUtils.js.map +1 -1
  242. package/dist/utils/componentPatterns.js.map +1 -1
  243. package/dist/utils/componentResponsibility.d.ts +13 -9
  244. package/dist/utils/componentResponsibility.d.ts.map +1 -1
  245. package/dist/utils/componentResponsibility.js +236 -206
  246. package/dist/utils/componentResponsibility.js.map +1 -1
  247. package/dist/utils/dependencyExtractor.d.ts +11 -6
  248. package/dist/utils/dependencyExtractor.d.ts.map +1 -1
  249. package/dist/utils/dependencyExtractor.js +200 -119
  250. package/dist/utils/dependencyExtractor.js.map +1 -1
  251. package/dist/utils/fileDiscovery.d.ts +1 -1
  252. package/dist/utils/fileDiscovery.d.ts.map +1 -1
  253. package/dist/utils/fileDiscovery.js.map +1 -1
  254. package/dist/utils/jsDocParser.d.ts +27 -30
  255. package/dist/utils/jsDocParser.d.ts.map +1 -1
  256. package/dist/utils/jsDocParser.js +271 -207
  257. package/dist/utils/jsDocParser.js.map +1 -1
  258. package/dist/utils/reactDetection.d.ts +27 -12
  259. package/dist/utils/reactDetection.d.ts.map +1 -1
  260. package/dist/utils/reactDetection.js +331 -219
  261. package/dist/utils/reactDetection.js.map +1 -1
  262. package/dist/workers/auditWorker.js +17 -3
  263. package/dist/workers/auditWorker.js.map +1 -1
  264. package/package.json +54 -51
  265. package/dist/adapters/GoAdapter.d.ts +0 -53
  266. package/dist/adapters/GoAdapter.d.ts.map +0 -1
  267. package/dist/adapters/GoAdapter.js +0 -611
  268. package/dist/adapters/GoAdapter.js.map +0 -1
  269. package/dist/adapters/GoConfig.d.ts +0 -35
  270. package/dist/adapters/GoConfig.d.ts.map +0 -1
  271. package/dist/adapters/GoConfig.js +0 -155
  272. package/dist/adapters/GoConfig.js.map +0 -1
  273. package/dist/adapters/LanguageAdapter.d.ts +0 -135
  274. package/dist/adapters/LanguageAdapter.d.ts.map +0 -1
  275. package/dist/adapters/LanguageAdapter.js +0 -47
  276. package/dist/adapters/LanguageAdapter.js.map +0 -1
  277. package/dist/adapters/TypeScriptAdapter.d.ts +0 -43
  278. package/dist/adapters/TypeScriptAdapter.d.ts.map +0 -1
  279. package/dist/adapters/TypeScriptAdapter.js +0 -386
  280. package/dist/adapters/TypeScriptAdapter.js.map +0 -1
  281. package/dist/adapters/UniversalAnalyzer.d.ts +0 -42
  282. package/dist/adapters/UniversalAnalyzer.d.ts.map +0 -1
  283. package/dist/adapters/UniversalAnalyzer.js +0 -103
  284. package/dist/adapters/UniversalAnalyzer.js.map +0 -1
  285. package/dist/adapters/UniversalSOLIDAnalyzer.d.ts +0 -48
  286. package/dist/adapters/UniversalSOLIDAnalyzer.d.ts.map +0 -1
  287. package/dist/adapters/UniversalSOLIDAnalyzer.js +0 -178
  288. package/dist/adapters/UniversalSOLIDAnalyzer.js.map +0 -1
  289. package/dist/adapters/solidAnalyzerCompat.d.ts +0 -21
  290. package/dist/adapters/solidAnalyzerCompat.d.ts.map +0 -1
  291. package/dist/adapters/solidAnalyzerCompat.js +0 -78
  292. package/dist/adapters/solidAnalyzerCompat.js.map +0 -1
  293. package/dist/analyzers/dataAccessAnalyzerCompat.d.ts +0 -20
  294. package/dist/analyzers/dataAccessAnalyzerCompat.d.ts.map +0 -1
  295. package/dist/analyzers/dataAccessAnalyzerCompat.js +0 -59
  296. package/dist/analyzers/dataAccessAnalyzerCompat.js.map +0 -1
  297. package/dist/analyzers/documentationAnalyzerCompat.d.ts +0 -20
  298. package/dist/analyzers/documentationAnalyzerCompat.d.ts.map +0 -1
  299. package/dist/analyzers/documentationAnalyzerCompat.js +0 -52
  300. package/dist/analyzers/documentationAnalyzerCompat.js.map +0 -1
  301. package/dist/analyzers/dryAnalyzerCompat.d.ts +0 -20
  302. package/dist/analyzers/dryAnalyzerCompat.d.ts.map +0 -1
  303. package/dist/analyzers/dryAnalyzerCompat.js +0 -44
  304. package/dist/analyzers/dryAnalyzerCompat.js.map +0 -1
  305. package/dist/analyzers/schemaAnalyzerCompat.d.ts +0 -20
  306. package/dist/analyzers/schemaAnalyzerCompat.d.ts.map +0 -1
  307. package/dist/analyzers/schemaAnalyzerCompat.js +0 -69
  308. package/dist/analyzers/schemaAnalyzerCompat.js.map +0 -1
  309. package/dist/analyzers/solidAnalyzerCompat.d.ts +0 -20
  310. package/dist/analyzers/solidAnalyzerCompat.d.ts.map +0 -1
  311. package/dist/analyzers/solidAnalyzerCompat.js +0 -78
  312. package/dist/analyzers/solidAnalyzerCompat.js.map +0 -1
  313. package/dist/codeIndexDb.d.ts.map +0 -1
  314. package/dist/codeIndexDb.js +0 -2102
  315. package/dist/codeIndexDb.js.map +0 -1
  316. package/dist/languages/typescript/TypeScriptAdapter.d.ts +0 -108
  317. package/dist/languages/typescript/TypeScriptAdapter.d.ts.map +0 -1
  318. package/dist/languages/typescript/TypeScriptAdapter.js +0 -567
  319. package/dist/languages/typescript/TypeScriptAdapter.js.map +0 -1
  320. package/dist/languages/typescript/test-extraction.d.ts +0 -2
  321. package/dist/languages/typescript/test-extraction.d.ts.map +0 -1
  322. package/dist/languages/typescript/test-extraction.js +0 -36
  323. package/dist/languages/typescript/test-extraction.js.map +0 -1
  324. package/dist/mcp-hybrid.d.ts +0 -10
  325. package/dist/mcp-hybrid.d.ts.map +0 -1
  326. package/dist/mcp-hybrid.js +0 -41
  327. package/dist/mcp-hybrid.js.map +0 -1
  328. package/dist/mcp-index.d.ts +0 -13
  329. package/dist/mcp-index.d.ts.map +0 -1
  330. package/dist/mcp-index.js +0 -136
  331. package/dist/mcp-index.js.map +0 -1
  332. package/dist/mcp-standalone.d.ts +0 -3
  333. package/dist/mcp-standalone.d.ts.map +0 -1
  334. package/dist/mcp-standalone.js +0 -1324
  335. package/dist/mcp-standalone.js.map +0 -1
  336. package/dist/mcp-ui-server.d.ts +0 -27
  337. package/dist/mcp-ui-server.d.ts.map +0 -1
  338. package/dist/mcp-ui-server.js +0 -484
  339. package/dist/mcp-ui-server.js.map +0 -1
  340. package/dist/test-multi-strategy-search.d.ts +0 -3
  341. package/dist/test-multi-strategy-search.d.ts.map +0 -1
  342. package/dist/test-multi-strategy-search.js +0 -170
  343. package/dist/test-multi-strategy-search.js.map +0 -1
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * Schema Analyzer
3
3
  * Analyzes code against loaded database schemas to find violations and patterns
4
+ *
5
+ * Uses tree-sitter AST patterns instead of the TypeScript compiler API.
4
6
  */
5
7
  import { CodeIndexDB } from '../codeIndexDB.js';
8
+ import { parseFile, getLineAndColumn, getNodeName } from '../languages/adapterBridge.js';
6
9
  import { promises as fs } from 'fs';
7
10
  import path from 'path';
8
- import ts from 'typescript';
9
11
  const DEFAULT_CONFIG = {
10
12
  enableTableUsageTracking: true,
11
13
  checkMissingReferences: true,
@@ -16,6 +18,30 @@ const DEFAULT_CONFIG = {
16
18
  allowedQueryPatterns: ['SELECT', 'INSERT', 'UPDATE', 'DELETE'],
17
19
  requiredSchemas: []
18
20
  };
21
+ const SQL_KEYWORDS = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP'];
22
+ // ---------------------------------------------------------------------------
23
+ // Helpers
24
+ // ---------------------------------------------------------------------------
25
+ /** Get the raw source text from an ASTNode's underlying tree-sitter node. */
26
+ function rawText(node) {
27
+ return node.raw?.text ?? '';
28
+ }
29
+ /** Strip surrounding single or double quotes from a string. */
30
+ function stripQuotes(text) {
31
+ if ((text.startsWith("'") && text.endsWith("'")) ||
32
+ (text.startsWith('"') && text.endsWith('"')) ||
33
+ (text.startsWith('`') && text.endsWith('`'))) {
34
+ return text.slice(1, -1);
35
+ }
36
+ return text;
37
+ }
38
+ /** Find the first direct child with a given type. */
39
+ function findChild(node, type) {
40
+ return node.children?.find(c => c.type === type);
41
+ }
42
+ // ---------------------------------------------------------------------------
43
+ // Main analyzer
44
+ // ---------------------------------------------------------------------------
19
45
  export const analyzeSchema = async (files, config = {}, options = {}, progressCallback) => {
20
46
  const finalConfig = { ...DEFAULT_CONFIG, ...config };
21
47
  const violations = [];
@@ -88,117 +114,141 @@ export const analyzeSchema = async (files, config = {}, options = {}, progressCa
88
114
  };
89
115
  async function analyzeFile(filePath, content, allTables, tableToSchema, config, db) {
90
116
  const violations = [];
91
- // Parse TypeScript/JavaScript
92
- const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
117
+ // Parse with tree-sitter
118
+ const ast = parseFile(filePath, content);
119
+ if (!ast) {
120
+ return violations;
121
+ }
93
122
  // Track schema usage for this file
94
123
  const schemaUsages = [];
95
- // Analyze the AST
96
- function visit(node, currentFunction) {
97
- // Detect ORM-specific patterns
98
- // 1. Drizzle ORM - Functional table definitions
99
- if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
100
- const funcName = node.expression.text;
101
- if (['pgTable', 'mysqlTable', 'sqliteTable'].includes(funcName)) {
102
- const tableName = extractTableNameFromDrizzle(node);
103
- if (tableName) {
104
- const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
105
- schemaUsages.push({
106
- tableName,
107
- functionName: currentFunction || 'schema-definition',
108
- usageType: 'reference',
109
- line: pos.line + 1,
110
- column: pos.character + 1
111
- });
124
+ /**
125
+ * Walk the AST while tracking the enclosing function name.
126
+ * Matches the original pattern: the visitor fires for the current node
127
+ * using the *parent* function context, then computes a new context for
128
+ * the node's children.
129
+ */
130
+ walkWithContext(ast.root, (node, currentFunction) => {
131
+ // ---------------------------------------------------------------
132
+ // 1. Drizzle ORM – Functional table definitions
133
+ // pgTable('table_name', { ... }), mysqlTable, sqliteTable
134
+ // ---------------------------------------------------------------
135
+ if (node.type === 'call_expression') {
136
+ const identNode = findChild(node, 'identifier');
137
+ if (identNode) {
138
+ const funcName = rawText(identNode);
139
+ if (['pgTable', 'mysqlTable', 'sqliteTable'].includes(funcName)) {
140
+ const tableName = extractTableNameFromDrizzle(node);
141
+ if (tableName) {
142
+ const { line, column } = getLineAndColumn(node);
143
+ schemaUsages.push({
144
+ tableName,
145
+ functionName: currentFunction || 'schema-definition',
146
+ usageType: 'reference',
147
+ line,
148
+ column,
149
+ });
150
+ }
112
151
  }
113
152
  }
114
153
  }
115
- // 2. TypeORM - Entity decorators
116
- if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) {
117
- const decoratorName = getDecoratorName(node.expression);
118
- if (decoratorName === 'Entity') {
119
- // Extract table name from Entity decorator
120
- const tableName = extractTableNameFromTypeORM(node.expression);
121
- if (tableName) {
122
- const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
123
- schemaUsages.push({
124
- tableName,
125
- functionName: currentFunction || 'entity-definition',
126
- usageType: 'reference',
127
- line: pos.line + 1,
128
- column: pos.character + 1
129
- });
154
+ // ---------------------------------------------------------------
155
+ // 2. TypeORM Entity decorators
156
+ // @Entity('table_name') or @Entity({ name: 'table_name' })
157
+ // ---------------------------------------------------------------
158
+ if (node.type === 'decorator') {
159
+ const callExpr = findChild(node, 'call_expression');
160
+ if (callExpr) {
161
+ const decoratorName = getDecoratorName(callExpr);
162
+ if (decoratorName === 'Entity') {
163
+ const tableName = extractTableNameFromTypeORM(callExpr);
164
+ if (tableName) {
165
+ const { line, column } = getLineAndColumn(node);
166
+ schemaUsages.push({
167
+ tableName,
168
+ functionName: currentFunction || 'entity-definition',
169
+ usageType: 'reference',
170
+ line,
171
+ column,
172
+ });
173
+ }
130
174
  }
131
175
  }
132
176
  }
133
- // 3. Mongoose - Schema constructors
134
- if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {
135
- if (node.expression.text === 'Schema') {
136
- // Analyze schema object literal for field references
177
+ // ---------------------------------------------------------------
178
+ // 3. Mongoose Schema constructors
179
+ // new Schema({ field: { type: String, ref: 'OtherModel' } })
180
+ // ---------------------------------------------------------------
181
+ if (node.type === 'new_expression') {
182
+ const exprIdent = findChild(node, 'identifier');
183
+ if (exprIdent && rawText(exprIdent) === 'Schema') {
137
184
  analyzeMongooseSchema(node, currentFunction);
138
185
  }
139
186
  }
140
- // 4. Prisma Client - Table access patterns
141
- if (ts.isPropertyAccessExpression(node)) {
142
- const propertyName = node.name.text;
143
- // Check if this looks like Prisma client table access (prisma.user.findMany)
144
- if (isPrismaBoundProperty(node)) {
145
- const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
146
- schemaUsages.push({
147
- tableName: propertyName,
148
- functionName: currentFunction || 'unknown',
149
- usageType: 'query',
150
- line: pos.line + 1,
151
- column: pos.character + 1
152
- });
187
+ // ---------------------------------------------------------------
188
+ // 4. Prisma Client – Table access patterns
189
+ // prisma.user.findMany()
190
+ // ---------------------------------------------------------------
191
+ if (node.type === 'member_expression') {
192
+ const propIdent = findChild(node, 'property_identifier');
193
+ if (propIdent) {
194
+ const propertyName = rawText(propIdent);
195
+ // Prisma-specific check (prisma.user, db.user, client.user)
196
+ if (isPrismaBoundProperty(node)) {
197
+ const { line, column } = getLineAndColumn(node);
198
+ schemaUsages.push({
199
+ tableName: propertyName,
200
+ functionName: currentFunction || 'unknown',
201
+ usageType: 'query',
202
+ line,
203
+ column,
204
+ });
205
+ }
153
206
  }
154
207
  }
155
- // 5. Detect SQL queries and table references (existing logic)
156
- if (ts.isStringLiteral(node) || ts.isTemplateExpression(node)) {
208
+ // ---------------------------------------------------------------
209
+ // 5. Detect SQL queries and table references in string/template literals
210
+ // ---------------------------------------------------------------
211
+ if (node.type === 'string' ||
212
+ node.type === 'template_string' ||
213
+ node.type === 'template_literal') {
157
214
  const queryText = getQueryText(node);
158
215
  if (queryText) {
159
216
  const queryAnalysis = analyzeQuery(queryText, allTables, filePath);
160
217
  violations.push(...queryAnalysis.violations);
161
- // Record schema usage
162
218
  for (const table of queryAnalysis.tables) {
163
- const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
219
+ const { line, column } = getLineAndColumn(node);
164
220
  schemaUsages.push({
165
221
  tableName: table,
166
222
  functionName: currentFunction || 'unknown',
167
223
  usageType: queryAnalysis.type,
168
- line: pos.line + 1,
169
- column: pos.character + 1,
170
- rawQuery: queryText
224
+ line,
225
+ column,
226
+ rawQuery: queryText,
171
227
  });
172
228
  }
173
229
  }
174
230
  }
175
- // Detect ORM/model references
176
- if (ts.isPropertyAccessExpression(node)) {
177
- const propertyName = node.name.text;
178
- if (allTables.has(propertyName)) {
179
- const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
180
- schemaUsages.push({
181
- tableName: propertyName,
182
- functionName: currentFunction || 'unknown',
183
- usageType: 'reference',
184
- line: pos.line + 1,
185
- column: pos.character + 1
186
- });
187
- }
188
- }
189
- // Track current function context
190
- let funcName = currentFunction;
191
- if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isArrowFunction(node)) {
192
- if (ts.isFunctionDeclaration(node) && node.name) {
193
- funcName = node.name.text;
194
- }
195
- else if (ts.isMethodDeclaration(node) && ts.isIdentifier(node.name)) {
196
- funcName = node.name.text;
231
+ // ---------------------------------------------------------------
232
+ // 6. General ORM / model references
233
+ // Any member expression whose property matches a known table name
234
+ // ---------------------------------------------------------------
235
+ if (node.type === 'member_expression') {
236
+ const propIdent = findChild(node, 'property_identifier');
237
+ if (propIdent) {
238
+ const propertyName = rawText(propIdent);
239
+ if (allTables.has(propertyName)) {
240
+ const { line, column } = getLineAndColumn(node);
241
+ schemaUsages.push({
242
+ tableName: propertyName,
243
+ functionName: currentFunction || 'unknown',
244
+ usageType: 'reference',
245
+ line,
246
+ column,
247
+ });
248
+ }
197
249
  }
198
250
  }
199
- ts.forEachChild(node, child => visit(child, funcName));
200
- }
201
- visit(sourceFile);
251
+ });
202
252
  // Record schema usages in database
203
253
  if (config.enableTableUsageTracking) {
204
254
  for (const usage of schemaUsages) {
@@ -209,7 +259,7 @@ async function analyzeFile(filePath, content, allTables, tableToSchema, config,
209
259
  usageType: usage.usageType,
210
260
  line: usage.line,
211
261
  column: usage.column,
212
- rawQuery: usage.rawQuery
262
+ rawQuery: usage.rawQuery,
213
263
  });
214
264
  }
215
265
  }
@@ -222,27 +272,61 @@ async function analyzeFile(filePath, content, allTables, tableToSchema, config,
222
272
  }
223
273
  return violations;
224
274
  }
275
+ // ---------------------------------------------------------------------------
276
+ // AST walker with function-context tracking
277
+ // ---------------------------------------------------------------------------
278
+ /**
279
+ * Walk an AST depth-first while tracking the name of the enclosing function.
280
+ * The visitor receives the current node and the *parent's* function name,
281
+ * then computes an updated name for the node's children.
282
+ */
283
+ function walkWithContext(node, visitor, currentFunction) {
284
+ // Invoke visitor with the parent's context
285
+ visitor(node, currentFunction);
286
+ // Determine the function context for children
287
+ let funcName = currentFunction;
288
+ if (node.type === 'function_declaration' ||
289
+ node.type === 'method_definition' ||
290
+ node.type === 'arrow_function') {
291
+ const name = getNodeName(node);
292
+ if (name) {
293
+ funcName = name;
294
+ }
295
+ }
296
+ // Recurse into children
297
+ if (node.children) {
298
+ for (const child of node.children) {
299
+ walkWithContext(child, visitor, funcName);
300
+ }
301
+ }
302
+ }
303
+ // ---------------------------------------------------------------------------
304
+ // Query text detection
305
+ // ---------------------------------------------------------------------------
225
306
  function getQueryText(node) {
226
- if (ts.isStringLiteral(node)) {
227
- const text = node.text.toUpperCase();
228
- // Check if it looks like SQL
229
- if (text.includes('SELECT') || text.includes('INSERT') ||
230
- text.includes('UPDATE') || text.includes('DELETE') ||
231
- text.includes('CREATE') || text.includes('DROP')) {
232
- return node.text;
307
+ if (node.type === 'string') {
308
+ const text = rawText(node);
309
+ const unquoted = stripQuotes(text);
310
+ const upper = unquoted.toUpperCase();
311
+ if (SQL_KEYWORDS.some(kw => upper.includes(kw))) {
312
+ return unquoted;
233
313
  }
234
314
  }
235
- if (ts.isTemplateExpression(node)) {
236
- // For template literals, check the head
237
- const headText = node.head.text.toUpperCase();
238
- if (headText.includes('SELECT') || headText.includes('INSERT') ||
239
- headText.includes('UPDATE') || headText.includes('DELETE')) {
240
- // Return a simplified version for analysis
241
- return node.head.text + ' ...';
315
+ if (node.type === 'template_string' || node.type === 'template_literal') {
316
+ // The first string_fragment contains the text before the first substitution
317
+ const headNode = node.children?.find(c => c.type === 'string_fragment');
318
+ if (headNode) {
319
+ const headText = rawText(headNode).toUpperCase();
320
+ if (SQL_KEYWORDS.some(kw => headText.includes(kw))) {
321
+ return rawText(headNode) + ' ...';
322
+ }
242
323
  }
243
324
  }
244
325
  return null;
245
326
  }
327
+ // ---------------------------------------------------------------------------
328
+ // SQL query analysis
329
+ // ---------------------------------------------------------------------------
246
330
  function analyzeQuery(query, allTables, filePath) {
247
331
  const violations = [];
248
332
  const tables = [];
@@ -256,7 +340,7 @@ function analyzeQuery(query, allTables, filePath) {
256
340
  type = 'update';
257
341
  else if (queryUpper.includes('DELETE'))
258
342
  type = 'delete';
259
- // Extract table names (basic regex - could be enhanced)
343
+ // Extract table names (basic regex could be enhanced)
260
344
  const tableMatches = query.match(/(?:FROM|JOIN|INTO|UPDATE)\s+([a-zA-Z_][a-zA-Z0-9_]*)/gi);
261
345
  if (tableMatches) {
262
346
  for (const match of tableMatches) {
@@ -269,7 +353,7 @@ function analyzeQuery(query, allTables, filePath) {
269
353
  schemaType: 'missing-reference',
270
354
  tableName,
271
355
  snippet: query.substring(0, 100),
272
- suggestion: 'Load the appropriate database schema or check table name spelling'
356
+ suggestion: 'Load the appropriate database schema or check table name spelling',
273
357
  });
274
358
  }
275
359
  else if (tableName) {
@@ -279,6 +363,9 @@ function analyzeQuery(query, allTables, filePath) {
279
363
  }
280
364
  return { violations, tables, type };
281
365
  }
366
+ // ---------------------------------------------------------------------------
367
+ // Validation checks
368
+ // ---------------------------------------------------------------------------
282
369
  function checkMissingTableReferences(usages, allTables, filePath) {
283
370
  const violations = [];
284
371
  for (const usage of usages) {
@@ -290,7 +377,7 @@ function checkMissingTableReferences(usages, allTables, filePath) {
290
377
  message: `Reference to unknown table '${usage.tableName}'`,
291
378
  schemaType: 'missing-reference',
292
379
  tableName: usage.tableName,
293
- suggestion: 'Load the database schema that contains this table'
380
+ suggestion: 'Load the database schema that contains this table',
294
381
  });
295
382
  }
296
383
  }
@@ -313,85 +400,157 @@ function validateQueryPatterns(usages, config, filePath) {
313
400
  severity: 'suggestion',
314
401
  message: `Function '${funcName}' has ${count} database queries (max recommended: ${config.maxQueriesPerFunction})`,
315
402
  schemaType: 'missing-reference',
316
- suggestion: 'Consider consolidating queries or extracting to a data access layer'
403
+ suggestion: 'Consider consolidating queries or extracting to a data access layer',
317
404
  });
318
405
  }
319
406
  }
320
407
  return violations;
321
408
  }
409
+ // ---------------------------------------------------------------------------
322
410
  // ORM-specific helper functions
411
+ // ---------------------------------------------------------------------------
412
+ /**
413
+ * Extract the table name from a Drizzle ORM call.
414
+ * Drizzle: pgTable('table_name', { ... })
415
+ */
323
416
  function extractTableNameFromDrizzle(node) {
324
- // Drizzle: pgTable('table_name', { ... })
325
- if (node.arguments.length > 0 && ts.isStringLiteral(node.arguments[0])) {
326
- return node.arguments[0].text;
417
+ // call_expression children: [expression, arguments]
418
+ const argsNode = findChild(node, 'arguments');
419
+ if (!argsNode)
420
+ return null;
421
+ // The first child of arguments that is a string literal
422
+ const stringChild = argsNode.children?.find(c => c.type === 'string');
423
+ if (stringChild) {
424
+ return stripQuotes(rawText(stringChild));
327
425
  }
328
426
  return null;
329
427
  }
428
+ /**
429
+ * Get the decorator name from a call_expression inside a decorator.
430
+ * e.g. @Entity(...) → 'Entity'
431
+ */
330
432
  function getDecoratorName(node) {
331
- if (ts.isIdentifier(node.expression)) {
332
- return node.expression.text;
433
+ // node is a call_expression inside a decorator
434
+ const identNode = findChild(node, 'identifier');
435
+ if (identNode) {
436
+ return rawText(identNode);
333
437
  }
334
438
  return null;
335
439
  }
440
+ /**
441
+ * Extract the table name from a TypeORM Entity decorator call.
442
+ * @Entity('table_name') or @Entity({ name: 'table_name' })
443
+ */
336
444
  function extractTableNameFromTypeORM(node) {
337
- // TypeORM: @Entity('table_name') or @Entity({ name: 'table_name' })
338
- if (node.arguments.length > 0) {
339
- const firstArg = node.arguments[0];
340
- if (ts.isStringLiteral(firstArg)) {
341
- return firstArg.text;
342
- }
343
- if (ts.isObjectLiteralExpression(firstArg)) {
344
- // Look for name property
345
- for (const prop of firstArg.properties) {
346
- if (ts.isPropertyAssignment(prop) &&
347
- ts.isIdentifier(prop.name) &&
348
- prop.name.text === 'name' &&
349
- ts.isStringLiteral(prop.initializer)) {
350
- return prop.initializer.text;
445
+ // node is a call_expression
446
+ const argsNode = findChild(node, 'arguments');
447
+ if (!argsNode)
448
+ return null;
449
+ // First non-bracket argument
450
+ const firstArg = argsNode.children?.find(c => c.type !== '(' && c.type !== ')');
451
+ if (!firstArg)
452
+ return null;
453
+ // @Entity('table_name')
454
+ if (firstArg.type === 'string') {
455
+ return stripQuotes(rawText(firstArg));
456
+ }
457
+ // @Entity({ name: 'table_name' })
458
+ if (firstArg.type === 'object') {
459
+ for (const prop of firstArg.children ?? []) {
460
+ if (prop.type === 'pair') {
461
+ // pair children: [key, :, value]
462
+ const keyNode = prop.children?.[0];
463
+ if (keyNode &&
464
+ (keyNode.type === 'identifier' || keyNode.type === 'string' || keyNode.type === 'property_identifier')) {
465
+ const keyText = stripQuotes(rawText(keyNode));
466
+ if (keyText === 'name') {
467
+ const valueNode = prop.children?.find(c => c.type === 'string');
468
+ if (valueNode) {
469
+ return stripQuotes(rawText(valueNode));
470
+ }
471
+ }
351
472
  }
352
473
  }
353
474
  }
354
475
  }
355
476
  return null;
356
477
  }
478
+ /**
479
+ * Analyze a Mongoose Schema constructor for field-level references.
480
+ * Mongoose: new Schema({ field: { type: String, ref: 'OtherModel' } })
481
+ */
357
482
  function analyzeMongooseSchema(node, currentFunction) {
358
- // Mongoose: new Schema({ field: { type: String, ref: 'OtherModel' } })
359
- if (node.arguments && node.arguments.length > 0) {
360
- const schemaArg = node.arguments[0];
361
- if (ts.isObjectLiteralExpression(schemaArg)) {
362
- // Look for ref properties that indicate relationships
363
- analyzeObjectForReferences(schemaArg, currentFunction);
364
- }
483
+ // node is a new_expression: children [new, expression, arguments]
484
+ const argsNode = findChild(node, 'arguments');
485
+ if (!argsNode)
486
+ return;
487
+ const schemaArg = argsNode.children?.find(c => c.type === 'object');
488
+ if (schemaArg) {
489
+ analyzeObjectForReferences(schemaArg, currentFunction);
365
490
  }
366
491
  }
492
+ /**
493
+ * Recurse into an object literal looking for { ref: 'ModelName' } patterns.
494
+ */
367
495
  function analyzeObjectForReferences(obj, currentFunction) {
368
- for (const prop of obj.properties) {
369
- if (ts.isPropertyAssignment(prop) && ts.isObjectLiteralExpression(prop.initializer)) {
370
- // Look for ref property
371
- for (const nestedProp of prop.initializer.properties) {
372
- if (ts.isPropertyAssignment(nestedProp) &&
373
- ts.isIdentifier(nestedProp.name) &&
374
- nestedProp.name.text === 'ref' &&
375
- ts.isStringLiteral(nestedProp.initializer)) {
376
- // Found a reference to another model
377
- const referencedModel = nestedProp.initializer.text;
378
- // Add to schema usage tracking
379
- // This would need access to the parent scope's schemaUsages array
496
+ // obj is an 'object' literal
497
+ for (const prop of obj.children ?? []) {
498
+ if (prop.type !== 'pair')
499
+ continue;
500
+ // pair children: [key, :, value]
501
+ const valueNode = prop.children?.find(c => c.type === 'object');
502
+ if (!valueNode)
503
+ continue;
504
+ // Look for a nested 'ref' property
505
+ for (const nestedProp of valueNode.children ?? []) {
506
+ if (nestedProp.type !== 'pair')
507
+ continue;
508
+ const keyNode = nestedProp.children?.[0];
509
+ if (!keyNode)
510
+ continue;
511
+ const keyText = stripQuotes(rawText(keyNode));
512
+ if (keyText === 'ref') {
513
+ const refValueNode = nestedProp.children?.find(c => c.type === 'string');
514
+ if (refValueNode) {
515
+ const referencedModel = stripQuotes(rawText(refValueNode));
516
+ // NOTE: referencedModel is currently not added to schemaUsages
517
+ // because this helper does not have access to the parent scope's array.
518
+ // Future enhancement: track Mongoose ref relationships.
519
+ void referencedModel;
380
520
  }
381
521
  }
382
522
  }
383
523
  }
384
524
  }
525
+ /**
526
+ * Check if a member_expression looks like a Prisma client table access.
527
+ * prisma.user.findMany() — the top-level object is 'prisma'/'db'/'client'.
528
+ */
385
529
  function isPrismaBoundProperty(node) {
386
- // Check if this looks like prisma.tableName.operation
387
- if (ts.isPropertyAccessExpression(node.expression) &&
388
- ts.isIdentifier(node.expression.expression)) {
389
- const baseName = node.expression.expression.text;
390
- // Common Prisma client variable names
391
- return ['prisma', 'db', 'client'].includes(baseName.toLowerCase());
530
+ // node is a member_expression: children [object, ., property_identifier]
531
+ // For prisma.user.findMany(), the outer member_expression's object is another
532
+ // member_expression (prisma.user), whose object is the identifier 'prisma'.
533
+ // Find the nested member_expression that is the object of this one
534
+ const nestedME = node.children?.find(c => c.type === 'member_expression');
535
+ if (nestedME) {
536
+ // The object of the nested member_expression is the base identifier
537
+ const baseId = findChild(nestedME, 'identifier');
538
+ if (baseId) {
539
+ const baseName = rawText(baseId).toLowerCase();
540
+ return ['prisma', 'db', 'client'].includes(baseName);
541
+ }
542
+ }
543
+ // Also handle direct access like prisma.$queryRaw
544
+ const directId = findChild(node, 'identifier');
545
+ if (directId) {
546
+ const baseName = rawText(directId).toLowerCase();
547
+ return ['prisma', 'db', 'client'].includes(baseName);
392
548
  }
393
549
  return false;
394
550
  }
551
+ // ---------------------------------------------------------------------------
552
+ // Analyzer Definition
553
+ // ---------------------------------------------------------------------------
395
554
  /**
396
555
  * Schema Analyzer Definition
397
556
  */