spindb 0.9.1 → 0.9.2
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/cli/commands/backup.ts +13 -11
- package/cli/commands/clone.ts +14 -10
- package/cli/commands/config.ts +29 -29
- package/cli/commands/connect.ts +51 -39
- package/cli/commands/create.ts +59 -32
- package/cli/commands/delete.ts +8 -8
- package/cli/commands/deps.ts +17 -15
- package/cli/commands/doctor.ts +11 -11
- package/cli/commands/edit.ts +108 -55
- package/cli/commands/engines.ts +17 -15
- package/cli/commands/info.ts +8 -6
- package/cli/commands/list.ts +31 -16
- package/cli/commands/logs.ts +15 -11
- package/cli/commands/menu/backup-handlers.ts +52 -47
- package/cli/commands/menu/container-handlers.ts +120 -78
- package/cli/commands/menu/engine-handlers.ts +21 -11
- package/cli/commands/menu/index.ts +4 -4
- package/cli/commands/menu/shell-handlers.ts +34 -31
- package/cli/commands/menu/sql-handlers.ts +22 -16
- package/cli/commands/menu/update-handlers.ts +19 -17
- package/cli/commands/restore.ts +22 -20
- package/cli/commands/run.ts +20 -18
- package/cli/commands/self-update.ts +5 -5
- package/cli/commands/start.ts +11 -9
- package/cli/commands/stop.ts +9 -9
- package/cli/commands/url.ts +12 -9
- package/cli/helpers.ts +9 -4
- package/cli/ui/prompts.ts +12 -5
- package/cli/ui/spinner.ts +4 -4
- package/cli/ui/theme.ts +4 -4
- package/core/binary-manager.ts +5 -1
- package/core/container-manager.ts +5 -5
- package/core/platform-service.ts +3 -3
- package/core/start-with-retry.ts +6 -6
- package/core/transaction-manager.ts +6 -6
- package/engines/mysql/index.ts +11 -11
- package/engines/mysql/restore.ts +4 -4
- package/engines/mysql/version-validator.ts +2 -2
- package/engines/postgresql/binary-manager.ts +17 -17
- package/engines/postgresql/index.ts +7 -2
- package/engines/postgresql/restore.ts +2 -2
- package/engines/postgresql/version-validator.ts +2 -2
- package/engines/sqlite/index.ts +21 -8
- package/package.json +1 -1
package/cli/commands/create.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
promptConfirm,
|
|
14
14
|
} from '../ui/prompts'
|
|
15
15
|
import { createSpinner } from '../ui/spinner'
|
|
16
|
-
import { header,
|
|
16
|
+
import { header, uiError, connectionBox } from '../ui/theme'
|
|
17
17
|
import { tmpdir } from 'os'
|
|
18
18
|
import { join } from 'path'
|
|
19
19
|
import { getMissingDependencies } from '../../core/dependency-manager'
|
|
@@ -21,9 +21,9 @@ import { platformService } from '../../core/platform-service'
|
|
|
21
21
|
import { startWithRetry } from '../../core/start-with-retry'
|
|
22
22
|
import { TransactionManager } from '../../core/transaction-manager'
|
|
23
23
|
import { isValidDatabaseName } from '../../core/error-handler'
|
|
24
|
+
import { resolve } from 'path'
|
|
24
25
|
import { Engine } from '../../types'
|
|
25
26
|
import type { BaseEngine } from '../../engines/base-engine'
|
|
26
|
-
import { resolve } from 'path'
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Simplified SQLite container creation flow
|
|
@@ -43,8 +43,13 @@ async function createSqliteContainer(
|
|
|
43
43
|
|
|
44
44
|
const missingDeps = await getMissingDependencies('sqlite')
|
|
45
45
|
if (missingDeps.length > 0) {
|
|
46
|
-
depsSpinner.warn(
|
|
47
|
-
|
|
46
|
+
depsSpinner.warn(
|
|
47
|
+
`Missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
|
|
48
|
+
)
|
|
49
|
+
const installed = await promptInstallDependencies(
|
|
50
|
+
missingDeps[0].binary,
|
|
51
|
+
'sqlite',
|
|
52
|
+
)
|
|
48
53
|
if (!installed) {
|
|
49
54
|
process.exit(1)
|
|
50
55
|
}
|
|
@@ -64,7 +69,7 @@ async function createSqliteContainer(
|
|
|
64
69
|
|
|
65
70
|
// Check if file already exists
|
|
66
71
|
if (existsSync(absolutePath)) {
|
|
67
|
-
console.error(
|
|
72
|
+
console.error(uiError(`File already exists: ${absolutePath}`))
|
|
68
73
|
process.exit(1)
|
|
69
74
|
}
|
|
70
75
|
|
|
@@ -75,9 +80,9 @@ async function createSqliteContainer(
|
|
|
75
80
|
// Initialize the SQLite database file and register in registry
|
|
76
81
|
await dbEngine.initDataDir(containerName, version, { path: absolutePath })
|
|
77
82
|
createSpinnerInstance.succeed('SQLite database created')
|
|
78
|
-
} catch (
|
|
83
|
+
} catch (error) {
|
|
79
84
|
createSpinnerInstance.fail('Failed to create SQLite database')
|
|
80
|
-
throw
|
|
85
|
+
throw error
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
// Handle --from restore
|
|
@@ -85,15 +90,17 @@ async function createSqliteContainer(
|
|
|
85
90
|
const config = await containerManager.getConfig(containerName)
|
|
86
91
|
if (config) {
|
|
87
92
|
const format = await dbEngine.detectBackupFormat(restoreLocation)
|
|
88
|
-
const restoreSpinner = createSpinner(
|
|
93
|
+
const restoreSpinner = createSpinner(
|
|
94
|
+
`Restoring from ${format.description}...`,
|
|
95
|
+
)
|
|
89
96
|
restoreSpinner.start()
|
|
90
97
|
|
|
91
98
|
try {
|
|
92
99
|
await dbEngine.restore(config, restoreLocation)
|
|
93
100
|
restoreSpinner.succeed('Backup restored successfully')
|
|
94
|
-
} catch (
|
|
101
|
+
} catch (error) {
|
|
95
102
|
restoreSpinner.fail('Failed to restore backup')
|
|
96
|
-
throw
|
|
103
|
+
throw error
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
}
|
|
@@ -146,7 +153,11 @@ function detectLocationType(location: string): {
|
|
|
146
153
|
if (existsSync(location)) {
|
|
147
154
|
// Check if it's a SQLite file (case-insensitive)
|
|
148
155
|
const lowerLocation = location.toLowerCase()
|
|
149
|
-
if (
|
|
156
|
+
if (
|
|
157
|
+
lowerLocation.endsWith('.sqlite') ||
|
|
158
|
+
lowerLocation.endsWith('.db') ||
|
|
159
|
+
lowerLocation.endsWith('.sqlite3')
|
|
160
|
+
) {
|
|
150
161
|
return { type: 'file', inferredEngine: Engine.SQLite }
|
|
151
162
|
}
|
|
152
163
|
return { type: 'file' }
|
|
@@ -158,7 +169,10 @@ function detectLocationType(location: string): {
|
|
|
158
169
|
export const createCommand = new Command('create')
|
|
159
170
|
.description('Create a new database container')
|
|
160
171
|
.argument('[name]', 'Container name')
|
|
161
|
-
.option(
|
|
172
|
+
.option(
|
|
173
|
+
'-e, --engine <engine>',
|
|
174
|
+
'Database engine (postgresql, mysql, sqlite)',
|
|
175
|
+
)
|
|
162
176
|
.option('-v, --version <version>', 'Database version')
|
|
163
177
|
.option('-d, --database <database>', 'Database name')
|
|
164
178
|
.option('-p, --port <port>', 'Port number')
|
|
@@ -207,7 +221,7 @@ export const createCommand = new Command('create')
|
|
|
207
221
|
const locationInfo = detectLocationType(options.from)
|
|
208
222
|
|
|
209
223
|
if (locationInfo.type === 'not_found') {
|
|
210
|
-
console.error(
|
|
224
|
+
console.error(uiError(`Location not found: ${options.from}`))
|
|
211
225
|
console.log(
|
|
212
226
|
chalk.gray(
|
|
213
227
|
' Provide a valid file path or connection string (postgresql://, mysql://)',
|
|
@@ -230,7 +244,7 @@ export const createCommand = new Command('create')
|
|
|
230
244
|
|
|
231
245
|
if (options.start === false) {
|
|
232
246
|
console.error(
|
|
233
|
-
|
|
247
|
+
uiError(
|
|
234
248
|
'Cannot use --no-start with --from (restore requires running container)',
|
|
235
249
|
),
|
|
236
250
|
)
|
|
@@ -257,7 +271,7 @@ export const createCommand = new Command('create')
|
|
|
257
271
|
// Validate database name to prevent SQL injection
|
|
258
272
|
if (!isValidDatabaseName(database)) {
|
|
259
273
|
console.error(
|
|
260
|
-
|
|
274
|
+
uiError(
|
|
261
275
|
'Database name must start with a letter and contain only letters, numbers, hyphens, and underscores',
|
|
262
276
|
),
|
|
263
277
|
)
|
|
@@ -282,13 +296,26 @@ export const createCommand = new Command('create')
|
|
|
282
296
|
// For server databases, validate --connect with --no-start
|
|
283
297
|
if (options.connect && options.start === false) {
|
|
284
298
|
console.error(
|
|
285
|
-
|
|
299
|
+
uiError(
|
|
286
300
|
'Cannot use --no-start with --connect (connection requires running container)',
|
|
287
301
|
),
|
|
288
302
|
)
|
|
289
303
|
process.exit(1)
|
|
290
304
|
}
|
|
291
305
|
|
|
306
|
+
// Validate --max-connections if provided
|
|
307
|
+
if (options.maxConnections) {
|
|
308
|
+
const parsed = parseInt(options.maxConnections, 10)
|
|
309
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
310
|
+
console.error(
|
|
311
|
+
uiError(
|
|
312
|
+
'Invalid --max-connections value: must be a positive integer',
|
|
313
|
+
),
|
|
314
|
+
)
|
|
315
|
+
process.exit(1)
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
292
319
|
const depsSpinner = createSpinner('Checking required tools...')
|
|
293
320
|
depsSpinner.start()
|
|
294
321
|
|
|
@@ -310,7 +337,7 @@ export const createCommand = new Command('create')
|
|
|
310
337
|
missingDeps = await getMissingDependencies(engine)
|
|
311
338
|
if (missingDeps.length > 0) {
|
|
312
339
|
console.error(
|
|
313
|
-
|
|
340
|
+
uiError(
|
|
314
341
|
`Still missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
|
|
315
342
|
),
|
|
316
343
|
)
|
|
@@ -399,9 +426,9 @@ export const createCommand = new Command('create')
|
|
|
399
426
|
})
|
|
400
427
|
|
|
401
428
|
createSpinnerInstance.succeed('Container created')
|
|
402
|
-
} catch (
|
|
429
|
+
} catch (error) {
|
|
403
430
|
createSpinnerInstance.fail('Failed to create container')
|
|
404
|
-
throw
|
|
431
|
+
throw error
|
|
405
432
|
}
|
|
406
433
|
|
|
407
434
|
const initSpinner = createSpinner('Initializing database cluster...')
|
|
@@ -415,10 +442,10 @@ export const createCommand = new Command('create')
|
|
|
415
442
|
: undefined,
|
|
416
443
|
})
|
|
417
444
|
initSpinner.succeed('Database cluster initialized')
|
|
418
|
-
} catch (
|
|
445
|
+
} catch (error) {
|
|
419
446
|
initSpinner.fail('Failed to initialize database cluster')
|
|
420
447
|
await tx.rollback()
|
|
421
|
-
throw
|
|
448
|
+
throw error
|
|
422
449
|
}
|
|
423
450
|
|
|
424
451
|
// --from requires start, --start forces start, --no-start skips, otherwise ask user
|
|
@@ -484,14 +511,14 @@ export const createCommand = new Command('create')
|
|
|
484
511
|
} else {
|
|
485
512
|
startSpinner.succeed(`${dbEngine.displayName} started`)
|
|
486
513
|
}
|
|
487
|
-
} catch (
|
|
514
|
+
} catch (error) {
|
|
488
515
|
if (!startSpinner.isSpinning) {
|
|
489
516
|
// Error was already handled above
|
|
490
517
|
} else {
|
|
491
518
|
startSpinner.fail(`Failed to start ${dbEngine.displayName}`)
|
|
492
519
|
}
|
|
493
520
|
await tx.rollback()
|
|
494
|
-
throw
|
|
521
|
+
throw error
|
|
495
522
|
}
|
|
496
523
|
|
|
497
524
|
const defaultDb = engineDefaults.superuser
|
|
@@ -504,10 +531,10 @@ export const createCommand = new Command('create')
|
|
|
504
531
|
try {
|
|
505
532
|
await dbEngine.createDatabase(config, database)
|
|
506
533
|
dbSpinner.succeed(`Database "${database}" created`)
|
|
507
|
-
} catch (
|
|
534
|
+
} catch (error) {
|
|
508
535
|
dbSpinner.fail(`Failed to create database "${database}"`)
|
|
509
536
|
await tx.rollback()
|
|
510
|
-
throw
|
|
537
|
+
throw error
|
|
511
538
|
}
|
|
512
539
|
}
|
|
513
540
|
}
|
|
@@ -538,8 +565,8 @@ export const createCommand = new Command('create')
|
|
|
538
565
|
dumpSpinner.succeed('Dump created from remote database')
|
|
539
566
|
backupPath = tempDumpPath
|
|
540
567
|
dumpSuccess = true
|
|
541
|
-
} catch (
|
|
542
|
-
const e =
|
|
568
|
+
} catch (error) {
|
|
569
|
+
const e = error as Error
|
|
543
570
|
dumpSpinner.fail('Failed to create dump')
|
|
544
571
|
|
|
545
572
|
if (
|
|
@@ -554,14 +581,14 @@ export const createCommand = new Command('create')
|
|
|
554
581
|
}
|
|
555
582
|
|
|
556
583
|
console.log()
|
|
557
|
-
console.error(
|
|
584
|
+
console.error(uiError('pg_dump error:'))
|
|
558
585
|
console.log(chalk.gray(` ${e.message}`))
|
|
559
586
|
process.exit(1)
|
|
560
587
|
}
|
|
561
588
|
}
|
|
562
589
|
|
|
563
590
|
if (!dumpSuccess) {
|
|
564
|
-
console.error(
|
|
591
|
+
console.error(uiError('Failed to create dump after retries'))
|
|
565
592
|
process.exit(1)
|
|
566
593
|
}
|
|
567
594
|
} else {
|
|
@@ -639,8 +666,8 @@ export const createCommand = new Command('create')
|
|
|
639
666
|
console.log()
|
|
640
667
|
}
|
|
641
668
|
}
|
|
642
|
-
} catch (
|
|
643
|
-
const e =
|
|
669
|
+
} catch (error) {
|
|
670
|
+
const e = error as Error
|
|
644
671
|
|
|
645
672
|
const missingToolPatterns = [
|
|
646
673
|
'pg_restore not found',
|
|
@@ -666,7 +693,7 @@ export const createCommand = new Command('create')
|
|
|
666
693
|
process.exit(1)
|
|
667
694
|
}
|
|
668
695
|
|
|
669
|
-
console.error(
|
|
696
|
+
console.error(uiError(e.message))
|
|
670
697
|
process.exit(1)
|
|
671
698
|
} finally {
|
|
672
699
|
if (tempDumpPath) {
|
package/cli/commands/delete.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { processManager } from '../../core/process-manager'
|
|
|
4
4
|
import { getEngine } from '../../engines'
|
|
5
5
|
import { promptContainerSelect, promptConfirm } from '../ui/prompts'
|
|
6
6
|
import { createSpinner } from '../ui/spinner'
|
|
7
|
-
import {
|
|
7
|
+
import { uiError, uiWarning } from '../ui/theme'
|
|
8
8
|
|
|
9
9
|
export const deleteCommand = new Command('delete')
|
|
10
10
|
.alias('rm')
|
|
@@ -24,7 +24,7 @@ export const deleteCommand = new Command('delete')
|
|
|
24
24
|
const containers = await containerManager.list()
|
|
25
25
|
|
|
26
26
|
if (containers.length === 0) {
|
|
27
|
-
console.log(
|
|
27
|
+
console.log(uiWarning('No containers found'))
|
|
28
28
|
return
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -38,7 +38,7 @@ export const deleteCommand = new Command('delete')
|
|
|
38
38
|
|
|
39
39
|
const config = await containerManager.getConfig(containerName)
|
|
40
40
|
if (!config) {
|
|
41
|
-
console.error(
|
|
41
|
+
console.error(uiError(`Container "${containerName}" not found`))
|
|
42
42
|
process.exit(1)
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -48,7 +48,7 @@ export const deleteCommand = new Command('delete')
|
|
|
48
48
|
false,
|
|
49
49
|
)
|
|
50
50
|
if (!confirmed) {
|
|
51
|
-
console.log(
|
|
51
|
+
console.log(uiWarning('Deletion cancelled'))
|
|
52
52
|
return
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -67,7 +67,7 @@ export const deleteCommand = new Command('delete')
|
|
|
67
67
|
stopSpinner.succeed(`Stopped "${containerName}"`)
|
|
68
68
|
} else {
|
|
69
69
|
console.error(
|
|
70
|
-
|
|
70
|
+
uiError(
|
|
71
71
|
`Container "${containerName}" is running. Stop it first or use --force`,
|
|
72
72
|
),
|
|
73
73
|
)
|
|
@@ -81,9 +81,9 @@ export const deleteCommand = new Command('delete')
|
|
|
81
81
|
await containerManager.delete(containerName, { force: true })
|
|
82
82
|
|
|
83
83
|
deleteSpinner.succeed(`Container "${containerName}" deleted`)
|
|
84
|
-
} catch (
|
|
85
|
-
const e =
|
|
86
|
-
console.error(
|
|
84
|
+
} catch (error) {
|
|
85
|
+
const e = error as Error
|
|
86
|
+
console.error(uiError(e.message))
|
|
87
87
|
process.exit(1)
|
|
88
88
|
}
|
|
89
89
|
},
|
package/cli/commands/deps.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander'
|
|
2
2
|
import chalk from 'chalk'
|
|
3
|
-
import { header,
|
|
3
|
+
import { header, uiSuccess, uiWarning, uiError } from '../ui/theme'
|
|
4
4
|
import { createSpinner } from '../ui/spinner'
|
|
5
5
|
import {
|
|
6
6
|
detectPackageManager,
|
|
@@ -84,7 +84,7 @@ depsCommand
|
|
|
84
84
|
// Check specific engine
|
|
85
85
|
const engineConfig = getEngineDependencies(options.engine)
|
|
86
86
|
if (!engineConfig) {
|
|
87
|
-
console.error(
|
|
87
|
+
console.error(uiError(`Unknown engine: ${options.engine}`))
|
|
88
88
|
console.log(
|
|
89
89
|
chalk.gray(
|
|
90
90
|
` Available engines: ${engineDependencies.map((e) => e.engine).join(', ')}`,
|
|
@@ -104,9 +104,9 @@ depsCommand
|
|
|
104
104
|
const total = statuses.length
|
|
105
105
|
console.log()
|
|
106
106
|
if (installed === total) {
|
|
107
|
-
console.log(
|
|
107
|
+
console.log(uiSuccess(`All ${total} dependencies installed`))
|
|
108
108
|
} else {
|
|
109
|
-
console.log(
|
|
109
|
+
console.log(uiWarning(`${installed}/${total} dependencies installed`))
|
|
110
110
|
console.log()
|
|
111
111
|
console.log(
|
|
112
112
|
chalk.gray(` Run: spindb deps install --engine ${options.engine}`),
|
|
@@ -132,7 +132,7 @@ depsCommand
|
|
|
132
132
|
const packageManager = await detectPackageManager()
|
|
133
133
|
|
|
134
134
|
if (!packageManager) {
|
|
135
|
-
console.log(
|
|
135
|
+
console.log(uiError('No supported package manager detected'))
|
|
136
136
|
console.log()
|
|
137
137
|
|
|
138
138
|
const platform = getCurrentPlatform()
|
|
@@ -161,7 +161,7 @@ depsCommand
|
|
|
161
161
|
const missing = await getAllMissingDependencies()
|
|
162
162
|
|
|
163
163
|
if (missing.length === 0) {
|
|
164
|
-
console.log(
|
|
164
|
+
console.log(uiSuccess('All dependencies are already installed'))
|
|
165
165
|
return
|
|
166
166
|
}
|
|
167
167
|
|
|
@@ -182,14 +182,14 @@ depsCommand
|
|
|
182
182
|
spinner.warn('Some dependencies failed to install')
|
|
183
183
|
console.log()
|
|
184
184
|
for (const f of failed) {
|
|
185
|
-
console.log(
|
|
185
|
+
console.log(uiError(` ${f.dependency.name}: ${f.error}`))
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
if (succeeded.length > 0) {
|
|
190
190
|
console.log()
|
|
191
191
|
console.log(
|
|
192
|
-
|
|
192
|
+
uiSuccess(
|
|
193
193
|
`Installed: ${succeeded.map((r) => r.dependency.name).join(', ')}`,
|
|
194
194
|
),
|
|
195
195
|
)
|
|
@@ -198,7 +198,7 @@ depsCommand
|
|
|
198
198
|
// Install dependencies for specific engine
|
|
199
199
|
const engineConfig = getEngineDependencies(options.engine)
|
|
200
200
|
if (!engineConfig) {
|
|
201
|
-
console.error(
|
|
201
|
+
console.error(uiError(`Unknown engine: ${options.engine}`))
|
|
202
202
|
console.log(
|
|
203
203
|
chalk.gray(
|
|
204
204
|
` Available engines: ${engineDependencies.map((e) => e.engine).join(', ')}`,
|
|
@@ -211,7 +211,9 @@ depsCommand
|
|
|
211
211
|
|
|
212
212
|
if (missing.length === 0) {
|
|
213
213
|
console.log(
|
|
214
|
-
|
|
214
|
+
uiSuccess(
|
|
215
|
+
`All ${engineConfig.displayName} dependencies are installed`,
|
|
216
|
+
),
|
|
215
217
|
)
|
|
216
218
|
return
|
|
217
219
|
}
|
|
@@ -241,7 +243,7 @@ depsCommand
|
|
|
241
243
|
spinner.warn('Some dependencies failed to install')
|
|
242
244
|
console.log()
|
|
243
245
|
for (const f of failed) {
|
|
244
|
-
console.log(
|
|
246
|
+
console.log(uiError(` ${f.dependency.name}: ${f.error}`))
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
// Show manual instructions
|
|
@@ -259,7 +261,7 @@ depsCommand
|
|
|
259
261
|
if (succeeded.length > 0) {
|
|
260
262
|
console.log()
|
|
261
263
|
console.log(
|
|
262
|
-
|
|
264
|
+
uiSuccess(
|
|
263
265
|
`Installed: ${succeeded.map((r) => r.dependency.name).join(', ')}`,
|
|
264
266
|
),
|
|
265
267
|
)
|
|
@@ -276,7 +278,7 @@ depsCommand
|
|
|
276
278
|
const missing = await getMissingDependencies('postgresql')
|
|
277
279
|
|
|
278
280
|
if (missing.length === 0) {
|
|
279
|
-
console.log(
|
|
281
|
+
console.log(uiSuccess('All PostgreSQL dependencies are installed'))
|
|
280
282
|
return
|
|
281
283
|
}
|
|
282
284
|
|
|
@@ -300,14 +302,14 @@ depsCommand
|
|
|
300
302
|
spinner.warn('Some dependencies failed to install')
|
|
301
303
|
console.log()
|
|
302
304
|
for (const f of failed) {
|
|
303
|
-
console.log(
|
|
305
|
+
console.log(uiError(` ${f.dependency.name}: ${f.error}`))
|
|
304
306
|
}
|
|
305
307
|
}
|
|
306
308
|
|
|
307
309
|
if (succeeded.length > 0) {
|
|
308
310
|
console.log()
|
|
309
311
|
console.log(
|
|
310
|
-
|
|
312
|
+
uiSuccess(
|
|
311
313
|
`Installed: ${succeeded.map((r) => r.dependency.name).join(', ')}`,
|
|
312
314
|
),
|
|
313
315
|
)
|
package/cli/commands/doctor.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { sqliteRegistry } from '../../engines/sqlite/registry'
|
|
|
18
18
|
import { paths } from '../../config/paths'
|
|
19
19
|
import { getSupportedEngines } from '../../config/engine-defaults'
|
|
20
20
|
import { checkEngineDependencies } from '../../core/dependency-manager'
|
|
21
|
-
import { header,
|
|
21
|
+
import { header, uiSuccess } from '../ui/theme'
|
|
22
22
|
import { Engine } from '../../types'
|
|
23
23
|
|
|
24
24
|
type HealthCheckResult = {
|
|
@@ -61,7 +61,7 @@ async function checkConfiguration(): Promise<HealthCheckResult> {
|
|
|
61
61
|
label: 'Refresh binary cache',
|
|
62
62
|
handler: async () => {
|
|
63
63
|
await configManager.refreshAllBinaries()
|
|
64
|
-
console.log(
|
|
64
|
+
console.log(uiSuccess('Binary cache refreshed'))
|
|
65
65
|
},
|
|
66
66
|
},
|
|
67
67
|
}
|
|
@@ -73,12 +73,12 @@ async function checkConfiguration(): Promise<HealthCheckResult> {
|
|
|
73
73
|
message: 'Configuration valid',
|
|
74
74
|
details: [`Binary tools cached: ${binaryCount}`],
|
|
75
75
|
}
|
|
76
|
-
} catch (
|
|
76
|
+
} catch (error) {
|
|
77
77
|
return {
|
|
78
78
|
name: 'Configuration',
|
|
79
79
|
status: 'error',
|
|
80
80
|
message: 'Configuration file is corrupted',
|
|
81
|
-
details: [(
|
|
81
|
+
details: [(error as Error).message],
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -125,12 +125,12 @@ async function checkContainers(): Promise<HealthCheckResult> {
|
|
|
125
125
|
message: `${containers.length} container(s)`,
|
|
126
126
|
details,
|
|
127
127
|
}
|
|
128
|
-
} catch (
|
|
128
|
+
} catch (error) {
|
|
129
129
|
return {
|
|
130
130
|
name: 'Containers',
|
|
131
131
|
status: 'error',
|
|
132
132
|
message: 'Failed to list containers',
|
|
133
|
-
details: [(
|
|
133
|
+
details: [(error as Error).message],
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -162,7 +162,7 @@ async function checkSqliteRegistry(): Promise<HealthCheckResult> {
|
|
|
162
162
|
label: 'Remove orphaned entries from registry',
|
|
163
163
|
handler: async () => {
|
|
164
164
|
const count = await sqliteRegistry.removeOrphans()
|
|
165
|
-
console.log(
|
|
165
|
+
console.log(uiSuccess(`Removed ${count} orphaned entries`))
|
|
166
166
|
},
|
|
167
167
|
},
|
|
168
168
|
}
|
|
@@ -173,12 +173,12 @@ async function checkSqliteRegistry(): Promise<HealthCheckResult> {
|
|
|
173
173
|
status: 'ok',
|
|
174
174
|
message: `${entries.length} database(s) registered, all files exist`,
|
|
175
175
|
}
|
|
176
|
-
} catch (
|
|
176
|
+
} catch (error) {
|
|
177
177
|
return {
|
|
178
178
|
name: 'SQLite Registry',
|
|
179
179
|
status: 'warning',
|
|
180
180
|
message: 'Could not check registry',
|
|
181
|
-
details: [(
|
|
181
|
+
details: [(error as Error).message],
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
}
|
|
@@ -211,12 +211,12 @@ async function checkBinaries(): Promise<HealthCheckResult> {
|
|
|
211
211
|
message: hasWarning ? 'Some tools missing' : 'All tools available',
|
|
212
212
|
details: results,
|
|
213
213
|
}
|
|
214
|
-
} catch (
|
|
214
|
+
} catch (error) {
|
|
215
215
|
return {
|
|
216
216
|
name: 'Database Tools',
|
|
217
217
|
status: 'error',
|
|
218
218
|
message: 'Failed to check tools',
|
|
219
|
-
details: [(
|
|
219
|
+
details: [(error as Error).message],
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
}
|