@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,459 +1,828 @@
1
1
  /**
2
2
  * mysql-mcp - DocStore Tools Unit Tests
3
- *
3
+ *
4
4
  * Tests for document store tool definitions and handler execution.
5
5
  */
6
6
 
7
- import { describe, it, expect, vi, beforeEach } from 'vitest';
8
- import { getDocStoreTools } from '../docstore.js';
9
- import type { MySQLAdapter } from '../../MySQLAdapter.js';
10
- import { createMockMySQLAdapter, createMockRequestContext, createMockQueryResult } from '../../../../__tests__/mocks/index.js';
7
+ import { describe, it, expect, vi, beforeEach } from "vitest";
8
+ import { getDocStoreTools } from "../docstore.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("getDocStoreTools", () => {
17
+ let tools: ReturnType<typeof getDocStoreTools>;
18
+
19
+ beforeEach(() => {
20
+ vi.clearAllMocks();
21
+ tools = getDocStoreTools(
22
+ createMockMySQLAdapter() as unknown as MySQLAdapter,
23
+ );
24
+ });
25
+
26
+ it("should return 9 docstore tools", () => {
27
+ expect(tools).toHaveLength(9);
28
+ });
29
+
30
+ it("should have docstore group for all tools", () => {
31
+ for (const tool of tools) {
32
+ expect(tool.group).toBe("docstore");
33
+ }
34
+ });
35
+
36
+ it("should have handler functions for all tools", () => {
37
+ for (const tool of tools) {
38
+ expect(typeof tool.handler).toBe("function");
39
+ }
40
+ });
41
+
42
+ it("should have inputSchema for all tools", () => {
43
+ for (const tool of tools) {
44
+ expect(tool.inputSchema).toBeDefined();
45
+ }
46
+ });
47
+
48
+ it("should include expected tool names", () => {
49
+ const toolNames = tools.map((t) => t.name);
50
+ expect(toolNames).toContain("mysql_doc_list_collections");
51
+ expect(toolNames).toContain("mysql_doc_create_collection");
52
+ expect(toolNames).toContain("mysql_doc_drop_collection");
53
+ expect(toolNames).toContain("mysql_doc_find");
54
+ expect(toolNames).toContain("mysql_doc_add");
55
+ expect(toolNames).toContain("mysql_doc_modify");
56
+ expect(toolNames).toContain("mysql_doc_remove");
57
+ expect(toolNames).toContain("mysql_doc_create_index");
58
+ expect(toolNames).toContain("mysql_doc_collection_info");
59
+ });
60
+ });
11
61
 
12
- describe('getDocStoreTools', () => {
13
- let tools: ReturnType<typeof getDocStoreTools>;
62
+ describe("Handler Execution", () => {
63
+ let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
64
+ let tools: ReturnType<typeof getDocStoreTools>;
65
+ let mockContext: ReturnType<typeof createMockRequestContext>;
66
+
67
+ beforeEach(() => {
68
+ vi.clearAllMocks();
69
+ mockAdapter = createMockMySQLAdapter();
70
+ tools = getDocStoreTools(mockAdapter as unknown as MySQLAdapter);
71
+ mockContext = createMockRequestContext();
72
+ });
73
+
74
+ describe("mysql_doc_list_collections", () => {
75
+ it("should list document collections", async () => {
76
+ mockAdapter.executeQuery.mockResolvedValue(
77
+ createMockQueryResult([{ name: "users_collection", rowCount: 100 }]),
78
+ );
79
+
80
+ const tool = tools.find((t) => t.name === "mysql_doc_list_collections")!;
81
+ const result = await tool.handler({}, mockContext);
82
+
83
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
84
+ expect(result).toHaveProperty("collections");
85
+ expect(result).toHaveProperty("count");
86
+ });
14
87
 
15
- beforeEach(() => {
16
- vi.clearAllMocks();
17
- tools = getDocStoreTools(createMockMySQLAdapter() as unknown as MySQLAdapter);
88
+ it("should filter by schema", async () => {
89
+ mockAdapter.executeQuery
90
+ .mockResolvedValueOnce(createMockQueryResult([{ SCHEMA_NAME: "mydb" }])) // schema exists
91
+ .mockResolvedValueOnce(createMockQueryResult([])); // collections query
92
+
93
+ const tool = tools.find((t) => t.name === "mysql_doc_list_collections")!;
94
+ await tool.handler({ schema: "mydb" }, mockContext);
95
+
96
+ // First call: schema existence check
97
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(2);
98
+ expect(mockAdapter.executeQuery).toHaveBeenNthCalledWith(
99
+ 1,
100
+ expect.stringContaining("SCHEMATA"),
101
+ ["mydb"],
102
+ );
103
+ // Second call: collections query with schema params
104
+ expect(mockAdapter.executeQuery).toHaveBeenNthCalledWith(
105
+ 2,
106
+ expect.any(String),
107
+ ["mydb", "mydb"],
108
+ );
18
109
  });
19
110
 
20
- it('should return 9 docstore tools', () => {
21
- expect(tools).toHaveLength(9);
111
+ it("should return exists: false for nonexistent schema", async () => {
112
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // schema does not exist
113
+
114
+ const tool = tools.find((t) => t.name === "mysql_doc_list_collections")!;
115
+ const result = await tool.handler(
116
+ { schema: "nonexistent_schema" },
117
+ mockContext,
118
+ );
119
+
120
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
121
+ expect(result).toEqual({
122
+ exists: false,
123
+ schema: "nonexistent_schema",
124
+ });
22
125
  });
126
+ });
127
+
128
+ describe("mysql_doc_create_collection", () => {
129
+ it("should create a new collection", async () => {
130
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
23
131
 
24
- it('should have docstore group for all tools', () => {
25
- for (const tool of tools) {
26
- expect(tool.group).toBe('docstore');
27
- }
132
+ const tool = tools.find((t) => t.name === "mysql_doc_create_collection")!;
133
+ const result = await tool.handler({ name: "products" }, mockContext);
134
+
135
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
136
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
137
+ expect(call).toContain("CREATE TABLE");
138
+ expect(call).toContain("doc JSON");
139
+ expect(result).toHaveProperty("success", true);
140
+ expect(result).toHaveProperty("collection", "products");
28
141
  });
29
142
 
30
- it('should have handler functions for all tools', () => {
31
- for (const tool of tools) {
32
- expect(typeof tool.handler).toBe('function');
33
- }
143
+ it("should reject invalid collection names", async () => {
144
+ const tool = tools.find((t) => t.name === "mysql_doc_create_collection")!;
145
+
146
+ await expect(
147
+ tool.handler({ name: "invalid-name" }, mockContext),
148
+ ).rejects.toThrow("Invalid collection name");
34
149
  });
35
150
 
36
- it('should have inputSchema for all tools', () => {
37
- for (const tool of tools) {
38
- expect(tool.inputSchema).toBeDefined();
39
- }
151
+ it("should add validation when specified", async () => {
152
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
153
+
154
+ const tool = tools.find((t) => t.name === "mysql_doc_create_collection")!;
155
+ await tool.handler(
156
+ {
157
+ name: "validated_docs",
158
+ validation: { level: "STRICT", schema: { type: "object" } },
159
+ },
160
+ mockContext,
161
+ );
162
+
163
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
164
+ expect(call).toContain("JSON_SCHEMA_VALID");
40
165
  });
41
166
 
42
- it('should include expected tool names', () => {
43
- const toolNames = tools.map(t => t.name);
44
- expect(toolNames).toContain('mysql_doc_list_collections');
45
- expect(toolNames).toContain('mysql_doc_create_collection');
46
- expect(toolNames).toContain('mysql_doc_drop_collection');
47
- expect(toolNames).toContain('mysql_doc_find');
48
- expect(toolNames).toContain('mysql_doc_add');
49
- expect(toolNames).toContain('mysql_doc_modify');
50
- expect(toolNames).toContain('mysql_doc_remove');
51
- expect(toolNames).toContain('mysql_doc_create_index');
52
- expect(toolNames).toContain('mysql_doc_collection_info');
167
+ it("should use default validation level when not specified", async () => {
168
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
169
+
170
+ const tool = tools.find((t) => t.name === "mysql_doc_create_collection")!;
171
+ await tool.handler({ name: "default_val" }, mockContext);
172
+
173
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
174
+ expect(call).not.toContain("JSON_SCHEMA_VALID");
53
175
  });
54
- });
55
176
 
56
- describe('Handler Execution', () => {
57
- let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
58
- let tools: ReturnType<typeof getDocStoreTools>;
59
- let mockContext: ReturnType<typeof createMockRequestContext>;
177
+ it("should support ifNotExists parameter", async () => {
178
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
179
+
180
+ const tool = tools.find((t) => t.name === "mysql_doc_create_collection")!;
181
+ await tool.handler(
182
+ { name: "my_collection", ifNotExists: true },
183
+ mockContext,
184
+ );
185
+
186
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
187
+ expect(call).toContain("CREATE TABLE IF NOT EXISTS");
188
+ });
189
+
190
+ it("should not use IF NOT EXISTS by default", async () => {
191
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
192
+
193
+ const tool = tools.find((t) => t.name === "mysql_doc_create_collection")!;
194
+ await tool.handler({ name: "my_collection" }, mockContext);
195
+
196
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
197
+ expect(call).toContain("CREATE TABLE `my_collection`");
198
+ expect(call).not.toContain("IF NOT EXISTS");
199
+ });
200
+
201
+ it("should return graceful error when collection already exists", async () => {
202
+ mockAdapter.executeQuery.mockRejectedValue(
203
+ new Error("Table 'my_collection' already exists"),
204
+ );
205
+
206
+ const tool = tools.find((t) => t.name === "mysql_doc_create_collection")!;
207
+ const result = (await tool.handler(
208
+ { name: "my_collection" },
209
+ mockContext,
210
+ )) as { success: boolean; reason: string };
211
+
212
+ expect(result).toHaveProperty("success", false);
213
+ expect(result).toHaveProperty(
214
+ "reason",
215
+ "Collection 'my_collection' already exists",
216
+ );
217
+ });
218
+ });
219
+
220
+ describe("mysql_doc_drop_collection", () => {
221
+ it("should drop collection with IF EXISTS by default", async () => {
222
+ mockAdapter.executeQuery
223
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // pre-check: collection exists
224
+ .mockResolvedValueOnce(createMockQueryResult([])); // DROP TABLE
225
+
226
+ const tool = tools.find((t) => t.name === "mysql_doc_drop_collection")!;
227
+ const result = await tool.handler({ name: "users" }, mockContext);
228
+
229
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(2);
230
+ const dropCall = mockAdapter.executeQuery.mock.calls[1][0] as string;
231
+ expect(dropCall).toContain("DROP TABLE IF EXISTS `users`");
232
+ expect(result).toHaveProperty("success", true);
233
+ expect(result).not.toHaveProperty("message");
234
+ });
235
+
236
+ it("should return informative message when collection did not exist with ifExists", async () => {
237
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // pre-check: collection does not exist
238
+
239
+ const tool = tools.find((t) => t.name === "mysql_doc_drop_collection")!;
240
+ const result = (await tool.handler(
241
+ { name: "nonexistent" },
242
+ mockContext,
243
+ )) as { success: boolean; collection: string; message: string };
244
+
245
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
246
+ expect(result).toHaveProperty("success", true);
247
+ expect(result).toHaveProperty("collection", "nonexistent");
248
+ expect(result).toHaveProperty("message", "Collection did not exist");
249
+ });
250
+
251
+ it("should drop collection without IF EXISTS when requested", async () => {
252
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
253
+
254
+ const tool = tools.find((t) => t.name === "mysql_doc_drop_collection")!;
255
+ await tool.handler({ name: "users", ifExists: false }, mockContext);
256
+
257
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
258
+ expect(call).toBe("DROP TABLE `users`");
259
+ });
260
+
261
+ it("should reject invalid collection names", async () => {
262
+ const tool = tools.find((t) => t.name === "mysql_doc_drop_collection")!;
263
+ await expect(
264
+ tool.handler({ name: "bad;drop table users" }, mockContext),
265
+ ).rejects.toThrow("Invalid collection name");
266
+ });
267
+
268
+ it("should return graceful error when collection does not exist", async () => {
269
+ mockAdapter.executeQuery.mockRejectedValue(
270
+ new Error("Unknown table 'testdb.nonexistent'"),
271
+ );
272
+
273
+ const tool = tools.find((t) => t.name === "mysql_doc_drop_collection")!;
274
+ const result = (await tool.handler(
275
+ { name: "nonexistent", ifExists: false },
276
+ mockContext,
277
+ )) as { success: boolean; reason: string };
278
+
279
+ expect(result).toHaveProperty("success", false);
280
+ expect(result).toHaveProperty(
281
+ "reason",
282
+ "Collection 'nonexistent' does not exist",
283
+ );
284
+ });
285
+ });
286
+
287
+ describe("mysql_doc_find", () => {
288
+ it("should query documents with filters", async () => {
289
+ // First call: collection existence check
290
+ // Second call: actual document query
291
+ mockAdapter.executeQuery
292
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
293
+ .mockResolvedValueOnce(
294
+ createMockQueryResult([{ doc: '{"name": "test"}' }]),
295
+ );
296
+
297
+ const tool = tools.find((t) => t.name === "mysql_doc_find")!;
298
+ const result = await tool.handler(
299
+ {
300
+ collection: "users",
301
+ filter: "$.age > 20",
302
+ },
303
+ mockContext,
304
+ );
305
+
306
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(2);
307
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
308
+ expect(call).toContain(
309
+ "WHERE JSON_EXTRACT(doc, '$.age > 20') IS NOT NULL",
310
+ );
311
+ expect(result).toHaveProperty("documents");
312
+ });
313
+
314
+ it("should return exists: false without error field for nonexistent collection", async () => {
315
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // collection does not exist
316
+
317
+ const tool = tools.find((t) => t.name === "mysql_doc_find")!;
318
+ const result = await tool.handler(
319
+ { collection: "nonexistent_col" },
320
+ mockContext,
321
+ );
322
+
323
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
324
+ expect(result).toEqual({
325
+ exists: false,
326
+ collection: "nonexistent_col",
327
+ documents: [],
328
+ count: 0,
329
+ });
330
+ expect(result).not.toHaveProperty("error");
331
+ });
332
+
333
+ it("should handle pre-parsed JSON documents", async () => {
334
+ mockAdapter.executeQuery
335
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
336
+ .mockResolvedValueOnce(
337
+ createMockQueryResult([{ doc: { id: 2, name: "test2" } }]),
338
+ );
339
+
340
+ const tool = tools.find((t) => t.name === "mysql_doc_find")!;
341
+ const result = (await tool.handler(
342
+ { collection: "users" },
343
+ mockContext,
344
+ )) as { documents: any[] };
60
345
 
61
- beforeEach(() => {
62
- vi.clearAllMocks();
63
- mockAdapter = createMockMySQLAdapter();
64
- tools = getDocStoreTools(mockAdapter as unknown as MySQLAdapter);
65
- mockContext = createMockRequestContext();
346
+ expect(result.documents[0]).toEqual({ id: 2, name: "test2" });
66
347
  });
67
348
 
68
- describe('mysql_doc_list_collections', () => {
69
- it('should list document collections', async () => {
70
- mockAdapter.executeQuery.mockResolvedValue(
71
- createMockQueryResult([{ name: 'users_collection', rowCount: 100 }])
72
- );
349
+ it("should apply filter", async () => {
350
+ mockAdapter.executeQuery
351
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
352
+ .mockResolvedValueOnce(createMockQueryResult([]));
73
353
 
74
- const tool = tools.find(t => t.name === 'mysql_doc_list_collections')!;
75
- const result = await tool.handler({}, mockContext);
354
+ const tool = tools.find((t) => t.name === "mysql_doc_find")!;
355
+ await tool.handler(
356
+ { collection: "users", filter: "$.name" },
357
+ mockContext,
358
+ );
359
+
360
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
361
+ expect(call).toContain("JSON_EXTRACT");
362
+ expect(call).toContain("$.name");
363
+ });
364
+
365
+ it("should support field projection", async () => {
366
+ mockAdapter.executeQuery
367
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
368
+ .mockResolvedValueOnce(createMockQueryResult([]));
369
+
370
+ const tool = tools.find((t) => t.name === "mysql_doc_find")!;
371
+ await tool.handler(
372
+ {
373
+ collection: "users",
374
+ fields: ["name", "email"],
375
+ },
376
+ mockContext,
377
+ );
378
+
379
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
380
+ // Verify exact SQL generation for projection
381
+ expect(call).toContain(
382
+ "JSON_OBJECT('name', JSON_EXTRACT(doc, '$.name'), 'email', JSON_EXTRACT(doc, '$.email')) as doc",
383
+ );
384
+ expect(call).toContain("FROM `users`");
385
+ });
76
386
 
77
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
78
- expect(result).toHaveProperty('collections');
79
- expect(result).toHaveProperty('count');
80
- });
387
+ it("should validate collection name", async () => {
388
+ const tool = tools.find((t) => t.name === "mysql_doc_find")!;
389
+ await expect(
390
+ tool.handler({ collection: "invalid-name; --" }, mockContext),
391
+ ).rejects.toThrow("Invalid collection name");
392
+ });
393
+
394
+ it("should return graceful response when collection does not exist", async () => {
395
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // collection does not exist
396
+
397
+ const tool = tools.find((t) => t.name === "mysql_doc_find")!;
398
+ const result = (await tool.handler(
399
+ { collection: "nonexistent" },
400
+ mockContext,
401
+ )) as {
402
+ exists: boolean;
403
+ documents: unknown[];
404
+ count: number;
405
+ };
406
+
407
+ expect(result).toHaveProperty("exists", false);
408
+ expect(result).toHaveProperty("documents", []);
409
+ expect(result).toHaveProperty("count", 0);
410
+ expect(result).not.toHaveProperty("error");
411
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
412
+ });
413
+ });
414
+
415
+ describe("mysql_doc_add", () => {
416
+ it("should add documents to collection", async () => {
417
+ mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
418
+ // First call is existence check — must return a row
419
+ mockAdapter.executeQuery.mockResolvedValueOnce(
420
+ createMockQueryResult([{ "1": 1 }]),
421
+ );
422
+
423
+ const tool = tools.find((t) => t.name === "mysql_doc_add")!;
424
+ const result = await tool.handler(
425
+ {
426
+ collection: "users",
427
+ documents: [{ name: "test" }],
428
+ },
429
+ mockContext,
430
+ );
431
+
432
+ expect(mockAdapter.executeQuery).toHaveBeenCalled();
433
+ expect(result).toHaveProperty("success", true);
434
+ expect(result).toHaveProperty("inserted", 1);
435
+ });
436
+
437
+ it("should handle multiple documents", async () => {
438
+ mockAdapter.executeQuery
439
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
440
+ .mockResolvedValue(createMockQueryResult([]));
441
+
442
+ const tool = tools.find((t) => t.name === "mysql_doc_add")!;
443
+ const result = await tool.handler(
444
+ {
445
+ collection: "users",
446
+ documents: [{ name: "user1" }, { name: "user2" }, { name: "user3" }],
447
+ },
448
+ mockContext,
449
+ );
450
+
451
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(4); // 1 existence check + 3 inserts
452
+ expect(result).toHaveProperty("inserted", 3);
453
+ });
454
+
455
+ it("should reject invalid collection names", async () => {
456
+ const tool = tools.find((t) => t.name === "mysql_doc_add")!;
457
+ await expect(
458
+ tool.handler(
459
+ {
460
+ collection: "invalid-name",
461
+ documents: [{ name: "test" }],
462
+ },
463
+ mockContext,
464
+ ),
465
+ ).rejects.toThrow("Invalid collection name");
466
+ });
81
467
 
82
- it('should filter by schema', async () => {
83
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
468
+ it("should return graceful response when collection does not exist", async () => {
469
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // collection does not exist
470
+
471
+ const tool = tools.find((t) => t.name === "mysql_doc_add")!;
472
+ const result = (await tool.handler(
473
+ {
474
+ collection: "nonexistent",
475
+ documents: [{ name: "test" }],
476
+ },
477
+ mockContext,
478
+ )) as { exists: boolean; collection: string };
479
+
480
+ expect(result).toHaveProperty("exists", false);
481
+ expect(result).toHaveProperty("collection", "nonexistent");
482
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
483
+ });
484
+ });
485
+
486
+ describe("mysql_doc_modify", () => {
487
+ it("should modify documents with set operation", async () => {
488
+ mockAdapter.executeQuery
489
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
490
+ .mockResolvedValueOnce(createMockQueryResult([], 5));
491
+
492
+ const tool = tools.find((t) => t.name === "mysql_doc_modify")!;
493
+ const result = await tool.handler(
494
+ {
495
+ collection: "users",
496
+ filter: "$.active",
497
+ set: { status: "updated" },
498
+ },
499
+ mockContext,
500
+ );
501
+
502
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
503
+ expect(call).toContain("JSON_SET");
504
+ expect(result).toHaveProperty("success", true);
505
+ expect(result).toHaveProperty("modified");
506
+ });
84
507
 
85
- const tool = tools.find(t => t.name === 'mysql_doc_list_collections')!;
86
- await tool.handler({ schema: 'mydb' }, mockContext);
508
+ it("should modify with unset operation", async () => {
509
+ mockAdapter.executeQuery
510
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
511
+ .mockResolvedValueOnce(createMockQueryResult([], 2));
512
+
513
+ const tool = tools.find((t) => t.name === "mysql_doc_modify")!;
514
+ await tool.handler(
515
+ {
516
+ collection: "users",
517
+ filter: "$.deprecated",
518
+ unset: ["oldField"],
519
+ },
520
+ mockContext,
521
+ );
522
+
523
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
524
+ expect(call).toContain("JSON_REMOVE");
525
+ });
87
526
 
88
- expect(mockAdapter.executeQuery).toHaveBeenCalledWith(
89
- expect.any(String),
90
- ['mydb', 'mydb']
91
- );
92
- });
527
+ it("should modify with both set and unset operations", async () => {
528
+ mockAdapter.executeQuery
529
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
530
+ .mockResolvedValueOnce(createMockQueryResult([], 2));
531
+
532
+ const tool = tools.find((t) => t.name === "mysql_doc_modify")!;
533
+ await tool.handler(
534
+ {
535
+ collection: "users",
536
+ filter: "$.id",
537
+ set: { status: "active" },
538
+ unset: ["temp"],
539
+ },
540
+ mockContext,
541
+ );
542
+
543
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
544
+ expect(call).toContain("JSON_SET");
545
+ expect(call).toContain("JSON_REMOVE");
546
+ expect(call).toContain("UPDATE `users` SET");
93
547
  });
94
548
 
95
- describe('mysql_doc_create_collection', () => {
96
- it('should create a new collection', async () => {
97
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
549
+ it("should throw if no modifications specified", async () => {
550
+ const tool = tools.find((t) => t.name === "mysql_doc_modify")!;
551
+
552
+ await expect(
553
+ tool.handler(
554
+ {
555
+ collection: "users",
556
+ filter: "$.active",
557
+ },
558
+ mockContext,
559
+ ),
560
+ ).rejects.toThrow("No modifications specified");
561
+ });
98
562
 
99
- const tool = tools.find(t => t.name === 'mysql_doc_create_collection')!;
100
- const result = await tool.handler({ name: 'products' }, mockContext);
563
+ it("should reject invalid collection names", async () => {
564
+ const tool = tools.find((t) => t.name === "mysql_doc_modify")!;
565
+ await expect(
566
+ tool.handler(
567
+ {
568
+ collection: "invalid-name",
569
+ filter: "$.id",
570
+ set: { a: 1 },
571
+ },
572
+ mockContext,
573
+ ),
574
+ ).rejects.toThrow("Invalid collection name");
575
+ });
101
576
 
102
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
103
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
104
- expect(call).toContain('CREATE TABLE');
105
- expect(call).toContain('doc JSON');
106
- expect(result).toHaveProperty('success', true);
107
- expect(result).toHaveProperty('collection', 'products');
108
- });
577
+ it("should return graceful response when collection does not exist", async () => {
578
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // collection does not exist
579
+
580
+ const tool = tools.find((t) => t.name === "mysql_doc_modify")!;
581
+ const result = (await tool.handler(
582
+ {
583
+ collection: "nonexistent",
584
+ filter: "$.name",
585
+ set: { status: "active" },
586
+ },
587
+ mockContext,
588
+ )) as { exists: boolean; collection: string };
589
+
590
+ expect(result).toHaveProperty("exists", false);
591
+ expect(result).toHaveProperty("collection", "nonexistent");
592
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
593
+ });
594
+ });
595
+
596
+ describe("mysql_doc_remove", () => {
597
+ it("should remove documents matching filter", async () => {
598
+ mockAdapter.executeQuery
599
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
600
+ .mockResolvedValueOnce(createMockQueryResult([], 3));
601
+
602
+ const tool = tools.find((t) => t.name === "mysql_doc_remove")!;
603
+ const result = await tool.handler(
604
+ {
605
+ collection: "users",
606
+ filter: "$.inactive",
607
+ },
608
+ mockContext,
609
+ );
610
+
611
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
612
+ expect(call).toContain("DELETE FROM");
613
+ expect(call).toContain("JSON_EXTRACT");
614
+ expect(result).toHaveProperty("success", true);
615
+ expect(result).toHaveProperty("removed");
616
+ });
109
617
 
110
- it('should reject invalid collection names', async () => {
111
- const tool = tools.find(t => t.name === 'mysql_doc_create_collection')!;
618
+ it("should reject invalid collection names", async () => {
619
+ const tool = tools.find((t) => t.name === "mysql_doc_remove")!;
620
+ await expect(
621
+ tool.handler(
622
+ {
623
+ collection: "invalid-name",
624
+ filter: "$.id",
625
+ },
626
+ mockContext,
627
+ ),
628
+ ).rejects.toThrow("Invalid collection name");
629
+ });
112
630
 
113
- await expect(tool.handler({ name: 'invalid-name' }, mockContext))
114
- .rejects.toThrow('Invalid collection name');
115
- });
631
+ it("should return graceful response when collection does not exist", async () => {
632
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // collection does not exist
633
+
634
+ const tool = tools.find((t) => t.name === "mysql_doc_remove")!;
635
+ const result = (await tool.handler(
636
+ {
637
+ collection: "nonexistent",
638
+ filter: "$.id",
639
+ },
640
+ mockContext,
641
+ )) as { exists: boolean; collection: string };
642
+
643
+ expect(result).toHaveProperty("exists", false);
644
+ expect(result).toHaveProperty("collection", "nonexistent");
645
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
646
+ });
647
+ });
648
+
649
+ describe("mysql_doc_create_index", () => {
650
+ it("should create index on document fields", async () => {
651
+ mockAdapter.executeQuery
652
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
653
+ .mockResolvedValue(createMockQueryResult([]));
654
+
655
+ const tool = tools.find((t) => t.name === "mysql_doc_create_index")!;
656
+ const result = await tool.handler(
657
+ {
658
+ collection: "users",
659
+ name: "idx_email",
660
+ fields: [{ path: "email", type: "TEXT" }],
661
+ },
662
+ mockContext,
663
+ );
664
+
665
+ // existence check + adds generated column + creates index
666
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(3);
667
+ expect(result).toHaveProperty("success", true);
668
+ expect(result).toHaveProperty("index", "idx_email");
669
+ });
116
670
 
117
- it('should add validation when specified', async () => {
118
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
671
+ it("should create composite index with multiple fields", async () => {
672
+ mockAdapter.executeQuery
673
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
674
+ .mockResolvedValue(createMockQueryResult([]));
675
+
676
+ const tool = tools.find((t) => t.name === "mysql_doc_create_index")!;
677
+ await tool.handler(
678
+ {
679
+ collection: "users",
680
+ name: "idx_name_age",
681
+ fields: [
682
+ { path: "name", type: "TEXT" },
683
+ { path: "age", type: "INT" },
684
+ ],
685
+ },
686
+ mockContext,
687
+ );
688
+
689
+ // existence check + 2 generated columns + 1 index creation
690
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(4);
691
+
692
+ const calls = mockAdapter.executeQuery.mock.calls;
693
+ const indexCall = calls[calls.length - 1][0] as string;
694
+ expect(indexCall).toContain("CREATE INDEX `idx_name_age`");
695
+ expect(indexCall).toContain("_idx_name");
696
+ expect(indexCall).toContain("_idx_age");
697
+ });
119
698
 
120
- const tool = tools.find(t => t.name === 'mysql_doc_create_collection')!;
121
- await tool.handler({
122
- name: 'validated_docs',
123
- validation: { level: 'STRICT', schema: { type: 'object' } }
124
- }, mockContext);
699
+ it("should create unique index", async () => {
700
+ mockAdapter.executeQuery
701
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
702
+ .mockResolvedValue(createMockQueryResult([]));
703
+
704
+ const tool = tools.find((t) => t.name === "mysql_doc_create_index")!;
705
+ await tool.handler(
706
+ {
707
+ collection: "users",
708
+ name: "idx_unique_email",
709
+ fields: [{ path: "email", type: "TEXT" }],
710
+ unique: true,
711
+ },
712
+ mockContext,
713
+ );
714
+
715
+ const calls = mockAdapter.executeQuery.mock.calls;
716
+ const lastCall = calls[calls.length - 1][0] as string;
717
+ expect(lastCall).toContain("UNIQUE INDEX");
718
+ });
125
719
 
126
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
127
- expect(call).toContain('JSON_SCHEMA_VALID');
128
- });
720
+ it("should reject invalid collection names", async () => {
721
+ const tool = tools.find((t) => t.name === "mysql_doc_create_index")!;
722
+ await expect(
723
+ tool.handler(
724
+ {
725
+ collection: "invalid-name",
726
+ name: "index",
727
+ fields: [{ path: "email", type: "TEXT" }],
728
+ },
729
+ mockContext,
730
+ ),
731
+ ).rejects.toThrow("Invalid collection name");
732
+ });
129
733
 
130
- it('should use default validation level when not specified', async () => {
131
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
734
+ it("should reject invalid index names", async () => {
735
+ const tool = tools.find((t) => t.name === "mysql_doc_create_index")!;
736
+ await expect(
737
+ tool.handler(
738
+ {
739
+ collection: "valid_coll",
740
+ name: "invalid-index",
741
+ fields: [{ path: "email", type: "TEXT" }],
742
+ },
743
+ mockContext,
744
+ ),
745
+ ).rejects.toThrow("Invalid index name");
746
+ });
132
747
 
133
- const tool = tools.find(t => t.name === 'mysql_doc_create_collection')!;
134
- await tool.handler({ name: 'default_val' }, mockContext);
748
+ it("should return graceful response when collection does not exist", async () => {
749
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // collection does not exist
750
+
751
+ const tool = tools.find((t) => t.name === "mysql_doc_create_index")!;
752
+ const result = (await tool.handler(
753
+ {
754
+ collection: "nonexistent",
755
+ name: "idx_test",
756
+ fields: [{ path: "email", type: "TEXT" }],
757
+ },
758
+ mockContext,
759
+ )) as { exists: boolean; collection: string };
760
+
761
+ expect(result).toHaveProperty("exists", false);
762
+ expect(result).toHaveProperty("collection", "nonexistent");
763
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
764
+ });
135
765
 
136
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
137
- expect(call).not.toContain('JSON_SCHEMA_VALID');
138
- });
766
+ it("should return graceful error on duplicate column", async () => {
767
+ mockAdapter.executeQuery
768
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
769
+ .mockRejectedValueOnce(new Error("Duplicate column name '_idx_email'"));
770
+
771
+ const tool = tools.find((t) => t.name === "mysql_doc_create_index")!;
772
+ const result = (await tool.handler(
773
+ {
774
+ collection: "users",
775
+ name: "idx_email",
776
+ fields: [{ path: "email", type: "TEXT" }],
777
+ },
778
+ mockContext,
779
+ )) as { success: boolean; reason: string };
780
+
781
+ expect(result).toHaveProperty("success", false);
782
+ expect(result.reason).toContain("already exist");
783
+ });
784
+ });
785
+
786
+ describe("mysql_doc_collection_info", () => {
787
+ it("should get collection statistics", async () => {
788
+ mockAdapter.executeQuery
789
+ .mockResolvedValueOnce(createMockQueryResult([{ "1": 1 }])) // collection exists
790
+ .mockResolvedValueOnce(createMockQueryResult([{ rowCount: 1000 }])) // COUNT(*) query
791
+ .mockResolvedValueOnce(
792
+ createMockQueryResult([{ dataSize: 50000, indexSize: 10000 }]),
793
+ ) // INFORMATION_SCHEMA.TABLES
794
+ .mockResolvedValueOnce(
795
+ createMockQueryResult([{ INDEX_NAME: "PRIMARY" }]),
796
+ ); // INFORMATION_SCHEMA.STATISTICS
797
+
798
+ const tool = tools.find((t) => t.name === "mysql_doc_collection_info")!;
799
+ const result = await tool.handler({ collection: "users" }, mockContext);
800
+
801
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(4);
802
+ expect(result).toHaveProperty("collection", "users");
803
+ expect(result).toHaveProperty("stats");
804
+ expect(result).toHaveProperty("indexes");
139
805
  });
140
806
 
141
- describe('mysql_doc_drop_collection', () => {
142
- it('should drop collection with IF EXISTS by default', async () => {
143
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
807
+ it("should reject invalid collection names", async () => {
808
+ const tool = tools.find((t) => t.name === "mysql_doc_collection_info")!;
809
+ await expect(
810
+ tool.handler({ collection: "invalid-nam$" }, mockContext),
811
+ ).rejects.toThrow("Invalid collection name");
812
+ });
144
813
 
145
- const tool = tools.find(t => t.name === 'mysql_doc_drop_collection')!;
146
- const result = await tool.handler({ name: 'users' }, mockContext);
814
+ it("should return graceful response when collection does not exist", async () => {
815
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([])); // collection does not exist
147
816
 
148
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
149
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
150
- expect(call).toContain('DROP TABLE IF EXISTS `users`');
151
- expect(result).toHaveProperty('success', true);
152
- });
817
+ const tool = tools.find((t) => t.name === "mysql_doc_collection_info")!;
818
+ const result = (await tool.handler(
819
+ { collection: "nonexistent" },
820
+ mockContext,
821
+ )) as { exists: boolean; collection: string };
153
822
 
154
- it('should drop collection without IF EXISTS when requested', async () => {
155
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
156
-
157
- const tool = tools.find(t => t.name === 'mysql_doc_drop_collection')!;
158
- await tool.handler({ name: 'users', ifExists: false }, mockContext);
159
-
160
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
161
- expect(call).toBe('DROP TABLE `users`');
162
- });
163
-
164
- it('should reject invalid collection names', async () => {
165
- const tool = tools.find(t => t.name === 'mysql_doc_drop_collection')!;
166
- await expect(tool.handler({ name: 'bad;drop table users' }, mockContext))
167
- .rejects.toThrow('Invalid collection name');
168
- });
169
- });
170
-
171
- describe('mysql_doc_find', () => {
172
- it('should query documents with filters', async () => {
173
- mockAdapter.executeQuery.mockResolvedValue(
174
- createMockQueryResult([{ doc: '{"name": "test"}' }])
175
- );
176
-
177
- const tool = tools.find(t => t.name === 'mysql_doc_find')!;
178
- const result = await tool.handler({
179
- collection: 'users',
180
- filter: '$.age > 20'
181
- }, mockContext);
182
-
183
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
184
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
185
- expect(call).toContain('WHERE JSON_EXTRACT(doc, \'$.age > 20\') IS NOT NULL');
186
- expect(result).toHaveProperty('documents');
187
- });
188
-
189
- it('should handle pre-parsed JSON documents', async () => {
190
- mockAdapter.executeQuery.mockResolvedValue(
191
- createMockQueryResult([{ doc: { id: 2, name: 'test2' } }])
192
- );
193
-
194
- const tool = tools.find(t => t.name === 'mysql_doc_find')!;
195
- const result = await tool.handler({ collection: 'users' }, mockContext) as { documents: any[] };
196
-
197
- expect(result.documents[0]).toEqual({ id: 2, name: 'test2' });
198
- });
199
-
200
- it('should apply filter', async () => {
201
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
202
-
203
- const tool = tools.find(t => t.name === 'mysql_doc_find')!;
204
- await tool.handler({ collection: 'users', filter: '$.name' }, mockContext);
205
-
206
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
207
- expect(call).toContain('JSON_EXTRACT');
208
- expect(call).toContain('$.name');
209
- });
210
-
211
- it('should support field projection', async () => {
212
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
213
-
214
- const tool = tools.find(t => t.name === 'mysql_doc_find')!;
215
- await tool.handler({
216
- collection: 'users',
217
- fields: ['name', 'email']
218
- }, mockContext);
219
-
220
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
221
- // Verify exact SQL generation for projection
222
- expect(call).toContain("JSON_OBJECT('name', JSON_EXTRACT(doc, '$.name'), 'email', JSON_EXTRACT(doc, '$.email')) as doc");
223
- expect(call).toContain("FROM `users`");
224
- });
225
-
226
- it('should validate collection name', async () => {
227
- const tool = tools.find(t => t.name === 'mysql_doc_find')!;
228
- await expect(tool.handler({ collection: 'invalid-name; --' }, mockContext))
229
- .rejects.toThrow('Invalid collection name');
230
- });
231
- });
232
-
233
- describe('mysql_doc_add', () => {
234
- it('should add documents to collection', async () => {
235
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
236
-
237
- const tool = tools.find(t => t.name === 'mysql_doc_add')!;
238
- const result = await tool.handler({
239
- collection: 'users',
240
- documents: [{ name: 'test' }]
241
- }, mockContext);
242
-
243
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
244
- expect(result).toHaveProperty('success', true);
245
- expect(result).toHaveProperty('inserted', 1);
246
- });
247
-
248
- it('should handle multiple documents', async () => {
249
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
250
-
251
- const tool = tools.find(t => t.name === 'mysql_doc_add')!;
252
- const result = await tool.handler({
253
- collection: 'users',
254
- documents: [{ name: 'user1' }, { name: 'user2' }, { name: 'user3' }]
255
- }, mockContext);
256
-
257
- expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(3);
258
- expect(result).toHaveProperty('inserted', 3);
259
- });
260
-
261
- it('should reject invalid collection names', async () => {
262
- const tool = tools.find(t => t.name === 'mysql_doc_add')!;
263
- await expect(tool.handler({
264
- collection: 'invalid-name',
265
- documents: [{ name: 'test' }]
266
- }, mockContext)).rejects.toThrow('Invalid collection name');
267
- });
268
- });
269
-
270
- describe('mysql_doc_modify', () => {
271
- it('should modify documents with set operation', async () => {
272
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([], 5));
273
-
274
- const tool = tools.find(t => t.name === 'mysql_doc_modify')!;
275
- const result = await tool.handler({
276
- collection: 'users',
277
- filter: '$.active',
278
- set: { status: 'updated' }
279
- }, mockContext);
280
-
281
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
282
- expect(call).toContain('JSON_SET');
283
- expect(result).toHaveProperty('success', true);
284
- expect(result).toHaveProperty('modified');
285
- });
286
-
287
- it('should modify with unset operation', async () => {
288
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([], 2));
289
-
290
- const tool = tools.find(t => t.name === 'mysql_doc_modify')!;
291
- await tool.handler({
292
- collection: 'users',
293
- filter: '$.deprecated',
294
- unset: ['oldField']
295
- }, mockContext);
296
-
297
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
298
- expect(call).toContain('JSON_REMOVE');
299
- });
300
-
301
- it('should modify with both set and unset operations', async () => {
302
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([], 2));
303
-
304
- const tool = tools.find(t => t.name === 'mysql_doc_modify')!;
305
- await tool.handler({
306
- collection: 'users',
307
- filter: '$.id',
308
- set: { status: 'active' },
309
- unset: ['temp']
310
- }, mockContext);
311
-
312
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
313
- expect(call).toContain('JSON_SET');
314
- expect(call).toContain('JSON_REMOVE');
315
- expect(call).toContain('UPDATE `users` SET');
316
- });
317
-
318
- it('should throw if no modifications specified', async () => {
319
- const tool = tools.find(t => t.name === 'mysql_doc_modify')!;
320
-
321
- await expect(tool.handler({
322
- collection: 'users',
323
- filter: '$.active'
324
- }, mockContext)).rejects.toThrow('No modifications specified');
325
- });
326
-
327
- it('should reject invalid collection names', async () => {
328
- const tool = tools.find(t => t.name === 'mysql_doc_modify')!;
329
- await expect(tool.handler({
330
- collection: 'invalid-name',
331
- filter: '$.id',
332
- set: { a: 1 }
333
- }, mockContext)).rejects.toThrow('Invalid collection name');
334
- });
335
- });
336
-
337
- describe('mysql_doc_remove', () => {
338
- it('should remove documents matching filter', async () => {
339
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([], 3));
340
-
341
- const tool = tools.find(t => t.name === 'mysql_doc_remove')!;
342
- const result = await tool.handler({
343
- collection: 'users',
344
- filter: '$.inactive'
345
- }, mockContext);
346
-
347
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
348
- expect(call).toContain('DELETE FROM');
349
- expect(call).toContain('JSON_EXTRACT');
350
- expect(result).toHaveProperty('success', true);
351
- expect(result).toHaveProperty('removed');
352
- });
353
-
354
- it('should reject invalid collection names', async () => {
355
- const tool = tools.find(t => t.name === 'mysql_doc_remove')!;
356
- await expect(tool.handler({
357
- collection: 'invalid-name',
358
- filter: '$.id'
359
- }, mockContext)).rejects.toThrow('Invalid collection name');
360
- });
361
- });
362
-
363
- describe('mysql_doc_create_index', () => {
364
- it('should create index on document fields', async () => {
365
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
366
-
367
- const tool = tools.find(t => t.name === 'mysql_doc_create_index')!;
368
- const result = await tool.handler({
369
- collection: 'users',
370
- name: 'idx_email',
371
- fields: [{ path: 'email', type: 'TEXT' }]
372
- }, mockContext);
373
-
374
- // First adds generated column, then creates index
375
- expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(2);
376
- expect(result).toHaveProperty('success', true);
377
- expect(result).toHaveProperty('index', 'idx_email');
378
- });
379
-
380
- it('should create composite index with multiple fields', async () => {
381
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
382
-
383
- const tool = tools.find(t => t.name === 'mysql_doc_create_index')!;
384
- await tool.handler({
385
- collection: 'users',
386
- name: 'idx_name_age',
387
- fields: [
388
- { path: 'name', type: 'TEXT' },
389
- { path: 'age', type: 'INT' }
390
- ]
391
- }, mockContext);
392
-
393
- // 2 generated columns + 1 index creation
394
- expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(3);
395
-
396
- const calls = mockAdapter.executeQuery.mock.calls;
397
- const indexCall = calls[calls.length - 1][0] as string;
398
- expect(indexCall).toContain('CREATE INDEX `idx_name_age`');
399
- expect(indexCall).toContain('_idx_name');
400
- expect(indexCall).toContain('_idx_age');
401
- });
402
-
403
- it('should create unique index', async () => {
404
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
405
-
406
- const tool = tools.find(t => t.name === 'mysql_doc_create_index')!;
407
- await tool.handler({
408
- collection: 'users',
409
- name: 'idx_unique_email',
410
- fields: [{ path: 'email', type: 'TEXT' }],
411
- unique: true
412
- }, mockContext);
413
-
414
- const calls = mockAdapter.executeQuery.mock.calls;
415
- const lastCall = calls[calls.length - 1][0] as string;
416
- expect(lastCall).toContain('UNIQUE INDEX');
417
- });
418
-
419
- it('should reject invalid collection names', async () => {
420
- const tool = tools.find(t => t.name === 'mysql_doc_create_index')!;
421
- await expect(tool.handler({
422
- collection: 'invalid-name',
423
- name: 'index',
424
- fields: [{ path: 'email', type: 'TEXT' }]
425
- }, mockContext)).rejects.toThrow('Invalid collection name');
426
- });
427
-
428
- it('should reject invalid index names', async () => {
429
- const tool = tools.find(t => t.name === 'mysql_doc_create_index')!;
430
- await expect(tool.handler({
431
- collection: 'valid_coll',
432
- name: 'invalid-index',
433
- fields: [{ path: 'email', type: 'TEXT' }]
434
- }, mockContext)).rejects.toThrow('Invalid index name');
435
- });
436
- });
437
-
438
- describe('mysql_doc_collection_info', () => {
439
- it('should get collection statistics', async () => {
440
- mockAdapter.executeQuery
441
- .mockResolvedValueOnce(createMockQueryResult([{ rowCount: 1000, dataSize: 50000 }]))
442
- .mockResolvedValueOnce(createMockQueryResult([{ INDEX_NAME: 'PRIMARY' }]));
443
-
444
- const tool = tools.find(t => t.name === 'mysql_doc_collection_info')!;
445
- const result = await tool.handler({ collection: 'users' }, mockContext);
446
-
447
- expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(2);
448
- expect(result).toHaveProperty('collection', 'users');
449
- expect(result).toHaveProperty('stats');
450
- expect(result).toHaveProperty('indexes');
451
- });
452
-
453
- it('should reject invalid collection names', async () => {
454
- const tool = tools.find(t => t.name === 'mysql_doc_collection_info')!;
455
- await expect(tool.handler({ collection: 'invalid-nam$' }, mockContext))
456
- .rejects.toThrow('Invalid collection name');
457
- });
823
+ expect(result).toHaveProperty("exists", false);
824
+ expect(result).toHaveProperty("collection", "nonexistent");
825
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
458
826
  });
827
+ });
459
828
  });