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.
Files changed (49) hide show
  1. package/README.md +4 -4
  2. package/cli/commands/create.ts +22 -1
  3. package/cli/commands/engines.ts +51 -21
  4. package/cli/commands/menu/container-handlers.ts +17 -1
  5. package/cli/commands/menu/engine-handlers.ts +48 -29
  6. package/cli/ui/theme.ts +5 -2
  7. package/config/engines.json +2 -2
  8. package/core/base-binary-manager.ts +6 -2
  9. package/core/base-document-binary-manager.ts +5 -2
  10. package/core/base-embedded-binary-manager.ts +5 -2
  11. package/core/base-server-binary-manager.ts +5 -2
  12. package/core/hostdb-client.ts +157 -22
  13. package/core/hostdb-metadata.ts +67 -43
  14. package/engines/clickhouse/binary-urls.ts +1 -1
  15. package/engines/cockroachdb/binary-urls.ts +9 -7
  16. package/engines/cockroachdb/hostdb-releases.ts +18 -106
  17. package/engines/cockroachdb/version-maps.ts +1 -1
  18. package/engines/couchdb/binary-urls.ts +1 -1
  19. package/engines/duckdb/binary-urls.ts +1 -1
  20. package/engines/duckdb/index.ts +4 -74
  21. package/engines/ferretdb/README.md +76 -38
  22. package/engines/ferretdb/backup.ts +18 -10
  23. package/engines/ferretdb/binary-manager.ts +233 -35
  24. package/engines/ferretdb/binary-urls.ts +69 -24
  25. package/engines/ferretdb/index.ts +424 -213
  26. package/engines/ferretdb/restore.ts +23 -16
  27. package/engines/ferretdb/version-maps.ts +36 -8
  28. package/engines/index.ts +3 -4
  29. package/engines/influxdb/binary-urls.ts +1 -1
  30. package/engines/mariadb/binary-urls.ts +2 -2
  31. package/engines/meilisearch/binary-urls.ts +1 -1
  32. package/engines/mysql/binary-urls.ts +2 -2
  33. package/engines/postgresql/binary-urls.ts +1 -1
  34. package/engines/qdrant/binary-urls.ts +1 -1
  35. package/engines/questdb/binary-manager.ts +16 -9
  36. package/engines/questdb/binary-urls.ts +9 -10
  37. package/engines/questdb/hostdb-releases.ts +19 -97
  38. package/engines/questdb/version-maps.ts +2 -2
  39. package/engines/redis/binary-urls.ts +1 -8
  40. package/engines/sqlite/binary-urls.ts +1 -1
  41. package/engines/sqlite/index.ts +4 -74
  42. package/engines/surrealdb/binary-urls.ts +9 -7
  43. package/engines/surrealdb/hostdb-releases.ts +18 -106
  44. package/engines/surrealdb/version-maps.ts +1 -1
  45. package/engines/typedb/binary-urls.ts +10 -8
  46. package/engines/typedb/hostdb-releases.ts +18 -113
  47. package/engines/typedb/version-maps.ts +1 -1
  48. package/engines/valkey/binary-urls.ts +1 -1
  49. 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 postgresql-documentdb binary
22
- * Shared helper to avoid duplication between getPgRestorePath and getPsqlPath
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 getDocumentDBBinaryPath(
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 fullBackendVersion = normalizeDocumentDBVersion(
32
- backendVersion || DEFAULT_DOCUMENTDB_VERSION,
33
- )
34
- const documentdbPath = ferretdbBinaryManager.getDocumentDBBinaryPath(
35
- fullBackendVersion,
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(documentdbPath, 'bin', `${binaryName}${ext}`)
45
+ return join(backendPath, 'bin', `${binaryName}${ext}`)
42
46
  }
43
47
 
44
48
  /**
45
- * Get the path to pg_restore from the postgresql-documentdb installation
49
+ * Get the path to pg_restore from the backend installation
46
50
  */
47
51
  function getPgRestorePath(container: ContainerConfig): string {
48
- return getDocumentDBBinaryPath(container, 'pg_restore')
52
+ return getBackendBinaryFullPath(container, 'pg_restore')
49
53
  }
50
54
 
51
55
  /**
52
- * Get the path to psql from the postgresql-documentdb installation
56
+ * Get the path to psql from the backend installation
53
57
  */
54
58
  function getPsqlPath(container: ContainerConfig): string {
55
- return getDocumentDBBinaryPath(container, 'psql')
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 postgresql-documentdb is installed.`,
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
- * To update: Check releases.json, find databases.ferretdb, copy all version strings.
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
- // 1-part: major version -> latest
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
- const WINDOWS_UNSUPPORTED_ENGINES = new Set([
27
- Engine.ClickHouse,
28
- Engine.FerretDB,
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://github.com/robertjbass/hostdb/releases/download/influxdb-{version}/influxdb-{version}-{platform}-{arch}.{ext}
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://github.com/robertjbass/hostdb/releases/download/mariadb-{version}/mariadb-{version}-{platform}-{arch}.tar.gz
36
- * Windows: https://github.com/robertjbass/hostdb/releases/download/mariadb-{version}/mariadb-{version}-{platform}-{arch}.zip
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://github.com/robertjbass/hostdb/releases/download/meilisearch-{version}/meilisearch-{version}-{platform}-{arch}.{ext}
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://github.com/robertjbass/hostdb/releases/download/mysql-{version}/mysql-{version}-{platform}-{arch}.tar.gz
40
- * Windows: https://github.com/robertjbass/hostdb/releases/download/mysql-{version}/mysql-{version}-{platform}-{arch}.zip
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://github.com/robertjbass/hostdb/releases/download/postgresql-{version}/postgresql-{version}-{platform}-{arch}.tar.gz
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://github.com/robertjbass/hostdb/releases/download/qdrant-{version}/qdrant-{version}-{platform}-{arch}.{ext}
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
- // Use 10-second timeout to avoid hanging on slow/unresponsive networks
255
- const response = await fetch(RELEASES_URL, {
256
- signal: AbortSignal.timeout(10000),
257
- })
258
- if (!response.ok) return false
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://github.com/robertjbass/hostdb/releases for updates.`,
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 hostdb.
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://github.com/robertjbass/hostdb/releases/download/questdb-{version}/questdb-{version}-{platform}-{arch}.tar.gz
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 `${HOSTDB_BASE_URL}/questdb-${fullVersion}/questdb-${fullVersion}-${platformKey}.${ext}`
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
- * QuestDB hostdb Releases
2
+ * hostdb Releases Module for QuestDB
3
3
  *
4
- * Fetches available QuestDB versions from hostdb releases.json
5
- * Falls back to local version-maps.ts if fetch fails.
4
+ * Fetches QuestDB binary information from the hostdb repository at
5
+ * https://github.com/robertjbass/hostdb
6
6
  */
7
7
 
8
- import { logDebug } from '../../core/error-handler'
9
- import { SUPPORTED_MAJOR_VERSIONS, FALLBACK_VERSION_MAP } from './version-maps'
10
-
11
- const RELEASES_URL =
12
- 'https://raw.githubusercontent.com/robertjbass/hostdb/main/releases.json'
13
-
14
- // Cache for fetched versions (5-minute TTL)
15
- let cachedVersions: Record<string, string[]> | null = null
16
- let cacheTimestamp = 0
17
- const CACHE_TTL_MS = 5 * 60 * 1000 // 5 minutes
18
-
19
- type ReleaseInfo = {
20
- version: string
21
- platforms: string[]
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 releases.json:
5
- * https://github.com/robertjbass/hostdb/blob/main/releases.json
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://github.com/robertjbass/hostdb/releases/download/redis-{version}/redis-{version}-{platform}-{arch}.{ext}
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://github.com/robertjbass/hostdb/releases/download/sqlite-{version}/sqlite-{version}-{platform}-{arch}.{ext}
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')
@@ -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
- SUPPORTED_MAJOR_VERSIONS,
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://github.com/robertjbass/hostdb/releases`,
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
- // Try to fetch from hostdb first
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 hostdb.
4
+ * Generates download URLs for SurrealDB binaries from the layerbase registry.
5
5
  */
6
6
 
7
- import type { Platform, Arch } from '../../types'
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://github.com/robertjbass/hostdb/releases/download/surrealdb-{version}/surrealdb-{version}-{platform}-{arch}.{ext}
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 `${HOSTDB_BASE_URL}/surrealdb-${fullVersion}/surrealdb-${fullVersion}-${platform}-${arch}.${ext}`
28
+ return buildHostdbUrl(Engine.SurrealDB, {
29
+ version: fullVersion,
30
+ hostdbPlatform: `${platform}-${arch}`,
31
+ extension: ext,
32
+ })
31
33
  }
32
34
 
33
35
  /**