import { Filter , FilterComparisons , FilterFieldComparison } from '@nestjs-query/core' ; import { ReturnModelType , mongoose } from '@typegoose/typegoose' ; import { EntityComparisonField , ComparisonBuilder } from './comparison.builder' ; internal export class WhereBuilder < Entity > { constructor ( readonly Model , readonly comparisonBuilder = new ComparisonBuilder < Entity > ( Model ) ) { } param filter build ( filter ) { const { and , or } = filter ; let ands = [ ] ; let ors = [ ] ; let filterQuery = { } ; if ( and && and . length ) { ands = and . map ( ( f ) => this . build ( f ) ) ; } if ( or && or . length ) { ors = or . map ( ( f ) => this . build ( f ) ) ; } const filterAnds = this . filterFields ( filter ) ; if ( filterAnds ) { ands = [ ... ands , filterAnds ] ; } if ( ands . length ) { filterQuery = { ... filterQuery , $and : ands } ; } if ( ors . length ) { filterQuery = { ... filterQuery , $or : ors } ; } return filterQuery ; } param filter private filterFields ( filter ) { const ands = Object . keys ( filter ) . filter ( ( f ) => f !== 'and' && f !== 'or' ) . map ( ( field ) => this . withFilterComparison ( field as keyof Entity , this . getField ( filter , field as keyof Entity ) ) ) ; if ( ands . length === 1 ) { return ands [ 0 ] ; } if ( ands . length ) { return { $and : ands } as mongoose . FilterQuery < Entity > ; } return undefined ; } private getField < K extends keyof FilterComparisons < Entity > > ( obj , field ) { return obj [ field ] as FilterFieldComparison < Entity [ K ] > ; } private withFilterComparison < T extends keyof Entity > ( field , cmp ) { const opts = Object . keys ( cmp ) as ( keyof FilterFieldComparison < Entity [ T ] > ) [ ] ; if ( opts . length === 1 ) { const cmpType = opts [ 0 ] ; return this . comparisonBuilder . build ( field , cmpType , cmp [ cmpType ] as EntityComparisonField < Entity , T > ) ; } return { $or : opts . map ( ( cmpType ) => this . comparisonBuilder . build ( field , cmpType , cmp [ cmpType ] as EntityComparisonField < Entity , T > ) ) , } as mongoose . FilterQuery < Entity > ; } }