spindb 0.5.2 → 0.5.4

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.
Files changed (38) hide show
  1. package/README.md +188 -9
  2. package/cli/commands/connect.ts +334 -105
  3. package/cli/commands/create.ts +106 -67
  4. package/cli/commands/deps.ts +19 -4
  5. package/cli/commands/edit.ts +245 -0
  6. package/cli/commands/engines.ts +434 -0
  7. package/cli/commands/info.ts +279 -0
  8. package/cli/commands/list.ts +1 -1
  9. package/cli/commands/menu.ts +664 -167
  10. package/cli/commands/restore.ts +11 -25
  11. package/cli/commands/start.ts +25 -20
  12. package/cli/commands/url.ts +79 -0
  13. package/cli/index.ts +9 -3
  14. package/cli/ui/prompts.ts +20 -12
  15. package/cli/ui/theme.ts +1 -1
  16. package/config/engine-defaults.ts +24 -1
  17. package/config/os-dependencies.ts +151 -113
  18. package/config/paths.ts +7 -36
  19. package/core/binary-manager.ts +12 -6
  20. package/core/config-manager.ts +17 -5
  21. package/core/dependency-manager.ts +144 -15
  22. package/core/error-handler.ts +336 -0
  23. package/core/platform-service.ts +634 -0
  24. package/core/port-manager.ts +11 -3
  25. package/core/process-manager.ts +12 -2
  26. package/core/start-with-retry.ts +167 -0
  27. package/core/transaction-manager.ts +170 -0
  28. package/engines/mysql/binary-detection.ts +177 -100
  29. package/engines/mysql/index.ts +240 -131
  30. package/engines/mysql/restore.ts +257 -0
  31. package/engines/mysql/version-validator.ts +373 -0
  32. package/{core/postgres-binary-manager.ts → engines/postgresql/binary-manager.ts} +63 -23
  33. package/engines/postgresql/binary-urls.ts +5 -3
  34. package/engines/postgresql/index.ts +35 -4
  35. package/engines/postgresql/restore.ts +54 -5
  36. package/engines/postgresql/version-validator.ts +262 -0
  37. package/package.json +6 -2
  38. package/cli/commands/postgres-tools.ts +0 -216
@@ -5,9 +5,11 @@
5
5
  * across different operating systems and package managers.
6
6
  */
7
7
 
8
+ import { getPostgresHomebrewPackage } from './engine-defaults'
9
+
8
10
  export type PackageManagerId = 'brew' | 'apt' | 'yum' | 'dnf' | 'pacman'
9
11
 
10
- export type Platform = 'darwin' | 'linux'
12
+ export type Platform = 'darwin' | 'linux' | 'win32'
11
13
 
12
14
  /**
13
15
  * Package definition for a specific package manager
@@ -116,122 +118,66 @@ export const packageManagers: PackageManagerConfig[] = [
116
118
  // PostgreSQL Dependencies
117
119
  // =============================================================================
118
120
 
121
+ /**
122
+ * Helper to create PostgreSQL client tool dependency
123
+ * Uses getPostgresHomebrewPackage() to get the current latest version
124
+ */
125
+ function createPostgresDependency(
126
+ name: string,
127
+ binary: string,
128
+ description: string,
129
+ ): Dependency {
130
+ const pgPackage = getPostgresHomebrewPackage()
131
+ return {
132
+ name,
133
+ binary,
134
+ description,
135
+ packages: {
136
+ brew: {
137
+ package: pgPackage,
138
+ postInstall: [`brew link --overwrite ${pgPackage}`],
139
+ },
140
+ apt: { package: 'postgresql-client' },
141
+ yum: { package: 'postgresql' },
142
+ dnf: { package: 'postgresql' },
143
+ pacman: { package: 'postgresql-libs' },
144
+ },
145
+ manualInstall: {
146
+ darwin: [
147
+ 'Install Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
148
+ `Then run: brew install ${pgPackage} && brew link --overwrite ${pgPackage}`,
149
+ 'Or install Postgres.app: https://postgresapp.com/downloads.html',
150
+ ],
151
+ linux: [
152
+ 'Ubuntu/Debian: sudo apt install postgresql-client',
153
+ 'CentOS/RHEL: sudo yum install postgresql',
154
+ 'Fedora: sudo dnf install postgresql',
155
+ 'Arch: sudo pacman -S postgresql-libs',
156
+ ],
157
+ },
158
+ }
159
+ }
160
+
119
161
  const postgresqlDependencies: EngineDependencies = {
120
162
  engine: 'postgresql',
121
163
  displayName: 'PostgreSQL',
122
164
  dependencies: [
123
- {
124
- name: 'psql',
125
- binary: 'psql',
126
- description: 'PostgreSQL interactive terminal',
127
- packages: {
128
- brew: {
129
- package: 'postgresql@17',
130
- postInstall: ['brew link --overwrite postgresql@17'],
131
- },
132
- apt: { package: 'postgresql-client' },
133
- yum: { package: 'postgresql' },
134
- dnf: { package: 'postgresql' },
135
- pacman: { package: 'postgresql-libs' },
136
- },
137
- manualInstall: {
138
- darwin: [
139
- 'Install Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
140
- 'Then run: brew install postgresql@17 && brew link --overwrite postgresql@17',
141
- 'Or install Postgres.app: https://postgresapp.com/downloads.html',
142
- ],
143
- linux: [
144
- 'Ubuntu/Debian: sudo apt install postgresql-client',
145
- 'CentOS/RHEL: sudo yum install postgresql',
146
- 'Fedora: sudo dnf install postgresql',
147
- 'Arch: sudo pacman -S postgresql-libs',
148
- ],
149
- },
150
- },
151
- {
152
- name: 'pg_dump',
153
- binary: 'pg_dump',
154
- description: 'PostgreSQL database backup utility',
155
- packages: {
156
- brew: {
157
- package: 'postgresql@17',
158
- postInstall: ['brew link --overwrite postgresql@17'],
159
- },
160
- apt: { package: 'postgresql-client' },
161
- yum: { package: 'postgresql' },
162
- dnf: { package: 'postgresql' },
163
- pacman: { package: 'postgresql-libs' },
164
- },
165
- manualInstall: {
166
- darwin: [
167
- 'Install Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
168
- 'Then run: brew install postgresql@17 && brew link --overwrite postgresql@17',
169
- 'Or install Postgres.app: https://postgresapp.com/downloads.html',
170
- ],
171
- linux: [
172
- 'Ubuntu/Debian: sudo apt install postgresql-client',
173
- 'CentOS/RHEL: sudo yum install postgresql',
174
- 'Fedora: sudo dnf install postgresql',
175
- 'Arch: sudo pacman -S postgresql-libs',
176
- ],
177
- },
178
- },
179
- {
180
- name: 'pg_restore',
181
- binary: 'pg_restore',
182
- description: 'PostgreSQL database restore utility',
183
- packages: {
184
- brew: {
185
- package: 'postgresql@17',
186
- postInstall: ['brew link --overwrite postgresql@17'],
187
- },
188
- apt: { package: 'postgresql-client' },
189
- yum: { package: 'postgresql' },
190
- dnf: { package: 'postgresql' },
191
- pacman: { package: 'postgresql-libs' },
192
- },
193
- manualInstall: {
194
- darwin: [
195
- 'Install Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
196
- 'Then run: brew install postgresql@17 && brew link --overwrite postgresql@17',
197
- 'Or install Postgres.app: https://postgresapp.com/downloads.html',
198
- ],
199
- linux: [
200
- 'Ubuntu/Debian: sudo apt install postgresql-client',
201
- 'CentOS/RHEL: sudo yum install postgresql',
202
- 'Fedora: sudo dnf install postgresql',
203
- 'Arch: sudo pacman -S postgresql-libs',
204
- ],
205
- },
206
- },
207
- {
208
- name: 'pg_basebackup',
209
- binary: 'pg_basebackup',
210
- description: 'PostgreSQL base backup utility for physical backups',
211
- packages: {
212
- brew: {
213
- package: 'postgresql@17',
214
- postInstall: ['brew link --overwrite postgresql@17'],
215
- },
216
- apt: { package: 'postgresql-client' },
217
- yum: { package: 'postgresql' },
218
- dnf: { package: 'postgresql' },
219
- pacman: { package: 'postgresql-libs' },
220
- },
221
- manualInstall: {
222
- darwin: [
223
- 'Install Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
224
- 'Then run: brew install postgresql@17 && brew link --overwrite postgresql@17',
225
- 'Or install Postgres.app: https://postgresapp.com/downloads.html',
226
- ],
227
- linux: [
228
- 'Ubuntu/Debian: sudo apt install postgresql-client',
229
- 'CentOS/RHEL: sudo yum install postgresql',
230
- 'Fedora: sudo dnf install postgresql',
231
- 'Arch: sudo pacman -S postgresql-libs',
232
- ],
233
- },
234
- },
165
+ createPostgresDependency('psql', 'psql', 'PostgreSQL interactive terminal'),
166
+ createPostgresDependency(
167
+ 'pg_dump',
168
+ 'pg_dump',
169
+ 'PostgreSQL database backup utility',
170
+ ),
171
+ createPostgresDependency(
172
+ 'pg_restore',
173
+ 'pg_restore',
174
+ 'PostgreSQL database restore utility',
175
+ ),
176
+ createPostgresDependency(
177
+ 'pg_basebackup',
178
+ 'pg_basebackup',
179
+ 'PostgreSQL base backup utility for physical backups',
180
+ ),
235
181
  ],
236
182
  }
237
183
 
@@ -343,6 +289,98 @@ const mysqlDependencies: EngineDependencies = {
343
289
  ],
344
290
  }
345
291
 
292
+ // =============================================================================
293
+ // Optional Tools (engine-agnostic)
294
+ // =============================================================================
295
+
296
+ /**
297
+ * usql - Universal SQL client
298
+ * Works with PostgreSQL, MySQL, SQLite, and 20+ other databases
299
+ * https://github.com/xo/usql
300
+ */
301
+ export const usqlDependency: Dependency = {
302
+ name: 'usql',
303
+ binary: 'usql',
304
+ description:
305
+ 'Universal SQL client with auto-completion, syntax highlighting, and multi-database support',
306
+ packages: {
307
+ brew: {
308
+ package: 'xo/xo/usql',
309
+ preInstall: ['brew tap xo/xo'],
310
+ },
311
+ // Note: usql is not in standard Linux package repos, must use manual install
312
+ },
313
+ manualInstall: {
314
+ darwin: [
315
+ 'Install Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
316
+ 'Then run: brew tap xo/xo && brew install xo/xo/usql',
317
+ ],
318
+ linux: [
319
+ 'Download from GitHub releases: https://github.com/xo/usql/releases',
320
+ 'Extract and move to PATH: sudo mv usql /usr/local/bin/',
321
+ 'Or install via Go: go install github.com/xo/usql@latest',
322
+ ],
323
+ },
324
+ }
325
+
326
+ /**
327
+ * pgcli - PostgreSQL CLI with auto-completion and syntax highlighting
328
+ * https://github.com/dbcli/pgcli
329
+ */
330
+ export const pgcliDependency: Dependency = {
331
+ name: 'pgcli',
332
+ binary: 'pgcli',
333
+ description:
334
+ 'PostgreSQL CLI with intelligent auto-completion and syntax highlighting',
335
+ packages: {
336
+ brew: { package: 'pgcli' },
337
+ apt: { package: 'pgcli' },
338
+ dnf: { package: 'pgcli' },
339
+ yum: { package: 'pgcli' },
340
+ pacman: { package: 'pgcli' },
341
+ },
342
+ manualInstall: {
343
+ darwin: [
344
+ 'Install with Homebrew: brew install pgcli',
345
+ 'Or with pip: pip install pgcli',
346
+ ],
347
+ linux: [
348
+ 'Debian/Ubuntu: sudo apt install pgcli',
349
+ 'Fedora: sudo dnf install pgcli',
350
+ 'Or with pip: pip install pgcli',
351
+ ],
352
+ },
353
+ }
354
+
355
+ /**
356
+ * mycli - MySQL CLI with auto-completion and syntax highlighting
357
+ * https://github.com/dbcli/mycli
358
+ */
359
+ export const mycliDependency: Dependency = {
360
+ name: 'mycli',
361
+ binary: 'mycli',
362
+ description:
363
+ 'MySQL/MariaDB CLI with intelligent auto-completion and syntax highlighting',
364
+ packages: {
365
+ brew: { package: 'mycli' },
366
+ apt: { package: 'mycli' },
367
+ dnf: { package: 'mycli' },
368
+ yum: { package: 'mycli' },
369
+ pacman: { package: 'mycli' },
370
+ },
371
+ manualInstall: {
372
+ darwin: [
373
+ 'Install with Homebrew: brew install mycli',
374
+ 'Or with pip: pip install mycli',
375
+ ],
376
+ linux: [
377
+ 'Debian/Ubuntu: sudo apt install mycli',
378
+ 'Fedora: sudo dnf install mycli',
379
+ 'Or with pip: pip install mycli',
380
+ ],
381
+ },
382
+ }
383
+
346
384
  // =============================================================================
347
385
  // Registry
348
386
  // =============================================================================
package/config/paths.ts CHANGED
@@ -1,46 +1,17 @@
1
- import { homedir } from 'os'
2
1
  import { join } from 'path'
3
- import { execSync } from 'child_process'
4
2
  import { getEngineDefaults } from './engine-defaults'
3
+ import { platformService } from '../core/platform-service'
5
4
 
6
5
  /**
7
- * Get the real user's home directory, even when running under sudo.
8
- * When a user runs `sudo spindb`, we want to use their home directory,
9
- * not root's home directory.
6
+ * Get the SpinDB home directory using the platform service.
7
+ * This handles sudo detection and platform-specific home directories.
10
8
  */
11
- function getRealHomeDir(): string {
12
- // Check if running under sudo
13
- const sudoUser = process.env.SUDO_USER
14
-
15
- if (sudoUser) {
16
- // Get the original user's home directory
17
- try {
18
- // Use getent to reliably get the home directory for the sudo user
19
- const result = execSync(`getent passwd ${sudoUser}`, {
20
- encoding: 'utf-8',
21
- })
22
- const parts = result.trim().split(':')
23
- if (parts.length >= 6 && parts[5]) {
24
- return parts[5]
25
- }
26
- } catch {
27
- // Fall back to constructing the path
28
- // On most Linux systems, home dirs are /home/username
29
- // On macOS, they're /Users/username
30
- const platform = process.platform
31
- if (platform === 'darwin') {
32
- return `/Users/${sudoUser}`
33
- } else {
34
- return `/home/${sudoUser}`
35
- }
36
- }
37
- }
38
-
39
- // Not running under sudo, use normal homedir
40
- return homedir()
9
+ function getSpinDBHome(): string {
10
+ const platformInfo = platformService.getPlatformInfo()
11
+ return join(platformInfo.homeDir, '.spindb')
41
12
  }
42
13
 
43
- const SPINDB_HOME = join(getRealHomeDir(), '.spindb')
14
+ const SPINDB_HOME = getSpinDBHome()
44
15
 
45
16
  /**
46
17
  * Options for container path functions
@@ -56,15 +56,17 @@ export class BinaryManager {
56
56
 
57
57
  /**
58
58
  * Check if binaries for a specific version are already installed
59
+ * Uses full version for directory naming (e.g., postgresql-17.7.0-darwin-arm64)
59
60
  */
60
61
  async isInstalled(
61
62
  version: string,
62
63
  platform: string,
63
64
  arch: string,
64
65
  ): Promise<boolean> {
66
+ const fullVersion = this.getFullVersion(version)
65
67
  const binPath = paths.getBinaryPath({
66
68
  engine: 'postgresql',
67
- version,
69
+ version: fullVersion,
68
70
  platform,
69
71
  arch,
70
72
  })
@@ -113,14 +115,15 @@ export class BinaryManager {
113
115
  arch: string,
114
116
  onProgress?: ProgressCallback,
115
117
  ): Promise<string> {
118
+ const fullVersion = this.getFullVersion(version)
116
119
  const url = this.getDownloadUrl(version, platform, arch)
117
120
  const binPath = paths.getBinaryPath({
118
121
  engine: 'postgresql',
119
- version,
122
+ version: fullVersion,
120
123
  platform,
121
124
  arch,
122
125
  })
123
- const tempDir = join(paths.bin, `temp-${version}-${platform}-${arch}`)
126
+ const tempDir = join(paths.bin, `temp-${fullVersion}-${platform}-${arch}`)
124
127
  const jarFile = join(tempDir, 'postgres.jar')
125
128
 
126
129
  // Ensure directories exist
@@ -200,9 +203,10 @@ export class BinaryManager {
200
203
  platform: string,
201
204
  arch: string,
202
205
  ): Promise<boolean> {
206
+ const fullVersion = this.getFullVersion(version)
203
207
  const binPath = paths.getBinaryPath({
204
208
  engine: 'postgresql',
205
- version,
209
+ version: fullVersion,
206
210
  platform,
207
211
  arch,
208
212
  })
@@ -256,9 +260,10 @@ export class BinaryManager {
256
260
  arch: string,
257
261
  binary: string,
258
262
  ): string {
263
+ const fullVersion = this.getFullVersion(version)
259
264
  const binPath = paths.getBinaryPath({
260
265
  engine: 'postgresql',
261
- version,
266
+ version: fullVersion,
262
267
  platform,
263
268
  arch,
264
269
  })
@@ -274,6 +279,7 @@ export class BinaryManager {
274
279
  arch: string,
275
280
  onProgress?: ProgressCallback,
276
281
  ): Promise<string> {
282
+ const fullVersion = this.getFullVersion(version)
277
283
  if (await this.isInstalled(version, platform, arch)) {
278
284
  onProgress?.({
279
285
  stage: 'cached',
@@ -281,7 +287,7 @@ export class BinaryManager {
281
287
  })
282
288
  return paths.getBinaryPath({
283
289
  engine: 'postgresql',
284
- version,
290
+ version: fullVersion,
285
291
  platform,
286
292
  arch,
287
293
  })
@@ -4,6 +4,7 @@ import { exec } from 'child_process'
4
4
  import { promisify } from 'util'
5
5
  import { dirname } from 'path'
6
6
  import { paths } from '../config/paths'
7
+ import { logDebug, logWarning } from './error-handler'
7
8
  import type {
8
9
  SpinDBConfig,
9
10
  BinaryConfig,
@@ -41,8 +42,12 @@ export class ConfigManager {
41
42
  const content = await readFile(configPath, 'utf8')
42
43
  this.config = JSON.parse(content) as SpinDBConfig
43
44
  return this.config
44
- } catch {
45
+ } catch (error) {
45
46
  // If config is corrupted, reset to default
47
+ logWarning('Config file corrupted, resetting to default', {
48
+ configPath,
49
+ error: error instanceof Error ? error.message : String(error),
50
+ })
46
51
  this.config = { ...DEFAULT_CONFIG }
47
52
  await this.save()
48
53
  return this.config
@@ -110,8 +115,12 @@ export class ConfigManager {
110
115
  if (match) {
111
116
  version = match[0]
112
117
  }
113
- } catch {
114
- // Version detection failed, that's ok
118
+ } catch (error) {
119
+ logDebug('Version detection failed', {
120
+ tool,
121
+ path,
122
+ error: error instanceof Error ? error.message : String(error),
123
+ })
115
124
  }
116
125
 
117
126
  config.binaries[tool] = {
@@ -142,8 +151,11 @@ export class ConfigManager {
142
151
  if (path && existsSync(path)) {
143
152
  return path
144
153
  }
145
- } catch {
146
- // which failed, binary not found
154
+ } catch (error) {
155
+ logDebug('which command failed for binary detection', {
156
+ tool,
157
+ error: error instanceof Error ? error.message : String(error),
158
+ })
147
159
  }
148
160
 
149
161
  // Check common locations
@@ -15,7 +15,11 @@ import {
15
15
  packageManagers,
16
16
  getEngineDependencies,
17
17
  getUniqueDependencies,
18
+ usqlDependency,
19
+ pgcliDependency,
20
+ mycliDependency,
18
21
  } from '../config/os-dependencies'
22
+ import { platformService } from './platform-service'
19
23
 
20
24
  const execAsync = promisify(exec)
21
25
 
@@ -46,7 +50,7 @@ export type InstallResult = {
46
50
  * Detect which package manager is available on the current system
47
51
  */
48
52
  export async function detectPackageManager(): Promise<DetectedPackageManager | null> {
49
- const platform = process.platform as Platform
53
+ const { platform } = platformService.getPlatformInfo()
50
54
 
51
55
  // Filter to package managers available on this platform
52
56
  const candidates = packageManagers.filter((pm) =>
@@ -73,7 +77,7 @@ export async function detectPackageManager(): Promise<DetectedPackageManager | n
73
77
  * Get the current platform
74
78
  */
75
79
  export function getCurrentPlatform(): Platform {
76
- return process.platform as Platform
80
+ return platformService.getPlatformInfo().platform as Platform
77
81
  }
78
82
 
79
83
  // =============================================================================
@@ -87,21 +91,12 @@ export async function findBinary(
87
91
  binary: string,
88
92
  ): Promise<{ path: string; version?: string } | null> {
89
93
  try {
90
- const command = process.platform === 'win32' ? 'where' : 'which'
91
- const { stdout } = await execAsync(`${command} ${binary}`)
92
- const path = stdout.trim().split('\n')[0]
93
-
94
+ // Use platformService to find the binary path
95
+ const path = await platformService.findToolPath(binary)
94
96
  if (!path) return null
95
97
 
96
98
  // Try to get version
97
- let version: string | undefined
98
- try {
99
- const { stdout: versionOutput } = await execAsync(`${binary} --version`)
100
- const match = versionOutput.match(/(\d+\.\d+(\.\d+)?)/)
101
- version = match ? match[1] : undefined
102
- } catch {
103
- // Version check failed, that's ok
104
- }
99
+ const version = (await platformService.getToolVersion(path)) || undefined
105
100
 
106
101
  return { path, version }
107
102
  } catch {
@@ -216,7 +211,9 @@ function execWithInheritedStdio(command: string): void {
216
211
  }
217
212
 
218
213
  if (result.status !== 0) {
219
- throw new Error(`Command failed with exit code ${result.status}: ${cmdToRun}`)
214
+ throw new Error(
215
+ `Command failed with exit code ${result.status}: ${cmdToRun}`,
216
+ )
220
217
  }
221
218
  }
222
219
 
@@ -427,3 +424,135 @@ export async function getAllDependencyReports(): Promise<
427
424
  )
428
425
  return reports
429
426
  }
427
+
428
+ // =============================================================================
429
+ // usql (Enhanced Shell) Support
430
+ // =============================================================================
431
+
432
+ /**
433
+ * Check if usql is installed
434
+ */
435
+ export async function isUsqlInstalled(): Promise<boolean> {
436
+ const status = await checkDependency(usqlDependency)
437
+ return status.installed
438
+ }
439
+
440
+ /**
441
+ * Get usql dependency status
442
+ */
443
+ export async function getUsqlStatus(): Promise<DependencyStatus> {
444
+ return checkDependency(usqlDependency)
445
+ }
446
+
447
+ /**
448
+ * Install usql using the detected package manager
449
+ */
450
+ export async function installUsql(
451
+ packageManager: DetectedPackageManager,
452
+ ): Promise<InstallResult> {
453
+ return installDependency(usqlDependency, packageManager)
454
+ }
455
+
456
+ /**
457
+ * Get usql manual installation instructions
458
+ */
459
+ export function getUsqlManualInstructions(
460
+ platform: Platform = getCurrentPlatform(),
461
+ ): string[] {
462
+ return getManualInstallInstructions(usqlDependency, platform)
463
+ }
464
+
465
+ /**
466
+ * Get the usql dependency definition
467
+ */
468
+ export function getUsqlDependency(): Dependency {
469
+ return usqlDependency
470
+ }
471
+
472
+ // =============================================================================
473
+ // pgcli (PostgreSQL Enhanced Shell) Support
474
+ // =============================================================================
475
+
476
+ /**
477
+ * Check if pgcli is installed
478
+ */
479
+ export async function isPgcliInstalled(): Promise<boolean> {
480
+ const status = await checkDependency(pgcliDependency)
481
+ return status.installed
482
+ }
483
+
484
+ /**
485
+ * Get pgcli dependency status
486
+ */
487
+ export async function getPgcliStatus(): Promise<DependencyStatus> {
488
+ return checkDependency(pgcliDependency)
489
+ }
490
+
491
+ /**
492
+ * Install pgcli using the detected package manager
493
+ */
494
+ export async function installPgcli(
495
+ packageManager: DetectedPackageManager,
496
+ ): Promise<InstallResult> {
497
+ return installDependency(pgcliDependency, packageManager)
498
+ }
499
+
500
+ /**
501
+ * Get pgcli manual installation instructions
502
+ */
503
+ export function getPgcliManualInstructions(
504
+ platform: Platform = getCurrentPlatform(),
505
+ ): string[] {
506
+ return getManualInstallInstructions(pgcliDependency, platform)
507
+ }
508
+
509
+ /**
510
+ * Get the pgcli dependency definition
511
+ */
512
+ export function getPgcliDependency(): Dependency {
513
+ return pgcliDependency
514
+ }
515
+
516
+ // =============================================================================
517
+ // mycli (MySQL Enhanced Shell) Support
518
+ // =============================================================================
519
+
520
+ /**
521
+ * Check if mycli is installed
522
+ */
523
+ export async function isMycliInstalled(): Promise<boolean> {
524
+ const status = await checkDependency(mycliDependency)
525
+ return status.installed
526
+ }
527
+
528
+ /**
529
+ * Get mycli dependency status
530
+ */
531
+ export async function getMycliStatus(): Promise<DependencyStatus> {
532
+ return checkDependency(mycliDependency)
533
+ }
534
+
535
+ /**
536
+ * Install mycli using the detected package manager
537
+ */
538
+ export async function installMycli(
539
+ packageManager: DetectedPackageManager,
540
+ ): Promise<InstallResult> {
541
+ return installDependency(mycliDependency, packageManager)
542
+ }
543
+
544
+ /**
545
+ * Get mycli manual installation instructions
546
+ */
547
+ export function getMycliManualInstructions(
548
+ platform: Platform = getCurrentPlatform(),
549
+ ): string[] {
550
+ return getManualInstallInstructions(mycliDependency, platform)
551
+ }
552
+
553
+ /**
554
+ * Get the mycli dependency definition
555
+ */
556
+ export function getMycliDependency(): Dependency {
557
+ return mycliDependency
558
+ }