import { Document, Model, AnyKeys, AnyObject, Types } from "mongoose"; import { AppException } from "./../exception_filter/app.exception"; export class NotFoundException extends AppException { constructor() { super(404, "Element not Found"); } } export abstract class EntityRepository { constructor(protected readonly entityModel: Model) {} async getAll(refs: string[] = []): Promise { const query = this.entityModel.find(); refs.forEach((ref) => query.populate(ref)); return await query.exec(); } async getCount(): Promise { return await this.entityModel.countDocuments({}).exec(); } async getCountBy(groupBy: string): Promise { const filter = "$" + groupBy; const query = this.entityModel.aggregate([ { $group: { _id: { [groupBy]: filter }, count: { $sum: 1 }, }, }, ]); return await query.exec(); } async findById(id: string, refs: string[] = []): Promise { const filters: object = { _id: new Types.ObjectId(id) }; const query = this.entityModel.find(filters); refs.forEach((ref) => query.populate(ref)); const result = await query.exec(); if (result.length === 0) { throw new NotFoundException(); } return result[0]; } async find(filters = {}, refs: string[] = []): Promise { const query = this.entityModel.find(filters); refs.forEach((ref) => query.populate(ref)); const result = await query.exec(); if (result.length === 0) { throw new NotFoundException(); } return result[0]; } async findAll( filters = {}, skip = 0, limit = -1, refs: string[] = [] ): Promise { let query; if (limit <= 0) { query = this.entityModel.find(filters); } else { query = this.entityModel.find(filters).skip(skip).limit(limit); } refs.forEach((ref) => query.populate(ref)); return await query.exec(); } async exists(filters = {}, refs: string[] = []): Promise { const query = this.entityModel.find(filters); refs.forEach((ref) => query.populate(ref)); const result = await query.exec(); return !(result.length === 0); } async save(document: T): Promise { await document.save(); return document; } async create(data: AnyKeys & AnyObject): Promise { const document = new this.entityModel(data); return await this.save(document as unknown as T); } async update(document: T): Promise { return await this.save(document); } async delete(id: string): Promise { const filters: object = { _id: new Types.ObjectId(id) }; await this.entityModel.deleteOne(filters).exec(); } }