spindb 0.9.1 → 0.9.3

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.
Files changed (55) hide show
  1. package/README.md +5 -8
  2. package/cli/commands/attach.ts +108 -0
  3. package/cli/commands/backup.ts +13 -11
  4. package/cli/commands/clone.ts +14 -10
  5. package/cli/commands/config.ts +29 -29
  6. package/cli/commands/connect.ts +51 -39
  7. package/cli/commands/create.ts +65 -32
  8. package/cli/commands/delete.ts +8 -8
  9. package/cli/commands/deps.ts +17 -15
  10. package/cli/commands/detach.ts +100 -0
  11. package/cli/commands/doctor.ts +27 -13
  12. package/cli/commands/edit.ts +120 -57
  13. package/cli/commands/engines.ts +17 -15
  14. package/cli/commands/info.ts +8 -6
  15. package/cli/commands/list.ts +127 -18
  16. package/cli/commands/logs.ts +15 -11
  17. package/cli/commands/menu/backup-handlers.ts +52 -47
  18. package/cli/commands/menu/container-handlers.ts +164 -79
  19. package/cli/commands/menu/engine-handlers.ts +21 -11
  20. package/cli/commands/menu/index.ts +4 -4
  21. package/cli/commands/menu/shell-handlers.ts +34 -31
  22. package/cli/commands/menu/sql-handlers.ts +22 -16
  23. package/cli/commands/menu/update-handlers.ts +19 -17
  24. package/cli/commands/restore.ts +22 -20
  25. package/cli/commands/run.ts +20 -18
  26. package/cli/commands/self-update.ts +5 -5
  27. package/cli/commands/sqlite.ts +247 -0
  28. package/cli/commands/start.ts +11 -9
  29. package/cli/commands/stop.ts +9 -9
  30. package/cli/commands/url.ts +12 -9
  31. package/cli/helpers.ts +9 -4
  32. package/cli/index.ts +6 -0
  33. package/cli/ui/prompts.ts +12 -5
  34. package/cli/ui/spinner.ts +4 -4
  35. package/cli/ui/theme.ts +4 -4
  36. package/config/paths.ts +0 -8
  37. package/core/binary-manager.ts +5 -1
  38. package/core/config-manager.ts +32 -0
  39. package/core/container-manager.ts +5 -5
  40. package/core/platform-service.ts +3 -3
  41. package/core/start-with-retry.ts +6 -6
  42. package/core/transaction-manager.ts +6 -6
  43. package/engines/mysql/backup.ts +37 -13
  44. package/engines/mysql/index.ts +11 -11
  45. package/engines/mysql/restore.ts +4 -4
  46. package/engines/mysql/version-validator.ts +2 -2
  47. package/engines/postgresql/binary-manager.ts +17 -17
  48. package/engines/postgresql/index.ts +7 -2
  49. package/engines/postgresql/restore.ts +2 -2
  50. package/engines/postgresql/version-validator.ts +2 -2
  51. package/engines/sqlite/index.ts +30 -15
  52. package/engines/sqlite/registry.ts +64 -33
  53. package/engines/sqlite/scanner.ts +99 -0
  54. package/package.json +4 -3
  55. package/types/index.ts +21 -1
@@ -22,7 +22,7 @@ import {
22
22
  import { getEngine } from '../../engines'
23
23
  import { getEngineDefaults } from '../../config/defaults'
24
24
  import { promptContainerSelect } from '../ui/prompts'
25
- import { error, warning, info, success } from '../ui/theme'
25
+ import { uiError, uiWarning, uiInfo, uiSuccess } from '../ui/theme'
26
26
  import { Engine } from '../../types'
27
27
 
28
28
  export const connectCommand = new Command('connect')
@@ -78,11 +78,13 @@ export const connectCommand = new Command('connect')
78
78
  if (connectable.length === 0) {
79
79
  if (containers.length === 0) {
80
80
  console.log(
81
- warning('No containers found. Create one with: spindb create'),
81
+ uiWarning(
82
+ 'No containers found. Create one with: spindb create',
83
+ ),
82
84
  )
83
85
  } else {
84
86
  console.log(
85
- warning(
87
+ uiWarning(
86
88
  'No running containers. Start one first with: spindb start',
87
89
  ),
88
90
  )
@@ -100,7 +102,7 @@ export const connectCommand = new Command('connect')
100
102
 
101
103
  const config = await containerManager.getConfig(containerName)
102
104
  if (!config) {
103
- console.error(error(`Container "${containerName}" not found`))
105
+ console.error(uiError(`Container "${containerName}" not found`))
104
106
  process.exit(1)
105
107
  }
106
108
 
@@ -114,9 +116,7 @@ export const connectCommand = new Command('connect')
114
116
  if (engineName === Engine.SQLite) {
115
117
  if (!existsSync(config.database)) {
116
118
  console.error(
117
- error(
118
- `SQLite database file not found: ${config.database}`,
119
- ),
119
+ uiError(`SQLite database file not found: ${config.database}`),
120
120
  )
121
121
  process.exit(1)
122
122
  }
@@ -127,7 +127,7 @@ export const connectCommand = new Command('connect')
127
127
  })
128
128
  if (!running) {
129
129
  console.error(
130
- error(
130
+ uiError(
131
131
  `Container "${containerName}" is not running. Start it first.`,
132
132
  ),
133
133
  )
@@ -145,17 +145,17 @@ export const connectCommand = new Command('connect')
145
145
  if (!usqlInstalled) {
146
146
  if (options.installTui) {
147
147
  console.log(
148
- info('Installing usql for enhanced shell experience...'),
148
+ uiInfo('Installing usql for enhanced shell experience...'),
149
149
  )
150
150
  const pm = await detectPackageManager()
151
151
  if (pm) {
152
152
  const result = await installUsql(pm)
153
153
  if (result.success) {
154
- console.log(success('usql installed successfully!'))
154
+ console.log(uiSuccess('usql installed successfully!'))
155
155
  console.log()
156
156
  } else {
157
157
  console.error(
158
- error(`Failed to install usql: ${result.error}`),
158
+ uiError(`Failed to install usql: ${result.error}`),
159
159
  )
160
160
  console.log()
161
161
  console.log(chalk.gray('Manual installation:'))
@@ -165,7 +165,7 @@ export const connectCommand = new Command('connect')
165
165
  process.exit(1)
166
166
  }
167
167
  } else {
168
- console.error(error('No supported package manager found'))
168
+ console.error(uiError('No supported package manager found'))
169
169
  console.log()
170
170
  console.log(chalk.gray('Manual installation:'))
171
171
  for (const instruction of getUsqlManualInstructions()) {
@@ -174,7 +174,7 @@ export const connectCommand = new Command('connect')
174
174
  process.exit(1)
175
175
  }
176
176
  } else {
177
- console.error(error('usql is not installed'))
177
+ console.error(uiError('usql is not installed'))
178
178
  console.log()
179
179
  console.log(
180
180
  chalk.gray('Install usql for enhanced shell experience:'),
@@ -194,7 +194,7 @@ export const connectCommand = new Command('connect')
194
194
  if (usePgcli) {
195
195
  if (engineName !== 'postgresql') {
196
196
  console.error(
197
- error('pgcli is only available for PostgreSQL containers'),
197
+ uiError('pgcli is only available for PostgreSQL containers'),
198
198
  )
199
199
  console.log(chalk.gray('For MySQL, use: spindb connect --mycli'))
200
200
  process.exit(1)
@@ -205,17 +205,17 @@ export const connectCommand = new Command('connect')
205
205
  if (!pgcliInstalled) {
206
206
  if (options.installPgcli) {
207
207
  console.log(
208
- info('Installing pgcli for enhanced PostgreSQL shell...'),
208
+ uiInfo('Installing pgcli for enhanced PostgreSQL shell...'),
209
209
  )
210
210
  const pm = await detectPackageManager()
211
211
  if (pm) {
212
212
  const result = await installPgcli(pm)
213
213
  if (result.success) {
214
- console.log(success('pgcli installed successfully!'))
214
+ console.log(uiSuccess('pgcli installed successfully!'))
215
215
  console.log()
216
216
  } else {
217
217
  console.error(
218
- error(`Failed to install pgcli: ${result.error}`),
218
+ uiError(`Failed to install pgcli: ${result.error}`),
219
219
  )
220
220
  console.log()
221
221
  console.log(chalk.gray('Manual installation:'))
@@ -225,7 +225,7 @@ export const connectCommand = new Command('connect')
225
225
  process.exit(1)
226
226
  }
227
227
  } else {
228
- console.error(error('No supported package manager found'))
228
+ console.error(uiError('No supported package manager found'))
229
229
  console.log()
230
230
  console.log(chalk.gray('Manual installation:'))
231
231
  for (const instruction of getPgcliManualInstructions()) {
@@ -234,7 +234,7 @@ export const connectCommand = new Command('connect')
234
234
  process.exit(1)
235
235
  }
236
236
  } else {
237
- console.error(error('pgcli is not installed'))
237
+ console.error(uiError('pgcli is not installed'))
238
238
  console.log()
239
239
  console.log(
240
240
  chalk.gray('Install pgcli for enhanced PostgreSQL shell:'),
@@ -253,7 +253,9 @@ export const connectCommand = new Command('connect')
253
253
  const useMycli = options.mycli || options.installMycli
254
254
  if (useMycli) {
255
255
  if (engineName !== 'mysql') {
256
- console.error(error('mycli is only available for MySQL containers'))
256
+ console.error(
257
+ uiError('mycli is only available for MySQL containers'),
258
+ )
257
259
  console.log(
258
260
  chalk.gray('For PostgreSQL, use: spindb connect --pgcli'),
259
261
  )
@@ -264,16 +266,18 @@ export const connectCommand = new Command('connect')
264
266
 
265
267
  if (!mycliInstalled) {
266
268
  if (options.installMycli) {
267
- console.log(info('Installing mycli for enhanced MySQL shell...'))
269
+ console.log(
270
+ uiInfo('Installing mycli for enhanced MySQL shell...'),
271
+ )
268
272
  const pm = await detectPackageManager()
269
273
  if (pm) {
270
274
  const result = await installMycli(pm)
271
275
  if (result.success) {
272
- console.log(success('mycli installed successfully!'))
276
+ console.log(uiSuccess('mycli installed successfully!'))
273
277
  console.log()
274
278
  } else {
275
279
  console.error(
276
- error(`Failed to install mycli: ${result.error}`),
280
+ uiError(`Failed to install mycli: ${result.error}`),
277
281
  )
278
282
  console.log()
279
283
  console.log(chalk.gray('Manual installation:'))
@@ -283,7 +287,7 @@ export const connectCommand = new Command('connect')
283
287
  process.exit(1)
284
288
  }
285
289
  } else {
286
- console.error(error('No supported package manager found'))
290
+ console.error(uiError('No supported package manager found'))
287
291
  console.log()
288
292
  console.log(chalk.gray('Manual installation:'))
289
293
  for (const instruction of getMycliManualInstructions()) {
@@ -292,7 +296,7 @@ export const connectCommand = new Command('connect')
292
296
  process.exit(1)
293
297
  }
294
298
  } else {
295
- console.error(error('mycli is not installed'))
299
+ console.error(uiError('mycli is not installed'))
296
300
  console.log()
297
301
  console.log(chalk.gray('Install mycli for enhanced MySQL shell:'))
298
302
  console.log(chalk.cyan(' spindb connect --install-mycli'))
@@ -309,9 +313,13 @@ export const connectCommand = new Command('connect')
309
313
  const useLitecli = options.litecli || options.installLitecli
310
314
  if (useLitecli) {
311
315
  if (engineName !== Engine.SQLite) {
312
- console.error(error('litecli is only available for SQLite containers'))
316
+ console.error(
317
+ uiError('litecli is only available for SQLite containers'),
318
+ )
313
319
  if (engineName === 'postgresql') {
314
- console.log(chalk.gray('For PostgreSQL, use: spindb connect --pgcli'))
320
+ console.log(
321
+ chalk.gray('For PostgreSQL, use: spindb connect --pgcli'),
322
+ )
315
323
  } else if (engineName === 'mysql') {
316
324
  console.log(chalk.gray('For MySQL, use: spindb connect --mycli'))
317
325
  }
@@ -322,16 +330,18 @@ export const connectCommand = new Command('connect')
322
330
 
323
331
  if (!litecliInstalled) {
324
332
  if (options.installLitecli) {
325
- console.log(info('Installing litecli for enhanced SQLite shell...'))
333
+ console.log(
334
+ uiInfo('Installing litecli for enhanced SQLite shell...'),
335
+ )
326
336
  const pm = await detectPackageManager()
327
337
  if (pm) {
328
338
  const result = await installLitecli(pm)
329
339
  if (result.success) {
330
- console.log(success('litecli installed successfully!'))
340
+ console.log(uiSuccess('litecli installed successfully!'))
331
341
  console.log()
332
342
  } else {
333
343
  console.error(
334
- error(`Failed to install litecli: ${result.error}`),
344
+ uiError(`Failed to install litecli: ${result.error}`),
335
345
  )
336
346
  console.log()
337
347
  console.log(chalk.gray('Manual installation:'))
@@ -341,7 +351,7 @@ export const connectCommand = new Command('connect')
341
351
  process.exit(1)
342
352
  }
343
353
  } else {
344
- console.error(error('No supported package manager found'))
354
+ console.error(uiError('No supported package manager found'))
345
355
  console.log()
346
356
  console.log(chalk.gray('Manual installation:'))
347
357
  for (const instruction of getLitecliManualInstructions()) {
@@ -350,9 +360,11 @@ export const connectCommand = new Command('connect')
350
360
  process.exit(1)
351
361
  }
352
362
  } else {
353
- console.error(error('litecli is not installed'))
363
+ console.error(uiError('litecli is not installed'))
354
364
  console.log()
355
- console.log(chalk.gray('Install litecli for enhanced SQLite shell:'))
365
+ console.log(
366
+ chalk.gray('Install litecli for enhanced SQLite shell:'),
367
+ )
356
368
  console.log(chalk.cyan(' spindb connect --install-litecli'))
357
369
  console.log()
358
370
  console.log(chalk.gray('Or install manually:'))
@@ -364,7 +376,7 @@ export const connectCommand = new Command('connect')
364
376
  }
365
377
  }
366
378
 
367
- console.log(info(`Connecting to ${containerName}:${database}...`))
379
+ console.log(uiInfo(`Connecting to ${containerName}:${database}...`))
368
380
  console.log()
369
381
 
370
382
  let clientCmd: string
@@ -415,7 +427,7 @@ export const connectCommand = new Command('connect')
415
427
 
416
428
  clientProcess.on('error', (err: NodeJS.ErrnoException) => {
417
429
  if (err.code === 'ENOENT') {
418
- console.log(warning(`${clientCmd} not found on your system.`))
430
+ console.log(uiWarning(`${clientCmd} not found on your system.`))
419
431
  console.log()
420
432
  console.log(
421
433
  chalk.gray(' Install client tools or connect manually:'),
@@ -451,16 +463,16 @@ export const connectCommand = new Command('connect')
451
463
  }
452
464
  console.log()
453
465
  } else {
454
- console.error(error(err.message))
466
+ console.error(uiError(err.message))
455
467
  }
456
468
  })
457
469
 
458
470
  await new Promise<void>((resolve) => {
459
471
  clientProcess.on('close', () => resolve())
460
472
  })
461
- } catch (err) {
462
- const e = err as Error
463
- console.error(error(e.message))
473
+ } catch (error) {
474
+ const e = error as Error
475
+ console.error(uiError(e.message))
464
476
  process.exit(1)
465
477
  }
466
478
  },
@@ -13,7 +13,7 @@ import {
13
13
  promptConfirm,
14
14
  } from '../ui/prompts'
15
15
  import { createSpinner } from '../ui/spinner'
16
- import { header, error, connectionBox } from '../ui/theme'
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(`Missing tools: ${missingDeps.map((d) => d.name).join(', ')}`)
47
- const installed = await promptInstallDependencies(missingDeps[0].binary, 'sqlite')
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(error(`File already exists: ${absolutePath}`))
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 (err) {
83
+ } catch (error) {
79
84
  createSpinnerInstance.fail('Failed to create SQLite database')
80
- throw err
85
+ throw error
81
86
  }
82
87
 
83
88
  // Handle --from restore
@@ -85,15 +90,23 @@ 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(`Restoring from ${format.description}...`)
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 (err) {
101
+ } catch (error) {
95
102
  restoreSpinner.fail('Failed to restore backup')
96
- throw err
103
+ // Clean up the created container on restore failure
104
+ try {
105
+ await containerManager.delete(containerName, { force: true })
106
+ } catch {
107
+ // Ignore cleanup errors - still throw the original restore error
108
+ }
109
+ throw error
97
110
  }
98
111
  }
99
112
  }
@@ -146,7 +159,11 @@ function detectLocationType(location: string): {
146
159
  if (existsSync(location)) {
147
160
  // Check if it's a SQLite file (case-insensitive)
148
161
  const lowerLocation = location.toLowerCase()
149
- if (lowerLocation.endsWith('.sqlite') || lowerLocation.endsWith('.db') || lowerLocation.endsWith('.sqlite3')) {
162
+ if (
163
+ lowerLocation.endsWith('.sqlite') ||
164
+ lowerLocation.endsWith('.db') ||
165
+ lowerLocation.endsWith('.sqlite3')
166
+ ) {
150
167
  return { type: 'file', inferredEngine: Engine.SQLite }
151
168
  }
152
169
  return { type: 'file' }
@@ -158,7 +175,10 @@ function detectLocationType(location: string): {
158
175
  export const createCommand = new Command('create')
159
176
  .description('Create a new database container')
160
177
  .argument('[name]', 'Container name')
161
- .option('-e, --engine <engine>', 'Database engine (postgresql, mysql, sqlite)')
178
+ .option(
179
+ '-e, --engine <engine>',
180
+ 'Database engine (postgresql, mysql, sqlite)',
181
+ )
162
182
  .option('-v, --version <version>', 'Database version')
163
183
  .option('-d, --database <database>', 'Database name')
164
184
  .option('-p, --port <port>', 'Port number')
@@ -207,7 +227,7 @@ export const createCommand = new Command('create')
207
227
  const locationInfo = detectLocationType(options.from)
208
228
 
209
229
  if (locationInfo.type === 'not_found') {
210
- console.error(error(`Location not found: ${options.from}`))
230
+ console.error(uiError(`Location not found: ${options.from}`))
211
231
  console.log(
212
232
  chalk.gray(
213
233
  ' Provide a valid file path or connection string (postgresql://, mysql://)',
@@ -230,7 +250,7 @@ export const createCommand = new Command('create')
230
250
 
231
251
  if (options.start === false) {
232
252
  console.error(
233
- error(
253
+ uiError(
234
254
  'Cannot use --no-start with --from (restore requires running container)',
235
255
  ),
236
256
  )
@@ -257,7 +277,7 @@ export const createCommand = new Command('create')
257
277
  // Validate database name to prevent SQL injection
258
278
  if (!isValidDatabaseName(database)) {
259
279
  console.error(
260
- error(
280
+ uiError(
261
281
  'Database name must start with a letter and contain only letters, numbers, hyphens, and underscores',
262
282
  ),
263
283
  )
@@ -282,13 +302,26 @@ export const createCommand = new Command('create')
282
302
  // For server databases, validate --connect with --no-start
283
303
  if (options.connect && options.start === false) {
284
304
  console.error(
285
- error(
305
+ uiError(
286
306
  'Cannot use --no-start with --connect (connection requires running container)',
287
307
  ),
288
308
  )
289
309
  process.exit(1)
290
310
  }
291
311
 
312
+ // Validate --max-connections if provided
313
+ if (options.maxConnections) {
314
+ const parsed = parseInt(options.maxConnections, 10)
315
+ if (!Number.isFinite(parsed) || parsed <= 0) {
316
+ console.error(
317
+ uiError(
318
+ 'Invalid --max-connections value: must be a positive integer',
319
+ ),
320
+ )
321
+ process.exit(1)
322
+ }
323
+ }
324
+
292
325
  const depsSpinner = createSpinner('Checking required tools...')
293
326
  depsSpinner.start()
294
327
 
@@ -310,7 +343,7 @@ export const createCommand = new Command('create')
310
343
  missingDeps = await getMissingDependencies(engine)
311
344
  if (missingDeps.length > 0) {
312
345
  console.error(
313
- error(
346
+ uiError(
314
347
  `Still missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
315
348
  ),
316
349
  )
@@ -399,9 +432,9 @@ export const createCommand = new Command('create')
399
432
  })
400
433
 
401
434
  createSpinnerInstance.succeed('Container created')
402
- } catch (err) {
435
+ } catch (error) {
403
436
  createSpinnerInstance.fail('Failed to create container')
404
- throw err
437
+ throw error
405
438
  }
406
439
 
407
440
  const initSpinner = createSpinner('Initializing database cluster...')
@@ -415,10 +448,10 @@ export const createCommand = new Command('create')
415
448
  : undefined,
416
449
  })
417
450
  initSpinner.succeed('Database cluster initialized')
418
- } catch (err) {
451
+ } catch (error) {
419
452
  initSpinner.fail('Failed to initialize database cluster')
420
453
  await tx.rollback()
421
- throw err
454
+ throw error
422
455
  }
423
456
 
424
457
  // --from requires start, --start forces start, --no-start skips, otherwise ask user
@@ -484,14 +517,14 @@ export const createCommand = new Command('create')
484
517
  } else {
485
518
  startSpinner.succeed(`${dbEngine.displayName} started`)
486
519
  }
487
- } catch (err) {
520
+ } catch (error) {
488
521
  if (!startSpinner.isSpinning) {
489
522
  // Error was already handled above
490
523
  } else {
491
524
  startSpinner.fail(`Failed to start ${dbEngine.displayName}`)
492
525
  }
493
526
  await tx.rollback()
494
- throw err
527
+ throw error
495
528
  }
496
529
 
497
530
  const defaultDb = engineDefaults.superuser
@@ -504,10 +537,10 @@ export const createCommand = new Command('create')
504
537
  try {
505
538
  await dbEngine.createDatabase(config, database)
506
539
  dbSpinner.succeed(`Database "${database}" created`)
507
- } catch (err) {
540
+ } catch (error) {
508
541
  dbSpinner.fail(`Failed to create database "${database}"`)
509
542
  await tx.rollback()
510
- throw err
543
+ throw error
511
544
  }
512
545
  }
513
546
  }
@@ -538,8 +571,8 @@ export const createCommand = new Command('create')
538
571
  dumpSpinner.succeed('Dump created from remote database')
539
572
  backupPath = tempDumpPath
540
573
  dumpSuccess = true
541
- } catch (err) {
542
- const e = err as Error
574
+ } catch (error) {
575
+ const e = error as Error
543
576
  dumpSpinner.fail('Failed to create dump')
544
577
 
545
578
  if (
@@ -554,14 +587,14 @@ export const createCommand = new Command('create')
554
587
  }
555
588
 
556
589
  console.log()
557
- console.error(error('pg_dump error:'))
590
+ console.error(uiError('pg_dump error:'))
558
591
  console.log(chalk.gray(` ${e.message}`))
559
592
  process.exit(1)
560
593
  }
561
594
  }
562
595
 
563
596
  if (!dumpSuccess) {
564
- console.error(error('Failed to create dump after retries'))
597
+ console.error(uiError('Failed to create dump after retries'))
565
598
  process.exit(1)
566
599
  }
567
600
  } else {
@@ -639,8 +672,8 @@ export const createCommand = new Command('create')
639
672
  console.log()
640
673
  }
641
674
  }
642
- } catch (err) {
643
- const e = err as Error
675
+ } catch (error) {
676
+ const e = error as Error
644
677
 
645
678
  const missingToolPatterns = [
646
679
  'pg_restore not found',
@@ -666,7 +699,7 @@ export const createCommand = new Command('create')
666
699
  process.exit(1)
667
700
  }
668
701
 
669
- console.error(error(e.message))
702
+ console.error(uiError(e.message))
670
703
  process.exit(1)
671
704
  } finally {
672
705
  if (tempDumpPath) {
@@ -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 { error, warning } from '../ui/theme'
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(warning('No containers found'))
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(error(`Container "${containerName}" not found`))
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(warning('Deletion cancelled'))
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
- error(
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 (err) {
85
- const e = err as Error
86
- console.error(error(e.message))
84
+ } catch (error) {
85
+ const e = error as Error
86
+ console.error(uiError(e.message))
87
87
  process.exit(1)
88
88
  }
89
89
  },