code-auditor-mcp 4.1.1 → 5.0.1

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 (1082) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +338 -0
  3. package/README.md +4 -4
  4. package/configs/hhra-compat.json +0 -8
  5. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.d.ts +1 -1
  6. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.d.ts.map +1 -1
  7. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.js +7 -1
  8. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.js.map +1 -1
  9. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts +2 -8
  10. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts.map +1 -1
  11. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.js +4 -4
  12. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.js.map +1 -1
  13. package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.d.ts +1 -1
  14. package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.d.ts.map +1 -1
  15. package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.js.map +1 -1
  16. package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.d.ts +2 -2
  17. package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.d.ts.map +1 -1
  18. package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.js.map +1 -1
  19. package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.d.ts +1 -1
  20. package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.d.ts.map +1 -1
  21. package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.js.map +1 -1
  22. package/dist/analyzers/applicability.d.ts +42 -0
  23. package/dist/analyzers/applicability.d.ts.map +1 -1
  24. package/dist/analyzers/applicability.js +74 -0
  25. package/dist/analyzers/applicability.js.map +1 -1
  26. package/dist/analyzers/cross-language/APIContractAnalyzer.js +18 -24
  27. package/dist/analyzers/cross-language/APIContractAnalyzer.js.map +1 -1
  28. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts +30 -23
  29. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
  30. package/dist/analyzers/cross-language/DependencyGraphBuilder.js +113 -76
  31. package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
  32. package/dist/analyzers/cross-language/SchemaValidator.d.ts +2 -0
  33. package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
  34. package/dist/analyzers/cross-language/SchemaValidator.js +8 -3
  35. package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
  36. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts.map +1 -1
  37. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js +210 -148
  38. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js.map +1 -1
  39. package/dist/analyzers/documentationAnalyzer.d.ts.map +1 -1
  40. package/dist/analyzers/documentationAnalyzer.js +23 -28
  41. package/dist/analyzers/documentationAnalyzer.js.map +1 -1
  42. package/dist/analyzers/handleIdentification.d.ts +356 -0
  43. package/dist/analyzers/handleIdentification.d.ts.map +1 -0
  44. package/dist/analyzers/handleIdentification.js +424 -0
  45. package/dist/analyzers/handleIdentification.js.map +1 -0
  46. package/dist/analyzers/manifestStaleness.d.ts +64 -0
  47. package/dist/analyzers/manifestStaleness.d.ts.map +1 -0
  48. package/dist/analyzers/manifestStaleness.js +115 -0
  49. package/dist/analyzers/manifestStaleness.js.map +1 -0
  50. package/dist/analyzers/orgFilterTiers.d.ts +73 -1
  51. package/dist/analyzers/orgFilterTiers.d.ts.map +1 -1
  52. package/dist/analyzers/orgFilterTiers.js +166 -1
  53. package/dist/analyzers/orgFilterTiers.js.map +1 -1
  54. package/dist/analyzers/provenance.d.ts +251 -57
  55. package/dist/analyzers/provenance.d.ts.map +1 -1
  56. package/dist/analyzers/provenance.js +1109 -429
  57. package/dist/analyzers/provenance.js.map +1 -1
  58. package/dist/analyzers/reactAnalyzer.d.ts +2 -0
  59. package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
  60. package/dist/analyzers/reactAnalyzer.js +2 -0
  61. package/dist/analyzers/reactAnalyzer.js.map +1 -1
  62. package/dist/analyzers/receiverResolution.d.ts +183 -0
  63. package/dist/analyzers/receiverResolution.d.ts.map +1 -0
  64. package/dist/analyzers/receiverResolution.js +540 -0
  65. package/dist/analyzers/receiverResolution.js.map +1 -0
  66. package/dist/analyzers/receiverRoot.d.ts +328 -0
  67. package/dist/analyzers/receiverRoot.d.ts.map +1 -0
  68. package/dist/analyzers/receiverRoot.js +990 -0
  69. package/dist/analyzers/receiverRoot.js.map +1 -0
  70. package/dist/analyzers/ruleRegistry.d.ts +12 -68
  71. package/dist/analyzers/ruleRegistry.d.ts.map +1 -1
  72. package/dist/analyzers/ruleRegistry.js +32 -342
  73. package/dist/analyzers/ruleRegistry.js.map +1 -1
  74. package/dist/analyzers/ruleTiming.d.ts +10 -0
  75. package/dist/analyzers/ruleTiming.d.ts.map +1 -1
  76. package/dist/analyzers/ruleTiming.js +20 -0
  77. package/dist/analyzers/ruleTiming.js.map +1 -1
  78. package/dist/analyzers/sqlLiteral.d.ts +76 -0
  79. package/dist/analyzers/sqlLiteral.d.ts.map +1 -0
  80. package/dist/analyzers/sqlLiteral.js +419 -0
  81. package/dist/analyzers/sqlLiteral.js.map +1 -0
  82. package/dist/analyzers/tsEcosystem.d.ts +115 -0
  83. package/dist/analyzers/tsEcosystem.d.ts.map +1 -0
  84. package/dist/analyzers/tsEcosystem.js +231 -0
  85. package/dist/analyzers/tsEcosystem.js.map +1 -0
  86. package/dist/analyzers/tsExpressionDescriptor.d.ts +156 -0
  87. package/dist/analyzers/tsExpressionDescriptor.d.ts.map +1 -0
  88. package/dist/analyzers/tsExpressionDescriptor.js +374 -0
  89. package/dist/analyzers/tsExpressionDescriptor.js.map +1 -0
  90. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts +6 -0
  91. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts.map +1 -1
  92. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js +107 -44
  93. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js.map +1 -1
  94. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
  95. package/dist/analyzers/universal/UniversalDRYAnalyzer.js +23 -35
  96. package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
  97. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts +287 -49
  98. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
  99. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +2130 -512
  100. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
  101. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts.map +1 -1
  102. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +2 -18
  103. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
  104. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts +0 -33
  105. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
  106. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +20 -143
  107. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
  108. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts +4 -3
  109. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
  110. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +36 -13
  111. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
  112. package/dist/analyzers/universal/UniversalSecretsAnalyzer.d.ts.map +1 -1
  113. package/dist/analyzers/universal/UniversalSecretsAnalyzer.js +6 -0
  114. package/dist/analyzers/universal/UniversalSecretsAnalyzer.js.map +1 -1
  115. package/dist/analyzers/universal/UniversalSecurityAnalyzer.d.ts +15 -0
  116. package/dist/analyzers/universal/UniversalSecurityAnalyzer.d.ts.map +1 -1
  117. package/dist/analyzers/universal/UniversalSecurityAnalyzer.js +25 -0
  118. package/dist/analyzers/universal/UniversalSecurityAnalyzer.js.map +1 -1
  119. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts +21 -32
  120. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts.map +1 -1
  121. package/dist/analyzers/universal/UniversalStylesAnalyzer.js +166 -196
  122. package/dist/analyzers/universal/UniversalStylesAnalyzer.js.map +1 -1
  123. package/dist/analyzers/universal/functionConcerns.d.ts +3 -0
  124. package/dist/analyzers/universal/functionConcerns.d.ts.map +1 -1
  125. package/dist/analyzers/universal/functionConcerns.js +4 -1
  126. package/dist/analyzers/universal/functionConcerns.js.map +1 -1
  127. package/dist/analyzers/universal/schema/codeAnalysis.d.ts +310 -69
  128. package/dist/analyzers/universal/schema/codeAnalysis.d.ts.map +1 -1
  129. package/dist/analyzers/universal/schema/codeAnalysis.js +709 -383
  130. package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
  131. package/dist/analyzers/universal/schema/config.d.ts +3 -14
  132. package/dist/analyzers/universal/schema/config.d.ts.map +1 -1
  133. package/dist/analyzers/universal/schema/config.js +3 -16
  134. package/dist/analyzers/universal/schema/config.js.map +1 -1
  135. package/dist/analyzers/universal/schema/discovery.d.ts +22 -1
  136. package/dist/analyzers/universal/schema/discovery.d.ts.map +1 -1
  137. package/dist/analyzers/universal/schema/discovery.js +36 -20
  138. package/dist/analyzers/universal/schema/discovery.js.map +1 -1
  139. package/dist/analyzers/universal/schema/jsonSchema.d.ts.map +1 -1
  140. package/dist/analyzers/universal/schema/jsonSchema.js +13 -3
  141. package/dist/analyzers/universal/schema/jsonSchema.js.map +1 -1
  142. package/dist/analyzers/universal/schema/migrations.d.ts +187 -27
  143. package/dist/analyzers/universal/schema/migrations.d.ts.map +1 -1
  144. package/dist/analyzers/universal/schema/migrations.js +443 -186
  145. package/dist/analyzers/universal/schema/migrations.js.map +1 -1
  146. package/dist/analyzers/universal/schema/types.d.ts +17 -3
  147. package/dist/analyzers/universal/schema/types.d.ts.map +1 -1
  148. package/dist/analyzers/universal/schema/violations.js +1 -1
  149. package/dist/analyzers/universal/schema/violations.js.map +1 -1
  150. package/dist/analyzers/universal/styleScale.d.ts +52 -0
  151. package/dist/analyzers/universal/styleScale.d.ts.map +1 -0
  152. package/dist/analyzers/universal/styleScale.js +95 -0
  153. package/dist/analyzers/universal/styleScale.js.map +1 -0
  154. package/dist/applyDataDirEnv.js +1 -1
  155. package/dist/applyDataDirEnv.js.map +1 -1
  156. package/dist/auditRouter.d.ts +26 -30
  157. package/dist/auditRouter.d.ts.map +1 -1
  158. package/dist/auditRouter.js +373 -143
  159. package/dist/auditRouter.js.map +1 -1
  160. package/dist/auditRunner.d.ts +64 -1
  161. package/dist/auditRunner.d.ts.map +1 -1
  162. package/dist/auditRunner.js +1538 -1033
  163. package/dist/auditRunner.js.map +1 -1
  164. package/dist/baseline.d.ts +30 -3
  165. package/dist/baseline.d.ts.map +1 -1
  166. package/dist/baseline.js +70 -9
  167. package/dist/baseline.js.map +1 -1
  168. package/dist/cli.js +969 -821
  169. package/dist/cli.js.map +1 -1
  170. package/dist/codeIndex/analyzerConfig.d.ts +60 -0
  171. package/dist/codeIndex/analyzerConfig.d.ts.map +1 -0
  172. package/dist/codeIndex/analyzerConfig.js +98 -0
  173. package/dist/codeIndex/analyzerConfig.js.map +1 -0
  174. package/dist/codeIndex/auditResults.d.ts +39 -0
  175. package/dist/codeIndex/auditResults.d.ts.map +1 -0
  176. package/dist/codeIndex/auditResults.js +99 -0
  177. package/dist/codeIndex/auditResults.js.map +1 -0
  178. package/dist/codeIndex/codeMap.d.ts +59 -0
  179. package/dist/codeIndex/codeMap.d.ts.map +1 -0
  180. package/dist/codeIndex/codeMap.js +72 -0
  181. package/dist/codeIndex/codeMap.js.map +1 -0
  182. package/dist/codeIndex/conventions.d.ts +33 -0
  183. package/dist/codeIndex/conventions.d.ts.map +1 -0
  184. package/dist/codeIndex/conventions.js +84 -0
  185. package/dist/codeIndex/conventions.js.map +1 -0
  186. package/dist/codeIndex/coverage.d.ts +78 -0
  187. package/dist/codeIndex/coverage.d.ts.map +1 -0
  188. package/dist/codeIndex/coverage.js +164 -0
  189. package/dist/codeIndex/coverage.js.map +1 -0
  190. package/dist/codeIndex/dependencyGraph.d.ts +97 -0
  191. package/dist/codeIndex/dependencyGraph.d.ts.map +1 -0
  192. package/dist/codeIndex/dependencyGraph.js +241 -0
  193. package/dist/codeIndex/dependencyGraph.js.map +1 -0
  194. package/dist/codeIndex/functionIndex.d.ts +111 -0
  195. package/dist/codeIndex/functionIndex.d.ts.map +1 -0
  196. package/dist/codeIndex/functionIndex.js +306 -0
  197. package/dist/codeIndex/functionIndex.js.map +1 -0
  198. package/dist/codeIndex/inferredReceivers.d.ts +32 -0
  199. package/dist/codeIndex/inferredReceivers.d.ts.map +1 -0
  200. package/dist/codeIndex/inferredReceivers.js +41 -0
  201. package/dist/codeIndex/inferredReceivers.js.map +1 -0
  202. package/dist/codeIndex/meta.d.ts +30 -0
  203. package/dist/codeIndex/meta.d.ts.map +1 -0
  204. package/dist/codeIndex/meta.js +37 -0
  205. package/dist/codeIndex/meta.js.map +1 -0
  206. package/dist/codeIndex/migrations.d.ts +96 -0
  207. package/dist/codeIndex/migrations.d.ts.map +1 -0
  208. package/dist/codeIndex/migrations.js +1302 -0
  209. package/dist/codeIndex/migrations.js.map +1 -0
  210. package/dist/codeIndex/projectTasks.d.ts +54 -0
  211. package/dist/codeIndex/projectTasks.d.ts.map +1 -0
  212. package/dist/codeIndex/projectTasks.js +81 -0
  213. package/dist/codeIndex/projectTasks.js.map +1 -0
  214. package/dist/codeIndex/provenance.d.ts +47 -0
  215. package/dist/codeIndex/provenance.d.ts.map +1 -0
  216. package/dist/codeIndex/provenance.js +48 -0
  217. package/dist/codeIndex/provenance.js.map +1 -0
  218. package/dist/codeIndex/rawSql.d.ts +54 -0
  219. package/dist/codeIndex/rawSql.d.ts.map +1 -0
  220. package/dist/codeIndex/rawSql.js +71 -0
  221. package/dist/codeIndex/rawSql.js.map +1 -0
  222. package/dist/codeIndex/schema.d.ts +99 -0
  223. package/dist/codeIndex/schema.d.ts.map +1 -0
  224. package/dist/codeIndex/schema.js +174 -0
  225. package/dist/codeIndex/schema.js.map +1 -0
  226. package/dist/codeIndex/search.d.ts +40 -0
  227. package/dist/codeIndex/search.d.ts.map +1 -0
  228. package/dist/codeIndex/search.js +316 -0
  229. package/dist/codeIndex/search.js.map +1 -0
  230. package/dist/codeIndex/shared.d.ts +27 -0
  231. package/dist/codeIndex/shared.d.ts.map +1 -0
  232. package/dist/codeIndex/shared.js +46 -0
  233. package/dist/codeIndex/shared.js.map +1 -0
  234. package/dist/codeIndex/sqliteCollection.d.ts +81 -0
  235. package/dist/codeIndex/sqliteCollection.d.ts.map +1 -0
  236. package/dist/codeIndex/sqliteCollection.js +250 -0
  237. package/dist/codeIndex/sqliteCollection.js.map +1 -0
  238. package/dist/codeIndex/whitelist.d.ts +59 -0
  239. package/dist/codeIndex/whitelist.d.ts.map +1 -0
  240. package/dist/codeIndex/whitelist.js +188 -0
  241. package/dist/codeIndex/whitelist.js.map +1 -0
  242. package/dist/codeIndexDB.d.ts +132 -271
  243. package/dist/codeIndexDB.d.ts.map +1 -1
  244. package/dist/codeIndexDB.js +365 -2729
  245. package/dist/codeIndexDB.js.map +1 -1
  246. package/dist/codeIndexService.d.ts +87 -12
  247. package/dist/codeIndexService.d.ts.map +1 -1
  248. package/dist/codeIndexService.js +110 -34
  249. package/dist/codeIndexService.js.map +1 -1
  250. package/dist/componentScanner.d.ts +35 -0
  251. package/dist/componentScanner.d.ts.map +1 -1
  252. package/dist/componentScanner.js +114 -80
  253. package/dist/componentScanner.js.map +1 -1
  254. package/dist/config/configGeneratePath.d.ts +4 -0
  255. package/dist/config/configGeneratePath.d.ts.map +1 -1
  256. package/dist/config/configGeneratePath.js +4 -0
  257. package/dist/config/configGeneratePath.js.map +1 -1
  258. package/dist/config/configLoader.d.ts +15 -0
  259. package/dist/config/configLoader.d.ts.map +1 -1
  260. package/dist/config/configLoader.js +15 -16
  261. package/dist/config/configLoader.js.map +1 -1
  262. package/dist/config/defaults.d.ts +11 -7
  263. package/dist/config/defaults.d.ts.map +1 -1
  264. package/dist/config/defaults.js +16 -14
  265. package/dist/config/defaults.js.map +1 -1
  266. package/dist/config/effectiveConfig.d.ts +17 -2
  267. package/dist/config/effectiveConfig.d.ts.map +1 -1
  268. package/dist/config/effectiveConfig.js +32 -25
  269. package/dist/config/effectiveConfig.js.map +1 -1
  270. package/dist/config/lintConfigReader.d.ts +6 -0
  271. package/dist/config/lintConfigReader.d.ts.map +1 -1
  272. package/dist/config/lintConfigReader.js +6 -0
  273. package/dist/config/lintConfigReader.js.map +1 -1
  274. package/dist/config/staticObjectExtract.d.ts +4 -0
  275. package/dist/config/staticObjectExtract.d.ts.map +1 -1
  276. package/dist/config/staticObjectExtract.js +7 -3
  277. package/dist/config/staticObjectExtract.js.map +1 -1
  278. package/dist/config/thresholdRationales.d.ts +2 -0
  279. package/dist/config/thresholdRationales.d.ts.map +1 -1
  280. package/dist/config/thresholdRationales.js +5 -2
  281. package/dist/config/thresholdRationales.js.map +1 -1
  282. package/dist/constants.d.ts +1 -1
  283. package/dist/conventions/conventionMiner.d.ts +105 -2
  284. package/dist/conventions/conventionMiner.d.ts.map +1 -1
  285. package/dist/conventions/conventionMiner.js +334 -259
  286. package/dist/conventions/conventionMiner.js.map +1 -1
  287. package/dist/coverage/coverageService.js +4 -4
  288. package/dist/coverage/coverageService.js.map +1 -1
  289. package/dist/daemon/args.d.ts +3 -0
  290. package/dist/daemon/args.d.ts.map +1 -1
  291. package/dist/daemon/args.js +3 -0
  292. package/dist/daemon/args.js.map +1 -1
  293. package/dist/daemon/core.d.ts +33 -27
  294. package/dist/daemon/core.d.ts.map +1 -1
  295. package/dist/daemon/core.js +198 -162
  296. package/dist/daemon/core.js.map +1 -1
  297. package/dist/daemon/lspServer.d.ts +8 -0
  298. package/dist/daemon/lspServer.d.ts.map +1 -1
  299. package/dist/daemon/lspServer.js +8 -0
  300. package/dist/daemon/lspServer.js.map +1 -1
  301. package/dist/daemon/main.d.ts +2 -0
  302. package/dist/daemon/main.d.ts.map +1 -1
  303. package/dist/daemon/main.js +2 -0
  304. package/dist/daemon/main.js.map +1 -1
  305. package/dist/daemon/resolve.d.ts +18 -3
  306. package/dist/daemon/resolve.d.ts.map +1 -1
  307. package/dist/daemon/resolve.js +25 -4
  308. package/dist/daemon/resolve.js.map +1 -1
  309. package/dist/daemon/socketClient.d.ts +10 -1
  310. package/dist/daemon/socketClient.d.ts.map +1 -1
  311. package/dist/daemon/socketClient.js +10 -1
  312. package/dist/daemon/socketClient.js.map +1 -1
  313. package/dist/daemon/socketServer.d.ts +13 -0
  314. package/dist/daemon/socketServer.d.ts.map +1 -1
  315. package/dist/daemon/socketServer.js +13 -0
  316. package/dist/daemon/socketServer.js.map +1 -1
  317. package/dist/dataPaths.d.ts +17 -8
  318. package/dist/dataPaths.d.ts.map +1 -1
  319. package/dist/dataPaths.js +16 -44
  320. package/dist/dataPaths.js.map +1 -1
  321. package/dist/dismissals.d.ts +22 -1
  322. package/dist/dismissals.d.ts.map +1 -1
  323. package/dist/dismissals.js +22 -1
  324. package/dist/dismissals.js.map +1 -1
  325. package/dist/enforcement/gate.d.ts +1 -0
  326. package/dist/enforcement/gate.d.ts.map +1 -1
  327. package/dist/enforcement/gate.js +1 -0
  328. package/dist/enforcement/gate.js.map +1 -1
  329. package/dist/fingerprint.d.ts +6 -0
  330. package/dist/fingerprint.d.ts.map +1 -1
  331. package/dist/fingerprint.js +46 -1
  332. package/dist/fingerprint.js.map +1 -1
  333. package/dist/functionScanner.d.ts +30 -1
  334. package/dist/functionScanner.d.ts.map +1 -1
  335. package/dist/functionScanner.js +258 -256
  336. package/dist/functionScanner.js.map +1 -1
  337. package/dist/generators/AWSQConfigGenerator.d.ts +23 -0
  338. package/dist/generators/AWSQConfigGenerator.d.ts.map +1 -1
  339. package/dist/generators/AWSQConfigGenerator.js +23 -0
  340. package/dist/generators/AWSQConfigGenerator.js.map +1 -1
  341. package/dist/generators/BaseConfigGenerator.d.ts +7 -0
  342. package/dist/generators/BaseConfigGenerator.d.ts.map +1 -1
  343. package/dist/generators/BaseConfigGenerator.js +7 -0
  344. package/dist/generators/BaseConfigGenerator.js.map +1 -1
  345. package/dist/generators/ClaudeConfigGenerator.d.ts +23 -0
  346. package/dist/generators/ClaudeConfigGenerator.d.ts.map +1 -1
  347. package/dist/generators/ClaudeConfigGenerator.js +23 -0
  348. package/dist/generators/ClaudeConfigGenerator.js.map +1 -1
  349. package/dist/generators/ClineConfigGenerator.d.ts +23 -0
  350. package/dist/generators/ClineConfigGenerator.d.ts.map +1 -1
  351. package/dist/generators/ClineConfigGenerator.js +23 -0
  352. package/dist/generators/ClineConfigGenerator.js.map +1 -1
  353. package/dist/generators/CodeiumConfigGenerator.d.ts +23 -0
  354. package/dist/generators/CodeiumConfigGenerator.d.ts.map +1 -1
  355. package/dist/generators/CodeiumConfigGenerator.js +23 -0
  356. package/dist/generators/CodeiumConfigGenerator.js.map +1 -1
  357. package/dist/generators/CodexConfigGenerator.d.ts +23 -0
  358. package/dist/generators/CodexConfigGenerator.d.ts.map +1 -1
  359. package/dist/generators/CodexConfigGenerator.js +23 -0
  360. package/dist/generators/CodexConfigGenerator.js.map +1 -1
  361. package/dist/generators/ConfigGeneratorFactory.d.ts +9 -0
  362. package/dist/generators/ConfigGeneratorFactory.d.ts.map +1 -1
  363. package/dist/generators/ConfigGeneratorFactory.js +9 -0
  364. package/dist/generators/ConfigGeneratorFactory.js.map +1 -1
  365. package/dist/generators/ContinueConfigGenerator.d.ts +23 -0
  366. package/dist/generators/ContinueConfigGenerator.d.ts.map +1 -1
  367. package/dist/generators/ContinueConfigGenerator.js +23 -0
  368. package/dist/generators/ContinueConfigGenerator.js.map +1 -1
  369. package/dist/generators/CopilotConfigGenerator.d.ts +23 -0
  370. package/dist/generators/CopilotConfigGenerator.d.ts.map +1 -1
  371. package/dist/generators/CopilotConfigGenerator.js +23 -0
  372. package/dist/generators/CopilotConfigGenerator.js.map +1 -1
  373. package/dist/generators/CursorConfigGenerator.d.ts +23 -0
  374. package/dist/generators/CursorConfigGenerator.d.ts.map +1 -1
  375. package/dist/generators/CursorConfigGenerator.js +23 -0
  376. package/dist/generators/CursorConfigGenerator.js.map +1 -1
  377. package/dist/generators/GeminiConfigGenerator.d.ts +23 -0
  378. package/dist/generators/GeminiConfigGenerator.d.ts.map +1 -1
  379. package/dist/generators/GeminiConfigGenerator.js +23 -0
  380. package/dist/generators/GeminiConfigGenerator.js.map +1 -1
  381. package/dist/generators/VSCodeConfigGenerator.d.ts +23 -0
  382. package/dist/generators/VSCodeConfigGenerator.d.ts.map +1 -1
  383. package/dist/generators/VSCodeConfigGenerator.js +23 -0
  384. package/dist/generators/VSCodeConfigGenerator.js.map +1 -1
  385. package/dist/generators/ZCodeConfigGenerator.d.ts +23 -0
  386. package/dist/generators/ZCodeConfigGenerator.d.ts.map +1 -1
  387. package/dist/generators/ZCodeConfigGenerator.js +23 -0
  388. package/dist/generators/ZCodeConfigGenerator.js.map +1 -1
  389. package/dist/graph/blastRadius.d.ts.map +1 -1
  390. package/dist/graph/blastRadius.js +12 -7
  391. package/dist/graph/blastRadius.js.map +1 -1
  392. package/dist/graph/callGraph.d.ts +31 -0
  393. package/dist/graph/callGraph.d.ts.map +1 -1
  394. package/dist/graph/callGraph.js +62 -32
  395. package/dist/graph/callGraph.js.map +1 -1
  396. package/dist/graph/importClassification.d.ts +28 -0
  397. package/dist/graph/importClassification.d.ts.map +1 -1
  398. package/dist/graph/importClassification.js +57 -0
  399. package/dist/graph/importClassification.js.map +1 -1
  400. package/dist/graph/importGraph.d.ts +38 -0
  401. package/dist/graph/importGraph.d.ts.map +1 -1
  402. package/dist/graph/importGraph.js +38 -0
  403. package/dist/graph/importGraph.js.map +1 -1
  404. package/dist/graph/outputFormatter.d.ts +12 -4
  405. package/dist/graph/outputFormatter.d.ts.map +1 -1
  406. package/dist/graph/outputFormatter.js +12 -62
  407. package/dist/graph/outputFormatter.js.map +1 -1
  408. package/dist/hooks/codex.d.ts +8 -1
  409. package/dist/hooks/codex.d.ts.map +1 -1
  410. package/dist/hooks/codex.js +7 -0
  411. package/dist/hooks/codex.js.map +1 -1
  412. package/dist/hooks/core.d.ts +6 -0
  413. package/dist/hooks/core.d.ts.map +1 -1
  414. package/dist/hooks/core.js +6 -1
  415. package/dist/hooks/core.js.map +1 -1
  416. package/dist/hooks/cursor.d.ts +11 -1
  417. package/dist/hooks/cursor.d.ts.map +1 -1
  418. package/dist/hooks/cursor.js +10 -0
  419. package/dist/hooks/cursor.js.map +1 -1
  420. package/dist/index.d.ts +4 -0
  421. package/dist/index.d.ts.map +1 -1
  422. package/dist/index.js +4 -0
  423. package/dist/index.js.map +1 -1
  424. package/dist/installConfig.d.ts +23 -5
  425. package/dist/installConfig.d.ts.map +1 -1
  426. package/dist/installConfig.js +23 -5
  427. package/dist/installConfig.js.map +1 -1
  428. package/dist/installer.d.ts +6 -0
  429. package/dist/installer.d.ts.map +1 -1
  430. package/dist/installer.js +6 -0
  431. package/dist/installer.js.map +1 -1
  432. package/dist/invariants/ruleEngine.d.ts +3 -0
  433. package/dist/invariants/ruleEngine.d.ts.map +1 -1
  434. package/dist/invariants/ruleEngine.js +156 -119
  435. package/dist/invariants/ruleEngine.js.map +1 -1
  436. package/dist/invariants/ruleValidator.d.ts +3 -0
  437. package/dist/invariants/ruleValidator.d.ts.map +1 -1
  438. package/dist/invariants/ruleValidator.js +185 -178
  439. package/dist/invariants/ruleValidator.js.map +1 -1
  440. package/dist/languages/LanguageOrchestrator.d.ts +4 -1
  441. package/dist/languages/LanguageOrchestrator.d.ts.map +1 -1
  442. package/dist/languages/LanguageOrchestrator.js +8 -19
  443. package/dist/languages/LanguageOrchestrator.js.map +1 -1
  444. package/dist/languages/RuntimeManager.d.ts +8 -0
  445. package/dist/languages/RuntimeManager.d.ts.map +1 -1
  446. package/dist/languages/RuntimeManager.js +55 -5
  447. package/dist/languages/RuntimeManager.js.map +1 -1
  448. package/dist/languages/UniversalAnalyzer.js +1 -1
  449. package/dist/languages/UniversalAnalyzer.js.map +1 -1
  450. package/dist/languages/adapterBridge.d.ts +4 -0
  451. package/dist/languages/adapterBridge.d.ts.map +1 -1
  452. package/dist/languages/adapterBridge.js +37 -3
  453. package/dist/languages/adapterBridge.js.map +1 -1
  454. package/dist/languages/go/GoAdapter.d.ts.map +1 -1
  455. package/dist/languages/go/GoAdapter.js +11 -14
  456. package/dist/languages/go/GoAdapter.js.map +1 -1
  457. package/dist/languages/go/analyzer-darwin-amd64 +0 -0
  458. package/dist/languages/go/analyzer-darwin-arm64 +0 -0
  459. package/dist/languages/go/analyzer-linux-amd64 +0 -0
  460. package/dist/languages/go/analyzer-linux-arm64 +0 -0
  461. package/dist/languages/go/analyzer-src/analyzer.go +2 -0
  462. package/dist/languages/go/analyzer-src/dataaccess.go +388 -0
  463. package/dist/languages/go/analyzer-src/types.go +8 -0
  464. package/dist/languages/go/analyzer-windows-amd64.exe +0 -0
  465. package/dist/languages/go/database-packages.json +8 -0
  466. package/dist/languages/go/goResolution.d.ts +229 -0
  467. package/dist/languages/go/goResolution.d.ts.map +1 -0
  468. package/dist/languages/go/goResolution.js +799 -0
  469. package/dist/languages/go/goResolution.js.map +1 -0
  470. package/dist/languages/go/stdlib-packages.json +353 -0
  471. package/dist/languages/go/tenantInputs.d.ts +37 -0
  472. package/dist/languages/go/tenantInputs.d.ts.map +1 -0
  473. package/dist/languages/go/tenantInputs.js +121 -0
  474. package/dist/languages/go/tenantInputs.js.map +1 -0
  475. package/dist/languages/index.d.ts +1 -0
  476. package/dist/languages/index.d.ts.map +1 -1
  477. package/dist/languages/index.js +5 -0
  478. package/dist/languages/index.js.map +1 -1
  479. package/dist/languages/json/JsonAdapter.d.ts +177 -0
  480. package/dist/languages/json/JsonAdapter.d.ts.map +1 -0
  481. package/dist/languages/json/JsonAdapter.js +531 -0
  482. package/dist/languages/json/JsonAdapter.js.map +1 -0
  483. package/dist/languages/locationIndex.d.ts +41 -0
  484. package/dist/languages/locationIndex.d.ts.map +1 -0
  485. package/dist/languages/locationIndex.js +42 -0
  486. package/dist/languages/locationIndex.js.map +1 -0
  487. package/dist/languages/sql/dialectDetection.d.ts +57 -0
  488. package/dist/languages/sql/dialectDetection.d.ts.map +1 -0
  489. package/dist/languages/sql/dialectDetection.js +135 -0
  490. package/dist/languages/sql/dialectDetection.js.map +1 -0
  491. package/dist/languages/sql/sqlAst.d.ts +494 -0
  492. package/dist/languages/sql/sqlAst.d.ts.map +1 -0
  493. package/dist/languages/sql/sqlAst.js +1817 -0
  494. package/dist/languages/sql/sqlAst.js.map +1 -0
  495. package/dist/languages/testConventions.d.ts +12 -1
  496. package/dist/languages/testConventions.d.ts.map +1 -1
  497. package/dist/languages/testConventions.js +13 -1
  498. package/dist/languages/testConventions.js.map +1 -1
  499. package/dist/languages/tree-sitter/TreeSitterCssAdapter.js +1 -1
  500. package/dist/languages/tree-sitter/TreeSitterCssAdapter.js.map +1 -1
  501. package/dist/languages/tree-sitter/converter.js +2 -2
  502. package/dist/languages/tree-sitter/converter.js.map +1 -1
  503. package/dist/languages/tree-sitter/parser.d.ts +3 -4
  504. package/dist/languages/tree-sitter/parser.d.ts.map +1 -1
  505. package/dist/languages/tree-sitter/parser.js +10 -4
  506. package/dist/languages/tree-sitter/parser.js.map +1 -1
  507. package/dist/languages/tree-sitter/rawNode.d.ts +3 -0
  508. package/dist/languages/tree-sitter/rawNode.d.ts.map +1 -1
  509. package/dist/languages/tree-sitter/rawNode.js +3 -0
  510. package/dist/languages/tree-sitter/rawNode.js.map +1 -1
  511. package/dist/languages/types.d.ts +7 -0
  512. package/dist/languages/types.d.ts.map +1 -1
  513. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +36 -0
  514. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
  515. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +168 -45
  516. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
  517. package/dist/languages/typescript/database-packages.json +19 -0
  518. package/dist/ledger.d.ts +118 -2
  519. package/dist/ledger.d.ts.map +1 -1
  520. package/dist/ledger.js +167 -45
  521. package/dist/ledger.js.map +1 -1
  522. package/dist/legacyIndexNotice.d.ts +32 -0
  523. package/dist/legacyIndexNotice.d.ts.map +1 -0
  524. package/dist/legacyIndexNotice.js +89 -0
  525. package/dist/legacyIndexNotice.js.map +1 -0
  526. package/dist/mcp-tools/discoveryQueries.d.ts +55 -0
  527. package/dist/mcp-tools/discoveryQueries.d.ts.map +1 -0
  528. package/dist/mcp-tools/discoveryQueries.js +157 -0
  529. package/dist/mcp-tools/discoveryQueries.js.map +1 -0
  530. package/dist/mcp-tools/projectTasks.d.ts +9 -123
  531. package/dist/mcp-tools/projectTasks.d.ts.map +1 -1
  532. package/dist/mcp-tools/projectTasks.js +180 -170
  533. package/dist/mcp-tools/projectTasks.js.map +1 -1
  534. package/dist/mcp-tools/whitelistTools.d.ts +20 -0
  535. package/dist/mcp-tools/whitelistTools.d.ts.map +1 -1
  536. package/dist/mcp-tools/whitelistTools.js +20 -0
  537. package/dist/mcp-tools/whitelistTools.js.map +1 -1
  538. package/dist/mcp-tools/workflowGuide.d.ts +9 -0
  539. package/dist/mcp-tools/workflowGuide.d.ts.map +1 -1
  540. package/dist/mcp-tools/workflowGuide.js +13 -5
  541. package/dist/mcp-tools/workflowGuide.js.map +1 -1
  542. package/dist/mcp-tools-shared.d.ts +78 -0
  543. package/dist/mcp-tools-shared.d.ts.map +1 -1
  544. package/dist/mcp-tools-shared.js +203 -340
  545. package/dist/mcp-tools-shared.js.map +1 -1
  546. package/dist/mcp-ui-simple.d.ts +2 -0
  547. package/dist/mcp-ui-simple.d.ts.map +1 -1
  548. package/dist/mcp-ui-simple.js +12 -5
  549. package/dist/mcp-ui-simple.js.map +1 -1
  550. package/dist/mcp.d.ts +6 -0
  551. package/dist/mcp.d.ts.map +1 -1
  552. package/dist/mcp.js +827 -850
  553. package/dist/mcp.js.map +1 -1
  554. package/dist/mcpAuditJobs.d.ts +29 -33
  555. package/dist/mcpAuditJobs.d.ts.map +1 -1
  556. package/dist/mcpAuditJobs.js +102 -791
  557. package/dist/mcpAuditJobs.js.map +1 -1
  558. package/dist/mcpAutoIndex.d.ts +5 -0
  559. package/dist/mcpAutoIndex.d.ts.map +1 -1
  560. package/dist/mcpAutoIndex.js +7 -2
  561. package/dist/mcpAutoIndex.js.map +1 -1
  562. package/dist/mcpDiagnostics.d.ts +7 -0
  563. package/dist/mcpDiagnostics.d.ts.map +1 -1
  564. package/dist/mcpDiagnostics.js +34 -9
  565. package/dist/mcpDiagnostics.js.map +1 -1
  566. package/dist/mcpToolErrors.d.ts +16 -0
  567. package/dist/mcpToolErrors.d.ts.map +1 -1
  568. package/dist/mcpToolErrors.js +16 -0
  569. package/dist/mcpToolErrors.js.map +1 -1
  570. package/dist/nextFile.d.ts +6 -0
  571. package/dist/nextFile.d.ts.map +1 -1
  572. package/dist/nextFile.js +6 -0
  573. package/dist/nextFile.js.map +1 -1
  574. package/dist/nextFileIncremental.d.ts +44 -4
  575. package/dist/nextFileIncremental.d.ts.map +1 -1
  576. package/dist/nextFileIncremental.js +47 -7
  577. package/dist/nextFileIncremental.js.map +1 -1
  578. package/dist/phase/batchFunctions.d.ts +38 -0
  579. package/dist/phase/batchFunctions.d.ts.map +1 -0
  580. package/dist/phase/batchFunctions.js +64 -0
  581. package/dist/phase/batchFunctions.js.map +1 -0
  582. package/dist/phase/checks.d.ts +39 -0
  583. package/dist/phase/checks.d.ts.map +1 -0
  584. package/dist/phase/checks.js +48 -0
  585. package/dist/phase/checks.js.map +1 -0
  586. package/dist/phase/codeBlocks.d.ts +25 -0
  587. package/dist/phase/codeBlocks.d.ts.map +1 -0
  588. package/dist/phase/codeBlocks.js +268 -0
  589. package/dist/phase/codeBlocks.js.map +1 -0
  590. package/dist/phase/colorMath.d.ts +41 -0
  591. package/dist/phase/colorMath.d.ts.map +1 -0
  592. package/dist/phase/colorMath.js +109 -0
  593. package/dist/phase/colorMath.js.map +1 -0
  594. package/dist/phase/config.d.ts +29 -0
  595. package/dist/phase/config.d.ts.map +1 -0
  596. package/dist/phase/config.js +54 -0
  597. package/dist/phase/config.js.map +1 -0
  598. package/dist/phase/consumed.d.ts +47 -0
  599. package/dist/phase/consumed.d.ts.map +1 -0
  600. package/dist/phase/consumed.js +22 -0
  601. package/dist/phase/consumed.js.map +1 -0
  602. package/dist/phase/conventionMining.d.ts +59 -0
  603. package/dist/phase/conventionMining.d.ts.map +1 -0
  604. package/dist/phase/conventionMining.js +152 -0
  605. package/dist/phase/conventionMining.js.map +1 -0
  606. package/dist/phase/coverage.d.ts +65 -0
  607. package/dist/phase/coverage.d.ts.map +1 -0
  608. package/dist/phase/coverage.js +121 -0
  609. package/dist/phase/coverage.js.map +1 -0
  610. package/dist/phase/dag.d.ts +49 -0
  611. package/dist/phase/dag.d.ts.map +1 -0
  612. package/dist/phase/dag.js +120 -0
  613. package/dist/phase/dag.js.map +1 -0
  614. package/dist/phase/dataAccessCalls.d.ts +33 -0
  615. package/dist/phase/dataAccessCalls.d.ts.map +1 -0
  616. package/dist/phase/dataAccessCalls.js +42 -0
  617. package/dist/phase/dataAccessCalls.js.map +1 -0
  618. package/dist/phase/dataAccessCallsCandidates.d.ts +25 -0
  619. package/dist/phase/dataAccessCallsCandidates.d.ts.map +1 -0
  620. package/dist/phase/dataAccessCallsCandidates.js +27 -0
  621. package/dist/phase/dataAccessCallsCandidates.js.map +1 -0
  622. package/dist/phase/dynamicSql.d.ts +18 -0
  623. package/dist/phase/dynamicSql.d.ts.map +1 -0
  624. package/dist/phase/dynamicSql.js +20 -0
  625. package/dist/phase/dynamicSql.js.map +1 -0
  626. package/dist/phase/exportForm.d.ts +23 -0
  627. package/dist/phase/exportForm.d.ts.map +1 -0
  628. package/dist/phase/exportForm.js +29 -0
  629. package/dist/phase/exportForm.js.map +1 -0
  630. package/dist/phase/exportSymbols.d.ts +21 -0
  631. package/dist/phase/exportSymbols.d.ts.map +1 -0
  632. package/dist/phase/exportSymbols.js +28 -0
  633. package/dist/phase/exportSymbols.js.map +1 -0
  634. package/dist/phase/fileHeader.d.ts +15 -0
  635. package/dist/phase/fileHeader.d.ts.map +1 -0
  636. package/dist/phase/fileHeader.js +33 -0
  637. package/dist/phase/fileHeader.js.map +1 -0
  638. package/dist/phase/fileImports.d.ts +39 -0
  639. package/dist/phase/fileImports.d.ts.map +1 -0
  640. package/dist/phase/fileImports.js +138 -0
  641. package/dist/phase/fileImports.js.map +1 -0
  642. package/dist/phase/fileSymbols.d.ts +25 -0
  643. package/dist/phase/fileSymbols.d.ts.map +1 -0
  644. package/dist/phase/fileSymbols.js +302 -0
  645. package/dist/phase/fileSymbols.js.map +1 -0
  646. package/dist/phase/functionBodies.d.ts +28 -0
  647. package/dist/phase/functionBodies.d.ts.map +1 -0
  648. package/dist/phase/functionBodies.js +67 -0
  649. package/dist/phase/functionBodies.js.map +1 -0
  650. package/dist/phase/functionIndex.d.ts +28 -0
  651. package/dist/phase/functionIndex.d.ts.map +1 -0
  652. package/dist/phase/functionIndex.js +152 -0
  653. package/dist/phase/functionIndex.js.map +1 -0
  654. package/dist/phase/goFunctionAnalysis.d.ts +47 -0
  655. package/dist/phase/goFunctionAnalysis.d.ts.map +1 -0
  656. package/dist/phase/goFunctionAnalysis.js +291 -0
  657. package/dist/phase/goFunctionAnalysis.js.map +1 -0
  658. package/dist/phase/goFunctions.d.ts +38 -0
  659. package/dist/phase/goFunctions.d.ts.map +1 -0
  660. package/dist/phase/goFunctions.js +154 -0
  661. package/dist/phase/goFunctions.js.map +1 -0
  662. package/dist/phase/goImports.d.ts +29 -0
  663. package/dist/phase/goImports.d.ts.map +1 -0
  664. package/dist/phase/goImports.js +68 -0
  665. package/dist/phase/goImports.js.map +1 -0
  666. package/dist/phase/goPackageBindings.d.ts +22 -0
  667. package/dist/phase/goPackageBindings.d.ts.map +1 -0
  668. package/dist/phase/goPackageBindings.js +30 -0
  669. package/dist/phase/goPackageBindings.js.map +1 -0
  670. package/dist/phase/goSwitches.d.ts +28 -0
  671. package/dist/phase/goSwitches.d.ts.map +1 -0
  672. package/dist/phase/goSwitches.js +52 -0
  673. package/dist/phase/goSwitches.js.map +1 -0
  674. package/dist/phase/importForm.d.ts +20 -0
  675. package/dist/phase/importForm.d.ts.map +1 -0
  676. package/dist/phase/importForm.js +27 -0
  677. package/dist/phase/importForm.js.map +1 -0
  678. package/dist/phase/importSpecifiers.d.ts +20 -0
  679. package/dist/phase/importSpecifiers.d.ts.map +1 -0
  680. package/dist/phase/importSpecifiers.js +30 -0
  681. package/dist/phase/importSpecifiers.js.map +1 -0
  682. package/dist/phase/imports.d.ts +18 -0
  683. package/dist/phase/imports.d.ts.map +1 -0
  684. package/dist/phase/imports.js +25 -0
  685. package/dist/phase/imports.js.map +1 -0
  686. package/dist/phase/jsonDocument.d.ts +26 -0
  687. package/dist/phase/jsonDocument.d.ts.map +1 -0
  688. package/dist/phase/jsonDocument.js +36 -0
  689. package/dist/phase/jsonDocument.js.map +1 -0
  690. package/dist/phase/localBinding.d.ts +33 -0
  691. package/dist/phase/localBinding.d.ts.map +1 -0
  692. package/dist/phase/localBinding.js +208 -0
  693. package/dist/phase/localBinding.js.map +1 -0
  694. package/dist/phase/loopQueries.d.ts +31 -0
  695. package/dist/phase/loopQueries.d.ts.map +1 -0
  696. package/dist/phase/loopQueries.js +44 -0
  697. package/dist/phase/loopQueries.js.map +1 -0
  698. package/dist/phase/loopQueryCandidates.d.ts +26 -0
  699. package/dist/phase/loopQueryCandidates.d.ts.map +1 -0
  700. package/dist/phase/loopQueryCandidates.js +28 -0
  701. package/dist/phase/loopQueryCandidates.js.map +1 -0
  702. package/dist/phase/oracles.d.ts +216 -0
  703. package/dist/phase/oracles.d.ts.map +1 -0
  704. package/dist/phase/oracles.js +484 -0
  705. package/dist/phase/oracles.js.map +1 -0
  706. package/dist/phase/phaseModel.d.ts +190 -0
  707. package/dist/phase/phaseModel.d.ts.map +1 -0
  708. package/dist/phase/phaseModel.js +468 -0
  709. package/dist/phase/phaseModel.js.map +1 -0
  710. package/dist/phase/producers.d.ts +450 -0
  711. package/dist/phase/producers.d.ts.map +1 -0
  712. package/dist/phase/producers.js +1027 -0
  713. package/dist/phase/producers.js.map +1 -0
  714. package/dist/phase/querySiteCandidates.d.ts +27 -0
  715. package/dist/phase/querySiteCandidates.d.ts.map +1 -0
  716. package/dist/phase/querySiteCandidates.js +66 -0
  717. package/dist/phase/querySiteCandidates.js.map +1 -0
  718. package/dist/phase/querySites.d.ts +30 -0
  719. package/dist/phase/querySites.d.ts.map +1 -0
  720. package/dist/phase/querySites.js +93 -0
  721. package/dist/phase/querySites.js.map +1 -0
  722. package/dist/phase/reachability.d.ts +61 -0
  723. package/dist/phase/reachability.d.ts.map +1 -0
  724. package/dist/phase/reachability.js +104 -0
  725. package/dist/phase/reachability.js.map +1 -0
  726. package/dist/phase/reactComponents.d.ts +33 -0
  727. package/dist/phase/reactComponents.d.ts.map +1 -0
  728. package/dist/phase/reactComponents.js +47 -0
  729. package/dist/phase/reactComponents.js.map +1 -0
  730. package/dist/phase/receiverActivity.d.ts +35 -0
  731. package/dist/phase/receiverActivity.d.ts.map +1 -0
  732. package/dist/phase/receiverActivity.js +66 -0
  733. package/dist/phase/receiverActivity.js.map +1 -0
  734. package/dist/phase/receiverConsumers.d.ts +200 -0
  735. package/dist/phase/receiverConsumers.d.ts.map +1 -0
  736. package/dist/phase/receiverConsumers.js +1025 -0
  737. package/dist/phase/receiverConsumers.js.map +1 -0
  738. package/dist/phase/receiverProvenance.d.ts +97 -0
  739. package/dist/phase/receiverProvenance.d.ts.map +1 -0
  740. package/dist/phase/receiverProvenance.js +337 -0
  741. package/dist/phase/receiverProvenance.js.map +1 -0
  742. package/dist/phase/routing.d.ts +47 -0
  743. package/dist/phase/routing.d.ts.map +1 -0
  744. package/dist/phase/routing.js +62 -0
  745. package/dist/phase/routing.js.map +1 -0
  746. package/dist/phase/rules/conventions.d.ts +61 -0
  747. package/dist/phase/rules/conventions.d.ts.map +1 -0
  748. package/dist/phase/rules/conventions.js +403 -0
  749. package/dist/phase/rules/conventions.js.map +1 -0
  750. package/dist/phase/rules/crossDomain.d.ts +102 -0
  751. package/dist/phase/rules/crossDomain.d.ts.map +1 -0
  752. package/dist/phase/rules/crossDomain.js +918 -0
  753. package/dist/phase/rules/crossDomain.js.map +1 -0
  754. package/dist/phase/rules/dataAccess.d.ts +62 -0
  755. package/dist/phase/rules/dataAccess.d.ts.map +1 -0
  756. package/dist/phase/rules/dataAccess.js +480 -0
  757. package/dist/phase/rules/dataAccess.js.map +1 -0
  758. package/dist/phase/rules/dependencyGraph.d.ts +44 -0
  759. package/dist/phase/rules/dependencyGraph.d.ts.map +1 -0
  760. package/dist/phase/rules/dependencyGraph.js +260 -0
  761. package/dist/phase/rules/dependencyGraph.js.map +1 -0
  762. package/dist/phase/rules/documentation.d.ts +45 -0
  763. package/dist/phase/rules/documentation.d.ts.map +1 -0
  764. package/dist/phase/rules/documentation.js +340 -0
  765. package/dist/phase/rules/documentation.js.map +1 -0
  766. package/dist/phase/rules/dry.d.ts +109 -0
  767. package/dist/phase/rules/dry.d.ts.map +1 -0
  768. package/dist/phase/rules/dry.js +803 -0
  769. package/dist/phase/rules/dry.js.map +1 -0
  770. package/dist/phase/rules/fileDocumentation.d.ts +36 -0
  771. package/dist/phase/rules/fileDocumentation.d.ts.map +1 -0
  772. package/dist/phase/rules/fileDocumentation.js +134 -0
  773. package/dist/phase/rules/fileDocumentation.js.map +1 -0
  774. package/dist/phase/rules/functionBodies.d.ts +33 -0
  775. package/dist/phase/rules/functionBodies.d.ts.map +1 -0
  776. package/dist/phase/rules/functionBodies.js +71 -0
  777. package/dist/phase/rules/functionBodies.js.map +1 -0
  778. package/dist/phase/rules/goRules.d.ts +49 -0
  779. package/dist/phase/rules/goRules.d.ts.map +1 -0
  780. package/dist/phase/rules/goRules.js +209 -0
  781. package/dist/phase/rules/goRules.js.map +1 -0
  782. package/dist/phase/rules/querySites.d.ts +29 -0
  783. package/dist/phase/rules/querySites.d.ts.map +1 -0
  784. package/dist/phase/rules/querySites.js +94 -0
  785. package/dist/phase/rules/querySites.js.map +1 -0
  786. package/dist/phase/rules/react.d.ts +38 -0
  787. package/dist/phase/rules/react.d.ts.map +1 -0
  788. package/dist/phase/rules/react.js +202 -0
  789. package/dist/phase/rules/react.js.map +1 -0
  790. package/dist/phase/rules/registry.d.ts +170 -0
  791. package/dist/phase/rules/registry.d.ts.map +1 -0
  792. package/dist/phase/rules/registry.js +103 -0
  793. package/dist/phase/rules/registry.js.map +1 -0
  794. package/dist/phase/rules/schema.d.ts +79 -0
  795. package/dist/phase/rules/schema.d.ts.map +1 -0
  796. package/dist/phase/rules/schema.js +273 -0
  797. package/dist/phase/rules/schema.js.map +1 -0
  798. package/dist/phase/rules/schemaJson.d.ts +32 -0
  799. package/dist/phase/rules/schemaJson.d.ts.map +1 -0
  800. package/dist/phase/rules/schemaJson.js +81 -0
  801. package/dist/phase/rules/schemaJson.js.map +1 -0
  802. package/dist/phase/rules/schemaValidator.d.ts +38 -0
  803. package/dist/phase/rules/schemaValidator.d.ts.map +1 -0
  804. package/dist/phase/rules/schemaValidator.js +107 -0
  805. package/dist/phase/rules/schemaValidator.js.map +1 -0
  806. package/dist/phase/rules/secrets.d.ts +34 -0
  807. package/dist/phase/rules/secrets.d.ts.map +1 -0
  808. package/dist/phase/rules/secrets.js +208 -0
  809. package/dist/phase/rules/secrets.js.map +1 -0
  810. package/dist/phase/rules/security.d.ts +30 -0
  811. package/dist/phase/rules/security.d.ts.map +1 -0
  812. package/dist/phase/rules/security.js +85 -0
  813. package/dist/phase/rules/security.js.map +1 -0
  814. package/dist/phase/rules/securityDefects.d.ts +37 -0
  815. package/dist/phase/rules/securityDefects.d.ts.map +1 -0
  816. package/dist/phase/rules/securityDefects.js +167 -0
  817. package/dist/phase/rules/securityDefects.js.map +1 -0
  818. package/dist/phase/rules/solid.d.ts +61 -0
  819. package/dist/phase/rules/solid.d.ts.map +1 -0
  820. package/dist/phase/rules/solid.js +562 -0
  821. package/dist/phase/rules/solid.js.map +1 -0
  822. package/dist/phase/rules/styles.d.ts +77 -0
  823. package/dist/phase/rules/styles.d.ts.map +1 -0
  824. package/dist/phase/rules/styles.js +868 -0
  825. package/dist/phase/rules/styles.js.map +1 -0
  826. package/dist/phase/rules/unreferencedModule.d.ts +26 -0
  827. package/dist/phase/rules/unreferencedModule.d.ts.map +1 -0
  828. package/dist/phase/rules/unreferencedModule.js +61 -0
  829. package/dist/phase/rules/unreferencedModule.js.map +1 -0
  830. package/dist/phase/runner.d.ts +549 -0
  831. package/dist/phase/runner.d.ts.map +1 -0
  832. package/dist/phase/runner.js +1098 -0
  833. package/dist/phase/runner.js.map +1 -0
  834. package/dist/phase/schemaCode.d.ts +34 -0
  835. package/dist/phase/schemaCode.d.ts.map +1 -0
  836. package/dist/phase/schemaCode.js +53 -0
  837. package/dist/phase/schemaCode.js.map +1 -0
  838. package/dist/phase/schemaObjects.d.ts +37 -0
  839. package/dist/phase/schemaObjects.d.ts.map +1 -0
  840. package/dist/phase/schemaObjects.js +139 -0
  841. package/dist/phase/schemaObjects.js.map +1 -0
  842. package/dist/phase/schemaUsage.d.ts +30 -0
  843. package/dist/phase/schemaUsage.d.ts.map +1 -0
  844. package/dist/phase/schemaUsage.js +99 -0
  845. package/dist/phase/schemaUsage.js.map +1 -0
  846. package/dist/phase/schemaUsageCandidates.d.ts +32 -0
  847. package/dist/phase/schemaUsageCandidates.d.ts.map +1 -0
  848. package/dist/phase/schemaUsageCandidates.js +165 -0
  849. package/dist/phase/schemaUsageCandidates.js.map +1 -0
  850. package/dist/phase/schemaValidations.d.ts +34 -0
  851. package/dist/phase/schemaValidations.d.ts.map +1 -0
  852. package/dist/phase/schemaValidations.js +53 -0
  853. package/dist/phase/schemaValidations.js.map +1 -0
  854. package/dist/phase/secretCandidates.d.ts +28 -0
  855. package/dist/phase/secretCandidates.d.ts.map +1 -0
  856. package/dist/phase/secretCandidates.js +132 -0
  857. package/dist/phase/secretCandidates.js.map +1 -0
  858. package/dist/phase/securityCandidates.d.ts +29 -0
  859. package/dist/phase/securityCandidates.d.ts.map +1 -0
  860. package/dist/phase/securityCandidates.js +469 -0
  861. package/dist/phase/securityCandidates.js.map +1 -0
  862. package/dist/phase/seeded-defects.d.ts +18 -0
  863. package/dist/phase/seeded-defects.d.ts.map +1 -0
  864. package/dist/phase/seeded-defects.js +61 -0
  865. package/dist/phase/seeded-defects.js.map +1 -0
  866. package/dist/phase/stringLiterals.d.ts +24 -0
  867. package/dist/phase/stringLiterals.d.ts.map +1 -0
  868. package/dist/phase/stringLiterals.js +35 -0
  869. package/dist/phase/stringLiterals.js.map +1 -0
  870. package/dist/phase/stylesCss.d.ts +25 -0
  871. package/dist/phase/stylesCss.d.ts.map +1 -0
  872. package/dist/phase/stylesCss.js +34 -0
  873. package/dist/phase/stylesCss.js.map +1 -0
  874. package/dist/phase/stylesMarkup.d.ts +31 -0
  875. package/dist/phase/stylesMarkup.d.ts.map +1 -0
  876. package/dist/phase/stylesMarkup.js +48 -0
  877. package/dist/phase/stylesMarkup.js.map +1 -0
  878. package/dist/phase/stylesSource.d.ts +36 -0
  879. package/dist/phase/stylesSource.d.ts.map +1 -0
  880. package/dist/phase/stylesSource.js +50 -0
  881. package/dist/phase/stylesSource.js.map +1 -0
  882. package/dist/phase/typeDeclarations.d.ts +33 -0
  883. package/dist/phase/typeDeclarations.d.ts.map +1 -0
  884. package/dist/phase/typeDeclarations.js +76 -0
  885. package/dist/phase/typeDeclarations.js.map +1 -0
  886. package/dist/phase/types.d.ts +2191 -0
  887. package/dist/phase/types.d.ts.map +1 -0
  888. package/dist/phase/types.js +27 -0
  889. package/dist/phase/types.js.map +1 -0
  890. package/dist/phase/withinFileProvenance.d.ts +50 -0
  891. package/dist/phase/withinFileProvenance.d.ts.map +1 -0
  892. package/dist/phase/withinFileProvenance.js +112 -0
  893. package/dist/phase/withinFileProvenance.js.map +1 -0
  894. package/dist/pipeline.d.ts +37 -30
  895. package/dist/pipeline.d.ts.map +1 -1
  896. package/dist/pipeline.js +131 -326
  897. package/dist/pipeline.js.map +1 -1
  898. package/dist/pipelineAdapters.d.ts +104 -21
  899. package/dist/pipelineAdapters.d.ts.map +1 -1
  900. package/dist/pipelineAdapters.js +1144 -984
  901. package/dist/pipelineAdapters.js.map +1 -1
  902. package/dist/pipelineTypes.d.ts +21 -0
  903. package/dist/pipelineTypes.d.ts.map +1 -1
  904. package/dist/pipelineTypes.js +21 -10
  905. package/dist/pipelineTypes.js.map +1 -1
  906. package/dist/presets/presets.d.ts +9 -2
  907. package/dist/presets/presets.d.ts.map +1 -1
  908. package/dist/presets/presets.js +15 -26
  909. package/dist/presets/presets.js.map +1 -1
  910. package/dist/reporting/csvReportGenerator.d.ts +14 -3
  911. package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
  912. package/dist/reporting/csvReportGenerator.js +14 -3
  913. package/dist/reporting/csvReportGenerator.js.map +1 -1
  914. package/dist/reporting/htmlReportGenerator.d.ts +5 -1
  915. package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
  916. package/dist/reporting/htmlReportGenerator.js +5 -1
  917. package/dist/reporting/htmlReportGenerator.js.map +1 -1
  918. package/dist/reporting/jsonReportGenerator.d.ts +9 -2
  919. package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
  920. package/dist/reporting/jsonReportGenerator.js +19 -5
  921. package/dist/reporting/jsonReportGenerator.js.map +1 -1
  922. package/dist/reporting/reportGenerator.d.ts +9 -2
  923. package/dist/reporting/reportGenerator.d.ts.map +1 -1
  924. package/dist/reporting/reportGenerator.js +9 -2
  925. package/dist/reporting/reportGenerator.js.map +1 -1
  926. package/dist/reporting/sarifReportGenerator.d.ts +14 -0
  927. package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
  928. package/dist/reporting/sarifReportGenerator.js +14 -0
  929. package/dist/reporting/sarifReportGenerator.js.map +1 -1
  930. package/dist/reporting/sizeDistribution.d.ts +19 -2
  931. package/dist/reporting/sizeDistribution.d.ts.map +1 -1
  932. package/dist/reporting/sizeDistribution.js +23 -5
  933. package/dist/reporting/sizeDistribution.js.map +1 -1
  934. package/dist/ruleAliases.d.ts +6 -8
  935. package/dist/ruleAliases.d.ts.map +1 -1
  936. package/dist/ruleAliases.js +29 -4
  937. package/dist/ruleAliases.js.map +1 -1
  938. package/dist/search/QueryParser.d.ts +1 -0
  939. package/dist/search/QueryParser.d.ts.map +1 -1
  940. package/dist/search/QueryParser.js +32 -91
  941. package/dist/search/QueryParser.js.map +1 -1
  942. package/dist/services/CodeMapGenerator.d.ts +19 -20
  943. package/dist/services/CodeMapGenerator.d.ts.map +1 -1
  944. package/dist/services/CodeMapGenerator.js +214 -194
  945. package/dist/services/CodeMapGenerator.js.map +1 -1
  946. package/dist/services/ProjectTaskRepository.d.ts +65 -3
  947. package/dist/services/ProjectTaskRepository.d.ts.map +1 -1
  948. package/dist/services/ProjectTaskRepository.js +94 -25
  949. package/dist/services/ProjectTaskRepository.js.map +1 -1
  950. package/dist/services/auditJobService.d.ts +17 -1
  951. package/dist/services/auditJobService.d.ts.map +1 -1
  952. package/dist/services/auditJobService.js +16 -0
  953. package/dist/services/auditJobService.js.map +1 -1
  954. package/dist/services/fileAccounting.d.ts +43 -5
  955. package/dist/services/fileAccounting.d.ts.map +1 -1
  956. package/dist/services/fileAccounting.js +48 -9
  957. package/dist/services/fileAccounting.js.map +1 -1
  958. package/dist/services/projectTaskHelpers.d.ts +45 -0
  959. package/dist/services/projectTaskHelpers.d.ts.map +1 -1
  960. package/dist/services/projectTaskHelpers.js +45 -0
  961. package/dist/services/projectTaskHelpers.js.map +1 -1
  962. package/dist/services/whitelistService.d.ts +40 -5
  963. package/dist/services/whitelistService.d.ts.map +1 -1
  964. package/dist/services/whitelistService.js +87 -46
  965. package/dist/services/whitelistService.js.map +1 -1
  966. package/dist/sqlite/betterSqlite3.d.ts +35 -1
  967. package/dist/sqlite/betterSqlite3.d.ts.map +1 -1
  968. package/dist/sqlite/betterSqlite3.js +35 -1
  969. package/dist/sqlite/betterSqlite3.js.map +1 -1
  970. package/dist/sqlite/driver.d.ts +23 -0
  971. package/dist/sqlite/driver.d.ts.map +1 -1
  972. package/dist/sqlite/driver.js +23 -0
  973. package/dist/sqlite/driver.js.map +1 -1
  974. package/dist/sqlite/nodeSqlite.d.ts +35 -1
  975. package/dist/sqlite/nodeSqlite.d.ts.map +1 -1
  976. package/dist/sqlite/nodeSqlite.js +35 -1
  977. package/dist/sqlite/nodeSqlite.js.map +1 -1
  978. package/dist/structuralSignature.d.ts +9 -0
  979. package/dist/structuralSignature.d.ts.map +1 -1
  980. package/dist/structuralSignature.js +9 -0
  981. package/dist/structuralSignature.js.map +1 -1
  982. package/dist/styles/cssAstExtractor.d.ts +15 -0
  983. package/dist/styles/cssAstExtractor.d.ts.map +1 -1
  984. package/dist/styles/cssAstExtractor.js +15 -0
  985. package/dist/styles/cssAstExtractor.js.map +1 -1
  986. package/dist/styles/normalizer.d.ts +6 -0
  987. package/dist/styles/normalizer.d.ts.map +1 -1
  988. package/dist/styles/normalizer.js +6 -0
  989. package/dist/styles/normalizer.js.map +1 -1
  990. package/dist/styles/styleExtractor.d.ts +29 -2
  991. package/dist/styles/styleExtractor.d.ts.map +1 -1
  992. package/dist/styles/styleExtractor.js +67 -48
  993. package/dist/styles/styleExtractor.js.map +1 -1
  994. package/dist/styles/styleIndexer.d.ts +8 -0
  995. package/dist/styles/styleIndexer.d.ts.map +1 -1
  996. package/dist/styles/styleIndexer.js +135 -138
  997. package/dist/styles/styleIndexer.js.map +1 -1
  998. package/dist/styles/tailwindConfigLoader.d.ts +12 -0
  999. package/dist/styles/tailwindConfigLoader.d.ts.map +1 -1
  1000. package/dist/styles/tailwindConfigLoader.js +12 -0
  1001. package/dist/styles/tailwindConfigLoader.js.map +1 -1
  1002. package/dist/styles/tailwindExpander.d.ts +3 -0
  1003. package/dist/styles/tailwindExpander.d.ts.map +1 -1
  1004. package/dist/styles/tailwindExpander.js +8 -4
  1005. package/dist/styles/tailwindExpander.js.map +1 -1
  1006. package/dist/styles/tailwindProbe.d.ts +9 -0
  1007. package/dist/styles/tailwindProbe.d.ts.map +1 -1
  1008. package/dist/styles/tailwindProbe.js +181 -166
  1009. package/dist/styles/tailwindProbe.js.map +1 -1
  1010. package/dist/styles/tailwindUtilityExpander.d.ts +13 -0
  1011. package/dist/styles/tailwindUtilityExpander.d.ts.map +1 -1
  1012. package/dist/styles/tailwindUtilityExpander.js +13 -0
  1013. package/dist/styles/tailwindUtilityExpander.js.map +1 -1
  1014. package/dist/symbols.d.ts +13 -11
  1015. package/dist/symbols.d.ts.map +1 -1
  1016. package/dist/symbols.js +14 -21
  1017. package/dist/symbols.js.map +1 -1
  1018. package/dist/telemetry.d.ts +31 -3
  1019. package/dist/telemetry.d.ts.map +1 -1
  1020. package/dist/telemetry.js +31 -3
  1021. package/dist/telemetry.js.map +1 -1
  1022. package/dist/tool-registry.d.ts +37 -1
  1023. package/dist/tool-registry.d.ts.map +1 -1
  1024. package/dist/tool-registry.js +37 -1
  1025. package/dist/tool-registry.js.map +1 -1
  1026. package/dist/types.d.ts +101 -71
  1027. package/dist/types.d.ts.map +1 -1
  1028. package/dist/types.js +7 -16
  1029. package/dist/types.js.map +1 -1
  1030. package/dist/ui/InteractivePrompts.d.ts +12 -0
  1031. package/dist/ui/InteractivePrompts.d.ts.map +1 -1
  1032. package/dist/ui/InteractivePrompts.js +12 -0
  1033. package/dist/ui/InteractivePrompts.js.map +1 -1
  1034. package/dist/utils/astParser.d.ts +15 -0
  1035. package/dist/utils/astParser.d.ts.map +1 -1
  1036. package/dist/utils/astParser.js +15 -0
  1037. package/dist/utils/astParser.js.map +1 -1
  1038. package/dist/utils/astUtils.d.ts +60 -0
  1039. package/dist/utils/astUtils.d.ts.map +1 -1
  1040. package/dist/utils/astUtils.js +350 -362
  1041. package/dist/utils/astUtils.js.map +1 -1
  1042. package/dist/utils/contentHash.d.ts +22 -0
  1043. package/dist/utils/contentHash.d.ts.map +1 -0
  1044. package/dist/utils/contentHash.js +26 -0
  1045. package/dist/utils/contentHash.js.map +1 -0
  1046. package/dist/utils/dependencyExtractor.d.ts +28 -0
  1047. package/dist/utils/dependencyExtractor.d.ts.map +1 -1
  1048. package/dist/utils/dependencyExtractor.js +28 -1
  1049. package/dist/utils/dependencyExtractor.js.map +1 -1
  1050. package/dist/utils/errorMessage.d.ts +10 -0
  1051. package/dist/utils/errorMessage.d.ts.map +1 -0
  1052. package/dist/utils/errorMessage.js +12 -0
  1053. package/dist/utils/errorMessage.js.map +1 -0
  1054. package/dist/utils/fileDiscovery.d.ts +61 -2
  1055. package/dist/utils/fileDiscovery.d.ts.map +1 -1
  1056. package/dist/utils/fileDiscovery.js +131 -23
  1057. package/dist/utils/fileDiscovery.js.map +1 -1
  1058. package/dist/utils/reactDetection.d.ts +34 -5
  1059. package/dist/utils/reactDetection.d.ts.map +1 -1
  1060. package/dist/utils/reactDetection.js +73 -52
  1061. package/dist/utils/reactDetection.js.map +1 -1
  1062. package/dist/version.generated.d.ts +1 -1
  1063. package/dist/version.generated.js +1 -1
  1064. package/dist/workers/auditWorker.js +7 -3
  1065. package/dist/workers/auditWorker.js.map +1 -1
  1066. package/examples/.auditrc.example.json +0 -8
  1067. package/examples/.auditrc.json +0 -11
  1068. package/examples/.code-auditor.json +0 -2
  1069. package/examples/nextjs.auditrc.json +0 -8
  1070. package/examples/node-api.auditrc.json +0 -7
  1071. package/examples/react.auditrc.json +0 -6
  1072. package/examples/tolerant-solid.auditrc.json +0 -5
  1073. package/package.json +11 -5
  1074. package/plugin/.claude-plugin/manifest.json +16 -0
  1075. package/plugin/.claude-plugin/plugin.json +1 -1
  1076. package/plugin/hooks/hooks.json +6 -2
  1077. package/plugin/scripts/hook-audit.sh +41 -14
  1078. package/plugin/scripts/hook-common.sh +50 -5
  1079. package/plugin/scripts/hook-drift-check.sh +72 -0
  1080. package/plugin/scripts/hook-self-audit.sh +17 -12
  1081. package/plugin/skills/code-auditor/SKILL.md +1 -1
  1082. package/server.json +2 -2
@@ -0,0 +1,1817 @@
1
+ /**
2
+ * SQL as a parsed format — the AST seam.
3
+ *
4
+ * Spec 70 R1: a SQL grammar joins the shipped grammars, SQL strings reaching a
5
+ * data-access call site are parsed into an AST like any other format, and the
6
+ * dialect is a *closed decision* — one named grammar, not a fallback ladder.
7
+ * Here that grammar is `node-sql-parser`; the dialect is a required parameter
8
+ * (the corpus's named {@link Dialect} discriminant, from the discovery-query
9
+ * registry), never a hardcoded constant — guessing `sqlite` on a Postgres repo
10
+ * would be a silent wrong answer. It is pure JavaScript (no WASM, no two-phase
11
+ * init), so it loads synchronously through the ordinary dependency path rather
12
+ * than the `initParsers()` WASM loader.
13
+ *
14
+ * The seam is {@link parseSql}: `{ ok: true, ast }` or `{ ok: false, reason }`.
15
+ * Every rule that reads SQL facts gets an AST or it gets nothing. There is no
16
+ * regex path to fall back to — a string the grammar cannot parse is a parse
17
+ * failure, and the caller turns that into `cannot-fire` with the reason. The
18
+ * twelve regex sites in the security family convert by consuming the helpers
19
+ * below (statement kind, relations, where facts, tenant predicate, insert
20
+ * columns, DDL facts), each of which walks the AST rather than scanning text.
21
+ *
22
+ * `node-sql-parser` is a CommonJS module; the default import is required in ESM.
23
+ */
24
+ import pkg from 'node-sql-parser';
25
+ const { Parser } = pkg;
26
+ const parser = new Parser();
27
+ /**
28
+ * The named default dialect a caller parses under when detection names none.
29
+ *
30
+ * Spec 70 R2: parsing a SQL literal does not require *proving* the site's
31
+ * dialect first — one grammar is named, with its dialect stated, and the parse
32
+ * is attempted under it. When {@link detectDialect} returns null (a repo names
33
+ * no driver, or names several), the caller still attempts the parse under this
34
+ * default rather than abstaining before it has looked. The default is sqlite:
35
+ * node-sql-parser's sqlite grammar is the most permissive, and the rest of this
36
+ * module already standardizes on "the sqlite grammar" as the baseline (see the
37
+ * `truncateConflictClause` / `ON CONFLICT` notes below).
38
+ *
39
+ * The honesty rule is not weakened, it moves: a literal that *parses* under the
40
+ * default yields facts; a literal that *fails* is reported `cannot-fire` with a
41
+ * reason naming **both** the parse failure and the fact that the dialect is
42
+ * undetermined (so the failure may be dialect-specific syntax), never a silent
43
+ * empty fact set.
44
+ */
45
+ export const DEFAULT_SQL_DIALECT = 'sqlite';
46
+ /** Map a node-sql-parser statement `type` to the closed {@link SqlStatementKind}. */
47
+ function statementKind(type) {
48
+ switch (type) {
49
+ case 'select': return 'select';
50
+ case 'insert': return 'insert';
51
+ case 'replace': return 'replace';
52
+ case 'update': return 'update';
53
+ case 'delete': return 'delete';
54
+ case 'create': return 'create';
55
+ case 'alter': return 'alter';
56
+ case 'drop': return 'drop';
57
+ case 'use': return 'use';
58
+ default: return 'other';
59
+ }
60
+ }
61
+ /** DDL statement kinds — schema definition (CREATE/ALTER/DROP/USE), not a
62
+ * row-level data-access query. Schema is extracted separately by the `.sql`
63
+ * visitor and Durable Object DDL (`pipelineAdapters.ts`); a data-access call is
64
+ * a DML query or an ORM operation, and a DDL literal must not surface as one. */
65
+ export function isDdlStatementKind(kind) {
66
+ return kind === 'create' || kind === 'alter' || kind === 'drop' || kind === 'use';
67
+ }
68
+ /**
69
+ * The standalone transaction-control statements the sqlite grammar does not
70
+ * accept, recognized — not parsed — as SQL. A `BEGIN`/`COMMIT`/`ROLLBACK` is
71
+ * unambiguous SQL with no data-access facts (no relations, no WHERE, not a
72
+ * write), so it proves its receiver is a handle and contributes nothing to any
73
+ * table/filter fact. Recognized via a closed set, case-insensitively, with an
74
+ * optional trailing `;`.
75
+ */
76
+ const TRANSACTION_CONTROL = new Set([
77
+ 'begin',
78
+ 'begin transaction',
79
+ 'begin deferred',
80
+ 'begin immediate',
81
+ 'begin exclusive',
82
+ 'commit',
83
+ 'commit transaction',
84
+ 'end',
85
+ 'end transaction',
86
+ 'rollback',
87
+ 'rollback transaction',
88
+ ]);
89
+ /** A synthetic statement for recognized transaction control. The AST walkers
90
+ * treat an unknown statement type as "no relations / no where / not a write",
91
+ * which is exactly the facts a BEGIN/COMMIT/ROLLBACK has. */
92
+ const TRANSACTION_MARKER = { type: 'transaction' };
93
+ /** True when `trimmed` is a standalone transaction-control statement. */
94
+ function isStandaloneTransactionControl(trimmed) {
95
+ const t = trimmed.replace(/;\s*$/, '').trim().toLowerCase();
96
+ return TRANSACTION_CONTROL.has(t);
97
+ }
98
+ /**
99
+ * Migration-file statements that name no *stored* table — recognized, not parsed,
100
+ * as SQL. A `PRAGMA` / `DROP INDEX` / `DROP VIEW` / `DROP TRIGGER` / `CREATE VIEW`
101
+ * / `CREATE TRIGGER` declares no table the rules track (an index/view/trigger is
102
+ * not a stored table, and a PRAGMA is a connection setting), so a migration's
103
+ * `PRAGMA foreign_keys=OFF` contributes nothing to any table/filter fact — the
104
+ * same "recognized, no facts" move as transaction control. Recognition is
105
+ * DDL-path only (in {@link parseSqlProgramTolerant}), never in {@link parseSql}:
106
+ * the per-call-site path must NOT recognize a `PRAGMA`, because
107
+ * `PRAGMA table_info(x)` names `x` and a caller reading "no tables" would take
108
+ * that as clean (an unknown/stale-table miss). Of these, some the sqlite grammar
109
+ * *rejects* (`PRAGMA`, `DROP INDEX`, `DROP TRIGGER`, a compound
110
+ * `CREATE VIEW … UNION ALL`) and recognition avoids a spurious `cannot-fire`; the
111
+ * rest (`DROP VIEW`, a simple `CREATE VIEW`, `CREATE TRIGGER`) actually parse,
112
+ * and are recognized anyway so the DDL table walker never reads a view/trigger
113
+ * name as a stored table. `DROP TABLE` is deliberately absent: it *does* name a
114
+ * stored table the lifecycle rules track, and the grammar parses it. Recognized
115
+ * via a closed keyword set, case-insensitively, with an optional trailing `;`.
116
+ */
117
+ const NO_FACTS_DDL_PREFIXES = ['pragma', 'drop index', 'drop view', 'drop trigger', 'create view', 'create trigger'];
118
+ /** A synthetic statement for recognized no-fact DDL. The AST walkers treat an
119
+ * unknown statement type as "no relations / no where / not a write", which is
120
+ * exactly the facts a PRAGMA / DROP INDEX / DROP VIEW / DROP TRIGGER has. */
121
+ const NO_FACTS_MARKER = { type: 'no-facts' };
122
+ function isNoTableFactsDdl(trimmed) {
123
+ const t = trimmed.replace(/;\s*$/, '').trim().toLowerCase();
124
+ for (const p of NO_FACTS_DDL_PREFIXES) {
125
+ if (!t.startsWith(p))
126
+ continue;
127
+ const after = t[p.length] ?? '';
128
+ if (t.length === p.length || /\s/.test(after))
129
+ return true;
130
+ }
131
+ return false;
132
+ }
133
+ /**
134
+ * Rewrite D1-style numbered positional parameters (`?1`, `?2`, …) to the bare
135
+ * `?` the sqlite grammar accepts. Parameter numbering is an ordering hint, not a
136
+ * fact: it does not affect which tables are read or whether a tenant predicate
137
+ * exists, so the rewrite is lossless for every consumer of this module. A `?`
138
+ * inside a single-quoted string literal is left untouched (that `?` is literal
139
+ * text, not a placeholder); quoted identifiers (`"…"`, `` `…` ``) are also
140
+ * skipped so an identifier containing `?` is not rewritten. A doubled quote
141
+ * (`''` inside a string) stays inside the region.
142
+ * @param sql The SQL text to rewrite.
143
+ * @returns The SQL with D1-style numbered parameters (`?1`) rewritten to bare `?`.
144
+ */
145
+ export function normalizePositionalParams(sql) {
146
+ let out = '';
147
+ let i = 0;
148
+ let quote = null;
149
+ while (i < sql.length) {
150
+ const ch = sql[i];
151
+ if (quote !== null) {
152
+ if (ch === quote) {
153
+ if (sql[i + 1] === quote) {
154
+ out += ch + ch;
155
+ i += 2;
156
+ continue;
157
+ }
158
+ quote = null;
159
+ }
160
+ out += ch;
161
+ i++;
162
+ continue;
163
+ }
164
+ if (ch === '"' || ch === "'" || ch === '`') {
165
+ quote = ch;
166
+ out += ch;
167
+ i++;
168
+ continue;
169
+ }
170
+ if (ch === '?' && /\d/.test(sql[i + 1] ?? '')) {
171
+ let j = i + 1;
172
+ while (j < sql.length && /\d/.test(sql[j]))
173
+ j++;
174
+ out += '?';
175
+ i = j;
176
+ continue;
177
+ }
178
+ out += ch;
179
+ i++;
180
+ }
181
+ return out;
182
+ }
183
+ /**
184
+ * Rewrite a JavaScript template substitution (`${…}`) to the SQL placeholder
185
+ * `?`. A `${…}` in the SQL text is a host-language interpolation — a value,
186
+ * identifier, or table name filled in at query-composition time — which the SQL
187
+ * grammar cannot tokenize (`${` is not a SQL spelling). A value-position
188
+ * substitution (`WHERE id = ${id}`, `SELECT ${cols} …`) is exactly a parameter,
189
+ * so `?` is a lossless rewrite: it preserves every table/filter fact the AST
190
+ * walk reads. A *table-position* substitution (`FROM ${table}`) rewrites to
191
+ * `FROM ?`, which the grammar rejects — the honest `cannot-fire`, because a
192
+ * dynamic table name is genuinely unreadable. A `${…}` inside a quoted string
193
+ * or quoted identifier is literal text the grammar already accepts, so it is
194
+ * left untouched (rewriting it would corrupt a string literal that happens to
195
+ * contain `$`).
196
+ * @param sql The SQL text to rewrite.
197
+ * @returns The SQL with `${…}` template substitutions rewritten to `?` placeholders.
198
+ */
199
+ export function normalizeTemplateSubstitutions(sql) {
200
+ let out = '';
201
+ let i = 0;
202
+ let quote = null;
203
+ while (i < sql.length) {
204
+ const ch = sql[i];
205
+ if (quote !== null) {
206
+ if (ch === quote) {
207
+ if (sql[i + 1] === quote) {
208
+ out += ch + ch;
209
+ i += 2;
210
+ continue;
211
+ }
212
+ quote = null;
213
+ }
214
+ out += ch;
215
+ i++;
216
+ continue;
217
+ }
218
+ if (ch === '"' || ch === "'" || ch === '`') {
219
+ quote = ch;
220
+ out += ch;
221
+ i++;
222
+ continue;
223
+ }
224
+ if (ch === '$' && sql[i + 1] === '{') {
225
+ // Skip to the matching `}` (no nested braces in a substitution).
226
+ let j = i + 2;
227
+ while (j < sql.length && sql[j] !== '}')
228
+ j++;
229
+ out += '?';
230
+ i = j < sql.length ? j + 1 : sql.length;
231
+ continue;
232
+ }
233
+ out += ch;
234
+ i++;
235
+ }
236
+ return out;
237
+ }
238
+ /**
239
+ * Rewrite sqlite's length-qualified `TEXT(N)` type spelling to `VARCHAR(N)`.
240
+ * Drizzle's sqlite dialect emits `text(N)` for string columns, and
241
+ * node-sql-parser's sqlite grammar accepts the length form only for `varchar(N)`
242
+ * — it rejects `text(N)` even though sqlite itself accepts it. SQLite gives
243
+ * `TEXT(N)` and `VARCHAR(N)` the same TEXT affinity, so the rewrite is lossless
244
+ * for every fact an AST walk reads (table/column names, types, declared lengths)
245
+ * and recovers a statement that would otherwise report a spurious `cannot-fire`.
246
+ * Only the `text` keyword *immediately followed by `(`* is rewritten — a bare
247
+ * `text` (no length), a longer identifier (`textual`), and any occurrence inside
248
+ * a string literal or quoted identifier are left intact.
249
+ * @param sql The SQL text to rewrite.
250
+ * @returns The SQL with length-qualified `text(N)` rewritten to `varchar(N)`.
251
+ */
252
+ export function normalizeSqliteTextLength(sql) {
253
+ let out = '';
254
+ let i = 0;
255
+ let quote = null;
256
+ while (i < sql.length) {
257
+ const ch = sql[i];
258
+ if (quote !== null) {
259
+ if (ch === quote) {
260
+ if (sql[i + 1] === quote) {
261
+ out += ch + ch;
262
+ i += 2;
263
+ continue;
264
+ }
265
+ quote = null;
266
+ }
267
+ out += ch;
268
+ i++;
269
+ continue;
270
+ }
271
+ if (ch === '"' || ch === "'" || ch === '`') {
272
+ quote = ch;
273
+ out += ch;
274
+ i++;
275
+ continue;
276
+ }
277
+ // `text` as a whole word, followed by optional whitespace then `(`.
278
+ if (ch === 't' || ch === 'T') {
279
+ const word = sql.slice(i, i + 4);
280
+ if (word.toLowerCase() === 'text') {
281
+ const prev = i === 0 ? '' : sql[i - 1];
282
+ const next = sql[i + 4] ?? '';
283
+ const wordStart = i === 0 || !/[a-zA-Z0-9_$]/.test(prev);
284
+ const wordEnd = !/[a-zA-Z0-9_$]/.test(next);
285
+ let j = i + 4;
286
+ while (j < sql.length && /\s/.test(sql[j]))
287
+ j++;
288
+ if (wordStart && wordEnd && sql[j] === '(') {
289
+ out += 'varchar';
290
+ i += 4;
291
+ continue;
292
+ }
293
+ }
294
+ }
295
+ out += ch;
296
+ i++;
297
+ }
298
+ return out;
299
+ }
300
+ /**
301
+ * Rewrite a string literal whose entire content is one backslash (`'\'`) to the
302
+ * doubled spelling (`'\\'`). SQLite spells "the escape character is a single
303
+ * backslash" as `'\'`, but node-sql-parser's lexer reads the bare `'\'` as an
304
+ * unterminated escaped-quote (`\'` with no closing quote) and rejects the whole
305
+ * statement — so a `LIKE … ESCAPE '\'` clause (recall-protocol's FTS-escape
306
+ * spelling) fails to parse. Doubling the backslash is the same value spelled the
307
+ * way the grammar accepts (`'\\'` is one literal backslash), so the rewrite is
308
+ * lossless: the escape character is still one backslash, and no fact a rule
309
+ * reads (relations, filters, statement kind) changes. Only the exact three-char
310
+ * sequence `'\'` is rewritten, and only where it opens a string literal (never
311
+ * inside a quoted identifier or a longer string), so a `'\''` (backslash then
312
+ * escaped quote) or a double-quoted identifier containing `'\'` is left intact.
313
+ * @param sql The SQL text to rewrite.
314
+ * @returns The SQL with a lone-backslash string literal rewritten to `'\\'`.
315
+ */
316
+ export function normalizeEscapeClause(sql) {
317
+ let out = '';
318
+ let i = 0;
319
+ let quote = null;
320
+ while (i < sql.length) {
321
+ const ch = sql[i];
322
+ if (quote !== null) {
323
+ if (ch === quote) {
324
+ if (sql[i + 1] === quote) {
325
+ out += ch + ch;
326
+ i += 2;
327
+ continue;
328
+ }
329
+ quote = null;
330
+ }
331
+ out += ch;
332
+ i++;
333
+ continue;
334
+ }
335
+ if (ch === '"' || ch === "'" || ch === '`') {
336
+ if (ch === "'" && sql[i + 1] === '\\' && sql[i + 2] === "'" && sql[i + 3] !== "'") {
337
+ out += "'\\\\'";
338
+ i += 3;
339
+ continue;
340
+ }
341
+ quote = ch;
342
+ out += ch;
343
+ i++;
344
+ continue;
345
+ }
346
+ out += ch;
347
+ i++;
348
+ }
349
+ return out;
350
+ }
351
+ /**
352
+ * Rewrite a bare `?` placeholder in a `LIMIT`/`OFFSET` clause to a literal
353
+ * (`LIMIT 1` / `OFFSET 0`). node-sql-parser's sqlite grammar accepts `LIMIT 5`
354
+ * but rejects `LIMIT ?` (a bound-parameter limit) even though sqlite itself
355
+ * accepts it — so a parameterized `SELECT … LIMIT ? OFFSET ?` (recall-protocol's
356
+ * paging spelling) fails to parse. The fact a rule reads from a LIMIT/OFFSET
357
+ * clause is *presence*, not the value (see `whereFacts`), so substituting a
358
+ * concrete literal is lossless: `LIMIT ?` still reports "has a limit". The
359
+ * rewrite fires only on a bare `?` immediately after the keyword (whitespace
360
+ * optional), and skips string literals and quoted identifiers.
361
+ * @param sql The SQL text to rewrite.
362
+ * @returns The SQL with `LIMIT ?` → `LIMIT 1` and `OFFSET ?` → `OFFSET 0`.
363
+ */
364
+ export function normalizeLimitOffsetPlaceholders(sql) {
365
+ let out = '';
366
+ let i = 0;
367
+ let quote = null;
368
+ while (i < sql.length) {
369
+ const ch = sql[i];
370
+ if (quote !== null) {
371
+ if (ch === quote) {
372
+ if (sql[i + 1] === quote) {
373
+ out += ch + ch;
374
+ i += 2;
375
+ continue;
376
+ }
377
+ quote = null;
378
+ }
379
+ out += ch;
380
+ i++;
381
+ continue;
382
+ }
383
+ if (ch === '"' || ch === "'" || ch === '`') {
384
+ quote = ch;
385
+ out += ch;
386
+ i++;
387
+ continue;
388
+ }
389
+ let keyword = null;
390
+ let value = null;
391
+ const lower6 = sql.slice(i, i + 6).toLowerCase();
392
+ if (lower6.startsWith('limit')) {
393
+ keyword = sql.slice(i, i + 5);
394
+ value = '1';
395
+ }
396
+ else if (lower6.startsWith('offset')) {
397
+ keyword = sql.slice(i, i + 6);
398
+ value = '0';
399
+ }
400
+ if (keyword !== null && value !== null) {
401
+ const prev = i === 0 ? '' : sql[i - 1];
402
+ const after = sql[i + keyword.length] ?? '';
403
+ if (!/[a-zA-Z0-9_$]/.test(prev) && !/[a-zA-Z0-9_$]/.test(after)) {
404
+ let j = i + keyword.length;
405
+ while (j < sql.length && /\s/.test(sql[j]))
406
+ j++;
407
+ if (sql[j] === '?') {
408
+ out += keyword + ' ' + value;
409
+ i = j + 1;
410
+ continue;
411
+ }
412
+ }
413
+ }
414
+ out += ch;
415
+ i++;
416
+ }
417
+ return out;
418
+ }
419
+ /**
420
+ * Rewrite a `CREATE VIRTUAL TABLE name USING fts5(cols…)` declaration to the
421
+ * `CREATE TABLE name (cols…)` the sqlite grammar accepts. node-sql-parser's
422
+ * sqlite grammar has no `CREATE VIRTUAL TABLE`, so a full-text-search table
423
+ * (recall-protocol's `strategies_fts`, declared `USING fts5(...)`) fails to parse
424
+ * and blanks the table — even though a virtual table is a first-class queryable
425
+ * relation the lifecycle rules track exactly like a stored table. The facts a
426
+ * rule reads from the declaration are the table name and its column names; the
427
+ * FTS5 module wrapper (`USING fts5`, a column's `UNINDEXED`, the trailing
428
+ * `tokenize = '…'` option) is module configuration, not a table fact. So the
429
+ * rewrite drops the module syntax and keeps the columns, recovering the same
430
+ * table/column facts a `CREATE TABLE` would carry. Only a `CREATE VIRTUAL TABLE`
431
+ * (word-boundary matched, case-insensitive) whose module argument list parses to
432
+ * at least one bare column is rewritten; anything else — a module option list
433
+ * with no columns, an unexpected shape — is left untouched and reports an honest
434
+ * parse failure rather than a fabricated table.
435
+ * @param sql The SQL text to rewrite.
436
+ * @returns The SQL with `CREATE VIRTUAL TABLE … USING <module>(cols)` rewritten to `CREATE TABLE … (cols)`.
437
+ */
438
+ export function normalizeVirtualTable(sql) {
439
+ let out = '';
440
+ let i = 0;
441
+ let quote = null;
442
+ const HEADER = 'create virtual table';
443
+ while (i < sql.length) {
444
+ const ch = sql[i];
445
+ if (quote !== null) {
446
+ if (ch === quote) {
447
+ if (sql[i + 1] === quote) {
448
+ out += ch + ch;
449
+ i += 2;
450
+ continue;
451
+ }
452
+ quote = null;
453
+ }
454
+ out += ch;
455
+ i++;
456
+ continue;
457
+ }
458
+ if (ch === '"' || ch === "'" || ch === '`') {
459
+ quote = ch;
460
+ out += ch;
461
+ i++;
462
+ continue;
463
+ }
464
+ const beforeOk = i === 0 || !/[a-zA-Z0-9_$]/.test(sql[i - 1]);
465
+ const afterHeader = sql[i + HEADER.length] ?? '';
466
+ const afterOk = !/[a-zA-Z0-9_$]/.test(afterHeader);
467
+ if (beforeOk && afterOk && sql.slice(i, i + HEADER.length).toLowerCase() === HEADER) {
468
+ // `CREATE VIRTUAL TABLE <name> USING <module>( <args> )`
469
+ let j = i + HEADER.length;
470
+ while (j < sql.length && /\s/.test(sql[j]))
471
+ j++;
472
+ const nameStart = j;
473
+ while (j < sql.length && !/\s/.test(sql[j]) && sql[j] !== '(')
474
+ j++;
475
+ const name = sql.slice(nameStart, j);
476
+ while (j < sql.length && /\s/.test(sql[j]))
477
+ j++;
478
+ if (sql.slice(j, j + 5).toLowerCase() === 'using') {
479
+ let k = j + 5;
480
+ while (k < sql.length && /\s/.test(sql[k]))
481
+ k++;
482
+ while (k < sql.length && /[a-zA-Z0-9_$]/.test(sql[k]))
483
+ k++; // module name
484
+ while (k < sql.length && /\s/.test(sql[k]))
485
+ k++;
486
+ if (sql[k] === '(') {
487
+ // find the module argument list's matching `)` (nested parens + quotes)
488
+ let m = k + 1;
489
+ let depth = 1;
490
+ let q = null;
491
+ while (m < sql.length && depth > 0) {
492
+ const c = sql[m];
493
+ if (q !== null) {
494
+ if (c === q) {
495
+ if (sql[m + 1] === q) {
496
+ m += 2;
497
+ continue;
498
+ }
499
+ q = null;
500
+ }
501
+ m++;
502
+ continue;
503
+ }
504
+ if (c === '"' || c === "'" || c === '`') {
505
+ q = c;
506
+ m++;
507
+ continue;
508
+ }
509
+ if (c === '(')
510
+ depth++;
511
+ else if (c === ')')
512
+ depth--;
513
+ m++;
514
+ }
515
+ const cols = extractFtsColumnNames(sql.slice(k + 1, m - 1));
516
+ if (cols.length > 0 && name.length > 0) {
517
+ out += `CREATE TABLE ${name} (${cols.join(', ')})`;
518
+ i = m;
519
+ continue;
520
+ }
521
+ }
522
+ }
523
+ out += ch;
524
+ i++;
525
+ continue;
526
+ }
527
+ out += ch;
528
+ i++;
529
+ }
530
+ return out;
531
+ }
532
+ /** Split an FTS5 module argument list into its bare column names, dropping
533
+ * `UNINDEXED`/`NOT INDEXED` modifiers and `name = '…'` option entries. */
534
+ function extractFtsColumnNames(args) {
535
+ const parts = [];
536
+ let i = 0;
537
+ let start = 0;
538
+ let depth = 0;
539
+ let quote = null;
540
+ while (i < args.length) {
541
+ const ch = args[i];
542
+ if (quote !== null) {
543
+ if (ch === quote) {
544
+ if (args[i + 1] === quote) {
545
+ i += 2;
546
+ continue;
547
+ }
548
+ quote = null;
549
+ }
550
+ i++;
551
+ continue;
552
+ }
553
+ if (ch === '"' || ch === "'" || ch === '`') {
554
+ quote = ch;
555
+ i++;
556
+ continue;
557
+ }
558
+ if (ch === '(')
559
+ depth++;
560
+ else if (ch === ')')
561
+ depth--;
562
+ else if (ch === ',' && depth === 0) {
563
+ parts.push(args.slice(start, i).trim());
564
+ start = i + 1;
565
+ }
566
+ i++;
567
+ }
568
+ parts.push(args.slice(start).trim());
569
+ const cols = [];
570
+ for (const part of parts) {
571
+ if (part === '')
572
+ continue;
573
+ if (part.includes('='))
574
+ continue; // `tokenize = '…'`, `prefix = '…'`, `content = …`
575
+ const name = part.split(/\s+/)[0];
576
+ if (name)
577
+ cols.push(name);
578
+ }
579
+ return cols;
580
+ }
581
+ /**
582
+ * Apply the declared input normalizations for a dialect: D1 numbered parameters
583
+ * `?n` → `?`, template substitutions `${…}` → `?`, `LIMIT ?`/`OFFSET ?` → a
584
+ * concrete literal, `'\'` → `'\\'`, `CREATE VIRTUAL TABLE … USING fts5(…)` →
585
+ * `CREATE TABLE …`, and — sqlite only, since it is a sqlite-specific spelling —
586
+ * length-qualified `text(N)` → `varchar(N)`.
587
+ */
588
+ function applyDeclaredNormalizations(trimmed, dialect) {
589
+ // Strip comments first. Every normalizer below tracks quoted strings to avoid
590
+ // rewriting inside them, but none of them models `--` / `/* … */` comments. An
591
+ // apostrophe in a comment — `don't` in a migration's header block — opens a
592
+ // quote that swallows the rest of the file and silently disables every rewrite
593
+ // after it (`text(N)` → `varchar(N)` and the rest). Comments are semantically
594
+ // inert, so dropping them before the quote-tracking rewrites is lossless and
595
+ // keeps the normalizers' quote state honest.
596
+ const uncommented = stripComments(trimmed);
597
+ const positional = normalizePositionalParams(uncommented);
598
+ const templated = normalizeTemplateSubstitutions(positional);
599
+ const limited = normalizeLimitOffsetPlaceholders(templated);
600
+ const escaped = normalizeEscapeClause(limited);
601
+ const tabled = normalizeVirtualTable(escaped);
602
+ return dialect === 'sqlite' ? normalizeSqliteTextLength(tabled) : tabled;
603
+ }
604
+ /**
605
+ * Split a (possibly multi-statement) SQL string on top-level `;`. Semicolons
606
+ * inside single/double-quoted strings and backtick identifiers are not statement
607
+ * boundaries, and empty fragments (a trailing `;`) are dropped. A single string
608
+ * literal carrying several DDL statements (`DROP TABLE a; DROP TABLE b;`) parses
609
+ * as its statements instead of failing "expected a single statement".
610
+ *
611
+ * A `CREATE TRIGGER … BEGIN … END` body carries `;` between its own statements
612
+ * that are not statement boundaries, so the trigger's `BEGIN … END` block is
613
+ * tracked and its internal `;` kept inside the statement — otherwise a trigger
614
+ * would be mid-body-split into a dangling header and a bare `END`. The tracking
615
+ * is scoped to a statement whose leading text is `CREATE TRIGGER`, so a
616
+ * transaction's `BEGIN;` or a stray `CASE`/`END` in ordinary SQL is split exactly
617
+ * as before. A `CASE … END` inside the body is tracked so its `END` is not
618
+ * mistaken for the trigger's closing `END`.
619
+ * @param sql The SQL text to split.
620
+ * @returns The top-level statements, in order, with empty fragments dropped.
621
+ */
622
+ export function splitSqlStatements(sql) {
623
+ const parts = [];
624
+ let current = '';
625
+ let i = 0;
626
+ let quote = null;
627
+ let beginDepth = 0;
628
+ let caseDepth = 0;
629
+ const wordBoundary = (c) => c === undefined || !/[a-zA-Z0-9_$]/.test(c);
630
+ while (i < sql.length) {
631
+ const ch = sql[i];
632
+ if (quote !== null) {
633
+ if (ch === quote) {
634
+ if (sql[i + 1] === quote) {
635
+ current += ch + ch;
636
+ i += 2;
637
+ continue;
638
+ }
639
+ quote = null;
640
+ }
641
+ current += ch;
642
+ i++;
643
+ continue;
644
+ }
645
+ // Skip comments before quote tracking: an apostrophe inside `-- don't` must
646
+ // not open a string literal and swallow every later `;` in the file, and a
647
+ // `;` inside a comment is prose, not a statement boundary. Mirrors
648
+ // `truncateConflictClause`'s comment handling. The comment text is dropped
649
+ // (semantically inert — the parser never needs it to extract ops).
650
+ if (ch === '-' && sql[i + 1] === '-') {
651
+ while (i < sql.length && sql[i] !== '\n')
652
+ i++;
653
+ continue;
654
+ }
655
+ if (ch === '/' && sql[i + 1] === '*') {
656
+ i += 2;
657
+ while (i < sql.length && !(sql[i] === '*' && sql[i + 1] === '/'))
658
+ i++;
659
+ i += 2;
660
+ continue;
661
+ }
662
+ if (ch === '"' || ch === "'" || ch === '`') {
663
+ quote = ch;
664
+ current += ch;
665
+ i++;
666
+ continue;
667
+ }
668
+ if (/[a-zA-Z]/.test(ch)) {
669
+ let j = i;
670
+ while (j < sql.length && /[a-zA-Z0-9_$]/.test(sql[j]))
671
+ j++;
672
+ const word = sql.slice(i, j).toLowerCase();
673
+ const prev = i === 0 ? undefined : sql[i - 1];
674
+ const after = sql[j];
675
+ if (wordBoundary(prev) && wordBoundary(after)) {
676
+ if (word === 'begin') {
677
+ if (current.trimStart().toLowerCase().startsWith('create trigger'))
678
+ beginDepth++;
679
+ }
680
+ else if (word === 'case') {
681
+ if (beginDepth > 0)
682
+ caseDepth++;
683
+ }
684
+ else if (word === 'end') {
685
+ if (caseDepth > 0)
686
+ caseDepth--;
687
+ else if (beginDepth > 0)
688
+ beginDepth--;
689
+ }
690
+ }
691
+ current += sql.slice(i, j);
692
+ i = j;
693
+ continue;
694
+ }
695
+ if (ch === ';') {
696
+ if (beginDepth === 0 && caseDepth === 0) {
697
+ const part = current.trim();
698
+ if (part.length > 0)
699
+ parts.push(part);
700
+ current = '';
701
+ }
702
+ else {
703
+ current += ch;
704
+ }
705
+ i++;
706
+ continue;
707
+ }
708
+ current += ch;
709
+ i++;
710
+ }
711
+ const tail = current.trim();
712
+ if (tail.length > 0)
713
+ parts.push(tail);
714
+ return parts;
715
+ }
716
+ /**
717
+ * Truncate a SQL string at its top-level `ON CONFLICT` clause, returning the
718
+ * prefix and a flag recording that a conflict clause was present but not parsed.
719
+ *
720
+ * Spec 70 (ON CONFLICT disposition): node-sql-parser's `sqlite` grammar has no
721
+ * `ON CONFLICT`, so a D1 `INSERT … ON CONFLICT (…) DO UPDATE` upsert is a parse
722
+ * failure — and the failure took the whole statement down, blanking the target
723
+ * table / write-status facts the prefix already answers. Those facts (target
724
+ * table, write status, predicate presence) are all answered by the
725
+ * `INSERT INTO x (cols) VALUES (…)` prefix, so the clause is cut at a *top-level*
726
+ * `ON CONFLICT` (not inside a string literal, comment, or parenthesized
727
+ * subexpression) and the prefix is parsed. The flag keeps "an upsert is present"
728
+ * distinct from "the write is a plain INSERT" — a future rule reading the update
729
+ * action sees "present but unread" rather than absent. This is a truncation, not
730
+ * a normalization: the clause's update action is recorded as dropped, never
731
+ * silently re-written into an equivalent spelling.
732
+ * @param sql The SQL text to scan.
733
+ * @returns The prefix before a top-level `ON CONFLICT` clause, plus a flag recording that a clause was truncated.
734
+ */
735
+ export function truncateConflictClause(sql) {
736
+ let i = 0;
737
+ let quote = null;
738
+ let depth = 0;
739
+ while (i < sql.length) {
740
+ const ch = sql[i];
741
+ if (quote !== null) {
742
+ if (ch === quote) {
743
+ if (sql[i + 1] === quote) {
744
+ i += 2;
745
+ continue;
746
+ }
747
+ quote = null;
748
+ }
749
+ i++;
750
+ continue;
751
+ }
752
+ if (ch === '"' || ch === "'" || ch === '`') {
753
+ quote = ch;
754
+ i++;
755
+ continue;
756
+ }
757
+ if (ch === '-' && sql[i + 1] === '-') {
758
+ while (i < sql.length && sql[i] !== '\n')
759
+ i++;
760
+ continue;
761
+ }
762
+ if (ch === '/' && sql[i + 1] === '*') {
763
+ i += 2;
764
+ while (i < sql.length && !(sql[i] === '*' && sql[i + 1] === '/'))
765
+ i++;
766
+ i += 2;
767
+ continue;
768
+ }
769
+ if (ch === '(') {
770
+ depth++;
771
+ i++;
772
+ continue;
773
+ }
774
+ if (ch === ')') {
775
+ depth--;
776
+ i++;
777
+ continue;
778
+ }
779
+ if (depth === 0 && (ch === 'o' || ch === 'O')) {
780
+ const before = i > 0 ? sql[i - 1] : '';
781
+ const beforeOk = !/[a-z0-9_$]/i.test(before);
782
+ if (beforeOk && sql.slice(i, i + 11).toLowerCase() === 'on conflict') {
783
+ const after = sql[i + 11];
784
+ const afterOk = after === undefined || !/[a-z0-9_]/i.test(after);
785
+ if (afterOk) {
786
+ return { text: sql.slice(0, i).trim(), truncated: true };
787
+ }
788
+ }
789
+ }
790
+ i++;
791
+ }
792
+ return { text: sql, truncated: false };
793
+ }
794
+ /** Parse one already-normalized statement string into a single-statement result. */
795
+ function parseSingleStatement(text, dialect) {
796
+ const { text: toParse, truncated } = truncateConflictClause(text);
797
+ let astified;
798
+ try {
799
+ astified = parser.astify(toParse, { database: dialect });
800
+ }
801
+ catch (error) {
802
+ return { ok: false, reason: error instanceof Error ? error.message : String(error) };
803
+ }
804
+ const conflictClauseTruncated = truncated || undefined;
805
+ if (Array.isArray(astified)) {
806
+ if (astified.length === 0) {
807
+ // The grammar consumed the input but produced no statement (e.g. a
808
+ // comment-only fragment) — an honest cannot-fire, not a crash.
809
+ return { ok: false, reason: 'SQL did not produce a statement' };
810
+ }
811
+ if (astified.length === 1) {
812
+ return { ok: true, ast: astified[0], kind: statementKind(astified[0].type), conflictClauseTruncated };
813
+ }
814
+ // A `;` the splitter missed — parse all of them and report the program.
815
+ return { ok: true, ast: astified[0], kind: statementKind(astified[0].type), statements: astified, conflictClauseTruncated };
816
+ }
817
+ if (astified === null || typeof astified !== 'object') {
818
+ return { ok: false, reason: 'SQL did not produce a statement' };
819
+ }
820
+ return { ok: true, ast: astified, kind: statementKind(astified.type), conflictClauseTruncated };
821
+ }
822
+ /**
823
+ * Parse a SQL string — one statement, or several separated by `;`. Returns
824
+ * `{ ok: false, reason }` on an empty string, a parse error (after the declared
825
+ * normalization below), or a program where any statement fails to parse. A
826
+ * multi-statement string that fully parses is `ok` with `statements` holding
827
+ * every AST.
828
+ *
829
+ * Normalization, applied before the grammar: (a) D1 numbered parameters `?n` →
830
+ * `?`; (b) a multi-statement string is split on top-level `;` and each statement
831
+ * parsed individually; (c) a standalone transaction-control statement is
832
+ * recognized as SQL with no facts. Anything still failing after those is a
833
+ * genuine `cannot-fire` (e.g. `ON CONFLICT … DO UPDATE`, a Postgres `::` cast).
834
+ *
835
+ * @param text The SQL text to parse.
836
+ * @param dialect The dialect to parse under — the corpus's named dialect, or
837
+ * {@link DEFAULT_SQL_DIALECT} when detection named none. The caller is still
838
+ * responsible for the honesty: when it supplied the default because the dialect
839
+ * is undetermined, a parse failure must be reported naming both the failure and
840
+ * the undetermined dialect.
841
+ * @returns `{ ok: true, ast, kind }` on success (with `statements` for a multi-statement string), or `{ ok: false, reason }` on an empty string, parse error, or unparseable program.
842
+ */
843
+ export function parseSql(text, dialect) {
844
+ const trimmed = text.trim();
845
+ if (trimmed.length === 0) {
846
+ return { ok: false, reason: 'empty SQL string' };
847
+ }
848
+ if (isStandaloneTransactionControl(trimmed)) {
849
+ return { ok: true, ast: TRANSACTION_MARKER, kind: 'other' };
850
+ }
851
+ const normalized = applyDeclaredNormalizations(trimmed, dialect);
852
+ const statements = splitSqlStatements(normalized);
853
+ if (statements.length === 0) {
854
+ // Only top-level `;` (or a substitution that normalized to nothing) — no
855
+ // statement text survives to parse.
856
+ return { ok: false, reason: 'SQL contained no statements' };
857
+ }
858
+ if (statements.length > 1) {
859
+ const asts = [];
860
+ let anyTruncated = false;
861
+ for (const statement of statements) {
862
+ const result = parseSingleStatement(statement, dialect);
863
+ if (!result.ok) {
864
+ return { ok: false, reason: `statement ${asts.length + 1} failed: ${result.reason}` };
865
+ }
866
+ asts.push(result.ast);
867
+ if (result.conflictClauseTruncated)
868
+ anyTruncated = true;
869
+ }
870
+ return { ok: true, ast: asts[0], kind: statementKind(asts[0].type), statements: asts, conflictClauseTruncated: anyTruncated || undefined };
871
+ }
872
+ return parseSingleStatement(statements[0], dialect);
873
+ }
874
+ /**
875
+ * A template placeholder (`{{VERSION}}`, `{{.MigrationName}}`). A migration that
876
+ * carries one is not SQL until it is rendered at deploy time, so it is classified
877
+ * "not SQL", not "unparseable SQL" — a distinct failure reason a caller can
878
+ * bucket separately from dialect gaps.
879
+ */
880
+ const TEMPLATE_PLACEHOLDER = /\{\{[^}]*\}\}/;
881
+ /**
882
+ * Remove `--` line comments and `/* … *\/` block comments (respecting quoted
883
+ * strings), so a `{{…}}` that appears only in a comment — prose naming a
884
+ * placeholder — is not mistaken for a template marker. A template placeholder
885
+ * that changes the SQL is inline in the statement text; one in a comment does not
886
+ * affect whether the file parses.
887
+ */
888
+ function stripComments(sql) {
889
+ let out = '';
890
+ let i = 0;
891
+ let quote = null;
892
+ while (i < sql.length) {
893
+ const ch = sql[i];
894
+ const next = sql[i + 1];
895
+ if (quote !== null) {
896
+ if (ch === quote) {
897
+ if (next === quote) {
898
+ out += ch + ch;
899
+ i += 2;
900
+ continue;
901
+ }
902
+ quote = null;
903
+ }
904
+ out += ch;
905
+ i++;
906
+ continue;
907
+ }
908
+ if (ch === '"' || ch === "'" || ch === '`') {
909
+ quote = ch;
910
+ out += ch;
911
+ i++;
912
+ continue;
913
+ }
914
+ if (ch === '-' && next === '-') {
915
+ while (i < sql.length && sql[i] !== '\n')
916
+ i++;
917
+ continue;
918
+ }
919
+ if (ch === '/' && next === '*') {
920
+ i += 2;
921
+ while (i < sql.length && !(sql[i] === '*' && sql[i + 1] === '/'))
922
+ i++;
923
+ i += 2;
924
+ continue;
925
+ }
926
+ out += ch;
927
+ i++;
928
+ }
929
+ return out;
930
+ }
931
+ /**
932
+ * Parse a `.sql` file's full text into its statements. Used by the DDL
933
+ * discovery path (which reads whole migration files), not by the per-call-site
934
+ * parse. Empty text is an empty program, not a failure; a templated migration
935
+ * (`{{…}}`) is "not SQL until rendered"; a syntax error anywhere is a failure of
936
+ * the whole file (the same "parse or nothing" contract as {@link parseSql}).
937
+ *
938
+ * D1 numbered parameters (`?n` → `?`) are normalized before parsing, as in
939
+ * {@link parseSql}.
940
+ *
941
+ * @param text The `.sql` file's full text.
942
+ * @param dialect The corpus's named dialect.
943
+ * @returns A parsed program, or a failure reason (templated migration / syntax error).
944
+ */
945
+ export function parseSqlProgram(text, dialect) {
946
+ const trimmed = text.trim();
947
+ if (trimmed.length === 0)
948
+ return { ok: true, statements: [] };
949
+ if (TEMPLATE_PLACEHOLDER.test(stripComments(trimmed))) {
950
+ return { ok: false, reason: 'templated migration (contains {{…}} placeholder — not SQL until rendered)' };
951
+ }
952
+ const normalized = applyDeclaredNormalizations(trimmed, dialect);
953
+ let astified;
954
+ try {
955
+ astified = parser.astify(normalized, { database: dialect });
956
+ }
957
+ catch (error) {
958
+ return { ok: false, reason: error instanceof Error ? error.message : String(error) };
959
+ }
960
+ if (Array.isArray(astified))
961
+ return { ok: true, statements: astified };
962
+ if (astified === null || typeof astified !== 'object')
963
+ return { ok: true, statements: [] };
964
+ return { ok: true, statements: [astified] };
965
+ }
966
+ /**
967
+ * Parse a `.sql` migration file tolerantly — statement by statement. The
968
+ * `parseSqlProgram` all-or-nothing contract is right for a single call-site
969
+ * query string (a query either parses or it is `cannot-fire`), but a migration
970
+ * file is a *sequence* of DDL statements, and one statement the grammar rejects
971
+ * (an `UPDATE … FROM`, a Drizzle `ALTER COLUMN "a" TO "a" <type>`) must not
972
+ * discard the well-formed `CREATE TABLE` beside it. Each statement is split on a
973
+ * top-level `;` and parsed individually; a `PRAGMA` / `DROP INDEX` / `DROP VIEW`
974
+ * / `DROP TRIGGER` / `CREATE VIEW` / `CREATE TRIGGER` is *recognized* as no-fact
975
+ * DDL (not parsed, not a failure), the successes are walked for DDL facts, and
976
+ * the remaining failures are reported so the caller can account for what it did
977
+ * not read. This is the honest successor to the regex scanners, which silently
978
+ * skipped whatever they did not match.
979
+ *
980
+ * @param text The `.sql` file's full text.
981
+ * @param dialect The corpus's named dialect.
982
+ * @param recognizeNoFactsDdl When true (a migration file), a `PRAGMA` /
983
+ * `DROP INDEX` / `DROP VIEW` / `DROP TRIGGER` / `CREATE VIEW` / `CREATE TRIGGER`
984
+ * is recognized as no-fact DDL rather than a parse failure. When false (a code
985
+ * SQL argument — see {@link parseSqlTables}), it is left to the grammar, so a
986
+ * `PRAGMA table_info(x)` surfaces as a parse failure (it names `x`) rather than
987
+ * reading "no tables" as clean.
988
+ * @returns The statements that parsed, the failures with reasons, and the indices of statements whose `ON CONFLICT` clause was truncated.
989
+ */
990
+ export function parseSqlProgramTolerant(text, dialect, recognizeNoFactsDdl = true) {
991
+ const trimmed = text.trim();
992
+ if (trimmed.length === 0)
993
+ return { statements: [], failures: [], truncatedConflictIndices: [] };
994
+ if (TEMPLATE_PLACEHOLDER.test(stripComments(trimmed))) {
995
+ return { statements: [], failures: [{ index: 0, reason: 'templated migration (contains {{…}} placeholder — not SQL until rendered)' }], truncatedConflictIndices: [] };
996
+ }
997
+ const normalized = applyDeclaredNormalizations(trimmed, dialect);
998
+ const parts = splitSqlStatements(normalized);
999
+ const statements = [];
1000
+ const failures = [];
1001
+ const truncatedConflictIndices = [];
1002
+ parts.forEach((part, index) => {
1003
+ if (recognizeNoFactsDdl && isNoTableFactsDdl(part)) {
1004
+ statements.push(NO_FACTS_MARKER);
1005
+ return;
1006
+ }
1007
+ const result = parseSingleStatement(part, dialect);
1008
+ if (result.ok) {
1009
+ if (result.conflictClauseTruncated)
1010
+ truncatedConflictIndices.push(statements.length);
1011
+ // A part can still parse to several statements (a `;` the splitter missed,
1012
+ // e.g. inside a comment-stripped span or a construct the splitter does not
1013
+ // model). `result.ast` is only the first of them — keep the rest, or the
1014
+ // producer silently drops every statement after the first.
1015
+ statements.push(...(result.statements ?? [result.ast]));
1016
+ }
1017
+ else {
1018
+ failures.push({ index, reason: result.reason });
1019
+ }
1020
+ });
1021
+ return { statements, failures, truncatedConflictIndices };
1022
+ }
1023
+ function relationName(entry) {
1024
+ if (entry === null || typeof entry !== 'object')
1025
+ return null;
1026
+ const table = entry.table;
1027
+ if (typeof table !== 'string' || table.length === 0)
1028
+ return null;
1029
+ return table;
1030
+ }
1031
+ function pushRelation(refs, entry, via) {
1032
+ const name = relationName(entry);
1033
+ if (name !== null)
1034
+ refs.push({ name, via });
1035
+ }
1036
+ /**
1037
+ * Collect every relation referenced by a statement — the raw FROM/JOIN/INTO/
1038
+ * target/rename/drop relations, *without* the CTE-alias filter. This is the
1039
+ * AST replacement for site #1's `extractTables` plus its bolted-on alias filter:
1040
+ * the CTE names are subtracted in {@link extractTableNames}, because a CTE name
1041
+ * is a named result set, not a stored table.
1042
+ *
1043
+ * The walk descends into CTE bodies (`WITH x AS (SELECT … FROM orders)`) and
1044
+ * into `FROM (SELECT …)` subqueries, so a real table referenced only inside a
1045
+ * CTE or subquery is still collected — the flat text scan saw those, and an AST
1046
+ * walk that did not would silently under-count.
1047
+ * @param ast The parsed statement (or program) to walk.
1048
+ * @returns Every relation referenced, with the clause it came from, before CTE filtering.
1049
+ */
1050
+ export function collectRelations(ast) {
1051
+ const refs = [];
1052
+ collectRelationsInto(ast, refs);
1053
+ return refs;
1054
+ }
1055
+ function collectRelationsInto(ast, refs) {
1056
+ switch (ast.type) {
1057
+ case 'select': {
1058
+ // CTE bodies reference real tables; walk them before the outer FROM.
1059
+ if (Array.isArray(ast.with)) {
1060
+ for (const cte of ast.with) {
1061
+ const inner = cte?.stmt?.ast;
1062
+ if (inner && typeof inner === 'object')
1063
+ collectRelationsInto(inner, refs);
1064
+ }
1065
+ }
1066
+ const from = ast.from;
1067
+ if (Array.isArray(from))
1068
+ for (const entry of from)
1069
+ collectFromEntry(entry, refs);
1070
+ else
1071
+ collectFromEntry(from, refs);
1072
+ break;
1073
+ }
1074
+ case 'insert':
1075
+ case 'replace':
1076
+ case 'update':
1077
+ case 'alter': {
1078
+ const table = ast.table;
1079
+ if (Array.isArray(table))
1080
+ for (const entry of table)
1081
+ pushRelation(refs, entry, 'target');
1082
+ else
1083
+ pushRelation(refs, table, 'target');
1084
+ break;
1085
+ }
1086
+ case 'delete': {
1087
+ const table = ast.table;
1088
+ if (Array.isArray(table))
1089
+ for (const entry of table)
1090
+ pushRelation(refs, entry, 'target');
1091
+ else
1092
+ pushRelation(refs, table, 'target');
1093
+ if (Array.isArray(ast.from))
1094
+ for (const entry of ast.from)
1095
+ pushRelation(refs, entry, 'from');
1096
+ break;
1097
+ }
1098
+ case 'create': {
1099
+ const table = ast.table;
1100
+ if (Array.isArray(table))
1101
+ for (const entry of table)
1102
+ pushRelation(refs, entry, 'target');
1103
+ else
1104
+ pushRelation(refs, table, 'target');
1105
+ break;
1106
+ }
1107
+ case 'drop': {
1108
+ if (Array.isArray(ast.name))
1109
+ for (const entry of ast.name)
1110
+ pushRelation(refs, entry, 'drop');
1111
+ break;
1112
+ }
1113
+ default:
1114
+ break;
1115
+ }
1116
+ }
1117
+ function collectFromEntry(entry, refs) {
1118
+ if (entry === null || typeof entry !== 'object')
1119
+ return;
1120
+ const e = entry;
1121
+ if (e.type === 'dual')
1122
+ return;
1123
+ // A subquery in FROM (`FROM (SELECT …)`) has no relation name of its own; its
1124
+ // inner SELECT references the real tables.
1125
+ if ('expr' in e && e.expr && typeof e.expr === 'object') {
1126
+ const inner = e.expr.ast;
1127
+ if (inner && typeof inner === 'object')
1128
+ collectRelationsInto(inner, refs);
1129
+ return;
1130
+ }
1131
+ const via = 'join' in e ? 'join' : 'from';
1132
+ pushRelation(refs, entry, via);
1133
+ }
1134
+ /** The names of the CTEs declared by a `WITH` clause, lowercased.
1135
+ * @param ast The parsed statement.
1136
+ * @returns The lowercased CTE names. */
1137
+ export function cteNames(ast) {
1138
+ const names = new Set();
1139
+ if (ast.type !== 'select' || !Array.isArray(ast.with))
1140
+ return names;
1141
+ for (const cte of ast.with) {
1142
+ const value = cte?.name?.value;
1143
+ if (typeof value === 'string' && value.length > 0)
1144
+ names.add(value.toLowerCase());
1145
+ }
1146
+ return names;
1147
+ }
1148
+ /**
1149
+ * The set of table names a statement references, CTE aliases excluded. This is
1150
+ * the AST replacement for `extractTables`: walk FROM/JOIN/INTO/target clauses,
1151
+ * collect relation nodes, then drop the CTE names declared in `WITH`. A CTE
1152
+ * name and a stored table of the same name resolve to the CTE, so a CTE
1153
+ * declaration wins.
1154
+ * @param ast The parsed statement.
1155
+ * @returns The referenced table names, de-duplicated, with CTE aliases excluded.
1156
+ */
1157
+ export function extractTableNames(ast) {
1158
+ const cte = cteNames(ast);
1159
+ const seen = new Set();
1160
+ const names = [];
1161
+ for (const ref of collectRelations(ast)) {
1162
+ const lower = ref.name.toLowerCase();
1163
+ if (cte.has(lower))
1164
+ continue;
1165
+ if (seen.has(lower))
1166
+ continue;
1167
+ seen.add(lower);
1168
+ names.push(ref.name);
1169
+ }
1170
+ return names;
1171
+ }
1172
+ /** node-sql-parser statement `type` values (AST nodes that are statements, not
1173
+ * expressions). A nested statement is any object carrying one of these. */
1174
+ const STATEMENT_TYPES = new Set([
1175
+ 'select', 'insert', 'replace', 'update', 'delete', 'create', 'alter', 'drop', 'use',
1176
+ ]);
1177
+ function isStatementNode(node) {
1178
+ if (node === null || typeof node !== 'object' || Array.isArray(node))
1179
+ return false;
1180
+ const type = node.type;
1181
+ return typeof type === 'string' && STATEMENT_TYPES.has(type);
1182
+ }
1183
+ /** Yield every statement reachable from `node`, excluding `node` itself. */
1184
+ function* nestedStatements(node) {
1185
+ if (node === null || typeof node !== 'object')
1186
+ return;
1187
+ if (Array.isArray(node)) {
1188
+ for (const item of node)
1189
+ yield* nestedStatements(item);
1190
+ return;
1191
+ }
1192
+ for (const value of Object.values(node)) {
1193
+ if (value === null || typeof value !== 'object')
1194
+ continue;
1195
+ if (isStatementNode(value))
1196
+ yield value;
1197
+ else
1198
+ yield* nestedStatements(value);
1199
+ }
1200
+ }
1201
+ /** Read a relation entry's bare table name and schema qualifier. */
1202
+ function relationParts(entry) {
1203
+ if (entry === null || typeof entry !== 'object')
1204
+ return null;
1205
+ const table = entry.table;
1206
+ if (typeof table !== 'string' || table.length === 0)
1207
+ return null;
1208
+ const db = entry.db;
1209
+ return { table, db: typeof db === 'string' && db.length > 0 ? db : null };
1210
+ }
1211
+ function pushTypedRelation(out, entry, type, conflictClauseTruncated = false) {
1212
+ const parts = relationParts(entry);
1213
+ if (parts !== null) {
1214
+ out.push({ table: parts.table, db: parts.db, type, ...(conflictClauseTruncated ? { conflictClauseTruncated: true } : {}) });
1215
+ }
1216
+ }
1217
+ /** Collect CTE names across a statement and its nested statements into `names`
1218
+ * (lowercased). */
1219
+ function collectCteNamesRecursive(node, names) {
1220
+ if (node.type === 'select' && Array.isArray(node.with)) {
1221
+ for (const cte of node.with) {
1222
+ const value = cte?.name?.value;
1223
+ if (typeof value === 'string' && value.length > 0)
1224
+ names.add(value.toLowerCase());
1225
+ }
1226
+ }
1227
+ for (const nested of nestedStatements(node))
1228
+ collectCteNamesRecursive(nested, names);
1229
+ }
1230
+ /** Collect `ALTER TABLE … RENAME TO` targets (transient names, not stored
1231
+ * tables) across a statement and its nested statements. */
1232
+ function collectRenameTargetsRecursive(node, names) {
1233
+ if (node.type === 'alter') {
1234
+ const expr = node.expr;
1235
+ if (Array.isArray(expr)) {
1236
+ for (const op of expr) {
1237
+ if (op && typeof op === 'object' && op.action === 'rename') {
1238
+ const target = op.table;
1239
+ if (typeof target === 'string' && target.length > 0)
1240
+ names.add(target.toLowerCase());
1241
+ }
1242
+ }
1243
+ }
1244
+ }
1245
+ for (const nested of nestedStatements(node))
1246
+ collectRenameTargetsRecursive(nested, names);
1247
+ }
1248
+ /** Emit the relations a statement names directly, with the statement's verb. A
1249
+ * DELETE's `from` duplicates its `table` (node-sql-parser carries both), so only
1250
+ * `table` is emitted as the write; a `CREATE` is emitted only for `CREATE TABLE`
1251
+ * (a `CREATE INDEX`/`CREATE VIEW` names no stored table the rules track). */
1252
+ function emitDirectRelations(ast, out, conflictClauseTruncated) {
1253
+ const table = ast.table;
1254
+ switch (ast.type) {
1255
+ case 'select': {
1256
+ const from = ast.from;
1257
+ if (Array.isArray(from))
1258
+ for (const entry of from)
1259
+ pushTypedRelation(out, entry, 'select', conflictClauseTruncated);
1260
+ else
1261
+ pushTypedRelation(out, from, 'select', conflictClauseTruncated);
1262
+ break;
1263
+ }
1264
+ case 'insert':
1265
+ case 'replace': {
1266
+ if (Array.isArray(table))
1267
+ for (const entry of table)
1268
+ pushTypedRelation(out, entry, 'insert', conflictClauseTruncated);
1269
+ else
1270
+ pushTypedRelation(out, table, 'insert', conflictClauseTruncated);
1271
+ break;
1272
+ }
1273
+ case 'update': {
1274
+ if (Array.isArray(table))
1275
+ for (const entry of table)
1276
+ pushTypedRelation(out, entry, 'update', conflictClauseTruncated);
1277
+ else
1278
+ pushTypedRelation(out, table, 'update', conflictClauseTruncated);
1279
+ break;
1280
+ }
1281
+ case 'delete': {
1282
+ if (Array.isArray(table))
1283
+ for (const entry of table)
1284
+ pushTypedRelation(out, entry, 'delete', conflictClauseTruncated);
1285
+ else
1286
+ pushTypedRelation(out, table, 'delete', conflictClauseTruncated);
1287
+ break;
1288
+ }
1289
+ case 'create': {
1290
+ if (ast.keyword === 'table') {
1291
+ if (Array.isArray(table))
1292
+ for (const entry of table)
1293
+ pushTypedRelation(out, entry, 'create', conflictClauseTruncated);
1294
+ else
1295
+ pushTypedRelation(out, table, 'create', conflictClauseTruncated);
1296
+ }
1297
+ break;
1298
+ }
1299
+ default:
1300
+ break;
1301
+ }
1302
+ }
1303
+ function walkTyped(ast, out, conflictClauseTruncated) {
1304
+ // The truncation flag applies to the *top-level* statement only — a nested
1305
+ // statement (CTE body, subquery) carries no `ON CONFLICT` of its own.
1306
+ emitDirectRelations(ast, out, conflictClauseTruncated);
1307
+ for (const nested of nestedStatements(ast))
1308
+ walkTyped(nested, out, false);
1309
+ }
1310
+ /** The typed relations of a parsed SQL program (one or more statements), with
1311
+ * CTE names and ALTER RENAME targets subtracted and nested statements descended.
1312
+ * `truncatedConflictIndices` names the statements whose text carried a top-level
1313
+ * `ON CONFLICT` clause (truncated before parsing); their relations are flagged
1314
+ * `conflictClauseTruncated` so a write is recorded as "upsert present but
1315
+ * unread" rather than a plain INSERT.
1316
+ * @param statements The parsed statements of the program.
1317
+ * @param truncatedConflictIndices Indices into `statements` whose `ON CONFLICT` clause was truncated.
1318
+ * @returns The typed relations, with CTE names and ALTER RENAME targets subtracted. */
1319
+ export function collectTypedRelations(statements, truncatedConflictIndices = new Set()) {
1320
+ const cte = new Set();
1321
+ const rename = new Set();
1322
+ for (const stmt of statements) {
1323
+ collectCteNamesRecursive(stmt, cte);
1324
+ collectRenameTargetsRecursive(stmt, rename);
1325
+ }
1326
+ const out = [];
1327
+ statements.forEach((stmt, index) => {
1328
+ walkTyped(stmt, out, truncatedConflictIndices.has(index));
1329
+ });
1330
+ return out.filter((r) => !cte.has(r.table.toLowerCase()) && !rename.has(r.table.toLowerCase()));
1331
+ }
1332
+ /** True when an expression is a literal `1` (the `1=1` tautology operand). */
1333
+ function isLiteralOne(node) {
1334
+ if (node === null || typeof node !== 'object')
1335
+ return false;
1336
+ const n = node;
1337
+ return n.type === 'number' && n.value === 1;
1338
+ }
1339
+ /** True when a WHERE expression reduces to "always true" (nothing is limited). */
1340
+ function isTautologyExpr(node) {
1341
+ if (node === null || typeof node !== 'object')
1342
+ return false;
1343
+ const n = node;
1344
+ if (n.type === 'bool')
1345
+ return n.value === true;
1346
+ if (n.type !== 'binary_expr')
1347
+ return false;
1348
+ const op = typeof n.operator === 'string' ? n.operator.toUpperCase() : '';
1349
+ if (op === 'AND')
1350
+ return isTautologyExpr(n.left) && isTautologyExpr(n.right);
1351
+ if (op === '=')
1352
+ return isLiteralOne(n.left) && isLiteralOne(n.right);
1353
+ return false;
1354
+ }
1355
+ /**
1356
+ * Row-limiting facts about a statement — the AST replacement for site #2's
1357
+ * `hasQueryFilter` + `whereClauseIsTautology`. A WHERE carrying a real predicate
1358
+ * (any non-tautology), a HAVING, or a LIMIT limits rows; a bare `WHERE 1=1` does
1359
+ * not.
1360
+ * @param ast The parsed statement.
1361
+ * @returns Row-limiting facts: presence of WHERE/HAVING/LIMIT and whether the WHERE is tautological.
1362
+ */
1363
+ export function whereFacts(ast) {
1364
+ const where = ast.where ?? null;
1365
+ const having = ast.having ?? null;
1366
+ const limit = ast.limit ?? null;
1367
+ return {
1368
+ hasWhere: where !== null && where !== undefined,
1369
+ hasHaving: having !== null && having !== undefined,
1370
+ // node-sql-parser emits `limit: { seperator: '', value: [] }` for a SELECT
1371
+ // with no LIMIT clause — a present-but-empty object, not `null`. Reading the
1372
+ // bare `limit != null` would mark every query "limited" and silence
1373
+ // `unfiltered-query`'s filterless-read/write halves. An empty `value` array
1374
+ // is "no limit"; a non-empty one (or a scalar/array form a dialect may emit)
1375
+ // is a real LIMIT.
1376
+ hasLimit: hasLimitClause(limit),
1377
+ whereIsTautology: where !== null && where !== undefined && isTautologyExpr(where),
1378
+ };
1379
+ }
1380
+ /** True when a parsed statement carries a real LIMIT. node-sql-parser's
1381
+ * `limit` is `{ seperator, value[] }`; `value.length === 0` means the SELECT
1382
+ * has no LIMIT clause, so the object alone does not prove one. */
1383
+ function hasLimitClause(limit) {
1384
+ if (limit === null || limit === undefined)
1385
+ return false;
1386
+ if (Array.isArray(limit))
1387
+ return limit.length > 0;
1388
+ if (typeof limit === 'object') {
1389
+ const value = limit.value;
1390
+ if (Array.isArray(value))
1391
+ return value.length > 0;
1392
+ return value !== null && value !== undefined;
1393
+ }
1394
+ return true;
1395
+ }
1396
+ // ─── Write verbs ─────────────────────────────────────────────────────────────
1397
+ /**
1398
+ * True when a statement is a write (INSERT/DELETE/UPDATE/REPLACE) — the AST
1399
+ * replacement for site #3's `hasWriteVerb`, which had to regex `REPLACE INTO`
1400
+ * as a two-word clause to avoid the `REPLACE()` string function. The statement
1401
+ * kind is that distinction, structurally.
1402
+ */
1403
+ export function isWriteStatement(ast) {
1404
+ return ast.type === 'insert' || ast.type === 'delete' || ast.type === 'update' || ast.type === 'replace';
1405
+ }
1406
+ /**
1407
+ * True when a statement mass-mutates existing rows (`UPDATE … SET`), the AST
1408
+ * replacement for `hasMassWriteVerb`. `DELETE` is deliberately excluded (Spec 68
1409
+ * disposition (a)); `INSERT`/`REPLACE` target specific rows.
1410
+ */
1411
+ export function isMassWriteStatement(ast) {
1412
+ return ast.type === 'update';
1413
+ }
1414
+ /**
1415
+ * True when a statement is an upsert — a `REPLACE`, or an `INSERT` carrying an
1416
+ * `ON CONFLICT` / `ON DUPLICATE KEY` clause — the AST replacement for
1417
+ * `isUpsertForm`. An upsert is keyed by construction, so it never reads as an
1418
+ * "unfiltered" mass write.
1419
+ * @param ast The parsed statement.
1420
+ * @returns True when the statement is an upsert (`REPLACE`, or `INSERT` with an `OR` / `ON DUPLICATE KEY` clause).
1421
+ */
1422
+ export function isUpsertStatement(ast) {
1423
+ if (ast.type === 'replace')
1424
+ return true;
1425
+ if (ast.type !== 'insert')
1426
+ return false;
1427
+ // SQLite upsert spelling is `INSERT OR IGNORE/REPLACE/ABORT/FAIL/ROLLBACK`,
1428
+ // carried on the `or` field; the MySQL `ON DUPLICATE KEY UPDATE` spelling lands
1429
+ // on `on_duplicate_update`. Postgres `ON CONFLICT` does not parse under the
1430
+ // sqlite dialect and is a parse failure, which is the honest result.
1431
+ const raw = ast;
1432
+ const hasOr = raw.or !== null && raw.or !== undefined;
1433
+ const hasOnDuplicate = raw.on_duplicate_update !== null && raw.on_duplicate_update !== undefined;
1434
+ return hasOr || hasOnDuplicate;
1435
+ }
1436
+ // ─── Insert columns ──────────────────────────────────────────────────────────
1437
+ /**
1438
+ * The column list of an INSERT/REPLACE — the AST replacement for site #6's
1439
+ * `rawInsertColumnList`. `null` columns (an `INSERT … VALUES` with no column
1440
+ * list) yields an empty array, which is a distinct, honest result.
1441
+ * @param ast The parsed statement.
1442
+ * @returns The INSERT/REPLACE column list, or an empty array when there is none.
1443
+ */
1444
+ export function insertColumns(ast) {
1445
+ if (ast.type !== 'insert' && ast.type !== 'replace')
1446
+ return [];
1447
+ const columns = ast.columns;
1448
+ if (!Array.isArray(columns))
1449
+ return [];
1450
+ return columns.filter((c) => typeof c === 'string');
1451
+ }
1452
+ // ─── Tenant predicate (org filter) ───────────────────────────────────────────
1453
+ /**
1454
+ * The column references that appear as *predicate operands* in a statement's
1455
+ * WHERE tree — the AST replacement for site #5's four regex families, collapsed
1456
+ * to one walk. A column name in the SELECT list, an INSERT column list, or a
1457
+ * comment is *not* an operand, so a projection can no longer masquerade as a
1458
+ * filter (the Spec 68 Thing 2 `sample_ownership` defect). A quoted identifier on
1459
+ * the left of a comparison (`"org_id" = ?`, the knex/Postgres form) is collected
1460
+ * too, because under a PostgreSQL-style dialect it is a column, not a string
1461
+ * literal.
1462
+ * @param ast The parsed statement.
1463
+ * @returns The lowercased column names that appear as WHERE-tree predicate operands.
1464
+ */
1465
+ export function whereColumnRefs(ast) {
1466
+ const refs = new Set();
1467
+ const where = ast.where;
1468
+ collectWhereColumnRefs(where, refs);
1469
+ return refs;
1470
+ }
1471
+ function collectWhereColumnRefs(node, refs) {
1472
+ if (node === null || typeof node !== 'object')
1473
+ return;
1474
+ if (Array.isArray(node)) {
1475
+ for (const item of node)
1476
+ collectWhereColumnRefs(item, refs);
1477
+ return;
1478
+ }
1479
+ const n = node;
1480
+ if (n.type === 'column_ref') {
1481
+ const column = n.column;
1482
+ if (typeof column === 'string' && column.length > 0)
1483
+ refs.add(column.toLowerCase());
1484
+ return;
1485
+ }
1486
+ // A double-quoted identifier on the left of a comparison is a column under
1487
+ // PostgreSQL/knex; its node-sql-parser shape is `double_quote_string`.
1488
+ if (n.type === 'double_quote_string') {
1489
+ const value = n.value;
1490
+ if (typeof value === 'string' && value.length > 0)
1491
+ refs.add(value.toLowerCase());
1492
+ return;
1493
+ }
1494
+ // Recurse into binary/boolean/logical expressions and their operands.
1495
+ for (const key of ['left', 'right', 'expr', 'args', 'value', 'columns']) {
1496
+ const child = n[key];
1497
+ if (child !== null && typeof child === 'object')
1498
+ collectWhereColumnRefs(child, refs);
1499
+ }
1500
+ }
1501
+ /**
1502
+ * True when a statement's WHERE clause applies an org/tenant-scoping predicate —
1503
+ * a `col op value` shape where `col` is in the tenant column set. This is the
1504
+ * AST form of `hasOrganizationFilter`; the tenant vocabulary is passed in (the
1505
+ * same vocabulary discovery uses), so the predicate and the tier set can never
1506
+ * read two different vocabularies.
1507
+ *
1508
+ * @param ast The parsed statement.
1509
+ * @param tenantColumns The tenant column names (lowercased) that count as scope.
1510
+ * @returns True when any WHERE predicate operand is a tenant column.
1511
+ */
1512
+ export function hasTenantPredicate(ast, tenantColumns) {
1513
+ if (tenantColumns.size === 0)
1514
+ return false;
1515
+ const refs = whereColumnRefs(ast);
1516
+ for (const ref of refs) {
1517
+ if (tenantColumns.has(ref))
1518
+ return true;
1519
+ }
1520
+ return false;
1521
+ }
1522
+ // ─── DDL facts ───────────────────────────────────────────────────────────────
1523
+ /** True when a statement is table DDL (`CREATE TABLE` / `DROP TABLE` / `ALTER TABLE`).
1524
+ * @param ast The parsed statement.
1525
+ * @returns True when the statement is `CREATE TABLE`, `DROP TABLE`, or `ALTER TABLE`. */
1526
+ export function isDdlStatement(ast) {
1527
+ if (ast.type === 'drop')
1528
+ return ast.keyword === 'table';
1529
+ if (ast.type === 'alter')
1530
+ return true;
1531
+ if (ast.type === 'create')
1532
+ return ast.keyword === 'table';
1533
+ return false;
1534
+ }
1535
+ /** The table names a DDL statement names (create target, drop names, alter target + rename).
1536
+ * @param ast The parsed statement.
1537
+ * @returns The table names the DDL statement names (create target, drop names, alter target + rename). */
1538
+ export function ddlTableNames(ast) {
1539
+ const names = new Set();
1540
+ for (const ref of collectRelations(ast))
1541
+ names.add(ref.name);
1542
+ if (ast.type === 'alter') {
1543
+ // `ALTER TABLE t RENAME TO newname` — the rename target is a table name.
1544
+ const expr = ast.expr;
1545
+ if (Array.isArray(expr)) {
1546
+ for (const op of expr) {
1547
+ if (op && typeof op === 'object' && op.action === 'rename') {
1548
+ const target = op.table;
1549
+ if (typeof target === 'string' && target.length > 0)
1550
+ names.add(target);
1551
+ }
1552
+ }
1553
+ }
1554
+ }
1555
+ return Array.from(names);
1556
+ }
1557
+ /** True when a constraint-flag field (`primary_key`, `unique`) is present and on. */
1558
+ function flagIsSet(value) {
1559
+ return value !== undefined && value !== null && value !== false;
1560
+ }
1561
+ /** The `not null` flag of a column definition — `nullable: { type: 'not null' }`
1562
+ * (or, on some dialects, a bare string). */
1563
+ function isNotNull(def) {
1564
+ const nullable = def.nullable;
1565
+ if (nullable === null || nullable === undefined)
1566
+ return false;
1567
+ if (typeof nullable === 'string')
1568
+ return nullable.toLowerCase() === 'not null';
1569
+ if (typeof nullable === 'object') {
1570
+ const t = nullable.type;
1571
+ return typeof t === 'string' && t.toLowerCase() === 'not null';
1572
+ }
1573
+ return false;
1574
+ }
1575
+ /**
1576
+ * Extract every column defined by a `CREATE TABLE` (or `ALTER TABLE … ADD
1577
+ * COLUMN`) statement — the AST replacement for site #9's
1578
+ * `extractDdlTableColumns` + `leadingColumnName` + `splitColumnDefs`, which
1579
+ * hand-rolled paren-depth and quote tracking. The column name and its
1580
+ * constraints (primary-key / not-null / unique) come straight off the
1581
+ * definition nodes.
1582
+ * @param ast The parsed `CREATE TABLE` or `ALTER TABLE … ADD COLUMN` statement.
1583
+ * @returns Each column with its primary-key / not-null / unique flags and data type.
1584
+ */
1585
+ export function ddlColumnDefinitions(ast) {
1586
+ const result = [];
1587
+ const tables = ddlTableNames(ast);
1588
+ const table = tables[0] ?? '';
1589
+ const emit = (d) => {
1590
+ const column = columnNameOf(d);
1591
+ if (column === null)
1592
+ return;
1593
+ const definition = d.definition;
1594
+ result.push({
1595
+ table,
1596
+ column,
1597
+ primaryKey: flagIsSet(d.primary_key),
1598
+ notNull: isNotNull(d),
1599
+ unique: flagIsSet(d.unique),
1600
+ dataType: typeof definition?.dataType === 'string' ? definition.dataType : null,
1601
+ });
1602
+ };
1603
+ if (ast.type === 'create') {
1604
+ const defs = ast.create_definitions;
1605
+ if (Array.isArray(defs)) {
1606
+ for (const def of defs)
1607
+ emit(def);
1608
+ }
1609
+ }
1610
+ else if (ast.type === 'alter') {
1611
+ const expr = ast.expr;
1612
+ if (Array.isArray(expr)) {
1613
+ for (const op of expr) {
1614
+ const d = op;
1615
+ if (d.action !== 'add')
1616
+ continue;
1617
+ emit(d);
1618
+ }
1619
+ }
1620
+ }
1621
+ return result;
1622
+ }
1623
+ function columnNameOf(def) {
1624
+ if (def === null || typeof def !== 'object')
1625
+ return null;
1626
+ const column = def.column;
1627
+ if (column === null || typeof column !== 'object')
1628
+ return null;
1629
+ const name = column.column;
1630
+ return typeof name === 'string' && name.length > 0 ? name : null;
1631
+ }
1632
+ /** The column name of a `column_ref` node (`{ type: 'column_ref', column: 'a' }`). */
1633
+ function columnRefNameOf(node) {
1634
+ if (node === null || typeof node !== 'object')
1635
+ return null;
1636
+ const column = node.column;
1637
+ return typeof column === 'string' && column.length > 0 ? column : null;
1638
+ }
1639
+ /** The referenced table name of a `reference_definition`. */
1640
+ function referenceTableOf(ref) {
1641
+ if (ref === null || typeof ref !== 'object')
1642
+ return '';
1643
+ const table = ref.table;
1644
+ const entry = Array.isArray(table) ? table[0] : table;
1645
+ const name = entry?.table;
1646
+ return typeof name === 'string' ? name : '';
1647
+ }
1648
+ /** The referenced column names of a `reference_definition`. */
1649
+ function referenceColumnsOf(ref) {
1650
+ if (ref === null || typeof ref !== 'object')
1651
+ return [];
1652
+ const definition = ref.definition;
1653
+ if (!Array.isArray(definition))
1654
+ return [];
1655
+ const names = [];
1656
+ for (const rc of definition) {
1657
+ const name = columnRefNameOf(rc);
1658
+ if (name !== null)
1659
+ names.push(name);
1660
+ }
1661
+ return names;
1662
+ }
1663
+ /** The local column names of a table-level constraint's `definition` list. */
1664
+ function constraintColumnNames(def) {
1665
+ if (def === null || typeof def !== 'object')
1666
+ return [];
1667
+ const definition = def.definition;
1668
+ if (!Array.isArray(definition))
1669
+ return [];
1670
+ const names = [];
1671
+ for (const c of definition) {
1672
+ const name = columnRefNameOf(c);
1673
+ if (name !== null)
1674
+ names.push(name);
1675
+ }
1676
+ return names;
1677
+ }
1678
+ /** The normalized (`lower`) `constraint_type` of a constraint definition, or null. */
1679
+ function constraintTypeOf(def) {
1680
+ if (def === null || typeof def !== 'object')
1681
+ return null;
1682
+ const raw = def.constraint_type;
1683
+ return typeof raw === 'string' && raw.length > 0 ? raw.toLowerCase() : null;
1684
+ }
1685
+ /**
1686
+ * Extract the foreign-key constraints of a `CREATE TABLE` or `ALTER TABLE … ADD
1687
+ * CONSTRAINT … FOREIGN KEY` statement — the AST replacement for site #10's FK
1688
+ * regexes. Covers the three DDL spellings: column-level `REFERENCES`, table-level
1689
+ * `FOREIGN KEY (…) REFERENCES`, and ALTER `ADD CONSTRAINT … FOREIGN KEY`. The
1690
+ * referenced table and columns come straight off the `reference_definition` node.
1691
+ * @param ast The parsed `CREATE TABLE` or `ALTER TABLE` statement.
1692
+ * @returns The foreign-key constraints, with local columns and the referenced table/columns.
1693
+ */
1694
+ export function ddlForeignKeys(ast) {
1695
+ if (ast.type !== 'create' && ast.type !== 'alter')
1696
+ return [];
1697
+ const result = [];
1698
+ const tables = ddlTableNames(ast);
1699
+ const table = tables[0] ?? '';
1700
+ const emit = (def) => {
1701
+ const ref = def.reference_definition;
1702
+ if (ref === null || typeof ref !== 'object' || ref === undefined)
1703
+ return;
1704
+ const localColumn = columnNameOf(def);
1705
+ const localColumns = constraintColumnNames(def);
1706
+ const columns = localColumn !== null ? [localColumn] : (localColumns.length > 0 ? localColumns : []);
1707
+ result.push({
1708
+ table,
1709
+ columns,
1710
+ referencesTable: referenceTableOf(ref),
1711
+ referencesColumns: referenceColumnsOf(ref),
1712
+ });
1713
+ };
1714
+ if (ast.type === 'create') {
1715
+ const defs = ast.create_definitions;
1716
+ if (Array.isArray(defs)) {
1717
+ for (const def of defs)
1718
+ emit(def);
1719
+ }
1720
+ }
1721
+ else {
1722
+ const expr = ast.expr;
1723
+ if (Array.isArray(expr)) {
1724
+ for (const op of expr) {
1725
+ const d = op;
1726
+ if (d.action !== 'add')
1727
+ continue;
1728
+ // `ALTER TABLE … ADD CONSTRAINT … FOREIGN KEY (…) REFERENCES …` carries the
1729
+ // constraint on `create_definitions` of the `add` op, not on the op itself.
1730
+ const cd = d.create_definitions;
1731
+ if (cd !== null && typeof cd === 'object' && cd !== undefined) {
1732
+ emit(cd);
1733
+ }
1734
+ }
1735
+ }
1736
+ }
1737
+ return result;
1738
+ }
1739
+ /**
1740
+ * The ordered CREATE / DROP / RENAME ops of a table-DDL statement — the AST
1741
+ * replacement for site #7's `DDL_RE` (which had to regex the whole
1742
+ * create/drop/alter-rename vocabulary as one alternation). The statement kind and
1743
+ * its target/rename nodes are read directly.
1744
+ * @param ast The parsed table-DDL statement.
1745
+ * @returns The ordered CREATE / DROP / RENAME ops.
1746
+ */
1747
+ export function ddlMigrationOps(ast) {
1748
+ if (ast.type === 'create' && ast.keyword === 'table') {
1749
+ const tables = ddlTableNames(ast);
1750
+ return [{ op: 'CREATE', table: tables[0] ?? '' }];
1751
+ }
1752
+ if (ast.type === 'drop' && ast.keyword === 'table') {
1753
+ return ddlTableNames(ast).map((t) => ({ op: 'DROP', table: t }));
1754
+ }
1755
+ if (ast.type === 'alter') {
1756
+ const tables = ddlTableNames(ast);
1757
+ const target = tables[0] ?? '';
1758
+ const expr = ast.expr;
1759
+ if (Array.isArray(expr)) {
1760
+ for (const op of expr) {
1761
+ if (op && typeof op === 'object' && op.action === 'rename') {
1762
+ const newTable = op.table;
1763
+ if (typeof newTable === 'string' && newTable.length > 0) {
1764
+ return [{ op: 'RENAME', table: target, newTable }];
1765
+ }
1766
+ }
1767
+ }
1768
+ }
1769
+ return [];
1770
+ }
1771
+ return [];
1772
+ }
1773
+ /**
1774
+ * The columns of a table-level or ALTER-added UNIQUE / PRIMARY KEY constraint —
1775
+ * the AST replacement for the table-level halves of `extractDdlUniqueColumns` and
1776
+ * `extractDdlPrimaryKeyColumns`, which had to hand-roll paren matching to find
1777
+ * the column list inside `UNIQUE (…)`. Column-level `UNIQUE` / `PRIMARY KEY` is
1778
+ * already carried by {@link ddlColumnDefinitions}.
1779
+ * @param ast The parsed `CREATE TABLE` or `ALTER TABLE` statement.
1780
+ * @param constraintType `'unique'` or `'primary key'`.
1781
+ * @returns The lowercased columns of table-level / ALTER-added constraints of that kind.
1782
+ */
1783
+ export function ddlConstraintColumns(ast, constraintType) {
1784
+ const names = [];
1785
+ const collect = (def) => {
1786
+ if (def === null || typeof def !== 'object')
1787
+ return;
1788
+ if (constraintTypeOf(def) !== constraintType)
1789
+ return;
1790
+ for (const name of constraintColumnNames(def))
1791
+ names.push(name.toLowerCase());
1792
+ };
1793
+ if (ast.type === 'create') {
1794
+ const defs = ast.create_definitions;
1795
+ if (Array.isArray(defs))
1796
+ for (const def of defs)
1797
+ collect(def);
1798
+ }
1799
+ else if (ast.type === 'alter') {
1800
+ const expr = ast.expr;
1801
+ if (Array.isArray(expr)) {
1802
+ for (const op of expr) {
1803
+ const d = op;
1804
+ if (d.action !== 'add')
1805
+ continue;
1806
+ collect(d.create_definitions);
1807
+ }
1808
+ }
1809
+ }
1810
+ return names;
1811
+ }
1812
+ // ─── Statement kind convenience ──────────────────────────────────────────────
1813
+ /** The {@link SqlStatementKind} of a parsed statement. */
1814
+ export function kindOf(ast) {
1815
+ return statementKind(ast.type);
1816
+ }
1817
+ //# sourceMappingURL=sqlAst.js.map