spindb 0.34.5 → 0.35.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 +4 -4
- package/cli/commands/create.ts +22 -1
- package/cli/commands/engines.ts +51 -21
- 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.json +2 -2
- 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
|
@@ -12,47 +12,51 @@ import { logDebug, logWarning } from '../../core/error-handler'
|
|
|
12
12
|
import { platformService } from '../../core/platform-service'
|
|
13
13
|
import { ferretdbBinaryManager } from './binary-manager'
|
|
14
14
|
import {
|
|
15
|
-
normalizeDocumentDBVersion,
|
|
16
15
|
DEFAULT_DOCUMENTDB_VERSION,
|
|
16
|
+
DEFAULT_V1_POSTGRESQL_VERSION,
|
|
17
|
+
isV1,
|
|
17
18
|
} from './version-maps'
|
|
18
19
|
import type { ContainerConfig, BackupFormat, RestoreResult } from '../../types'
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
|
-
* Resolve the path to a
|
|
22
|
-
*
|
|
22
|
+
* Resolve the path to a backend binary (pg_restore, psql, etc.)
|
|
23
|
+
* Uses version-aware backend resolution (v1 = plain PostgreSQL, v2 = postgresql-documentdb)
|
|
23
24
|
*/
|
|
24
|
-
function
|
|
25
|
+
function getBackendBinaryFullPath(
|
|
25
26
|
container: ContainerConfig,
|
|
26
27
|
binaryName: string,
|
|
27
28
|
): string {
|
|
28
|
-
const { backendVersion } = container
|
|
29
|
+
const { version, backendVersion } = container
|
|
29
30
|
const { platform, arch } = platformService.getPlatformInfo()
|
|
31
|
+
const v1 = isV1(version)
|
|
30
32
|
|
|
31
|
-
const
|
|
32
|
-
backendVersion ||
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const effectiveBackendVersion = v1
|
|
34
|
+
? backendVersion || DEFAULT_V1_POSTGRESQL_VERSION
|
|
35
|
+
: backendVersion || DEFAULT_DOCUMENTDB_VERSION
|
|
36
|
+
|
|
37
|
+
const backendPath = ferretdbBinaryManager.getBackendBinaryPath(
|
|
38
|
+
version,
|
|
39
|
+
effectiveBackendVersion,
|
|
36
40
|
platform,
|
|
37
41
|
arch,
|
|
38
42
|
)
|
|
39
43
|
|
|
40
44
|
const ext = platformService.getExecutableExtension()
|
|
41
|
-
return join(
|
|
45
|
+
return join(backendPath, 'bin', `${binaryName}${ext}`)
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
/**
|
|
45
|
-
* Get the path to pg_restore from the
|
|
49
|
+
* Get the path to pg_restore from the backend installation
|
|
46
50
|
*/
|
|
47
51
|
function getPgRestorePath(container: ContainerConfig): string {
|
|
48
|
-
return
|
|
52
|
+
return getBackendBinaryFullPath(container, 'pg_restore')
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
/**
|
|
52
|
-
* Get the path to psql from the
|
|
56
|
+
* Get the path to psql from the backend installation
|
|
53
57
|
*/
|
|
54
58
|
function getPsqlPath(container: ContainerConfig): string {
|
|
55
|
-
return
|
|
59
|
+
return getBackendBinaryFullPath(container, 'psql')
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
/**
|
|
@@ -196,8 +200,11 @@ export async function restoreBackup(
|
|
|
196
200
|
|
|
197
201
|
if (!existsSync(toolPath)) {
|
|
198
202
|
const toolName = isSqlFormat ? 'psql' : 'pg_restore'
|
|
203
|
+
const backendName = isV1(container.version)
|
|
204
|
+
? 'PostgreSQL'
|
|
205
|
+
: 'postgresql-documentdb'
|
|
199
206
|
throw new Error(
|
|
200
|
-
`${toolName} not found at ${toolPath}. Make sure
|
|
207
|
+
`${toolName} not found at ${toolPath}. Make sure ${backendName} is installed.`,
|
|
201
208
|
)
|
|
202
209
|
}
|
|
203
210
|
|
|
@@ -5,11 +5,16 @@
|
|
|
5
5
|
* Until then, manually keep this in sync with robertjbass/hostdb releases.json:
|
|
6
6
|
* https://github.com/robertjbass/hostdb/blob/main/releases.json
|
|
7
7
|
*
|
|
8
|
-
* FerretDB requires two binaries:
|
|
8
|
+
* FerretDB v2 requires two binaries:
|
|
9
9
|
* - ferretdb: The MongoDB-compatible proxy
|
|
10
10
|
* - postgresql-documentdb: PostgreSQL 17 with DocumentDB extension
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* FerretDB v1 requires:
|
|
13
|
+
* - ferretdb: The MongoDB-compatible proxy
|
|
14
|
+
* - Plain PostgreSQL (reuses postgresqlBinaryManager)
|
|
15
|
+
*
|
|
16
|
+
* To update: Check releases.json, find databases.ferretdb,
|
|
17
|
+
* copy all version strings (both v1.x and v2.x are under the same engine).
|
|
13
18
|
*/
|
|
14
19
|
|
|
15
20
|
import { logDebug } from '../../core/error-handler'
|
|
@@ -17,15 +22,20 @@ import { compareVersions } from '../../core/version-utils'
|
|
|
17
22
|
|
|
18
23
|
/**
|
|
19
24
|
* Map major versions to full versions for FerretDB proxy
|
|
20
|
-
* Keys are major versions (e.g., "2")
|
|
25
|
+
* Keys are major versions (e.g., "1", "2")
|
|
21
26
|
* Values are full versions from hostdb releases.json
|
|
27
|
+
*
|
|
28
|
+
* v1.x uses plain PostgreSQL as backend (all platforms incl. Windows)
|
|
29
|
+
* v2.x uses postgresql-documentdb as backend (macOS/Linux only)
|
|
22
30
|
*/
|
|
23
31
|
export const FERRETDB_VERSION_MAP: Record<string, string> = {
|
|
24
|
-
//
|
|
32
|
+
// v1: uses plain PostgreSQL backend
|
|
33
|
+
'1': '1.24.2',
|
|
34
|
+
'1.24': '1.24.2',
|
|
35
|
+
'1.24.2': '1.24.2',
|
|
36
|
+
// v2: uses postgresql-documentdb backend
|
|
25
37
|
'2': '2.7.0',
|
|
26
|
-
// 2-part: major.minor -> latest patch
|
|
27
38
|
'2.7': '2.7.0',
|
|
28
|
-
// 3-part: exact version (identity mapping)
|
|
29
39
|
'2.7.0': '2.7.0',
|
|
30
40
|
}
|
|
31
41
|
|
|
@@ -45,13 +55,31 @@ export const DOCUMENTDB_VERSION_MAP: Record<string, string> = {
|
|
|
45
55
|
* Supported major FerretDB versions (1-part format).
|
|
46
56
|
* Used for grouping and display purposes.
|
|
47
57
|
*/
|
|
48
|
-
export const SUPPORTED_MAJOR_VERSIONS = ['2']
|
|
58
|
+
export const SUPPORTED_MAJOR_VERSIONS = ['1', '2']
|
|
49
59
|
|
|
50
60
|
/**
|
|
51
|
-
* Default postgresql-documentdb version to use with FerretDB
|
|
61
|
+
* Default postgresql-documentdb version to use with FerretDB v2
|
|
52
62
|
*/
|
|
53
63
|
export const DEFAULT_DOCUMENTDB_VERSION = '17-0.107.0'
|
|
54
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Default PostgreSQL version to use as backend for FerretDB v1
|
|
67
|
+
* v1 uses plain PostgreSQL (no DocumentDB extension needed)
|
|
68
|
+
*/
|
|
69
|
+
export const DEFAULT_V1_POSTGRESQL_VERSION = '17'
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Check if a FerretDB version is v1.x (uses plain PostgreSQL backend)
|
|
73
|
+
* vs v2.x (uses postgresql-documentdb backend)
|
|
74
|
+
*
|
|
75
|
+
* @param version - Version string (can be major, major.minor, or full)
|
|
76
|
+
* @returns true if the version is v1.x
|
|
77
|
+
*/
|
|
78
|
+
export function isV1(version: string): boolean {
|
|
79
|
+
const normalized = normalizeVersion(version)
|
|
80
|
+
return normalized.startsWith('1.')
|
|
81
|
+
}
|
|
82
|
+
|
|
55
83
|
/**
|
|
56
84
|
* Fallback map of major versions to stable patch versions
|
|
57
85
|
* Used when hostdb repository is unreachable.
|
package/engines/index.ts
CHANGED
|
@@ -23,10 +23,9 @@ import type { EngineInfo } from '../types'
|
|
|
23
23
|
|
|
24
24
|
// Engines not supported on Windows
|
|
25
25
|
// These engines either don't have Windows binaries or have issues running on Windows
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
])
|
|
26
|
+
// Note: FerretDB v1 supports Windows (v2 does not), so it's not blanket-blocked here.
|
|
27
|
+
// Version-specific platform checks are handled by the engine itself.
|
|
28
|
+
const WINDOWS_UNSUPPORTED_ENGINES = new Set([Engine.ClickHouse])
|
|
30
29
|
|
|
31
30
|
// Registry of available database engines
|
|
32
31
|
export const engines: Record<string, BaseEngine> = {
|
|
@@ -36,7 +36,7 @@ export function getHostdbPlatform(
|
|
|
36
36
|
/**
|
|
37
37
|
* Build the download URL for InfluxDB binaries from hostdb
|
|
38
38
|
*
|
|
39
|
-
* Format: https://
|
|
39
|
+
* Format: https://registry.layerbase.host/influxdb-{version}/influxdb-{version}-{platform}-{arch}.{ext}
|
|
40
40
|
*
|
|
41
41
|
* @param version - InfluxDB version (e.g., '3', '3.8.0')
|
|
42
42
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux', 'win32')
|
|
@@ -32,8 +32,8 @@ export function getHostdbPlatform(
|
|
|
32
32
|
/**
|
|
33
33
|
* Build the download URL for MariaDB binaries from hostdb
|
|
34
34
|
*
|
|
35
|
-
* Format: https://
|
|
36
|
-
* Windows: https://
|
|
35
|
+
* Format: https://registry.layerbase.host/mariadb-{version}/mariadb-{version}-{platform}-{arch}.tar.gz
|
|
36
|
+
* Windows: https://registry.layerbase.host/mariadb-{version}/mariadb-{version}-{platform}-{arch}.zip
|
|
37
37
|
*
|
|
38
38
|
* @param version - MariaDB version (e.g., '11.8', '11.8.5')
|
|
39
39
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux')
|
|
@@ -36,7 +36,7 @@ export function getHostdbPlatform(
|
|
|
36
36
|
/**
|
|
37
37
|
* Build the download URL for Meilisearch binaries from hostdb
|
|
38
38
|
*
|
|
39
|
-
* Format: https://
|
|
39
|
+
* Format: https://registry.layerbase.host/meilisearch-{version}/meilisearch-{version}-{platform}-{arch}.{ext}
|
|
40
40
|
*
|
|
41
41
|
* @param version - Meilisearch version (e.g., '1', '1.33.1')
|
|
42
42
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux', 'win32')
|
|
@@ -36,8 +36,8 @@ export function getHostdbPlatform(
|
|
|
36
36
|
/**
|
|
37
37
|
* Build the download URL for MySQL binaries from hostdb
|
|
38
38
|
*
|
|
39
|
-
* Format: https://
|
|
40
|
-
* Windows: https://
|
|
39
|
+
* Format: https://registry.layerbase.host/mysql-{version}/mysql-{version}-{platform}-{arch}.tar.gz
|
|
40
|
+
* Windows: https://registry.layerbase.host/mysql-{version}/mysql-{version}-{platform}-{arch}.zip
|
|
41
41
|
*
|
|
42
42
|
* @param version - MySQL version (e.g., '8.0', '8.0.40')
|
|
43
43
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux')
|
|
@@ -34,7 +34,7 @@ export function getHostdbPlatform(
|
|
|
34
34
|
/**
|
|
35
35
|
* Build the download URL for PostgreSQL binaries from hostdb
|
|
36
36
|
*
|
|
37
|
-
* Format: https://
|
|
37
|
+
* Format: https://registry.layerbase.host/postgresql-{version}/postgresql-{version}-{platform}-{arch}.tar.gz
|
|
38
38
|
*
|
|
39
39
|
* @param version - PostgreSQL version (e.g., '17', '17.7.0')
|
|
40
40
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux')
|
|
@@ -37,7 +37,7 @@ export function getHostdbPlatform(
|
|
|
37
37
|
/**
|
|
38
38
|
* Build the download URL for Qdrant binaries from hostdb
|
|
39
39
|
*
|
|
40
|
-
* Format: https://
|
|
40
|
+
* Format: https://registry.layerbase.host/qdrant-{version}/qdrant-{version}-{platform}-{arch}.{ext}
|
|
41
41
|
*
|
|
42
42
|
* @param version - Qdrant version (e.g., '1', '1.16.3')
|
|
43
43
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux', 'win32')
|
|
@@ -24,12 +24,10 @@ import { existsSync } from 'fs'
|
|
|
24
24
|
import { join, dirname, relative } from 'path'
|
|
25
25
|
import { chmod, symlink, readdir } from 'fs/promises'
|
|
26
26
|
import { logDebug } from '../../core/error-handler'
|
|
27
|
+
import { getReleasesUrls } from '../../core/hostdb-client'
|
|
27
28
|
import { moveEntry } from '../../core/fs-error-utils'
|
|
28
29
|
import { paths } from '../../config/paths'
|
|
29
30
|
|
|
30
|
-
const RELEASES_URL =
|
|
31
|
-
'https://raw.githubusercontent.com/robertjbass/hostdb/main/releases.json'
|
|
32
|
-
|
|
33
31
|
class QuestDBBinaryManager extends BaseBinaryManager {
|
|
34
32
|
protected readonly config: BinaryManagerConfig = {
|
|
35
33
|
engine: Engine.QuestDB,
|
|
@@ -251,11 +249,20 @@ class QuestDBBinaryManager extends BaseBinaryManager {
|
|
|
251
249
|
*/
|
|
252
250
|
private async checkHostdbAvailability(): Promise<boolean> {
|
|
253
251
|
try {
|
|
254
|
-
//
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
252
|
+
// Try layerbase first, fall back to GitHub
|
|
253
|
+
let response: Response | null = null
|
|
254
|
+
for (const url of getReleasesUrls()) {
|
|
255
|
+
try {
|
|
256
|
+
response = await fetch(url, {
|
|
257
|
+
signal: AbortSignal.timeout(10000),
|
|
258
|
+
})
|
|
259
|
+
if (response.ok) break
|
|
260
|
+
response = null
|
|
261
|
+
} catch {
|
|
262
|
+
// Try next URL
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (!response || !response.ok) return false
|
|
259
266
|
|
|
260
267
|
const releases = (await response.json()) as {
|
|
261
268
|
databases?: Record<string, unknown>
|
|
@@ -287,7 +294,7 @@ class QuestDBBinaryManager extends BaseBinaryManager {
|
|
|
287
294
|
`To use QuestDB now, you can:\n` +
|
|
288
295
|
` 1. Wait for the next hostdb release with QuestDB binaries\n` +
|
|
289
296
|
` 2. Download QuestDB manually from https://questdb.io/get-questdb/\n\n` +
|
|
290
|
-
`Check https://
|
|
297
|
+
`Check https://registry.layerbase.host for updates.`,
|
|
291
298
|
)
|
|
292
299
|
}
|
|
293
300
|
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* QuestDB Binary URLs
|
|
3
3
|
*
|
|
4
|
-
* Constructs download URLs for QuestDB binaries from
|
|
4
|
+
* Constructs download URLs for QuestDB binaries from the layerbase registry.
|
|
5
5
|
* QuestDB archives are self-contained with bundled JRE.
|
|
6
6
|
*
|
|
7
7
|
* URL pattern:
|
|
8
|
-
* https://
|
|
8
|
+
* https://registry.layerbase.host/questdb-{version}/questdb-{version}-{platform}-{arch}.tar.gz
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { FALLBACK_VERSION_MAP } from './version-maps'
|
|
12
|
-
import { type Platform, type Arch } from '../../types'
|
|
13
|
-
|
|
14
|
-
const HOSTDB_BASE_URL =
|
|
15
|
-
'https://github.com/robertjbass/hostdb/releases/download'
|
|
12
|
+
import { Engine, type Platform, type Arch } from '../../types'
|
|
13
|
+
import { buildHostdbUrl } from '../../core/hostdb-client'
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
16
|
* Get the binary download URL for a specific version and platform
|
|
@@ -25,11 +23,12 @@ export function getBinaryUrl(
|
|
|
25
23
|
// Resolve to full version
|
|
26
24
|
const fullVersion = FALLBACK_VERSION_MAP[version] || version
|
|
27
25
|
|
|
28
|
-
// Construct platform key (e.g., 'darwin-arm64', 'linux-x64', 'win32-x64')
|
|
29
|
-
const platformKey = `${platform}-${arch}`
|
|
30
|
-
|
|
31
26
|
// Windows uses .zip, Unix uses .tar.gz
|
|
32
27
|
const ext = platform === 'win32' ? 'zip' : 'tar.gz'
|
|
33
28
|
|
|
34
|
-
return
|
|
29
|
+
return buildHostdbUrl(Engine.QuestDB, {
|
|
30
|
+
version: fullVersion,
|
|
31
|
+
hostdbPlatform: `${platform}-${arch}`,
|
|
32
|
+
extension: ext,
|
|
33
|
+
})
|
|
35
34
|
}
|
|
@@ -1,101 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* hostdb Releases Module for QuestDB
|
|
3
3
|
*
|
|
4
|
-
* Fetches
|
|
5
|
-
*
|
|
4
|
+
* Fetches QuestDB binary information from the hostdb repository at
|
|
5
|
+
* https://github.com/robertjbass/hostdb
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
type ReleasesJson = {
|
|
25
|
-
[engine: string]: ReleaseInfo[]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Fetch available QuestDB versions from hostdb
|
|
30
|
-
* Returns a map of major version to available full versions
|
|
31
|
-
*/
|
|
32
|
-
export async function fetchAvailableVersions(): Promise<
|
|
33
|
-
Record<string, string[]>
|
|
34
|
-
> {
|
|
35
|
-
// Return cached result if still valid
|
|
36
|
-
const now = Date.now()
|
|
37
|
-
if (cachedVersions && now - cacheTimestamp < CACHE_TTL_MS) {
|
|
38
|
-
return cachedVersions
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
const response = await fetch(RELEASES_URL)
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
throw new Error(`HTTP ${response.status}`)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const releases = (await response.json()) as ReleasesJson
|
|
48
|
-
const questdbReleases = releases.questdb || []
|
|
49
|
-
|
|
50
|
-
// Group versions by major version
|
|
51
|
-
const versionMap: Record<string, string[]> = {}
|
|
52
|
-
|
|
53
|
-
for (const release of questdbReleases) {
|
|
54
|
-
const version = release.version
|
|
55
|
-
// Extract major version (e.g., '9' from '9.2.3')
|
|
56
|
-
const majorMatch = version.match(/^(\d+)/)
|
|
57
|
-
if (!majorMatch) continue
|
|
58
|
-
|
|
59
|
-
const major = majorMatch[1]
|
|
60
|
-
|
|
61
|
-
// Only include supported major versions
|
|
62
|
-
if (!SUPPORTED_MAJOR_VERSIONS.includes(major)) continue
|
|
63
|
-
|
|
64
|
-
if (!versionMap[major]) {
|
|
65
|
-
versionMap[major] = []
|
|
66
|
-
}
|
|
67
|
-
versionMap[major].push(version)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Sort versions within each major (newest first)
|
|
71
|
-
for (const major of Object.keys(versionMap)) {
|
|
72
|
-
versionMap[major].sort((a, b) => {
|
|
73
|
-
const partsA = a.split('.').map(Number)
|
|
74
|
-
const partsB = b.split('.').map(Number)
|
|
75
|
-
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
76
|
-
const diff = (partsB[i] || 0) - (partsA[i] || 0)
|
|
77
|
-
if (diff !== 0) return diff
|
|
78
|
-
}
|
|
79
|
-
return 0
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Cache the result
|
|
84
|
-
cachedVersions = versionMap
|
|
85
|
-
cacheTimestamp = now
|
|
86
|
-
|
|
87
|
-
return versionMap
|
|
88
|
-
} catch (error) {
|
|
89
|
-
logDebug(`Failed to fetch QuestDB versions from hostdb: ${error}`)
|
|
90
|
-
|
|
91
|
-
// Fall back to local version map
|
|
92
|
-
const fallbackMap: Record<string, string[]> = {}
|
|
93
|
-
for (const major of SUPPORTED_MAJOR_VERSIONS) {
|
|
94
|
-
const fullVersion = FALLBACK_VERSION_MAP[major]
|
|
95
|
-
if (fullVersion) {
|
|
96
|
-
fallbackMap[major] = [fullVersion]
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return fallbackMap
|
|
100
|
-
}
|
|
101
|
-
}
|
|
8
|
+
import { createHostdbReleases } from '../../core/hostdb-releases-factory'
|
|
9
|
+
import { QUESTDB_VERSION_MAP, SUPPORTED_MAJOR_VERSIONS } from './version-maps'
|
|
10
|
+
import { questdbBinaryManager } from './binary-manager'
|
|
11
|
+
import { Engine } from '../../types'
|
|
12
|
+
|
|
13
|
+
const hostdbReleases = createHostdbReleases({
|
|
14
|
+
engine: Engine.QuestDB,
|
|
15
|
+
displayName: 'QuestDB',
|
|
16
|
+
versionMap: QUESTDB_VERSION_MAP,
|
|
17
|
+
supportedMajorVersions: SUPPORTED_MAJOR_VERSIONS,
|
|
18
|
+
groupingStrategy: 'single-digit',
|
|
19
|
+
listInstalled: () => questdbBinaryManager.listInstalled(),
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
export const fetchAvailableVersions = hostdbReleases.fetchAvailableVersions
|
|
23
|
+
export const getLatestVersion = hostdbReleases.getLatestVersion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* QuestDB Version Maps
|
|
3
3
|
*
|
|
4
|
-
* IMPORTANT: Keep this in sync with hostdb
|
|
5
|
-
* https://github.com/robertjbass/hostdb/blob/main/
|
|
4
|
+
* IMPORTANT: Keep this in sync with hostdb databases.json:
|
|
5
|
+
* https://github.com/robertjbass/hostdb/blob/main/databases.json
|
|
6
6
|
*
|
|
7
7
|
* QuestDB uses standard semantic versioning (e.g., 9.2.3)
|
|
8
8
|
*/
|
|
@@ -37,7 +37,7 @@ export function getHostdbPlatform(
|
|
|
37
37
|
/**
|
|
38
38
|
* Build the download URL for Redis binaries from hostdb
|
|
39
39
|
*
|
|
40
|
-
* Format: https://
|
|
40
|
+
* Format: https://registry.layerbase.host/redis-{version}/redis-{version}-{platform}-{arch}.{ext}
|
|
41
41
|
*
|
|
42
42
|
* @param version - Redis version (e.g., '7', '7.4.7')
|
|
43
43
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux', 'win32')
|
|
@@ -115,10 +115,3 @@ function normalizeVersion(
|
|
|
115
115
|
)
|
|
116
116
|
return version
|
|
117
117
|
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Get the full version string for a major version
|
|
121
|
-
*
|
|
122
|
-
* @param majorVersion - Major version (e.g., '7', '8')
|
|
123
|
-
* @returns Full version string (e.g., '7.4.7') or null if not supported
|
|
124
|
-
*/
|
|
@@ -12,7 +12,7 @@ import { Engine, type Platform, type Arch } from '../../types'
|
|
|
12
12
|
/**
|
|
13
13
|
* Build the download URL for SQLite binaries from hostdb
|
|
14
14
|
*
|
|
15
|
-
* Format: https://
|
|
15
|
+
* Format: https://registry.layerbase.host/sqlite-{version}/sqlite-{version}-{platform}-{arch}.{ext}
|
|
16
16
|
*
|
|
17
17
|
* @param version - SQLite version (e.g., '3', '3.51.2')
|
|
18
18
|
* @param platform - Platform identifier (e.g., 'darwin', 'linux', 'win32')
|
package/engines/sqlite/index.ts
CHANGED
|
@@ -26,18 +26,10 @@ import { platformService } from '../../core/platform-service'
|
|
|
26
26
|
import { paths } from '../../config/paths'
|
|
27
27
|
import { sqliteBinaryManager } from './binary-manager'
|
|
28
28
|
import { getBinaryUrl } from './binary-urls'
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
SQLITE_VERSION_MAP,
|
|
32
|
-
normalizeVersion,
|
|
33
|
-
} from './version-maps'
|
|
34
|
-
import {
|
|
35
|
-
fetchHostdbReleases,
|
|
36
|
-
getEngineReleases,
|
|
37
|
-
} from '../../core/hostdb-client'
|
|
29
|
+
import { SUPPORTED_MAJOR_VERSIONS, normalizeVersion } from './version-maps'
|
|
30
|
+
import { fetchAvailableVersions } from './hostdb-releases'
|
|
38
31
|
import { logDebug } from '../../core/error-handler'
|
|
39
32
|
import {
|
|
40
|
-
Engine,
|
|
41
33
|
type Platform,
|
|
42
34
|
type Arch,
|
|
43
35
|
type ContainerConfig,
|
|
@@ -517,7 +509,7 @@ export class SQLiteEngine extends BaseEngine {
|
|
|
517
509
|
throw new Error(
|
|
518
510
|
`File not found (404) at ${url}. ` +
|
|
519
511
|
`This version may have been removed from hostdb. ` +
|
|
520
|
-
`Try a different version or check https://
|
|
512
|
+
`Try a different version or check https://registry.layerbase.host`,
|
|
521
513
|
)
|
|
522
514
|
}
|
|
523
515
|
throw new Error(
|
|
@@ -579,69 +571,7 @@ export class SQLiteEngine extends BaseEngine {
|
|
|
579
571
|
}
|
|
580
572
|
|
|
581
573
|
async fetchAvailableVersions(): Promise<Record<string, string[]>> {
|
|
582
|
-
|
|
583
|
-
try {
|
|
584
|
-
const releases = await fetchHostdbReleases()
|
|
585
|
-
const sqliteReleases = getEngineReleases(releases, Engine.SQLite)
|
|
586
|
-
|
|
587
|
-
if (sqliteReleases && Object.keys(sqliteReleases).length > 0) {
|
|
588
|
-
const result: Record<string, string[]> = {}
|
|
589
|
-
|
|
590
|
-
for (const major of SUPPORTED_MAJOR_VERSIONS) {
|
|
591
|
-
result[major] = []
|
|
592
|
-
|
|
593
|
-
// Find all versions matching this major version
|
|
594
|
-
for (const [, release] of Object.entries(sqliteReleases)) {
|
|
595
|
-
if (release.version.startsWith(`${major}.`)) {
|
|
596
|
-
result[major].push(release.version)
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
// Sort descending (latest first)
|
|
601
|
-
result[major].sort((a, b) => {
|
|
602
|
-
const partsA = a.split('.').map(Number)
|
|
603
|
-
const partsB = b.split('.').map(Number)
|
|
604
|
-
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
605
|
-
const diff = (partsB[i] || 0) - (partsA[i] || 0)
|
|
606
|
-
if (diff !== 0) return diff
|
|
607
|
-
}
|
|
608
|
-
return 0
|
|
609
|
-
})
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
return result
|
|
613
|
-
}
|
|
614
|
-
} catch (error) {
|
|
615
|
-
logDebug('Failed to fetch SQLite versions from hostdb, checking local', {
|
|
616
|
-
error: error instanceof Error ? error.message : String(error),
|
|
617
|
-
})
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
// Offline fallback: return only locally installed versions
|
|
621
|
-
const installed = await sqliteBinaryManager.listInstalled()
|
|
622
|
-
if (installed.length > 0) {
|
|
623
|
-
const result: Record<string, string[]> = {}
|
|
624
|
-
for (const binary of installed) {
|
|
625
|
-
const major = binary.version.split('.')[0]
|
|
626
|
-
if (!result[major]) {
|
|
627
|
-
result[major] = []
|
|
628
|
-
}
|
|
629
|
-
if (!result[major].includes(binary.version)) {
|
|
630
|
-
result[major].push(binary.version)
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
return result
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
// Last resort: return hardcoded version map
|
|
637
|
-
const result: Record<string, string[]> = {}
|
|
638
|
-
for (const major of SUPPORTED_MAJOR_VERSIONS) {
|
|
639
|
-
const fullVersion = SQLITE_VERSION_MAP[major]
|
|
640
|
-
if (fullVersion) {
|
|
641
|
-
result[major] = [fullVersion]
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
return result
|
|
574
|
+
return fetchAvailableVersions()
|
|
645
575
|
}
|
|
646
576
|
|
|
647
577
|
// Helper to get sqlite3 path or throw a helpful error
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SurrealDB binary URL generation
|
|
3
3
|
*
|
|
4
|
-
* Generates download URLs for SurrealDB binaries from
|
|
4
|
+
* Generates download URLs for SurrealDB binaries from the layerbase registry.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type
|
|
7
|
+
import { Engine, type Platform, type Arch } from '../../types'
|
|
8
8
|
import { normalizeVersion } from './version-maps'
|
|
9
|
-
|
|
10
|
-
const HOSTDB_BASE_URL =
|
|
11
|
-
'https://github.com/robertjbass/hostdb/releases/download'
|
|
9
|
+
import { buildHostdbUrl } from '../../core/hostdb-client'
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
12
|
* Get the binary download URL for a specific version and platform
|
|
15
13
|
*
|
|
16
|
-
* URL format: https://
|
|
14
|
+
* URL format: https://registry.layerbase.host/surrealdb-{version}/surrealdb-{version}-{platform}-{arch}.{ext}
|
|
17
15
|
*
|
|
18
16
|
* @param version - SurrealDB version (e.g., '2.3.2' or '2')
|
|
19
17
|
* @param platform - Target platform (darwin, linux, win32)
|
|
@@ -27,7 +25,11 @@ export function getBinaryUrl(
|
|
|
27
25
|
const fullVersion = normalizeVersion(version)
|
|
28
26
|
const ext = platform === 'win32' ? 'zip' : 'tar.gz'
|
|
29
27
|
|
|
30
|
-
return
|
|
28
|
+
return buildHostdbUrl(Engine.SurrealDB, {
|
|
29
|
+
version: fullVersion,
|
|
30
|
+
hostdbPlatform: `${platform}-${arch}`,
|
|
31
|
+
extension: ext,
|
|
32
|
+
})
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
/**
|