Skip to content

Commit 174014c

Browse files
committed
fix tests and readme
1 parent ca51edc commit 174014c

File tree

17 files changed

+172
-253
lines changed

17 files changed

+172
-253
lines changed

README.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ pg0 gives you **real PostgreSQL** with the same simplicity as SQLite:
2222

2323
Use pg0 for local development, testing, CI/CD pipelines, or any scenario where you want PostgreSQL without the setup overhead.
2424

25+
## Supported Platforms
26+
27+
| Platform | Architecture | Binary |
28+
|----------|--------------|--------|
29+
| macOS | Apple Silicon (M1/M2/M3) | `pg0-macos-arm64` |
30+
| Linux | x86_64 (glibc) | `pg0-linux-amd64-gnu` |
31+
| Linux | x86_64 (musl/Alpine) | `pg0-linux-amd64-musl` |
32+
| Linux | ARM64 (glibc) | `pg0-linux-arm64-gnu` |
33+
| Linux | ARM64 (musl/Alpine) | `pg0-linux-arm64-musl` |
34+
| Windows | x64 | `pg0-windows-amd64.exe` |
35+
2536
## Features
2637

2738
- **Zero dependencies** - single binary, works offline
@@ -141,12 +152,14 @@ docker run -d myimage bash -c "pg0 start && exec your-application"
141152

142153
### Alpine (musl-based)
143154

155+
**Note:** The musl binary requires ICU 74. Use Alpine 3.20 (not 3.22+) as newer versions have ICU 76.
156+
144157
```dockerfile
145-
FROM alpine:latest
146-
# or: python:3.11-alpine
158+
FROM alpine:3.20
159+
# or: python:3.12-alpine3.20
147160

148161
# Install required dependencies
149-
RUN apk add --no-cache curl bash shadow
162+
RUN apk add --no-cache curl bash shadow icu-libs lz4-libs libxml2
150163

151164
# Create non-root user (PostgreSQL cannot run as root)
152165
RUN adduser -D -s /bin/bash pguser
@@ -183,9 +196,9 @@ docker run --rm -it python:3.11-slim bash -c '
183196
pg0 psql -c \"SELECT version();\""
184197
'
185198

186-
# Alpine
187-
docker run --rm -it python:3.11-alpine sh -c '
188-
apk add --no-cache curl bash shadow &&
199+
# Alpine (use 3.20 for ICU 74 compatibility)
200+
docker run --rm -it python:3.12-alpine3.20 sh -c '
201+
apk add --no-cache curl bash shadow icu-libs lz4-libs libxml2 &&
189202
adduser -D pguser &&
190203
su - pguser -c "curl -fsSL https://raw.githubusercontent.com/vectorize-io/pg0/main/install.sh | bash &&
191204
export PATH=\"\$HOME/.local/bin:\$PATH\" &&

docker-tests/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ Automated tests to verify pg0 works correctly across different platforms and dis
88
|------|-------|----------|--------------|------|
99
| `test_debian_amd64.sh` | python:3.11-slim | linux/amd64 | x86_64 | glibc |
1010
| `test_debian_arm64.sh` | python:3.11-slim | linux/arm64 | aarch64 | glibc |
11-
| `test_alpine_amd64.sh` | python:3.11-alpine | linux/amd64 | x86_64 | musl |
12-
| `test_alpine_arm64.sh` | python:3.11-alpine | linux/arm64 | aarch64 | musl |
11+
| `test_alpine_amd64.sh` | python:3.12-alpine3.20 | linux/amd64 | x86_64 | musl |
12+
| `test_alpine_arm64.sh` | python:3.12-alpine3.20 | linux/arm64 | aarch64 | musl |
1313

1414
## What Each Test Does
1515

@@ -55,10 +55,12 @@ chmod +x *.sh
5555
- ✅ All queries: Success
5656

5757
### Alpine (musl)
58-
- ✅ PostgreSQL: Works
59-
- ⚠️ pgvector: May fail (no musl binaries available yet)
58+
- ✅ PostgreSQL: Works (requires `icu-libs`, `lz4-libs`, `libxml2` packages and ICU 74 - use Alpine 3.20)
59+
- ⚠️ pgvector: Fails (no musl binaries available - glibc-only)
6060
- ✅ Basic queries: Success
6161

62+
**Note:** The PostgreSQL musl binary is built against ICU 74. Alpine 3.22+ uses ICU 76 which is not compatible. Use Alpine 3.20 for musl-based deployments.
63+
6264
## Requirements
6365

6466
- Docker installed and running

docker-tests/test_alpine_amd64.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@ set -e
33

44
echo "=================================="
55
echo "Testing pg0 on Alpine AMD64"
6-
echo "Image: python:3.11-alpine"
6+
echo "Image: python:3.12-alpine3.20"
77
echo "Platform: linux/amd64"
88
echo "=================================="
99

1010
# Get the script directory to find install.sh
1111
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
1212
INSTALL_SCRIPT="$SCRIPT_DIR/../install.sh"
1313

14+
# Note: Using Alpine 3.20 because the musl PostgreSQL binary requires ICU 74
15+
# Alpine 3.22 has ICU 76 which is not compatible
1416
docker run --rm --platform=linux/amd64 \
1517
-v "$INSTALL_SCRIPT:/tmp/install.sh:ro" \
16-
python:3.11-alpine sh -c '
18+
python:3.12-alpine3.20 sh -c '
1719
set -e
1820
1921
echo "=== System Info ==="
@@ -22,7 +24,7 @@ cat /etc/os-release | grep PRETTY_NAME
2224
2325
echo ""
2426
echo "=== Installing dependencies ==="
25-
apk add --no-cache curl bash sudo procps shadow > /dev/null 2>&1
27+
apk add --no-cache curl bash sudo procps shadow icu-libs lz4-libs libxml2 > /dev/null 2>&1
2628
2729
echo ""
2830
echo "=== Creating non-root user ==="

docker-tests/test_alpine_arm64.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@ set -e
33

44
echo "=================================="
55
echo "Testing pg0 on Alpine ARM64"
6-
echo "Image: python:3.11-alpine"
6+
echo "Image: python:3.12-alpine3.20"
77
echo "Platform: linux/arm64"
88
echo "=================================="
99

1010
# Get the script directory to find install.sh
1111
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
1212
INSTALL_SCRIPT="$SCRIPT_DIR/../install.sh"
1313

14+
# Note: Using Alpine 3.20 because the musl PostgreSQL binary requires ICU 74
15+
# Alpine 3.22 has ICU 76 which is not compatible
1416
docker run --rm --platform=linux/arm64 \
1517
-v "$INSTALL_SCRIPT:/tmp/install.sh:ro" \
16-
python:3.11-alpine sh -c '
18+
python:3.12-alpine3.20 sh -c '
1719
set -e
1820
1921
echo "=== System Info ==="
@@ -22,7 +24,7 @@ cat /etc/os-release | grep PRETTY_NAME
2224
2325
echo ""
2426
echo "=== Installing dependencies ==="
25-
apk add --no-cache curl bash sudo procps shadow > /dev/null 2>&1
27+
apk add --no-cache curl bash sudo procps shadow icu-libs lz4-libs libxml2 > /dev/null 2>&1
2628
2729
echo ""
2830
echo "=== Creating non-root user ==="

sdk/node/README.md

Lines changed: 35 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,73 @@
11
# pg0 - Embedded PostgreSQL for Node.js
22

3-
Zero-config PostgreSQL with pgvector support. Just `npm install` and go.
3+
[![npm](https://badge.fury.io/js/@vectorize-io%2Fpg0.svg)](https://www.npmjs.com/package/@vectorize-io/pg0)
44

5-
## Installation
5+
Embedded PostgreSQL with pgvector. No installation, no Docker, no configuration.
6+
7+
## Install
68

79
```bash
810
npm install @vectorize-io/pg0
911
```
1012

11-
## Quick Start
13+
## Usage
1214

1315
```typescript
1416
import { Pg0 } from "@vectorize-io/pg0";
1517

16-
// Start PostgreSQL (auto-installs on first run)
18+
// Basic usage
1719
const pg = new Pg0();
1820
await pg.start();
19-
2021
console.log(await pg.getUri()); // postgresql://postgres:postgres@localhost:5432/postgres
21-
22+
await pg.execute("CREATE EXTENSION IF NOT EXISTS vector");
2223
await pg.stop();
23-
```
24-
25-
## Synchronous API
26-
27-
```typescript
28-
import { Pg0 } from "@vectorize-io/pg0";
29-
30-
const pg = new Pg0();
31-
pg.startSync();
32-
console.log(pg.getUriSync());
33-
pg.stopSync();
34-
```
35-
36-
## Custom Configuration
37-
38-
```typescript
39-
import { Pg0 } from "@vectorize-io/pg0";
4024

25+
// Custom configuration
4126
const pg = new Pg0({
27+
name: "myapp",
4228
port: 5433,
4329
username: "myuser",
4430
password: "mypass",
4531
database: "mydb",
46-
config: {
47-
shared_buffers: "512MB",
48-
maintenance_work_mem: "1GB",
49-
},
32+
config: { shared_buffers: "512MB" }
5033
});
51-
5234
await pg.start();
53-
console.log(await pg.getUri());
5435
await pg.stop();
55-
```
56-
57-
## Multiple Instances
5836

59-
```typescript
60-
import { Pg0, listInstances } from "@vectorize-io/pg0";
61-
62-
const app = new Pg0({ name: "app", port: 5432 });
63-
const test = new Pg0({ name: "test", port: 5433 });
64-
65-
await app.start();
66-
await test.start();
67-
68-
for (const instance of await listInstances()) {
69-
console.log(`${instance.name}: ${instance.uri}`);
70-
}
71-
72-
await app.stop();
73-
await test.stop();
37+
// Sync API also available
38+
pg.startSync();
39+
pg.stopSync();
7440
```
7541

76-
## API Reference
42+
## API
7743

7844
### Pg0 Class
7945

80-
```typescript
81-
const pg = new Pg0({
82-
name: "default", // Instance name
83-
port: 5432, // Port
84-
username: "postgres", // Username
85-
password: "postgres", // Password
86-
database: "postgres", // Database
87-
dataDir: undefined, // Custom data directory
88-
config: {}, // PostgreSQL config options
89-
});
90-
91-
// Async methods
92-
await pg.start(); // Start PostgreSQL -> InstanceInfo
93-
await pg.stop(); // Stop PostgreSQL
94-
await pg.info(); // Get instance info -> InstanceInfo
95-
await pg.getUri(); // Connection URI
96-
await pg.isRunning(); // Is running
97-
await pg.execute(sql); // Execute SQL -> string
98-
99-
// Sync methods
100-
pg.startSync();
101-
pg.stopSync();
102-
pg.infoSync();
103-
pg.getUriSync();
104-
pg.isRunningSync();
105-
pg.executeSync(sql);
106-
```
46+
| Method | Description |
47+
|--------|-------------|
48+
| `start()` / `startSync()` | Start PostgreSQL, returns `InstanceInfo` |
49+
| `stop()` / `stopSync()` | Stop PostgreSQL |
50+
| `drop()` / `dropSync()` | Stop and delete all data |
51+
| `info()` / `infoSync()` | Get instance info |
52+
| `execute(sql)` / `executeSync(sql)` | Run SQL query |
53+
| `getUri()` / `getUriSync()` | Get connection URI |
54+
| `isRunning()` / `isRunningSync()` | Check if running |
10755

10856
### Module Functions
10957

11058
```typescript
111-
import { start, stop, info, listInstances, install } from "@vectorize-io/pg0";
112-
113-
// Async
114-
await start({ port: 5432 }); // Start -> InstanceInfo
115-
await stop("default"); // Stop
116-
await info("default"); // Info -> InstanceInfo
117-
await listInstances(); // List all -> InstanceInfo[]
118-
await install(); // Install pg0 binary
119-
120-
// Sync
121-
startSync({ port: 5432 });
122-
stopSync("default");
123-
infoSync("default");
124-
listInstancesSync();
125-
installSync();
126-
```
59+
import { start, stop, drop, info, listInstances } from "@vectorize-io/pg0";
12760

128-
### InstanceInfo
61+
await start({ name: "default", port: 5432 }); // Start instance
62+
await stop("default"); // Stop instance
63+
await drop("default"); // Delete instance
64+
await info("default"); // Get instance info
65+
await listInstances(); // List all instances
12966

130-
```typescript
131-
interface InstanceInfo {
132-
name: string;
133-
running: boolean;
134-
pid?: number;
135-
port?: number;
136-
version?: string;
137-
username?: string;
138-
database?: string;
139-
data_dir?: string;
140-
uri?: string;
141-
}
67+
// Sync versions: startSync, stopSync, dropSync, infoSync, listInstancesSync
14268
```
69+
70+
## Links
71+
72+
- [GitHub](https://github.com/vectorize-io/pg0)
73+
- [CLI Documentation](https://github.com/vectorize-io/pg0#readme)

sdk/node/dist/src/index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ export declare class Pg0 {
111111
export declare function listInstances(): Promise<InstanceInfo[]>;
112112
/** List all pg0 instances (synchronous). */
113113
export declare function listInstancesSync(): InstanceInfo[];
114+
/** List available PostgreSQL extensions. */
115+
export declare function listExtensions(): Promise<string[]>;
116+
/** List available PostgreSQL extensions (synchronous). */
117+
export declare function listExtensionsSync(): string[];
114118
/** Start a PostgreSQL instance (convenience function). */
115119
export declare function start(options?: Pg0Options): Promise<InstanceInfo>;
116120
/** Start a PostgreSQL instance (synchronous convenience function). */

sdk/node/dist/src/index.js

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ exports.install = install;
55
exports.installSync = installSync;
66
exports.listInstances = listInstances;
77
exports.listInstancesSync = listInstancesSync;
8+
exports.listExtensions = listExtensions;
9+
exports.listExtensionsSync = listExtensionsSync;
810
exports.start = start;
911
exports.startSync = startSync;
1012
exports.stop = stop;
@@ -63,10 +65,37 @@ function getPlatform() {
6365
return "darwin-aarch64"; // Intel Macs use Rosetta
6466
}
6567
else if (os === "linux") {
68+
// Detect architecture
69+
let arch_str;
6670
if (cpu === "x64") {
67-
return "linux-x86_64";
71+
arch_str = "x86_64";
6872
}
69-
throw new Pg0NotFoundError(`Unsupported Linux architecture: ${cpu}`);
73+
else if (cpu === "arm64") {
74+
arch_str = "aarch64";
75+
}
76+
else {
77+
throw new Pg0NotFoundError(`Unsupported Linux architecture: ${cpu}`);
78+
}
79+
// Detect libc (musl vs glibc)
80+
// Check for musl by looking for the musl loader
81+
const { execSync } = require("child_process");
82+
try {
83+
const ldd = execSync("ldd --version 2>&1", { encoding: "utf-8" });
84+
if (ldd.toLowerCase().includes("musl")) {
85+
return `linux-${arch_str}-musl`;
86+
}
87+
}
88+
catch {
89+
// If ldd fails, check for musl loader file
90+
const { existsSync } = require("fs");
91+
if (existsSync(`/lib/ld-musl-${arch_str}.so.1`) ||
92+
existsSync(`/lib/ld-musl-x86_64.so.1`) ||
93+
existsSync(`/lib/ld-musl-aarch64.so.1`)) {
94+
return `linux-${arch_str}-musl`;
95+
}
96+
}
97+
// Default to glibc
98+
return `linux-${arch_str}-gnu`;
7099
}
71100
else if (os === "win32") {
72101
return "windows-x86_64";
@@ -428,6 +457,16 @@ async function listInstances() {
428457
function listInstancesSync() {
429458
return JSON.parse(runPg0Sync("list", "-o", "json"));
430459
}
460+
/** List available PostgreSQL extensions. */
461+
async function listExtensions() {
462+
const { stdout } = await runPg0("list-extensions");
463+
return stdout.trim().split("\n").filter(line => line.trim());
464+
}
465+
/** List available PostgreSQL extensions (synchronous). */
466+
function listExtensionsSync() {
467+
const stdout = runPg0Sync("list-extensions");
468+
return stdout.trim().split("\n").filter(line => line.trim());
469+
}
431470
/** Start a PostgreSQL instance (convenience function). */
432471
async function start(options = {}) {
433472
return new Pg0(options).start();

0 commit comments

Comments
 (0)