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
|
@@ -1,1811 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk'
|
|
2
|
-
import inquirer from 'inquirer'
|
|
3
|
-
import { spawn } from 'child_process'
|
|
4
|
-
import { escapeablePrompt } from '../../ui/prompts'
|
|
5
|
-
import { getPageSize } from '../../constants'
|
|
6
|
-
import { existsSync } from 'fs'
|
|
7
|
-
import { chmod, mkdir, writeFile, rm } from 'fs/promises'
|
|
8
|
-
import { join, dirname, resolve, sep } from 'path'
|
|
9
|
-
import { containerManager } from '../../../core/container-manager'
|
|
10
|
-
import {
|
|
11
|
-
isUsqlInstalled,
|
|
12
|
-
isPgcliInstalled,
|
|
13
|
-
isMycliInstalled,
|
|
14
|
-
isLitecliInstalled,
|
|
15
|
-
isIredisInstalled,
|
|
16
|
-
detectPackageManager,
|
|
17
|
-
installUsql,
|
|
18
|
-
installPgcli,
|
|
19
|
-
installMycli,
|
|
20
|
-
installLitecli,
|
|
21
|
-
installIredis,
|
|
22
|
-
getUsqlManualInstructions,
|
|
23
|
-
getPgcliManualInstructions,
|
|
24
|
-
getMycliManualInstructions,
|
|
25
|
-
getLitecliManualInstructions,
|
|
26
|
-
getIredisManualInstructions,
|
|
27
|
-
} from '../../../core/dependency-manager'
|
|
28
|
-
import { platformService } from '../../../core/platform-service'
|
|
29
|
-
import { portManager } from '../../../core/port-manager'
|
|
30
|
-
import { configManager } from '../../../core/config-manager'
|
|
31
|
-
import {
|
|
32
|
-
getPgwebStatus,
|
|
33
|
-
stopPgweb,
|
|
34
|
-
PGWEB_VERSION,
|
|
35
|
-
} from '../../../core/pgweb-utils'
|
|
36
|
-
import {
|
|
37
|
-
DBLAB_ENGINES,
|
|
38
|
-
DBLAB_VERSION,
|
|
39
|
-
getDblabArgs,
|
|
40
|
-
getDblabPlatformSuffix,
|
|
41
|
-
} from '../../../core/dblab-utils'
|
|
42
|
-
import { getEngine } from '../../../engines'
|
|
43
|
-
import { createSpinner } from '../../ui/spinner'
|
|
44
|
-
import { uiError, uiWarning, uiInfo, uiSuccess } from '../../ui/theme'
|
|
45
|
-
import { logDebug } from '../../../core/error-handler'
|
|
46
|
-
import { pressEnterToContinue } from './shared'
|
|
47
|
-
import { paths } from '../../../config/paths'
|
|
48
|
-
import { getEngineConfig } from '../../../config/engines-registry'
|
|
49
|
-
import { getConsoleBaseArgs } from '../../../engines/typedb/cli-utils'
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Open a URL in the system's default browser
|
|
53
|
-
*/
|
|
54
|
-
function openInBrowser(url: string): void {
|
|
55
|
-
const platform = process.platform
|
|
56
|
-
let cmd: string
|
|
57
|
-
let args: string[]
|
|
58
|
-
|
|
59
|
-
if (platform === 'darwin') {
|
|
60
|
-
cmd = 'open'
|
|
61
|
-
args = [url]
|
|
62
|
-
} else if (platform === 'win32') {
|
|
63
|
-
cmd = 'cmd'
|
|
64
|
-
args = ['/c', 'start', '', url]
|
|
65
|
-
} else {
|
|
66
|
-
// Linux and others
|
|
67
|
-
cmd = 'xdg-open'
|
|
68
|
-
args = [url]
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
spawn(cmd, args, { detached: true, stdio: 'ignore' }).unref()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function handleCopyConnectionString(
|
|
75
|
-
containerName: string,
|
|
76
|
-
database?: string,
|
|
77
|
-
): Promise<void> {
|
|
78
|
-
const config = await containerManager.getConfig(containerName)
|
|
79
|
-
if (!config) {
|
|
80
|
-
console.error(uiError(`Container "${containerName}" not found`))
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const engine = getEngine(config.engine)
|
|
85
|
-
// Use provided database or fall back to container's default
|
|
86
|
-
const connectionString = engine.getConnectionString(config, database)
|
|
87
|
-
|
|
88
|
-
const copied = await platformService.copyToClipboard(connectionString)
|
|
89
|
-
|
|
90
|
-
console.log()
|
|
91
|
-
if (copied) {
|
|
92
|
-
console.log(uiSuccess('Connection string copied to clipboard'))
|
|
93
|
-
console.log(chalk.gray(` ${connectionString}`))
|
|
94
|
-
} else {
|
|
95
|
-
console.log(uiWarning('Could not copy to clipboard. Connection string:'))
|
|
96
|
-
console.log(chalk.cyan(` ${connectionString}`))
|
|
97
|
-
}
|
|
98
|
-
console.log()
|
|
99
|
-
|
|
100
|
-
await escapeablePrompt([
|
|
101
|
-
{
|
|
102
|
-
type: 'input',
|
|
103
|
-
name: 'continue',
|
|
104
|
-
message: chalk.gray('Press Enter to continue...'),
|
|
105
|
-
},
|
|
106
|
-
])
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export async function handleOpenShell(
|
|
110
|
-
containerName: string,
|
|
111
|
-
database?: string,
|
|
112
|
-
): Promise<void> {
|
|
113
|
-
const config = await containerManager.getConfig(containerName)
|
|
114
|
-
if (!config) {
|
|
115
|
-
console.error(uiError(`Container "${containerName}" not found`))
|
|
116
|
-
return
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const engine = getEngine(config.engine)
|
|
120
|
-
// Use provided database or fall back to container's default
|
|
121
|
-
const activeDatabase = database || config.database
|
|
122
|
-
const connectionString = engine.getConnectionString(config, activeDatabase)
|
|
123
|
-
|
|
124
|
-
const shellCheckSpinner = createSpinner('Checking available shells...')
|
|
125
|
-
shellCheckSpinner.start()
|
|
126
|
-
|
|
127
|
-
const [
|
|
128
|
-
usqlInstalled,
|
|
129
|
-
pgcliInstalled,
|
|
130
|
-
mycliInstalled,
|
|
131
|
-
litecliInstalled,
|
|
132
|
-
iredisInstalled,
|
|
133
|
-
] = await Promise.all([
|
|
134
|
-
isUsqlInstalled(),
|
|
135
|
-
isPgcliInstalled(),
|
|
136
|
-
isMycliInstalled(),
|
|
137
|
-
isLitecliInstalled(),
|
|
138
|
-
isIredisInstalled(),
|
|
139
|
-
])
|
|
140
|
-
|
|
141
|
-
shellCheckSpinner.stop()
|
|
142
|
-
// Clear the spinner line
|
|
143
|
-
process.stdout.write('\x1b[1A\x1b[2K')
|
|
144
|
-
|
|
145
|
-
type ShellChoice =
|
|
146
|
-
| 'default'
|
|
147
|
-
| 'browser'
|
|
148
|
-
| 'api-info'
|
|
149
|
-
| 'install-webui'
|
|
150
|
-
| 'pgweb'
|
|
151
|
-
| 'install-pgweb'
|
|
152
|
-
| 'stop-pgweb'
|
|
153
|
-
| 'dblab'
|
|
154
|
-
| 'install-dblab'
|
|
155
|
-
| 'duckdb-ui'
|
|
156
|
-
| 'usql'
|
|
157
|
-
| 'install-usql'
|
|
158
|
-
| 'pgcli'
|
|
159
|
-
| 'install-pgcli'
|
|
160
|
-
| 'mycli'
|
|
161
|
-
| 'install-mycli'
|
|
162
|
-
| 'litecli'
|
|
163
|
-
| 'install-litecli'
|
|
164
|
-
| 'iredis'
|
|
165
|
-
| 'install-iredis'
|
|
166
|
-
| 'back'
|
|
167
|
-
|
|
168
|
-
// Engine-specific shell names
|
|
169
|
-
let defaultShellName: string
|
|
170
|
-
let engineSpecificCli: string | null
|
|
171
|
-
let engineSpecificInstalled: boolean
|
|
172
|
-
let engineSpecificValue: ShellChoice | null
|
|
173
|
-
let engineSpecificInstallValue: ShellChoice | null
|
|
174
|
-
|
|
175
|
-
if (config.engine === 'sqlite') {
|
|
176
|
-
defaultShellName = 'sqlite3'
|
|
177
|
-
engineSpecificCli = 'litecli'
|
|
178
|
-
engineSpecificInstalled = litecliInstalled
|
|
179
|
-
engineSpecificValue = 'litecli'
|
|
180
|
-
engineSpecificInstallValue = 'install-litecli'
|
|
181
|
-
} else if (config.engine === 'duckdb') {
|
|
182
|
-
defaultShellName = 'duckdb'
|
|
183
|
-
// DuckDB has no separate enhanced CLI tool
|
|
184
|
-
engineSpecificCli = null
|
|
185
|
-
engineSpecificInstalled = false
|
|
186
|
-
engineSpecificValue = null
|
|
187
|
-
engineSpecificInstallValue = null
|
|
188
|
-
} else if (config.engine === 'mysql') {
|
|
189
|
-
defaultShellName = 'mysql'
|
|
190
|
-
engineSpecificCli = 'mycli'
|
|
191
|
-
engineSpecificInstalled = mycliInstalled
|
|
192
|
-
engineSpecificValue = 'mycli'
|
|
193
|
-
engineSpecificInstallValue = 'install-mycli'
|
|
194
|
-
} else if (config.engine === 'mariadb') {
|
|
195
|
-
defaultShellName = 'mariadb'
|
|
196
|
-
engineSpecificCli = 'mycli'
|
|
197
|
-
engineSpecificInstalled = mycliInstalled
|
|
198
|
-
engineSpecificValue = 'mycli'
|
|
199
|
-
engineSpecificInstallValue = 'install-mycli'
|
|
200
|
-
} else if (config.engine === 'mongodb' || config.engine === 'ferretdb') {
|
|
201
|
-
defaultShellName = 'mongosh'
|
|
202
|
-
// mongosh IS the enhanced shell for MongoDB/FerretDB (no separate enhanced CLI like pgcli/mycli)
|
|
203
|
-
engineSpecificCli = null
|
|
204
|
-
engineSpecificInstalled = false
|
|
205
|
-
engineSpecificValue = null
|
|
206
|
-
engineSpecificInstallValue = null
|
|
207
|
-
} else if (config.engine === 'redis') {
|
|
208
|
-
defaultShellName = 'redis-cli'
|
|
209
|
-
engineSpecificCli = 'iredis'
|
|
210
|
-
engineSpecificInstalled = iredisInstalled
|
|
211
|
-
engineSpecificValue = 'iredis'
|
|
212
|
-
engineSpecificInstallValue = 'install-iredis'
|
|
213
|
-
} else if (config.engine === 'valkey') {
|
|
214
|
-
defaultShellName = 'valkey-cli'
|
|
215
|
-
engineSpecificCli = 'iredis' // iredis is protocol-compatible with Valkey
|
|
216
|
-
engineSpecificInstalled = iredisInstalled
|
|
217
|
-
engineSpecificValue = 'iredis'
|
|
218
|
-
engineSpecificInstallValue = 'install-iredis'
|
|
219
|
-
} else if (config.engine === 'clickhouse') {
|
|
220
|
-
defaultShellName = 'clickhouse client'
|
|
221
|
-
// ClickHouse client is bundled, no separate enhanced CLI
|
|
222
|
-
engineSpecificCli = null
|
|
223
|
-
engineSpecificInstalled = false
|
|
224
|
-
engineSpecificValue = null
|
|
225
|
-
engineSpecificInstallValue = null
|
|
226
|
-
} else if (config.engine === 'qdrant') {
|
|
227
|
-
// Qdrant uses REST API, open dashboard in browser
|
|
228
|
-
defaultShellName = 'Web Dashboard'
|
|
229
|
-
engineSpecificCli = null
|
|
230
|
-
engineSpecificInstalled = false
|
|
231
|
-
engineSpecificValue = null
|
|
232
|
-
engineSpecificInstallValue = null
|
|
233
|
-
} else if (config.engine === 'meilisearch') {
|
|
234
|
-
// Meilisearch uses REST API, open dashboard in browser
|
|
235
|
-
defaultShellName = 'Web Dashboard'
|
|
236
|
-
engineSpecificCli = null
|
|
237
|
-
engineSpecificInstalled = false
|
|
238
|
-
engineSpecificValue = null
|
|
239
|
-
engineSpecificInstallValue = null
|
|
240
|
-
} else if (config.engine === 'influxdb') {
|
|
241
|
-
// InfluxDB uses influxdb3 query subcommand (same binary as server)
|
|
242
|
-
defaultShellName = 'influxdb3 query'
|
|
243
|
-
engineSpecificCli = null
|
|
244
|
-
engineSpecificInstalled = false
|
|
245
|
-
engineSpecificValue = null
|
|
246
|
-
engineSpecificInstallValue = null
|
|
247
|
-
} else if (config.engine === 'weaviate') {
|
|
248
|
-
// Weaviate uses REST API, open web dashboard in browser
|
|
249
|
-
defaultShellName = 'REST API'
|
|
250
|
-
engineSpecificCli = null
|
|
251
|
-
engineSpecificInstalled = false
|
|
252
|
-
engineSpecificValue = null
|
|
253
|
-
engineSpecificInstallValue = null
|
|
254
|
-
} else if (config.engine === 'couchdb') {
|
|
255
|
-
// CouchDB uses REST API, open Fauxton dashboard in browser
|
|
256
|
-
defaultShellName = 'Fauxton Dashboard'
|
|
257
|
-
engineSpecificCli = null
|
|
258
|
-
engineSpecificInstalled = false
|
|
259
|
-
engineSpecificValue = null
|
|
260
|
-
engineSpecificInstallValue = null
|
|
261
|
-
} else if (config.engine === 'surrealdb') {
|
|
262
|
-
// SurrealDB uses surreal sql command
|
|
263
|
-
defaultShellName = 'surreal sql'
|
|
264
|
-
engineSpecificCli = null
|
|
265
|
-
engineSpecificInstalled = false
|
|
266
|
-
engineSpecificValue = null
|
|
267
|
-
engineSpecificInstallValue = null
|
|
268
|
-
} else if (config.engine === 'questdb') {
|
|
269
|
-
// QuestDB uses PostgreSQL wire protocol, can use psql or Web Console
|
|
270
|
-
// Note: Don't recommend pgcli for QuestDB - pgcli uses PostgreSQL functions
|
|
271
|
-
// like unnest() that QuestDB doesn't support, causing autocompletion errors
|
|
272
|
-
defaultShellName = 'psql'
|
|
273
|
-
engineSpecificCli = null
|
|
274
|
-
engineSpecificInstalled = false
|
|
275
|
-
engineSpecificValue = null
|
|
276
|
-
engineSpecificInstallValue = null
|
|
277
|
-
} else if (config.engine === 'cockroachdb') {
|
|
278
|
-
// CockroachDB uses cockroach sql command
|
|
279
|
-
defaultShellName = 'cockroach sql'
|
|
280
|
-
engineSpecificCli = null
|
|
281
|
-
engineSpecificInstalled = false
|
|
282
|
-
engineSpecificValue = null
|
|
283
|
-
engineSpecificInstallValue = null
|
|
284
|
-
} else if (config.engine === 'typedb') {
|
|
285
|
-
// TypeDB uses typedb console
|
|
286
|
-
defaultShellName = 'typedb console'
|
|
287
|
-
engineSpecificCli = null
|
|
288
|
-
engineSpecificInstalled = false
|
|
289
|
-
engineSpecificValue = null
|
|
290
|
-
engineSpecificInstallValue = null
|
|
291
|
-
} else if (config.engine === 'tigerbeetle') {
|
|
292
|
-
// TigerBeetle uses tigerbeetle repl command
|
|
293
|
-
defaultShellName = 'tigerbeetle repl'
|
|
294
|
-
engineSpecificCli = null
|
|
295
|
-
engineSpecificInstalled = false
|
|
296
|
-
engineSpecificValue = null
|
|
297
|
-
engineSpecificInstallValue = null
|
|
298
|
-
} else {
|
|
299
|
-
defaultShellName = 'psql'
|
|
300
|
-
engineSpecificCli = 'pgcli'
|
|
301
|
-
engineSpecificInstalled = pgcliInstalled
|
|
302
|
-
engineSpecificValue = 'pgcli'
|
|
303
|
-
engineSpecificInstallValue = 'install-pgcli'
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Check if Qdrant Web UI is installed by verifying actual Web UI files exist
|
|
307
|
-
// (not just an empty static directory)
|
|
308
|
-
let qdrantWebUiInstalled = false
|
|
309
|
-
if (config.engine === 'qdrant') {
|
|
310
|
-
const containerDir = paths.getContainerPath(config.name, {
|
|
311
|
-
engine: 'qdrant',
|
|
312
|
-
})
|
|
313
|
-
const staticDir = join(containerDir, 'static')
|
|
314
|
-
// Check for index.html which is always present in a valid Web UI install
|
|
315
|
-
qdrantWebUiInstalled = existsSync(join(staticDir, 'index.html'))
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const choices: Array<
|
|
319
|
-
{ name: string; value: ShellChoice } | inquirer.Separator
|
|
320
|
-
> = []
|
|
321
|
-
|
|
322
|
-
// For Qdrant: show either "Open Web UI" or "Download Web UI" based on installation status
|
|
323
|
-
if (config.engine === 'qdrant') {
|
|
324
|
-
if (qdrantWebUiInstalled) {
|
|
325
|
-
choices.push({
|
|
326
|
-
name: `◎ Open Web UI in browser`,
|
|
327
|
-
value: 'default',
|
|
328
|
-
})
|
|
329
|
-
} else {
|
|
330
|
-
choices.push({
|
|
331
|
-
name: `↓ Download Web UI (enables dashboard)`,
|
|
332
|
-
value: 'install-webui',
|
|
333
|
-
})
|
|
334
|
-
}
|
|
335
|
-
// Always show API info option for Qdrant
|
|
336
|
-
choices.push({
|
|
337
|
-
name: `ℹ Show API info`,
|
|
338
|
-
value: 'api-info',
|
|
339
|
-
})
|
|
340
|
-
} else if (config.engine === 'meilisearch') {
|
|
341
|
-
// Meilisearch: dashboard is built-in at root URL
|
|
342
|
-
choices.push({
|
|
343
|
-
name: `◎ Open Dashboard in browser`,
|
|
344
|
-
value: 'default',
|
|
345
|
-
})
|
|
346
|
-
// Always show API info option for Meilisearch
|
|
347
|
-
choices.push({
|
|
348
|
-
name: `ℹ Show API info`,
|
|
349
|
-
value: 'api-info',
|
|
350
|
-
})
|
|
351
|
-
} else if (config.engine === 'influxdb') {
|
|
352
|
-
// InfluxDB: influxdb3 query CLI + API info
|
|
353
|
-
choices.push({
|
|
354
|
-
name: `▸ Use default shell (influxdb3 query)`,
|
|
355
|
-
value: 'default',
|
|
356
|
-
})
|
|
357
|
-
choices.push({
|
|
358
|
-
name: `ℹ Show API info`,
|
|
359
|
-
value: 'api-info',
|
|
360
|
-
})
|
|
361
|
-
} else if (config.engine === 'weaviate') {
|
|
362
|
-
// Weaviate: REST API dashboard + API info
|
|
363
|
-
choices.push({
|
|
364
|
-
name: `◎ Open Dashboard in browser`,
|
|
365
|
-
value: 'default',
|
|
366
|
-
})
|
|
367
|
-
choices.push({
|
|
368
|
-
name: `ℹ Show API info`,
|
|
369
|
-
value: 'api-info',
|
|
370
|
-
})
|
|
371
|
-
} else if (config.engine === 'couchdb') {
|
|
372
|
-
// CouchDB: Fauxton dashboard is built-in at /_utils
|
|
373
|
-
choices.push({
|
|
374
|
-
name: `◎ Open Fauxton Dashboard in browser`,
|
|
375
|
-
value: 'default',
|
|
376
|
-
})
|
|
377
|
-
// Always show API info option for CouchDB
|
|
378
|
-
choices.push({
|
|
379
|
-
name: `ℹ Show API info`,
|
|
380
|
-
value: 'api-info',
|
|
381
|
-
})
|
|
382
|
-
} else {
|
|
383
|
-
// Non-REST-API engines: show default shell option
|
|
384
|
-
choices.push({
|
|
385
|
-
name: `▸ Use default shell (${defaultShellName})`,
|
|
386
|
-
value: 'default',
|
|
387
|
-
})
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Only show engine-specific CLI option if one exists (MongoDB's mongosh IS the default)
|
|
391
|
-
if (engineSpecificCli !== null) {
|
|
392
|
-
if (engineSpecificInstalled) {
|
|
393
|
-
choices.push({
|
|
394
|
-
name: `★ Use ${engineSpecificCli} (enhanced features, recommended)`,
|
|
395
|
-
value: engineSpecificValue!,
|
|
396
|
-
})
|
|
397
|
-
} else {
|
|
398
|
-
choices.push({
|
|
399
|
-
name: `↓ Install ${engineSpecificCli} (enhanced features, recommended)`,
|
|
400
|
-
value: engineSpecificInstallValue!,
|
|
401
|
-
})
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// usql supports SQL databases - skip for non-SQL engines
|
|
406
|
-
const engineConfig = await getEngineConfig(config.engine)
|
|
407
|
-
if (engineConfig.queryLanguage === 'sql') {
|
|
408
|
-
if (usqlInstalled) {
|
|
409
|
-
choices.push({
|
|
410
|
-
name: '★ Use usql (universal SQL client)',
|
|
411
|
-
value: 'usql',
|
|
412
|
-
})
|
|
413
|
-
} else {
|
|
414
|
-
choices.push({
|
|
415
|
-
name: '↓ Install usql (universal SQL client)',
|
|
416
|
-
value: 'install-usql',
|
|
417
|
-
})
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// dblab visual TUI (supports PostgreSQL, MySQL, MariaDB, CockroachDB, SQLite, QuestDB)
|
|
422
|
-
if (DBLAB_ENGINES.has(config.engine)) {
|
|
423
|
-
const dblabPath = await configManager.getBinaryPath('dblab')
|
|
424
|
-
if (dblabPath) {
|
|
425
|
-
choices.push({
|
|
426
|
-
name: '★ Use dblab (visual TUI)',
|
|
427
|
-
value: 'dblab',
|
|
428
|
-
})
|
|
429
|
-
} else {
|
|
430
|
-
choices.push({
|
|
431
|
-
name: '↓ Download dblab (visual TUI)',
|
|
432
|
-
value: 'install-dblab',
|
|
433
|
-
})
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// Web Panel section for engines with browser-based UIs
|
|
438
|
-
if (config.engine === 'clickhouse') {
|
|
439
|
-
const httpPort = config.port + 1
|
|
440
|
-
choices.push(new inquirer.Separator(chalk.gray(`───── Web Panel ─────`)))
|
|
441
|
-
choices.push({
|
|
442
|
-
name: `◎ Open Play UI (port ${httpPort})`,
|
|
443
|
-
value: 'browser',
|
|
444
|
-
})
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
if (config.engine === 'questdb') {
|
|
448
|
-
const httpPort = config.port + 188
|
|
449
|
-
choices.push(new inquirer.Separator(chalk.gray(`───── Web Panel ─────`)))
|
|
450
|
-
choices.push({
|
|
451
|
-
name: `◎ Open Web Console (port ${httpPort})`,
|
|
452
|
-
value: 'browser',
|
|
453
|
-
})
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
if (config.engine === 'duckdb') {
|
|
457
|
-
choices.push(new inquirer.Separator(chalk.gray(`───── Web Panel ─────`)))
|
|
458
|
-
choices.push({
|
|
459
|
-
name: `◎ Open Web UI (built-in, port 4213)`,
|
|
460
|
-
value: 'duckdb-ui',
|
|
461
|
-
})
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if (
|
|
465
|
-
config.engine === 'postgresql' ||
|
|
466
|
-
config.engine === 'cockroachdb' ||
|
|
467
|
-
config.engine === 'ferretdb'
|
|
468
|
-
) {
|
|
469
|
-
choices.push(new inquirer.Separator(chalk.gray(`───── Web Panel ─────`)))
|
|
470
|
-
const pgwebPath = await configManager.getBinaryPath('pgweb')
|
|
471
|
-
if (pgwebPath) {
|
|
472
|
-
const pgwebStatus = await getPgwebStatus(containerName, config.engine)
|
|
473
|
-
if (pgwebStatus.running) {
|
|
474
|
-
choices.push({
|
|
475
|
-
name: `◎ Open pgweb (port ${pgwebStatus.port})`,
|
|
476
|
-
value: 'pgweb',
|
|
477
|
-
})
|
|
478
|
-
choices.push({
|
|
479
|
-
name: `■ Stop pgweb`,
|
|
480
|
-
value: 'stop-pgweb',
|
|
481
|
-
})
|
|
482
|
-
} else {
|
|
483
|
-
choices.push({
|
|
484
|
-
name: `◎ Open pgweb`,
|
|
485
|
-
value: 'pgweb',
|
|
486
|
-
})
|
|
487
|
-
}
|
|
488
|
-
} else {
|
|
489
|
-
choices.push({
|
|
490
|
-
name: `↓ Download pgweb`,
|
|
491
|
-
value: 'install-pgweb',
|
|
492
|
-
})
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
choices.push(new inquirer.Separator())
|
|
497
|
-
choices.push({
|
|
498
|
-
name: `${chalk.blue('←')} Back`,
|
|
499
|
-
value: 'back',
|
|
500
|
-
})
|
|
501
|
-
|
|
502
|
-
const { shellChoice } = await escapeablePrompt<{ shellChoice: ShellChoice }>([
|
|
503
|
-
{
|
|
504
|
-
type: 'list',
|
|
505
|
-
name: 'shellChoice',
|
|
506
|
-
message: 'Select console option:',
|
|
507
|
-
choices,
|
|
508
|
-
pageSize: getPageSize(),
|
|
509
|
-
},
|
|
510
|
-
])
|
|
511
|
-
|
|
512
|
-
if (shellChoice === 'back') {
|
|
513
|
-
return
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Handle browser option for ClickHouse Play UI
|
|
517
|
-
if (shellChoice === 'browser') {
|
|
518
|
-
if (config.engine === 'clickhouse') {
|
|
519
|
-
// ClickHouse HTTP port is native port + 1 (e.g., 9000 -> 9001)
|
|
520
|
-
const httpPort = config.port + 1
|
|
521
|
-
const playUrl = `http://127.0.0.1:${httpPort}/play`
|
|
522
|
-
console.log()
|
|
523
|
-
console.log(uiInfo(`Opening ClickHouse Play UI in browser...`))
|
|
524
|
-
console.log(chalk.gray(` ${playUrl}`))
|
|
525
|
-
console.log()
|
|
526
|
-
openInBrowser(playUrl)
|
|
527
|
-
await pressEnterToContinue()
|
|
528
|
-
} else if (config.engine === 'questdb') {
|
|
529
|
-
// QuestDB Web Console on HTTP port (PG port + 188)
|
|
530
|
-
const httpPort = config.port + 188
|
|
531
|
-
const consoleUrl = `http://127.0.0.1:${httpPort}`
|
|
532
|
-
console.log()
|
|
533
|
-
console.log(uiInfo(`Opening QuestDB Web Console in browser...`))
|
|
534
|
-
console.log(chalk.gray(` ${consoleUrl}`))
|
|
535
|
-
console.log()
|
|
536
|
-
openInBrowser(consoleUrl)
|
|
537
|
-
await pressEnterToContinue()
|
|
538
|
-
}
|
|
539
|
-
return
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// Handle DuckDB built-in Web UI (duckdb -ui)
|
|
543
|
-
if (shellChoice === 'duckdb-ui') {
|
|
544
|
-
const duckdbPath = await configManager.getBinaryPath('duckdb')
|
|
545
|
-
if (!duckdbPath) {
|
|
546
|
-
console.error(
|
|
547
|
-
uiError(
|
|
548
|
-
'DuckDB binary not found. Download it with: spindb engines download duckdb',
|
|
549
|
-
),
|
|
550
|
-
)
|
|
551
|
-
await pressEnterToContinue()
|
|
552
|
-
return
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
console.log()
|
|
556
|
-
console.log(uiInfo('Launching DuckDB Web UI...'))
|
|
557
|
-
console.log(chalk.gray(' http://localhost:4213'))
|
|
558
|
-
console.log()
|
|
559
|
-
|
|
560
|
-
const uiProcess = spawn(duckdbPath, [config.database, '-ui'], {
|
|
561
|
-
stdio: 'inherit',
|
|
562
|
-
})
|
|
563
|
-
|
|
564
|
-
await new Promise<void>((resolve) => {
|
|
565
|
-
let settled = false
|
|
566
|
-
const settle = () => {
|
|
567
|
-
if (!settled) {
|
|
568
|
-
settled = true
|
|
569
|
-
resolve()
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
uiProcess.on('error', (err: NodeJS.ErrnoException) => {
|
|
574
|
-
if (err.code === 'ENOENT') {
|
|
575
|
-
console.log(uiWarning('DuckDB binary not found.'))
|
|
576
|
-
} else {
|
|
577
|
-
console.log(uiError(`Failed to start DuckDB UI: ${err.message}`))
|
|
578
|
-
}
|
|
579
|
-
settle()
|
|
580
|
-
})
|
|
581
|
-
|
|
582
|
-
uiProcess.on('close', () => {
|
|
583
|
-
if (process.stdout.isTTY) {
|
|
584
|
-
process.stdout.write('\x1b[2J\x1b[3J\x1b[H')
|
|
585
|
-
}
|
|
586
|
-
settle()
|
|
587
|
-
})
|
|
588
|
-
})
|
|
589
|
-
return
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// Handle Qdrant/Meilisearch API info display
|
|
593
|
-
if (shellChoice === 'api-info') {
|
|
594
|
-
console.log()
|
|
595
|
-
if (config.engine === 'qdrant') {
|
|
596
|
-
console.log(chalk.cyan('Qdrant REST API:'))
|
|
597
|
-
console.log(chalk.white(` HTTP: http://127.0.0.1:${config.port}`))
|
|
598
|
-
console.log(chalk.white(` gRPC: 127.0.0.1:${config.port + 1}`))
|
|
599
|
-
console.log()
|
|
600
|
-
console.log(chalk.gray('Example curl commands:'))
|
|
601
|
-
console.log(
|
|
602
|
-
chalk.gray(` curl http://127.0.0.1:${config.port}/collections`),
|
|
603
|
-
)
|
|
604
|
-
console.log(chalk.gray(` curl http://127.0.0.1:${config.port}/healthz`))
|
|
605
|
-
} else if (config.engine === 'meilisearch') {
|
|
606
|
-
console.log(chalk.cyan('Meilisearch REST API:'))
|
|
607
|
-
console.log(chalk.white(` HTTP: http://127.0.0.1:${config.port}`))
|
|
608
|
-
console.log()
|
|
609
|
-
console.log(chalk.gray('Example curl commands:'))
|
|
610
|
-
console.log(chalk.gray(` curl http://127.0.0.1:${config.port}/indexes`))
|
|
611
|
-
console.log(chalk.gray(` curl http://127.0.0.1:${config.port}/health`))
|
|
612
|
-
console.log(chalk.gray(` curl http://127.0.0.1:${config.port}/stats`))
|
|
613
|
-
} else if (config.engine === 'influxdb') {
|
|
614
|
-
console.log(chalk.cyan('InfluxDB REST API:'))
|
|
615
|
-
console.log(chalk.white(` HTTP: http://127.0.0.1:${config.port}`))
|
|
616
|
-
console.log()
|
|
617
|
-
console.log(chalk.gray('Example curl commands:'))
|
|
618
|
-
console.log(chalk.gray(` curl http://127.0.0.1:${config.port}/health`))
|
|
619
|
-
console.log(
|
|
620
|
-
chalk.gray(
|
|
621
|
-
` curl -H "Content-Type: application/json" http://127.0.0.1:${config.port}/api/v3/query_sql -d '{"db":"mydb","q":"SELECT 1"}'`,
|
|
622
|
-
),
|
|
623
|
-
)
|
|
624
|
-
} else if (config.engine === 'weaviate') {
|
|
625
|
-
console.log(chalk.cyan('Weaviate REST API:'))
|
|
626
|
-
console.log(chalk.white(` HTTP: http://127.0.0.1:${config.port}`))
|
|
627
|
-
console.log(chalk.white(` gRPC: 127.0.0.1:${config.port + 1}`))
|
|
628
|
-
console.log()
|
|
629
|
-
console.log(chalk.gray('Example curl commands:'))
|
|
630
|
-
console.log(
|
|
631
|
-
chalk.gray(
|
|
632
|
-
` curl http://127.0.0.1:${config.port}/v1/.well-known/ready`,
|
|
633
|
-
),
|
|
634
|
-
)
|
|
635
|
-
console.log(
|
|
636
|
-
chalk.gray(` curl http://127.0.0.1:${config.port}/v1/schema`),
|
|
637
|
-
)
|
|
638
|
-
} else if (config.engine === 'couchdb') {
|
|
639
|
-
console.log(chalk.cyan('CouchDB REST API:'))
|
|
640
|
-
console.log(chalk.white(` HTTP: http://127.0.0.1:${config.port}`))
|
|
641
|
-
console.log(
|
|
642
|
-
chalk.white(` Fauxton: http://127.0.0.1:${config.port}/_utils`),
|
|
643
|
-
)
|
|
644
|
-
console.log()
|
|
645
|
-
console.log(chalk.cyan('Credentials:'))
|
|
646
|
-
console.log(chalk.white(` Username: admin`))
|
|
647
|
-
console.log(chalk.white(` Password: admin`))
|
|
648
|
-
console.log()
|
|
649
|
-
console.log(chalk.gray('Example curl commands:'))
|
|
650
|
-
console.log(chalk.gray(` curl http://127.0.0.1:${config.port}`))
|
|
651
|
-
console.log(chalk.gray(` curl http://127.0.0.1:${config.port}/_all_dbs`))
|
|
652
|
-
console.log(
|
|
653
|
-
chalk.gray(` curl -X PUT http://127.0.0.1:${config.port}/mydb`),
|
|
654
|
-
)
|
|
655
|
-
}
|
|
656
|
-
console.log()
|
|
657
|
-
await pressEnterToContinue()
|
|
658
|
-
return
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
if (shellChoice === 'install-pgcli') {
|
|
662
|
-
console.log()
|
|
663
|
-
console.log(uiInfo('Installing pgcli for enhanced PostgreSQL shell...'))
|
|
664
|
-
const pm = await detectPackageManager()
|
|
665
|
-
if (pm) {
|
|
666
|
-
const result = await installPgcli(pm)
|
|
667
|
-
if (result.success) {
|
|
668
|
-
console.log(uiSuccess('pgcli installed successfully!'))
|
|
669
|
-
console.log()
|
|
670
|
-
await launchShell(
|
|
671
|
-
containerName,
|
|
672
|
-
config,
|
|
673
|
-
connectionString,
|
|
674
|
-
'pgcli',
|
|
675
|
-
activeDatabase,
|
|
676
|
-
)
|
|
677
|
-
} else {
|
|
678
|
-
console.error(uiError(`Failed to install pgcli: ${result.error}`))
|
|
679
|
-
console.log()
|
|
680
|
-
console.log(chalk.gray('Manual installation:'))
|
|
681
|
-
for (const instruction of getPgcliManualInstructions()) {
|
|
682
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
683
|
-
}
|
|
684
|
-
console.log()
|
|
685
|
-
await pressEnterToContinue()
|
|
686
|
-
}
|
|
687
|
-
} else {
|
|
688
|
-
console.error(uiError('No supported package manager found'))
|
|
689
|
-
console.log()
|
|
690
|
-
console.log(chalk.gray('Manual installation:'))
|
|
691
|
-
for (const instruction of getPgcliManualInstructions()) {
|
|
692
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
693
|
-
}
|
|
694
|
-
console.log()
|
|
695
|
-
await pressEnterToContinue()
|
|
696
|
-
}
|
|
697
|
-
return
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
if (shellChoice === 'install-mycli') {
|
|
701
|
-
console.log()
|
|
702
|
-
console.log(uiInfo('Installing mycli for enhanced MySQL shell...'))
|
|
703
|
-
const pm = await detectPackageManager()
|
|
704
|
-
if (pm) {
|
|
705
|
-
const result = await installMycli(pm)
|
|
706
|
-
if (result.success) {
|
|
707
|
-
console.log(uiSuccess('mycli installed successfully!'))
|
|
708
|
-
console.log()
|
|
709
|
-
await launchShell(
|
|
710
|
-
containerName,
|
|
711
|
-
config,
|
|
712
|
-
connectionString,
|
|
713
|
-
'mycli',
|
|
714
|
-
activeDatabase,
|
|
715
|
-
)
|
|
716
|
-
} else {
|
|
717
|
-
console.error(uiError(`Failed to install mycli: ${result.error}`))
|
|
718
|
-
console.log()
|
|
719
|
-
console.log(chalk.gray('Manual installation:'))
|
|
720
|
-
for (const instruction of getMycliManualInstructions()) {
|
|
721
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
722
|
-
}
|
|
723
|
-
console.log()
|
|
724
|
-
await pressEnterToContinue()
|
|
725
|
-
}
|
|
726
|
-
} else {
|
|
727
|
-
console.error(uiError('No supported package manager found'))
|
|
728
|
-
console.log()
|
|
729
|
-
console.log(chalk.gray('Manual installation:'))
|
|
730
|
-
for (const instruction of getMycliManualInstructions()) {
|
|
731
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
732
|
-
}
|
|
733
|
-
console.log()
|
|
734
|
-
await pressEnterToContinue()
|
|
735
|
-
}
|
|
736
|
-
return
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
if (shellChoice === 'install-usql') {
|
|
740
|
-
console.log()
|
|
741
|
-
console.log(uiInfo('Installing usql for enhanced shell experience...'))
|
|
742
|
-
const pm = await detectPackageManager()
|
|
743
|
-
if (pm) {
|
|
744
|
-
const result = await installUsql(pm)
|
|
745
|
-
if (result.success) {
|
|
746
|
-
console.log(uiSuccess('usql installed successfully!'))
|
|
747
|
-
console.log()
|
|
748
|
-
await launchShell(
|
|
749
|
-
containerName,
|
|
750
|
-
config,
|
|
751
|
-
connectionString,
|
|
752
|
-
'usql',
|
|
753
|
-
activeDatabase,
|
|
754
|
-
)
|
|
755
|
-
} else {
|
|
756
|
-
console.error(uiError(`Failed to install usql: ${result.error}`))
|
|
757
|
-
console.log()
|
|
758
|
-
console.log(chalk.gray('Manual installation:'))
|
|
759
|
-
for (const instruction of getUsqlManualInstructions()) {
|
|
760
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
761
|
-
}
|
|
762
|
-
console.log()
|
|
763
|
-
await pressEnterToContinue()
|
|
764
|
-
}
|
|
765
|
-
} else {
|
|
766
|
-
console.error(uiError('No supported package manager found'))
|
|
767
|
-
console.log()
|
|
768
|
-
console.log(chalk.gray('Manual installation:'))
|
|
769
|
-
for (const instruction of getUsqlManualInstructions()) {
|
|
770
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
771
|
-
}
|
|
772
|
-
console.log()
|
|
773
|
-
await pressEnterToContinue()
|
|
774
|
-
}
|
|
775
|
-
return
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
if (shellChoice === 'install-litecli') {
|
|
779
|
-
console.log()
|
|
780
|
-
console.log(uiInfo('Installing litecli for enhanced SQLite shell...'))
|
|
781
|
-
const pm = await detectPackageManager()
|
|
782
|
-
if (pm) {
|
|
783
|
-
const result = await installLitecli(pm)
|
|
784
|
-
if (result.success) {
|
|
785
|
-
console.log(uiSuccess('litecli installed successfully!'))
|
|
786
|
-
console.log()
|
|
787
|
-
await launchShell(
|
|
788
|
-
containerName,
|
|
789
|
-
config,
|
|
790
|
-
connectionString,
|
|
791
|
-
'litecli',
|
|
792
|
-
activeDatabase,
|
|
793
|
-
)
|
|
794
|
-
} else {
|
|
795
|
-
console.error(uiError(`Failed to install litecli: ${result.error}`))
|
|
796
|
-
console.log()
|
|
797
|
-
console.log(chalk.gray('Manual installation:'))
|
|
798
|
-
for (const instruction of getLitecliManualInstructions()) {
|
|
799
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
800
|
-
}
|
|
801
|
-
console.log()
|
|
802
|
-
await pressEnterToContinue()
|
|
803
|
-
}
|
|
804
|
-
} else {
|
|
805
|
-
console.error(uiError('No supported package manager found'))
|
|
806
|
-
console.log()
|
|
807
|
-
console.log(chalk.gray('Manual installation:'))
|
|
808
|
-
for (const instruction of getLitecliManualInstructions()) {
|
|
809
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
810
|
-
}
|
|
811
|
-
console.log()
|
|
812
|
-
await pressEnterToContinue()
|
|
813
|
-
}
|
|
814
|
-
return
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
if (shellChoice === 'install-iredis') {
|
|
818
|
-
console.log()
|
|
819
|
-
console.log(uiInfo('Installing iredis for enhanced Redis shell...'))
|
|
820
|
-
const pm = await detectPackageManager()
|
|
821
|
-
if (pm) {
|
|
822
|
-
const result = await installIredis(pm)
|
|
823
|
-
if (result.success) {
|
|
824
|
-
console.log(uiSuccess('iredis installed successfully!'))
|
|
825
|
-
console.log()
|
|
826
|
-
await launchShell(
|
|
827
|
-
containerName,
|
|
828
|
-
config,
|
|
829
|
-
connectionString,
|
|
830
|
-
'iredis',
|
|
831
|
-
activeDatabase,
|
|
832
|
-
)
|
|
833
|
-
} else {
|
|
834
|
-
console.error(uiError(`Failed to install iredis: ${result.error}`))
|
|
835
|
-
console.log()
|
|
836
|
-
console.log(chalk.gray('Manual installation:'))
|
|
837
|
-
for (const instruction of getIredisManualInstructions(
|
|
838
|
-
platformService.getPlatformInfo().platform,
|
|
839
|
-
)) {
|
|
840
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
841
|
-
}
|
|
842
|
-
console.log()
|
|
843
|
-
await pressEnterToContinue()
|
|
844
|
-
}
|
|
845
|
-
} else {
|
|
846
|
-
console.error(uiError('No supported package manager found'))
|
|
847
|
-
console.log()
|
|
848
|
-
console.log(chalk.gray('Manual installation:'))
|
|
849
|
-
for (const instruction of getIredisManualInstructions(
|
|
850
|
-
platformService.getPlatformInfo().platform,
|
|
851
|
-
)) {
|
|
852
|
-
console.log(chalk.cyan(` ${instruction}`))
|
|
853
|
-
}
|
|
854
|
-
console.log()
|
|
855
|
-
await pressEnterToContinue()
|
|
856
|
-
}
|
|
857
|
-
return
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
// Handle dblab download → launch immediately after install
|
|
861
|
-
if (shellChoice === 'install-dblab') {
|
|
862
|
-
const dblabBinaryPath = await downloadDblabCli()
|
|
863
|
-
if (dblabBinaryPath) {
|
|
864
|
-
await launchDblab(config, activeDatabase)
|
|
865
|
-
}
|
|
866
|
-
return
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
// Handle dblab launch
|
|
870
|
-
if (shellChoice === 'dblab') {
|
|
871
|
-
await launchDblab(config, activeDatabase)
|
|
872
|
-
return
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
// Handle pgweb download → launch immediately after install
|
|
876
|
-
if (shellChoice === 'install-pgweb') {
|
|
877
|
-
const pgwebBinaryPath = await downloadPgweb()
|
|
878
|
-
if (pgwebBinaryPath) {
|
|
879
|
-
await launchPgweb(containerName, config, activeDatabase)
|
|
880
|
-
}
|
|
881
|
-
return
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
// Handle pgweb launch
|
|
885
|
-
if (shellChoice === 'pgweb') {
|
|
886
|
-
await launchPgweb(containerName, config, activeDatabase)
|
|
887
|
-
return
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
// Handle pgweb stop
|
|
891
|
-
if (shellChoice === 'stop-pgweb') {
|
|
892
|
-
await stopPgwebProcess(containerName, config.engine)
|
|
893
|
-
return
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
// Handle install-webui option for Qdrant
|
|
897
|
-
if (shellChoice === 'install-webui') {
|
|
898
|
-
if (config.engine === 'qdrant') {
|
|
899
|
-
await downloadQdrantWebUI(config.name)
|
|
900
|
-
}
|
|
901
|
-
return
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
await launchShell(
|
|
905
|
-
containerName,
|
|
906
|
-
config,
|
|
907
|
-
connectionString,
|
|
908
|
-
shellChoice,
|
|
909
|
-
activeDatabase,
|
|
910
|
-
)
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
/**
|
|
914
|
-
* Download and install Qdrant Web UI from GitHub releases
|
|
915
|
-
*/
|
|
916
|
-
async function downloadQdrantWebUI(containerName: string): Promise<void> {
|
|
917
|
-
console.log()
|
|
918
|
-
const spinner = createSpinner('Downloading Qdrant Web UI...')
|
|
919
|
-
spinner.start()
|
|
920
|
-
|
|
921
|
-
try {
|
|
922
|
-
// Get latest release info from GitHub
|
|
923
|
-
const releaseUrl =
|
|
924
|
-
'https://api.github.com/repos/qdrant/qdrant-web-ui/releases/latest'
|
|
925
|
-
const releaseResponse = await fetch(releaseUrl, {
|
|
926
|
-
headers: { 'User-Agent': 'spindb' },
|
|
927
|
-
})
|
|
928
|
-
|
|
929
|
-
if (!releaseResponse.ok) {
|
|
930
|
-
throw new Error(`Failed to fetch release info: ${releaseResponse.status}`)
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
const releaseData = (await releaseResponse.json()) as {
|
|
934
|
-
assets: Array<{ name: string; browser_download_url: string }>
|
|
935
|
-
tag_name: string
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
// Find dist-qdrant.zip asset
|
|
939
|
-
const zipAsset = releaseData.assets.find(
|
|
940
|
-
(a) => a.name === 'dist-qdrant.zip',
|
|
941
|
-
)
|
|
942
|
-
if (!zipAsset) {
|
|
943
|
-
throw new Error('Could not find dist-qdrant.zip in latest release')
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
spinner.text = `Downloading Qdrant Web UI ${releaseData.tag_name}...`
|
|
947
|
-
|
|
948
|
-
// Download the zip file
|
|
949
|
-
const downloadResponse = await fetch(zipAsset.browser_download_url)
|
|
950
|
-
if (!downloadResponse.ok || !downloadResponse.body) {
|
|
951
|
-
throw new Error(`Failed to download: ${downloadResponse.status}`)
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
// Get container directory and create static folder
|
|
955
|
-
const containerDir = paths.getContainerPath(containerName, {
|
|
956
|
-
engine: 'qdrant',
|
|
957
|
-
})
|
|
958
|
-
const staticDir = join(containerDir, 'static')
|
|
959
|
-
|
|
960
|
-
// Remove existing static dir if present
|
|
961
|
-
await rm(staticDir, { recursive: true, force: true })
|
|
962
|
-
await mkdir(staticDir, { recursive: true })
|
|
963
|
-
|
|
964
|
-
spinner.text = 'Extracting Web UI...'
|
|
965
|
-
|
|
966
|
-
// Save and extract zip
|
|
967
|
-
const tempZip = join(containerDir, 'webui-temp.zip')
|
|
968
|
-
const buffer = Buffer.from(await downloadResponse.arrayBuffer())
|
|
969
|
-
await writeFile(tempZip, buffer)
|
|
970
|
-
|
|
971
|
-
try {
|
|
972
|
-
// Extract zip - the zip contains a 'dist' folder, we need its contents
|
|
973
|
-
const unzipper = await import('unzipper')
|
|
974
|
-
const directory = await unzipper.Open.file(tempZip)
|
|
975
|
-
|
|
976
|
-
// Resolve staticDir to absolute path for zip-slip protection
|
|
977
|
-
const resolvedStaticDir = resolve(staticDir)
|
|
978
|
-
|
|
979
|
-
for (const entry of directory.files) {
|
|
980
|
-
// Skip directories and files not in dist/
|
|
981
|
-
if (entry.type === 'Directory') continue
|
|
982
|
-
if (!entry.path.startsWith('dist/')) continue
|
|
983
|
-
|
|
984
|
-
// Remove 'dist/' prefix to get relative path
|
|
985
|
-
const relativePath = entry.path.replace(/^dist\//, '')
|
|
986
|
-
if (!relativePath) continue
|
|
987
|
-
|
|
988
|
-
// Zip-slip protection: ensure resolved path is within staticDir
|
|
989
|
-
// Use path.sep for platform-safe comparison (backslash on Windows, forward slash on Unix)
|
|
990
|
-
const targetPath = resolve(staticDir, relativePath)
|
|
991
|
-
if (!targetPath.startsWith(resolvedStaticDir + sep)) {
|
|
992
|
-
// Path traversal attempt - skip this entry
|
|
993
|
-
continue
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
const targetDir = dirname(targetPath)
|
|
997
|
-
await mkdir(targetDir, { recursive: true })
|
|
998
|
-
const content = await entry.buffer()
|
|
999
|
-
await writeFile(targetPath, content)
|
|
1000
|
-
}
|
|
1001
|
-
} finally {
|
|
1002
|
-
// Clean up temp zip even if extraction fails
|
|
1003
|
-
await rm(tempZip, { force: true })
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
spinner.succeed(`Qdrant Web UI ${releaseData.tag_name} installed`)
|
|
1007
|
-
console.log()
|
|
1008
|
-
console.log(uiWarning('Restart Qdrant for the Web UI to take effect:'))
|
|
1009
|
-
console.log(
|
|
1010
|
-
chalk.gray(
|
|
1011
|
-
` spindb stop ${containerName} && spindb start ${containerName}`,
|
|
1012
|
-
),
|
|
1013
|
-
)
|
|
1014
|
-
console.log()
|
|
1015
|
-
} catch (error) {
|
|
1016
|
-
spinner.fail('Failed to download Qdrant Web UI')
|
|
1017
|
-
console.error(uiError((error as Error).message))
|
|
1018
|
-
console.log()
|
|
1019
|
-
console.log(chalk.gray('You can manually download from:'))
|
|
1020
|
-
console.log(
|
|
1021
|
-
chalk.cyan(' https://github.com/qdrant/qdrant-web-ui/releases'),
|
|
1022
|
-
)
|
|
1023
|
-
console.log(chalk.gray(`\nExtract dist-qdrant.zip contents to:`))
|
|
1024
|
-
console.log(
|
|
1025
|
-
chalk.cyan(
|
|
1026
|
-
` ${paths.getContainerPath(containerName, { engine: 'qdrant' })}/static/`,
|
|
1027
|
-
),
|
|
1028
|
-
)
|
|
1029
|
-
console.log()
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
await pressEnterToContinue()
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
/**
|
|
1036
|
-
* Stop a running pgweb process for a container (with UI feedback)
|
|
1037
|
-
*/
|
|
1038
|
-
export async function stopPgwebProcess(
|
|
1039
|
-
containerName: string,
|
|
1040
|
-
engine: string,
|
|
1041
|
-
): Promise<void> {
|
|
1042
|
-
const stopped = await stopPgweb(containerName, engine)
|
|
1043
|
-
|
|
1044
|
-
console.log()
|
|
1045
|
-
if (stopped) {
|
|
1046
|
-
console.log(uiSuccess('pgweb stopped'))
|
|
1047
|
-
} else {
|
|
1048
|
-
console.log(uiInfo('pgweb is not running'))
|
|
1049
|
-
}
|
|
1050
|
-
console.log()
|
|
1051
|
-
await pressEnterToContinue()
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
/**
|
|
1055
|
-
* Download and install pgweb from GitHub releases
|
|
1056
|
-
*/
|
|
1057
|
-
async function downloadPgweb(): Promise<string | null> {
|
|
1058
|
-
console.log()
|
|
1059
|
-
const spinner = createSpinner('Downloading pgweb...')
|
|
1060
|
-
spinner.start()
|
|
1061
|
-
|
|
1062
|
-
try {
|
|
1063
|
-
const platform = process.platform
|
|
1064
|
-
const arch = process.arch
|
|
1065
|
-
let suffix: string
|
|
1066
|
-
|
|
1067
|
-
if (platform === 'darwin' && arch === 'arm64') {
|
|
1068
|
-
suffix = 'darwin_arm64'
|
|
1069
|
-
} else if (platform === 'darwin' && arch === 'x64') {
|
|
1070
|
-
suffix = 'darwin_amd64'
|
|
1071
|
-
} else if (platform === 'linux' && arch === 'arm64') {
|
|
1072
|
-
suffix = 'linux_arm64'
|
|
1073
|
-
} else if (platform === 'linux' && arch === 'x64') {
|
|
1074
|
-
suffix = 'linux_amd64'
|
|
1075
|
-
} else if (platform === 'win32' && arch === 'x64') {
|
|
1076
|
-
suffix = 'windows_amd64.exe'
|
|
1077
|
-
} else {
|
|
1078
|
-
throw new Error(`Unsupported platform: ${platform} ${arch}`)
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
const zipUrl = `https://github.com/sosedoff/pgweb/releases/download/v${PGWEB_VERSION}/pgweb_${suffix}.zip`
|
|
1082
|
-
|
|
1083
|
-
spinner.text = `Downloading pgweb v${PGWEB_VERSION}...`
|
|
1084
|
-
|
|
1085
|
-
const response = await fetch(zipUrl)
|
|
1086
|
-
if (!response.ok || !response.body) {
|
|
1087
|
-
throw new Error(`Failed to download: ${response.status}`)
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
const isWin = platform === 'win32'
|
|
1091
|
-
const binaryName = isWin ? 'pgweb.exe' : 'pgweb'
|
|
1092
|
-
const platformArch = `${platform}-${arch}`
|
|
1093
|
-
const installDir = join(
|
|
1094
|
-
paths.bin,
|
|
1095
|
-
`pgweb-${PGWEB_VERSION}-${platformArch}`,
|
|
1096
|
-
'bin',
|
|
1097
|
-
)
|
|
1098
|
-
await mkdir(installDir, { recursive: true })
|
|
1099
|
-
|
|
1100
|
-
const tempZip = join(paths.bin, 'pgweb-temp.zip')
|
|
1101
|
-
const buffer = Buffer.from(await response.arrayBuffer())
|
|
1102
|
-
await writeFile(tempZip, buffer)
|
|
1103
|
-
|
|
1104
|
-
spinner.text = 'Extracting pgweb...'
|
|
1105
|
-
|
|
1106
|
-
try {
|
|
1107
|
-
const unzipper = await import('unzipper')
|
|
1108
|
-
const directory = await unzipper.Open.file(tempZip)
|
|
1109
|
-
|
|
1110
|
-
const resolvedInstallDir = resolve(installDir)
|
|
1111
|
-
let extracted = false
|
|
1112
|
-
|
|
1113
|
-
for (const entry of directory.files) {
|
|
1114
|
-
if (entry.type === 'Directory') continue
|
|
1115
|
-
|
|
1116
|
-
// Zip-slip protection
|
|
1117
|
-
const targetPath = resolve(installDir, binaryName)
|
|
1118
|
-
if (!targetPath.startsWith(resolvedInstallDir + sep)) {
|
|
1119
|
-
continue
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
// The zip contains the binary (possibly named pgweb_<platform>_<arch> or pgweb_<platform>_<arch>.exe)
|
|
1123
|
-
const content = await entry.buffer()
|
|
1124
|
-
await writeFile(targetPath, content)
|
|
1125
|
-
extracted = true
|
|
1126
|
-
break // Only one file in the zip
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
if (!extracted) {
|
|
1130
|
-
throw new Error('Could not find pgweb binary in zip archive')
|
|
1131
|
-
}
|
|
1132
|
-
} finally {
|
|
1133
|
-
await rm(tempZip, { force: true })
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
const binaryPath = join(installDir, binaryName)
|
|
1137
|
-
|
|
1138
|
-
// chmod on Unix
|
|
1139
|
-
if (!isWin) {
|
|
1140
|
-
await chmod(binaryPath, 0o755)
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
// Register in config
|
|
1144
|
-
await configManager.setBinaryPath('pgweb', binaryPath, 'bundled')
|
|
1145
|
-
|
|
1146
|
-
spinner.succeed(`pgweb v${PGWEB_VERSION} installed`)
|
|
1147
|
-
console.log()
|
|
1148
|
-
|
|
1149
|
-
return binaryPath
|
|
1150
|
-
} catch (error) {
|
|
1151
|
-
spinner.fail('Failed to download pgweb')
|
|
1152
|
-
console.error(uiError((error as Error).message))
|
|
1153
|
-
console.log()
|
|
1154
|
-
console.log(chalk.gray('You can manually download from:'))
|
|
1155
|
-
console.log(chalk.cyan(' https://github.com/sosedoff/pgweb/releases'))
|
|
1156
|
-
console.log()
|
|
1157
|
-
await pressEnterToContinue()
|
|
1158
|
-
return null
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
/**
|
|
1163
|
-
* Download and install dblab from GitHub releases.
|
|
1164
|
-
* Exported as downloadDblabCli for use from the CLI connect command.
|
|
1165
|
-
*/
|
|
1166
|
-
export async function downloadDblabCli(): Promise<string | null> {
|
|
1167
|
-
console.log()
|
|
1168
|
-
const spinner = createSpinner('Downloading dblab...')
|
|
1169
|
-
spinner.start()
|
|
1170
|
-
|
|
1171
|
-
try {
|
|
1172
|
-
const suffix = getDblabPlatformSuffix()
|
|
1173
|
-
const tarUrl = `https://github.com/danvergara/dblab/releases/download/v${DBLAB_VERSION}/dblab_${DBLAB_VERSION}_${suffix}.tar.gz`
|
|
1174
|
-
|
|
1175
|
-
spinner.text = `Downloading dblab v${DBLAB_VERSION}...`
|
|
1176
|
-
|
|
1177
|
-
const response = await fetch(tarUrl)
|
|
1178
|
-
if (!response.ok || !response.body) {
|
|
1179
|
-
throw new Error(`Failed to download: ${response.status}`)
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
const isWin = process.platform === 'win32'
|
|
1183
|
-
const binaryName = isWin ? 'dblab.exe' : 'dblab'
|
|
1184
|
-
const platformArch = `${process.platform}-${process.arch}`
|
|
1185
|
-
const installDir = join(
|
|
1186
|
-
paths.bin,
|
|
1187
|
-
`dblab-${DBLAB_VERSION}-${platformArch}`,
|
|
1188
|
-
'bin',
|
|
1189
|
-
)
|
|
1190
|
-
await mkdir(installDir, { recursive: true })
|
|
1191
|
-
|
|
1192
|
-
const tempTar = join(paths.bin, 'dblab-temp.tar.gz')
|
|
1193
|
-
const buffer = Buffer.from(await response.arrayBuffer())
|
|
1194
|
-
await writeFile(tempTar, buffer)
|
|
1195
|
-
|
|
1196
|
-
spinner.text = 'Extracting dblab...'
|
|
1197
|
-
|
|
1198
|
-
try {
|
|
1199
|
-
const { spawnSync } = await import('child_process')
|
|
1200
|
-
const result = spawnSync('tar', ['-xzf', tempTar, '-C', installDir], {
|
|
1201
|
-
stdio: 'pipe',
|
|
1202
|
-
})
|
|
1203
|
-
if (result.status !== 0) {
|
|
1204
|
-
throw new Error(
|
|
1205
|
-
`tar extraction failed: ${result.stderr?.toString() || 'unknown error'}`,
|
|
1206
|
-
)
|
|
1207
|
-
}
|
|
1208
|
-
} finally {
|
|
1209
|
-
await rm(tempTar, { force: true })
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
const binaryPath = join(installDir, binaryName)
|
|
1213
|
-
|
|
1214
|
-
if (!existsSync(binaryPath)) {
|
|
1215
|
-
throw new Error('Could not find dblab binary after extraction')
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
// chmod on Unix
|
|
1219
|
-
if (!isWin) {
|
|
1220
|
-
await chmod(binaryPath, 0o755)
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
// Register in config
|
|
1224
|
-
await configManager.setBinaryPath('dblab', binaryPath, 'bundled')
|
|
1225
|
-
|
|
1226
|
-
spinner.succeed(`dblab v${DBLAB_VERSION} installed`)
|
|
1227
|
-
console.log()
|
|
1228
|
-
|
|
1229
|
-
return binaryPath
|
|
1230
|
-
} catch (error) {
|
|
1231
|
-
spinner.fail('Failed to download dblab')
|
|
1232
|
-
console.error(uiError((error as Error).message))
|
|
1233
|
-
console.log()
|
|
1234
|
-
console.log(chalk.gray('You can manually download from:'))
|
|
1235
|
-
console.log(chalk.cyan(' https://github.com/danvergara/dblab/releases'))
|
|
1236
|
-
console.log()
|
|
1237
|
-
await pressEnterToContinue()
|
|
1238
|
-
return null
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
/**
|
|
1243
|
-
* Launch dblab visual TUI for a container
|
|
1244
|
-
*/
|
|
1245
|
-
async function launchDblab(
|
|
1246
|
-
config: NonNullable<Awaited<ReturnType<typeof containerManager.getConfig>>>,
|
|
1247
|
-
database: string,
|
|
1248
|
-
): Promise<void> {
|
|
1249
|
-
const dblabPath = await configManager.getBinaryPath('dblab')
|
|
1250
|
-
if (!dblabPath) {
|
|
1251
|
-
console.error(uiError('dblab not found. Download it first.'))
|
|
1252
|
-
await pressEnterToContinue()
|
|
1253
|
-
return
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
const args = getDblabArgs(config, database)
|
|
1257
|
-
|
|
1258
|
-
console.log()
|
|
1259
|
-
console.log(chalk.gray(' dblab keybindings:'))
|
|
1260
|
-
console.log(
|
|
1261
|
-
chalk.gray(
|
|
1262
|
-
' Ctrl+Space: run query | Ctrl+H/J/K/L: navigate panels | Ctrl+S: structure view',
|
|
1263
|
-
),
|
|
1264
|
-
)
|
|
1265
|
-
console.log()
|
|
1266
|
-
await escapeablePrompt([
|
|
1267
|
-
{
|
|
1268
|
-
type: 'input',
|
|
1269
|
-
name: 'continue',
|
|
1270
|
-
message: chalk.gray('Press Enter to launch dblab...'),
|
|
1271
|
-
},
|
|
1272
|
-
])
|
|
1273
|
-
|
|
1274
|
-
const dblabProcess = spawn(dblabPath, args, {
|
|
1275
|
-
stdio: 'inherit',
|
|
1276
|
-
})
|
|
1277
|
-
|
|
1278
|
-
await new Promise<void>((resolve) => {
|
|
1279
|
-
let settled = false
|
|
1280
|
-
|
|
1281
|
-
const settle = () => {
|
|
1282
|
-
if (!settled) {
|
|
1283
|
-
settled = true
|
|
1284
|
-
resolve()
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
dblabProcess.on('error', (err: NodeJS.ErrnoException) => {
|
|
1289
|
-
if (err.code === 'ENOENT') {
|
|
1290
|
-
console.log(uiWarning('dblab not found on your system.'))
|
|
1291
|
-
console.log()
|
|
1292
|
-
console.log(chalk.gray(' Download it with:'))
|
|
1293
|
-
console.log(chalk.cyan(' spindb connect --install-dblab'))
|
|
1294
|
-
} else {
|
|
1295
|
-
console.log(uiError(`Failed to start dblab: ${err.message}`))
|
|
1296
|
-
}
|
|
1297
|
-
settle()
|
|
1298
|
-
})
|
|
1299
|
-
|
|
1300
|
-
dblabProcess.on('close', () => {
|
|
1301
|
-
if (process.stdout.isTTY) {
|
|
1302
|
-
process.stdout.write('\x1b[2J\x1b[3J\x1b[H')
|
|
1303
|
-
}
|
|
1304
|
-
settle()
|
|
1305
|
-
})
|
|
1306
|
-
})
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
/**
|
|
1310
|
-
* Launch pgweb for a PostgreSQL-compatible container
|
|
1311
|
-
*/
|
|
1312
|
-
async function launchPgweb(
|
|
1313
|
-
containerName: string,
|
|
1314
|
-
config: NonNullable<Awaited<ReturnType<typeof containerManager.getConfig>>>,
|
|
1315
|
-
database: string,
|
|
1316
|
-
): Promise<void> {
|
|
1317
|
-
const pgwebPath = await configManager.getBinaryPath('pgweb')
|
|
1318
|
-
if (!pgwebPath) {
|
|
1319
|
-
console.error(uiError('pgweb not found. Download it first.'))
|
|
1320
|
-
await pressEnterToContinue()
|
|
1321
|
-
return
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
const containerDir = paths.getContainerPath(containerName, {
|
|
1325
|
-
engine: config.engine,
|
|
1326
|
-
})
|
|
1327
|
-
const pidFile = join(containerDir, 'pgweb.pid')
|
|
1328
|
-
const portFile = join(containerDir, 'pgweb.port')
|
|
1329
|
-
|
|
1330
|
-
// Check if already running — just open browser
|
|
1331
|
-
const status = await getPgwebStatus(containerName, config.engine)
|
|
1332
|
-
if (status.running && status.port) {
|
|
1333
|
-
const url = `http://127.0.0.1:${status.port}`
|
|
1334
|
-
console.log()
|
|
1335
|
-
console.log(uiInfo(`Opening pgweb`))
|
|
1336
|
-
console.log(chalk.gray(` ${url}`))
|
|
1337
|
-
console.log()
|
|
1338
|
-
openInBrowser(url)
|
|
1339
|
-
await pressEnterToContinue()
|
|
1340
|
-
return
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
// Find available port starting at 8081
|
|
1344
|
-
let port = 8081
|
|
1345
|
-
while (!(await portManager.isPortAvailable(port)) && port < 8200) {
|
|
1346
|
-
port++
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
if (port >= 8200) {
|
|
1350
|
-
console.error(
|
|
1351
|
-
uiError(
|
|
1352
|
-
'Could not find an available port for pgweb (scanned 8081–8199). ' +
|
|
1353
|
-
'Check for other pgweb or server processes using those ports.',
|
|
1354
|
-
),
|
|
1355
|
-
)
|
|
1356
|
-
await pressEnterToContinue()
|
|
1357
|
-
return
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
// Build connection URL
|
|
1361
|
-
let connectionUrl: string
|
|
1362
|
-
if (config.engine === 'ferretdb') {
|
|
1363
|
-
// FerretDB has a PostgreSQL backend on backendPort — always connects to 'ferretdb' database
|
|
1364
|
-
if (!config.backendPort) {
|
|
1365
|
-
console.log()
|
|
1366
|
-
console.error(
|
|
1367
|
-
uiError(
|
|
1368
|
-
'PostgreSQL backend port not set — restart the container first',
|
|
1369
|
-
),
|
|
1370
|
-
)
|
|
1371
|
-
console.log()
|
|
1372
|
-
await pressEnterToContinue()
|
|
1373
|
-
return
|
|
1374
|
-
}
|
|
1375
|
-
connectionUrl = `postgresql://postgres@127.0.0.1:${config.backendPort}/ferretdb?sslmode=disable`
|
|
1376
|
-
} else if (config.engine === 'cockroachdb') {
|
|
1377
|
-
connectionUrl = `postgresql://root@127.0.0.1:${config.port}/${database}?sslmode=disable`
|
|
1378
|
-
} else {
|
|
1379
|
-
connectionUrl = `postgresql://postgres@127.0.0.1:${config.port}/${database}?sslmode=disable`
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
// Spawn pgweb detached
|
|
1383
|
-
const pgwebProcess = spawn(
|
|
1384
|
-
pgwebPath,
|
|
1385
|
-
['--url', connectionUrl, '--bind', '127.0.0.1', '--listen', String(port)],
|
|
1386
|
-
{
|
|
1387
|
-
stdio: ['ignore', 'ignore', 'ignore'],
|
|
1388
|
-
detached: true,
|
|
1389
|
-
},
|
|
1390
|
-
)
|
|
1391
|
-
|
|
1392
|
-
pgwebProcess.unref()
|
|
1393
|
-
|
|
1394
|
-
// Write PID and port files
|
|
1395
|
-
if (pgwebProcess.pid) {
|
|
1396
|
-
await writeFile(pidFile, String(pgwebProcess.pid))
|
|
1397
|
-
await writeFile(portFile, String(port))
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
// Brief wait for startup
|
|
1401
|
-
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
1402
|
-
|
|
1403
|
-
const url = `http://127.0.0.1:${port}`
|
|
1404
|
-
console.log()
|
|
1405
|
-
console.log(uiSuccess(`pgweb started on ${url}`))
|
|
1406
|
-
console.log(chalk.gray(` PID: ${pgwebProcess.pid}`))
|
|
1407
|
-
console.log()
|
|
1408
|
-
openInBrowser(url)
|
|
1409
|
-
await pressEnterToContinue()
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
async function launchShell(
|
|
1413
|
-
containerName: string,
|
|
1414
|
-
config: NonNullable<Awaited<ReturnType<typeof containerManager.getConfig>>>,
|
|
1415
|
-
connectionString: string,
|
|
1416
|
-
shellType: 'default' | 'usql' | 'pgcli' | 'mycli' | 'litecli' | 'iredis',
|
|
1417
|
-
database: string,
|
|
1418
|
-
): Promise<void> {
|
|
1419
|
-
console.log(uiInfo(`Connecting to ${containerName}...`))
|
|
1420
|
-
console.log()
|
|
1421
|
-
|
|
1422
|
-
let shellCmd: string
|
|
1423
|
-
let shellArgs: string[]
|
|
1424
|
-
let installHint: string
|
|
1425
|
-
let spawnCwd: string | undefined
|
|
1426
|
-
|
|
1427
|
-
if (shellType === 'pgcli') {
|
|
1428
|
-
// pgcli accepts connection strings
|
|
1429
|
-
shellCmd = 'pgcli'
|
|
1430
|
-
shellArgs = [connectionString]
|
|
1431
|
-
installHint = 'brew install pgcli'
|
|
1432
|
-
} else if (shellType === 'mycli') {
|
|
1433
|
-
// mycli: mycli -h host -P port -u user database
|
|
1434
|
-
shellCmd = 'mycli'
|
|
1435
|
-
shellArgs = [
|
|
1436
|
-
'-h',
|
|
1437
|
-
'127.0.0.1',
|
|
1438
|
-
'-P',
|
|
1439
|
-
String(config.port),
|
|
1440
|
-
'-u',
|
|
1441
|
-
'root',
|
|
1442
|
-
database,
|
|
1443
|
-
]
|
|
1444
|
-
installHint = 'brew install mycli'
|
|
1445
|
-
} else if (shellType === 'litecli') {
|
|
1446
|
-
// litecli takes the database file path directly
|
|
1447
|
-
shellCmd = 'litecli'
|
|
1448
|
-
shellArgs = [config.database]
|
|
1449
|
-
installHint = 'brew install litecli'
|
|
1450
|
-
} else if (shellType === 'usql') {
|
|
1451
|
-
// usql accepts connection strings directly for PostgreSQL, MySQL, and SQLite
|
|
1452
|
-
shellCmd = 'usql'
|
|
1453
|
-
shellArgs = [connectionString]
|
|
1454
|
-
installHint = 'brew tap xo/xo && brew install xo/xo/usql'
|
|
1455
|
-
} else if (config.engine === 'sqlite') {
|
|
1456
|
-
// Default SQLite shell
|
|
1457
|
-
shellCmd = 'sqlite3'
|
|
1458
|
-
shellArgs = [config.database]
|
|
1459
|
-
installHint = 'brew install sqlite3'
|
|
1460
|
-
} else if (config.engine === 'duckdb') {
|
|
1461
|
-
// DuckDB shell
|
|
1462
|
-
const duckdbPath = await configManager.getBinaryPath('duckdb')
|
|
1463
|
-
shellCmd = duckdbPath || 'duckdb'
|
|
1464
|
-
shellArgs = [config.database]
|
|
1465
|
-
installHint = 'spindb engines download duckdb'
|
|
1466
|
-
} else if (config.engine === 'mysql') {
|
|
1467
|
-
// MySQL uses downloaded binaries - get the actual path
|
|
1468
|
-
const mysqlPath = await configManager.getBinaryPath('mysql')
|
|
1469
|
-
shellCmd = mysqlPath || 'mysql'
|
|
1470
|
-
shellArgs = [
|
|
1471
|
-
'-u',
|
|
1472
|
-
'root',
|
|
1473
|
-
'-h',
|
|
1474
|
-
'127.0.0.1',
|
|
1475
|
-
'-P',
|
|
1476
|
-
String(config.port),
|
|
1477
|
-
database,
|
|
1478
|
-
]
|
|
1479
|
-
installHint = 'spindb engines download mysql'
|
|
1480
|
-
} else if (config.engine === 'mariadb') {
|
|
1481
|
-
// MariaDB uses downloaded binaries, not system PATH - get the actual path
|
|
1482
|
-
const mariadbPath = await configManager.getBinaryPath('mariadb')
|
|
1483
|
-
shellCmd = mariadbPath || 'mariadb'
|
|
1484
|
-
shellArgs = [
|
|
1485
|
-
'-u',
|
|
1486
|
-
'root',
|
|
1487
|
-
'-h',
|
|
1488
|
-
'127.0.0.1',
|
|
1489
|
-
'-P',
|
|
1490
|
-
String(config.port),
|
|
1491
|
-
database,
|
|
1492
|
-
]
|
|
1493
|
-
installHint = 'spindb engines download mariadb'
|
|
1494
|
-
} else if (config.engine === 'mongodb' || config.engine === 'ferretdb') {
|
|
1495
|
-
shellCmd = 'mongosh'
|
|
1496
|
-
shellArgs = [connectionString]
|
|
1497
|
-
installHint = 'brew install mongosh'
|
|
1498
|
-
} else if (shellType === 'iredis') {
|
|
1499
|
-
// iredis: enhanced Redis CLI
|
|
1500
|
-
shellCmd = 'iredis'
|
|
1501
|
-
shellArgs = ['-h', '127.0.0.1', '-p', String(config.port), '-n', database]
|
|
1502
|
-
installHint = 'brew install iredis'
|
|
1503
|
-
} else if (config.engine === 'redis') {
|
|
1504
|
-
// Default Redis shell
|
|
1505
|
-
shellCmd = 'redis-cli'
|
|
1506
|
-
shellArgs = ['-h', '127.0.0.1', '-p', String(config.port), '-n', database]
|
|
1507
|
-
installHint = 'brew install redis'
|
|
1508
|
-
} else if (config.engine === 'valkey') {
|
|
1509
|
-
// Default Valkey shell
|
|
1510
|
-
const valkeyCliPath = await configManager.getBinaryPath('valkey-cli')
|
|
1511
|
-
shellCmd = valkeyCliPath || 'valkey-cli'
|
|
1512
|
-
shellArgs = ['-h', '127.0.0.1', '-p', String(config.port), '-n', database]
|
|
1513
|
-
installHint = 'spindb engines download valkey'
|
|
1514
|
-
} else if (config.engine === 'clickhouse') {
|
|
1515
|
-
// ClickHouse uses a unified binary with subcommands
|
|
1516
|
-
const clickhousePath = await configManager.getBinaryPath('clickhouse')
|
|
1517
|
-
shellCmd = clickhousePath || 'clickhouse'
|
|
1518
|
-
shellArgs = [
|
|
1519
|
-
'client',
|
|
1520
|
-
'--host',
|
|
1521
|
-
'127.0.0.1',
|
|
1522
|
-
'--port',
|
|
1523
|
-
String(config.port),
|
|
1524
|
-
'--database',
|
|
1525
|
-
database,
|
|
1526
|
-
]
|
|
1527
|
-
installHint = 'spindb engines download clickhouse'
|
|
1528
|
-
} else if (config.engine === 'qdrant') {
|
|
1529
|
-
// Qdrant: Open Web UI in browser (only shown when Web UI is installed)
|
|
1530
|
-
const dashboardUrl = `http://127.0.0.1:${config.port}/dashboard`
|
|
1531
|
-
console.log(uiInfo(`Opening Qdrant Dashboard in browser...`))
|
|
1532
|
-
console.log(chalk.gray(` ${dashboardUrl}`))
|
|
1533
|
-
console.log()
|
|
1534
|
-
openInBrowser(dashboardUrl)
|
|
1535
|
-
await pressEnterToContinue()
|
|
1536
|
-
return
|
|
1537
|
-
} else if (config.engine === 'meilisearch') {
|
|
1538
|
-
// Meilisearch: Open dashboard in browser (served at root URL)
|
|
1539
|
-
const dashboardUrl = `http://127.0.0.1:${config.port}`
|
|
1540
|
-
console.log(uiInfo(`Opening Meilisearch Dashboard in browser...`))
|
|
1541
|
-
console.log(chalk.gray(` ${dashboardUrl}`))
|
|
1542
|
-
console.log()
|
|
1543
|
-
openInBrowser(dashboardUrl)
|
|
1544
|
-
await pressEnterToContinue()
|
|
1545
|
-
return
|
|
1546
|
-
} else if (config.engine === 'weaviate') {
|
|
1547
|
-
// Weaviate: Open REST API root in browser
|
|
1548
|
-
const dashboardUrl = `http://127.0.0.1:${config.port}`
|
|
1549
|
-
console.log(uiInfo(`Opening Weaviate in browser...`))
|
|
1550
|
-
console.log(chalk.gray(` ${dashboardUrl}`))
|
|
1551
|
-
console.log()
|
|
1552
|
-
openInBrowser(dashboardUrl)
|
|
1553
|
-
await pressEnterToContinue()
|
|
1554
|
-
return
|
|
1555
|
-
} else if (config.engine === 'influxdb') {
|
|
1556
|
-
// InfluxDB: influxdb3 query is one-shot (no REPL), use interactive loop
|
|
1557
|
-
const engine = getEngine(config.engine)
|
|
1558
|
-
const influxdbPath = await engine
|
|
1559
|
-
.getInfluxDBPath(config.version)
|
|
1560
|
-
.catch(() => null)
|
|
1561
|
-
if (!influxdbPath) {
|
|
1562
|
-
console.log(
|
|
1563
|
-
uiWarning('influxdb3 not found. Run: spindb engines download influxdb'),
|
|
1564
|
-
)
|
|
1565
|
-
await pressEnterToContinue()
|
|
1566
|
-
return
|
|
1567
|
-
}
|
|
1568
|
-
// Query available databases from the REST API
|
|
1569
|
-
let db = database || config.name
|
|
1570
|
-
try {
|
|
1571
|
-
const resp = await fetch(
|
|
1572
|
-
`http://127.0.0.1:${config.port}/api/v3/configure/database?format=json`,
|
|
1573
|
-
)
|
|
1574
|
-
if (resp.ok) {
|
|
1575
|
-
const databases = (await resp.json()) as Array<Record<string, string>>
|
|
1576
|
-
const dbNames = databases
|
|
1577
|
-
.map((d) => d['iox::database'] || d.name)
|
|
1578
|
-
.filter((n) => n && n !== '_internal')
|
|
1579
|
-
if (dbNames.length === 0) {
|
|
1580
|
-
console.log(
|
|
1581
|
-
uiWarning(
|
|
1582
|
-
'No databases exist yet. Write data first to create a database.',
|
|
1583
|
-
),
|
|
1584
|
-
)
|
|
1585
|
-
console.log(
|
|
1586
|
-
chalk.gray(
|
|
1587
|
-
` curl -X POST "http://127.0.0.1:${config.port}/api/v3/write_lp?db=${db}" -H "Content-Type: text/plain" -d 'measurement,tag=value field=1'`,
|
|
1588
|
-
),
|
|
1589
|
-
)
|
|
1590
|
-
console.log()
|
|
1591
|
-
await pressEnterToContinue()
|
|
1592
|
-
return
|
|
1593
|
-
}
|
|
1594
|
-
if (!dbNames.includes(db)) {
|
|
1595
|
-
if (dbNames.length === 1) {
|
|
1596
|
-
db = dbNames[0]
|
|
1597
|
-
} else {
|
|
1598
|
-
const { chosenDb } = await escapeablePrompt<{ chosenDb: string }>([
|
|
1599
|
-
{
|
|
1600
|
-
type: 'list',
|
|
1601
|
-
name: 'chosenDb',
|
|
1602
|
-
message: 'Select database:',
|
|
1603
|
-
choices: dbNames,
|
|
1604
|
-
},
|
|
1605
|
-
])
|
|
1606
|
-
db = chosenDb
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
} catch {
|
|
1611
|
-
// Server may not support this endpoint; proceed with default db
|
|
1612
|
-
}
|
|
1613
|
-
console.log(chalk.cyan(`InfluxDB SQL Console (${db})`))
|
|
1614
|
-
console.log(chalk.gray(` Type SQL queries, or "exit" to quit.\n`))
|
|
1615
|
-
let running = true
|
|
1616
|
-
while (running) {
|
|
1617
|
-
const { sql } = await escapeablePrompt<{ sql: string }>([
|
|
1618
|
-
{
|
|
1619
|
-
type: 'input',
|
|
1620
|
-
name: 'sql',
|
|
1621
|
-
message: chalk.blue('sql>'),
|
|
1622
|
-
},
|
|
1623
|
-
])
|
|
1624
|
-
const trimmed = (sql || '').trim()
|
|
1625
|
-
if (
|
|
1626
|
-
trimmed.toLowerCase() === 'exit' ||
|
|
1627
|
-
trimmed.toLowerCase() === 'quit'
|
|
1628
|
-
) {
|
|
1629
|
-
running = false
|
|
1630
|
-
break
|
|
1631
|
-
}
|
|
1632
|
-
if (!trimmed) {
|
|
1633
|
-
continue
|
|
1634
|
-
}
|
|
1635
|
-
const queryProcess = spawn(
|
|
1636
|
-
influxdbPath,
|
|
1637
|
-
[
|
|
1638
|
-
'query',
|
|
1639
|
-
'--host',
|
|
1640
|
-
`http://127.0.0.1:${config.port}`,
|
|
1641
|
-
'--database',
|
|
1642
|
-
db,
|
|
1643
|
-
'--',
|
|
1644
|
-
trimmed,
|
|
1645
|
-
],
|
|
1646
|
-
{ stdio: 'inherit' },
|
|
1647
|
-
)
|
|
1648
|
-
await new Promise<void>((resolve) => {
|
|
1649
|
-
queryProcess.on('error', (err) => {
|
|
1650
|
-
console.error(uiError(`Query failed: ${err.message}`))
|
|
1651
|
-
resolve()
|
|
1652
|
-
})
|
|
1653
|
-
queryProcess.on('close', () => {
|
|
1654
|
-
logDebug('influxdb query process exited')
|
|
1655
|
-
resolve()
|
|
1656
|
-
})
|
|
1657
|
-
})
|
|
1658
|
-
}
|
|
1659
|
-
return
|
|
1660
|
-
} else if (config.engine === 'couchdb') {
|
|
1661
|
-
// CouchDB: Open Fauxton dashboard in browser (served at /_utils)
|
|
1662
|
-
const dashboardUrl = `http://127.0.0.1:${config.port}/_utils`
|
|
1663
|
-
console.log()
|
|
1664
|
-
console.log(chalk.cyan('CouchDB Fauxton Dashboard'))
|
|
1665
|
-
console.log(chalk.gray(` ${dashboardUrl}`))
|
|
1666
|
-
console.log()
|
|
1667
|
-
console.log(chalk.cyan('Credentials (if prompted):'))
|
|
1668
|
-
console.log(chalk.white(` Username: admin`))
|
|
1669
|
-
console.log(chalk.white(` Password: admin`))
|
|
1670
|
-
console.log()
|
|
1671
|
-
|
|
1672
|
-
// Prompt before opening so user can see credentials
|
|
1673
|
-
await escapeablePrompt([
|
|
1674
|
-
{
|
|
1675
|
-
type: 'input',
|
|
1676
|
-
name: 'continue',
|
|
1677
|
-
message: chalk.gray('Press Enter to open in browser...'),
|
|
1678
|
-
},
|
|
1679
|
-
])
|
|
1680
|
-
|
|
1681
|
-
openInBrowser(dashboardUrl)
|
|
1682
|
-
return
|
|
1683
|
-
} else if (config.engine === 'surrealdb') {
|
|
1684
|
-
// SurrealDB uses surreal sql command
|
|
1685
|
-
const engine = getEngine(config.engine)
|
|
1686
|
-
const surrealPath = await engine
|
|
1687
|
-
.getSurrealPath(config.version)
|
|
1688
|
-
.catch(() => 'surreal')
|
|
1689
|
-
const namespace = config.name.replace(/-/g, '_')
|
|
1690
|
-
shellCmd = surrealPath
|
|
1691
|
-
shellArgs = [
|
|
1692
|
-
'sql',
|
|
1693
|
-
'--endpoint',
|
|
1694
|
-
`ws://127.0.0.1:${config.port}`,
|
|
1695
|
-
'--namespace',
|
|
1696
|
-
namespace,
|
|
1697
|
-
'--database',
|
|
1698
|
-
database || 'default',
|
|
1699
|
-
'--username',
|
|
1700
|
-
'root',
|
|
1701
|
-
'--password',
|
|
1702
|
-
'root',
|
|
1703
|
-
]
|
|
1704
|
-
installHint = 'spindb engines download surrealdb'
|
|
1705
|
-
// SurrealDB writes history.txt to cwd - use container directory
|
|
1706
|
-
spawnCwd = join(paths.containers, 'surrealdb', config.name)
|
|
1707
|
-
} else if (config.engine === 'cockroachdb') {
|
|
1708
|
-
// CockroachDB uses cockroach sql command
|
|
1709
|
-
const engine = getEngine(config.engine)
|
|
1710
|
-
const cockroachPath = await engine
|
|
1711
|
-
.getCockroachPath(config.version)
|
|
1712
|
-
.catch(() => 'cockroach')
|
|
1713
|
-
shellCmd = cockroachPath
|
|
1714
|
-
shellArgs = [
|
|
1715
|
-
'sql',
|
|
1716
|
-
'--insecure',
|
|
1717
|
-
'--host',
|
|
1718
|
-
`127.0.0.1:${config.port}`,
|
|
1719
|
-
'--database',
|
|
1720
|
-
database,
|
|
1721
|
-
]
|
|
1722
|
-
installHint = 'spindb engines download cockroachdb'
|
|
1723
|
-
} else if (config.engine === 'questdb') {
|
|
1724
|
-
// QuestDB uses PostgreSQL wire protocol on port 8812
|
|
1725
|
-
// Default credentials: admin/quest
|
|
1726
|
-
shellCmd = 'psql'
|
|
1727
|
-
const db = database || 'qdb'
|
|
1728
|
-
// QuestDB connection string with explicit password
|
|
1729
|
-
const questDbConnStr = `postgresql://admin:quest@127.0.0.1:${config.port}/${db}`
|
|
1730
|
-
shellArgs = [questDbConnStr]
|
|
1731
|
-
installHint = 'brew install libpq && brew link --force libpq'
|
|
1732
|
-
} else if (config.engine === 'typedb') {
|
|
1733
|
-
// TypeDB uses typedb console with address and tls-disabled flags
|
|
1734
|
-
const engine = getEngine(config.engine)
|
|
1735
|
-
const consolePath = await engine
|
|
1736
|
-
.getTypeDBConsolePath(config.version)
|
|
1737
|
-
.catch(() => null)
|
|
1738
|
-
if (consolePath) {
|
|
1739
|
-
shellCmd = consolePath
|
|
1740
|
-
shellArgs = getConsoleBaseArgs(config.port)
|
|
1741
|
-
} else {
|
|
1742
|
-
// Fallback: use the typedb launcher with 'console' subcommand
|
|
1743
|
-
shellCmd = 'typedb'
|
|
1744
|
-
shellArgs = ['console', ...getConsoleBaseArgs(config.port)]
|
|
1745
|
-
}
|
|
1746
|
-
installHint = 'spindb engines download typedb'
|
|
1747
|
-
} else if (config.engine === 'tigerbeetle') {
|
|
1748
|
-
// TigerBeetle uses tigerbeetle repl command
|
|
1749
|
-
// Cluster ID 0 is the default for local single-node development.
|
|
1750
|
-
// TigerBeetle format/start also use cluster 0 (see engines/tigerbeetle/index.ts).
|
|
1751
|
-
const clusterId = 0
|
|
1752
|
-
const engine = getEngine(config.engine)
|
|
1753
|
-
const tigerbeetlePath = await engine
|
|
1754
|
-
.getTigerBeetlePath(config.version)
|
|
1755
|
-
.catch(() => null)
|
|
1756
|
-
shellCmd = tigerbeetlePath || 'tigerbeetle'
|
|
1757
|
-
shellArgs = [
|
|
1758
|
-
'repl',
|
|
1759
|
-
`--cluster=${clusterId}`,
|
|
1760
|
-
`--addresses=127.0.0.1:${config.port}`,
|
|
1761
|
-
]
|
|
1762
|
-
installHint = 'spindb engines download tigerbeetle'
|
|
1763
|
-
} else {
|
|
1764
|
-
// PostgreSQL default shell - look up downloaded binary path
|
|
1765
|
-
const psqlPath = await configManager.getBinaryPath('psql')
|
|
1766
|
-
shellCmd = psqlPath || 'psql'
|
|
1767
|
-
shellArgs = [connectionString]
|
|
1768
|
-
installHint = 'spindb engines download postgresql'
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
const shellProcess = spawn(shellCmd, shellArgs, {
|
|
1772
|
-
stdio: 'inherit',
|
|
1773
|
-
cwd: spawnCwd,
|
|
1774
|
-
})
|
|
1775
|
-
|
|
1776
|
-
await new Promise<void>((resolve) => {
|
|
1777
|
-
let settled = false
|
|
1778
|
-
|
|
1779
|
-
const settle = () => {
|
|
1780
|
-
if (!settled) {
|
|
1781
|
-
settled = true
|
|
1782
|
-
resolve()
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
shellProcess.on('error', (err: NodeJS.ErrnoException) => {
|
|
1787
|
-
if (err.code === 'ENOENT') {
|
|
1788
|
-
console.log(uiWarning(`${shellCmd} not found on your system.`))
|
|
1789
|
-
console.log()
|
|
1790
|
-
console.log(chalk.gray(' Connect manually with:'))
|
|
1791
|
-
console.log(chalk.cyan(` ${connectionString}`))
|
|
1792
|
-
console.log()
|
|
1793
|
-
console.log(chalk.gray(` Install ${shellCmd}:`))
|
|
1794
|
-
console.log(chalk.cyan(` ${installHint}`))
|
|
1795
|
-
} else {
|
|
1796
|
-
console.log(uiError(`Failed to start ${shellCmd}: ${err.message}`))
|
|
1797
|
-
}
|
|
1798
|
-
settle()
|
|
1799
|
-
})
|
|
1800
|
-
|
|
1801
|
-
shellProcess.on('close', () => {
|
|
1802
|
-
// Clear terminal to remove any residual graphics from shells (e.g., usql logo)
|
|
1803
|
-
// Use aggressive ANSI sequences: clear screen + scrollback + reset cursor
|
|
1804
|
-
// Only emit ANSI escape codes when output is a TTY
|
|
1805
|
-
if (process.stdout.isTTY) {
|
|
1806
|
-
process.stdout.write('\x1b[2J\x1b[3J\x1b[H')
|
|
1807
|
-
}
|
|
1808
|
-
settle()
|
|
1809
|
-
})
|
|
1810
|
-
})
|
|
1811
|
-
}
|