codesift-mcp 0.9.5 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1358) hide show
  1. package/README.md +62 -23
  2. package/dist/cli/commands.d.ts.map +1 -1
  3. package/dist/cli/commands.js +92 -2
  4. package/dist/cli/commands.js.map +1 -1
  5. package/dist/cli/help.d.ts +1 -1
  6. package/dist/cli/help.d.ts.map +1 -1
  7. package/dist/cli/help.js +18 -0
  8. package/dist/cli/help.js.map +1 -1
  9. package/dist/cli/hooks/input.d.ts +11 -0
  10. package/dist/cli/hooks/input.d.ts.map +1 -0
  11. package/dist/cli/hooks/input.js +111 -0
  12. package/dist/cli/hooks/input.js.map +1 -0
  13. package/dist/cli/hooks/post-tool-use.d.ts +2 -0
  14. package/dist/cli/hooks/post-tool-use.d.ts.map +1 -0
  15. package/dist/cli/hooks/post-tool-use.js +339 -0
  16. package/dist/cli/hooks/post-tool-use.js.map +1 -0
  17. package/dist/cli/hooks/pre-compact.d.ts +2 -0
  18. package/dist/cli/hooks/pre-compact.d.ts.map +1 -0
  19. package/dist/cli/hooks/pre-compact.js +41 -0
  20. package/dist/cli/hooks/pre-compact.js.map +1 -0
  21. package/dist/cli/hooks/pre-tool-use.d.ts +5 -0
  22. package/dist/cli/hooks/pre-tool-use.d.ts.map +1 -0
  23. package/dist/cli/hooks/pre-tool-use.js +215 -0
  24. package/dist/cli/hooks/pre-tool-use.js.map +1 -0
  25. package/dist/cli/hooks/session.d.ts +5 -0
  26. package/dist/cli/hooks/session.d.ts.map +1 -0
  27. package/dist/cli/hooks/session.js +188 -0
  28. package/dist/cli/hooks/session.js.map +1 -0
  29. package/dist/cli/hooks/shared.d.ts +6 -0
  30. package/dist/cli/hooks/shared.d.ts.map +1 -0
  31. package/dist/cli/hooks/shared.js +70 -0
  32. package/dist/cli/hooks/shared.js.map +1 -0
  33. package/dist/cli/hooks/wiki.d.ts +10 -0
  34. package/dist/cli/hooks/wiki.d.ts.map +1 -0
  35. package/dist/cli/hooks/wiki.js +202 -0
  36. package/dist/cli/hooks/wiki.js.map +1 -0
  37. package/dist/cli/hooks.d.ts +5 -16
  38. package/dist/cli/hooks.d.ts.map +1 -1
  39. package/dist/cli/hooks.js +5 -1132
  40. package/dist/cli/hooks.js.map +1 -1
  41. package/dist/cli/setup/claude.d.ts +4 -0
  42. package/dist/cli/setup/claude.d.ts.map +1 -0
  43. package/dist/cli/setup/claude.js +123 -0
  44. package/dist/cli/setup/claude.js.map +1 -0
  45. package/dist/cli/setup/codex.d.ts +12 -0
  46. package/dist/cli/setup/codex.d.ts.map +1 -0
  47. package/dist/cli/setup/codex.js +182 -0
  48. package/dist/cli/setup/codex.js.map +1 -0
  49. package/dist/cli/setup/cursor.d.ts +3 -0
  50. package/dist/cli/setup/cursor.d.ts.map +1 -0
  51. package/dist/cli/setup/cursor.js +6 -0
  52. package/dist/cli/setup/cursor.js.map +1 -0
  53. package/dist/cli/setup/fs.d.ts +6 -0
  54. package/dist/cli/setup/fs.d.ts.map +1 -0
  55. package/dist/cli/setup/fs.js +44 -0
  56. package/dist/cli/setup/fs.js.map +1 -0
  57. package/dist/cli/setup/gemini.d.ts +5 -0
  58. package/dist/cli/setup/gemini.d.ts.map +1 -0
  59. package/dist/cli/setup/gemini.js +46 -0
  60. package/dist/cli/setup/gemini.js.map +1 -0
  61. package/dist/cli/setup/hooks.d.ts +12 -0
  62. package/dist/cli/setup/hooks.d.ts.map +1 -0
  63. package/dist/cli/setup/hooks.js +29 -0
  64. package/dist/cli/setup/hooks.js.map +1 -0
  65. package/dist/cli/setup/mcp.d.ts +13 -0
  66. package/dist/cli/setup/mcp.d.ts.map +1 -0
  67. package/dist/cli/setup/mcp.js +104 -0
  68. package/dist/cli/setup/mcp.js.map +1 -0
  69. package/dist/cli/setup/rules.d.ts +4 -0
  70. package/dist/cli/setup/rules.d.ts.map +1 -0
  71. package/dist/cli/setup/rules.js +157 -0
  72. package/dist/cli/setup/rules.js.map +1 -0
  73. package/dist/cli/setup/types.d.ts +24 -0
  74. package/dist/cli/setup/types.d.ts.map +1 -0
  75. package/dist/cli/setup/types.js +2 -0
  76. package/dist/cli/setup/types.js.map +1 -0
  77. package/dist/cli/setup.d.ts +8 -48
  78. package/dist/cli/setup.d.ts.map +1 -1
  79. package/dist/cli/setup.js +49 -705
  80. package/dist/cli/setup.js.map +1 -1
  81. package/dist/cli/telemetry-commands.d.ts +2 -0
  82. package/dist/cli/telemetry-commands.d.ts.map +1 -0
  83. package/dist/cli/telemetry-commands.js +50 -0
  84. package/dist/cli/telemetry-commands.js.map +1 -0
  85. package/dist/config.d.ts +15 -0
  86. package/dist/config.d.ts.map +1 -1
  87. package/dist/config.js +56 -2
  88. package/dist/config.js.map +1 -1
  89. package/dist/formatter-dispatch.d.ts +53 -0
  90. package/dist/formatter-dispatch.d.ts.map +1 -0
  91. package/dist/formatter-dispatch.js +54 -0
  92. package/dist/formatter-dispatch.js.map +1 -0
  93. package/dist/formatters-analysis.d.ts +9 -0
  94. package/dist/formatters-analysis.d.ts.map +1 -0
  95. package/dist/formatters-analysis.js +166 -0
  96. package/dist/formatters-analysis.js.map +1 -0
  97. package/dist/formatters-core.d.ts +200 -0
  98. package/dist/formatters-core.d.ts.map +1 -0
  99. package/dist/formatters-core.js +206 -0
  100. package/dist/formatters-core.js.map +1 -0
  101. package/dist/formatters-graph.d.ts +124 -0
  102. package/dist/formatters-graph.d.ts.map +1 -0
  103. package/dist/formatters-graph.js +175 -0
  104. package/dist/formatters-graph.js.map +1 -0
  105. package/dist/formatters-nextjs.d.ts +22 -0
  106. package/dist/formatters-nextjs.d.ts.map +1 -0
  107. package/dist/formatters-nextjs.js +394 -0
  108. package/dist/formatters-nextjs.js.map +1 -0
  109. package/dist/formatters.d.ts +8 -349
  110. package/dist/formatters.d.ts.map +1 -1
  111. package/dist/formatters.js +10 -929
  112. package/dist/formatters.js.map +1 -1
  113. package/dist/parser/astro-template/preprocess.d.ts +12 -0
  114. package/dist/parser/astro-template/preprocess.d.ts.map +1 -0
  115. package/dist/parser/astro-template/preprocess.js +34 -0
  116. package/dist/parser/astro-template/preprocess.js.map +1 -0
  117. package/dist/parser/astro-template/resolution.d.ts +16 -0
  118. package/dist/parser/astro-template/resolution.d.ts.map +1 -0
  119. package/dist/parser/astro-template/resolution.js +58 -0
  120. package/dist/parser/astro-template/resolution.js.map +1 -0
  121. package/dist/parser/astro-template/scanner.d.ts +4 -0
  122. package/dist/parser/astro-template/scanner.d.ts.map +1 -0
  123. package/dist/parser/astro-template/scanner.js +71 -0
  124. package/dist/parser/astro-template/scanner.js.map +1 -0
  125. package/dist/parser/astro-template/state.d.ts +22 -0
  126. package/dist/parser/astro-template/state.d.ts.map +1 -0
  127. package/dist/parser/astro-template/state.js +48 -0
  128. package/dist/parser/astro-template/state.js.map +1 -0
  129. package/dist/parser/astro-template/tag-processor.d.ts +3 -0
  130. package/dist/parser/astro-template/tag-processor.d.ts.map +1 -0
  131. package/dist/parser/astro-template/tag-processor.js +63 -0
  132. package/dist/parser/astro-template/tag-processor.js.map +1 -0
  133. package/dist/parser/astro-template/types.d.ts +42 -0
  134. package/dist/parser/astro-template/types.d.ts.map +1 -0
  135. package/dist/parser/astro-template/types.js +2 -0
  136. package/dist/parser/astro-template/types.js.map +1 -0
  137. package/dist/parser/astro-template.d.ts +2 -45
  138. package/dist/parser/astro-template.d.ts.map +1 -1
  139. package/dist/parser/astro-template.js +7 -168
  140. package/dist/parser/astro-template.js.map +1 -1
  141. package/dist/parser/extractors/_shared.js +1 -1
  142. package/dist/parser/extractors/_shared.js.map +1 -1
  143. package/dist/parser/extractors/astro.js +1 -1
  144. package/dist/parser/extractors/astro.js.map +1 -1
  145. package/dist/parser/extractors/conversation.js +1 -1
  146. package/dist/parser/extractors/conversation.js.map +1 -1
  147. package/dist/parser/extractors/hono-app-discovery.d.ts +4 -0
  148. package/dist/parser/extractors/hono-app-discovery.d.ts.map +1 -0
  149. package/dist/parser/extractors/hono-app-discovery.js +169 -0
  150. package/dist/parser/extractors/hono-app-discovery.js.map +1 -0
  151. package/dist/parser/extractors/hono-ast-utils.d.ts +6 -0
  152. package/dist/parser/extractors/hono-ast-utils.d.ts.map +1 -0
  153. package/dist/parser/extractors/hono-ast-utils.js +77 -0
  154. package/dist/parser/extractors/hono-ast-utils.js.map +1 -0
  155. package/dist/parser/extractors/hono-context-extractor.d.ts +15 -0
  156. package/dist/parser/extractors/hono-context-extractor.d.ts.map +1 -0
  157. package/dist/parser/extractors/hono-context-extractor.js +191 -0
  158. package/dist/parser/extractors/hono-context-extractor.js.map +1 -0
  159. package/dist/parser/extractors/hono-middleware-extractor.d.ts +38 -0
  160. package/dist/parser/extractors/hono-middleware-extractor.d.ts.map +1 -0
  161. package/dist/parser/extractors/hono-middleware-extractor.js +480 -0
  162. package/dist/parser/extractors/hono-middleware-extractor.js.map +1 -0
  163. package/dist/parser/extractors/hono-openapi-extractor.d.ts +11 -0
  164. package/dist/parser/extractors/hono-openapi-extractor.d.ts.map +1 -0
  165. package/dist/parser/extractors/hono-openapi-extractor.js +119 -0
  166. package/dist/parser/extractors/hono-openapi-extractor.js.map +1 -0
  167. package/dist/parser/extractors/hono-route-extractor.d.ts +11 -0
  168. package/dist/parser/extractors/hono-route-extractor.d.ts.map +1 -0
  169. package/dist/parser/extractors/hono-route-extractor.js +128 -0
  170. package/dist/parser/extractors/hono-route-extractor.js.map +1 -0
  171. package/dist/parser/extractors/hono-route-utils.d.ts +11 -0
  172. package/dist/parser/extractors/hono-route-utils.d.ts.map +1 -0
  173. package/dist/parser/extractors/hono-route-utils.js +40 -0
  174. package/dist/parser/extractors/hono-route-utils.js.map +1 -0
  175. package/dist/parser/extractors/hono-runtime-extractor.d.ts +17 -0
  176. package/dist/parser/extractors/hono-runtime-extractor.d.ts.map +1 -0
  177. package/dist/parser/extractors/hono-runtime-extractor.js +141 -0
  178. package/dist/parser/extractors/hono-runtime-extractor.js.map +1 -0
  179. package/dist/parser/extractors/hono.d.ts +5 -79
  180. package/dist/parser/extractors/hono.d.ts.map +1 -1
  181. package/dist/parser/extractors/hono.js +32 -1159
  182. package/dist/parser/extractors/hono.js.map +1 -1
  183. package/dist/parser/extractors/kotlin-ast-helpers.d.ts +43 -0
  184. package/dist/parser/extractors/kotlin-ast-helpers.d.ts.map +1 -0
  185. package/dist/parser/extractors/kotlin-ast-helpers.js +187 -0
  186. package/dist/parser/extractors/kotlin-ast-helpers.js.map +1 -0
  187. package/dist/parser/extractors/kotlin-test-symbols.d.ts +21 -0
  188. package/dist/parser/extractors/kotlin-test-symbols.d.ts.map +1 -0
  189. package/dist/parser/extractors/kotlin-test-symbols.js +162 -0
  190. package/dist/parser/extractors/kotlin-test-symbols.js.map +1 -0
  191. package/dist/parser/extractors/kotlin.d.ts.map +1 -1
  192. package/dist/parser/extractors/kotlin.js +3 -334
  193. package/dist/parser/extractors/kotlin.js.map +1 -1
  194. package/dist/parser/extractors/markdown.js +1 -1
  195. package/dist/parser/extractors/markdown.js.map +1 -1
  196. package/dist/parser/extractors/prisma.js +1 -1
  197. package/dist/parser/extractors/prisma.js.map +1 -1
  198. package/dist/parser/extractors/sql-boundaries.d.ts +3 -0
  199. package/dist/parser/extractors/sql-boundaries.d.ts.map +1 -0
  200. package/dist/parser/extractors/sql-boundaries.js +19 -0
  201. package/dist/parser/extractors/sql-boundaries.js.map +1 -0
  202. package/dist/parser/extractors/sql-columns.d.ts +14 -0
  203. package/dist/parser/extractors/sql-columns.d.ts.map +1 -0
  204. package/dist/parser/extractors/sql-columns.js +59 -0
  205. package/dist/parser/extractors/sql-columns.js.map +1 -0
  206. package/dist/parser/extractors/sql-docstrings.d.ts +2 -0
  207. package/dist/parser/extractors/sql-docstrings.d.ts.map +1 -0
  208. package/dist/parser/extractors/sql-docstrings.js +45 -0
  209. package/dist/parser/extractors/sql-docstrings.js.map +1 -0
  210. package/dist/parser/extractors/sql-end-scanner.d.ts +5 -0
  211. package/dist/parser/extractors/sql-end-scanner.d.ts.map +1 -0
  212. package/dist/parser/extractors/sql-end-scanner.js +84 -0
  213. package/dist/parser/extractors/sql-end-scanner.js.map +1 -0
  214. package/dist/parser/extractors/sql-jinja.d.ts +2 -0
  215. package/dist/parser/extractors/sql-jinja.d.ts.map +1 -0
  216. package/dist/parser/extractors/sql-jinja.js +8 -0
  217. package/dist/parser/extractors/sql-jinja.js.map +1 -0
  218. package/dist/parser/extractors/sql-matcher-catalog.d.ts +9 -0
  219. package/dist/parser/extractors/sql-matcher-catalog.d.ts.map +1 -0
  220. package/dist/parser/extractors/sql-matcher-catalog.js +15 -0
  221. package/dist/parser/extractors/sql-matcher-catalog.js.map +1 -0
  222. package/dist/parser/extractors/sql-matchers.d.ts +9 -0
  223. package/dist/parser/extractors/sql-matchers.d.ts.map +1 -0
  224. package/dist/parser/extractors/sql-matchers.js +20 -0
  225. package/dist/parser/extractors/sql-matchers.js.map +1 -0
  226. package/dist/parser/extractors/sql-offsets.d.ts +2 -0
  227. package/dist/parser/extractors/sql-offsets.d.ts.map +1 -0
  228. package/dist/parser/extractors/sql-offsets.js +25 -0
  229. package/dist/parser/extractors/sql-offsets.js.map +1 -0
  230. package/dist/parser/extractors/sql-parens.d.ts +4 -0
  231. package/dist/parser/extractors/sql-parens.d.ts.map +1 -0
  232. package/dist/parser/extractors/sql-parens.js +70 -0
  233. package/dist/parser/extractors/sql-parens.js.map +1 -0
  234. package/dist/parser/extractors/sql-symbols.d.ts +11 -0
  235. package/dist/parser/extractors/sql-symbols.d.ts.map +1 -0
  236. package/dist/parser/extractors/sql-symbols.js +23 -0
  237. package/dist/parser/extractors/sql-symbols.js.map +1 -0
  238. package/dist/parser/extractors/sql.d.ts +2 -30
  239. package/dist/parser/extractors/sql.d.ts.map +1 -1
  240. package/dist/parser/extractors/sql.js +23 -496
  241. package/dist/parser/extractors/sql.js.map +1 -1
  242. package/dist/parser/extractors/typescript-cjs-nodes.d.ts +5 -0
  243. package/dist/parser/extractors/typescript-cjs-nodes.d.ts.map +1 -0
  244. package/dist/parser/extractors/typescript-cjs-nodes.js +148 -0
  245. package/dist/parser/extractors/typescript-cjs-nodes.js.map +1 -0
  246. package/dist/parser/extractors/typescript-class-nodes.d.ts +8 -0
  247. package/dist/parser/extractors/typescript-class-nodes.d.ts.map +1 -0
  248. package/dist/parser/extractors/typescript-class-nodes.js +183 -0
  249. package/dist/parser/extractors/typescript-class-nodes.js.map +1 -0
  250. package/dist/parser/extractors/typescript-declaration-nodes.d.ts +5 -0
  251. package/dist/parser/extractors/typescript-declaration-nodes.d.ts.map +1 -0
  252. package/dist/parser/extractors/typescript-declaration-nodes.js +105 -0
  253. package/dist/parser/extractors/typescript-declaration-nodes.js.map +1 -0
  254. package/dist/parser/extractors/typescript-module-nodes.d.ts +6 -0
  255. package/dist/parser/extractors/typescript-module-nodes.d.ts.map +1 -0
  256. package/dist/parser/extractors/typescript-module-nodes.js +151 -0
  257. package/dist/parser/extractors/typescript-module-nodes.js.map +1 -0
  258. package/dist/parser/extractors/typescript-react.d.ts +11 -0
  259. package/dist/parser/extractors/typescript-react.d.ts.map +1 -0
  260. package/dist/parser/extractors/typescript-react.js +101 -0
  261. package/dist/parser/extractors/typescript-react.js.map +1 -0
  262. package/dist/parser/extractors/typescript-shared.d.ts +26 -0
  263. package/dist/parser/extractors/typescript-shared.d.ts.map +1 -0
  264. package/dist/parser/extractors/typescript-shared.js +101 -0
  265. package/dist/parser/extractors/typescript-shared.js.map +1 -0
  266. package/dist/parser/extractors/typescript-test-nodes.d.ts +4 -0
  267. package/dist/parser/extractors/typescript-test-nodes.d.ts.map +1 -0
  268. package/dist/parser/extractors/typescript-test-nodes.js +112 -0
  269. package/dist/parser/extractors/typescript-test-nodes.js.map +1 -0
  270. package/dist/parser/extractors/typescript-type-nodes.d.ts +6 -0
  271. package/dist/parser/extractors/typescript-type-nodes.d.ts.map +1 -0
  272. package/dist/parser/extractors/typescript-type-nodes.js +48 -0
  273. package/dist/parser/extractors/typescript-type-nodes.js.map +1 -0
  274. package/dist/parser/extractors/typescript.d.ts.map +1 -1
  275. package/dist/parser/extractors/typescript.js +68 -1127
  276. package/dist/parser/extractors/typescript.js.map +1 -1
  277. package/dist/parser/parser-manager.d.ts.map +1 -1
  278. package/dist/parser/parser-manager.js +5 -0
  279. package/dist/parser/parser-manager.js.map +1 -1
  280. package/dist/parser/symbol-extractor.d.ts +1 -12
  281. package/dist/parser/symbol-extractor.d.ts.map +1 -1
  282. package/dist/parser/symbol-extractor.js +2 -24
  283. package/dist/parser/symbol-extractor.js.map +1 -1
  284. package/dist/parser/symbol-utils.d.ts +4 -0
  285. package/dist/parser/symbol-utils.d.ts.map +1 -0
  286. package/dist/parser/symbol-utils.js +20 -0
  287. package/dist/parser/symbol-utils.js.map +1 -0
  288. package/dist/register-tool-groups/analysis/cross-repo.d.ts +4 -0
  289. package/dist/register-tool-groups/analysis/cross-repo.d.ts.map +1 -0
  290. package/dist/register-tool-groups/analysis/cross-repo.js +108 -0
  291. package/dist/register-tool-groups/analysis/cross-repo.js.map +1 -0
  292. package/dist/register-tool-groups/analysis/review.d.ts +3 -0
  293. package/dist/register-tool-groups/analysis/review.d.ts.map +1 -0
  294. package/dist/register-tool-groups/analysis/review.js +96 -0
  295. package/dist/register-tool-groups/analysis/review.js.map +1 -0
  296. package/dist/register-tool-groups/analysis/workspace.d.ts +3 -0
  297. package/dist/register-tool-groups/analysis/workspace.d.ts.map +1 -0
  298. package/dist/register-tool-groups/analysis/workspace.js +82 -0
  299. package/dist/register-tool-groups/analysis/workspace.js.map +1 -0
  300. package/dist/register-tool-groups/analysis.d.ts +3 -0
  301. package/dist/register-tool-groups/analysis.d.ts.map +1 -0
  302. package/dist/register-tool-groups/analysis.js +541 -0
  303. package/dist/register-tool-groups/analysis.js.map +1 -0
  304. package/dist/register-tool-groups/astro.d.ts +3 -0
  305. package/dist/register-tool-groups/astro.d.ts.map +1 -0
  306. package/dist/register-tool-groups/astro.js +302 -0
  307. package/dist/register-tool-groups/astro.js.map +1 -0
  308. package/dist/register-tool-groups/core/index.d.ts +3 -0
  309. package/dist/register-tool-groups/core/index.d.ts.map +1 -0
  310. package/dist/register-tool-groups/core/index.js +96 -0
  311. package/dist/register-tool-groups/core/index.js.map +1 -0
  312. package/dist/register-tool-groups/core/meta.d.ts +3 -0
  313. package/dist/register-tool-groups/core/meta.d.ts.map +1 -0
  314. package/dist/register-tool-groups/core/meta.js +180 -0
  315. package/dist/register-tool-groups/core/meta.js.map +1 -0
  316. package/dist/register-tool-groups/core/schema.d.ts +3 -0
  317. package/dist/register-tool-groups/core/schema.d.ts.map +1 -0
  318. package/dist/register-tool-groups/core/schema.js +16 -0
  319. package/dist/register-tool-groups/core/schema.js.map +1 -0
  320. package/dist/register-tool-groups/core/search.d.ts +4 -0
  321. package/dist/register-tool-groups/core/search.d.ts.map +1 -0
  322. package/dist/register-tool-groups/core/search.js +262 -0
  323. package/dist/register-tool-groups/core/search.js.map +1 -0
  324. package/dist/register-tool-groups/core/symbols.d.ts +3 -0
  325. package/dist/register-tool-groups/core/symbols.d.ts.map +1 -0
  326. package/dist/register-tool-groups/core/symbols.js +338 -0
  327. package/dist/register-tool-groups/core/symbols.js.map +1 -0
  328. package/dist/register-tool-groups/core.d.ts +3 -0
  329. package/dist/register-tool-groups/core.d.ts.map +1 -0
  330. package/dist/register-tool-groups/core.js +12 -0
  331. package/dist/register-tool-groups/core.js.map +1 -0
  332. package/dist/register-tool-groups/deps.d.ts +10 -0
  333. package/dist/register-tool-groups/deps.d.ts.map +1 -0
  334. package/dist/register-tool-groups/deps.js +6 -0
  335. package/dist/register-tool-groups/deps.js.map +1 -0
  336. package/dist/register-tool-groups/handler-wrappers.d.ts +63 -0
  337. package/dist/register-tool-groups/handler-wrappers.d.ts.map +1 -0
  338. package/dist/register-tool-groups/handler-wrappers.js +106 -0
  339. package/dist/register-tool-groups/handler-wrappers.js.map +1 -0
  340. package/dist/register-tool-groups/hono.d.ts +3 -0
  341. package/dist/register-tool-groups/hono.d.ts.map +1 -0
  342. package/dist/register-tool-groups/hono.js +179 -0
  343. package/dist/register-tool-groups/hono.js.map +1 -0
  344. package/dist/register-tool-groups/index.d.ts +3 -0
  345. package/dist/register-tool-groups/index.d.ts.map +1 -0
  346. package/dist/register-tool-groups/index.js +28 -0
  347. package/dist/register-tool-groups/index.js.map +1 -0
  348. package/dist/register-tool-groups/kotlin.d.ts +3 -0
  349. package/dist/register-tool-groups/kotlin.d.ts.map +1 -0
  350. package/dist/register-tool-groups/kotlin.js +162 -0
  351. package/dist/register-tool-groups/kotlin.js.map +1 -0
  352. package/dist/register-tool-groups/meta.d.ts +3 -0
  353. package/dist/register-tool-groups/meta.d.ts.map +1 -0
  354. package/dist/register-tool-groups/meta.js +563 -0
  355. package/dist/register-tool-groups/meta.js.map +1 -0
  356. package/dist/register-tool-groups/nextjs.d.ts +3 -0
  357. package/dist/register-tool-groups/nextjs.d.ts.map +1 -0
  358. package/dist/register-tool-groups/nextjs.js +78 -0
  359. package/dist/register-tool-groups/nextjs.js.map +1 -0
  360. package/dist/register-tool-groups/php.d.ts +3 -0
  361. package/dist/register-tool-groups/php.d.ts.map +1 -0
  362. package/dist/register-tool-groups/php.js +312 -0
  363. package/dist/register-tool-groups/php.js.map +1 -0
  364. package/dist/register-tool-groups/python.d.ts +3 -0
  365. package/dist/register-tool-groups/python.d.ts.map +1 -0
  366. package/dist/register-tool-groups/python.js +366 -0
  367. package/dist/register-tool-groups/python.js.map +1 -0
  368. package/dist/register-tool-groups/react.d.ts +3 -0
  369. package/dist/register-tool-groups/react.d.ts.map +1 -0
  370. package/dist/register-tool-groups/react.js +119 -0
  371. package/dist/register-tool-groups/react.js.map +1 -0
  372. package/dist/register-tool-groups/shared.d.ts +156 -0
  373. package/dist/register-tool-groups/shared.d.ts.map +1 -0
  374. package/dist/register-tool-groups/shared.js +182 -0
  375. package/dist/register-tool-groups/shared.js.map +1 -0
  376. package/dist/register-tool-groups/sql.d.ts +3 -0
  377. package/dist/register-tool-groups/sql.d.ts.map +1 -0
  378. package/dist/register-tool-groups/sql.js +260 -0
  379. package/dist/register-tool-groups/sql.js.map +1 -0
  380. package/dist/register-tool-loaders.d.ts +22 -22
  381. package/dist/register-tool-loaders.d.ts.map +1 -1
  382. package/dist/register-tools/autoload.d.ts +8 -0
  383. package/dist/register-tools/autoload.d.ts.map +1 -0
  384. package/dist/register-tools/autoload.js +517 -0
  385. package/dist/register-tools/autoload.js.map +1 -0
  386. package/dist/register-tools/discovery.d.ts +55 -0
  387. package/dist/register-tools/discovery.d.ts.map +1 -0
  388. package/dist/register-tools/discovery.js +206 -0
  389. package/dist/register-tools/discovery.js.map +1 -0
  390. package/dist/register-tools/runtime.d.ts +89 -0
  391. package/dist/register-tools/runtime.d.ts.map +1 -0
  392. package/dist/register-tools/runtime.js +491 -0
  393. package/dist/register-tools/runtime.js.map +1 -0
  394. package/dist/register-tools.d.ts +5 -172
  395. package/dist/register-tools.d.ts.map +1 -1
  396. package/dist/register-tools.js +27 -4878
  397. package/dist/register-tools.js.map +1 -1
  398. package/dist/search/bm25.js +1 -1
  399. package/dist/search/bm25.js.map +1 -1
  400. package/dist/search/tool-embedding-cache.d.ts +4 -0
  401. package/dist/search/tool-embedding-cache.d.ts.map +1 -0
  402. package/dist/search/tool-embedding-cache.js +44 -0
  403. package/dist/search/tool-embedding-cache.js.map +1 -0
  404. package/dist/search/tool-embedding-storage.d.ts +8 -0
  405. package/dist/search/tool-embedding-storage.d.ts.map +1 -0
  406. package/dist/search/tool-embedding-storage.js +56 -0
  407. package/dist/search/tool-embedding-storage.js.map +1 -0
  408. package/dist/search/tool-ranker-bm25.d.ts +6 -0
  409. package/dist/search/tool-ranker-bm25.d.ts.map +1 -0
  410. package/dist/search/tool-ranker-bm25.js +40 -0
  411. package/dist/search/tool-ranker-bm25.js.map +1 -0
  412. package/dist/search/tool-ranker-orchestrator.d.ts +3 -0
  413. package/dist/search/tool-ranker-orchestrator.d.ts.map +1 -0
  414. package/dist/search/tool-ranker-orchestrator.js +49 -0
  415. package/dist/search/tool-ranker-orchestrator.js.map +1 -0
  416. package/dist/search/tool-ranker-reasoning.d.ts +4 -0
  417. package/dist/search/tool-ranker-reasoning.d.ts.map +1 -0
  418. package/dist/search/tool-ranker-reasoning.js +35 -0
  419. package/dist/search/tool-ranker-reasoning.js.map +1 -0
  420. package/dist/search/tool-ranker-signal-math.d.ts +6 -0
  421. package/dist/search/tool-ranker-signal-math.d.ts.map +1 -0
  422. package/dist/search/tool-ranker-signal-math.js +51 -0
  423. package/dist/search/tool-ranker-signal-math.js.map +1 -0
  424. package/dist/search/tool-ranker-signals.d.ts +20 -0
  425. package/dist/search/tool-ranker-signals.d.ts.map +1 -0
  426. package/dist/search/tool-ranker-signals.js +50 -0
  427. package/dist/search/tool-ranker-signals.js.map +1 -0
  428. package/dist/search/tool-ranker-types.d.ts +26 -0
  429. package/dist/search/tool-ranker-types.d.ts.map +1 -0
  430. package/dist/search/tool-ranker-types.js +2 -0
  431. package/dist/search/tool-ranker-types.js.map +1 -0
  432. package/dist/search/tool-ranker.d.ts +6 -89
  433. package/dist/search/tool-ranker.d.ts.map +1 -1
  434. package/dist/search/tool-ranker.js +5 -419
  435. package/dist/search/tool-ranker.js.map +1 -1
  436. package/dist/server-helpers/repo-resolution.d.ts +45 -0
  437. package/dist/server-helpers/repo-resolution.d.ts.map +1 -0
  438. package/dist/server-helpers/repo-resolution.js +113 -0
  439. package/dist/server-helpers/repo-resolution.js.map +1 -0
  440. package/dist/server-helpers/response-hints.d.ts +9 -0
  441. package/dist/server-helpers/response-hints.d.ts.map +1 -0
  442. package/dist/server-helpers/response-hints.js +225 -0
  443. package/dist/server-helpers/response-hints.js.map +1 -0
  444. package/dist/server-helpers.d.ts +14 -35
  445. package/dist/server-helpers.d.ts.map +1 -1
  446. package/dist/server-helpers.js +62 -322
  447. package/dist/server-helpers.js.map +1 -1
  448. package/dist/server.d.ts.map +1 -1
  449. package/dist/server.js +45 -0
  450. package/dist/server.js.map +1 -1
  451. package/dist/storage/_shared.d.ts +9 -0
  452. package/dist/storage/_shared.d.ts.map +1 -1
  453. package/dist/storage/_shared.js +24 -0
  454. package/dist/storage/_shared.js.map +1 -1
  455. package/dist/storage/telemetry/aggregator.d.ts +52 -0
  456. package/dist/storage/telemetry/aggregator.d.ts.map +1 -0
  457. package/dist/storage/telemetry/aggregator.js +188 -0
  458. package/dist/storage/telemetry/aggregator.js.map +1 -0
  459. package/dist/storage/telemetry/anon-id.d.ts +11 -0
  460. package/dist/storage/telemetry/anon-id.d.ts.map +1 -0
  461. package/dist/storage/telemetry/anon-id.js +62 -0
  462. package/dist/storage/telemetry/anon-id.js.map +1 -0
  463. package/dist/storage/telemetry/config.d.ts +37 -0
  464. package/dist/storage/telemetry/config.d.ts.map +1 -0
  465. package/dist/storage/telemetry/config.js +130 -0
  466. package/dist/storage/telemetry/config.js.map +1 -0
  467. package/dist/storage/telemetry/env-profile.d.ts +19 -0
  468. package/dist/storage/telemetry/env-profile.d.ts.map +1 -0
  469. package/dist/storage/telemetry/env-profile.js +67 -0
  470. package/dist/storage/telemetry/env-profile.js.map +1 -0
  471. package/dist/storage/telemetry/payload.d.ts +8 -0
  472. package/dist/storage/telemetry/payload.d.ts.map +1 -0
  473. package/dist/storage/telemetry/payload.js +22 -0
  474. package/dist/storage/telemetry/payload.js.map +1 -0
  475. package/dist/storage/telemetry/sanitizer.d.ts +48 -0
  476. package/dist/storage/telemetry/sanitizer.d.ts.map +1 -0
  477. package/dist/storage/telemetry/sanitizer.js +82 -0
  478. package/dist/storage/telemetry/sanitizer.js.map +1 -0
  479. package/dist/storage/telemetry/uploader.d.ts +11 -0
  480. package/dist/storage/telemetry/uploader.d.ts.map +1 -0
  481. package/dist/storage/telemetry/uploader.js +140 -0
  482. package/dist/storage/telemetry/uploader.js.map +1 -0
  483. package/dist/storage/usage-tracker.d.ts +13 -0
  484. package/dist/storage/usage-tracker.d.ts.map +1 -1
  485. package/dist/storage/usage-tracker.js +33 -0
  486. package/dist/storage/usage-tracker.js.map +1 -1
  487. package/dist/tools/astro-actions/ast.d.ts +14 -0
  488. package/dist/tools/astro-actions/ast.d.ts.map +1 -0
  489. package/dist/tools/astro-actions/ast.js +75 -0
  490. package/dist/tools/astro-actions/ast.js.map +1 -0
  491. package/dist/tools/astro-actions/audit.d.ts +5 -0
  492. package/dist/tools/astro-actions/audit.d.ts.map +1 -0
  493. package/dist/tools/astro-actions/audit.js +102 -0
  494. package/dist/tools/astro-actions/audit.js.map +1 -0
  495. package/dist/tools/astro-actions/callers.d.ts +9 -0
  496. package/dist/tools/astro-actions/callers.d.ts.map +1 -0
  497. package/dist/tools/astro-actions/callers.js +84 -0
  498. package/dist/tools/astro-actions/callers.js.map +1 -0
  499. package/dist/tools/astro-actions/parser.d.ts +3 -0
  500. package/dist/tools/astro-actions/parser.d.ts.map +1 -0
  501. package/dist/tools/astro-actions/parser.js +156 -0
  502. package/dist/tools/astro-actions/parser.js.map +1 -0
  503. package/dist/tools/astro-actions/types.d.ts +58 -0
  504. package/dist/tools/astro-actions/types.d.ts.map +1 -0
  505. package/dist/tools/astro-actions/types.js +2 -0
  506. package/dist/tools/astro-actions/types.js.map +1 -0
  507. package/dist/tools/astro-actions/zod-ast.d.ts +7 -0
  508. package/dist/tools/astro-actions/zod-ast.d.ts.map +1 -0
  509. package/dist/tools/astro-actions/zod-ast.js +51 -0
  510. package/dist/tools/astro-actions/zod-ast.js.map +1 -0
  511. package/dist/tools/astro-actions.d.ts +6 -46
  512. package/dist/tools/astro-actions.d.ts.map +1 -1
  513. package/dist/tools/astro-actions.js +6 -545
  514. package/dist/tools/astro-actions.js.map +1 -1
  515. package/dist/tools/astro-content-collections/diagnostics.d.ts +3 -0
  516. package/dist/tools/astro-content-collections/diagnostics.d.ts.map +1 -0
  517. package/dist/tools/astro-content-collections/diagnostics.js +277 -0
  518. package/dist/tools/astro-content-collections/diagnostics.js.map +1 -0
  519. package/dist/tools/astro-content-collections/discovery.d.ts +6 -0
  520. package/dist/tools/astro-content-collections/discovery.d.ts.map +1 -0
  521. package/dist/tools/astro-content-collections/discovery.js +152 -0
  522. package/dist/tools/astro-content-collections/discovery.js.map +1 -0
  523. package/dist/tools/astro-content-collections/schema.d.ts +15 -0
  524. package/dist/tools/astro-content-collections/schema.d.ts.map +1 -0
  525. package/dist/tools/astro-content-collections/schema.js +119 -0
  526. package/dist/tools/astro-content-collections/schema.js.map +1 -0
  527. package/dist/tools/astro-content-collections/types.d.ts +61 -0
  528. package/dist/tools/astro-content-collections/types.d.ts.map +1 -0
  529. package/dist/tools/astro-content-collections/types.js +2 -0
  530. package/dist/tools/astro-content-collections/types.js.map +1 -0
  531. package/dist/tools/astro-content-collections.d.ts +5 -40
  532. package/dist/tools/astro-content-collections.d.ts.map +1 -1
  533. package/dist/tools/astro-content-collections.js +42 -449
  534. package/dist/tools/astro-content-collections.js.map +1 -1
  535. package/dist/tools/astro-routes.js +1 -1
  536. package/dist/tools/astro-routes.js.map +1 -1
  537. package/dist/tools/complexity-tools.d.ts +6 -0
  538. package/dist/tools/complexity-tools.d.ts.map +1 -1
  539. package/dist/tools/complexity-tools.js +26 -0
  540. package/dist/tools/complexity-tools.js.map +1 -1
  541. package/dist/tools/context-levels/l0.d.ts +4 -0
  542. package/dist/tools/context-levels/l0.d.ts.map +1 -0
  543. package/dist/tools/context-levels/l0.js +17 -0
  544. package/dist/tools/context-levels/l0.js.map +1 -0
  545. package/dist/tools/context-levels/l1.d.ts +4 -0
  546. package/dist/tools/context-levels/l1.d.ts.map +1 -0
  547. package/dist/tools/context-levels/l1.js +26 -0
  548. package/dist/tools/context-levels/l1.js.map +1 -0
  549. package/dist/tools/context-levels/l2.d.ts +4 -0
  550. package/dist/tools/context-levels/l2.d.ts.map +1 -0
  551. package/dist/tools/context-levels/l2.js +36 -0
  552. package/dist/tools/context-levels/l2.js.map +1 -0
  553. package/dist/tools/context-levels/l3.d.ts +4 -0
  554. package/dist/tools/context-levels/l3.d.ts.map +1 -0
  555. package/dist/tools/context-levels/l3.js +30 -0
  556. package/dist/tools/context-levels/l3.js.map +1 -0
  557. package/dist/tools/context-levels/shared.d.ts +2 -0
  558. package/dist/tools/context-levels/shared.d.ts.map +1 -0
  559. package/dist/tools/context-levels/shared.js +4 -0
  560. package/dist/tools/context-levels/shared.js.map +1 -0
  561. package/dist/tools/context-levels/types.d.ts +34 -0
  562. package/dist/tools/context-levels/types.d.ts.map +1 -0
  563. package/dist/tools/context-levels/types.js +2 -0
  564. package/dist/tools/context-levels/types.js.map +1 -0
  565. package/dist/tools/context-tools.d.ts +2 -34
  566. package/dist/tools/context-tools.d.ts.map +1 -1
  567. package/dist/tools/context-tools.js +11 -127
  568. package/dist/tools/context-tools.js.map +1 -1
  569. package/dist/tools/conversation-cache.d.ts +6 -0
  570. package/dist/tools/conversation-cache.d.ts.map +1 -0
  571. package/dist/tools/conversation-cache.js +29 -0
  572. package/dist/tools/conversation-cache.js.map +1 -0
  573. package/dist/tools/conversation-index-tools.d.ts +39 -0
  574. package/dist/tools/conversation-index-tools.d.ts.map +1 -0
  575. package/dist/tools/conversation-index-tools.js +136 -0
  576. package/dist/tools/conversation-index-tools.js.map +1 -0
  577. package/dist/tools/conversation-paths.d.ts +4 -0
  578. package/dist/tools/conversation-paths.d.ts.map +1 -0
  579. package/dist/tools/conversation-paths.js +15 -0
  580. package/dist/tools/conversation-paths.js.map +1 -0
  581. package/dist/tools/conversation-search-tools.d.ts +52 -0
  582. package/dist/tools/conversation-search-tools.d.ts.map +1 -0
  583. package/dist/tools/conversation-search-tools.js +229 -0
  584. package/dist/tools/conversation-search-tools.js.map +1 -0
  585. package/dist/tools/conversation-tools.d.ts +6 -112
  586. package/dist/tools/conversation-tools.d.ts.map +1 -1
  587. package/dist/tools/conversation-tools.js +4 -425
  588. package/dist/tools/conversation-tools.js.map +1 -1
  589. package/dist/tools/cross-repo-outbound-lexer/call-detectors.d.ts +5 -0
  590. package/dist/tools/cross-repo-outbound-lexer/call-detectors.d.ts.map +1 -0
  591. package/dist/tools/cross-repo-outbound-lexer/call-detectors.js +76 -0
  592. package/dist/tools/cross-repo-outbound-lexer/call-detectors.js.map +1 -0
  593. package/dist/tools/cross-repo-outbound-lexer/context.d.ts +18 -0
  594. package/dist/tools/cross-repo-outbound-lexer/context.d.ts.map +1 -0
  595. package/dist/tools/cross-repo-outbound-lexer/context.js +33 -0
  596. package/dist/tools/cross-repo-outbound-lexer/context.js.map +1 -0
  597. package/dist/tools/cross-repo-outbound-lexer/literal-readers.d.ts +6 -0
  598. package/dist/tools/cross-repo-outbound-lexer/literal-readers.d.ts.map +1 -0
  599. package/dist/tools/cross-repo-outbound-lexer/literal-readers.js +65 -0
  600. package/dist/tools/cross-repo-outbound-lexer/literal-readers.js.map +1 -0
  601. package/dist/tools/cross-repo-outbound-lexer/non-code-states.d.ts +3 -0
  602. package/dist/tools/cross-repo-outbound-lexer/non-code-states.d.ts.map +1 -0
  603. package/dist/tools/cross-repo-outbound-lexer/non-code-states.js +103 -0
  604. package/dist/tools/cross-repo-outbound-lexer/non-code-states.js.map +1 -0
  605. package/dist/tools/cross-repo-outbound-lexer/template-reader.d.ts +3 -0
  606. package/dist/tools/cross-repo-outbound-lexer/template-reader.d.ts.map +1 -0
  607. package/dist/tools/cross-repo-outbound-lexer/template-reader.js +82 -0
  608. package/dist/tools/cross-repo-outbound-lexer/template-reader.js.map +1 -0
  609. package/dist/tools/cross-repo-outbound-lexer/types.d.ts +18 -0
  610. package/dist/tools/cross-repo-outbound-lexer/types.d.ts.map +1 -0
  611. package/dist/tools/cross-repo-outbound-lexer/types.js +2 -0
  612. package/dist/tools/cross-repo-outbound-lexer/types.js.map +1 -0
  613. package/dist/tools/cross-repo-outbound-lexer.d.ts +5 -31
  614. package/dist/tools/cross-repo-outbound-lexer.d.ts.map +1 -1
  615. package/dist/tools/cross-repo-outbound-lexer.js +75 -575
  616. package/dist/tools/cross-repo-outbound-lexer.js.map +1 -1
  617. package/dist/tools/dependency-audit-freshness-tools.d.ts +3 -0
  618. package/dist/tools/dependency-audit-freshness-tools.d.ts.map +1 -0
  619. package/dist/tools/dependency-audit-freshness-tools.js +62 -0
  620. package/dist/tools/dependency-audit-freshness-tools.js.map +1 -0
  621. package/dist/tools/dependency-audit-license-tools.d.ts +5 -0
  622. package/dist/tools/dependency-audit-license-tools.d.ts.map +1 -0
  623. package/dist/tools/dependency-audit-license-tools.js +75 -0
  624. package/dist/tools/dependency-audit-license-tools.js.map +1 -0
  625. package/dist/tools/dependency-audit-lockfile-tools.d.ts +3 -0
  626. package/dist/tools/dependency-audit-lockfile-tools.d.ts.map +1 -0
  627. package/dist/tools/dependency-audit-lockfile-tools.js +147 -0
  628. package/dist/tools/dependency-audit-lockfile-tools.js.map +1 -0
  629. package/dist/tools/dependency-audit-tools.d.ts +2 -54
  630. package/dist/tools/dependency-audit-tools.d.ts.map +1 -1
  631. package/dist/tools/dependency-audit-tools.js +69 -484
  632. package/dist/tools/dependency-audit-tools.js.map +1 -1
  633. package/dist/tools/dependency-audit-types.d.ts +65 -0
  634. package/dist/tools/dependency-audit-types.d.ts.map +1 -0
  635. package/dist/tools/dependency-audit-types.js +19 -0
  636. package/dist/tools/dependency-audit-types.js.map +1 -0
  637. package/dist/tools/dependency-audit-vulnerability-tools.d.ts +4 -0
  638. package/dist/tools/dependency-audit-vulnerability-tools.d.ts.map +1 -0
  639. package/dist/tools/dependency-audit-vulnerability-tools.js +103 -0
  640. package/dist/tools/dependency-audit-vulnerability-tools.js.map +1 -0
  641. package/dist/tools/diff-tools.d.ts.map +1 -1
  642. package/dist/tools/diff-tools.js +5 -7
  643. package/dist/tools/diff-tools.js.map +1 -1
  644. package/dist/tools/impact-tools.d.ts.map +1 -1
  645. package/dist/tools/impact-tools.js +5 -4
  646. package/dist/tools/impact-tools.js.map +1 -1
  647. package/dist/tools/index-shared.d.ts +17 -0
  648. package/dist/tools/index-shared.d.ts.map +1 -0
  649. package/dist/tools/index-shared.js +18 -0
  650. package/dist/tools/index-shared.js.map +1 -0
  651. package/dist/tools/index-tools/file-indexer.d.ts +27 -0
  652. package/dist/tools/index-tools/file-indexer.d.ts.map +1 -0
  653. package/dist/tools/index-tools/file-indexer.js +223 -0
  654. package/dist/tools/index-tools/file-indexer.js.map +1 -0
  655. package/dist/tools/index-tools/folder-indexer.d.ts +21 -0
  656. package/dist/tools/index-tools/folder-indexer.d.ts.map +1 -0
  657. package/dist/tools/index-tools/folder-indexer.js +399 -0
  658. package/dist/tools/index-tools/folder-indexer.js.map +1 -0
  659. package/dist/tools/index-tools/folder-merge.d.ts +23 -0
  660. package/dist/tools/index-tools/folder-merge.d.ts.map +1 -0
  661. package/dist/tools/index-tools/folder-merge.js +205 -0
  662. package/dist/tools/index-tools/folder-merge.js.map +1 -0
  663. package/dist/tools/index-tools/parse.d.ts +35 -0
  664. package/dist/tools/index-tools/parse.d.ts.map +1 -0
  665. package/dist/tools/index-tools/parse.js +262 -0
  666. package/dist/tools/index-tools/parse.js.map +1 -0
  667. package/dist/tools/index-tools/registry.d.ts +40 -0
  668. package/dist/tools/index-tools/registry.d.ts.map +1 -0
  669. package/dist/tools/index-tools/registry.js +258 -0
  670. package/dist/tools/index-tools/registry.js.map +1 -0
  671. package/dist/tools/index-tools/snapshots.d.ts +51 -0
  672. package/dist/tools/index-tools/snapshots.d.ts.map +1 -0
  673. package/dist/tools/index-tools/snapshots.js +223 -0
  674. package/dist/tools/index-tools/snapshots.js.map +1 -0
  675. package/dist/tools/index-tools/state.d.ts +8 -0
  676. package/dist/tools/index-tools/state.d.ts.map +1 -0
  677. package/dist/tools/index-tools/state.js +6 -0
  678. package/dist/tools/index-tools/state.js.map +1 -0
  679. package/dist/tools/index-tools/types.d.ts +20 -0
  680. package/dist/tools/index-tools/types.d.ts.map +1 -0
  681. package/dist/tools/index-tools/types.js +2 -0
  682. package/dist/tools/index-tools/types.js.map +1 -0
  683. package/dist/tools/index-tools/watcher.d.ts +10 -0
  684. package/dist/tools/index-tools/watcher.d.ts.map +1 -0
  685. package/dist/tools/index-tools/watcher.js +130 -0
  686. package/dist/tools/index-tools/watcher.js.map +1 -0
  687. package/dist/tools/index-tools.d.ts +16 -152
  688. package/dist/tools/index-tools.d.ts.map +1 -1
  689. package/dist/tools/index-tools.js +12 -1674
  690. package/dist/tools/index-tools.js.map +1 -1
  691. package/dist/tools/kotlin-extension-tools.d.ts +16 -0
  692. package/dist/tools/kotlin-extension-tools.d.ts.map +1 -0
  693. package/dist/tools/kotlin-extension-tools.js +31 -0
  694. package/dist/tools/kotlin-extension-tools.js.map +1 -0
  695. package/dist/tools/kotlin-flow-tools.d.ts +12 -0
  696. package/dist/tools/kotlin-flow-tools.d.ts.map +1 -0
  697. package/dist/tools/kotlin-flow-tools.js +72 -0
  698. package/dist/tools/kotlin-flow-tools.js.map +1 -0
  699. package/dist/tools/kotlin-kmp-tools.d.ts +29 -0
  700. package/dist/tools/kotlin-kmp-tools.d.ts.map +1 -0
  701. package/dist/tools/kotlin-kmp-tools.js +87 -0
  702. package/dist/tools/kotlin-kmp-tools.js.map +1 -0
  703. package/dist/tools/kotlin-sealed-tools.d.ts +27 -0
  704. package/dist/tools/kotlin-sealed-tools.d.ts.map +1 -0
  705. package/dist/tools/kotlin-sealed-tools.js +130 -0
  706. package/dist/tools/kotlin-sealed-tools.js.map +1 -0
  707. package/dist/tools/kotlin-suspend-tools.d.ts +24 -0
  708. package/dist/tools/kotlin-suspend-tools.d.ts.map +1 -0
  709. package/dist/tools/kotlin-suspend-tools.js +161 -0
  710. package/dist/tools/kotlin-suspend-tools.js.map +1 -0
  711. package/dist/tools/kotlin-tools.d.ts +6 -141
  712. package/dist/tools/kotlin-tools.d.ts.map +1 -1
  713. package/dist/tools/kotlin-tools.js +6 -571
  714. package/dist/tools/kotlin-tools.js.map +1 -1
  715. package/dist/tools/nest-audit-tools.d.ts +43 -0
  716. package/dist/tools/nest-audit-tools.d.ts.map +1 -0
  717. package/dist/tools/nest-audit-tools.js +232 -0
  718. package/dist/tools/nest-audit-tools.js.map +1 -0
  719. package/dist/tools/nest-di-tools.d.ts +32 -0
  720. package/dist/tools/nest-di-tools.d.ts.map +1 -0
  721. package/dist/tools/nest-di-tools.js +161 -0
  722. package/dist/tools/nest-di-tools.js.map +1 -0
  723. package/dist/tools/nest-guard-tools.d.ts +34 -0
  724. package/dist/tools/nest-guard-tools.d.ts.map +1 -0
  725. package/dist/tools/nest-guard-tools.js +240 -0
  726. package/dist/tools/nest-guard-tools.js.map +1 -0
  727. package/dist/tools/nest-lifecycle-tools.d.ts +16 -0
  728. package/dist/tools/nest-lifecycle-tools.d.ts.map +1 -0
  729. package/dist/tools/nest-lifecycle-tools.js +54 -0
  730. package/dist/tools/nest-lifecycle-tools.js.map +1 -0
  731. package/dist/tools/nest-module-tools.d.ts +28 -0
  732. package/dist/tools/nest-module-tools.d.ts.map +1 -0
  733. package/dist/tools/nest-module-tools.js +86 -0
  734. package/dist/tools/nest-module-tools.js.map +1 -0
  735. package/dist/tools/nest-pipeline-tools.d.ts +32 -0
  736. package/dist/tools/nest-pipeline-tools.d.ts.map +1 -0
  737. package/dist/tools/nest-pipeline-tools.js +122 -0
  738. package/dist/tools/nest-pipeline-tools.js.map +1 -0
  739. package/dist/tools/nest-route-tools.d.ts +43 -0
  740. package/dist/tools/nest-route-tools.d.ts.map +1 -0
  741. package/dist/tools/nest-route-tools.js +261 -0
  742. package/dist/tools/nest-route-tools.js.map +1 -0
  743. package/dist/tools/nest-shared-tools.d.ts +13 -0
  744. package/dist/tools/nest-shared-tools.d.ts.map +1 -0
  745. package/dist/tools/nest-shared-tools.js +36 -0
  746. package/dist/tools/nest-shared-tools.js.map +1 -0
  747. package/dist/tools/nest-tools.d.ts +18 -195
  748. package/dist/tools/nest-tools.d.ts.map +1 -1
  749. package/dist/tools/nest-tools.js +11 -1140
  750. package/dist/tools/nest-tools.js.map +1 -1
  751. package/dist/tools/pattern-registry.d.ts +4 -0
  752. package/dist/tools/pattern-registry.d.ts.map +1 -0
  753. package/dist/tools/pattern-registry.js +3 -0
  754. package/dist/tools/pattern-registry.js.map +1 -0
  755. package/dist/tools/pattern-tools.d.ts +5 -46
  756. package/dist/tools/pattern-tools.d.ts.map +1 -1
  757. package/dist/tools/pattern-tools.js +4 -1102
  758. package/dist/tools/pattern-tools.js.map +1 -1
  759. package/dist/tools/patterns/adapters/astro.d.ts +3 -0
  760. package/dist/tools/patterns/adapters/astro.d.ts.map +1 -0
  761. package/dist/tools/patterns/adapters/astro.js +56 -0
  762. package/dist/tools/patterns/adapters/astro.js.map +1 -0
  763. package/dist/tools/patterns/adapters/common.d.ts +3 -0
  764. package/dist/tools/patterns/adapters/common.d.ts.map +1 -0
  765. package/dist/tools/patterns/adapters/common.js +38 -0
  766. package/dist/tools/patterns/adapters/common.js.map +1 -0
  767. package/dist/tools/patterns/adapters/database.d.ts +3 -0
  768. package/dist/tools/patterns/adapters/database.d.ts.map +1 -0
  769. package/dist/tools/patterns/adapters/database.js +32 -0
  770. package/dist/tools/patterns/adapters/database.js.map +1 -0
  771. package/dist/tools/patterns/adapters/hono.d.ts +3 -0
  772. package/dist/tools/patterns/adapters/hono.d.ts.map +1 -0
  773. package/dist/tools/patterns/adapters/hono.js +32 -0
  774. package/dist/tools/patterns/adapters/hono.js.map +1 -0
  775. package/dist/tools/patterns/adapters/kotlin.d.ts +3 -0
  776. package/dist/tools/patterns/adapters/kotlin.d.ts.map +1 -0
  777. package/dist/tools/patterns/adapters/kotlin.js +50 -0
  778. package/dist/tools/patterns/adapters/kotlin.js.map +1 -0
  779. package/dist/tools/patterns/adapters/nest.d.ts +3 -0
  780. package/dist/tools/patterns/adapters/nest.d.ts.map +1 -0
  781. package/dist/tools/patterns/adapters/nest.js +122 -0
  782. package/dist/tools/patterns/adapters/nest.js.map +1 -0
  783. package/dist/tools/patterns/adapters/nextjs.d.ts +4 -0
  784. package/dist/tools/patterns/adapters/nextjs.d.ts.map +1 -0
  785. package/dist/tools/patterns/adapters/nextjs.js +59 -0
  786. package/dist/tools/patterns/adapters/nextjs.js.map +1 -0
  787. package/dist/tools/patterns/adapters/php.d.ts +3 -0
  788. package/dist/tools/patterns/adapters/php.d.ts.map +1 -0
  789. package/dist/tools/patterns/adapters/php.js +157 -0
  790. package/dist/tools/patterns/adapters/php.js.map +1 -0
  791. package/dist/tools/patterns/adapters/python.d.ts +3 -0
  792. package/dist/tools/patterns/adapters/python.d.ts.map +1 -0
  793. package/dist/tools/patterns/adapters/python.js +72 -0
  794. package/dist/tools/patterns/adapters/python.js.map +1 -0
  795. package/dist/tools/patterns/adapters/react.d.ts +4 -0
  796. package/dist/tools/patterns/adapters/react.d.ts.map +1 -0
  797. package/dist/tools/patterns/adapters/react.js +345 -0
  798. package/dist/tools/patterns/adapters/react.js.map +1 -0
  799. package/dist/tools/patterns/catalog.d.ts +8 -0
  800. package/dist/tools/patterns/catalog.d.ts.map +1 -0
  801. package/dist/tools/patterns/catalog.js +30 -0
  802. package/dist/tools/patterns/catalog.js.map +1 -0
  803. package/dist/tools/patterns/execution.d.ts +38 -0
  804. package/dist/tools/patterns/execution.d.ts.map +1 -0
  805. package/dist/tools/patterns/execution.js +298 -0
  806. package/dist/tools/patterns/execution.js.map +1 -0
  807. package/dist/tools/patterns/types.d.ts +13 -0
  808. package/dist/tools/patterns/types.d.ts.map +1 -0
  809. package/dist/tools/patterns/types.js +2 -0
  810. package/dist/tools/patterns/types.js.map +1 -0
  811. package/dist/tools/pg-drift-compare.d.ts +3 -0
  812. package/dist/tools/pg-drift-compare.d.ts.map +1 -0
  813. package/dist/tools/pg-drift-compare.js +30 -0
  814. package/dist/tools/pg-drift-compare.js.map +1 -0
  815. package/dist/tools/pg-drift-schema.d.ts +5 -0
  816. package/dist/tools/pg-drift-schema.d.ts.map +1 -0
  817. package/dist/tools/pg-drift-schema.js +28 -0
  818. package/dist/tools/pg-drift-schema.js.map +1 -0
  819. package/dist/tools/pg-drift-types.d.ts +25 -0
  820. package/dist/tools/pg-drift-types.d.ts.map +1 -0
  821. package/dist/tools/pg-drift-types.js +2 -0
  822. package/dist/tools/pg-drift-types.js.map +1 -0
  823. package/dist/tools/pg-drift.d.ts +5 -0
  824. package/dist/tools/pg-drift.d.ts.map +1 -0
  825. package/dist/tools/pg-drift.js +30 -0
  826. package/dist/tools/pg-drift.js.map +1 -0
  827. package/dist/tools/pg-introspect-formatters.d.ts +7 -0
  828. package/dist/tools/pg-introspect-formatters.d.ts.map +1 -0
  829. package/dist/tools/pg-introspect-formatters.js +66 -0
  830. package/dist/tools/pg-introspect-formatters.js.map +1 -0
  831. package/dist/tools/pg-introspect-tools.d.ts +5 -146
  832. package/dist/tools/pg-introspect-tools.d.ts.map +1 -1
  833. package/dist/tools/pg-introspect-tools.js +3 -395
  834. package/dist/tools/pg-introspect-tools.js.map +1 -1
  835. package/dist/tools/pg-introspection.d.ts +90 -0
  836. package/dist/tools/pg-introspection.d.ts.map +1 -0
  837. package/dist/tools/pg-introspection.js +288 -0
  838. package/dist/tools/pg-introspection.js.map +1 -0
  839. package/dist/tools/php-active-record-tools.d.ts +22 -0
  840. package/dist/tools/php-active-record-tools.d.ts.map +1 -0
  841. package/dist/tools/php-active-record-tools.js +165 -0
  842. package/dist/tools/php-active-record-tools.js.map +1 -0
  843. package/dist/tools/php-event-tools.d.ts +21 -0
  844. package/dist/tools/php-event-tools.d.ts.map +1 -0
  845. package/dist/tools/php-event-tools.js +205 -0
  846. package/dist/tools/php-event-tools.js.map +1 -0
  847. package/dist/tools/php-god-model-tools.d.ts +34 -0
  848. package/dist/tools/php-god-model-tools.d.ts.map +1 -0
  849. package/dist/tools/php-god-model-tools.js +88 -0
  850. package/dist/tools/php-god-model-tools.js.map +1 -0
  851. package/dist/tools/php-import-utils.d.ts +10 -0
  852. package/dist/tools/php-import-utils.d.ts.map +1 -0
  853. package/dist/tools/php-import-utils.js +71 -0
  854. package/dist/tools/php-import-utils.js.map +1 -0
  855. package/dist/tools/php-namespace-tools.d.ts +10 -0
  856. package/dist/tools/php-namespace-tools.d.ts.map +1 -0
  857. package/dist/tools/php-namespace-tools.js +98 -0
  858. package/dist/tools/php-namespace-tools.js.map +1 -0
  859. package/dist/tools/php-nplus1-tools.d.ts +27 -0
  860. package/dist/tools/php-nplus1-tools.d.ts.map +1 -0
  861. package/dist/tools/php-nplus1-tools.js +191 -0
  862. package/dist/tools/php-nplus1-tools.js.map +1 -0
  863. package/dist/tools/php-project-audit-tools.d.ts +31 -0
  864. package/dist/tools/php-project-audit-tools.d.ts.map +1 -0
  865. package/dist/tools/php-project-audit-tools.js +173 -0
  866. package/dist/tools/php-project-audit-tools.js.map +1 -0
  867. package/dist/tools/php-security-tools.d.ts +24 -0
  868. package/dist/tools/php-security-tools.d.ts.map +1 -0
  869. package/dist/tools/php-security-tools.js +172 -0
  870. package/dist/tools/php-security-tools.js.map +1 -0
  871. package/dist/tools/php-service-tools.d.ts +25 -0
  872. package/dist/tools/php-service-tools.d.ts.map +1 -0
  873. package/dist/tools/php-service-tools.js +326 -0
  874. package/dist/tools/php-service-tools.js.map +1 -0
  875. package/dist/tools/php-tools.d.ts +21 -255
  876. package/dist/tools/php-tools.d.ts.map +1 -1
  877. package/dist/tools/php-tools.js +12 -1423
  878. package/dist/tools/php-tools.js.map +1 -1
  879. package/dist/tools/php-view-tools.d.ts +76 -0
  880. package/dist/tools/php-view-tools.d.ts.map +1 -0
  881. package/dist/tools/php-view-tools.js +413 -0
  882. package/dist/tools/php-view-tools.js.map +1 -0
  883. package/dist/tools/plan-turn/formatter.d.ts +3 -0
  884. package/dist/tools/plan-turn/formatter.d.ts.map +1 -0
  885. package/dist/tools/plan-turn/formatter.js +88 -0
  886. package/dist/tools/plan-turn/formatter.js.map +1 -0
  887. package/dist/tools/plan-turn/framework-context.d.ts +5 -0
  888. package/dist/tools/plan-turn/framework-context.d.ts.map +1 -0
  889. package/dist/tools/plan-turn/framework-context.js +68 -0
  890. package/dist/tools/plan-turn/framework-context.js.map +1 -0
  891. package/dist/tools/plan-turn/framework-data.d.ts +5 -0
  892. package/dist/tools/plan-turn/framework-data.d.ts.map +1 -0
  893. package/dist/tools/plan-turn/framework-data.js +48 -0
  894. package/dist/tools/plan-turn/framework-data.js.map +1 -0
  895. package/dist/tools/plan-turn/orchestrator.d.ts +4 -0
  896. package/dist/tools/plan-turn/orchestrator.d.ts.map +1 -0
  897. package/dist/tools/plan-turn/orchestrator.js +262 -0
  898. package/dist/tools/plan-turn/orchestrator.js.map +1 -0
  899. package/dist/tools/plan-turn/query-parser.d.ts +6 -0
  900. package/dist/tools/plan-turn/query-parser.d.ts.map +1 -0
  901. package/dist/tools/plan-turn/query-parser.js +60 -0
  902. package/dist/tools/plan-turn/query-parser.js.map +1 -0
  903. package/dist/tools/plan-turn/recommendations.d.ts +11 -0
  904. package/dist/tools/plan-turn/recommendations.d.ts.map +1 -0
  905. package/dist/tools/plan-turn/recommendations.js +93 -0
  906. package/dist/tools/plan-turn/recommendations.js.map +1 -0
  907. package/dist/tools/plan-turn/stale-index.d.ts +4 -0
  908. package/dist/tools/plan-turn/stale-index.d.ts.map +1 -0
  909. package/dist/tools/plan-turn/stale-index.js +17 -0
  910. package/dist/tools/plan-turn/stale-index.js.map +1 -0
  911. package/dist/tools/plan-turn/types.d.ts +61 -0
  912. package/dist/tools/plan-turn/types.d.ts.map +1 -0
  913. package/dist/tools/plan-turn/types.js +2 -0
  914. package/dist/tools/plan-turn/types.js.map +1 -0
  915. package/dist/tools/plan-turn-tools.d.ts +8 -111
  916. package/dist/tools/plan-turn-tools.d.ts.map +1 -1
  917. package/dist/tools/plan-turn-tools.js +6 -696
  918. package/dist/tools/plan-turn-tools.js.map +1 -1
  919. package/dist/tools/project-profile-express.d.ts +3 -0
  920. package/dist/tools/project-profile-express.d.ts.map +1 -0
  921. package/dist/tools/project-profile-express.js +46 -0
  922. package/dist/tools/project-profile-express.js.map +1 -0
  923. package/dist/tools/project-profile-extractors.d.ts +9 -0
  924. package/dist/tools/project-profile-extractors.d.ts.map +1 -0
  925. package/dist/tools/project-profile-extractors.js +312 -0
  926. package/dist/tools/project-profile-extractors.js.map +1 -0
  927. package/dist/tools/project-profile-fs.d.ts +3 -0
  928. package/dist/tools/project-profile-fs.d.ts.map +1 -0
  929. package/dist/tools/project-profile-fs.js +19 -0
  930. package/dist/tools/project-profile-fs.js.map +1 -0
  931. package/dist/tools/project-profile-hono.d.ts +13 -0
  932. package/dist/tools/project-profile-hono.d.ts.map +1 -0
  933. package/dist/tools/project-profile-hono.js +110 -0
  934. package/dist/tools/project-profile-hono.js.map +1 -0
  935. package/dist/tools/project-profile-imports.d.ts +6 -0
  936. package/dist/tools/project-profile-imports.d.ts.map +1 -0
  937. package/dist/tools/project-profile-imports.js +95 -0
  938. package/dist/tools/project-profile-imports.js.map +1 -0
  939. package/dist/tools/project-profile-nest.d.ts +8 -0
  940. package/dist/tools/project-profile-nest.d.ts.map +1 -0
  941. package/dist/tools/project-profile-nest.js +352 -0
  942. package/dist/tools/project-profile-nest.js.map +1 -0
  943. package/dist/tools/project-profile-next.d.ts +5 -0
  944. package/dist/tools/project-profile-next.d.ts.map +1 -0
  945. package/dist/tools/project-profile-next.js +92 -0
  946. package/dist/tools/project-profile-next.js.map +1 -0
  947. package/dist/tools/project-profile-persistence.d.ts +3 -0
  948. package/dist/tools/project-profile-persistence.d.ts.map +1 -0
  949. package/dist/tools/project-profile-persistence.js +19 -0
  950. package/dist/tools/project-profile-persistence.js.map +1 -0
  951. package/dist/tools/project-profile-php.d.ts +8 -0
  952. package/dist/tools/project-profile-php.d.ts.map +1 -0
  953. package/dist/tools/project-profile-php.js +76 -0
  954. package/dist/tools/project-profile-php.js.map +1 -0
  955. package/dist/tools/project-profile-python.d.ts +5 -0
  956. package/dist/tools/project-profile-python.d.ts.map +1 -0
  957. package/dist/tools/project-profile-python.js +51 -0
  958. package/dist/tools/project-profile-python.js.map +1 -0
  959. package/dist/tools/project-profile-react.d.ts +6 -0
  960. package/dist/tools/project-profile-react.d.ts.map +1 -0
  961. package/dist/tools/project-profile-react.js +106 -0
  962. package/dist/tools/project-profile-react.js.map +1 -0
  963. package/dist/tools/project-profile-stack.d.ts +3 -0
  964. package/dist/tools/project-profile-stack.d.ts.map +1 -0
  965. package/dist/tools/project-profile-stack.js +354 -0
  966. package/dist/tools/project-profile-stack.js.map +1 -0
  967. package/dist/tools/project-profile-summary.d.ts +30 -0
  968. package/dist/tools/project-profile-summary.d.ts.map +1 -0
  969. package/dist/tools/project-profile-summary.js +112 -0
  970. package/dist/tools/project-profile-summary.js.map +1 -0
  971. package/dist/tools/project-profile-types.d.ts +315 -0
  972. package/dist/tools/project-profile-types.d.ts.map +1 -0
  973. package/dist/tools/project-profile-types.js +2 -0
  974. package/dist/tools/project-profile-types.js.map +1 -0
  975. package/dist/tools/project-tools.d.ts +20 -383
  976. package/dist/tools/project-tools.d.ts.map +1 -1
  977. package/dist/tools/project-tools.js +37 -1621
  978. package/dist/tools/project-tools.js.map +1 -1
  979. package/dist/tools/python-audit/aggregate.d.ts +3 -0
  980. package/dist/tools/python-audit/aggregate.d.ts.map +1 -0
  981. package/dist/tools/python-audit/aggregate.js +103 -0
  982. package/dist/tools/python-audit/aggregate.js.map +1 -0
  983. package/dist/tools/python-audit/checks/anti-patterns.d.ts +6 -0
  984. package/dist/tools/python-audit/checks/anti-patterns.d.ts.map +1 -0
  985. package/dist/tools/python-audit/checks/anti-patterns.js +14 -0
  986. package/dist/tools/python-audit/checks/anti-patterns.js.map +1 -0
  987. package/dist/tools/python-audit/checks/celery.d.ts +2 -0
  988. package/dist/tools/python-audit/checks/celery.d.ts.map +1 -0
  989. package/dist/tools/python-audit/checks/celery.js +5 -0
  990. package/dist/tools/python-audit/checks/celery.js.map +1 -0
  991. package/dist/tools/python-audit/checks/circular-imports.d.ts +2 -0
  992. package/dist/tools/python-audit/checks/circular-imports.d.ts.map +1 -0
  993. package/dist/tools/python-audit/checks/circular-imports.js +5 -0
  994. package/dist/tools/python-audit/checks/circular-imports.js.map +1 -0
  995. package/dist/tools/python-audit/checks/dead-code.d.ts +2 -0
  996. package/dist/tools/python-audit/checks/dead-code.d.ts.map +1 -0
  997. package/dist/tools/python-audit/checks/dead-code.js +5 -0
  998. package/dist/tools/python-audit/checks/dead-code.js.map +1 -0
  999. package/dist/tools/python-audit/checks/dependencies.d.ts +2 -0
  1000. package/dist/tools/python-audit/checks/dependencies.d.ts.map +1 -0
  1001. package/dist/tools/python-audit/checks/dependencies.js +5 -0
  1002. package/dist/tools/python-audit/checks/dependencies.js.map +1 -0
  1003. package/dist/tools/python-audit/checks/django-settings.d.ts +2 -0
  1004. package/dist/tools/python-audit/checks/django-settings.d.ts.map +1 -0
  1005. package/dist/tools/python-audit/checks/django-settings.js +5 -0
  1006. package/dist/tools/python-audit/checks/django-settings.js.map +1 -0
  1007. package/dist/tools/python-audit/checks/framework-wiring.d.ts +2 -0
  1008. package/dist/tools/python-audit/checks/framework-wiring.d.ts.map +1 -0
  1009. package/dist/tools/python-audit/checks/framework-wiring.js +5 -0
  1010. package/dist/tools/python-audit/checks/framework-wiring.js.map +1 -0
  1011. package/dist/tools/python-audit/checks/pytest-fixtures.d.ts +2 -0
  1012. package/dist/tools/python-audit/checks/pytest-fixtures.d.ts.map +1 -0
  1013. package/dist/tools/python-audit/checks/pytest-fixtures.js +5 -0
  1014. package/dist/tools/python-audit/checks/pytest-fixtures.js.map +1 -0
  1015. package/dist/tools/python-audit/runner.d.ts +5 -0
  1016. package/dist/tools/python-audit/runner.d.ts.map +1 -0
  1017. package/dist/tools/python-audit/runner.js +18 -0
  1018. package/dist/tools/python-audit/runner.js.map +1 -0
  1019. package/dist/tools/python-audit/types.d.ts +43 -0
  1020. package/dist/tools/python-audit/types.d.ts.map +1 -0
  1021. package/dist/tools/python-audit/types.js +2 -0
  1022. package/dist/tools/python-audit/types.js.map +1 -0
  1023. package/dist/tools/python-audit.d.ts +3 -39
  1024. package/dist/tools/python-audit.d.ts.map +1 -1
  1025. package/dist/tools/python-audit.js +34 -233
  1026. package/dist/tools/python-audit.js.map +1 -1
  1027. package/dist/tools/react-compiler-tools.d.ts +37 -0
  1028. package/dist/tools/react-compiler-tools.d.ts.map +1 -0
  1029. package/dist/tools/react-compiler-tools.js +104 -0
  1030. package/dist/tools/react-compiler-tools.js.map +1 -0
  1031. package/dist/tools/react-component-tree-tools.d.ts +58 -0
  1032. package/dist/tools/react-component-tree-tools.d.ts.map +1 -0
  1033. package/dist/tools/react-component-tree-tools.js +292 -0
  1034. package/dist/tools/react-component-tree-tools.js.map +1 -0
  1035. package/dist/tools/react-context-tools.d.ts +41 -0
  1036. package/dist/tools/react-context-tools.d.ts.map +1 -0
  1037. package/dist/tools/react-context-tools.js +76 -0
  1038. package/dist/tools/react-context-tools.js.map +1 -0
  1039. package/dist/tools/react-hooks-tools.d.ts +58 -0
  1040. package/dist/tools/react-hooks-tools.d.ts.map +1 -0
  1041. package/dist/tools/react-hooks-tools.js +144 -0
  1042. package/dist/tools/react-hooks-tools.js.map +1 -0
  1043. package/dist/tools/react-quickstart-tools.d.ts +59 -0
  1044. package/dist/tools/react-quickstart-tools.d.ts.map +1 -0
  1045. package/dist/tools/react-quickstart-tools.js +164 -0
  1046. package/dist/tools/react-quickstart-tools.js.map +1 -0
  1047. package/dist/tools/react-render-tools.d.ts +75 -0
  1048. package/dist/tools/react-render-tools.d.ts.map +1 -0
  1049. package/dist/tools/react-render-tools.js +234 -0
  1050. package/dist/tools/react-render-tools.js.map +1 -0
  1051. package/dist/tools/react-shared-tools.d.ts +5 -0
  1052. package/dist/tools/react-shared-tools.d.ts.map +1 -0
  1053. package/dist/tools/react-shared-tools.js +12 -0
  1054. package/dist/tools/react-shared-tools.js.map +1 -0
  1055. package/dist/tools/react-suspense-tools.d.ts +29 -0
  1056. package/dist/tools/react-suspense-tools.d.ts.map +1 -0
  1057. package/dist/tools/react-suspense-tools.js +269 -0
  1058. package/dist/tools/react-suspense-tools.js.map +1 -0
  1059. package/dist/tools/react-tools.d.ts +19 -340
  1060. package/dist/tools/react-tools.d.ts.map +1 -1
  1061. package/dist/tools/react-tools.js +10 -1263
  1062. package/dist/tools/react-tools.js.map +1 -1
  1063. package/dist/tools/review-diff/check-runner.d.ts +5 -0
  1064. package/dist/tools/review-diff/check-runner.d.ts.map +1 -0
  1065. package/dist/tools/review-diff/check-runner.js +26 -0
  1066. package/dist/tools/review-diff/check-runner.js.map +1 -0
  1067. package/dist/tools/review-diff/checks/astro-hydration.d.ts +8 -0
  1068. package/dist/tools/review-diff/checks/astro-hydration.d.ts.map +1 -0
  1069. package/dist/tools/review-diff/checks/astro-hydration.js +54 -0
  1070. package/dist/tools/review-diff/checks/astro-hydration.js.map +1 -0
  1071. package/dist/tools/review-diff/checks/blast-radius.d.ts +7 -0
  1072. package/dist/tools/review-diff/checks/blast-radius.d.ts.map +1 -0
  1073. package/dist/tools/review-diff/checks/blast-radius.js +39 -0
  1074. package/dist/tools/review-diff/checks/blast-radius.js.map +1 -0
  1075. package/dist/tools/review-diff/checks/breaking.d.ts +13 -0
  1076. package/dist/tools/review-diff/checks/breaking.d.ts.map +1 -0
  1077. package/dist/tools/review-diff/checks/breaking.js +115 -0
  1078. package/dist/tools/review-diff/checks/breaking.js.map +1 -0
  1079. package/dist/tools/review-diff/checks/bug-patterns.d.ts +8 -0
  1080. package/dist/tools/review-diff/checks/bug-patterns.d.ts.map +1 -0
  1081. package/dist/tools/review-diff/checks/bug-patterns.js +130 -0
  1082. package/dist/tools/review-diff/checks/bug-patterns.js.map +1 -0
  1083. package/dist/tools/review-diff/checks/complexity.d.ts +8 -0
  1084. package/dist/tools/review-diff/checks/complexity.d.ts.map +1 -0
  1085. package/dist/tools/review-diff/checks/complexity.js +41 -0
  1086. package/dist/tools/review-diff/checks/complexity.js.map +1 -0
  1087. package/dist/tools/review-diff/checks/coupling.d.ts +7 -0
  1088. package/dist/tools/review-diff/checks/coupling.d.ts.map +1 -0
  1089. package/dist/tools/review-diff/checks/coupling.js +52 -0
  1090. package/dist/tools/review-diff/checks/coupling.js.map +1 -0
  1091. package/dist/tools/review-diff/checks/dead-code.d.ts +7 -0
  1092. package/dist/tools/review-diff/checks/dead-code.d.ts.map +1 -0
  1093. package/dist/tools/review-diff/checks/dead-code.js +39 -0
  1094. package/dist/tools/review-diff/checks/dead-code.js.map +1 -0
  1095. package/dist/tools/review-diff/checks/hotspots.d.ts +8 -0
  1096. package/dist/tools/review-diff/checks/hotspots.d.ts.map +1 -0
  1097. package/dist/tools/review-diff/checks/hotspots.js +39 -0
  1098. package/dist/tools/review-diff/checks/hotspots.js.map +1 -0
  1099. package/dist/tools/review-diff/checks/secrets.d.ts +7 -0
  1100. package/dist/tools/review-diff/checks/secrets.d.ts.map +1 -0
  1101. package/dist/tools/review-diff/checks/secrets.js +38 -0
  1102. package/dist/tools/review-diff/checks/secrets.js.map +1 -0
  1103. package/dist/tools/review-diff/checks/test-gaps.d.ts +16 -0
  1104. package/dist/tools/review-diff/checks/test-gaps.d.ts.map +1 -0
  1105. package/dist/tools/review-diff/checks/test-gaps.js +77 -0
  1106. package/dist/tools/review-diff/checks/test-gaps.js.map +1 -0
  1107. package/dist/tools/review-diff/constants.d.ts +6 -0
  1108. package/dist/tools/review-diff/constants.d.ts.map +1 -0
  1109. package/dist/tools/review-diff/constants.js +16 -0
  1110. package/dist/tools/review-diff/constants.js.map +1 -0
  1111. package/dist/tools/review-diff/file-pattern.d.ts +2 -0
  1112. package/dist/tools/review-diff/file-pattern.d.ts.map +1 -0
  1113. package/dist/tools/review-diff/file-pattern.js +9 -0
  1114. package/dist/tools/review-diff/file-pattern.js.map +1 -0
  1115. package/dist/tools/review-diff/orchestrator.d.ts +3 -0
  1116. package/dist/tools/review-diff/orchestrator.d.ts.map +1 -0
  1117. package/dist/tools/review-diff/orchestrator.js +173 -0
  1118. package/dist/tools/review-diff/orchestrator.js.map +1 -0
  1119. package/dist/tools/review-diff/scoring.d.ts +31 -0
  1120. package/dist/tools/review-diff/scoring.d.ts.map +1 -0
  1121. package/dist/tools/review-diff/scoring.js +82 -0
  1122. package/dist/tools/review-diff/scoring.js.map +1 -0
  1123. package/dist/tools/review-diff/timeout.d.ts +5 -0
  1124. package/dist/tools/review-diff/timeout.d.ts.map +1 -0
  1125. package/dist/tools/review-diff/timeout.js +14 -0
  1126. package/dist/tools/review-diff/timeout.js.map +1 -0
  1127. package/dist/tools/review-diff/types.d.ts +56 -0
  1128. package/dist/tools/review-diff/types.d.ts.map +1 -0
  1129. package/dist/tools/review-diff/types.js +2 -0
  1130. package/dist/tools/review-diff/types.js.map +1 -0
  1131. package/dist/tools/review-diff-tools.d.ts +19 -147
  1132. package/dist/tools/review-diff-tools.d.ts.map +1 -1
  1133. package/dist/tools/review-diff-tools.js +18 -941
  1134. package/dist/tools/review-diff-tools.js.map +1 -1
  1135. package/dist/tools/route-shared.d.ts +6 -0
  1136. package/dist/tools/route-shared.d.ts.map +1 -0
  1137. package/dist/tools/route-shared.js +37 -0
  1138. package/dist/tools/route-shared.js.map +1 -0
  1139. package/dist/tools/route-tools.d.ts +1 -7
  1140. package/dist/tools/route-tools.d.ts.map +1 -1
  1141. package/dist/tools/route-tools.js +2 -22
  1142. package/dist/tools/route-tools.js.map +1 -1
  1143. package/dist/tools/search-tools/constants.d.ts +33 -0
  1144. package/dist/tools/search-tools/constants.d.ts.map +1 -0
  1145. package/dist/tools/search-tools/constants.js +54 -0
  1146. package/dist/tools/search-tools/constants.js.map +1 -0
  1147. package/dist/tools/search-tools/ripgrep.d.ts +13 -0
  1148. package/dist/tools/search-tools/ripgrep.d.ts.map +1 -0
  1149. package/dist/tools/search-tools/ripgrep.js +138 -0
  1150. package/dist/tools/search-tools/ripgrep.js.map +1 -0
  1151. package/dist/tools/search-tools/semantic-search.d.ts +9 -0
  1152. package/dist/tools/search-tools/semantic-search.d.ts.map +1 -0
  1153. package/dist/tools/search-tools/semantic-search.js +19 -0
  1154. package/dist/tools/search-tools/semantic-search.js.map +1 -0
  1155. package/dist/tools/search-tools/symbol-search.d.ts +4 -0
  1156. package/dist/tools/search-tools/symbol-search.d.ts.map +1 -0
  1157. package/dist/tools/search-tools/symbol-search.js +146 -0
  1158. package/dist/tools/search-tools/symbol-search.js.map +1 -0
  1159. package/dist/tools/search-tools/text-search.d.ts +10 -0
  1160. package/dist/tools/search-tools/text-search.d.ts.map +1 -0
  1161. package/dist/tools/search-tools/text-search.js +260 -0
  1162. package/dist/tools/search-tools/text-search.js.map +1 -0
  1163. package/dist/tools/search-tools/types.d.ts +28 -0
  1164. package/dist/tools/search-tools/types.d.ts.map +1 -0
  1165. package/dist/tools/search-tools/types.js +2 -0
  1166. package/dist/tools/search-tools/types.js.map +1 -0
  1167. package/dist/tools/search-tools/zero-hit.d.ts +3 -0
  1168. package/dist/tools/search-tools/zero-hit.d.ts.map +1 -0
  1169. package/dist/tools/search-tools/zero-hit.js +92 -0
  1170. package/dist/tools/search-tools/zero-hit.js.map +1 -0
  1171. package/dist/tools/search-tools.d.ts +5 -64
  1172. package/dist/tools/search-tools.d.ts.map +1 -1
  1173. package/dist/tools/search-tools.js +4 -770
  1174. package/dist/tools/search-tools.js.map +1 -1
  1175. package/dist/tools/secret-detectors.d.ts +12 -0
  1176. package/dist/tools/secret-detectors.d.ts.map +1 -0
  1177. package/dist/tools/secret-detectors.js +86 -0
  1178. package/dist/tools/secret-detectors.js.map +1 -0
  1179. package/dist/tools/secret-file-scanner.d.ts +7 -0
  1180. package/dist/tools/secret-file-scanner.d.ts.map +1 -0
  1181. package/dist/tools/secret-file-scanner.js +52 -0
  1182. package/dist/tools/secret-file-scanner.js.map +1 -0
  1183. package/dist/tools/secret-scan-cache.d.ts +6 -0
  1184. package/dist/tools/secret-scan-cache.d.ts.map +1 -0
  1185. package/dist/tools/secret-scan-cache.js +14 -0
  1186. package/dist/tools/secret-scan-cache.js.map +1 -0
  1187. package/dist/tools/secret-scan-shared.d.ts +5 -0
  1188. package/dist/tools/secret-scan-shared.d.ts.map +1 -0
  1189. package/dist/tools/secret-scan-shared.js +4 -0
  1190. package/dist/tools/secret-scan-shared.js.map +1 -0
  1191. package/dist/tools/secret-scan-types.d.ts +21 -0
  1192. package/dist/tools/secret-scan-types.d.ts.map +1 -0
  1193. package/dist/tools/secret-scan-types.js +2 -0
  1194. package/dist/tools/secret-scan-types.js.map +1 -0
  1195. package/dist/tools/secret-tools.d.ts +3 -75
  1196. package/dist/tools/secret-tools.d.ts.map +1 -1
  1197. package/dist/tools/secret-tools.js +4 -316
  1198. package/dist/tools/secret-tools.js.map +1 -1
  1199. package/dist/tools/sql-audit-tools.d.ts +42 -0
  1200. package/dist/tools/sql-audit-tools.d.ts.map +1 -0
  1201. package/dist/tools/sql-audit-tools.js +130 -0
  1202. package/dist/tools/sql-audit-tools.js.map +1 -0
  1203. package/dist/tools/sql-column-tools.d.ts +28 -0
  1204. package/dist/tools/sql-column-tools.d.ts.map +1 -0
  1205. package/dist/tools/sql-column-tools.js +58 -0
  1206. package/dist/tools/sql-column-tools.js.map +1 -0
  1207. package/dist/tools/sql-complexity-tools.d.ts +22 -0
  1208. package/dist/tools/sql-complexity-tools.d.ts.map +1 -0
  1209. package/dist/tools/sql-complexity-tools.js +60 -0
  1210. package/dist/tools/sql-complexity-tools.js.map +1 -0
  1211. package/dist/tools/sql-dml-safety-tools.d.ts +26 -0
  1212. package/dist/tools/sql-dml-safety-tools.d.ts.map +1 -0
  1213. package/dist/tools/sql-dml-safety-tools.js +104 -0
  1214. package/dist/tools/sql-dml-safety-tools.js.map +1 -0
  1215. package/dist/tools/sql-drift-tools.d.ts +39 -0
  1216. package/dist/tools/sql-drift-tools.d.ts.map +1 -0
  1217. package/dist/tools/sql-drift-tools.js +238 -0
  1218. package/dist/tools/sql-drift-tools.js.map +1 -0
  1219. package/dist/tools/sql-lint-schema-tools.d.ts +28 -0
  1220. package/dist/tools/sql-lint-schema-tools.d.ts.map +1 -0
  1221. package/dist/tools/sql-lint-schema-tools.js +96 -0
  1222. package/dist/tools/sql-lint-schema-tools.js.map +1 -0
  1223. package/dist/tools/sql-migration-diff-tools.d.ts +24 -0
  1224. package/dist/tools/sql-migration-diff-tools.d.ts.map +1 -0
  1225. package/dist/tools/sql-migration-diff-tools.js +120 -0
  1226. package/dist/tools/sql-migration-diff-tools.js.map +1 -0
  1227. package/dist/tools/sql-orphan-table-tools.d.ts +20 -0
  1228. package/dist/tools/sql-orphan-table-tools.d.ts.map +1 -0
  1229. package/dist/tools/sql-orphan-table-tools.js +70 -0
  1230. package/dist/tools/sql-orphan-table-tools.js.map +1 -0
  1231. package/dist/tools/sql-query-tools.d.ts +32 -0
  1232. package/dist/tools/sql-query-tools.d.ts.map +1 -0
  1233. package/dist/tools/sql-query-tools.js +130 -0
  1234. package/dist/tools/sql-query-tools.js.map +1 -0
  1235. package/dist/tools/sql-schema-tools.d.ts +47 -0
  1236. package/dist/tools/sql-schema-tools.d.ts.map +1 -0
  1237. package/dist/tools/sql-schema-tools.js +202 -0
  1238. package/dist/tools/sql-schema-tools.js.map +1 -0
  1239. package/dist/tools/sql-shared-tools.d.ts +6 -0
  1240. package/dist/tools/sql-shared-tools.d.ts.map +1 -0
  1241. package/dist/tools/sql-shared-tools.js +59 -0
  1242. package/dist/tools/sql-shared-tools.js.map +1 -0
  1243. package/dist/tools/sql-tools.d.ts +25 -296
  1244. package/dist/tools/sql-tools.d.ts.map +1 -1
  1245. package/dist/tools/sql-tools.js +15 -1232
  1246. package/dist/tools/sql-tools.js.map +1 -1
  1247. package/dist/tools/status-tools.js +1 -1
  1248. package/dist/tools/status-tools.js.map +1 -1
  1249. package/dist/tools/workspace-tools.d.ts +1 -1
  1250. package/dist/tools/yii3-migration-categories-application.d.ts +4 -0
  1251. package/dist/tools/yii3-migration-categories-application.d.ts.map +1 -0
  1252. package/dist/tools/yii3-migration-categories-application.js +56 -0
  1253. package/dist/tools/yii3-migration-categories-application.js.map +1 -0
  1254. package/dist/tools/yii3-migration-categories-infrastructure.d.ts +4 -0
  1255. package/dist/tools/yii3-migration-categories-infrastructure.d.ts.map +1 -0
  1256. package/dist/tools/yii3-migration-categories-infrastructure.js +67 -0
  1257. package/dist/tools/yii3-migration-categories-infrastructure.js.map +1 -0
  1258. package/dist/tools/yii3-migration-categories-model-view.d.ts +4 -0
  1259. package/dist/tools/yii3-migration-categories-model-view.d.ts.map +1 -0
  1260. package/dist/tools/yii3-migration-categories-model-view.js +59 -0
  1261. package/dist/tools/yii3-migration-categories-model-view.js.map +1 -0
  1262. package/dist/tools/yii3-migration-categories-runtime.d.ts +4 -0
  1263. package/dist/tools/yii3-migration-categories-runtime.d.ts.map +1 -0
  1264. package/dist/tools/yii3-migration-categories-runtime.js +49 -0
  1265. package/dist/tools/yii3-migration-categories-runtime.js.map +1 -0
  1266. package/dist/tools/yii3-migration-categories.d.ts +5 -0
  1267. package/dist/tools/yii3-migration-categories.d.ts.map +1 -0
  1268. package/dist/tools/yii3-migration-categories.js +18 -0
  1269. package/dist/tools/yii3-migration-categories.js.map +1 -0
  1270. package/dist/tools/yii3-migration-report.d.ts +4 -0
  1271. package/dist/tools/yii3-migration-report.d.ts.map +1 -0
  1272. package/dist/tools/yii3-migration-report.js +88 -0
  1273. package/dist/tools/yii3-migration-report.js.map +1 -0
  1274. package/dist/tools/yii3-migration-scanner.d.ts +28 -0
  1275. package/dist/tools/yii3-migration-scanner.d.ts.map +1 -0
  1276. package/dist/tools/yii3-migration-scanner.js +87 -0
  1277. package/dist/tools/yii3-migration-scanner.js.map +1 -0
  1278. package/dist/tools/yii3-migration-tools.d.ts +4 -73
  1279. package/dist/tools/yii3-migration-tools.d.ts.map +1 -1
  1280. package/dist/tools/yii3-migration-tools.js +5 -433
  1281. package/dist/tools/yii3-migration-tools.js.map +1 -1
  1282. package/dist/tools/yii3-migration-types.d.ts +50 -0
  1283. package/dist/tools/yii3-migration-types.d.ts.map +1 -0
  1284. package/dist/tools/yii3-migration-types.js +3 -0
  1285. package/dist/tools/yii3-migration-types.js.map +1 -0
  1286. package/dist/utils/edge-provenance.d.ts +55 -0
  1287. package/dist/utils/edge-provenance.d.ts.map +1 -0
  1288. package/dist/utils/edge-provenance.js +53 -0
  1289. package/dist/utils/edge-provenance.js.map +1 -0
  1290. package/dist/utils/git-validation.d.ts +24 -0
  1291. package/dist/utils/git-validation.d.ts.map +1 -1
  1292. package/dist/utils/git-validation.js +30 -0
  1293. package/dist/utils/git-validation.js.map +1 -1
  1294. package/dist/utils/overlay-cache.d.ts +38 -0
  1295. package/dist/utils/overlay-cache.d.ts.map +1 -0
  1296. package/dist/utils/overlay-cache.js +73 -0
  1297. package/dist/utils/overlay-cache.js.map +1 -0
  1298. package/dist/utils/source-stripper/code-handler.d.ts +3 -0
  1299. package/dist/utils/source-stripper/code-handler.d.ts.map +1 -0
  1300. package/dist/utils/source-stripper/code-handler.js +79 -0
  1301. package/dist/utils/source-stripper/code-handler.js.map +1 -0
  1302. package/dist/utils/source-stripper/comment-handler.d.ts +4 -0
  1303. package/dist/utils/source-stripper/comment-handler.d.ts.map +1 -0
  1304. package/dist/utils/source-stripper/comment-handler.js +24 -0
  1305. package/dist/utils/source-stripper/comment-handler.js.map +1 -0
  1306. package/dist/utils/source-stripper/machine.d.ts +2 -0
  1307. package/dist/utils/source-stripper/machine.d.ts.map +1 -0
  1308. package/dist/utils/source-stripper/machine.js +34 -0
  1309. package/dist/utils/source-stripper/machine.js.map +1 -0
  1310. package/dist/utils/source-stripper/regex-handler.d.ts +3 -0
  1311. package/dist/utils/source-stripper/regex-handler.d.ts.map +1 -0
  1312. package/dist/utils/source-stripper/regex-handler.js +44 -0
  1313. package/dist/utils/source-stripper/regex-handler.js.map +1 -0
  1314. package/dist/utils/source-stripper/state.d.ts +4 -0
  1315. package/dist/utils/source-stripper/state.d.ts.map +1 -0
  1316. package/dist/utils/source-stripper/state.js +20 -0
  1317. package/dist/utils/source-stripper/state.js.map +1 -0
  1318. package/dist/utils/source-stripper/string-handler.d.ts +3 -0
  1319. package/dist/utils/source-stripper/string-handler.d.ts.map +1 -0
  1320. package/dist/utils/source-stripper/string-handler.js +19 -0
  1321. package/dist/utils/source-stripper/string-handler.js.map +1 -0
  1322. package/dist/utils/source-stripper/template-handler.d.ts +4 -0
  1323. package/dist/utils/source-stripper/template-handler.d.ts.map +1 -0
  1324. package/dist/utils/source-stripper/template-handler.js +40 -0
  1325. package/dist/utils/source-stripper/template-handler.js.map +1 -0
  1326. package/dist/utils/source-stripper/types.d.ts +17 -0
  1327. package/dist/utils/source-stripper/types.d.ts.map +1 -0
  1328. package/dist/utils/source-stripper/types.js +4 -0
  1329. package/dist/utils/source-stripper/types.js.map +1 -0
  1330. package/dist/utils/source-stripper.d.ts +0 -21
  1331. package/dist/utils/source-stripper.d.ts.map +1 -1
  1332. package/dist/utils/source-stripper.js +6 -234
  1333. package/dist/utils/source-stripper.js.map +1 -1
  1334. package/dist/utils/walk/errors.d.ts +4 -0
  1335. package/dist/utils/walk/errors.d.ts.map +1 -0
  1336. package/dist/utils/walk/errors.js +18 -0
  1337. package/dist/utils/walk/errors.js.map +1 -0
  1338. package/dist/utils/walk/filters.d.ts +11 -0
  1339. package/dist/utils/walk/filters.d.ts.map +1 -0
  1340. package/dist/utils/walk/filters.js +53 -0
  1341. package/dist/utils/walk/filters.js.map +1 -0
  1342. package/dist/utils/walk/limits.d.ts +10 -0
  1343. package/dist/utils/walk/limits.d.ts.map +1 -0
  1344. package/dist/utils/walk/limits.js +22 -0
  1345. package/dist/utils/walk/limits.js.map +1 -0
  1346. package/dist/utils/walk/traversal.d.ts +9 -0
  1347. package/dist/utils/walk/traversal.d.ts.map +1 -0
  1348. package/dist/utils/walk/traversal.js +38 -0
  1349. package/dist/utils/walk/traversal.js.map +1 -0
  1350. package/dist/utils/walk/types.d.ts +18 -0
  1351. package/dist/utils/walk/types.d.ts.map +1 -0
  1352. package/dist/utils/walk/types.js +2 -0
  1353. package/dist/utils/walk/types.js.map +1 -0
  1354. package/dist/utils/walk.d.ts +4 -65
  1355. package/dist/utils/walk.d.ts.map +1 -1
  1356. package/dist/utils/walk.js +23 -151
  1357. package/dist/utils/walk.js.map +1 -1
  1358. package/package.json +6 -5
@@ -1,1427 +1,16 @@
1
1
  /**
2
2
  * PHP/Yii2-specific code intelligence tools.
3
3
  *
4
- * Provides 9 hidden/discoverable tools that augment generic code intelligence
5
- * with PHP framework awareness: PSR-4 namespace resolution, ActiveRecord schema
6
- * extraction, event/listener tracing, view mapping, service locator resolution,
7
- * security scanning, compound project audit (9-gate), N+1 query detection,
8
- * and god-model detection.
9
- */
10
- import { readFile } from "node:fs/promises";
11
- import { join } from "node:path";
12
- import { getCodeIndex } from "./index-tools.js";
13
- import { searchPatterns } from "./pattern-tools.js";
14
- export async function resolvePhpNamespace(repo, className) {
15
- const index = await getCodeIndex(repo);
16
- if (!index)
17
- throw new Error(`Repository "${repo}" not found.`);
18
- const composer = await readJsonSafe(join(index.root, "composer.json"));
19
- const psr4 = {
20
- ...(composer?.autoload?.["psr-4"] ?? {}),
21
- ...(composer?.["autoload-dev"]?.["psr-4"] ?? {}),
22
- };
23
- // Strip leading backslash
24
- const normalized = className.replace(/^\\/, "");
25
- const parts = normalized.split("\\");
26
- const namespaceOnly = parts.slice(0, -1).join("\\");
27
- const shortName = parts[parts.length - 1];
28
- // Find matching PSR-4 prefix (longest match wins)
29
- let bestPrefix = null;
30
- let bestRoot = null;
31
- for (const [prefix, roots] of Object.entries(psr4)) {
32
- const normalizedPrefix = prefix.replace(/\\$/, "");
33
- if (normalized.startsWith(normalizedPrefix + "\\") || normalized === normalizedPrefix) {
34
- if (!bestPrefix || normalizedPrefix.length > bestPrefix.length) {
35
- bestPrefix = normalizedPrefix;
36
- bestRoot = Array.isArray(roots) ? roots[0] ?? null : roots;
37
- }
38
- }
39
- }
40
- if (!bestPrefix || !bestRoot) {
41
- return {
42
- class_name: shortName,
43
- namespace: namespaceOnly,
44
- file_path: null,
45
- exists: false,
46
- psr4_root: null,
47
- psr4_prefix: null,
48
- };
49
- }
50
- // Construct file path: strip prefix, replace \ with /, append .php
51
- const remainder = normalized.slice(bestPrefix.length).replace(/^\\/, "");
52
- const relativePath = remainder.replace(/\\/g, "/") + ".php";
53
- const root = bestRoot.replace(/\/$/, "");
54
- const filePath = root + "/" + relativePath;
55
- // Check if file exists in index (strip leading ./ for comparison)
56
- const normalizedFP = filePath.replace(/^\.\//, "");
57
- const exists = index.files.some((f) => f.path === normalizedFP || f.path === filePath);
58
- return {
59
- class_name: shortName,
60
- namespace: namespaceOnly,
61
- file_path: filePath,
62
- exists,
63
- psr4_root: bestRoot,
64
- psr4_prefix: bestPrefix,
65
- };
66
- }
67
- /**
68
- * Names of class roots that we treat as "this is an ActiveRecord". The check
69
- * is done on the LAST namespace segment so prefixed forms (yii\\db\\ActiveRecord,
70
- * \\yii\\db\\ActiveRecord, app\\models\\ActiveRecord) all match. Includes
71
- * yii\\base\\Model because Yii2 form models extending Model share the
72
- * rules() / behaviors() lifecycle that analyzeActiveRecord introspects;
73
- * downstream callers can filter by tableName() presence if they need a
74
- * stricter "real DB-backed AR" criterion.
75
- */
76
- const AR_ROOT_NAMES = new Set(["ActiveRecord", "Model", "BaseActiveRecord"]);
77
- /**
78
- * Walk a class symbol's `extends` chain and return true if any ancestor
79
- * matches a known ActiveRecord base class. Resolves transitively via the
80
- * symbol index — handles cases like `User extends BaseUser` where
81
- * `BaseUser extends ActiveRecord`.
82
- *
83
- * Direct match (root name in our AR_ROOT_NAMES set) wins immediately.
84
- * Otherwise we look up the parent class symbol by name and recurse. The
85
- * lookup uses last-segment name matching (e.g. `BaseUser` matches a class
86
- * symbol whose `name` is exactly `BaseUser`, regardless of namespace) which
87
- * is good enough for the codebases we care about; cross-package aliased
88
- * resolution would require parsing per-file `use` tables.
89
- *
90
- * Cycle protection via a visited set; depth-cap of 5 (no real Yii2 model
91
- * has a deeper chain).
92
- */
93
- function isActiveRecordHierarchy(cls, index, visited = new Set(), depth = 0) {
94
- if (depth > 5)
95
- return false;
96
- if (visited.has(cls.name))
97
- return false;
98
- visited.add(cls.name);
99
- const exts = cls.extends ?? [];
100
- for (const baseFqcn of exts) {
101
- // Last segment of FQCN (handles "\\yii\\db\\ActiveRecord" and aliases).
102
- const last = baseFqcn.split(/[\\\\]+/).pop() ?? baseFqcn;
103
- if (AR_ROOT_NAMES.has(last))
104
- return true;
105
- // Look up the base class as an indexed symbol and recurse.
106
- const baseSym = index.symbols.find((s) => s.kind === "class" && s.name === last);
107
- if (baseSym && isActiveRecordHierarchy(baseSym, index, visited, depth + 1)) {
108
- return true;
109
- }
110
- }
111
- // Fallback for older indexes (e.g. before the v2.0.0 extractor bump): if
112
- // `extends` is missing on this symbol, try the legacy regex against
113
- // `source` so we don't regress on unindexed projects.
114
- if (!cls.extends && cls.source) {
115
- return /extends\s+(?:ActiveRecord|Model|\\yii\\db\\ActiveRecord)\b/.test(cls.source);
116
- }
117
- return false;
118
- }
119
- export async function analyzeActiveRecord(repo, options) {
120
- const index = await getCodeIndex(repo);
121
- if (!index)
122
- throw new Error(`Repository "${repo}" not found.`);
123
- // Find PHP class symbols in model files
124
- const classSymbols = index.symbols.filter((s) => {
125
- if (s.kind !== "class")
126
- return false;
127
- if (!s.file.endsWith(".php"))
128
- return false;
129
- if (options?.model_name && s.name !== options.model_name)
130
- return false;
131
- if (options?.file_pattern && !s.file.includes(options.file_pattern))
132
- return false;
133
- return true;
134
- });
135
- const models = [];
136
- for (const cls of classSymbols) {
137
- if (!cls.source)
138
- continue;
139
- if (!isActiveRecordHierarchy(cls, index))
140
- continue;
141
- const model = {
142
- name: cls.name,
143
- file: cls.file,
144
- table_name: null,
145
- relations: [],
146
- rules: [],
147
- behaviors: [],
148
- methods: [],
149
- };
150
- // Extract tableName() return value
151
- const tableMatch = /function\s+tableName\s*\([^)]*\)[^{]*\{[^}]*return\s+['"]([^'"]+)['"]/s.exec(cls.source);
152
- if (tableMatch)
153
- model.table_name = tableMatch[1];
154
- // Find child method symbols
155
- const methods = index.symbols.filter((s) => s.parent === cls.id && s.kind === "method");
156
- model.methods = methods.map((m) => m.name);
157
- // Extract relations from getX() methods that return hasOne/hasMany.
158
- // Two-pass detection:
159
- // Pass 1: find the primary `->hasOne(Target::class, ...)` or
160
- // `->hasMany(Target::class, ...)` call.
161
- // Pass 2: scan the rest of the source for modifiers:
162
- // ->via('relation') (Yii2 2.0.13+ junction table via relation)
163
- // ->viaTable('tbl', [...]) (direct junction table)
164
- // ->inverseOf('relation') (bidirectional relation)
165
- // The presence of `via` or `viaTable` upgrades the relation type
166
- // to `manyMany`. `inverseOf` is decorative and doesn't change type.
167
- for (const m of methods) {
168
- if (!m.name.startsWith("get") || !m.source)
169
- continue;
170
- const relName = m.name.slice(3);
171
- const primaryRe = /->(hasOne|hasMany)\s*\(\s*([\w\\]+)(?:::class)?/;
172
- const primaryMatch = primaryRe.exec(m.source);
173
- if (!primaryMatch)
174
- continue;
175
- const baseType = primaryMatch[1] === "hasOne" ? "hasOne" : "hasMany";
176
- const targetClass = primaryMatch[2];
177
- // Scan the method source for junction-table modifiers on the same chain.
178
- // If found, the semantic type is manyMany even though the primary call was hasMany.
179
- const hasJunction = /->(?:via|viaTable)\s*\(/.test(m.source);
180
- const type = hasJunction ? "manyMany" : baseType;
181
- model.relations.push({
182
- name: relName.charAt(0).toLowerCase() + relName.slice(1),
183
- type,
184
- target_class: targetClass,
185
- });
186
- }
187
- // Extract rule validators (loose regex on rules() method source)
188
- const rulesMethod = methods.find((m) => m.name === "rules");
189
- if (rulesMethod?.source) {
190
- const ruleMatches = rulesMethod.source.matchAll(/\[\s*\[?['"]?[\w,\s'"]+['"]?\]?\s*,\s*['"]([\w]+)['"]/g);
191
- for (const rm of ruleMatches) {
192
- if (rm[1] && !model.rules.includes(rm[1]))
193
- model.rules.push(rm[1]);
194
- }
195
- }
196
- // Extract behaviors from behaviors() method
197
- const behaviorsMethod = methods.find((m) => m.name === "behaviors");
198
- if (behaviorsMethod?.source) {
199
- const bMatches = behaviorsMethod.source.matchAll(/([A-Z]\w+Behavior)(?:::class)?/g);
200
- for (const bm of bMatches) {
201
- if (bm[1] && !model.behaviors.includes(bm[1]))
202
- model.behaviors.push(bm[1]);
203
- }
204
- }
205
- models.push(model);
206
- }
207
- return { models, total: models.length };
208
- }
209
- /**
210
- * Build a class-const → literal-value map for the entire index. Yii2's
211
- * canonical event idiom is `Event::on(User::class, User::EVENT_AFTER_LOGIN, ...)`,
212
- * where `EVENT_AFTER_LOGIN` is a class constant with a string value. The
213
- * default tracePhpEvent regex only sees literals, so without resolution
214
- * `Class::CONST` references look like dead code. This pre-pass walks all
215
- * `constant` symbols belonging to PHP classes and extracts their string /
216
- * int literal values from `source`.
217
- *
218
- * Map keys are `ClassName::CONST_NAME`. Class lookup is by last name segment
219
- * — same convention as isActiveRecordHierarchy — so namespace prefixes don't
220
- * matter for callers using `User::EVENT_X` against a class named `User`.
221
- *
222
- * Returns an empty map if no constants resolve. Cost is one O(n) walk per
223
- * call; could be cached on the index in the future if event tracing becomes
224
- * a hot path.
225
- */
226
- function buildConstantValueMap(index) {
227
- const out = new Map();
228
- // First, build classId → className map so we can resolve const owners.
229
- const classIdToName = new Map();
230
- for (const s of index.symbols) {
231
- if (s.kind === "class" || s.kind === "interface" || s.kind === "enum") {
232
- // Use the symbol id as key — every constant carries `parent` referring
233
- // to its enclosing class id, so we only need the id→name lookup.
234
- const id = s.id;
235
- if (id)
236
- classIdToName.set(id, s.name);
237
- }
238
- }
239
- for (const s of index.symbols) {
240
- if (s.kind !== "constant")
241
- continue;
242
- if (!s.parent || !s.source)
243
- continue;
244
- const className = classIdToName.get(s.parent);
245
- if (!className)
246
- continue;
247
- // Match the literal value: `const NAME = 'value';` or `const NAME = "v";`
248
- // or `const NAME = 42;`. We accept the first occurrence in the constant's
249
- // source slice — the extractor already narrows source to a single decl.
250
- const m = /=\s*(?:['"]([^'"]+)['"]|(-?\d+(?:\.\d+)?))/.exec(s.source);
251
- if (!m)
252
- continue;
253
- const value = m[1] ?? m[2];
254
- if (value === undefined)
255
- continue;
256
- out.set(`${className}::${s.name}`, value);
257
- }
258
- return out;
259
- }
260
- export async function tracePhpEvent(repo, options) {
261
- const index = await getCodeIndex(repo);
262
- if (!index)
263
- throw new Error(`Repository "${repo}" not found.`);
264
- const eventMap = new Map();
265
- const constantValues = buildConstantValueMap(index);
266
- const getOrCreate = (name) => {
267
- let e = eventMap.get(name);
268
- if (!e) {
269
- e = { event_name: name, triggers: [], listeners: [] };
270
- eventMap.set(name, e);
271
- }
272
- return e;
273
- };
274
- // Resolve `Class::CONST` references to their literal values via the pre-pass
275
- // map. Returns the original key when the class+const pair isn't indexed
276
- // (e.g. constants defined in vendor/) so the trace at least shows there's
277
- // SOMETHING happening at this site.
278
- const resolveEventName = (raw) => {
279
- return constantValues.get(raw) ?? raw;
280
- };
281
- // Scan PHP file symbols for event triggers and listeners
282
- const phpSymbols = index.symbols.filter((s) => s.file.endsWith(".php") && s.source);
283
- for (const sym of phpSymbols) {
284
- const source = sym.source;
285
- // Triggers: ->trigger('eventName') or ->trigger(Class::CONST)
286
- // Now also accepts a bare identifier path (Foo::BAR) in addition to the
287
- // string-literal form.
288
- const triggerRe = /->trigger\s*\(\s*(?:['"]([^'"]+)['"]|([A-Z_][\w]*::[A-Z_][\w]*))/g;
289
- let match;
290
- while ((match = triggerRe.exec(source)) !== null) {
291
- const literal = match[1];
292
- const constRef = match[2];
293
- const eventName = literal ?? (constRef ? resolveEventName(constRef) : undefined);
294
- if (!eventName)
295
- continue;
296
- if (options?.event_name && eventName !== options.event_name)
297
- continue;
298
- const line = sym.start_line + (source.slice(0, match.index).match(/\n/g)?.length ?? 0);
299
- getOrCreate(eventName).triggers.push({
300
- file: sym.file,
301
- line,
302
- context: extractLineContext(source, match.index),
303
- });
304
- }
305
- // Listeners: ->on('eventName', ...) or ::on('eventName', ...) or
306
- // ::on(Foo::class, Foo::EVENT_BAR, ...)
307
- // Yii2 prefers the class-const form for built-in events, so resolution is
308
- // critical here.
309
- const listenerRe = /(?:->|::)on\s*\(\s*(?:[A-Z_][\w]*::class\s*,\s*)?(?:['"]([^'"]+)['"]|([A-Z_][\w]*::[A-Z_][\w]*))/g;
310
- while ((match = listenerRe.exec(source)) !== null) {
311
- const literal = match[1];
312
- const constRef = match[2];
313
- const eventName = literal ?? (constRef ? resolveEventName(constRef) : undefined);
314
- if (!eventName)
315
- continue;
316
- if (options?.event_name && eventName !== options.event_name)
317
- continue;
318
- const line = sym.start_line + (source.slice(0, match.index).match(/\n/g)?.length ?? 0);
319
- getOrCreate(eventName).listeners.push({
320
- file: sym.file,
321
- line,
322
- context: extractLineContext(source, match.index),
323
- });
324
- }
325
- }
326
- const events = [...eventMap.values()];
327
- return { events, total: events.length };
328
- }
329
- /**
330
- * Yii2 view + layout + widget + asset-bundle inventory.
331
- *
332
- * Beyond the original render→view mapping (Sprint 1), the tool now also:
333
- * - Distinguishes render flavors (full/partial/ajax/json/file) so
334
- * downstream caching/SEO audits can scope their checks.
335
- * - Resolves `@alias/...` paths via the path-alias map sourced from
336
- * `Yii::setAlias()` calls and `aliases` keys in config files.
337
- * - Captures `$this->layout = '...'` assignments (controller-wide and
338
- * per-action overrides).
339
- * - Lists widget references (`GridView::begin/widget`) found anywhere
340
- * in the codebase.
341
- * - Lists `AssetBundle::register($this)` calls.
342
- */
343
- export async function findPhpViews(repo, options) {
344
- const index = await getCodeIndex(repo);
345
- if (!index)
346
- throw new Error(`Repository "${repo}" not found.`);
347
- const includeWidgets = options?.include_widgets ?? true;
348
- const includeBundles = options?.include_asset_bundles ?? true;
349
- const mappings = [];
350
- const layouts = [];
351
- const widgets = [];
352
- const assetBundles = [];
353
- // Resolve path aliases up-front. The map is consulted for every
354
- // render() / layout assignment / view file path that begins with `@`.
355
- const aliasMap = await resolvePathAliases(index);
356
- // Find action methods in controllers
357
- const controllers = index.symbols.filter((s) => s.kind === "class" && s.name.endsWith("Controller") && s.file.endsWith(".php"));
358
- for (const ctrl of controllers) {
359
- if (options?.controller && !ctrl.name.includes(options.controller))
360
- continue;
361
- // Controller-wide layout: `$this->layout = '...'` declared as a property
362
- // OR set in init() / beforeAction() / a per-action method.
363
- if (ctrl.source) {
364
- const layoutPropRe = /(?:public|protected|private)?\s*\$layout\s*=\s*['"]([^'"]+)['"]/;
365
- const propMatch = layoutPropRe.exec(ctrl.source);
366
- if (propMatch) {
367
- const layoutName = propMatch[1];
368
- layouts.push({
369
- controller: ctrl.name,
370
- action: null,
371
- layout: layoutName,
372
- layout_file: resolveLayoutFile(layoutName, ctrl.name, aliasMap, index),
373
- set_at_line: ctrl.start_line + (ctrl.source.slice(0, propMatch.index).match(/\n/g)?.length ?? 0),
374
- });
375
- }
376
- }
377
- const actions = index.symbols.filter((s) => s.parent === ctrl.id && s.kind === "method" && s.name.startsWith("action"));
378
- for (const action of actions) {
379
- if (!action.source)
380
- continue;
381
- // Match $this->render('viewName'), renderPartial('...'), renderAjax('...')
382
- // Capture the render KIND from the suffix so callers can filter by
383
- // flavor downstream.
384
- const renderRe = /\$this->render(Partial|Ajax|AsJson|File)?\s*\(\s*['"]([^'"]+)['"]/g;
385
- let match;
386
- while ((match = renderRe.exec(action.source)) !== null) {
387
- const suffix = match[1] ?? "";
388
- const viewName = match[2];
389
- const renderKind = suffix === ""
390
- ? "full"
391
- : suffix.toLowerCase().replace("asjson", "json");
392
- const { file: viewFile, alias } = resolveViewFile(viewName, ctrl.name, aliasMap, index);
393
- const line = action.start_line + (action.source.slice(0, match.index).match(/\n/g)?.length ?? 0);
394
- mappings.push({
395
- controller: ctrl.name,
396
- action: action.name,
397
- view_name: viewName,
398
- view_file: viewFile,
399
- render_line: line,
400
- render_kind: renderKind,
401
- path_alias: alias,
402
- });
403
- }
404
- // Per-action layout override: `$this->layout = '...'` inside the
405
- // action body. Distinct entry from the controller-wide property.
406
- const layoutAssignRe = /\$this->layout\s*=\s*['"]([^'"]+)['"]/g;
407
- while ((match = layoutAssignRe.exec(action.source)) !== null) {
408
- const layoutName = match[1];
409
- const line = action.start_line +
410
- (action.source.slice(0, match.index).match(/\n/g)?.length ?? 0);
411
- layouts.push({
412
- controller: ctrl.name,
413
- action: action.name,
414
- layout: layoutName,
415
- layout_file: resolveLayoutFile(layoutName, ctrl.name, aliasMap, index),
416
- set_at_line: line,
417
- });
418
- }
419
- }
420
- }
421
- // Widget references — scan ALL PHP symbols + all .php files at module
422
- // level (views are file-scope code, not symbols).
423
- if (includeWidgets) {
424
- collectWidgetRefs(index, widgets);
425
- }
426
- // AssetBundle::register() — same scope.
427
- if (includeBundles) {
428
- collectAssetBundleRefs(index, assetBundles);
429
- }
430
- return {
431
- mappings,
432
- total: mappings.length,
433
- layouts,
434
- widgets,
435
- asset_bundles: assetBundles,
436
- };
437
- }
438
- /**
439
- * Build a path-alias map from Yii::setAlias() calls + config-file aliases.
440
- * Map is keyed by the alias INCLUDING the leading `@` (so callers can
441
- * test membership cheaply against the input string).
442
- *
443
- * Default Yii2 aliases (`@app`, `@webroot`, etc.) are inferred from the
444
- * repo root when not explicitly set, so a fresh project still gets a
445
- * useful default map.
446
- */
447
- async function resolvePathAliases(index) {
448
- const aliases = new Map();
449
- // Default aliases. `@app` is the conventional Yii2 anchor — almost
450
- // every project has it pointing at the repo root.
451
- aliases.set("@app", ".");
452
- // Scan main config files for explicit aliases. Both
453
- // 'aliases' => ['@foo' => 'path']
454
- // and
455
- // Yii::setAlias('@foo', 'path');
456
- // are recognized.
457
- const configFiles = index.files.filter((f) => /config\/(?:web|main|console|api|backend|frontend|common)(?:[-_][\w-]+)?\.php$/.test(f.path));
458
- for (const cf of configFiles) {
459
- let source;
460
- try {
461
- source = await readFile(join(index.root, cf.path), "utf-8");
462
- }
463
- catch {
464
- continue;
465
- }
466
- // `aliases` => ['@x' => 'path', ...]
467
- const aliasArrayRe = /['"]aliases['"]\s*=>\s*\[([^\]]+)\]/g;
468
- let m;
469
- while ((m = aliasArrayRe.exec(source)) !== null) {
470
- const inner = m[1];
471
- const entryRe = /['"](@[\w/.-]+)['"]\s*=>\s*['"]([^'"]+)['"]/g;
472
- let em;
473
- while ((em = entryRe.exec(inner)) !== null) {
474
- aliases.set(em[1], em[2]);
475
- }
476
- }
477
- // Yii::setAlias('@x', 'path');
478
- const setAliasRe = /Yii::setAlias\s*\(\s*['"](@[\w/.-]+)['"]\s*,\s*['"]([^'"]+)['"]/g;
479
- while ((m = setAliasRe.exec(source)) !== null) {
480
- aliases.set(m[1], m[2]);
481
- }
482
- }
483
- return aliases;
484
- }
485
- /**
486
- * Resolve a view name to a path within the indexed file set. Prefers
487
- * explicit `@alias/...` resolution; otherwise falls back to the Yii2
488
- * convention `views/<controller-id>/<view>.php`. Returns the resolved
489
- * (path, alias) pair — alias is the leading `@token` if one was used.
490
- *
491
- * The resolved path is matched against `index.files` to confirm the view
492
- * actually exists; if not, file is null but alias is still surfaced so
493
- * callers can flag missing-file findings against external asset paths.
494
- */
495
- function resolveViewFile(viewName, controllerClass, aliases, index) {
496
- // Path alias: `@app/views/...` or any alias-prefixed string.
497
- if (viewName.startsWith("@")) {
498
- const aliasMatch = /^(@[\w-]+)(\/.*)?$/.exec(viewName);
499
- if (aliasMatch) {
500
- const alias = aliasMatch[1];
501
- const remainder = aliasMatch[2] ?? "";
502
- const aliasTarget = aliases.get(alias);
503
- if (aliasTarget !== undefined) {
504
- const candidate = (aliasTarget.replace(/\/$/, "") + remainder).replace(/^\.\//, "");
505
- const final = candidate.endsWith(".php") ? candidate : candidate + ".php";
506
- const exists = index.files.some((f) => f.path === final || f.path.endsWith("/" + final));
507
- return { file: exists ? final : null, alias };
508
- }
509
- return { file: null, alias };
510
- }
511
- }
512
- // Path-style relative name: `subdir/foo` keeps the explicit subdir.
513
- const isPath = viewName.includes("/");
514
- const controllerId = pascalToKebab(controllerClass.replace(/Controller$/, ""));
515
- const candidate = isPath
516
- ? `views/${viewName}.php`
517
- : `views/${controllerId}/${viewName}.php`;
518
- const exists = index.files.some((f) => f.path === candidate || f.path.endsWith("/" + candidate));
519
- return { file: exists ? candidate : null, alias: null };
520
- }
521
- function resolveLayoutFile(layoutName, controllerClass, aliases, index) {
522
- // Layouts default to `views/layouts/<name>.php` rather than per-controller.
523
- if (layoutName.startsWith("@")) {
524
- const aliasMatch = /^(@[\w-]+)(\/.*)?$/.exec(layoutName);
525
- if (aliasMatch) {
526
- const aliasTarget = aliases.get(aliasMatch[1]);
527
- if (!aliasTarget)
528
- return null;
529
- const remainder = aliasMatch[2] ?? "";
530
- const candidate = (aliasTarget.replace(/\/$/, "") + remainder).replace(/^\.\//, "");
531
- const final = candidate.endsWith(".php") ? candidate : candidate + ".php";
532
- const exists = index.files.some((f) => f.path === final || f.path.endsWith("/" + final));
533
- return exists ? final : null;
534
- }
535
- return null;
536
- }
537
- const isPath = layoutName.includes("/");
538
- const candidate = isPath
539
- ? `views/${layoutName}.php`
540
- : `views/layouts/${layoutName}.php`;
541
- const exists = index.files.some((f) => f.path === candidate || f.path.endsWith("/" + candidate));
542
- return exists ? candidate : null;
543
- void controllerClass; // referenced for future per-module path resolution
544
- }
545
- function collectWidgetRefs(index, out) {
546
- // Build a quick parentId → class name map so we can attribute widget
547
- // references to their containing class (when the widget lives inside
548
- // a class method).
549
- const idToClass = new Map();
550
- for (const s of index.symbols) {
551
- if (s.kind === "class") {
552
- const id = s.id;
553
- if (id)
554
- idToClass.set(id, s.name);
555
- }
556
- }
557
- // Yii2 widget API: `Widget::begin([...])` (followed by ::end()) and
558
- // `Widget::widget([...])`. Both are method-call forms; we look for any
559
- // CamelCase identifier ending in expected widget suffixes (Form, View,
560
- // Pjax, Menu, Pager, Breadcrumbs, Modal) to filter out unrelated
561
- // static calls. The bound list is pragmatic — the Yii2 ecosystem has
562
- // hundreds of widget classes but ~95% match this suffix family.
563
- const WIDGET_SUFFIXES = /(?:Form|View|Pjax|Menu|Pager|Breadcrumbs|Modal|GridView|ListView|DetailView|LinkPager|Captcha|Alert|Tabs|NavBar|Carousel|Dropdown|FileInput|DatePicker|RangeInput|Select2|TimePicker|Slider|MaskedInput|RadioButton|Tag)$/;
564
- const re = /\b([A-Z][\w]*?)::(begin|widget)\s*\(/g;
565
- for (const sym of index.symbols) {
566
- if (!sym.source)
567
- continue;
568
- if (!sym.file.endsWith(".php"))
569
- continue;
570
- let m;
571
- while ((m = re.exec(sym.source)) !== null) {
572
- const widgetName = m[1];
573
- const kindRaw = m[2];
574
- if (!WIDGET_SUFFIXES.test(widgetName))
575
- continue;
576
- const callerClass = sym.parent ? idToClass.get(sym.parent) ?? null : null;
577
- const callerMethod = sym.kind === "method" ? sym.name : null;
578
- const line = sym.start_line +
579
- (sym.source.slice(0, m.index).match(/\n/g)?.length ?? 0);
580
- out.push({
581
- widget: widgetName,
582
- caller_class: callerClass,
583
- caller_method: callerMethod,
584
- file: sym.file,
585
- line,
586
- kind: kindRaw === "begin" ? "begin" : "widget",
587
- });
588
- }
589
- }
590
- }
591
- function collectAssetBundleRefs(index, out) {
592
- // `BundleClass::register($this)` — the canonical AssetBundle entry
593
- // point. We capture the class name (last segment for FQCN forms).
594
- const re = /\b([A-Z][\w\\]*?)::register\s*\(\s*\$this\b/g;
595
- for (const sym of index.symbols) {
596
- if (!sym.source)
597
- continue;
598
- if (!sym.file.endsWith(".php"))
599
- continue;
600
- let m;
601
- while ((m = re.exec(sym.source)) !== null) {
602
- const fqcn = m[1];
603
- const last = fqcn.split(/[\\\\]+/).pop() ?? fqcn;
604
- // Reject obvious false positives — `Yii::register()` doesn't exist
605
- // but a few user classes might also expose `register($this)` for
606
- // unrelated reasons. Filter to names that LOOK like an AssetBundle:
607
- // suffix `Asset` is the universal Yii2 convention.
608
- if (!/Asset(?:s|Bundle)?$/.test(last))
609
- continue;
610
- const line = sym.start_line +
611
- (sym.source.slice(0, m.index).match(/\n/g)?.length ?? 0);
612
- out.push({ bundle: last, file: sym.file, line });
613
- }
614
- }
615
- }
616
- export async function resolvePhpService(repo, options) {
617
- const index = await getCodeIndex(repo);
618
- if (!index)
619
- throw new Error(`Repository "${repo}" not found.`);
620
- const services = [];
621
- // Sprint 3: include `params*.php` only as suppress-source — those files
622
- // hold flat key-value pairs that look like components but aren't. We also
623
- // drop config/test*.php (intentionally divergent) and pick up the broader
624
- // *-local.php and main-*.php variants (advanced template + per-env splits).
625
- const configFiles = index.files.filter((f) => {
626
- if (!f.path.endsWith(".php"))
627
- return false;
628
- if (/config\/test/.test(f.path))
629
- return false;
630
- return /config\/(?:web|console|main|db|api|backend|frontend|common)(?:[-_][\w-]+)?\.php$/.test(f.path);
631
- });
632
- // Track (name, class, source, configFile) tuples so we don't duplicate
633
- // when the same component appears in both web.php and main-local.php.
634
- const seen = new Set();
635
- const dedupKey = (name, cls, sourceLabel, file) => `${sourceLabel}::${name}::${cls ?? "<factory>"}::${file}`;
636
- const pushService = (s) => {
637
- const key = dedupKey(s.name, s.class, s.source, s.config_file ?? "");
638
- if (seen.has(key))
639
- return;
640
- seen.add(key);
641
- services.push(s);
642
- };
643
- for (const cf of configFiles) {
644
- let source;
645
- try {
646
- source = await readFile(join(index.root, cf.path), "utf-8");
647
- }
648
- catch {
649
- continue;
650
- }
651
- // Match component definitions: 'componentName' => ['class' => 'FQCN', ...]
652
- // Top-level components live under 'components' => [...]; module-scoped
653
- // ones live under 'modules' => ['<id>' => ['components' => [...]]]. We
654
- // don't try to distinguish here — every match is tagged via post-pass.
655
- //
656
- // The key pattern accepts both bare names ("db") and FQCNs
657
- // ("app\\interfaces\\LoggerInterface") because container.singletons /
658
- // container.definitions almost always use FQCNs as keys.
659
- const componentRe = /['"]([\w\\-]+)['"]\s*=>\s*\[\s*['"]class['"]\s*=>\s*['"]([\w\\]+)['"]/g;
660
- let match;
661
- while ((match = componentRe.exec(source)) !== null) {
662
- const name = match[1];
663
- const cls = match[2];
664
- if (options?.service_name && name !== options.service_name)
665
- continue;
666
- // Resolve class to file via PSR-4
667
- let filePath = null;
668
- try {
669
- const resolved = await resolvePhpNamespace(repo, cls);
670
- if (resolved.exists)
671
- filePath = resolved.file_path;
672
- }
673
- catch { /* ignore */ }
674
- // Best-effort source labeling: scan the prefix up to the match to see
675
- // whether we're inside `'modules' => ['x' => ['components' => [...]]]`
676
- // or `'container' => ['singletons' => [...]]`. This is fuzzy; the
677
- // labeling failures fall back to "components".
678
- const prefix = source.slice(0, match.index);
679
- const sourceLabel = inferConfigSection(prefix);
680
- pushService({
681
- name,
682
- class: cls,
683
- file: filePath,
684
- config_file: cf.path,
685
- source: sourceLabel,
686
- });
687
- }
688
- // DI container: `Yii::$container->set(InterfaceName::class, ImplName::class)`
689
- // and the static `'container' => ['definitions' => [...]]` form. Both are
690
- // common in Yii2 codebases that use interface-based DI.
691
- const containerSetRe = /Yii::\$container->set\s*\(\s*([\w\\]+)::class\s*,\s*([\w\\]+)::class/g;
692
- while ((match = containerSetRe.exec(source)) !== null) {
693
- const iface = match[1];
694
- const impl = match[2];
695
- if (options?.service_name && iface !== options.service_name)
696
- continue;
697
- let filePath = null;
698
- try {
699
- const resolved = await resolvePhpNamespace(repo, impl);
700
- if (resolved.exists)
701
- filePath = resolved.file_path;
702
- }
703
- catch { /* ignore */ }
704
- pushService({
705
- name: iface,
706
- class: impl,
707
- file: filePath,
708
- config_file: cf.path,
709
- source: "container.set",
710
- });
711
- }
712
- // Closure / factory: `'mailer' => function() { return new Mailer(); }`
713
- // We can't statically resolve the produced class, so we surface the
714
- // service name with class=null and is_factory=true so callers can
715
- // either ignore them or flag them as needs-manual-review.
716
- const factoryRe = /['"]([\w-]+)['"]\s*=>\s*function\s*\(/g;
717
- while ((match = factoryRe.exec(source)) !== null) {
718
- const name = match[1];
719
- if (options?.service_name && name !== options.service_name)
720
- continue;
721
- pushService({
722
- name,
723
- class: null,
724
- file: null,
725
- config_file: cf.path,
726
- source: "factory",
727
- is_factory: true,
728
- });
729
- }
730
- }
731
- return { services, total: services.length };
732
- }
733
- /**
734
- * Sprint 3 helper: given the source prefix up to a component match, identify
735
- * which Yii2 config section we're inside by walking the prefix forward with a
736
- * bracket-balanced stack. Each `'KEY' => [` pushes KEY onto the stack; each
737
- * matching `]` pops it. At the end of the prefix the stack tells us the
738
- * exact nesting path, regardless of how many sibling sections came before.
739
- *
740
- * Why not regex: regex can't track balanced brackets. The previous version
741
- * used non-greedy `[\\s\\S]*?` which incorrectly matched a `'modules' =>
742
- * ['x' => [...]]` block that had already closed by the time we reached a
743
- * `'container' => ['singletons' => ...]` later in the file.
744
- *
745
- * Returns one of:
746
- * "module:<id>" — inside `'modules' => ['<id>' => ['components' => [<HERE>...
747
- * "container.singletons" — inside `'container' => ['singletons' => [<HERE>...
748
- * "container.definitions" — inside `'container' => ['definitions' => [<HERE>...
749
- * "components" — fallback (top-level components or unknown)
750
- *
751
- * String literals (single + double quoted) and PHP comments are skipped so
752
- * brackets inside them don't confuse the depth counter.
753
- */
754
- function inferConfigSection(prefix) {
755
- const stack = [];
756
- let depth = 0;
757
- let i = 0;
758
- while (i < prefix.length) {
759
- const c = prefix[i];
760
- // Skip comments
761
- if (c === "/" && prefix[i + 1] === "/") {
762
- const nl = prefix.indexOf("\n", i);
763
- i = nl === -1 ? prefix.length : nl + 1;
764
- continue;
765
- }
766
- if (c === "/" && prefix[i + 1] === "*") {
767
- const end = prefix.indexOf("*/", i + 2);
768
- i = end === -1 ? prefix.length : end + 2;
769
- continue;
770
- }
771
- if (c === "#") {
772
- const nl = prefix.indexOf("\n", i);
773
- i = nl === -1 ? prefix.length : nl + 1;
774
- continue;
775
- }
776
- // Look for `'KEY' => [` BEFORE the generic string-skip — otherwise the
777
- // string-skip swallows the opening quote and we never push the key.
778
- if (c === '"' || c === "'") {
779
- const m = /^(['"])([\w\\-]+)\1\s*=>\s*\[/.exec(prefix.slice(i));
780
- if (m) {
781
- const keyName = m[2];
782
- // Push at the new depth (after the bracket we're about to enter).
783
- stack.push({ key: keyName, depth: depth + 1 });
784
- depth++;
785
- i += m[0].length;
786
- continue;
787
- }
788
- // Plain string literal — skip past the closing quote.
789
- const quote = c;
790
- i++;
791
- while (i < prefix.length) {
792
- if (prefix[i] === "\\") {
793
- i += 2;
794
- continue;
795
- }
796
- if (prefix[i] === quote) {
797
- i++;
798
- break;
799
- }
800
- i++;
801
- }
802
- continue;
803
- }
804
- if (c === "[") {
805
- depth++;
806
- i++;
807
- continue;
808
- }
809
- if (c === "]") {
810
- depth--;
811
- while (stack.length > 0 && stack[stack.length - 1].depth > depth) {
812
- stack.pop();
813
- }
814
- i++;
815
- continue;
816
- }
817
- i++;
818
- }
819
- // Read the live nesting path from the stack.
820
- const keys = stack.map((f) => f.key);
821
- // module:<id> when we're inside modules.<id>.components.<*>
822
- const modIdx = keys.indexOf("modules");
823
- if (modIdx !== -1 && keys.length >= modIdx + 3) {
824
- const moduleId = keys[modIdx + 1];
825
- const inner = keys[modIdx + 2];
826
- if (inner === "components")
827
- return `module:${moduleId}`;
828
- }
829
- const cIdx = keys.indexOf("container");
830
- if (cIdx !== -1 && keys.length >= cIdx + 2) {
831
- const sub = keys[cIdx + 1];
832
- if (sub === "singletons")
833
- return "container.singletons";
834
- if (sub === "definitions")
835
- return "container.definitions";
836
- }
837
- return "components";
838
- }
839
- const PHP_SECURITY_CHECKS = [
840
- // Original 8 checks
841
- { pattern: "sql-injection-php", severity: "critical" },
842
- { pattern: "xss-php", severity: "critical" },
843
- { pattern: "eval-php", severity: "critical" },
844
- { pattern: "exec-php", severity: "critical" },
845
- { pattern: "unserialize-php", severity: "high" },
846
- { pattern: "file-include-var", severity: "high" },
847
- { pattern: "unescaped-yii-view", severity: "high" },
848
- { pattern: "raw-query-yii", severity: "high" },
849
- // Sprint 2 additions: Yii2- + PHP-specific patterns informed by tgm-panel
850
- // db-audit + perf-audit findings, plus the gap analysis section 4 catalog.
851
- { pattern: "yii-csrf-disabled", severity: "high" },
852
- { pattern: "yii-debug-mode-prod", severity: "critical" },
853
- { pattern: "yii-cookie-no-validation", severity: "high" },
854
- { pattern: "yii-mass-assignment-unsafe", severity: "medium" },
855
- { pattern: "yii-raw-sql-where", severity: "high" },
856
- { pattern: "php-md5-password", severity: "high" },
857
- { pattern: "php-rand-token", severity: "high" },
858
- { pattern: "php-loose-comparison-secret", severity: "medium" },
859
- { pattern: "yii-rbac-cached-permission", severity: "low" },
860
- { pattern: "yii-no-row-level-locking", severity: "high" },
861
- { pattern: "yii-config-hardcoded-secret", severity: "critical" },
862
- { pattern: "yii-unbounded-all", severity: "medium" },
863
- ];
864
- /**
865
- * Patterns that hit code at module level (top-level `return [...]`,
866
- * top-level `define(...)` calls in entry-point files) and therefore are
867
- * NOT visible via `searchPatterns` — that helper iterates `index.symbols`,
868
- * so files without any class/function/method produce zero hits. We scan
869
- * these patterns by reading file content directly.
870
- */
871
- const FILE_LEVEL_PATTERNS = new Set([
872
- "yii-debug-mode-prod",
873
- "yii-cookie-no-validation",
874
- "yii-config-hardcoded-secret",
875
- ]);
876
- export async function phpSecurityScan(repo, options) {
877
- const selectedChecks = options?.checks
878
- ? PHP_SECURITY_CHECKS.filter((c) => options.checks.includes(c.pattern))
879
- : PHP_SECURITY_CHECKS;
880
- const findings = [];
881
- const summary = { critical: 0, high: 0, medium: 0, low: 0, total: 0 };
882
- // Symbol-level scans run via the existing searchPatterns helper. Skip the
883
- // file-level patterns here — they're handled below by a direct file read.
884
- const symbolLevelChecks = selectedChecks.filter((c) => !FILE_LEVEL_PATTERNS.has(c.pattern));
885
- const fileLevelChecks = selectedChecks.filter((c) => FILE_LEVEL_PATTERNS.has(c.pattern));
886
- // Run pattern checks in parallel
887
- const results = await Promise.all(symbolLevelChecks.map((check) => searchPatterns(repo, check.pattern, {
888
- file_pattern: options?.file_pattern ?? ".php",
889
- include_tests: false,
890
- }).then((r) => ({ check, result: r })).catch(() => null)));
891
- for (const res of results) {
892
- if (!res)
893
- continue;
894
- for (const m of res.result.matches) {
895
- findings.push({
896
- severity: res.check.severity,
897
- pattern: res.check.pattern,
898
- file: m.file,
899
- line: m.start_line,
900
- context: m.context,
901
- description: "", // description populated by searchPatterns but not in PatternMatch type
902
- });
903
- summary[res.check.severity]++;
904
- summary.total++;
905
- }
906
- }
907
- // File-level scan: read every PHP file once, run each file-level pattern
908
- // against it. This catches top-level `define('YII_DEBUG', true)` and
909
- // hardcoded literals in `return [...]` config arrays which never live
910
- // inside a class or function.
911
- if (fileLevelChecks.length > 0) {
912
- const fileFindings = await runFileLevelChecks(repo, fileLevelChecks, options?.file_pattern);
913
- for (const f of fileFindings) {
914
- findings.push(f);
915
- summary[f.severity]++;
916
- summary.total++;
917
- }
918
- }
919
- return {
920
- findings,
921
- summary,
922
- checks_run: selectedChecks.map((c) => c.pattern),
923
- };
924
- }
925
- async function runFileLevelChecks(repo, checks, filePattern) {
926
- const index = await getCodeIndex(repo);
927
- if (!index)
928
- return [];
929
- const { BUILTIN_PATTERNS } = await import("./pattern-tools.js");
930
- const out = [];
931
- const phpFiles = index.files.filter((f) => {
932
- if (!f.path.endsWith(".php"))
933
- return false;
934
- if (filePattern && !f.path.includes(filePattern))
935
- return false;
936
- return true;
937
- });
938
- // Pull each pattern definition up-front. We want one regex object per
939
- // check, not per file, to avoid re-compilation churn.
940
- const compiled = checks
941
- .map((check) => {
942
- const def = BUILTIN_PATTERNS[check.pattern];
943
- if (!def)
944
- return null;
945
- // Re-create the regex with /g so we can iterate matches across the
946
- // whole file content. Built-in patterns are stored without /g because
947
- // searchPatterns calls .exec() once per symbol.
948
- const flags = (def.regex.flags.includes("g") ? "" : "g") + def.regex.flags;
949
- return {
950
- check,
951
- regex: new RegExp(def.regex.source, flags),
952
- fileIncludePattern: def.fileIncludePattern,
953
- fileExcludePattern: def.fileExcludePattern,
954
- };
955
- })
956
- .filter((c) => c !== null);
957
- await Promise.all(phpFiles.map(async (file) => {
958
- let content;
959
- try {
960
- content = await readFile(join(index.root, file.path), "utf-8");
961
- }
962
- catch {
963
- return;
964
- }
965
- for (const c of compiled) {
966
- if (c.fileIncludePattern && !c.fileIncludePattern.test(file.path))
967
- continue;
968
- if (c.fileExcludePattern && c.fileExcludePattern.test(file.path))
969
- continue;
970
- c.regex.lastIndex = 0;
971
- let m;
972
- while ((m = c.regex.exec(content)) !== null) {
973
- const line = countLines(content, m.index);
974
- out.push({
975
- severity: c.check.severity,
976
- pattern: c.check.pattern,
977
- file: file.path,
978
- line,
979
- context: extractLine(content, m.index),
980
- description: "",
981
- });
982
- }
983
- }
984
- }));
985
- return out;
986
- }
987
- function countLines(source, idx) {
988
- let line = 1;
989
- for (let i = 0; i < idx; i++) {
990
- if (source.charCodeAt(i) === 10)
991
- line++;
992
- }
993
- return line;
994
- }
995
- function extractLine(source, idx) {
996
- const start = source.lastIndexOf("\n", idx) + 1;
997
- const end = source.indexOf("\n", idx);
998
- const out = source.slice(start, end === -1 ? source.length : end);
999
- return out.trim().slice(0, 200);
1000
- }
1001
- // ---------------------------------------------------------------------------
1002
- // 7h. find_php_n_plus_one — detect foreach + relation access without ->with()
1003
- // ---------------------------------------------------------------------------
1004
- /**
1005
- * Common ActiveRecord scalar field names. Property access like $user->id or
1006
- * $user->created_at inside a foreach is NOT a relation (no N+1 risk), so we
1007
- * allow-list these to cut false positives.
1008
- */
1009
- const SCALAR_FIELD_NAMES = new Set([
1010
- "id", "name", "title", "created_at", "updated_at", "deleted_at", "status",
1011
- "email", "slug", "code", "type", "value", "label", "description", "enabled",
1012
- "active", "position", "sort", "order", "count", "total", "amount", "price",
1013
- "uuid", "hash", "token", "key", "url", "path", "image", "avatar",
1014
- ]);
1015
- /**
1016
- * PHP method names that look like `get*` but are NOT ActiveRecord relation
1017
- * getters. `$item->save()` / `$item->validate()` inside a foreach is fine;
1018
- * flagging them as N+1 would be a false positive. These names are stripped
1019
- * from the `get\w+()` method-call detection before the eager-load check.
1020
- */
1021
- const METHOD_CALL_BLOCKLIST = new Set([
1022
- "save", "validate", "delete", "refresh", "load", "populate", "toArray",
1023
- "afterSave", "beforeSave", "beforeDelete", "afterDelete",
1024
- "getAttributes", "getAttribute", "getIsNewRecord", "getErrors", "getFirstError",
1025
- "getOldAttributes", "getDirtyAttributes", "getPrimaryKey", "getTableSchema",
1026
- ]);
1027
- /**
1028
- * Detect N+1 query patterns in Yii2/Eloquent controllers.
1029
- *
1030
- * Pattern: `foreach ($items as $item) { $item->relation->... }` without a
1031
- * prior `->with('relation')` call in the same method scope. This is the
1032
- * most common N+1 anti-pattern in Yii2 ActiveRecord code.
1033
- *
1034
- * Known limitations (acceptable for a "discovery" tool, not a gate):
1035
- * - Regex-based — can miss multi-line foreach bodies split across nested blocks
1036
- * - Doesn't cross function boundaries — eager loading in caller is invisible
1037
- * - False positives on nested loops if the outer collection is already eager-loaded
1038
- */
1039
- export async function findPhpNPlusOne(repo, options) {
1040
- const index = await getCodeIndex(repo);
1041
- if (!index)
1042
- throw new Error(`Repository "${repo}" not found.`);
1043
- const findings = [];
1044
- const limit = options?.limit ?? 100;
1045
- const filePattern = options?.file_pattern;
1046
- // Normalize `getProfile` → `profile` so the ->with() check matches whether
1047
- // the relation is accessed as a property or via its auto-generated getter.
1048
- const normalizeGetter = (name) => {
1049
- const bare = name.replace(/^get/, "");
1050
- return bare.length > 0 ? bare.charAt(0).toLowerCase() + bare.slice(1) : "";
1051
- };
1052
- // A finding is emitted exactly once per (foreach × relation-name) tuple so
1053
- // that chained patterns don't double-report the same relation that the
1054
- // property pattern already caught in the same loop body.
1055
- const emitFinding = (sym, foreachIdx, relation, pattern, seen) => {
1056
- if (!relation || seen.has(relation))
1057
- return findings.length >= limit;
1058
- seen.add(relation);
1059
- if (SCALAR_FIELD_NAMES.has(relation.toLowerCase()))
1060
- return findings.length >= limit;
1061
- const beforeForeach = sym.source.slice(0, foreachIdx);
1062
- const withRe = new RegExp(`\\bwith\\s*\\(\\s*['"]${relation}['"]`);
1063
- if (withRe.test(beforeForeach))
1064
- return findings.length >= limit;
1065
- const lineOffset = beforeForeach.split("\n").length - 1;
1066
- findings.push({
1067
- file: sym.file,
1068
- method: sym.name,
1069
- line: sym.start_line + lineOffset,
1070
- relation,
1071
- pattern,
1072
- });
1073
- return findings.length >= limit;
1074
- };
1075
- // Helper: scan a single chunk of source (a method body OR a view file) for
1076
- // all 4 N+1 patterns. Returns true once `limit` is hit so the caller can
1077
- // short-circuit.
1078
- function scanChunk(file, methodName, src, startLine) {
1079
- const foreachRe = /foreach\s*\(\s*\$(\w+)\s+as\s+(?:\$\w+\s*=>\s*)?\$(\w+)\s*\)/g;
1080
- let fm;
1081
- while ((fm = foreachRe.exec(src)) !== null) {
1082
- const itemVar = fm[2];
1083
- const foreachIdx = fm.index;
1084
- const after = src.slice(foreachIdx);
1085
- const seen = new Set();
1086
- // Pattern 1 — property access: $item->profile
1087
- const propRe = new RegExp(`\\$${itemVar}->(\\w+)(?![\\w(])`, "g");
1088
- let m;
1089
- while ((m = propRe.exec(after)) !== null) {
1090
- if (emitFinding({ file, name: methodName, source: src, start_line: startLine }, foreachIdx, m[1], "foreach-access-without-with", seen)) {
1091
- return true;
1092
- }
1093
- }
1094
- // Pattern 2 — getter method call: $item->getProfile()
1095
- const getterRe = new RegExp(`\\$${itemVar}->(get\\w+)\\s*\\(\\s*\\)`, "g");
1096
- while ((m = getterRe.exec(after)) !== null) {
1097
- const rawMethod = m[1];
1098
- if (METHOD_CALL_BLOCKLIST.has(rawMethod))
1099
- continue;
1100
- const normalized = normalizeGetter(rawMethod);
1101
- if (!normalized || METHOD_CALL_BLOCKLIST.has(normalized.toLowerCase()))
1102
- continue;
1103
- if (emitFinding({ file, name: methodName, source: src, start_line: startLine }, foreachIdx, normalized, "foreach-getter-without-with", seen)) {
1104
- return true;
1105
- }
1106
- }
1107
- // Pattern 3 — chained access: $item->rel->sub
1108
- const chainRe = new RegExp(`\\$${itemVar}->(\\w+)->\\w`, "g");
1109
- while ((m = chainRe.exec(after)) !== null) {
1110
- if (emitFinding({ file, name: methodName, source: src, start_line: startLine }, foreachIdx, m[1], "foreach-chained-without-with", seen)) {
1111
- return true;
1112
- }
1113
- }
1114
- // Pattern 4 (Sprint 3) — explicit lookup in loop body. Inside the foreach,
1115
- // a `Model::findOne(...)` / `Model::findAll(...)` / `->find()` is the
1116
- // lazy-load smell — each iteration hits the database.
1117
- //
1118
- // We scan a bounded 2000-char window after the foreach header to keep
1119
- // the regex cost predictable on large methods. A nested foreach inside
1120
- // the window will still match on its own /g iteration, and the outer
1121
- // `seen` set deduplicates so we never double-report a single class+method.
1122
- const body = after.slice(0, Math.min(after.length, 2000));
1123
- const findOneRe = /(\w+)::(findOne|findAll|find|findBySql)\s*\(/g;
1124
- let lm;
1125
- while ((lm = findOneRe.exec(body)) !== null) {
1126
- const targetClass = lm[1];
1127
- const method = lm[2];
1128
- // Filter common false positives: top-level utility classes that
1129
- // happen to expose static `find*` methods but aren't AR.
1130
- if (targetClass === "Yii" ||
1131
- targetClass === "ArrayHelper" ||
1132
- targetClass === "self" ||
1133
- targetClass === "static") {
1134
- continue;
1135
- }
1136
- const synthetic = `${targetClass}::${method}`;
1137
- if (emitFinding({ file, name: methodName, source: src, start_line: startLine }, foreachIdx, synthetic, "foreach-findone-in-loop", seen)) {
1138
- return true;
1139
- }
1140
- }
1141
- }
1142
- return false;
1143
- }
1144
- // Method-level scan (Patterns 1-4 inside class methods, the original surface).
1145
- for (const sym of index.symbols) {
1146
- if (sym.kind !== "method" || !sym.file.endsWith(".php") || !sym.source)
1147
- continue;
1148
- if (filePattern && !sym.file.includes(filePattern))
1149
- continue;
1150
- if (scanChunk(sym.file, sym.name, sym.source, sym.start_line)) {
1151
- return { findings, total: findings.length };
1152
- }
1153
- }
1154
- // View-level scan (Sprint 3 Pattern 5) — Yii2 views/**/*.php files render
1155
- // lists of models at module level. They're not class methods so they have
1156
- // no symbol; scan the raw file content. `views/**/*.php` is the canonical
1157
- // path; `_*.php` partials live at the same level.
1158
- const viewFiles = index.files.filter((f) => {
1159
- if (!f.path.endsWith(".php"))
1160
- return false;
1161
- if (filePattern && !f.path.includes(filePattern))
1162
- return false;
1163
- // Standard Yii2 view paths (basic + advanced + module-scoped layouts).
1164
- return /(?:^|\/)(?:views|widgets|layouts)\//.test(f.path);
1165
- });
1166
- await Promise.all(viewFiles.map(async (file) => {
1167
- if (findings.length >= limit)
1168
- return;
1169
- let content;
1170
- try {
1171
- content = await readFile(join(index.root, file.path), "utf-8");
1172
- }
1173
- catch {
1174
- return;
1175
- }
1176
- // For views the "method name" is just the file basename — that's what
1177
- // the caller sees in the finding when there is no enclosing function.
1178
- const methodName = file.path.split("/").pop() ?? file.path;
1179
- scanChunk(file.path, methodName, content, 1);
1180
- }));
1181
- return { findings, total: findings.length };
1182
- }
1183
- /**
1184
- * Flag oversized PHP classes. Two scopes:
1185
- *
1186
- * - `scope: "activerecord"` (default) — only models extending ActiveRecord.
1187
- * Uses `analyzeActiveRecord` for model detection and counts relations as a
1188
- * third threshold alongside methods and lines. Classic Yii2 god-model case:
1189
- * Survey.php in Mobi2 with 175 methods, 30 relations, 2291 lines.
1190
- *
1191
- * - `scope: "all"` — every PHP class in the index, regardless of base class.
1192
- * Captures service god-classes (UserService with 80 methods), component
1193
- * aggregates, and any other PHP class that outgrew its responsibility.
1194
- * `relation_count` is 0 for non-AR classes — the `min_relations` check is
1195
- * skipped so a service with 60 methods isn't hidden by a relation threshold.
1196
- *
1197
- * Thresholds default to 50/15/500 but are configurable for both scopes.
1198
- */
1199
- export async function findPhpGodModel(repo, options) {
1200
- const index = await getCodeIndex(repo);
1201
- if (!index)
1202
- throw new Error(`Repository "${repo}" not found.`);
1203
- const minM = options?.min_methods ?? 50;
1204
- const minR = options?.min_relations ?? 15;
1205
- const minL = options?.min_lines ?? 500;
1206
- const scope = options?.scope ?? "activerecord";
1207
- const models = [];
1208
- if (scope === "activerecord") {
1209
- const ar = await analyzeActiveRecord(repo);
1210
- for (const m of ar.models) {
1211
- // Look up the class symbol by (name, kind, file) — file match keeps
1212
- // duplicate class names in different paths reported independently.
1213
- const classSym = index.symbols.find((s) => s.name === m.name && s.kind === "class" && s.file === m.file);
1214
- const lineCount = classSym ? classSym.end_line - classSym.start_line : 0;
1215
- const reasons = [];
1216
- if (m.methods.length > minM)
1217
- reasons.push(`methods: ${m.methods.length} > ${minM}`);
1218
- if (m.relations.length > minR)
1219
- reasons.push(`relations: ${m.relations.length} > ${minR}`);
1220
- if (lineCount > minL)
1221
- reasons.push(`lines: ${lineCount} > ${minL}`);
1222
- if (reasons.length > 0) {
1223
- models.push({
1224
- name: m.name,
1225
- file: m.file,
1226
- method_count: m.methods.length,
1227
- relation_count: m.relations.length,
1228
- line_count: lineCount,
1229
- reasons,
1230
- });
1231
- }
1232
- }
1233
- }
1234
- else {
1235
- // scope === "all" — iterate every PHP class symbol directly.
1236
- const classSyms = index.symbols.filter((s) => s.kind === "class" && s.file.endsWith(".php"));
1237
- for (const cls of classSyms) {
1238
- const methodCount = index.symbols.filter((s) => s.parent === cls.id && s.kind === "method").length;
1239
- const lineCount = cls.end_line - cls.start_line;
1240
- const reasons = [];
1241
- if (methodCount > minM)
1242
- reasons.push(`methods: ${methodCount} > ${minM}`);
1243
- if (lineCount > minL)
1244
- reasons.push(`lines: ${lineCount} > ${minL}`);
1245
- // min_relations intentionally skipped in "all" scope — not AR, no relations
1246
- if (reasons.length > 0) {
1247
- models.push({
1248
- name: cls.name,
1249
- file: cls.file,
1250
- method_count: methodCount,
1251
- relation_count: 0,
1252
- line_count: lineCount,
1253
- reasons,
1254
- });
1255
- }
1256
- }
1257
- }
1258
- // Sort by severity (number of reasons desc, then methods desc)
1259
- models.sort((a, b) => b.reasons.length - a.reasons.length || b.method_count - a.method_count);
1260
- return { models, total: models.length };
1261
- }
1262
- const AUDIT_TIMEOUT = 8000;
1263
- export async function phpProjectAudit(repo, options) {
1264
- const startTime = Date.now();
1265
- const gates = [];
1266
- const allChecks = ["security", "activerecord", "complexity", "dead_code", "patterns", "clones", "hotspots", "n_plus_one", "god_model", "yii_performance"];
1267
- const enabled = new Set(options?.checks ?? allChecks);
1268
- const fp = options?.file_pattern ?? ".php";
1269
- const secOpts = {};
1270
- if (options?.file_pattern)
1271
- secOpts.file_pattern = options.file_pattern;
1272
- const tasks = [];
1273
- if (enabled.has("security"))
1274
- tasks.push({ name: "security", run: () => phpSecurityScan(repo, secOpts) });
1275
- if (enabled.has("activerecord"))
1276
- tasks.push({ name: "activerecord", run: () => analyzeActiveRecord(repo, options?.file_pattern ? { file_pattern: options.file_pattern } : undefined) });
1277
- if (enabled.has("complexity"))
1278
- tasks.push({ name: "complexity", run: async () => { const { analyzeComplexity } = await import("./complexity-tools.js"); return analyzeComplexity(repo, { file_pattern: fp, top_n: 10 }); } });
1279
- if (enabled.has("dead_code"))
1280
- tasks.push({ name: "dead_code", run: async () => { const { findDeadCode } = await import("./symbol-tools.js"); return findDeadCode(repo, { file_pattern: fp }); } });
1281
- if (enabled.has("patterns"))
1282
- tasks.push({ name: "patterns", run: () => searchPatterns(repo, "empty-catch", { file_pattern: fp }) });
1283
- if (enabled.has("clones"))
1284
- tasks.push({ name: "clones", run: async () => { const { findClones } = await import("./clone-tools.js"); return findClones(repo, { file_pattern: fp }); } });
1285
- if (enabled.has("hotspots"))
1286
- tasks.push({ name: "hotspots", run: async () => { const { analyzeHotspots } = await import("./hotspot-tools.js"); return analyzeHotspots(repo, {}); } });
1287
- if (enabled.has("n_plus_one"))
1288
- tasks.push({ name: "n_plus_one", run: () => findPhpNPlusOne(repo, options?.file_pattern ? { file_pattern: options.file_pattern } : undefined) });
1289
- if (enabled.has("god_model"))
1290
- tasks.push({ name: "god_model", run: () => findPhpGodModel(repo) });
1291
- if (enabled.has("yii_performance")) {
1292
- // Sprint 7: 5 perf patterns sourced from tgm-panel performance-audit
1293
- // findings. Run them through the file-level scanner alongside
1294
- // file-level security patterns so module-level matches (configs,
1295
- // entry-points, view files) are picked up. Each pattern uses its own
1296
- // severity tier consistent with the perf-audit recommendations.
1297
- const PERF_PATTERNS = [
1298
- { pattern: "yii-translate-in-loop", severity: "medium" },
1299
- { pattern: "yii-dbtarget-info-level", severity: "medium" },
1300
- { pattern: "yii-find-with-large-then-filter", severity: "high" },
1301
- { pattern: "yii-cache-no-ttl", severity: "low" },
1302
- { pattern: "yii-no-batch-on-large", severity: "high" },
1303
- ];
1304
- tasks.push({
1305
- name: "yii_performance",
1306
- run: async () => {
1307
- // We reuse the security scan plumbing (parallel pattern runs +
1308
- // file-level fallback) but with the perf catalog. The result shape
1309
- // matches PhpSecurityScanResult — caller treats it as informational.
1310
- const findings = [];
1311
- const summary = { critical: 0, high: 0, medium: 0, low: 0, total: 0 };
1312
- const symbolResults = await Promise.all(PERF_PATTERNS.map((check) => searchPatterns(repo, check.pattern, {
1313
- file_pattern: fp,
1314
- include_tests: false,
1315
- }).then((r) => ({ check, result: r })).catch(() => null)));
1316
- for (const res of symbolResults) {
1317
- if (!res)
1318
- continue;
1319
- for (const m of res.result.matches) {
1320
- findings.push({
1321
- severity: res.check.severity,
1322
- pattern: res.check.pattern,
1323
- file: m.file,
1324
- line: m.start_line,
1325
- context: m.context,
1326
- description: "",
1327
- });
1328
- summary[res.check.severity]++;
1329
- summary.total++;
1330
- }
1331
- }
1332
- return {
1333
- findings,
1334
- summary,
1335
- checks_run: PERF_PATTERNS.map((p) => p.pattern),
1336
- };
1337
- },
1338
- });
1339
- }
1340
- const settled = await Promise.allSettled(tasks.map(async (t) => {
1341
- const s = Date.now();
1342
- const r = await Promise.race([t.run(), new Promise((ok) => setTimeout(() => ok("TIMEOUT"), AUDIT_TIMEOUT))]);
1343
- return { name: t.name, result: r, ms: Date.now() - s };
1344
- }));
1345
- let securityResult = { findings: [], summary: { critical: 0, high: 0, medium: 0, low: 0, total: 0 }, checks_run: [] };
1346
- let arResult = { models: [], total: 0 };
1347
- let totalFindings = 0;
1348
- for (const s of settled) {
1349
- if (s.status === "rejected") {
1350
- gates.push({ name: "unknown", status: "error", findings_count: 0, duration_ms: 0, error: String(s.reason) });
1351
- continue;
1352
- }
1353
- const { name, result, ms } = s.value;
1354
- if (result === "TIMEOUT") {
1355
- gates.push({ name, status: "timeout", findings_count: 0, duration_ms: ms });
1356
- continue;
1357
- }
1358
- let count = 0;
1359
- // activerecord is informational (model count), not a problem finding — excluded from totalFindings and health score
1360
- if (name === "security") {
1361
- securityResult = result;
1362
- count = securityResult.summary.total;
1363
- }
1364
- else if (name === "activerecord") {
1365
- arResult = result;
1366
- count = arResult.total;
1367
- }
1368
- else if (name === "complexity")
1369
- count = result?.summary?.above_threshold ?? 0;
1370
- else if (name === "dead_code")
1371
- count = result?.candidates?.length ?? 0;
1372
- else if (name === "patterns")
1373
- count = result?.matches?.length ?? 0;
1374
- else if (name === "clones")
1375
- count = result?.clones?.length ?? 0;
1376
- else if (name === "hotspots")
1377
- count = result?.hotspots?.length ?? 0;
1378
- else if (name === "n_plus_one")
1379
- count = result?.findings?.length ?? 0;
1380
- else if (name === "god_model")
1381
- count = result?.models?.length ?? 0;
1382
- else if (name === "yii_performance")
1383
- count = result?.findings?.length ?? 0;
1384
- if (name !== "activerecord")
1385
- totalFindings += count;
1386
- gates.push({ name, status: "ok", findings_count: count, duration_ms: ms });
1387
- }
1388
- const sec = securityResult.summary;
1389
- // Logarithmic penalties — a few critical findings are serious, but hundreds of
1390
- // complexity warnings shouldn't tank the score to 0. Each gate uses log2 scaling
1391
- // so 1 finding ≈ 0, 10 ≈ 17, 100 ≈ 33, 1000 ≈ 50 penalty points.
1392
- const secPenalty = sec.total > 0 ? Math.round(Math.log2(sec.total + 1) * (sec.critical > 0 ? 8 : 4)) : 0;
1393
- const qualityFindings = totalFindings - sec.total;
1394
- const qualPenalty = qualityFindings > 0 ? Math.round(Math.log2(qualityFindings + 1) * 4) : 0;
1395
- const healthScore = Math.max(0, Math.min(100, 100 - secPenalty - qualPenalty));
1396
- const topRisks = gates.filter(g => g.findings_count > 0 && g.name !== "activerecord").sort((a, b) => b.findings_count - a.findings_count).slice(0, 3).map(g => `${g.name}: ${g.findings_count} findings`);
1397
- return {
1398
- repo, duration_ms: Date.now() - startTime,
1399
- checks_run: gates.filter(g => g.status === "ok").map(g => g.name),
1400
- gates,
1401
- summary: { total_findings: totalFindings, critical: sec.critical, high: sec.high, medium: sec.medium, low: sec.low, health_score: healthScore, top_risks: topRisks },
1402
- security: securityResult,
1403
- activerecord: arResult,
1404
- };
1405
- }
1406
- // ---------------------------------------------------------------------------
1407
- // Helpers
1408
- // ---------------------------------------------------------------------------
1409
- async function readJsonSafe(path) {
1410
- try {
1411
- const content = await readFile(path, "utf-8");
1412
- return JSON.parse(content);
1413
- }
1414
- catch {
1415
- return null;
1416
- }
1417
- }
1418
- function extractLineContext(source, index) {
1419
- const lineStart = source.lastIndexOf("\n", index) + 1;
1420
- const lineEnd = source.indexOf("\n", index);
1421
- const end = lineEnd === -1 ? source.length : lineEnd;
1422
- return source.slice(lineStart, end).trim().slice(0, 200);
1423
- }
1424
- function pascalToKebab(s) {
1425
- return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
1426
- }
4
+ * Compatibility facade: public exports remain stable while implementations
5
+ * live in per-tool modules.
6
+ */
7
+ export { resolvePhpNamespace } from "./php-namespace-tools.js";
8
+ export { analyzeActiveRecord } from "./php-active-record-tools.js";
9
+ export { tracePhpEvent } from "./php-event-tools.js";
10
+ export { findPhpViews } from "./php-view-tools.js";
11
+ export { resolvePhpService } from "./php-service-tools.js";
12
+ export { phpSecurityScan } from "./php-security-tools.js";
13
+ export { findPhpNPlusOne } from "./php-nplus1-tools.js";
14
+ export { findPhpGodModel } from "./php-god-model-tools.js";
15
+ export { phpProjectAudit } from "./php-project-audit-tools.js";
1427
16
  //# sourceMappingURL=php-tools.js.map