spindb 0.31.4 → 0.33.1
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/LICENSE +8 -0
- package/README.md +107 -826
- package/cli/commands/create.ts +5 -1
- package/cli/commands/engines.ts +256 -1
- package/cli/commands/menu/backup-handlers.ts +16 -0
- package/cli/commands/menu/container-handlers.ts +170 -17
- package/cli/commands/menu/engine-handlers.ts +6 -0
- package/cli/commands/menu/settings-handlers.ts +6 -0
- package/cli/commands/menu/shell-handlers.ts +74 -14
- package/cli/commands/menu/sql-handlers.ts +8 -50
- package/cli/commands/menu/validators.ts +8 -0
- package/cli/commands/users.ts +264 -0
- package/cli/constants.ts +8 -0
- package/cli/helpers.ts +140 -0
- package/cli/index.ts +2 -0
- package/cli/ui/prompts.ts +24 -20
- package/config/backup-formats.ts +28 -0
- package/config/engine-defaults.ts +26 -0
- package/config/engines-registry.ts +1 -0
- package/config/engines.json +50 -0
- package/config/engines.schema.json +6 -1
- package/core/base-binary-manager.ts +6 -1
- package/core/config-manager.ts +20 -0
- package/core/credential-manager.ts +257 -0
- package/core/dependency-manager.ts +5 -0
- package/core/docker-exporter.ts +30 -0
- package/core/error-handler.ts +19 -0
- package/engines/base-engine.ts +32 -1
- package/engines/clickhouse/index.ts +99 -3
- package/engines/cockroachdb/index.ts +69 -2
- package/engines/couchdb/index.ts +149 -1
- package/engines/ferretdb/README.md +4 -0
- package/engines/ferretdb/index.ts +342 -13
- package/engines/index.ts +8 -0
- package/engines/influxdb/README.md +180 -0
- package/engines/influxdb/api-client.ts +64 -0
- package/engines/influxdb/backup.ts +160 -0
- package/engines/influxdb/binary-manager.ts +110 -0
- package/engines/influxdb/binary-urls.ts +69 -0
- package/engines/influxdb/hostdb-releases.ts +23 -0
- package/engines/influxdb/index.ts +1227 -0
- package/engines/influxdb/restore.ts +417 -0
- package/engines/influxdb/version-maps.ts +75 -0
- package/engines/influxdb/version-validator.ts +128 -0
- package/engines/mariadb/index.ts +96 -1
- package/engines/meilisearch/index.ts +97 -1
- package/engines/mongodb/index.ts +82 -0
- package/engines/mysql/index.ts +105 -1
- package/engines/postgresql/index.ts +92 -0
- package/engines/qdrant/index.ts +107 -2
- package/engines/redis/index.ts +106 -12
- package/engines/surrealdb/index.ts +102 -2
- package/engines/typedb/backup.ts +167 -0
- package/engines/typedb/binary-manager.ts +200 -0
- package/engines/typedb/binary-urls.ts +38 -0
- package/engines/typedb/cli-utils.ts +210 -0
- package/engines/typedb/hostdb-releases.ts +118 -0
- package/engines/typedb/index.ts +1275 -0
- package/engines/typedb/restore.ts +377 -0
- package/engines/typedb/version-maps.ts +48 -0
- package/engines/typedb/version-validator.ts +127 -0
- package/engines/valkey/index.ts +70 -2
- package/package.json +4 -1
- package/types/index.ts +37 -0
package/cli/helpers.ts
CHANGED
|
@@ -224,6 +224,26 @@ export type InstalledQuestDBEngine = {
|
|
|
224
224
|
source: 'downloaded'
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
export type InstalledTypeDBEngine = {
|
|
228
|
+
engine: 'typedb'
|
|
229
|
+
version: string
|
|
230
|
+
platform: string
|
|
231
|
+
arch: string
|
|
232
|
+
path: string
|
|
233
|
+
sizeBytes: number
|
|
234
|
+
source: 'downloaded'
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export type InstalledInfluxDBEngine = {
|
|
238
|
+
engine: 'influxdb'
|
|
239
|
+
version: string
|
|
240
|
+
platform: string
|
|
241
|
+
arch: string
|
|
242
|
+
path: string
|
|
243
|
+
sizeBytes: number
|
|
244
|
+
source: 'downloaded'
|
|
245
|
+
}
|
|
246
|
+
|
|
227
247
|
export type InstalledEngine =
|
|
228
248
|
| InstalledPostgresEngine
|
|
229
249
|
| InstalledMariadbEngine
|
|
@@ -241,6 +261,8 @@ export type InstalledEngine =
|
|
|
241
261
|
| InstalledCockroachDBEngine
|
|
242
262
|
| InstalledSurrealDBEngine
|
|
243
263
|
| InstalledQuestDBEngine
|
|
264
|
+
| InstalledTypeDBEngine
|
|
265
|
+
| InstalledInfluxDBEngine
|
|
244
266
|
|
|
245
267
|
async function getPostgresVersion(binPath: string): Promise<string | null> {
|
|
246
268
|
const ext = platformService.getExecutableExtension()
|
|
@@ -1088,6 +1110,114 @@ async function getInstalledQuestDBEngines(): Promise<InstalledQuestDBEngine[]> {
|
|
|
1088
1110
|
return engines
|
|
1089
1111
|
}
|
|
1090
1112
|
|
|
1113
|
+
// Get TypeDB version from binary path
|
|
1114
|
+
// TypeDB is a Rust binary but uses a launcher script. Check for server binary existence.
|
|
1115
|
+
async function getTypeDBVersion(binPath: string): Promise<string | null> {
|
|
1116
|
+
const ext = platformService.getExecutableExtension()
|
|
1117
|
+
const serverPath = join(binPath, 'bin', 'server', `typedb_server_bin${ext}`)
|
|
1118
|
+
if (!existsSync(serverPath)) {
|
|
1119
|
+
return null
|
|
1120
|
+
}
|
|
1121
|
+
// TypeDB server binary doesn't have a simple --version flag
|
|
1122
|
+
// Return null to use directory-parsed version
|
|
1123
|
+
return null
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// Get installed TypeDB engines from downloaded binaries
|
|
1127
|
+
async function getInstalledTypeDBEngines(): Promise<InstalledTypeDBEngine[]> {
|
|
1128
|
+
const binDir = paths.bin
|
|
1129
|
+
|
|
1130
|
+
if (!existsSync(binDir)) {
|
|
1131
|
+
return []
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
const entries = await readdir(binDir, { withFileTypes: true })
|
|
1135
|
+
const engines: InstalledTypeDBEngine[] = []
|
|
1136
|
+
|
|
1137
|
+
for (const entry of entries) {
|
|
1138
|
+
if (!entry.isDirectory()) continue
|
|
1139
|
+
if (!entry.name.startsWith('typedb-')) continue
|
|
1140
|
+
|
|
1141
|
+
const parsed = parseEngineDirectory(entry.name, 'typedb-', binDir)
|
|
1142
|
+
if (!parsed) continue
|
|
1143
|
+
|
|
1144
|
+
const actualVersion =
|
|
1145
|
+
(await getTypeDBVersion(parsed.path)) || parsed.version
|
|
1146
|
+
const sizeBytes = await calculateDirectorySize(parsed.path)
|
|
1147
|
+
|
|
1148
|
+
engines.push({
|
|
1149
|
+
engine: 'typedb',
|
|
1150
|
+
version: actualVersion,
|
|
1151
|
+
platform: parsed.platform,
|
|
1152
|
+
arch: parsed.arch,
|
|
1153
|
+
path: parsed.path,
|
|
1154
|
+
sizeBytes,
|
|
1155
|
+
source: 'downloaded',
|
|
1156
|
+
})
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
engines.sort((a, b) => compareVersions(b.version, a.version))
|
|
1160
|
+
|
|
1161
|
+
return engines
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// Get InfluxDB version from binary path
|
|
1165
|
+
async function getInfluxDBVersion(binPath: string): Promise<string | null> {
|
|
1166
|
+
const ext = platformService.getExecutableExtension()
|
|
1167
|
+
const influxdbPath = join(binPath, 'bin', `influxdb3${ext}`)
|
|
1168
|
+
if (!existsSync(influxdbPath)) {
|
|
1169
|
+
return null
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
try {
|
|
1173
|
+
const { stdout } = await execFileAsync(influxdbPath, ['--version'])
|
|
1174
|
+
const match = stdout.match(/v?(\d+\.\d+\.\d+)/)
|
|
1175
|
+
return match ? match[1] : null
|
|
1176
|
+
} catch {
|
|
1177
|
+
return null
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// Get installed InfluxDB engines from downloaded binaries
|
|
1182
|
+
async function getInstalledInfluxDBEngines(): Promise<
|
|
1183
|
+
InstalledInfluxDBEngine[]
|
|
1184
|
+
> {
|
|
1185
|
+
const binDir = paths.bin
|
|
1186
|
+
|
|
1187
|
+
if (!existsSync(binDir)) {
|
|
1188
|
+
return []
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
const entries = await readdir(binDir, { withFileTypes: true })
|
|
1192
|
+
const engines: InstalledInfluxDBEngine[] = []
|
|
1193
|
+
|
|
1194
|
+
for (const entry of entries) {
|
|
1195
|
+
if (!entry.isDirectory()) continue
|
|
1196
|
+
if (!entry.name.startsWith('influxdb-')) continue
|
|
1197
|
+
|
|
1198
|
+
const parsed = parseEngineDirectory(entry.name, 'influxdb-', binDir)
|
|
1199
|
+
if (!parsed) continue
|
|
1200
|
+
|
|
1201
|
+
const actualVersion =
|
|
1202
|
+
(await getInfluxDBVersion(parsed.path)) || parsed.version
|
|
1203
|
+
const sizeBytes = await calculateDirectorySize(parsed.path)
|
|
1204
|
+
|
|
1205
|
+
engines.push({
|
|
1206
|
+
engine: 'influxdb',
|
|
1207
|
+
version: actualVersion,
|
|
1208
|
+
platform: parsed.platform,
|
|
1209
|
+
arch: parsed.arch,
|
|
1210
|
+
path: parsed.path,
|
|
1211
|
+
sizeBytes,
|
|
1212
|
+
source: 'downloaded',
|
|
1213
|
+
})
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
engines.sort((a, b) => compareVersions(b.version, a.version))
|
|
1217
|
+
|
|
1218
|
+
return engines
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1091
1221
|
// Get FerretDB version from binary path
|
|
1092
1222
|
async function getFerretDBVersion(binPath: string): Promise<string | null> {
|
|
1093
1223
|
const ext = platformService.getExecutableExtension()
|
|
@@ -1182,6 +1312,8 @@ const ENGINE_PREFIXES = [
|
|
|
1182
1312
|
'cockroachdb-',
|
|
1183
1313
|
'surrealdb-',
|
|
1184
1314
|
'questdb-',
|
|
1315
|
+
'typedb-',
|
|
1316
|
+
'influxdb-',
|
|
1185
1317
|
] as const
|
|
1186
1318
|
|
|
1187
1319
|
/**
|
|
@@ -1228,6 +1360,8 @@ export async function getInstalledEngines(): Promise<InstalledEngine[]> {
|
|
|
1228
1360
|
cockroachdbEngines,
|
|
1229
1361
|
surrealdbEngines,
|
|
1230
1362
|
questdbEngines,
|
|
1363
|
+
typedbEngines,
|
|
1364
|
+
influxdbEngines,
|
|
1231
1365
|
] = await Promise.all([
|
|
1232
1366
|
getInstalledPostgresEngines(),
|
|
1233
1367
|
getInstalledMariadbEngines(),
|
|
@@ -1245,6 +1379,8 @@ export async function getInstalledEngines(): Promise<InstalledEngine[]> {
|
|
|
1245
1379
|
getInstalledCockroachDBEngines(),
|
|
1246
1380
|
getInstalledSurrealDBEngines(),
|
|
1247
1381
|
getInstalledQuestDBEngines(),
|
|
1382
|
+
getInstalledTypeDBEngines(),
|
|
1383
|
+
getInstalledInfluxDBEngines(),
|
|
1248
1384
|
])
|
|
1249
1385
|
|
|
1250
1386
|
return [
|
|
@@ -1264,6 +1400,8 @@ export async function getInstalledEngines(): Promise<InstalledEngine[]> {
|
|
|
1264
1400
|
...cockroachdbEngines,
|
|
1265
1401
|
...surrealdbEngines,
|
|
1266
1402
|
...questdbEngines,
|
|
1403
|
+
...typedbEngines,
|
|
1404
|
+
...influxdbEngines,
|
|
1267
1405
|
]
|
|
1268
1406
|
}
|
|
1269
1407
|
|
|
@@ -1283,4 +1421,6 @@ export {
|
|
|
1283
1421
|
getInstalledCockroachDBEngines,
|
|
1284
1422
|
getInstalledSurrealDBEngines,
|
|
1285
1423
|
getInstalledQuestDBEngines,
|
|
1424
|
+
getInstalledTypeDBEngines,
|
|
1425
|
+
getInstalledInfluxDBEngines,
|
|
1286
1426
|
}
|
package/cli/index.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { pullCommand } from './commands/pull'
|
|
|
31
31
|
import { whichCommand } from './commands/which'
|
|
32
32
|
import { exportCommand } from './commands/export'
|
|
33
33
|
import { queryCommand } from './commands/query'
|
|
34
|
+
import { usersCommand } from './commands/users'
|
|
34
35
|
import { updateManager } from '../core/update-manager'
|
|
35
36
|
import { configManager } from '../core/config-manager'
|
|
36
37
|
import { setCachedIconMode } from './constants'
|
|
@@ -144,6 +145,7 @@ export async function run(): Promise<void> {
|
|
|
144
145
|
program.addCommand(whichCommand)
|
|
145
146
|
program.addCommand(exportCommand)
|
|
146
147
|
program.addCommand(queryCommand)
|
|
148
|
+
program.addCommand(usersCommand)
|
|
147
149
|
|
|
148
150
|
if (process.argv.length <= 2) {
|
|
149
151
|
// Only show update notification in interactive menu mode (once at startup)
|
package/cli/ui/prompts.ts
CHANGED
|
@@ -472,40 +472,44 @@ export async function promptEngine(options?: {
|
|
|
472
472
|
}): Promise<string> {
|
|
473
473
|
const engines = listEngines()
|
|
474
474
|
|
|
475
|
-
|
|
476
|
-
| { name: string; value: string; short?: string }
|
|
477
|
-
| inquirer.Separator
|
|
478
|
-
|
|
479
|
-
const choices: Choice[] = engines.map((e) => ({
|
|
475
|
+
const engineChoices: FilterableChoice[] = engines.map((e) => ({
|
|
480
476
|
name: `${getEngineIcon(e.name)} ${e.displayName} ${chalk.gray(`(versions: ${e.supportedVersions.join(', ')})`)}`,
|
|
481
477
|
value: e.name,
|
|
482
478
|
short: e.displayName,
|
|
483
479
|
}))
|
|
484
480
|
|
|
481
|
+
const footerChoices: (FilterableChoice | inquirer.Separator)[] = [
|
|
482
|
+
new inquirer.Separator(),
|
|
483
|
+
new inquirer.Separator(
|
|
484
|
+
chalk.gray(` ${engines.length} engines — type to filter`),
|
|
485
|
+
),
|
|
486
|
+
]
|
|
487
|
+
|
|
485
488
|
if (options?.includeBack) {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
+
footerChoices.push(new inquirer.Separator())
|
|
490
|
+
footerChoices.push({
|
|
491
|
+
name: `${chalk.blue('←')} Back`,
|
|
492
|
+
value: BACK_VALUE,
|
|
493
|
+
})
|
|
494
|
+
footerChoices.push({
|
|
489
495
|
name: `${chalk.blue('⌂')} Back to main menu ${chalk.gray('(esc)')}`,
|
|
490
496
|
value: MAIN_MENU_VALUE,
|
|
491
497
|
})
|
|
492
|
-
choices.push(new inquirer.Separator())
|
|
493
498
|
}
|
|
494
499
|
|
|
495
|
-
|
|
500
|
+
footerChoices.push(new inquirer.Separator())
|
|
501
|
+
|
|
502
|
+
const allChoices = [...engineChoices, ...footerChoices]
|
|
503
|
+
|
|
504
|
+
const engine = await filterableListPrompt(
|
|
505
|
+
allChoices,
|
|
506
|
+
'Select database engine:',
|
|
496
507
|
{
|
|
497
|
-
|
|
498
|
-
name: 'engine',
|
|
499
|
-
message: 'Select database engine:',
|
|
500
|
-
choices,
|
|
508
|
+
filterableCount: engineChoices.length,
|
|
501
509
|
pageSize: getPageSize(),
|
|
510
|
+
emptyText: 'No engines match filter',
|
|
502
511
|
},
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
// Escape returns to main menu
|
|
506
|
-
if (engine === ESCAPE_VALUE) {
|
|
507
|
-
return MAIN_MENU_VALUE
|
|
508
|
-
}
|
|
512
|
+
)
|
|
509
513
|
|
|
510
514
|
return engine
|
|
511
515
|
}
|
package/config/backup-formats.ts
CHANGED
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
type CockroachDBFormat,
|
|
27
27
|
type SurrealDBFormat,
|
|
28
28
|
type QuestDBFormat,
|
|
29
|
+
type TypeDBFormat,
|
|
30
|
+
type InfluxDBFormat,
|
|
29
31
|
type BackupFormatType,
|
|
30
32
|
} from '../types'
|
|
31
33
|
|
|
@@ -61,6 +63,8 @@ export const BACKUP_FORMATS: {
|
|
|
61
63
|
[Engine.CockroachDB]: EngineBackupFormats<CockroachDBFormat>
|
|
62
64
|
[Engine.SurrealDB]: EngineBackupFormats<SurrealDBFormat>
|
|
63
65
|
[Engine.QuestDB]: EngineBackupFormats<QuestDBFormat>
|
|
66
|
+
[Engine.TypeDB]: EngineBackupFormats<TypeDBFormat>
|
|
67
|
+
[Engine.InfluxDB]: EngineBackupFormats<InfluxDBFormat>
|
|
64
68
|
} = {
|
|
65
69
|
[Engine.PostgreSQL]: {
|
|
66
70
|
formats: {
|
|
@@ -308,6 +312,30 @@ export const BACKUP_FORMATS: {
|
|
|
308
312
|
supportsFormatChoice: false, // Only SQL format supported
|
|
309
313
|
defaultFormat: 'sql',
|
|
310
314
|
},
|
|
315
|
+
[Engine.TypeDB]: {
|
|
316
|
+
formats: {
|
|
317
|
+
typeql: {
|
|
318
|
+
extension: '.typeql',
|
|
319
|
+
label: '.typeql',
|
|
320
|
+
description: 'TypeQL dump - schema and data as TypeQL statements',
|
|
321
|
+
spinnerLabel: 'TypeQL',
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
supportsFormatChoice: false, // Only TypeQL format supported
|
|
325
|
+
defaultFormat: 'typeql',
|
|
326
|
+
},
|
|
327
|
+
[Engine.InfluxDB]: {
|
|
328
|
+
formats: {
|
|
329
|
+
sql: {
|
|
330
|
+
extension: '.sql',
|
|
331
|
+
label: '.sql',
|
|
332
|
+
description: 'SQL dump - time-series data as SQL statements',
|
|
333
|
+
spinnerLabel: 'SQL',
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
supportsFormatChoice: false, // Only SQL format supported
|
|
337
|
+
defaultFormat: 'sql',
|
|
338
|
+
},
|
|
311
339
|
}
|
|
312
340
|
|
|
313
341
|
/**
|
|
@@ -239,6 +239,32 @@ export const engineDefaults: Record<Engine, EngineDefaults> = {
|
|
|
239
239
|
clientTools: ['questdb'],
|
|
240
240
|
maxConnections: 0, // Not applicable - managed internally
|
|
241
241
|
},
|
|
242
|
+
[Engine.TypeDB]: {
|
|
243
|
+
defaultVersion: '3',
|
|
244
|
+
defaultPort: 1729, // TypeDB main port (gRPC protocol)
|
|
245
|
+
portRange: { start: 1729, end: 1829 },
|
|
246
|
+
latestVersion: '3',
|
|
247
|
+
superuser: 'admin', // Default admin user (password: 'password')
|
|
248
|
+
connectionScheme: 'typedb', // TypeDB proprietary protocol
|
|
249
|
+
logFileName: 'typedb.log',
|
|
250
|
+
pidFileName: 'typedb.pid',
|
|
251
|
+
dataSubdir: 'data',
|
|
252
|
+
clientTools: ['typedb', 'typedb_console_bin'],
|
|
253
|
+
maxConnections: 0, // Not applicable - managed internally
|
|
254
|
+
},
|
|
255
|
+
[Engine.InfluxDB]: {
|
|
256
|
+
defaultVersion: '3',
|
|
257
|
+
defaultPort: 8086, // InfluxDB HTTP API port
|
|
258
|
+
portRange: { start: 8086, end: 8186 },
|
|
259
|
+
latestVersion: '3',
|
|
260
|
+
superuser: '', // No auth by default for local dev
|
|
261
|
+
connectionScheme: 'http',
|
|
262
|
+
logFileName: 'influxdb.log',
|
|
263
|
+
pidFileName: 'influxdb.pid',
|
|
264
|
+
dataSubdir: 'data',
|
|
265
|
+
clientTools: [], // InfluxDB uses REST API, no separate CLI tools
|
|
266
|
+
maxConnections: 0, // Not applicable for time-series DB
|
|
267
|
+
},
|
|
242
268
|
}
|
|
243
269
|
|
|
244
270
|
/**
|
package/config/engines.json
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"defaultPort": 5432,
|
|
12
12
|
"runtime": "server",
|
|
13
13
|
"queryLanguage": "sql",
|
|
14
|
+
"scriptFileLabel": "Run SQL file",
|
|
14
15
|
"connectionScheme": "postgresql",
|
|
15
16
|
"superuser": "postgres",
|
|
16
17
|
"clientTools": ["psql", "pg_dump", "pg_restore"],
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
"defaultPort": 3306,
|
|
27
28
|
"runtime": "server",
|
|
28
29
|
"queryLanguage": "sql",
|
|
30
|
+
"scriptFileLabel": "Run SQL file",
|
|
29
31
|
"connectionScheme": "mysql",
|
|
30
32
|
"superuser": "root",
|
|
31
33
|
"clientTools": ["mysql", "mysqldump", "mysqladmin"],
|
|
@@ -41,6 +43,7 @@
|
|
|
41
43
|
"defaultPort": 3307,
|
|
42
44
|
"runtime": "server",
|
|
43
45
|
"queryLanguage": "sql",
|
|
46
|
+
"scriptFileLabel": "Run SQL file",
|
|
44
47
|
"connectionScheme": "mysql",
|
|
45
48
|
"superuser": "root",
|
|
46
49
|
"clientTools": ["mariadb", "mariadb-dump", "mariadb-admin"]
|
|
@@ -55,6 +58,7 @@
|
|
|
55
58
|
"defaultPort": null,
|
|
56
59
|
"runtime": "embedded",
|
|
57
60
|
"queryLanguage": "sql",
|
|
61
|
+
"scriptFileLabel": "Run SQL file",
|
|
58
62
|
"connectionScheme": "sqlite",
|
|
59
63
|
"superuser": null,
|
|
60
64
|
"clientTools": ["sqlite3", "sqldiff", "sqlite3_analyzer", "sqlite3_rsync"]
|
|
@@ -69,6 +73,7 @@
|
|
|
69
73
|
"defaultPort": null,
|
|
70
74
|
"runtime": "embedded",
|
|
71
75
|
"queryLanguage": "sql",
|
|
76
|
+
"scriptFileLabel": "Run SQL file",
|
|
72
77
|
"connectionScheme": "duckdb",
|
|
73
78
|
"superuser": null,
|
|
74
79
|
"clientTools": ["duckdb"],
|
|
@@ -85,6 +90,7 @@
|
|
|
85
90
|
"defaultPort": 27017,
|
|
86
91
|
"runtime": "server",
|
|
87
92
|
"queryLanguage": "javascript",
|
|
93
|
+
"scriptFileLabel": "Run script file",
|
|
88
94
|
"connectionScheme": "mongodb",
|
|
89
95
|
"superuser": null,
|
|
90
96
|
"clientTools": ["mongod", "mongosh", "mongodump", "mongorestore"],
|
|
@@ -100,6 +106,7 @@
|
|
|
100
106
|
"defaultPort": 6379,
|
|
101
107
|
"runtime": "server",
|
|
102
108
|
"queryLanguage": "redis",
|
|
109
|
+
"scriptFileLabel": "Run command file",
|
|
103
110
|
"connectionScheme": "redis",
|
|
104
111
|
"superuser": null,
|
|
105
112
|
"clientTools": ["redis-server", "redis-cli"],
|
|
@@ -115,6 +122,7 @@
|
|
|
115
122
|
"defaultPort": 6379,
|
|
116
123
|
"runtime": "server",
|
|
117
124
|
"queryLanguage": "redis",
|
|
125
|
+
"scriptFileLabel": "Run command file",
|
|
118
126
|
"connectionScheme": "redis",
|
|
119
127
|
"superuser": null,
|
|
120
128
|
"clientTools": ["valkey-server", "valkey-cli"],
|
|
@@ -131,6 +139,7 @@
|
|
|
131
139
|
"defaultPort": 9000,
|
|
132
140
|
"runtime": "server",
|
|
133
141
|
"queryLanguage": "sql",
|
|
142
|
+
"scriptFileLabel": "Run SQL file",
|
|
134
143
|
"connectionScheme": "clickhouse",
|
|
135
144
|
"superuser": "default",
|
|
136
145
|
"clientTools": ["clickhouse"],
|
|
@@ -147,6 +156,7 @@
|
|
|
147
156
|
"defaultPort": 6333,
|
|
148
157
|
"runtime": "server",
|
|
149
158
|
"queryLanguage": "rest",
|
|
159
|
+
"scriptFileLabel": null,
|
|
150
160
|
"connectionScheme": "http",
|
|
151
161
|
"superuser": null,
|
|
152
162
|
"clientTools": ["qdrant"],
|
|
@@ -163,6 +173,7 @@
|
|
|
163
173
|
"defaultPort": 7700,
|
|
164
174
|
"runtime": "server",
|
|
165
175
|
"queryLanguage": "rest",
|
|
176
|
+
"scriptFileLabel": null,
|
|
166
177
|
"connectionScheme": "http",
|
|
167
178
|
"superuser": null,
|
|
168
179
|
"clientTools": ["meilisearch"],
|
|
@@ -179,6 +190,7 @@
|
|
|
179
190
|
"defaultPort": 27017,
|
|
180
191
|
"runtime": "server",
|
|
181
192
|
"queryLanguage": "javascript",
|
|
193
|
+
"scriptFileLabel": "Run script file",
|
|
182
194
|
"connectionScheme": "mongodb",
|
|
183
195
|
"superuser": null,
|
|
184
196
|
"clientTools": ["ferretdb", "mongosh", "mongodump", "mongorestore"],
|
|
@@ -195,6 +207,7 @@
|
|
|
195
207
|
"defaultPort": 5984,
|
|
196
208
|
"runtime": "server",
|
|
197
209
|
"queryLanguage": "rest",
|
|
210
|
+
"scriptFileLabel": null,
|
|
198
211
|
"connectionScheme": "http",
|
|
199
212
|
"superuser": null,
|
|
200
213
|
"clientTools": ["couchdb"],
|
|
@@ -211,6 +224,7 @@
|
|
|
211
224
|
"defaultPort": 26257,
|
|
212
225
|
"runtime": "server",
|
|
213
226
|
"queryLanguage": "sql",
|
|
227
|
+
"scriptFileLabel": "Run SQL file",
|
|
214
228
|
"connectionScheme": "postgresql",
|
|
215
229
|
"superuser": "root",
|
|
216
230
|
"clientTools": ["cockroach"],
|
|
@@ -227,6 +241,7 @@
|
|
|
227
241
|
"defaultPort": 8000,
|
|
228
242
|
"runtime": "server",
|
|
229
243
|
"queryLanguage": "surrealql",
|
|
244
|
+
"scriptFileLabel": "Run SurrealQL file",
|
|
230
245
|
"connectionScheme": "ws",
|
|
231
246
|
"superuser": "root",
|
|
232
247
|
"clientTools": ["surreal"],
|
|
@@ -243,11 +258,46 @@
|
|
|
243
258
|
"defaultPort": 8812,
|
|
244
259
|
"runtime": "server",
|
|
245
260
|
"queryLanguage": "sql",
|
|
261
|
+
"scriptFileLabel": "Run SQL file",
|
|
246
262
|
"connectionScheme": "postgresql",
|
|
247
263
|
"superuser": "admin",
|
|
248
264
|
"clientTools": ["questdb"],
|
|
249
265
|
"licensing": "Apache-2.0",
|
|
250
266
|
"notes": "High-performance time-series database. PostgreSQL wire protocol on port 8812. Web Console at port+188. Bundled JRE (no Java required)."
|
|
267
|
+
},
|
|
268
|
+
"typedb": {
|
|
269
|
+
"displayName": "TypeDB",
|
|
270
|
+
"icon": "🤖",
|
|
271
|
+
"status": "integrated",
|
|
272
|
+
"binarySource": "hostdb",
|
|
273
|
+
"supportedVersions": ["3.8.0"],
|
|
274
|
+
"defaultVersion": "3.8.0",
|
|
275
|
+
"defaultPort": 1729,
|
|
276
|
+
"runtime": "server",
|
|
277
|
+
"queryLanguage": "typeql",
|
|
278
|
+
"scriptFileLabel": "Run TypeQL file",
|
|
279
|
+
"connectionScheme": "typedb",
|
|
280
|
+
"superuser": "admin",
|
|
281
|
+
"clientTools": ["typedb", "typedb-console"],
|
|
282
|
+
"licensing": "MPL-2.0",
|
|
283
|
+
"notes": "Strongly-typed database for knowledge representation and reasoning. TypeQL query language. Main port 1729, HTTP port 8000. Default credentials: admin/password."
|
|
284
|
+
},
|
|
285
|
+
"influxdb": {
|
|
286
|
+
"displayName": "InfluxDB",
|
|
287
|
+
"icon": "📈",
|
|
288
|
+
"status": "integrated",
|
|
289
|
+
"binarySource": "hostdb",
|
|
290
|
+
"supportedVersions": ["3.8.0"],
|
|
291
|
+
"defaultVersion": "3.8.0",
|
|
292
|
+
"defaultPort": 8086,
|
|
293
|
+
"runtime": "server",
|
|
294
|
+
"queryLanguage": "sql",
|
|
295
|
+
"scriptFileLabel": null,
|
|
296
|
+
"connectionScheme": "http",
|
|
297
|
+
"superuser": null,
|
|
298
|
+
"clientTools": ["influxdb3"],
|
|
299
|
+
"licensing": ["Apache-2.0", "MIT"],
|
|
300
|
+
"notes": "Purpose-built time-series database with SQL support. InfluxDB 3.x is a Rust rewrite using Apache Arrow/DataFusion. HTTP API on port 8086."
|
|
251
301
|
}
|
|
252
302
|
}
|
|
253
303
|
}
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"defaultPort",
|
|
28
28
|
"runtime",
|
|
29
29
|
"queryLanguage",
|
|
30
|
+
"scriptFileLabel",
|
|
30
31
|
"connectionScheme",
|
|
31
32
|
"superuser",
|
|
32
33
|
"clientTools"
|
|
@@ -72,9 +73,13 @@
|
|
|
72
73
|
},
|
|
73
74
|
"queryLanguage": {
|
|
74
75
|
"type": "string",
|
|
75
|
-
"enum": ["sql", "javascript", "redis", "rest"],
|
|
76
|
+
"enum": ["sql", "javascript", "redis", "rest", "surrealql", "typeql"],
|
|
76
77
|
"description": "Query language used by the engine"
|
|
77
78
|
},
|
|
79
|
+
"scriptFileLabel": {
|
|
80
|
+
"type": ["string", "null"],
|
|
81
|
+
"description": "Menu label for running script files (e.g., 'Run SQL file', 'Run TypeQL file'). Null for REST API engines that don't support script files."
|
|
82
|
+
},
|
|
78
83
|
"connectionScheme": {
|
|
79
84
|
"type": "string",
|
|
80
85
|
"description": "URI scheme for connection strings"
|
|
@@ -44,6 +44,9 @@ export type BinaryManagerConfig = {
|
|
|
44
44
|
export abstract class BaseBinaryManager {
|
|
45
45
|
protected abstract readonly config: BinaryManagerConfig
|
|
46
46
|
|
|
47
|
+
/** Timeout for `--version` verification after download (ms). Override in subclass if needed. */
|
|
48
|
+
protected verifyTimeoutMs = 30_000
|
|
49
|
+
|
|
47
50
|
/**
|
|
48
51
|
* Get the download URL for a version.
|
|
49
52
|
* Must be implemented by subclass to use engine-specific binary-urls module.
|
|
@@ -446,7 +449,9 @@ export abstract class BaseBinaryManager {
|
|
|
446
449
|
}
|
|
447
450
|
|
|
448
451
|
try {
|
|
449
|
-
const { stdout, stderr } = await spawnAsync(serverPath, ['--version']
|
|
452
|
+
const { stdout, stderr } = await spawnAsync(serverPath, ['--version'], {
|
|
453
|
+
timeout: this.verifyTimeoutMs,
|
|
454
|
+
})
|
|
450
455
|
// Log stderr if present (may contain warnings)
|
|
451
456
|
if (stderr && stderr.trim()) {
|
|
452
457
|
logDebug(`${this.config.serverBinary} stderr`, {
|
package/core/config-manager.ts
CHANGED
|
@@ -78,6 +78,10 @@ const SURREALDB_TOOLS: BinaryTool[] = ['surreal']
|
|
|
78
78
|
|
|
79
79
|
const QUESTDB_TOOLS: BinaryTool[] = ['questdb']
|
|
80
80
|
|
|
81
|
+
const TYPEDB_TOOLS: BinaryTool[] = ['typedb', 'typedb_console_bin']
|
|
82
|
+
|
|
83
|
+
const INFLUXDB_TOOLS: BinaryTool[] = ['influxdb3']
|
|
84
|
+
|
|
81
85
|
const ENHANCED_SHELLS: BinaryTool[] = [
|
|
82
86
|
'pgcli',
|
|
83
87
|
'mycli',
|
|
@@ -100,6 +104,8 @@ const ALL_TOOLS: BinaryTool[] = [
|
|
|
100
104
|
...COCKROACHDB_TOOLS,
|
|
101
105
|
...SURREALDB_TOOLS,
|
|
102
106
|
...QUESTDB_TOOLS,
|
|
107
|
+
...TYPEDB_TOOLS,
|
|
108
|
+
...INFLUXDB_TOOLS,
|
|
103
109
|
...SQLITE_TOOLS,
|
|
104
110
|
...DUCKDB_TOOLS,
|
|
105
111
|
...ENHANCED_SHELLS,
|
|
@@ -121,6 +127,8 @@ const ENGINE_BINARY_MAP: Partial<Record<Engine, BinaryTool[]>> = {
|
|
|
121
127
|
[Engine.CockroachDB]: COCKROACHDB_TOOLS,
|
|
122
128
|
[Engine.SurrealDB]: SURREALDB_TOOLS,
|
|
123
129
|
[Engine.QuestDB]: QUESTDB_TOOLS,
|
|
130
|
+
[Engine.TypeDB]: TYPEDB_TOOLS,
|
|
131
|
+
[Engine.InfluxDB]: INFLUXDB_TOOLS,
|
|
124
132
|
}
|
|
125
133
|
|
|
126
134
|
export class ConfigManager {
|
|
@@ -352,6 +360,8 @@ export class ConfigManager {
|
|
|
352
360
|
redis: { found: BinaryTool[]; missing: BinaryTool[] }
|
|
353
361
|
valkey: { found: BinaryTool[]; missing: BinaryTool[] }
|
|
354
362
|
meilisearch: { found: BinaryTool[]; missing: BinaryTool[] }
|
|
363
|
+
typedb: { found: BinaryTool[]; missing: BinaryTool[] }
|
|
364
|
+
influxdb: { found: BinaryTool[]; missing: BinaryTool[] }
|
|
355
365
|
enhanced: { found: BinaryTool[]; missing: BinaryTool[] }
|
|
356
366
|
}> {
|
|
357
367
|
// First, scan ~/.spindb/bin/ for downloaded (bundled) binaries
|
|
@@ -405,6 +415,14 @@ export class ConfigManager {
|
|
|
405
415
|
found: found.filter((t) => MEILISEARCH_TOOLS.includes(t)),
|
|
406
416
|
missing: missing.filter((t) => MEILISEARCH_TOOLS.includes(t)),
|
|
407
417
|
},
|
|
418
|
+
typedb: {
|
|
419
|
+
found: found.filter((t) => TYPEDB_TOOLS.includes(t)),
|
|
420
|
+
missing: missing.filter((t) => TYPEDB_TOOLS.includes(t)),
|
|
421
|
+
},
|
|
422
|
+
influxdb: {
|
|
423
|
+
found: found.filter((t) => INFLUXDB_TOOLS.includes(t)),
|
|
424
|
+
missing: missing.filter((t) => INFLUXDB_TOOLS.includes(t)),
|
|
425
|
+
},
|
|
408
426
|
enhanced: {
|
|
409
427
|
found: found.filter((t) => ENHANCED_SHELLS.includes(t)),
|
|
410
428
|
missing: missing.filter((t) => ENHANCED_SHELLS.includes(t)),
|
|
@@ -601,6 +619,8 @@ export {
|
|
|
601
619
|
COCKROACHDB_TOOLS,
|
|
602
620
|
SURREALDB_TOOLS,
|
|
603
621
|
QUESTDB_TOOLS,
|
|
622
|
+
TYPEDB_TOOLS,
|
|
623
|
+
INFLUXDB_TOOLS,
|
|
604
624
|
SQLITE_TOOLS,
|
|
605
625
|
DUCKDB_TOOLS,
|
|
606
626
|
ENHANCED_SHELLS,
|