codesift-mcp 0.3.0 → 0.5.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 (543) hide show
  1. package/README.md +215 -23
  2. package/dist/cache/hono-cache.d.ts +50 -0
  3. package/dist/cache/hono-cache.d.ts.map +1 -0
  4. package/dist/cache/hono-cache.js +132 -0
  5. package/dist/cache/hono-cache.js.map +1 -0
  6. package/dist/cli/help.d.ts.map +1 -1
  7. package/dist/cli/help.js +8 -6
  8. package/dist/cli/help.js.map +1 -1
  9. package/dist/cli/platform.d.ts.map +1 -1
  10. package/dist/cli/platform.js +12 -14
  11. package/dist/cli/platform.js.map +1 -1
  12. package/dist/cli/setup.d.ts +1 -1
  13. package/dist/cli/setup.d.ts.map +1 -1
  14. package/dist/cli/setup.js +27 -3
  15. package/dist/cli/setup.js.map +1 -1
  16. package/dist/formatters-shortening.d.ts +13 -0
  17. package/dist/formatters-shortening.d.ts.map +1 -1
  18. package/dist/formatters-shortening.js +131 -0
  19. package/dist/formatters-shortening.js.map +1 -1
  20. package/dist/formatters.d.ts +38 -0
  21. package/dist/formatters.d.ts.map +1 -1
  22. package/dist/formatters.js +521 -0
  23. package/dist/formatters.js.map +1 -1
  24. package/dist/instructions.d.ts +1 -1
  25. package/dist/instructions.d.ts.map +1 -1
  26. package/dist/instructions.js +39 -38
  27. package/dist/instructions.js.map +1 -1
  28. package/dist/lsp/lsp-servers.d.ts.map +1 -1
  29. package/dist/lsp/lsp-servers.js +5 -0
  30. package/dist/lsp/lsp-servers.js.map +1 -1
  31. package/dist/lsp/lsp-tools.d.ts.map +1 -1
  32. package/dist/lsp/lsp-tools.js +1 -0
  33. package/dist/lsp/lsp-tools.js.map +1 -1
  34. package/dist/parser/astro-template.d.ts +47 -0
  35. package/dist/parser/astro-template.d.ts.map +1 -0
  36. package/dist/parser/astro-template.js +171 -0
  37. package/dist/parser/astro-template.js.map +1 -0
  38. package/dist/parser/extractors/_shared.d.ts +4 -0
  39. package/dist/parser/extractors/_shared.d.ts.map +1 -1
  40. package/dist/parser/extractors/_shared.js +8 -0
  41. package/dist/parser/extractors/_shared.js.map +1 -1
  42. package/dist/parser/extractors/astro.d.ts +4 -5
  43. package/dist/parser/extractors/astro.d.ts.map +1 -1
  44. package/dist/parser/extractors/astro.js +102 -26
  45. package/dist/parser/extractors/astro.js.map +1 -1
  46. package/dist/parser/extractors/gradle-kts.d.ts +4 -0
  47. package/dist/parser/extractors/gradle-kts.d.ts.map +1 -0
  48. package/dist/parser/extractors/gradle-kts.js +246 -0
  49. package/dist/parser/extractors/gradle-kts.js.map +1 -0
  50. package/dist/parser/extractors/hono-inline-analyzer.d.ts +34 -0
  51. package/dist/parser/extractors/hono-inline-analyzer.d.ts.map +1 -0
  52. package/dist/parser/extractors/hono-inline-analyzer.js +465 -0
  53. package/dist/parser/extractors/hono-inline-analyzer.js.map +1 -0
  54. package/dist/parser/extractors/hono-model.d.ts +196 -0
  55. package/dist/parser/extractors/hono-model.d.ts.map +1 -0
  56. package/dist/parser/extractors/hono-model.js +10 -0
  57. package/dist/parser/extractors/hono-model.js.map +1 -0
  58. package/dist/parser/extractors/hono.d.ts +118 -0
  59. package/dist/parser/extractors/hono.d.ts.map +1 -0
  60. package/dist/parser/extractors/hono.js +1527 -0
  61. package/dist/parser/extractors/hono.js.map +1 -0
  62. package/dist/parser/extractors/kotlin.d.ts +4 -0
  63. package/dist/parser/extractors/kotlin.d.ts.map +1 -0
  64. package/dist/parser/extractors/kotlin.js +521 -0
  65. package/dist/parser/extractors/kotlin.js.map +1 -0
  66. package/dist/parser/extractors/php.d.ts +22 -0
  67. package/dist/parser/extractors/php.d.ts.map +1 -0
  68. package/dist/parser/extractors/php.js +334 -0
  69. package/dist/parser/extractors/php.js.map +1 -0
  70. package/dist/parser/extractors/python.d.ts.map +1 -1
  71. package/dist/parser/extractors/python.js +234 -11
  72. package/dist/parser/extractors/python.js.map +1 -1
  73. package/dist/parser/extractors/sql.d.ts +33 -0
  74. package/dist/parser/extractors/sql.d.ts.map +1 -0
  75. package/dist/parser/extractors/sql.js +506 -0
  76. package/dist/parser/extractors/sql.js.map +1 -0
  77. package/dist/parser/extractors/typescript.d.ts.map +1 -1
  78. package/dist/parser/extractors/typescript.js +209 -3
  79. package/dist/parser/extractors/typescript.js.map +1 -1
  80. package/dist/parser/languages/tree-sitter-javascript.wasm +0 -0
  81. package/dist/parser/languages/tree-sitter-kotlin.wasm +0 -0
  82. package/dist/parser/languages/tree-sitter-php.wasm +0 -0
  83. package/dist/parser/languages/tree-sitter-php_only.wasm +0 -0
  84. package/dist/parser/languages/tree-sitter-python.wasm +0 -0
  85. package/dist/parser/parse-cache.d.ts +39 -0
  86. package/dist/parser/parse-cache.d.ts.map +1 -0
  87. package/dist/parser/parse-cache.js +87 -0
  88. package/dist/parser/parse-cache.js.map +1 -0
  89. package/dist/parser/parser-manager.d.ts +32 -0
  90. package/dist/parser/parser-manager.d.ts.map +1 -1
  91. package/dist/parser/parser-manager.js +93 -3
  92. package/dist/parser/parser-manager.js.map +1 -1
  93. package/dist/parser/symbol-extractor.d.ts.map +1 -1
  94. package/dist/parser/symbol-extractor.js +16 -0
  95. package/dist/parser/symbol-extractor.js.map +1 -1
  96. package/dist/register-tools.d.ts +38 -2
  97. package/dist/register-tools.d.ts.map +1 -1
  98. package/dist/register-tools.js +2444 -195
  99. package/dist/register-tools.js.map +1 -1
  100. package/dist/search/reranker.js +1 -1
  101. package/dist/search/reranker.js.map +1 -1
  102. package/dist/search/tool-ranker.d.ts +90 -0
  103. package/dist/search/tool-ranker.d.ts.map +1 -0
  104. package/dist/search/tool-ranker.js +420 -0
  105. package/dist/search/tool-ranker.js.map +1 -0
  106. package/dist/server-helpers.d.ts.map +1 -1
  107. package/dist/server-helpers.js +11 -0
  108. package/dist/server-helpers.js.map +1 -1
  109. package/dist/server.js +47 -14
  110. package/dist/server.js.map +1 -1
  111. package/dist/storage/index-store.d.ts +15 -1
  112. package/dist/storage/index-store.d.ts.map +1 -1
  113. package/dist/storage/index-store.js +27 -1
  114. package/dist/storage/index-store.js.map +1 -1
  115. package/dist/storage/session-state.d.ts +1 -1
  116. package/dist/storage/session-state.d.ts.map +1 -1
  117. package/dist/storage/session-state.js +6 -4
  118. package/dist/storage/session-state.js.map +1 -1
  119. package/dist/storage/usage-tracker.d.ts.map +1 -1
  120. package/dist/storage/usage-tracker.js +4 -1
  121. package/dist/storage/usage-tracker.js.map +1 -1
  122. package/dist/tools/agent-config-tools.d.ts +24 -0
  123. package/dist/tools/agent-config-tools.d.ts.map +1 -0
  124. package/dist/tools/agent-config-tools.js +119 -0
  125. package/dist/tools/agent-config-tools.js.map +1 -0
  126. package/dist/tools/architecture-tools.d.ts +23 -0
  127. package/dist/tools/architecture-tools.d.ts.map +1 -0
  128. package/dist/tools/architecture-tools.js +140 -0
  129. package/dist/tools/architecture-tools.js.map +1 -0
  130. package/dist/tools/astro-actions.d.ts +54 -0
  131. package/dist/tools/astro-actions.d.ts.map +1 -0
  132. package/dist/tools/astro-actions.js +561 -0
  133. package/dist/tools/astro-actions.js.map +1 -0
  134. package/dist/tools/astro-audit.d.ts +87 -0
  135. package/dist/tools/astro-audit.d.ts.map +1 -0
  136. package/dist/tools/astro-audit.js +345 -0
  137. package/dist/tools/astro-audit.js.map +1 -0
  138. package/dist/tools/astro-config.d.ts +33 -0
  139. package/dist/tools/astro-config.d.ts.map +1 -0
  140. package/dist/tools/astro-config.js +260 -0
  141. package/dist/tools/astro-config.js.map +1 -0
  142. package/dist/tools/astro-content-collections.d.ts +44 -0
  143. package/dist/tools/astro-content-collections.d.ts.map +1 -0
  144. package/dist/tools/astro-content-collections.js +630 -0
  145. package/dist/tools/astro-content-collections.js.map +1 -0
  146. package/dist/tools/astro-islands.d.ts +63 -0
  147. package/dist/tools/astro-islands.d.ts.map +1 -0
  148. package/dist/tools/astro-islands.js +255 -0
  149. package/dist/tools/astro-islands.js.map +1 -0
  150. package/dist/tools/astro-migration.d.ts +31 -0
  151. package/dist/tools/astro-migration.d.ts.map +1 -0
  152. package/dist/tools/astro-migration.js +378 -0
  153. package/dist/tools/astro-migration.js.map +1 -0
  154. package/dist/tools/astro-routes.d.ts +49 -0
  155. package/dist/tools/astro-routes.d.ts.map +1 -0
  156. package/dist/tools/astro-routes.js +119 -0
  157. package/dist/tools/astro-routes.js.map +1 -0
  158. package/dist/tools/async-correctness.d.ts +26 -0
  159. package/dist/tools/async-correctness.d.ts.map +1 -0
  160. package/dist/tools/async-correctness.js +166 -0
  161. package/dist/tools/async-correctness.js.map +1 -0
  162. package/dist/tools/audit-tools.d.ts +38 -0
  163. package/dist/tools/audit-tools.d.ts.map +1 -0
  164. package/dist/tools/audit-tools.js +248 -0
  165. package/dist/tools/audit-tools.js.map +1 -0
  166. package/dist/tools/celery-tools.d.ts +38 -0
  167. package/dist/tools/celery-tools.d.ts.map +1 -0
  168. package/dist/tools/celery-tools.js +154 -0
  169. package/dist/tools/celery-tools.js.map +1 -0
  170. package/dist/tools/clone-tools.js +1 -1
  171. package/dist/tools/clone-tools.js.map +1 -1
  172. package/dist/tools/complexity-tools.d.ts +4 -0
  173. package/dist/tools/complexity-tools.d.ts.map +1 -1
  174. package/dist/tools/complexity-tools.js +78 -4
  175. package/dist/tools/complexity-tools.js.map +1 -1
  176. package/dist/tools/compose-tools.d.ts +60 -0
  177. package/dist/tools/compose-tools.d.ts.map +1 -0
  178. package/dist/tools/compose-tools.js +203 -0
  179. package/dist/tools/compose-tools.js.map +1 -0
  180. package/dist/tools/coupling-tools.d.ts +50 -0
  181. package/dist/tools/coupling-tools.d.ts.map +1 -0
  182. package/dist/tools/coupling-tools.js +262 -0
  183. package/dist/tools/coupling-tools.js.map +1 -0
  184. package/dist/tools/dependency-audit-tools.d.ts +65 -0
  185. package/dist/tools/dependency-audit-tools.d.ts.map +1 -0
  186. package/dist/tools/dependency-audit-tools.js +553 -0
  187. package/dist/tools/dependency-audit-tools.js.map +1 -0
  188. package/dist/tools/django-settings.d.ts +22 -0
  189. package/dist/tools/django-settings.d.ts.map +1 -0
  190. package/dist/tools/django-settings.js +301 -0
  191. package/dist/tools/django-settings.js.map +1 -0
  192. package/dist/tools/django-view-security-tools.d.ts +32 -0
  193. package/dist/tools/django-view-security-tools.d.ts.map +1 -0
  194. package/dist/tools/django-view-security-tools.js +184 -0
  195. package/dist/tools/django-view-security-tools.js.map +1 -0
  196. package/dist/tools/fastapi-depends.d.ts +63 -0
  197. package/dist/tools/fastapi-depends.d.ts.map +1 -0
  198. package/dist/tools/fastapi-depends.js +191 -0
  199. package/dist/tools/fastapi-depends.js.map +1 -0
  200. package/dist/tools/frequency-tools.js +1 -1
  201. package/dist/tools/frequency-tools.js.map +1 -1
  202. package/dist/tools/graph-tools.d.ts +8 -2
  203. package/dist/tools/graph-tools.d.ts.map +1 -1
  204. package/dist/tools/graph-tools.js +44 -3
  205. package/dist/tools/graph-tools.js.map +1 -1
  206. package/dist/tools/hilt-tools.d.ts +55 -0
  207. package/dist/tools/hilt-tools.d.ts.map +1 -0
  208. package/dist/tools/hilt-tools.js +258 -0
  209. package/dist/tools/hilt-tools.js.map +1 -0
  210. package/dist/tools/hono-analyze-app.d.ts +48 -0
  211. package/dist/tools/hono-analyze-app.d.ts.map +1 -0
  212. package/dist/tools/hono-analyze-app.js +94 -0
  213. package/dist/tools/hono-analyze-app.js.map +1 -0
  214. package/dist/tools/hono-api-contract.d.ts +22 -0
  215. package/dist/tools/hono-api-contract.d.ts.map +1 -0
  216. package/dist/tools/hono-api-contract.js +112 -0
  217. package/dist/tools/hono-api-contract.js.map +1 -0
  218. package/dist/tools/hono-conditional-middleware.d.ts +27 -0
  219. package/dist/tools/hono-conditional-middleware.d.ts.map +1 -0
  220. package/dist/tools/hono-conditional-middleware.js +62 -0
  221. package/dist/tools/hono-conditional-middleware.js.map +1 -0
  222. package/dist/tools/hono-context-flow.d.ts +24 -0
  223. package/dist/tools/hono-context-flow.d.ts.map +1 -0
  224. package/dist/tools/hono-context-flow.js +70 -0
  225. package/dist/tools/hono-context-flow.js.map +1 -0
  226. package/dist/tools/hono-dead-routes.d.ts +26 -0
  227. package/dist/tools/hono-dead-routes.d.ts.map +1 -0
  228. package/dist/tools/hono-dead-routes.js +102 -0
  229. package/dist/tools/hono-dead-routes.js.map +1 -0
  230. package/dist/tools/hono-entry-resolver.d.ts +27 -0
  231. package/dist/tools/hono-entry-resolver.d.ts.map +1 -0
  232. package/dist/tools/hono-entry-resolver.js +31 -0
  233. package/dist/tools/hono-entry-resolver.js.map +1 -0
  234. package/dist/tools/hono-env-regression.d.ts +29 -0
  235. package/dist/tools/hono-env-regression.d.ts.map +1 -0
  236. package/dist/tools/hono-env-regression.js +157 -0
  237. package/dist/tools/hono-env-regression.js.map +1 -0
  238. package/dist/tools/hono-inline-analyze.d.ts +31 -0
  239. package/dist/tools/hono-inline-analyze.d.ts.map +1 -0
  240. package/dist/tools/hono-inline-analyze.js +59 -0
  241. package/dist/tools/hono-inline-analyze.js.map +1 -0
  242. package/dist/tools/hono-middleware-chain.d.ts +40 -0
  243. package/dist/tools/hono-middleware-chain.d.ts.map +1 -0
  244. package/dist/tools/hono-middleware-chain.js +121 -0
  245. package/dist/tools/hono-middleware-chain.js.map +1 -0
  246. package/dist/tools/hono-modules.d.ts +22 -0
  247. package/dist/tools/hono-modules.d.ts.map +1 -0
  248. package/dist/tools/hono-modules.js +118 -0
  249. package/dist/tools/hono-modules.js.map +1 -0
  250. package/dist/tools/hono-response-types.d.ts +37 -0
  251. package/dist/tools/hono-response-types.d.ts.map +1 -0
  252. package/dist/tools/hono-response-types.js +76 -0
  253. package/dist/tools/hono-response-types.js.map +1 -0
  254. package/dist/tools/hono-rpc-types.d.ts +21 -0
  255. package/dist/tools/hono-rpc-types.d.ts.map +1 -0
  256. package/dist/tools/hono-rpc-types.js +49 -0
  257. package/dist/tools/hono-rpc-types.js.map +1 -0
  258. package/dist/tools/hono-security.d.ts +31 -0
  259. package/dist/tools/hono-security.d.ts.map +1 -0
  260. package/dist/tools/hono-security.js +269 -0
  261. package/dist/tools/hono-security.js.map +1 -0
  262. package/dist/tools/hono-visualize.d.ts +13 -0
  263. package/dist/tools/hono-visualize.d.ts.map +1 -0
  264. package/dist/tools/hono-visualize.js +64 -0
  265. package/dist/tools/hono-visualize.js.map +1 -0
  266. package/dist/tools/hotspot-tools.d.ts.map +1 -1
  267. package/dist/tools/hotspot-tools.js +9 -7
  268. package/dist/tools/hotspot-tools.js.map +1 -1
  269. package/dist/tools/index-tools.d.ts +17 -0
  270. package/dist/tools/index-tools.d.ts.map +1 -1
  271. package/dist/tools/index-tools.js +210 -10
  272. package/dist/tools/index-tools.js.map +1 -1
  273. package/dist/tools/kotlin-tools.d.ts +142 -0
  274. package/dist/tools/kotlin-tools.d.ts.map +1 -0
  275. package/dist/tools/kotlin-tools.js +572 -0
  276. package/dist/tools/kotlin-tools.js.map +1 -0
  277. package/dist/tools/legacy-hono-conventions.d.ts +14 -0
  278. package/dist/tools/legacy-hono-conventions.d.ts.map +1 -0
  279. package/dist/tools/legacy-hono-conventions.js +152 -0
  280. package/dist/tools/legacy-hono-conventions.js.map +1 -0
  281. package/dist/tools/migration-lint-tools.d.ts +26 -0
  282. package/dist/tools/migration-lint-tools.d.ts.map +1 -0
  283. package/dist/tools/migration-lint-tools.js +247 -0
  284. package/dist/tools/migration-lint-tools.js.map +1 -0
  285. package/dist/tools/model-tools.d.ts +30 -0
  286. package/dist/tools/model-tools.d.ts.map +1 -0
  287. package/dist/tools/model-tools.js +145 -0
  288. package/dist/tools/model-tools.js.map +1 -0
  289. package/dist/tools/nest-ext-tools.d.ts +207 -0
  290. package/dist/tools/nest-ext-tools.d.ts.map +1 -0
  291. package/dist/tools/nest-ext-tools.js +752 -0
  292. package/dist/tools/nest-ext-tools.js.map +1 -0
  293. package/dist/tools/nest-tools.d.ts +198 -0
  294. package/dist/tools/nest-tools.d.ts.map +1 -0
  295. package/dist/tools/nest-tools.js +1142 -0
  296. package/dist/tools/nest-tools.js.map +1 -0
  297. package/dist/tools/nextjs-api-contract-readers.d.ts +14 -0
  298. package/dist/tools/nextjs-api-contract-readers.d.ts.map +1 -0
  299. package/dist/tools/nextjs-api-contract-readers.js +204 -0
  300. package/dist/tools/nextjs-api-contract-readers.js.map +1 -0
  301. package/dist/tools/nextjs-api-contract-tools.d.ts +57 -0
  302. package/dist/tools/nextjs-api-contract-tools.d.ts.map +1 -0
  303. package/dist/tools/nextjs-api-contract-tools.js +144 -0
  304. package/dist/tools/nextjs-api-contract-tools.js.map +1 -0
  305. package/dist/tools/nextjs-boundary-tools.d.ts +39 -0
  306. package/dist/tools/nextjs-boundary-tools.d.ts.map +1 -0
  307. package/dist/tools/nextjs-boundary-tools.js +152 -0
  308. package/dist/tools/nextjs-boundary-tools.js.map +1 -0
  309. package/dist/tools/nextjs-component-readers.d.ts +101 -0
  310. package/dist/tools/nextjs-component-readers.d.ts.map +1 -0
  311. package/dist/tools/nextjs-component-readers.js +287 -0
  312. package/dist/tools/nextjs-component-readers.js.map +1 -0
  313. package/dist/tools/nextjs-component-tools.d.ts +51 -0
  314. package/dist/tools/nextjs-component-tools.d.ts.map +1 -0
  315. package/dist/tools/nextjs-component-tools.js +212 -0
  316. package/dist/tools/nextjs-component-tools.js.map +1 -0
  317. package/dist/tools/nextjs-data-flow-tools.d.ts +42 -0
  318. package/dist/tools/nextjs-data-flow-tools.d.ts.map +1 -0
  319. package/dist/tools/nextjs-data-flow-tools.js +158 -0
  320. package/dist/tools/nextjs-data-flow-tools.js.map +1 -0
  321. package/dist/tools/nextjs-framework-audit-tools.d.ts +60 -0
  322. package/dist/tools/nextjs-framework-audit-tools.d.ts.map +1 -0
  323. package/dist/tools/nextjs-framework-audit-tools.js +394 -0
  324. package/dist/tools/nextjs-framework-audit-tools.js.map +1 -0
  325. package/dist/tools/nextjs-link-tools.d.ts +41 -0
  326. package/dist/tools/nextjs-link-tools.d.ts.map +1 -0
  327. package/dist/tools/nextjs-link-tools.js +157 -0
  328. package/dist/tools/nextjs-link-tools.js.map +1 -0
  329. package/dist/tools/nextjs-metadata-tools.d.ts +74 -0
  330. package/dist/tools/nextjs-metadata-tools.d.ts.map +1 -0
  331. package/dist/tools/nextjs-metadata-tools.js +252 -0
  332. package/dist/tools/nextjs-metadata-tools.js.map +1 -0
  333. package/dist/tools/nextjs-middleware-coverage-tools.d.ts +41 -0
  334. package/dist/tools/nextjs-middleware-coverage-tools.d.ts.map +1 -0
  335. package/dist/tools/nextjs-middleware-coverage-tools.js +88 -0
  336. package/dist/tools/nextjs-middleware-coverage-tools.js.map +1 -0
  337. package/dist/tools/nextjs-route-readers.d.ts +81 -0
  338. package/dist/tools/nextjs-route-readers.d.ts.map +1 -0
  339. package/dist/tools/nextjs-route-readers.js +340 -0
  340. package/dist/tools/nextjs-route-readers.js.map +1 -0
  341. package/dist/tools/nextjs-route-tools.d.ts +36 -0
  342. package/dist/tools/nextjs-route-tools.d.ts.map +1 -0
  343. package/dist/tools/nextjs-route-tools.js +175 -0
  344. package/dist/tools/nextjs-route-tools.js.map +1 -0
  345. package/dist/tools/nextjs-security-readers.d.ts +22 -0
  346. package/dist/tools/nextjs-security-readers.d.ts.map +1 -0
  347. package/dist/tools/nextjs-security-readers.js +318 -0
  348. package/dist/tools/nextjs-security-readers.js.map +1 -0
  349. package/dist/tools/nextjs-security-scoring.d.ts +15 -0
  350. package/dist/tools/nextjs-security-scoring.d.ts.map +1 -0
  351. package/dist/tools/nextjs-security-scoring.js +65 -0
  352. package/dist/tools/nextjs-security-scoring.js.map +1 -0
  353. package/dist/tools/nextjs-security-tools.d.ts +75 -0
  354. package/dist/tools/nextjs-security-tools.d.ts.map +1 -0
  355. package/dist/tools/nextjs-security-tools.js +153 -0
  356. package/dist/tools/nextjs-security-tools.js.map +1 -0
  357. package/dist/tools/nextjs-tools.d.ts +15 -0
  358. package/dist/tools/nextjs-tools.d.ts.map +1 -0
  359. package/dist/tools/nextjs-tools.js +15 -0
  360. package/dist/tools/nextjs-tools.js.map +1 -0
  361. package/dist/tools/outline-tools.d.ts.map +1 -1
  362. package/dist/tools/outline-tools.js +20 -0
  363. package/dist/tools/outline-tools.js.map +1 -1
  364. package/dist/tools/pattern-tools.d.ts +8 -0
  365. package/dist/tools/pattern-tools.d.ts.map +1 -1
  366. package/dist/tools/pattern-tools.js +651 -3
  367. package/dist/tools/pattern-tools.js.map +1 -1
  368. package/dist/tools/perf-tools.d.ts +32 -0
  369. package/dist/tools/perf-tools.d.ts.map +1 -0
  370. package/dist/tools/perf-tools.js +227 -0
  371. package/dist/tools/perf-tools.js.map +1 -0
  372. package/dist/tools/php-tools.d.ts +185 -0
  373. package/dist/tools/php-tools.d.ts.map +1 -0
  374. package/dist/tools/php-tools.js +645 -0
  375. package/dist/tools/php-tools.js.map +1 -0
  376. package/dist/tools/plan-turn-tools.d.ts +89 -0
  377. package/dist/tools/plan-turn-tools.d.ts.map +1 -0
  378. package/dist/tools/plan-turn-tools.js +508 -0
  379. package/dist/tools/plan-turn-tools.js.map +1 -0
  380. package/dist/tools/prisma-schema-tools.d.ts +44 -0
  381. package/dist/tools/prisma-schema-tools.d.ts.map +1 -0
  382. package/dist/tools/prisma-schema-tools.js +358 -0
  383. package/dist/tools/prisma-schema-tools.js.map +1 -0
  384. package/dist/tools/project-tools.d.ts +116 -7
  385. package/dist/tools/project-tools.d.ts.map +1 -1
  386. package/dist/tools/project-tools.js +595 -218
  387. package/dist/tools/project-tools.js.map +1 -1
  388. package/dist/tools/pydantic-models.d.ts +46 -0
  389. package/dist/tools/pydantic-models.d.ts.map +1 -0
  390. package/dist/tools/pydantic-models.js +249 -0
  391. package/dist/tools/pydantic-models.js.map +1 -0
  392. package/dist/tools/pyproject-tools.d.ts +23 -0
  393. package/dist/tools/pyproject-tools.d.ts.map +1 -0
  394. package/dist/tools/pyproject-tools.js +133 -0
  395. package/dist/tools/pyproject-tools.js.map +1 -0
  396. package/dist/tools/pytest-tools.d.ts +20 -0
  397. package/dist/tools/pytest-tools.d.ts.map +1 -0
  398. package/dist/tools/pytest-tools.js +106 -0
  399. package/dist/tools/pytest-tools.js.map +1 -0
  400. package/dist/tools/python-audit.d.ts +40 -0
  401. package/dist/tools/python-audit.d.ts.map +1 -0
  402. package/dist/tools/python-audit.js +244 -0
  403. package/dist/tools/python-audit.js.map +1 -0
  404. package/dist/tools/python-callers.d.ts +28 -0
  405. package/dist/tools/python-callers.d.ts.map +1 -0
  406. package/dist/tools/python-callers.js +110 -0
  407. package/dist/tools/python-callers.js.map +1 -0
  408. package/dist/tools/python-circular-imports.d.ts +19 -0
  409. package/dist/tools/python-circular-imports.d.ts.map +1 -0
  410. package/dist/tools/python-circular-imports.js +126 -0
  411. package/dist/tools/python-circular-imports.js.map +1 -0
  412. package/dist/tools/python-constants-tools.d.ts +44 -0
  413. package/dist/tools/python-constants-tools.d.ts.map +1 -0
  414. package/dist/tools/python-constants-tools.js +525 -0
  415. package/dist/tools/python-constants-tools.js.map +1 -0
  416. package/dist/tools/python-deps-analyzer.d.ts +46 -0
  417. package/dist/tools/python-deps-analyzer.d.ts.map +1 -0
  418. package/dist/tools/python-deps-analyzer.js +227 -0
  419. package/dist/tools/python-deps-analyzer.js.map +1 -0
  420. package/dist/tools/query-tools.d.ts +23 -0
  421. package/dist/tools/query-tools.d.ts.map +1 -0
  422. package/dist/tools/query-tools.js +256 -0
  423. package/dist/tools/query-tools.js.map +1 -0
  424. package/dist/tools/react-tools.d.ts +263 -0
  425. package/dist/tools/react-tools.d.ts.map +1 -0
  426. package/dist/tools/react-tools.js +839 -0
  427. package/dist/tools/react-tools.js.map +1 -0
  428. package/dist/tools/report-tools.js +47 -0
  429. package/dist/tools/report-tools.js.map +1 -1
  430. package/dist/tools/review-diff-tools.d.ts +5 -4
  431. package/dist/tools/review-diff-tools.d.ts.map +1 -1
  432. package/dist/tools/review-diff-tools.js +157 -66
  433. package/dist/tools/review-diff-tools.js.map +1 -1
  434. package/dist/tools/room-tools.d.ts +36 -0
  435. package/dist/tools/room-tools.d.ts.map +1 -0
  436. package/dist/tools/room-tools.js +147 -0
  437. package/dist/tools/room-tools.js.map +1 -0
  438. package/dist/tools/route-tools.d.ts +27 -1
  439. package/dist/tools/route-tools.d.ts.map +1 -1
  440. package/dist/tools/route-tools.js +744 -18
  441. package/dist/tools/route-tools.js.map +1 -1
  442. package/dist/tools/ruff-tools.d.ts +32 -0
  443. package/dist/tools/ruff-tools.d.ts.map +1 -0
  444. package/dist/tools/ruff-tools.js +114 -0
  445. package/dist/tools/ruff-tools.js.map +1 -0
  446. package/dist/tools/search-ranker.d.ts.map +1 -1
  447. package/dist/tools/search-ranker.js +7 -0
  448. package/dist/tools/search-ranker.js.map +1 -1
  449. package/dist/tools/search-tools.d.ts +3 -2
  450. package/dist/tools/search-tools.d.ts.map +1 -1
  451. package/dist/tools/search-tools.js +16 -3
  452. package/dist/tools/search-tools.js.map +1 -1
  453. package/dist/tools/serialization-tools.d.ts +24 -0
  454. package/dist/tools/serialization-tools.d.ts.map +1 -0
  455. package/dist/tools/serialization-tools.js +156 -0
  456. package/dist/tools/serialization-tools.js.map +1 -0
  457. package/dist/tools/sql-tools.d.ts +274 -0
  458. package/dist/tools/sql-tools.d.ts.map +1 -0
  459. package/dist/tools/sql-tools.js +1160 -0
  460. package/dist/tools/sql-tools.js.map +1 -0
  461. package/dist/tools/status-tools.d.ts +10 -0
  462. package/dist/tools/status-tools.d.ts.map +1 -0
  463. package/dist/tools/status-tools.js +32 -0
  464. package/dist/tools/status-tools.js.map +1 -0
  465. package/dist/tools/symbol-tools.d.ts +19 -0
  466. package/dist/tools/symbol-tools.d.ts.map +1 -1
  467. package/dist/tools/symbol-tools.js +75 -4
  468. package/dist/tools/symbol-tools.js.map +1 -1
  469. package/dist/tools/taint-tools.d.ts +43 -0
  470. package/dist/tools/taint-tools.d.ts.map +1 -0
  471. package/dist/tools/taint-tools.js +922 -0
  472. package/dist/tools/taint-tools.js.map +1 -0
  473. package/dist/tools/test-impact-tools.d.ts +29 -0
  474. package/dist/tools/test-impact-tools.d.ts.map +1 -0
  475. package/dist/tools/test-impact-tools.js +156 -0
  476. package/dist/tools/test-impact-tools.js.map +1 -0
  477. package/dist/tools/typecheck-tools.d.ts +39 -0
  478. package/dist/tools/typecheck-tools.d.ts.map +1 -0
  479. package/dist/tools/typecheck-tools.js +191 -0
  480. package/dist/tools/typecheck-tools.js.map +1 -0
  481. package/dist/tools/wiring-tools.d.ts +19 -0
  482. package/dist/tools/wiring-tools.d.ts.map +1 -0
  483. package/dist/tools/wiring-tools.js +147 -0
  484. package/dist/tools/wiring-tools.js.map +1 -0
  485. package/dist/types.d.ts +9 -1
  486. package/dist/types.d.ts.map +1 -1
  487. package/dist/utils/framework-detect.d.ts +18 -2
  488. package/dist/utils/framework-detect.d.ts.map +1 -1
  489. package/dist/utils/framework-detect.js +150 -3
  490. package/dist/utils/framework-detect.js.map +1 -1
  491. package/dist/utils/import-graph.d.ts +42 -0
  492. package/dist/utils/import-graph.d.ts.map +1 -1
  493. package/dist/utils/import-graph.js +248 -9
  494. package/dist/utils/import-graph.js.map +1 -1
  495. package/dist/utils/language-detect.d.ts +21 -0
  496. package/dist/utils/language-detect.d.ts.map +1 -0
  497. package/dist/utils/language-detect.js +183 -0
  498. package/dist/utils/language-detect.js.map +1 -0
  499. package/dist/utils/nextjs-ast-readers.d.ts +44 -0
  500. package/dist/utils/nextjs-ast-readers.d.ts.map +1 -0
  501. package/dist/utils/nextjs-ast-readers.js +341 -0
  502. package/dist/utils/nextjs-ast-readers.js.map +1 -0
  503. package/dist/utils/nextjs-audit-cache.d.ts +51 -0
  504. package/dist/utils/nextjs-audit-cache.d.ts.map +1 -0
  505. package/dist/utils/nextjs-audit-cache.js +116 -0
  506. package/dist/utils/nextjs-audit-cache.js.map +1 -0
  507. package/dist/utils/nextjs-metadata-readers.d.ts +65 -0
  508. package/dist/utils/nextjs-metadata-readers.d.ts.map +1 -0
  509. package/dist/utils/nextjs-metadata-readers.js +447 -0
  510. package/dist/utils/nextjs-metadata-readers.js.map +1 -0
  511. package/dist/utils/nextjs.d.ts +42 -0
  512. package/dist/utils/nextjs.d.ts.map +1 -0
  513. package/dist/utils/nextjs.js +284 -0
  514. package/dist/utils/nextjs.js.map +1 -0
  515. package/dist/utils/python-import-resolver.d.ts +42 -0
  516. package/dist/utils/python-import-resolver.d.ts.map +1 -0
  517. package/dist/utils/python-import-resolver.js +101 -0
  518. package/dist/utils/python-import-resolver.js.map +1 -0
  519. package/dist/utils/python-imports.d.ts +28 -0
  520. package/dist/utils/python-imports.d.ts.map +1 -0
  521. package/dist/utils/python-imports.js +117 -0
  522. package/dist/utils/python-imports.js.map +1 -0
  523. package/dist/utils/react-alias.d.ts +15 -0
  524. package/dist/utils/react-alias.d.ts.map +1 -0
  525. package/dist/utils/react-alias.js +31 -0
  526. package/dist/utils/react-alias.js.map +1 -0
  527. package/dist/utils/test-file.d.ts.map +1 -1
  528. package/dist/utils/test-file.js +7 -0
  529. package/dist/utils/test-file.js.map +1 -1
  530. package/dist/utils/walk.d.ts +22 -0
  531. package/dist/utils/walk.d.ts.map +1 -1
  532. package/dist/utils/walk.js +70 -2
  533. package/dist/utils/walk.js.map +1 -1
  534. package/package.json +4 -3
  535. package/rules/codesift.md +71 -5
  536. package/rules/codesift.mdc +71 -5
  537. package/rules/codex.md +71 -5
  538. package/rules/gemini.md +71 -5
  539. package/src/parser/languages/tree-sitter-javascript.wasm +0 -0
  540. package/src/parser/languages/tree-sitter-kotlin.wasm +0 -0
  541. package/src/parser/languages/tree-sitter-php.wasm +0 -0
  542. package/src/parser/languages/tree-sitter-php_only.wasm +0 -0
  543. package/src/parser/languages/tree-sitter-python.wasm +0 -0
@@ -0,0 +1,839 @@
1
+ /**
2
+ * React-specific code intelligence tools.
3
+ *
4
+ * - traceComponentTree: BFS component composition tree (which components
5
+ * render which, via JSX usage)
6
+ * - analyzeHooks: hook inventory + Rule of Hooks violation detection
7
+ * - analyzeRenders: static re-render risk analysis (inline props, missing memo)
8
+ */
9
+ import { getCodeIndex } from "./index-tools.js";
10
+ import { isTestFileStrict as isTestFile } from "../utils/test-file.js";
11
+ import { resolveAlias } from "../utils/react-alias.js";
12
+ export { buildJsxAdjacency, buildComponentTree, extractJsxComponents, extractHookCalls, extractHookNames, findRuleOfHooksViolations, findRenderRisks };
13
+ // formatRendersMarkdown and buildContextGraph are exported inline at definition site below
14
+ // ── Limits (mirror graph-tools.ts) ──────────────────────────
15
+ const MAX_TREE_NODES = 500;
16
+ const MAX_CHILDREN_PER_NODE = 20;
17
+ const DEFAULT_DEPTH = 3;
18
+ // ── React stdlib hooks (used as denylist in tracing and inventory) ──
19
+ export const REACT_STDLIB_HOOKS = new Set([
20
+ "useState", "useEffect", "useCallback", "useMemo", "useRef",
21
+ "useContext", "useReducer", "useLayoutEffect", "useImperativeHandle",
22
+ "useDebugValue", "useDeferredValue", "useTransition", "useId",
23
+ "useSyncExternalStore", "useInsertionEffect", "useOptimistic",
24
+ "useFormState", "useFormStatus", "use",
25
+ ]);
26
+ /**
27
+ * Extract PascalCase JSX element names from source code.
28
+ * Returns the set of component names used via `<ComponentName ...>` or `<ComponentName/>`.
29
+ * HTML elements (lowercase) are skipped.
30
+ */
31
+ function extractJsxComponents(source) {
32
+ const names = new Set();
33
+ const pattern = /<([A-Z][a-zA-Z0-9_$]*)\b/g;
34
+ let m;
35
+ while ((m = pattern.exec(source)) !== null) {
36
+ names.add(m[1]);
37
+ }
38
+ return names;
39
+ }
40
+ /**
41
+ * Build component → rendered-components adjacency from the index.
42
+ * Only considers symbols with kind "component" (requires Wave 1 extractor).
43
+ */
44
+ function buildJsxAdjacency(symbols) {
45
+ const children = new Map();
46
+ // name → component symbols lookup (may have multiple definitions with same name)
47
+ const nameToComponents = new Map();
48
+ // file → component symbols lookup (used by alias-resolved imports)
49
+ const fileToComponents = new Map();
50
+ for (const sym of symbols) {
51
+ if (sym.kind !== "component")
52
+ continue;
53
+ const existing = nameToComponents.get(sym.name);
54
+ if (existing)
55
+ existing.push(sym);
56
+ else
57
+ nameToComponents.set(sym.name, [sym]);
58
+ const fileExisting = fileToComponents.get(sym.file);
59
+ if (fileExisting)
60
+ fileExisting.push(sym);
61
+ else
62
+ fileToComponents.set(sym.file, [sym]);
63
+ }
64
+ // Build a synthetic files list for resolveAlias() — needs only `path` field.
65
+ const filesList = [...fileToComponents.keys()].map((path) => ({ path }));
66
+ for (const sym of symbols) {
67
+ if (sym.kind !== "component" || !sym.source)
68
+ continue;
69
+ const rendered = extractJsxComponents(sym.source);
70
+ const childList = [];
71
+ // Parse alias imports in this component's source for fallback resolution
72
+ // (Tier 4 — Item 8 wired into trace_component_tree).
73
+ // Pattern: import { X, Y as Z } from "@/components/Button"
74
+ // Pattern: import Default from "@/components/Foo"
75
+ const aliasImports = new Map(); // localName → resolved file
76
+ const importRe = /import\s+(?:(\w+)|(?:\{([^}]+)\}))(?:\s*,\s*(?:(\w+)|(?:\{([^}]+)\})))?\s+from\s+["'](@\/[^"']+)["']/g;
77
+ let im;
78
+ while ((im = importRe.exec(sym.source)) !== null) {
79
+ const aliasPath = im[5];
80
+ const resolved = resolveAlias(aliasPath, filesList);
81
+ if (!resolved)
82
+ continue;
83
+ // default import
84
+ if (im[1])
85
+ aliasImports.set(im[1], resolved);
86
+ if (im[3])
87
+ aliasImports.set(im[3], resolved);
88
+ // named imports {A, B as C}
89
+ const namedGroup = im[2] ?? im[4];
90
+ if (namedGroup) {
91
+ for (const part of namedGroup.split(",")) {
92
+ const trimmed = part.trim();
93
+ // Handle "X as Y" → local name is Y
94
+ const asMatch = trimmed.match(/^(\w+)\s+as\s+(\w+)$/);
95
+ const localName = asMatch ? asMatch[2] : trimmed.replace(/\s.*$/, "");
96
+ if (localName)
97
+ aliasImports.set(localName, resolved);
98
+ }
99
+ }
100
+ }
101
+ for (const name of rendered) {
102
+ if (name === sym.name)
103
+ continue; // skip self-reference
104
+ const targets = nameToComponents.get(name);
105
+ if (targets) {
106
+ for (const target of targets) {
107
+ if (target.id !== sym.id)
108
+ childList.push(target);
109
+ }
110
+ continue;
111
+ }
112
+ // Fallback: alias-resolved import lookup
113
+ const aliasTargetFile = aliasImports.get(name);
114
+ if (aliasTargetFile) {
115
+ const fileTargets = fileToComponents.get(aliasTargetFile) ?? [];
116
+ for (const target of fileTargets) {
117
+ if (target.id !== sym.id)
118
+ childList.push(target);
119
+ }
120
+ }
121
+ }
122
+ if (childList.length > 0)
123
+ children.set(sym.id, childList);
124
+ }
125
+ return { children };
126
+ }
127
+ /**
128
+ * BFS the component composition tree from a root component.
129
+ * Returns a CallNode tree of rendered components up to maxDepth.
130
+ */
131
+ function buildComponentTree(root, adjacency, maxDepth) {
132
+ const visited = new Set([root.id]);
133
+ let totalNodes = 1;
134
+ function expand(symbol, depth) {
135
+ if (depth >= maxDepth || totalNodes >= MAX_TREE_NODES) {
136
+ return { symbol, children: [] };
137
+ }
138
+ const kids = adjacency.children.get(symbol.id) ?? [];
139
+ const out = [];
140
+ for (const kid of kids) {
141
+ if (totalNodes >= MAX_TREE_NODES)
142
+ break;
143
+ if (out.length >= MAX_CHILDREN_PER_NODE)
144
+ break;
145
+ if (visited.has(kid.id))
146
+ continue;
147
+ visited.add(kid.id);
148
+ totalNodes++;
149
+ out.push(expand(kid, depth + 1));
150
+ }
151
+ return { symbol, children: out };
152
+ }
153
+ return expand(root, 0);
154
+ }
155
+ function stripSource(sym) {
156
+ const { source: _, repo: _r, tokens: _t, start_col: _sc, end_col: _ec, id, ...rest } = sym;
157
+ const shortId = id.includes(":") ? id.slice(id.indexOf(":") + 1) : id;
158
+ return { ...rest, id: shortId };
159
+ }
160
+ function stripTreeSource(node) {
161
+ return {
162
+ symbol: stripSource(node.symbol),
163
+ children: node.children.map(stripTreeSource),
164
+ };
165
+ }
166
+ function treeToMermaid(tree, rootName) {
167
+ const lines = ["graph TD"];
168
+ const visited = new Set();
169
+ function nodeId(sym) {
170
+ return sym.id.replace(/[^a-zA-Z0-9_]/g, "_");
171
+ }
172
+ function nodeLabel(sym) {
173
+ const shortFile = sym.file.split("/").pop() ?? sym.file;
174
+ return `${sym.name}<br/><small>${shortFile}:${sym.start_line}</small>`;
175
+ }
176
+ function walk(node, parentId) {
177
+ const id = nodeId(node.symbol);
178
+ if (!visited.has(id)) {
179
+ visited.add(id);
180
+ lines.push(` ${id}["${nodeLabel(node.symbol)}"]`);
181
+ }
182
+ if (parentId) {
183
+ lines.push(` ${parentId} --> ${id}`);
184
+ }
185
+ for (const child of node.children) {
186
+ walk(child, id);
187
+ }
188
+ }
189
+ walk(tree);
190
+ lines.push(` %% root: ${rootName}`);
191
+ return lines.join("\n");
192
+ }
193
+ /**
194
+ * Trace the React component composition tree from a root component.
195
+ * Returns a tree of JSX children (which components the root renders,
196
+ * and recursively their children).
197
+ */
198
+ export async function traceComponentTree(repo, rootComponent, options) {
199
+ const index = await getCodeIndex(repo);
200
+ if (!index) {
201
+ throw new Error(`Repository not found: ${repo}`);
202
+ }
203
+ const maxDepth = options?.depth ?? DEFAULT_DEPTH;
204
+ const outputFormat = options?.output_format ?? "json";
205
+ const includeSource = options?.include_source ?? false;
206
+ const includeTests = options?.include_tests ?? false;
207
+ const symbols = includeTests
208
+ ? index.symbols
209
+ : index.symbols.filter((s) => !isTestFile(s.file));
210
+ // Find root component
211
+ const candidates = symbols.filter((s) => s.name === rootComponent && s.kind === "component");
212
+ const target = candidates[0];
213
+ if (!target) {
214
+ throw new Error(`Component "${rootComponent}" not found in repository "${repo}". ` +
215
+ `Make sure it has kind: "component" — index may need refresh.`);
216
+ }
217
+ const adjacency = buildJsxAdjacency(symbols);
218
+ const tree = buildComponentTree(target, adjacency, maxDepth);
219
+ if (outputFormat === "mermaid") {
220
+ return { mermaid: treeToMermaid(tree, rootComponent), root: rootComponent, depth: maxDepth };
221
+ }
222
+ return includeSource ? tree : stripTreeSource(tree);
223
+ }
224
+ /**
225
+ * Scan a component/hook source for Rule of Hooks violations.
226
+ * Detects: hook inside if/for/while/switch, hook after early return.
227
+ * Returns a list of human-readable violation descriptions.
228
+ */
229
+ function findRuleOfHooksViolations(source) {
230
+ const violations = [];
231
+ // Heuristic: hook call inside if/for/while/switch block
232
+ const conditionalHook = /\b(if|for|while|switch)\s*\([^)]*\)\s*\{[^}]*\b(use[A-Z]\w*)\s*\(/;
233
+ const condMatch = conditionalHook.exec(source);
234
+ if (condMatch) {
235
+ violations.push(`Hook "${condMatch[2]}" called inside ${condMatch[1]} block — violates Rule of Hooks`);
236
+ }
237
+ // Heuristic: hook after early return
238
+ const earlyReturnHook = /\breturn\s+[^;{]*;\s*\n[\s\S]*?\b(use[A-Z]\w*)\s*\(/;
239
+ const earlyMatch = earlyReturnHook.exec(source);
240
+ if (earlyMatch) {
241
+ violations.push(`Hook "${earlyMatch[1]}" called after early return — violates Rule of Hooks`);
242
+ }
243
+ return violations;
244
+ }
245
+ /**
246
+ * Extract unique hook names from source (no line numbers, no cap).
247
+ * Use when you only need the set of hooks — e.g. React context bundle.
248
+ */
249
+ function extractHookNames(source) {
250
+ const names = new Set();
251
+ const pattern = /\b(use[A-Z]\w*)\s*\(/g;
252
+ let m;
253
+ while ((m = pattern.exec(source)) !== null) {
254
+ names.add(m[1]);
255
+ }
256
+ return names;
257
+ }
258
+ /**
259
+ * Extract hook calls from source with their relative line number.
260
+ */
261
+ function extractHookCalls(source) {
262
+ const calls = [];
263
+ const lines = source.split("\n");
264
+ const pattern = /\b(use[A-Z]\w*)\s*\(/;
265
+ for (let i = 0; i < lines.length && calls.length < 20; i++) {
266
+ const line = lines[i];
267
+ const m = pattern.exec(line);
268
+ if (m) {
269
+ calls.push({
270
+ name: m[1],
271
+ line: i + 1,
272
+ is_stdlib: REACT_STDLIB_HOOKS.has(m[1]),
273
+ context: line.trim().slice(0, 160),
274
+ });
275
+ }
276
+ }
277
+ return calls;
278
+ }
279
+ /**
280
+ * Analyze hook usage across components and custom hooks in a repo.
281
+ *
282
+ * Returns:
283
+ * - per-symbol inventory (hooks called, violations)
284
+ * - codebase-wide hook usage summary
285
+ * - Rule of Hooks violation count
286
+ */
287
+ export async function analyzeHooks(repo, options) {
288
+ const index = await getCodeIndex(repo);
289
+ if (!index) {
290
+ throw new Error(`Repository not found: ${repo}`);
291
+ }
292
+ const componentName = options?.component_name;
293
+ const filePattern = options?.file_pattern;
294
+ const includeTests = options?.include_tests ?? false;
295
+ const maxEntries = options?.max_entries ?? 100;
296
+ // Filter symbols to components and hooks
297
+ let symbols = index.symbols.filter((s) => s.kind === "component" || s.kind === "hook");
298
+ if (!includeTests)
299
+ symbols = symbols.filter((s) => !isTestFile(s.file));
300
+ if (componentName)
301
+ symbols = symbols.filter((s) => s.name === componentName);
302
+ if (filePattern)
303
+ symbols = symbols.filter((s) => s.file.includes(filePattern));
304
+ const entries = [];
305
+ const globalHookCount = new Map();
306
+ let totalComponents = 0;
307
+ let totalHooks = 0;
308
+ let violationsCount = 0;
309
+ for (const sym of symbols) {
310
+ if (!sym.source)
311
+ continue;
312
+ const hookCalls = extractHookCalls(sym.source);
313
+ const violations = findRuleOfHooksViolations(sym.source);
314
+ if (sym.kind === "component")
315
+ totalComponents++;
316
+ else if (sym.kind === "hook")
317
+ totalHooks++;
318
+ // Skip empty entries (no hooks, no violations)
319
+ if (hookCalls.length === 0 && violations.length === 0)
320
+ continue;
321
+ violationsCount += violations.length;
322
+ for (const call of hookCalls) {
323
+ globalHookCount.set(call.name, (globalHookCount.get(call.name) ?? 0) + 1);
324
+ }
325
+ entries.push({
326
+ name: sym.name,
327
+ kind: sym.kind,
328
+ file: sym.file,
329
+ start_line: sym.start_line,
330
+ hook_count: hookCalls.length,
331
+ hooks: hookCalls,
332
+ violations,
333
+ });
334
+ if (entries.length >= maxEntries)
335
+ break;
336
+ }
337
+ // Sort entries: violations first, then by hook_count descending
338
+ entries.sort((a, b) => {
339
+ const vdiff = b.violations.length - a.violations.length;
340
+ if (vdiff !== 0)
341
+ return vdiff;
342
+ return b.hook_count - a.hook_count;
343
+ });
344
+ const hook_usage = [...globalHookCount.entries()]
345
+ .sort((a, b) => b[1] - a[1])
346
+ .slice(0, 20)
347
+ .map(([name, count]) => ({
348
+ name,
349
+ count,
350
+ is_stdlib: REACT_STDLIB_HOOKS.has(name),
351
+ }));
352
+ return {
353
+ entries,
354
+ total_components: totalComponents,
355
+ total_custom_hooks: totalHooks,
356
+ hook_usage,
357
+ violations_count: violationsCount,
358
+ };
359
+ }
360
+ /** Patterns for inline prop creation in JSX — each creates a new reference every render */
361
+ const INLINE_OBJECT_RE = /\b\w+\s*=\s*\{\s*\{/g; // prop={{ ... }}
362
+ const INLINE_ARRAY_RE = /\b\w+\s*=\s*\{\s*\[/g; // prop={[ ... ]}
363
+ const INLINE_FN_RE = /\bon[A-Z]\w*\s*=\s*\{\s*(?:\([^)]*\)|[a-z_$][\w$]*)\s*=>/g; // onX={() => ...}
364
+ /** Default prop values that create new references: = [] or = {} in params */
365
+ const UNSTABLE_DEFAULT_RE = /(?:[:,]\s*)(\w+)\s*=\s*(\[\s*\]|\{\s*\})/g;
366
+ /**
367
+ * Analyze a single component source for re-render risks.
368
+ */
369
+ function findRenderRisks(source) {
370
+ const risks = [];
371
+ const lines = source.split("\n");
372
+ for (let i = 0; i < lines.length && risks.length < 20; i++) {
373
+ const line = lines[i];
374
+ const lineNum = i + 1;
375
+ const trimmed = line.trim();
376
+ // Skip comments
377
+ if (trimmed.startsWith("//") || trimmed.startsWith("*"))
378
+ continue;
379
+ // Inline object prop: prop={{ key: val }}
380
+ if (INLINE_OBJECT_RE.test(line)) {
381
+ INLINE_OBJECT_RE.lastIndex = 0;
382
+ risks.push({
383
+ type: "inline-object",
384
+ line: lineNum,
385
+ context: trimmed.slice(0, 120),
386
+ suggestion: "Extract to a const or useMemo — object literal creates new reference every render",
387
+ });
388
+ }
389
+ // Inline array prop: prop={[1, 2, 3]}
390
+ if (INLINE_ARRAY_RE.test(line)) {
391
+ INLINE_ARRAY_RE.lastIndex = 0;
392
+ risks.push({
393
+ type: "inline-array",
394
+ line: lineNum,
395
+ context: trimmed.slice(0, 120),
396
+ suggestion: "Extract to a const or useMemo — array literal creates new reference every render",
397
+ });
398
+ }
399
+ // Inline function in event handler: onClick={() => ...}
400
+ if (INLINE_FN_RE.test(line)) {
401
+ INLINE_FN_RE.lastIndex = 0;
402
+ risks.push({
403
+ type: "inline-function",
404
+ line: lineNum,
405
+ context: trimmed.slice(0, 120),
406
+ suggestion: "Extract to useCallback or a named handler — arrow function creates new reference every render",
407
+ });
408
+ }
409
+ // Unstable default value: { items = [], config = {} }
410
+ UNSTABLE_DEFAULT_RE.lastIndex = 0;
411
+ let dm;
412
+ while ((dm = UNSTABLE_DEFAULT_RE.exec(line)) !== null && risks.length < 20) {
413
+ risks.push({
414
+ type: "unstable-default",
415
+ line: lineNum,
416
+ context: trimmed.slice(0, 120),
417
+ suggestion: `Default value \`${dm[1]} = ${dm[2]}\` creates new reference every render — hoist to module const`,
418
+ });
419
+ }
420
+ }
421
+ return risks;
422
+ }
423
+ /**
424
+ * Analyze re-render risk across React components in a repo.
425
+ *
426
+ * Detects:
427
+ * - Inline object/array/function props in JSX (new reference every render)
428
+ * - Unstable default parameter values ([] or {} in component params)
429
+ * - Components not wrapped in React.memo that render children (missing-memo)
430
+ *
431
+ * Returns per-component risk assessment with actionable suggestions.
432
+ */
433
+ /**
434
+ * Format an AnalyzeRendersResult as human-readable Markdown.
435
+ * Used by analyzeRenders when format="markdown" is requested.
436
+ */
437
+ export function formatRendersMarkdown(result) {
438
+ const lines = [];
439
+ lines.push("# Render Analysis");
440
+ lines.push("");
441
+ lines.push(`Total components: ${result.total_components} | High risk: ${result.high_risk_count}`);
442
+ lines.push("");
443
+ lines.push("## Summary");
444
+ lines.push(`- inline_objects: ${result.summary.inline_objects}`);
445
+ lines.push(`- inline_arrays: ${result.summary.inline_arrays}`);
446
+ lines.push(`- inline_functions: ${result.summary.inline_functions}`);
447
+ lines.push(`- unstable_defaults: ${result.summary.unstable_defaults}`);
448
+ lines.push(`- missing_memo: ${result.summary.missing_memo}`);
449
+ lines.push("");
450
+ lines.push("## Entries");
451
+ lines.push("");
452
+ lines.push("| Component | File | Risk | Issues | Children | Memo |");
453
+ lines.push("|-----------|------|------|--------|----------|------|");
454
+ for (const e of result.entries) {
455
+ const file = e.file.length > 40 ? "…" + e.file.slice(-39) : e.file;
456
+ lines.push(`| ${e.name} | ${file}:${e.start_line} | ${e.risk_level} | ${e.risk_count} | ${e.children_count} | ${e.is_memoized ? "✓" : "✗"} |`);
457
+ }
458
+ return lines.join("\n");
459
+ }
460
+ export async function analyzeRenders(repo, options) {
461
+ const index = await getCodeIndex(repo);
462
+ if (!index) {
463
+ throw new Error(`Repository not found: ${repo}`);
464
+ }
465
+ const componentName = options?.component_name;
466
+ const filePattern = options?.file_pattern;
467
+ const includeTests = options?.include_tests ?? false;
468
+ const maxEntries = options?.max_entries ?? 100;
469
+ let components = index.symbols.filter((s) => s.kind === "component");
470
+ if (!includeTests)
471
+ components = components.filter((s) => !isTestFile(s.file));
472
+ if (componentName)
473
+ components = components.filter((s) => s.name === componentName);
474
+ if (filePattern)
475
+ components = components.filter((s) => s.file.includes(filePattern));
476
+ const entries = [];
477
+ const summary = { inline_objects: 0, inline_arrays: 0, inline_functions: 0, unstable_defaults: 0, missing_memo: 0 };
478
+ let highRiskCount = 0;
479
+ for (const sym of components) {
480
+ if (entries.length >= maxEntries)
481
+ break;
482
+ if (!sym.source)
483
+ continue;
484
+ const isMemoized = /\b(?:React\.)?memo\s*\(/.test(sym.source);
485
+ const risks = findRenderRisks(sym.source);
486
+ // Count children rendered (PascalCase JSX elements)
487
+ const childrenSet = new Set();
488
+ const jsxPattern = /<([A-Z][a-zA-Z0-9_$]*)\b/g;
489
+ let jm;
490
+ while ((jm = jsxPattern.exec(sym.source)) !== null) {
491
+ if (jm[1] !== sym.name)
492
+ childrenSet.add(jm[1]);
493
+ }
494
+ // Check missing-memo: component renders children and is not memoized
495
+ if (!isMemoized && childrenSet.size > 0 && risks.length > 0) {
496
+ risks.push({
497
+ type: "missing-memo",
498
+ line: 1,
499
+ context: `${sym.name} renders ${childrenSet.size} child component(s) and has ${risks.length} inline props`,
500
+ suggestion: "Wrap in React.memo() — parent re-renders will propagate to children via new prop references",
501
+ });
502
+ summary.missing_memo++;
503
+ }
504
+ // Aggregate summary counts
505
+ for (const r of risks) {
506
+ if (r.type === "inline-object")
507
+ summary.inline_objects++;
508
+ else if (r.type === "inline-array")
509
+ summary.inline_arrays++;
510
+ else if (r.type === "inline-function")
511
+ summary.inline_functions++;
512
+ else if (r.type === "unstable-default")
513
+ summary.unstable_defaults++;
514
+ }
515
+ // Risk level classification — factors children_count to amplify components
516
+ // that propagate prop instability to many children (Bug #4 fix).
517
+ const riskLevel = ((risks.length >= 3 && childrenSet.size >= 3) || risks.length >= 5) ? "high" :
518
+ (risks.length >= 2 || (risks.length >= 1 && childrenSet.size >= 1)) ? "medium" : "low";
519
+ if (riskLevel === "high")
520
+ highRiskCount++;
521
+ // Only include components with risks or if specifically queried
522
+ if (risks.length > 0 || componentName) {
523
+ entries.push({
524
+ name: sym.name,
525
+ file: sym.file,
526
+ start_line: sym.start_line,
527
+ is_memoized: isMemoized,
528
+ risk_count: risks.length,
529
+ risk_level: riskLevel,
530
+ risks,
531
+ children_count: childrenSet.size,
532
+ });
533
+ }
534
+ }
535
+ // Sort: high risk first, then by risk_count descending
536
+ entries.sort((a, b) => {
537
+ const levelOrder = { high: 3, medium: 2, low: 1 };
538
+ const ld = levelOrder[b.risk_level] - levelOrder[a.risk_level];
539
+ if (ld !== 0)
540
+ return ld;
541
+ return b.risk_count - a.risk_count;
542
+ });
543
+ const jsonResult = {
544
+ entries,
545
+ total_components: components.length,
546
+ high_risk_count: highRiskCount,
547
+ summary,
548
+ };
549
+ if (options?.format === "markdown") {
550
+ return formatRendersMarkdown(jsonResult);
551
+ }
552
+ return jsonResult;
553
+ }
554
+ const MAX_CONTEXT_SYMBOLS = 500;
555
+ /**
556
+ * Build a graph of React Context flows: createContext → Provider → useContext consumers.
557
+ *
558
+ * Single-pass scan over all symbols (capped at 500). No cycle detection — relies
559
+ * on visited set keyed by context name to prevent re-processing.
560
+ *
561
+ * Detection patterns:
562
+ * - createContext call: `const X = createContext(...)` or `const X = React.createContext(...)`
563
+ * - Provider usage: `<X.Provider value={...}>` (anywhere in any source)
564
+ * - Consumer usage: `useContext(X)` (anywhere in any source)
565
+ *
566
+ * Phase 2 features (not implemented here):
567
+ * - Cycle detection in provider chains
568
+ * - Re-render impact analysis ("which consumers re-render when X changes")
569
+ * - Context value type tracking
570
+ */
571
+ export function buildContextGraph(symbols) {
572
+ const contexts = new Map();
573
+ const createPattern = /\bconst\s+(\w+)\s*(?::[^=]+)?\s*=\s*(?:React\.)?createContext\b/g;
574
+ // Pass 1: Find context definitions
575
+ let scanned = 0;
576
+ for (const sym of symbols) {
577
+ if (scanned >= MAX_CONTEXT_SYMBOLS)
578
+ break;
579
+ if (!sym.source)
580
+ continue;
581
+ scanned++;
582
+ let m;
583
+ createPattern.lastIndex = 0;
584
+ while ((m = createPattern.exec(sym.source)) !== null) {
585
+ const name = m[1];
586
+ if (contexts.has(name))
587
+ continue; // visited — skip duplicate definition
588
+ // Compute line offset within symbol source
589
+ const linesBefore = sym.source.slice(0, m.index).split("\n").length;
590
+ contexts.set(name, {
591
+ name,
592
+ created_in: { file: sym.file, line: sym.start_line + linesBefore - 1 },
593
+ providers: [],
594
+ consumers: [],
595
+ });
596
+ }
597
+ }
598
+ if (contexts.size === 0)
599
+ return { contexts: [] };
600
+ // Pass 2: Find providers and consumers
601
+ scanned = 0;
602
+ for (const sym of symbols) {
603
+ if (scanned >= MAX_CONTEXT_SYMBOLS)
604
+ break;
605
+ if (!sym.source)
606
+ continue;
607
+ if (sym.kind !== "component" && sym.kind !== "hook")
608
+ continue;
609
+ scanned++;
610
+ for (const [ctxName, info] of contexts) {
611
+ // Provider: <X.Provider
612
+ const providerRe = new RegExp(`<${ctxName}\\.Provider\\b`);
613
+ if (providerRe.test(sym.source)) {
614
+ info.providers.push({ file: sym.file, line: sym.start_line });
615
+ }
616
+ // Consumer: useContext(X)
617
+ const consumerRe = new RegExp(`useContext\\s*\\(\\s*${ctxName}\\b`);
618
+ if (consumerRe.test(sym.source)) {
619
+ info.consumers.push({
620
+ file: sym.file,
621
+ component: sym.name,
622
+ line: sym.start_line,
623
+ });
624
+ }
625
+ }
626
+ }
627
+ return { contexts: [...contexts.values()] };
628
+ }
629
+ // ─────────────────────────────────────────────────────────────
630
+ // audit_compiler_readiness — React Compiler adoption readiness
631
+ // ─────────────────────────────────────────────────────────────
632
+ const COMPILER_PATTERNS = [
633
+ "compiler-side-effect-in-render",
634
+ "compiler-ref-read-in-render",
635
+ "compiler-prop-mutation",
636
+ "compiler-state-mutation",
637
+ "compiler-try-catch-bailout",
638
+ "compiler-redundant-memo",
639
+ "compiler-redundant-usecallback",
640
+ ];
641
+ /**
642
+ * Audit a React codebase for React Compiler (v1.0) adoption readiness.
643
+ *
644
+ * Scans all components for patterns that cause the compiler to silently
645
+ * bail out of auto-memoization. Returns a readiness score (0-100) with
646
+ * prioritized fix list.
647
+ *
648
+ * No competitor offers codebase-wide compiler readiness analysis.
649
+ */
650
+ export async function auditCompilerReadiness(repo, options) {
651
+ const { searchPatterns } = await import("./pattern-tools.js");
652
+ const index = await getCodeIndex(repo);
653
+ if (!index)
654
+ throw new Error(`Repository not found: ${repo}`);
655
+ const includeTests = options?.include_tests ?? false;
656
+ const filePattern = options?.file_pattern;
657
+ // Count total components
658
+ let components = index.symbols.filter((s) => s.kind === "component");
659
+ if (!includeTests)
660
+ components = components.filter((s) => !isTestFile(s.file));
661
+ if (filePattern)
662
+ components = components.filter((s) => s.file.includes(filePattern));
663
+ const totalComponents = components.length;
664
+ // Run all compiler patterns in parallel
665
+ const patternResults = await Promise.all(COMPILER_PATTERNS.map(async (pattern) => {
666
+ try {
667
+ const result = await searchPatterns(repo, pattern, {
668
+ file_pattern: filePattern,
669
+ include_tests: includeTests,
670
+ max_results: 200,
671
+ });
672
+ return { pattern, matches: result.matches, description: result.pattern };
673
+ }
674
+ catch {
675
+ return { pattern, matches: [], description: pattern };
676
+ }
677
+ }));
678
+ // Aggregate: which components have bailout issues
679
+ const componentIssues = new Map(); // "name@file" → issue count
680
+ let redundantMemoization = 0;
681
+ const issues = [];
682
+ for (const { pattern, matches, description } of patternResults) {
683
+ if (matches.length === 0)
684
+ continue;
685
+ const isRedundant = pattern === "compiler-redundant-memo" || pattern === "compiler-redundant-usecallback";
686
+ if (isRedundant) {
687
+ redundantMemoization += matches.length;
688
+ }
689
+ issues.push({
690
+ pattern,
691
+ count: matches.length,
692
+ description: description.split(": ").slice(1).join(": ") || description,
693
+ });
694
+ for (const m of matches) {
695
+ if (!isRedundant) {
696
+ const key = `${m.name}@${m.file}`;
697
+ componentIssues.set(key, (componentIssues.get(key) ?? 0) + 1);
698
+ }
699
+ }
700
+ }
701
+ // Sort issues by count descending
702
+ issues.sort((a, b) => b.count - a.count);
703
+ // Top bailout components
704
+ const top_bailout_components = [...componentIssues.entries()]
705
+ .sort((a, b) => b[1] - a[1])
706
+ .slice(0, 10)
707
+ .map(([key, count]) => {
708
+ const [name, file] = key.split("@");
709
+ return { name: name, file: file, issues: count };
710
+ });
711
+ const bailoutCount = componentIssues.size;
712
+ const compatibleCount = Math.max(0, totalComponents - bailoutCount);
713
+ // Readiness score: percentage of components without bailout issues
714
+ const readiness_score = totalComponents > 0
715
+ ? Math.round((compatibleCount / totalComponents) * 100)
716
+ : 100; // empty repo = ready
717
+ return {
718
+ readiness_score,
719
+ total_components: totalComponents,
720
+ compatible_components: compatibleCount,
721
+ bailout_components: bailoutCount,
722
+ redundant_memoization: redundantMemoization,
723
+ issues,
724
+ top_bailout_components,
725
+ };
726
+ }
727
+ /**
728
+ * Day-1 onboarding composite for React projects. Single call that runs:
729
+ * - Component/hook inventory
730
+ * - Stack detection (state mgmt, routing, UI lib, form lib, build tool)
731
+ * - Critical pattern scan (XSS, Rule of Hooks, memory leaks)
732
+ * - Top hook usage summary
733
+ * - Suggested follow-up queries
734
+ *
735
+ * Meant to be the first tool a React developer runs on an unfamiliar codebase.
736
+ * Replaces 5-6 manual tool calls with one structured report.
737
+ */
738
+ export async function reactQuickstart(repo) {
739
+ const { searchPatterns } = await import("./pattern-tools.js");
740
+ const { analyzeProject } = await import("./project-tools.js");
741
+ const index = await getCodeIndex(repo);
742
+ if (!index)
743
+ throw new Error(`Repository not found: ${repo}`);
744
+ // Inventory
745
+ const components = index.symbols.filter((s) => s.kind === "component" && !isTestFile(s.file));
746
+ const hooks = index.symbols.filter((s) => s.kind === "hook" && !isTestFile(s.file));
747
+ // Find likely root component: prefer App > Root > Main > Layout > Page
748
+ const rootNames = ["App", "Root", "Main", "Layout", "Page"];
749
+ const likelyRoot = components.find((c) => rootNames.includes(c.name))?.name
750
+ ?? components[0]?.name
751
+ ?? null;
752
+ // Stack detection via analyze_project
753
+ let stack = {
754
+ state_management: null,
755
+ routing: null,
756
+ ui_library: null,
757
+ form_library: null,
758
+ build_tool: null,
759
+ };
760
+ try {
761
+ const proj = await analyzeProject(repo, { force: false });
762
+ const rc = proj?.conventions?.react_conventions;
763
+ const si = proj?.stack;
764
+ if (rc) {
765
+ stack = {
766
+ state_management: rc.state_management ?? null,
767
+ routing: rc.routing ?? null,
768
+ ui_library: rc.ui_library ?? null,
769
+ form_library: rc.form_library ?? null,
770
+ build_tool: si?.build_tool ?? null,
771
+ };
772
+ }
773
+ else if (si) {
774
+ stack.build_tool = si.build_tool ?? null;
775
+ }
776
+ }
777
+ catch {
778
+ // analyze_project may fail on non-React repos — fall through
779
+ }
780
+ // Critical pattern scans — run in parallel
781
+ const criticalPatterns = [
782
+ { name: "dangerously-set-html", severity: "critical" },
783
+ { name: "hook-in-condition", severity: "critical" },
784
+ { name: "conditional-render-hook", severity: "critical" },
785
+ { name: "useEffect-missing-cleanup", severity: "warning" },
786
+ { name: "useEffect-setstate-loop", severity: "critical" },
787
+ { name: "rsc-non-serializable-prop", severity: "warning" },
788
+ ];
789
+ const scanResults = await Promise.all(criticalPatterns.map(async ({ name, severity }) => {
790
+ try {
791
+ const result = await searchPatterns(repo, name, { max_results: 20 });
792
+ return { pattern: name, count: result.matches.length, severity };
793
+ }
794
+ catch {
795
+ return { pattern: name, count: 0, severity };
796
+ }
797
+ }));
798
+ const critical_issues = scanResults.filter((r) => r.count > 0);
799
+ // Top hooks used across components
800
+ const hookCounts = new Map();
801
+ for (const c of components) {
802
+ if (!c.source)
803
+ continue;
804
+ const matches = c.source.matchAll(/\b(use[A-Z]\w*)\s*\(/g);
805
+ for (const m of matches) {
806
+ const name = m[1];
807
+ hookCounts.set(name, (hookCounts.get(name) ?? 0) + 1);
808
+ }
809
+ }
810
+ const top_hooks = [...hookCounts.entries()]
811
+ .sort((a, b) => b[1] - a[1])
812
+ .slice(0, 5)
813
+ .map(([name, count]) => ({ name, count }));
814
+ // Suggested next queries
815
+ const suggested_queries = [];
816
+ if (likelyRoot) {
817
+ suggested_queries.push(`trace_component_tree("${likelyRoot}") // explore render hierarchy`);
818
+ }
819
+ suggested_queries.push(`analyze_renders() // find re-render risks`);
820
+ suggested_queries.push(`analyze_hooks() // Rule of Hooks + hook inventory`);
821
+ if (components.length >= 10) {
822
+ suggested_queries.push(`audit_compiler_readiness() // React Compiler adoption check`);
823
+ }
824
+ if (critical_issues.some((i) => i.severity === "critical")) {
825
+ suggested_queries.push(`search_patterns("dangerously-set-html") // investigate XSS risks`);
826
+ }
827
+ return {
828
+ overview: {
829
+ total_components: components.length,
830
+ total_custom_hooks: hooks.length,
831
+ likely_root_component: likelyRoot,
832
+ stack,
833
+ },
834
+ critical_issues,
835
+ top_hooks,
836
+ suggested_queries,
837
+ };
838
+ }
839
+ //# sourceMappingURL=react-tools.js.map