
Security News
Crates.io Implements Trusted Publishing Support
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
A fast and lightweight orm for postgres and node.js, written in typescript.
A fast, lightweight ORM for PostgreSQL and node.js, written in Typescript.
This ORM does not:
npm install pg postgres-pool bigal
Model definitions need to extend Entity
.
import { column, primaryColumn, table, Entity } from 'bigal';
import { Store } from './Store';
import { Category } from './Category';
import { ProductCategory } from './ProductCategory';
@table({
name: 'products',
})
export class Product extends Entity {
@primaryColumn({ type: 'integer' })
public id!: number;
@column({
type: 'string',
required: true,
})
public name!: string;
@column({
type: 'string',
})
public sku?: string;
@column({
type: 'string[]',
defaultsTo: [],
name: 'alias_names',
})
public aliases?: string[];
@column({
model: () => Store.name,
name: 'store_id',
})
public store!: number | Store;
@column({
collection: () => Category.name,
through: () => ProductCategory.name,
via: 'product',
})
public categories?: Category[];
}
import {
initialize,
Repository,
} from 'bigal';
import { Pool } from 'postgres-pool';
import {
Category,
Product,
ProductCategory,
Store,
} from './models';
let pool: Pool;
let readonlyPool: Pool;
export function startup({
connectionString,
readonlyConnectionString,
}: {
connectionString: string,
readonlyConnectionString: string,
}) {
pool = new Pool(connectionString);
readonlyPool = new Pool(readonlyConnectionString);
const repositoriesByName = initialize({
models: [
Category,
Product,
ProductCategory,
Store,
],
pool,
readonlyPool,
});
let categoryRepository: Repository<Category>;
let productRepository: Repository<Category>;
let storeRepository: Repository<Category>;
for (const [modelName, repository] = Object.entries(repositoriesByName)) {
switch (modelName) {
case 'Category':
categoryRepository = repository;
break;
case 'Product':
productRepository = repository;
break;
case 'Store':
storeRepository = repository;
break;
}
}
return {
categoryRepository,
productRepository,
storeRepository,
}
}
export function shutdown() {
const shutdownEvents = [];
if (pool) {
shutdownEvents.push(pool.end());
}
if (readonlyPool) {
shutdownEvents.push(readonlyPool.end());
}
return Promise.all(shutdownEvents);
}
.findOne()
- Fetch a single objectconst item = await ProductRepository.findOne().where({
id: context.params.id,
});
const item = await ProductRepository.findOne({
select: ['name'],
}).where({
id: context.params.id,
});
const poolOverride = new Pool(connectionString);
const item = await ProductRepository.findOne({
pool: poolOverride,
}).where({
id: context.params.id,
});
const item = await ProductRepository.findOne()
.where({
id: context.params.id,
})
.populate('store', {
select: ['name'],
});
const poolOverride = new Pool(connectionString);
const item = await ProductRepository.findOne()
.where({
id: context.params.id,
})
.populate('store', {
select: ['name'],
pool: poolOverride,
});
const item = await ProductRepository.findOne()
.where({
foo: context.params.foo,
})
.sort('name asc');
.find()
- Fetch a multiple objectsconst items = await ProductRepository.find().where({
foo: context.params.foo,
});
const items = await ProductRepository.find({
select: ['name'],
}).where({
foo: context.params.foo,
});
const poolOverride = new Pool(connectionString);
const item = await ProductRepository.find({
pool: poolOverride,
}).where({
foo: context.params.foo,
});
const items = await PersonRepository.find().where({
firstName: {
like: ['walter', 'Jess%'],
},
});
const items = await PersonRepository.find().where({
lastName: {
'!': {
lastName: [null, '', 'Whi%'],
},
},
});
const items = await PersonRepository.find()
.where({
firstName: {
like: 'walter',
},
lastName: {
like: 'white',
},
})
.sort({
age: 1,
occupation: -1,
});
const items = await PersonRepository.find()
.where({
age: [22, 23, 24],
})
.limit(42);
x
resultsconst items = await FooRepository.find()
.where({
or: [
{
foo: context.params.foo,
},
{
bar: context.params.foo,
},
],
})
.skip(42);
skip()
& limit()
const items = await FooRepository.find()
.where({
foo: context.params.foo,
})
.skip(84)
.limit(42);
paginate
const page = 2;
const pageSize = 42;
const items = await FooRepository.find()
.where({
foo: context.params.foo,
})
.paginate(page, pageSize);
.count()
- Get the number of records matching the where criteriaconst count = await PersonRepository.count().where({
name: {
like: 'Karl',
},
});
// count = 3
.create()
- Insert one or multiple objectsconst item = await PersonRepository.create({
name: 'Karl',
});
// item = { id: 42, name: 'Karl', createdAt: ... }
await PersonRepository.create(
{
name: 'Karl',
},
{
returnRecords: false,
},
);
const item = await PersonRepository.create(
{
name: 'Karl',
},
{
returnSelect: ['name'],
},
);
// item = { id: 42, name: 'Karl' }
Note: The primary key will always be included. To only return the primary key value, pass an empty array
const items = await PersonRepository.create([
{
name: 'LX',
},
{
name: 'Big Al',
},
]);
// items = [{ id: 24, name: 'LX', createdAt: ... }, { id: 25, name: 'Big Al', createdAt: ... }]
await PersonRepository.create(
[
{
name: 'LX',
},
{
name: 'Big Al',
},
],
{
returnRecords: false,
},
);
const items = await PersonRepository.create(
[
{
name: 'LX',
},
{
name: 'Big Al',
},
],
{
returnSelect: ['id'],
},
);
// items = [{ id: 24 }, { id: 25 }]
Note: The primary key will always be included. To only return the primary key value, pass an empty array
const item = await PersonRepository.create(
{
name: 'Karl',
},
{
onConflict: {
action: 'ignore',
targets: ['name'],
},
},
);
// item = { id: 42, name: 'Karl', createdAt: ... }
const item = await PersonRepository.create(
{
name: 'Karl',
},
{
onConflict: {
action: 'merge',
targets: ['ssn'],
},
},
);
// item = { id: 42, name: 'Karl', createdAt: ... }
const item = await PersonRepository.create(
{
name: 'Karl',
},
{
onConflict: {
action: 'merge',
targets: ['ssn'],
merge: ['name', 'age'],
},
},
);
// item = { id: 42, name: 'Karl', createdAt: ... }
.update()
- Update objectsconst items = await PersonRepository.update(
{
id: 42,
},
{
name: 'Big Al',
},
);
// items = [{ id: 42, name: 'Big Al', createdAt: ... }]
Note: This method will return an array, regardless of how many records were affected
await PersonRepository.update(
{
id: 42,
},
{
name: 'Big Al',
},
{
returnRecords: false,
},
);
const items = await PersonRepository.update(
{
id: [42, 43],
},
{
occupation: 'Water Purification Engineer',
},
{
returnSelect: ['id'],
},
);
// items = [{ id: 42 }, { id: 43 }]
.destroy()
- Delete objects from the dbconst items = await PersonRepository.destroy({
id: 42,
});
// items = [{ id: 42, name: 'Big Al', createdAt: ... }]
Note: This method will return an array, regardless of how many records were affected
await PersonRepository.destroy(
{
id: 42,
},
{
returnRecords: false,
},
);
const items = await PersonRepository.destroy(
{
id: [24, 25],
},
{
returnSelect: ['name'],
},
);
// items = [{ id: 24, name: 'LX' }, { id: 25, name: 'Big Al' }]
Note: The primary key will always be included. To only return the primary key value, pass an empty array
BigAl expects that all entity collection properties must be optional. There will be some type issues with QueryResult if you make a collection non-optional.
For example:
export class Store extends Entity {
@primaryColumn({ type: 'integer' })
public id!: number;
@column({
type: 'string',
required: true,
})
public name!: string;
// This property MUST be optional
@column({
collection: () => Product.name,
via: 'store',
})
public products?: Product[];
}
If you have a json property, with an id
field, on an entity model, TypeScript will probably think it is a BigAl
entity due to how the type system works. In that case, you'll want to wrap the type with NotEntity<>
. For example:
export interface IMyJsonType {
id: string;
foo: string;
}
export class Product extends Entity {
@primaryColumn({ type: 'integer' })
public id!: number;
@column({
type: 'string',
required: true,
})
public name!: string;
@column({
type: 'json',
})
public myJson?: NotEntity<IMyJsonType>;
}
Debugging can be enabled by passing the DEBUG_BIGAL
environment flag with a value of true
.
Debugging will print the generated SQL code in the console.
MIT
FAQs
A fast and lightweight orm for postgres and node.js, written in typescript.
The npm package bigal receives a total of 1,485 weekly downloads. As such, bigal popularity was classified as popular.
We found that bigal 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
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
Research
/Security News
Undocumented protestware found in 28 npm packages disrupts UI for Russian-language users visiting Russian and Belarusian domains.
Research
/Security News
North Korean threat actors deploy 67 malicious npm packages using the newly discovered XORIndex malware loader.