spindb 0.37.2 → 0.38.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/dist/cli/bin.js +9 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/attach.js +102 -0
- package/dist/cli/commands/attach.js.map +1 -0
- package/dist/cli/commands/backup.js +197 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/backups.js +190 -0
- package/dist/cli/commands/backups.js.map +1 -0
- package/dist/cli/commands/clone.js +119 -0
- package/dist/cli/commands/clone.js.map +1 -0
- package/dist/cli/commands/config.js +276 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/connect.js +559 -0
- package/dist/cli/commands/connect.js.map +1 -0
- package/dist/cli/commands/create.js +952 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/databases.js +485 -0
- package/dist/cli/commands/databases.js.map +1 -0
- package/dist/cli/commands/delete.js +106 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/deps.js +238 -0
- package/dist/cli/commands/deps.js.map +1 -0
- package/dist/cli/commands/detach.js +81 -0
- package/dist/cli/commands/detach.js.map +1 -0
- package/dist/cli/commands/doctor.js +567 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/duckdb.js +207 -0
- package/dist/cli/commands/duckdb.js.map +1 -0
- package/dist/cli/commands/edit.js +524 -0
- package/dist/cli/commands/edit.js.map +1 -0
- package/dist/cli/commands/engines.js +1414 -0
- package/dist/cli/commands/engines.js.map +1 -0
- package/dist/cli/commands/export.js +383 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/info.js +270 -0
- package/dist/cli/commands/info.js.map +1 -0
- package/dist/cli/commands/list.js +215 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/logs.js +81 -0
- package/dist/cli/commands/logs.js.map +1 -0
- package/dist/cli/commands/menu/backup-handlers.js +1202 -0
- package/dist/cli/commands/menu/backup-handlers.js.map +1 -0
- package/dist/cli/commands/menu/container-handlers.js +1788 -0
- package/dist/cli/commands/menu/container-handlers.js.map +1 -0
- package/dist/cli/commands/menu/engine-handlers.js +235 -0
- package/dist/cli/commands/menu/engine-handlers.js.map +1 -0
- package/dist/cli/commands/menu/index.js +266 -0
- package/dist/cli/commands/menu/index.js.map +1 -0
- package/dist/cli/commands/menu/settings-handlers.js +320 -0
- package/dist/cli/commands/menu/settings-handlers.js.map +1 -0
- package/dist/cli/commands/menu/shared.js +13 -0
- package/dist/cli/commands/menu/shared.js.map +1 -0
- package/dist/cli/commands/menu/shell-handlers.js +1573 -0
- package/dist/cli/commands/menu/shell-handlers.js.map +1 -0
- package/dist/cli/commands/menu/sql-handlers.js +185 -0
- package/dist/cli/commands/menu/sql-handlers.js.map +1 -0
- package/dist/cli/commands/menu/update-handlers.js +322 -0
- package/dist/cli/commands/menu/update-handlers.js.map +1 -0
- package/dist/cli/commands/menu/validators.js +9 -0
- package/dist/cli/commands/menu/validators.js.map +1 -0
- package/dist/cli/commands/ports.js +166 -0
- package/dist/cli/commands/ports.js.map +1 -0
- package/dist/cli/commands/pull.js +166 -0
- package/dist/cli/commands/pull.js.map +1 -0
- package/dist/cli/commands/query.js +180 -0
- package/dist/cli/commands/query.js.map +1 -0
- package/dist/cli/commands/restore.js +428 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/run.js +115 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/self-update.js +99 -0
- package/dist/cli/commands/self-update.js.map +1 -0
- package/dist/cli/commands/sqlite.js +207 -0
- package/dist/cli/commands/sqlite.js.map +1 -0
- package/dist/cli/commands/start.js +196 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/stop.js +182 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/url.js +88 -0
- package/dist/cli/commands/url.js.map +1 -0
- package/dist/cli/commands/users.js +189 -0
- package/dist/cli/commands/users.js.map +1 -0
- package/dist/cli/commands/version.js +52 -0
- package/dist/cli/commands/version.js.map +1 -0
- package/dist/cli/commands/which.js +258 -0
- package/dist/cli/commands/which.js.map +1 -0
- package/dist/cli/constants.js +212 -0
- package/dist/cli/constants.js.map +1 -0
- package/dist/cli/helpers.js +1120 -0
- package/dist/cli/helpers.js.map +1 -0
- package/dist/cli/index.js +146 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui/prompts.js +1002 -0
- package/dist/cli/ui/prompts.js.map +1 -0
- package/dist/cli/ui/spinner.js +74 -0
- package/dist/cli/ui/spinner.js.map +1 -0
- package/dist/cli/ui/theme.js +99 -0
- package/dist/cli/ui/theme.js.map +1 -0
- package/dist/cli/utils/file-follower.js +79 -0
- package/dist/cli/utils/file-follower.js.map +1 -0
- package/dist/config/backup-formats.js +363 -0
- package/dist/config/backup-formats.js.map +1 -0
- package/dist/config/defaults.js +25 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/engine-defaults.js +303 -0
- package/dist/config/engine-defaults.js.map +1 -0
- package/dist/config/engines-registry.js +103 -0
- package/dist/config/engines-registry.js.map +1 -0
- package/dist/config/os-dependencies.js +767 -0
- package/dist/config/os-dependencies.js.map +1 -0
- package/dist/config/paths.js +156 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/version.js +3 -0
- package/dist/config/version.js.map +1 -0
- package/dist/core/backup-restore.js +219 -0
- package/dist/core/backup-restore.js.map +1 -0
- package/dist/core/base-binary-manager.js +403 -0
- package/dist/core/base-binary-manager.js.map +1 -0
- package/dist/core/base-document-binary-manager.js +364 -0
- package/dist/core/base-document-binary-manager.js.map +1 -0
- package/dist/core/base-embedded-binary-manager.js +364 -0
- package/dist/core/base-embedded-binary-manager.js.map +1 -0
- package/dist/core/base-server-binary-manager.js +368 -0
- package/dist/core/base-server-binary-manager.js.map +1 -0
- package/dist/core/config-manager.js +495 -0
- package/dist/core/config-manager.js.map +1 -0
- package/dist/core/container-manager.js +609 -0
- package/dist/core/container-manager.js.map +1 -0
- package/dist/core/credential-generator.js +67 -0
- package/dist/core/credential-generator.js.map +1 -0
- package/dist/core/credential-manager.js +211 -0
- package/dist/core/credential-manager.js.map +1 -0
- package/dist/core/dblab-utils.js +105 -0
- package/dist/core/dblab-utils.js.map +1 -0
- package/dist/core/dependency-manager.js +359 -0
- package/dist/core/dependency-manager.js.map +1 -0
- package/dist/core/docker-exporter.js +1077 -0
- package/dist/core/docker-exporter.js.map +1 -0
- package/dist/core/error-handler.js +295 -0
- package/dist/core/error-handler.js.map +1 -0
- package/dist/core/fs-error-utils.js +74 -0
- package/dist/core/fs-error-utils.js.map +1 -0
- package/dist/core/homebrew-version-manager.js +280 -0
- package/dist/core/homebrew-version-manager.js.map +1 -0
- package/dist/core/hostdb-client.js +252 -0
- package/dist/core/hostdb-client.js.map +1 -0
- package/dist/core/hostdb-metadata.js +243 -0
- package/dist/core/hostdb-metadata.js.map +1 -0
- package/dist/core/hostdb-releases-factory.js +161 -0
- package/dist/core/hostdb-releases-factory.js.map +1 -0
- package/dist/core/library-env.js +88 -0
- package/dist/core/library-env.js.map +1 -0
- package/dist/core/pgweb-utils.js +53 -0
- package/dist/core/pgweb-utils.js.map +1 -0
- package/dist/core/platform-service.js +632 -0
- package/dist/core/platform-service.js.map +1 -0
- package/dist/core/port-manager.js +136 -0
- package/dist/core/port-manager.js.map +1 -0
- package/dist/core/process-manager.js +445 -0
- package/dist/core/process-manager.js.map +1 -0
- package/dist/core/pull-manager.js +418 -0
- package/dist/core/pull-manager.js.map +1 -0
- package/dist/core/query-parser.js +449 -0
- package/dist/core/query-parser.js.map +1 -0
- package/dist/core/spawn-utils.js +90 -0
- package/dist/core/spawn-utils.js.map +1 -0
- package/dist/core/start-with-retry.js +90 -0
- package/dist/core/start-with-retry.js.map +1 -0
- package/dist/core/test-cleanup.js +85 -0
- package/dist/core/test-cleanup.js.map +1 -0
- package/dist/core/tls-generator.js +84 -0
- package/dist/core/tls-generator.js.map +1 -0
- package/dist/core/transaction-manager.js +139 -0
- package/dist/core/transaction-manager.js.map +1 -0
- package/dist/core/update-manager.js +241 -0
- package/dist/core/update-manager.js.map +1 -0
- package/dist/core/version-migration.js +260 -0
- package/dist/core/version-migration.js.map +1 -0
- package/dist/core/version-utils.js +91 -0
- package/dist/core/version-utils.js.map +1 -0
- package/dist/engines/base-engine.js +179 -0
- package/dist/engines/base-engine.js.map +1 -0
- package/dist/engines/clickhouse/backup.js +289 -0
- package/dist/engines/clickhouse/backup.js.map +1 -0
- package/dist/engines/clickhouse/binary-manager.js +145 -0
- package/dist/engines/clickhouse/binary-manager.js.map +1 -0
- package/dist/engines/clickhouse/binary-urls.js +100 -0
- package/dist/engines/clickhouse/binary-urls.js.map +1 -0
- package/dist/engines/clickhouse/cli-utils.js +143 -0
- package/dist/engines/clickhouse/cli-utils.js.map +1 -0
- package/dist/engines/clickhouse/hostdb-releases.js +24 -0
- package/dist/engines/clickhouse/hostdb-releases.js.map +1 -0
- package/dist/engines/clickhouse/index.js +1077 -0
- package/dist/engines/clickhouse/index.js.map +1 -0
- package/dist/engines/clickhouse/restore.js +335 -0
- package/dist/engines/clickhouse/restore.js.map +1 -0
- package/dist/engines/clickhouse/version-maps.js +83 -0
- package/dist/engines/clickhouse/version-maps.js.map +1 -0
- package/dist/engines/clickhouse/version-validator.js +133 -0
- package/dist/engines/clickhouse/version-validator.js.map +1 -0
- package/dist/engines/cockroachdb/backup.js +261 -0
- package/dist/engines/cockroachdb/backup.js.map +1 -0
- package/dist/engines/cockroachdb/binary-manager.js +33 -0
- package/dist/engines/cockroachdb/binary-manager.js.map +1 -0
- package/dist/engines/cockroachdb/binary-urls.js +33 -0
- package/dist/engines/cockroachdb/binary-urls.js.map +1 -0
- package/dist/engines/cockroachdb/cli-utils.js +338 -0
- package/dist/engines/cockroachdb/cli-utils.js.map +1 -0
- package/dist/engines/cockroachdb/hostdb-releases.js +21 -0
- package/dist/engines/cockroachdb/hostdb-releases.js.map +1 -0
- package/dist/engines/cockroachdb/index.js +1016 -0
- package/dist/engines/cockroachdb/index.js.map +1 -0
- package/dist/engines/cockroachdb/restore.js +323 -0
- package/dist/engines/cockroachdb/restore.js.map +1 -0
- package/dist/engines/cockroachdb/version-maps.js +37 -0
- package/dist/engines/cockroachdb/version-maps.js.map +1 -0
- package/dist/engines/couchdb/api-client.js +64 -0
- package/dist/engines/couchdb/api-client.js.map +1 -0
- package/dist/engines/couchdb/backup.js +90 -0
- package/dist/engines/couchdb/backup.js.map +1 -0
- package/dist/engines/couchdb/binary-manager.js +62 -0
- package/dist/engines/couchdb/binary-manager.js.map +1 -0
- package/dist/engines/couchdb/binary-urls.js +92 -0
- package/dist/engines/couchdb/binary-urls.js.map +1 -0
- package/dist/engines/couchdb/hostdb-releases.js +21 -0
- package/dist/engines/couchdb/hostdb-releases.js.map +1 -0
- package/dist/engines/couchdb/index.js +1043 -0
- package/dist/engines/couchdb/index.js.map +1 -0
- package/dist/engines/couchdb/restore.js +198 -0
- package/dist/engines/couchdb/restore.js.map +1 -0
- package/dist/engines/couchdb/version-maps.js +67 -0
- package/dist/engines/couchdb/version-maps.js.map +1 -0
- package/dist/engines/couchdb/version-validator.js +88 -0
- package/dist/engines/couchdb/version-validator.js.map +1 -0
- package/dist/engines/duckdb/binary-manager.js +33 -0
- package/dist/engines/duckdb/binary-manager.js.map +1 -0
- package/{engines/duckdb/binary-urls.ts → dist/engines/duckdb/binary-urls.js} +11 -16
- package/dist/engines/duckdb/binary-urls.js.map +1 -0
- package/dist/engines/duckdb/hostdb-releases.js +21 -0
- package/dist/engines/duckdb/hostdb-releases.js.map +1 -0
- package/dist/engines/duckdb/index.js +594 -0
- package/dist/engines/duckdb/index.js.map +1 -0
- package/dist/engines/duckdb/registry.js +265 -0
- package/dist/engines/duckdb/registry.js.map +1 -0
- package/dist/engines/duckdb/scanner.js +12 -0
- package/dist/engines/duckdb/scanner.js.map +1 -0
- package/dist/engines/duckdb/version-maps.js +67 -0
- package/dist/engines/duckdb/version-maps.js.map +1 -0
- package/dist/engines/duckdb/version-validator.js +62 -0
- package/dist/engines/duckdb/version-validator.js.map +1 -0
- package/dist/engines/ferretdb/backup.js +170 -0
- package/dist/engines/ferretdb/backup.js.map +1 -0
- package/dist/engines/ferretdb/binary-manager.js +765 -0
- package/dist/engines/ferretdb/binary-manager.js.map +1 -0
- package/dist/engines/ferretdb/binary-urls.js +135 -0
- package/dist/engines/ferretdb/binary-urls.js.map +1 -0
- package/dist/engines/ferretdb/index.js +1517 -0
- package/dist/engines/ferretdb/index.js.map +1 -0
- package/dist/engines/ferretdb/restore.js +310 -0
- package/dist/engines/ferretdb/restore.js.map +1 -0
- package/{engines/ferretdb/version-maps.ts → dist/engines/ferretdb/version-maps.js} +62 -79
- package/dist/engines/ferretdb/version-maps.js.map +1 -0
- package/dist/engines/file-based-utils.js +184 -0
- package/dist/engines/file-based-utils.js.map +1 -0
- package/dist/engines/index.js +124 -0
- package/dist/engines/index.js.map +1 -0
- package/dist/engines/influxdb/api-client.js +54 -0
- package/dist/engines/influxdb/api-client.js.map +1 -0
- package/dist/engines/influxdb/backup.js +119 -0
- package/dist/engines/influxdb/backup.js.map +1 -0
- package/dist/engines/influxdb/binary-manager.js +87 -0
- package/dist/engines/influxdb/binary-manager.js.map +1 -0
- package/dist/engines/influxdb/binary-urls.js +56 -0
- package/dist/engines/influxdb/binary-urls.js.map +1 -0
- package/dist/engines/influxdb/hostdb-releases.js +21 -0
- package/dist/engines/influxdb/hostdb-releases.js.map +1 -0
- package/dist/engines/influxdb/index.js +962 -0
- package/dist/engines/influxdb/index.js.map +1 -0
- package/dist/engines/influxdb/restore.js +329 -0
- package/dist/engines/influxdb/restore.js.map +1 -0
- package/dist/engines/influxdb/version-maps.js +64 -0
- package/dist/engines/influxdb/version-maps.js.map +1 -0
- package/dist/engines/influxdb/version-validator.js +109 -0
- package/dist/engines/influxdb/version-validator.js.map +1 -0
- package/dist/engines/mariadb/backup.js +178 -0
- package/dist/engines/mariadb/backup.js.map +1 -0
- package/dist/engines/mariadb/binary-manager.js +33 -0
- package/dist/engines/mariadb/binary-manager.js.map +1 -0
- package/{engines/mariadb/binary-urls.ts → dist/engines/mariadb/binary-urls.js} +38 -55
- package/dist/engines/mariadb/binary-urls.js.map +1 -0
- package/dist/engines/mariadb/hostdb-releases.js +21 -0
- package/dist/engines/mariadb/hostdb-releases.js.map +1 -0
- package/dist/engines/mariadb/index.js +1011 -0
- package/dist/engines/mariadb/index.js.map +1 -0
- package/dist/engines/mariadb/restore.js +322 -0
- package/dist/engines/mariadb/restore.js.map +1 -0
- package/dist/engines/mariadb/version-maps.js +63 -0
- package/dist/engines/mariadb/version-maps.js.map +1 -0
- package/dist/engines/mariadb/version-validator.js +143 -0
- package/dist/engines/mariadb/version-validator.js.map +1 -0
- package/dist/engines/meilisearch/api-client.js +50 -0
- package/dist/engines/meilisearch/api-client.js.map +1 -0
- package/dist/engines/meilisearch/backup.js +167 -0
- package/dist/engines/meilisearch/backup.js.map +1 -0
- package/dist/engines/meilisearch/binary-manager.js +31 -0
- package/dist/engines/meilisearch/binary-manager.js.map +1 -0
- package/dist/engines/meilisearch/binary-urls.js +56 -0
- package/dist/engines/meilisearch/binary-urls.js.map +1 -0
- package/dist/engines/meilisearch/hostdb-releases.js +21 -0
- package/dist/engines/meilisearch/hostdb-releases.js.map +1 -0
- package/dist/engines/meilisearch/index.js +992 -0
- package/dist/engines/meilisearch/index.js.map +1 -0
- package/dist/engines/meilisearch/restore.js +167 -0
- package/dist/engines/meilisearch/restore.js.map +1 -0
- package/dist/engines/meilisearch/version-maps.js +67 -0
- package/dist/engines/meilisearch/version-maps.js.map +1 -0
- package/dist/engines/meilisearch/version-validator.js +109 -0
- package/dist/engines/meilisearch/version-validator.js.map +1 -0
- package/dist/engines/mongodb/backup.js +109 -0
- package/dist/engines/mongodb/backup.js.map +1 -0
- package/dist/engines/mongodb/binary-manager.js +36 -0
- package/dist/engines/mongodb/binary-manager.js.map +1 -0
- package/dist/engines/mongodb/binary-urls.js +46 -0
- package/dist/engines/mongodb/binary-urls.js.map +1 -0
- package/dist/engines/mongodb/cli-utils.js +131 -0
- package/dist/engines/mongodb/cli-utils.js.map +1 -0
- package/dist/engines/mongodb/hostdb-releases.js +77 -0
- package/dist/engines/mongodb/hostdb-releases.js.map +1 -0
- package/dist/engines/mongodb/index.js +873 -0
- package/dist/engines/mongodb/index.js.map +1 -0
- package/dist/engines/mongodb/restore.js +276 -0
- package/dist/engines/mongodb/restore.js.map +1 -0
- package/dist/engines/mongodb/version-maps.js +79 -0
- package/dist/engines/mongodb/version-maps.js.map +1 -0
- package/dist/engines/mongodb/version-validator.js +133 -0
- package/dist/engines/mongodb/version-validator.js.map +1 -0
- package/dist/engines/mysql/backup.js +210 -0
- package/dist/engines/mysql/backup.js.map +1 -0
- package/dist/engines/mysql/binary-detection.js +325 -0
- package/dist/engines/mysql/binary-detection.js.map +1 -0
- package/dist/engines/mysql/binary-manager.js +30 -0
- package/dist/engines/mysql/binary-manager.js.map +1 -0
- package/dist/engines/mysql/binary-urls.js +87 -0
- package/dist/engines/mysql/binary-urls.js.map +1 -0
- package/{engines/mysql/hostdb-releases.ts → dist/engines/mysql/hostdb-releases.js} +20 -23
- package/dist/engines/mysql/hostdb-releases.js.map +1 -0
- package/dist/engines/mysql/index.js +1066 -0
- package/dist/engines/mysql/index.js.map +1 -0
- package/dist/engines/mysql/restore.js +361 -0
- package/dist/engines/mysql/restore.js.map +1 -0
- package/dist/engines/mysql/version-maps.js +79 -0
- package/dist/engines/mysql/version-maps.js.map +1 -0
- package/dist/engines/mysql/version-validator.js +266 -0
- package/dist/engines/mysql/version-validator.js.map +1 -0
- package/dist/engines/postgresql/backup.js +118 -0
- package/dist/engines/postgresql/backup.js.map +1 -0
- package/dist/engines/postgresql/binary-manager.js +85 -0
- package/dist/engines/postgresql/binary-manager.js.map +1 -0
- package/dist/engines/postgresql/binary-urls.js +80 -0
- package/dist/engines/postgresql/binary-urls.js.map +1 -0
- package/dist/engines/postgresql/hostdb-releases.js +21 -0
- package/dist/engines/postgresql/hostdb-releases.js.map +1 -0
- package/dist/engines/postgresql/index.js +852 -0
- package/dist/engines/postgresql/index.js.map +1 -0
- package/dist/engines/postgresql/remote-version.js +109 -0
- package/dist/engines/postgresql/remote-version.js.map +1 -0
- package/dist/engines/postgresql/restore.js +254 -0
- package/dist/engines/postgresql/restore.js.map +1 -0
- package/dist/engines/postgresql/version-maps.js +73 -0
- package/dist/engines/postgresql/version-maps.js.map +1 -0
- package/dist/engines/postgresql/version-validator.js +286 -0
- package/dist/engines/postgresql/version-validator.js.map +1 -0
- package/dist/engines/qdrant/api-client.js +50 -0
- package/dist/engines/qdrant/api-client.js.map +1 -0
- package/dist/engines/qdrant/backup.js +115 -0
- package/dist/engines/qdrant/backup.js.map +1 -0
- package/dist/engines/qdrant/binary-manager.js +31 -0
- package/dist/engines/qdrant/binary-manager.js.map +1 -0
- package/dist/engines/qdrant/binary-urls.js +92 -0
- package/dist/engines/qdrant/binary-urls.js.map +1 -0
- package/dist/engines/qdrant/cli-utils.js +39 -0
- package/dist/engines/qdrant/cli-utils.js.map +1 -0
- package/dist/engines/qdrant/hostdb-releases.js +21 -0
- package/dist/engines/qdrant/hostdb-releases.js.map +1 -0
- package/dist/engines/qdrant/index.js +1002 -0
- package/dist/engines/qdrant/index.js.map +1 -0
- package/dist/engines/qdrant/restore.js +154 -0
- package/dist/engines/qdrant/restore.js.map +1 -0
- package/dist/engines/qdrant/version-maps.js +67 -0
- package/dist/engines/qdrant/version-maps.js.map +1 -0
- package/dist/engines/qdrant/version-validator.js +109 -0
- package/dist/engines/qdrant/version-validator.js.map +1 -0
- package/dist/engines/questdb/backup.js +191 -0
- package/dist/engines/questdb/backup.js.map +1 -0
- package/dist/engines/questdb/binary-manager.js +247 -0
- package/dist/engines/questdb/binary-manager.js.map +1 -0
- package/dist/engines/questdb/binary-urls.js +27 -0
- package/dist/engines/questdb/binary-urls.js.map +1 -0
- package/dist/engines/questdb/hostdb-releases.js +21 -0
- package/dist/engines/questdb/hostdb-releases.js.map +1 -0
- package/dist/engines/questdb/index.js +814 -0
- package/dist/engines/questdb/index.js.map +1 -0
- package/dist/engines/questdb/restore.js +202 -0
- package/dist/engines/questdb/restore.js.map +1 -0
- package/dist/engines/questdb/version-maps.js +33 -0
- package/dist/engines/questdb/version-maps.js.map +1 -0
- package/dist/engines/questdb/version-validator.js +99 -0
- package/dist/engines/questdb/version-validator.js.map +1 -0
- package/dist/engines/redis/backup.js +292 -0
- package/dist/engines/redis/backup.js.map +1 -0
- package/dist/engines/redis/binary-manager.js +32 -0
- package/dist/engines/redis/binary-manager.js.map +1 -0
- package/dist/engines/redis/binary-urls.js +96 -0
- package/dist/engines/redis/binary-urls.js.map +1 -0
- package/dist/engines/redis/cli-utils.js +38 -0
- package/dist/engines/redis/cli-utils.js.map +1 -0
- package/dist/engines/redis/hostdb-releases.js +21 -0
- package/dist/engines/redis/hostdb-releases.js.map +1 -0
- package/dist/engines/redis/index.js +1263 -0
- package/dist/engines/redis/index.js.map +1 -0
- package/dist/engines/redis/restore.js +338 -0
- package/dist/engines/redis/restore.js.map +1 -0
- package/dist/engines/redis/version-maps.js +70 -0
- package/dist/engines/redis/version-maps.js.map +1 -0
- package/dist/engines/redis/version-validator.js +109 -0
- package/dist/engines/redis/version-validator.js.map +1 -0
- package/dist/engines/sqlite/binary-manager.js +39 -0
- package/dist/engines/sqlite/binary-manager.js.map +1 -0
- package/{engines/sqlite/binary-urls.ts → dist/engines/sqlite/binary-urls.js} +11 -16
- package/dist/engines/sqlite/binary-urls.js.map +1 -0
- package/dist/engines/sqlite/hostdb-releases.js +21 -0
- package/dist/engines/sqlite/hostdb-releases.js.map +1 -0
- package/dist/engines/sqlite/index.js +493 -0
- package/dist/engines/sqlite/index.js.map +1 -0
- package/dist/engines/sqlite/registry.js +163 -0
- package/dist/engines/sqlite/registry.js.map +1 -0
- package/dist/engines/sqlite/scanner.js +12 -0
- package/dist/engines/sqlite/scanner.js.map +1 -0
- package/dist/engines/sqlite/version-maps.js +57 -0
- package/dist/engines/sqlite/version-maps.js.map +1 -0
- package/dist/engines/surrealdb/backup.js +97 -0
- package/dist/engines/surrealdb/backup.js.map +1 -0
- package/dist/engines/surrealdb/binary-manager.js +33 -0
- package/dist/engines/surrealdb/binary-manager.js.map +1 -0
- package/dist/engines/surrealdb/binary-urls.js +33 -0
- package/dist/engines/surrealdb/binary-urls.js.map +1 -0
- package/dist/engines/surrealdb/cli-utils.js +147 -0
- package/dist/engines/surrealdb/cli-utils.js.map +1 -0
- package/dist/engines/surrealdb/hostdb-releases.js +21 -0
- package/dist/engines/surrealdb/hostdb-releases.js.map +1 -0
- package/dist/engines/surrealdb/index.js +1022 -0
- package/dist/engines/surrealdb/index.js.map +1 -0
- package/dist/engines/surrealdb/restore.js +224 -0
- package/dist/engines/surrealdb/restore.js.map +1 -0
- package/dist/engines/surrealdb/version-maps.js +36 -0
- package/dist/engines/surrealdb/version-maps.js.map +1 -0
- package/dist/engines/tigerbeetle/backup.js +36 -0
- package/dist/engines/tigerbeetle/backup.js.map +1 -0
- package/dist/engines/tigerbeetle/binary-manager.js +72 -0
- package/dist/engines/tigerbeetle/binary-manager.js.map +1 -0
- package/dist/engines/tigerbeetle/binary-urls.js +49 -0
- package/dist/engines/tigerbeetle/binary-urls.js.map +1 -0
- package/dist/engines/tigerbeetle/hostdb-releases.js +21 -0
- package/dist/engines/tigerbeetle/hostdb-releases.js.map +1 -0
- package/dist/engines/tigerbeetle/index.js +559 -0
- package/dist/engines/tigerbeetle/index.js.map +1 -0
- package/dist/engines/tigerbeetle/restore.js +91 -0
- package/dist/engines/tigerbeetle/restore.js.map +1 -0
- package/{engines/tigerbeetle/version-maps.ts → dist/engines/tigerbeetle/version-maps.js} +22 -31
- package/dist/engines/tigerbeetle/version-maps.js.map +1 -0
- package/dist/engines/tigerbeetle/version-validator.js +108 -0
- package/dist/engines/tigerbeetle/version-validator.js.map +1 -0
- package/dist/engines/typedb/backup.js +129 -0
- package/dist/engines/typedb/backup.js.map +1 -0
- package/dist/engines/typedb/binary-manager.js +151 -0
- package/dist/engines/typedb/binary-manager.js.map +1 -0
- package/dist/engines/typedb/binary-urls.js +33 -0
- package/dist/engines/typedb/binary-urls.js.map +1 -0
- package/dist/engines/typedb/cli-utils.js +163 -0
- package/dist/engines/typedb/cli-utils.js.map +1 -0
- package/dist/engines/typedb/hostdb-releases.js +21 -0
- package/dist/engines/typedb/hostdb-releases.js.map +1 -0
- package/dist/engines/typedb/index.js +1003 -0
- package/dist/engines/typedb/index.js.map +1 -0
- package/dist/engines/typedb/restore.js +279 -0
- package/dist/engines/typedb/restore.js.map +1 -0
- package/dist/engines/typedb/version-maps.js +40 -0
- package/dist/engines/typedb/version-maps.js.map +1 -0
- package/dist/engines/typedb/version-validator.js +103 -0
- package/dist/engines/typedb/version-validator.js.map +1 -0
- package/dist/engines/valkey/backup.js +292 -0
- package/dist/engines/valkey/backup.js.map +1 -0
- package/dist/engines/valkey/binary-manager.js +33 -0
- package/dist/engines/valkey/binary-manager.js.map +1 -0
- package/dist/engines/valkey/binary-urls.js +98 -0
- package/dist/engines/valkey/binary-urls.js.map +1 -0
- package/dist/engines/valkey/cli-utils.js +38 -0
- package/dist/engines/valkey/cli-utils.js.map +1 -0
- package/dist/engines/valkey/hostdb-releases.js +21 -0
- package/dist/engines/valkey/hostdb-releases.js.map +1 -0
- package/dist/engines/valkey/index.js +1257 -0
- package/dist/engines/valkey/index.js.map +1 -0
- package/dist/engines/valkey/restore.js +340 -0
- package/dist/engines/valkey/restore.js.map +1 -0
- package/dist/engines/valkey/version-maps.js +70 -0
- package/dist/engines/valkey/version-maps.js.map +1 -0
- package/dist/engines/valkey/version-validator.js +112 -0
- package/dist/engines/valkey/version-validator.js.map +1 -0
- package/dist/engines/weaviate/api-client.js +50 -0
- package/dist/engines/weaviate/api-client.js.map +1 -0
- package/dist/engines/weaviate/backup.js +95 -0
- package/dist/engines/weaviate/backup.js.map +1 -0
- package/dist/engines/weaviate/binary-manager.js +58 -0
- package/dist/engines/weaviate/binary-manager.js.map +1 -0
- package/dist/engines/weaviate/binary-urls.js +92 -0
- package/dist/engines/weaviate/binary-urls.js.map +1 -0
- package/dist/engines/weaviate/cli-utils.js +39 -0
- package/dist/engines/weaviate/cli-utils.js.map +1 -0
- package/dist/engines/weaviate/hostdb-releases.js +21 -0
- package/dist/engines/weaviate/hostdb-releases.js.map +1 -0
- package/dist/engines/weaviate/index.js +871 -0
- package/dist/engines/weaviate/index.js.map +1 -0
- package/dist/engines/weaviate/restore.js +185 -0
- package/dist/engines/weaviate/restore.js.map +1 -0
- package/dist/engines/weaviate/version-maps.js +67 -0
- package/dist/engines/weaviate/version-maps.js.map +1 -0
- package/dist/engines/weaviate/version-validator.js +109 -0
- package/dist/engines/weaviate/version-validator.js.map +1 -0
- package/dist/types/index.js +102 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +12 -9
- package/bin/cli.js +0 -68
- package/cli/bin.ts +0 -10
- package/cli/commands/attach.ts +0 -139
- package/cli/commands/backup.ts +0 -290
- package/cli/commands/backups.ts +0 -247
- package/cli/commands/clone.ts +0 -159
- package/cli/commands/config.ts +0 -367
- package/cli/commands/connect.ts +0 -684
- package/cli/commands/create.ts +0 -1201
- package/cli/commands/databases.ts +0 -630
- package/cli/commands/delete.ts +0 -133
- package/cli/commands/deps.ts +0 -342
- package/cli/commands/detach.ts +0 -107
- package/cli/commands/doctor.ts +0 -689
- package/cli/commands/duckdb.ts +0 -273
- package/cli/commands/edit.ts +0 -683
- package/cli/commands/engines.ts +0 -1914
- package/cli/commands/export.ts +0 -544
- package/cli/commands/info.ts +0 -340
- package/cli/commands/list.ts +0 -284
- package/cli/commands/logs.ts +0 -102
- package/cli/commands/menu/backup-handlers.ts +0 -1571
- package/cli/commands/menu/container-handlers.ts +0 -2288
- package/cli/commands/menu/engine-handlers.ts +0 -355
- package/cli/commands/menu/index.ts +0 -342
- package/cli/commands/menu/settings-handlers.ts +0 -365
- package/cli/commands/menu/shared.ts +0 -23
- package/cli/commands/menu/shell-handlers.ts +0 -1811
- package/cli/commands/menu/sql-handlers.ts +0 -231
- package/cli/commands/menu/update-handlers.ts +0 -378
- package/cli/commands/menu/validators.ts +0 -8
- package/cli/commands/ports.ts +0 -211
- package/cli/commands/pull.ts +0 -223
- package/cli/commands/query.ts +0 -241
- package/cli/commands/restore.ts +0 -587
- package/cli/commands/run.ts +0 -178
- package/cli/commands/self-update.ts +0 -121
- package/cli/commands/sqlite.ts +0 -273
- package/cli/commands/start.ts +0 -218
- package/cli/commands/stop.ts +0 -241
- package/cli/commands/url.ts +0 -104
- package/cli/commands/users.ts +0 -264
- package/cli/commands/version.ts +0 -55
- package/cli/commands/which.ts +0 -290
- package/cli/constants.ts +0 -233
- package/cli/helpers.ts +0 -1593
- package/cli/index.ts +0 -162
- package/cli/ui/prompts.ts +0 -1525
- package/cli/ui/spinner.ts +0 -88
- package/cli/ui/theme.ts +0 -128
- package/cli/utils/file-follower.ts +0 -93
- package/config/backup-formats.ts +0 -446
- package/config/defaults.ts +0 -56
- package/config/engine-defaults.ts +0 -336
- package/config/engines-registry.ts +0 -150
- package/config/engines.schema.json +0 -135
- package/config/os-dependencies.ts +0 -888
- package/config/paths.ts +0 -200
- package/core/backup-restore.ts +0 -330
- package/core/base-binary-manager.ts +0 -562
- package/core/base-document-binary-manager.ts +0 -523
- package/core/base-embedded-binary-manager.ts +0 -547
- package/core/base-server-binary-manager.ts +0 -523
- package/core/config-manager.ts +0 -652
- package/core/container-manager.ts +0 -787
- package/core/credential-generator.ts +0 -93
- package/core/credential-manager.ts +0 -259
- package/core/dblab-utils.ts +0 -113
- package/core/dependency-manager.ts +0 -512
- package/core/docker-exporter.ts +0 -1345
- package/core/error-handler.ts +0 -419
- package/core/fs-error-utils.ts +0 -82
- package/core/homebrew-version-manager.ts +0 -352
- package/core/hostdb-client.ts +0 -344
- package/core/hostdb-metadata.ts +0 -350
- package/core/hostdb-releases-factory.ts +0 -237
- package/core/library-env.ts +0 -118
- package/core/pgweb-utils.ts +0 -62
- package/core/platform-service.ts +0 -829
- package/core/port-manager.ts +0 -165
- package/core/process-manager.ts +0 -576
- package/core/pull-manager.ts +0 -511
- package/core/query-parser.ts +0 -514
- package/core/spawn-utils.ts +0 -122
- package/core/start-with-retry.ts +0 -130
- package/core/test-cleanup.ts +0 -108
- package/core/tls-generator.ts +0 -116
- package/core/transaction-manager.ts +0 -158
- package/core/update-manager.ts +0 -308
- package/core/version-migration.ts +0 -346
- package/core/version-utils.ts +0 -104
- package/engines/base-engine.ts +0 -340
- package/engines/clickhouse/README.md +0 -231
- package/engines/clickhouse/backup.ts +0 -398
- package/engines/clickhouse/binary-manager.ts +0 -201
- package/engines/clickhouse/binary-urls.ts +0 -125
- package/engines/clickhouse/cli-utils.ts +0 -176
- package/engines/clickhouse/hostdb-releases.ts +0 -30
- package/engines/clickhouse/index.ts +0 -1345
- package/engines/clickhouse/restore.ts +0 -466
- package/engines/clickhouse/version-maps.ts +0 -95
- package/engines/clickhouse/version-validator.ts +0 -154
- package/engines/cockroachdb/README.md +0 -170
- package/engines/cockroachdb/backup.ts +0 -376
- package/engines/cockroachdb/binary-manager.ts +0 -45
- package/engines/cockroachdb/binary-urls.ts +0 -40
- package/engines/cockroachdb/cli-utils.ts +0 -384
- package/engines/cockroachdb/hostdb-releases.ts +0 -26
- package/engines/cockroachdb/index.ts +0 -1276
- package/engines/cockroachdb/restore.ts +0 -455
- package/engines/cockroachdb/version-maps.ts +0 -42
- package/engines/couchdb/README.md +0 -257
- package/engines/couchdb/api-client.ts +0 -81
- package/engines/couchdb/backup.ts +0 -137
- package/engines/couchdb/binary-manager.ts +0 -86
- package/engines/couchdb/binary-urls.ts +0 -115
- package/engines/couchdb/hostdb-releases.ts +0 -23
- package/engines/couchdb/index.ts +0 -1429
- package/engines/couchdb/restore.ts +0 -290
- package/engines/couchdb/version-maps.ts +0 -78
- package/engines/couchdb/version-validator.ts +0 -111
- package/engines/duckdb/README.md +0 -154
- package/engines/duckdb/binary-manager.ts +0 -45
- package/engines/duckdb/hostdb-releases.ts +0 -23
- package/engines/duckdb/index.ts +0 -749
- package/engines/duckdb/registry.ts +0 -303
- package/engines/duckdb/scanner.ts +0 -22
- package/engines/duckdb/version-maps.ts +0 -78
- package/engines/duckdb/version-validator.ts +0 -78
- package/engines/ferretdb/README.md +0 -262
- package/engines/ferretdb/backup.ts +0 -173
- package/engines/ferretdb/binary-manager.ts +0 -1095
- package/engines/ferretdb/binary-urls.ts +0 -183
- package/engines/ferretdb/index.ts +0 -1907
- package/engines/ferretdb/restore.ts +0 -357
- package/engines/file-based-utils.ts +0 -262
- package/engines/index.ts +0 -131
- package/engines/influxdb/README.md +0 -180
- package/engines/influxdb/api-client.ts +0 -64
- package/engines/influxdb/backup.ts +0 -160
- package/engines/influxdb/binary-manager.ts +0 -110
- package/engines/influxdb/binary-urls.ts +0 -69
- package/engines/influxdb/hostdb-releases.ts +0 -23
- package/engines/influxdb/index.ts +0 -1272
- package/engines/influxdb/restore.ts +0 -417
- package/engines/influxdb/version-maps.ts +0 -75
- package/engines/influxdb/version-validator.ts +0 -128
- package/engines/mariadb/README.md +0 -141
- package/engines/mariadb/backup.ts +0 -233
- package/engines/mariadb/binary-manager.ts +0 -45
- package/engines/mariadb/hostdb-releases.ts +0 -23
- package/engines/mariadb/index.ts +0 -1300
- package/engines/mariadb/restore.ts +0 -447
- package/engines/mariadb/version-maps.ts +0 -72
- package/engines/mariadb/version-validator.ts +0 -181
- package/engines/meilisearch/README.md +0 -255
- package/engines/meilisearch/api-client.ts +0 -61
- package/engines/meilisearch/backup.ts +0 -233
- package/engines/meilisearch/binary-manager.ts +0 -43
- package/engines/meilisearch/binary-urls.ts +0 -69
- package/engines/meilisearch/hostdb-releases.ts +0 -26
- package/engines/meilisearch/index.ts +0 -1292
- package/engines/meilisearch/restore.ts +0 -219
- package/engines/meilisearch/version-maps.ts +0 -78
- package/engines/meilisearch/version-validator.ts +0 -128
- package/engines/mongodb/README.md +0 -162
- package/engines/mongodb/backup.ts +0 -127
- package/engines/mongodb/binary-manager.ts +0 -48
- package/engines/mongodb/binary-urls.ts +0 -63
- package/engines/mongodb/cli-utils.ts +0 -171
- package/engines/mongodb/hostdb-releases.ts +0 -91
- package/engines/mongodb/index.ts +0 -1118
- package/engines/mongodb/restore.ts +0 -361
- package/engines/mongodb/version-maps.ts +0 -91
- package/engines/mongodb/version-validator.ts +0 -160
- package/engines/mysql/README.md +0 -142
- package/engines/mysql/backup.ts +0 -270
- package/engines/mysql/binary-detection.ts +0 -408
- package/engines/mysql/binary-manager.ts +0 -42
- package/engines/mysql/binary-urls.ts +0 -104
- package/engines/mysql/index.ts +0 -1361
- package/engines/mysql/restore.ts +0 -500
- package/engines/mysql/version-maps.ts +0 -91
- package/engines/mysql/version-validator.ts +0 -369
- package/engines/postgresql/README.md +0 -158
- package/engines/postgresql/backup.ts +0 -151
- package/engines/postgresql/binary-manager.ts +0 -114
- package/engines/postgresql/binary-urls.ts +0 -99
- package/engines/postgresql/hostdb-releases.ts +0 -26
- package/engines/postgresql/index.ts +0 -1143
- package/engines/postgresql/remote-version.ts +0 -161
- package/engines/postgresql/restore.ts +0 -342
- package/engines/postgresql/version-maps.ts +0 -83
- package/engines/postgresql/version-validator.ts +0 -413
- package/engines/qdrant/README.md +0 -222
- package/engines/qdrant/api-client.ts +0 -61
- package/engines/qdrant/backup.ts +0 -165
- package/engines/qdrant/binary-manager.ts +0 -43
- package/engines/qdrant/binary-urls.ts +0 -115
- package/engines/qdrant/cli-utils.ts +0 -43
- package/engines/qdrant/hostdb-releases.ts +0 -23
- package/engines/qdrant/index.ts +0 -1312
- package/engines/qdrant/restore.ts +0 -203
- package/engines/qdrant/version-maps.ts +0 -78
- package/engines/qdrant/version-validator.ts +0 -128
- package/engines/questdb/README.md +0 -334
- package/engines/questdb/backup.ts +0 -220
- package/engines/questdb/binary-manager.ts +0 -310
- package/engines/questdb/binary-urls.ts +0 -34
- package/engines/questdb/hostdb-releases.ts +0 -23
- package/engines/questdb/index.ts +0 -1023
- package/engines/questdb/restore.ts +0 -260
- package/engines/questdb/version-maps.ts +0 -37
- package/engines/questdb/version-validator.ts +0 -121
- package/engines/redis/README.md +0 -173
- package/engines/redis/backup.ts +0 -389
- package/engines/redis/binary-manager.ts +0 -44
- package/engines/redis/binary-urls.ts +0 -117
- package/engines/redis/cli-utils.ts +0 -42
- package/engines/redis/hostdb-releases.ts +0 -23
- package/engines/redis/index.ts +0 -1583
- package/engines/redis/restore.ts +0 -443
- package/engines/redis/version-maps.ts +0 -81
- package/engines/redis/version-validator.ts +0 -131
- package/engines/sqlite/README.md +0 -162
- package/engines/sqlite/binary-manager.ts +0 -52
- package/engines/sqlite/hostdb-releases.ts +0 -23
- package/engines/sqlite/index.ts +0 -641
- package/engines/sqlite/registry.ts +0 -198
- package/engines/sqlite/scanner.ts +0 -22
- package/engines/sqlite/version-maps.ts +0 -64
- package/engines/surrealdb/README.md +0 -218
- package/engines/surrealdb/backup.ts +0 -131
- package/engines/surrealdb/binary-manager.ts +0 -45
- package/engines/surrealdb/binary-urls.ts +0 -40
- package/engines/surrealdb/cli-utils.ts +0 -173
- package/engines/surrealdb/hostdb-releases.ts +0 -23
- package/engines/surrealdb/index.ts +0 -1246
- package/engines/surrealdb/restore.ts +0 -302
- package/engines/surrealdb/version-maps.ts +0 -41
- package/engines/tigerbeetle/README.md +0 -61
- package/engines/tigerbeetle/backup.ts +0 -49
- package/engines/tigerbeetle/binary-manager.ts +0 -95
- package/engines/tigerbeetle/binary-urls.ts +0 -62
- package/engines/tigerbeetle/hostdb-releases.ts +0 -26
- package/engines/tigerbeetle/index.ts +0 -746
- package/engines/tigerbeetle/restore.ts +0 -130
- package/engines/tigerbeetle/version-validator.ts +0 -126
- package/engines/typedb/backup.ts +0 -167
- package/engines/typedb/binary-manager.ts +0 -200
- package/engines/typedb/binary-urls.ts +0 -40
- package/engines/typedb/cli-utils.ts +0 -210
- package/engines/typedb/hostdb-releases.ts +0 -23
- package/engines/typedb/index.ts +0 -1275
- package/engines/typedb/restore.ts +0 -377
- package/engines/typedb/version-maps.ts +0 -48
- package/engines/typedb/version-validator.ts +0 -127
- package/engines/valkey/README.md +0 -219
- package/engines/valkey/backup.ts +0 -389
- package/engines/valkey/binary-manager.ts +0 -45
- package/engines/valkey/binary-urls.ts +0 -122
- package/engines/valkey/cli-utils.ts +0 -42
- package/engines/valkey/hostdb-releases.ts +0 -23
- package/engines/valkey/index.ts +0 -1585
- package/engines/valkey/restore.ts +0 -446
- package/engines/valkey/version-maps.ts +0 -81
- package/engines/valkey/version-validator.ts +0 -131
- package/engines/weaviate/README.md +0 -302
- package/engines/weaviate/api-client.ts +0 -61
- package/engines/weaviate/backup.ts +0 -145
- package/engines/weaviate/binary-manager.ts +0 -80
- package/engines/weaviate/binary-urls.ts +0 -115
- package/engines/weaviate/cli-utils.ts +0 -43
- package/engines/weaviate/hostdb-releases.ts +0 -23
- package/engines/weaviate/index.ts +0 -1139
- package/engines/weaviate/restore.ts +0 -235
- package/engines/weaviate/version-maps.ts +0 -78
- package/engines/weaviate/version-validator.ts +0 -128
- package/types/index.ts +0 -624
- /package/{config → dist/config}/engines.json +0 -0
|
@@ -0,0 +1,1077 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { mkdir, writeFile, readFile, unlink, chmod } from 'fs/promises';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { BaseEngine } from '../base-engine.js';
|
|
6
|
+
import { paths } from '../../config/paths.js';
|
|
7
|
+
import { getEngineDefaults } from '../../config/defaults.js';
|
|
8
|
+
import { platformService } from '../../core/platform-service.js';
|
|
9
|
+
import { configManager } from '../../core/config-manager.js';
|
|
10
|
+
import { logDebug, logWarning, assertValidUsername, } from '../../core/error-handler.js';
|
|
11
|
+
import { processManager } from '../../core/process-manager.js';
|
|
12
|
+
import { clickhouseBinaryManager } from './binary-manager.js';
|
|
13
|
+
import { getBinaryUrl } from './binary-urls.js';
|
|
14
|
+
import { normalizeVersion, SUPPORTED_MAJOR_VERSIONS, CLICKHOUSE_VERSION_MAP, } from './version-maps.js';
|
|
15
|
+
import { fetchAvailableVersions as fetchHostdbVersions } from './hostdb-releases.js';
|
|
16
|
+
import { detectBackupFormat as detectBackupFormatImpl, restoreBackup, } from './restore.js';
|
|
17
|
+
import { createBackup } from './backup.js';
|
|
18
|
+
import { validateClickHouseIdentifier, escapeClickHouseIdentifier, } from './cli-utils.js';
|
|
19
|
+
import { parseClickHouseJSONResult } from '../../core/query-parser.js';
|
|
20
|
+
const ENGINE = 'clickhouse';
|
|
21
|
+
const engineDef = getEngineDefaults(ENGINE);
|
|
22
|
+
/**
|
|
23
|
+
* Generate ClickHouse server configuration XML
|
|
24
|
+
*/
|
|
25
|
+
function generateClickHouseConfig(options) {
|
|
26
|
+
const { port, httpPort, dataDir, logDir, tmpDir, pidFile } = options;
|
|
27
|
+
return `<?xml version="1.0"?>
|
|
28
|
+
<clickhouse>
|
|
29
|
+
<logger>
|
|
30
|
+
<level>information</level>
|
|
31
|
+
<log>${logDir}/clickhouse-server.log</log>
|
|
32
|
+
<errorlog>${logDir}/clickhouse-server.err.log</errorlog>
|
|
33
|
+
<size>100M</size>
|
|
34
|
+
<count>3</count>
|
|
35
|
+
</logger>
|
|
36
|
+
|
|
37
|
+
<http_port>${httpPort}</http_port>
|
|
38
|
+
<tcp_port>${port}</tcp_port>
|
|
39
|
+
|
|
40
|
+
<listen_host>127.0.0.1</listen_host>
|
|
41
|
+
|
|
42
|
+
<pid_file>${pidFile}</pid_file>
|
|
43
|
+
|
|
44
|
+
<path>${dataDir}/</path>
|
|
45
|
+
<tmp_path>${tmpDir}/</tmp_path>
|
|
46
|
+
<user_files_path>${dataDir}/user_files/</user_files_path>
|
|
47
|
+
|
|
48
|
+
<users_config>users.xml</users_config>
|
|
49
|
+
|
|
50
|
+
<default_profile>default</default_profile>
|
|
51
|
+
<default_database>default</default_database>
|
|
52
|
+
|
|
53
|
+
<mark_cache_size>5368709120</mark_cache_size>
|
|
54
|
+
<max_concurrent_queries>100</max_concurrent_queries>
|
|
55
|
+
|
|
56
|
+
<user_directories>
|
|
57
|
+
<users_xml>
|
|
58
|
+
<path>users.xml</path>
|
|
59
|
+
</users_xml>
|
|
60
|
+
<local_directory>
|
|
61
|
+
<path>${dataDir}/access/</path>
|
|
62
|
+
</local_directory>
|
|
63
|
+
</user_directories>
|
|
64
|
+
</clickhouse>
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate ClickHouse users configuration XML
|
|
69
|
+
*/
|
|
70
|
+
function generateUsersConfig() {
|
|
71
|
+
return `<?xml version="1.0"?>
|
|
72
|
+
<clickhouse>
|
|
73
|
+
<profiles>
|
|
74
|
+
<default>
|
|
75
|
+
<max_memory_usage>10000000000</max_memory_usage>
|
|
76
|
+
<use_uncompressed_cache>0</use_uncompressed_cache>
|
|
77
|
+
<load_balancing>random</load_balancing>
|
|
78
|
+
</default>
|
|
79
|
+
</profiles>
|
|
80
|
+
|
|
81
|
+
<users>
|
|
82
|
+
<default>
|
|
83
|
+
<password></password>
|
|
84
|
+
<networks>
|
|
85
|
+
<ip>127.0.0.1</ip>
|
|
86
|
+
</networks>
|
|
87
|
+
<profile>default</profile>
|
|
88
|
+
<quota>default</quota>
|
|
89
|
+
<access_management>1</access_management>
|
|
90
|
+
</default>
|
|
91
|
+
</users>
|
|
92
|
+
|
|
93
|
+
<quotas>
|
|
94
|
+
<default>
|
|
95
|
+
<interval>
|
|
96
|
+
<duration>3600</duration>
|
|
97
|
+
<queries>0</queries>
|
|
98
|
+
<errors>0</errors>
|
|
99
|
+
<result_rows>0</result_rows>
|
|
100
|
+
<read_rows>0</read_rows>
|
|
101
|
+
<execution_time>0</execution_time>
|
|
102
|
+
</interval>
|
|
103
|
+
</default>
|
|
104
|
+
</quotas>
|
|
105
|
+
</clickhouse>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Parse a ClickHouse connection string
|
|
110
|
+
* Format: clickhouse://[user:password@]host[:port][/database]
|
|
111
|
+
*
|
|
112
|
+
* Examples:
|
|
113
|
+
* - clickhouse://localhost:8123
|
|
114
|
+
* - clickhouse://default:password@localhost:8123/mydb
|
|
115
|
+
* - clickhouse://user:pass@remote.host:8123/analytics
|
|
116
|
+
*/
|
|
117
|
+
function parseClickHouseConnectionString(connectionString) {
|
|
118
|
+
let url;
|
|
119
|
+
// Normalize connection string
|
|
120
|
+
let normalized = connectionString.trim();
|
|
121
|
+
// Support clickhouse:// scheme (convert to http:// for URL parsing)
|
|
122
|
+
if (normalized.startsWith('clickhouse://')) {
|
|
123
|
+
normalized = normalized.replace('clickhouse://', 'http://');
|
|
124
|
+
}
|
|
125
|
+
else if (!normalized.startsWith('http://') &&
|
|
126
|
+
!normalized.startsWith('https://')) {
|
|
127
|
+
throw new Error(`Invalid ClickHouse connection string: ${connectionString}\n` +
|
|
128
|
+
'Expected format: clickhouse://[user:password@]host:port[/database]');
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
url = new URL(normalized);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
throw new Error(`Invalid ClickHouse connection string: ${connectionString}\n` +
|
|
135
|
+
'Expected format: clickhouse://[user:password@]host:port[/database]');
|
|
136
|
+
}
|
|
137
|
+
const host = url.hostname || 'localhost';
|
|
138
|
+
// ClickHouse HTTP API default port is 8123
|
|
139
|
+
const port = parseInt(url.port, 10) || 8123;
|
|
140
|
+
const scheme = url.protocol === 'https:' ? 'https' : 'http';
|
|
141
|
+
const user = url.username || undefined;
|
|
142
|
+
const password = url.password || undefined;
|
|
143
|
+
// Database is in the path
|
|
144
|
+
let database = 'default';
|
|
145
|
+
if (url.pathname && url.pathname !== '/') {
|
|
146
|
+
database = url.pathname.replace(/^\//, '');
|
|
147
|
+
}
|
|
148
|
+
const baseUrl = `${scheme}://${host}:${port}`;
|
|
149
|
+
return { baseUrl, user, password, database };
|
|
150
|
+
}
|
|
151
|
+
export class ClickHouseEngine extends BaseEngine {
|
|
152
|
+
name = ENGINE;
|
|
153
|
+
displayName = 'ClickHouse';
|
|
154
|
+
defaultPort = engineDef.defaultPort;
|
|
155
|
+
supportedVersions = SUPPORTED_MAJOR_VERSIONS;
|
|
156
|
+
// Get platform info for binary operations
|
|
157
|
+
getPlatformInfo() {
|
|
158
|
+
return platformService.getPlatformInfo();
|
|
159
|
+
}
|
|
160
|
+
// Fetch available versions from hostdb (dynamically or from cache/fallback)
|
|
161
|
+
async fetchAvailableVersions() {
|
|
162
|
+
return fetchHostdbVersions();
|
|
163
|
+
}
|
|
164
|
+
// Get binary download URL from hostdb
|
|
165
|
+
getBinaryUrl(version, platform, arch) {
|
|
166
|
+
return getBinaryUrl(version, platform, arch);
|
|
167
|
+
}
|
|
168
|
+
// Resolves version string to full version (e.g., '25.12' -> '25.12.3.21')
|
|
169
|
+
resolveFullVersion(version) {
|
|
170
|
+
if (/^\d+\.\d+\.\d+\.\d+$/.test(version)) {
|
|
171
|
+
return version;
|
|
172
|
+
}
|
|
173
|
+
return CLICKHOUSE_VERSION_MAP[version] || version;
|
|
174
|
+
}
|
|
175
|
+
// Get the path where binaries for a version would be installed
|
|
176
|
+
getBinaryPath(version) {
|
|
177
|
+
const fullVersion = this.resolveFullVersion(version);
|
|
178
|
+
const { platform: p, arch: a } = this.getPlatformInfo();
|
|
179
|
+
return paths.getBinaryPath({
|
|
180
|
+
engine: 'clickhouse',
|
|
181
|
+
version: fullVersion,
|
|
182
|
+
platform: p,
|
|
183
|
+
arch: a,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// Verify that ClickHouse binaries are available
|
|
187
|
+
async verifyBinary(binPath) {
|
|
188
|
+
const clickhousePath = join(binPath, 'bin', 'clickhouse');
|
|
189
|
+
return existsSync(clickhousePath);
|
|
190
|
+
}
|
|
191
|
+
// Check if a specific ClickHouse version is installed (downloaded)
|
|
192
|
+
async isBinaryInstalled(version) {
|
|
193
|
+
const { platform, arch } = this.getPlatformInfo();
|
|
194
|
+
return clickhouseBinaryManager.isInstalled(version, platform, arch);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Ensure ClickHouse binaries are available for a specific version
|
|
198
|
+
* Downloads from hostdb if not already installed
|
|
199
|
+
* Returns the path to the bin directory
|
|
200
|
+
*/
|
|
201
|
+
async ensureBinaries(version, onProgress) {
|
|
202
|
+
const { platform, arch } = this.getPlatformInfo();
|
|
203
|
+
const binPath = await clickhouseBinaryManager.ensureInstalled(version, platform, arch, onProgress);
|
|
204
|
+
// Register binary in config
|
|
205
|
+
const clickhousePath = join(binPath, 'bin', 'clickhouse');
|
|
206
|
+
if (existsSync(clickhousePath)) {
|
|
207
|
+
await configManager.setBinaryPath('clickhouse', clickhousePath, 'bundled');
|
|
208
|
+
}
|
|
209
|
+
return binPath;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Initialize a new ClickHouse data directory
|
|
213
|
+
* Creates the directory structure and configuration files
|
|
214
|
+
*/
|
|
215
|
+
async initDataDir(containerName, _version, options = {}) {
|
|
216
|
+
const dataDir = paths.getContainerDataPath(containerName, {
|
|
217
|
+
engine: ENGINE,
|
|
218
|
+
});
|
|
219
|
+
const containerDir = paths.getContainerPath(containerName, {
|
|
220
|
+
engine: ENGINE,
|
|
221
|
+
});
|
|
222
|
+
const logDir = containerDir;
|
|
223
|
+
const tmpDir = join(dataDir, 'tmp');
|
|
224
|
+
const port = options.port || engineDef.defaultPort;
|
|
225
|
+
const httpPort = port + 1; // HTTP port is native port + 1
|
|
226
|
+
// Create directories
|
|
227
|
+
await mkdir(dataDir, { recursive: true });
|
|
228
|
+
await mkdir(tmpDir, { recursive: true });
|
|
229
|
+
await mkdir(join(dataDir, 'user_files'), { recursive: true });
|
|
230
|
+
const accessDir = join(dataDir, 'access');
|
|
231
|
+
await mkdir(accessDir, { recursive: true, mode: 0o700 });
|
|
232
|
+
await chmod(accessDir, 0o700).catch((err) => {
|
|
233
|
+
logDebug(`Failed to chmod ${accessDir}: ${err}`);
|
|
234
|
+
});
|
|
235
|
+
logDebug(`Created ClickHouse data directory: ${dataDir}`);
|
|
236
|
+
// Generate config.xml
|
|
237
|
+
const configPath = join(containerDir, 'config.xml');
|
|
238
|
+
const pidFile = join(containerDir, engineDef.pidFileName);
|
|
239
|
+
const configContent = generateClickHouseConfig({
|
|
240
|
+
port,
|
|
241
|
+
httpPort,
|
|
242
|
+
dataDir,
|
|
243
|
+
logDir,
|
|
244
|
+
tmpDir,
|
|
245
|
+
pidFile,
|
|
246
|
+
});
|
|
247
|
+
await writeFile(configPath, configContent);
|
|
248
|
+
logDebug(`Generated ClickHouse config: ${configPath}`);
|
|
249
|
+
// Generate users.xml
|
|
250
|
+
const usersConfigPath = join(containerDir, 'users.xml');
|
|
251
|
+
const usersConfigContent = generateUsersConfig();
|
|
252
|
+
await writeFile(usersConfigPath, usersConfigContent);
|
|
253
|
+
logDebug(`Generated ClickHouse users config: ${usersConfigPath}`);
|
|
254
|
+
return dataDir;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Regenerate config.xml with updated paths after container rename
|
|
258
|
+
* Called by container-manager after moving the directory
|
|
259
|
+
*/
|
|
260
|
+
async regenerateConfig(containerName, port) {
|
|
261
|
+
const dataDir = paths.getContainerDataPath(containerName, {
|
|
262
|
+
engine: ENGINE,
|
|
263
|
+
});
|
|
264
|
+
const containerDir = paths.getContainerPath(containerName, {
|
|
265
|
+
engine: ENGINE,
|
|
266
|
+
});
|
|
267
|
+
const logDir = containerDir;
|
|
268
|
+
const tmpDir = join(dataDir, 'tmp');
|
|
269
|
+
const httpPort = port + 1;
|
|
270
|
+
const accessDir = join(dataDir, 'access');
|
|
271
|
+
try {
|
|
272
|
+
await mkdir(accessDir, { recursive: true, mode: 0o700 });
|
|
273
|
+
await chmod(accessDir, 0o700).catch((err) => {
|
|
274
|
+
logDebug(`Failed to chmod ${accessDir}: ${err}`);
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
logWarning(`Failed to create ClickHouse access directory ${accessDir}: ${error}`);
|
|
279
|
+
}
|
|
280
|
+
const configPath = join(containerDir, 'config.xml');
|
|
281
|
+
const pidFile = join(containerDir, engineDef.pidFileName);
|
|
282
|
+
const configContent = generateClickHouseConfig({
|
|
283
|
+
port,
|
|
284
|
+
httpPort,
|
|
285
|
+
dataDir,
|
|
286
|
+
logDir,
|
|
287
|
+
tmpDir,
|
|
288
|
+
pidFile,
|
|
289
|
+
});
|
|
290
|
+
await writeFile(configPath, configContent);
|
|
291
|
+
logDebug(`Regenerated ClickHouse config after rename: ${configPath}`);
|
|
292
|
+
}
|
|
293
|
+
// Get the path to clickhouse binary for a version
|
|
294
|
+
async getClickHousePath(version) {
|
|
295
|
+
const { platform, arch } = this.getPlatformInfo();
|
|
296
|
+
const fullVersion = normalizeVersion(version);
|
|
297
|
+
const binPath = paths.getBinaryPath({
|
|
298
|
+
engine: 'clickhouse',
|
|
299
|
+
version: fullVersion,
|
|
300
|
+
platform,
|
|
301
|
+
arch,
|
|
302
|
+
});
|
|
303
|
+
const clickhousePath = join(binPath, 'bin', 'clickhouse');
|
|
304
|
+
if (existsSync(clickhousePath)) {
|
|
305
|
+
return clickhousePath;
|
|
306
|
+
}
|
|
307
|
+
throw new Error(`ClickHouse ${version} is not installed. Run: spindb engines download clickhouse ${version}`);
|
|
308
|
+
}
|
|
309
|
+
// Get the path to clickhouse binary (for client operations)
|
|
310
|
+
async getClickHouseClientPath(version) {
|
|
311
|
+
// Check config cache first
|
|
312
|
+
const cached = await configManager.getBinaryPath('clickhouse');
|
|
313
|
+
if (cached && existsSync(cached)) {
|
|
314
|
+
return cached;
|
|
315
|
+
}
|
|
316
|
+
// If version provided, use downloaded binary
|
|
317
|
+
if (version) {
|
|
318
|
+
return this.getClickHousePath(version);
|
|
319
|
+
}
|
|
320
|
+
throw new Error('ClickHouse binary not found. Run: spindb engines download clickhouse <version>');
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Start ClickHouse server
|
|
324
|
+
*/
|
|
325
|
+
async start(container, onProgress) {
|
|
326
|
+
const { name, port, version, binaryPath } = container;
|
|
327
|
+
// Check if already running
|
|
328
|
+
const alreadyRunning = await processManager.isRunning(name, {
|
|
329
|
+
engine: ENGINE,
|
|
330
|
+
});
|
|
331
|
+
if (alreadyRunning) {
|
|
332
|
+
return {
|
|
333
|
+
port,
|
|
334
|
+
connectionString: this.getConnectionString(container),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
// Get ClickHouse binary path
|
|
338
|
+
let clickhouseBinary = null;
|
|
339
|
+
if (binaryPath && existsSync(binaryPath)) {
|
|
340
|
+
const serverPath = join(binaryPath, 'bin', 'clickhouse');
|
|
341
|
+
if (existsSync(serverPath)) {
|
|
342
|
+
clickhouseBinary = serverPath;
|
|
343
|
+
logDebug(`Using stored binary path: ${clickhouseBinary}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (!clickhouseBinary) {
|
|
347
|
+
try {
|
|
348
|
+
clickhouseBinary = await this.getClickHousePath(version);
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
const originalMessage = error instanceof Error ? error.message : String(error);
|
|
352
|
+
throw new Error(`ClickHouse ${version} is not installed. Run: spindb engines download clickhouse ${version}\n` +
|
|
353
|
+
` Original error: ${originalMessage}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const containerDir = paths.getContainerPath(name, { engine: ENGINE });
|
|
357
|
+
const configPath = join(containerDir, 'config.xml');
|
|
358
|
+
const logFile = join(containerDir, 'clickhouse-server.log');
|
|
359
|
+
const pidFile = join(containerDir, 'clickhouse.pid');
|
|
360
|
+
onProgress?.({ stage: 'starting', message: 'Starting ClickHouse...' });
|
|
361
|
+
logDebug(`Starting ClickHouse with config: ${configPath}`);
|
|
362
|
+
const args = ['server', '--config-file', configPath, '--daemon'];
|
|
363
|
+
// Spawn the daemon process and wait for it to exit
|
|
364
|
+
// ClickHouse with --daemon forks immediately and the parent exits
|
|
365
|
+
const spawnResult = await new Promise((resolve, reject) => {
|
|
366
|
+
const proc = spawn(clickhouseBinary, args, {
|
|
367
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
368
|
+
detached: true,
|
|
369
|
+
});
|
|
370
|
+
let stdout = '';
|
|
371
|
+
let stderr = '';
|
|
372
|
+
proc.stdout?.on('data', (data) => {
|
|
373
|
+
stdout += data.toString();
|
|
374
|
+
logDebug(`clickhouse stdout: ${data.toString()}`);
|
|
375
|
+
});
|
|
376
|
+
proc.stderr?.on('data', (data) => {
|
|
377
|
+
stderr += data.toString();
|
|
378
|
+
logDebug(`clickhouse stderr: ${data.toString()}`);
|
|
379
|
+
});
|
|
380
|
+
proc.on('error', reject);
|
|
381
|
+
proc.on('close', (code) => {
|
|
382
|
+
logDebug(`ClickHouse spawn process closed with code: ${code}`);
|
|
383
|
+
// Don't unref until we capture the result
|
|
384
|
+
proc.unref();
|
|
385
|
+
resolve({ code, stdout, stderr });
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
// Check if spawn was successful
|
|
389
|
+
if (spawnResult.code !== 0 && spawnResult.code !== null) {
|
|
390
|
+
throw new Error(spawnResult.stderr ||
|
|
391
|
+
spawnResult.stdout ||
|
|
392
|
+
`clickhouse server exited with code ${spawnResult.code}`);
|
|
393
|
+
}
|
|
394
|
+
// Wait for server to be ready (outside of event handler to keep event loop alive)
|
|
395
|
+
logDebug(`Waiting for ClickHouse server to be ready on port ${port}...`);
|
|
396
|
+
const ready = await this.waitForReady(port, version);
|
|
397
|
+
logDebug(`waitForReady returned: ${ready}`);
|
|
398
|
+
if (!ready) {
|
|
399
|
+
throw new Error(`ClickHouse failed to start within timeout. Check logs at: ${logFile}`);
|
|
400
|
+
}
|
|
401
|
+
// ClickHouse in daemon mode doesn't respect <pid_file> config
|
|
402
|
+
// So we manually find and write the PID after server is ready
|
|
403
|
+
logDebug(`Finding PID for port ${port}...`);
|
|
404
|
+
try {
|
|
405
|
+
const pids = await platformService.findProcessByPort(port);
|
|
406
|
+
logDebug(`findProcessByPort output: ${JSON.stringify(pids)}`);
|
|
407
|
+
if (pids.length > 0) {
|
|
408
|
+
const serverPid = String(pids[0]);
|
|
409
|
+
logDebug(`Writing PID ${serverPid} to ${pidFile}`);
|
|
410
|
+
await writeFile(pidFile, serverPid, 'utf8');
|
|
411
|
+
logDebug(`Wrote PID ${serverPid} to ${pidFile}`);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
logDebug(`No PIDs found for port ${port}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch (pidError) {
|
|
418
|
+
// Non-fatal: PID file is optional for operation
|
|
419
|
+
logDebug(`Could not write PID file: ${pidError}`);
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
port,
|
|
423
|
+
connectionString: this.getConnectionString(container),
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
// Wait for ClickHouse to be ready
|
|
427
|
+
// ClickHouse can take longer to start on CI runners due to resource constraints
|
|
428
|
+
async waitForReady(port, version, timeoutMs = 120000) {
|
|
429
|
+
logDebug(`waitForReady called for port ${port}, version ${version}`);
|
|
430
|
+
const startTime = Date.now();
|
|
431
|
+
const checkInterval = 500;
|
|
432
|
+
let clickhouse;
|
|
433
|
+
try {
|
|
434
|
+
logDebug('Getting clickhouse client path...');
|
|
435
|
+
clickhouse = await this.getClickHouseClientPath(version);
|
|
436
|
+
logDebug(`Got clickhouse client path: ${clickhouse}`);
|
|
437
|
+
}
|
|
438
|
+
catch (err) {
|
|
439
|
+
logDebug(`Error getting clickhouse client path: ${err}`);
|
|
440
|
+
logWarning('ClickHouse binary not found, cannot verify server is ready. Assuming ready after delay.');
|
|
441
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
logDebug(`Starting connection loop, timeout: ${timeoutMs}ms`);
|
|
445
|
+
let attempt = 0;
|
|
446
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
447
|
+
attempt++;
|
|
448
|
+
logDebug(`Connection attempt ${attempt}...`);
|
|
449
|
+
try {
|
|
450
|
+
const args = [
|
|
451
|
+
'client',
|
|
452
|
+
'--host',
|
|
453
|
+
'127.0.0.1',
|
|
454
|
+
'--port',
|
|
455
|
+
String(port),
|
|
456
|
+
'--query',
|
|
457
|
+
'SELECT 1',
|
|
458
|
+
];
|
|
459
|
+
await new Promise((resolve, reject) => {
|
|
460
|
+
const proc = spawn(clickhouse, args, {
|
|
461
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
462
|
+
});
|
|
463
|
+
proc.on('close', (code) => {
|
|
464
|
+
logDebug(`Client process closed with code ${code}`);
|
|
465
|
+
if (code === 0)
|
|
466
|
+
resolve();
|
|
467
|
+
else
|
|
468
|
+
reject(new Error(`Exit code ${code}`));
|
|
469
|
+
});
|
|
470
|
+
proc.on('error', (err) => {
|
|
471
|
+
logDebug(`Client process error: ${err}`);
|
|
472
|
+
reject(err);
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
logDebug(`ClickHouse ready on port ${port}`);
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
catch (err) {
|
|
479
|
+
logDebug(`Attempt ${attempt} failed: ${err}`);
|
|
480
|
+
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
logWarning(`ClickHouse did not become ready within ${timeoutMs}ms`);
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Stop ClickHouse server
|
|
488
|
+
*/
|
|
489
|
+
async stop(container) {
|
|
490
|
+
const { name, port } = container;
|
|
491
|
+
const containerDir = paths.getContainerPath(name, { engine: ENGINE });
|
|
492
|
+
const pidFile = join(containerDir, 'clickhouse.pid');
|
|
493
|
+
logDebug(`Stopping ClickHouse container "${name}" on port ${port}`);
|
|
494
|
+
// Find PID by checking the process using cross-platform helper
|
|
495
|
+
let pid = null;
|
|
496
|
+
// Try to find ClickHouse process by port
|
|
497
|
+
try {
|
|
498
|
+
const pids = await platformService.findProcessByPort(port);
|
|
499
|
+
if (pids.length > 0) {
|
|
500
|
+
pid = pids[0];
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
catch {
|
|
504
|
+
// Ignore
|
|
505
|
+
}
|
|
506
|
+
// Kill process if found
|
|
507
|
+
if (pid && platformService.isProcessRunning(pid)) {
|
|
508
|
+
logDebug(`Killing ClickHouse process ${pid}`);
|
|
509
|
+
try {
|
|
510
|
+
await platformService.terminateProcess(pid, false);
|
|
511
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
512
|
+
if (platformService.isProcessRunning(pid)) {
|
|
513
|
+
logWarning(`Graceful termination failed, force killing ${pid}`);
|
|
514
|
+
await platformService.terminateProcess(pid, true);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
logDebug(`Process termination error: ${error}`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
// Cleanup PID file
|
|
522
|
+
if (existsSync(pidFile)) {
|
|
523
|
+
try {
|
|
524
|
+
await unlink(pidFile);
|
|
525
|
+
}
|
|
526
|
+
catch {
|
|
527
|
+
// Ignore
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
logDebug('ClickHouse stopped');
|
|
531
|
+
}
|
|
532
|
+
// Get ClickHouse server status
|
|
533
|
+
async status(container) {
|
|
534
|
+
const { port, version } = container;
|
|
535
|
+
// Try to connect
|
|
536
|
+
try {
|
|
537
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
538
|
+
const args = [
|
|
539
|
+
'client',
|
|
540
|
+
'--host',
|
|
541
|
+
'127.0.0.1',
|
|
542
|
+
'--port',
|
|
543
|
+
String(port),
|
|
544
|
+
'--query',
|
|
545
|
+
'SELECT 1',
|
|
546
|
+
];
|
|
547
|
+
await new Promise((resolve, reject) => {
|
|
548
|
+
const proc = spawn(clickhouse, args, {
|
|
549
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
550
|
+
});
|
|
551
|
+
proc.on('close', (code) => {
|
|
552
|
+
if (code === 0)
|
|
553
|
+
resolve();
|
|
554
|
+
else
|
|
555
|
+
reject(new Error(`Exit code ${code}`));
|
|
556
|
+
});
|
|
557
|
+
proc.on('error', reject);
|
|
558
|
+
});
|
|
559
|
+
return { running: true, message: 'ClickHouse is running' };
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
return { running: false, message: 'ClickHouse is not running' };
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
// Detect backup format
|
|
566
|
+
async detectBackupFormat(filePath) {
|
|
567
|
+
return detectBackupFormatImpl(filePath);
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Restore a backup
|
|
571
|
+
*/
|
|
572
|
+
async restore(container, backupPath, options = {}) {
|
|
573
|
+
const { name, port, version } = container;
|
|
574
|
+
return restoreBackup(backupPath, {
|
|
575
|
+
containerName: name,
|
|
576
|
+
port,
|
|
577
|
+
database: options.database || container.database || 'default',
|
|
578
|
+
version,
|
|
579
|
+
clean: options.clean,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Get connection string
|
|
584
|
+
* Format: clickhouse://127.0.0.1:PORT/DATABASE
|
|
585
|
+
*/
|
|
586
|
+
getConnectionString(container, database) {
|
|
587
|
+
const { port } = container;
|
|
588
|
+
const db = database || container.database || 'default';
|
|
589
|
+
return `clickhouse://127.0.0.1:${port}/${db}`;
|
|
590
|
+
}
|
|
591
|
+
// Open clickhouse client interactive shell
|
|
592
|
+
async connect(container, database) {
|
|
593
|
+
const { port, version } = container;
|
|
594
|
+
const db = database || container.database || 'default';
|
|
595
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
596
|
+
const spawnOptions = {
|
|
597
|
+
stdio: 'inherit',
|
|
598
|
+
};
|
|
599
|
+
return new Promise((resolve, reject) => {
|
|
600
|
+
const proc = spawn(clickhouse, [
|
|
601
|
+
'client',
|
|
602
|
+
'--host',
|
|
603
|
+
'127.0.0.1',
|
|
604
|
+
'--port',
|
|
605
|
+
String(port),
|
|
606
|
+
'--database',
|
|
607
|
+
db,
|
|
608
|
+
], spawnOptions);
|
|
609
|
+
proc.on('error', reject);
|
|
610
|
+
proc.on('close', () => resolve());
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Create a new database
|
|
615
|
+
*/
|
|
616
|
+
async createDatabase(container, database) {
|
|
617
|
+
const { port, version } = container;
|
|
618
|
+
// Validate database identifier to prevent SQL injection
|
|
619
|
+
validateClickHouseIdentifier(database, 'database');
|
|
620
|
+
const escapedDb = escapeClickHouseIdentifier(database);
|
|
621
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
622
|
+
const args = [
|
|
623
|
+
'client',
|
|
624
|
+
'--host',
|
|
625
|
+
'127.0.0.1',
|
|
626
|
+
'--port',
|
|
627
|
+
String(port),
|
|
628
|
+
'--query',
|
|
629
|
+
`CREATE DATABASE IF NOT EXISTS ${escapedDb}`,
|
|
630
|
+
];
|
|
631
|
+
await new Promise((resolve, reject) => {
|
|
632
|
+
const proc = spawn(clickhouse, args, {
|
|
633
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
634
|
+
});
|
|
635
|
+
let stderr = '';
|
|
636
|
+
proc.stderr?.on('data', (data) => {
|
|
637
|
+
stderr += data.toString();
|
|
638
|
+
});
|
|
639
|
+
proc.on('close', (code) => {
|
|
640
|
+
if (code === 0) {
|
|
641
|
+
logDebug(`Created ClickHouse database: ${database}`);
|
|
642
|
+
resolve();
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
reject(new Error(`Failed to create database: ${stderr}`));
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
proc.on('error', reject);
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Drop a database
|
|
653
|
+
*/
|
|
654
|
+
async dropDatabase(container, database) {
|
|
655
|
+
const { port, version } = container;
|
|
656
|
+
if (database === 'default' || database === 'system') {
|
|
657
|
+
throw new Error(`Cannot drop system database: ${database}`);
|
|
658
|
+
}
|
|
659
|
+
// Validate database identifier to prevent SQL injection
|
|
660
|
+
validateClickHouseIdentifier(database, 'database');
|
|
661
|
+
const escapedDb = escapeClickHouseIdentifier(database);
|
|
662
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
663
|
+
const args = [
|
|
664
|
+
'client',
|
|
665
|
+
'--host',
|
|
666
|
+
'127.0.0.1',
|
|
667
|
+
'--port',
|
|
668
|
+
String(port),
|
|
669
|
+
'--query',
|
|
670
|
+
`DROP DATABASE IF EXISTS ${escapedDb}`,
|
|
671
|
+
];
|
|
672
|
+
await new Promise((resolve, reject) => {
|
|
673
|
+
const proc = spawn(clickhouse, args, {
|
|
674
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
675
|
+
});
|
|
676
|
+
let stderr = '';
|
|
677
|
+
proc.stderr?.on('data', (data) => {
|
|
678
|
+
stderr += data.toString();
|
|
679
|
+
});
|
|
680
|
+
proc.on('close', (code) => {
|
|
681
|
+
if (code === 0) {
|
|
682
|
+
logDebug(`Dropped ClickHouse database: ${database}`);
|
|
683
|
+
resolve();
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
reject(new Error(`Failed to drop database: ${stderr}`));
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
proc.on('error', reject);
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Get the database size in bytes
|
|
694
|
+
*/
|
|
695
|
+
async getDatabaseSize(container) {
|
|
696
|
+
const { port, version, database } = container;
|
|
697
|
+
try {
|
|
698
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
699
|
+
// Validate and escape the database name to prevent SQL injection
|
|
700
|
+
const dbName = database || 'default';
|
|
701
|
+
validateClickHouseIdentifier(dbName, 'database');
|
|
702
|
+
// Escape single quotes for string literal in WHERE clause
|
|
703
|
+
const escapedDbName = dbName.replace(/'/g, "''");
|
|
704
|
+
const query = `SELECT sum(bytes_on_disk) FROM system.parts WHERE database = '${escapedDbName}'`;
|
|
705
|
+
const result = await new Promise((resolve, reject) => {
|
|
706
|
+
const args = [
|
|
707
|
+
'client',
|
|
708
|
+
'--host',
|
|
709
|
+
'127.0.0.1',
|
|
710
|
+
'--port',
|
|
711
|
+
String(port),
|
|
712
|
+
'--query',
|
|
713
|
+
query,
|
|
714
|
+
];
|
|
715
|
+
const proc = spawn(clickhouse, args, {
|
|
716
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
717
|
+
});
|
|
718
|
+
let stdout = '';
|
|
719
|
+
proc.stdout?.on('data', (data) => {
|
|
720
|
+
stdout += data.toString();
|
|
721
|
+
});
|
|
722
|
+
proc.on('close', (code) => {
|
|
723
|
+
if (code === 0)
|
|
724
|
+
resolve(stdout.trim());
|
|
725
|
+
else
|
|
726
|
+
reject(new Error(`Exit code ${code}`));
|
|
727
|
+
});
|
|
728
|
+
proc.on('error', reject);
|
|
729
|
+
});
|
|
730
|
+
const size = parseInt(result, 10);
|
|
731
|
+
return isNaN(size) ? null : size;
|
|
732
|
+
}
|
|
733
|
+
catch {
|
|
734
|
+
return null;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Dump from a remote ClickHouse connection
|
|
739
|
+
* Uses ClickHouse's HTTP API to export schema and data
|
|
740
|
+
*
|
|
741
|
+
* Connection string format: clickhouse://[user:password@]host[:port][/database]
|
|
742
|
+
*/
|
|
743
|
+
async dumpFromConnectionString(connectionString, outputPath) {
|
|
744
|
+
// Parse connection string
|
|
745
|
+
const { baseUrl, user, password, database } = parseClickHouseConnectionString(connectionString);
|
|
746
|
+
// Validate and escape database identifier for SQL injection prevention
|
|
747
|
+
validateClickHouseIdentifier(database, 'database');
|
|
748
|
+
const escapedDatabase = escapeClickHouseIdentifier(database);
|
|
749
|
+
logDebug(`Connecting to remote ClickHouse at ${baseUrl} (db: ${database})`);
|
|
750
|
+
// Build headers for authentication
|
|
751
|
+
const headers = {};
|
|
752
|
+
if (user) {
|
|
753
|
+
headers['X-ClickHouse-User'] = user;
|
|
754
|
+
if (password) {
|
|
755
|
+
headers['X-ClickHouse-Key'] = password;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
// Helper to execute a query via HTTP API
|
|
759
|
+
const execQuery = async (query) => {
|
|
760
|
+
const url = new URL(baseUrl);
|
|
761
|
+
url.searchParams.set('query', query);
|
|
762
|
+
url.searchParams.set('database', database);
|
|
763
|
+
const response = await fetch(url.toString(), {
|
|
764
|
+
method: 'GET',
|
|
765
|
+
headers,
|
|
766
|
+
});
|
|
767
|
+
if (!response.ok) {
|
|
768
|
+
const errorText = await response.text();
|
|
769
|
+
throw new Error(`ClickHouse query failed: ${errorText}`);
|
|
770
|
+
}
|
|
771
|
+
return response.text();
|
|
772
|
+
};
|
|
773
|
+
// Test connectivity
|
|
774
|
+
try {
|
|
775
|
+
const result = await execQuery('SELECT 1');
|
|
776
|
+
if (!result.trim().includes('1')) {
|
|
777
|
+
throw new Error(`Unexpected test query response: ${result.trim()}`);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
catch (error) {
|
|
781
|
+
throw new Error(`Failed to connect to ClickHouse at ${baseUrl}: ${error.message}`);
|
|
782
|
+
}
|
|
783
|
+
// Get list of tables
|
|
784
|
+
const tablesResult = await execQuery(`SELECT name FROM system.tables WHERE database = '${database.replace(/'/g, "''")}' ORDER BY name`);
|
|
785
|
+
const tables = tablesResult
|
|
786
|
+
.trim()
|
|
787
|
+
.split('\n')
|
|
788
|
+
.filter((t) => t.trim());
|
|
789
|
+
logDebug(`Found ${tables.length} tables in database ${database}`);
|
|
790
|
+
// Build SQL backup
|
|
791
|
+
const lines = [];
|
|
792
|
+
lines.push('-- ClickHouse backup generated by SpinDB');
|
|
793
|
+
lines.push(`-- Source: ${baseUrl}`);
|
|
794
|
+
lines.push(`-- Database: ${database}`);
|
|
795
|
+
lines.push(`-- Date: ${new Date().toISOString()}`);
|
|
796
|
+
lines.push('');
|
|
797
|
+
for (const table of tables) {
|
|
798
|
+
// Validate table name
|
|
799
|
+
validateClickHouseIdentifier(table, 'table');
|
|
800
|
+
const escapedTable = escapeClickHouseIdentifier(table);
|
|
801
|
+
lines.push(`-- Table: ${table}`);
|
|
802
|
+
lines.push('');
|
|
803
|
+
// Get CREATE TABLE statement (using TSVRaw for unescaped output)
|
|
804
|
+
try {
|
|
805
|
+
const createUrl = new URL(baseUrl);
|
|
806
|
+
createUrl.searchParams.set('query', `SHOW CREATE TABLE ${escapedDatabase}.${escapedTable} FORMAT TSVRaw`);
|
|
807
|
+
const createResponse = await fetch(createUrl.toString(), { headers });
|
|
808
|
+
if (!createResponse.ok) {
|
|
809
|
+
logWarning(`Could not get CREATE TABLE for ${table}`);
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
let createStmt = (await createResponse.text()).trim();
|
|
813
|
+
// Strip database prefix for portability
|
|
814
|
+
const dbPrefixPattern = new RegExp(`(CREATE TABLE\\s+)\`?${database.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\`?\\.`, 'i');
|
|
815
|
+
createStmt = createStmt.replace(dbPrefixPattern, '$1');
|
|
816
|
+
lines.push(createStmt + ';');
|
|
817
|
+
lines.push('');
|
|
818
|
+
}
|
|
819
|
+
catch (error) {
|
|
820
|
+
logWarning(`Could not get CREATE TABLE for ${table}: ${error}`);
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
823
|
+
// Export data using SQLInsert format
|
|
824
|
+
try {
|
|
825
|
+
const dataUrl = new URL(baseUrl);
|
|
826
|
+
dataUrl.searchParams.set('query', `SELECT * FROM ${escapedDatabase}.${escapedTable} FORMAT SQLInsert`);
|
|
827
|
+
const dataResponse = await fetch(dataUrl.toString(), { headers });
|
|
828
|
+
if (!dataResponse.ok) {
|
|
829
|
+
const errorText = await dataResponse.text();
|
|
830
|
+
logWarning(`Could not export data for ${table}: HTTP ${dataResponse.status} - ${errorText}`);
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
const data = (await dataResponse.text()).trim();
|
|
834
|
+
if (data) {
|
|
835
|
+
// SQLInsert format uses 'table' as placeholder, replace with actual table name
|
|
836
|
+
// Handle variations: TABLE, `table`, "table", 'table' with optional whitespace
|
|
837
|
+
const insertData = data.replace(/INSERT\s+INTO\s+[`"']?table[`"']?\s*\(/gi, `INSERT INTO ${escapedTable} (`);
|
|
838
|
+
lines.push(insertData);
|
|
839
|
+
lines.push('');
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
catch (error) {
|
|
844
|
+
logWarning(`Could not export data for ${table}: ${error}`);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
// Write to file
|
|
848
|
+
const content = lines.join('\n');
|
|
849
|
+
await writeFile(outputPath, content, 'utf-8');
|
|
850
|
+
return {
|
|
851
|
+
filePath: outputPath,
|
|
852
|
+
warnings: tables.length === 0
|
|
853
|
+
? [`Database '${database}' has no tables`]
|
|
854
|
+
: undefined,
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
// Create a backup
|
|
858
|
+
async backup(container, outputPath, options) {
|
|
859
|
+
return createBackup(container, outputPath, options);
|
|
860
|
+
}
|
|
861
|
+
// Run a SQL file or inline SQL statement
|
|
862
|
+
async runScript(container, options) {
|
|
863
|
+
const { port, version } = container;
|
|
864
|
+
const db = options.database || container.database || 'default';
|
|
865
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
866
|
+
if (options.file) {
|
|
867
|
+
// Read file and pipe to clickhouse client
|
|
868
|
+
const fileContent = await readFile(options.file, 'utf-8');
|
|
869
|
+
const args = [
|
|
870
|
+
'client',
|
|
871
|
+
'--host',
|
|
872
|
+
'127.0.0.1',
|
|
873
|
+
'--port',
|
|
874
|
+
String(port),
|
|
875
|
+
'--database',
|
|
876
|
+
db,
|
|
877
|
+
'--multiquery',
|
|
878
|
+
];
|
|
879
|
+
await new Promise((resolve, reject) => {
|
|
880
|
+
const proc = spawn(clickhouse, args, {
|
|
881
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
882
|
+
});
|
|
883
|
+
proc.on('error', reject);
|
|
884
|
+
proc.on('close', (code) => {
|
|
885
|
+
if (code === 0 || code === null)
|
|
886
|
+
resolve();
|
|
887
|
+
else
|
|
888
|
+
reject(new Error(`clickhouse client exited with code ${code}`));
|
|
889
|
+
});
|
|
890
|
+
proc.stdin?.write(fileContent);
|
|
891
|
+
proc.stdin?.end();
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
else if (options.sql) {
|
|
895
|
+
// Run inline SQL via stdin to avoid command injection
|
|
896
|
+
const args = [
|
|
897
|
+
'client',
|
|
898
|
+
'--host',
|
|
899
|
+
'127.0.0.1',
|
|
900
|
+
'--port',
|
|
901
|
+
String(port),
|
|
902
|
+
'--database',
|
|
903
|
+
db,
|
|
904
|
+
'--multiquery',
|
|
905
|
+
];
|
|
906
|
+
await new Promise((resolve, reject) => {
|
|
907
|
+
const proc = spawn(clickhouse, args, {
|
|
908
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
909
|
+
});
|
|
910
|
+
proc.on('error', reject);
|
|
911
|
+
proc.on('close', (code) => {
|
|
912
|
+
if (code === 0 || code === null)
|
|
913
|
+
resolve();
|
|
914
|
+
else
|
|
915
|
+
reject(new Error(`clickhouse client exited with code ${code}`));
|
|
916
|
+
});
|
|
917
|
+
proc.stdin?.write(options.sql);
|
|
918
|
+
proc.stdin?.end();
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
throw new Error('Either file or sql option must be provided');
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
async executeQuery(container, query, options) {
|
|
926
|
+
const { port, version } = container;
|
|
927
|
+
const db = options?.database || container.database || 'default';
|
|
928
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
929
|
+
// Handle FORMAT clause: replace existing FORMAT or append FORMAT JSON
|
|
930
|
+
// Regex matches "FORMAT <type>" with optional trailing whitespace/semicolon
|
|
931
|
+
let queryWithFormat = query.trim();
|
|
932
|
+
const formatRegex = /\bFORMAT\s+\w+\s*;?\s*$/i;
|
|
933
|
+
if (formatRegex.test(queryWithFormat)) {
|
|
934
|
+
// Replace existing FORMAT clause with FORMAT JSON
|
|
935
|
+
queryWithFormat = queryWithFormat.replace(formatRegex, 'FORMAT JSON');
|
|
936
|
+
}
|
|
937
|
+
else {
|
|
938
|
+
// No FORMAT clause, append FORMAT JSON
|
|
939
|
+
queryWithFormat = queryWithFormat.replace(/;?\s*$/, ' FORMAT JSON');
|
|
940
|
+
}
|
|
941
|
+
return new Promise((resolve, reject) => {
|
|
942
|
+
const args = [
|
|
943
|
+
'client',
|
|
944
|
+
'--host',
|
|
945
|
+
'127.0.0.1',
|
|
946
|
+
'--port',
|
|
947
|
+
String(port),
|
|
948
|
+
'--database',
|
|
949
|
+
db,
|
|
950
|
+
'--query',
|
|
951
|
+
queryWithFormat,
|
|
952
|
+
];
|
|
953
|
+
const proc = spawn(clickhouse, args, {
|
|
954
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
955
|
+
});
|
|
956
|
+
let stdout = '';
|
|
957
|
+
let stderr = '';
|
|
958
|
+
proc.stdout?.on('data', (data) => {
|
|
959
|
+
stdout += data.toString();
|
|
960
|
+
});
|
|
961
|
+
proc.stderr?.on('data', (data) => {
|
|
962
|
+
stderr += data.toString();
|
|
963
|
+
});
|
|
964
|
+
proc.on('error', reject);
|
|
965
|
+
proc.on('close', (code) => {
|
|
966
|
+
if (code === 0) {
|
|
967
|
+
resolve(parseClickHouseJSONResult(stdout));
|
|
968
|
+
}
|
|
969
|
+
else {
|
|
970
|
+
reject(new Error(stderr || `clickhouse exited with code ${code}`));
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* List all user databases, excluding system databases (system, information_schema, INFORMATION_SCHEMA).
|
|
977
|
+
*/
|
|
978
|
+
async listDatabases(container) {
|
|
979
|
+
const { port, version } = container;
|
|
980
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
981
|
+
logDebug(`Listing databases on port ${port} with version ${version}`);
|
|
982
|
+
return new Promise((resolve, reject) => {
|
|
983
|
+
const args = [
|
|
984
|
+
'client',
|
|
985
|
+
'--host',
|
|
986
|
+
'127.0.0.1',
|
|
987
|
+
'--port',
|
|
988
|
+
String(port),
|
|
989
|
+
'--query',
|
|
990
|
+
'SHOW DATABASES',
|
|
991
|
+
];
|
|
992
|
+
const proc = spawn(clickhouse, args, {
|
|
993
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
994
|
+
});
|
|
995
|
+
let stdout = '';
|
|
996
|
+
let stderr = '';
|
|
997
|
+
proc.stdout?.on('data', (data) => {
|
|
998
|
+
stdout += data.toString();
|
|
999
|
+
});
|
|
1000
|
+
proc.stderr?.on('data', (data) => {
|
|
1001
|
+
stderr += data.toString();
|
|
1002
|
+
});
|
|
1003
|
+
proc.on('error', reject);
|
|
1004
|
+
proc.on('close', (code) => {
|
|
1005
|
+
if (code !== 0) {
|
|
1006
|
+
reject(new Error(stderr || `clickhouse exited with code ${code}`));
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
// Parse output (one database per line)
|
|
1010
|
+
const systemDatabases = [
|
|
1011
|
+
'system',
|
|
1012
|
+
'information_schema',
|
|
1013
|
+
'INFORMATION_SCHEMA',
|
|
1014
|
+
];
|
|
1015
|
+
const databases = stdout
|
|
1016
|
+
.trim()
|
|
1017
|
+
.split('\n')
|
|
1018
|
+
.map((db) => db.trim())
|
|
1019
|
+
.filter((db) => db.length > 0 && !systemDatabases.includes(db));
|
|
1020
|
+
resolve(databases);
|
|
1021
|
+
});
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
async createUser(container, options) {
|
|
1025
|
+
const { username, password, database } = options;
|
|
1026
|
+
assertValidUsername(username);
|
|
1027
|
+
const { port, version } = container;
|
|
1028
|
+
const db = database || container.database || 'default';
|
|
1029
|
+
validateClickHouseIdentifier(username, 'username');
|
|
1030
|
+
validateClickHouseIdentifier(db, 'database');
|
|
1031
|
+
const escapedUser = escapeClickHouseIdentifier(username);
|
|
1032
|
+
const escapedDb = escapeClickHouseIdentifier(db);
|
|
1033
|
+
const clickhouse = await this.getClickHouseClientPath(version);
|
|
1034
|
+
const escapedPass = password.replace(/\\/g, '\\\\').replace(/'/g, "''");
|
|
1035
|
+
const sql = `CREATE USER IF NOT EXISTS ${escapedUser} IDENTIFIED BY '${escapedPass}'; ALTER USER ${escapedUser} IDENTIFIED BY '${escapedPass}'; GRANT ALL ON ${escapedDb}.* TO ${escapedUser};`;
|
|
1036
|
+
const args = [
|
|
1037
|
+
'client',
|
|
1038
|
+
'--host',
|
|
1039
|
+
'127.0.0.1',
|
|
1040
|
+
'--port',
|
|
1041
|
+
String(port),
|
|
1042
|
+
'--multiquery',
|
|
1043
|
+
];
|
|
1044
|
+
await new Promise((resolve, reject) => {
|
|
1045
|
+
const proc = spawn(clickhouse, args, {
|
|
1046
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1047
|
+
});
|
|
1048
|
+
let stderr = '';
|
|
1049
|
+
proc.stderr?.on('data', (data) => {
|
|
1050
|
+
stderr += data.toString();
|
|
1051
|
+
});
|
|
1052
|
+
proc.on('close', (code) => {
|
|
1053
|
+
if (code === 0) {
|
|
1054
|
+
logDebug(`Created ClickHouse user: ${username}`);
|
|
1055
|
+
resolve();
|
|
1056
|
+
}
|
|
1057
|
+
else {
|
|
1058
|
+
reject(new Error(`Failed to create user: ${stderr}`));
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
1061
|
+
proc.on('error', reject);
|
|
1062
|
+
proc.stdin?.write(sql);
|
|
1063
|
+
proc.stdin?.end();
|
|
1064
|
+
});
|
|
1065
|
+
const connectionString = `clickhouse://${encodeURIComponent(username)}:${encodeURIComponent(password)}@127.0.0.1:${port}/${db}`;
|
|
1066
|
+
return {
|
|
1067
|
+
username,
|
|
1068
|
+
password,
|
|
1069
|
+
connectionString,
|
|
1070
|
+
engine: container.engine,
|
|
1071
|
+
container: container.name,
|
|
1072
|
+
database: db,
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
export const clickhouseEngine = new ClickHouseEngine();
|
|
1077
|
+
//# sourceMappingURL=index.js.map
|