Skip to content

Repository

ArteMerlow edited this page May 28, 2025 · 1 revision

Repository pattern

Repository is a wrapper over QueryBuilder that allows you to remove unnecessary actions, type fields and work with relationships/soft deletes

To create a repository, you simply need to create an instance of the class by specifying the table (Module)

const usersRepository = new Repository(Users);

The repository also accepts DTO as a second argument. You can read more about them on this page

// Repository with DTO
const dtoUsersRepository = new Repository(Users, UserDTO);

The only difference between these two options is that a repository with a specified DTO will return that same DTO in SELECT-like queries. Types are taken from the table (module)

Note that if you don't specify returnsNullWhenErrors: true then methods in Repository will throw exceptions on errors.

Examples

Adds new user with name = 'Alice' and money = 200

const usersRepository = new Repository(Users);
await usersRepository.insert({ first_name: 'Alice', money: 200 });

Updates Users sets is_banned: false where user_id: 1

const usersRepository = new Repository(Users);
await usersRepository.update({ is_banned: false }, { user_id: 1 });

Selects all users

const usersRepository = new Repository(Users);
const users : Users[] = await usersRepository.find();

Selects one user where balance is 1

const usersRepository = new Repository(Users);
const user : Users | null = await usersRepository.findOne({ money: 1 });

This call will be converted to:

SELECT * FROM users WHERE first_name = 'Alice' OR money = 300 OR rank = 'Moderator' AND is_banned = false ORDER BY id DESC, money ASC LIMIT 2

const usersRepository = new Repository(Users);
const users : Users[] = await usersRepository.find({
    first_name: ['Alice'],
    money: [300],
    rank: 'Moderator',
    is_banned: false
}, {
    order: {
        id: 'DESC',
        money: 'ASC'
    },
    limit: 2
})

All methods

insert(values: TableFieldBlock)

Just INSERT query

findOne(values: WhereBlock = {}, params?: AdditionalParams)

SELECT query with LIMIT 1 (NOTE: without orders)

find(values: WhereBlock = {}, params?: AdditionalParams)

Just SELECT query

update(values: TableFieldBlock, where: WhereBlock)

Just UPDATE query

delete(where: WhereBlock)

Just DELETE query

queryBuilder()

Returns new QueryBuilder with specified table

query(sql: string, escape?: any[])

Sends SQL query

save(obj: T)

Inserts object if its not exists or updates by primary key

remove(obj: T)

Checks that specified object exists and sends DELETE query

startTransaction()

Starts transaction with current connection

commitTransaction()

Commits and stops current transaction

rollbackTransaction()

Rollbacks current transaction

exists(where: WhereBlock = {})

Checks that object exists and returns boolean

count(where: WhereBlock = {})

Returns count of results

logTable()

Output module table to console

softDelete(where: WhereBlock)

Sets SoftDelete column to current Date

softFind(values: WhereBlock = {}, params?: AdditionalParams)

Automatically adds a condition to the WHERE clause, under which soft_delete_column_name IS NULL

softFindOne(values: WhereBlock = {}, params?: AdditionalParams)

Similar to the previous method, but adds LIMIT 1

clone(where: WhereBlock, edit: TableFieldBlock)

Clones specified values

updateInstance(instance: T | B, params?: AdditionalParams)

Updates specified object by Object.assign

findByAutoincrementKey(id: number, params?: AdditionalParams)

Finds rows by autoincrement key

findOneByAutoincrementKey(id: number, params?: AdditionalParams)

Finds one row by autoincrement key

findOrFail(values: WhereBlock = {}, params?: AdditionalParams)

Finds object and checks its length. If length is 0, throws error

addRelation(relation: K, entityId: number, relatedEntity: number | R)

Adds rows to JOIN table

removeRelation(relation: K, entityId: number, relatedEntity: number | R)

Removes rows in JOIN table by specified values

deleteAllManyToManyRelations(relation: K)

Truncate join table by specified relation

deleteAll()

Deletes all rows and sets autoincrement key to one

What is inside the methods and interfaces used?

AdditionalParams

This is a type created from SelectQueryParams and Partial. It is needed for additional SQL constructs in SELECT queries.

export interface SelectQueryParams<T> {
    // Sets LIMIT
    limit: number;
    // Sets OFFSET
    offset: number;
    // Add orders 
    order: Partial<{ [K in keyof T]: 'ASC' | 'DESC' }>;
    // You can disable caching this query
    useCache: boolean;
    // Time to live of cache
    cacheTTL: number;
    // Mixed relations
    relations: (string | ClassConstructor<Module>)[];
    // Depth of relations
    depth: number;
}

TableFieldBlock

This is a Partial, where T is the module passed to the repository. Needed for parameter typing

export type TableFieldBlock<T extends Module> = Partial<T>

WhereBlock

This is a type similar to TableFieldBlock, but also allows you to specify an array. The type is used exclusively for the WHERE clause.

export type WhereBlock<T extends Module> = {
    [K in keyof T]?: T[K] | T[K][];
};

Clone this wiki locally