spindb 0.1.0 → 0.2.0

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.
@@ -12,7 +12,12 @@
12
12
  "Bash(node bin/cli.js:*)",
13
13
  "Bash(pnpm add:*)",
14
14
  "Bash(pnpm run format:*)",
15
- "Bash(pnpm run lint:*)"
15
+ "Bash(pnpm run lint:*)",
16
+ "Bash(node /Users/bob/dev/db-container/bin/cli.js:*)",
17
+ "Bash(node -e \"\nconst { fetchAvailableVersions, SUPPORTED_MAJOR_VERSIONS } = require(''./src/engines/postgresql/binary-urls.ts'');\n\")",
18
+ "Bash(node --import tsx bin/cli.js:*)",
19
+ "Bash(node --import tsx:*)",
20
+ "Bash(cat:*)"
16
21
  ],
17
22
  "deny": [],
18
23
  "ask": []
package/CLAUDE.md CHANGED
@@ -78,6 +78,28 @@ Client tools (psql, pg_restore) are detected from the system. The `config-manage
78
78
  ### Interactive Menu
79
79
  When `spindb` is run with no arguments, it shows an interactive menu (`src/cli/commands/menu.ts`) using Inquirer's list prompt. Users navigate with arrow keys.
80
80
 
81
+ **Menu Navigation Rules:**
82
+ - Any submenu with a "Back" button that goes to a parent menu (not main menu) MUST also have a "Back to main menu" option
83
+ - Back buttons use blue color: `${chalk.blue('←')} Back to...`
84
+ - Main menu buttons use house emoji: `${chalk.blue('🏠')} Back to main menu`
85
+
86
+ ### Container Config
87
+ Each container has a `container.json` with:
88
+ ```typescript
89
+ type ContainerConfig = {
90
+ name: string
91
+ engine: string
92
+ version: string
93
+ port: number
94
+ database: string // User's database name (separate from container name)
95
+ created: string
96
+ status: 'created' | 'running' | 'stopped'
97
+ clonedFrom?: string
98
+ }
99
+ ```
100
+
101
+ The `database` field allows users to specify a custom database name in the connection string (e.g., `postgresql://postgres@localhost:5432/my-app-db`).
102
+
81
103
  ## Common Tasks
82
104
 
83
105
  ### Running the CLI
@@ -112,17 +134,24 @@ import { platform, arch } from 'os';
112
134
  // Mapped to zonky.io names in defaults.ts platformMappings
113
135
  ```
114
136
 
115
- ### Version Mapping
116
- Major versions (14, 15, 16, 17) map to full versions in `src/engines/postgresql/binary-urls.ts`:
137
+ ### Version Fetching
138
+ PostgreSQL versions are fetched dynamically from Maven Central with a 5-minute cache. Falls back to `FALLBACK_VERSION_MAP` if network fails. See `src/engines/postgresql/binary-urls.ts`:
139
+
117
140
  ```typescript
118
- const VERSION_MAP = {
119
- '14': '14.15.0',
120
- '15': '15.10.0',
121
- '16': '16.6.0',
122
- '17': '17.2.0'
123
- };
141
+ // Fallback versions (used when Maven is unreachable)
142
+ export const FALLBACK_VERSION_MAP: Record<string, string> = {
143
+ '14': '14.20.0',
144
+ '15': '15.15.0',
145
+ '16': '16.11.0',
146
+ '17': '17.7.0',
147
+ }
148
+
149
+ // Dynamic fetching from Maven
150
+ export async function fetchAvailableVersions(): Promise<Record<string, string[]>>
124
151
  ```
125
152
 
153
+ The create flow uses two-step version selection: first major version (14, 15, 16, 17), then specific minor version within that major.
154
+
126
155
  ### Port Management
127
156
  - Default port: 5432
128
157
  - If busy, scans 5432-5500 for available port
@@ -142,15 +171,16 @@ PID file location: `~/.spindb/containers/{name}/data/postmaster.pid`
142
171
  1. **No client tools bundled** - psql/pg_restore must be installed separately
143
172
  2. **macOS/Linux only** - No Windows support (zonky.io doesn't provide Windows binaries)
144
173
  3. **No backup command** - pg_dump must be run manually with system tools
145
- 4. **No automatic updates** - Binary versions are hardcoded in VERSION_MAP
174
+ 4. **Database names immutable** - Cannot rename database after creation (would require `ALTER DATABASE`)
146
175
 
147
- ## Future Improvements (Not Implemented)
176
+ ## Future Improvements
148
177
 
178
+ See `TODO.md` for full list. Key items:
149
179
  - [ ] Add `spindb backup` command (wrapper around pg_dump)
150
- - [ ] Support MySQL/SQLite engines (architecture supports it)
151
180
  - [ ] Add `spindb logs` command to tail postgres.log
152
181
  - [ ] Add `spindb exec` for running SQL files
153
- - [ ] Automatic binary version updates
182
+ - [ ] Database rename support
183
+ - [ ] Support MySQL/SQLite engines (architecture supports it)
154
184
  - [ ] Windows support (would need different binary source)
155
185
 
156
186
  ## Code Style Notes
package/README.md CHANGED
@@ -10,6 +10,9 @@ Spin up local PostgreSQL databases without Docker. A lightweight alternative to
10
10
  - **Auto port management** - Automatically finds available ports
11
11
  - **Clone containers** - Duplicate databases with all data
12
12
  - **Backup restore** - Restore pg_dump backups (requires system PostgreSQL client tools)
13
+ - **Custom database names** - Specify database name separate from container name
14
+ - **Engine management** - View installed PostgreSQL versions and free up disk space
15
+ - **Dynamic version selection** - Fetches all available versions from Maven Central
13
16
 
14
17
  ## Installation
15
18
 
@@ -109,10 +112,15 @@ spindb config set pg_restore /path/to/pg_restore
109
112
 
110
113
  ## Examples
111
114
 
112
- ### Create a database with specific version
115
+ ### Create a database with specific version and name
113
116
 
114
117
  ```bash
118
+ # Specify PostgreSQL version and port
115
119
  spindb create mydb --pg-version 15 --port 5433
120
+
121
+ # Specify a custom database name (different from container name)
122
+ spindb create mydb --database my_app_db
123
+ # Connection string: postgresql://postgres@localhost:5432/my_app_db
116
124
  ```
117
125
 
118
126
  ### Restore a backup
@@ -145,7 +153,21 @@ spindb start test-branch
145
153
  spindb connect mydb
146
154
 
147
155
  # Or use the connection string directly
148
- psql postgresql://postgres@localhost:5432/postgres
156
+ psql postgresql://postgres@localhost:5432/mydb
157
+ ```
158
+
159
+ ### Manage installed engines
160
+
161
+ 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.
162
+
163
+ ```
164
+ ENGINE VERSION PLATFORM SIZE
165
+ ────────────────────────────────────────────────────────
166
+ postgresql 17 darwin-arm64 45.2 MB
167
+ postgresql 16.9.0 darwin-arm64 44.8 MB
168
+ postgresql 16 darwin-arm64 44.8 MB
169
+ ────────────────────────────────────────────────────────
170
+ 3 version(s) 134.8 MB
149
171
  ```
150
172
 
151
173
  ## Configuration
@@ -201,4 +223,3 @@ rm -rf ~/.spindb
201
223
  ## License
202
224
 
203
225
  MIT
204
- # spindb
package/TODO.md CHANGED
@@ -14,16 +14,25 @@ Similar to ngrok - free tier for individual developers with core functionality,
14
14
  - [ ] **Run SQL file** - Add menu option to run a `.sql` file against a container (wrapper around `psql -f`)
15
15
  - [ ] **Backup command** - Add `spindb backup` to create dumps using `pg_dump`
16
16
  - [ ] **Logs command** - Add `spindb logs <container>` to tail `postgres.log`
17
- - [ ] **Engine/binary management** - Menu to list installed PostgreSQL versions, install new versions, uninstall unused versions (free up disk space)
17
+ - [x] **Engine/binary management** - Menu to list installed PostgreSQL versions, install new versions, uninstall unused versions (free up disk space)
18
18
 
19
19
  ### Medium Priority
20
- - [ ] **Container rename** - Rename a container without cloning/deleting
21
- - [ ] **Export connection string** - Copy connection string to clipboard
20
+ - [x] **Container rename** - Rename a container without cloning/deleting (via Edit menu)
21
+ - [ ] **Database rename** - Rename a database within a container (requires stopping container, running `ALTER DATABASE ... RENAME TO ...`, updating config)
22
+ - [x] **Export connection string** - Copy connection string to clipboard (via container submenu)
22
23
  - [ ] **Multiple databases per container** - List/create/delete databases within a container
24
+ - [x] **Fetch available versions** - Query Maven Central API to show all available PostgreSQL versions instead of hardcoded list
23
25
 
24
26
  ### Low Priority
25
27
  - [ ] **SQLite support** - Add SQLite engine
26
28
  - [ ] **Health checks** - Periodic connection tests to verify containers are responsive
29
+ - [ ] **Offline Support** - Package binaries locally for offline installation
30
+ - [ ] **Binary caching** - Cache downloaded binaries locally to avoid re-downloading
31
+ - [ ] **Binary version management** - List, install, and remove different PostgreSQL versions
32
+ - [ ] **Binary verification** - Verify downloaded binaries with checksums
33
+ - [ ] **Binary cleanup** - Remove old cached binaries to free up disk space
34
+ - [ ] **Binary space monitoring** - Show disk usage of cached binaries
35
+ - [ ] **Binary auto-cleanup** - Automatically remove old versions after a retention period
27
36
 
28
37
  ---
29
38
 
package/eslint.config.js CHANGED
@@ -5,9 +5,15 @@ export default tseslint.config(
5
5
  eslint.configs.recommended,
6
6
  ...tseslint.configs.recommended,
7
7
  {
8
- ignores: ['dist/', 'node_modules/', 'bin/'],
8
+ ignores: ['dist/', 'node_modules/', 'bin/', 'eslint.config.js'],
9
9
  },
10
10
  {
11
+ languageOptions: {
12
+ parserOptions: {
13
+ project: true,
14
+ tsconfigRootDir: import.meta.dirname,
15
+ },
16
+ },
11
17
  rules: {
12
18
  '@typescript-eslint/no-unused-vars': [
13
19
  'error',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spindb",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Spin up local database containers without Docker. A DBngin-like CLI for PostgreSQL.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,6 +17,7 @@ export const createCommand = new Command('create')
17
17
  'PostgreSQL version',
18
18
  defaults.postgresVersion,
19
19
  )
20
+ .option('-d, --database <database>', 'Database name')
20
21
  .option('-p, --port <port>', 'Port number')
21
22
  .option('--no-start', 'Do not start the container after creation')
22
23
  .action(
@@ -25,6 +26,7 @@ export const createCommand = new Command('create')
25
26
  options: {
26
27
  engine: string
27
28
  pgVersion: string
29
+ database?: string
28
30
  port?: string
29
31
  start: boolean
30
32
  },
@@ -33,6 +35,7 @@ export const createCommand = new Command('create')
33
35
  let containerName = name
34
36
  let engine = options.engine
35
37
  let version = options.pgVersion
38
+ let database = options.database
36
39
 
37
40
  // Interactive mode if no name provided
38
41
  if (!containerName) {
@@ -40,8 +43,12 @@ export const createCommand = new Command('create')
40
43
  containerName = answers.name
41
44
  engine = answers.engine
42
45
  version = answers.version
46
+ database = answers.database
43
47
  }
44
48
 
49
+ // Default database name to container name if not specified
50
+ database = database ?? containerName
51
+
45
52
  console.log(header('Creating Database Container'))
46
53
  console.log()
47
54
 
@@ -97,19 +104,20 @@ export const createCommand = new Command('create')
97
104
  engine: dbEngine.name,
98
105
  version,
99
106
  port,
107
+ database,
100
108
  })
101
109
 
102
110
  createSpinnerInstance.succeed('Container created')
103
111
 
104
- // Initialize database
105
- const initSpinner = createSpinner('Initializing database...')
112
+ // Initialize database cluster
113
+ const initSpinner = createSpinner('Initializing database cluster...')
106
114
  initSpinner.start()
107
115
 
108
116
  await dbEngine.initDataDir(containerName, version, {
109
117
  superuser: defaults.superuser,
110
118
  })
111
119
 
112
- initSpinner.succeed('Database initialized')
120
+ initSpinner.succeed('Database cluster initialized')
113
121
 
114
122
  // Start container if requested
115
123
  if (options.start !== false) {
@@ -125,6 +133,18 @@ export const createCommand = new Command('create')
125
133
  }
126
134
 
127
135
  startSpinner.succeed('PostgreSQL started')
136
+
137
+ // Create the user's database (if different from 'postgres')
138
+ if (config && database !== 'postgres') {
139
+ const dbSpinner = createSpinner(
140
+ `Creating database "${database}"...`,
141
+ )
142
+ dbSpinner.start()
143
+
144
+ await dbEngine.createDatabase(config, database)
145
+
146
+ dbSpinner.succeed(`Database "${database}" created`)
147
+ }
128
148
  }
129
149
 
130
150
  // Show success message