2021-06-02 01:59:40 +00:00
|
|
|
/**
|
|
|
|
* Type representing a valid where operator.
|
|
|
|
*/
|
|
|
|
type WhereOperator = '&' | '>' | '>=' | '<' | '<=' | '!=' | '<=>' | '%' | '|' | '!' | '~' | '=' | '^'
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type associating search items with a key.
|
|
|
|
*/
|
|
|
|
type AssociatedSearchItem = { key: any, item: any }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type representing the result of a where.
|
|
|
|
*/
|
|
|
|
type WhereResult = any[]
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if the given item satisfies the given where clause.
|
|
|
|
* @param {AssociatedSearchItem} item
|
|
|
|
* @param {WhereOperator} operator
|
|
|
|
* @param [operand]
|
|
|
|
* @return boolean
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
const whereMatch = (item: AssociatedSearchItem, operator: WhereOperator, operand?: unknown): boolean => {
|
2021-06-02 01:59:40 +00:00
|
|
|
switch ( operator ) {
|
2021-06-03 03:36:25 +00:00
|
|
|
case '&':
|
|
|
|
if ( item.key & Number(operand) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '>':
|
|
|
|
if ( item.key > (operand as any) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '>=':
|
|
|
|
if ( item.key >= (operand as any) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '<':
|
|
|
|
if ( item.key < (operand as any) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '<=':
|
|
|
|
if ( item.key <= (operand as any) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '!=':
|
|
|
|
if ( item.key !== (operand as any) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '<=>':
|
|
|
|
if ( item.key === operand && typeof item.key !== 'undefined' && item.key !== null ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '%':
|
|
|
|
if ( item.key % Number(operand) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '|':
|
|
|
|
if ( item.key | Number(operand) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '!':
|
|
|
|
if ( !item.key ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '~':
|
|
|
|
if ( ~item.key ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '=':
|
|
|
|
if ( item.key === operand ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case '^':
|
|
|
|
if ( item.key ^ Number(operand) ) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
break
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Apply the given where clause to the items and return those that match.
|
|
|
|
* @param {Array<AssociatedSearchItem>} items
|
|
|
|
* @param {WhereOperator} operator
|
|
|
|
* @param [operand]
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
const applyWhere = (items: AssociatedSearchItem[], operator: WhereOperator, operand?: unknown): WhereResult => {
|
2021-06-02 01:59:40 +00:00
|
|
|
const matches: WhereResult = []
|
|
|
|
for ( const item of items ) {
|
2021-06-03 03:36:25 +00:00
|
|
|
if ( whereMatch(item, operator, operand) ) {
|
2021-06-02 01:59:40 +00:00
|
|
|
matches.push(item.item)
|
2021-06-03 03:36:25 +00:00
|
|
|
}
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return matches
|
|
|
|
}
|
|
|
|
|
|
|
|
export { WhereOperator, WhereResult, AssociatedSearchItem, applyWhere, whereMatch }
|