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
package/engines/couchdb/index.ts
DELETED
|
@@ -1,1429 +0,0 @@
|
|
|
1
|
-
import { spawn, type SpawnOptions } from 'child_process'
|
|
2
|
-
import { existsSync } from 'fs'
|
|
3
|
-
import { mkdir, writeFile, readFile, unlink } from 'fs/promises'
|
|
4
|
-
import { join, dirname } from 'path'
|
|
5
|
-
import { BaseEngine } from '../base-engine'
|
|
6
|
-
import { paths } from '../../config/paths'
|
|
7
|
-
import { getEngineDefaults } from '../../config/defaults'
|
|
8
|
-
import { platformService, isWindows } from '../../core/platform-service'
|
|
9
|
-
import { configManager } from '../../core/config-manager'
|
|
10
|
-
import {
|
|
11
|
-
logDebug,
|
|
12
|
-
logWarning,
|
|
13
|
-
assertValidUsername,
|
|
14
|
-
} from '../../core/error-handler'
|
|
15
|
-
import { processManager } from '../../core/process-manager'
|
|
16
|
-
import { portManager } from '../../core/port-manager'
|
|
17
|
-
import { couchdbBinaryManager } from './binary-manager'
|
|
18
|
-
import { getBinaryUrl } from './binary-urls'
|
|
19
|
-
import {
|
|
20
|
-
normalizeVersion,
|
|
21
|
-
SUPPORTED_MAJOR_VERSIONS,
|
|
22
|
-
COUCHDB_VERSION_MAP,
|
|
23
|
-
} from './version-maps'
|
|
24
|
-
import { fetchAvailableVersions as fetchHostdbVersions } from './hostdb-releases'
|
|
25
|
-
import {
|
|
26
|
-
detectBackupFormat as detectBackupFormatImpl,
|
|
27
|
-
restoreBackup,
|
|
28
|
-
} from './restore'
|
|
29
|
-
import { createBackup } from './backup'
|
|
30
|
-
import { couchdbApiRequest } from './api-client'
|
|
31
|
-
import {
|
|
32
|
-
type Platform,
|
|
33
|
-
type Arch,
|
|
34
|
-
type ContainerConfig,
|
|
35
|
-
type ProgressCallback,
|
|
36
|
-
type BackupFormat,
|
|
37
|
-
type BackupOptions,
|
|
38
|
-
type BackupResult,
|
|
39
|
-
type RestoreResult,
|
|
40
|
-
type DumpResult,
|
|
41
|
-
type StatusResult,
|
|
42
|
-
type QueryResult,
|
|
43
|
-
type QueryOptions,
|
|
44
|
-
type CreateUserOptions,
|
|
45
|
-
type UserCredentials,
|
|
46
|
-
} from '../../types'
|
|
47
|
-
import { parseRESTAPIResult } from '../../core/query-parser'
|
|
48
|
-
|
|
49
|
-
const ENGINE = 'couchdb'
|
|
50
|
-
const engineDef = getEngineDefaults(ENGINE)
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Get the correct extension for CouchDB binary.
|
|
54
|
-
* On Windows, CouchDB uses a .cmd batch file, not .exe
|
|
55
|
-
*/
|
|
56
|
-
function getCouchDBExtension(): string {
|
|
57
|
-
return isWindows() ? '.cmd' : ''
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Generate CouchDB local.ini configuration content
|
|
62
|
-
* CouchDB 3.x requires at least one admin account to start
|
|
63
|
-
*/
|
|
64
|
-
function generateCouchDBConfig(options: {
|
|
65
|
-
port: number
|
|
66
|
-
dataDir: string
|
|
67
|
-
logDir: string
|
|
68
|
-
bindAddress?: string
|
|
69
|
-
}): string {
|
|
70
|
-
const bindAddress = options.bindAddress || '127.0.0.1'
|
|
71
|
-
|
|
72
|
-
return `; SpinDB generated CouchDB configuration
|
|
73
|
-
[couchdb]
|
|
74
|
-
database_dir = ${options.dataDir}
|
|
75
|
-
view_index_dir = ${options.dataDir}
|
|
76
|
-
|
|
77
|
-
[chttpd]
|
|
78
|
-
port = ${options.port}
|
|
79
|
-
bind_address = ${bindAddress}
|
|
80
|
-
; Allow anonymous access for local development (no login required)
|
|
81
|
-
require_valid_user = false
|
|
82
|
-
|
|
83
|
-
[chttpd_auth]
|
|
84
|
-
; Allow anonymous access to Fauxton dashboard
|
|
85
|
-
require_valid_user = false
|
|
86
|
-
|
|
87
|
-
[log]
|
|
88
|
-
file = ${options.logDir}/couchdb.log
|
|
89
|
-
level = info
|
|
90
|
-
|
|
91
|
-
[admins]
|
|
92
|
-
; CouchDB 3.x requires admin account - credentials available if needed: admin/admin
|
|
93
|
-
admin = admin
|
|
94
|
-
`
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Generate container-specific vm.args with unique Erlang node name
|
|
99
|
-
* Each CouchDB instance needs a unique node name to avoid conflicts
|
|
100
|
-
*/
|
|
101
|
-
function generateVmArgs(port: number, _containerDir: string): string {
|
|
102
|
-
// Use port in node name to ensure uniqueness
|
|
103
|
-
const nodeName = `couchdb_${port}@127.0.0.1`
|
|
104
|
-
|
|
105
|
-
// Read base vm.args and replace the node name
|
|
106
|
-
return `# SpinDB generated CouchDB vm.args
|
|
107
|
-
# Unique node name based on port to allow multiple instances
|
|
108
|
-
-name ${nodeName}
|
|
109
|
-
|
|
110
|
-
# All nodes must share the same magic cookie for distributed Erlang to work.
|
|
111
|
-
# -setcookie
|
|
112
|
-
|
|
113
|
-
# Which interfaces should the node listen on?
|
|
114
|
-
-kernel inet_dist_use_interface {127,0,0,1}
|
|
115
|
-
|
|
116
|
-
# Tell kernel and SASL not to log anything
|
|
117
|
-
-kernel error_logger silent
|
|
118
|
-
-sasl sasl_error_logger false
|
|
119
|
-
|
|
120
|
-
# Prevent overlapping partitions
|
|
121
|
-
-kernel prevent_overlapping_partitions false
|
|
122
|
-
|
|
123
|
-
# Erlang process limit
|
|
124
|
-
+P 1048576
|
|
125
|
-
|
|
126
|
-
# Increase the pool of dirty IO schedulers
|
|
127
|
-
+SDio 16
|
|
128
|
-
|
|
129
|
-
# Increase distribution buffer size
|
|
130
|
-
+zdbbl 32768
|
|
131
|
-
|
|
132
|
-
# Disable interactive shell
|
|
133
|
-
+Bd -noinput
|
|
134
|
-
|
|
135
|
-
# Set maximum SSL session lifetime
|
|
136
|
-
-ssl session_lifetime 300
|
|
137
|
-
|
|
138
|
-
# OS Mon Settings - disable all monitoring on Windows to avoid win32sysinfo issues
|
|
139
|
-
-os_mon start_cpu_sup false
|
|
140
|
-
-os_mon start_memsup false
|
|
141
|
-
-os_mon start_disksup false
|
|
142
|
-
`
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Generate Erlang sys.config to disable os_mon features before application starts.
|
|
147
|
-
* On Windows, os_mon tries to use win32sysinfo which may crash if the port program
|
|
148
|
-
* is missing or broken. Setting these in sys.config takes effect before os_mon starts.
|
|
149
|
-
*/
|
|
150
|
-
function generateSysConfig(): string {
|
|
151
|
-
// Minimal Erlang sys.config - no comments, just config
|
|
152
|
-
// os_mon settings must be set BEFORE the application starts
|
|
153
|
-
return `[{os_mon,[{start_cpu_sup,false},{start_disksup,false},{start_memsup,false}]}].
|
|
154
|
-
`
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Parse a CouchDB connection string for remote operations
|
|
159
|
-
*/
|
|
160
|
-
function parseCouchDBConnectionString(connectionString: string): {
|
|
161
|
-
baseUrl: string
|
|
162
|
-
headers: Record<string, string>
|
|
163
|
-
database?: string
|
|
164
|
-
} {
|
|
165
|
-
let url: URL
|
|
166
|
-
let scheme = 'http'
|
|
167
|
-
|
|
168
|
-
// Handle couchdb:// scheme by converting to http://
|
|
169
|
-
let normalized = connectionString.trim()
|
|
170
|
-
if (normalized.startsWith('couchdb://')) {
|
|
171
|
-
normalized = normalized.replace('couchdb://', 'http://')
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Ensure scheme is present
|
|
175
|
-
if (!normalized.startsWith('http://') && !normalized.startsWith('https://')) {
|
|
176
|
-
normalized = `http://${normalized}`
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
url = new URL(normalized)
|
|
181
|
-
scheme = url.protocol.replace(':', '')
|
|
182
|
-
} catch {
|
|
183
|
-
throw new Error(
|
|
184
|
-
`Invalid CouchDB connection string: ${connectionString}\n` +
|
|
185
|
-
'Expected format: http://host:port or couchdb://host:port',
|
|
186
|
-
)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const headers: Record<string, string> = {
|
|
190
|
-
'Content-Type': 'application/json',
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Handle basic auth if present
|
|
194
|
-
if (url.username && url.password) {
|
|
195
|
-
const auth = Buffer.from(`${url.username}:${url.password}`).toString(
|
|
196
|
-
'base64',
|
|
197
|
-
)
|
|
198
|
-
headers['Authorization'] = `Basic ${auth}`
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Construct base URL without auth and query params
|
|
202
|
-
const port = url.port || '5984'
|
|
203
|
-
const baseUrl = `${scheme}://${url.hostname}:${port}`
|
|
204
|
-
|
|
205
|
-
// Extract database from pathname
|
|
206
|
-
const pathname = url.pathname || ''
|
|
207
|
-
const database =
|
|
208
|
-
pathname.length > 1 ? pathname.slice(1).split('/')[0] : undefined
|
|
209
|
-
|
|
210
|
-
return { baseUrl, headers, database }
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Make an HTTP request to a remote CouchDB server
|
|
215
|
-
*/
|
|
216
|
-
async function remoteCouchDBRequest(
|
|
217
|
-
baseUrl: string,
|
|
218
|
-
method: string,
|
|
219
|
-
path: string,
|
|
220
|
-
headers: Record<string, string>,
|
|
221
|
-
body?: Record<string, unknown>,
|
|
222
|
-
timeoutMs = 30000,
|
|
223
|
-
): Promise<{ status: number; data: unknown }> {
|
|
224
|
-
const url = `${baseUrl}${path}`
|
|
225
|
-
|
|
226
|
-
const controller = new AbortController()
|
|
227
|
-
const timeoutId = setTimeout(() => controller.abort(), timeoutMs)
|
|
228
|
-
|
|
229
|
-
const options: RequestInit = {
|
|
230
|
-
method,
|
|
231
|
-
headers,
|
|
232
|
-
signal: controller.signal,
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (body) {
|
|
236
|
-
options.body = JSON.stringify(body)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
const response = await fetch(url, options)
|
|
241
|
-
|
|
242
|
-
let data: unknown
|
|
243
|
-
const contentType = response.headers.get('content-type') || ''
|
|
244
|
-
if (contentType.includes('application/json')) {
|
|
245
|
-
data = await response.json()
|
|
246
|
-
} else {
|
|
247
|
-
data = await response.text()
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return { status: response.status, data }
|
|
251
|
-
} catch (error) {
|
|
252
|
-
if (error instanceof Error && error.name === 'AbortError') {
|
|
253
|
-
throw new Error(
|
|
254
|
-
`Remote CouchDB request timed out after ${timeoutMs / 1000}s: ${method} ${path}`,
|
|
255
|
-
)
|
|
256
|
-
}
|
|
257
|
-
throw error
|
|
258
|
-
} finally {
|
|
259
|
-
clearTimeout(timeoutId)
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export class CouchDBEngine extends BaseEngine {
|
|
264
|
-
name = ENGINE
|
|
265
|
-
displayName = 'CouchDB'
|
|
266
|
-
defaultPort = engineDef.defaultPort
|
|
267
|
-
supportedVersions = SUPPORTED_MAJOR_VERSIONS
|
|
268
|
-
|
|
269
|
-
// Get platform info for binary operations
|
|
270
|
-
getPlatformInfo(): { platform: Platform; arch: Arch } {
|
|
271
|
-
return platformService.getPlatformInfo()
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Fetch available versions from hostdb
|
|
275
|
-
async fetchAvailableVersions(): Promise<Record<string, string[]>> {
|
|
276
|
-
return fetchHostdbVersions()
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Get binary download URL from hostdb
|
|
280
|
-
getBinaryUrl(version: string, platform: Platform, arch: Arch): string {
|
|
281
|
-
return getBinaryUrl(version, platform, arch)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Resolves version string to full version (e.g., '3' -> '3.5.1')
|
|
285
|
-
resolveFullVersion(version: string): string {
|
|
286
|
-
if (/^\d+\.\d+\.\d+$/.test(version)) {
|
|
287
|
-
return version
|
|
288
|
-
}
|
|
289
|
-
if (COUCHDB_VERSION_MAP[version]) {
|
|
290
|
-
return COUCHDB_VERSION_MAP[version]
|
|
291
|
-
}
|
|
292
|
-
// Normalize to exactly 3 segments (e.g., "3" -> "3.0.0", "3.5" -> "3.5.0")
|
|
293
|
-
const segments = version.split('.').slice(0, 3)
|
|
294
|
-
while (segments.length < 3) {
|
|
295
|
-
segments.push('0')
|
|
296
|
-
}
|
|
297
|
-
return segments.join('.')
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Get the path where binaries for a version would be installed
|
|
301
|
-
getBinaryPath(version: string): string {
|
|
302
|
-
const fullVersion = this.resolveFullVersion(version)
|
|
303
|
-
const { platform: p, arch: a } = this.getPlatformInfo()
|
|
304
|
-
return paths.getBinaryPath({
|
|
305
|
-
engine: 'couchdb',
|
|
306
|
-
version: fullVersion,
|
|
307
|
-
platform: p,
|
|
308
|
-
arch: a,
|
|
309
|
-
})
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Verify that CouchDB binaries are available
|
|
313
|
-
async verifyBinary(binPath: string): Promise<boolean> {
|
|
314
|
-
// CouchDB has a startup script rather than a direct binary
|
|
315
|
-
// On Windows it's .cmd, on Unix it's just 'couchdb'
|
|
316
|
-
const serverPath = join(binPath, 'bin', `couchdb${getCouchDBExtension()}`)
|
|
317
|
-
return existsSync(serverPath)
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Check if a specific CouchDB version is installed
|
|
321
|
-
async isBinaryInstalled(version: string): Promise<boolean> {
|
|
322
|
-
const { platform, arch } = this.getPlatformInfo()
|
|
323
|
-
return couchdbBinaryManager.isInstalled(version, platform, arch)
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Ensure CouchDB binaries are available for a specific version
|
|
328
|
-
*/
|
|
329
|
-
async ensureBinaries(
|
|
330
|
-
version: string,
|
|
331
|
-
onProgress?: ProgressCallback,
|
|
332
|
-
): Promise<string> {
|
|
333
|
-
const { platform, arch } = this.getPlatformInfo()
|
|
334
|
-
|
|
335
|
-
const binPath = await couchdbBinaryManager.ensureInstalled(
|
|
336
|
-
version,
|
|
337
|
-
platform,
|
|
338
|
-
arch,
|
|
339
|
-
onProgress,
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
// Register binaries in config
|
|
343
|
-
const toolPath = join(binPath, 'bin', `couchdb${getCouchDBExtension()}`)
|
|
344
|
-
if (existsSync(toolPath)) {
|
|
345
|
-
await configManager.setBinaryPath('couchdb', toolPath, 'bundled')
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
return binPath
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Initialize a new CouchDB data directory
|
|
353
|
-
*/
|
|
354
|
-
async initDataDir(
|
|
355
|
-
containerName: string,
|
|
356
|
-
_version: string,
|
|
357
|
-
options: Record<string, unknown> = {},
|
|
358
|
-
): Promise<string> {
|
|
359
|
-
const dataDir = paths.getContainerDataPath(containerName, {
|
|
360
|
-
engine: ENGINE,
|
|
361
|
-
})
|
|
362
|
-
const containerDir = paths.getContainerPath(containerName, {
|
|
363
|
-
engine: ENGINE,
|
|
364
|
-
})
|
|
365
|
-
const port = (options.port as number) || engineDef.defaultPort
|
|
366
|
-
|
|
367
|
-
// Create directories
|
|
368
|
-
if (!existsSync(dataDir)) {
|
|
369
|
-
await mkdir(dataDir, { recursive: true })
|
|
370
|
-
logDebug(`Created CouchDB data directory: ${dataDir}`)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const logDir = join(containerDir, 'log')
|
|
374
|
-
if (!existsSync(logDir)) {
|
|
375
|
-
await mkdir(logDir, { recursive: true })
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Generate local.ini config
|
|
379
|
-
const configPath = join(containerDir, 'local.ini')
|
|
380
|
-
const configContent = generateCouchDBConfig({
|
|
381
|
-
port,
|
|
382
|
-
dataDir,
|
|
383
|
-
logDir,
|
|
384
|
-
})
|
|
385
|
-
await writeFile(configPath, configContent)
|
|
386
|
-
logDebug(`Generated CouchDB config: ${configPath}`)
|
|
387
|
-
|
|
388
|
-
// Generate container-specific vm.args with unique node name
|
|
389
|
-
const vmArgsPath = join(containerDir, 'vm.args')
|
|
390
|
-
const vmArgsContent = generateVmArgs(port, containerDir)
|
|
391
|
-
await writeFile(vmArgsPath, vmArgsContent)
|
|
392
|
-
logDebug(`Generated CouchDB vm.args: ${vmArgsPath}`)
|
|
393
|
-
|
|
394
|
-
return dataDir
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// Get the path to couchdb server
|
|
398
|
-
async getCouchDBServerPath(version: string): Promise<string> {
|
|
399
|
-
const { platform, arch } = this.getPlatformInfo()
|
|
400
|
-
const fullVersion = normalizeVersion(version)
|
|
401
|
-
const binPath = paths.getBinaryPath({
|
|
402
|
-
engine: 'couchdb',
|
|
403
|
-
version: fullVersion,
|
|
404
|
-
platform,
|
|
405
|
-
arch,
|
|
406
|
-
})
|
|
407
|
-
const serverPath = join(binPath, 'bin', `couchdb${getCouchDBExtension()}`)
|
|
408
|
-
if (existsSync(serverPath)) {
|
|
409
|
-
return serverPath
|
|
410
|
-
}
|
|
411
|
-
throw new Error(
|
|
412
|
-
`CouchDB ${version} is not installed. Run: spindb engines download couchdb ${version}`,
|
|
413
|
-
)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Get the path to couchdb binary
|
|
417
|
-
async getCouchDBPath(version?: string): Promise<string> {
|
|
418
|
-
const cached = await configManager.getBinaryPath('couchdb')
|
|
419
|
-
if (cached && existsSync(cached)) {
|
|
420
|
-
return cached
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
if (version) {
|
|
424
|
-
const { platform, arch } = this.getPlatformInfo()
|
|
425
|
-
const fullVersion = normalizeVersion(version)
|
|
426
|
-
const binPath = paths.getBinaryPath({
|
|
427
|
-
engine: 'couchdb',
|
|
428
|
-
version: fullVersion,
|
|
429
|
-
platform,
|
|
430
|
-
arch,
|
|
431
|
-
})
|
|
432
|
-
const couchdbPath = join(
|
|
433
|
-
binPath,
|
|
434
|
-
'bin',
|
|
435
|
-
`couchdb${getCouchDBExtension()}`,
|
|
436
|
-
)
|
|
437
|
-
if (existsSync(couchdbPath)) {
|
|
438
|
-
return couchdbPath
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
throw new Error(
|
|
443
|
-
'couchdb not found. Run: spindb engines download couchdb <version>',
|
|
444
|
-
)
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Start CouchDB server
|
|
449
|
-
*/
|
|
450
|
-
async start(
|
|
451
|
-
container: ContainerConfig,
|
|
452
|
-
onProgress?: ProgressCallback,
|
|
453
|
-
): Promise<{ port: number; connectionString: string }> {
|
|
454
|
-
const { name, port, version, binaryPath } = container
|
|
455
|
-
|
|
456
|
-
// Check if already running
|
|
457
|
-
const alreadyRunning = await processManager.isRunning(name, {
|
|
458
|
-
engine: ENGINE,
|
|
459
|
-
})
|
|
460
|
-
if (alreadyRunning) {
|
|
461
|
-
return {
|
|
462
|
-
port,
|
|
463
|
-
connectionString: this.getConnectionString(container),
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Find couchdb binary
|
|
468
|
-
let couchdbServer: string | null = null
|
|
469
|
-
|
|
470
|
-
if (binaryPath && existsSync(binaryPath)) {
|
|
471
|
-
const serverPath = join(
|
|
472
|
-
binaryPath,
|
|
473
|
-
'bin',
|
|
474
|
-
`couchdb${getCouchDBExtension()}`,
|
|
475
|
-
)
|
|
476
|
-
if (existsSync(serverPath)) {
|
|
477
|
-
couchdbServer = serverPath
|
|
478
|
-
logDebug(`Using stored binary path: ${couchdbServer}`)
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
if (!couchdbServer) {
|
|
483
|
-
try {
|
|
484
|
-
couchdbServer = await this.getCouchDBServerPath(version)
|
|
485
|
-
} catch (error) {
|
|
486
|
-
const originalMessage =
|
|
487
|
-
error instanceof Error ? error.message : String(error)
|
|
488
|
-
throw new Error(
|
|
489
|
-
`CouchDB ${version} is not installed. Run: spindb engines download couchdb ${version}\n` +
|
|
490
|
-
` Original error: ${originalMessage}`,
|
|
491
|
-
)
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
logDebug(`Using couchdb for version ${version}: ${couchdbServer}`)
|
|
496
|
-
|
|
497
|
-
const containerDir = paths.getContainerPath(name, { engine: ENGINE })
|
|
498
|
-
const configPath = join(containerDir, 'local.ini')
|
|
499
|
-
const dataDir = paths.getContainerDataPath(name, { engine: ENGINE })
|
|
500
|
-
const logDir = join(containerDir, 'log')
|
|
501
|
-
const logFile = join(logDir, 'couchdb.log')
|
|
502
|
-
const pidFile = join(containerDir, 'couchdb.pid')
|
|
503
|
-
|
|
504
|
-
// Check port availability
|
|
505
|
-
const portWaitTimeout = isWindows() ? 60000 : 0
|
|
506
|
-
const portCheckStart = Date.now()
|
|
507
|
-
const portCheckInterval = 1000
|
|
508
|
-
|
|
509
|
-
while (!(await portManager.isPortAvailable(port))) {
|
|
510
|
-
if (Date.now() - portCheckStart >= portWaitTimeout) {
|
|
511
|
-
throw new Error(`Port ${port} is already in use.`)
|
|
512
|
-
}
|
|
513
|
-
logDebug(`Waiting for port ${port} to become available...`)
|
|
514
|
-
await new Promise((resolve) => setTimeout(resolve, portCheckInterval))
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// Regenerate config with current port
|
|
518
|
-
const configContent = generateCouchDBConfig({
|
|
519
|
-
port,
|
|
520
|
-
dataDir,
|
|
521
|
-
logDir,
|
|
522
|
-
})
|
|
523
|
-
await writeFile(configPath, configContent)
|
|
524
|
-
|
|
525
|
-
// Regenerate vm.args with unique node name for this port
|
|
526
|
-
const vmArgsPath = join(containerDir, 'vm.args')
|
|
527
|
-
const vmArgsContent = generateVmArgs(port, containerDir)
|
|
528
|
-
await writeFile(vmArgsPath, vmArgsContent)
|
|
529
|
-
|
|
530
|
-
onProgress?.({ stage: 'starting', message: 'Starting CouchDB...' })
|
|
531
|
-
|
|
532
|
-
logDebug(`Starting couchdb with config: ${configPath}`)
|
|
533
|
-
|
|
534
|
-
// Get the binary directory for default config paths
|
|
535
|
-
const binDir = dirname(dirname(couchdbServer))
|
|
536
|
-
const defaultIni = join(binDir, 'etc', 'default.ini')
|
|
537
|
-
|
|
538
|
-
// CouchDB uses COUCHDB_INI_FILES to load config files in order
|
|
539
|
-
// COUCHDB_ARGS_FILE specifies custom vm.args with unique node name
|
|
540
|
-
// On Windows, CouchDB may need additional paths set
|
|
541
|
-
const env: Record<string, string | undefined> = {
|
|
542
|
-
...process.env,
|
|
543
|
-
COUCHDB_INI_FILES: `${defaultIni} ${configPath}`,
|
|
544
|
-
COUCHDB_ARGS_FILE: vmArgsPath,
|
|
545
|
-
// Set CouchDB binary directory for Windows
|
|
546
|
-
COUCHDB_BINDIR: join(binDir, 'bin'),
|
|
547
|
-
COUCHDB_QUERY_SERVER_JAVASCRIPT: join(binDir, 'bin', 'couchjs'),
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
// On Windows, use sys.config to disable os_mon before it starts
|
|
551
|
-
// The vm.args settings are too late - os_mon crashes during init
|
|
552
|
-
// Erlang reads releases/sys.config at startup, so we modify that file
|
|
553
|
-
if (isWindows()) {
|
|
554
|
-
const sysConfigContent = generateSysConfig()
|
|
555
|
-
|
|
556
|
-
// The CRITICAL location - Erlang release reads from releases/sys.config
|
|
557
|
-
const releasesSysConfig = join(binDir, 'releases', 'sys.config')
|
|
558
|
-
await writeFile(releasesSysConfig, sysConfigContent)
|
|
559
|
-
|
|
560
|
-
// Copy vm.args to where Windows CouchDB expects it
|
|
561
|
-
const expectedVmArgs = join(binDir, 'etc', 'vm.args')
|
|
562
|
-
await writeFile(expectedVmArgs, vmArgsContent)
|
|
563
|
-
|
|
564
|
-
// Also update releases/vm.args
|
|
565
|
-
const releasesVmArgs = join(binDir, 'releases', 'vm.args')
|
|
566
|
-
await writeFile(releasesVmArgs, vmArgsContent)
|
|
567
|
-
|
|
568
|
-
// CRITICAL: Write config to binary's etc/local.ini
|
|
569
|
-
// Windows CouchDB doesn't respect COUCHDB_INI_FILES env var and may not scan local.d/
|
|
570
|
-
// Write directly to etc/local.ini which CouchDB definitely reads
|
|
571
|
-
// Note: This means only one container can run per binary install (typical for local dev)
|
|
572
|
-
const localIniPath = join(binDir, 'etc', 'local.ini')
|
|
573
|
-
await writeFile(localIniPath, configContent)
|
|
574
|
-
logDebug(`Wrote config to ${localIniPath}`)
|
|
575
|
-
|
|
576
|
-
// Modify the os_mon.app file directly to disable features
|
|
577
|
-
// This sets the default env values in the application spec itself
|
|
578
|
-
const osMonAppPath = join(
|
|
579
|
-
binDir,
|
|
580
|
-
'lib',
|
|
581
|
-
'os_mon-2.9.1',
|
|
582
|
-
'ebin',
|
|
583
|
-
'os_mon.app',
|
|
584
|
-
)
|
|
585
|
-
try {
|
|
586
|
-
const osMonApp = await readFile(osMonAppPath, 'utf8')
|
|
587
|
-
// Replace the default env settings to disable all features
|
|
588
|
-
const modifiedApp = osMonApp
|
|
589
|
-
.replace('{start_cpu_sup, true}', '{start_cpu_sup, false}')
|
|
590
|
-
.replace('{start_disksup, true}', '{start_disksup, false}')
|
|
591
|
-
.replace('{start_memsup, true}', '{start_memsup, false}')
|
|
592
|
-
await writeFile(osMonAppPath, modifiedApp)
|
|
593
|
-
logDebug('Modified os_mon.app to disable features')
|
|
594
|
-
} catch (err) {
|
|
595
|
-
logDebug(`Failed to modify os_mon.app: ${err}`)
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// Add os_mon priv/bin to PATH so win32sysinfo.exe can be found
|
|
599
|
-
const osMonPrivBin = join(binDir, 'lib', 'os_mon-2.9.1', 'priv', 'bin')
|
|
600
|
-
const existingPath = env.PATH || process.env.PATH || ''
|
|
601
|
-
env.PATH = `${osMonPrivBin};${existingPath}`
|
|
602
|
-
|
|
603
|
-
logDebug(`Wrote sys.config to ${releasesSysConfig}`)
|
|
604
|
-
logDebug(`Wrote vm.args to ${releasesVmArgs}`)
|
|
605
|
-
logDebug(`Added to PATH: ${osMonPrivBin}`)
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// Spawn CouchDB process
|
|
609
|
-
if (isWindows()) {
|
|
610
|
-
return new Promise((resolve, reject) => {
|
|
611
|
-
// On Windows, run from the CouchDB installation directory
|
|
612
|
-
// The Erlang VM expects to find files relative to its installation
|
|
613
|
-
const spawnOpts: SpawnOptions = {
|
|
614
|
-
cwd: binDir,
|
|
615
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
616
|
-
detached: true,
|
|
617
|
-
windowsHide: true,
|
|
618
|
-
env,
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// On Windows, .cmd files must be executed via cmd.exe
|
|
622
|
-
const proc = spawn('cmd.exe', ['/c', couchdbServer!], spawnOpts)
|
|
623
|
-
let settled = false
|
|
624
|
-
let stderrOutput = ''
|
|
625
|
-
let stdoutOutput = ''
|
|
626
|
-
|
|
627
|
-
proc.on('error', (err) => {
|
|
628
|
-
if (settled) return
|
|
629
|
-
settled = true
|
|
630
|
-
reject(new Error(`Failed to spawn CouchDB server: ${err.message}`))
|
|
631
|
-
})
|
|
632
|
-
|
|
633
|
-
proc.on('exit', (code, signal) => {
|
|
634
|
-
if (settled) return
|
|
635
|
-
settled = true
|
|
636
|
-
const reason = signal ? `signal ${signal}` : `code ${code}`
|
|
637
|
-
reject(
|
|
638
|
-
new Error(
|
|
639
|
-
`CouchDB process exited unexpectedly (${reason}).\n` +
|
|
640
|
-
`Stderr: ${stderrOutput || '(none)'}\n` +
|
|
641
|
-
`Stdout: ${stdoutOutput || '(none)'}`,
|
|
642
|
-
),
|
|
643
|
-
)
|
|
644
|
-
})
|
|
645
|
-
|
|
646
|
-
proc.stdout?.on('data', (data: Buffer) => {
|
|
647
|
-
stdoutOutput += data.toString()
|
|
648
|
-
})
|
|
649
|
-
proc.stderr?.on('data', (data: Buffer) => {
|
|
650
|
-
stderrOutput += data.toString()
|
|
651
|
-
})
|
|
652
|
-
|
|
653
|
-
proc.unref()
|
|
654
|
-
|
|
655
|
-
setTimeout(async () => {
|
|
656
|
-
if (settled) return
|
|
657
|
-
|
|
658
|
-
if (!proc.pid) {
|
|
659
|
-
settled = true
|
|
660
|
-
reject(new Error('CouchDB server process failed to start (no PID)'))
|
|
661
|
-
return
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
try {
|
|
665
|
-
await writeFile(pidFile, String(proc.pid))
|
|
666
|
-
} catch {
|
|
667
|
-
// Non-fatal
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
const ready = await this.waitForReady(port)
|
|
671
|
-
if (settled) return
|
|
672
|
-
|
|
673
|
-
if (ready) {
|
|
674
|
-
settled = true
|
|
675
|
-
resolve({
|
|
676
|
-
port,
|
|
677
|
-
connectionString: this.getConnectionString(container),
|
|
678
|
-
})
|
|
679
|
-
} else {
|
|
680
|
-
settled = true
|
|
681
|
-
|
|
682
|
-
if (proc.pid && platformService.isProcessRunning(proc.pid)) {
|
|
683
|
-
try {
|
|
684
|
-
await platformService.terminateProcess(proc.pid, true)
|
|
685
|
-
} catch {
|
|
686
|
-
// Ignore cleanup errors
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
reject(
|
|
691
|
-
new Error(
|
|
692
|
-
`CouchDB failed to start within timeout.\n` +
|
|
693
|
-
`Binary: ${couchdbServer}\n` +
|
|
694
|
-
`Config: ${configPath}\n` +
|
|
695
|
-
`Log file: ${logFile}`,
|
|
696
|
-
),
|
|
697
|
-
)
|
|
698
|
-
}
|
|
699
|
-
}, 500)
|
|
700
|
-
})
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
// macOS/Linux
|
|
704
|
-
const proc = spawn(couchdbServer, [], {
|
|
705
|
-
cwd: containerDir,
|
|
706
|
-
stdio: ['ignore', 'ignore', 'ignore'],
|
|
707
|
-
detached: true,
|
|
708
|
-
env,
|
|
709
|
-
})
|
|
710
|
-
proc.unref()
|
|
711
|
-
|
|
712
|
-
if (!proc.pid) {
|
|
713
|
-
throw new Error('CouchDB server process failed to start (no PID)')
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
try {
|
|
717
|
-
await writeFile(pidFile, String(proc.pid))
|
|
718
|
-
} catch {
|
|
719
|
-
// Non-fatal
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
const ready = await this.waitForReady(port)
|
|
723
|
-
|
|
724
|
-
if (ready) {
|
|
725
|
-
return {
|
|
726
|
-
port,
|
|
727
|
-
connectionString: this.getConnectionString(container),
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
throw new Error(
|
|
732
|
-
`CouchDB failed to start within timeout.\n` +
|
|
733
|
-
`Binary: ${couchdbServer}\n` +
|
|
734
|
-
`Config: ${configPath}\n` +
|
|
735
|
-
`Log file: ${logFile}`,
|
|
736
|
-
)
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// Wait for CouchDB to be ready
|
|
740
|
-
private async waitForReady(
|
|
741
|
-
port: number,
|
|
742
|
-
timeoutMs = 30000,
|
|
743
|
-
): Promise<boolean> {
|
|
744
|
-
const startTime = Date.now()
|
|
745
|
-
const checkInterval = 500
|
|
746
|
-
|
|
747
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
748
|
-
try {
|
|
749
|
-
const response = await couchdbApiRequest(port, 'GET', '/')
|
|
750
|
-
if (response.status === 200) {
|
|
751
|
-
logDebug(`CouchDB ready on port ${port}`)
|
|
752
|
-
return true
|
|
753
|
-
}
|
|
754
|
-
} catch {
|
|
755
|
-
// Connection failed, wait and retry
|
|
756
|
-
}
|
|
757
|
-
await new Promise((resolve) => setTimeout(resolve, checkInterval))
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
logDebug(`CouchDB did not become ready within ${timeoutMs}ms`)
|
|
761
|
-
return false
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
/**
|
|
765
|
-
* Stop CouchDB server
|
|
766
|
-
*/
|
|
767
|
-
async stop(container: ContainerConfig): Promise<void> {
|
|
768
|
-
const { name, port } = container
|
|
769
|
-
const containerDir = paths.getContainerPath(name, { engine: ENGINE })
|
|
770
|
-
const pidFile = join(containerDir, 'couchdb.pid')
|
|
771
|
-
|
|
772
|
-
logDebug(`Stopping CouchDB container "${name}" on port ${port}`)
|
|
773
|
-
|
|
774
|
-
let pid: number | null = null
|
|
775
|
-
|
|
776
|
-
if (existsSync(pidFile)) {
|
|
777
|
-
try {
|
|
778
|
-
const content = await readFile(pidFile, 'utf8')
|
|
779
|
-
pid = parseInt(content.trim(), 10)
|
|
780
|
-
} catch {
|
|
781
|
-
// Ignore
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
if (pid && platformService.isProcessRunning(pid)) {
|
|
786
|
-
logDebug(`Killing CouchDB process ${pid}`)
|
|
787
|
-
try {
|
|
788
|
-
if (isWindows()) {
|
|
789
|
-
await platformService.terminateProcess(pid, true)
|
|
790
|
-
} else {
|
|
791
|
-
await platformService.terminateProcess(pid, false)
|
|
792
|
-
await new Promise((resolve) => setTimeout(resolve, 2000))
|
|
793
|
-
|
|
794
|
-
if (platformService.isProcessRunning(pid)) {
|
|
795
|
-
logWarning(`Graceful termination failed, force killing ${pid}`)
|
|
796
|
-
await platformService.terminateProcess(pid, true)
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
} catch (error) {
|
|
800
|
-
logDebug(`Process termination error: ${error}`)
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
if (isWindows()) {
|
|
805
|
-
await new Promise((resolve) => setTimeout(resolve, 3000))
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
// Kill any processes still listening on the port
|
|
809
|
-
const portPids = await platformService.findProcessByPort(port)
|
|
810
|
-
for (const portPid of portPids) {
|
|
811
|
-
if (platformService.isProcessRunning(portPid)) {
|
|
812
|
-
logDebug(`Killing process ${portPid} still on port ${port}`)
|
|
813
|
-
try {
|
|
814
|
-
await platformService.terminateProcess(portPid, true)
|
|
815
|
-
} catch {
|
|
816
|
-
// Ignore
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
if (isWindows() && portPids.length > 0) {
|
|
822
|
-
await new Promise((resolve) => setTimeout(resolve, 2000))
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
// Cleanup PID file
|
|
826
|
-
if (existsSync(pidFile)) {
|
|
827
|
-
try {
|
|
828
|
-
await unlink(pidFile)
|
|
829
|
-
} catch {
|
|
830
|
-
// Ignore
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// Note: On Windows, we write to etc/local.ini which gets overwritten on each start
|
|
835
|
-
// No cleanup needed as the file is shared and will be updated on next container start
|
|
836
|
-
|
|
837
|
-
// Wait for port to be released on Windows
|
|
838
|
-
if (isWindows()) {
|
|
839
|
-
logDebug(`Waiting for port ${port} to be released...`)
|
|
840
|
-
const portWaitStart = Date.now()
|
|
841
|
-
const portWaitTimeout = 30000
|
|
842
|
-
const checkInterval = 500
|
|
843
|
-
|
|
844
|
-
while (Date.now() - portWaitStart < portWaitTimeout) {
|
|
845
|
-
if (await portManager.isPortAvailable(port)) {
|
|
846
|
-
logDebug('Port released successfully')
|
|
847
|
-
break
|
|
848
|
-
}
|
|
849
|
-
await new Promise((resolve) => setTimeout(resolve, checkInterval))
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
logDebug('CouchDB stopped')
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
// Get CouchDB server status
|
|
857
|
-
async status(container: ContainerConfig): Promise<StatusResult> {
|
|
858
|
-
const { name, port } = container
|
|
859
|
-
const containerDir = paths.getContainerPath(name, { engine: ENGINE })
|
|
860
|
-
const pidFile = join(containerDir, 'couchdb.pid')
|
|
861
|
-
|
|
862
|
-
// Try health check via REST API
|
|
863
|
-
try {
|
|
864
|
-
const response = await couchdbApiRequest(port, 'GET', '/')
|
|
865
|
-
if (response.status === 200) {
|
|
866
|
-
return { running: true, message: 'CouchDB is running' }
|
|
867
|
-
}
|
|
868
|
-
} catch {
|
|
869
|
-
// Not responding, check PID
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
// Check PID file
|
|
873
|
-
if (existsSync(pidFile)) {
|
|
874
|
-
try {
|
|
875
|
-
const content = await readFile(pidFile, 'utf8')
|
|
876
|
-
const pid = parseInt(content.trim(), 10)
|
|
877
|
-
if (!isNaN(pid) && pid > 0 && platformService.isProcessRunning(pid)) {
|
|
878
|
-
return {
|
|
879
|
-
running: true,
|
|
880
|
-
message: `CouchDB is running (PID: ${pid})`,
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
} catch {
|
|
884
|
-
// Ignore
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
return { running: false, message: 'CouchDB is not running' }
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
// Detect backup format
|
|
892
|
-
async detectBackupFormat(filePath: string): Promise<BackupFormat> {
|
|
893
|
-
return detectBackupFormatImpl(filePath)
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
/**
|
|
897
|
-
* Restore a backup
|
|
898
|
-
* CouchDB can restore while running (uses REST API)
|
|
899
|
-
*/
|
|
900
|
-
async restore(
|
|
901
|
-
container: ContainerConfig,
|
|
902
|
-
backupPath: string,
|
|
903
|
-
options: { database?: string; flush?: boolean } = {},
|
|
904
|
-
): Promise<RestoreResult> {
|
|
905
|
-
const { port } = container
|
|
906
|
-
|
|
907
|
-
return restoreBackup(backupPath, {
|
|
908
|
-
port,
|
|
909
|
-
database: options.database,
|
|
910
|
-
flush: options.flush,
|
|
911
|
-
})
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
/**
|
|
915
|
-
* Get connection string
|
|
916
|
-
* Format: http://127.0.0.1:PORT
|
|
917
|
-
*/
|
|
918
|
-
getConnectionString(container: ContainerConfig, database?: string): string {
|
|
919
|
-
const { port } = container
|
|
920
|
-
const base = `http://127.0.0.1:${port}`
|
|
921
|
-
return database ? `${base}/${database}` : base
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
// Open Fauxton web UI
|
|
925
|
-
async connect(container: ContainerConfig, _database?: string): Promise<void> {
|
|
926
|
-
const { port } = container
|
|
927
|
-
const url = `http://127.0.0.1:${port}/_utils`
|
|
928
|
-
|
|
929
|
-
console.log(`CouchDB REST API available at: http://127.0.0.1:${port}`)
|
|
930
|
-
console.log(`CouchDB Fauxton UI: ${url}`)
|
|
931
|
-
console.log('')
|
|
932
|
-
console.log('Example commands:')
|
|
933
|
-
console.log(` curl http://127.0.0.1:${port}`)
|
|
934
|
-
console.log(` curl http://127.0.0.1:${port}/_all_dbs`)
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
/**
|
|
938
|
-
* Create a new database
|
|
939
|
-
*/
|
|
940
|
-
async createDatabase(
|
|
941
|
-
container: ContainerConfig,
|
|
942
|
-
database: string,
|
|
943
|
-
): Promise<void> {
|
|
944
|
-
const { port } = container
|
|
945
|
-
|
|
946
|
-
const response = await couchdbApiRequest(
|
|
947
|
-
port,
|
|
948
|
-
'PUT',
|
|
949
|
-
`/${encodeURIComponent(database)}`,
|
|
950
|
-
)
|
|
951
|
-
|
|
952
|
-
if (response.status !== 201 && response.status !== 412) {
|
|
953
|
-
// 412 means database already exists
|
|
954
|
-
throw new Error(
|
|
955
|
-
`Failed to create database: ${JSON.stringify(response.data)}`,
|
|
956
|
-
)
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
logDebug(`Created CouchDB database: ${database}`)
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
/**
|
|
963
|
-
* Drop a database
|
|
964
|
-
*/
|
|
965
|
-
async dropDatabase(
|
|
966
|
-
container: ContainerConfig,
|
|
967
|
-
database: string,
|
|
968
|
-
): Promise<void> {
|
|
969
|
-
const { port } = container
|
|
970
|
-
|
|
971
|
-
const response = await couchdbApiRequest(
|
|
972
|
-
port,
|
|
973
|
-
'DELETE',
|
|
974
|
-
`/${encodeURIComponent(database)}`,
|
|
975
|
-
)
|
|
976
|
-
|
|
977
|
-
// Accept 200 (OK) or 202 (Accepted) for async deletes
|
|
978
|
-
if (response.status !== 200 && response.status !== 202) {
|
|
979
|
-
throw new Error(
|
|
980
|
-
`Failed to delete database: ${JSON.stringify(response.data)}`,
|
|
981
|
-
)
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
logDebug(
|
|
985
|
-
`Deleted CouchDB database: ${database} (status: ${response.status})`,
|
|
986
|
-
)
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
/**
|
|
990
|
-
* Get the size of the CouchDB instance
|
|
991
|
-
*/
|
|
992
|
-
async getDatabaseSize(container: ContainerConfig): Promise<number | null> {
|
|
993
|
-
const { port } = container
|
|
994
|
-
|
|
995
|
-
try {
|
|
996
|
-
// CouchDB doesn't directly expose total size, but we can sum up database sizes
|
|
997
|
-
const dbsResponse = await couchdbApiRequest(port, 'GET', '/_all_dbs')
|
|
998
|
-
if (dbsResponse.status !== 200) {
|
|
999
|
-
return null
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
const dbs = dbsResponse.data as string[]
|
|
1003
|
-
let totalSize = 0
|
|
1004
|
-
|
|
1005
|
-
for (const db of dbs) {
|
|
1006
|
-
if (db.startsWith('_')) continue // Skip system dbs
|
|
1007
|
-
const infoResponse = await couchdbApiRequest(
|
|
1008
|
-
port,
|
|
1009
|
-
'GET',
|
|
1010
|
-
`/${encodeURIComponent(db)}`,
|
|
1011
|
-
)
|
|
1012
|
-
if (infoResponse.status === 200) {
|
|
1013
|
-
const info = infoResponse.data as { sizes?: { file?: number } }
|
|
1014
|
-
totalSize += info.sizes?.file || 0
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
return totalSize > 0 ? totalSize : null
|
|
1019
|
-
} catch {
|
|
1020
|
-
return null
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
/**
|
|
1025
|
-
* Dump from a remote CouchDB connection
|
|
1026
|
-
*/
|
|
1027
|
-
async dumpFromConnectionString(
|
|
1028
|
-
connectionString: string,
|
|
1029
|
-
outputPath: string,
|
|
1030
|
-
): Promise<DumpResult> {
|
|
1031
|
-
const { baseUrl, headers, database } =
|
|
1032
|
-
parseCouchDBConnectionString(connectionString)
|
|
1033
|
-
|
|
1034
|
-
logDebug(`Connecting to remote CouchDB at ${baseUrl}`)
|
|
1035
|
-
|
|
1036
|
-
// Check connectivity
|
|
1037
|
-
const infoResponse = await remoteCouchDBRequest(
|
|
1038
|
-
baseUrl,
|
|
1039
|
-
'GET',
|
|
1040
|
-
'/',
|
|
1041
|
-
headers,
|
|
1042
|
-
)
|
|
1043
|
-
if (infoResponse.status !== 200) {
|
|
1044
|
-
throw new Error(
|
|
1045
|
-
`Failed to connect to CouchDB at ${baseUrl}: ${JSON.stringify(infoResponse.data)}`,
|
|
1046
|
-
)
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
const serverInfo = infoResponse.data as { version?: string }
|
|
1050
|
-
logDebug(`Connected to CouchDB ${serverInfo?.version || 'unknown'}`)
|
|
1051
|
-
|
|
1052
|
-
// Get databases to backup
|
|
1053
|
-
let databasesToBackup: string[]
|
|
1054
|
-
|
|
1055
|
-
if (database) {
|
|
1056
|
-
databasesToBackup = [database]
|
|
1057
|
-
} else {
|
|
1058
|
-
const dbsResponse = await remoteCouchDBRequest(
|
|
1059
|
-
baseUrl,
|
|
1060
|
-
'GET',
|
|
1061
|
-
'/_all_dbs',
|
|
1062
|
-
headers,
|
|
1063
|
-
)
|
|
1064
|
-
if (dbsResponse.status !== 200) {
|
|
1065
|
-
throw new Error(
|
|
1066
|
-
`Failed to list databases: ${JSON.stringify(dbsResponse.data)}`,
|
|
1067
|
-
)
|
|
1068
|
-
}
|
|
1069
|
-
const allDbs = dbsResponse.data as string[]
|
|
1070
|
-
databasesToBackup = allDbs.filter((db) => !db.startsWith('_'))
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
logDebug(`Backing up ${databasesToBackup.length} database(s)`)
|
|
1074
|
-
|
|
1075
|
-
// Export documents from each database
|
|
1076
|
-
const backup = {
|
|
1077
|
-
version: serverInfo?.version || 'unknown',
|
|
1078
|
-
created: new Date().toISOString(),
|
|
1079
|
-
databases: [] as Array<{ name: string; docs: unknown[] }>,
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
for (const dbName of databasesToBackup) {
|
|
1083
|
-
logDebug(`Exporting database: ${dbName}`)
|
|
1084
|
-
|
|
1085
|
-
const docsResponse = await remoteCouchDBRequest(
|
|
1086
|
-
baseUrl,
|
|
1087
|
-
'GET',
|
|
1088
|
-
`/${encodeURIComponent(dbName)}/_all_docs?include_docs=true`,
|
|
1089
|
-
headers,
|
|
1090
|
-
undefined,
|
|
1091
|
-
300000, // 5 minutes for large databases
|
|
1092
|
-
)
|
|
1093
|
-
|
|
1094
|
-
if (docsResponse.status !== 200) {
|
|
1095
|
-
throw new Error(
|
|
1096
|
-
`Failed to export database ${dbName}: ${JSON.stringify(docsResponse.data)}`,
|
|
1097
|
-
)
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
const docsData = docsResponse.data as {
|
|
1101
|
-
rows?: Array<{ doc?: unknown }>
|
|
1102
|
-
}
|
|
1103
|
-
const docs =
|
|
1104
|
-
docsData.rows
|
|
1105
|
-
?.map((row) => row.doc)
|
|
1106
|
-
.filter((doc): doc is unknown => doc !== undefined) || []
|
|
1107
|
-
|
|
1108
|
-
// Filter out design documents
|
|
1109
|
-
const userDocs = docs.filter((doc) => {
|
|
1110
|
-
const d = doc as { _id?: string }
|
|
1111
|
-
return d._id && !d._id.startsWith('_design/')
|
|
1112
|
-
})
|
|
1113
|
-
|
|
1114
|
-
backup.databases.push({
|
|
1115
|
-
name: dbName,
|
|
1116
|
-
docs: userDocs,
|
|
1117
|
-
})
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
// Write backup to file
|
|
1121
|
-
await mkdir(dirname(outputPath), { recursive: true })
|
|
1122
|
-
await writeFile(outputPath, JSON.stringify(backup, null, 2))
|
|
1123
|
-
|
|
1124
|
-
return {
|
|
1125
|
-
filePath: outputPath,
|
|
1126
|
-
warnings:
|
|
1127
|
-
databasesToBackup.length === 0
|
|
1128
|
-
? ['Remote CouchDB instance has no user databases']
|
|
1129
|
-
: undefined,
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
// Create a backup
|
|
1134
|
-
async backup(
|
|
1135
|
-
container: ContainerConfig,
|
|
1136
|
-
outputPath: string,
|
|
1137
|
-
options: BackupOptions,
|
|
1138
|
-
): Promise<BackupResult> {
|
|
1139
|
-
return createBackup(container, outputPath, options)
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
// Run a command - CouchDB uses REST API, not command files
|
|
1143
|
-
async runScript(
|
|
1144
|
-
container: ContainerConfig,
|
|
1145
|
-
options: { file?: string; sql?: string; database?: string },
|
|
1146
|
-
): Promise<void> {
|
|
1147
|
-
const { port } = container
|
|
1148
|
-
|
|
1149
|
-
if (options.file) {
|
|
1150
|
-
throw new Error(
|
|
1151
|
-
'CouchDB does not support command files. Use the REST API directly.\n' +
|
|
1152
|
-
`Example: curl http://127.0.0.1:${port}/_all_dbs`,
|
|
1153
|
-
)
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
if (options.sql) {
|
|
1157
|
-
const command = options.sql.trim().toUpperCase()
|
|
1158
|
-
|
|
1159
|
-
if (command === 'LIST DATABASES' || command === 'SHOW DATABASES') {
|
|
1160
|
-
const response = await couchdbApiRequest(port, 'GET', '/_all_dbs')
|
|
1161
|
-
console.log(JSON.stringify(response.data, null, 2))
|
|
1162
|
-
return
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
throw new Error(
|
|
1166
|
-
'CouchDB uses REST API for operations. Use curl or the CouchDB client libraries.\n' +
|
|
1167
|
-
`API endpoint: http://127.0.0.1:${port}`,
|
|
1168
|
-
)
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
throw new Error('Either file or sql option must be provided')
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
/**
|
|
1175
|
-
* Execute a query via REST API
|
|
1176
|
-
*
|
|
1177
|
-
* Query format: METHOD /path [JSON body]
|
|
1178
|
-
* Examples:
|
|
1179
|
-
* GET /_all_dbs
|
|
1180
|
-
* GET /mydb/_all_docs
|
|
1181
|
-
* POST /mydb/_find {"selector": {"type": "user"}}
|
|
1182
|
-
*/
|
|
1183
|
-
async executeQuery(
|
|
1184
|
-
container: ContainerConfig,
|
|
1185
|
-
query: string,
|
|
1186
|
-
options?: QueryOptions,
|
|
1187
|
-
): Promise<QueryResult> {
|
|
1188
|
-
const { port } = container
|
|
1189
|
-
|
|
1190
|
-
// Parse the query string: METHOD /path [body]
|
|
1191
|
-
// If options?.method is provided, query can be just the path
|
|
1192
|
-
const trimmed = query.trim()
|
|
1193
|
-
const spaceIdx = trimmed.indexOf(' ')
|
|
1194
|
-
|
|
1195
|
-
let method: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
|
1196
|
-
let rest: string
|
|
1197
|
-
|
|
1198
|
-
if (options?.method) {
|
|
1199
|
-
// Method provided via options
|
|
1200
|
-
method = options.method as 'GET' | 'POST' | 'PUT' | 'DELETE'
|
|
1201
|
-
if (spaceIdx !== -1) {
|
|
1202
|
-
// Check if first token looks like a method (GET, POST, etc.)
|
|
1203
|
-
const firstToken = trimmed.substring(0, spaceIdx).toUpperCase()
|
|
1204
|
-
if (['GET', 'POST', 'PUT', 'DELETE'].includes(firstToken)) {
|
|
1205
|
-
// Query has method prefix, use rest after it
|
|
1206
|
-
rest = trimmed.substring(spaceIdx + 1).trim()
|
|
1207
|
-
} else {
|
|
1208
|
-
// Query is path + body, use entire trimmed
|
|
1209
|
-
rest = trimmed
|
|
1210
|
-
}
|
|
1211
|
-
} else {
|
|
1212
|
-
// Query is just the path
|
|
1213
|
-
rest = trimmed
|
|
1214
|
-
}
|
|
1215
|
-
} else {
|
|
1216
|
-
// No method in options, must parse from query
|
|
1217
|
-
if (spaceIdx === -1) {
|
|
1218
|
-
throw new Error(
|
|
1219
|
-
'Invalid query format. Expected: METHOD /path [body]\n' +
|
|
1220
|
-
'Example: GET /_all_dbs',
|
|
1221
|
-
)
|
|
1222
|
-
}
|
|
1223
|
-
method = trimmed.substring(0, spaceIdx).toUpperCase() as
|
|
1224
|
-
| 'GET'
|
|
1225
|
-
| 'POST'
|
|
1226
|
-
| 'PUT'
|
|
1227
|
-
| 'DELETE'
|
|
1228
|
-
rest = trimmed.substring(spaceIdx + 1).trim()
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
// Extract path and optional JSON body
|
|
1232
|
-
let path: string
|
|
1233
|
-
let body: Record<string, unknown> | undefined = options?.body
|
|
1234
|
-
|
|
1235
|
-
const bodyStart = rest.indexOf('{')
|
|
1236
|
-
if (bodyStart !== -1 && !body) {
|
|
1237
|
-
path = rest.substring(0, bodyStart).trim()
|
|
1238
|
-
try {
|
|
1239
|
-
body = JSON.parse(rest.substring(bodyStart)) as Record<string, unknown>
|
|
1240
|
-
} catch {
|
|
1241
|
-
throw new Error('Invalid JSON body in query')
|
|
1242
|
-
}
|
|
1243
|
-
} else {
|
|
1244
|
-
path = rest
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
// Ensure path starts with /
|
|
1248
|
-
if (!path.startsWith('/')) {
|
|
1249
|
-
path = '/' + path
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
const response = await couchdbApiRequest(port, method, path, body)
|
|
1253
|
-
|
|
1254
|
-
if (response.status >= 400) {
|
|
1255
|
-
throw new Error(
|
|
1256
|
-
`CouchDB API error (${response.status}): ${JSON.stringify(response.data)}`,
|
|
1257
|
-
)
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
return parseRESTAPIResult(JSON.stringify(response.data))
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
/**
|
|
1264
|
-
* List all user databases, excluding system databases (_users, _replicator, _global_changes).
|
|
1265
|
-
*/
|
|
1266
|
-
async listDatabases(container: ContainerConfig): Promise<string[]> {
|
|
1267
|
-
const { port } = container
|
|
1268
|
-
|
|
1269
|
-
const response = await couchdbApiRequest(port, 'GET', '/_all_dbs')
|
|
1270
|
-
|
|
1271
|
-
if (response.status >= 400) {
|
|
1272
|
-
throw new Error(
|
|
1273
|
-
`CouchDB API error (${response.status}): ${JSON.stringify(response.data)}`,
|
|
1274
|
-
)
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
const allDatabases = response.data as string[]
|
|
1278
|
-
const systemDatabases = ['_users', '_replicator', '_global_changes']
|
|
1279
|
-
const databases = allDatabases.filter(
|
|
1280
|
-
(db) => !systemDatabases.includes(db) && !db.startsWith('_'),
|
|
1281
|
-
)
|
|
1282
|
-
|
|
1283
|
-
return databases
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
async createUser(
|
|
1287
|
-
container: ContainerConfig,
|
|
1288
|
-
options: CreateUserOptions,
|
|
1289
|
-
): Promise<UserCredentials> {
|
|
1290
|
-
const { username, password, database } = options
|
|
1291
|
-
assertValidUsername(username)
|
|
1292
|
-
const { port } = container
|
|
1293
|
-
const db = database || container.database
|
|
1294
|
-
if (!db) {
|
|
1295
|
-
throw new Error(
|
|
1296
|
-
'No database specified. Use --database or create a database first.',
|
|
1297
|
-
)
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
// Ensure _users system database exists (CouchDB 3.x doesn't auto-create it)
|
|
1301
|
-
const usersDbResponse = await couchdbApiRequest(port, 'PUT', '/_users')
|
|
1302
|
-
if (usersDbResponse.status !== 201 && usersDbResponse.status !== 412) {
|
|
1303
|
-
throw new Error(
|
|
1304
|
-
`Failed to ensure _users database exists: ${JSON.stringify(usersDbResponse.data)}`,
|
|
1305
|
-
)
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
// Create user document in _users database
|
|
1309
|
-
const userDoc = {
|
|
1310
|
-
_id: `org.couchdb.user:${username}`,
|
|
1311
|
-
name: username,
|
|
1312
|
-
type: 'user',
|
|
1313
|
-
roles: [],
|
|
1314
|
-
password,
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
const createResponse = await couchdbApiRequest(
|
|
1318
|
-
port,
|
|
1319
|
-
'PUT',
|
|
1320
|
-
`/_users/org.couchdb.user:${encodeURIComponent(username)}`,
|
|
1321
|
-
userDoc as unknown as Record<string, unknown>,
|
|
1322
|
-
)
|
|
1323
|
-
|
|
1324
|
-
if (createResponse.status !== 201 && createResponse.status !== 409) {
|
|
1325
|
-
throw new Error(
|
|
1326
|
-
`Failed to create user: ${JSON.stringify(createResponse.data)}`,
|
|
1327
|
-
)
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
if (createResponse.status === 409) {
|
|
1331
|
-
// User exists — fetch current doc revision and update password
|
|
1332
|
-
const getResponse = await couchdbApiRequest(
|
|
1333
|
-
port,
|
|
1334
|
-
'GET',
|
|
1335
|
-
`/_users/org.couchdb.user:${encodeURIComponent(username)}`,
|
|
1336
|
-
)
|
|
1337
|
-
|
|
1338
|
-
if (getResponse.status !== 200 || !getResponse.data) {
|
|
1339
|
-
throw new Error(
|
|
1340
|
-
`Failed to fetch existing user "${username}" (status ${getResponse.status}): ${JSON.stringify(getResponse.data)}`,
|
|
1341
|
-
)
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
const existingDoc = getResponse.data as Record<string, unknown>
|
|
1345
|
-
const rev = existingDoc._rev as string
|
|
1346
|
-
if (!rev) {
|
|
1347
|
-
throw new Error(
|
|
1348
|
-
`User "${username}" already exists but document has no _rev field: ${JSON.stringify(getResponse.data)}`,
|
|
1349
|
-
)
|
|
1350
|
-
}
|
|
1351
|
-
const updateResponse = await couchdbApiRequest(
|
|
1352
|
-
port,
|
|
1353
|
-
'PUT',
|
|
1354
|
-
`/_users/org.couchdb.user:${encodeURIComponent(username)}`,
|
|
1355
|
-
{ ...existingDoc, password, _rev: rev },
|
|
1356
|
-
)
|
|
1357
|
-
if (updateResponse.status !== 201) {
|
|
1358
|
-
throw new Error(
|
|
1359
|
-
`Failed to update user: ${JSON.stringify(updateResponse.data)}`,
|
|
1360
|
-
)
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
// Ensure the target database exists before setting security
|
|
1365
|
-
const dbCreateResponse = await couchdbApiRequest(
|
|
1366
|
-
port,
|
|
1367
|
-
'PUT',
|
|
1368
|
-
`/${encodeURIComponent(db)}`,
|
|
1369
|
-
)
|
|
1370
|
-
// 201 = created, 412 = already exists — both are fine
|
|
1371
|
-
if (dbCreateResponse.status !== 201 && dbCreateResponse.status !== 412) {
|
|
1372
|
-
throw new Error(
|
|
1373
|
-
`Failed to ensure database "${db}" exists: ${JSON.stringify(dbCreateResponse.data)}`,
|
|
1374
|
-
)
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
// Grant access to the target database via _security document
|
|
1378
|
-
const secResponse = await couchdbApiRequest(
|
|
1379
|
-
port,
|
|
1380
|
-
'GET',
|
|
1381
|
-
`/${encodeURIComponent(db)}/_security`,
|
|
1382
|
-
)
|
|
1383
|
-
|
|
1384
|
-
if (secResponse.status !== 200) {
|
|
1385
|
-
throw new Error(
|
|
1386
|
-
`Failed to read database security for "${db}": ${JSON.stringify(secResponse.data)}`,
|
|
1387
|
-
)
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
const security = (secResponse.data || {}) as Record<string, unknown>
|
|
1391
|
-
const members = (security.members || {}) as Record<string, unknown>
|
|
1392
|
-
const names = ((members.names || []) as string[]).slice()
|
|
1393
|
-
|
|
1394
|
-
if (!names.includes(username)) {
|
|
1395
|
-
names.push(username)
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
const secPutResponse = await couchdbApiRequest(
|
|
1399
|
-
port,
|
|
1400
|
-
'PUT',
|
|
1401
|
-
`/${encodeURIComponent(db)}/_security`,
|
|
1402
|
-
{
|
|
1403
|
-
...security,
|
|
1404
|
-
members: { ...members, names },
|
|
1405
|
-
},
|
|
1406
|
-
)
|
|
1407
|
-
|
|
1408
|
-
if (secPutResponse.status !== 200 && secPutResponse.status !== 201) {
|
|
1409
|
-
throw new Error(
|
|
1410
|
-
`Failed to update database security for "${db}": ${JSON.stringify(secPutResponse.data)}`,
|
|
1411
|
-
)
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
logDebug(`Created CouchDB user: ${username}`)
|
|
1415
|
-
|
|
1416
|
-
const connectionString = `http://${encodeURIComponent(username)}:${encodeURIComponent(password)}@127.0.0.1:${port}/${encodeURIComponent(db)}`
|
|
1417
|
-
|
|
1418
|
-
return {
|
|
1419
|
-
username,
|
|
1420
|
-
password,
|
|
1421
|
-
connectionString,
|
|
1422
|
-
engine: container.engine,
|
|
1423
|
-
container: container.name,
|
|
1424
|
-
database: db,
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
export const couchdbEngine = new CouchDBEngine()
|