@heyhru/server-plugin-pg
v0.8.2
Published
PostgreSQL connection pool with unified execute interface
Readme
@heyhru/server-plugin-pg
PostgreSQL connection pool with a unified, parameter-style execute interface, plus a tiny migration runner that piggybacks on the same PgDb handle.
Install
pnpm add @heyhru/server-plugin-pgTwo ways to talk to Postgres
This package ships two abstractions for two distinct use cases:
createPgDb(url, opts)/getPgDb()— singleton app DB with?-style placeholders, intended for the app's own data (users, sessions, etc.).createPool(config)— multi-instance target DB pool used by data-source registries that connect to many user-owned databases.
App DB (singleton)
import { createPgDb, getPgDb } from "@heyhru/server-plugin-pg";
await createPgDb(process.env.DATABASE_URL!, {
ssl: true,
poolMin: 2,
poolMax: 10,
idleTimeoutMs: 10_000,
});
const db = getPgDb();
await db.run("INSERT INTO users (email) VALUES (?)", ["[email protected]"]);
const rows = await db.query<{ id: string }>("SELECT id FROM users WHERE email = ?", [
"[email protected]",
]);? placeholders are converted to $1, $2, ... internally so callers stay agnostic of pg-specific syntax.
Migrations
runMigrations(db, migrations) walks an ordered list of { name, sql } records, applies any that have not yet been recorded in the _migrations tracking table, and inserts a marker on success.
import { createPgDb, getPgDb, runMigrations, type Migration } from "@heyhru/server-plugin-pg";
const migrations: Migration[] = [
{ name: "001_users.sql", sql: () => `CREATE TABLE users (...)` },
{ name: "002_audit.sql", sql: () => `CREATE TABLE audit_log (...)` },
];
await createPgDb(process.env.DATABASE_URL!);
await runMigrations(getPgDb(), migrations, {
onApplied: (name) => console.log(`migrated: ${name}`),
});The runner is intentionally minimal: no down migrations, no checksums, no transactions across migrations. Each migration is run sequentially and recorded only after success.
Target DB pool
import { createPool } from "@heyhru/server-plugin-pg";
const pool = createPool({
host: "db.example.com",
port: 5432,
database: "analytics",
username: "ro",
password: "secret",
poolMin: 2,
poolMax: 10,
ssl: true,
});
const rows = await pool.execute("SELECT NOW()");
await pool.end();Use this when you maintain a registry of user-supplied connection strings (DMS-style), not for the app's own DB.
