spindb 0.19.4 → 0.20.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 +24 -25
- package/cli/commands/backup.ts +42 -64
- package/cli/commands/create.ts +30 -13
- package/cli/commands/deps.ts +2 -1
- package/cli/commands/engines.ts +4 -4
- package/cli/commands/menu/backup-handlers.ts +18 -85
- package/cli/commands/restore.ts +95 -49
- package/cli/ui/prompts.ts +33 -37
- package/config/backup-formats.ts +204 -133
- package/config/engine-defaults.ts +29 -41
- package/config/paths.ts +6 -2
- package/core/backup-restore.ts +2 -2
- package/core/base-binary-manager.ts +515 -0
- package/core/base-document-binary-manager.ts +504 -0
- package/core/base-embedded-binary-manager.ts +538 -0
- package/core/base-server-binary-manager.ts +507 -0
- package/core/container-manager.ts +20 -0
- package/core/fs-error-utils.ts +79 -0
- package/core/homebrew-version-manager.ts +9 -8
- package/core/hostdb-client.ts +71 -35
- package/core/hostdb-metadata.ts +8 -7
- package/core/hostdb-releases-factory.ts +237 -0
- package/core/platform-service.ts +31 -14
- package/core/start-with-retry.ts +1 -11
- package/core/version-utils.ts +27 -0
- package/engines/clickhouse/backup.ts +15 -1
- package/engines/clickhouse/binary-manager.ts +63 -292
- package/engines/clickhouse/binary-urls.ts +19 -47
- package/engines/clickhouse/hostdb-releases.ts +15 -187
- package/engines/clickhouse/index.ts +52 -14
- package/engines/clickhouse/restore.ts +54 -11
- package/engines/clickhouse/version-maps.ts +6 -3
- package/engines/duckdb/binary-manager.ts +22 -450
- package/engines/duckdb/binary-urls.ts +11 -98
- package/engines/duckdb/hostdb-releases.ts +23 -0
- package/engines/duckdb/index.ts +107 -44
- package/engines/duckdb/version-maps.ts +19 -6
- package/engines/mariadb/backup.ts +7 -2
- package/engines/mariadb/binary-manager.ts +24 -355
- package/engines/mariadb/binary-urls.ts +31 -50
- package/engines/mariadb/hostdb-releases.ts +14 -177
- package/engines/mariadb/index.ts +20 -18
- package/engines/mariadb/restore.ts +2 -2
- package/engines/mariadb/version-maps.ts +4 -3
- package/engines/mongodb/backup.ts +9 -8
- package/engines/mongodb/binary-manager.ts +26 -413
- package/engines/mongodb/binary-urls.ts +23 -31
- package/engines/mongodb/hostdb-releases.ts +3 -93
- package/engines/mongodb/index.ts +15 -13
- package/engines/mongodb/restore.ts +40 -9
- package/engines/mongodb/version-maps.ts +4 -2
- package/engines/mysql/binary-detection.ts +7 -6
- package/engines/mysql/binary-manager.ts +21 -374
- package/engines/mysql/binary-urls.ts +20 -38
- package/engines/mysql/hostdb-releases.ts +26 -184
- package/engines/mysql/index.ts +21 -16
- package/engines/mysql/version-maps.ts +7 -4
- package/engines/postgresql/binary-manager.ts +90 -576
- package/engines/postgresql/binary-urls.ts +31 -67
- package/engines/postgresql/hostdb-releases.ts +14 -175
- package/engines/postgresql/index.ts +33 -79
- package/engines/postgresql/restore.ts +24 -18
- package/engines/postgresql/version-maps.ts +0 -1
- package/engines/redis/backup.ts +5 -5
- package/engines/redis/binary-manager.ts +23 -450
- package/engines/redis/binary-urls.ts +25 -41
- package/engines/redis/hostdb-releases.ts +14 -168
- package/engines/redis/index.ts +20 -14
- package/engines/redis/restore.ts +51 -21
- package/engines/redis/version-maps.ts +5 -4
- package/engines/sqlite/binary-manager.ts +28 -455
- package/engines/sqlite/binary-urls.ts +11 -102
- package/engines/sqlite/hostdb-releases.ts +23 -0
- package/engines/sqlite/index.ts +60 -28
- package/engines/sqlite/version-maps.ts +4 -3
- package/engines/valkey/backup.ts +5 -5
- package/engines/valkey/binary-manager.ts +24 -452
- package/engines/valkey/binary-urls.ts +20 -41
- package/engines/valkey/hostdb-releases.ts +14 -173
- package/engines/valkey/index.ts +20 -14
- package/engines/valkey/restore.ts +51 -22
- package/engines/valkey/version-maps.ts +4 -3
- package/package.json +1 -1
- package/types/index.ts +89 -8
- package/core/binary-manager.ts +0 -799
- package/engines/postgresql/edb-binary-urls.ts +0 -161
package/README.md
CHANGED
|
@@ -269,8 +269,8 @@ psql $(spindb url mydb)
|
|
|
269
269
|
spindb backup mydb # Auto-generated filename
|
|
270
270
|
spindb backup mydb --name production-backup # Custom name
|
|
271
271
|
spindb backup mydb --output ./backups/ # Custom directory
|
|
272
|
-
spindb backup mydb --format sql # SQL text format
|
|
273
|
-
spindb backup mydb --format
|
|
272
|
+
spindb backup mydb --format sql # SQL text format (PostgreSQL)
|
|
273
|
+
spindb backup mydb --format custom # Custom binary format (PostgreSQL)
|
|
274
274
|
|
|
275
275
|
# Restore from backups
|
|
276
276
|
spindb restore mydb backup.dump
|
|
@@ -430,7 +430,7 @@ spindb create modern --engine postgresql --db-version 18
|
|
|
430
430
|
|
|
431
431
|
# Backup formats
|
|
432
432
|
spindb backup myapp --format sql # Plain SQL (.sql)
|
|
433
|
-
spindb backup myapp --format
|
|
433
|
+
spindb backup myapp --format custom # Binary custom format (.dump)
|
|
434
434
|
```
|
|
435
435
|
|
|
436
436
|
**Versions:** 15, 16, 17, 18
|
|
@@ -563,12 +563,12 @@ Every engine supports backup and restore with engine-specific formats:
|
|
|
563
563
|
|
|
564
564
|
| Format | Extension | Tool | Use Case |
|
|
565
565
|
|--------|-----------|------|----------|
|
|
566
|
-
|
|
|
567
|
-
|
|
|
566
|
+
| sql | `.sql` | pg_dump | Human-readable, portable |
|
|
567
|
+
| custom | `.dump` | pg_dump -Fc | Compressed, faster restore |
|
|
568
568
|
|
|
569
569
|
```bash
|
|
570
|
-
spindb backup mydb --sql
|
|
571
|
-
spindb backup mydb --
|
|
570
|
+
spindb backup mydb --format sql # Plain SQL
|
|
571
|
+
spindb backup mydb --format custom # Binary custom format
|
|
572
572
|
spindb restore mydb backup.dump
|
|
573
573
|
```
|
|
574
574
|
|
|
@@ -576,23 +576,23 @@ spindb restore mydb backup.dump
|
|
|
576
576
|
|
|
577
577
|
| Format | Extension | Tool | Use Case |
|
|
578
578
|
|--------|-----------|------|----------|
|
|
579
|
-
|
|
|
580
|
-
|
|
|
579
|
+
| sql | `.sql` | mysqldump / mariadb-dump | Human-readable |
|
|
580
|
+
| compressed | `.sql.gz` | mysqldump + gzip | Smaller file size |
|
|
581
581
|
|
|
582
582
|
```bash
|
|
583
|
-
spindb backup mydb --sql
|
|
584
|
-
spindb backup mydb --
|
|
583
|
+
spindb backup mydb --format sql # Plain SQL
|
|
584
|
+
spindb backup mydb --format compressed # Compressed SQL
|
|
585
585
|
```
|
|
586
586
|
|
|
587
587
|
### MongoDB
|
|
588
588
|
|
|
589
589
|
| Format | Extension | Tool | Use Case |
|
|
590
590
|
|--------|-----------|------|----------|
|
|
591
|
-
|
|
|
592
|
-
|
|
|
591
|
+
| bson | _(directory)_ | mongodump | Binary, preserves all types |
|
|
592
|
+
| archive | `.archive` | mongodump --archive | Single compressed file |
|
|
593
593
|
|
|
594
594
|
```bash
|
|
595
|
-
spindb backup mydb
|
|
595
|
+
spindb backup mydb --format bson # BSON directory
|
|
596
596
|
spindb backup mydb --format archive # Single .archive file
|
|
597
597
|
```
|
|
598
598
|
|
|
@@ -600,12 +600,12 @@ spindb backup mydb --format archive # Single .archive file
|
|
|
600
600
|
|
|
601
601
|
| Format | Extension | Tool | Use Case |
|
|
602
602
|
|--------|-----------|------|----------|
|
|
603
|
-
|
|
|
604
|
-
|
|
|
603
|
+
| rdb | `.rdb` | BGSAVE | Binary snapshot, requires stop/start |
|
|
604
|
+
| text | `.redis` / `.valkey` | Custom | Human-readable commands |
|
|
605
605
|
|
|
606
606
|
```bash
|
|
607
|
-
spindb backup mydb --
|
|
608
|
-
spindb backup mydb --
|
|
607
|
+
spindb backup mydb --format rdb # RDB snapshot (default)
|
|
608
|
+
spindb backup mydb --format text # Text commands
|
|
609
609
|
|
|
610
610
|
# Restore with merge or replace strategy
|
|
611
611
|
spindb restore mydb backup.redis # Prompts: Replace all / Merge
|
|
@@ -615,23 +615,22 @@ spindb restore mydb backup.redis # Prompts: Replace all / Merge
|
|
|
615
615
|
|
|
616
616
|
| Format | Extension | Tool | Use Case |
|
|
617
617
|
|--------|-----------|------|----------|
|
|
618
|
-
|
|
|
619
|
-
|
|
|
618
|
+
| sql | `.sql` | .dump / duckdb | Human-readable |
|
|
619
|
+
| binary | `.sqlite` / `.duckdb` | File copy | Exact database copy |
|
|
620
620
|
|
|
621
621
|
```bash
|
|
622
|
-
spindb backup mydb --sql
|
|
623
|
-
spindb backup mydb --
|
|
622
|
+
spindb backup mydb --format sql # SQL dump
|
|
623
|
+
spindb backup mydb --format binary # Binary copy (default)
|
|
624
624
|
```
|
|
625
625
|
|
|
626
626
|
### ClickHouse
|
|
627
627
|
|
|
628
628
|
| Format | Extension | Tool | Use Case |
|
|
629
629
|
|--------|-----------|------|----------|
|
|
630
|
-
|
|
|
631
|
-
| Native | `.clickhouse` | clickhouse-backup | Native format (future) |
|
|
630
|
+
| sql | `.sql` | clickhouse-client | Plain SQL dump |
|
|
632
631
|
|
|
633
632
|
```bash
|
|
634
|
-
spindb backup mydb --sql
|
|
633
|
+
spindb backup mydb --format sql # SQL dump (only format)
|
|
635
634
|
```
|
|
636
635
|
|
|
637
636
|
---
|
package/cli/commands/backup.ts
CHANGED
|
@@ -14,6 +14,15 @@ import {
|
|
|
14
14
|
import { createSpinner } from '../ui/spinner'
|
|
15
15
|
import { uiSuccess, uiError, uiWarning, formatBytes } from '../ui/theme'
|
|
16
16
|
import { getMissingDependencies } from '../../core/dependency-manager'
|
|
17
|
+
import { isFileBasedEngine } from '../../types'
|
|
18
|
+
import {
|
|
19
|
+
getBackupExtension,
|
|
20
|
+
getBackupSpinnerLabel,
|
|
21
|
+
getDefaultFormat,
|
|
22
|
+
isValidFormat,
|
|
23
|
+
getValidFormats,
|
|
24
|
+
} from '../../config/backup-formats'
|
|
25
|
+
import type { BackupFormatType } from '../../types'
|
|
17
26
|
|
|
18
27
|
function generateTimestamp(): string {
|
|
19
28
|
const now = new Date()
|
|
@@ -28,42 +37,6 @@ function generateDefaultFilename(
|
|
|
28
37
|
return `${containerName}-${database}-backup-${timestamp}`
|
|
29
38
|
}
|
|
30
39
|
|
|
31
|
-
function getExtension(format: 'sql' | 'dump', engine: string): string {
|
|
32
|
-
// Handle 'sql' format (human-readable option)
|
|
33
|
-
if (format === 'sql') {
|
|
34
|
-
// MongoDB uses BSON directory format for 'sql' choice
|
|
35
|
-
return engine === 'mongodb' ? '' : '.sql'
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Handle 'dump' format (binary/compressed option)
|
|
39
|
-
switch (engine) {
|
|
40
|
-
case 'mysql':
|
|
41
|
-
return '.sql.gz'
|
|
42
|
-
case 'sqlite':
|
|
43
|
-
return '.sqlite'
|
|
44
|
-
case 'mongodb':
|
|
45
|
-
return '.archive'
|
|
46
|
-
case 'redis':
|
|
47
|
-
return '.rdb'
|
|
48
|
-
case 'postgresql':
|
|
49
|
-
default:
|
|
50
|
-
return '.dump'
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function getFormatDescription(format: 'sql' | 'dump', engine: string): string {
|
|
55
|
-
if (engine === 'redis') {
|
|
56
|
-
return 'RDB snapshot'
|
|
57
|
-
}
|
|
58
|
-
if (engine === 'mongodb') {
|
|
59
|
-
return format === 'sql' ? 'BSON directory' : 'archive'
|
|
60
|
-
}
|
|
61
|
-
if (engine === 'sqlite') {
|
|
62
|
-
return format === 'sql' ? 'SQL' : 'binary'
|
|
63
|
-
}
|
|
64
|
-
return format === 'sql' ? 'SQL' : 'dump'
|
|
65
|
-
}
|
|
66
|
-
|
|
67
40
|
export const backupCommand = new Command('backup')
|
|
68
41
|
.description('Create a backup of a database')
|
|
69
42
|
.argument('[container]', 'Container name')
|
|
@@ -73,9 +46,7 @@ export const backupCommand = new Command('backup')
|
|
|
73
46
|
'-o, --output <path>',
|
|
74
47
|
'Output directory (defaults to current directory)',
|
|
75
48
|
)
|
|
76
|
-
.option('--format <format>', '
|
|
77
|
-
.option('--sql', 'Output as plain SQL (shorthand for --format sql)')
|
|
78
|
-
.option('--dump', 'Output as dump format (shorthand for --format dump)')
|
|
49
|
+
.option('--format <format>', 'Backup format (engine-specific, e.g., sql, custom, rdb, binary)')
|
|
79
50
|
.option('-j, --json', 'Output result as JSON')
|
|
80
51
|
.action(
|
|
81
52
|
async (
|
|
@@ -85,8 +56,6 @@ export const backupCommand = new Command('backup')
|
|
|
85
56
|
name?: string
|
|
86
57
|
output?: string
|
|
87
58
|
format?: string
|
|
88
|
-
sql?: boolean
|
|
89
|
-
dump?: boolean
|
|
90
59
|
json?: boolean
|
|
91
60
|
},
|
|
92
61
|
) => {
|
|
@@ -130,16 +99,19 @@ export const backupCommand = new Command('backup')
|
|
|
130
99
|
|
|
131
100
|
const { engine: engineName } = config
|
|
132
101
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
102
|
+
// File-based engines (SQLite, DuckDB) don't need to be "running"
|
|
103
|
+
if (!isFileBasedEngine(engineName)) {
|
|
104
|
+
const running = await processManager.isRunning(containerName, {
|
|
105
|
+
engine: engineName,
|
|
106
|
+
})
|
|
107
|
+
if (!running) {
|
|
108
|
+
console.error(
|
|
109
|
+
uiError(
|
|
110
|
+
`Container "${containerName}" is not running. Start it first.`,
|
|
111
|
+
),
|
|
112
|
+
)
|
|
113
|
+
process.exit(1)
|
|
114
|
+
}
|
|
143
115
|
}
|
|
144
116
|
|
|
145
117
|
const engine = getEngine(engineName)
|
|
@@ -193,20 +165,26 @@ export const backupCommand = new Command('backup')
|
|
|
193
165
|
}
|
|
194
166
|
}
|
|
195
167
|
|
|
196
|
-
let format:
|
|
168
|
+
let format: BackupFormatType = getDefaultFormat(engineName)
|
|
197
169
|
|
|
198
|
-
if (options.
|
|
199
|
-
format
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
170
|
+
if (options.format) {
|
|
171
|
+
if (!isValidFormat(engineName, options.format)) {
|
|
172
|
+
const validFormats = getValidFormats(engineName)
|
|
173
|
+
console.error(
|
|
174
|
+
uiError(
|
|
175
|
+
`Invalid format "${options.format}" for ${engineName}. ` +
|
|
176
|
+
`Valid formats: ${validFormats.join(', ')}`,
|
|
177
|
+
),
|
|
178
|
+
)
|
|
205
179
|
process.exit(1)
|
|
206
180
|
}
|
|
207
|
-
|
|
181
|
+
// Safe to cast: isValidFormat above guarantees the format is valid
|
|
182
|
+
format = options.format as BackupFormatType
|
|
208
183
|
} else if (!containerArg) {
|
|
209
|
-
|
|
184
|
+
const selectedFormat = await promptBackupFormat(engineName)
|
|
185
|
+
if (selectedFormat) {
|
|
186
|
+
format = selectedFormat
|
|
187
|
+
}
|
|
210
188
|
}
|
|
211
189
|
|
|
212
190
|
const defaultFilename = generateDefaultFilename(
|
|
@@ -219,13 +197,13 @@ export const backupCommand = new Command('backup')
|
|
|
219
197
|
filename = await promptBackupFilename(defaultFilename)
|
|
220
198
|
}
|
|
221
199
|
|
|
222
|
-
const extension =
|
|
200
|
+
const extension = getBackupExtension(engineName, format)
|
|
223
201
|
const outputDir = options.output || process.cwd()
|
|
224
202
|
const outputPath = join(outputDir, `${filename}${extension}`)
|
|
225
203
|
|
|
226
|
-
const
|
|
204
|
+
const spinnerLabel = getBackupSpinnerLabel(engineName, format)
|
|
227
205
|
const backupSpinner = createSpinner(
|
|
228
|
-
`Creating ${
|
|
206
|
+
`Creating ${spinnerLabel} backup of "${databaseName}"...`,
|
|
229
207
|
)
|
|
230
208
|
backupSpinner.start()
|
|
231
209
|
|
package/cli/commands/create.ts
CHANGED
|
@@ -444,23 +444,40 @@ export const createCommand = new Command('create')
|
|
|
444
444
|
database = answers.database
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
-
// Redis
|
|
447
|
+
// Redis/Valkey use numbered databases (0-15), default to "0"
|
|
448
448
|
// Other engines default to container name (with hyphens replaced by underscores for SQL compatibility)
|
|
449
|
-
if (engine === Engine.Redis) {
|
|
449
|
+
if (engine === Engine.Redis || engine === Engine.Valkey) {
|
|
450
450
|
database = database ?? '0'
|
|
451
|
+
// Validate Redis/Valkey database is a pure integer string 0-15
|
|
452
|
+
// Reject decimals ("1.5"), scientific notation ("1e2"), and trailing garbage ("5abc")
|
|
453
|
+
if (!/^[0-9]+$/.test(database)) {
|
|
454
|
+
console.error(
|
|
455
|
+
uiError(
|
|
456
|
+
'Redis/Valkey database must be an integer between 0 and 15',
|
|
457
|
+
),
|
|
458
|
+
)
|
|
459
|
+
process.exit(1)
|
|
460
|
+
}
|
|
461
|
+
const dbIndex = parseInt(database, 10)
|
|
462
|
+
if (dbIndex < 0 || dbIndex > 15) {
|
|
463
|
+
console.error(
|
|
464
|
+
uiError(
|
|
465
|
+
'Redis/Valkey database must be an integer between 0 and 15',
|
|
466
|
+
),
|
|
467
|
+
)
|
|
468
|
+
process.exit(1)
|
|
469
|
+
}
|
|
451
470
|
} else {
|
|
452
471
|
database = database ?? containerName.replace(/-/g, '_')
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
)
|
|
463
|
-
process.exit(1)
|
|
472
|
+
// Validate database name to prevent SQL injection
|
|
473
|
+
if (!isValidDatabaseName(database)) {
|
|
474
|
+
console.error(
|
|
475
|
+
uiError(
|
|
476
|
+
'Database name must start with a letter and contain only letters, numbers, and underscores',
|
|
477
|
+
),
|
|
478
|
+
)
|
|
479
|
+
process.exit(1)
|
|
480
|
+
}
|
|
464
481
|
}
|
|
465
482
|
|
|
466
483
|
console.log(header('Creating Database Container'))
|
package/cli/commands/deps.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getCurrentPlatform,
|
|
14
14
|
type DependencyStatus,
|
|
15
15
|
} from '../../core/dependency-manager'
|
|
16
|
+
import { Platform } from '../../types'
|
|
16
17
|
import {
|
|
17
18
|
engineDependencies,
|
|
18
19
|
getEngineDependencies,
|
|
@@ -134,7 +135,7 @@ depsCommand
|
|
|
134
135
|
console.log()
|
|
135
136
|
|
|
136
137
|
const platform = getCurrentPlatform()
|
|
137
|
-
if (platform ===
|
|
138
|
+
if (platform === Platform.Darwin) {
|
|
138
139
|
console.log(chalk.gray(' macOS: Install Homebrew first:'))
|
|
139
140
|
console.log(
|
|
140
141
|
chalk.cyan(
|
package/cli/commands/engines.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { containerManager } from '../../core/container-manager'
|
|
|
10
10
|
import { processManager } from '../../core/process-manager'
|
|
11
11
|
import { configManager } from '../../core/config-manager'
|
|
12
12
|
import { getEngine } from '../../engines'
|
|
13
|
-
import {
|
|
13
|
+
import { postgresqlBinaryManager } from '../../engines/postgresql/binary-manager'
|
|
14
14
|
import { paths } from '../../config/paths'
|
|
15
15
|
import { platformService } from '../../core/platform-service'
|
|
16
16
|
import {
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
type InstalledRedisEngine,
|
|
42
42
|
type InstalledValkeyEngine,
|
|
43
43
|
} from '../helpers'
|
|
44
|
-
import { Engine } from '../../types'
|
|
44
|
+
import { Engine, Platform } from '../../types'
|
|
45
45
|
import {
|
|
46
46
|
loadEnginesJson,
|
|
47
47
|
type EngineConfig,
|
|
@@ -969,7 +969,7 @@ enginesCommand
|
|
|
969
969
|
|
|
970
970
|
// Show the path for reference
|
|
971
971
|
const { platform, arch } = platformService.getPlatformInfo()
|
|
972
|
-
const fullVersion =
|
|
972
|
+
const fullVersion = postgresqlBinaryManager.getFullVersion(version)
|
|
973
973
|
const binPath = paths.getBinaryPath({
|
|
974
974
|
engine: 'postgresql',
|
|
975
975
|
version: fullVersion,
|
|
@@ -1290,7 +1290,7 @@ enginesCommand
|
|
|
1290
1290
|
if (['clickhouse', 'ch'].includes(normalizedEngine)) {
|
|
1291
1291
|
// Check platform support
|
|
1292
1292
|
const { platform } = platformService.getPlatformInfo()
|
|
1293
|
-
if (platform ===
|
|
1293
|
+
if (platform === Platform.Win32) {
|
|
1294
1294
|
console.error(
|
|
1295
1295
|
uiError('ClickHouse is not supported on Windows via hostdb'),
|
|
1296
1296
|
)
|
|
@@ -10,8 +10,6 @@ import { platformService } from '../../../core/platform-service'
|
|
|
10
10
|
import { portManager } from '../../../core/port-manager'
|
|
11
11
|
import { getEngine } from '../../../engines'
|
|
12
12
|
import { defaults } from '../../../config/defaults'
|
|
13
|
-
import { getPostgresHomebrewPackage } from '../../../config/engine-defaults'
|
|
14
|
-
import { updatePostgresClientTools } from '../../../engines/postgresql/binary-manager'
|
|
15
13
|
import {
|
|
16
14
|
getBackupExtension,
|
|
17
15
|
getBackupSpinnerLabel,
|
|
@@ -667,90 +665,25 @@ export async function handleRestore(): Promise<void> {
|
|
|
667
665
|
)
|
|
668
666
|
console.log()
|
|
669
667
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
try {
|
|
689
|
-
const updateSuccess = await updatePostgresClientTools()
|
|
690
|
-
|
|
691
|
-
if (updateSuccess) {
|
|
692
|
-
upgradeSpinner.succeed('PostgreSQL client tools upgraded')
|
|
693
|
-
console.log()
|
|
694
|
-
console.log(
|
|
695
|
-
uiSuccess(
|
|
696
|
-
'Please try the restore again with the updated tools.',
|
|
697
|
-
),
|
|
698
|
-
)
|
|
699
|
-
await pressEnterToContinue()
|
|
700
|
-
return
|
|
701
|
-
} else {
|
|
702
|
-
upgradeSpinner.fail('Upgrade failed')
|
|
703
|
-
console.log()
|
|
704
|
-
console.log(
|
|
705
|
-
uiError('Automatic upgrade failed. Please upgrade manually:'),
|
|
706
|
-
)
|
|
707
|
-
const pgPackage = getPostgresHomebrewPackage()
|
|
708
|
-
const latestMajor = pgPackage.split('@')[1]
|
|
709
|
-
console.log(
|
|
710
|
-
uiWarning(
|
|
711
|
-
` macOS: brew install ${pgPackage} && brew link --force ${pgPackage}`,
|
|
712
|
-
),
|
|
713
|
-
)
|
|
714
|
-
console.log(
|
|
715
|
-
chalk.gray(
|
|
716
|
-
` This installs PostgreSQL ${latestMajor} client tools: pg_restore, pg_dump, psql, and libpq`,
|
|
717
|
-
),
|
|
718
|
-
)
|
|
719
|
-
console.log(
|
|
720
|
-
uiWarning(
|
|
721
|
-
` Ubuntu/Debian: sudo apt update && sudo apt install postgresql-client-${latestMajor}`,
|
|
722
|
-
),
|
|
723
|
-
)
|
|
724
|
-
console.log(
|
|
725
|
-
chalk.gray(
|
|
726
|
-
` This installs PostgreSQL ${latestMajor} client tools: pg_restore, pg_dump, psql, and libpq`,
|
|
727
|
-
),
|
|
728
|
-
)
|
|
729
|
-
await pressEnterToContinue()
|
|
730
|
-
return
|
|
731
|
-
}
|
|
732
|
-
} catch {
|
|
733
|
-
upgradeSpinner.fail('Upgrade failed')
|
|
734
|
-
console.log(uiError('Failed to upgrade PostgreSQL client tools'))
|
|
735
|
-
console.log(
|
|
736
|
-
chalk.gray(
|
|
737
|
-
'Manual upgrade may be required for pg_restore, pg_dump, and psql',
|
|
738
|
-
),
|
|
739
|
-
)
|
|
740
|
-
await pressEnterToContinue()
|
|
741
|
-
return
|
|
742
|
-
}
|
|
743
|
-
} else {
|
|
744
|
-
console.log()
|
|
745
|
-
console.log(
|
|
746
|
-
uiWarning(
|
|
747
|
-
'Restore cancelled. Please upgrade PostgreSQL client tools manually and try again.',
|
|
748
|
-
),
|
|
749
|
-
)
|
|
750
|
-
await pressEnterToContinue()
|
|
751
|
-
return
|
|
752
|
-
}
|
|
668
|
+
console.log()
|
|
669
|
+
console.log(
|
|
670
|
+
uiWarning(
|
|
671
|
+
`To restore this backup, download PostgreSQL ${requiredVersion} binaries:`,
|
|
672
|
+
),
|
|
673
|
+
)
|
|
674
|
+
console.log(
|
|
675
|
+
chalk.cyan(` spindb engines download postgresql ${requiredVersion}`),
|
|
676
|
+
)
|
|
677
|
+
console.log()
|
|
678
|
+
console.log(
|
|
679
|
+
chalk.gray(
|
|
680
|
+
'Then create a new container with that version and try the restore again.',
|
|
681
|
+
),
|
|
682
|
+
)
|
|
683
|
+
await pressEnterToContinue()
|
|
684
|
+
return
|
|
753
685
|
} else {
|
|
686
|
+
// Other restore errors - show warnings
|
|
754
687
|
restoreSpinner.warn('Restore completed with warnings')
|
|
755
688
|
if (result.stderr) {
|
|
756
689
|
console.log()
|