spindb 0.5.4 → 0.5.5

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.
@@ -0,0 +1,93 @@
1
+ /**
2
+ * PostgreSQL Backup
3
+ *
4
+ * Creates database backups in SQL or custom (.dump) format using pg_dump.
5
+ */
6
+
7
+ import { spawn } from 'child_process'
8
+ import { stat } from 'fs/promises'
9
+ import { configManager } from '../../core/config-manager'
10
+ import { defaults } from '../../config/defaults'
11
+ import type { ContainerConfig, BackupOptions, BackupResult } from '../../types'
12
+
13
+ /**
14
+ * Get pg_dump path from config, with helpful error message
15
+ */
16
+ async function getPgDumpPath(): Promise<string> {
17
+ const pgDumpPath = await configManager.getBinaryPath('pg_dump')
18
+ if (!pgDumpPath) {
19
+ throw new Error(
20
+ 'pg_dump not found. Install PostgreSQL client tools:\n' +
21
+ ' macOS: brew install libpq && brew link --force libpq\n' +
22
+ ' Ubuntu/Debian: apt install postgresql-client\n\n' +
23
+ 'Or configure manually: spindb config set pg_dump /path/to/pg_dump',
24
+ )
25
+ }
26
+ return pgDumpPath
27
+ }
28
+
29
+ /**
30
+ * Create a backup of a PostgreSQL database
31
+ *
32
+ * CLI equivalent:
33
+ * - SQL format: pg_dump -Fp -h 127.0.0.1 -p {port} -U postgres -d {database} -f {outputPath}
34
+ * - Dump format: pg_dump -Fc -h 127.0.0.1 -p {port} -U postgres -d {database} -f {outputPath}
35
+ */
36
+ export async function createBackup(
37
+ container: ContainerConfig,
38
+ outputPath: string,
39
+ options: BackupOptions,
40
+ ): Promise<BackupResult> {
41
+ const { port } = container
42
+ const { database, format } = options
43
+
44
+ const pgDumpPath = await getPgDumpPath()
45
+
46
+ // -Fp = plain SQL format, -Fc = custom format
47
+ const formatFlag = format === 'sql' ? '-Fp' : '-Fc'
48
+
49
+ return new Promise((resolve, reject) => {
50
+ const args = [
51
+ '-h',
52
+ '127.0.0.1',
53
+ '-p',
54
+ String(port),
55
+ '-U',
56
+ defaults.superuser,
57
+ '-d',
58
+ database,
59
+ formatFlag,
60
+ '-f',
61
+ outputPath,
62
+ ]
63
+
64
+ const proc = spawn(pgDumpPath, args, {
65
+ stdio: ['pipe', 'pipe', 'pipe'],
66
+ })
67
+
68
+ let stderr = ''
69
+
70
+ proc.stderr?.on('data', (data: Buffer) => {
71
+ stderr += data.toString()
72
+ })
73
+
74
+ proc.on('error', (err: NodeJS.ErrnoException) => {
75
+ reject(err)
76
+ })
77
+
78
+ proc.on('close', async (code) => {
79
+ if (code === 0) {
80
+ // Get file size
81
+ const stats = await stat(outputPath)
82
+ resolve({
83
+ path: outputPath,
84
+ format: format === 'sql' ? 'sql' : 'custom',
85
+ size: stats.size,
86
+ })
87
+ } else {
88
+ const errorMessage = stderr || `pg_dump exited with code ${code}`
89
+ reject(new Error(errorMessage))
90
+ }
91
+ })
92
+ })
93
+ }
@@ -16,10 +16,13 @@ import {
16
16
  FALLBACK_VERSION_MAP,
17
17
  } from './binary-urls'
18
18
  import { detectBackupFormat, restoreBackup } from './restore'
19
+ import { createBackup } from './backup'
19
20
  import type {
20
21
  ContainerConfig,
21
22
  ProgressCallback,
22
23
  BackupFormat,
24
+ BackupOptions,
25
+ BackupResult,
23
26
  RestoreResult,
24
27
  DumpResult,
25
28
  StatusResult,
@@ -369,6 +372,29 @@ export class PostgreSQLEngine extends BaseEngine {
369
372
  }
370
373
  }
371
374
 
375
+ /**
376
+ * Get the size of the container's database in bytes
377
+ * Uses pg_database_size() to get accurate data size
378
+ * Returns null if container is not running or query fails
379
+ */
380
+ async getDatabaseSize(container: ContainerConfig): Promise<number | null> {
381
+ const { port, database } = container
382
+ const db = database || 'postgres'
383
+
384
+ try {
385
+ const psqlPath = await this.getPsqlPath()
386
+ // Query pg_database_size for the specific database
387
+ const { stdout } = await execAsync(
388
+ `"${psqlPath}" -h 127.0.0.1 -p ${port} -U ${defaults.superuser} -d postgres -t -A -c "SELECT pg_database_size('${db}')"`,
389
+ )
390
+ const size = parseInt(stdout.trim(), 10)
391
+ return isNaN(size) ? null : size
392
+ } catch {
393
+ // Container not running or query failed
394
+ return null
395
+ }
396
+ }
397
+
372
398
  /**
373
399
  * Create a dump from a remote database using a connection string
374
400
  * @param connectionString PostgreSQL connection string (e.g., postgresql://user:pass@host:port/dbname)
@@ -420,6 +446,17 @@ export class PostgreSQLEngine extends BaseEngine {
420
446
  })
421
447
  })
422
448
  }
449
+
450
+ /**
451
+ * Create a backup of a PostgreSQL database
452
+ */
453
+ async backup(
454
+ container: ContainerConfig,
455
+ outputPath: string,
456
+ options: BackupOptions,
457
+ ): Promise<BackupResult> {
458
+ return createBackup(container, outputPath, options)
459
+ }
423
460
  }
424
461
 
425
462
  export const postgresqlEngine = new PostgreSQLEngine()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spindb",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Spin up local database containers without Docker. A DBngin-like CLI for PostgreSQL and MySQL.",
5
5
  "type": "module",
6
6
  "bin": {
package/types/index.ts CHANGED
@@ -4,6 +4,7 @@ export type ContainerConfig = {
4
4
  version: string
5
5
  port: number
6
6
  database: string
7
+ databases?: string[]
7
8
  created: string
8
9
  status: 'created' | 'running' | 'stopped'
9
10
  clonedFrom?: string
@@ -56,6 +57,17 @@ export type RestoreResult = {
56
57
  code?: number
57
58
  }
58
59
 
60
+ export type BackupOptions = {
61
+ database: string
62
+ format: 'sql' | 'dump'
63
+ }
64
+
65
+ export type BackupResult = {
66
+ path: string
67
+ format: string
68
+ size: number
69
+ }
70
+
59
71
  export type DumpResult = {
60
72
  filePath: string
61
73
  stdout?: string
@@ -85,6 +97,10 @@ export type BinaryTool =
85
97
  | 'mysqlpump'
86
98
  | 'mysqld'
87
99
  | 'mysqladmin'
100
+ // Enhanced shells (optional)
101
+ | 'pgcli'
102
+ | 'mycli'
103
+ | 'usql'
88
104
 
89
105
  /**
90
106
  * Source of a binary - bundled (downloaded by spindb) or system (found on PATH)
@@ -118,6 +134,10 @@ export type SpinDBConfig = {
118
134
  mysqlpump?: BinaryConfig
119
135
  mysqld?: BinaryConfig
120
136
  mysqladmin?: BinaryConfig
137
+ // Enhanced shells (optional)
138
+ pgcli?: BinaryConfig
139
+ mycli?: BinaryConfig
140
+ usql?: BinaryConfig
121
141
  }
122
142
  // Default settings
123
143
  defaults?: {