UNPKG

@webda/core

Version:

Expose API with Lambda

391 lines (390 loc) 11.8 kB
import { AbstractParseTreeVisitor, ParseTree } from "antlr4ts/tree/index.js"; import { WebdaQLLexer } from "./WebdaQLLexer.js"; import { AndLogicExpressionContext, BinaryComparisonExpressionContext, BooleanLiteralContext, ContainsExpressionContext, InExpressionContext, IntegerLiteralContext, LikeExpressionContext, LimitExpressionContext, OffsetExpressionContext, OrLogicExpressionContext, OrderExpressionContext, OrderFieldExpressionContext, SetExpressionContext, StringLiteralContext, WebdaqlContext } from "./WebdaQLParserParser.js"; import { WebdaQLParserVisitor } from "./WebdaQLParserVisitor.js"; type value = boolean | string | number; /** * Meta Query Language * * */ export declare namespace WebdaQL { interface OrderBy { field: string; direction: "ASC" | "DESC"; } function PrependCondition(query?: string, condition?: string): string; /** * Create Expression based on the parsed token * * Expression allow to optimize and split between Query and Filter */ class ExpressionBuilder extends AbstractParseTreeVisitor<Query> implements WebdaQLParserVisitor<any> { /** * Contain the parsed limit */ limit: number; /** * Contain the parsed offset */ offset: string; orderBy: OrderBy[]; /** * Default result for the override * @returns */ protected defaultResult(): Query; /** * Get offset * @returns */ getOffset(): string; /** * Get limit * @returns */ getLimit(): number; /** * Read the limit * @param ctx */ visitLimitExpression(ctx: LimitExpressionContext): void; /** * Read the offset if provided * @param ctx */ visitOffsetExpression(ctx: OffsetExpressionContext): void; /** * Visit a order field expression */ visitOrderFieldExpression(ctx: OrderFieldExpressionContext): OrderBy; /** * Read the order by values */ visitOrderExpression(ctx: OrderExpressionContext): void; /** * Return only AndExpression * @param ctx * @returns */ visitWebdaql(ctx: WebdaqlContext): Query; /** * Simplify Logic expression and regroup them * @param ctx * @returns */ getComparison(ctx: AndLogicExpressionContext | OrLogicExpressionContext): any[]; /** * Get the AndExpression, regrouping all the parameters * * By default the parser is doing a AND (b AND (c AND d)) creating 3 depth expressions * This visitor simplify to a AND b AND c AND d with only one Expression */ visitAndLogicExpression(ctx: AndLogicExpressionContext): AndExpression; /** * Implement the BinaryComparison with all methods managed */ visitBinaryComparisonExpression(ctx: BinaryComparisonExpressionContext): ComparisonExpression<ComparisonOperator>; /** * Visit each value of the [..., ..., ...] set */ visitSetExpression(ctx: SetExpressionContext): value[]; /** * a LIKE "%A?" * @param ctx * @returns */ visitLikeExpression(ctx: LikeExpressionContext): ComparisonExpression<"LIKE">; /** * Map the a IN ['b','c'] */ visitInExpression(ctx: InExpressionContext): ComparisonExpression<"IN">; /** * Map the a CONTAINS 'b' */ visitContainsExpression(ctx: ContainsExpressionContext): ComparisonExpression<"CONTAINS">; /** * Get the OrExpression, regrouping all the parameters * * By default the parser is doing a OR (b OR (c OR d)) creating 3 depth expressions * This visitor simplify to a OR b OR c OR d with only one Expression */ visitOrLogicExpression(ctx: OrLogicExpressionContext): OrExpression; /** * Read the string literal (removing the simple or double bracket) */ visitStringLiteral(ctx: StringLiteralContext): string; /** * Read the boolean literal */ visitBooleanLiteral(ctx: BooleanLiteralContext): boolean; /** * Read the number literal */ visitIntegerLiteral(ctx: IntegerLiteralContext): number; } /** * Represent a full Query */ interface Query { /** * Filtering part of the expression */ filter: Expression; /** * Limit value */ limit?: number; /** * Offset value */ continuationToken?: string; /** * Order by clause */ orderBy?: OrderBy[]; /** * Get the string representation of the query */ toString(): string; } /** * Represent the query expression or subset */ abstract class Expression<T = string> { operator: T; constructor(operator: T); /** * Evaluate the expression for the target object * @param target to evaluate */ abstract eval(target: any): boolean; /** * Return the representation of the expression * @param depth */ abstract toString(depth?: number): string; } type ComparisonOperator = "=" | "<=" | ">=" | "<" | ">" | "!=" | "LIKE" | "IN" | "CONTAINS"; /** * Comparison expression */ class ComparisonExpression<T extends ComparisonOperator = ComparisonOperator> extends Expression<T> { /** * Right side of the comparison */ value: value | value[]; /** * Attribute to read from the object (split by .) */ attribute: string[]; /** * * @param operator of the expression * @param attribute of the object to read * @param value */ constructor(operator: T, attribute: string, value: value | any[]); static likeToRegex(like: string): RegExp; /** * Read the value from the object * * @param target * @returns */ static getAttributeValue(target: any, attribute: string[]): any; /** * Set the value of the attribute based on the assignment * * If used as a Set expression * @param target */ setAttributeValue(target: any): void; /** * @override */ eval(target: any): boolean; /** * Return a string represantation of a value */ toStringValue(value: value | value[]): string; /** * Allow subclass to create different display */ toStringAttribute(): string; /** * Allow subclass to create different display */ toStringOperator(): T; /** * @override */ toString(): string; } /** * Abstract logic expression (AND|OR) * * Could add XOR in the future */ abstract class LogicalExpression<T> extends Expression<T> { /** * Contains the members of the logical expression */ children: Expression[]; /** * * @param operator * @param children */ constructor(operator: T, children: Expression[]); /** * @override */ toString(depth?: number): string; } /** * AND Expression implementation */ class AndExpression extends LogicalExpression<"AND"> { /** * @param children Expressions to use for AND */ constructor(children: Expression[]); /** * @override */ eval(target: any): boolean; } /** * OR Expression implementation */ class OrExpression extends LogicalExpression<"OR"> { /** * @param children Expressions to use for OR */ constructor(children: Expression[]); /** * @override */ eval(target: any): boolean; } /** * */ class QueryValidator { protected sql: string; protected lexer: WebdaQLLexer; protected tree: WebdaqlContext; protected query: Query; protected builder: ExpressionBuilder; constructor(sql: string, builder?: ExpressionBuilder); hasCondition(): boolean; toString(): string; merge(query: string, type?: "OR" | "AND"): this; /** * Get offset * @returns */ getOffset(): string; /** * Get limit * @returns */ getLimit(): number; /** * Get the expression by itself * @returns */ getExpression(): Expression; /** * Retrieve parsed query * @returns */ getQuery(): Query; /** * Verify if a target fit the expression * @param target * @returns */ eval(target: any): boolean; /** * Display parse tree back as query * @param tree * @returns */ displayTree(tree?: ParseTree): string; } /** * For now reuse same parser */ class SetterValidator extends QueryValidator { constructor(sql: string); eval(target: any): boolean; assign(target: any, expression: Expression): void; } class PartialValidator extends QueryValidator { builder: PartialExpressionBuilder; constructor(query: string, builder?: PartialExpressionBuilder); /** * Eval the query * @param target * @param partial * @returns */ eval(target: any, partial?: boolean): boolean; /** * Return if the result ignored some fields * @returns */ wasPartialMatch(): boolean; } class PartialComparisonExpression<T extends ComparisonOperator = ComparisonOperator> extends ComparisonExpression<T> { protected builder: PartialExpressionBuilder; constructor(builder: PartialExpressionBuilder, op: T, attribute: string, value: any); /** * Override the eval to check if the attribute is present * if not and we are in partial mode, return true * * @param target * @returns */ eval(target: any): boolean; } class PartialExpressionBuilder extends ExpressionBuilder { /** * Enforce the partial mode */ partial: boolean; /** * If eval was called in partial mode */ partialMatch: boolean; setPartial(partial: boolean): void; setPartialMatch(partial: boolean): void; /** * a LIKE "%A?" * @param ctx * @returns */ visitLikeExpression(ctx: any): PartialComparisonExpression<"LIKE">; /** * Implement the BinaryComparison with all methods managed */ visitBinaryComparisonExpression(ctx: any): PartialComparisonExpression<any>; /** * Map the a IN ['b','c'] */ visitInExpression(ctx: any): PartialComparisonExpression<"IN">; /** * Map the a CONTAINS 'b' */ visitContainsExpression(ctx: any): PartialComparisonExpression<"CONTAINS">; } /** * Remove artifact from sanitize-html inside query * @param query * @returns */ function unsanitize(query: string): string; } export {};