
Security News
Federal Audit Finds NIST Wasted Funds With No Plan to Clear NVD Backlog
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.
@askalf/pgflex
Advanced tools
One Postgres API. Two modes. Real PostgreSQL (pg) for production, PGlite (in-process WASM) for standalone / dev. Same SQL, same query shape, drop the server when you don't need it.
One Postgres API. Two modes. Same SQL.
Switch between a real PostgreSQL server (pg) and in-process PostgreSQL (PGlite, WASM) with one line of config. Production runs on real Postgres; dev / standalone / "no-Docker mode" runs in-process. Same SQL, same query shape, same parameter style — drop the server when you don't need it.
npm install @askalf/pgflex
Most apps need Postgres. Most dev environments don't want the overhead of running a Postgres server. Most CI environments REALLY don't want it. PGlite (electric-sql/pglite) gives you full PostgreSQL — JSONB, ON CONFLICT, RETURNING, triggers, functions, even pgvector — running in WASM, in your Node process, with no server, no port, no Docker.
pgflex is the thin adapter on top: one DatabaseAdapter interface, two backends, mode flips via config or env var. Your SQL, your transactions, and your codepaths stay identical between modes.
import { createAdapter } from '@askalf/pgflex';
// Production — real Postgres server
const db = await createAdapter({
mode: 'pg',
connectionString: process.env.DATABASE_URL!,
});
// Dev / standalone — PGlite, no server needed
const db = await createAdapter({
mode: 'pglite',
dataDir: '~/.myapp/data', // or 'memory://' for ephemeral
});
const users = await db.query<{ name: string }>(
'SELECT name FROM users WHERE active = $1',
[true],
);
import { createAdapterFromEnv } from '@askalf/pgflex';
// PGFLEX_MODE=pglite → pglite at $PGFLEX_DATA_DIR (or ~/.pgflex/data)
// otherwise → pg at $DATABASE_URL
const db = await createAdapterFromEnv();
You can rename any of the env vars:
const db = await createAdapterFromEnv({
modeEnvVar: 'MYAPP_MODE',
connectionStringEnvVar: 'MYAPP_DB_URL',
dataDirEnvVar: 'MYAPP_DATA_DIR',
pgliteExtensions: ['vector'],
});
const transferred = await db.transaction(async (tx) => {
await tx.query('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [30, 1]);
await tx.query('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [30, 2]);
return 30;
});
Auto-commits on return. Auto-rolls-back on throw.
interface DatabaseAdapter {
query<T>(text: string, params?: unknown[]): Promise<T[]>;
queryOne<T>(text: string, params?: unknown[]): Promise<T | null>;
transaction<T>(fn: (client: TransactionClient) => Promise<T>): Promise<T>;
close(): Promise<void>;
readonly mode: 'pg' | 'pglite';
}
That's it. Same shape across both backends. db.mode is exposed if some piece of your app needs to branch on the runtime — but most don't.
const db = await createAdapter({
mode: 'pglite',
dataDir: 'memory://',
extensions: ['vector'],
});
await db.query('CREATE TABLE docs (id INT, embedding vector(1536))');
v0.0.1 wires vector (pgvector) end-to-end — both the JS-side WASM hooks and CREATE EXTENSION vector happen during init().
Other PGlite contrib extensions (uuid-ossp, pgcrypto, tsm_system_rows, etc.) need their own JS-side import to register the WASM hooks. Listing them in the extensions array currently only runs CREATE EXTENSION IF NOT EXISTS <name>, which is enough for extensions baked into PGlite's core WASM but not enough for the contrib ones. Open an issue if you need one wired up; they're ~5 lines each.
In pg mode, extensions are the database admin's responsibility — they're either there or they aren't.
@electric-sql/pglite is in optionalDependencies, so:
pg mode, you can install with --no-optional and skip the WASM bytes.pglite mode, it gets installed by default.If pglite mode is selected and the package isn't installed, init() throws a clear error telling you what to install.
In pg mode, every connection gets SET statement_timeout = 30000 automatically. Protects the pool from runaway queries. Override at the SQL level (SET statement_timeout = ...) or open an issue if you need it tunable from the adapter config.
import { PgAdapter } from '@askalf/pgflex';
const adapter = new PgAdapter(process.env.DATABASE_URL!);
const pool = adapter.getPool(); // raw pg.Pool — for LISTEN/NOTIFY etc.
Use sparingly. Code that touches the underlying pool won't work in pglite mode.
query(text, params) function.pg mode uses pg.Pool directly; pglite mode is single-process by design.pg-only SQL (e.g. pg_sleep, server-side functions you've installed yourself, advisory locks), it'll fail in pglite mode the same way pg would fail without those features.MIT — see LICENSE.
| Project | What it does |
|---|---|
| dario | Use your Claude Max/Pro subscription as an API. Local OAuth proxy that works with any Anthropic or OpenAI SDK. |
| brio | Capability layer for AI workloads — semantic cache, cost-aware tiering, policy. Sits in front of any Anthropic-compat endpoint. |
| hands | Cross-platform computer-use agent. |
FAQs
One Postgres API. Two modes. Real PostgreSQL (pg) for production, PGlite (in-process WASM) for standalone / dev. Same SQL, same query shape, drop the server when you don't need it.
The npm package @askalf/pgflex receives a total of 7 weekly downloads. As such, @askalf/pgflex popularity was classified as not popular.
We found that @askalf/pgflex demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.