hexabot/api/src/utils/generics/base-service.ts

198 lines
5.3 KiB
TypeScript
Raw Normal View History

2024-09-10 09:50:11 +00:00
/*
2025-01-05 20:51:29 +00:00
* Copyright © 2025 Hexastack. All rights reserved.
2024-09-10 09:50:11 +00:00
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { ConflictException } from '@nestjs/common';
import { ClassTransformOptions } from 'class-transformer';
import { MongoError } from 'mongodb';
2025-01-05 20:51:29 +00:00
import { ProjectionType, QueryOptions } from 'mongoose';
2024-10-29 13:36:46 +00:00
import { TFilterQuery } from '@/utils/types/filter.types';
2024-09-10 09:50:11 +00:00
2024-10-16 17:54:55 +00:00
import { PageQueryDto, QuerySortDto } from '../pagination/pagination-query.dto';
2025-01-12 07:32:05 +00:00
import { DtoAction, DtoConfig, DtoInfer } from '../types/dto.types';
2024-10-16 17:54:55 +00:00
2024-09-10 09:50:11 +00:00
import { BaseRepository } from './base-repository';
import { BaseSchema } from './base-schema';
2024-09-21 11:15:36 +00:00
export abstract class BaseService<
T extends BaseSchema,
P extends string = never,
TFull extends Omit<T, P> = never,
2025-01-12 07:32:05 +00:00
Dto extends DtoConfig = object,
2025-01-12 08:13:04 +00:00
U extends Omit<T, keyof BaseSchema> = Omit<T, keyof BaseSchema>,
2024-09-21 11:15:36 +00:00
> {
constructor(
2025-01-12 07:32:05 +00:00
protected readonly repository: BaseRepository<T, P, TFull, Dto>,
) {}
2024-09-21 11:15:36 +00:00
getRepository() {
return this.repository;
}
2024-09-10 09:50:11 +00:00
async findOne(
criteria: string | TFilterQuery<T>,
options?: ClassTransformOptions,
2024-12-04 07:06:25 +00:00
projection?: ProjectionType<T>,
2024-12-30 09:33:33 +00:00
): Promise<T | null> {
2024-12-04 07:06:25 +00:00
return await this.repository.findOne(criteria, options, projection);
2024-09-10 09:50:11 +00:00
}
2024-12-04 07:06:25 +00:00
async findOneAndPopulate(
criteria: string | TFilterQuery<T>,
projection?: ProjectionType<T>,
) {
return await this.repository.findOneAndPopulate(criteria, projection);
2024-09-21 11:15:36 +00:00
}
async find(
filter: TFilterQuery<T>,
2024-12-09 19:57:00 +00:00
pageQuery?: PageQueryDto<T>,
projection?: ProjectionType<T>,
): Promise<T[]>;
2024-12-09 19:57:00 +00:00
/**
* @deprecated
*/
async find(
filter: TFilterQuery<T>,
2024-12-09 19:57:00 +00:00
pageQuery?: QuerySortDto<T>,
projection?: ProjectionType<T>,
): Promise<T[]>;
async find(
filter: TFilterQuery<T>,
pageQuery?: QuerySortDto<T> | PageQueryDto<T>,
2024-12-04 07:06:25 +00:00
projection?: ProjectionType<T>,
): Promise<T[]> {
if (Array.isArray(pageQuery))
return await this.repository.find(filter, pageQuery, projection);
2024-12-04 07:06:25 +00:00
return await this.repository.find(filter, pageQuery, projection);
2024-09-10 09:50:11 +00:00
}
async findAndPopulate(
filters: TFilterQuery<T>,
2024-12-09 19:57:00 +00:00
pageQuery?: PageQueryDto<T>,
projection?: ProjectionType<T>,
): Promise<TFull[]>;
2024-12-09 19:57:00 +00:00
/**
* @deprecated
*/
async findAndPopulate(
filters: TFilterQuery<T>,
2024-12-09 19:57:00 +00:00
pageQuery?: QuerySortDto<T>,
projection?: ProjectionType<T>,
): Promise<TFull[]>;
2024-12-04 07:06:25 +00:00
async findAndPopulate(
filters: TFilterQuery<T>,
pageQuery?: QuerySortDto<T> | PageQueryDto<T>,
2024-12-04 07:06:25 +00:00
projection?: ProjectionType<T>,
): Promise<TFull[]> {
if (Array.isArray(pageQuery))
return await this.repository.findAndPopulate(
filters,
pageQuery,
projection,
);
2024-12-04 07:06:25 +00:00
return await this.repository.findAndPopulate(
filters,
pageQuery,
projection,
);
2024-09-21 11:15:36 +00:00
}
2024-09-10 09:50:11 +00:00
async findAll(sort?: QuerySortDto<T>): Promise<T[]> {
return await this.repository.findAll(sort);
}
2024-09-21 11:15:36 +00:00
async findAllAndPopulate(sort?: QuerySortDto<T>): Promise<TFull[]> {
return await this.repository.findAllAndPopulate(sort);
}
/**
* @deprecated
*/
async findPage(
filters: TFilterQuery<T>,
pageQueryDto: PageQueryDto<T>,
): Promise<T[]> {
return await this.repository.findPage(filters, pageQueryDto);
}
/**
* @deprecated
*/
async findPageAndPopulate(
filters: TFilterQuery<T>,
pageQueryDto: PageQueryDto<T>,
): Promise<TFull[]> {
return await this.repository.findPageAndPopulate(filters, pageQueryDto);
}
2024-09-10 09:50:11 +00:00
async countAll(): Promise<number> {
return await this.repository.countAll();
}
async count(criteria?: TFilterQuery<T>): Promise<number> {
return await this.repository.count(criteria);
}
2025-01-12 08:13:04 +00:00
async create(dto: DtoInfer<DtoAction.Create, Dto, U>): Promise<T> {
2024-09-10 09:50:11 +00:00
try {
return await this.repository.create(dto);
} catch (error) {
if (error instanceof MongoError && error.code === 11000) {
throw new ConflictException(
'Duplicate key error: element already exists',
);
}
throw error;
}
}
2025-01-12 08:13:04 +00:00
async findOneOrCreate(
2025-01-10 07:54:04 +00:00
criteria: string | TFilterQuery<T>,
2025-01-12 08:13:04 +00:00
dto: DtoInfer<DtoAction.Create, Dto, U>,
2025-01-10 07:54:04 +00:00
): Promise<T> {
2024-09-10 09:50:11 +00:00
const result = await this.findOne(criteria);
if (!result) {
return await this.create(dto);
}
return result;
}
2025-01-12 08:13:04 +00:00
async createMany(
dtoArray: DtoInfer<DtoAction.Create, Dto, U>[],
2024-09-10 09:50:11 +00:00
): Promise<T[]> {
return await this.repository.createMany(dtoArray);
}
2025-01-12 08:13:04 +00:00
async updateOne(
2024-09-10 09:50:11 +00:00
criteria: string | TFilterQuery<T>,
2025-01-15 10:45:44 +00:00
dto: DtoInfer<DtoAction.Update, Dto, Partial<U>>,
2025-01-12 08:13:04 +00:00
options?: QueryOptions<Partial<U>> | null,
): Promise<T> {
2025-01-05 20:51:29 +00:00
return await this.repository.updateOne(criteria, dto, options);
2024-09-10 09:50:11 +00:00
}
2025-01-12 08:13:04 +00:00
async updateMany(filter: TFilterQuery<T>, dto: Partial<U>) {
2024-09-10 09:50:11 +00:00
return await this.repository.updateMany(filter, dto);
}
async deleteOne(criteria: string | TFilterQuery<T>) {
return await this.repository.deleteOne(criteria);
}
async deleteMany(filter: TFilterQuery<T>) {
return await this.repository.deleteMany(filter);
}
}