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 +77 -100
- package/cli/commands/clone.ts +3 -1
- package/cli/commands/connect.ts +50 -24
- package/cli/commands/create.ts +265 -112
- package/cli/commands/delete.ts +3 -1
- package/cli/commands/list.ts +14 -3
- package/cli/commands/menu.ts +250 -84
- package/cli/commands/restore.ts +142 -38
- package/cli/commands/start.ts +30 -4
- package/cli/commands/stop.ts +3 -1
- package/cli/ui/prompts.ts +95 -32
- package/config/defaults.ts +40 -15
- package/config/engine-defaults.ts +84 -0
- package/config/os-dependencies.ts +68 -19
- package/config/paths.ts +116 -23
- package/core/binary-manager.ts +30 -5
- package/core/container-manager.ts +124 -60
- package/core/dependency-manager.ts +44 -22
- package/core/port-manager.ts +42 -31
- package/core/postgres-binary-manager.ts +10 -9
- package/core/process-manager.ts +14 -6
- package/engines/index.ts +7 -2
- package/engines/mysql/binary-detection.ts +248 -0
- package/engines/mysql/index.ts +699 -0
- package/engines/postgresql/index.ts +13 -6
- package/package.json +4 -2
- package/types/index.ts +29 -5
|
@@ -0,0 +1,248 @@
|
|
|
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 { existsSync } from 'fs'
|
|
9
|
+
import { platform } from 'os'
|
|
10
|
+
|
|
11
|
+
const execAsync = promisify(exec)
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Common paths where MySQL binaries might be installed
|
|
15
|
+
*/
|
|
16
|
+
const MYSQL_SEARCH_PATHS = {
|
|
17
|
+
darwin: [
|
|
18
|
+
// Homebrew (Apple Silicon)
|
|
19
|
+
'/opt/homebrew/bin',
|
|
20
|
+
'/opt/homebrew/opt/mysql/bin',
|
|
21
|
+
'/opt/homebrew/opt/mysql@8.0/bin',
|
|
22
|
+
'/opt/homebrew/opt/mysql@8.4/bin',
|
|
23
|
+
'/opt/homebrew/opt/mysql@5.7/bin',
|
|
24
|
+
// Homebrew (Intel)
|
|
25
|
+
'/usr/local/bin',
|
|
26
|
+
'/usr/local/opt/mysql/bin',
|
|
27
|
+
'/usr/local/opt/mysql@8.0/bin',
|
|
28
|
+
'/usr/local/opt/mysql@8.4/bin',
|
|
29
|
+
'/usr/local/opt/mysql@5.7/bin',
|
|
30
|
+
// Official MySQL installer
|
|
31
|
+
'/usr/local/mysql/bin',
|
|
32
|
+
],
|
|
33
|
+
linux: [
|
|
34
|
+
'/usr/bin',
|
|
35
|
+
'/usr/sbin',
|
|
36
|
+
'/usr/local/bin',
|
|
37
|
+
'/usr/local/mysql/bin',
|
|
38
|
+
],
|
|
39
|
+
win32: [
|
|
40
|
+
'C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin',
|
|
41
|
+
'C:\\Program Files\\MySQL\\MySQL Server 8.4\\bin',
|
|
42
|
+
'C:\\Program Files\\MySQL\\MySQL Server 5.7\\bin',
|
|
43
|
+
],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get search paths for the current platform
|
|
48
|
+
*/
|
|
49
|
+
function getSearchPaths(): string[] {
|
|
50
|
+
const plat = platform()
|
|
51
|
+
return MYSQL_SEARCH_PATHS[plat as keyof typeof MYSQL_SEARCH_PATHS] || []
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if a binary exists at the given path
|
|
56
|
+
*/
|
|
57
|
+
function binaryExists(path: string): boolean {
|
|
58
|
+
return existsSync(path)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Find a MySQL binary by name
|
|
63
|
+
*/
|
|
64
|
+
export async function findMysqlBinary(
|
|
65
|
+
name: string,
|
|
66
|
+
): Promise<string | null> {
|
|
67
|
+
// First, try using 'which' or 'where' command
|
|
68
|
+
try {
|
|
69
|
+
const cmd = platform() === 'win32' ? 'where' : 'which'
|
|
70
|
+
const { stdout } = await execAsync(`${cmd} ${name}`)
|
|
71
|
+
const path = stdout.trim().split('\n')[0]
|
|
72
|
+
if (path && binaryExists(path)) {
|
|
73
|
+
return path
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
// Not found in PATH, continue to search common locations
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Search common installation paths
|
|
80
|
+
const searchPaths = getSearchPaths()
|
|
81
|
+
for (const dir of searchPaths) {
|
|
82
|
+
const fullPath = platform() === 'win32'
|
|
83
|
+
? `${dir}\\${name}.exe`
|
|
84
|
+
: `${dir}/${name}`
|
|
85
|
+
if (binaryExists(fullPath)) {
|
|
86
|
+
return fullPath
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get the path to mysqld (MySQL server)
|
|
95
|
+
*/
|
|
96
|
+
export async function getMysqldPath(): Promise<string | null> {
|
|
97
|
+
return findMysqlBinary('mysqld')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the path to mysql client
|
|
102
|
+
*/
|
|
103
|
+
export async function getMysqlClientPath(): Promise<string | null> {
|
|
104
|
+
return findMysqlBinary('mysql')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get the path to mysqladmin
|
|
109
|
+
*/
|
|
110
|
+
export async function getMysqladminPath(): Promise<string | null> {
|
|
111
|
+
return findMysqlBinary('mysqladmin')
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get the path to mysqldump
|
|
116
|
+
*/
|
|
117
|
+
export async function getMysqldumpPath(): Promise<string | null> {
|
|
118
|
+
return findMysqlBinary('mysqldump')
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get the path to mysql_install_db (MariaDB initialization script)
|
|
123
|
+
*/
|
|
124
|
+
export async function getMysqlInstallDbPath(): Promise<string | null> {
|
|
125
|
+
return findMysqlBinary('mysql_install_db')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get the path to mariadb-install-db (alternative MariaDB initialization)
|
|
130
|
+
*/
|
|
131
|
+
export async function getMariadbInstallDbPath(): Promise<string | null> {
|
|
132
|
+
return findMysqlBinary('mariadb-install-db')
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Detect if the installed MySQL is actually MariaDB
|
|
137
|
+
*/
|
|
138
|
+
export async function isMariaDB(): Promise<boolean> {
|
|
139
|
+
const mysqld = await getMysqldPath()
|
|
140
|
+
if (!mysqld) return false
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
const { stdout } = await execAsync(`"${mysqld}" --version`)
|
|
144
|
+
return stdout.toLowerCase().includes('mariadb')
|
|
145
|
+
} catch {
|
|
146
|
+
return false
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get the MySQL server version from a mysqld binary
|
|
152
|
+
*/
|
|
153
|
+
export async function getMysqlVersion(
|
|
154
|
+
mysqldPath: string,
|
|
155
|
+
): Promise<string | null> {
|
|
156
|
+
try {
|
|
157
|
+
const { stdout } = await execAsync(`"${mysqldPath}" --version`)
|
|
158
|
+
// Example output: mysqld Ver 8.0.35 for macos14.0 on arm64 (Homebrew)
|
|
159
|
+
const match = stdout.match(/Ver\s+(\d+\.\d+\.\d+)/)
|
|
160
|
+
return match ? match[1] : null
|
|
161
|
+
} catch {
|
|
162
|
+
return null
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get the major version from a full version string
|
|
168
|
+
* e.g., "8.0.35" -> "8.0"
|
|
169
|
+
*/
|
|
170
|
+
export function getMajorVersion(fullVersion: string): string {
|
|
171
|
+
const parts = fullVersion.split('.')
|
|
172
|
+
return `${parts[0]}.${parts[1]}`
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Detect all installed MySQL versions
|
|
177
|
+
* Returns a map of major version -> full version string
|
|
178
|
+
*/
|
|
179
|
+
export async function detectInstalledVersions(): Promise<
|
|
180
|
+
Record<string, string>
|
|
181
|
+
> {
|
|
182
|
+
const versions: Record<string, string> = {}
|
|
183
|
+
|
|
184
|
+
// Check default mysqld
|
|
185
|
+
const defaultMysqld = await getMysqldPath()
|
|
186
|
+
if (defaultMysqld) {
|
|
187
|
+
const version = await getMysqlVersion(defaultMysqld)
|
|
188
|
+
if (version) {
|
|
189
|
+
const major = getMajorVersion(version)
|
|
190
|
+
versions[major] = version
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Check versioned Homebrew installations
|
|
195
|
+
const homebrewPaths = platform() === 'darwin'
|
|
196
|
+
? [
|
|
197
|
+
'/opt/homebrew/opt/mysql@5.7/bin/mysqld',
|
|
198
|
+
'/opt/homebrew/opt/mysql@8.0/bin/mysqld',
|
|
199
|
+
'/opt/homebrew/opt/mysql@8.4/bin/mysqld',
|
|
200
|
+
'/usr/local/opt/mysql@5.7/bin/mysqld',
|
|
201
|
+
'/usr/local/opt/mysql@8.0/bin/mysqld',
|
|
202
|
+
'/usr/local/opt/mysql@8.4/bin/mysqld',
|
|
203
|
+
]
|
|
204
|
+
: []
|
|
205
|
+
|
|
206
|
+
for (const path of homebrewPaths) {
|
|
207
|
+
if (binaryExists(path)) {
|
|
208
|
+
const version = await getMysqlVersion(path)
|
|
209
|
+
if (version) {
|
|
210
|
+
const major = getMajorVersion(version)
|
|
211
|
+
if (!versions[major]) {
|
|
212
|
+
versions[major] = version
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return versions
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get install instructions for MySQL
|
|
223
|
+
*/
|
|
224
|
+
export function getInstallInstructions(): string {
|
|
225
|
+
const plat = platform()
|
|
226
|
+
|
|
227
|
+
if (plat === 'darwin') {
|
|
228
|
+
return (
|
|
229
|
+
'MySQL server not found. Install MySQL:\n' +
|
|
230
|
+
' brew install mysql\n' +
|
|
231
|
+
' # or for a specific version:\n' +
|
|
232
|
+
' brew install mysql@8.0'
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (plat === 'linux') {
|
|
237
|
+
return (
|
|
238
|
+
'MySQL server not found. Install MySQL:\n' +
|
|
239
|
+
' Ubuntu/Debian: sudo apt install mysql-server\n' +
|
|
240
|
+
' RHEL/CentOS: sudo yum install mysql-server'
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
'MySQL server not found. Please install MySQL from:\n' +
|
|
246
|
+
' https://dev.mysql.com/downloads/mysql/'
|
|
247
|
+
)
|
|
248
|
+
}
|