spindb 0.27.6 β 0.30.1
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/README.md +133 -47
- package/cli/commands/create.ts +92 -26
- package/cli/commands/databases.ts +278 -74
- package/cli/commands/export.ts +362 -0
- package/cli/commands/menu/backup-handlers.ts +62 -27
- package/cli/commands/menu/container-handlers.ts +641 -144
- package/cli/commands/menu/engine-handlers.ts +2 -2
- package/cli/commands/menu/index.ts +2 -1
- package/cli/commands/menu/shell-handlers.ts +69 -42
- package/cli/commands/menu/sql-handlers.ts +8 -18
- package/cli/commands/pull.ts +223 -0
- package/cli/commands/self-update.ts +18 -6
- package/cli/commands/sqlite.ts +1 -3
- package/cli/commands/which.ts +290 -0
- package/cli/constants.ts +10 -0
- package/cli/index.ts +6 -0
- package/cli/ui/prompts.ts +216 -44
- package/cli/ui/theme.ts +1 -6
- package/core/credential-generator.ts +93 -0
- package/core/docker-exporter.ts +895 -0
- package/core/pull-manager.ts +496 -0
- package/core/tls-generator.ts +116 -0
- package/core/update-manager.ts +25 -15
- package/engines/base-engine.ts +14 -0
- package/engines/clickhouse/README.md +231 -0
- package/engines/cockroachdb/README.md +170 -0
- package/engines/couchdb/README.md +257 -0
- package/engines/duckdb/README.md +154 -0
- package/engines/ferretdb/README.md +220 -0
- package/engines/mariadb/README.md +141 -0
- package/engines/mariadb/backup.ts +2 -4
- package/engines/mariadb/index.ts +47 -0
- package/engines/meilisearch/README.md +255 -0
- package/engines/mongodb/README.md +162 -0
- package/engines/mongodb/backup.ts +2 -2
- package/engines/mongodb/cli-utils.ts +107 -14
- package/engines/mongodb/index.ts +2 -1
- package/engines/mongodb/restore.ts +13 -6
- package/engines/mysql/README.md +142 -0
- package/engines/mysql/backup.ts +66 -9
- package/engines/mysql/index.ts +48 -0
- package/engines/mysql/restore.ts +56 -12
- package/engines/postgresql/README.md +158 -0
- package/engines/postgresql/backup.ts +70 -14
- package/engines/postgresql/index.ts +26 -0
- package/engines/postgresql/restore.ts +129 -18
- package/engines/qdrant/README.md +222 -0
- package/engines/qdrant/cli-utils.ts +2 -4
- package/engines/questdb/README.md +334 -0
- package/engines/questdb/index.ts +1 -2
- package/engines/redis/README.md +173 -0
- package/engines/redis/cli-utils.ts +2 -4
- package/engines/sqlite/README.md +162 -0
- package/engines/surrealdb/README.md +218 -0
- package/engines/surrealdb/index.ts +1 -2
- package/engines/valkey/README.md +219 -0
- package/engines/valkey/cli-utils.ts +2 -4
- package/package.json +3 -3
- package/types/index.ts +25 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/spindb)
|
|
4
4
|
[](https://www.npmjs.com/package/spindb)
|
|
5
5
|
[](LICENSE)
|
|
6
|
-
[](#
|
|
6
|
+
[](#supported-engines--platforms)
|
|
7
7
|
|
|
8
8
|
**One CLI for all your local databases.**
|
|
9
9
|
|
|
@@ -26,6 +26,35 @@ spindb create cache --engine redis
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
+
## Supported Engines & Platforms
|
|
30
|
+
|
|
31
|
+
SpinDB supports **16 database engines** across **5 platform architectures**βall with a consistent API.
|
|
32
|
+
|
|
33
|
+
| Engine | Type | macOS ARM | macOS Intel | Linux x64 | Linux ARM | Windows |
|
|
34
|
+
|--------|------|:---------:|:-----------:|:---------:|:---------:|:-------:|
|
|
35
|
+
| π **PostgreSQL** | Relational SQL | β
| β
| β
| β
| β
|
|
|
36
|
+
| π¬ **MySQL** | Relational SQL | β
| β
| β
| β
| β
|
|
|
37
|
+
| π¦ **MariaDB** | Relational SQL | β
| β
| β
| β
| β
|
|
|
38
|
+
| πͺΆ **SQLite** | Embedded SQL | β
| β
| β
| β
| β
|
|
|
39
|
+
| π¦ **DuckDB** | Embedded OLAP | β
| β
| β
| β
| β
|
|
|
40
|
+
| π **MongoDB** | Document Store | β
| β
| β
| β
| β
|
|
|
41
|
+
| π¦ **FerretDB** | Document Store | β
| β
| β
| β
| β |
|
|
42
|
+
| π΄ **Redis** | Key-Value | β
| β
| β
| β
| β
|
|
|
43
|
+
| π· **Valkey** | Key-Value | β
| β
| β
| β
| β
|
|
|
44
|
+
| π **ClickHouse** | Columnar OLAP | β
| β
| β
| β
| β |
|
|
45
|
+
| π§ **Qdrant** | Vector Search | β
| β
| β
| β
| β
|
|
|
46
|
+
| π **Meilisearch** | Full-Text Search | β
| β
| β
| β
| β
|
|
|
47
|
+
| ποΈ **CouchDB** | Document Store | β
| β
| β
| β
| β
|
|
|
48
|
+
| πͺ³ **CockroachDB** | Distributed SQL | β
| β
| β
| β
| β
|
|
|
49
|
+
| π **SurrealDB** | Multi-Model | β
| β
| β
| β
| β
|
|
|
50
|
+
| β±οΈ **QuestDB** | Time-Series | β
| β
| β
| β
| β
|
|
|
51
|
+
|
|
52
|
+
**78 combinations. One CLI. Zero configuration.**
|
|
53
|
+
|
|
54
|
+
> ClickHouse and FerretDB are available on Windows via WSL.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
29
58
|
## What is SpinDB?
|
|
30
59
|
|
|
31
60
|
SpinDB is **three tools in one**:
|
|
@@ -68,33 +97,6 @@ spindb run mydb -c "SELECT * FROM system.tables" # ClickHouse
|
|
|
68
97
|
|
|
69
98
|
---
|
|
70
99
|
|
|
71
|
-
## Platform Coverage
|
|
72
|
-
|
|
73
|
-
SpinDB works across **16 database engines** and **5 platform architectures** with a **single, consistent API**.
|
|
74
|
-
|
|
75
|
-
| Database | macOS ARM64 | macOS Intel | Linux x64 | Linux ARM64 | Windows x64 |
|
|
76
|
-
|----------|:-----------:|:-----------:|:---------:|:-----------:|:-----------:|
|
|
77
|
-
| π **PostgreSQL** | β
| β
| β
| β
| β
|
|
|
78
|
-
| π¬ **MySQL** | β
| β
| β
| β
| β
|
|
|
79
|
-
| π¦ **MariaDB** | β
| β
| β
| β
| β
|
|
|
80
|
-
| πͺΆ **SQLite** | β
| β
| β
| β
| β
|
|
|
81
|
-
| π¦ **DuckDB** | β
| β
| β
| β
| β
|
|
|
82
|
-
| π **MongoDB** | β
| β
| β
| β
| β
|
|
|
83
|
-
| π¦ **FerretDB** | β
| β
| β
| β
| β |
|
|
84
|
-
| π΄ **Redis** | β
| β
| β
| β
| β
|
|
|
85
|
-
| π· **Valkey** | β
| β
| β
| β
| β
|
|
|
86
|
-
| π **ClickHouse** | β
| β
| β
| β
| β |
|
|
87
|
-
| π§ **Qdrant** | β
| β
| β
| β
| β
|
|
|
88
|
-
| π **Meilisearch** | β
| β
| β
| β
| β
|
|
|
89
|
-
| ποΈ **CouchDB** | β
| β
| β
| β
| β
|
|
|
90
|
-
| πͺ³ **CockroachDB** | β
| β
| β
| β
| β
|
|
|
91
|
-
| π **SurrealDB** | β
| β
| β
| β
| β
|
|
|
92
|
-
| β±οΈ **QuestDB** | β
| β
| β
| β
| β
|
|
|
93
|
-
|
|
94
|
-
**78 combinations. One CLI. Zero configuration.**
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
100
|
## Quick Start
|
|
99
101
|
|
|
100
102
|
Install SpinDB globally using your preferred package manager:
|
|
@@ -165,20 +167,56 @@ SpinDB runs databases as **native processes** with **isolated data directories**
|
|
|
165
167
|
- **Multi-version support** - Run PostgreSQL 14 and 18 side-by-side
|
|
166
168
|
- **Unified interface** - Manage PostgreSQL, MongoDB, and Redis the same way
|
|
167
169
|
|
|
168
|
-
### Comparison
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
|
173
|
-
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
|
|
|
177
|
-
|
|
|
178
|
-
|
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
170
|
+
### Comparison: Database GUI Tools
|
|
171
|
+
|
|
172
|
+
*For developers who prefer visual interfaces or use macOS-native tools.*
|
|
173
|
+
|
|
174
|
+
| Feature | SpinDB | DBngin | Postgres.app | Laragon |
|
|
175
|
+
|---------|--------|--------|--------------|---------|
|
|
176
|
+
| **Engines supported** | 16 | 3 (PG/MySQL/Redis) | 1 (PostgreSQL) | 4 (PG/MySQL/MariaDB/MongoDB) |
|
|
177
|
+
| CLI-first | β
| β GUI-only | β GUI-only | β οΈ Limited CLI |
|
|
178
|
+
| Multi-version support | β
| β
| β
| β
|
|
|
179
|
+
| Built-in backup/restore | β
| β
| β | β οΈ Manual |
|
|
180
|
+
| Clone databases | β
| β
| β | β |
|
|
181
|
+
| macOS | β
| β
| β
| β |
|
|
182
|
+
| Linux | β
| β | β | β |
|
|
183
|
+
| Windows | β
| β | β | β
|
|
|
184
|
+
| Free for commercial use | β | β
| β
| β
|
|
|
185
|
+
|
|
186
|
+
### Comparison: Docker & Containers
|
|
187
|
+
|
|
188
|
+
*For developers already using containerization.*
|
|
189
|
+
|
|
190
|
+
| Feature | SpinDB | Docker Desktop | Podman | OrbStack |
|
|
191
|
+
|---------|--------|----------------|--------|----------|
|
|
192
|
+
| **Engines supported** | 16 unified | Any (manual setup) | Any (manual setup) | Any (manual setup) |
|
|
193
|
+
| Daemon required | β | β
| β (rootless) | β
|
|
|
194
|
+
| Resource overhead | Native | VM + containers | VM + containers | VM + containers |
|
|
195
|
+
| Built-in backup/restore | β
| β Manual | β Manual | β Manual |
|
|
196
|
+
| Connection strings | β
Auto-generated | β Manual | β Manual | β Manual |
|
|
197
|
+
| Version switching | β
Instant | β οΈ Pull images | β οΈ Pull images | β οΈ Pull images |
|
|
198
|
+
| Database-specific CLI | β
Included | β Exec into container | β Exec into container | β Exec into container |
|
|
199
|
+
| Prod parity | β οΈ Native binaries | β
Exact images | β
Exact images | β
Exact images |
|
|
200
|
+
| Free for commercial use | β | β οΈ Paid for orgs | β
| β οΈ Paid tiers |
|
|
201
|
+
|
|
202
|
+
### Comparison: Package Managers
|
|
203
|
+
|
|
204
|
+
*For developers who "just install" databases system-wide.*
|
|
205
|
+
|
|
206
|
+
| Feature | SpinDB | Homebrew | apt/winget | asdf-vm |
|
|
207
|
+
|---------|--------|----------|------------|---------|
|
|
208
|
+
| **Engines supported** | 16 unified | Many (separate formulas) | Many (separate packages) | Many (plugins) |
|
|
209
|
+
| Multi-version side-by-side | β
| β οΈ Complex | β | β
|
|
|
210
|
+
| Isolated data directories | β
| β System-wide | β System-wide | β |
|
|
211
|
+
| Built-in backup/restore | β
| β | β | β |
|
|
212
|
+
| Unified CLI across engines | β
| β | β | β |
|
|
213
|
+
| No root/sudo required | β
| β
| β | β
|
|
|
214
|
+
| macOS | β
| β
| β | β
|
|
|
215
|
+
| Linux | β
| β
| β
| β
|
|
|
216
|
+
| Windows | β
| β | β
(winget) | β οΈ WSL |
|
|
217
|
+
| Free for commercial use | β | β
| β
| β
|
|
|
218
|
+
|
|
219
|
+
> **Note on licensing:** SpinDB requires a commercial license for business use. For personal projects, education, research, nonprofits, and government use, SpinDB is free. See [License](#license) for details.
|
|
182
220
|
|
|
183
221
|
---
|
|
184
222
|
|
|
@@ -241,6 +279,7 @@ spindb create mydb --engine mongodb # MongoDB
|
|
|
241
279
|
spindb create mydb --engine mysql --db-version 8.0 # MySQL 8.0
|
|
242
280
|
spindb create mydb --port 5433 # Custom port
|
|
243
281
|
spindb create mydb --start --connect # Create, start, and connect
|
|
282
|
+
spindb create mydb --force # Overwrite existing container
|
|
244
283
|
|
|
245
284
|
# Start/stop databases
|
|
246
285
|
spindb start mydb
|
|
@@ -290,14 +329,63 @@ spindb backup mydb --format custom # Custom binary format (PostgreS
|
|
|
290
329
|
spindb restore mydb backup.dump
|
|
291
330
|
spindb restore mydb backup.sql --database prod_copy
|
|
292
331
|
|
|
293
|
-
# Pull from remote database
|
|
294
|
-
spindb restore mydb --from-url "postgresql://user:pass@prod-host/db"
|
|
295
|
-
|
|
296
332
|
# Clone existing database
|
|
297
333
|
spindb create prod-copy --from ./prod-backup.dump
|
|
298
334
|
spindb create staging --from "postgresql://user:pass@prod:5432/production"
|
|
299
335
|
```
|
|
300
336
|
|
|
337
|
+
### Pull from Remote Database
|
|
338
|
+
|
|
339
|
+
Sync production data to your local database while automatically backing up your original data:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
# Pull production data (backs up original, replaces with remote)
|
|
343
|
+
spindb pull mydb --from "postgresql://user:pass@prod-host/db"
|
|
344
|
+
|
|
345
|
+
# Read URL from environment variable (keeps credentials out of shell history)
|
|
346
|
+
spindb pull mydb --from-env CLONE_FROM_DATABASE_URL
|
|
347
|
+
|
|
348
|
+
# Clone mode: pull to new database (original untouched)
|
|
349
|
+
spindb pull mydb --from-env PROD_URL --as mydb_prod
|
|
350
|
+
|
|
351
|
+
# Preview what will happen
|
|
352
|
+
spindb pull mydb --from-env PROD_URL --dry-run
|
|
353
|
+
|
|
354
|
+
# Run post-pull script (e.g., sync local credentials)
|
|
355
|
+
spindb pull mydb --from-env PROD_URL --post-script ./sync-credentials.ts
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Export to Docker
|
|
359
|
+
|
|
360
|
+
Generate a Docker-ready package from any SpinDB container:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Export to Docker (generates Dockerfile, docker-compose.yml, etc.)
|
|
364
|
+
spindb export docker mydb
|
|
365
|
+
|
|
366
|
+
# Custom output directory
|
|
367
|
+
spindb export docker mydb -o ./deploy
|
|
368
|
+
|
|
369
|
+
# Override port (default: engine's standard port, e.g., 5432 for PostgreSQL)
|
|
370
|
+
spindb export docker mydb -p 5433
|
|
371
|
+
|
|
372
|
+
# Skip database backup or TLS certificates
|
|
373
|
+
spindb export docker mydb --no-data
|
|
374
|
+
spindb export docker mydb --no-tls
|
|
375
|
+
|
|
376
|
+
# JSON output for scripting
|
|
377
|
+
spindb export docker mydb --json --force
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Generated files:
|
|
381
|
+
- `Dockerfile` - Ubuntu 22.04 + Node.js 22 + SpinDB
|
|
382
|
+
- `docker-compose.yml` - Container orchestration
|
|
383
|
+
- `.env` - Auto-generated credentials
|
|
384
|
+
- `certs/` - TLS certificates (self-signed)
|
|
385
|
+
- `data/` - Database backup
|
|
386
|
+
- `entrypoint.sh` - Startup script
|
|
387
|
+
- `README.md` - Instructions
|
|
388
|
+
|
|
301
389
|
### Container Management
|
|
302
390
|
|
|
303
391
|
```bash
|
|
@@ -440,8 +528,6 @@ Databases run as **native processes**, and **data persists across restarts**. Wh
|
|
|
440
528
|
|
|
441
529
|
## Engine-Specific Details
|
|
442
530
|
|
|
443
|
-
Each database engine has unique features and behaviors. See full documentation in [ENGINES.md](ENGINES.md).
|
|
444
|
-
|
|
445
531
|
### PostgreSQL π
|
|
446
532
|
|
|
447
533
|
```bash
|
package/cli/commands/create.ts
CHANGED
|
@@ -37,10 +37,17 @@ async function createSqliteContainer(
|
|
|
37
37
|
path?: string
|
|
38
38
|
from?: string | null
|
|
39
39
|
connect?: boolean
|
|
40
|
+
force?: boolean
|
|
40
41
|
json?: boolean
|
|
41
42
|
},
|
|
42
43
|
): Promise<void> {
|
|
43
|
-
const {
|
|
44
|
+
const {
|
|
45
|
+
path: filePath,
|
|
46
|
+
from: restoreLocation,
|
|
47
|
+
connect,
|
|
48
|
+
force,
|
|
49
|
+
json,
|
|
50
|
+
} = options
|
|
44
51
|
|
|
45
52
|
// Check dependencies
|
|
46
53
|
const depsSpinner = json ? null : createSpinner('Checking required tools...')
|
|
@@ -70,17 +77,26 @@ async function createSqliteContainer(
|
|
|
70
77
|
|
|
71
78
|
// Check if container already exists
|
|
72
79
|
if (await containerManager.exists(containerName)) {
|
|
73
|
-
if (
|
|
80
|
+
if (force) {
|
|
81
|
+
// Delete existing container with force
|
|
82
|
+
if (!json) {
|
|
83
|
+
console.log(
|
|
84
|
+
chalk.yellow(` Removing existing container "${containerName}"...`),
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
await containerManager.delete(containerName, { force: true })
|
|
88
|
+
} else if (json) {
|
|
74
89
|
return exitWithError({
|
|
75
|
-
message: `Container "${containerName}" already exists
|
|
90
|
+
message: `Container "${containerName}" already exists. Use --force to overwrite.`,
|
|
76
91
|
json: true,
|
|
77
92
|
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
} else {
|
|
94
|
+
while (await containerManager.exists(containerName)) {
|
|
95
|
+
console.log(
|
|
96
|
+
chalk.yellow(` Container "${containerName}" already exists.`),
|
|
97
|
+
)
|
|
98
|
+
containerName = await promptContainerName()
|
|
99
|
+
}
|
|
84
100
|
}
|
|
85
101
|
}
|
|
86
102
|
|
|
@@ -190,10 +206,17 @@ async function createDuckDBContainer(
|
|
|
190
206
|
path?: string
|
|
191
207
|
from?: string | null
|
|
192
208
|
connect?: boolean
|
|
209
|
+
force?: boolean
|
|
193
210
|
json?: boolean
|
|
194
211
|
},
|
|
195
212
|
): Promise<void> {
|
|
196
|
-
const {
|
|
213
|
+
const {
|
|
214
|
+
path: filePath,
|
|
215
|
+
from: restoreLocation,
|
|
216
|
+
connect,
|
|
217
|
+
force,
|
|
218
|
+
json,
|
|
219
|
+
} = options
|
|
197
220
|
|
|
198
221
|
// Check dependencies
|
|
199
222
|
const depsSpinner = json ? null : createSpinner('Checking required tools...')
|
|
@@ -223,17 +246,26 @@ async function createDuckDBContainer(
|
|
|
223
246
|
|
|
224
247
|
// Check if container already exists
|
|
225
248
|
if (await containerManager.exists(containerName)) {
|
|
226
|
-
if (
|
|
249
|
+
if (force) {
|
|
250
|
+
// Delete existing container with force
|
|
251
|
+
if (!json) {
|
|
252
|
+
console.log(
|
|
253
|
+
chalk.yellow(` Removing existing container "${containerName}"...`),
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
await containerManager.delete(containerName, { force: true })
|
|
257
|
+
} else if (json) {
|
|
227
258
|
return exitWithError({
|
|
228
|
-
message: `Container "${containerName}" already exists
|
|
259
|
+
message: `Container "${containerName}" already exists. Use --force to overwrite.`,
|
|
229
260
|
json: true,
|
|
230
261
|
})
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
262
|
+
} else {
|
|
263
|
+
while (await containerManager.exists(containerName)) {
|
|
264
|
+
console.log(
|
|
265
|
+
chalk.yellow(` Container "${containerName}" already exists.`),
|
|
266
|
+
)
|
|
267
|
+
containerName = await promptContainerName()
|
|
268
|
+
}
|
|
237
269
|
}
|
|
238
270
|
}
|
|
239
271
|
|
|
@@ -404,6 +436,10 @@ export const createCommand = new Command('create')
|
|
|
404
436
|
'--max-connections <number>',
|
|
405
437
|
'Maximum number of database connections (default: 200)',
|
|
406
438
|
)
|
|
439
|
+
.option(
|
|
440
|
+
'-f, --force',
|
|
441
|
+
'Overwrite existing container without prompting (deletes existing data)',
|
|
442
|
+
)
|
|
407
443
|
.option('--start', 'Start the container after creation (skip prompt)')
|
|
408
444
|
.option('--no-start', 'Do not start the container after creation')
|
|
409
445
|
.option('--connect', 'Open a shell connection after creation')
|
|
@@ -422,6 +458,7 @@ export const createCommand = new Command('create')
|
|
|
422
458
|
port?: string
|
|
423
459
|
path?: string
|
|
424
460
|
maxConnections?: string
|
|
461
|
+
force?: boolean
|
|
425
462
|
start?: boolean
|
|
426
463
|
connect?: boolean
|
|
427
464
|
from?: string
|
|
@@ -541,6 +578,7 @@ export const createCommand = new Command('create')
|
|
|
541
578
|
path: options.path,
|
|
542
579
|
from: restoreLocation,
|
|
543
580
|
connect: options.connect,
|
|
581
|
+
force: options.force,
|
|
544
582
|
json: options.json,
|
|
545
583
|
})
|
|
546
584
|
return
|
|
@@ -552,6 +590,7 @@ export const createCommand = new Command('create')
|
|
|
552
590
|
path: options.path,
|
|
553
591
|
from: restoreLocation,
|
|
554
592
|
connect: options.connect,
|
|
593
|
+
force: options.force,
|
|
555
594
|
json: options.json,
|
|
556
595
|
})
|
|
557
596
|
return
|
|
@@ -733,17 +772,44 @@ export const createCommand = new Command('create')
|
|
|
733
772
|
}
|
|
734
773
|
|
|
735
774
|
if (await containerManager.exists(containerName)) {
|
|
736
|
-
if (options.
|
|
775
|
+
if (options.force) {
|
|
776
|
+
// Stop the container if it's running, then delete it
|
|
777
|
+
const existingConfig =
|
|
778
|
+
await containerManager.getConfig(containerName)
|
|
779
|
+
if (existingConfig?.status === 'running') {
|
|
780
|
+
if (!options.json) {
|
|
781
|
+
console.log(
|
|
782
|
+
chalk.yellow(
|
|
783
|
+
` Stopping existing container "${containerName}"...`,
|
|
784
|
+
),
|
|
785
|
+
)
|
|
786
|
+
}
|
|
787
|
+
try {
|
|
788
|
+
await dbEngine.stop(existingConfig)
|
|
789
|
+
} catch {
|
|
790
|
+
// Ignore stop errors - container may already be stopped
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
if (!options.json) {
|
|
794
|
+
console.log(
|
|
795
|
+
chalk.yellow(
|
|
796
|
+
` Removing existing container "${containerName}"...`,
|
|
797
|
+
),
|
|
798
|
+
)
|
|
799
|
+
}
|
|
800
|
+
await containerManager.delete(containerName, { force: true })
|
|
801
|
+
} else if (options.json) {
|
|
737
802
|
return exitWithError({
|
|
738
|
-
message: `Container "${containerName}" already exists
|
|
803
|
+
message: `Container "${containerName}" already exists. Use --force to overwrite.`,
|
|
739
804
|
json: true,
|
|
740
805
|
})
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
806
|
+
} else {
|
|
807
|
+
while (await containerManager.exists(containerName)) {
|
|
808
|
+
console.log(
|
|
809
|
+
chalk.yellow(` Container "${containerName}" already exists.`),
|
|
810
|
+
)
|
|
811
|
+
containerName = await promptContainerName()
|
|
812
|
+
}
|
|
747
813
|
}
|
|
748
814
|
}
|
|
749
815
|
|