@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
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* 5 tools total: status, instances, topology, router status, switchover.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { z } from "zod";
|
|
8
|
+
import { z, ZodError } from "zod";
|
|
9
9
|
import type { MySQLAdapter } from "../../MySQLAdapter.js";
|
|
10
10
|
import type {
|
|
11
11
|
ToolDefinition,
|
|
@@ -16,8 +16,17 @@ import type {
|
|
|
16
16
|
// Schemas
|
|
17
17
|
// =============================================================================
|
|
18
18
|
|
|
19
|
+
const LimitSchemaBase = z.object({
|
|
20
|
+
limit: z.number().optional().describe("Maximum number of results"),
|
|
21
|
+
});
|
|
22
|
+
|
|
19
23
|
const LimitSchema = z.object({
|
|
20
|
-
limit: z
|
|
24
|
+
limit: z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(0)
|
|
28
|
+
.default(100)
|
|
29
|
+
.describe("Maximum number of results"),
|
|
21
30
|
});
|
|
22
31
|
|
|
23
32
|
const SummarySchema = z.object({
|
|
@@ -48,8 +57,8 @@ export function createClusterStatusTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
48
57
|
idempotentHint: true,
|
|
49
58
|
},
|
|
50
59
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
51
|
-
const { summary } = SummarySchema.parse(params);
|
|
52
60
|
try {
|
|
61
|
+
const { summary } = SummarySchema.parse(params);
|
|
53
62
|
// Check for cluster metadata schema
|
|
54
63
|
const schemaCheck = await adapter.executeQuery(`
|
|
55
64
|
SELECT SCHEMA_NAME
|
|
@@ -140,7 +149,12 @@ export function createClusterStatusTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
140
149
|
isInnoDBCluster: false,
|
|
141
150
|
message:
|
|
142
151
|
"Unable to query cluster metadata. Ensure InnoDB Cluster is properly configured.",
|
|
143
|
-
error:
|
|
152
|
+
error:
|
|
153
|
+
error instanceof ZodError
|
|
154
|
+
? error.issues.map((i) => i.message).join(", ")
|
|
155
|
+
: error instanceof Error
|
|
156
|
+
? error.message
|
|
157
|
+
: String(error),
|
|
144
158
|
};
|
|
145
159
|
}
|
|
146
160
|
},
|
|
@@ -158,18 +172,32 @@ export function createClusterInstancesTool(
|
|
|
158
172
|
title: "MySQL Cluster Instances",
|
|
159
173
|
description: "List all instances in the InnoDB Cluster.",
|
|
160
174
|
group: "cluster",
|
|
161
|
-
inputSchema:
|
|
175
|
+
inputSchema: LimitSchemaBase,
|
|
162
176
|
requiredScopes: ["read"],
|
|
163
177
|
annotations: {
|
|
164
178
|
readOnlyHint: true,
|
|
165
179
|
idempotentHint: true,
|
|
166
180
|
},
|
|
167
181
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
168
|
-
|
|
182
|
+
let limit: number;
|
|
183
|
+
try {
|
|
184
|
+
({ limit } = LimitSchema.parse(params));
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return {
|
|
187
|
+
instances: [],
|
|
188
|
+
count: 0,
|
|
189
|
+
error:
|
|
190
|
+
error instanceof ZodError
|
|
191
|
+
? error.issues.map((i) => i.message).join(", ")
|
|
192
|
+
: error instanceof Error
|
|
193
|
+
? error.message
|
|
194
|
+
: String(error),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
169
197
|
|
|
170
198
|
try {
|
|
171
|
-
const result = await adapter.executeQuery(
|
|
172
|
-
|
|
199
|
+
const result = await adapter.executeQuery(
|
|
200
|
+
`SELECT
|
|
173
201
|
i.instance_id as instanceId,
|
|
174
202
|
i.cluster_id as clusterId,
|
|
175
203
|
i.address,
|
|
@@ -181,31 +209,48 @@ export function createClusterInstancesTool(
|
|
|
181
209
|
FROM mysql_innodb_cluster_metadata.instances i
|
|
182
210
|
LEFT JOIN performance_schema.replication_group_members m
|
|
183
211
|
ON i.mysql_server_uuid = m.MEMBER_ID
|
|
184
|
-
LIMIT ${String(limit)}
|
|
185
|
-
|
|
212
|
+
LIMIT ${String(limit)}`,
|
|
213
|
+
[],
|
|
214
|
+
);
|
|
186
215
|
|
|
187
216
|
return {
|
|
188
217
|
instances: result.rows ?? [],
|
|
189
218
|
count: result.rows?.length ?? 0,
|
|
190
219
|
};
|
|
191
|
-
} catch {
|
|
220
|
+
} catch (primaryError) {
|
|
192
221
|
// Fallback to GR members
|
|
193
|
-
|
|
194
|
-
|
|
222
|
+
try {
|
|
223
|
+
const grResult = await adapter.executeQuery(
|
|
224
|
+
`SELECT
|
|
195
225
|
MEMBER_ID as serverUuid,
|
|
196
226
|
CONCAT(MEMBER_HOST, ':', MEMBER_PORT) as address,
|
|
197
227
|
MEMBER_STATE as memberState,
|
|
198
228
|
MEMBER_ROLE as memberRole,
|
|
199
229
|
MEMBER_VERSION as version
|
|
200
230
|
FROM performance_schema.replication_group_members
|
|
201
|
-
LIMIT ${String(limit)}
|
|
202
|
-
|
|
231
|
+
LIMIT ${String(limit)}`,
|
|
232
|
+
[],
|
|
233
|
+
);
|
|
203
234
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
235
|
+
return {
|
|
236
|
+
source: "group_replication",
|
|
237
|
+
instances: grResult.rows ?? [],
|
|
238
|
+
count: grResult.rows?.length ?? 0,
|
|
239
|
+
};
|
|
240
|
+
} catch (fallbackError) {
|
|
241
|
+
return {
|
|
242
|
+
instances: [],
|
|
243
|
+
count: 0,
|
|
244
|
+
error:
|
|
245
|
+
fallbackError instanceof Error
|
|
246
|
+
? fallbackError.message
|
|
247
|
+
: String(fallbackError),
|
|
248
|
+
primaryError:
|
|
249
|
+
primaryError instanceof Error
|
|
250
|
+
? primaryError.message
|
|
251
|
+
: String(primaryError),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
209
254
|
}
|
|
210
255
|
},
|
|
211
256
|
};
|
|
@@ -229,8 +274,9 @@ export function createClusterTopologyTool(
|
|
|
229
274
|
idempotentHint: true,
|
|
230
275
|
},
|
|
231
276
|
handler: async (_params: unknown, _context: RequestContext) => {
|
|
232
|
-
|
|
233
|
-
|
|
277
|
+
try {
|
|
278
|
+
// Get all GR members
|
|
279
|
+
const membersResult = await adapter.executeQuery(`
|
|
234
280
|
SELECT
|
|
235
281
|
MEMBER_ID as id,
|
|
236
282
|
MEMBER_HOST as host,
|
|
@@ -242,93 +288,107 @@ export function createClusterTopologyTool(
|
|
|
242
288
|
ORDER BY MEMBER_ROLE DESC, MEMBER_HOST
|
|
243
289
|
`);
|
|
244
290
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
291
|
+
const members = membersResult.rows ?? [];
|
|
292
|
+
const grMemberIds = new Set(
|
|
293
|
+
members.map((m) => m["id"] as string).filter(Boolean),
|
|
294
|
+
);
|
|
249
295
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
296
|
+
// Cross-reference with cluster metadata for offline instances
|
|
297
|
+
let metadataOffline: Record<string, unknown>[] = [];
|
|
298
|
+
try {
|
|
299
|
+
const metaResult = await adapter.executeQuery(`
|
|
254
300
|
SELECT
|
|
255
301
|
mysql_server_uuid as id,
|
|
256
302
|
SUBSTRING_INDEX(address, ':', 1) as host,
|
|
257
303
|
CAST(SUBSTRING_INDEX(address, ':', -1) AS UNSIGNED) as port
|
|
258
304
|
FROM mysql_innodb_cluster_metadata.instances
|
|
259
305
|
`);
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
306
|
+
if (metaResult.rows) {
|
|
307
|
+
metadataOffline = metaResult.rows
|
|
308
|
+
.filter((i) => !grMemberIds.has(i["id"] as string))
|
|
309
|
+
.map((i) => ({
|
|
310
|
+
id: i["id"],
|
|
311
|
+
host: i["host"],
|
|
312
|
+
port: i["port"],
|
|
313
|
+
state: "OFFLINE",
|
|
314
|
+
role: "NONE",
|
|
315
|
+
version: null,
|
|
316
|
+
source: "metadata",
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
} catch {
|
|
320
|
+
// Cluster metadata not available; skip
|
|
272
321
|
}
|
|
273
|
-
} catch {
|
|
274
|
-
// Cluster metadata not available; skip
|
|
275
|
-
}
|
|
276
322
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
323
|
+
// Build topology representation
|
|
324
|
+
const topology = {
|
|
325
|
+
primary: members.filter((m) => m["role"] === "PRIMARY"),
|
|
326
|
+
secondaries: members.filter((m) => m["role"] === "SECONDARY"),
|
|
327
|
+
recovering: members.filter((m) => m["state"] === "RECOVERING"),
|
|
328
|
+
offline: [
|
|
329
|
+
...members.filter(
|
|
330
|
+
(m) => m["state"] !== "ONLINE" && m["state"] !== "RECOVERING",
|
|
331
|
+
),
|
|
332
|
+
...metadataOffline,
|
|
333
|
+
],
|
|
334
|
+
};
|
|
289
335
|
|
|
290
|
-
|
|
291
|
-
|
|
336
|
+
// Generate ASCII visualization
|
|
337
|
+
let ascii = "=== MySQL Cluster Topology ===\n\n";
|
|
292
338
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
339
|
+
if (topology.primary.length > 0) {
|
|
340
|
+
ascii += " PRIMARY:\n";
|
|
341
|
+
for (const p of topology.primary) {
|
|
342
|
+
const pm = p;
|
|
343
|
+
ascii += ` ★ ${pm["host"] as string}:${String(pm["port"])} (${pm["state"] as string})\n`;
|
|
344
|
+
}
|
|
298
345
|
}
|
|
299
|
-
}
|
|
300
346
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
347
|
+
if (topology.secondaries.length > 0) {
|
|
348
|
+
ascii += "\n SECONDARY:\n";
|
|
349
|
+
for (const s of topology.secondaries) {
|
|
350
|
+
const sm = s;
|
|
351
|
+
ascii += ` ○ ${sm["host"] as string}:${String(sm["port"])} (${sm["state"] as string})\n`;
|
|
352
|
+
}
|
|
306
353
|
}
|
|
307
|
-
}
|
|
308
354
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
355
|
+
if (topology.recovering.length > 0) {
|
|
356
|
+
ascii += "\n RECOVERING:\n";
|
|
357
|
+
for (const r of topology.recovering) {
|
|
358
|
+
const rm = r;
|
|
359
|
+
ascii += ` ⟳ ${rm["host"] as string}:${String(rm["port"])}\n`;
|
|
360
|
+
}
|
|
314
361
|
}
|
|
315
|
-
}
|
|
316
362
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
363
|
+
if (topology.offline.length > 0) {
|
|
364
|
+
ascii += "\n OFFLINE/ERROR:\n";
|
|
365
|
+
for (const o of topology.offline) {
|
|
366
|
+
const om = o;
|
|
367
|
+
ascii += ` ✗ ${om["host"] as string}:${String(om["port"])} (${om["state"] as string})\n`;
|
|
368
|
+
}
|
|
322
369
|
}
|
|
323
|
-
}
|
|
324
370
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
371
|
+
const allMembers = members.length + metadataOffline.length;
|
|
372
|
+
return {
|
|
373
|
+
topology,
|
|
374
|
+
visualization: ascii,
|
|
375
|
+
totalMembers: allMembers,
|
|
376
|
+
onlineMembers: members.filter((m) => m["state"] === "ONLINE").length,
|
|
377
|
+
};
|
|
378
|
+
} catch (error) {
|
|
379
|
+
return {
|
|
380
|
+
topology: {
|
|
381
|
+
primary: [],
|
|
382
|
+
secondaries: [],
|
|
383
|
+
recovering: [],
|
|
384
|
+
offline: [],
|
|
385
|
+
},
|
|
386
|
+
visualization: "",
|
|
387
|
+
totalMembers: 0,
|
|
388
|
+
onlineMembers: 0,
|
|
389
|
+
error: error instanceof Error ? error.message : String(error),
|
|
390
|
+
};
|
|
391
|
+
}
|
|
332
392
|
},
|
|
333
393
|
};
|
|
334
394
|
}
|
|
@@ -351,8 +411,6 @@ export function createClusterRouterStatusTool(
|
|
|
351
411
|
idempotentHint: true,
|
|
352
412
|
},
|
|
353
413
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
354
|
-
const { summary } = SummarySchema.parse(params);
|
|
355
|
-
|
|
356
414
|
// Compute staleness: null lastCheckIn or >1 hour old
|
|
357
415
|
const computeStale = (lastCheckIn: unknown): boolean => {
|
|
358
416
|
if (lastCheckIn == null) return true;
|
|
@@ -362,6 +420,7 @@ export function createClusterRouterStatusTool(
|
|
|
362
420
|
};
|
|
363
421
|
|
|
364
422
|
try {
|
|
423
|
+
const { summary } = SummarySchema.parse(params);
|
|
365
424
|
// Summary mode: return only essential router info
|
|
366
425
|
if (summary) {
|
|
367
426
|
const result = await adapter.executeQuery(`
|
|
@@ -428,13 +487,19 @@ export function createClusterRouterStatusTool(
|
|
|
428
487
|
count: routers.length,
|
|
429
488
|
staleCount,
|
|
430
489
|
};
|
|
431
|
-
} catch {
|
|
490
|
+
} catch (error) {
|
|
432
491
|
return {
|
|
433
492
|
available: false,
|
|
434
493
|
message:
|
|
435
494
|
"Router metadata not available. Ensure InnoDB Cluster is configured.",
|
|
436
495
|
suggestion:
|
|
437
496
|
"Use mysql_router_status tool if connecting directly to Router REST API.",
|
|
497
|
+
error:
|
|
498
|
+
error instanceof ZodError
|
|
499
|
+
? error.issues.map((i) => i.message).join(", ")
|
|
500
|
+
: error instanceof Error
|
|
501
|
+
? error.message
|
|
502
|
+
: String(error),
|
|
438
503
|
};
|
|
439
504
|
}
|
|
440
505
|
},
|
|
@@ -460,8 +525,9 @@ export function createClusterSwitchoverTool(
|
|
|
460
525
|
idempotentHint: true,
|
|
461
526
|
},
|
|
462
527
|
handler: async (_params: unknown, _context: RequestContext) => {
|
|
463
|
-
|
|
464
|
-
|
|
528
|
+
try {
|
|
529
|
+
// Get current members status
|
|
530
|
+
const membersResult = await adapter.executeQuery(`
|
|
465
531
|
SELECT
|
|
466
532
|
m.MEMBER_ID as memberId,
|
|
467
533
|
m.MEMBER_HOST as host,
|
|
@@ -476,71 +542,79 @@ export function createClusterSwitchoverTool(
|
|
|
476
542
|
ON m.MEMBER_ID = s.MEMBER_ID
|
|
477
543
|
`);
|
|
478
544
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
// Analyze each secondary for switchover suitability
|
|
486
|
-
const candidates = onlineSecondaries.map((s) => {
|
|
487
|
-
const sec = s;
|
|
488
|
-
const txQueue = (sec["txQueue"] as number) ?? 0;
|
|
489
|
-
const applierQueue = (sec["applierQueue"] as number) ?? 0;
|
|
490
|
-
const totalQueue = txQueue + applierQueue;
|
|
491
|
-
|
|
492
|
-
let suitability: "GOOD" | "ACCEPTABLE" | "NOT_RECOMMENDED";
|
|
493
|
-
let reason: string;
|
|
494
|
-
|
|
495
|
-
if (totalQueue === 0) {
|
|
496
|
-
suitability = "GOOD";
|
|
497
|
-
reason = "Fully synchronized";
|
|
498
|
-
} else if (totalQueue < 100) {
|
|
499
|
-
suitability = "ACCEPTABLE";
|
|
500
|
-
reason = `Minor lag: ${String(totalQueue)} transactions pending`;
|
|
501
|
-
} else {
|
|
502
|
-
suitability = "NOT_RECOMMENDED";
|
|
503
|
-
reason = `Significant lag: ${String(totalQueue)} transactions pending`;
|
|
504
|
-
}
|
|
545
|
+
const members = membersResult.rows ?? [];
|
|
546
|
+
const onlineSecondaries = members.filter((m) => {
|
|
547
|
+
const member = m;
|
|
548
|
+
return member["state"] === "ONLINE" && member["role"] === "SECONDARY";
|
|
549
|
+
});
|
|
505
550
|
|
|
551
|
+
// Analyze each secondary for switchover suitability
|
|
552
|
+
const candidates = onlineSecondaries.map((s) => {
|
|
553
|
+
const sec = s;
|
|
554
|
+
const txQueue = (sec["txQueue"] as number) ?? 0;
|
|
555
|
+
const applierQueue = (sec["applierQueue"] as number) ?? 0;
|
|
556
|
+
const totalQueue = txQueue + applierQueue;
|
|
557
|
+
|
|
558
|
+
let suitability: "GOOD" | "ACCEPTABLE" | "NOT_RECOMMENDED";
|
|
559
|
+
let reason: string;
|
|
560
|
+
|
|
561
|
+
if (totalQueue === 0) {
|
|
562
|
+
suitability = "GOOD";
|
|
563
|
+
reason = "Fully synchronized";
|
|
564
|
+
} else if (totalQueue < 100) {
|
|
565
|
+
suitability = "ACCEPTABLE";
|
|
566
|
+
reason = `Minor lag: ${String(totalQueue)} transactions pending`;
|
|
567
|
+
} else {
|
|
568
|
+
suitability = "NOT_RECOMMENDED";
|
|
569
|
+
reason = `Significant lag: ${String(totalQueue)} transactions pending`;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
return {
|
|
573
|
+
memberId: sec["memberId"],
|
|
574
|
+
host: sec["host"],
|
|
575
|
+
port: sec["port"],
|
|
576
|
+
version: sec["version"],
|
|
577
|
+
txQueue,
|
|
578
|
+
applierQueue,
|
|
579
|
+
suitability,
|
|
580
|
+
reason,
|
|
581
|
+
};
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
// Sort by suitability
|
|
585
|
+
candidates.sort((a, b) => {
|
|
586
|
+
const order = { GOOD: 0, ACCEPTABLE: 1, NOT_RECOMMENDED: 2 };
|
|
587
|
+
return order[a.suitability] - order[b.suitability];
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
const firstCandidate = candidates[0];
|
|
506
591
|
return {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
592
|
+
currentPrimary: members.find((m) => m["role"] === "PRIMARY") ?? null,
|
|
593
|
+
candidates,
|
|
594
|
+
recommendedTarget:
|
|
595
|
+
candidates.length > 0 &&
|
|
596
|
+
firstCandidate &&
|
|
597
|
+
firstCandidate.suitability !== "NOT_RECOMMENDED"
|
|
598
|
+
? firstCandidate
|
|
599
|
+
: null,
|
|
600
|
+
canSwitchover: candidates.some(
|
|
601
|
+
(c) => c.suitability !== "NOT_RECOMMENDED",
|
|
602
|
+
),
|
|
603
|
+
warning:
|
|
604
|
+
onlineSecondaries.length === 0
|
|
605
|
+
? "No online secondaries available for switchover."
|
|
606
|
+
: candidates.every((c) => c.suitability === "NOT_RECOMMENDED")
|
|
607
|
+
? "All secondaries have significant replication lag. Switchover not recommended."
|
|
608
|
+
: undefined,
|
|
515
609
|
};
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const firstCandidate = candidates[0];
|
|
525
|
-
return {
|
|
526
|
-
currentPrimary: members.find((m) => m["role"] === "PRIMARY"),
|
|
527
|
-
candidates,
|
|
528
|
-
recommendedTarget:
|
|
529
|
-
candidates.length > 0 &&
|
|
530
|
-
firstCandidate &&
|
|
531
|
-
firstCandidate.suitability !== "NOT_RECOMMENDED"
|
|
532
|
-
? firstCandidate
|
|
533
|
-
: null,
|
|
534
|
-
canSwitchover: candidates.some(
|
|
535
|
-
(c) => c.suitability !== "NOT_RECOMMENDED",
|
|
536
|
-
),
|
|
537
|
-
warning:
|
|
538
|
-
onlineSecondaries.length === 0
|
|
539
|
-
? "No online secondaries available for switchover."
|
|
540
|
-
: candidates.every((c) => c.suitability === "NOT_RECOMMENDED")
|
|
541
|
-
? "All secondaries have significant replication lag. Switchover not recommended."
|
|
542
|
-
: undefined,
|
|
543
|
-
};
|
|
610
|
+
} catch (error) {
|
|
611
|
+
return {
|
|
612
|
+
currentPrimary: null,
|
|
613
|
+
candidates: [],
|
|
614
|
+
canSwitchover: false,
|
|
615
|
+
error: error instanceof Error ? error.message : String(error),
|
|
616
|
+
};
|
|
617
|
+
}
|
|
544
618
|
},
|
|
545
619
|
};
|
|
546
620
|
}
|