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
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
- **88 combinations. One CLI. Zero configuration.**
54
+ **89 combinations. One CLI. Zero configuration.**
55
55
 
56
- > ClickHouse and FerretDB are available on Windows via WSL.
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** - Not supported (postgresql-documentdb has startup issues on 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
  ---
@@ -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) {
@@ -74,7 +74,9 @@ import { typedbBinaryManager } from '../../engines/typedb/binary-manager'
74
74
  import { influxdbBinaryManager } from '../../engines/influxdb/binary-manager'
75
75
  import {
76
76
  DEFAULT_DOCUMENTDB_VERSION,
77
+ DEFAULT_V1_POSTGRESQL_VERSION,
77
78
  normalizeDocumentDBVersion,
79
+ isV1,
78
80
  } from '../../engines/ferretdb/version-maps'
79
81
 
80
82
  // Display manual installation instructions for missing dependencies
@@ -1727,26 +1729,41 @@ enginesCommand
1727
1729
  }
1728
1730
 
1729
1731
  if (['ferretdb', 'ferret'].includes(normalizedEngine)) {
1730
- // Check platform support
1731
1732
  const { platform } = platformService.getPlatformInfo()
1732
- if (platform === Platform.Win32) {
1733
+
1734
+ if (!version) {
1735
+ // Auto-select v1 on Windows (v2 not supported)
1736
+ if (platform === Platform.Win32) {
1737
+ version = '1'
1738
+ console.log(
1739
+ chalk.gray(
1740
+ ' Auto-selecting FerretDB v1 (v2 is not available on Windows)',
1741
+ ),
1742
+ )
1743
+ } else {
1744
+ console.error(uiError('FerretDB requires a version (e.g., 1 or 2)'))
1745
+ process.exit(1)
1746
+ }
1747
+ }
1748
+
1749
+ // Block v2 on Windows with helpful message
1750
+ if (platform === Platform.Win32 && !isV1(version)) {
1733
1751
  console.error(
1734
- uiError('FerretDB is not supported on Windows via hostdb'),
1752
+ uiError(
1753
+ 'FerretDB v2 is not supported on Windows (postgresql-documentdb has startup issues)',
1754
+ ),
1735
1755
  )
1736
1756
  console.log(
1737
1757
  chalk.gray(
1738
- ' FerretDB binaries are only available for macOS and Linux.',
1758
+ ' Use FerretDB v1 instead, which uses plain PostgreSQL:',
1739
1759
  ),
1740
1760
  )
1741
- process.exit(1)
1742
- }
1743
-
1744
- if (!version) {
1745
- console.error(uiError('FerretDB requires a version (e.g., 2)'))
1761
+ console.log(chalk.cyan(' spindb engines download ferretdb 1'))
1746
1762
  process.exit(1)
1747
1763
  }
1748
1764
 
1749
1765
  const engine = getEngine(Engine.FerretDB)
1766
+ const v1 = isV1(version)
1750
1767
 
1751
1768
  const spinner = createSpinner(
1752
1769
  `Checking FerretDB ${version} binaries...`,
@@ -1780,18 +1797,31 @@ enginesCommand
1780
1797
  )
1781
1798
  console.log(chalk.gray(` FerretDB location: ${binPath}`))
1782
1799
 
1783
- // Also show postgresql-documentdb location
1784
- const fullDocumentDBVersion = normalizeDocumentDBVersion(
1785
- DEFAULT_DOCUMENTDB_VERSION,
1786
- )
1787
- const documentdbPath = ferretdbBinaryManager.getDocumentDBBinaryPath(
1788
- fullDocumentDBVersion,
1789
- ferretPlatform,
1790
- ferretArch,
1791
- )
1792
- console.log(
1793
- chalk.gray(` postgresql-documentdb location: ${documentdbPath}`),
1794
- )
1800
+ // Show backend location (version-dependent)
1801
+ if (v1) {
1802
+ const pgFullVersion = postgresqlBinaryManager.getFullVersion(
1803
+ DEFAULT_V1_POSTGRESQL_VERSION,
1804
+ )
1805
+ const pgPath = paths.getBinaryPath({
1806
+ engine: 'postgresql',
1807
+ version: pgFullVersion,
1808
+ platform: ferretPlatform,
1809
+ arch: ferretArch,
1810
+ })
1811
+ console.log(chalk.gray(` PostgreSQL backend location: ${pgPath}`))
1812
+ } else {
1813
+ const fullDocumentDBVersion = normalizeDocumentDBVersion(
1814
+ DEFAULT_DOCUMENTDB_VERSION,
1815
+ )
1816
+ const documentdbPath = ferretdbBinaryManager.getDocumentDBBinaryPath(
1817
+ fullDocumentDBVersion,
1818
+ ferretPlatform,
1819
+ ferretArch,
1820
+ )
1821
+ console.log(
1822
+ chalk.gray(` postgresql-documentdb location: ${documentdbPath}`),
1823
+ )
1824
+ }
1795
1825
 
1796
1826
  // Skip client tools check - FerretDB uses MongoDB client tools (mongosh)
1797
1827
  // which are installed separately via: spindb engines download mongodb
@@ -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
- await dbEngine.start(config)
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 - also clean up postgresql-documentdb backend
289
- // But only if no other FerretDB installations share it
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 platform-arch from ferretdb directory name (e.g., "darwin-arm64")
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
- const entries = await readdir(binDir, { withFileTypes: true })
300
-
301
- // Check if other FerretDB installations exist for the same platform
302
- // If so, don't delete the shared postgresql-documentdb backend
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 (otherFerretInstalls.length > 0) {
312
- // Other FerretDB versions exist - skip documentdb deletion
313
- spinner.text = `Skipping postgresql-documentdb (shared by ${otherFerretInstalls.length} other FerretDB install(s))`
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
- // No other FerretDB installs - safe to delete documentdb backend
316
- const documentdbPattern = `postgresql-documentdb-`
317
- for (const entry of entries) {
318
- if (
319
- entry.isDirectory() &&
320
- entry.name.startsWith(documentdbPattern) &&
321
- entry.name.endsWith(platformArch)
322
- ) {
323
- const documentdbPath = join(binDir, entry.name)
324
- spinner.text = `Deleting postgresql-documentdb backend...`
325
- await rm(documentdbPath, { recursive: true, force: true })
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 === 0) return '0 B'
120
+ if (!Number.isFinite(bytes) || bytes <= 0) return '0 B'
121
121
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
122
- const i = Math.floor(Math.log(bytes) / Math.log(1024))
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
  }
@@ -185,7 +185,7 @@
185
185
  "icon": "πŸ¦”",
186
186
  "status": "integrated",
187
187
  "binarySource": "hostdb",
188
- "supportedVersions": ["2.7.0"],
188
+ "supportedVersions": ["1.24.2", "2.7.0"],
189
189
  "defaultVersion": "2.7.0",
190
190
  "defaultPort": 27017,
191
191
  "runtime": "server",
@@ -195,7 +195,7 @@
195
195
  "superuser": null,
196
196
  "clientTools": ["ferretdb", "mongosh", "mongodump", "mongorestore"],
197
197
  "licensing": "Apache-2.0",
198
- "notes": "MongoDB-compatible proxy using PostgreSQL as backend. Requires postgresql-documentdb."
198
+ "notes": "MongoDB-compatible proxy. v2 uses postgresql-documentdb (macOS/Linux). v1 uses plain PostgreSQL (all platforms incl. Windows)."
199
199
  },
200
200
  "couchdb": {
201
201
  "displayName": "CouchDB",
@@ -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 fetch(url, { signal: controller.signal })
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://github.com/robertjbass/hostdb/releases`,
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 fetch(url, { signal: controller.signal })
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://github.com/robertjbass/hostdb/releases`,
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 fetch(url, { signal: controller.signal })
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://github.com/robertjbass/hostdb/releases`,
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 fetch(url, { signal: controller.signal })
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://github.com/robertjbass/hostdb/releases`,
230
+ `Try a different version or check https://registry.layerbase.host`,
228
231
  )
229
232
  }
230
233
  throw new Error(