@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.
- package/.dockerignore +1 -0
- package/.gitattributes +18 -0
- package/.github/workflows/codeql.yml +2 -10
- package/.github/workflows/docker-publish.yml +15 -13
- package/CHANGELOG.md +287 -1
- package/DOCKER_README.md +100 -265
- package/Dockerfile +5 -0
- package/README.md +124 -59
- package/VERSION +1 -1
- package/dist/__tests__/mocks/adapter.d.ts.map +1 -1
- package/dist/__tests__/mocks/adapter.js +2 -0
- package/dist/__tests__/mocks/adapter.js.map +1 -1
- package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
- package/dist/adapters/DatabaseAdapter.js +50 -9
- package/dist/adapters/DatabaseAdapter.js.map +1 -1
- package/dist/adapters/mysql/MySQLAdapter.d.ts +6 -0
- package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
- package/dist/adapters/mysql/MySQLAdapter.js +8 -0
- package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
- package/dist/adapters/mysql/SchemaManager.js +16 -15
- package/dist/adapters/mysql/SchemaManager.js.map +1 -1
- package/dist/adapters/mysql/prompts/index.js +10 -20
- package/dist/adapters/mysql/prompts/index.js.map +1 -1
- package/dist/adapters/mysql/prompts/proxysqlSetup.js +1 -1
- package/dist/adapters/mysql/resources/docstore.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/docstore.js +10 -7
- package/dist/adapters/mysql/resources/docstore.js.map +1 -1
- package/dist/adapters/mysql/resources/events.js +11 -8
- package/dist/adapters/mysql/resources/events.js.map +1 -1
- package/dist/adapters/mysql/resources/indexes.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/indexes.js +12 -15
- package/dist/adapters/mysql/resources/indexes.js.map +1 -1
- package/dist/adapters/mysql/resources/innodb.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/innodb.js +20 -17
- package/dist/adapters/mysql/resources/innodb.js.map +1 -1
- package/dist/adapters/mysql/resources/locks.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/locks.js +9 -6
- package/dist/adapters/mysql/resources/locks.js.map +1 -1
- package/dist/adapters/mysql/resources/performance.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/performance.js +15 -15
- package/dist/adapters/mysql/resources/performance.js.map +1 -1
- package/dist/adapters/mysql/resources/spatial.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/spatial.js +9 -6
- package/dist/adapters/mysql/resources/spatial.js.map +1 -1
- package/dist/adapters/mysql/resources/sysschema.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/sysschema.js +12 -9
- package/dist/adapters/mysql/resources/sysschema.js.map +1 -1
- package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/admin/backup.js +170 -121
- package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
- package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/admin/maintenance.js +106 -57
- package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
- package/dist/adapters/mysql/tools/admin/monitoring.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/admin/monitoring.js +183 -101
- package/dist/adapters/mysql/tools/admin/monitoring.js.map +1 -1
- package/dist/adapters/mysql/tools/cluster/group-replication.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/cluster/group-replication.js +164 -120
- package/dist/adapters/mysql/tools/cluster/group-replication.js.map +1 -1
- package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +212 -145
- package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
- package/dist/adapters/mysql/tools/codemode/index.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/codemode/index.js +6 -4
- package/dist/adapters/mysql/tools/codemode/index.js.map +1 -1
- package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/core.js +152 -29
- package/dist/adapters/mysql/tools/core.js.map +1 -1
- package/dist/adapters/mysql/tools/docstore.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/docstore.js +340 -163
- package/dist/adapters/mysql/tools/docstore.js.map +1 -1
- package/dist/adapters/mysql/tools/events.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/events.js +284 -198
- package/dist/adapters/mysql/tools/events.js.map +1 -1
- package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/json/core.js +11 -39
- package/dist/adapters/mysql/tools/json/core.js.map +1 -1
- package/dist/adapters/mysql/tools/json/enhanced.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/json/enhanced.js +15 -33
- package/dist/adapters/mysql/tools/json/enhanced.js.map +1 -1
- package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/json/helpers.js +13 -24
- package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
- package/dist/adapters/mysql/tools/partitioning.js +3 -0
- package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
- package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/performance/analysis.js +89 -60
- package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
- package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/performance/optimization.js +151 -127
- package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
- package/dist/adapters/mysql/tools/proxysql.d.ts +1 -1
- package/dist/adapters/mysql/tools/proxysql.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/proxysql.js +289 -176
- package/dist/adapters/mysql/tools/proxysql.js.map +1 -1
- package/dist/adapters/mysql/tools/replication.js +75 -49
- package/dist/adapters/mysql/tools/replication.js.map +1 -1
- package/dist/adapters/mysql/tools/roles.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/roles.js +224 -182
- package/dist/adapters/mysql/tools/roles.js.map +1 -1
- package/dist/adapters/mysql/tools/router.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/router.js +168 -67
- package/dist/adapters/mysql/tools/router.js.map +1 -1
- package/dist/adapters/mysql/tools/schema/constraints.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/schema/constraints.js +21 -3
- package/dist/adapters/mysql/tools/schema/constraints.js.map +1 -1
- package/dist/adapters/mysql/tools/schema/management.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/schema/management.js +61 -14
- package/dist/adapters/mysql/tools/schema/management.js.map +1 -1
- package/dist/adapters/mysql/tools/schema/routines.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/schema/routines.js +27 -4
- package/dist/adapters/mysql/tools/schema/routines.js.map +1 -1
- package/dist/adapters/mysql/tools/schema/scheduled_events.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/schema/scheduled_events.js +24 -3
- package/dist/adapters/mysql/tools/schema/scheduled_events.js.map +1 -1
- package/dist/adapters/mysql/tools/schema/triggers.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/schema/triggers.js +23 -2
- package/dist/adapters/mysql/tools/schema/triggers.js.map +1 -1
- package/dist/adapters/mysql/tools/schema/views.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/schema/views.js +47 -7
- package/dist/adapters/mysql/tools/schema/views.js.map +1 -1
- package/dist/adapters/mysql/tools/security/audit.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/security/audit.js +102 -34
- package/dist/adapters/mysql/tools/security/audit.js.map +1 -1
- package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/security/data-protection.js +264 -205
- package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
- package/dist/adapters/mysql/tools/security/encryption.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/security/encryption.js +137 -104
- package/dist/adapters/mysql/tools/security/encryption.js.map +1 -1
- package/dist/adapters/mysql/tools/shell/backup.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/shell/backup.js +71 -59
- package/dist/adapters/mysql/tools/shell/backup.js.map +1 -1
- package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/shell/restore.js +61 -47
- package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
- package/dist/adapters/mysql/tools/spatial/geometry.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/spatial/geometry.js +19 -5
- package/dist/adapters/mysql/tools/spatial/geometry.js.map +1 -1
- package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/spatial/operations.js +42 -17
- package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
- package/dist/adapters/mysql/tools/spatial/queries.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/spatial/queries.js +109 -57
- package/dist/adapters/mysql/tools/spatial/queries.js.map +1 -1
- package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/spatial/setup.js +103 -50
- package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
- package/dist/adapters/mysql/tools/stats/comparative.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/stats/comparative.js +128 -79
- package/dist/adapters/mysql/tools/stats/comparative.js.map +1 -1
- package/dist/adapters/mysql/tools/stats/descriptive.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/stats/descriptive.js +174 -102
- package/dist/adapters/mysql/tools/stats/descriptive.js.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/activity.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/activity.js +50 -25
- package/dist/adapters/mysql/tools/sysschema/activity.js.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/performance.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/performance.js +121 -66
- package/dist/adapters/mysql/tools/sysschema/performance.js.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/resources.js +101 -64
- package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
- package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/text/fulltext.js +18 -32
- package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
- package/dist/adapters/mysql/tools/transactions.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/transactions.js +48 -23
- package/dist/adapters/mysql/tools/transactions.js.map +1 -1
- package/dist/adapters/mysql/types/proxysql-types.d.ts +15 -0
- package/dist/adapters/mysql/types/proxysql-types.d.ts.map +1 -1
- package/dist/adapters/mysql/types/proxysql-types.js +33 -1
- package/dist/adapters/mysql/types/proxysql-types.js.map +1 -1
- package/dist/adapters/mysql/types/router-types.d.ts +1 -1
- package/dist/adapters/mysql/types/router-types.js +1 -1
- package/dist/adapters/mysql/types/router-types.js.map +1 -1
- package/dist/adapters/mysql/types/shell-types.js +2 -2
- package/dist/adapters/mysql/types/shell-types.js.map +1 -1
- package/dist/adapters/mysql/types.d.ts +485 -21
- package/dist/adapters/mysql/types.d.ts.map +1 -1
- package/dist/adapters/mysql/types.js +546 -19
- package/dist/adapters/mysql/types.js.map +1 -1
- package/dist/auth/scopes.js +1 -1
- package/dist/auth/scopes.js.map +1 -1
- package/dist/codemode/api.d.ts +3 -2
- package/dist/codemode/api.d.ts.map +1 -1
- package/dist/codemode/api.js +80 -5
- package/dist/codemode/api.js.map +1 -1
- package/dist/codemode/sandbox-factory.js +1 -1
- package/dist/codemode/sandbox-factory.js.map +1 -1
- package/dist/codemode/types.d.ts +26 -0
- package/dist/codemode/types.d.ts.map +1 -1
- package/dist/codemode/types.js +2 -0
- package/dist/codemode/types.js.map +1 -1
- package/dist/codemode/worker-sandbox.d.ts +4 -2
- package/dist/codemode/worker-sandbox.d.ts.map +1 -1
- package/dist/codemode/worker-sandbox.js +66 -7
- package/dist/codemode/worker-sandbox.js.map +1 -1
- package/dist/codemode/worker-script.d.ts +3 -0
- package/dist/codemode/worker-script.d.ts.map +1 -1
- package/dist/codemode/worker-script.js +128 -75
- package/dist/codemode/worker-script.js.map +1 -1
- package/dist/constants/ServerInstructions.d.ts +1 -1
- package/dist/constants/ServerInstructions.d.ts.map +1 -1
- package/dist/constants/ServerInstructions.js +37 -31
- package/dist/constants/ServerInstructions.js.map +1 -1
- package/dist/filtering/ToolConstants.d.ts +1 -1
- package/dist/filtering/ToolConstants.d.ts.map +1 -1
- package/dist/filtering/ToolConstants.js +1 -2
- package/dist/filtering/ToolConstants.js.map +1 -1
- package/dist/pool/ConnectionPool.d.ts.map +1 -1
- package/dist/pool/ConnectionPool.js.map +1 -1
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +6 -0
- package/dist/transports/http.js.map +1 -1
- package/dist/utils/validators.d.ts +1 -1
- package/dist/utils/validators.d.ts.map +1 -1
- package/dist/utils/validators.js.map +1 -1
- package/package.json +4 -4
- package/releases/v2.3.0-release-notes.md +20 -20
- package/releases/v2.3.1-release-notes.md +34 -0
- package/releases/v3.0.0-release-notes.md +81 -0
- package/src/__tests__/mocks/adapter.ts +3 -0
- package/src/__tests__/perf.test.ts +6 -6
- package/src/adapters/DatabaseAdapter.ts +58 -9
- package/src/adapters/__tests__/DatabaseAdapter.test.ts +89 -8
- package/src/adapters/mysql/MySQLAdapter.ts +17 -2
- package/src/adapters/mysql/SchemaManager.ts +21 -21
- package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +1 -1
- package/src/adapters/mysql/prompts/index.ts +12 -22
- package/src/adapters/mysql/prompts/proxysqlSetup.ts +1 -1
- package/src/adapters/mysql/resources/docstore.ts +13 -10
- package/src/adapters/mysql/resources/events.ts +12 -12
- package/src/adapters/mysql/resources/indexes.ts +17 -19
- package/src/adapters/mysql/resources/innodb.ts +23 -22
- package/src/adapters/mysql/resources/locks.ts +9 -7
- package/src/adapters/mysql/resources/performance.ts +23 -18
- package/src/adapters/mysql/resources/spatial.ts +9 -7
- package/src/adapters/mysql/resources/sysschema.ts +12 -11
- package/src/adapters/mysql/tools/__tests__/core.test.ts +126 -55
- package/src/adapters/mysql/tools/__tests__/docstore.test.ts +459 -88
- package/src/adapters/mysql/tools/__tests__/events.test.ts +281 -103
- package/src/adapters/mysql/tools/__tests__/proxysql.test.ts +128 -28
- package/src/adapters/mysql/tools/__tests__/replication.test.ts +48 -2
- package/src/adapters/mysql/tools/__tests__/roles.test.ts +15 -18
- package/src/adapters/mysql/tools/__tests__/router.test.ts +32 -5
- package/src/adapters/mysql/tools/__tests__/security.test.ts +126 -2
- package/src/adapters/mysql/tools/__tests__/security_injection.test.ts +84 -76
- package/src/adapters/mysql/tools/__tests__/security_integration.test.ts +47 -50
- package/src/adapters/mysql/tools/__tests__/spatial.test.ts +11 -10
- package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +54 -38
- package/src/adapters/mysql/tools/__tests__/stats.test.ts +285 -152
- package/src/adapters/mysql/tools/__tests__/transactions.test.ts +13 -13
- package/src/adapters/mysql/tools/admin/__tests__/backup.test.ts +171 -25
- package/src/adapters/mysql/tools/admin/__tests__/maintenance.test.ts +240 -4
- package/src/adapters/mysql/tools/admin/__tests__/monitoring-summary.test.ts +274 -0
- package/src/adapters/mysql/tools/admin/__tests__/monitoring.test.ts +94 -5
- package/src/adapters/mysql/tools/admin/backup.ts +193 -143
- package/src/adapters/mysql/tools/admin/maintenance.ts +118 -69
- package/src/adapters/mysql/tools/admin/monitoring.ts +201 -125
- package/src/adapters/mysql/tools/cluster/__tests__/group-replication.test.ts +69 -0
- package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +141 -0
- package/src/adapters/mysql/tools/cluster/group-replication.ts +172 -132
- package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +231 -157
- package/src/adapters/mysql/tools/codemode/__tests__/codemode-tool.test.ts +227 -0
- package/src/adapters/mysql/tools/codemode/index.ts +5 -3
- package/src/adapters/mysql/tools/core.ts +152 -38
- package/src/adapters/mysql/tools/docstore.ts +422 -205
- package/src/adapters/mysql/tools/events.ts +334 -233
- package/src/adapters/mysql/tools/json/__tests__/core.test.ts +20 -0
- package/src/adapters/mysql/tools/json/__tests__/enhanced.test.ts +82 -50
- package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +42 -3
- package/src/adapters/mysql/tools/json/core.ts +21 -42
- package/src/adapters/mysql/tools/json/enhanced.ts +22 -37
- package/src/adapters/mysql/tools/json/helpers.ts +21 -25
- package/src/adapters/mysql/tools/partitioning.ts +3 -0
- package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +98 -5
- package/src/adapters/mysql/tools/performance/__tests__/optimization-coverage.test.ts +515 -0
- package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +187 -0
- package/src/adapters/mysql/tools/performance/analysis.ts +95 -69
- package/src/adapters/mysql/tools/performance/optimization.ts +182 -153
- package/src/adapters/mysql/tools/proxysql.ts +314 -209
- package/src/adapters/mysql/tools/replication.ts +84 -57
- package/src/adapters/mysql/tools/roles.ts +274 -226
- package/src/adapters/mysql/tools/router.ts +181 -85
- package/src/adapters/mysql/tools/schema/__tests__/constraints.test.ts +13 -0
- package/src/adapters/mysql/tools/schema/__tests__/management.test.ts +60 -25
- package/src/adapters/mysql/tools/schema/__tests__/scheduled_events.test.ts +11 -0
- package/src/adapters/mysql/tools/schema/__tests__/triggers.test.ts +25 -4
- package/src/adapters/mysql/tools/schema/__tests__/views.test.ts +46 -14
- package/src/adapters/mysql/tools/schema/constraints.ts +22 -3
- package/src/adapters/mysql/tools/schema/management.ts +60 -15
- package/src/adapters/mysql/tools/schema/routines.ts +26 -4
- package/src/adapters/mysql/tools/schema/scheduled_events.ts +25 -3
- package/src/adapters/mysql/tools/schema/triggers.ts +27 -2
- package/src/adapters/mysql/tools/schema/views.ts +46 -8
- package/src/adapters/mysql/tools/security/__tests__/audit.test.ts +90 -4
- package/src/adapters/mysql/tools/security/audit.ts +113 -39
- package/src/adapters/mysql/tools/security/data-protection.ts +293 -233
- package/src/adapters/mysql/tools/security/encryption.ts +172 -139
- package/src/adapters/mysql/tools/shell/__tests__/backup.test.ts +29 -0
- package/src/adapters/mysql/tools/shell/backup.ts +90 -73
- package/src/adapters/mysql/tools/shell/restore.ts +62 -48
- package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +22 -14
- package/src/adapters/mysql/tools/spatial/__tests__/queries.test.ts +65 -51
- package/src/adapters/mysql/tools/spatial/geometry.ts +23 -7
- package/src/adapters/mysql/tools/spatial/operations.ts +60 -31
- package/src/adapters/mysql/tools/spatial/queries.ts +142 -65
- package/src/adapters/mysql/tools/spatial/setup.ts +121 -55
- package/src/adapters/mysql/tools/stats/__tests__/comparative.test.ts +12 -10
- package/src/adapters/mysql/tools/stats/comparative.ts +150 -98
- package/src/adapters/mysql/tools/stats/descriptive.ts +204 -127
- package/src/adapters/mysql/tools/sysschema/__tests__/error-paths.test.ts +222 -0
- package/src/adapters/mysql/tools/sysschema/__tests__/performance.test.ts +45 -0
- package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +6 -3
- package/src/adapters/mysql/tools/sysschema/activity.ts +52 -27
- package/src/adapters/mysql/tools/sysschema/performance.ts +132 -68
- package/src/adapters/mysql/tools/sysschema/resources.ts +105 -67
- package/src/adapters/mysql/tools/text/__tests__/fulltext.test.ts +45 -17
- package/src/adapters/mysql/tools/text/fulltext.ts +27 -38
- package/src/adapters/mysql/tools/transactions.ts +49 -24
- package/src/adapters/mysql/types/proxysql-types.ts +38 -1
- package/src/adapters/mysql/types/router-types.ts +1 -1
- package/src/adapters/mysql/types/shell-types.ts +2 -2
- package/src/adapters/mysql/types.ts +632 -19
- package/src/auth/__tests__/scopes.test.ts +2 -2
- package/src/auth/scopes.ts +1 -1
- package/src/codemode/__tests__/api.test.ts +417 -0
- package/src/codemode/__tests__/sandbox-factory.test.ts +158 -0
- package/src/codemode/__tests__/sandbox.test.ts +301 -0
- package/src/codemode/__tests__/security.test.ts +368 -0
- package/src/codemode/__tests__/worker-sandbox.test.ts +179 -0
- package/src/codemode/__tests__/worker-script.test.ts +226 -0
- package/src/codemode/api.ts +89 -5
- package/src/codemode/sandbox-factory.ts +1 -1
- package/src/codemode/types.ts +34 -0
- package/src/codemode/worker-sandbox.ts +74 -7
- package/src/codemode/worker-script.ts +157 -86
- package/src/constants/ServerInstructions.ts +37 -31
- package/src/filtering/ToolConstants.ts +1 -2
- package/src/filtering/__tests__/ToolFilter.test.ts +9 -9
- package/src/pool/ConnectionPool.ts +4 -1
- package/src/transports/__tests__/http.test.ts +15 -3
- package/src/transports/http.ts +12 -0
- package/src/utils/validators.ts +2 -1
- package/vitest.config.ts +3 -1
- package/CODE_MODE.md +0 -245
|
@@ -23,10 +23,30 @@ export function createInnodbResource(
|
|
|
23
23
|
priority: 0.7,
|
|
24
24
|
},
|
|
25
25
|
handler: async (_uri: string, _context: RequestContext) => {
|
|
26
|
-
//
|
|
27
|
-
const bufferPoolResult = await
|
|
26
|
+
// Performance optimization: run all three independent queries in parallel
|
|
27
|
+
const [bufferPoolResult, configResult, opsResult] = await Promise.all([
|
|
28
|
+
// Get buffer pool status
|
|
29
|
+
adapter.executeQuery(`
|
|
28
30
|
SHOW GLOBAL STATUS WHERE Variable_name LIKE 'Innodb_buffer_pool%'
|
|
29
|
-
`)
|
|
31
|
+
`),
|
|
32
|
+
// Get buffer pool size configuration
|
|
33
|
+
adapter.executeQuery(`
|
|
34
|
+
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
|
|
35
|
+
'innodb_buffer_pool_size', 'innodb_buffer_pool_instances',
|
|
36
|
+
'innodb_log_file_size', 'innodb_log_files_in_group',
|
|
37
|
+
'innodb_flush_log_at_trx_commit', 'innodb_file_per_table'
|
|
38
|
+
)
|
|
39
|
+
`),
|
|
40
|
+
// Get row operations
|
|
41
|
+
adapter.executeQuery(`
|
|
42
|
+
SHOW GLOBAL STATUS WHERE Variable_name IN (
|
|
43
|
+
'Innodb_rows_read', 'Innodb_rows_inserted',
|
|
44
|
+
'Innodb_rows_updated', 'Innodb_rows_deleted',
|
|
45
|
+
'Innodb_data_reads', 'Innodb_data_writes',
|
|
46
|
+
'Innodb_os_log_written', 'Innodb_log_writes'
|
|
47
|
+
)
|
|
48
|
+
`),
|
|
49
|
+
]);
|
|
30
50
|
|
|
31
51
|
const bufferPool: Record<string, number> = {};
|
|
32
52
|
for (const row of bufferPoolResult.rows ?? []) {
|
|
@@ -36,30 +56,11 @@ export function createInnodbResource(
|
|
|
36
56
|
);
|
|
37
57
|
}
|
|
38
58
|
|
|
39
|
-
// Get buffer pool size configuration
|
|
40
|
-
const configResult = await adapter.executeQuery(`
|
|
41
|
-
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
|
|
42
|
-
'innodb_buffer_pool_size', 'innodb_buffer_pool_instances',
|
|
43
|
-
'innodb_log_file_size', 'innodb_log_files_in_group',
|
|
44
|
-
'innodb_flush_log_at_trx_commit', 'innodb_file_per_table'
|
|
45
|
-
)
|
|
46
|
-
`);
|
|
47
|
-
|
|
48
59
|
const config: Record<string, string> = {};
|
|
49
60
|
for (const row of configResult.rows ?? []) {
|
|
50
61
|
config[row["Variable_name"] as string] = row["Value"] as string;
|
|
51
62
|
}
|
|
52
63
|
|
|
53
|
-
// Get row operations
|
|
54
|
-
const opsResult = await adapter.executeQuery(`
|
|
55
|
-
SHOW GLOBAL STATUS WHERE Variable_name IN (
|
|
56
|
-
'Innodb_rows_read', 'Innodb_rows_inserted',
|
|
57
|
-
'Innodb_rows_updated', 'Innodb_rows_deleted',
|
|
58
|
-
'Innodb_data_reads', 'Innodb_data_writes',
|
|
59
|
-
'Innodb_os_log_written', 'Innodb_log_writes'
|
|
60
|
-
)
|
|
61
|
-
`);
|
|
62
|
-
|
|
63
64
|
const operations: Record<string, number> = {};
|
|
64
65
|
for (const row of opsResult.rows ?? []) {
|
|
65
66
|
operations[row["Variable_name"] as string] = parseInt(
|
|
@@ -20,8 +20,10 @@ export function createLocksResource(adapter: MySQLAdapter): ResourceDefinition {
|
|
|
20
20
|
},
|
|
21
21
|
handler: async (_uri: string, _context: RequestContext) => {
|
|
22
22
|
try {
|
|
23
|
-
//
|
|
24
|
-
const lockWaitsResult = await
|
|
23
|
+
// Performance optimization: run both independent queries in parallel
|
|
24
|
+
const [lockWaitsResult, lockStatusResult] = await Promise.all([
|
|
25
|
+
// Get current lock waits from performance_schema
|
|
26
|
+
adapter.executeQuery(`
|
|
25
27
|
SELECT
|
|
26
28
|
r.trx_id AS waiting_trx_id,
|
|
27
29
|
r.trx_mysql_thread_id AS waiting_thread,
|
|
@@ -34,12 +36,12 @@ export function createLocksResource(adapter: MySQLAdapter): ResourceDefinition {
|
|
|
34
36
|
JOIN information_schema.innodb_trx r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID
|
|
35
37
|
JOIN information_schema.innodb_trx b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID
|
|
36
38
|
LIMIT 20
|
|
37
|
-
`)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const lockStatusResult = await adapter.executeQuery(`
|
|
39
|
+
`),
|
|
40
|
+
// Get global lock status
|
|
41
|
+
adapter.executeQuery(`
|
|
41
42
|
SHOW STATUS LIKE 'Innodb_row_lock%'
|
|
42
|
-
`)
|
|
43
|
+
`),
|
|
44
|
+
]);
|
|
43
45
|
|
|
44
46
|
const lockStats: Record<string, unknown> = {};
|
|
45
47
|
for (const row of lockStatusResult.rows ?? []) {
|
|
@@ -23,8 +23,9 @@ export function createPerformanceResource(
|
|
|
23
23
|
priority: 0.8,
|
|
24
24
|
},
|
|
25
25
|
handler: async (_uri: string, _context: RequestContext) => {
|
|
26
|
-
//
|
|
27
|
-
|
|
26
|
+
// Performance optimization: run both queries in parallel
|
|
27
|
+
// The performance_schema query may fail, but we handle that gracefully
|
|
28
|
+
const statusPromise = adapter.executeQuery(`
|
|
28
29
|
SHOW GLOBAL STATUS WHERE Variable_name IN (
|
|
29
30
|
'Queries', 'Questions', 'Slow_queries',
|
|
30
31
|
'Select_full_join', 'Select_range_check', 'Select_scan',
|
|
@@ -35,18 +36,9 @@ export function createPerformanceResource(
|
|
|
35
36
|
)
|
|
36
37
|
`);
|
|
37
38
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
row["Value"] as string,
|
|
42
|
-
10,
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Get performance schema if available (MySQL 5.6+)
|
|
47
|
-
let topQueries: unknown[] = [];
|
|
48
|
-
try {
|
|
49
|
-
const perfResult = await adapter.executeQuery(`
|
|
39
|
+
const perfPromise = adapter
|
|
40
|
+
.executeQuery(
|
|
41
|
+
`
|
|
50
42
|
SELECT
|
|
51
43
|
DIGEST_TEXT as query_pattern,
|
|
52
44
|
COUNT_STAR as execution_count,
|
|
@@ -59,12 +51,25 @@ export function createPerformanceResource(
|
|
|
59
51
|
WHERE DIGEST_TEXT IS NOT NULL
|
|
60
52
|
ORDER BY SUM_TIMER_WAIT DESC
|
|
61
53
|
LIMIT 10
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
`,
|
|
55
|
+
)
|
|
56
|
+
.catch(() => ({ rows: [] as Record<string, unknown>[] }));
|
|
57
|
+
|
|
58
|
+
const [statusResult, perfResult] = await Promise.all([
|
|
59
|
+
statusPromise,
|
|
60
|
+
perfPromise,
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
const status: Record<string, number> = {};
|
|
64
|
+
for (const row of statusResult.rows ?? []) {
|
|
65
|
+
status[row["Variable_name"] as string] = parseInt(
|
|
66
|
+
row["Value"] as string,
|
|
67
|
+
10,
|
|
68
|
+
);
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
const topQueries = perfResult.rows ?? [];
|
|
72
|
+
|
|
68
73
|
// Calculate derived metrics
|
|
69
74
|
const tmpTablesCreated = status["Created_tmp_tables"] ?? 0;
|
|
70
75
|
const tmpDiskRatio =
|
|
@@ -21,8 +21,10 @@ export function createSpatialResource(
|
|
|
21
21
|
priority: 0.5,
|
|
22
22
|
},
|
|
23
23
|
handler: async (_uri: string, _context: RequestContext) => {
|
|
24
|
-
//
|
|
25
|
-
const columnsResult = await
|
|
24
|
+
// Performance optimization: run both independent queries in parallel
|
|
25
|
+
const [columnsResult, indexesResult] = await Promise.all([
|
|
26
|
+
// Get spatial columns
|
|
27
|
+
adapter.executeQuery(`
|
|
26
28
|
SELECT
|
|
27
29
|
TABLE_SCHEMA as schema_name,
|
|
28
30
|
TABLE_NAME as table_name,
|
|
@@ -34,10 +36,9 @@ export function createSpatialResource(
|
|
|
34
36
|
'multipoint', 'multilinestring', 'multipolygon', 'geometrycollection')
|
|
35
37
|
AND TABLE_SCHEMA = DATABASE()
|
|
36
38
|
ORDER BY TABLE_NAME, COLUMN_NAME
|
|
37
|
-
`)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const indexesResult = await adapter.executeQuery(`
|
|
39
|
+
`),
|
|
40
|
+
// Get spatial indexes
|
|
41
|
+
adapter.executeQuery(`
|
|
41
42
|
SELECT
|
|
42
43
|
TABLE_NAME as table_name,
|
|
43
44
|
INDEX_NAME as index_name,
|
|
@@ -46,7 +47,8 @@ export function createSpatialResource(
|
|
|
46
47
|
WHERE INDEX_TYPE = 'SPATIAL'
|
|
47
48
|
AND TABLE_SCHEMA = DATABASE()
|
|
48
49
|
ORDER BY TABLE_NAME, INDEX_NAME
|
|
49
|
-
`)
|
|
50
|
+
`),
|
|
51
|
+
]);
|
|
50
52
|
|
|
51
53
|
return {
|
|
52
54
|
spatialColumnCount: columnsResult.rows?.length ?? 0,
|
|
@@ -22,27 +22,28 @@ export function createSysSchemaResource(
|
|
|
22
22
|
},
|
|
23
23
|
handler: async (_uri: string, _context: RequestContext) => {
|
|
24
24
|
try {
|
|
25
|
-
//
|
|
26
|
-
const usersResult = await
|
|
25
|
+
// Performance optimization: run all three independent queries in parallel
|
|
26
|
+
const [usersResult, statementsResult, locksResult] = await Promise.all([
|
|
27
|
+
// Top resource consumers
|
|
28
|
+
adapter.executeQuery(`
|
|
27
29
|
SELECT user, total_connections, current_connections,
|
|
28
30
|
total_memory_allocated as memory_bytes
|
|
29
31
|
FROM sys.user_summary
|
|
30
32
|
ORDER BY total_memory_allocated DESC
|
|
31
33
|
LIMIT 5
|
|
32
|
-
`)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const statementsResult = await adapter.executeQuery(`
|
|
34
|
+
`),
|
|
35
|
+
// Slow statements
|
|
36
|
+
adapter.executeQuery(`
|
|
36
37
|
SELECT SUBSTRING(query, 1, 100) as query_preview,
|
|
37
38
|
exec_count, total_latency, avg_latency
|
|
38
39
|
FROM sys.statements_with_runtimes_in_95th_percentile
|
|
39
40
|
LIMIT 5
|
|
40
|
-
`)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const locksResult = await adapter.executeQuery(`
|
|
41
|
+
`),
|
|
42
|
+
// Current lock waits
|
|
43
|
+
adapter.executeQuery(`
|
|
44
44
|
SELECT COUNT(*) as lock_wait_count FROM sys.innodb_lock_waits
|
|
45
|
-
`)
|
|
45
|
+
`),
|
|
46
|
+
]);
|
|
46
47
|
const lockRow = locksResult.rows?.[0];
|
|
47
48
|
|
|
48
49
|
return {
|
|
@@ -300,6 +300,16 @@ describe("Handler Execution", () => {
|
|
|
300
300
|
|
|
301
301
|
expect(mockAdapter.listTables).toHaveBeenCalled();
|
|
302
302
|
});
|
|
303
|
+
|
|
304
|
+
it("should return exists: false for nonexistent database", async () => {
|
|
305
|
+
mockAdapter.executeReadQuery.mockResolvedValue(createMockQueryResult([]));
|
|
306
|
+
|
|
307
|
+
const tool = tools.find((t) => t.name === "mysql_list_tables")!;
|
|
308
|
+
const result = await tool.handler({ database: "fake_db" }, mockContext);
|
|
309
|
+
|
|
310
|
+
expect(result).toHaveProperty("exists", false);
|
|
311
|
+
expect(result).toHaveProperty("database", "fake_db");
|
|
312
|
+
});
|
|
303
313
|
});
|
|
304
314
|
|
|
305
315
|
describe("mysql_describe_table", () => {
|
|
@@ -380,6 +390,7 @@ describe("Handler Execution", () => {
|
|
|
380
390
|
});
|
|
381
391
|
|
|
382
392
|
it("should handle IF NOT EXISTS clause", async () => {
|
|
393
|
+
mockAdapter.describeTable.mockResolvedValue({ columns: [] });
|
|
383
394
|
mockAdapter.executeQuery.mockResolvedValue({ rows: [], rowsAffected: 0 });
|
|
384
395
|
|
|
385
396
|
const tool = tools.find((t) => t.name === "mysql_create_table")!;
|
|
@@ -458,25 +469,49 @@ describe("Handler Execution", () => {
|
|
|
458
469
|
|
|
459
470
|
expect(result).toHaveProperty("success", false);
|
|
460
471
|
expect(result).toHaveProperty(
|
|
461
|
-
"
|
|
472
|
+
"error",
|
|
462
473
|
"Table 'test_table' already exists",
|
|
463
474
|
);
|
|
464
475
|
});
|
|
465
476
|
|
|
466
|
-
it("should
|
|
477
|
+
it("should return structured error for non-existence errors in create table", async () => {
|
|
467
478
|
mockAdapter.executeQuery.mockRejectedValue(new Error("Access denied"));
|
|
468
479
|
|
|
469
480
|
const tool = tools.find((t) => t.name === "mysql_create_table")!;
|
|
481
|
+
const result = await tool.handler(
|
|
482
|
+
{
|
|
483
|
+
name: "test_table",
|
|
484
|
+
columns: [{ name: "id", type: "INT" }],
|
|
485
|
+
},
|
|
486
|
+
mockContext,
|
|
487
|
+
);
|
|
470
488
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
489
|
+
expect(result).toHaveProperty("success", false);
|
|
490
|
+
expect((result as Record<string, unknown>).error).toContain(
|
|
491
|
+
"Access denied",
|
|
492
|
+
);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it("should return skipped indicator when ifNotExists is true and table exists", async () => {
|
|
496
|
+
mockAdapter.describeTable.mockResolvedValue({
|
|
497
|
+
columns: [{ name: "id", type: "int" }],
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
const tool = tools.find((t) => t.name === "mysql_create_table")!;
|
|
501
|
+
const result = await tool.handler(
|
|
502
|
+
{
|
|
503
|
+
name: "existing_table",
|
|
504
|
+
columns: [{ name: "id", type: "INT" }],
|
|
505
|
+
ifNotExists: true,
|
|
506
|
+
},
|
|
507
|
+
mockContext,
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
expect(result).toHaveProperty("success", true);
|
|
511
|
+
expect(result).toHaveProperty("skipped", true);
|
|
512
|
+
expect(result).toHaveProperty("reason", "Table already exists");
|
|
513
|
+
// Should NOT call executeQuery since it short-circuits
|
|
514
|
+
expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
|
|
480
515
|
});
|
|
481
516
|
});
|
|
482
517
|
|
|
@@ -503,12 +538,14 @@ describe("Handler Execution", () => {
|
|
|
503
538
|
expect(sqlCall).toContain("IF EXISTS");
|
|
504
539
|
});
|
|
505
540
|
|
|
506
|
-
it("should
|
|
541
|
+
it("should return structured error for invalid table names", async () => {
|
|
507
542
|
const tool = tools.find((t) => t.name === "mysql_drop_table")!;
|
|
543
|
+
const result = await tool.handler({ table: "invalid-name" }, mockContext);
|
|
508
544
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
545
|
+
expect(result).toHaveProperty("success", false);
|
|
546
|
+
expect((result as Record<string, unknown>).error).toBe(
|
|
547
|
+
"Invalid table name",
|
|
548
|
+
);
|
|
512
549
|
});
|
|
513
550
|
|
|
514
551
|
it("should handle qualified table names", async () => {
|
|
@@ -518,7 +555,7 @@ describe("Handler Execution", () => {
|
|
|
518
555
|
await tool.handler({ table: "db.table" }, mockContext);
|
|
519
556
|
|
|
520
557
|
const sqlCall = mockAdapter.executeQuery.mock.calls[0]?.[0] as string;
|
|
521
|
-
expect(sqlCall).toContain("DROP TABLE
|
|
558
|
+
expect(sqlCall).toContain("DROP TABLE `db`.`table`");
|
|
522
559
|
});
|
|
523
560
|
|
|
524
561
|
it("should return graceful error when table does not exist", async () => {
|
|
@@ -534,7 +571,7 @@ describe("Handler Execution", () => {
|
|
|
534
571
|
|
|
535
572
|
expect(result).toHaveProperty("success", false);
|
|
536
573
|
expect(result).toHaveProperty(
|
|
537
|
-
"
|
|
574
|
+
"error",
|
|
538
575
|
"Table 'nonexistent' does not exist",
|
|
539
576
|
);
|
|
540
577
|
});
|
|
@@ -554,14 +591,19 @@ describe("Handler Execution", () => {
|
|
|
554
591
|
expect(result).toHaveProperty("reason", "Table did not exist");
|
|
555
592
|
});
|
|
556
593
|
|
|
557
|
-
it("should
|
|
594
|
+
it("should return structured error for non-existence errors in drop table", async () => {
|
|
558
595
|
mockAdapter.executeQuery.mockRejectedValue(new Error("Access denied"));
|
|
559
596
|
|
|
560
597
|
const tool = tools.find((t) => t.name === "mysql_drop_table")!;
|
|
598
|
+
const result = await tool.handler(
|
|
599
|
+
{ table: "some_table", ifExists: false },
|
|
600
|
+
mockContext,
|
|
601
|
+
);
|
|
561
602
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
603
|
+
expect(result).toHaveProperty("success", false);
|
|
604
|
+
expect((result as Record<string, unknown>).error).toContain(
|
|
605
|
+
"Access denied",
|
|
606
|
+
);
|
|
565
607
|
});
|
|
566
608
|
});
|
|
567
609
|
|
|
@@ -629,34 +671,38 @@ describe("Handler Execution", () => {
|
|
|
629
671
|
expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
|
|
630
672
|
});
|
|
631
673
|
|
|
632
|
-
it("should
|
|
674
|
+
it("should return structured error for invalid index names", async () => {
|
|
633
675
|
const tool = tools.find((t) => t.name === "mysql_create_index")!;
|
|
676
|
+
const result = await tool.handler(
|
|
677
|
+
{
|
|
678
|
+
name: "invalid-name",
|
|
679
|
+
table: "users",
|
|
680
|
+
columns: ["email"],
|
|
681
|
+
},
|
|
682
|
+
mockContext,
|
|
683
|
+
);
|
|
634
684
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
table: "users",
|
|
640
|
-
columns: ["email"],
|
|
641
|
-
},
|
|
642
|
-
mockContext,
|
|
643
|
-
),
|
|
644
|
-
).rejects.toThrow("Invalid index name");
|
|
685
|
+
expect(result).toHaveProperty("success", false);
|
|
686
|
+
expect((result as Record<string, unknown>).error).toBe(
|
|
687
|
+
"Invalid index name",
|
|
688
|
+
);
|
|
645
689
|
});
|
|
646
690
|
|
|
647
|
-
it("should
|
|
691
|
+
it("should return structured error for invalid table names", async () => {
|
|
648
692
|
const tool = tools.find((t) => t.name === "mysql_create_index")!;
|
|
693
|
+
const result = await tool.handler(
|
|
694
|
+
{
|
|
695
|
+
name: "valid_name",
|
|
696
|
+
table: "invalid-table",
|
|
697
|
+
columns: ["email"],
|
|
698
|
+
},
|
|
699
|
+
mockContext,
|
|
700
|
+
);
|
|
649
701
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
table: "invalid-table",
|
|
655
|
-
columns: ["email"],
|
|
656
|
-
},
|
|
657
|
-
mockContext,
|
|
658
|
-
),
|
|
659
|
-
).rejects.toThrow("Invalid table name");
|
|
702
|
+
expect(result).toHaveProperty("success", false);
|
|
703
|
+
expect((result as Record<string, unknown>).error).toBe(
|
|
704
|
+
"Invalid table name",
|
|
705
|
+
);
|
|
660
706
|
});
|
|
661
707
|
|
|
662
708
|
it("should handle qualified table names", async () => {
|
|
@@ -714,7 +760,7 @@ describe("Handler Execution", () => {
|
|
|
714
760
|
|
|
715
761
|
expect(result).toHaveProperty("success", false);
|
|
716
762
|
expect(result).toHaveProperty(
|
|
717
|
-
"
|
|
763
|
+
"error",
|
|
718
764
|
"Index 'idx_existing' already exists on table 'users'",
|
|
719
765
|
);
|
|
720
766
|
});
|
|
@@ -738,21 +784,46 @@ describe("Handler Execution", () => {
|
|
|
738
784
|
expect(result).toHaveProperty("table", "nonexistent");
|
|
739
785
|
});
|
|
740
786
|
|
|
741
|
-
it("should
|
|
787
|
+
it("should return structured error for non-index errors in create index", async () => {
|
|
742
788
|
mockAdapter.executeQuery.mockRejectedValue(new Error("Access denied"));
|
|
743
789
|
|
|
744
790
|
const tool = tools.find((t) => t.name === "mysql_create_index")!;
|
|
791
|
+
const result = await tool.handler(
|
|
792
|
+
{
|
|
793
|
+
name: "idx_test",
|
|
794
|
+
table: "users",
|
|
795
|
+
columns: ["email"],
|
|
796
|
+
},
|
|
797
|
+
mockContext,
|
|
798
|
+
);
|
|
799
|
+
|
|
800
|
+
expect(result).toHaveProperty("success", false);
|
|
801
|
+
expect((result as Record<string, unknown>).error).toContain(
|
|
802
|
+
"Access denied",
|
|
803
|
+
);
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
it("should return column-specific error for invalid column names", async () => {
|
|
807
|
+
mockAdapter.executeQuery.mockRejectedValue(
|
|
808
|
+
new Error("Key column 'nonexistent_col' doesn't exist in table"),
|
|
809
|
+
);
|
|
810
|
+
|
|
811
|
+
const tool = tools.find((t) => t.name === "mysql_create_index")!;
|
|
812
|
+
const result = await tool.handler(
|
|
813
|
+
{
|
|
814
|
+
name: "idx_test",
|
|
815
|
+
table: "users",
|
|
816
|
+
columns: ["nonexistent_col"],
|
|
817
|
+
},
|
|
818
|
+
mockContext,
|
|
819
|
+
);
|
|
745
820
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
},
|
|
753
|
-
mockContext,
|
|
754
|
-
),
|
|
755
|
-
).rejects.toThrow("Access denied");
|
|
821
|
+
expect(result).toHaveProperty("success", false);
|
|
822
|
+
expect((result as Record<string, unknown>).error).toContain(
|
|
823
|
+
"Column 'nonexistent_col' does not exist",
|
|
824
|
+
);
|
|
825
|
+
// Should NOT return exists: false (table exists, column doesn't)
|
|
826
|
+
expect(result).not.toHaveProperty("exists", false);
|
|
756
827
|
});
|
|
757
828
|
});
|
|
758
829
|
});
|