@neverinfamous/mysql-mcp 2.1.0 → 2.3.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 (802) hide show
  1. package/.env.example +14 -4
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +7 -1
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +6 -1
  4. package/.github/dependabot.yml +15 -0
  5. package/.github/pull_request_template.md +5 -0
  6. package/.github/workflows/codeql.yml +41 -42
  7. package/.github/workflows/docker-publish.yml +247 -210
  8. package/.github/workflows/publish-npm.yml +16 -6
  9. package/CHANGELOG.md +357 -22
  10. package/CODE_MODE.md +245 -0
  11. package/CODE_OF_CONDUCT.md +2 -0
  12. package/DOCKER_README.md +250 -161
  13. package/Dockerfile +2 -2
  14. package/README.md +239 -182
  15. package/SECURITY.md +0 -8
  16. package/VERSION +1 -1
  17. package/dist/__tests__/mocks/adapter.d.ts +3 -3
  18. package/dist/__tests__/mocks/adapter.d.ts.map +1 -1
  19. package/dist/__tests__/mocks/adapter.js +51 -35
  20. package/dist/__tests__/mocks/adapter.js.map +1 -1
  21. package/dist/__tests__/mocks/index.d.ts +4 -4
  22. package/dist/__tests__/mocks/index.d.ts.map +1 -1
  23. package/dist/__tests__/mocks/index.js +2 -2
  24. package/dist/__tests__/mocks/index.js.map +1 -1
  25. package/dist/__tests__/mocks/mysql.d.ts +2 -2
  26. package/dist/__tests__/mocks/mysql.d.ts.map +1 -1
  27. package/dist/__tests__/mocks/mysql.js +14 -14
  28. package/dist/__tests__/mocks/mysql.js.map +1 -1
  29. package/dist/__tests__/setup.d.ts.map +1 -1
  30. package/dist/__tests__/setup.js +7 -7
  31. package/dist/__tests__/setup.js.map +1 -1
  32. package/dist/adapters/DatabaseAdapter.d.ts +2 -2
  33. package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
  34. package/dist/adapters/DatabaseAdapter.js +69 -40
  35. package/dist/adapters/DatabaseAdapter.js.map +1 -1
  36. package/dist/adapters/mysql/MySQLAdapter.d.ts +14 -4
  37. package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
  38. package/dist/adapters/mysql/MySQLAdapter.js +152 -116
  39. package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
  40. package/dist/adapters/mysql/SchemaManager.d.ts +1 -1
  41. package/dist/adapters/mysql/SchemaManager.d.ts.map +1 -1
  42. package/dist/adapters/mysql/SchemaManager.js +76 -56
  43. package/dist/adapters/mysql/SchemaManager.js.map +1 -1
  44. package/dist/adapters/mysql/index.d.ts +2 -2
  45. package/dist/adapters/mysql/index.js +2 -2
  46. package/dist/adapters/mysql/prompts/backupStrategy.d.ts +1 -1
  47. package/dist/adapters/mysql/prompts/backupStrategy.d.ts.map +1 -1
  48. package/dist/adapters/mysql/prompts/backupStrategy.js +21 -9
  49. package/dist/adapters/mysql/prompts/backupStrategy.js.map +1 -1
  50. package/dist/adapters/mysql/prompts/clusterSetup.d.ts +1 -1
  51. package/dist/adapters/mysql/prompts/clusterSetup.d.ts.map +1 -1
  52. package/dist/adapters/mysql/prompts/clusterSetup.js +3 -3
  53. package/dist/adapters/mysql/prompts/clusterSetup.js.map +1 -1
  54. package/dist/adapters/mysql/prompts/docstoreSetup.d.ts +1 -1
  55. package/dist/adapters/mysql/prompts/docstoreSetup.js +3 -3
  56. package/dist/adapters/mysql/prompts/docstoreSetup.js.map +1 -1
  57. package/dist/adapters/mysql/prompts/eventScheduler.d.ts +1 -1
  58. package/dist/adapters/mysql/prompts/eventScheduler.js +3 -3
  59. package/dist/adapters/mysql/prompts/eventScheduler.js.map +1 -1
  60. package/dist/adapters/mysql/prompts/healthCheck.d.ts +1 -1
  61. package/dist/adapters/mysql/prompts/healthCheck.d.ts.map +1 -1
  62. package/dist/adapters/mysql/prompts/healthCheck.js +10 -6
  63. package/dist/adapters/mysql/prompts/healthCheck.js.map +1 -1
  64. package/dist/adapters/mysql/prompts/index.d.ts +10 -3
  65. package/dist/adapters/mysql/prompts/index.d.ts.map +1 -1
  66. package/dist/adapters/mysql/prompts/index.js +106 -63
  67. package/dist/adapters/mysql/prompts/index.js.map +1 -1
  68. package/dist/adapters/mysql/prompts/indexTuning.d.ts +1 -1
  69. package/dist/adapters/mysql/prompts/indexTuning.d.ts.map +1 -1
  70. package/dist/adapters/mysql/prompts/indexTuning.js +11 -7
  71. package/dist/adapters/mysql/prompts/indexTuning.js.map +1 -1
  72. package/dist/adapters/mysql/prompts/mysqlshSetup.d.ts +1 -1
  73. package/dist/adapters/mysql/prompts/mysqlshSetup.js +4 -4
  74. package/dist/adapters/mysql/prompts/mysqlshSetup.js.map +1 -1
  75. package/dist/adapters/mysql/prompts/proxysqlSetup.d.ts +1 -1
  76. package/dist/adapters/mysql/prompts/proxysqlSetup.js +3 -3
  77. package/dist/adapters/mysql/prompts/proxysqlSetup.js.map +1 -1
  78. package/dist/adapters/mysql/prompts/replicationSetup.d.ts +1 -1
  79. package/dist/adapters/mysql/prompts/replicationSetup.d.ts.map +1 -1
  80. package/dist/adapters/mysql/prompts/replicationSetup.js +13 -7
  81. package/dist/adapters/mysql/prompts/replicationSetup.js.map +1 -1
  82. package/dist/adapters/mysql/prompts/routerSetup.d.ts +1 -1
  83. package/dist/adapters/mysql/prompts/routerSetup.d.ts.map +1 -1
  84. package/dist/adapters/mysql/prompts/routerSetup.js +8 -3
  85. package/dist/adapters/mysql/prompts/routerSetup.js.map +1 -1
  86. package/dist/adapters/mysql/prompts/spatialSetup.d.ts +1 -1
  87. package/dist/adapters/mysql/prompts/spatialSetup.js +3 -3
  88. package/dist/adapters/mysql/prompts/spatialSetup.js.map +1 -1
  89. package/dist/adapters/mysql/prompts/sysSchema.d.ts +1 -1
  90. package/dist/adapters/mysql/prompts/sysSchema.d.ts.map +1 -1
  91. package/dist/adapters/mysql/prompts/sysSchema.js +3 -3
  92. package/dist/adapters/mysql/prompts/sysSchema.js.map +1 -1
  93. package/dist/adapters/mysql/resources/capabilities.d.ts +2 -2
  94. package/dist/adapters/mysql/resources/capabilities.d.ts.map +1 -1
  95. package/dist/adapters/mysql/resources/capabilities.js +19 -16
  96. package/dist/adapters/mysql/resources/capabilities.js.map +1 -1
  97. package/dist/adapters/mysql/resources/cluster.d.ts +2 -2
  98. package/dist/adapters/mysql/resources/cluster.d.ts.map +1 -1
  99. package/dist/adapters/mysql/resources/cluster.js +17 -15
  100. package/dist/adapters/mysql/resources/cluster.js.map +1 -1
  101. package/dist/adapters/mysql/resources/docstore.d.ts +2 -2
  102. package/dist/adapters/mysql/resources/docstore.d.ts.map +1 -1
  103. package/dist/adapters/mysql/resources/docstore.js +12 -12
  104. package/dist/adapters/mysql/resources/docstore.js.map +1 -1
  105. package/dist/adapters/mysql/resources/events.d.ts +2 -2
  106. package/dist/adapters/mysql/resources/events.d.ts.map +1 -1
  107. package/dist/adapters/mysql/resources/events.js +12 -12
  108. package/dist/adapters/mysql/resources/events.js.map +1 -1
  109. package/dist/adapters/mysql/resources/health.d.ts +2 -2
  110. package/dist/adapters/mysql/resources/health.d.ts.map +1 -1
  111. package/dist/adapters/mysql/resources/health.js +36 -32
  112. package/dist/adapters/mysql/resources/health.js.map +1 -1
  113. package/dist/adapters/mysql/resources/index.d.ts +11 -3
  114. package/dist/adapters/mysql/resources/index.d.ts.map +1 -1
  115. package/dist/adapters/mysql/resources/index.js +28 -20
  116. package/dist/adapters/mysql/resources/index.js.map +1 -1
  117. package/dist/adapters/mysql/resources/indexes.d.ts +2 -2
  118. package/dist/adapters/mysql/resources/indexes.d.ts.map +1 -1
  119. package/dist/adapters/mysql/resources/indexes.js +12 -12
  120. package/dist/adapters/mysql/resources/indexes.js.map +1 -1
  121. package/dist/adapters/mysql/resources/innodb.d.ts +2 -2
  122. package/dist/adapters/mysql/resources/innodb.d.ts.map +1 -1
  123. package/dist/adapters/mysql/resources/innodb.js +37 -36
  124. package/dist/adapters/mysql/resources/innodb.js.map +1 -1
  125. package/dist/adapters/mysql/resources/locks.d.ts +2 -2
  126. package/dist/adapters/mysql/resources/locks.d.ts.map +1 -1
  127. package/dist/adapters/mysql/resources/locks.js +14 -14
  128. package/dist/adapters/mysql/resources/locks.js.map +1 -1
  129. package/dist/adapters/mysql/resources/performance.d.ts +2 -2
  130. package/dist/adapters/mysql/resources/performance.d.ts.map +1 -1
  131. package/dist/adapters/mysql/resources/performance.js +30 -29
  132. package/dist/adapters/mysql/resources/performance.js.map +1 -1
  133. package/dist/adapters/mysql/resources/pool.d.ts +2 -2
  134. package/dist/adapters/mysql/resources/pool.d.ts.map +1 -1
  135. package/dist/adapters/mysql/resources/pool.js +9 -9
  136. package/dist/adapters/mysql/resources/pool.js.map +1 -1
  137. package/dist/adapters/mysql/resources/processlist.d.ts +2 -2
  138. package/dist/adapters/mysql/resources/processlist.d.ts.map +1 -1
  139. package/dist/adapters/mysql/resources/processlist.js +9 -9
  140. package/dist/adapters/mysql/resources/processlist.js.map +1 -1
  141. package/dist/adapters/mysql/resources/replication.d.ts +2 -2
  142. package/dist/adapters/mysql/resources/replication.d.ts.map +1 -1
  143. package/dist/adapters/mysql/resources/replication.js +42 -35
  144. package/dist/adapters/mysql/resources/replication.js.map +1 -1
  145. package/dist/adapters/mysql/resources/schema.d.ts +2 -2
  146. package/dist/adapters/mysql/resources/schema.d.ts.map +1 -1
  147. package/dist/adapters/mysql/resources/schema.js +8 -8
  148. package/dist/adapters/mysql/resources/schema.js.map +1 -1
  149. package/dist/adapters/mysql/resources/spatial.d.ts +2 -2
  150. package/dist/adapters/mysql/resources/spatial.d.ts.map +1 -1
  151. package/dist/adapters/mysql/resources/spatial.js +9 -9
  152. package/dist/adapters/mysql/resources/spatial.js.map +1 -1
  153. package/dist/adapters/mysql/resources/status.d.ts +2 -2
  154. package/dist/adapters/mysql/resources/status.d.ts.map +1 -1
  155. package/dist/adapters/mysql/resources/status.js +10 -10
  156. package/dist/adapters/mysql/resources/status.js.map +1 -1
  157. package/dist/adapters/mysql/resources/sysschema.d.ts +2 -2
  158. package/dist/adapters/mysql/resources/sysschema.d.ts.map +1 -1
  159. package/dist/adapters/mysql/resources/sysschema.js +10 -10
  160. package/dist/adapters/mysql/resources/sysschema.js.map +1 -1
  161. package/dist/adapters/mysql/resources/tables.d.ts +2 -2
  162. package/dist/adapters/mysql/resources/tables.d.ts.map +1 -1
  163. package/dist/adapters/mysql/resources/tables.js +8 -8
  164. package/dist/adapters/mysql/resources/tables.js.map +1 -1
  165. package/dist/adapters/mysql/resources/variables.d.ts +2 -2
  166. package/dist/adapters/mysql/resources/variables.d.ts.map +1 -1
  167. package/dist/adapters/mysql/resources/variables.js +10 -10
  168. package/dist/adapters/mysql/resources/variables.js.map +1 -1
  169. package/dist/adapters/mysql/tools/admin/backup.d.ts +2 -2
  170. package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
  171. package/dist/adapters/mysql/tools/admin/backup.js +193 -101
  172. package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
  173. package/dist/adapters/mysql/tools/admin/index.d.ts +2 -2
  174. package/dist/adapters/mysql/tools/admin/index.js +6 -6
  175. package/dist/adapters/mysql/tools/admin/index.js.map +1 -1
  176. package/dist/adapters/mysql/tools/admin/maintenance.d.ts +2 -2
  177. package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
  178. package/dist/adapters/mysql/tools/admin/maintenance.js +97 -66
  179. package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
  180. package/dist/adapters/mysql/tools/admin/monitoring.d.ts +2 -2
  181. package/dist/adapters/mysql/tools/admin/monitoring.d.ts.map +1 -1
  182. package/dist/adapters/mysql/tools/admin/monitoring.js +215 -79
  183. package/dist/adapters/mysql/tools/admin/monitoring.js.map +1 -1
  184. package/dist/adapters/mysql/tools/cluster/group-replication.d.ts +2 -2
  185. package/dist/adapters/mysql/tools/cluster/group-replication.d.ts.map +1 -1
  186. package/dist/adapters/mysql/tools/cluster/group-replication.js +90 -74
  187. package/dist/adapters/mysql/tools/cluster/group-replication.js.map +1 -1
  188. package/dist/adapters/mysql/tools/cluster/index.d.ts +2 -2
  189. package/dist/adapters/mysql/tools/cluster/index.js +3 -3
  190. package/dist/adapters/mysql/tools/cluster/index.js.map +1 -1
  191. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts +2 -2
  192. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
  193. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +225 -97
  194. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
  195. package/dist/adapters/mysql/tools/codemode/index.d.ts +38 -0
  196. package/dist/adapters/mysql/tools/codemode/index.d.ts.map +1 -0
  197. package/dist/adapters/mysql/tools/codemode/index.js +203 -0
  198. package/dist/adapters/mysql/tools/codemode/index.js.map +1 -0
  199. package/dist/adapters/mysql/tools/core.d.ts +2 -2
  200. package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
  201. package/dist/adapters/mysql/tools/core.js +234 -114
  202. package/dist/adapters/mysql/tools/core.js.map +1 -1
  203. package/dist/adapters/mysql/tools/docstore.d.ts +2 -2
  204. package/dist/adapters/mysql/tools/docstore.d.ts.map +1 -1
  205. package/dist/adapters/mysql/tools/docstore.js +252 -117
  206. package/dist/adapters/mysql/tools/docstore.js.map +1 -1
  207. package/dist/adapters/mysql/tools/events.d.ts +2 -2
  208. package/dist/adapters/mysql/tools/events.d.ts.map +1 -1
  209. package/dist/adapters/mysql/tools/events.js +236 -113
  210. package/dist/adapters/mysql/tools/events.js.map +1 -1
  211. package/dist/adapters/mysql/tools/index.d.ts +19 -19
  212. package/dist/adapters/mysql/tools/index.d.ts.map +1 -1
  213. package/dist/adapters/mysql/tools/index.js +19 -19
  214. package/dist/adapters/mysql/tools/index.js.map +1 -1
  215. package/dist/adapters/mysql/tools/json/core.d.ts +2 -2
  216. package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
  217. package/dist/adapters/mysql/tools/json/core.js +225 -131
  218. package/dist/adapters/mysql/tools/json/core.js.map +1 -1
  219. package/dist/adapters/mysql/tools/json/enhanced.d.ts +2 -2
  220. package/dist/adapters/mysql/tools/json/enhanced.d.ts.map +1 -1
  221. package/dist/adapters/mysql/tools/json/enhanced.js +274 -163
  222. package/dist/adapters/mysql/tools/json/enhanced.js.map +1 -1
  223. package/dist/adapters/mysql/tools/json/helpers.d.ts +2 -2
  224. package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
  225. package/dist/adapters/mysql/tools/json/helpers.js +141 -57
  226. package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
  227. package/dist/adapters/mysql/tools/json/index.d.ts +2 -2
  228. package/dist/adapters/mysql/tools/json/index.js +6 -6
  229. package/dist/adapters/mysql/tools/json/index.js.map +1 -1
  230. package/dist/adapters/mysql/tools/partitioning.d.ts +2 -2
  231. package/dist/adapters/mysql/tools/partitioning.d.ts.map +1 -1
  232. package/dist/adapters/mysql/tools/partitioning.js +180 -64
  233. package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
  234. package/dist/adapters/mysql/tools/performance/analysis.d.ts +2 -2
  235. package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
  236. package/dist/adapters/mysql/tools/performance/analysis.js +184 -101
  237. package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
  238. package/dist/adapters/mysql/tools/performance/index.d.ts +2 -2
  239. package/dist/adapters/mysql/tools/performance/index.js +4 -4
  240. package/dist/adapters/mysql/tools/performance/index.js.map +1 -1
  241. package/dist/adapters/mysql/tools/performance/optimization.d.ts +3 -3
  242. package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
  243. package/dist/adapters/mysql/tools/performance/optimization.js +229 -77
  244. package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
  245. package/dist/adapters/mysql/tools/proxysql.d.ts +2 -2
  246. package/dist/adapters/mysql/tools/proxysql.d.ts.map +1 -1
  247. package/dist/adapters/mysql/tools/proxysql.js +213 -125
  248. package/dist/adapters/mysql/tools/proxysql.js.map +1 -1
  249. package/dist/adapters/mysql/tools/replication.d.ts +2 -2
  250. package/dist/adapters/mysql/tools/replication.d.ts.map +1 -1
  251. package/dist/adapters/mysql/tools/replication.js +117 -66
  252. package/dist/adapters/mysql/tools/replication.js.map +1 -1
  253. package/dist/adapters/mysql/tools/roles.d.ts +2 -2
  254. package/dist/adapters/mysql/tools/roles.d.ts.map +1 -1
  255. package/dist/adapters/mysql/tools/roles.js +276 -84
  256. package/dist/adapters/mysql/tools/roles.js.map +1 -1
  257. package/dist/adapters/mysql/tools/router.d.ts +2 -2
  258. package/dist/adapters/mysql/tools/router.d.ts.map +1 -1
  259. package/dist/adapters/mysql/tools/router.js +174 -109
  260. package/dist/adapters/mysql/tools/router.js.map +1 -1
  261. package/dist/adapters/mysql/tools/schema/constraints.d.ts +2 -2
  262. package/dist/adapters/mysql/tools/schema/constraints.d.ts.map +1 -1
  263. package/dist/adapters/mysql/tools/schema/constraints.js +24 -15
  264. package/dist/adapters/mysql/tools/schema/constraints.js.map +1 -1
  265. package/dist/adapters/mysql/tools/schema/index.d.ts +2 -2
  266. package/dist/adapters/mysql/tools/schema/index.d.ts.map +1 -1
  267. package/dist/adapters/mysql/tools/schema/index.js +7 -7
  268. package/dist/adapters/mysql/tools/schema/index.js.map +1 -1
  269. package/dist/adapters/mysql/tools/schema/management.d.ts +2 -2
  270. package/dist/adapters/mysql/tools/schema/management.d.ts.map +1 -1
  271. package/dist/adapters/mysql/tools/schema/management.js +99 -42
  272. package/dist/adapters/mysql/tools/schema/management.js.map +1 -1
  273. package/dist/adapters/mysql/tools/schema/routines.d.ts +2 -2
  274. package/dist/adapters/mysql/tools/schema/routines.d.ts.map +1 -1
  275. package/dist/adapters/mysql/tools/schema/routines.js +36 -19
  276. package/dist/adapters/mysql/tools/schema/routines.js.map +1 -1
  277. package/dist/adapters/mysql/tools/schema/scheduled_events.d.ts +2 -2
  278. package/dist/adapters/mysql/tools/schema/scheduled_events.d.ts.map +1 -1
  279. package/dist/adapters/mysql/tools/schema/scheduled_events.js +26 -13
  280. package/dist/adapters/mysql/tools/schema/scheduled_events.js.map +1 -1
  281. package/dist/adapters/mysql/tools/schema/triggers.d.ts +2 -2
  282. package/dist/adapters/mysql/tools/schema/triggers.d.ts.map +1 -1
  283. package/dist/adapters/mysql/tools/schema/triggers.js +24 -13
  284. package/dist/adapters/mysql/tools/schema/triggers.js.map +1 -1
  285. package/dist/adapters/mysql/tools/schema/views.d.ts +2 -2
  286. package/dist/adapters/mysql/tools/schema/views.d.ts.map +1 -1
  287. package/dist/adapters/mysql/tools/schema/views.js +59 -28
  288. package/dist/adapters/mysql/tools/schema/views.js.map +1 -1
  289. package/dist/adapters/mysql/tools/security/audit.d.ts +2 -2
  290. package/dist/adapters/mysql/tools/security/audit.d.ts.map +1 -1
  291. package/dist/adapters/mysql/tools/security/audit.js +61 -55
  292. package/dist/adapters/mysql/tools/security/audit.js.map +1 -1
  293. package/dist/adapters/mysql/tools/security/data-protection.d.ts +2 -2
  294. package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
  295. package/dist/adapters/mysql/tools/security/data-protection.js +193 -80
  296. package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
  297. package/dist/adapters/mysql/tools/security/encryption.d.ts +2 -2
  298. package/dist/adapters/mysql/tools/security/encryption.d.ts.map +1 -1
  299. package/dist/adapters/mysql/tools/security/encryption.js +86 -67
  300. package/dist/adapters/mysql/tools/security/encryption.js.map +1 -1
  301. package/dist/adapters/mysql/tools/security/index.d.ts +2 -2
  302. package/dist/adapters/mysql/tools/security/index.js +4 -4
  303. package/dist/adapters/mysql/tools/security/index.js.map +1 -1
  304. package/dist/adapters/mysql/tools/shell/backup.d.ts +1 -1
  305. package/dist/adapters/mysql/tools/shell/backup.d.ts.map +1 -1
  306. package/dist/adapters/mysql/tools/shell/backup.js +122 -63
  307. package/dist/adapters/mysql/tools/shell/backup.js.map +1 -1
  308. package/dist/adapters/mysql/tools/shell/common.d.ts.map +1 -1
  309. package/dist/adapters/mysql/tools/shell/common.js +61 -37
  310. package/dist/adapters/mysql/tools/shell/common.js.map +1 -1
  311. package/dist/adapters/mysql/tools/shell/data-transfer.d.ts +1 -1
  312. package/dist/adapters/mysql/tools/shell/data-transfer.d.ts.map +1 -1
  313. package/dist/adapters/mysql/tools/shell/data-transfer.js +125 -69
  314. package/dist/adapters/mysql/tools/shell/data-transfer.js.map +1 -1
  315. package/dist/adapters/mysql/tools/shell/index.d.ts +2 -2
  316. package/dist/adapters/mysql/tools/shell/index.js +6 -6
  317. package/dist/adapters/mysql/tools/shell/index.js.map +1 -1
  318. package/dist/adapters/mysql/tools/shell/info.d.ts +1 -1
  319. package/dist/adapters/mysql/tools/shell/info.d.ts.map +1 -1
  320. package/dist/adapters/mysql/tools/shell/info.js +12 -12
  321. package/dist/adapters/mysql/tools/shell/info.js.map +1 -1
  322. package/dist/adapters/mysql/tools/shell/restore.d.ts +1 -1
  323. package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
  324. package/dist/adapters/mysql/tools/shell/restore.js +128 -43
  325. package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
  326. package/dist/adapters/mysql/tools/shell/utilities.d.ts +1 -1
  327. package/dist/adapters/mysql/tools/shell/utilities.d.ts.map +1 -1
  328. package/dist/adapters/mysql/tools/shell/utilities.js +42 -18
  329. package/dist/adapters/mysql/tools/shell/utilities.js.map +1 -1
  330. package/dist/adapters/mysql/tools/spatial/geometry.d.ts +2 -2
  331. package/dist/adapters/mysql/tools/spatial/geometry.d.ts.map +1 -1
  332. package/dist/adapters/mysql/tools/spatial/geometry.js +85 -46
  333. package/dist/adapters/mysql/tools/spatial/geometry.js.map +1 -1
  334. package/dist/adapters/mysql/tools/spatial/index.d.ts +2 -2
  335. package/dist/adapters/mysql/tools/spatial/index.js +5 -5
  336. package/dist/adapters/mysql/tools/spatial/index.js.map +1 -1
  337. package/dist/adapters/mysql/tools/spatial/operations.d.ts +2 -2
  338. package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
  339. package/dist/adapters/mysql/tools/spatial/operations.js +175 -106
  340. package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
  341. package/dist/adapters/mysql/tools/spatial/queries.d.ts +2 -2
  342. package/dist/adapters/mysql/tools/spatial/queries.d.ts.map +1 -1
  343. package/dist/adapters/mysql/tools/spatial/queries.js +144 -100
  344. package/dist/adapters/mysql/tools/spatial/queries.js.map +1 -1
  345. package/dist/adapters/mysql/tools/spatial/setup.d.ts +2 -2
  346. package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
  347. package/dist/adapters/mysql/tools/spatial/setup.js +122 -34
  348. package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
  349. package/dist/adapters/mysql/tools/stats/comparative.d.ts +2 -2
  350. package/dist/adapters/mysql/tools/stats/comparative.d.ts.map +1 -1
  351. package/dist/adapters/mysql/tools/stats/comparative.js +159 -107
  352. package/dist/adapters/mysql/tools/stats/comparative.js.map +1 -1
  353. package/dist/adapters/mysql/tools/stats/descriptive.d.ts +2 -2
  354. package/dist/adapters/mysql/tools/stats/descriptive.d.ts.map +1 -1
  355. package/dist/adapters/mysql/tools/stats/descriptive.js +268 -205
  356. package/dist/adapters/mysql/tools/stats/descriptive.js.map +1 -1
  357. package/dist/adapters/mysql/tools/stats/index.d.ts +2 -2
  358. package/dist/adapters/mysql/tools/stats/index.js +3 -3
  359. package/dist/adapters/mysql/tools/stats/index.js.map +1 -1
  360. package/dist/adapters/mysql/tools/sysschema/activity.d.ts +2 -2
  361. package/dist/adapters/mysql/tools/sysschema/activity.d.ts.map +1 -1
  362. package/dist/adapters/mysql/tools/sysschema/activity.js +23 -23
  363. package/dist/adapters/mysql/tools/sysschema/activity.js.map +1 -1
  364. package/dist/adapters/mysql/tools/sysschema/index.d.ts +2 -2
  365. package/dist/adapters/mysql/tools/sysschema/index.js +4 -4
  366. package/dist/adapters/mysql/tools/sysschema/index.js.map +1 -1
  367. package/dist/adapters/mysql/tools/sysschema/performance.d.ts +2 -2
  368. package/dist/adapters/mysql/tools/sysschema/performance.d.ts.map +1 -1
  369. package/dist/adapters/mysql/tools/sysschema/performance.js +58 -43
  370. package/dist/adapters/mysql/tools/sysschema/performance.js.map +1 -1
  371. package/dist/adapters/mysql/tools/sysschema/resources.d.ts +2 -2
  372. package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
  373. package/dist/adapters/mysql/tools/sysschema/resources.js +58 -33
  374. package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
  375. package/dist/adapters/mysql/tools/text/fulltext.d.ts +4 -3
  376. package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
  377. package/dist/adapters/mysql/tools/text/fulltext.js +214 -55
  378. package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
  379. package/dist/adapters/mysql/tools/text/index.d.ts +3 -3
  380. package/dist/adapters/mysql/tools/text/index.d.ts.map +1 -1
  381. package/dist/adapters/mysql/tools/text/index.js +6 -5
  382. package/dist/adapters/mysql/tools/text/index.js.map +1 -1
  383. package/dist/adapters/mysql/tools/text/processing.d.ts +2 -2
  384. package/dist/adapters/mysql/tools/text/processing.d.ts.map +1 -1
  385. package/dist/adapters/mysql/tools/text/processing.js +175 -122
  386. package/dist/adapters/mysql/tools/text/processing.js.map +1 -1
  387. package/dist/adapters/mysql/tools/transactions.d.ts +2 -2
  388. package/dist/adapters/mysql/tools/transactions.d.ts.map +1 -1
  389. package/dist/adapters/mysql/tools/transactions.js +162 -85
  390. package/dist/adapters/mysql/tools/transactions.js.map +1 -1
  391. package/dist/adapters/mysql/types/proxysql-types.d.ts +7 -2
  392. package/dist/adapters/mysql/types/proxysql-types.d.ts.map +1 -1
  393. package/dist/adapters/mysql/types/proxysql-types.js +52 -30
  394. package/dist/adapters/mysql/types/proxysql-types.js.map +1 -1
  395. package/dist/adapters/mysql/types/router-types.d.ts +1 -1
  396. package/dist/adapters/mysql/types/router-types.js +17 -17
  397. package/dist/adapters/mysql/types/router-types.js.map +1 -1
  398. package/dist/adapters/mysql/types/shell-types.d.ts +1 -2
  399. package/dist/adapters/mysql/types/shell-types.d.ts.map +1 -1
  400. package/dist/adapters/mysql/types/shell-types.js +255 -82
  401. package/dist/adapters/mysql/types/shell-types.js.map +1 -1
  402. package/dist/adapters/mysql/types.d.ts +976 -80
  403. package/dist/adapters/mysql/types.d.ts.map +1 -1
  404. package/dist/adapters/mysql/types.js +1317 -170
  405. package/dist/adapters/mysql/types.js.map +1 -1
  406. package/dist/auth/AuthorizationServerDiscovery.d.ts +1 -1
  407. package/dist/auth/AuthorizationServerDiscovery.d.ts.map +1 -1
  408. package/dist/auth/AuthorizationServerDiscovery.js +16 -14
  409. package/dist/auth/AuthorizationServerDiscovery.js.map +1 -1
  410. package/dist/auth/OAuthResourceServer.d.ts +1 -1
  411. package/dist/auth/OAuthResourceServer.d.ts.map +1 -1
  412. package/dist/auth/OAuthResourceServer.js +4 -4
  413. package/dist/auth/OAuthResourceServer.js.map +1 -1
  414. package/dist/auth/TokenValidator.d.ts +1 -1
  415. package/dist/auth/TokenValidator.d.ts.map +1 -1
  416. package/dist/auth/TokenValidator.js +30 -20
  417. package/dist/auth/TokenValidator.js.map +1 -1
  418. package/dist/auth/errors.d.ts.map +1 -1
  419. package/dist/auth/errors.js +24 -24
  420. package/dist/auth/errors.js.map +1 -1
  421. package/dist/auth/index.d.ts +7 -7
  422. package/dist/auth/index.d.ts.map +1 -1
  423. package/dist/auth/index.js +6 -6
  424. package/dist/auth/index.js.map +1 -1
  425. package/dist/auth/middleware.d.ts +2 -2
  426. package/dist/auth/middleware.d.ts.map +1 -1
  427. package/dist/auth/middleware.js +28 -24
  428. package/dist/auth/middleware.js.map +1 -1
  429. package/dist/auth/scopes.d.ts +2 -2
  430. package/dist/auth/scopes.d.ts.map +1 -1
  431. package/dist/auth/scopes.js +23 -16
  432. package/dist/auth/scopes.js.map +1 -1
  433. package/dist/auth/types.d.ts +2 -2
  434. package/dist/auth/types.d.ts.map +1 -1
  435. package/dist/cli/args.d.ts +1 -1
  436. package/dist/cli/args.d.ts.map +1 -1
  437. package/dist/cli/args.js +82 -68
  438. package/dist/cli/args.js.map +1 -1
  439. package/dist/cli.d.ts +1 -1
  440. package/dist/cli.d.ts.map +1 -1
  441. package/dist/cli.js +44 -34
  442. package/dist/cli.js.map +1 -1
  443. package/dist/codemode/api.d.ts +69 -0
  444. package/dist/codemode/api.d.ts.map +1 -0
  445. package/dist/codemode/api.js +1035 -0
  446. package/dist/codemode/api.js.map +1 -0
  447. package/dist/codemode/index.d.ts +13 -0
  448. package/dist/codemode/index.d.ts.map +1 -0
  449. package/dist/codemode/index.js +17 -0
  450. package/dist/codemode/index.js.map +1 -0
  451. package/dist/codemode/sandbox-factory.d.ts +72 -0
  452. package/dist/codemode/sandbox-factory.d.ts.map +1 -0
  453. package/dist/codemode/sandbox-factory.js +88 -0
  454. package/dist/codemode/sandbox-factory.js.map +1 -0
  455. package/dist/codemode/sandbox.d.ts +96 -0
  456. package/dist/codemode/sandbox.d.ts.map +1 -0
  457. package/dist/codemode/sandbox.js +345 -0
  458. package/dist/codemode/sandbox.js.map +1 -0
  459. package/dist/codemode/security.d.ts +44 -0
  460. package/dist/codemode/security.d.ts.map +1 -0
  461. package/dist/codemode/security.js +149 -0
  462. package/dist/codemode/security.js.map +1 -0
  463. package/dist/codemode/types.d.ts +137 -0
  464. package/dist/codemode/types.d.ts.map +1 -0
  465. package/dist/codemode/types.js +46 -0
  466. package/dist/codemode/types.js.map +1 -0
  467. package/dist/codemode/worker-sandbox.d.ts +82 -0
  468. package/dist/codemode/worker-sandbox.d.ts.map +1 -0
  469. package/dist/codemode/worker-sandbox.js +244 -0
  470. package/dist/codemode/worker-sandbox.js.map +1 -0
  471. package/dist/codemode/worker-script.d.ts +8 -0
  472. package/dist/codemode/worker-script.d.ts.map +1 -0
  473. package/dist/codemode/worker-script.js +113 -0
  474. package/dist/codemode/worker-script.js.map +1 -0
  475. package/dist/constants/ServerInstructions.d.ts +2 -2
  476. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  477. package/dist/constants/ServerInstructions.js +252 -36
  478. package/dist/constants/ServerInstructions.js.map +1 -1
  479. package/dist/filtering/ToolConstants.d.ts +12 -12
  480. package/dist/filtering/ToolConstants.d.ts.map +1 -1
  481. package/dist/filtering/ToolConstants.js +253 -214
  482. package/dist/filtering/ToolConstants.js.map +1 -1
  483. package/dist/filtering/ToolFilter.d.ts +2 -2
  484. package/dist/filtering/ToolFilter.d.ts.map +1 -1
  485. package/dist/filtering/ToolFilter.js +47 -36
  486. package/dist/filtering/ToolFilter.js.map +1 -1
  487. package/dist/index.d.ts +9 -9
  488. package/dist/index.d.ts.map +1 -1
  489. package/dist/index.js +7 -7
  490. package/dist/index.js.map +1 -1
  491. package/dist/logging/McpLogging.d.ts +2 -2
  492. package/dist/logging/McpLogging.d.ts.map +1 -1
  493. package/dist/logging/McpLogging.js +16 -13
  494. package/dist/logging/McpLogging.js.map +1 -1
  495. package/dist/logging/index.d.ts +1 -1
  496. package/dist/logging/index.js +1 -1
  497. package/dist/pool/ConnectionPool.d.ts +3 -3
  498. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  499. package/dist/pool/ConnectionPool.js +30 -26
  500. package/dist/pool/ConnectionPool.js.map +1 -1
  501. package/dist/progress/ProgressReporter.d.ts +1 -1
  502. package/dist/progress/ProgressReporter.d.ts.map +1 -1
  503. package/dist/progress/ProgressReporter.js +5 -5
  504. package/dist/progress/ProgressReporter.js.map +1 -1
  505. package/dist/progress/index.d.ts +1 -1
  506. package/dist/progress/index.d.ts.map +1 -1
  507. package/dist/progress/index.js +1 -1
  508. package/dist/progress/index.js.map +1 -1
  509. package/dist/server/McpServer.d.ts +3 -3
  510. package/dist/server/McpServer.d.ts.map +1 -1
  511. package/dist/server/McpServer.js +58 -53
  512. package/dist/server/McpServer.js.map +1 -1
  513. package/dist/transports/http.d.ts +3 -3
  514. package/dist/transports/http.d.ts.map +1 -1
  515. package/dist/transports/http.js +36 -33
  516. package/dist/transports/http.js.map +1 -1
  517. package/dist/transports/index.d.ts +1 -1
  518. package/dist/transports/index.d.ts.map +1 -1
  519. package/dist/transports/index.js +1 -1
  520. package/dist/transports/index.js.map +1 -1
  521. package/dist/types/index.d.ts +6 -6
  522. package/dist/types/index.d.ts.map +1 -1
  523. package/dist/types/index.js +1 -1
  524. package/dist/types/index.js.map +1 -1
  525. package/dist/types/modules/database.d.ts +1 -1
  526. package/dist/types/modules/database.d.ts.map +1 -1
  527. package/dist/types/modules/errors.d.ts.map +1 -1
  528. package/dist/types/modules/errors.js +15 -15
  529. package/dist/types/modules/errors.js.map +1 -1
  530. package/dist/types/modules/oauth.d.ts +1 -1
  531. package/dist/types/modules/oauth.d.ts.map +1 -1
  532. package/dist/types/modules/query.d.ts +8 -8
  533. package/dist/types/modules/query.d.ts.map +1 -1
  534. package/dist/types/modules/server.d.ts +5 -3
  535. package/dist/types/modules/server.d.ts.map +1 -1
  536. package/dist/types/modules/tools.d.ts +6 -6
  537. package/dist/types/modules/tools.d.ts.map +1 -1
  538. package/dist/utils/logger.d.ts +2 -2
  539. package/dist/utils/logger.d.ts.map +1 -1
  540. package/dist/utils/logger.js +58 -55
  541. package/dist/utils/logger.js.map +1 -1
  542. package/dist/utils/promptGenerator.d.ts +1 -1
  543. package/dist/utils/promptGenerator.d.ts.map +1 -1
  544. package/dist/utils/promptGenerator.js +24 -16
  545. package/dist/utils/promptGenerator.js.map +1 -1
  546. package/dist/utils/validators.d.ts +21 -2
  547. package/dist/utils/validators.d.ts.map +1 -1
  548. package/dist/utils/validators.js +101 -13
  549. package/dist/utils/validators.js.map +1 -1
  550. package/eslint.config.js +117 -81
  551. package/package.json +66 -64
  552. package/releases/release-notes.md +32 -26
  553. package/releases/v2.0.0-release-notes.md +99 -51
  554. package/releases/v2.1.0-release-notes.md +14 -5
  555. package/releases/v2.2.0-release-notes.md +239 -0
  556. package/releases/v2.3.0-release-notes.md +191 -0
  557. package/server.json +1 -1
  558. package/src/__tests__/cli.test.ts +302 -247
  559. package/src/__tests__/index.test.ts +21 -21
  560. package/src/__tests__/mocks/adapter.ts +204 -163
  561. package/src/__tests__/mocks/index.ts +30 -23
  562. package/src/__tests__/mocks/mysql.ts +94 -84
  563. package/src/__tests__/perf.test.ts +207 -203
  564. package/src/__tests__/performance.test.ts +173 -164
  565. package/src/__tests__/setup.ts +26 -21
  566. package/src/adapters/DatabaseAdapter.ts +386 -340
  567. package/src/adapters/__tests__/DatabaseAdapter.test.ts +455 -377
  568. package/src/adapters/mysql/MySQLAdapter.ts +560 -486
  569. package/src/adapters/mysql/SchemaManager.ts +251 -208
  570. package/src/adapters/mysql/__tests__/MySQLAdapter.integration.test.ts +150 -147
  571. package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +590 -477
  572. package/src/adapters/mysql/__tests__/SchemaManager.test.ts +196 -154
  573. package/src/adapters/mysql/index.ts +2 -2
  574. package/src/adapters/mysql/prompts/__tests__/indexTuning.test.ts +33 -26
  575. package/src/adapters/mysql/prompts/__tests__/prompts.test.ts +277 -239
  576. package/src/adapters/mysql/prompts/backupStrategy.ts +29 -17
  577. package/src/adapters/mysql/prompts/clusterSetup.ts +11 -10
  578. package/src/adapters/mysql/prompts/docstoreSetup.ts +10 -10
  579. package/src/adapters/mysql/prompts/eventScheduler.ts +10 -10
  580. package/src/adapters/mysql/prompts/healthCheck.ts +20 -15
  581. package/src/adapters/mysql/prompts/index.ts +202 -145
  582. package/src/adapters/mysql/prompts/indexTuning.ts +22 -17
  583. package/src/adapters/mysql/prompts/mysqlshSetup.ts +11 -11
  584. package/src/adapters/mysql/prompts/proxysqlSetup.ts +10 -10
  585. package/src/adapters/mysql/prompts/replicationSetup.ts +24 -16
  586. package/src/adapters/mysql/prompts/routerSetup.ts +15 -10
  587. package/src/adapters/mysql/prompts/spatialSetup.ts +10 -10
  588. package/src/adapters/mysql/prompts/sysSchema.ts +11 -10
  589. package/src/adapters/mysql/resources/__tests__/capabilities.test.ts +118 -47
  590. package/src/adapters/mysql/resources/__tests__/cluster.test.ts +163 -104
  591. package/src/adapters/mysql/resources/__tests__/docstore.test.ts +88 -81
  592. package/src/adapters/mysql/resources/__tests__/events.test.ts +94 -83
  593. package/src/adapters/mysql/resources/__tests__/health.test.ts +131 -91
  594. package/src/adapters/mysql/resources/__tests__/indexes.test.ts +125 -102
  595. package/src/adapters/mysql/resources/__tests__/innodb.test.ts +86 -62
  596. package/src/adapters/mysql/resources/__tests__/locks.test.ts +142 -104
  597. package/src/adapters/mysql/resources/__tests__/performance.test.ts +81 -58
  598. package/src/adapters/mysql/resources/__tests__/pool.test.ts +45 -40
  599. package/src/adapters/mysql/resources/__tests__/processlist.test.ts +39 -23
  600. package/src/adapters/mysql/resources/__tests__/replication.test.ts +265 -211
  601. package/src/adapters/mysql/resources/__tests__/resources.test.ts +121 -109
  602. package/src/adapters/mysql/resources/__tests__/schema.test.ts +29 -23
  603. package/src/adapters/mysql/resources/__tests__/spatial.test.ts +58 -45
  604. package/src/adapters/mysql/resources/__tests__/status.test.ts +62 -45
  605. package/src/adapters/mysql/resources/__tests__/sysschema.test.ts +99 -60
  606. package/src/adapters/mysql/resources/__tests__/tables.test.ts +41 -32
  607. package/src/adapters/mysql/resources/__tests__/variables.test.ts +77 -49
  608. package/src/adapters/mysql/resources/capabilities.ts +61 -42
  609. package/src/adapters/mysql/resources/cluster.ts +58 -49
  610. package/src/adapters/mysql/resources/docstore.ts +46 -41
  611. package/src/adapters/mysql/resources/events.ts +37 -31
  612. package/src/adapters/mysql/resources/health.ts +98 -74
  613. package/src/adapters/mysql/resources/index.ts +55 -47
  614. package/src/adapters/mysql/resources/indexes.ts +66 -51
  615. package/src/adapters/mysql/resources/innodb.ts +98 -81
  616. package/src/adapters/mysql/resources/locks.ts +43 -40
  617. package/src/adapters/mysql/resources/performance.ts +80 -67
  618. package/src/adapters/mysql/resources/pool.ts +23 -20
  619. package/src/adapters/mysql/resources/processlist.ts +23 -18
  620. package/src/adapters/mysql/resources/replication.ts +124 -105
  621. package/src/adapters/mysql/resources/schema.ts +23 -18
  622. package/src/adapters/mysql/resources/spatial.ts +31 -26
  623. package/src/adapters/mysql/resources/status.ts +27 -22
  624. package/src/adapters/mysql/resources/sysschema.ts +41 -36
  625. package/src/adapters/mysql/resources/tables.ts +23 -18
  626. package/src/adapters/mysql/resources/variables.ts +27 -22
  627. package/src/adapters/mysql/tools/__tests__/cluster.test.ts +419 -311
  628. package/src/adapters/mysql/tools/__tests__/core.test.ts +701 -382
  629. package/src/adapters/mysql/tools/__tests__/docstore.test.ts +782 -413
  630. package/src/adapters/mysql/tools/__tests__/events.test.ts +806 -486
  631. package/src/adapters/mysql/tools/__tests__/json_core.test.ts +326 -259
  632. package/src/adapters/mysql/tools/__tests__/json_enhanced.test.ts +452 -352
  633. package/src/adapters/mysql/tools/__tests__/json_helpers.test.ts +203 -128
  634. package/src/adapters/mysql/tools/__tests__/proxysql.test.ts +576 -340
  635. package/src/adapters/mysql/tools/__tests__/replication.test.ts +796 -390
  636. package/src/adapters/mysql/tools/__tests__/roles.test.ts +423 -166
  637. package/src/adapters/mysql/tools/__tests__/router.test.ts +644 -540
  638. package/src/adapters/mysql/tools/__tests__/security.test.ts +746 -421
  639. package/src/adapters/mysql/tools/__tests__/security_injection.test.ts +246 -173
  640. package/src/adapters/mysql/tools/__tests__/security_integration.test.ts +244 -205
  641. package/src/adapters/mysql/tools/__tests__/spatial.test.ts +443 -298
  642. package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +535 -150
  643. package/src/adapters/mysql/tools/__tests__/stats.test.ts +861 -553
  644. package/src/adapters/mysql/tools/__tests__/transactions.test.ts +452 -263
  645. package/src/adapters/mysql/tools/admin/__tests__/backup.test.ts +612 -372
  646. package/src/adapters/mysql/tools/admin/__tests__/maintenance.test.ts +550 -257
  647. package/src/adapters/mysql/tools/admin/__tests__/monitoring.test.ts +549 -352
  648. package/src/adapters/mysql/tools/admin/backup.ts +339 -215
  649. package/src/adapters/mysql/tools/admin/index.ts +46 -46
  650. package/src/adapters/mysql/tools/admin/maintenance.ts +180 -130
  651. package/src/adapters/mysql/tools/admin/monitoring.ts +373 -199
  652. package/src/adapters/mysql/tools/cluster/__tests__/group-replication.test.ts +200 -186
  653. package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +399 -95
  654. package/src/adapters/mysql/tools/cluster/group-replication.ts +218 -183
  655. package/src/adapters/mysql/tools/cluster/index.ts +27 -27
  656. package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +413 -251
  657. package/src/adapters/mysql/tools/codemode/index.ts +249 -0
  658. package/src/adapters/mysql/tools/core.ts +425 -285
  659. package/src/adapters/mysql/tools/docstore.ts +478 -276
  660. package/src/adapters/mysql/tools/events.ts +441 -285
  661. package/src/adapters/mysql/tools/index.ts +31 -20
  662. package/src/adapters/mysql/tools/json/__tests__/core.test.ts +456 -199
  663. package/src/adapters/mysql/tools/json/__tests__/enhanced.test.ts +554 -298
  664. package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +195 -74
  665. package/src/adapters/mysql/tools/json/__tests__/validation.test.ts +106 -72
  666. package/src/adapters/mysql/tools/json/core.ts +368 -263
  667. package/src/adapters/mysql/tools/json/enhanced.ts +368 -229
  668. package/src/adapters/mysql/tools/json/helpers.ts +205 -113
  669. package/src/adapters/mysql/tools/json/index.ts +46 -46
  670. package/src/adapters/mysql/tools/partitioning.ts +289 -140
  671. package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +664 -249
  672. package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +436 -179
  673. package/src/adapters/mysql/tools/performance/analysis.ts +319 -215
  674. package/src/adapters/mysql/tools/performance/index.ts +33 -33
  675. package/src/adapters/mysql/tools/performance/optimization.ts +438 -183
  676. package/src/adapters/mysql/tools/proxysql.ts +462 -320
  677. package/src/adapters/mysql/tools/replication.ts +233 -180
  678. package/src/adapters/mysql/tools/roles.ts +429 -171
  679. package/src/adapters/mysql/tools/router.ts +410 -292
  680. package/src/adapters/mysql/tools/schema/__tests__/constraints.test.ts +157 -82
  681. package/src/adapters/mysql/tools/schema/__tests__/management.test.ts +226 -101
  682. package/src/adapters/mysql/tools/schema/__tests__/routines.test.ts +80 -35
  683. package/src/adapters/mysql/tools/schema/__tests__/scheduled_events.test.ts +59 -40
  684. package/src/adapters/mysql/tools/schema/__tests__/triggers.test.ts +65 -40
  685. package/src/adapters/mysql/tools/schema/__tests__/views.test.ts +146 -77
  686. package/src/adapters/mysql/tools/schema/constraints.ts +61 -42
  687. package/src/adapters/mysql/tools/schema/index.ts +26 -35
  688. package/src/adapters/mysql/tools/schema/management.ts +167 -94
  689. package/src/adapters/mysql/tools/schema/routines.ts +79 -48
  690. package/src/adapters/mysql/tools/schema/scheduled_events.ts +53 -32
  691. package/src/adapters/mysql/tools/schema/triggers.ts +51 -33
  692. package/src/adapters/mysql/tools/schema/views.ts +96 -53
  693. package/src/adapters/mysql/tools/security/__tests__/audit.test.ts +216 -158
  694. package/src/adapters/mysql/tools/security/__tests__/data-protection.test.ts +154 -98
  695. package/src/adapters/mysql/tools/security/__tests__/encryption.test.ts +174 -138
  696. package/src/adapters/mysql/tools/security/audit.ts +213 -193
  697. package/src/adapters/mysql/tools/security/data-protection.ts +342 -198
  698. package/src/adapters/mysql/tools/security/encryption.ts +233 -193
  699. package/src/adapters/mysql/tools/security/index.ts +26 -26
  700. package/src/adapters/mysql/tools/shell/__tests__/backup.test.ts +443 -283
  701. package/src/adapters/mysql/tools/shell/__tests__/common.test.ts +183 -130
  702. package/src/adapters/mysql/tools/shell/__tests__/data-transfer.test.ts +516 -353
  703. package/src/adapters/mysql/tools/shell/__tests__/info.test.ts +65 -63
  704. package/src/adapters/mysql/tools/shell/__tests__/restore.test.ts +260 -174
  705. package/src/adapters/mysql/tools/shell/__tests__/utilities.test.ts +161 -143
  706. package/src/adapters/mysql/tools/shell/backup.ts +280 -188
  707. package/src/adapters/mysql/tools/shell/common.ts +203 -153
  708. package/src/adapters/mysql/tools/shell/data-transfer.ts +286 -200
  709. package/src/adapters/mysql/tools/shell/index.ts +29 -29
  710. package/src/adapters/mysql/tools/shell/info.ts +35 -31
  711. package/src/adapters/mysql/tools/shell/restore.ts +236 -121
  712. package/src/adapters/mysql/tools/shell/utilities.ts +86 -45
  713. package/src/adapters/mysql/tools/spatial/__tests__/geometry.test.ts +129 -89
  714. package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +284 -148
  715. package/src/adapters/mysql/tools/spatial/__tests__/queries.test.ts +340 -245
  716. package/src/adapters/mysql/tools/spatial/geometry.ts +120 -74
  717. package/src/adapters/mysql/tools/spatial/index.ts +33 -33
  718. package/src/adapters/mysql/tools/spatial/operations.ts +254 -171
  719. package/src/adapters/mysql/tools/spatial/queries.ts +221 -165
  720. package/src/adapters/mysql/tools/spatial/setup.ts +180 -73
  721. package/src/adapters/mysql/tools/stats/__tests__/comparative.test.ts +188 -130
  722. package/src/adapters/mysql/tools/stats/comparative.ts +261 -187
  723. package/src/adapters/mysql/tools/stats/descriptive.ts +414 -322
  724. package/src/adapters/mysql/tools/stats/index.ts +23 -23
  725. package/src/adapters/mysql/tools/sysschema/__tests__/activity.test.ts +99 -71
  726. package/src/adapters/mysql/tools/sysschema/__tests__/io_summary_fix.test.ts +21 -18
  727. package/src/adapters/mysql/tools/sysschema/__tests__/performance.test.ts +149 -108
  728. package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +243 -104
  729. package/src/adapters/mysql/tools/sysschema/activity.ts +72 -64
  730. package/src/adapters/mysql/tools/sysschema/index.ts +24 -24
  731. package/src/adapters/mysql/tools/sysschema/performance.ts +140 -115
  732. package/src/adapters/mysql/tools/sysschema/resources.ts +140 -99
  733. package/src/adapters/mysql/tools/text/__tests__/fulltext.test.ts +526 -145
  734. package/src/adapters/mysql/tools/text/__tests__/processing.test.ts +452 -193
  735. package/src/adapters/mysql/tools/text/fulltext.ts +327 -123
  736. package/src/adapters/mysql/tools/text/index.ts +32 -30
  737. package/src/adapters/mysql/tools/text/processing.ts +281 -212
  738. package/src/adapters/mysql/tools/transactions.ts +288 -197
  739. package/src/adapters/mysql/types/__tests__/shell-types.test.ts +204 -202
  740. package/src/adapters/mysql/types/proxysql-types.ts +142 -109
  741. package/src/adapters/mysql/types/router-types.ts +36 -36
  742. package/src/adapters/mysql/types/shell-types.ts +280 -94
  743. package/src/adapters/mysql/types.ts +1475 -164
  744. package/src/auth/AuthorizationServerDiscovery.ts +127 -113
  745. package/src/auth/OAuthResourceServer.ts +67 -62
  746. package/src/auth/TokenValidator.ts +136 -119
  747. package/src/auth/__tests__/AuthorizationServerDiscovery.test.ts +295 -274
  748. package/src/auth/__tests__/OAuthResourceServer.test.ts +180 -169
  749. package/src/auth/__tests__/TokenValidator.test.ts +297 -285
  750. package/src/auth/__tests__/errors.test.ts +180 -175
  751. package/src/auth/__tests__/middleware.test.ts +281 -247
  752. package/src/auth/__tests__/scopes.test.ts +136 -134
  753. package/src/auth/errors.ts +56 -56
  754. package/src/auth/index.ts +23 -17
  755. package/src/auth/middleware.ts +161 -139
  756. package/src/auth/scopes.ts +134 -107
  757. package/src/auth/types.ts +155 -155
  758. package/src/cli/__tests__/args.test.ts +241 -216
  759. package/src/cli/__tests__/main.test.ts +191 -158
  760. package/src/cli/args.ts +285 -258
  761. package/src/cli.ts +150 -127
  762. package/src/codemode/api.ts +1224 -0
  763. package/src/codemode/index.ts +51 -0
  764. package/src/codemode/sandbox-factory.ts +146 -0
  765. package/src/codemode/sandbox.ts +450 -0
  766. package/src/codemode/security.ts +188 -0
  767. package/src/codemode/types.ts +194 -0
  768. package/src/codemode/worker-sandbox.ts +326 -0
  769. package/src/codemode/worker-script.ts +144 -0
  770. package/src/constants/ServerInstructions.ts +295 -70
  771. package/src/filtering/ToolConstants.ts +311 -272
  772. package/src/filtering/ToolFilter.ts +254 -220
  773. package/src/filtering/__tests__/ToolFilter.test.ts +469 -396
  774. package/src/index.ts +62 -57
  775. package/src/logging/McpLogging.ts +128 -119
  776. package/src/logging/__tests__/McpLogging.test.ts +223 -223
  777. package/src/logging/index.ts +2 -2
  778. package/src/pool/ConnectionPool.ts +260 -246
  779. package/src/pool/__tests__/ConnectionPool.test.ts +452 -418
  780. package/src/progress/ProgressReporter.ts +123 -123
  781. package/src/progress/__tests__/ProgressReporter.test.ts +235 -229
  782. package/src/progress/index.ts +6 -2
  783. package/src/server/McpServer.ts +305 -285
  784. package/src/server/__tests__/McpServer.test.ts +333 -291
  785. package/src/transports/__tests__/http.test.ts +658 -527
  786. package/src/transports/http.ts +237 -203
  787. package/src/transports/index.ts +6 -2
  788. package/src/types/__tests__/types.test.ts +197 -193
  789. package/src/types/index.ts +49 -37
  790. package/src/types/modules/database.ts +65 -63
  791. package/src/types/modules/errors.ts +41 -37
  792. package/src/types/modules/oauth.ts +46 -46
  793. package/src/types/modules/query.ts +75 -75
  794. package/src/types/modules/server.ts +21 -18
  795. package/src/types/modules/tools.ts +182 -178
  796. package/src/utils/__tests__/logger.test.ts +424 -414
  797. package/src/utils/__tests__/validators.test.ts +250 -165
  798. package/src/utils/logger.ts +344 -330
  799. package/src/utils/promptGenerator.ts +58 -47
  800. package/src/utils/validators.ts +217 -91
  801. package/tsconfig.json +41 -50
  802. package/vitest.config.ts +23 -23
@@ -1,577 +1,885 @@
1
1
  /**
2
2
  * mysql-mcp - Stats Tools Unit Tests
3
- *
3
+ *
4
4
  * Tests for stats tool definitions, annotations, and handler execution.
5
5
  */
6
6
 
7
- import { describe, it, expect, vi, beforeEach } from 'vitest';
8
- import { getStatsTools } from '../stats/index.js';
9
- import type { MySQLAdapter } from '../../MySQLAdapter.js';
10
- import { createMockMySQLAdapter, createMockRequestContext, createMockQueryResult } from '../../../../__tests__/mocks/index.js';
11
-
12
- describe('getStatsTools', () => {
13
- let tools: ReturnType<typeof getStatsTools>;
7
+ import { describe, it, expect, vi, beforeEach } from "vitest";
8
+ import { getStatsTools } from "../stats/index.js";
9
+ import type { MySQLAdapter } from "../../MySQLAdapter.js";
10
+ import {
11
+ createMockMySQLAdapter,
12
+ createMockRequestContext,
13
+ createMockQueryResult,
14
+ } from "../../../../__tests__/mocks/index.js";
15
+
16
+ describe("getStatsTools", () => {
17
+ let tools: ReturnType<typeof getStatsTools>;
18
+
19
+ beforeEach(() => {
20
+ vi.clearAllMocks();
21
+ tools = getStatsTools(createMockMySQLAdapter() as unknown as MySQLAdapter);
22
+ });
23
+
24
+ it("should return 8 stats tools", () => {
25
+ expect(tools).toHaveLength(8);
26
+ });
27
+
28
+ it("should have stats group for all tools", () => {
29
+ for (const tool of tools) {
30
+ expect(tool.group).toBe("stats");
31
+ }
32
+ });
33
+
34
+ it("should have handler functions for all tools", () => {
35
+ for (const tool of tools) {
36
+ expect(typeof tool.handler).toBe("function");
37
+ }
38
+ });
39
+
40
+ it("should have inputSchema for all tools", () => {
41
+ for (const tool of tools) {
42
+ expect(tool.inputSchema).toBeDefined();
43
+ }
44
+ });
45
+
46
+ it("should include expected tool names", () => {
47
+ const names = tools.map((t) => t.name);
48
+ expect(names).toContain("mysql_stats_descriptive");
49
+ expect(names).toContain("mysql_stats_percentiles");
50
+ expect(names).toContain("mysql_stats_correlation");
51
+ expect(names).toContain("mysql_stats_distribution");
52
+ expect(names).toContain("mysql_stats_time_series");
53
+ expect(names).toContain("mysql_stats_regression");
54
+ expect(names).toContain("mysql_stats_sampling");
55
+ expect(names).toContain("mysql_stats_histogram");
56
+ });
57
+ });
14
58
 
15
- beforeEach(() => {
16
- vi.clearAllMocks();
17
- tools = getStatsTools(createMockMySQLAdapter() as unknown as MySQLAdapter);
59
+ describe("Handler Execution", () => {
60
+ let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
61
+ let tools: ReturnType<typeof getStatsTools>;
62
+ let mockContext: ReturnType<typeof createMockRequestContext>;
63
+
64
+ beforeEach(() => {
65
+ vi.clearAllMocks();
66
+ mockAdapter = createMockMySQLAdapter();
67
+ tools = getStatsTools(mockAdapter as unknown as MySQLAdapter);
68
+ mockContext = createMockRequestContext();
69
+ });
70
+
71
+ describe("mysql_stats_descriptive", () => {
72
+ it("should calculate descriptive statistics", async () => {
73
+ mockAdapter.executeQuery.mockImplementation(async (query) => {
74
+ if (query.includes("COUNT(*) as count")) {
75
+ return createMockQueryResult([{ count: 100 }]);
76
+ }
77
+ if (query.includes("AVG(val) as median")) {
78
+ return createMockQueryResult([{ median: 50 }]);
79
+ }
80
+ return createMockQueryResult([
81
+ {
82
+ count: 100,
83
+ mean: 50.5,
84
+ min: 1,
85
+ max: 100,
86
+ range: 99,
87
+ stddev: 10,
88
+ variance: 100,
89
+ sum: 5050,
90
+ },
91
+ ]);
92
+ });
93
+
94
+ const tool = tools.find((t) => t.name === "mysql_stats_descriptive")!;
95
+ const result = await tool.handler(
96
+ { table: "orders", column: "total" },
97
+ mockContext,
98
+ );
99
+
100
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(3);
101
+
102
+ // Verify all queries were made
103
+ const calls = mockAdapter.executeQuery.mock.calls.map(
104
+ (c) => c[0] as string,
105
+ );
106
+ expect(calls.some((c) => c.includes("COUNT(*)"))).toBe(true);
107
+ expect(calls.some((c) => c.includes("OFFSET"))).toBe(true);
108
+ expect(calls.some((c) => c.includes("as `range`"))).toBe(true);
109
+
110
+ // Returns column, count, mean, median, stddev, etc
111
+ expect(result).toHaveProperty("column", "total");
112
+ expect(result).toHaveProperty("count", 100);
113
+ expect(result).toHaveProperty("median", 50);
114
+ expect(result).toHaveProperty("range", 99);
18
115
  });
19
116
 
20
- it('should return 8 stats tools', () => {
21
- expect(tools).toHaveLength(8);
117
+ it("should include where clause in all queries", async () => {
118
+ mockAdapter.executeQuery.mockResolvedValue(
119
+ createMockQueryResult([{ count: 10 }]),
120
+ );
121
+
122
+ const tool = tools.find((t) => t.name === "mysql_stats_descriptive")!;
123
+ await tool.handler(
124
+ { table: "orders", column: "total", where: 'status = "completed"' },
125
+ mockContext,
126
+ );
127
+
128
+ // Check that WHERE clause was present in all queries
129
+ const calls = mockAdapter.executeQuery.mock.calls.map(
130
+ (c) => c[0] as string,
131
+ );
132
+ expect(calls.length).toBeGreaterThan(0);
133
+ for (const call of calls) {
134
+ expect(call).toContain('WHERE status = "completed"');
135
+ }
22
136
  });
23
137
 
24
- it('should have stats group for all tools', () => {
25
- for (const tool of tools) {
26
- expect(tool.group).toBe('stats');
138
+ it("should return nulls when count is 0", async () => {
139
+ mockAdapter.executeQuery.mockImplementation(async (query) => {
140
+ if (query.includes("COUNT(*) as count")) {
141
+ return createMockQueryResult([{ count: 0 }]);
27
142
  }
143
+ return createMockQueryResult([]);
144
+ });
145
+
146
+ const tool = tools.find((t) => t.name === "mysql_stats_descriptive")!;
147
+ const result = await tool.handler(
148
+ { table: "orders", column: "total" },
149
+ mockContext,
150
+ );
151
+
152
+ expect(result).toHaveProperty("count", 0);
153
+ expect(result).toHaveProperty("mean", null);
154
+ expect(result).toHaveProperty("median", null);
155
+ });
156
+ });
157
+
158
+ describe("mysql_stats_percentiles", () => {
159
+ it("should calculate percentiles", async () => {
160
+ mockAdapter.executeQuery.mockResolvedValue(
161
+ createMockQueryResult([{ cnt: 100 }]),
162
+ );
163
+
164
+ const tool = tools.find((t) => t.name === "mysql_stats_percentiles")!;
165
+ const result = await tool.handler(
166
+ { table: "orders", column: "total" },
167
+ mockContext,
168
+ );
169
+
170
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
171
+ // Returns column, totalCount, percentiles
172
+ expect(result).toHaveProperty("totalCount");
173
+ expect(result).toHaveProperty("percentiles");
28
174
  });
29
175
 
30
- it('should have handler functions for all tools', () => {
31
- for (const tool of tools) {
32
- expect(typeof tool.handler).toBe('function');
33
- }
176
+ it("should use custom percentiles", async () => {
177
+ mockAdapter.executeQuery.mockResolvedValue(
178
+ createMockQueryResult([{ cnt: 100 }]),
179
+ );
180
+
181
+ const tool = tools.find((t) => t.name === "mysql_stats_percentiles")!;
182
+ await tool.handler(
183
+ {
184
+ table: "orders",
185
+ column: "total",
186
+ percentiles: [10, 50, 90, 99],
187
+ },
188
+ mockContext,
189
+ );
190
+
191
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
192
+ });
193
+ });
194
+
195
+ describe("mysql_stats_correlation", () => {
196
+ it("should calculate correlation coefficient", async () => {
197
+ mockAdapter.executeQuery.mockResolvedValue(
198
+ createMockQueryResult([
199
+ {
200
+ correlation: 0.85,
201
+ sample_size: 100,
202
+ mean_x: 50,
203
+ mean_y: 60,
204
+ std_x: 10,
205
+ std_y: 12,
206
+ },
207
+ ]),
208
+ );
209
+
210
+ const tool = tools.find((t) => t.name === "mysql_stats_correlation")!;
211
+ const result = await tool.handler(
212
+ {
213
+ table: "data",
214
+ column1: "height",
215
+ column2: "weight",
216
+ },
217
+ mockContext,
218
+ );
219
+
220
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
221
+ expect(result).toHaveProperty("column1", "height");
222
+ expect(result).toHaveProperty("column2", "weight");
223
+ expect(result).toHaveProperty("correlation");
224
+ });
225
+ });
226
+
227
+ describe("mysql_stats_distribution", () => {
228
+ it("should analyze data distribution", async () => {
229
+ mockAdapter.executeQuery.mockResolvedValue(
230
+ createMockQueryResult([{ min_val: 0, max_val: 100 }]),
231
+ );
232
+
233
+ const tool = tools.find((t) => t.name === "mysql_stats_distribution")!;
234
+ const result = await tool.handler(
235
+ {
236
+ table: "orders",
237
+ column: "amount",
238
+ buckets: 10,
239
+ },
240
+ mockContext,
241
+ );
242
+
243
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
244
+ expect(result).toHaveProperty("distribution");
245
+ });
246
+ });
247
+
248
+ describe("mysql_stats_time_series", () => {
249
+ it("should compute time series with moving average", async () => {
250
+ mockAdapter.executeQuery.mockResolvedValue(
251
+ createMockQueryResult([{ period: "2024-01", value: 100 }]),
252
+ );
253
+
254
+ const tool = tools.find((t) => t.name === "mysql_stats_time_series")!;
255
+ const result = await tool.handler(
256
+ {
257
+ table: "sales",
258
+ timeColumn: "sale_date",
259
+ valueColumn: "amount",
260
+ interval: "month",
261
+ },
262
+ mockContext,
263
+ );
264
+
265
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
266
+ expect(result).toHaveProperty("dataPoints");
267
+ });
268
+ });
269
+
270
+ describe("mysql_stats_regression", () => {
271
+ it("should perform linear regression", async () => {
272
+ mockAdapter.executeQuery.mockResolvedValue(
273
+ createMockQueryResult([
274
+ {
275
+ n: 100,
276
+ avg_x: 50,
277
+ avg_y: 60,
278
+ sum_x: 5000,
279
+ sum_y: 6000,
280
+ sum_xy: 310000,
281
+ sum_x2: 260000,
282
+ sum_y2: 370000,
283
+ },
284
+ ]),
285
+ );
286
+
287
+ const tool = tools.find((t) => t.name === "mysql_stats_regression")!;
288
+ const result = await tool.handler(
289
+ {
290
+ table: "data",
291
+ xColumn: "x",
292
+ yColumn: "y",
293
+ },
294
+ mockContext,
295
+ );
296
+
297
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
298
+ expect(result).toHaveProperty("slope");
299
+ expect(result).toHaveProperty("intercept");
300
+ });
301
+ });
302
+
303
+ describe("mysql_stats_sampling", () => {
304
+ it("should return random sample", async () => {
305
+ mockAdapter.executeQuery.mockResolvedValue(
306
+ createMockQueryResult([{ id: 1 }, { id: 5 }, { id: 10 }]),
307
+ );
308
+
309
+ const tool = tools.find((t) => t.name === "mysql_stats_sampling")!;
310
+ const result = await tool.handler(
311
+ {
312
+ table: "users",
313
+ sampleSize: 100,
314
+ },
315
+ mockContext,
316
+ );
317
+
318
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
319
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
320
+ expect(call).toContain("RAND()");
321
+ expect(result).toHaveProperty("sample");
34
322
  });
35
323
 
36
- it('should have inputSchema for all tools', () => {
37
- for (const tool of tools) {
38
- expect(tool.inputSchema).toBeDefined();
39
- }
324
+ it("should accept specific columns", async () => {
325
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
326
+
327
+ const tool = tools.find((t) => t.name === "mysql_stats_sampling")!;
328
+ await tool.handler(
329
+ {
330
+ table: "users",
331
+ sampleSize: 10,
332
+ columns: ["id", "name"],
333
+ },
334
+ mockContext,
335
+ );
336
+
337
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
338
+ expect(call).toContain("`id`");
339
+ expect(call).toContain("`name`");
340
+ });
341
+ });
342
+
343
+ describe("mysql_stats_histogram", () => {
344
+ it("should query histogram data", async () => {
345
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
346
+
347
+ const tool = tools.find((t) => t.name === "mysql_stats_histogram")!;
348
+ const result = await tool.handler(
349
+ {
350
+ table: "orders",
351
+ column: "total",
352
+ },
353
+ mockContext,
354
+ );
355
+
356
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
357
+ expect(result).toBeDefined();
40
358
  });
41
359
 
42
- it('should include expected tool names', () => {
43
- const names = tools.map(t => t.name);
44
- expect(names).toContain('mysql_stats_descriptive');
45
- expect(names).toContain('mysql_stats_percentiles');
46
- expect(names).toContain('mysql_stats_correlation');
47
- expect(names).toContain('mysql_stats_distribution');
48
- expect(names).toContain('mysql_stats_time_series');
49
- expect(names).toContain('mysql_stats_regression');
50
- expect(names).toContain('mysql_stats_sampling');
51
- expect(names).toContain('mysql_stats_histogram');
360
+ it("should create histogram when update is true", async () => {
361
+ mockAdapter.executeQuery.mockResolvedValue(
362
+ createMockQueryResult([{ TABLE_NAME: "orders" }]),
363
+ );
364
+
365
+ const tool = tools.find((t) => t.name === "mysql_stats_histogram")!;
366
+ await tool.handler(
367
+ {
368
+ table: "orders",
369
+ column: "total",
370
+ update: true,
371
+ buckets: 32,
372
+ },
373
+ mockContext,
374
+ );
375
+
376
+ // calls[0] is table existence check, calls[1] is ANALYZE TABLE
377
+ const calls = mockAdapter.executeQuery.mock.calls.map(
378
+ (c) => c[0] as string,
379
+ );
380
+ expect(calls.some((c) => c.includes("ANALYZE TABLE"))).toBe(true);
52
381
  });
53
- });
54
382
 
55
- describe('Handler Execution', () => {
56
- let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
57
- let tools: ReturnType<typeof getStatsTools>;
58
- let mockContext: ReturnType<typeof createMockRequestContext>;
59
-
60
- beforeEach(() => {
61
- vi.clearAllMocks();
62
- mockAdapter = createMockMySQLAdapter();
63
- tools = getStatsTools(mockAdapter as unknown as MySQLAdapter);
64
- mockContext = createMockRequestContext();
65
- });
66
-
67
- describe('mysql_stats_descriptive', () => {
68
- it('should calculate descriptive statistics', async () => {
69
- mockAdapter.executeQuery.mockImplementation(async (query) => {
70
- if (query.includes('COUNT(*) as count')) {
71
- return createMockQueryResult([{ count: 100 }]);
72
- }
73
- if (query.includes('AVG(val) as median')) {
74
- return createMockQueryResult([{ median: 50 }]);
75
- }
76
- return createMockQueryResult([{
77
- count: 100,
78
- mean: 50.5,
79
- min: 1,
80
- max: 100,
81
- range: 99,
82
- stddev: 10,
83
- variance: 100,
84
- sum: 5050
85
- }]);
86
- });
87
-
88
- const tool = tools.find(t => t.name === 'mysql_stats_descriptive')!;
89
- const result = await tool.handler({ table: 'orders', column: 'total' }, mockContext);
90
-
91
- expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(3);
92
-
93
- // Verify all queries were made
94
- const calls = mockAdapter.executeQuery.mock.calls.map(c => c[0] as string);
95
- expect(calls.some(c => c.includes('COUNT(*)'))).toBe(true);
96
- expect(calls.some(c => c.includes('OFFSET'))).toBe(true);
97
- expect(calls.some(c => c.includes('as `range`'))).toBe(true);
98
-
99
- // Returns column, count, mean, median, stddev, etc
100
- expect(result).toHaveProperty('column', 'total');
101
- expect(result).toHaveProperty('count', 100);
102
- expect(result).toHaveProperty('median', 50);
103
- expect(result).toHaveProperty('range', 99);
104
- });
105
-
106
- it('should include where clause in all queries', async () => {
107
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([{ count: 10 }]));
108
-
109
- const tool = tools.find(t => t.name === 'mysql_stats_descriptive')!;
110
- await tool.handler({ table: 'orders', column: 'total', where: 'status = "completed"' }, mockContext);
111
-
112
- // Check that WHERE clause was present in all queries
113
- const calls = mockAdapter.executeQuery.mock.calls.map(c => c[0] as string);
114
- expect(calls.length).toBeGreaterThan(0);
115
- for (const call of calls) {
116
- expect(call).toContain('WHERE status = "completed"');
117
- }
118
- });
119
-
120
- it('should return nulls when count is 0', async () => {
121
- mockAdapter.executeQuery.mockImplementation(async (query) => {
122
- if (query.includes('COUNT(*) as count')) {
123
- return createMockQueryResult([{ count: 0 }]);
124
- }
125
- return createMockQueryResult([]);
126
- });
127
-
128
- const tool = tools.find(t => t.name === 'mysql_stats_descriptive')!;
129
- const result = await tool.handler({ table: 'orders', column: 'total' }, mockContext);
130
-
131
- expect(result).toHaveProperty('count', 0);
132
- expect(result).toHaveProperty('mean', null);
133
- expect(result).toHaveProperty('median', null);
134
- });
135
- });
136
-
137
- describe('mysql_stats_percentiles', () => {
138
- it('should calculate percentiles', async () => {
139
- mockAdapter.executeQuery.mockResolvedValue(
140
- createMockQueryResult([{ cnt: 100 }])
141
- );
142
-
143
- const tool = tools.find(t => t.name === 'mysql_stats_percentiles')!;
144
- const result = await tool.handler({ table: 'orders', column: 'total' }, mockContext);
145
-
146
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
147
- // Returns column, totalCount, percentiles
148
- expect(result).toHaveProperty('totalCount');
149
- expect(result).toHaveProperty('percentiles');
150
- });
151
-
152
- it('should use custom percentiles', async () => {
153
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([{ cnt: 100 }]));
154
-
155
- const tool = tools.find(t => t.name === 'mysql_stats_percentiles')!;
156
- await tool.handler({
157
- table: 'orders',
158
- column: 'total',
159
- percentiles: [10, 50, 90, 99]
160
- }, mockContext);
161
-
162
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
163
- });
164
- });
165
-
166
- describe('mysql_stats_correlation', () => {
167
- it('should calculate correlation coefficient', async () => {
168
- mockAdapter.executeQuery.mockResolvedValue(
169
- createMockQueryResult([{
170
- correlation: 0.85,
171
- sample_size: 100,
172
- mean_x: 50,
173
- mean_y: 60,
174
- std_x: 10,
175
- std_y: 12
176
- }])
177
- );
178
-
179
- const tool = tools.find(t => t.name === 'mysql_stats_correlation')!;
180
- const result = await tool.handler({
181
- table: 'data',
182
- column1: 'height',
183
- column2: 'weight'
184
- }, mockContext);
185
-
186
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
187
- expect(result).toHaveProperty('column1', 'height');
188
- expect(result).toHaveProperty('column2', 'weight');
189
- expect(result).toHaveProperty('correlation');
190
- });
191
- });
192
-
193
- describe('mysql_stats_distribution', () => {
194
- it('should analyze data distribution', async () => {
195
- mockAdapter.executeQuery.mockResolvedValue(
196
- createMockQueryResult([
197
- { min_val: 0, max_val: 100 }
198
- ])
199
- );
200
-
201
- const tool = tools.find(t => t.name === 'mysql_stats_distribution')!;
202
- const result = await tool.handler({
203
- table: 'orders',
204
- column: 'amount',
205
- buckets: 10
206
- }, mockContext);
207
-
208
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
209
- expect(result).toHaveProperty('distribution');
210
- });
211
- });
212
-
213
- describe('mysql_stats_time_series', () => {
214
- it('should compute time series with moving average', async () => {
215
- mockAdapter.executeQuery.mockResolvedValue(
216
- createMockQueryResult([
217
- { period: '2024-01', value: 100 }
218
- ])
219
- );
220
-
221
- const tool = tools.find(t => t.name === 'mysql_stats_time_series')!;
222
- const result = await tool.handler({
223
- table: 'sales',
224
- timeColumn: 'sale_date',
225
- valueColumn: 'amount',
226
- interval: 'month'
227
- }, mockContext);
228
-
229
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
230
- expect(result).toHaveProperty('dataPoints');
231
- });
232
- });
233
-
234
- describe('mysql_stats_regression', () => {
235
- it('should perform linear regression', async () => {
236
- mockAdapter.executeQuery.mockResolvedValue(
237
- createMockQueryResult([{
238
- n: 100,
239
- avg_x: 50,
240
- avg_y: 60,
241
- sum_x: 5000,
242
- sum_y: 6000,
243
- sum_xy: 310000,
244
- sum_x2: 260000,
245
- sum_y2: 370000
246
- }])
247
- );
248
-
249
- const tool = tools.find(t => t.name === 'mysql_stats_regression')!;
250
- const result = await tool.handler({
251
- table: 'data',
252
- xColumn: 'x',
253
- yColumn: 'y'
254
- }, mockContext);
255
-
256
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
257
- expect(result).toHaveProperty('slope');
258
- expect(result).toHaveProperty('intercept');
259
- });
260
- });
261
-
262
- describe('mysql_stats_sampling', () => {
263
- it('should return random sample', async () => {
264
- mockAdapter.executeQuery.mockResolvedValue(
265
- createMockQueryResult([{ id: 1 }, { id: 5 }, { id: 10 }])
266
- );
267
-
268
- const tool = tools.find(t => t.name === 'mysql_stats_sampling')!;
269
- const result = await tool.handler({
270
- table: 'users',
271
- sampleSize: 100
272
- }, mockContext);
273
-
274
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
275
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
276
- expect(call).toContain('RAND()');
277
- expect(result).toHaveProperty('sample');
278
- });
279
-
280
- it('should accept specific columns', async () => {
281
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
282
-
283
- const tool = tools.find(t => t.name === 'mysql_stats_sampling')!;
284
- await tool.handler({
285
- table: 'users',
286
- sampleSize: 10,
287
- columns: ['id', 'name']
288
- }, mockContext);
289
-
290
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
291
- expect(call).toContain('`id`');
292
- expect(call).toContain('`name`');
293
- });
294
- });
295
-
296
- describe('mysql_stats_histogram', () => {
297
- it('should query histogram data', async () => {
298
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
299
-
300
- const tool = tools.find(t => t.name === 'mysql_stats_histogram')!;
301
- const result = await tool.handler({
302
- table: 'orders',
303
- column: 'total'
304
- }, mockContext);
305
-
306
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
307
- expect(result).toBeDefined();
308
- });
309
-
310
- it('should create histogram when update is true', async () => {
311
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
312
-
313
- const tool = tools.find(t => t.name === 'mysql_stats_histogram')!;
314
- await tool.handler({
315
- table: 'orders',
316
- column: 'total',
317
- update: true,
318
- buckets: 32
319
- }, mockContext);
320
-
321
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
322
- expect(call).toContain('ANALYZE TABLE');
323
- });
324
-
325
- it('should return histogram metadata when exists', async () => {
326
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([{
327
- schemaName: 'test',
328
- tableName: 'orders',
329
- columnName: 'total',
330
- histogramType: 'singleton'
331
- }]));
332
-
333
- const tool = tools.find(t => t.name === 'mysql_stats_histogram')!;
334
- const result = await tool.handler({
335
- table: 'orders',
336
- column: 'total'
337
- }, mockContext) as { exists: boolean };
338
-
339
- expect(result.exists).toBe(true);
340
- });
383
+ it("should return histogram metadata when exists", async () => {
384
+ mockAdapter.executeQuery.mockResolvedValue(
385
+ createMockQueryResult([
386
+ {
387
+ schemaName: "test",
388
+ tableName: "orders",
389
+ columnName: "total",
390
+ histogramType: "singleton",
391
+ },
392
+ ]),
393
+ );
394
+
395
+ const tool = tools.find((t) => t.name === "mysql_stats_histogram")!;
396
+ const result = (await tool.handler(
397
+ {
398
+ table: "orders",
399
+ column: "total",
400
+ },
401
+ mockContext,
402
+ )) as { exists: boolean };
403
+
404
+ expect(result.exists).toBe(true);
341
405
  });
406
+ });
342
407
  });
343
408
 
344
- describe('Stats Validation Errors', () => {
345
- let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
346
- let tools: ReturnType<typeof getStatsTools>;
347
- let mockContext: ReturnType<typeof createMockRequestContext>;
348
-
349
- beforeEach(() => {
350
- vi.clearAllMocks();
351
- mockAdapter = createMockMySQLAdapter();
352
- tools = getStatsTools(mockAdapter as unknown as MySQLAdapter);
353
- mockContext = createMockRequestContext();
354
- });
355
-
356
- describe('mysql_stats_descriptive', () => {
357
- it('should reject invalid table name', async () => {
358
- const tool = tools.find(t => t.name === 'mysql_stats_descriptive')!;
359
- await expect(tool.handler({
360
- table: '123-invalid',
361
- column: 'total'
362
- }, mockContext)).rejects.toThrow('Invalid table name');
363
- });
364
-
365
- it('should reject invalid column name', async () => {
366
- const tool = tools.find(t => t.name === 'mysql_stats_descriptive')!;
367
- await expect(tool.handler({
368
- table: 'orders',
369
- column: '123-bad'
370
- }, mockContext)).rejects.toThrow('Invalid column name');
371
- });
372
- });
373
-
374
- describe('mysql_stats_percentiles', () => {
375
- it('should reject invalid table name', async () => {
376
- const tool = tools.find(t => t.name === 'mysql_stats_percentiles')!;
377
- await expect(tool.handler({
378
- table: '123-invalid',
379
- column: 'amount'
380
- }, mockContext)).rejects.toThrow('Invalid table name');
381
- });
382
-
383
- it('should reject invalid column name', async () => {
384
- const tool = tools.find(t => t.name === 'mysql_stats_percentiles')!;
385
- await expect(tool.handler({
386
- table: 'orders',
387
- column: 'bad-col'
388
- }, mockContext)).rejects.toThrow('Invalid column name');
389
- });
390
-
391
- it('should return empty percentiles when table is empty', async () => {
392
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([{ cnt: 0 }]));
393
-
394
- const tool = tools.find(t => t.name === 'mysql_stats_percentiles')!;
395
- const result = await tool.handler({
396
- table: 'empty_table',
397
- column: 'value'
398
- }, mockContext) as { totalCount: number };
399
-
400
- expect(result.totalCount).toBe(0);
401
- });
402
- });
403
-
404
- describe('mysql_stats_correlation', () => {
405
- it('should reject invalid table name', async () => {
406
- const tool = tools.find(t => t.name === 'mysql_stats_correlation')!;
407
- await expect(tool.handler({
408
- table: '123-bad',
409
- column1: 'x',
410
- column2: 'y'
411
- }, mockContext)).rejects.toThrow('Invalid table name');
412
- });
413
-
414
- it('should reject invalid column names', async () => {
415
- const tool = tools.find(t => t.name === 'mysql_stats_correlation')!;
416
- await expect(tool.handler({
417
- table: 'data',
418
- column1: 'bad-col',
419
- column2: 'y'
420
- }, mockContext)).rejects.toThrow('Invalid column name');
421
- });
422
- });
423
-
424
- describe('mysql_stats_distribution', () => {
425
- it('should reject invalid table name', async () => {
426
- const tool = tools.find(t => t.name === 'mysql_stats_distribution')!;
427
- await expect(tool.handler({
428
- table: '123-bad',
429
- column: 'amount'
430
- }, mockContext)).rejects.toThrow('Invalid table name');
431
- });
432
-
433
- it('should reject invalid column name', async () => {
434
- const tool = tools.find(t => t.name === 'mysql_stats_distribution')!;
435
- await expect(tool.handler({
436
- table: 'orders',
437
- column: 'bad-col'
438
- }, mockContext)).rejects.toThrow('Invalid column name');
439
- });
440
-
441
- it('should handle same min/max values', async () => {
442
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([
443
- { min_val: 50, max_val: 50 }
444
- ]));
445
-
446
- const tool = tools.find(t => t.name === 'mysql_stats_distribution')!;
447
- const result = await tool.handler({
448
- table: 'constant',
449
- column: 'val'
450
- }, mockContext) as { bucketCount: number };
451
-
452
- expect(result.bucketCount).toBe(1);
453
- });
454
- });
455
-
456
- describe('mysql_stats_time_series', () => {
457
- it('should reject invalid table name', async () => {
458
- const tool = tools.find(t => t.name === 'mysql_stats_time_series')!;
459
- await expect(tool.handler({
460
- table: '123-bad',
461
- valueColumn: 'amount',
462
- timeColumn: 'created_at'
463
- }, mockContext)).rejects.toThrow('Invalid table name');
464
- });
465
-
466
- it('should reject invalid column names', async () => {
467
- const tool = tools.find(t => t.name === 'mysql_stats_time_series')!;
468
- await expect(tool.handler({
469
- table: 'sales',
470
- valueColumn: 'bad-col',
471
- timeColumn: 'created_at'
472
- }, mockContext)).rejects.toThrow('Invalid column name');
473
- });
474
-
475
- it('should use different interval formats', async () => {
476
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
477
-
478
- const tool = tools.find(t => t.name === 'mysql_stats_time_series')!;
479
-
480
- await tool.handler({
481
- table: 'metrics',
482
- valueColumn: 'value',
483
- timeColumn: 'ts',
484
- interval: 'minute'
485
- }, mockContext);
486
-
487
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
488
- expect(call).toContain('%H:%i');
489
- });
490
- });
491
-
492
- describe('mysql_stats_regression', () => {
493
- it('should reject invalid table name', async () => {
494
- const tool = tools.find(t => t.name === 'mysql_stats_regression')!;
495
- await expect(tool.handler({
496
- table: '123-bad',
497
- xColumn: 'x',
498
- yColumn: 'y'
499
- }, mockContext)).rejects.toThrow('Invalid table name');
500
- });
501
-
502
- it('should reject invalid column names', async () => {
503
- const tool = tools.find(t => t.name === 'mysql_stats_regression')!;
504
- await expect(tool.handler({
505
- table: 'data',
506
- xColumn: 'bad-x',
507
- yColumn: 'y'
508
- }, mockContext)).rejects.toThrow('Invalid column name');
509
- });
510
-
511
- it('should return error for insufficient data points', async () => {
512
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([{
513
- n: 1, sum_x: 1, sum_y: 1
514
- }]));
515
-
516
- const tool = tools.find(t => t.name === 'mysql_stats_regression')!;
517
- const result = await tool.handler({
518
- table: 'small_data',
519
- xColumn: 'x',
520
- yColumn: 'y'
521
- }, mockContext) as { error: string };
522
-
523
- expect(result.error).toContain('Insufficient');
524
- });
525
- });
526
-
527
- describe('mysql_stats_sampling', () => {
528
- it('should reject invalid table name', async () => {
529
- const tool = tools.find(t => t.name === 'mysql_stats_sampling')!;
530
- await expect(tool.handler({
531
- table: '123-bad',
532
- sampleSize: 10
533
- }, mockContext)).rejects.toThrow('Invalid table name');
534
- });
535
-
536
- it('should reject invalid column names', async () => {
537
- const tool = tools.find(t => t.name === 'mysql_stats_sampling')!;
538
- await expect(tool.handler({
539
- table: 'users',
540
- sampleSize: 10,
541
- columns: ['valid', 'bad-column']
542
- }, mockContext)).rejects.toThrow('Invalid column name');
543
- });
544
-
545
- it('should use seed for reproducibility', async () => {
546
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
547
-
548
- const tool = tools.find(t => t.name === 'mysql_stats_sampling')!;
549
- await tool.handler({
550
- table: 'users',
551
- sampleSize: 10,
552
- seed: 42
553
- }, mockContext);
554
-
555
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
556
- expect(call).toContain('RAND(42)');
557
- });
558
- });
559
-
560
- describe('mysql_stats_histogram', () => {
561
- it('should reject invalid table name', async () => {
562
- const tool = tools.find(t => t.name === 'mysql_stats_histogram')!;
563
- await expect(tool.handler({
564
- table: '123-bad',
565
- column: 'amount'
566
- }, mockContext)).rejects.toThrow('Invalid table name');
567
- });
568
-
569
- it('should reject invalid column name', async () => {
570
- const tool = tools.find(t => t.name === 'mysql_stats_histogram')!;
571
- await expect(tool.handler({
572
- table: 'orders',
573
- column: 'bad-col'
574
- }, mockContext)).rejects.toThrow('Invalid column name');
575
- });
409
+ describe("Stats Validation Errors", () => {
410
+ let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
411
+ let tools: ReturnType<typeof getStatsTools>;
412
+ let mockContext: ReturnType<typeof createMockRequestContext>;
413
+
414
+ beforeEach(() => {
415
+ vi.clearAllMocks();
416
+ mockAdapter = createMockMySQLAdapter();
417
+ tools = getStatsTools(mockAdapter as unknown as MySQLAdapter);
418
+ mockContext = createMockRequestContext();
419
+ });
420
+
421
+ describe("mysql_stats_descriptive", () => {
422
+ it("should reject invalid table name", async () => {
423
+ const tool = tools.find((t) => t.name === "mysql_stats_descriptive")!;
424
+ await expect(
425
+ tool.handler(
426
+ {
427
+ table: "123-invalid",
428
+ column: "total",
429
+ },
430
+ mockContext,
431
+ ),
432
+ ).rejects.toThrow("Invalid table name");
433
+ });
434
+
435
+ it("should reject invalid column name", async () => {
436
+ const tool = tools.find((t) => t.name === "mysql_stats_descriptive")!;
437
+ await expect(
438
+ tool.handler(
439
+ {
440
+ table: "orders",
441
+ column: "123-bad",
442
+ },
443
+ mockContext,
444
+ ),
445
+ ).rejects.toThrow("Invalid column name");
446
+ });
447
+ });
448
+
449
+ describe("mysql_stats_percentiles", () => {
450
+ it("should reject invalid table name", async () => {
451
+ const tool = tools.find((t) => t.name === "mysql_stats_percentiles")!;
452
+ await expect(
453
+ tool.handler(
454
+ {
455
+ table: "123-invalid",
456
+ column: "amount",
457
+ },
458
+ mockContext,
459
+ ),
460
+ ).rejects.toThrow("Invalid table name");
461
+ });
462
+
463
+ it("should reject invalid column name", async () => {
464
+ const tool = tools.find((t) => t.name === "mysql_stats_percentiles")!;
465
+ await expect(
466
+ tool.handler(
467
+ {
468
+ table: "orders",
469
+ column: "bad-col",
470
+ },
471
+ mockContext,
472
+ ),
473
+ ).rejects.toThrow("Invalid column name");
474
+ });
475
+
476
+ it("should return empty percentiles when table is empty", async () => {
477
+ mockAdapter.executeQuery.mockResolvedValue(
478
+ createMockQueryResult([{ cnt: 0 }]),
479
+ );
480
+
481
+ const tool = tools.find((t) => t.name === "mysql_stats_percentiles")!;
482
+ const result = (await tool.handler(
483
+ {
484
+ table: "empty_table",
485
+ column: "value",
486
+ },
487
+ mockContext,
488
+ )) as { totalCount: number };
489
+
490
+ expect(result.totalCount).toBe(0);
491
+ });
492
+ });
493
+
494
+ describe("mysql_stats_correlation", () => {
495
+ it("should reject invalid table name", async () => {
496
+ const tool = tools.find((t) => t.name === "mysql_stats_correlation")!;
497
+ await expect(
498
+ tool.handler(
499
+ {
500
+ table: "123-bad",
501
+ column1: "x",
502
+ column2: "y",
503
+ },
504
+ mockContext,
505
+ ),
506
+ ).rejects.toThrow("Invalid table name");
507
+ });
508
+
509
+ it("should reject invalid column names", async () => {
510
+ const tool = tools.find((t) => t.name === "mysql_stats_correlation")!;
511
+ await expect(
512
+ tool.handler(
513
+ {
514
+ table: "data",
515
+ column1: "bad-col",
516
+ column2: "y",
517
+ },
518
+ mockContext,
519
+ ),
520
+ ).rejects.toThrow("Invalid column name");
521
+ });
522
+ });
523
+
524
+ describe("mysql_stats_distribution", () => {
525
+ it("should reject invalid table name", async () => {
526
+ const tool = tools.find((t) => t.name === "mysql_stats_distribution")!;
527
+ await expect(
528
+ tool.handler(
529
+ {
530
+ table: "123-bad",
531
+ column: "amount",
532
+ },
533
+ mockContext,
534
+ ),
535
+ ).rejects.toThrow("Invalid table name");
536
+ });
537
+
538
+ it("should reject invalid column name", async () => {
539
+ const tool = tools.find((t) => t.name === "mysql_stats_distribution")!;
540
+ await expect(
541
+ tool.handler(
542
+ {
543
+ table: "orders",
544
+ column: "bad-col",
545
+ },
546
+ mockContext,
547
+ ),
548
+ ).rejects.toThrow("Invalid column name");
549
+ });
550
+
551
+ it("should handle same min/max values", async () => {
552
+ mockAdapter.executeQuery.mockResolvedValue(
553
+ createMockQueryResult([{ min_val: 50, max_val: 50 }]),
554
+ );
555
+
556
+ const tool = tools.find((t) => t.name === "mysql_stats_distribution")!;
557
+ const result = (await tool.handler(
558
+ {
559
+ table: "constant",
560
+ column: "val",
561
+ },
562
+ mockContext,
563
+ )) as { bucketCount: number };
564
+
565
+ expect(result.bucketCount).toBe(1);
566
+ });
567
+ });
568
+
569
+ describe("mysql_stats_time_series", () => {
570
+ it("should reject invalid table name", async () => {
571
+ const tool = tools.find((t) => t.name === "mysql_stats_time_series")!;
572
+ await expect(
573
+ tool.handler(
574
+ {
575
+ table: "123-bad",
576
+ valueColumn: "amount",
577
+ timeColumn: "created_at",
578
+ },
579
+ mockContext,
580
+ ),
581
+ ).rejects.toThrow("Invalid table name");
582
+ });
583
+
584
+ it("should reject invalid column names", async () => {
585
+ const tool = tools.find((t) => t.name === "mysql_stats_time_series")!;
586
+ await expect(
587
+ tool.handler(
588
+ {
589
+ table: "sales",
590
+ valueColumn: "bad-col",
591
+ timeColumn: "created_at",
592
+ },
593
+ mockContext,
594
+ ),
595
+ ).rejects.toThrow("Invalid column name");
596
+ });
597
+
598
+ it("should use different interval formats", async () => {
599
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
600
+
601
+ const tool = tools.find((t) => t.name === "mysql_stats_time_series")!;
602
+
603
+ await tool.handler(
604
+ {
605
+ table: "metrics",
606
+ valueColumn: "value",
607
+ timeColumn: "ts",
608
+ interval: "minute",
609
+ },
610
+ mockContext,
611
+ );
612
+
613
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
614
+ expect(call).toContain("%H:%i");
615
+ });
616
+ });
617
+
618
+ describe("mysql_stats_regression", () => {
619
+ it("should reject invalid table name", async () => {
620
+ const tool = tools.find((t) => t.name === "mysql_stats_regression")!;
621
+ await expect(
622
+ tool.handler(
623
+ {
624
+ table: "123-bad",
625
+ xColumn: "x",
626
+ yColumn: "y",
627
+ },
628
+ mockContext,
629
+ ),
630
+ ).rejects.toThrow("Invalid table name");
631
+ });
632
+
633
+ it("should reject invalid column names", async () => {
634
+ const tool = tools.find((t) => t.name === "mysql_stats_regression")!;
635
+ await expect(
636
+ tool.handler(
637
+ {
638
+ table: "data",
639
+ xColumn: "bad-x",
640
+ yColumn: "y",
641
+ },
642
+ mockContext,
643
+ ),
644
+ ).rejects.toThrow("Invalid column name");
645
+ });
646
+
647
+ it("should return error for insufficient data points", async () => {
648
+ mockAdapter.executeQuery.mockResolvedValue(
649
+ createMockQueryResult([
650
+ {
651
+ n: 1,
652
+ sum_x: 1,
653
+ sum_y: 1,
654
+ },
655
+ ]),
656
+ );
657
+
658
+ const tool = tools.find((t) => t.name === "mysql_stats_regression")!;
659
+ const result = (await tool.handler(
660
+ {
661
+ table: "small_data",
662
+ xColumn: "x",
663
+ yColumn: "y",
664
+ },
665
+ mockContext,
666
+ )) as { error: string };
667
+
668
+ expect(result.error).toContain("Insufficient");
669
+ });
670
+ });
671
+
672
+ describe("mysql_stats_sampling", () => {
673
+ it("should reject invalid table name", async () => {
674
+ const tool = tools.find((t) => t.name === "mysql_stats_sampling")!;
675
+ await expect(
676
+ tool.handler(
677
+ {
678
+ table: "123-bad",
679
+ sampleSize: 10,
680
+ },
681
+ mockContext,
682
+ ),
683
+ ).rejects.toThrow("Invalid table name");
576
684
  });
685
+
686
+ it("should reject invalid column names", async () => {
687
+ const tool = tools.find((t) => t.name === "mysql_stats_sampling")!;
688
+ await expect(
689
+ tool.handler(
690
+ {
691
+ table: "users",
692
+ sampleSize: 10,
693
+ columns: ["valid", "bad-column"],
694
+ },
695
+ mockContext,
696
+ ),
697
+ ).rejects.toThrow("Invalid column name");
698
+ });
699
+
700
+ it("should use seed for reproducibility", async () => {
701
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
702
+
703
+ const tool = tools.find((t) => t.name === "mysql_stats_sampling")!;
704
+ await tool.handler(
705
+ {
706
+ table: "users",
707
+ sampleSize: 10,
708
+ seed: 42,
709
+ },
710
+ mockContext,
711
+ );
712
+
713
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
714
+ expect(call).toContain("RAND(42)");
715
+ });
716
+ });
717
+
718
+ describe("mysql_stats_histogram", () => {
719
+ it("should reject invalid table name", async () => {
720
+ const tool = tools.find((t) => t.name === "mysql_stats_histogram")!;
721
+ await expect(
722
+ tool.handler(
723
+ {
724
+ table: "123-bad",
725
+ column: "amount",
726
+ },
727
+ mockContext,
728
+ ),
729
+ ).rejects.toThrow("Invalid table name");
730
+ });
731
+
732
+ it("should reject invalid column name", async () => {
733
+ const tool = tools.find((t) => t.name === "mysql_stats_histogram")!;
734
+ await expect(
735
+ tool.handler(
736
+ {
737
+ table: "orders",
738
+ column: "bad-col",
739
+ },
740
+ mockContext,
741
+ ),
742
+ ).rejects.toThrow("Invalid column name");
743
+ });
744
+ });
745
+ });
746
+
747
+ describe("Stats Nonexistent Table Handling", () => {
748
+ let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
749
+ let tools: ReturnType<typeof getStatsTools>;
750
+ let mockContext: ReturnType<typeof createMockRequestContext>;
751
+
752
+ beforeEach(() => {
753
+ vi.clearAllMocks();
754
+ mockAdapter = createMockMySQLAdapter();
755
+ tools = getStatsTools(mockAdapter as unknown as MySQLAdapter);
756
+ mockContext = createMockRequestContext();
757
+ });
758
+
759
+ const tableDoesNotExistError = new Error(
760
+ "Table 'testdb.nonexistent' doesn't exist",
761
+ );
762
+
763
+ it("mysql_stats_descriptive returns exists:false for nonexistent table", async () => {
764
+ mockAdapter.executeQuery.mockRejectedValue(tableDoesNotExistError);
765
+
766
+ const tool = tools.find((t) => t.name === "mysql_stats_descriptive")!;
767
+ const result = (await tool.handler(
768
+ { table: "nonexistent", column: "val" },
769
+ mockContext,
770
+ )) as { exists: boolean; table: string };
771
+
772
+ expect(result.exists).toBe(false);
773
+ expect(result.table).toBe("nonexistent");
774
+ });
775
+
776
+ it("mysql_stats_percentiles returns exists:false for nonexistent table", async () => {
777
+ mockAdapter.executeQuery.mockRejectedValue(tableDoesNotExistError);
778
+
779
+ const tool = tools.find((t) => t.name === "mysql_stats_percentiles")!;
780
+ const result = (await tool.handler(
781
+ { table: "nonexistent", column: "val" },
782
+ mockContext,
783
+ )) as { exists: boolean; table: string };
784
+
785
+ expect(result.exists).toBe(false);
786
+ expect(result.table).toBe("nonexistent");
787
+ });
788
+
789
+ it("mysql_stats_correlation returns exists:false for nonexistent table", async () => {
790
+ mockAdapter.executeQuery.mockRejectedValue(tableDoesNotExistError);
791
+
792
+ const tool = tools.find((t) => t.name === "mysql_stats_correlation")!;
793
+ const result = (await tool.handler(
794
+ { table: "nonexistent", column1: "x", column2: "y" },
795
+ mockContext,
796
+ )) as { exists: boolean; table: string };
797
+
798
+ expect(result.exists).toBe(false);
799
+ expect(result.table).toBe("nonexistent");
800
+ });
801
+
802
+ it("mysql_stats_distribution returns exists:false for nonexistent table", async () => {
803
+ mockAdapter.executeQuery.mockRejectedValue(tableDoesNotExistError);
804
+
805
+ const tool = tools.find((t) => t.name === "mysql_stats_distribution")!;
806
+ const result = (await tool.handler(
807
+ { table: "nonexistent", column: "val" },
808
+ mockContext,
809
+ )) as { exists: boolean; table: string };
810
+
811
+ expect(result.exists).toBe(false);
812
+ expect(result.table).toBe("nonexistent");
813
+ });
814
+
815
+ it("mysql_stats_time_series returns exists:false for nonexistent table", async () => {
816
+ mockAdapter.executeQuery.mockRejectedValue(tableDoesNotExistError);
817
+
818
+ const tool = tools.find((t) => t.name === "mysql_stats_time_series")!;
819
+ const result = (await tool.handler(
820
+ {
821
+ table: "nonexistent",
822
+ valueColumn: "val",
823
+ timeColumn: "ts",
824
+ },
825
+ mockContext,
826
+ )) as { exists: boolean; table: string };
827
+
828
+ expect(result.exists).toBe(false);
829
+ expect(result.table).toBe("nonexistent");
830
+ });
831
+
832
+ it("mysql_stats_regression returns exists:false for nonexistent table", async () => {
833
+ mockAdapter.executeQuery.mockRejectedValue(tableDoesNotExistError);
834
+
835
+ const tool = tools.find((t) => t.name === "mysql_stats_regression")!;
836
+ const result = (await tool.handler(
837
+ { table: "nonexistent", xColumn: "x", yColumn: "y" },
838
+ mockContext,
839
+ )) as { exists: boolean; table: string };
840
+
841
+ expect(result.exists).toBe(false);
842
+ expect(result.table).toBe("nonexistent");
843
+ });
844
+
845
+ it("mysql_stats_sampling returns exists:false for nonexistent table", async () => {
846
+ mockAdapter.executeQuery.mockRejectedValue(tableDoesNotExistError);
847
+
848
+ const tool = tools.find((t) => t.name === "mysql_stats_sampling")!;
849
+ const result = (await tool.handler(
850
+ { table: "nonexistent", sampleSize: 10 },
851
+ mockContext,
852
+ )) as { exists: boolean; table: string };
853
+
854
+ expect(result.exists).toBe(false);
855
+ expect(result.table).toBe("nonexistent");
856
+ });
857
+
858
+ it("mysql_stats_histogram returns exists:false for nonexistent table", async () => {
859
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
860
+
861
+ const tool = tools.find((t) => t.name === "mysql_stats_histogram")!;
862
+ const result = (await tool.handler(
863
+ { table: "nonexistent", column: "val" },
864
+ mockContext,
865
+ )) as { exists: boolean; table: string };
866
+
867
+ expect(result.exists).toBe(false);
868
+ expect(result.table).toBe("nonexistent");
869
+ });
870
+
871
+ it("mysql_stats_descriptive returns success:false for unknown column", async () => {
872
+ mockAdapter.executeQuery.mockRejectedValue(
873
+ new Error("Unknown column 'bad_col' in 'field list'"),
874
+ );
875
+
876
+ const tool = tools.find((t) => t.name === "mysql_stats_descriptive")!;
877
+ const result = (await tool.handler(
878
+ { table: "orders", column: "bad_col" },
879
+ mockContext,
880
+ )) as { success: boolean; error: string };
881
+
882
+ expect(result.success).toBe(false);
883
+ expect(result.error).toContain("Unknown column");
884
+ });
577
885
  });