fix: enhance dynamic DTO typing

This commit is contained in:
yassinedorbozgithub 2025-01-12 08:32:05 +01:00
parent 156d10210b
commit 8a1039148c
4 changed files with 22 additions and 22 deletions

View File

@ -30,7 +30,7 @@ import {
import { TFilterQuery } from '@/utils/types/filter.types'; import { TFilterQuery } from '@/utils/types/filter.types';
import { PageQueryDto, QuerySortDto } from '../pagination/pagination-query.dto'; import { PageQueryDto, QuerySortDto } from '../pagination/pagination-query.dto';
import { DtoAction, DtoInfer, DtoProps } from '../types/dto.types'; import { DtoAction, DtoConfig, DtoInfer } from '../types/dto.types';
import { BaseSchema } from './base-schema'; import { BaseSchema } from './base-schema';
import { LifecycleHookManager } from './lifecycle-hook-manager'; import { LifecycleHookManager } from './lifecycle-hook-manager';
@ -71,7 +71,7 @@ export abstract class BaseRepository<
T extends FlattenMaps<unknown>, T extends FlattenMaps<unknown>,
P extends string = never, P extends string = never,
TFull extends Omit<T, P> = never, TFull extends Omit<T, P> = never,
DTOCruds extends DtoProps<T> = unknown, Dto extends DtoConfig = object,
U = Omit<T, keyof BaseSchema>, U = Omit<T, keyof BaseSchema>,
D = Document<T>, D = Document<T>,
> { > {
@ -456,7 +456,7 @@ export abstract class BaseRepository<
return await this.model.countDocuments(criteria).exec(); return await this.model.countDocuments(criteria).exec();
} }
async create(dto: DtoInfer<DtoAction.Create, DTOCruds, U>): Promise<T> { async create(dto: DtoInfer<DtoAction.Create, Dto, U>): Promise<T> {
const doc = await this.model.create(dto); const doc = await this.model.create(dto);
return plainToClass( return plainToClass(
@ -467,7 +467,7 @@ export abstract class BaseRepository<
} }
async createMany( async createMany(
dtoArray: DtoInfer<DtoAction.Create, DTOCruds, U>[], dtoArray: DtoInfer<DtoAction.Create, Dto, U>[],
): Promise<T[]> { ): Promise<T[]> {
const docs = await this.model.create(dtoArray); const docs = await this.model.create(dtoArray);

View File

@ -8,7 +8,7 @@
import { FlattenMaps } from 'mongoose'; import { FlattenMaps } from 'mongoose';
import { DtoAction, DtoInfer, DtoProps } from '../types/dto.types'; import { DtoAction, DtoConfig, DtoInfer } from '../types/dto.types';
import { BaseRepository } from './base-repository'; import { BaseRepository } from './base-repository';
import { BaseSchema } from './base-schema'; import { BaseSchema } from './base-schema';
@ -17,10 +17,10 @@ export abstract class BaseSeeder<
T extends FlattenMaps<unknown>, T extends FlattenMaps<unknown>,
P extends string = never, P extends string = never,
TFull extends Omit<T, P> = never, TFull extends Omit<T, P> = never,
DTOCruds extends DtoProps<any> = unknown, Dto extends DtoConfig = object,
> { > {
constructor( constructor(
protected readonly repository: BaseRepository<T, P, TFull, DTOCruds>, protected readonly repository: BaseRepository<T, P, TFull, Dto>,
) {} ) {}
async findAll(): Promise<T[]> { async findAll(): Promise<T[]> {
@ -33,7 +33,7 @@ export abstract class BaseSeeder<
} }
async seed<D extends Omit<T, keyof BaseSchema>>( async seed<D extends Omit<T, keyof BaseSchema>>(
models: DtoInfer<DtoAction.Create, DTOCruds, D>[], models: DtoInfer<DtoAction.Create, Dto, D>[],
): Promise<boolean> { ): Promise<boolean> {
if (await this.isEmpty()) { if (await this.isEmpty()) {
await this.repository.createMany(models); await this.repository.createMany(models);

View File

@ -14,7 +14,7 @@ import { ProjectionType, QueryOptions } from 'mongoose';
import { TFilterQuery } from '@/utils/types/filter.types'; import { TFilterQuery } from '@/utils/types/filter.types';
import { PageQueryDto, QuerySortDto } from '../pagination/pagination-query.dto'; import { PageQueryDto, QuerySortDto } from '../pagination/pagination-query.dto';
import { DtoAction, DtoInfer, DtoProps } from '../types/dto.types'; import { DtoAction, DtoConfig, DtoInfer } from '../types/dto.types';
import { BaseRepository } from './base-repository'; import { BaseRepository } from './base-repository';
import { BaseSchema } from './base-schema'; import { BaseSchema } from './base-schema';
@ -23,10 +23,10 @@ export abstract class BaseService<
T extends BaseSchema, T extends BaseSchema,
P extends string = never, P extends string = never,
TFull extends Omit<T, P> = never, TFull extends Omit<T, P> = never,
DTOCruds extends DtoProps<any> = unknown, Dto extends DtoConfig = object,
> { > {
constructor( constructor(
protected readonly repository: BaseRepository<T, P, TFull, DTOCruds>, protected readonly repository: BaseRepository<T, P, TFull, Dto>,
) {} ) {}
getRepository() { getRepository() {
@ -145,7 +145,7 @@ export abstract class BaseService<
} }
async create<D extends Omit<T, keyof BaseSchema>>( async create<D extends Omit<T, keyof BaseSchema>>(
dto: DtoInfer<DtoAction.Create, DTOCruds, D>, dto: DtoInfer<DtoAction.Create, Dto, D>,
): Promise<T> { ): Promise<T> {
try { try {
return await this.repository.create(dto); return await this.repository.create(dto);
@ -161,7 +161,7 @@ export abstract class BaseService<
async findOneOrCreate<D extends Omit<T, keyof BaseSchema>>( async findOneOrCreate<D extends Omit<T, keyof BaseSchema>>(
criteria: string | TFilterQuery<T>, criteria: string | TFilterQuery<T>,
dto: DtoInfer<DtoAction.Create, DTOCruds, D>, dto: DtoInfer<DtoAction.Create, Dto, D>,
): Promise<T> { ): Promise<T> {
const result = await this.findOne(criteria); const result = await this.findOne(criteria);
if (!result) { if (!result) {
@ -171,7 +171,7 @@ export abstract class BaseService<
} }
async createMany<D extends Omit<T, keyof BaseSchema>>( async createMany<D extends Omit<T, keyof BaseSchema>>(
dtoArray: DtoInfer<DtoAction.Create, DTOCruds, D>[], dtoArray: DtoInfer<DtoAction.Create, Dto, D>[],
): Promise<T[]> { ): Promise<T[]> {
return await this.repository.createMany(dtoArray); return await this.repository.createMany(dtoArray);
} }

View File

@ -13,12 +13,12 @@ export enum DtoAction {
Delete = 'delete', Delete = 'delete',
} }
export type DtoConfig<T extends Partial<Record<DtoAction, object>>> = T; export type DtoConfig<
C extends Partial<Record<DtoAction, object>> = Partial<
Record<DtoAction, object>
>,
> = C;
export type DtoProps<T extends Record<string, unknown>> = { export type DtoInfer<K extends keyof Dto, Dto, I> = Dto[K] extends object
[K in DtoAction]?: T[K]; ? Dto[K]
}; : I;
export type DtoInfer<K extends keyof DTO, DTO, T> = DTO[K] extends object
? DTO[K]
: T;