spindb 0.34.5 β 0.35.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 +4 -4
- package/cli/commands/create.ts +22 -1
- package/cli/commands/engines.ts +56 -22
- package/cli/commands/menu/container-handlers.ts +17 -1
- package/cli/commands/menu/engine-handlers.ts +48 -29
- package/cli/ui/theme.ts +5 -2
- package/config/engines-registry.ts +56 -0
- package/config/engines.json +14 -3
- package/config/engines.schema.json +13 -0
- package/core/base-binary-manager.ts +6 -2
- package/core/base-document-binary-manager.ts +5 -2
- package/core/base-embedded-binary-manager.ts +5 -2
- package/core/base-server-binary-manager.ts +5 -2
- package/core/hostdb-client.ts +157 -22
- package/core/hostdb-metadata.ts +67 -43
- package/engines/clickhouse/binary-urls.ts +1 -1
- package/engines/cockroachdb/binary-urls.ts +9 -7
- package/engines/cockroachdb/hostdb-releases.ts +18 -106
- package/engines/cockroachdb/version-maps.ts +1 -1
- package/engines/couchdb/binary-urls.ts +1 -1
- package/engines/duckdb/binary-urls.ts +1 -1
- package/engines/duckdb/index.ts +4 -74
- package/engines/ferretdb/README.md +76 -38
- package/engines/ferretdb/backup.ts +18 -10
- package/engines/ferretdb/binary-manager.ts +233 -35
- package/engines/ferretdb/binary-urls.ts +69 -24
- package/engines/ferretdb/index.ts +424 -213
- package/engines/ferretdb/restore.ts +23 -16
- package/engines/ferretdb/version-maps.ts +36 -8
- package/engines/index.ts +3 -4
- package/engines/influxdb/binary-urls.ts +1 -1
- package/engines/mariadb/binary-urls.ts +2 -2
- package/engines/meilisearch/binary-urls.ts +1 -1
- package/engines/mysql/binary-urls.ts +2 -2
- package/engines/postgresql/binary-urls.ts +1 -1
- package/engines/qdrant/binary-urls.ts +1 -1
- package/engines/questdb/binary-manager.ts +16 -9
- package/engines/questdb/binary-urls.ts +9 -10
- package/engines/questdb/hostdb-releases.ts +19 -97
- package/engines/questdb/version-maps.ts +2 -2
- package/engines/redis/binary-urls.ts +1 -8
- package/engines/sqlite/binary-urls.ts +1 -1
- package/engines/sqlite/index.ts +4 -74
- package/engines/surrealdb/binary-urls.ts +9 -7
- package/engines/surrealdb/hostdb-releases.ts +18 -106
- package/engines/surrealdb/version-maps.ts +1 -1
- package/engines/typedb/binary-urls.ts +10 -8
- package/engines/typedb/hostdb-releases.ts +18 -113
- package/engines/typedb/version-maps.ts +1 -1
- package/engines/valkey/binary-urls.ts +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ SpinDB supports **18 database engines** across **5 platform architectures**βal
|
|
|
38
38
|
| πͺΆ **SQLite** | Embedded SQL | β
| β
| β
| β
| β
|
|
|
39
39
|
| π¦ **DuckDB** | Embedded OLAP | β
| β
| β
| β
| β
|
|
|
40
40
|
| π **MongoDB** | Document Store | β
| β
| β
| β
| β
|
|
|
41
|
-
| π¦ **FerretDB** | Document Store | β
| β
| β
| β
|
|
|
41
|
+
| π¦ **FerretDB** | Document Store | β
| β
| β
| β
| β οΈ |
|
|
42
42
|
| π΄ **Redis** | Key-Value | β
| β
| β
| β
| β
|
|
|
43
43
|
| π· **Valkey** | Key-Value | β
| β
| β
| β
| β
|
|
|
44
44
|
| π **ClickHouse** | Columnar OLAP | β
| β
| β
| β
| β |
|
|
@@ -51,9 +51,9 @@ SpinDB supports **18 database engines** across **5 platform architectures**βal
|
|
|
51
51
|
| π€ **TypeDB** | Knowledge Graph | β
| β
| β
| β
| β
|
|
|
52
52
|
| π **InfluxDB** | Time-Series | β
| β
| β
| β
| β
|
|
|
53
53
|
|
|
54
|
-
**
|
|
54
|
+
**89 combinations. One CLI. Zero configuration.**
|
|
55
55
|
|
|
56
|
-
> ClickHouse
|
|
56
|
+
> ClickHouse is available on Windows via WSL. FerretDB v1 is natively supported on Windows (uses plain PostgreSQL backend); v2 requires macOS/Linux.
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
@@ -272,7 +272,7 @@ See [DEPLOY.md](DEPLOY.md) for comprehensive deployment documentation.
|
|
|
272
272
|
|
|
273
273
|
- **Local only** - Databases bind to `127.0.0.1`. Remote connection support planned for v1.1.
|
|
274
274
|
- **ClickHouse Windows** - Not supported (hostdb doesn't build for Windows).
|
|
275
|
-
- **FerretDB Windows** -
|
|
275
|
+
- **FerretDB Windows** - v1 supported natively (plain PostgreSQL backend). v2 not supported (postgresql-documentdb has startup issues); use WSL for v2.
|
|
276
276
|
- **Qdrant, Meilisearch, CouchDB** - Use REST API instead of CLI shell. Access via HTTP at the configured port.
|
|
277
277
|
|
|
278
278
|
---
|
package/cli/commands/create.ts
CHANGED
|
@@ -22,7 +22,11 @@ import { startWithRetry } from '../../core/start-with-retry'
|
|
|
22
22
|
import { TransactionManager } from '../../core/transaction-manager'
|
|
23
23
|
import { isValidDatabaseName, exitWithError } from '../../core/error-handler'
|
|
24
24
|
import { resolve } from 'path'
|
|
25
|
-
import { Engine } from '../../types'
|
|
25
|
+
import { Engine, Platform } from '../../types'
|
|
26
|
+
import {
|
|
27
|
+
FERRETDB_VERSION_MAP,
|
|
28
|
+
isV1 as isFerretDBv1,
|
|
29
|
+
} from '../../engines/ferretdb/version-maps'
|
|
26
30
|
import type { BaseEngine } from '../../engines/base-engine'
|
|
27
31
|
|
|
28
32
|
/**
|
|
@@ -535,6 +539,23 @@ export const createCommand = new Command('create')
|
|
|
535
539
|
database = answers.database
|
|
536
540
|
}
|
|
537
541
|
|
|
542
|
+
// FerretDB: force v1 on Windows (v2 requires postgresql-documentdb, not available on Windows)
|
|
543
|
+
// Runs after both CLI and interactive paths have resolved engine + version
|
|
544
|
+
if (
|
|
545
|
+
engine === Engine.FerretDB &&
|
|
546
|
+
!isFerretDBv1(version) &&
|
|
547
|
+
platformService.getPlatformInfo().platform === Platform.Win32
|
|
548
|
+
) {
|
|
549
|
+
version = FERRETDB_VERSION_MAP['1']
|
|
550
|
+
if (!options.json) {
|
|
551
|
+
console.log(
|
|
552
|
+
chalk.yellow(
|
|
553
|
+
` FerretDB v2 is not supported on Windows β using v1 (${version})`,
|
|
554
|
+
),
|
|
555
|
+
)
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
538
559
|
// Redis/Valkey use numbered databases (0-15), default to "0"
|
|
539
560
|
// Other engines default to container name (with hyphens replaced by underscores for SQL compatibility)
|
|
540
561
|
if (engine === Engine.Redis || engine === Engine.Valkey) {
|
package/cli/commands/engines.ts
CHANGED
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
import { Engine, Platform } from '../../types'
|
|
54
54
|
import {
|
|
55
55
|
loadEnginesJson,
|
|
56
|
+
filterEnginesByPlatform,
|
|
56
57
|
type EngineConfig,
|
|
57
58
|
} from '../../config/engines-registry'
|
|
58
59
|
import { mysqlBinaryManager } from '../../engines/mysql/binary-manager'
|
|
@@ -74,7 +75,9 @@ import { typedbBinaryManager } from '../../engines/typedb/binary-manager'
|
|
|
74
75
|
import { influxdbBinaryManager } from '../../engines/influxdb/binary-manager'
|
|
75
76
|
import {
|
|
76
77
|
DEFAULT_DOCUMENTDB_VERSION,
|
|
78
|
+
DEFAULT_V1_POSTGRESQL_VERSION,
|
|
77
79
|
normalizeDocumentDBVersion,
|
|
80
|
+
isV1,
|
|
78
81
|
} from '../../engines/ferretdb/version-maps'
|
|
79
82
|
|
|
80
83
|
// Display manual installation instructions for missing dependencies
|
|
@@ -1727,26 +1730,41 @@ enginesCommand
|
|
|
1727
1730
|
}
|
|
1728
1731
|
|
|
1729
1732
|
if (['ferretdb', 'ferret'].includes(normalizedEngine)) {
|
|
1730
|
-
// Check platform support
|
|
1731
1733
|
const { platform } = platformService.getPlatformInfo()
|
|
1732
|
-
|
|
1734
|
+
|
|
1735
|
+
if (!version) {
|
|
1736
|
+
// Auto-select v1 on Windows (v2 not supported)
|
|
1737
|
+
if (platform === Platform.Win32) {
|
|
1738
|
+
version = '1'
|
|
1739
|
+
console.log(
|
|
1740
|
+
chalk.gray(
|
|
1741
|
+
' Auto-selecting FerretDB v1 (v2 is not available on Windows)',
|
|
1742
|
+
),
|
|
1743
|
+
)
|
|
1744
|
+
} else {
|
|
1745
|
+
console.error(uiError('FerretDB requires a version (e.g., 1 or 2)'))
|
|
1746
|
+
process.exit(1)
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// Block v2 on Windows with helpful message
|
|
1751
|
+
if (platform === Platform.Win32 && !isV1(version)) {
|
|
1733
1752
|
console.error(
|
|
1734
|
-
uiError(
|
|
1753
|
+
uiError(
|
|
1754
|
+
'FerretDB v2 is not supported on Windows (postgresql-documentdb has startup issues)',
|
|
1755
|
+
),
|
|
1735
1756
|
)
|
|
1736
1757
|
console.log(
|
|
1737
1758
|
chalk.gray(
|
|
1738
|
-
' FerretDB
|
|
1759
|
+
' Use FerretDB v1 instead, which uses plain PostgreSQL:',
|
|
1739
1760
|
),
|
|
1740
1761
|
)
|
|
1741
|
-
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1744
|
-
if (!version) {
|
|
1745
|
-
console.error(uiError('FerretDB requires a version (e.g., 2)'))
|
|
1762
|
+
console.log(chalk.cyan(' spindb engines download ferretdb 1'))
|
|
1746
1763
|
process.exit(1)
|
|
1747
1764
|
}
|
|
1748
1765
|
|
|
1749
1766
|
const engine = getEngine(Engine.FerretDB)
|
|
1767
|
+
const v1 = isV1(version)
|
|
1750
1768
|
|
|
1751
1769
|
const spinner = createSpinner(
|
|
1752
1770
|
`Checking FerretDB ${version} binaries...`,
|
|
@@ -1780,18 +1798,31 @@ enginesCommand
|
|
|
1780
1798
|
)
|
|
1781
1799
|
console.log(chalk.gray(` FerretDB location: ${binPath}`))
|
|
1782
1800
|
|
|
1783
|
-
//
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1801
|
+
// Show backend location (version-dependent)
|
|
1802
|
+
if (v1) {
|
|
1803
|
+
const pgFullVersion = postgresqlBinaryManager.getFullVersion(
|
|
1804
|
+
DEFAULT_V1_POSTGRESQL_VERSION,
|
|
1805
|
+
)
|
|
1806
|
+
const pgPath = paths.getBinaryPath({
|
|
1807
|
+
engine: 'postgresql',
|
|
1808
|
+
version: pgFullVersion,
|
|
1809
|
+
platform: ferretPlatform,
|
|
1810
|
+
arch: ferretArch,
|
|
1811
|
+
})
|
|
1812
|
+
console.log(chalk.gray(` PostgreSQL backend location: ${pgPath}`))
|
|
1813
|
+
} else {
|
|
1814
|
+
const fullDocumentDBVersion = normalizeDocumentDBVersion(
|
|
1815
|
+
DEFAULT_DOCUMENTDB_VERSION,
|
|
1816
|
+
)
|
|
1817
|
+
const documentdbPath = ferretdbBinaryManager.getDocumentDBBinaryPath(
|
|
1818
|
+
fullDocumentDBVersion,
|
|
1819
|
+
ferretPlatform,
|
|
1820
|
+
ferretArch,
|
|
1821
|
+
)
|
|
1822
|
+
console.log(
|
|
1823
|
+
chalk.gray(` postgresql-documentdb location: ${documentdbPath}`),
|
|
1824
|
+
)
|
|
1825
|
+
}
|
|
1795
1826
|
|
|
1796
1827
|
// Skip client tools check - FerretDB uses MongoDB client tools (mongosh)
|
|
1797
1828
|
// which are installed separately via: spindb engines download mongodb
|
|
@@ -2126,7 +2157,10 @@ enginesCommand
|
|
|
2126
2157
|
.option('--all', 'Include pending and planned engines')
|
|
2127
2158
|
.action(async (options: { json?: boolean; all?: boolean }) => {
|
|
2128
2159
|
try {
|
|
2129
|
-
const
|
|
2160
|
+
const rawData = await loadEnginesJson()
|
|
2161
|
+
const { platform, arch } = platformService.getPlatformInfo()
|
|
2162
|
+
const platformKey = `${platform}-${arch}`
|
|
2163
|
+
const enginesData = filterEnginesByPlatform(rawData, platformKey)
|
|
2130
2164
|
|
|
2131
2165
|
if (options.json) {
|
|
2132
2166
|
// Output full JSON
|
|
@@ -377,7 +377,23 @@ export async function handleCreate(): Promise<'main' | string | void> {
|
|
|
377
377
|
|
|
378
378
|
const config = await containerManager.getConfig(containerNameFinal)
|
|
379
379
|
if (config) {
|
|
380
|
-
|
|
380
|
+
try {
|
|
381
|
+
await dbEngine.start(config)
|
|
382
|
+
} catch (error) {
|
|
383
|
+
startSpinner.fail(`${dbEngine.displayName} failed to start`)
|
|
384
|
+
const e = error as Error
|
|
385
|
+
console.log()
|
|
386
|
+
console.log(uiError(e.message))
|
|
387
|
+
console.log()
|
|
388
|
+
// Clean up the container that was created but failed to start
|
|
389
|
+
try {
|
|
390
|
+
await containerManager.delete(containerNameFinal, { force: true })
|
|
391
|
+
} catch {
|
|
392
|
+
// Ignore cleanup errors
|
|
393
|
+
}
|
|
394
|
+
await pressEnterToContinue()
|
|
395
|
+
return
|
|
396
|
+
}
|
|
381
397
|
await containerManager.updateConfig(containerNameFinal, {
|
|
382
398
|
status: 'running',
|
|
383
399
|
})
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
type InstalledInfluxDBEngine,
|
|
35
35
|
} from '../../helpers'
|
|
36
36
|
|
|
37
|
+
import { isV1 } from '../../../engines/ferretdb/version-maps'
|
|
37
38
|
import { type MenuChoice } from './shared'
|
|
38
39
|
|
|
39
40
|
export async function handleEngines(): Promise<void> {
|
|
@@ -285,50 +286,68 @@ async function handleDeleteEngine(
|
|
|
285
286
|
try {
|
|
286
287
|
await rm(enginePath, { recursive: true, force: true })
|
|
287
288
|
|
|
288
|
-
// FerretDB is a composite engine -
|
|
289
|
-
|
|
289
|
+
// FerretDB is a composite engine - handle backend cleanup based on version
|
|
290
|
+
let backendStatus = ''
|
|
290
291
|
if (engineName === 'ferretdb') {
|
|
291
292
|
// enginePath is like: ~/.spindb/bin/ferretdb-2.7.0-darwin-arm64
|
|
292
|
-
// We need to find: ~/.spindb/bin/postgresql-documentdb-*-darwin-arm64
|
|
293
293
|
const binDir = dirname(enginePath)
|
|
294
294
|
const ferretDirName = basename(enginePath)
|
|
295
|
-
// Extract
|
|
295
|
+
// Extract version from directory name (e.g., "2.7.0" from "ferretdb-2.7.0-darwin-arm64")
|
|
296
296
|
const parts = ferretDirName.split('-')
|
|
297
297
|
const platformArch = parts.slice(-2).join('-') // "darwin-arm64"
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const otherFerretInstalls = entries.filter(
|
|
304
|
-
(entry) =>
|
|
305
|
-
entry.isDirectory() &&
|
|
306
|
-
entry.name.startsWith('ferretdb-') &&
|
|
307
|
-
entry.name.endsWith(platformArch) &&
|
|
308
|
-
entry.name !== ferretDirName,
|
|
299
|
+
// Extract version: remove "ferretdb-" prefix and "-platform-arch" suffix
|
|
300
|
+
const versionPart = ferretDirName.slice(
|
|
301
|
+
'ferretdb-'.length,
|
|
302
|
+
ferretDirName.length - `-${platformArch}`.length,
|
|
309
303
|
)
|
|
310
304
|
|
|
311
|
-
if (
|
|
312
|
-
//
|
|
313
|
-
|
|
305
|
+
if (isV1(versionPart)) {
|
|
306
|
+
// v1: Don't delete shared PostgreSQL binaries (used by standalone PG containers)
|
|
307
|
+
backendStatus =
|
|
308
|
+
' (PostgreSQL backend kept β shared with standalone containers)'
|
|
314
309
|
} else {
|
|
315
|
-
//
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
310
|
+
// v2: Clean up postgresql-documentdb backend if no other v2 FerretDB installs share it
|
|
311
|
+
const entries = await readdir(binDir, { withFileTypes: true })
|
|
312
|
+
|
|
313
|
+
// Check if other v2 FerretDB installations exist for the same platform
|
|
314
|
+
const otherV2Installs = entries.filter((entry) => {
|
|
315
|
+
if (!entry.isDirectory()) return false
|
|
316
|
+
if (!entry.name.startsWith('ferretdb-')) return false
|
|
317
|
+
if (!entry.name.endsWith(platformArch)) return false
|
|
318
|
+
if (entry.name === ferretDirName) return false
|
|
319
|
+
const otherVersion = entry.name.slice(
|
|
320
|
+
'ferretdb-'.length,
|
|
321
|
+
entry.name.length - `-${platformArch}`.length,
|
|
322
|
+
)
|
|
323
|
+
return !isV1(otherVersion)
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
if (otherV2Installs.length > 0) {
|
|
327
|
+
backendStatus = ` (postgresql-documentdb kept β shared by ${otherV2Installs.length} other v2 install(s))`
|
|
328
|
+
} else {
|
|
329
|
+
const documentdbPattern = `postgresql-documentdb-`
|
|
330
|
+
let cleaned = false
|
|
331
|
+
for (const entry of entries) {
|
|
332
|
+
if (
|
|
333
|
+
entry.isDirectory() &&
|
|
334
|
+
entry.name.startsWith(documentdbPattern) &&
|
|
335
|
+
entry.name.endsWith(platformArch)
|
|
336
|
+
) {
|
|
337
|
+
const documentdbPath = join(binDir, entry.name)
|
|
338
|
+
spinner.text = `Deleting postgresql-documentdb backend...`
|
|
339
|
+
await rm(documentdbPath, { recursive: true, force: true })
|
|
340
|
+
cleaned = true
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (cleaned) {
|
|
344
|
+
backendStatus = ' (postgresql-documentdb backend also deleted)'
|
|
326
345
|
}
|
|
327
346
|
}
|
|
328
347
|
}
|
|
329
348
|
}
|
|
330
349
|
|
|
331
|
-
spinner.succeed(`Deleted ${engineName} ${engineVersion}`)
|
|
350
|
+
spinner.succeed(`Deleted ${engineName} ${engineVersion}${backendStatus}`)
|
|
332
351
|
} catch (error) {
|
|
333
352
|
const e = error as Error
|
|
334
353
|
spinner.fail(`Failed to delete: ${e.message}`)
|
package/cli/ui/theme.ts
CHANGED
|
@@ -117,9 +117,12 @@ export function connectionBox(
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
export function formatBytes(bytes: number): string {
|
|
120
|
-
if (bytes
|
|
120
|
+
if (!Number.isFinite(bytes) || bytes <= 0) return '0 B'
|
|
121
121
|
const units = ['B', 'KB', 'MB', 'GB', 'TB']
|
|
122
|
-
const i = Math.
|
|
122
|
+
const i = Math.max(
|
|
123
|
+
0,
|
|
124
|
+
Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1),
|
|
125
|
+
)
|
|
123
126
|
const value = bytes / Math.pow(1024, i)
|
|
124
127
|
return `${value.toFixed(1)} ${units[i]}`
|
|
125
128
|
}
|
|
@@ -19,6 +19,8 @@ export type EngineConfig = {
|
|
|
19
19
|
clientTools: string[]
|
|
20
20
|
licensing?: string | string[]
|
|
21
21
|
notes?: string
|
|
22
|
+
platforms?: string[]
|
|
23
|
+
versionPlatforms?: Record<string, string[]>
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export type EnginesJson = {
|
|
@@ -92,3 +94,57 @@ export function getAllEngines(): Engine[] {
|
|
|
92
94
|
export function clearEnginesCache(): void {
|
|
93
95
|
cachedEngines = null
|
|
94
96
|
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Filter engines data to only include engines and versions supported on the given platform.
|
|
100
|
+
*
|
|
101
|
+
* - If an engine has `platforms` and the platformKey isn't listed, the engine is removed.
|
|
102
|
+
* - If an engine has `versionPlatforms`, versions whose entry excludes the platformKey are removed.
|
|
103
|
+
* Versions with no entry in `versionPlatforms` are kept (assumed all-platform).
|
|
104
|
+
* - If filtering removes all versions, the engine is removed.
|
|
105
|
+
* - If the defaultVersion is removed, it's set to the first remaining version.
|
|
106
|
+
*/
|
|
107
|
+
export function filterEnginesByPlatform(
|
|
108
|
+
enginesData: EnginesJson,
|
|
109
|
+
platformKey: string,
|
|
110
|
+
): EnginesJson {
|
|
111
|
+
const filtered: Record<string, EngineConfig> = {}
|
|
112
|
+
|
|
113
|
+
for (const [name, config] of Object.entries(enginesData.engines)) {
|
|
114
|
+
// Engine-level platform check
|
|
115
|
+
if (config.platforms && !config.platforms.includes(platformKey)) {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Version-level platform check
|
|
120
|
+
if (config.versionPlatforms) {
|
|
121
|
+
const filteredVersions = config.supportedVersions.filter((version) => {
|
|
122
|
+
const platforms = config.versionPlatforms![version]
|
|
123
|
+
// If no entry for this version, it's available on all platforms
|
|
124
|
+
if (!platforms) return true
|
|
125
|
+
return platforms.includes(platformKey)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
if (filteredVersions.length === 0) {
|
|
129
|
+
continue
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const defaultVersion = filteredVersions.includes(config.defaultVersion)
|
|
133
|
+
? config.defaultVersion
|
|
134
|
+
: filteredVersions[0]
|
|
135
|
+
|
|
136
|
+
filtered[name] = {
|
|
137
|
+
...config,
|
|
138
|
+
supportedVersions: filteredVersions,
|
|
139
|
+
defaultVersion,
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
filtered[name] = config
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
...enginesData,
|
|
148
|
+
engines: filtered as Record<Engine, EngineConfig>,
|
|
149
|
+
}
|
|
150
|
+
}
|
package/config/engines.json
CHANGED
|
@@ -144,7 +144,8 @@
|
|
|
144
144
|
"superuser": "default",
|
|
145
145
|
"clientTools": ["clickhouse"],
|
|
146
146
|
"licensing": "Apache-2.0",
|
|
147
|
-
"notes": "Column-oriented OLAP database. Uses YY.MM.X.build versioning. Native port 9000, HTTP port 8123. WSL only on Windows."
|
|
147
|
+
"notes": "Column-oriented OLAP database. Uses YY.MM.X.build versioning. Native port 9000, HTTP port 8123. WSL only on Windows.",
|
|
148
|
+
"platforms": ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64"]
|
|
148
149
|
},
|
|
149
150
|
"qdrant": {
|
|
150
151
|
"displayName": "Qdrant",
|
|
@@ -185,7 +186,7 @@
|
|
|
185
186
|
"icon": "π¦",
|
|
186
187
|
"status": "integrated",
|
|
187
188
|
"binarySource": "hostdb",
|
|
188
|
-
"supportedVersions": ["2.7.0"],
|
|
189
|
+
"supportedVersions": ["1.24.2", "2.7.0"],
|
|
189
190
|
"defaultVersion": "2.7.0",
|
|
190
191
|
"defaultPort": 27017,
|
|
191
192
|
"runtime": "server",
|
|
@@ -195,7 +196,17 @@
|
|
|
195
196
|
"superuser": null,
|
|
196
197
|
"clientTools": ["ferretdb", "mongosh", "mongodump", "mongorestore"],
|
|
197
198
|
"licensing": "Apache-2.0",
|
|
198
|
-
"notes": "MongoDB-compatible proxy
|
|
199
|
+
"notes": "MongoDB-compatible proxy. v2 uses postgresql-documentdb (macOS/Linux). v1 uses plain PostgreSQL (all platforms incl. Windows).",
|
|
200
|
+
"versionPlatforms": {
|
|
201
|
+
"1.24.2": [
|
|
202
|
+
"darwin-arm64",
|
|
203
|
+
"darwin-x64",
|
|
204
|
+
"linux-arm64",
|
|
205
|
+
"linux-x64",
|
|
206
|
+
"win32-x64"
|
|
207
|
+
],
|
|
208
|
+
"2.7.0": ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64"]
|
|
209
|
+
}
|
|
199
210
|
},
|
|
200
211
|
"couchdb": {
|
|
201
212
|
"displayName": "CouchDB",
|
|
@@ -114,6 +114,19 @@
|
|
|
114
114
|
"notes": {
|
|
115
115
|
"type": "string",
|
|
116
116
|
"description": "Additional notes about the engine"
|
|
117
|
+
},
|
|
118
|
+
"platforms": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": { "type": "string" },
|
|
121
|
+
"description": "Supported platform-arch combos (e.g. 'darwin-arm64'). If omitted, all platforms are supported."
|
|
122
|
+
},
|
|
123
|
+
"versionPlatforms": {
|
|
124
|
+
"type": "object",
|
|
125
|
+
"additionalProperties": {
|
|
126
|
+
"type": "array",
|
|
127
|
+
"items": { "type": "string" }
|
|
128
|
+
},
|
|
129
|
+
"description": "Per-version platform overrides. Keys are version strings, values are platform-arch arrays."
|
|
117
130
|
}
|
|
118
131
|
},
|
|
119
132
|
"additionalProperties": false
|
|
@@ -17,6 +17,7 @@ import { paths } from '../config/paths'
|
|
|
17
17
|
import { spawnAsync } from './spawn-utils'
|
|
18
18
|
import { moveEntry } from './fs-error-utils'
|
|
19
19
|
import { logDebug } from './error-handler'
|
|
20
|
+
import { fetchWithRegistryFallback } from './hostdb-client'
|
|
20
21
|
import {
|
|
21
22
|
type Engine,
|
|
22
23
|
Platform,
|
|
@@ -186,7 +187,9 @@ export abstract class BaseBinaryManager {
|
|
|
186
187
|
|
|
187
188
|
let response: Response
|
|
188
189
|
try {
|
|
189
|
-
response = await
|
|
190
|
+
response = await fetchWithRegistryFallback(url, {
|
|
191
|
+
signal: controller.signal,
|
|
192
|
+
})
|
|
190
193
|
} catch (error) {
|
|
191
194
|
const err = error as Error
|
|
192
195
|
if (err.name === 'AbortError') {
|
|
@@ -202,7 +205,7 @@ export abstract class BaseBinaryManager {
|
|
|
202
205
|
throw new Error(
|
|
203
206
|
`${this.config.displayName} ${fullVersion} binaries not found (404). ` +
|
|
204
207
|
`This version may have been removed from hostdb. ` +
|
|
205
|
-
`Try a different version or check https://
|
|
208
|
+
`Try a different version or check https://registry.layerbase.host`,
|
|
206
209
|
)
|
|
207
210
|
}
|
|
208
211
|
throw new Error(
|
|
@@ -451,6 +454,7 @@ export abstract class BaseBinaryManager {
|
|
|
451
454
|
try {
|
|
452
455
|
const { stdout, stderr } = await spawnAsync(serverPath, ['--version'], {
|
|
453
456
|
timeout: this.verifyTimeoutMs,
|
|
457
|
+
cwd: binPath,
|
|
454
458
|
})
|
|
455
459
|
// Log stderr if present (may contain warnings)
|
|
456
460
|
if (stderr && stderr.trim()) {
|
|
@@ -25,6 +25,7 @@ import { paths } from '../config/paths'
|
|
|
25
25
|
import { spawnAsync, extractWindowsArchive } from './spawn-utils'
|
|
26
26
|
import { isRenameFallbackError } from './fs-error-utils'
|
|
27
27
|
import { logDebug } from './error-handler'
|
|
28
|
+
import { fetchWithRegistryFallback } from './hostdb-client'
|
|
28
29
|
import {
|
|
29
30
|
type Engine,
|
|
30
31
|
Platform,
|
|
@@ -203,14 +204,16 @@ export abstract class BaseDocumentBinaryManager {
|
|
|
203
204
|
let response: Response
|
|
204
205
|
let fileStream: ReturnType<typeof createWriteStream> | null = null
|
|
205
206
|
try {
|
|
206
|
-
response = await
|
|
207
|
+
response = await fetchWithRegistryFallback(url, {
|
|
208
|
+
signal: controller.signal,
|
|
209
|
+
})
|
|
207
210
|
|
|
208
211
|
if (!response.ok) {
|
|
209
212
|
if (response.status === 404) {
|
|
210
213
|
throw new Error(
|
|
211
214
|
`${this.config.displayName} ${fullVersion} binaries not found (404). ` +
|
|
212
215
|
`This version may have been removed from hostdb. ` +
|
|
213
|
-
`Try a different version or check https://
|
|
216
|
+
`Try a different version or check https://registry.layerbase.host`,
|
|
214
217
|
)
|
|
215
218
|
}
|
|
216
219
|
throw new Error(
|
|
@@ -23,6 +23,7 @@ import { paths } from '../config/paths'
|
|
|
23
23
|
import { spawnAsync } from './spawn-utils'
|
|
24
24
|
import { moveEntry } from './fs-error-utils'
|
|
25
25
|
import { compareVersions } from './version-utils'
|
|
26
|
+
import { fetchWithRegistryFallback } from './hostdb-client'
|
|
26
27
|
import {
|
|
27
28
|
type Engine,
|
|
28
29
|
Platform,
|
|
@@ -201,7 +202,9 @@ export abstract class BaseEmbeddedBinaryManager {
|
|
|
201
202
|
|
|
202
203
|
let response: Response
|
|
203
204
|
try {
|
|
204
|
-
response = await
|
|
205
|
+
response = await fetchWithRegistryFallback(url, {
|
|
206
|
+
signal: controller.signal,
|
|
207
|
+
})
|
|
205
208
|
} catch (error) {
|
|
206
209
|
const err = error as Error
|
|
207
210
|
if (err.name === 'AbortError') {
|
|
@@ -220,7 +223,7 @@ export abstract class BaseEmbeddedBinaryManager {
|
|
|
220
223
|
throw new Error(
|
|
221
224
|
`${this.config.displayName} ${fullVersion} binaries not found (404). ` +
|
|
222
225
|
`This version may have been removed from hostdb. ` +
|
|
223
|
-
`Try a different version or check https://
|
|
226
|
+
`Try a different version or check https://registry.layerbase.host`,
|
|
224
227
|
)
|
|
225
228
|
}
|
|
226
229
|
throw new Error(
|
|
@@ -23,6 +23,7 @@ import { pipeline } from 'stream/promises'
|
|
|
23
23
|
import { paths } from '../config/paths'
|
|
24
24
|
import { spawnAsync, extractWindowsArchive } from './spawn-utils'
|
|
25
25
|
import { isRenameFallbackError } from './fs-error-utils'
|
|
26
|
+
import { fetchWithRegistryFallback } from './hostdb-client'
|
|
26
27
|
import {
|
|
27
28
|
type Engine,
|
|
28
29
|
Platform,
|
|
@@ -205,7 +206,9 @@ export abstract class BaseServerBinaryManager {
|
|
|
205
206
|
|
|
206
207
|
let response: Response
|
|
207
208
|
try {
|
|
208
|
-
response = await
|
|
209
|
+
response = await fetchWithRegistryFallback(url, {
|
|
210
|
+
signal: controller.signal,
|
|
211
|
+
})
|
|
209
212
|
} catch (error) {
|
|
210
213
|
const err = error as Error
|
|
211
214
|
if (err.name === 'AbortError') {
|
|
@@ -224,7 +227,7 @@ export abstract class BaseServerBinaryManager {
|
|
|
224
227
|
throw new Error(
|
|
225
228
|
`${this.config.displayName} ${fullVersion} binaries not found (404). ` +
|
|
226
229
|
`This version may have been removed from hostdb. ` +
|
|
227
|
-
`Try a different version or check https://
|
|
230
|
+
`Try a different version or check https://registry.layerbase.host`,
|
|
228
231
|
)
|
|
229
232
|
}
|
|
230
233
|
throw new Error(
|