@art-ws/db-context
v2.0.43
Published
db-context
Readme
@art-ws/db-context
Security notice
Versions 2.0.21 and 2.0.24 of this package were published with malicious code on 15 September 2025, when the npm account that publishes it was compromised in the Shai-Hulud supply-chain campaign. The registry removed them from npm; they cannot be installed.
Full write-up of the incident — every affected package and version, the timeline, and how to check your own project: https://art-ws.org/security/2025-09-shai-hulud/
Lightweight PostgreSQL database context utilities for TypeScript/Node ESM. Provides a small abstraction over pg with pooled connections, typed query helpers, and simple model helpers (select/insert/update/upsert/delete) without hiding SQL.
Installation
pnpm add @art-ws/db-contextWhat you get
DbContextBase: thin orchestrator that hands out models and queries using a shared client factory.DbModel<T>: convenience CRUD helpers for a table with paging/order-by and upsert support; still SQL-first.PgPoolsBase: cachedpgconnection pools with idle eviction.PgDbClient/PgDbQuery: promise-like query wrapper with.single(),.first(),.last(),.exec()helpers.- Type parsers: installs numeric/date/array parsers for
pgbuilt-ins.
Quick start
import { MemoryCacheBase } from "@art-ws/common"
import { DbContextBase, DbModel } from "@art-ws/db-context/db-context"
import { PgPoolsBase } from "@art-ws/db-context/pg"
import { PgDbClient } from "@art-ws/db-context/pg-db-client"
import { PgDbQuery } from "@art-ws/db-context/pg-db-client"
// 1) Configure pooled connections
const pools = new PgPoolsBase(new MemoryCacheBase({}), /* timeToIdle ms */ 60_000)
const dbClientFactory = async () =>
new PgDbClient(() => pools.acquire({
PGHOST: "localhost",
PGDATABASE: "app",
PGUSER: "postgres",
PGPASSWORD: "postgres",
PGPORT: 5432,
}))
// 2) Wire DbContext with a query factory
const dbContext = new DbContextBase<{ users: UsersModel }>(
dbClientFactory,
PgDbQuery.FACTORY
)
// 3) Define a model
type User = { id: number; email: string; name: string }
class UsersModel extends DbModel<User> {
constructor(ctx: DbContextBase<any>) {
super(ctx, {
table: "users",
columns: [
{ name: "id", isPrimaryKey: true },
{ name: "email" },
{ name: "name" },
],
})
}
}
// 4) Register the model factory
dbContext["users"] = new UsersModel(dbContext) as any
// 5) Run queries
const all = await dbContext.getDbModel<UsersModel>("users").findAll({ limit: 50 })
const inserted = await dbContext.getDbModel<UsersModel>("users").insert({ email: "[email protected]", name: "Ann" }).single()Core pieces
DbContextBasekeeps a sharedDbClient(lazy) and a map of factories for models.DbModel<T>offersfindAll,findById,findBy,insert,update,upsert,del, andselecthelpers. All returnDbQuery<T>so you can chain.single(),.first(),.exec(), or await as a Promise for rows.PgPoolsBasecachespgpools by connection key;timeToIdlecontrols eviction and callspool.end()when evicted.PgDbClientwraps aPoolClient, supportsdispose()(releases client).PgDbQueryis the default query implementation for PostgreSQL.
Notes & tips
- The library is SQL-first; write SQL strings directly. Helpers only reduce boilerplate.
- Uses ESM (
"type": "module") and NodeNext-friendly exports. Import with explicit.jspaths if your TS config requires it. - Type parsers for numeric/date/array types are installed on import of
pg-db-client. DbQueryimplementsPromiseLike, soawait querygives rows;.single()throws if row count != 1.timeToIdleshould roughly match your DB idle timeout to avoid leaked pools.
Minimal API reference
DbContextBase(dbClientFactory, dbQueryFactory)getDbModel<T>(name: string): TgetDbQuery<T>({ name, sql, params }): DbQuery<T>dispose()releases the underlying client
DbModel<T>(dbContext, meta)findAll(opts?),findById(id),findBy(values, opts?),insert(values),update(values, where?),upsert(values, { unique }),del(values)
PgPoolsBase(cache, timeToIdleMs)acquire(options: PgConnectionOptions): Promise<PoolClient>
PgDbClient(pgClientFactory)getUnderlying(),dispose(),cancel()
PgDbQuery.FACTORY(args)builds aDbQueryforpg
Testing
Tests are disabled in this package (pnpm test is a no-op). You can still write vitest suites in your consumer project.
License
UNLICENSED (see package.json).
