spindb 0.4.1 → 0.5.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.
- package/README.md +207 -101
- package/cli/commands/clone.ts +3 -1
- package/cli/commands/connect.ts +54 -24
- package/cli/commands/create.ts +309 -189
- package/cli/commands/delete.ts +3 -1
- package/cli/commands/deps.ts +19 -4
- package/cli/commands/edit.ts +245 -0
- package/cli/commands/engines.ts +434 -0
- package/cli/commands/info.ts +279 -0
- package/cli/commands/list.ts +14 -3
- package/cli/commands/menu.ts +510 -198
- package/cli/commands/restore.ts +66 -43
- package/cli/commands/start.ts +50 -19
- package/cli/commands/stop.ts +3 -1
- package/cli/commands/url.ts +79 -0
- package/cli/index.ts +9 -3
- package/cli/ui/prompts.ts +99 -34
- package/config/defaults.ts +40 -15
- package/config/engine-defaults.ts +107 -0
- package/config/os-dependencies.ts +119 -124
- package/config/paths.ts +82 -56
- package/core/binary-manager.ts +44 -6
- package/core/config-manager.ts +17 -5
- package/core/container-manager.ts +124 -60
- package/core/dependency-manager.ts +9 -15
- package/core/error-handler.ts +336 -0
- package/core/platform-service.ts +634 -0
- package/core/port-manager.ts +51 -32
- package/core/process-manager.ts +26 -8
- package/core/start-with-retry.ts +167 -0
- package/core/transaction-manager.ts +170 -0
- package/engines/index.ts +7 -2
- package/engines/mysql/binary-detection.ts +325 -0
- package/engines/mysql/index.ts +808 -0
- package/engines/mysql/restore.ts +257 -0
- package/engines/mysql/version-validator.ts +373 -0
- package/{core/postgres-binary-manager.ts → engines/postgresql/binary-manager.ts} +63 -23
- package/engines/postgresql/binary-urls.ts +5 -3
- package/engines/postgresql/index.ts +17 -9
- package/engines/postgresql/restore.ts +54 -5
- package/engines/postgresql/version-validator.ts +262 -0
- package/package.json +9 -3
- package/types/index.ts +29 -5
- package/cli/commands/postgres-tools.ts +0 -216
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MySQL binary detection for system-installed MySQL
|
|
3
|
+
* Detects MySQL installations from Homebrew, apt, or other package managers
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { exec } from 'child_process'
|
|
7
|
+
import { promisify } from 'util'
|
|
8
|
+
import { platformService } from '../../core/platform-service'
|
|
9
|
+
|
|
10
|
+
const execAsync = promisify(exec)
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Find a MySQL binary by name using the platform service
|
|
14
|
+
*/
|
|
15
|
+
export async function findMysqlBinary(name: string): Promise<string | null> {
|
|
16
|
+
return platformService.findToolPath(name)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get the path to mysqld (MySQL server)
|
|
21
|
+
*/
|
|
22
|
+
export async function getMysqldPath(): Promise<string | null> {
|
|
23
|
+
return findMysqlBinary('mysqld')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get the path to mysql client
|
|
28
|
+
*/
|
|
29
|
+
export async function getMysqlClientPath(): Promise<string | null> {
|
|
30
|
+
return findMysqlBinary('mysql')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get the path to mysqladmin
|
|
35
|
+
*/
|
|
36
|
+
export async function getMysqladminPath(): Promise<string | null> {
|
|
37
|
+
return findMysqlBinary('mysqladmin')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the path to mysqldump
|
|
42
|
+
*/
|
|
43
|
+
export async function getMysqldumpPath(): Promise<string | null> {
|
|
44
|
+
return findMysqlBinary('mysqldump')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the path to mysql_install_db (MariaDB initialization script)
|
|
49
|
+
*/
|
|
50
|
+
export async function getMysqlInstallDbPath(): Promise<string | null> {
|
|
51
|
+
return findMysqlBinary('mysql_install_db')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get the path to mariadb-install-db (alternative MariaDB initialization)
|
|
56
|
+
*/
|
|
57
|
+
export async function getMariadbInstallDbPath(): Promise<string | null> {
|
|
58
|
+
return findMysqlBinary('mariadb-install-db')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Detect if the installed MySQL is actually MariaDB
|
|
63
|
+
*/
|
|
64
|
+
export async function isMariaDB(): Promise<boolean> {
|
|
65
|
+
const mysqld = await getMysqldPath()
|
|
66
|
+
if (!mysqld) return false
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const { stdout } = await execAsync(`"${mysqld}" --version`)
|
|
70
|
+
return stdout.toLowerCase().includes('mariadb')
|
|
71
|
+
} catch {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get the MySQL server version from a mysqld binary
|
|
78
|
+
*/
|
|
79
|
+
export async function getMysqlVersion(
|
|
80
|
+
mysqldPath: string,
|
|
81
|
+
): Promise<string | null> {
|
|
82
|
+
try {
|
|
83
|
+
const { stdout } = await execAsync(`"${mysqldPath}" --version`)
|
|
84
|
+
// Example output: mysqld Ver 8.0.35 for macos14.0 on arm64 (Homebrew)
|
|
85
|
+
const match = stdout.match(/Ver\s+(\d+\.\d+\.\d+)/)
|
|
86
|
+
return match ? match[1] : null
|
|
87
|
+
} catch {
|
|
88
|
+
return null
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the major version from a full version string
|
|
94
|
+
* e.g., "8.0.35" -> "8.0"
|
|
95
|
+
*/
|
|
96
|
+
export function getMajorVersion(fullVersion: string): string {
|
|
97
|
+
const parts = fullVersion.split('.')
|
|
98
|
+
return `${parts[0]}.${parts[1]}`
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Detect all installed MySQL versions
|
|
103
|
+
* Returns a map of major version -> full version string
|
|
104
|
+
*/
|
|
105
|
+
export async function detectInstalledVersions(): Promise<
|
|
106
|
+
Record<string, string>
|
|
107
|
+
> {
|
|
108
|
+
const versions: Record<string, string> = {}
|
|
109
|
+
const { platform } = platformService.getPlatformInfo()
|
|
110
|
+
|
|
111
|
+
// Check default mysqld
|
|
112
|
+
const defaultMysqld = await getMysqldPath()
|
|
113
|
+
if (defaultMysqld) {
|
|
114
|
+
const version = await getMysqlVersion(defaultMysqld)
|
|
115
|
+
if (version) {
|
|
116
|
+
const major = getMajorVersion(version)
|
|
117
|
+
versions[major] = version
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Check versioned Homebrew installations (macOS only)
|
|
122
|
+
if (platform === 'darwin') {
|
|
123
|
+
const homebrewPaths = [
|
|
124
|
+
'/opt/homebrew/opt/mysql@5.7/bin/mysqld',
|
|
125
|
+
'/opt/homebrew/opt/mysql@8.0/bin/mysqld',
|
|
126
|
+
'/opt/homebrew/opt/mysql@8.4/bin/mysqld',
|
|
127
|
+
'/usr/local/opt/mysql@5.7/bin/mysqld',
|
|
128
|
+
'/usr/local/opt/mysql@8.0/bin/mysqld',
|
|
129
|
+
'/usr/local/opt/mysql@8.4/bin/mysqld',
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
const { existsSync } = await import('fs')
|
|
133
|
+
for (const path of homebrewPaths) {
|
|
134
|
+
if (existsSync(path)) {
|
|
135
|
+
const version = await getMysqlVersion(path)
|
|
136
|
+
if (version) {
|
|
137
|
+
const major = getMajorVersion(version)
|
|
138
|
+
if (!versions[major]) {
|
|
139
|
+
versions[major] = version
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return versions
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get install instructions for MySQL
|
|
151
|
+
*/
|
|
152
|
+
export function getInstallInstructions(): string {
|
|
153
|
+
const { platform } = platformService.getPlatformInfo()
|
|
154
|
+
|
|
155
|
+
if (platform === 'darwin') {
|
|
156
|
+
return (
|
|
157
|
+
'MySQL server not found. Install MySQL:\n' +
|
|
158
|
+
' brew install mysql\n' +
|
|
159
|
+
' # or for a specific version:\n' +
|
|
160
|
+
' brew install mysql@8.0'
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (platform === 'linux') {
|
|
165
|
+
return (
|
|
166
|
+
'MySQL server not found. Install MySQL:\n' +
|
|
167
|
+
' Ubuntu/Debian: sudo apt install mysql-server\n' +
|
|
168
|
+
' RHEL/CentOS: sudo yum install mysql-server'
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
'MySQL server not found. Please install MySQL from:\n' +
|
|
174
|
+
' https://dev.mysql.com/downloads/mysql/'
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export type MysqlPackageManager =
|
|
179
|
+
| 'homebrew'
|
|
180
|
+
| 'apt'
|
|
181
|
+
| 'yum'
|
|
182
|
+
| 'dnf'
|
|
183
|
+
| 'pacman'
|
|
184
|
+
| 'unknown'
|
|
185
|
+
|
|
186
|
+
export type MysqlInstallInfo = {
|
|
187
|
+
packageManager: MysqlPackageManager
|
|
188
|
+
packageName: string
|
|
189
|
+
path: string
|
|
190
|
+
uninstallCommand: string
|
|
191
|
+
isMariaDB: boolean
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Detect which package manager installed MySQL and get uninstall info
|
|
196
|
+
*/
|
|
197
|
+
export async function getMysqlInstallInfo(
|
|
198
|
+
mysqldPath: string,
|
|
199
|
+
): Promise<MysqlInstallInfo> {
|
|
200
|
+
const { platform } = platformService.getPlatformInfo()
|
|
201
|
+
const mariadb = await isMariaDB()
|
|
202
|
+
|
|
203
|
+
// macOS: Check if path is in Homebrew directories
|
|
204
|
+
if (platform === 'darwin') {
|
|
205
|
+
if (
|
|
206
|
+
mysqldPath.includes('/opt/homebrew/') ||
|
|
207
|
+
mysqldPath.includes('/usr/local/Cellar/')
|
|
208
|
+
) {
|
|
209
|
+
// Extract package name from path
|
|
210
|
+
// e.g., /opt/homebrew/opt/mysql@8.0/bin/mysqld -> mysql@8.0
|
|
211
|
+
// e.g., /opt/homebrew/bin/mysqld -> mysql (linked)
|
|
212
|
+
let packageName = mariadb ? 'mariadb' : 'mysql'
|
|
213
|
+
|
|
214
|
+
const versionMatch = mysqldPath.match(/mysql@(\d+\.\d+)/)
|
|
215
|
+
if (versionMatch) {
|
|
216
|
+
packageName = `mysql@${versionMatch[1]}`
|
|
217
|
+
} else {
|
|
218
|
+
// Try to get from Homebrew directly
|
|
219
|
+
try {
|
|
220
|
+
const { stdout } = await execAsync('brew list --formula')
|
|
221
|
+
const packages = stdout.split('\n')
|
|
222
|
+
const mysqlPackage = packages.find(
|
|
223
|
+
(p) =>
|
|
224
|
+
p.startsWith('mysql') ||
|
|
225
|
+
p.startsWith('mariadb') ||
|
|
226
|
+
p === 'percona-server',
|
|
227
|
+
)
|
|
228
|
+
if (mysqlPackage) {
|
|
229
|
+
packageName = mysqlPackage
|
|
230
|
+
}
|
|
231
|
+
} catch {
|
|
232
|
+
// Ignore errors
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
packageManager: 'homebrew',
|
|
238
|
+
packageName,
|
|
239
|
+
path: mysqldPath,
|
|
240
|
+
uninstallCommand: `brew uninstall ${packageName}`,
|
|
241
|
+
isMariaDB: mariadb,
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Linux: Detect package manager from path or check installed packages
|
|
247
|
+
if (platform === 'linux') {
|
|
248
|
+
// Check for apt (Debian/Ubuntu)
|
|
249
|
+
try {
|
|
250
|
+
const { stdout } = await execAsync('which apt 2>/dev/null')
|
|
251
|
+
if (stdout.trim()) {
|
|
252
|
+
const packageName = mariadb ? 'mariadb-server' : 'mysql-server'
|
|
253
|
+
return {
|
|
254
|
+
packageManager: 'apt',
|
|
255
|
+
packageName,
|
|
256
|
+
path: mysqldPath,
|
|
257
|
+
uninstallCommand: `sudo apt remove ${packageName}`,
|
|
258
|
+
isMariaDB: mariadb,
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
} catch {
|
|
262
|
+
// Not apt
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Check for dnf (Fedora/RHEL 8+)
|
|
266
|
+
try {
|
|
267
|
+
const { stdout } = await execAsync('which dnf 2>/dev/null')
|
|
268
|
+
if (stdout.trim()) {
|
|
269
|
+
const packageName = mariadb ? 'mariadb-server' : 'mysql-server'
|
|
270
|
+
return {
|
|
271
|
+
packageManager: 'dnf',
|
|
272
|
+
packageName,
|
|
273
|
+
path: mysqldPath,
|
|
274
|
+
uninstallCommand: `sudo dnf remove ${packageName}`,
|
|
275
|
+
isMariaDB: mariadb,
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} catch {
|
|
279
|
+
// Not dnf
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Check for yum (CentOS/RHEL 7)
|
|
283
|
+
try {
|
|
284
|
+
const { stdout } = await execAsync('which yum 2>/dev/null')
|
|
285
|
+
if (stdout.trim()) {
|
|
286
|
+
const packageName = mariadb ? 'mariadb-server' : 'mysql-server'
|
|
287
|
+
return {
|
|
288
|
+
packageManager: 'yum',
|
|
289
|
+
packageName,
|
|
290
|
+
path: mysqldPath,
|
|
291
|
+
uninstallCommand: `sudo yum remove ${packageName}`,
|
|
292
|
+
isMariaDB: mariadb,
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
} catch {
|
|
296
|
+
// Not yum
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Check for pacman (Arch Linux)
|
|
300
|
+
try {
|
|
301
|
+
const { stdout } = await execAsync('which pacman 2>/dev/null')
|
|
302
|
+
if (stdout.trim()) {
|
|
303
|
+
const packageName = mariadb ? 'mariadb' : 'mysql'
|
|
304
|
+
return {
|
|
305
|
+
packageManager: 'pacman',
|
|
306
|
+
packageName,
|
|
307
|
+
path: mysqldPath,
|
|
308
|
+
uninstallCommand: `sudo pacman -Rs ${packageName}`,
|
|
309
|
+
isMariaDB: mariadb,
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
// Not pacman
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Unknown package manager
|
|
318
|
+
return {
|
|
319
|
+
packageManager: 'unknown',
|
|
320
|
+
packageName: mariadb ? 'mariadb' : 'mysql',
|
|
321
|
+
path: mysqldPath,
|
|
322
|
+
uninstallCommand: 'Use your system package manager to uninstall',
|
|
323
|
+
isMariaDB: mariadb,
|
|
324
|
+
}
|
|
325
|
+
}
|