Skip to content

Instantly share code, notes, and snippets.

@GoodnessEzeokafor
Created September 15, 2024 13:07
Show Gist options
  • Save GoodnessEzeokafor/7b45ec3b312ebae3c7a8a1d89e1beb49 to your computer and use it in GitHub Desktop.
Save GoodnessEzeokafor/7b45ec3b312ebae3c7a8a1d89e1beb49 to your computer and use it in GitHub Desktop.
clean-code architecture
/** generic repository */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Model } from 'sequelize';
import { IGenericRepository } from 'src/core';
export class SequelizeGenericRepository<T extends Model>
implements IGenericRepository<T>
{
private model: any;
constructor(model: any) {
this.model = model;
}
async findAllWithPagination(
query: any,
options?: {
useDefault?: boolean;
selectFields?: string[] | string;
relationFields?: string[] | string;
},
): Promise<{ data: T[]; pagination: any }> {
const { perPage = 10, page = 1, order = [['createdAt', 'DESC']] } = query;
const where: any = {};
Object.keys(query).forEach((key) => {
if (['limit', 'offset', 'order', 'perPage', 'page'].includes(key)) return;
where[key] = query[key];
});
const offset = (page - 1) * perPage;
const count = await this.model.count({ where });
const data = await this.model.findAll({
where,
order,
limit: perPage,
offset,
// ...(options?.selectFields ? { attributes: options.selectFields } : {}),
// ...(options?.relationFields
// ? {
// include: options.relationFields.map((field) => ({
// required: false,
// })),
// }
// : {}),
});
return {
data: data as T[],
pagination: {
hasPrevious: page > 1,
prevPage: page - 1,
hasNext: page < Math.ceil(count / perPage),
next: page + 1,
currentPage: Number(page),
pageSize: perPage,
lastPage: Math.ceil(count / perPage),
total: count,
},
};
}
async findOne(key: Partial<T> | Partial<T>[]): Promise<T | null> {
const where: any = {};
Object.keys(key).forEach((k) => (where[k] = key[k]));
return await this.model.findOne({
where,
});
}
async create(
payload: Partial<T>,
options?: { transaction?: any },
): Promise<T> {
if (options?.transaction) {
return await this.model.create(payload, {
transaction: options?.transaction,
});
}
return await this.model.create(payload);
}
async length(filter: Partial<T>): Promise<number> {
return await this.model.count({ where: filter });
}
async update(
key: Partial<T>,
payload: Partial<T>,
options?: { transaction: any },
) {
const where: any = {};
Object.keys(key).forEach((k) => (where[k] = key[k]));
return await this.model.update(payload, {
where,
...(options?.transaction ? { transaction: options.transaction } : {}),
});
}
async delete(key: Partial<T>, options?: { transaction: any }) {
const where: any = {};
Object.keys(key).forEach((k) => (where[k] = key[k]));
return await this.model.destroy({
where,
...(options?.transaction ? { transaction: options.transaction } : {}),
});
}
async bulkCreate(payload: Partial<T[]>, _options?: { transaction: any }) {
return await this.model.bulkCreate(payload);
}
}
/** abstract repository */
import { CategoryEntity, FeedbackEntity } from '../entities';
export abstract class IGenericRepository<T> {
abstract findAllWithPagination(
query?: any,
options?: {
useDefault?: boolean;
selectFields?: string[] | string;
relationFields?: string[] | string;
},
): Promise<{
data: any;
pagination: {
hasPrevious: boolean;
prevPage: number;
hasNext: boolean;
next: number;
currentPage: number;
pageSize: number;
lastPage: number;
total: any;
};
}>;
abstract findOne(
key: Partial<T> | Partial<T>[],
options?: {
useDefault?: boolean;
selectFields?: string[] | string;
relationFields?: string[] | string;
relationIds?: boolean;
},
): Promise<T>;
abstract create(
payload: Partial<T>,
options?: { transaction?: any },
): Promise<T>;
abstract length(filter: Partial<T>): Promise<any>;
abstract delete(key: Partial<T>, options?: { transaction: any });
abstract update(
key: Partial<T>,
payload: Partial<T>,
options?: { transaction?: any },
): Promise<any>;
}
export abstract class IDatabaseServices {
abstract feedbacks?: IGenericRepository<FeedbackEntity>;
abstract categories?: IGenericRepository<CategoryEntity>;
}
/** abstract repository */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment