spindb 0.4.0 → 0.5.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/README.md CHANGED
@@ -1,18 +1,19 @@
1
1
  # SpinDB
2
2
 
3
- Spin up local PostgreSQL databases without Docker. A lightweight alternative to DBngin.
3
+ Spin up local PostgreSQL and MySQL databases without Docker. A lightweight alternative to DBngin.
4
4
 
5
5
  ## Features
6
6
 
7
- - **No Docker required** - Downloads and runs PostgreSQL binaries directly
8
- - **Multiple containers** - Run multiple isolated PostgreSQL instances on different ports
7
+ - **No Docker required** - Downloads PostgreSQL binaries directly, uses system MySQL
8
+ - **Multiple engines** - PostgreSQL and MySQL support
9
+ - **Multiple containers** - Run multiple isolated database instances on different ports
9
10
  - **Interactive menu** - Arrow-key navigation for all operations
10
11
  - **Auto port management** - Automatically finds available ports
11
12
  - **Clone containers** - Duplicate databases with all data
12
- - **Backup restore** - Restore pg_dump backups (requires system PostgreSQL client tools)
13
+ - **Backup restore** - Restore pg_dump/mysqldump backups
13
14
  - **Custom database names** - Specify database name separate from container name
14
15
  - **Engine management** - View installed PostgreSQL versions and free up disk space
15
- - **Dynamic version selection** - Fetches all available versions from Maven Central
16
+ - **Dynamic version selection** - Fetches available PostgreSQL versions from Maven Central
16
17
 
17
18
  ## Installation
18
19
 
@@ -31,7 +32,8 @@ pnpm add -g spindb
31
32
  spindb
32
33
 
33
34
  # Or use commands directly
34
- spindb create mydb
35
+ spindb create mydb # PostgreSQL (default)
36
+ spindb create mydb --engine mysql # MySQL
35
37
  spindb list
36
38
  spindb connect mydb
37
39
  ```
@@ -45,61 +47,71 @@ spindb connect mydb
45
47
  | `spindb list` | List all containers |
46
48
  | `spindb start [name]` | Start a container |
47
49
  | `spindb stop [name]` | Stop a container |
48
- | `spindb connect [name]` | Connect with psql |
50
+ | `spindb connect [name]` | Connect with psql/mysql shell |
49
51
  | `spindb restore [name] [backup]` | Restore a backup file |
50
52
  | `spindb clone [source] [target]` | Clone a container |
51
53
  | `spindb delete [name]` | Delete a container |
52
54
  | `spindb config show` | Show configuration |
53
- | `spindb config detect` | Auto-detect PostgreSQL tools |
55
+ | `spindb config detect` | Auto-detect database tools |
54
56
  | `spindb deps check` | Check status of client tools |
55
57
  | `spindb deps install` | Install missing client tools |
56
58
 
57
- ## How It Works
59
+ ## Supported Engines
60
+
61
+ ### PostgreSQL 🐘
62
+
63
+ - Downloads binaries from [zonky.io](https://github.com/zonkyio/embedded-postgres-binaries)
64
+ - Versions: 14, 15, 16, 17
65
+ - Requires system client tools (psql, pg_dump, pg_restore) for some operations
58
66
 
59
- SpinDB downloads pre-built PostgreSQL binaries from [zonky.io](https://github.com/zonkyio/embedded-postgres-binaries) on first use. These are the same binaries used by embedded-postgres for Java testing.
67
+ ### MySQL 🐬
68
+
69
+ - Uses system-installed MySQL (via Homebrew, apt, etc.)
70
+ - Version determined by system installation
71
+ - Requires: mysqld, mysql, mysqldump, mysqladmin
72
+
73
+ ## How It Works
60
74
 
61
75
  Data is stored in `~/.spindb/`:
62
76
  ```
63
77
  ~/.spindb/
64
- ├── bin/ # PostgreSQL server binaries
65
- │ └── postgresql-16-darwin-arm64/
66
- ├── containers/ # Container data
67
- └── mydb/
68
- ├── container.json # Container config
69
- │ ├── data/ # PostgreSQL data directory
70
- └── postgres.log # Server logs
71
- └── config.json # SpinDB configuration
78
+ ├── bin/ # PostgreSQL server binaries
79
+ │ └── postgresql-17-darwin-arm64/
80
+ ├── containers/
81
+ ├── postgresql/ # PostgreSQL containers
82
+ │ └── mydb/
83
+ ├── container.json
84
+ ├── data/
85
+ │ │ └── postgres.log
86
+ │ └── mysql/ # MySQL containers
87
+ │ └── mydb/
88
+ │ ├── container.json
89
+ │ ├── data/
90
+ │ └── mysql.log
91
+ └── config.json
72
92
  ```
73
93
 
74
- ## PostgreSQL Client Tools
94
+ ## Client Tools
75
95
 
76
- SpinDB bundles the PostgreSQL **server** (postgres, pg_ctl, initdb) but not client tools (psql, pg_dump, pg_restore). For `connect` and `restore` commands, you need PostgreSQL client tools installed.
96
+ SpinDB bundles the PostgreSQL **server** but not client tools. For `connect` and `restore` commands, you need client tools installed.
77
97
 
78
98
  ### Automatic Installation
79
99
 
80
- SpinDB can check and install client tools automatically:
81
-
82
100
  ```bash
83
101
  # Check status of all client tools
84
102
  spindb deps check
85
103
 
86
- # Install missing tools (uses Homebrew, apt, yum, dnf, or pacman)
104
+ # Install missing tools
87
105
  spindb deps install
88
106
 
89
107
  # Install for a specific engine
90
108
  spindb deps install --engine postgresql
91
109
  spindb deps install --engine mysql
92
-
93
- # Install all missing dependencies for all engines
94
- spindb deps install --all
95
-
96
- # List all supported dependencies
97
- spindb deps list
98
110
  ```
99
111
 
100
112
  ### Manual Installation
101
113
 
102
- If automatic installation doesn't work, install manually:
114
+ #### PostgreSQL
103
115
 
104
116
  ```bash
105
117
  # macOS (Homebrew)
@@ -109,30 +121,21 @@ brew link --overwrite postgresql@17
109
121
  # Ubuntu/Debian
110
122
  sudo apt install postgresql-client
111
123
 
112
- # CentOS/RHEL
113
- sudo yum install postgresql
114
-
115
- # Fedora
116
- sudo dnf install postgresql
117
-
118
124
  # Arch
119
125
  sudo pacman -S postgresql-libs
120
-
121
- # Or use Postgres.app (macOS)
122
- # Client tools are automatically detected
123
126
  ```
124
127
 
125
- SpinDB auto-detects installed tools. Check what's configured:
128
+ #### MySQL
126
129
 
127
130
  ```bash
128
- spindb config show
129
- ```
131
+ # macOS (Homebrew)
132
+ brew install mysql
130
133
 
131
- Manually configure tool paths:
134
+ # Ubuntu/Debian
135
+ sudo apt install mysql-server
132
136
 
133
- ```bash
134
- spindb config set psql /path/to/psql
135
- spindb config set pg_restore /path/to/pg_restore
137
+ # Arch
138
+ sudo pacman -S mysql
136
139
  ```
137
140
 
138
141
  ## Supported Platforms
@@ -140,53 +143,31 @@ spindb config set pg_restore /path/to/pg_restore
140
143
  - macOS (Apple Silicon & Intel)
141
144
  - Linux (x64 & ARM64)
142
145
 
143
- ## Supported PostgreSQL Versions
144
-
145
- - PostgreSQL 14
146
- - PostgreSQL 15
147
- - PostgreSQL 16
148
- - PostgreSQL 17
149
-
150
146
  ## Examples
151
147
 
152
- ### Create a database with specific version and name
148
+ ### Create databases
153
149
 
154
150
  ```bash
155
- # Specify PostgreSQL version and port
156
- spindb create mydb --pg-version 15 --port 5433
151
+ # PostgreSQL with specific version and port
152
+ spindb create mydb --engine postgresql --version 16 --port 5433
153
+
154
+ # MySQL
155
+ spindb create mydb --engine mysql --port 3307
157
156
 
158
- # Specify a custom database name (different from container name)
157
+ # With custom database name
159
158
  spindb create mydb --database my_app_db
160
- # Connection string: postgresql://postgres@localhost:5432/my_app_db
161
159
  ```
162
160
 
163
161
  ### Create and restore in one command
164
162
 
165
163
  ```bash
166
- # Create a container and restore from a dump file
164
+ # Create and restore from a dump file
167
165
  spindb create mydb --from ./backup.dump
168
166
 
169
- # Create a container and pull from a remote database
167
+ # Create and pull from a remote database
170
168
  spindb create mydb --from "postgresql://user:pass@remote-host:5432/production_db"
171
-
172
- # With specific version and database name
173
- spindb create mydb --pg-version 17 --database myapp --from ./backup.dump
174
- ```
175
-
176
- The `--from` option auto-detects whether the location is a file path or connection string.
177
-
178
- ### Restore to an existing container
179
-
180
- ```bash
181
- # Restore from a dump file (supports .sql, custom format, and tar format)
182
- spindb restore mydb ./backup.dump -d myapp
183
-
184
- # Or pull directly from a remote database
185
- spindb restore mydb --from-url "postgresql://user:pass@remote-host:5432/production_db" -d myapp
186
169
  ```
187
170
 
188
- The interactive menu (`spindb` → "Restore backup") also offers an option to create a new container as part of the restore flow.
189
-
190
171
  ### Clone for testing
191
172
 
192
173
  ```bash
@@ -200,63 +181,58 @@ spindb clone production-copy test-branch
200
181
  spindb start test-branch
201
182
  ```
202
183
 
203
- ### Connect and run queries
184
+ ### Connect to databases
204
185
 
205
186
  ```bash
206
- # Interactive psql session
187
+ # Interactive shell (auto-detects engine)
207
188
  spindb connect mydb
208
189
 
209
- # Or use the connection string directly
190
+ # Or use connection string directly
210
191
  psql postgresql://postgres@localhost:5432/mydb
192
+ mysql -u root -h 127.0.0.1 -P 3306 mydb
211
193
  ```
212
194
 
213
195
  ### Manage installed engines
214
196
 
215
- The Engines menu (accessible from the main menu) shows all installed PostgreSQL versions with their disk usage. You can delete unused versions to free up space.
197
+ The Engines menu shows installed PostgreSQL versions with disk usage:
216
198
 
217
199
  ```
218
200
  ENGINE VERSION PLATFORM SIZE
219
201
  ────────────────────────────────────────────────────────
220
202
  postgresql 17 darwin-arm64 45.2 MB
221
- postgresql 16.9.0 darwin-arm64 44.8 MB
222
203
  postgresql 16 darwin-arm64 44.8 MB
223
204
  ────────────────────────────────────────────────────────
224
- 3 version(s) 134.8 MB
205
+ 2 version(s) 90.0 MB
225
206
  ```
226
207
 
227
- ## Configuration
228
-
229
- Configuration is stored in `~/.spindb/config.json`. You can edit it directly or use the `config` commands:
208
+ ## Running Tests
230
209
 
231
210
  ```bash
232
- # Show all config
233
- spindb config show
234
-
235
- # Re-detect system tools
236
- spindb config detect
211
+ # Run all tests (PostgreSQL + MySQL)
212
+ pnpm test
237
213
 
238
- # Set custom binary path
239
- spindb config set psql /usr/local/bin/psql
240
-
241
- # Get path for scripting
242
- spindb config path psql
214
+ # Run individual test suites
215
+ pnpm test:pg
216
+ pnpm test:mysql
243
217
  ```
244
218
 
245
219
  ## Troubleshooting
246
220
 
247
221
  ### Port already in use
248
222
 
249
- SpinDB automatically finds an available port if the default (5432) is in use. You can also specify a port:
223
+ SpinDB automatically finds an available port. You can also specify one:
250
224
 
251
225
  ```bash
252
226
  spindb create mydb --port 5433
253
227
  ```
254
228
 
255
- ### psql not found
229
+ ### Client tool not found
256
230
 
257
- Install PostgreSQL client tools (see above) or configure the path manually:
231
+ Install client tools or configure the path:
258
232
 
259
233
  ```bash
234
+ spindb deps install
235
+ # or
260
236
  spindb config set psql /path/to/psql
261
237
  ```
262
238
 
@@ -265,7 +241,8 @@ spindb config set psql /path/to/psql
265
241
  Check the logs:
266
242
 
267
243
  ```bash
268
- cat ~/.spindb/containers/mydb/postgres.log
244
+ cat ~/.spindb/containers/postgresql/mydb/postgres.log
245
+ cat ~/.spindb/containers/mysql/mydb/mysql.log
269
246
  ```
270
247
 
271
248
  ### Reset everything
@@ -58,7 +58,9 @@ export const cloneCommand = new Command('clone')
58
58
  }
59
59
 
60
60
  // Check source is stopped
61
- const running = await processManager.isRunning(sourceName)
61
+ const running = await processManager.isRunning(sourceName, {
62
+ engine: sourceConfig.engine,
63
+ })
62
64
  if (running) {
63
65
  console.error(
64
66
  error(
@@ -4,14 +4,15 @@ import chalk from 'chalk'
4
4
  import { containerManager } from '../../core/container-manager'
5
5
  import { processManager } from '../../core/process-manager'
6
6
  import { getEngine } from '../../engines'
7
+ import { getEngineDefaults } from '../../config/defaults'
7
8
  import { promptContainerSelect } from '../ui/prompts'
8
9
  import { error, warning, info } from '../ui/theme'
9
10
 
10
11
  export const connectCommand = new Command('connect')
11
- .description('Connect to a container with psql')
12
+ .description('Connect to a container with database client')
12
13
  .argument('[name]', 'Container name')
13
- .option('-d, --database <name>', 'Database name', 'postgres')
14
- .action(async (name: string | undefined, options: { database: string }) => {
14
+ .option('-d, --database <name>', 'Database name')
15
+ .action(async (name: string | undefined, options: { database?: string }) => {
15
16
  try {
16
17
  let containerName = name
17
18
 
@@ -50,8 +51,16 @@ export const connectCommand = new Command('connect')
50
51
  process.exit(1)
51
52
  }
52
53
 
54
+ const { engine: engineName } = config
55
+ const engineDefaults = getEngineDefaults(engineName)
56
+
57
+ // Default database: container's database or superuser
58
+ const database = options.database ?? config.database ?? engineDefaults.superuser
59
+
53
60
  // Check if running
54
- const running = await processManager.isRunning(containerName)
61
+ const running = await processManager.isRunning(containerName, {
62
+ engine: engineName,
63
+ })
55
64
  if (!running) {
56
65
  console.error(
57
66
  error(`Container "${containerName}" is not running. Start it first.`),
@@ -60,35 +69,52 @@ export const connectCommand = new Command('connect')
60
69
  }
61
70
 
62
71
  // Get engine
63
- const engine = getEngine(config.engine)
64
- const connectionString = engine.getConnectionString(
65
- config,
66
- options.database,
67
- )
72
+ const engine = getEngine(engineName)
73
+ const connectionString = engine.getConnectionString(config, database)
68
74
 
69
- console.log(info(`Connecting to ${containerName}:${options.database}...`))
75
+ console.log(info(`Connecting to ${containerName}:${database}...`))
70
76
  console.log()
71
77
 
72
- // Try to use system psql (the bundled binaries don't include psql)
73
- const psqlProcess = spawn('psql', [connectionString], {
78
+ // Build client command based on engine
79
+ let clientCmd: string
80
+ let clientArgs: string[]
81
+
82
+ if (engineName === 'mysql') {
83
+ // MySQL: mysql -h 127.0.0.1 -P port -u root database
84
+ clientCmd = 'mysql'
85
+ clientArgs = [
86
+ '-h', '127.0.0.1',
87
+ '-P', String(config.port),
88
+ '-u', engineDefaults.superuser,
89
+ database,
90
+ ]
91
+ } else {
92
+ // PostgreSQL: psql connection_string
93
+ clientCmd = 'psql'
94
+ clientArgs = [connectionString]
95
+ }
96
+
97
+ const clientProcess = spawn(clientCmd, clientArgs, {
74
98
  stdio: 'inherit',
75
99
  })
76
100
 
77
- psqlProcess.on('error', (err: NodeJS.ErrnoException) => {
101
+ clientProcess.on('error', (err: NodeJS.ErrnoException) => {
78
102
  if (err.code === 'ENOENT') {
79
- console.log(warning('psql not found on your system.'))
103
+ console.log(warning(`${clientCmd} not found on your system.`))
80
104
  console.log()
81
- console.log(
82
- chalk.gray(
83
- ' Install PostgreSQL client tools or connect manually:',
84
- ),
85
- )
105
+ console.log(chalk.gray(' Install client tools or connect manually:'))
86
106
  console.log(chalk.cyan(` ${connectionString}`))
87
107
  console.log()
88
- console.log(chalk.gray(' On macOS with Homebrew:'))
89
- console.log(
90
- chalk.cyan(' brew install libpq && brew link --force libpq'),
91
- )
108
+
109
+ if (engineName === 'mysql') {
110
+ console.log(chalk.gray(' On macOS with Homebrew:'))
111
+ console.log(chalk.cyan(' brew install mysql-client'))
112
+ } else {
113
+ console.log(chalk.gray(' On macOS with Homebrew:'))
114
+ console.log(
115
+ chalk.cyan(' brew install libpq && brew link --force libpq'),
116
+ )
117
+ }
92
118
  console.log()
93
119
  } else {
94
120
  console.error(error(err.message))
@@ -96,7 +122,7 @@ export const connectCommand = new Command('connect')
96
122
  })
97
123
 
98
124
  await new Promise<void>((resolve) => {
99
- psqlProcess.on('close', () => resolve())
125
+ clientProcess.on('close', () => resolve())
100
126
  })
101
127
  } catch (err) {
102
128
  const e = err as Error