class param { queryString } query param { query } query returns { query } export class APIfeatures { queryString : { [ key ] : string ; } ; query : any ; constructor ( query , queryString ) { this . query = query ; this . queryString = queryString ; } filter ( ) { const queryObj = { ... this . queryString } ; const excludedFields = [ 'page' , 'sort' , 'limit' , 'fields' ] ; excludedFields . forEach ( ( el ) => delete queryObj [ el ] ) ; let queryStr = JSON . stringify ( queryObj ) ; queryStr = queryStr . replace ( /\b(gte|gt|lte|lt)\b/g , ( match ) => `$${ match }` ) ; this . query = this . query . find ( JSON . parse ( queryStr ) ) ; if ( queryObj . model ) { const filterByModel = { model : { $regex : queryObj . model , $options : 'i' } , } ; this . query = this . query . find ( filterByModel ) ; } return this ; } sort ( ) { if ( this . queryString . sort ) { const sortBy = this . queryString . sort . split ( ',' ) . join ( ' ' ) ; this . query = this . query . sort ( sortBy ) ; } else { this . query . sort ( '-createdAt' ) ; } return this ; } limitFields ( ) { if ( this . queryString . fields ) { const fields = this . queryString . fields . split ( ',' ) . join ( ' ' ) ; this . query = this . query . select ( fields ) ; } else { this . query = this . query . select ( '-__v' ) ; } return this ; } paginate ( ) { const page = Number ( this . queryString . page ) || 1 ; const limit = Number ( this . queryString . limit ) || 10 ; const skip = ( page - 1 ) * limit ; this . query = this . query . skip ( skip ) . limit ( limit ) ; return this ; } }