diff --git a/src/lib/LogicalIterator.ts b/src/lib/LogicalIterator.ts index dd913c4..9a220d7 100644 --- a/src/lib/LogicalIterator.ts +++ b/src/lib/LogicalIterator.ts @@ -1,21 +1,26 @@ -const OR = '$or'; -const AND = '$and'; -import { isArray, toPairs, uniq} from 'lodash'; +import { isArray, toPairs, uniq } from 'lodash'; +import { Model } from 'objection'; import { debug } from '../config'; // Types -import { Model } from 'objection'; import { Expression, ExpressionValue, PropertyOmissionPredicate, ExpressionObject, - LogicalExpressionIteratorOptions + LogicalExpressionIteratorOptions, + StringFormatter, + LogicalIterator } from './types'; +const OR = '$or'; +const AND = '$and'; + // Typescript type predicate check during runtime // https://stackoverflow.com/questions/12789231/class-type-check-in-typescript -function _isArray(objectOrArray: Object | T[]): objectOrArray is T[] { +function _isArray( + objectOrArray: Record | T[] +): objectOrArray is T[] { return isArray(objectOrArray); } @@ -26,15 +31,21 @@ function _isArray(objectOrArray: Object | T[]): objectOrArray is T[] { * @param {Object|Array} objectOrArray * @returns {Array} */ -function arrayize(objectOrArray: Object | Item[]): Item[] { +function arrayize( + objectOrArray: Record | T[] +): T[] { if (_isArray(objectOrArray)) return objectOrArray; - const tuples = toPairs(objectOrArray) - const objectArray = tuples.map(item => ({ [item[0]]: item[1] })); - return objectArray as Item[]; -}; + const tuples = toPairs(objectOrArray); + const objectArray = tuples.map((item) => ({ [item[0]]: item[1] })); + return objectArray as T[]; +} // Helper function to confirm the rhs Expression is an object of SubExpressions -function hasSubExpression(lhs: string, rhs: ExpressionValue): rhs is ExpressionObject { +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function hasSubExpression( + lhs: string, + rhs: ExpressionValue +): rhs is ExpressionObject { return [OR, AND].includes(lhs); } @@ -54,7 +65,9 @@ export function getPropertiesFromExpression( if (hasSubExpression(lhs, rhs)) { for (const subExpression of arrayize(rhs)) { - properties = properties.concat(getPropertiesFromExpression(subExpression, test)); + properties = properties.concat( + getPropertiesFromExpression(subExpression, test) + ); } } else { if (test(lhs)) properties.push(lhs); @@ -63,7 +76,7 @@ export function getPropertiesFromExpression( } return uniq(properties); -}; +} /** * Returns a function which iterates an object composed of $or/$and operators @@ -84,8 +97,8 @@ export function getPropertiesFromExpression( */ export function iterateLogicalExpression({ onExit, // onExit(propertyOrOperator, value, builder) - onLiteral, // onLiteral(value, builder) -}: LogicalExpressionIteratorOptions) { + onLiteral // onLiteral(value, builder) +}: LogicalExpressionIteratorOptions): LogicalIterator { /** * * @param {Object} expression @@ -93,15 +106,15 @@ export function iterateLogicalExpression({ * @param {Boolean} or * @param {Function} propertyTransform A preOnExit transform for the property name */ - const iterator = function( + const iterator = function ( expression: Expression, builder: M, or = false, - propertyTransform = p => p + propertyTransform: StringFormatter = (p) => p ) { debug('Iterating through', expression); - builder[or ? 'orWhere' : 'where'](subQueryBuilder => { + builder[or ? 'orWhere' : 'where']((subQueryBuilder) => { // Assume equality if the target expression is a primitive if (typeof expression !== 'object') { return onLiteral(expression, subQueryBuilder); @@ -113,7 +126,7 @@ export function iterateLogicalExpression({ if (hasSubExpression(lhs, rhs)) { // Wrap nested conditions in their own scope - subQueryBuilder.where(innerBuilder => { + subQueryBuilder.where((innerBuilder) => { for (const subExpression of arrayize(rhs)) { iterator( subExpression, @@ -133,4 +146,4 @@ export function iterateLogicalExpression({ }; return iterator; -}; +} diff --git a/src/lib/types.ts b/src/lib/types.ts index d138a7f..24a2e61 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,13 +1,10 @@ -import { - QueryBuilder, - Model -} from 'objection'; +import { QueryBuilder, Model } from 'objection'; // Shared types export interface Relation { propertyName: string; relationName: string; - fullyQualifiedProperty: string + fullyQualifiedProperty: string; } export type Primitive = number | string | null; @@ -25,7 +22,7 @@ type OperationHandler = ( export type Operators = { [f: string]: OperationHandler; -} +}; export type AggregationCallback = ( RelatedModelClass: K @@ -46,13 +43,15 @@ export type ExpressionValue = Expression | string | number; export type ExpressionObject = { [key: string]: ExpressionValue; }; -export type Expression = ExpressionObject | ExpressionObject[] | string | number; -export type PropertyOmissionPredicate = ( - propertyName?: string -) => boolean; +export type Expression = + | ExpressionObject + | ExpressionObject[] + | string + | number; +export type PropertyOmissionPredicate = (propertyName?: string) => boolean; export type Item = { - [x: string]: any; + [x: string]: unknown; }; export type LogicalIteratorExitFunction = ( @@ -97,8 +96,17 @@ export interface AggregationConfig { // Filter definition export type EagerExpression = { - $where?: Expression, - $aggregations?: AggregationConfig[] -} + $where?: Expression; + $aggregations?: AggregationConfig[]; +}; + +export type RequireExpression = Expression; -export type RequireExpression = Expression; \ No newline at end of file +export type StringFormatter = (s: string) => string; + +export type LogicalIterator = ( + expression: Expression, + builder: QueryBuilder, + or?: boolean, + propertyTransform?: StringFormatter +) => void;