import { AggregateQuery , Filter , Query , SortDirection , SortField } from '@nestjs-query/core' ; import { DocumentType , ReturnModelType , mongoose } from '@typegoose/typegoose' ; import { AggregateBuilder , TypegooseGroupAndAggregate } from './aggregate.builder' ; import { getSchemaKey } from './helpers' ; import { WhereBuilder } from './where.builder' ; const TYPEGOOSE_SORT_DIRECTION = { [ SortDirection . ASC ] : 1 , [ SortDirection . DESC ] : - 1 , } ; type TypegooseSort = Record < string , 1 | - 1 > ; type TypegooseQuery < Entity > = { filterQuery : mongoose . FilterQuery < new ( ) => Entity > ; options : { limit ? : number ; skip ? : number ; sort ? : TypegooseSort ; } ; } ; type TypegooseAggregateQuery < Entity > = TypegooseQuery < Entity > & { aggregate : TypegooseGroupAndAggregate ; } ; internal export class FilterQueryBuilder < Entity > { constructor ( readonly Model , readonly whereBuilder = new WhereBuilder < Entity > ( Model ) , readonly aggregateBuilder = new AggregateBuilder < Entity > ( ) ) { } buildQuery ( { filter , paging , sorting } ) { return { filterQuery : this . buildFilterQuery ( filter ) , options : { limit : paging ?. limit , skip : paging ?. offset , sort : this . buildSorting ( sorting ) } , } ; } buildAggregateQuery ( aggregate , filter ? ) { return { filterQuery : this . buildFilterQuery ( filter ) , aggregate : this . aggregateBuilder . build ( aggregate ) , options : { sort : this . buildAggregateSorting ( aggregate ) } , } ; } buildIdAggregateQuery ( id , filter , aggregate ) { return { filterQuery : this . buildIdFilterQuery ( id , filter ) , aggregate : this . aggregateBuilder . build ( aggregate ) , options : { sort : this . buildAggregateSorting ( aggregate ) } , } ; } buildIdFilterQuery ( id , filter ? ) { return { ... this . buildFilterQuery ( filter ) , _id : Array . isArray ( id ) ? { $in : id } : id , } ; } param filter buildFilterQuery ( filter ? ) { if ( ! filter ) { return { } ; } return this . whereBuilder . build ( filter ) ; } param sorts buildSorting ( sorts ? ) { if ( ! sorts ) { return undefined ; } return sorts . reduce ( ( sort , sortField ) => { const field = getSchemaKey ( sortField . field . toString ( ) ) ; const direction = TYPEGOOSE_SORT_DIRECTION [ sortField . direction ] ; return { ... sort , [ field ] : direction } ; } , { } ) ; } private buildAggregateSorting ( aggregate ) { const aggregateGroupBy = this . aggregateBuilder . getGroupBySelects ( aggregate . groupBy ) ; if ( ! aggregateGroupBy ) { return undefined ; } return aggregateGroupBy . reduce ( ( sort , sortField ) => { return { ... sort , [ getSchemaKey ( sortField ) ] : TYPEGOOSE_SORT_DIRECTION [ SortDirection . ASC ] } ; } , { } ) ; } }