import { Builder , CursorDirection , IndexBuilder , ModelInterface , QueryBuilderInterface , QueryTypes } from "./model.interface.js" ; import { RelationBuilder } from "./relation.builder.js" ; import { nestedAttributeValue } from "../utils.js" ; export class QueryBuilder extends RelationBuilder implements QueryBuilderInterface { /**
     * Index filter setting
     */ public indexBuilder : IndexBuilder | null = null ; /**
     * Non indexed columns search settings
     */ public builder : Builder [ ] = [ ] ; /**
     * Search direction and type
     */ public cursor : CursorDirection | null = null ; param indexName param value public whereIndex ( indexName , value ) { this . indexBuilder = { index : indexName , value , type : QueryTypes . Where } ; return this ; } param indexName param values public whereIndexIn ( indexName , values ) { this . indexBuilder = { index : indexName , value : values , type : QueryTypes . WhereIn } ; return this ; } param indexName param values param unique public whereMultiIndexIn ( indexName , values , unique = false ) { this . indexBuilder = { index : indexName , value : values , type : QueryTypes . WhereInArray } ; return this ; } param indexName param value public indexGte ( indexName , value ) { this . indexBuilder = { index : indexName , value , type : QueryTypes . GreaterThanEqual } ; return this ; } param indexName param value public indexGt ( indexName , value ) { this . indexBuilder = { index : indexName , value , type : QueryTypes . GreaterThan } ; return this ; } param indexName param value public indexLte ( indexName , value ) { this . indexBuilder = { index : indexName , value , type : QueryTypes . LessThanEqual } ; return this ; } param indexName param value public indexLt ( indexName , value ) { this . indexBuilder = { index : indexName , value , type : QueryTypes . LessThan } ; return this ; } param indexName param lower param upper public indexBetween ( indexName , lower , upper ) { this . indexBuilder = { index : indexName , value : [ lower , upper ] , type : QueryTypes . Between } ; return this ; } param attributeName param value public where ( attributeName , value ) { this . builder . push ( { attribute : attributeName , value , type : QueryTypes . Where } ) ; return this ; } param attributeName param values public whereIn ( attributeName , values ) { this . builder . push ( { attribute : attributeName , value : values , type : QueryTypes . WhereIn } ) ; return this ; } param attributeName param values param unique public whereInArray ( attributeName , values , unique = false ) { this . builder . push ( { attribute : attributeName , value : values , type : QueryTypes . WhereInArray } ) ; return this ; } param attributeName param value public gte ( attributeName , value ) { this . builder . push ( { attribute : attributeName , value , type : QueryTypes . GreaterThanEqual } ) ; return this ; } param attributeName param value public gt ( attributeName , value ) { this . builder . push ( { attribute : attributeName , value , type : QueryTypes . GreaterThan } ) ; return this ; } param attributeName param value public lte ( attributeName , value ) { this . builder . push ( { attribute : attributeName , value , type : QueryTypes . LessThanEqual } ) ; return this ; } param attributeName param value public lt ( attributeName , value ) { this . builder . push ( { attribute : attributeName , value , type : QueryTypes . LessThan } ) ; return this ; } param attributeName param lower param upper public between ( attributeName , lower , upper ) { this . builder . push ( { attribute : attributeName , value : [ lower , upper ] , type : QueryTypes . Between } ) ; return this ; } public cursorDirection ( direction ) { this . cursor = direction ; return this ; } param indexBuilder public keyRange ( indexBuilder ) { let range ; switch ( indexBuilder . type ) { case QueryTypes . Where : range = IDBKeyRange . only ( indexBuilder . value ) ; break ; case QueryTypes . WhereIn : this . whereIn ( indexBuilder . index , indexBuilder . value ) ; let values = indexBuilder . value . sort ( ) ; range = IDBKeyRange . bound ( values [ 0 ] , values [ values . length - 1 ] , false , false ) ; break ; case QueryTypes . GreaterThanEqual : range = IDBKeyRange . lowerBound ( indexBuilder . value , false ) ; break ; case QueryTypes . GreaterThan : range = IDBKeyRange . lowerBound ( indexBuilder . value , true ) ; break ; case QueryTypes . LessThanEqual : range = IDBKeyRange . upperBound ( indexBuilder . value , false ) ; break ; case QueryTypes . LessThan : range = IDBKeyRange . lowerBound ( indexBuilder . value , true ) ; break ; case QueryTypes . Between : range = IDBKeyRange . bound ( indexBuilder . value [ 0 ] , indexBuilder . value [ 1 ] , false , false ) ; break ; case QueryTypes . WhereInArray : this . whereInArray ( indexBuilder . index , indexBuilder . value ) ; let whereInArrayValues = indexBuilder . value . sort ( ) ; range = IDBKeyRange . bound ( whereInArrayValues [ 0 ] , whereInArrayValues [ whereInArrayValues . length - 1 ] , false , false ) ; break ; default : throw 'Invalid builder type given' ; } return range ; } param result protected allowedToProcess ( result ) { for ( const builder of this . builder ) { switch ( builder . type ) { case QueryTypes . Where : if ( ! nestedAttributeValue ( builder . attribute , result ) === builder . value ) { return false ; } break ; case QueryTypes . WhereIn : let whereInStatus = false ; const resultValue = nestedAttributeValue ( builder . attribute , result ) ; for ( const checkValue of builder . value ) { if ( resultValue === checkValue ) { whereInStatus = true ; break ; } } if ( ! whereInStatus ) { return false ; } break ; case QueryTypes . WhereInArray : let whereInArrayStatus = false ; const resultValues = nestedAttributeValue ( builder . attribute , result ) ; if ( ! ( resultValues instanceof Array ) ) { return false ; } for ( const checkValue of builder . value ) { if ( resultValues . includes ( checkValue ) ) { whereInArrayStatus = true ; break ; } } if ( ! whereInArrayStatus ) { return false ; } break ; case QueryTypes . GreaterThan : if ( nestedAttributeValue ( builder . attribute , result ) <= builder . value ) { return false ; } break ; case QueryTypes . GreaterThanEqual : if ( nestedAttributeValue ( builder . attribute , result ) < builder . value ) { return false ; } break ; case QueryTypes . LessThan : if ( nestedAttributeValue ( builder . attribute , result ) >= builder . value ) { return false ; } break ; case QueryTypes . LessThanEqual : if ( nestedAttributeValue ( builder . attribute , result ) > builder . value ) { return false ; } break ; case QueryTypes . Between : const value = nestedAttributeValue ( builder . attribute , result ) ; if ( builder . value [ 0 ] >= value && builder . value [ 1 ] <= value ) { return false ; } break ; default : throw new Error ( 'Query type not recognized' ) ; } } return true ; } /**
     * Resets the builder values for filtering
     */ public resetBuilder ( ) { this . indexBuilder = null ; this . builder = [ ] ; return this ; } }