@neverinfamous/mysql-mcp 2.3.0 → 3.0.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 (347) hide show
  1. package/.dockerignore +1 -0
  2. package/.gitattributes +18 -0
  3. package/.github/workflows/codeql.yml +2 -10
  4. package/.github/workflows/docker-publish.yml +15 -13
  5. package/CHANGELOG.md +287 -1
  6. package/DOCKER_README.md +100 -265
  7. package/Dockerfile +5 -0
  8. package/README.md +124 -59
  9. package/VERSION +1 -1
  10. package/dist/__tests__/mocks/adapter.d.ts.map +1 -1
  11. package/dist/__tests__/mocks/adapter.js +2 -0
  12. package/dist/__tests__/mocks/adapter.js.map +1 -1
  13. package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
  14. package/dist/adapters/DatabaseAdapter.js +50 -9
  15. package/dist/adapters/DatabaseAdapter.js.map +1 -1
  16. package/dist/adapters/mysql/MySQLAdapter.d.ts +6 -0
  17. package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
  18. package/dist/adapters/mysql/MySQLAdapter.js +8 -0
  19. package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
  20. package/dist/adapters/mysql/SchemaManager.js +16 -15
  21. package/dist/adapters/mysql/SchemaManager.js.map +1 -1
  22. package/dist/adapters/mysql/prompts/index.js +10 -20
  23. package/dist/adapters/mysql/prompts/index.js.map +1 -1
  24. package/dist/adapters/mysql/prompts/proxysqlSetup.js +1 -1
  25. package/dist/adapters/mysql/resources/docstore.d.ts.map +1 -1
  26. package/dist/adapters/mysql/resources/docstore.js +10 -7
  27. package/dist/adapters/mysql/resources/docstore.js.map +1 -1
  28. package/dist/adapters/mysql/resources/events.js +11 -8
  29. package/dist/adapters/mysql/resources/events.js.map +1 -1
  30. package/dist/adapters/mysql/resources/indexes.d.ts.map +1 -1
  31. package/dist/adapters/mysql/resources/indexes.js +12 -15
  32. package/dist/adapters/mysql/resources/indexes.js.map +1 -1
  33. package/dist/adapters/mysql/resources/innodb.d.ts.map +1 -1
  34. package/dist/adapters/mysql/resources/innodb.js +20 -17
  35. package/dist/adapters/mysql/resources/innodb.js.map +1 -1
  36. package/dist/adapters/mysql/resources/locks.d.ts.map +1 -1
  37. package/dist/adapters/mysql/resources/locks.js +9 -6
  38. package/dist/adapters/mysql/resources/locks.js.map +1 -1
  39. package/dist/adapters/mysql/resources/performance.d.ts.map +1 -1
  40. package/dist/adapters/mysql/resources/performance.js +15 -15
  41. package/dist/adapters/mysql/resources/performance.js.map +1 -1
  42. package/dist/adapters/mysql/resources/spatial.d.ts.map +1 -1
  43. package/dist/adapters/mysql/resources/spatial.js +9 -6
  44. package/dist/adapters/mysql/resources/spatial.js.map +1 -1
  45. package/dist/adapters/mysql/resources/sysschema.d.ts.map +1 -1
  46. package/dist/adapters/mysql/resources/sysschema.js +12 -9
  47. package/dist/adapters/mysql/resources/sysschema.js.map +1 -1
  48. package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
  49. package/dist/adapters/mysql/tools/admin/backup.js +170 -121
  50. package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
  51. package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
  52. package/dist/adapters/mysql/tools/admin/maintenance.js +106 -57
  53. package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
  54. package/dist/adapters/mysql/tools/admin/monitoring.d.ts.map +1 -1
  55. package/dist/adapters/mysql/tools/admin/monitoring.js +183 -101
  56. package/dist/adapters/mysql/tools/admin/monitoring.js.map +1 -1
  57. package/dist/adapters/mysql/tools/cluster/group-replication.d.ts.map +1 -1
  58. package/dist/adapters/mysql/tools/cluster/group-replication.js +164 -120
  59. package/dist/adapters/mysql/tools/cluster/group-replication.js.map +1 -1
  60. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
  61. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +212 -145
  62. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
  63. package/dist/adapters/mysql/tools/codemode/index.d.ts.map +1 -1
  64. package/dist/adapters/mysql/tools/codemode/index.js +6 -4
  65. package/dist/adapters/mysql/tools/codemode/index.js.map +1 -1
  66. package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
  67. package/dist/adapters/mysql/tools/core.js +152 -29
  68. package/dist/adapters/mysql/tools/core.js.map +1 -1
  69. package/dist/adapters/mysql/tools/docstore.d.ts.map +1 -1
  70. package/dist/adapters/mysql/tools/docstore.js +340 -163
  71. package/dist/adapters/mysql/tools/docstore.js.map +1 -1
  72. package/dist/adapters/mysql/tools/events.d.ts.map +1 -1
  73. package/dist/adapters/mysql/tools/events.js +284 -198
  74. package/dist/adapters/mysql/tools/events.js.map +1 -1
  75. package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
  76. package/dist/adapters/mysql/tools/json/core.js +11 -39
  77. package/dist/adapters/mysql/tools/json/core.js.map +1 -1
  78. package/dist/adapters/mysql/tools/json/enhanced.d.ts.map +1 -1
  79. package/dist/adapters/mysql/tools/json/enhanced.js +15 -33
  80. package/dist/adapters/mysql/tools/json/enhanced.js.map +1 -1
  81. package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
  82. package/dist/adapters/mysql/tools/json/helpers.js +13 -24
  83. package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
  84. package/dist/adapters/mysql/tools/partitioning.js +3 -0
  85. package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
  86. package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
  87. package/dist/adapters/mysql/tools/performance/analysis.js +89 -60
  88. package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
  89. package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
  90. package/dist/adapters/mysql/tools/performance/optimization.js +151 -127
  91. package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
  92. package/dist/adapters/mysql/tools/proxysql.d.ts +1 -1
  93. package/dist/adapters/mysql/tools/proxysql.d.ts.map +1 -1
  94. package/dist/adapters/mysql/tools/proxysql.js +289 -176
  95. package/dist/adapters/mysql/tools/proxysql.js.map +1 -1
  96. package/dist/adapters/mysql/tools/replication.js +75 -49
  97. package/dist/adapters/mysql/tools/replication.js.map +1 -1
  98. package/dist/adapters/mysql/tools/roles.d.ts.map +1 -1
  99. package/dist/adapters/mysql/tools/roles.js +224 -182
  100. package/dist/adapters/mysql/tools/roles.js.map +1 -1
  101. package/dist/adapters/mysql/tools/router.d.ts.map +1 -1
  102. package/dist/adapters/mysql/tools/router.js +168 -67
  103. package/dist/adapters/mysql/tools/router.js.map +1 -1
  104. package/dist/adapters/mysql/tools/schema/constraints.d.ts.map +1 -1
  105. package/dist/adapters/mysql/tools/schema/constraints.js +21 -3
  106. package/dist/adapters/mysql/tools/schema/constraints.js.map +1 -1
  107. package/dist/adapters/mysql/tools/schema/management.d.ts.map +1 -1
  108. package/dist/adapters/mysql/tools/schema/management.js +61 -14
  109. package/dist/adapters/mysql/tools/schema/management.js.map +1 -1
  110. package/dist/adapters/mysql/tools/schema/routines.d.ts.map +1 -1
  111. package/dist/adapters/mysql/tools/schema/routines.js +27 -4
  112. package/dist/adapters/mysql/tools/schema/routines.js.map +1 -1
  113. package/dist/adapters/mysql/tools/schema/scheduled_events.d.ts.map +1 -1
  114. package/dist/adapters/mysql/tools/schema/scheduled_events.js +24 -3
  115. package/dist/adapters/mysql/tools/schema/scheduled_events.js.map +1 -1
  116. package/dist/adapters/mysql/tools/schema/triggers.d.ts.map +1 -1
  117. package/dist/adapters/mysql/tools/schema/triggers.js +23 -2
  118. package/dist/adapters/mysql/tools/schema/triggers.js.map +1 -1
  119. package/dist/adapters/mysql/tools/schema/views.d.ts.map +1 -1
  120. package/dist/adapters/mysql/tools/schema/views.js +47 -7
  121. package/dist/adapters/mysql/tools/schema/views.js.map +1 -1
  122. package/dist/adapters/mysql/tools/security/audit.d.ts.map +1 -1
  123. package/dist/adapters/mysql/tools/security/audit.js +102 -34
  124. package/dist/adapters/mysql/tools/security/audit.js.map +1 -1
  125. package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
  126. package/dist/adapters/mysql/tools/security/data-protection.js +264 -205
  127. package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
  128. package/dist/adapters/mysql/tools/security/encryption.d.ts.map +1 -1
  129. package/dist/adapters/mysql/tools/security/encryption.js +137 -104
  130. package/dist/adapters/mysql/tools/security/encryption.js.map +1 -1
  131. package/dist/adapters/mysql/tools/shell/backup.d.ts.map +1 -1
  132. package/dist/adapters/mysql/tools/shell/backup.js +71 -59
  133. package/dist/adapters/mysql/tools/shell/backup.js.map +1 -1
  134. package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
  135. package/dist/adapters/mysql/tools/shell/restore.js +61 -47
  136. package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
  137. package/dist/adapters/mysql/tools/spatial/geometry.d.ts.map +1 -1
  138. package/dist/adapters/mysql/tools/spatial/geometry.js +19 -5
  139. package/dist/adapters/mysql/tools/spatial/geometry.js.map +1 -1
  140. package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
  141. package/dist/adapters/mysql/tools/spatial/operations.js +42 -17
  142. package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
  143. package/dist/adapters/mysql/tools/spatial/queries.d.ts.map +1 -1
  144. package/dist/adapters/mysql/tools/spatial/queries.js +109 -57
  145. package/dist/adapters/mysql/tools/spatial/queries.js.map +1 -1
  146. package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
  147. package/dist/adapters/mysql/tools/spatial/setup.js +103 -50
  148. package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
  149. package/dist/adapters/mysql/tools/stats/comparative.d.ts.map +1 -1
  150. package/dist/adapters/mysql/tools/stats/comparative.js +128 -79
  151. package/dist/adapters/mysql/tools/stats/comparative.js.map +1 -1
  152. package/dist/adapters/mysql/tools/stats/descriptive.d.ts.map +1 -1
  153. package/dist/adapters/mysql/tools/stats/descriptive.js +174 -102
  154. package/dist/adapters/mysql/tools/stats/descriptive.js.map +1 -1
  155. package/dist/adapters/mysql/tools/sysschema/activity.d.ts.map +1 -1
  156. package/dist/adapters/mysql/tools/sysschema/activity.js +50 -25
  157. package/dist/adapters/mysql/tools/sysschema/activity.js.map +1 -1
  158. package/dist/adapters/mysql/tools/sysschema/performance.d.ts.map +1 -1
  159. package/dist/adapters/mysql/tools/sysschema/performance.js +121 -66
  160. package/dist/adapters/mysql/tools/sysschema/performance.js.map +1 -1
  161. package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
  162. package/dist/adapters/mysql/tools/sysschema/resources.js +101 -64
  163. package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
  164. package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
  165. package/dist/adapters/mysql/tools/text/fulltext.js +18 -32
  166. package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
  167. package/dist/adapters/mysql/tools/transactions.d.ts.map +1 -1
  168. package/dist/adapters/mysql/tools/transactions.js +48 -23
  169. package/dist/adapters/mysql/tools/transactions.js.map +1 -1
  170. package/dist/adapters/mysql/types/proxysql-types.d.ts +15 -0
  171. package/dist/adapters/mysql/types/proxysql-types.d.ts.map +1 -1
  172. package/dist/adapters/mysql/types/proxysql-types.js +33 -1
  173. package/dist/adapters/mysql/types/proxysql-types.js.map +1 -1
  174. package/dist/adapters/mysql/types/router-types.d.ts +1 -1
  175. package/dist/adapters/mysql/types/router-types.js +1 -1
  176. package/dist/adapters/mysql/types/router-types.js.map +1 -1
  177. package/dist/adapters/mysql/types/shell-types.js +2 -2
  178. package/dist/adapters/mysql/types/shell-types.js.map +1 -1
  179. package/dist/adapters/mysql/types.d.ts +485 -21
  180. package/dist/adapters/mysql/types.d.ts.map +1 -1
  181. package/dist/adapters/mysql/types.js +546 -19
  182. package/dist/adapters/mysql/types.js.map +1 -1
  183. package/dist/auth/scopes.js +1 -1
  184. package/dist/auth/scopes.js.map +1 -1
  185. package/dist/codemode/api.d.ts +3 -2
  186. package/dist/codemode/api.d.ts.map +1 -1
  187. package/dist/codemode/api.js +80 -5
  188. package/dist/codemode/api.js.map +1 -1
  189. package/dist/codemode/sandbox-factory.js +1 -1
  190. package/dist/codemode/sandbox-factory.js.map +1 -1
  191. package/dist/codemode/types.d.ts +26 -0
  192. package/dist/codemode/types.d.ts.map +1 -1
  193. package/dist/codemode/types.js +2 -0
  194. package/dist/codemode/types.js.map +1 -1
  195. package/dist/codemode/worker-sandbox.d.ts +4 -2
  196. package/dist/codemode/worker-sandbox.d.ts.map +1 -1
  197. package/dist/codemode/worker-sandbox.js +66 -7
  198. package/dist/codemode/worker-sandbox.js.map +1 -1
  199. package/dist/codemode/worker-script.d.ts +3 -0
  200. package/dist/codemode/worker-script.d.ts.map +1 -1
  201. package/dist/codemode/worker-script.js +128 -75
  202. package/dist/codemode/worker-script.js.map +1 -1
  203. package/dist/constants/ServerInstructions.d.ts +1 -1
  204. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  205. package/dist/constants/ServerInstructions.js +37 -31
  206. package/dist/constants/ServerInstructions.js.map +1 -1
  207. package/dist/filtering/ToolConstants.d.ts +1 -1
  208. package/dist/filtering/ToolConstants.d.ts.map +1 -1
  209. package/dist/filtering/ToolConstants.js +1 -2
  210. package/dist/filtering/ToolConstants.js.map +1 -1
  211. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  212. package/dist/pool/ConnectionPool.js.map +1 -1
  213. package/dist/transports/http.d.ts.map +1 -1
  214. package/dist/transports/http.js +6 -0
  215. package/dist/transports/http.js.map +1 -1
  216. package/dist/utils/validators.d.ts +1 -1
  217. package/dist/utils/validators.d.ts.map +1 -1
  218. package/dist/utils/validators.js.map +1 -1
  219. package/package.json +4 -4
  220. package/releases/v2.3.0-release-notes.md +20 -20
  221. package/releases/v2.3.1-release-notes.md +34 -0
  222. package/releases/v3.0.0-release-notes.md +81 -0
  223. package/src/__tests__/mocks/adapter.ts +3 -0
  224. package/src/__tests__/perf.test.ts +6 -6
  225. package/src/adapters/DatabaseAdapter.ts +58 -9
  226. package/src/adapters/__tests__/DatabaseAdapter.test.ts +89 -8
  227. package/src/adapters/mysql/MySQLAdapter.ts +17 -2
  228. package/src/adapters/mysql/SchemaManager.ts +21 -21
  229. package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +1 -1
  230. package/src/adapters/mysql/prompts/index.ts +12 -22
  231. package/src/adapters/mysql/prompts/proxysqlSetup.ts +1 -1
  232. package/src/adapters/mysql/resources/docstore.ts +13 -10
  233. package/src/adapters/mysql/resources/events.ts +12 -12
  234. package/src/adapters/mysql/resources/indexes.ts +17 -19
  235. package/src/adapters/mysql/resources/innodb.ts +23 -22
  236. package/src/adapters/mysql/resources/locks.ts +9 -7
  237. package/src/adapters/mysql/resources/performance.ts +23 -18
  238. package/src/adapters/mysql/resources/spatial.ts +9 -7
  239. package/src/adapters/mysql/resources/sysschema.ts +12 -11
  240. package/src/adapters/mysql/tools/__tests__/core.test.ts +126 -55
  241. package/src/adapters/mysql/tools/__tests__/docstore.test.ts +459 -88
  242. package/src/adapters/mysql/tools/__tests__/events.test.ts +281 -103
  243. package/src/adapters/mysql/tools/__tests__/proxysql.test.ts +128 -28
  244. package/src/adapters/mysql/tools/__tests__/replication.test.ts +48 -2
  245. package/src/adapters/mysql/tools/__tests__/roles.test.ts +15 -18
  246. package/src/adapters/mysql/tools/__tests__/router.test.ts +32 -5
  247. package/src/adapters/mysql/tools/__tests__/security.test.ts +126 -2
  248. package/src/adapters/mysql/tools/__tests__/security_injection.test.ts +84 -76
  249. package/src/adapters/mysql/tools/__tests__/security_integration.test.ts +47 -50
  250. package/src/adapters/mysql/tools/__tests__/spatial.test.ts +11 -10
  251. package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +54 -38
  252. package/src/adapters/mysql/tools/__tests__/stats.test.ts +285 -152
  253. package/src/adapters/mysql/tools/__tests__/transactions.test.ts +13 -13
  254. package/src/adapters/mysql/tools/admin/__tests__/backup.test.ts +171 -25
  255. package/src/adapters/mysql/tools/admin/__tests__/maintenance.test.ts +240 -4
  256. package/src/adapters/mysql/tools/admin/__tests__/monitoring-summary.test.ts +274 -0
  257. package/src/adapters/mysql/tools/admin/__tests__/monitoring.test.ts +94 -5
  258. package/src/adapters/mysql/tools/admin/backup.ts +193 -143
  259. package/src/adapters/mysql/tools/admin/maintenance.ts +118 -69
  260. package/src/adapters/mysql/tools/admin/monitoring.ts +201 -125
  261. package/src/adapters/mysql/tools/cluster/__tests__/group-replication.test.ts +69 -0
  262. package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +141 -0
  263. package/src/adapters/mysql/tools/cluster/group-replication.ts +172 -132
  264. package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +231 -157
  265. package/src/adapters/mysql/tools/codemode/__tests__/codemode-tool.test.ts +227 -0
  266. package/src/adapters/mysql/tools/codemode/index.ts +5 -3
  267. package/src/adapters/mysql/tools/core.ts +152 -38
  268. package/src/adapters/mysql/tools/docstore.ts +422 -205
  269. package/src/adapters/mysql/tools/events.ts +334 -233
  270. package/src/adapters/mysql/tools/json/__tests__/core.test.ts +20 -0
  271. package/src/adapters/mysql/tools/json/__tests__/enhanced.test.ts +82 -50
  272. package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +42 -3
  273. package/src/adapters/mysql/tools/json/core.ts +21 -42
  274. package/src/adapters/mysql/tools/json/enhanced.ts +22 -37
  275. package/src/adapters/mysql/tools/json/helpers.ts +21 -25
  276. package/src/adapters/mysql/tools/partitioning.ts +3 -0
  277. package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +98 -5
  278. package/src/adapters/mysql/tools/performance/__tests__/optimization-coverage.test.ts +515 -0
  279. package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +187 -0
  280. package/src/adapters/mysql/tools/performance/analysis.ts +95 -69
  281. package/src/adapters/mysql/tools/performance/optimization.ts +182 -153
  282. package/src/adapters/mysql/tools/proxysql.ts +314 -209
  283. package/src/adapters/mysql/tools/replication.ts +84 -57
  284. package/src/adapters/mysql/tools/roles.ts +274 -226
  285. package/src/adapters/mysql/tools/router.ts +181 -85
  286. package/src/adapters/mysql/tools/schema/__tests__/constraints.test.ts +13 -0
  287. package/src/adapters/mysql/tools/schema/__tests__/management.test.ts +60 -25
  288. package/src/adapters/mysql/tools/schema/__tests__/scheduled_events.test.ts +11 -0
  289. package/src/adapters/mysql/tools/schema/__tests__/triggers.test.ts +25 -4
  290. package/src/adapters/mysql/tools/schema/__tests__/views.test.ts +46 -14
  291. package/src/adapters/mysql/tools/schema/constraints.ts +22 -3
  292. package/src/adapters/mysql/tools/schema/management.ts +60 -15
  293. package/src/adapters/mysql/tools/schema/routines.ts +26 -4
  294. package/src/adapters/mysql/tools/schema/scheduled_events.ts +25 -3
  295. package/src/adapters/mysql/tools/schema/triggers.ts +27 -2
  296. package/src/adapters/mysql/tools/schema/views.ts +46 -8
  297. package/src/adapters/mysql/tools/security/__tests__/audit.test.ts +90 -4
  298. package/src/adapters/mysql/tools/security/audit.ts +113 -39
  299. package/src/adapters/mysql/tools/security/data-protection.ts +293 -233
  300. package/src/adapters/mysql/tools/security/encryption.ts +172 -139
  301. package/src/adapters/mysql/tools/shell/__tests__/backup.test.ts +29 -0
  302. package/src/adapters/mysql/tools/shell/backup.ts +90 -73
  303. package/src/adapters/mysql/tools/shell/restore.ts +62 -48
  304. package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +22 -14
  305. package/src/adapters/mysql/tools/spatial/__tests__/queries.test.ts +65 -51
  306. package/src/adapters/mysql/tools/spatial/geometry.ts +23 -7
  307. package/src/adapters/mysql/tools/spatial/operations.ts +60 -31
  308. package/src/adapters/mysql/tools/spatial/queries.ts +142 -65
  309. package/src/adapters/mysql/tools/spatial/setup.ts +121 -55
  310. package/src/adapters/mysql/tools/stats/__tests__/comparative.test.ts +12 -10
  311. package/src/adapters/mysql/tools/stats/comparative.ts +150 -98
  312. package/src/adapters/mysql/tools/stats/descriptive.ts +204 -127
  313. package/src/adapters/mysql/tools/sysschema/__tests__/error-paths.test.ts +222 -0
  314. package/src/adapters/mysql/tools/sysschema/__tests__/performance.test.ts +45 -0
  315. package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +6 -3
  316. package/src/adapters/mysql/tools/sysschema/activity.ts +52 -27
  317. package/src/adapters/mysql/tools/sysschema/performance.ts +132 -68
  318. package/src/adapters/mysql/tools/sysschema/resources.ts +105 -67
  319. package/src/adapters/mysql/tools/text/__tests__/fulltext.test.ts +45 -17
  320. package/src/adapters/mysql/tools/text/fulltext.ts +27 -38
  321. package/src/adapters/mysql/tools/transactions.ts +49 -24
  322. package/src/adapters/mysql/types/proxysql-types.ts +38 -1
  323. package/src/adapters/mysql/types/router-types.ts +1 -1
  324. package/src/adapters/mysql/types/shell-types.ts +2 -2
  325. package/src/adapters/mysql/types.ts +632 -19
  326. package/src/auth/__tests__/scopes.test.ts +2 -2
  327. package/src/auth/scopes.ts +1 -1
  328. package/src/codemode/__tests__/api.test.ts +417 -0
  329. package/src/codemode/__tests__/sandbox-factory.test.ts +158 -0
  330. package/src/codemode/__tests__/sandbox.test.ts +301 -0
  331. package/src/codemode/__tests__/security.test.ts +368 -0
  332. package/src/codemode/__tests__/worker-sandbox.test.ts +179 -0
  333. package/src/codemode/__tests__/worker-script.test.ts +226 -0
  334. package/src/codemode/api.ts +89 -5
  335. package/src/codemode/sandbox-factory.ts +1 -1
  336. package/src/codemode/types.ts +34 -0
  337. package/src/codemode/worker-sandbox.ts +74 -7
  338. package/src/codemode/worker-script.ts +157 -86
  339. package/src/constants/ServerInstructions.ts +37 -31
  340. package/src/filtering/ToolConstants.ts +1 -2
  341. package/src/filtering/__tests__/ToolFilter.test.ts +9 -9
  342. package/src/pool/ConnectionPool.ts +4 -1
  343. package/src/transports/__tests__/http.test.ts +15 -3
  344. package/src/transports/http.ts +12 -0
  345. package/src/utils/validators.ts +2 -1
  346. package/vitest.config.ts +3 -1
  347. package/CODE_MODE.md +0 -245
@@ -204,6 +204,21 @@ describe("Replication Handler Execution", () => {
204
204
  expect(mockAdapter.executeQuery).toHaveBeenCalled();
205
205
  expect(result).toBeDefined();
206
206
  });
207
+
208
+ it("should return structured error on query failure", async () => {
209
+ mockAdapter.executeQuery.mockRejectedValue(
210
+ new Error("GTID not supported"),
211
+ );
212
+
213
+ const tool = tools.find((t) => t.name === "mysql_gtid_status")!;
214
+ const result = (await tool.handler({}, mockContext)) as {
215
+ success: boolean;
216
+ error: string;
217
+ };
218
+
219
+ expect(result.success).toBe(false);
220
+ expect(result.error).toContain("Failed to retrieve GTID status");
221
+ });
207
222
  });
208
223
 
209
224
  describe("mysql_replication_lag", () => {
@@ -710,14 +725,18 @@ describe("Replication Fallback Handling", () => {
710
725
  expect(result).toHaveProperty("status");
711
726
  });
712
727
 
713
- it("should return error when binary logging is disabled", async () => {
728
+ it("should return structured error when binary logging is disabled", async () => {
714
729
  mockAdapter.executeQuery
715
730
  .mockRejectedValueOnce(new Error("Unknown command"))
716
731
  .mockRejectedValueOnce(new Error("Binary logging not enabled"));
717
732
 
718
733
  const tool = tools.find((t) => t.name === "mysql_master_status")!;
719
- const result = (await tool.handler({}, mockContext)) as { error: string };
734
+ const result = (await tool.handler({}, mockContext)) as {
735
+ success: boolean;
736
+ error: string;
737
+ };
720
738
 
739
+ expect(result.success).toBe(false);
721
740
  expect(result.error).toContain("Binary logging");
722
741
  });
723
742
  });
@@ -812,6 +831,33 @@ describe("Replication Fallback Handling", () => {
812
831
  });
813
832
  });
814
833
 
834
+ describe("mysql_binlog_events limit:0 guard", () => {
835
+ it("should return empty events for limit: 0 without querying MySQL", async () => {
836
+ const tool = tools.find((t) => t.name === "mysql_binlog_events")!;
837
+ const result = (await tool.handler(
838
+ { logFile: "mysql-bin.000001", limit: 0 },
839
+ mockContext,
840
+ )) as { events: unknown[] };
841
+
842
+ expect(result.events).toEqual([]);
843
+ // Should NOT have called executeQuery — guard returns before any SQL
844
+ expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
845
+ });
846
+
847
+ it("should return structured error for negative limit", async () => {
848
+ const tool = tools.find((t) => t.name === "mysql_binlog_events")!;
849
+ const result = (await tool.handler(
850
+ { logFile: "mysql-bin.000001", limit: -1 },
851
+ mockContext,
852
+ )) as { success: boolean; error: string };
853
+
854
+ expect(result.success).toBe(false);
855
+ expect(result.error).toBeDefined();
856
+ // Should NOT have called executeQuery — Zod rejects before any SQL
857
+ expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
858
+ });
859
+ });
860
+
815
861
  describe("mysql_replication_lag fallback", () => {
816
862
  it("should return lag from replica status", async () => {
817
863
  mockAdapter.executeQuery.mockResolvedValue(
@@ -108,11 +108,10 @@ describe("Handler Execution", () => {
108
108
  expect(call).toContain("CREATE ROLE 'test_role'");
109
109
  });
110
110
 
111
- it("should reject invalid role names", async () => {
111
+ it("should return structured error for invalid role names", async () => {
112
112
  const tool = tools.find((t) => t.name === "mysql_role_create")!;
113
- await expect(
114
- tool.handler({ name: "invalid-role" }, mockContext),
115
- ).rejects.toThrow("Invalid role name");
113
+ const result = await tool.handler({ name: "invalid-role" }, mockContext);
114
+ expect(result).toEqual({ success: false, error: "Invalid role name" });
116
115
  });
117
116
 
118
117
  it("should return skipped when ifNotExists and role already exists", async () => {
@@ -170,14 +169,13 @@ describe("Handler Execution", () => {
170
169
  );
171
170
  });
172
171
 
173
- it("should reject invalid role names", async () => {
172
+ it("should return structured error for invalid role names", async () => {
174
173
  const tool = tools.find((t) => t.name === "mysql_role_grant")!;
175
- await expect(
176
- tool.handler(
177
- { role: "invalid-role", privileges: ["SELECT"] },
178
- mockContext,
179
- ),
180
- ).rejects.toThrow("Invalid role name");
174
+ const result = await tool.handler(
175
+ { role: "invalid-role", privileges: ["SELECT"] },
176
+ mockContext,
177
+ );
178
+ expect(result).toEqual({ success: false, error: "Invalid role name" });
181
179
  });
182
180
  });
183
181
 
@@ -218,7 +216,7 @@ describe("Handler Execution", () => {
218
216
  role: "test_role",
219
217
  user: "testuser",
220
218
  host: "localhost",
221
- reason:
219
+ error:
222
220
  "Role 'test_role' is not assigned to user 'testuser'@'localhost'",
223
221
  });
224
222
  expect(mockAdapter.rawQuery).not.toHaveBeenCalled();
@@ -249,11 +247,10 @@ describe("Handler Execution", () => {
249
247
  expect(call).toContain("DROP ROLE 'test_role'");
250
248
  });
251
249
 
252
- it("should reject invalid role names", async () => {
250
+ it("should return structured error for invalid role names", async () => {
253
251
  const tool = tools.find((t) => t.name === "mysql_role_drop")!;
254
- await expect(
255
- tool.handler({ name: "invalid-role" }, mockContext),
256
- ).rejects.toThrow("Invalid role name");
252
+ const result = await tool.handler({ name: "invalid-role" }, mockContext);
253
+ expect(result).toEqual({ success: false, error: "Invalid role name" });
257
254
  });
258
255
 
259
256
  it("should return skipped when ifExists and role does not exist", async () => {
@@ -367,7 +364,7 @@ describe("Handler Execution", () => {
367
364
 
368
365
  expect(result).toEqual({
369
366
  success: false,
370
- reason: "Role 'test_role' already exists",
367
+ error: "Role 'test_role' already exists",
371
368
  });
372
369
  });
373
370
  });
@@ -386,7 +383,7 @@ describe("Handler Execution", () => {
386
383
 
387
384
  expect(result).toEqual({
388
385
  success: false,
389
- reason: "Role 'test_role' does not exist",
386
+ error: "Role 'test_role' does not exist",
390
387
  });
391
388
  });
392
389
  });
@@ -475,7 +475,7 @@ describe("Error Handling", () => {
475
475
 
476
476
  expect(result).toEqual({
477
477
  available: false,
478
- reason: "Router API error: 401 Unauthorized",
478
+ error: "Router API error: 401 Unauthorized",
479
479
  });
480
480
  });
481
481
 
@@ -510,8 +510,8 @@ describe("Error Handling", () => {
510
510
  );
511
511
 
512
512
  expect(result).toEqual({
513
- available: false,
514
- reason: "Router API error: 404 Not Found",
513
+ success: false,
514
+ error: "Router API error: 404 Not Found",
515
515
  });
516
516
  });
517
517
 
@@ -535,7 +535,7 @@ describe("Error Handling", () => {
535
535
 
536
536
  expect(result).toEqual({
537
537
  available: false,
538
- reason: "Router API request failed: Network error",
538
+ error: "Router API request failed: Network error",
539
539
  });
540
540
  });
541
541
 
@@ -561,11 +561,38 @@ describe("Error Handling", () => {
561
561
 
562
562
  expect(result).toEqual({
563
563
  available: false,
564
- reason: expect.stringContaining("Connection refused"),
564
+ error: expect.stringContaining("Connection refused"),
565
565
  });
566
566
  });
567
567
  });
568
568
 
569
+ describe("Zod Validation Error Handling", () => {
570
+ let tools: ReturnType<typeof getRouterTools>;
571
+ let mockContext: ReturnType<typeof createMockRequestContext>;
572
+
573
+ beforeEach(() => {
574
+ vi.clearAllMocks();
575
+ tools = getRouterTools(createMockMySQLAdapter() as unknown as MySQLAdapter);
576
+ mockContext = createMockRequestContext();
577
+ });
578
+
579
+ it("should return structured error for invalid routeName type", async () => {
580
+ const tool = tools.find((t) => t.name === "mysql_router_route_status")!;
581
+ const result = await tool.handler({ routeName: 123 }, mockContext);
582
+
583
+ expect(result).toHaveProperty("success", false);
584
+ expect(result).toHaveProperty("error");
585
+ });
586
+
587
+ it("should return structured error for invalid metadataName type", async () => {
588
+ const tool = tools.find((t) => t.name === "mysql_router_metadata_status")!;
589
+ const result = await tool.handler({ metadataName: true }, mockContext);
590
+
591
+ expect(result).toHaveProperty("success", false);
592
+ expect(result).toHaveProperty("error");
593
+ });
594
+ });
595
+
569
596
  describe("Authentication and TLS Handling", () => {
570
597
  let originalEnv: NodeJS.ProcessEnv;
571
598
 
@@ -101,8 +101,19 @@ describe("Security Tools", () => {
101
101
  const tool = tools.find((t) => t.name === "mysql_security_audit");
102
102
  const result = (await tool?.handler({}, mockContext)) as any;
103
103
 
104
+ expect(result.success).toBe(false);
105
+ expect(result.error).toBe("Connect error");
106
+ });
107
+
108
+ it("should include error field in access-denied response", async () => {
109
+ mockAdapter.executeQuery.mockRejectedValue(new Error("Access denied"));
110
+
111
+ const tool = tools.find((t) => t.name === "mysql_security_audit");
112
+ const result = (await tool?.handler({}, mockContext)) as any;
113
+
114
+ expect(result.success).toBe(false);
115
+ expect(result.error).toContain("Audit logging is not enabled");
104
116
  expect(result.available).toBe(false);
105
- expect(result.message).toContain("Audit logging is not enabled");
106
117
  });
107
118
  });
108
119
 
@@ -153,7 +164,9 @@ describe("Security Tools", () => {
153
164
  );
154
165
  const result = (await tool?.handler({}, mockContext)) as any;
155
166
 
167
+ expect(result.success).toBe(false);
156
168
  expect(result.available).toBe(false);
169
+ expect(result.error).toContain("Firewall tables not accessible");
157
170
  });
158
171
  });
159
172
 
@@ -200,8 +213,9 @@ describe("Security Tools", () => {
200
213
  );
201
214
  const result = (await tool?.handler({}, mockContext)) as any;
202
215
 
216
+ expect(result.success).toBe(false);
203
217
  expect(result.installed).toBe(false);
204
- expect(result.message).toBe("Firewall plugin check failed");
218
+ expect(result.error).toContain("Firewall plugin check failed");
205
219
  });
206
220
  });
207
221
 
@@ -501,6 +515,27 @@ describe("Security Tools", () => {
501
515
  expect(result.sslEnabled).toBe(false);
502
516
  expect(result.currentCipher).toBe("None");
503
517
  });
518
+
519
+ it("should return 'None' for empty cipher string", async () => {
520
+ // Status with empty Ssl_cipher (SSL disabled but variable present)
521
+ mockAdapter.executeQuery.mockResolvedValueOnce(
522
+ createMockQueryResult([
523
+ { Variable_name: "Ssl_cipher", Value: "" },
524
+ { Variable_name: "Ssl_version", Value: "" },
525
+ ]),
526
+ );
527
+ // Variables
528
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
529
+ // Connection
530
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
531
+
532
+ const tool = tools.find((t) => t.name === "mysql_security_ssl_status");
533
+ const result = (await tool?.handler({}, mockContext)) as any;
534
+
535
+ expect(result.sslEnabled).toBe(false);
536
+ expect(result.currentCipher).toBe("None");
537
+ expect(result.sslVersion).toBe("N/A");
538
+ });
504
539
  });
505
540
 
506
541
  describe("mysql_security_user_privileges", () => {
@@ -788,4 +823,93 @@ describe("Security Tools", () => {
788
823
  expect(result.encryptionSettings).toEqual({ "": "invalid" });
789
824
  });
790
825
  });
826
+
827
+ describe("Error handling (try/catch wrapping)", () => {
828
+ it("mysql_security_ssl_status should return structured error on query failure", async () => {
829
+ mockAdapter.executeQuery.mockRejectedValue(new Error("Access denied"));
830
+
831
+ const tool = tools.find((t) => t.name === "mysql_security_ssl_status");
832
+ const result = (await tool?.handler({}, mockContext)) as any;
833
+
834
+ expect(result.success).toBe(false);
835
+ expect(result.error).toBe("Access denied");
836
+ });
837
+
838
+ it("mysql_security_encryption_status should return structured error on query failure", async () => {
839
+ mockAdapter.executeQuery.mockRejectedValue(
840
+ new Error("Query failed: Execute failed: Access denied"),
841
+ );
842
+
843
+ const tool = tools.find(
844
+ (t) => t.name === "mysql_security_encryption_status",
845
+ );
846
+ const result = (await tool?.handler({}, mockContext)) as any;
847
+
848
+ expect(result.success).toBe(false);
849
+ expect(result.error).toBe("Access denied");
850
+ });
851
+
852
+ it("mysql_security_user_privileges should return structured error on query failure", async () => {
853
+ mockAdapter.executeQuery.mockRejectedValue(
854
+ new Error("Query failed: Access denied to mysql.user"),
855
+ );
856
+
857
+ const tool = tools.find(
858
+ (t) => t.name === "mysql_security_user_privileges",
859
+ );
860
+ const result = (await tool?.handler({}, mockContext)) as any;
861
+
862
+ expect(result.success).toBe(false);
863
+ expect(result.error).toBe("Access denied to mysql.user");
864
+ });
865
+
866
+ it("mysql_security_sensitive_tables should return structured error on query failure", async () => {
867
+ mockAdapter.executeQuery.mockRejectedValue(
868
+ new Error("Execute failed: Connection lost"),
869
+ );
870
+
871
+ const tool = tools.find(
872
+ (t) => t.name === "mysql_security_sensitive_tables",
873
+ );
874
+ const result = (await tool?.handler({}, mockContext)) as any;
875
+
876
+ expect(result.success).toBe(false);
877
+ expect(result.error).toBe("Connection lost");
878
+ });
879
+
880
+ it("mysql_security_user_privileges should use backtick-quoted identifiers in SHOW GRANTS", async () => {
881
+ // Setup: one user returned
882
+ mockAdapter.executeQuery.mockResolvedValueOnce(
883
+ createMockQueryResult([
884
+ {
885
+ User: "test_user",
886
+ Host: "localhost",
887
+ plugin: "caching_sha2_password",
888
+ account_locked: "N",
889
+ },
890
+ ]),
891
+ );
892
+ // SHOW GRANTS
893
+ mockAdapter.executeQuery.mockResolvedValueOnce(
894
+ createMockQueryResult([
895
+ {
896
+ "Grants for test_user@localhost":
897
+ "GRANT USAGE ON *.* TO `test_user`@`localhost`",
898
+ },
899
+ ]),
900
+ );
901
+ // Role edges
902
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
903
+
904
+ const tool = tools.find(
905
+ (t) => t.name === "mysql_security_user_privileges",
906
+ );
907
+ await tool?.handler({}, mockContext);
908
+
909
+ // The SHOW GRANTS call is the second call (index 1)
910
+ const grantsCall = mockAdapter.executeQuery.mock.calls[1][0] as string;
911
+ expect(grantsCall).toContain("`test_user`@`localhost`");
912
+ expect(grantsCall).not.toContain("'test_user'@'localhost'");
913
+ });
914
+ });
791
915
  });
@@ -28,94 +28,100 @@ describe("Security: SQL Injection Prevention", () => {
28
28
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
29
29
  const exportTool = tools.find((t) => t.name === "mysql_export_table")!;
30
30
 
31
- await expect(
32
- exportTool.handler(
33
- {
34
- table: "users; DROP TABLE users",
35
- format: "SQL",
36
- },
37
- mockContext,
38
- ),
39
- ).rejects.toThrow("Invalid table name");
31
+ const result = (await exportTool.handler(
32
+ {
33
+ table: "users; DROP TABLE users",
34
+ format: "SQL",
35
+ },
36
+ mockContext,
37
+ )) as { success: boolean; error: string };
38
+
39
+ expect(result.success).toBe(false);
40
+ expect(result.error).toContain("Invalid table name");
40
41
  });
41
42
 
42
43
  it("should reject table name starting with number", async () => {
43
44
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
44
45
  const exportTool = tools.find((t) => t.name === "mysql_export_table")!;
45
46
 
46
- await expect(
47
- exportTool.handler(
48
- {
49
- table: "123users",
50
- format: "SQL",
51
- },
52
- mockContext,
53
- ),
54
- ).rejects.toThrow("Invalid table name");
47
+ const result = (await exportTool.handler(
48
+ {
49
+ table: "123users",
50
+ format: "SQL",
51
+ },
52
+ mockContext,
53
+ )) as { success: boolean; error: string };
54
+
55
+ expect(result.success).toBe(false);
56
+ expect(result.error).toContain("Invalid table name");
55
57
  });
56
58
 
57
59
  it("should reject WHERE clause with stacked queries", async () => {
58
60
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
59
61
  const exportTool = tools.find((t) => t.name === "mysql_export_table")!;
60
62
 
61
- await expect(
62
- exportTool.handler(
63
- {
64
- table: "users",
65
- format: "SQL",
66
- where: "1=1; DROP TABLE users",
67
- },
68
- mockContext,
69
- ),
70
- ).rejects.toThrow("dangerous SQL patterns");
63
+ const result = (await exportTool.handler(
64
+ {
65
+ table: "users",
66
+ format: "SQL",
67
+ where: "1=1; DROP TABLE users",
68
+ },
69
+ mockContext,
70
+ )) as { success: boolean; error: string };
71
+
72
+ expect(result.success).toBe(false);
73
+ expect(result.error).toContain("dangerous SQL patterns");
71
74
  });
72
75
 
73
76
  it("should reject WHERE clause with UNION attack", async () => {
74
77
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
75
78
  const exportTool = tools.find((t) => t.name === "mysql_export_table")!;
76
79
 
77
- await expect(
78
- exportTool.handler(
79
- {
80
- table: "users",
81
- format: "SQL",
82
- where: "1=1 UNION SELECT password FROM admin",
83
- },
84
- mockContext,
85
- ),
86
- ).rejects.toThrow("dangerous SQL patterns");
80
+ const result = (await exportTool.handler(
81
+ {
82
+ table: "users",
83
+ format: "SQL",
84
+ where: "1=1 UNION SELECT password FROM admin",
85
+ },
86
+ mockContext,
87
+ )) as { success: boolean; error: string };
88
+
89
+ expect(result.success).toBe(false);
90
+ expect(result.error).toContain("dangerous SQL patterns");
87
91
  });
88
92
 
89
93
  it("should reject WHERE clause with timing attack (SLEEP)", async () => {
90
94
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
91
95
  const exportTool = tools.find((t) => t.name === "mysql_export_table")!;
92
96
 
93
- await expect(
94
- exportTool.handler(
95
- {
96
- table: "users",
97
- format: "SQL",
98
- where: "1=1 AND SLEEP(5)",
99
- },
100
- mockContext,
101
- ),
102
- ).rejects.toThrow("dangerous SQL patterns");
97
+ const result = (await exportTool.handler(
98
+ {
99
+ table: "users",
100
+ format: "SQL",
101
+ where: "1=1 AND SLEEP(5)",
102
+ },
103
+ mockContext,
104
+ )) as { success: boolean; error: string };
105
+
106
+ expect(result.success).toBe(false);
107
+ expect(result.error).toContain("dangerous SQL patterns");
103
108
  });
104
109
 
105
110
  it("should reject WHERE clause with unbalanced quotes", async () => {
106
111
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
107
112
  const exportTool = tools.find((t) => t.name === "mysql_export_table")!;
108
113
 
109
- await expect(
110
- exportTool.handler(
111
- {
112
- table: "users",
113
- format: "SQL",
114
- where: "id = 1 OR '1'='1",
115
- },
116
- mockContext,
117
- ),
118
- ).rejects.toThrow("unbalanced");
114
+ const result = (await exportTool.handler(
115
+ {
116
+ table: "users",
117
+ format: "SQL",
118
+ where: "id = 1 OR '1'='1",
119
+ },
120
+ mockContext,
121
+ )) as { success: boolean; error: string };
122
+
123
+ expect(result.success).toBe(false);
124
+ expect(result.error).toContain("unbalanced");
119
125
  });
120
126
 
121
127
  it("should accept valid table and WHERE", async () => {
@@ -142,30 +148,32 @@ describe("Security: SQL Injection Prevention", () => {
142
148
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
143
149
  const importTool = tools.find((t) => t.name === "mysql_import_data")!;
144
150
 
145
- await expect(
146
- importTool.handler(
147
- {
148
- table: "users`; DROP TABLE users; --",
149
- data: [{ id: 1, name: "test" }],
150
- },
151
- mockContext,
152
- ),
153
- ).rejects.toThrow("Invalid table name");
151
+ const result = (await importTool.handler(
152
+ {
153
+ table: "users`; DROP TABLE users; --",
154
+ data: [{ id: 1, name: "test" }],
155
+ },
156
+ mockContext,
157
+ )) as { success: boolean; error: string };
158
+
159
+ expect(result.success).toBe(false);
160
+ expect(result.error).toContain("Invalid table name");
154
161
  });
155
162
 
156
163
  it("should reject column name with injection", async () => {
157
164
  const tools = getBackupTools(mockAdapter as unknown as MySQLAdapter);
158
165
  const importTool = tools.find((t) => t.name === "mysql_import_data")!;
159
166
 
160
- await expect(
161
- importTool.handler(
162
- {
163
- table: "users",
164
- data: [{ "id; DROP TABLE": 1 }],
165
- },
166
- mockContext,
167
- ),
168
- ).rejects.toThrow("Invalid column name");
167
+ const result = (await importTool.handler(
168
+ {
169
+ table: "users",
170
+ data: [{ "id; DROP TABLE": 1 }],
171
+ },
172
+ mockContext,
173
+ )) as { success: boolean; error: string };
174
+
175
+ expect(result.success).toBe(false);
176
+ expect(result.error).toContain("Invalid column name");
169
177
  });
170
178
  });
171
179