pgserve 1.1.3-rc.4 → 1.1.3-rc.7

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,16 @@ 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
49
48
  output: pgserve-linux-x64
50
49
  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
50
+ # macOS ARM64 (Apple Silicon)
51
+ - platform: darwin-arm64
61
52
  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
53
+ os: macos-latest
54
+ # Windows x64 - must build on Windows for --windows-icon
55
+ - platform: windows-x64
66
56
  output: pgserve-windows-x64.exe
67
57
  os: windows-latest
68
58
 
@@ -89,12 +79,12 @@ jobs:
89
79
  ls -lh dist/
90
80
  shell: bash
91
81
 
92
- # Linux/macOS: cross-compile
82
+ # Linux/macOS: native build
93
83
  - name: Build for ${{ matrix.platform }}
94
84
  if: matrix.platform != 'windows-x64'
95
85
  run: |
96
86
  mkdir -p dist
97
- bun build --compile --target=${{ matrix.target }} bin/pglite-server.js --outfile dist/${{ matrix.output }}
87
+ bun build --compile bin/pglite-server.js --outfile dist/${{ matrix.output }}
98
88
  ls -lh dist/
99
89
 
100
90
  - name: Upload artifact
@@ -147,7 +137,8 @@ jobs:
147
137
  ls -la dist/
148
138
 
149
139
  MISSING=""
150
- for platform in linux-x64 linux-arm64 darwin-x64 darwin-arm64; do
140
+ # Supported platforms: linux-x64, darwin-arm64, windows-x64
141
+ for platform in linux-x64 darwin-arm64; do
151
142
  if [ ! -f "dist/pgserve-$platform" ]; then
152
143
  MISSING="$MISSING pgserve-$platform"
153
144
  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.7",
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
@@ -13,11 +13,162 @@
13
13
  * - No locale dependency (works on any system)
14
14
  */
15
15
 
16
+ /* global fetch, Bun */
16
17
  import os from 'os';
17
18
  import path from 'path';
18
19
  import fs from 'fs';
19
20
  import crypto from 'crypto';
20
21
 
22
+ /**
23
+ * Get platform key for binary lookup (e.g., 'windows-x64', 'linux-x64', 'darwin-arm64')
24
+ * @returns {string} Platform key
25
+ */
26
+ function getPlatformKey() {
27
+ const platform = os.platform();
28
+ const arch = os.arch();
29
+
30
+ if (platform === 'win32') return 'windows-x64';
31
+ if (platform === 'linux' && arch === 'x64') return 'linux-x64';
32
+ if (platform === 'darwin' && arch === 'arm64') return 'darwin-arm64';
33
+ if (platform === 'darwin' && arch === 'x64') return 'darwin-x64';
34
+ if (platform === 'linux' && arch === 'arm64') return 'linux-arm64';
35
+
36
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
37
+ }
38
+
39
+ /**
40
+ * Get the directory where extracted binaries are cached
41
+ * @returns {string} Cache directory path
42
+ */
43
+ function getBinaryCacheDir() {
44
+ const platformKey = getPlatformKey();
45
+ return path.join(os.homedir(), '.pgserve', 'bin', platformKey);
46
+ }
47
+
48
+ /**
49
+ * Download and extract PostgreSQL binaries on first run.
50
+ * Downloads from npm registry (@embedded-postgres packages).
51
+ *
52
+ * @returns {Promise<string>} Path to extracted directory
53
+ */
54
+ async function downloadPostgresBinaries() {
55
+ const platform = os.platform();
56
+ const cacheDir = getBinaryCacheDir();
57
+ const cacheBinDir = path.join(cacheDir, 'bin');
58
+ const initdbName = platform === 'win32' ? 'initdb.exe' : 'initdb';
59
+ const postgresName = platform === 'win32' ? 'postgres.exe' : 'postgres';
60
+
61
+ // Check if already downloaded
62
+ if (fs.existsSync(path.join(cacheBinDir, initdbName)) &&
63
+ fs.existsSync(path.join(cacheBinDir, postgresName))) {
64
+ return cacheDir;
65
+ }
66
+
67
+ const platformKey = getPlatformKey();
68
+ const pkgName = `@embedded-postgres/${platformKey}`;
69
+ const pkgVersion = '17.7.0-beta.15';
70
+
71
+ console.log(`[pgserve] PostgreSQL binaries not found.`);
72
+ console.log(`[pgserve] Downloading ${pkgName}@${pkgVersion}...`);
73
+
74
+ // Get tarball URL from npm registry
75
+ const registryUrl = `https://registry.npmjs.org/${pkgName}`;
76
+ const registryRes = await fetch(registryUrl);
77
+ if (!registryRes.ok) {
78
+ throw new Error(`Failed to fetch package info: ${registryRes.status}`);
79
+ }
80
+ const pkgInfo = await registryRes.json();
81
+ const tarballUrl = pkgInfo.versions[pkgVersion]?.dist?.tarball;
82
+
83
+ if (!tarballUrl) {
84
+ throw new Error(`Version ${pkgVersion} not found for ${pkgName}`);
85
+ }
86
+
87
+ // Download tarball
88
+ console.log(`[pgserve] Downloading from npm registry...`);
89
+ const tarballRes = await fetch(tarballUrl);
90
+ if (!tarballRes.ok) {
91
+ throw new Error(`Failed to download tarball: ${tarballRes.status}`);
92
+ }
93
+
94
+ const tarballBuffer = await tarballRes.arrayBuffer();
95
+ const tarballSize = (tarballBuffer.byteLength / 1024 / 1024).toFixed(1);
96
+ console.log(`[pgserve] Downloaded ${tarballSize} MB`);
97
+
98
+ // Create temp file for tarball
99
+ const tempDir = path.join(os.tmpdir(), `pgserve-download-${Date.now()}`);
100
+ fs.mkdirSync(tempDir, { recursive: true });
101
+ const tarballPath = path.join(tempDir, 'package.tgz');
102
+ fs.writeFileSync(tarballPath, Buffer.from(tarballBuffer));
103
+
104
+ // Extract tarball using tar (available on all platforms via bun/node)
105
+ console.log(`[pgserve] Extracting binaries...`);
106
+ fs.mkdirSync(cacheDir, { recursive: true });
107
+
108
+ // Use Bun.spawn for extraction
109
+ const extractProc = Bun.spawn(['tar', '-xzf', tarballPath, '-C', tempDir], {
110
+ stdout: 'pipe',
111
+ stderr: 'pipe'
112
+ });
113
+ await extractProc.exited;
114
+
115
+ // Copy native/* to cache dir
116
+ const nativeDir = path.join(tempDir, 'package', 'native');
117
+ if (!fs.existsSync(nativeDir)) {
118
+ throw new Error('Extracted package does not contain native/ directory');
119
+ }
120
+
121
+ // Copy files recursively
122
+ await copyDirRecursive(nativeDir, cacheDir);
123
+
124
+ // Make executables executable (Unix only)
125
+ if (platform !== 'win32') {
126
+ const binDir = path.join(cacheDir, 'bin');
127
+ if (fs.existsSync(binDir)) {
128
+ const files = fs.readdirSync(binDir);
129
+ for (const file of files) {
130
+ const filePath = path.join(binDir, file);
131
+ try {
132
+ fs.chmodSync(filePath, 0o755);
133
+ } catch {
134
+ // Ignore
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ // Cleanup temp
141
+ try {
142
+ fs.rmSync(tempDir, { recursive: true, force: true });
143
+ } catch {
144
+ // Ignore cleanup errors
145
+ }
146
+
147
+ console.log(`[pgserve] PostgreSQL binaries installed to ${cacheDir}`);
148
+ return cacheDir;
149
+ }
150
+
151
+ /**
152
+ * Recursively copy a directory
153
+ * @param {string} src - Source directory
154
+ * @param {string} dest - Destination directory
155
+ */
156
+ async function copyDirRecursive(src, dest) {
157
+ const entries = fs.readdirSync(src, { withFileTypes: true });
158
+
159
+ for (const entry of entries) {
160
+ const srcPath = path.join(src, entry.name);
161
+ const destPath = path.join(dest, entry.name);
162
+
163
+ if (entry.isDirectory()) {
164
+ fs.mkdirSync(destPath, { recursive: true });
165
+ await copyDirRecursive(srcPath, destPath);
166
+ } else {
167
+ fs.copyFileSync(srcPath, destPath);
168
+ }
169
+ }
170
+ }
171
+
21
172
  /**
22
173
  * Ensure library symlinks exist in the lib directory.
23
174
  * The @embedded-postgres package ships versioned libraries but binaries look for soname versions.
@@ -94,10 +245,45 @@ function ensureLibrarySymlinks(libDir, platform) {
94
245
  }
95
246
 
96
247
  // Resolve binary paths from embedded-postgres platform packages
97
- function getBinaryPaths() {
248
+ // Now async to support bundled binary extraction
249
+ async function getBinaryPaths() {
98
250
  const platform = os.platform();
99
251
  const arch = os.arch();
252
+ const exeSuffix = platform === 'win32' ? '.exe' : '';
253
+
254
+ // Priority 1: Check extracted cache directory (standalone exe mode)
255
+ // This is where bundled binaries are extracted on first run
256
+ const cacheDir = getBinaryCacheDir();
257
+ const cacheBinDir = path.join(cacheDir, 'bin');
258
+ const cachedInitdb = path.join(cacheBinDir, 'initdb' + exeSuffix);
259
+ const cachedPostgres = path.join(cacheBinDir, 'postgres' + exeSuffix);
260
+
261
+ if (fs.existsSync(cachedInitdb) && fs.existsSync(cachedPostgres)) {
262
+ const libDir = path.join(cacheDir, 'lib');
263
+ if ((platform === 'linux' || platform === 'darwin') && fs.existsSync(libDir)) {
264
+ ensureLibrarySymlinks(libDir, platform);
265
+ }
266
+ return { initdb: cachedInitdb, postgres: cachedPostgres, binDir: cacheBinDir, libDir };
267
+ }
268
+
269
+ // Priority 2: Download binaries if not found (standalone exe mode)
270
+ // This downloads from npm registry on first run
271
+ const downloadedDir = await downloadPostgresBinaries();
272
+ if (downloadedDir) {
273
+ const downloadedBinDir = path.join(downloadedDir, 'bin');
274
+ const downloadedInitdb = path.join(downloadedBinDir, 'initdb' + exeSuffix);
275
+ const downloadedPostgres = path.join(downloadedBinDir, 'postgres' + exeSuffix);
276
+
277
+ if (fs.existsSync(downloadedInitdb) && fs.existsSync(downloadedPostgres)) {
278
+ const libDir = path.join(downloadedDir, 'lib');
279
+ if ((platform === 'linux' || platform === 'darwin') && fs.existsSync(libDir)) {
280
+ ensureLibrarySymlinks(libDir, platform);
281
+ }
282
+ return { initdb: downloadedInitdb, postgres: downloadedPostgres, binDir: downloadedBinDir, libDir };
283
+ }
284
+ }
100
285
 
286
+ // Priority 3: Find the package in node_modules (npm install case)
101
287
  let pkgName;
102
288
  if (platform === 'linux' && arch === 'x64') {
103
289
  pkgName = '@embedded-postgres/linux-x64';
@@ -111,7 +297,6 @@ function getBinaryPaths() {
111
297
  throw new Error(`Unsupported platform: ${platform}-${arch}`);
112
298
  }
113
299
 
114
- // Find the package in node_modules (check multiple locations for npx/pnpm/npm compatibility)
115
300
  const possiblePaths = [
116
301
  path.join(process.cwd(), 'node_modules', pkgName, 'native', 'bin'),
117
302
  path.join(import.meta.dirname, '..', 'node_modules', pkgName, 'native', 'bin'),
@@ -120,8 +305,8 @@ function getBinaryPaths() {
120
305
  ];
121
306
 
122
307
  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');
308
+ const initdb = path.join(binDir, 'initdb' + exeSuffix);
309
+ const postgres = path.join(binDir, 'postgres' + exeSuffix);
125
310
  if (fs.existsSync(initdb) && fs.existsSync(postgres)) {
126
311
  // Resolve the actual binary paths (handles symlinks from package managers)
127
312
  const realInitdb = fs.realpathSync(initdb);
@@ -237,8 +422,8 @@ export class PostgresManager {
237
422
  * Start the embedded PostgreSQL instance
238
423
  */
239
424
  async start() {
240
- // Get binary paths
241
- this.binaries = getBinaryPaths();
425
+ // Get binary paths (may extract bundled binaries on first run)
426
+ this.binaries = await getBinaryPaths();
242
427
 
243
428
  // Make binaries executable
244
429
  await fs.promises.chmod(this.binaries.initdb, '755');