pgserve 1.1.3-rc.4 → 1.1.3-rc.6

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.
@@ -43,26 +43,19 @@ jobs:
43
43
  fail-fast: false
44
44
  matrix:
45
45
  include:
46
- # Linux/macOS: cross-compile on ubuntu (faster)
47
- - target: bun-linux-x64
48
- platform: linux-x64
46
+ # Linux x64
47
+ - platform: linux-x64
48
+ pg_pkg: linux-x64
49
49
  output: pgserve-linux-x64
50
50
  os: ubuntu-latest
51
- - target: bun-linux-arm64
52
- platform: linux-arm64
53
- output: pgserve-linux-arm64
54
- os: ubuntu-latest
55
- - target: bun-darwin-x64
56
- platform: darwin-x64
57
- output: pgserve-darwin-x64
58
- os: ubuntu-latest
59
- - target: bun-darwin-arm64
60
- platform: darwin-arm64
51
+ # macOS ARM64 (Apple Silicon) - must build on macOS for native binaries
52
+ - platform: darwin-arm64
53
+ pg_pkg: darwin-arm64
61
54
  output: pgserve-darwin-arm64
62
- os: ubuntu-latest
63
- # Windows: native build required for --windows-icon
64
- - target: bun-windows-x64
65
- platform: windows-x64
55
+ os: macos-latest
56
+ # Windows x64 - must build on Windows for --windows-icon
57
+ - platform: windows-x64
58
+ pg_pkg: windows-x64
66
59
  output: pgserve-windows-x64.exe
67
60
  os: windows-latest
68
61
 
@@ -80,6 +73,18 @@ jobs:
80
73
  - name: Install dependencies
81
74
  run: bun install
82
75
 
76
+ # Bundle PostgreSQL binaries for standalone exe
77
+ - name: Bundle PostgreSQL binaries
78
+ run: |
79
+ echo "Installing @embedded-postgres/${{ matrix.pg_pkg }}..."
80
+ npm install @embedded-postgres/${{ matrix.pg_pkg }}
81
+ mkdir -p embedded-postgres
82
+ cp -r node_modules/@embedded-postgres/${{ matrix.pg_pkg }}/native/* embedded-postgres/
83
+ echo "Bundled PostgreSQL binaries:"
84
+ ls -la embedded-postgres/
85
+ ls -la embedded-postgres/bin/ || true
86
+ shell: bash
87
+
83
88
  # Windows: native build with custom icon
84
89
  - name: Build for Windows (with icon)
85
90
  if: matrix.platform == 'windows-x64'
@@ -89,12 +94,12 @@ jobs:
89
94
  ls -lh dist/
90
95
  shell: bash
91
96
 
92
- # Linux/macOS: cross-compile
97
+ # Linux/macOS: native build
93
98
  - name: Build for ${{ matrix.platform }}
94
99
  if: matrix.platform != 'windows-x64'
95
100
  run: |
96
101
  mkdir -p dist
97
- bun build --compile --target=${{ matrix.target }} bin/pglite-server.js --outfile dist/${{ matrix.output }}
102
+ bun build --compile bin/pglite-server.js --outfile dist/${{ matrix.output }}
98
103
  ls -lh dist/
99
104
 
100
105
  - name: Upload artifact
@@ -147,7 +152,8 @@ jobs:
147
152
  ls -la dist/
148
153
 
149
154
  MISSING=""
150
- for platform in linux-x64 linux-arm64 darwin-x64 darwin-arm64; do
155
+ # Supported platforms: linux-x64, darwin-arm64, windows-x64
156
+ for platform in linux-x64 darwin-arm64; do
151
157
  if [ ! -f "dist/pgserve-$platform" ]; then
152
158
  MISSING="$MISSING pgserve-$platform"
153
159
  fi
package/assets/icon.ico CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgserve",
3
- "version": "1.1.3-rc.4",
3
+ "version": "1.1.3-rc.6",
4
4
  "description": "Embedded PostgreSQL server with true concurrent connections - zero config, auto-provision databases",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/postgres.js CHANGED
@@ -18,6 +18,124 @@ import path from 'path';
18
18
  import fs from 'fs';
19
19
  import crypto from 'crypto';
20
20
 
21
+ /**
22
+ * Get platform key for binary lookup (e.g., 'windows-x64', 'linux-x64', 'darwin-arm64')
23
+ * @returns {string} Platform key
24
+ */
25
+ function getPlatformKey() {
26
+ const platform = os.platform();
27
+ const arch = os.arch();
28
+
29
+ if (platform === 'win32') return 'windows-x64';
30
+ if (platform === 'linux' && arch === 'x64') return 'linux-x64';
31
+ if (platform === 'darwin' && arch === 'arm64') return 'darwin-arm64';
32
+ if (platform === 'darwin' && arch === 'x64') return 'darwin-x64';
33
+ if (platform === 'linux' && arch === 'arm64') return 'linux-arm64';
34
+
35
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
36
+ }
37
+
38
+ /**
39
+ * Get the directory where extracted binaries are cached
40
+ * @returns {string} Cache directory path
41
+ */
42
+ function getBinaryCacheDir() {
43
+ const platformKey = getPlatformKey();
44
+ return path.join(os.homedir(), '.pgserve', 'bin', platformKey);
45
+ }
46
+
47
+ /**
48
+ * Check if bundled PostgreSQL binaries exist (standalone exe mode)
49
+ * When compiled with `bun build --compile`, the embedded-postgres folder
50
+ * should be bundled alongside the executable.
51
+ * @returns {string|null} Path to bundled binaries or null if not found
52
+ */
53
+ function getBundledBinaryDir() {
54
+ // Check for embedded-postgres folder relative to the module
55
+ // This works when binaries are bundled during build
56
+ const bundledDir = path.join(import.meta.dirname, '..', 'embedded-postgres');
57
+ if (fs.existsSync(path.join(bundledDir, 'bin'))) {
58
+ return bundledDir;
59
+ }
60
+ return null;
61
+ }
62
+
63
+ /**
64
+ * Extract bundled PostgreSQL binaries to cache directory.
65
+ * Bun-compiled binaries can read embedded files but cannot execute them directly.
66
+ * We extract to ~/.pgserve/bin/{platform}/ for execution.
67
+ *
68
+ * @returns {Promise<string>} Path to extracted bin directory
69
+ */
70
+ async function extractBundledBinaries() {
71
+ const platform = os.platform();
72
+ const cacheDir = getBinaryCacheDir();
73
+ const cacheBinDir = path.join(cacheDir, 'bin');
74
+ const initdbName = platform === 'win32' ? 'initdb.exe' : 'initdb';
75
+ const postgresName = platform === 'win32' ? 'postgres.exe' : 'postgres';
76
+
77
+ // Check if already extracted
78
+ if (fs.existsSync(path.join(cacheBinDir, initdbName)) &&
79
+ fs.existsSync(path.join(cacheBinDir, postgresName))) {
80
+ return cacheDir;
81
+ }
82
+
83
+ // Get bundled directory
84
+ const bundledDir = getBundledBinaryDir();
85
+ if (!bundledDir) {
86
+ return null;
87
+ }
88
+
89
+ console.log('[pgserve] Extracting PostgreSQL binaries...');
90
+
91
+ // Create cache directory
92
+ fs.mkdirSync(cacheDir, { recursive: true });
93
+
94
+ // Copy bundled binaries to cache
95
+ // Use recursive copy to get bin/, lib/, share/ directories
96
+ await copyRecursive(bundledDir, cacheDir);
97
+
98
+ // Make executables executable (Unix only)
99
+ if (platform !== 'win32') {
100
+ const binDir = path.join(cacheDir, 'bin');
101
+ const files = fs.readdirSync(binDir);
102
+ for (const file of files) {
103
+ const filePath = path.join(binDir, file);
104
+ try {
105
+ fs.chmodSync(filePath, 0o755);
106
+ } catch {
107
+ // Ignore permission errors for non-executables
108
+ }
109
+ }
110
+ }
111
+
112
+ console.log(`[pgserve] Binaries extracted to ${cacheDir}`);
113
+ return cacheDir;
114
+ }
115
+
116
+ /**
117
+ * Recursively copy a directory
118
+ * @param {string} src - Source directory
119
+ * @param {string} dest - Destination directory
120
+ */
121
+ async function copyRecursive(src, dest) {
122
+ const entries = fs.readdirSync(src, { withFileTypes: true });
123
+
124
+ for (const entry of entries) {
125
+ const srcPath = path.join(src, entry.name);
126
+ const destPath = path.join(dest, entry.name);
127
+
128
+ if (entry.isDirectory()) {
129
+ fs.mkdirSync(destPath, { recursive: true });
130
+ await copyRecursive(srcPath, destPath);
131
+ } else {
132
+ // Read and write file (works with Bun's virtual filesystem)
133
+ const content = fs.readFileSync(srcPath);
134
+ fs.writeFileSync(destPath, content);
135
+ }
136
+ }
137
+ }
138
+
21
139
  /**
22
140
  * Ensure library symlinks exist in the lib directory.
23
141
  * The @embedded-postgres package ships versioned libraries but binaries look for soname versions.
@@ -94,10 +212,47 @@ function ensureLibrarySymlinks(libDir, platform) {
94
212
  }
95
213
 
96
214
  // Resolve binary paths from embedded-postgres platform packages
97
- function getBinaryPaths() {
215
+ // Now async to support bundled binary extraction
216
+ async function getBinaryPaths() {
98
217
  const platform = os.platform();
99
218
  const arch = os.arch();
219
+ const exeSuffix = platform === 'win32' ? '.exe' : '';
220
+
221
+ // Priority 1: Check extracted cache directory (standalone exe mode)
222
+ // This is where bundled binaries are extracted on first run
223
+ const cacheDir = getBinaryCacheDir();
224
+ const cacheBinDir = path.join(cacheDir, 'bin');
225
+ const cachedInitdb = path.join(cacheBinDir, 'initdb' + exeSuffix);
226
+ const cachedPostgres = path.join(cacheBinDir, 'postgres' + exeSuffix);
227
+
228
+ if (fs.existsSync(cachedInitdb) && fs.existsSync(cachedPostgres)) {
229
+ const libDir = path.join(cacheDir, 'lib');
230
+ if ((platform === 'linux' || platform === 'darwin') && fs.existsSync(libDir)) {
231
+ ensureLibrarySymlinks(libDir, platform);
232
+ }
233
+ return { initdb: cachedInitdb, postgres: cachedPostgres, binDir: cacheBinDir, libDir };
234
+ }
235
+
236
+ // Priority 2: Check for bundled binaries and extract if found (standalone exe mode)
237
+ const bundledDir = getBundledBinaryDir();
238
+ if (bundledDir) {
239
+ const extractedDir = await extractBundledBinaries();
240
+ if (extractedDir) {
241
+ const extractedBinDir = path.join(extractedDir, 'bin');
242
+ const extractedInitdb = path.join(extractedBinDir, 'initdb' + exeSuffix);
243
+ const extractedPostgres = path.join(extractedBinDir, 'postgres' + exeSuffix);
244
+
245
+ if (fs.existsSync(extractedInitdb) && fs.existsSync(extractedPostgres)) {
246
+ const libDir = path.join(extractedDir, 'lib');
247
+ if ((platform === 'linux' || platform === 'darwin') && fs.existsSync(libDir)) {
248
+ ensureLibrarySymlinks(libDir, platform);
249
+ }
250
+ return { initdb: extractedInitdb, postgres: extractedPostgres, binDir: extractedBinDir, libDir };
251
+ }
252
+ }
253
+ }
100
254
 
255
+ // Priority 3: Find the package in node_modules (npm install case)
101
256
  let pkgName;
102
257
  if (platform === 'linux' && arch === 'x64') {
103
258
  pkgName = '@embedded-postgres/linux-x64';
@@ -111,7 +266,6 @@ function getBinaryPaths() {
111
266
  throw new Error(`Unsupported platform: ${platform}-${arch}`);
112
267
  }
113
268
 
114
- // Find the package in node_modules (check multiple locations for npx/pnpm/npm compatibility)
115
269
  const possiblePaths = [
116
270
  path.join(process.cwd(), 'node_modules', pkgName, 'native', 'bin'),
117
271
  path.join(import.meta.dirname, '..', 'node_modules', pkgName, 'native', 'bin'),
@@ -120,8 +274,8 @@ function getBinaryPaths() {
120
274
  ];
121
275
 
122
276
  for (const binDir of possiblePaths) {
123
- const initdb = path.join(binDir, platform === 'win32' ? 'initdb.exe' : 'initdb');
124
- const postgres = path.join(binDir, platform === 'win32' ? 'postgres.exe' : 'postgres');
277
+ const initdb = path.join(binDir, 'initdb' + exeSuffix);
278
+ const postgres = path.join(binDir, 'postgres' + exeSuffix);
125
279
  if (fs.existsSync(initdb) && fs.existsSync(postgres)) {
126
280
  // Resolve the actual binary paths (handles symlinks from package managers)
127
281
  const realInitdb = fs.realpathSync(initdb);
@@ -237,8 +391,8 @@ export class PostgresManager {
237
391
  * Start the embedded PostgreSQL instance
238
392
  */
239
393
  async start() {
240
- // Get binary paths
241
- this.binaries = getBinaryPaths();
394
+ // Get binary paths (may extract bundled binaries on first run)
395
+ this.binaries = await getBinaryPaths();
242
396
 
243
397
  // Make binaries executable
244
398
  await fs.promises.chmod(this.binaries.initdb, '755');