spindb 0.34.3 → 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 (64) hide show
  1. package/README.md +4 -4
  2. package/cli/commands/attach.ts +38 -9
  3. package/cli/commands/backups.ts +5 -0
  4. package/cli/commands/connect.ts +6 -6
  5. package/cli/commands/create.ts +22 -1
  6. package/cli/commands/detach.ts +16 -9
  7. package/cli/commands/doctor.ts +2 -2
  8. package/cli/commands/duckdb.ts +273 -0
  9. package/cli/commands/edit.ts +31 -21
  10. package/cli/commands/engines.ts +51 -21
  11. package/cli/commands/info.ts +26 -16
  12. package/cli/commands/list.ts +44 -26
  13. package/cli/commands/menu/container-handlers.ts +17 -1
  14. package/cli/commands/menu/engine-handlers.ts +48 -29
  15. package/cli/commands/menu/update-handlers.ts +2 -2
  16. package/cli/commands/sqlite.ts +21 -0
  17. package/cli/index.ts +2 -0
  18. package/cli/ui/theme.ts +5 -2
  19. package/config/engines.json +2 -2
  20. package/core/base-binary-manager.ts +6 -2
  21. package/core/base-document-binary-manager.ts +5 -2
  22. package/core/base-embedded-binary-manager.ts +5 -2
  23. package/core/base-server-binary-manager.ts +5 -2
  24. package/core/hostdb-client.ts +157 -22
  25. package/core/hostdb-metadata.ts +67 -43
  26. package/engines/clickhouse/binary-urls.ts +1 -1
  27. package/engines/cockroachdb/binary-urls.ts +9 -7
  28. package/engines/cockroachdb/hostdb-releases.ts +18 -106
  29. package/engines/cockroachdb/version-maps.ts +1 -1
  30. package/engines/couchdb/binary-urls.ts +1 -1
  31. package/engines/duckdb/binary-urls.ts +1 -1
  32. package/engines/duckdb/index.ts +4 -74
  33. package/engines/duckdb/scanner.ts +22 -0
  34. package/engines/ferretdb/README.md +76 -38
  35. package/engines/ferretdb/backup.ts +18 -10
  36. package/engines/ferretdb/binary-manager.ts +233 -35
  37. package/engines/ferretdb/binary-urls.ts +69 -24
  38. package/engines/ferretdb/index.ts +424 -213
  39. package/engines/ferretdb/restore.ts +23 -16
  40. package/engines/ferretdb/version-maps.ts +36 -8
  41. package/engines/file-based-utils.ts +262 -0
  42. package/engines/index.ts +3 -4
  43. package/engines/influxdb/binary-urls.ts +1 -1
  44. package/engines/mariadb/binary-urls.ts +2 -2
  45. package/engines/meilisearch/binary-urls.ts +1 -1
  46. package/engines/mysql/binary-urls.ts +2 -2
  47. package/engines/postgresql/binary-urls.ts +1 -1
  48. package/engines/qdrant/binary-urls.ts +1 -1
  49. package/engines/questdb/binary-manager.ts +16 -9
  50. package/engines/questdb/binary-urls.ts +9 -10
  51. package/engines/questdb/hostdb-releases.ts +19 -97
  52. package/engines/questdb/version-maps.ts +2 -2
  53. package/engines/redis/binary-urls.ts +1 -8
  54. package/engines/sqlite/binary-urls.ts +1 -1
  55. package/engines/sqlite/index.ts +4 -74
  56. package/engines/sqlite/scanner.ts +11 -88
  57. package/engines/surrealdb/binary-urls.ts +9 -7
  58. package/engines/surrealdb/hostdb-releases.ts +18 -106
  59. package/engines/surrealdb/version-maps.ts +1 -1
  60. package/engines/typedb/binary-urls.ts +10 -8
  61. package/engines/typedb/hostdb-releases.ts +18 -113
  62. package/engines/typedb/version-maps.ts +1 -1
  63. package/engines/valkey/binary-urls.ts +1 -1
  64. package/package.json +4 -1
@@ -1,114 +1,26 @@
1
1
  /**
2
- * CockroachDB hostdb releases integration
2
+ * hostdb Releases Module for CockroachDB
3
3
  *
4
- * Fetches available versions from hostdb releases.json and provides
5
- * fallback to local version maps.
4
+ * Fetches CockroachDB binary information from the hostdb repository at
5
+ * https://github.com/robertjbass/hostdb
6
6
  */
7
7
 
8
- import { logDebug } from '../../core/error-handler'
8
+ import { createHostdbReleases } from '../../core/hostdb-releases-factory'
9
9
  import {
10
10
  COCKROACHDB_VERSION_MAP,
11
11
  SUPPORTED_MAJOR_VERSIONS,
12
12
  } from './version-maps'
13
-
14
- const HOSTDB_RELEASES_URL =
15
- 'https://raw.githubusercontent.com/robertjbass/hostdb/main/releases.json'
16
-
17
- // Cache for fetched versions (expires after 5 minutes)
18
- let cachedVersions: Record<string, string[]> | null = null
19
- let cacheExpiry = 0
20
- const CACHE_TTL_MS = 5 * 60 * 1000
21
-
22
- type HostdbReleases = {
23
- [engine: string]: {
24
- versions: {
25
- version: string
26
- platforms: string[]
27
- }[]
28
- }
29
- }
30
-
31
- /**
32
- * Fetch available CockroachDB versions from hostdb
33
- * Returns a map of major version to available patch versions
34
- *
35
- * Falls back to local version maps if fetch fails
36
- */
37
- export async function fetchAvailableVersions(): Promise<
38
- Record<string, string[]>
39
- > {
40
- // Return cached versions if still valid
41
- if (cachedVersions && Date.now() < cacheExpiry) {
42
- return cachedVersions
43
- }
44
-
45
- try {
46
- const response = await fetch(HOSTDB_RELEASES_URL)
47
- if (!response.ok) {
48
- throw new Error(`HTTP ${response.status}`)
49
- }
50
-
51
- const releases = (await response.json()) as HostdbReleases
52
- const cockroachdbReleases = releases.cockroachdb
53
-
54
- if (!cockroachdbReleases?.versions) {
55
- throw new Error('No CockroachDB versions found in releases.json')
56
- }
57
-
58
- // Group versions by major version (YY.MM format)
59
- const versionMap: Record<string, string[]> = {}
60
-
61
- for (const { version } of cockroachdbReleases.versions) {
62
- // Extract major version (e.g., "25" from "25.4.2")
63
- const majorMatch = version.match(/^(\d+)/)
64
- if (!majorMatch) continue
65
-
66
- const majorVersion = majorMatch[1]
67
- if (!versionMap[majorVersion]) {
68
- versionMap[majorVersion] = []
69
- }
70
- versionMap[majorVersion].push(version)
71
- }
72
-
73
- // Sort versions within each major version (newest first)
74
- for (const major of Object.keys(versionMap)) {
75
- versionMap[major].sort((a, b) => {
76
- const partsA = a.split('.').map(Number)
77
- const partsB = b.split('.').map(Number)
78
- for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
79
- const diff = (partsB[i] || 0) - (partsA[i] || 0)
80
- if (diff !== 0) return diff
81
- }
82
- return 0
83
- })
84
- }
85
-
86
- // Cache the results
87
- cachedVersions = versionMap
88
- cacheExpiry = Date.now() + CACHE_TTL_MS
89
-
90
- logDebug('Fetched CockroachDB versions from hostdb', { versionMap })
91
- return versionMap
92
- } catch (error) {
93
- logDebug(`Failed to fetch hostdb releases: ${error}`)
94
-
95
- // Fall back to local version maps
96
- const fallbackMap: Record<string, string[]> = {}
97
- for (const major of SUPPORTED_MAJOR_VERSIONS) {
98
- const fullVersion = COCKROACHDB_VERSION_MAP[major]
99
- if (fullVersion) {
100
- fallbackMap[major] = [fullVersion]
101
- }
102
- }
103
-
104
- return fallbackMap
105
- }
106
- }
107
-
108
- /**
109
- * Clear the version cache (useful for testing)
110
- */
111
- export function clearVersionCache(): void {
112
- cachedVersions = null
113
- cacheExpiry = 0
114
- }
13
+ import { cockroachdbBinaryManager } from './binary-manager'
14
+ import { Engine } from '../../types'
15
+
16
+ const hostdbReleases = createHostdbReleases({
17
+ engine: Engine.CockroachDB,
18
+ displayName: 'CockroachDB',
19
+ versionMap: COCKROACHDB_VERSION_MAP,
20
+ supportedMajorVersions: SUPPORTED_MAJOR_VERSIONS,
21
+ groupingStrategy: 'single-digit',
22
+ listInstalled: () => cockroachdbBinaryManager.listInstalled(),
23
+ })
24
+
25
+ export const fetchAvailableVersions = hostdbReleases.fetchAvailableVersions
26
+ export const getLatestVersion = hostdbReleases.getLatestVersion
@@ -2,7 +2,7 @@
2
2
  * CockroachDB version mapping
3
3
  *
4
4
  * Maps short version aliases to full versions from hostdb releases.
5
- * MUST stay in sync with hostdb releases.json
5
+ * MUST stay in sync with hostdb databases.json
6
6
  */
7
7
 
8
8
  // Full version map for CockroachDB
@@ -37,7 +37,7 @@ export function getHostdbPlatform(
37
37
  /**
38
38
  * Build the download URL for CouchDB binaries from hostdb
39
39
  *
40
- * Format: https://github.com/robertjbass/hostdb/releases/download/couchdb-{version}/couchdb-{version}-{platform}-{arch}.{ext}
40
+ * Format: https://registry.layerbase.host/couchdb-{version}/couchdb-{version}-{platform}-{arch}.{ext}
41
41
  *
42
42
  * @param version - CouchDB version (e.g., '3', '3.5.1')
43
43
  * @param platform - Platform identifier (e.g., 'darwin', 'linux', 'win32')
@@ -12,7 +12,7 @@ import { Engine, type Platform, type Arch } from '../../types'
12
12
  /**
13
13
  * Build the download URL for DuckDB binaries from hostdb
14
14
  *
15
- * Format: https://github.com/robertjbass/hostdb/releases/download/duckdb-{version}/duckdb-{version}-{platform}-{arch}.{ext}
15
+ * Format: https://registry.layerbase.host/duckdb-{version}/duckdb-{version}-{platform}-{arch}.{ext}
16
16
  *
17
17
  * @param version - DuckDB version (e.g., '1', '1.4.3')
18
18
  * @param platform - Platform identifier (e.g., 'darwin', 'linux', 'win32')
@@ -25,18 +25,10 @@ import { platformService } from '../../core/platform-service'
25
25
  import { paths } from '../../config/paths'
26
26
  import { duckdbBinaryManager } from './binary-manager'
27
27
  import { getBinaryUrl } from './binary-urls'
28
- import {
29
- SUPPORTED_MAJOR_VERSIONS,
30
- DUCKDB_VERSION_MAP,
31
- normalizeVersion,
32
- } from './version-maps'
33
- import {
34
- fetchHostdbReleases,
35
- getEngineReleases,
36
- } from '../../core/hostdb-client'
28
+ import { SUPPORTED_MAJOR_VERSIONS, normalizeVersion } from './version-maps'
29
+ import { fetchAvailableVersions } from './hostdb-releases'
37
30
  import { logDebug } from '../../core/error-handler'
38
31
  import {
39
- Engine,
40
32
  type Platform,
41
33
  type Arch,
42
34
  type ContainerConfig,
@@ -570,7 +562,7 @@ export class DuckDBEngine extends BaseEngine {
570
562
  throw new Error(
571
563
  `File not found (404) at ${url}. ` +
572
564
  `This version may have been removed from hostdb. ` +
573
- `Try a different version or check https://github.com/robertjbass/hostdb/releases`,
565
+ `Try a different version or check https://registry.layerbase.host`,
574
566
  )
575
567
  }
576
568
  throw new Error(
@@ -680,69 +672,7 @@ export class DuckDBEngine extends BaseEngine {
680
672
  }
681
673
 
682
674
  async fetchAvailableVersions(): Promise<Record<string, string[]>> {
683
- // Try to fetch from hostdb first
684
- try {
685
- const releases = await fetchHostdbReleases()
686
- const duckdbReleases = getEngineReleases(releases, Engine.DuckDB)
687
-
688
- if (duckdbReleases && Object.keys(duckdbReleases).length > 0) {
689
- const result: Record<string, string[]> = {}
690
-
691
- for (const major of SUPPORTED_MAJOR_VERSIONS) {
692
- result[major] = []
693
-
694
- // Find all versions matching this major version
695
- for (const [, release] of Object.entries(duckdbReleases)) {
696
- if (release.version.startsWith(`${major}.`)) {
697
- result[major].push(release.version)
698
- }
699
- }
700
-
701
- // Sort descending (latest first)
702
- result[major].sort((a, b) => {
703
- const partsA = a.split('.').map(Number)
704
- const partsB = b.split('.').map(Number)
705
- for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
706
- const diff = (partsB[i] || 0) - (partsA[i] || 0)
707
- if (diff !== 0) return diff
708
- }
709
- return 0
710
- })
711
- }
712
-
713
- return result
714
- }
715
- } catch (error) {
716
- logDebug('Failed to fetch DuckDB versions from hostdb, checking local', {
717
- error: error instanceof Error ? error.message : String(error),
718
- })
719
- }
720
-
721
- // Offline fallback: return only locally installed versions
722
- const installed = await duckdbBinaryManager.listInstalled()
723
- if (installed.length > 0) {
724
- const result: Record<string, string[]> = {}
725
- for (const binary of installed) {
726
- const major = binary.version.split('.')[0]
727
- if (!result[major]) {
728
- result[major] = []
729
- }
730
- if (!result[major].includes(binary.version)) {
731
- result[major].push(binary.version)
732
- }
733
- }
734
- return result
735
- }
736
-
737
- // Last resort: return hardcoded version map
738
- const result: Record<string, string[]> = {}
739
- for (const major of SUPPORTED_MAJOR_VERSIONS) {
740
- const fullVersion = DUCKDB_VERSION_MAP[major]
741
- if (fullVersion) {
742
- result[major] = [fullVersion]
743
- }
744
- }
745
- return result
675
+ return fetchAvailableVersions()
746
676
  }
747
677
 
748
678
  // Helper to get duckdb path or throw a helpful error
@@ -0,0 +1,22 @@
1
+ /**
2
+ * DuckDB Scanner — thin wrapper around shared file-based-utils
3
+ */
4
+
5
+ import { Engine } from '../../types'
6
+ import {
7
+ scanForUnregisteredFiles,
8
+ deriveContainerName as sharedDeriveContainerName,
9
+ type UnregisteredFile,
10
+ } from '../file-based-utils'
11
+
12
+ export type { UnregisteredFile }
13
+
14
+ export async function scanForUnregisteredDuckDBFiles(
15
+ directory?: string,
16
+ ): Promise<UnregisteredFile[]> {
17
+ return scanForUnregisteredFiles(Engine.DuckDB, directory)
18
+ }
19
+
20
+ export function deriveContainerName(fileName: string): string {
21
+ return sharedDeriveContainerName(fileName, Engine.DuckDB)
22
+ }
@@ -2,45 +2,52 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- FerretDB is a MongoDB-compatible proxy that stores data in PostgreSQL. It requires **two binaries** to function:
5
+ FerretDB is a MongoDB-compatible proxy that stores data in PostgreSQL. It supports **two major versions** with different backends:
6
6
 
7
- 1. **ferretdb** - Stateless Go proxy (MongoDB wire protocol -> PostgreSQL SQL)
8
- 2. **postgresql-documentdb** - PostgreSQL 17 with DocumentDB extension
7
+ **v2 (default, macOS/Linux only):**
8
+ 1. **ferretdb** (hostdb: `ferretdb`) - Stateless Go proxy
9
+ 2. **postgresql-documentdb** (hostdb: `postgresql-documentdb`) - PostgreSQL 17 with DocumentDB extension
9
10
 
10
- This is a **composite engine** with unique binary management requirements.
11
+ **v1 (all platforms including Windows):**
12
+ 1. **ferretdb** (hostdb: `ferretdb`) - Stateless Go proxy (same protocol, older version)
13
+ 2. **Plain PostgreSQL** - Standard PostgreSQL via `postgresqlBinaryManager` (shared with standalone PG containers)
14
+
15
+ This is a **composite engine** with unique binary management requirements. The `isV1(version)` helper in `version-maps.ts` is the single branching point for all version-dependent behavior.
11
16
 
12
17
  ## Platform Support
13
18
 
14
- | Platform | Architecture | Status | Notes |
15
- |----------|--------------|--------|-------|
16
- | darwin | x64 | Supported | Both binaries available |
17
- | darwin | arm64 | Supported | Both binaries available (Apple Silicon) |
18
- | linux | x64 | Supported | Both binaries available |
19
- | linux | arm64 | Supported | Both binaries available |
20
- | win32 | x64 | **NOT SUPPORTED** | postgresql-documentdb has startup issues |
19
+ | Platform | Architecture | v1 Status | v2 Status | Notes |
20
+ |----------|--------------|-----------|-----------|-------|
21
+ | darwin | x64 | Supported | Supported | Both backends available |
22
+ | darwin | arm64 | Supported | Supported | Both backends available (Apple Silicon) |
23
+ | linux | x64 | Supported | Supported | Both backends available |
24
+ | linux | arm64 | Supported | Supported | Both backends available |
25
+ | win32 | x64 | Supported | **NOT SUPPORTED** | v2: postgresql-documentdb has startup issues |
26
+
27
+ ### Windows Support
21
28
 
22
- ### Windows Limitation
29
+ FerretDB **v1 is supported on Windows**. v2 is not available on Windows because postgresql-documentdb fails to initialize properly. `spindb create` auto-selects v1 on Windows. `spindb engines download ferretdb 2` on Windows is blocked with a helpful error suggesting v1.
23
30
 
24
- FerretDB is **not available on Windows** due to postgresql-documentdb startup issues. The Windows binaries exist in hostdb, but the PostgreSQL backend fails to initialize properly. This has been extensively tested and currently requires WSL as a workaround.
31
+ **Important hostdb note:** hostdb has `ferretdb` v2 proxy binaries for Windows but does NOT have `postgresql-documentdb` for Windows. This means the v2 proxy would download successfully but fail to start (no backend). The version-aware platform check in `binary-urls.ts` prevents this.
25
32
 
26
33
  ### macOS SIP / Container Limitations
27
34
 
28
- On macOS, System Integrity Protection (SIP) can block creating symlinks in system directories (e.g., `/usr/local`). In containerized or locked-down environments, even `sudo` may not permit writes to those paths. If you hit permission errors during setup, use a non-system install location or run with elevated privileges when available. See https://github.com/robertjbass/spindb#ferretdb for details.
35
+ On macOS, System Integrity Protection (SIP) can block creating symlinks in system directories (e.g., `/usr/local`). In containerized or locked-down environments, even `sudo` may not permit writes to those paths. If you hit permission errors during setup, use a non-system install location or run with elevated privileges when available. See https://github.com/robertjbass/spindb#ferretdb for details. This only applies to v2 (DocumentDB's Homebrew-derived paths).
29
36
 
30
37
  ## Binary Packaging
31
38
 
32
39
  ### Archive Format
33
- - **Unix (macOS/Linux)**: `tar.gz` for both binaries
34
- - **Windows**: Not applicable (unsupported)
40
+ - **Unix (macOS/Linux)**: `tar.gz` for both versions
41
+ - **Windows**: `zip` for v1 proxy, plain PostgreSQL handled by `postgresqlBinaryManager`
35
42
 
36
- ### FerretDB Archive Structure
43
+ ### FerretDB Archive Structure (both v1 and v2)
37
44
  ```
38
45
  ferretdb/
39
46
  └── bin/
40
47
  └── ferretdb # Go proxy binary
41
48
  ```
42
49
 
43
- ### postgresql-documentdb Archive Structure
50
+ ### postgresql-documentdb Archive Structure (v2 only)
44
51
  ```
45
52
  postgresql-documentdb/
46
53
  ├── bin/
@@ -57,7 +64,13 @@ postgresql-documentdb/
57
64
  └── share/ # Configuration and data files
58
65
  ```
59
66
 
60
- ### Why Custom PostgreSQL Build?
67
+ ### v1 Backend (Plain PostgreSQL)
68
+
69
+ v1 delegates backend management to `postgresqlBinaryManager`, which downloads standard PostgreSQL from hostdb. The PostgreSQL binaries are shared with standalone PostgreSQL containers — deleting a FerretDB v1 installation does NOT delete the shared PostgreSQL.
70
+
71
+ **Caveat:** If `postgresqlBinaryManager.isInstalled()` finds an existing minimal PostgreSQL install (e.g., from a previous DocumentDB extraction) that only has server binaries (`postgres`, `pg_ctl`, `initdb`) but lacks client tools (`psql`), the engine falls back to `postgres --single` mode for pre-start database creation.
72
+
73
+ ### Why Custom PostgreSQL Build? (v2)
61
74
 
62
75
  The postgresql-documentdb bundle is a **custom PostgreSQL 17 build** that includes:
63
76
  - DocumentDB extension (MongoDB-compatible storage)
@@ -79,11 +92,15 @@ Homebrew PostgreSQL has hardcoded paths (`/opt/homebrew/lib/...`) that break on
79
92
  ```typescript
80
93
  // FerretDB versions
81
94
  export const FERRETDB_VERSION_MAP: Record<string, string> = {
82
- '2': '2.7.0',
95
+ '1': '1.24.2', // v1: plain PostgreSQL backend
96
+ '2': '2.7.0', // v2: postgresql-documentdb backend
83
97
  }
84
98
 
85
- // postgresql-documentdb version format: {pg_major}-{documentdb_version}
99
+ // v2 backend version format: {pg_major}-{documentdb_version}
86
100
  export const DEFAULT_DOCUMENTDB_VERSION = '17-0.107.0'
101
+
102
+ // v1 backend: standard PostgreSQL major version
103
+ export const DEFAULT_V1_POSTGRESQL_VERSION = '17'
87
104
  ```
88
105
 
89
106
  ## Implementation Details
@@ -91,14 +108,17 @@ export const DEFAULT_DOCUMENTDB_VERSION = '17-0.107.0'
91
108
  ### Composite Binary Manager
92
109
 
93
110
  FerretDB uses a custom `FerretDBCompositeBinaryManager` that:
94
- - Downloads both binaries atomically (rolls back if either fails)
95
- - Manages separate version tracking for FerretDB and DocumentDB
96
- - Handles platform-specific library requirements
111
+ - Downloads both binaries atomically (rolls back if either fails) — v2 only
112
+ - For v1, downloads FerretDB proxy then delegates PostgreSQL to `postgresqlBinaryManager`
113
+ - `isV1(version)` branches all version-dependent behavior
114
+ - `getBackendBinaryPath()` / `getBackendSpawnEnv()` abstract v1/v2 backend resolution
97
115
 
98
116
  ### Architecture
99
117
 
100
118
  ```
101
- MongoDB Client (:27017) -> FerretDB Proxy -> PostgreSQL+DocumentDB (:54320+)
119
+ MongoDB Client (:27017) -> FerretDB Proxy -> PostgreSQL backend (:54320+)
120
+ v1: plain PostgreSQL
121
+ v2: PostgreSQL + DocumentDB
102
122
  ```
103
123
 
104
124
  ### Three Ports Per Container
@@ -111,11 +131,19 @@ FerretDB containers use **three ports**:
111
131
  ### FerretDB-Specific Startup Flags
112
132
 
113
133
  ```bash
134
+ # v2:
114
135
  ferretdb \
115
- --no-auth \ # Disable SCRAM authentication
136
+ --no-auth \ # Disable SCRAM authentication (v2 only)
116
137
  --debug-addr=127.0.0.1:${port + 10000} \ # Unique debug port per container
117
138
  --listen-addr=127.0.0.1:${port} \ # MongoDB wire protocol port
118
139
  --postgresql-url=postgres://postgres@127.0.0.1:${backendPort}/ferretdb
140
+
141
+ # v1 (differences):
142
+ ferretdb \
143
+ # no --no-auth (auth disabled by default in v1)
144
+ --debug-addr=127.0.0.1:${port + 10000} \
145
+ --listen-addr=127.0.0.1:${port} \
146
+ --postgresql-url=postgres://postgres@127.0.0.1:${backendPort}/ferretdb?sslmode=disable
119
147
  ```
120
148
 
121
149
  ### Linux LD_LIBRARY_PATH
@@ -123,10 +151,10 @@ ferretdb \
123
151
  On Linux, the bundled binaries need `LD_LIBRARY_PATH` set to find shared libraries:
124
152
 
125
153
  ```typescript
126
- getDocumentDBSpawnEnv(): { LD_LIBRARY_PATH: '/path/to/lib:$LD_LIBRARY_PATH' }
154
+ getBackendSpawnEnv(): { LD_LIBRARY_PATH: '/path/to/lib:$LD_LIBRARY_PATH' }
127
155
  ```
128
156
 
129
- macOS uses `@loader_path` which doesn't need environment variables.
157
+ macOS uses `@loader_path` which doesn't need environment variables. Applies to both v1 and v2.
130
158
 
131
159
  ### macOS Code Signing
132
160
 
@@ -163,9 +191,9 @@ Restore may fail with: `duplicate key value violates unique constraint`
163
191
 
164
192
  ### Uninstall Behavior
165
193
 
166
- When uninstalling FerretDB:
167
- - FerretDB proxy binary is deleted
168
- - postgresql-documentdb binary is **also deleted** (dedicated dependency)
194
+ **v2:** Both FerretDB proxy and postgresql-documentdb are deleted. The postgresql-documentdb binary is a dedicated dependency not shared with other engines.
195
+
196
+ **v1:** Only the FerretDB proxy is deleted. Plain PostgreSQL binaries are **NOT deleted** because they are shared with standalone PostgreSQL containers.
169
197
 
170
198
  This differs from QuestDB's PostgreSQL dependency (see QuestDB README).
171
199
 
@@ -173,7 +201,7 @@ This differs from QuestDB's PostgreSQL dependency (see QuestDB README).
173
201
 
174
202
  ### 1. Authentication Gotcha
175
203
 
176
- FerretDB 2.x enables SCRAM authentication by default. The `--setup-username` and `--setup-password` flags **do NOT exist** despite documentation suggestions. Use `--no-auth` instead.
204
+ FerretDB 2.x enables SCRAM authentication by default. The `--setup-username` and `--setup-password` flags **do NOT exist** despite documentation suggestions. Use `--no-auth` instead. FerretDB 1.x has auth disabled by default (no flag needed).
177
205
 
178
206
  ### 2. Debug Port Conflicts
179
207
 
@@ -187,9 +215,17 @@ Like MongoDB, databases don't appear until data is written. The engine uses the
187
215
 
188
216
  Namespace is derived from container name: `my-app` -> `my_app` (dashes replaced with underscores).
189
217
 
190
- ### 5. Windows Unsupported
218
+ ### 5. Windows: v2 Unsupported, v1 Supported
219
+
220
+ Extensive testing confirmed postgresql-documentdb (v2 backend) does not start properly on Windows. FerretDB v1 uses plain PostgreSQL and works on all platforms including Windows. **Note:** hostdb has v2 proxy binaries for Windows but NOT the backend — the download command blocks v2 on Windows to prevent broken installs.
221
+
222
+ ### 6. v1 Binary Verification
223
+
224
+ FerretDB v1 hostdb builds panic on `--version` because the source expects `build/version/version.txt` (via `//go:embed`). The hostdb build script must create this file. SpinDB skips `--version` verification for v1 (only checks binary exists).
225
+
226
+ ### 7. v1 Database Creation Without psql
191
227
 
192
- Extensive testing confirmed postgresql-documentdb does not start properly on Windows. WSL is the recommended workaround.
228
+ If the PostgreSQL backend is a minimal install lacking `psql`, the engine uses `postgres --single` mode before server start to create the `ferretdb` database. This requires exclusive data directory access, so it runs before `pg_ctl start`.
193
229
 
194
230
  ## Docker E2E Test Notes
195
231
 
@@ -201,9 +237,9 @@ FerretDB Docker E2E tests verify:
201
237
 
202
238
  ## CI/CD Notes
203
239
 
204
- ### Skipped on Windows
240
+ ### Windows CI
205
241
 
206
- FerretDB CI tests are skipped on Windows runners due to platform limitation.
242
+ FerretDB v2 CI tests are skipped on Windows runners. v1 tests should run on all platforms.
207
243
 
208
244
  ### GitHub Actions Cache Step
209
245
 
@@ -214,11 +250,13 @@ FerretDB CI tests are skipped on Windows runners due to platform limitation.
214
250
  path: |
215
251
  ~/.spindb/bin/ferretdb-*
216
252
  ~/.spindb/bin/postgresql-documentdb-*
253
+ ~/.spindb/bin/postgresql-*
217
254
  key: ferretdb-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('engines/ferretdb/version-maps.ts') }}
218
255
  ```
219
256
 
220
257
  ## Related Documentation
221
258
 
222
259
  - [plans/FERRETDB.md](../../plans/FERRETDB.md) - Original implementation plan (may be outdated)
223
- - hostdb releases: [ferretdb-2.7.0](https://github.com/robertjbass/hostdb/releases/tag/ferretdb-2.7.0)
224
- - hostdb releases: [postgresql-documentdb-17-0.107.0](https://github.com/robertjbass/hostdb/releases/tag/postgresql-documentdb-17-0.107.0)
260
+ - hostdb releases: [ferretdb-2.7.0](https://github.com/robertjbass/hostdb/releases/tag/ferretdb-2.7.0) (v2 proxy)
261
+ - hostdb releases: [ferretdb-1.24.2](https://github.com/robertjbass/hostdb/releases/tag/ferretdb-1.24.2) (v1 proxy)
262
+ - hostdb releases: [postgresql-documentdb-17-0.107.0](https://github.com/robertjbass/hostdb/releases/tag/postgresql-documentdb-17-0.107.0) (v2 backend)
@@ -14,29 +14,34 @@ import { logDebug } from '../../core/error-handler'
14
14
  import { platformService } from '../../core/platform-service'
15
15
  import { ferretdbBinaryManager } from './binary-manager'
16
16
  import {
17
- normalizeDocumentDBVersion,
18
17
  DEFAULT_DOCUMENTDB_VERSION,
18
+ DEFAULT_V1_POSTGRESQL_VERSION,
19
+ isV1,
19
20
  } from './version-maps'
20
21
  import type { ContainerConfig, BackupOptions, BackupResult } from '../../types'
21
22
 
22
23
  /**
23
- * Get the path to pg_dump from the postgresql-documentdb installation
24
+ * Get the path to pg_dump from the backend installation
25
+ * Uses version-aware backend resolution (v1 = plain PostgreSQL, v2 = postgresql-documentdb)
24
26
  */
25
27
  function getPgDumpPath(container: ContainerConfig): string {
26
- const { backendVersion } = container
28
+ const { version, backendVersion } = container
27
29
  const { platform, arch } = platformService.getPlatformInfo()
30
+ const v1 = isV1(version)
28
31
 
29
- const fullBackendVersion = normalizeDocumentDBVersion(
30
- backendVersion || DEFAULT_DOCUMENTDB_VERSION,
31
- )
32
- const documentdbPath = ferretdbBinaryManager.getDocumentDBBinaryPath(
33
- fullBackendVersion,
32
+ const effectiveBackendVersion = v1
33
+ ? backendVersion || DEFAULT_V1_POSTGRESQL_VERSION
34
+ : backendVersion || DEFAULT_DOCUMENTDB_VERSION
35
+
36
+ const backendPath = ferretdbBinaryManager.getBackendBinaryPath(
37
+ version,
38
+ effectiveBackendVersion,
34
39
  platform,
35
40
  arch,
36
41
  )
37
42
 
38
43
  const ext = platformService.getExecutableExtension()
39
- return join(documentdbPath, 'bin', `pg_dump${ext}`)
44
+ return join(backendPath, 'bin', `pg_dump${ext}`)
40
45
  }
41
46
 
42
47
  /**
@@ -63,8 +68,11 @@ export async function createBackup(
63
68
  const pgDump = getPgDumpPath(container)
64
69
 
65
70
  if (!existsSync(pgDump)) {
71
+ const backendName = isV1(container.version)
72
+ ? 'PostgreSQL'
73
+ : 'postgresql-documentdb'
66
74
  throw new Error(
67
- `pg_dump not found at ${pgDump}. Make sure postgresql-documentdb is installed.`,
75
+ `pg_dump not found at ${pgDump}. Make sure ${backendName} is installed.`,
68
76
  )
69
77
  }
70
78