import { ComplexExpression, BinaryExpression } from "./Expression"; import { EXPRESSION_TYPE } from "./constants"; /** * A fluent API operation for creating a filter for a query by chaining different rules. */ export class WhereQuery { private expression: ComplexExpression; constructor(private parent: QueryType, type: string = EXPRESSION_TYPE.and) { this.expression = new ComplexExpression(type, []); } /** * Adds an `and` clause to the current condition and returns it for further chaining. */ and(): WhereQuery> { return new WhereQuery(this, EXPRESSION_TYPE.and); } /** * Adds an `or` clause to the current condition and returns it for further chaining. */ or(): WhereQuery> { return new WhereQuery(this, EXPRESSION_TYPE.or); } /** * Adds an `any` clause to the current condition and returns it for further chaining. */ any(): WhereQuery> { return new WhereQuery(this, EXPRESSION_TYPE.any); } /** * Adds a `not` clause to the current condition and returns it for further chaining. */ not(): WhereQuery> { return new WhereQuery(this, EXPRESSION_TYPE.not); } /** * Adds a condition that a field must be equal to a specific value. */ eq(parameter: string, constant: any): WhereQuery { return this.simple(EXPRESSION_TYPE.eq, parameter, constant); } /** * Adds a condition that a field must *not* be equal to a specific value. */ ne(parameter: string, constant: any): WhereQuery { return this.simple(EXPRESSION_TYPE.ne, parameter, constant); } /** * Adds a condition that a field must be `greater than` a certain value. Applicable to Number, String, and Date fields. */ gt(parameter: string, constant: any) { return this.simple(EXPRESSION_TYPE.gt, parameter, constant); } /** * Adds a condition that a field must be `greater than or equal` to a certain value. Applicable to Number, String, and Date fields. */ gte(parameter: string, constant: any) { return this.simple(EXPRESSION_TYPE.ge, parameter, constant); } /** * Adds a condition that a field must be `less than` a certain value. Applicable to Number, String, and Date fields. */ lt(parameter: string, constant: any) { return this.simple(EXPRESSION_TYPE.lt, parameter, constant); } /** * Adds a condition that a field must be `less than or equal` to a certain value. Applicable to Number, String, and Date fields. */ lte(parameter: string, constant: any) { return this.simple(EXPRESSION_TYPE.le, parameter, constant); } /** * Adds a condition that a field value must *start* with a specified string. */ startsWith(parameter: string, constant: any, caseSensitive = true) { return this.simple(EXPRESSION_TYPE.startsWith, parameter, constant, caseSensitive); } /** * Adds a condition that a field value must *contain* a specified string. */ contains(parameter: string, constant: any, caseSensitive = true) { return this.simple(EXPRESSION_TYPE.contains, parameter, constant, caseSensitive); } /** * Adds a condition that a field value must *end* with a specified string. */ endsWith(parameter: string, constant: any, caseSensitive = true) { return this.simple(EXPRESSION_TYPE.endsWith, parameter, constant, caseSensitive); } /** * Adds a condition that specific values should be found in that field e.g. Id in (id1, id2, id3). */ in(parameter: string, constant: any) { return this.simple(EXPRESSION_TYPE.in, parameter, constant); } /** * Ends the definition of the current WhereQuery. You need to call this method in order to continue with the definition of the parent {@link Query}. All other `WhereQuery` methods return the current instance of `WhereQuery` to allow chaining. */ done(): QueryType { if (this.parent instanceof WhereQuery) { this.parent.addComplexExpression(this); // TODO: If has and() || or() must call done() twice if (this.expression.getType() === EXPRESSION_TYPE.not) return this.parent; } return this.parent; } getExpression(): ComplexExpression { return this.expression; } private simple(type: string, parameter: string, constant: any, caseSensitive = true): WhereQuery { const currentExpr = new BinaryExpression(type, parameter, constant, caseSensitive); const subExpressions = this.expression.getExpressions(); subExpressions.push(currentExpr); if (this.expression.getType() === EXPRESSION_TYPE.not && subExpressions.length > 1) throw new Error("Invalid operators count!"); return this; } private addComplexExpression(subQuery: WhereQuery): void { const subExpression = subQuery.getExpression(); this.expression.getExpressions().push(subExpression); } }