PostgreSQL-native
Built exclusively for Postgres, not a lowest-common-denominator abstraction. Queries are tuned for Postgres performance. JSONB, DISTINCT ON, subquery joins, and ON CONFLICT upserts work out of the box.
Built exclusively for Postgres. Type-safe fluent query builder, decorator-based models, and queries tuned for Postgres performance.
Define a model, query it — that's it.
import { column, primaryColumn, table, Entity, initialize } from 'bigal';
import { Pool } from 'postgres-pool';
@table({ name: 'products' })
class Product extends Entity {
@primaryColumn({ type: 'integer' })
public id!: number;
@column({ type: 'string', required: true })
public name!: string;
@column({ type: 'integer', required: true })
public priceCents!: number;
@column({ model: () => 'Store', name: 'store_id' })
public store!: number | Store;
}
const repos = initialize({
models: [Product, Store],
pool: new Pool('postgres://localhost/mydb'),
});
const productRepo = repos.Product as Repository<Product>;
// Fluent queries — just await the chain
const products = await productRepo
.find()
.where({ priceCents: { '>': 1000 }, name: { contains: 'widget' } })
.sort('name asc')
.limit(10);
// Joins and subqueries
const expensiveProducts = await productRepo
.find()
.join('store')
.where({
store: { name: 'Acme' },
price: { '>': subquery(productRepo).avg('price') },
});
// Upserts with ON CONFLICT
await productRepo.create({ name: 'Widget', sku: 'WDG-001', priceCents: 999 }, { onConflict: { action: 'merge', targets: ['sku'], merge: ['priceCents'] } });