import { GrpcNotFoundException } from 'nestjs-grpc-exceptions'; import { Paginated, PaginateQuery } from 'nestjs-paginate'; import { IBaseRepository } from '@/core/domain/interfaces/base.repository.interface'; import { instanceToPlain } from 'class-transformer'; import { IBaseService } from './base.interface'; export class BaseService< Entity, CreateMessage extends Partial, UpdateMessage extends Partial & { id: number }, Message, > implements IBaseService { constructor(private readonly repository: IBaseRepository) {} /** * Finds a single entity by its ID. * @param id - The ID of the entity to find. * @returns A promise that resolves to the mapped message. * @throws GrpcNotFoundException if the entity is not found. */ async findOne(id: number): Promise { const entity = await this.repository.findById(id); if (!entity) { throw new GrpcNotFoundException(`${this.constructor.name.replace('Service', '')} not found`); } return entity as Message; } /** * Retrieves all entities. * @returns A promise that resolves to an object containing an array of mapped messages. */ async findAll(): Promise<{ data: Message[] }> { const entities: Entity[] = await this.repository.find(); return { data: entities as unknown as Message[], }; } /** * Retrieves paginated entities based on the provided query. * @param query - Pagination and filter criteria. * @returns A promise that resolves to the paginated result with rows and count. */ async getMany(query?: PaginateQuery): Promise> { const entities: Paginated = await this.repository.getMany(query); return entities as unknown as Paginated; } /** * Creates a new entity from the provided DTO. * @param createDTO - The data transfer object for creating an entity. * @returns A promise that resolves to the mapped message of the created entity. */ async create(createDTO: CreateMessage): Promise { const plain = instanceToPlain(createDTO); const entity = this.repository.create(plain as Entity); await this.repository.save(entity); return entity as unknown as Message; } /** * Updates an existing entity with the provided DTO. * @param updateDTO - The data transfer object for updating an entity. * @returns A promise that resolves to the mapped message of the updated entity. * @throws GrpcNotFoundException if the entity is not found. */ async update(updateDTO: UpdateMessage): Promise { const entity = await this.repository.findById(updateDTO.id); if (!entity) { throw new GrpcNotFoundException(`${this.constructor.name.replace('Service', '')} not found`); } await this.repository.update(updateDTO.id, instanceToPlain(updateDTO) as any); const updatedEntity: Entity = await this.repository.findById(updateDTO.id); return updatedEntity as unknown as Message; } /** * Deletes an entity by its ID. * @param id - The ID of the entity to delete. * @returns A promise that resolves when the entity is deleted. */ async remove(id: number): Promise { await this.repository.delete(id); } /** * Counts all entities. * @param options - Optional query options for counting entities. * @returns A promise that resolves to an object containing the count. */ async count(options?: any): Promise<{ count: number }> { const count = await this.repository.count(options || {}); return { count }; } }