import { Clauses } from '../../../core/src' ; import { isNumber , isArray } from 'is-what' ; import { getProp } from 'path-to-prop' ; import { sort , ISortByObjectSorter } from 'fast-sort' ; param { Map < string , Record < string , any > > } collectionDB param { Clauses } clauses returns { Map < string , Record < string , any > > } export function filterDataPerClauses ( collectionDB , clauses ) { const { where = [ ] , orderBy = [ ] , limit } = clauses ; if ( ! where . length && ! orderBy . length && ! isNumber ( limit ) ) return collectionDB ; const entries = [ ] ; collectionDB . forEach ( ( docData , docId ) => { const passesWhereFilters = where . every ( ( whereQuery ) => { const [ fieldPath , operator , expectedValue ] = whereQuery ; const valueAtFieldPath = getProp ( docData , fieldPath ) as any ; let passes = false ; switch ( operator ) { case '==' : passes = valueAtFieldPath == expectedValue ; break ; case '!=' : passes = valueAtFieldPath != expectedValue ; break ; case '<' : passes = valueAtFieldPath < expectedValue ; break ; case '<=' : passes = valueAtFieldPath <= expectedValue ; break ; case '>' : passes = valueAtFieldPath > expectedValue ; break ; case '>=' : passes = valueAtFieldPath >= expectedValue ; break ; case 'in' : passes = isArray ( expectedValue ) && expectedValue . includes ( valueAtFieldPath ) ; break ; case 'not-in' : passes = isArray ( expectedValue ) && ! expectedValue . includes ( valueAtFieldPath ) ; break ; case 'array-contains' : passes = isArray ( valueAtFieldPath ) && valueAtFieldPath . includes ( expectedValue ) ; break ; case 'array-contains-any' : passes = isArray ( valueAtFieldPath ) && valueAtFieldPath . some ( ( v ) => isArray ( expectedValue ) && expectedValue . includes ( v ) ) ; break ; default : throw new Error ( 'invalid operator' ) ; } return passes ; } ) ; if ( ! passesWhereFilters ) return ; entries . push ( [ docId , docData ] ) ; } ) ; const by = orderBy . reduce ( ( carry , [ path , direction = 'asc' ] ) => { const sorter = { [ direction as 'asc' ] : ( entry ) => getProp ( entry [ 1 ] , path ) , } ; carry . push ( sorter ) ; return carry ; } , [ ] as ISortByObjectSorter < [ string , Record < string , any > ] > [ ] ) ; const entriesOrdered = orderBy . length ? sort ( entries ) . by ( by ) : entries ; const entriesLimited = isNumber ( limit ) ? entriesOrdered . slice ( 0 , limit ) : entriesOrdered ; const filteredDataMap = new Map ( entriesLimited ) ; return filteredDataMap ; }