import { ComplexQueryExpression } from './api/ComplexQueryLang.js'; import '@arcgis/core/geometry/Geometry'; /** * Callback method that is triggered while walking over an AST. * @internal */ type VisitCallback = (node: ASTNode, walker: Walker, childIndex: number, childrenCount: number) => void; /** * Callback method that is triggered while walking over child nodes on an AST. * @internal */ type ChildVisitCallback = (node: ASTNode, childIndex: number, childrenCount: number) => void; /** * Encoder that transforms an AST. * @typeParam T result type of the encoder. * @internal */ interface Encoder { /** Method that is called for each AST node. Children are visited first. */ (node?: ASTNode, queryOptions?: ComplexQueryOptions, subResults?: T[], operator?: OperatorImpl): T; /** Optional method that is called before children are visited. */ pre?(node: ASTNode, queryOptions: ComplexQueryOptions, subResults: T[], operator: OperatorImpl): void; } /** * Helper to analyze an AST. */ interface Walker { /** Root of the AST */ ROOT: ASTNode; /** Global query options. */ queryOptions: ComplexQueryOptions; /** All parents of the current node. */ parents: ASTNode[]; /** Index of the current node in the parent's children. */ currentIndex: number; /** Current ASTNode. */ current: ASTNode; /** Function to move the walker to the next sibling. */ toNextSibling(): Walker | undefined; /** Function to move the walker to the previous sibling. */ toPrevSibling(): Walker | undefined; /** Function to move the walker to a sibling with an offset relative to the current position. */ toSibling(offsetFromCurrentPosition: number): Walker | undefined; /** Function to pick a sibling at an offset relative to the current position. */ sibling(offsetFromCurrentPosition: number): ASTNode | undefined; /** Function to check if the next sibling exists. */ hasNextSibling(): boolean; /** Function to check if the previous sibling exists. */ hasPrevSibling(): boolean; /** Function to move the walker to the first child. */ toFirstChild(): Walker | undefined; /** Function to move the walker to the last child. */ toLastChild(): Walker | undefined; /** Function to move the walker to the child at a given index. */ toChild(childIndex: number): Walker | undefined; /** Function to pick the child at a given index. */ child(childIndex: number): ASTNode | undefined; /** Function to check if the child at a given index exists. */ hasChild(childIndex: number): boolean; /** Function to check if the current node has children. */ hasChildren(): boolean; /** Function to move the walker to the current parent. */ toParent(): Walker | undefined; /** Function to check if the current node has a parent. */ hasParent(): boolean; /** Function to move the walker to an ancestor with given an offset. e.g. 1=direct parent, 2 = grandparent, ... */ toAncestor(offset: number): Walker | undefined; /** Function to move the walker to the AST root. */ toROOT(): Walker; /** Function to pick the parent of the current node. */ parent(): ASTNode | undefined; /** Function to pick the child nodes of the current node. */ children(): ASTNode[]; /** Function to get the number of children of the current node. */ childrenCount(): number; /** Function to check if a given node is the root of the AST. * If no parameter is provided, this function will test if the walker is at the root position of the AST. */ isROOT(node?: ASTNode): boolean; /** Function to create a new walker at the current node position. */ walker(): Walker; /** Function to walk over all children. */ walkChildren(cb: ChildVisitCallback, scope?: any): void; /** Function to walk over the AST. * The visitor callback is called once for every node. * Parents are visited before the children. */ walkPreOrder(cb: VisitCallback, scope?: any): void; /** Function to walk over the AST. * The visitor callback is called once for every node. * Parents are visited after the children. */ walkPostOrder(cb: VisitCallback, scope?: any): void; /** Function to walk over the AST. * The visitor callback is called twice for every node. */ walk(cb: VisitCallback, scope?: any): void; } /** * Node in the AST. */ interface ASTNode { /** Name of the operator. */ o: string; /** Child nodes of this node. */ c?: ASTNode[]; /** Name of the left side attribute of the operator. */ n?: string; /** Value of the right side of the operator. Can be an array of values. */ v?: any; /** Value type (typeof v). Is an array if 'v' is an array, too. */ vt?: string[] | string; /** Indicate, if 'v' is an array. */ isArray?: boolean; } /** * Options used to modify a query or evaluation. */ interface ComplexQueryOptions { [k: string]: any; ignoreCase?: boolean; suggestContains?: boolean; } /** * AST representation of a complex query. */ interface AST { /** * Query options used to parse the query. */ queryOptions: ComplexQueryOptions; /** * Function to provide access to the root node. */ root(): ASTNode | undefined; /** * Function to create a walker for easier visiting of nodes in the AST. */ walker(): Walker; /** * Function to be called after modification of the AST to reduce * useless '$and' or '$or' operators. * @returns the optimized AST (not a copy!) */ optimize(): AST; } /** * Helper to create a walker for a given ast node. * @param root root node of walker * @param queryOpts queryoptions * @returns a Walker */ declare function walkerForASTNode(root: ASTNode, queryOpts?: ComplexQueryOptions): Walker; type Thing = any; type ResolveCallback = (item: Thing, path: string) => any; type Processor = (item: Thing, resolve: ResolveCallback) => boolean; interface OperatorImpl { types: Record; parent?: boolean; values?: boolean; clearName?: boolean; convert?: (type: string, value: any) => any; optimize?: (node: ASTNode, walker: Walker) => void; evaluate(astNode: ASTNode, queryOptions: ComplexQueryOptions, subProcessors?: Processor[]): Processor; } interface OperatorChain { chain: string[]; } type OperatorHelper = (...arg: any) => any; declare class Parser { readonly operators: Record; private _ast; private _qopts; private _q; private _nstack; private _names; private _deep; constructor(query?: ComplexQueryExpression, queryOptions?: ComplexQueryOptions); parse(): AST; private _parse; private _visit; } /** * Interpreter and test engine for ComplexQueryExpressions. * * @example * import ComplexQuery from "store-api/ComplexQuery"; * * const query = { * $and : [{ * a : { * $eqw: "test*" * }, * $or : [{ x : { $lt : 1 }}, * { x : { $gt : 2 }}] * }] * } * const options = {}; * * const cq = ComplexQuery.parse(query, options); * * const astRootNode = cq.ast.root(); * * // the ast root node is an object structure like this: * const expectedRootNode = { * o : "$and", * c : [{ * o : "$eqw", * n : "a", * v : "test*" * }, * { * o : "$or", * c : [{ * o : $lt, * n : "x", * v : 1 * },{ * o : $gt, * n : "x", * v : 2 * }] * }] * } */ declare class ComplexQuery { /** * Internally used Parser. * Exported to allow new operations. * To add a new operator use: * ```ts * ComplexQuery.Parser.prototype.operators[] = * ``` */ static Parser: typeof Parser; /** * Normalized syntax tree of the query. */ ast: AST; private constructor(); /** * Factory method to create a ComplexQuery. */ static parse(query?: ComplexQueryExpression, queryOptions?: ComplexQueryOptions): ComplexQuery; /** * Function to test if a given query is a complex query. * @param query expression * @param queryOptions options * @returns true if the expression is a complex query, otherwise false. */ static isComplexQuery(query: any, queryOptions?: ComplexQueryOptions): boolean; /** * Function to find matching ASTNodes in the AST. * @param query query to parse * @param queryOptions query options * @param operatorName name of operator to find * @param propertyName name of property referenced by the operator * @returns array of matching ASTNodes or an empty array if nothing is found. */ static findOperators(query: ComplexQueryExpression, queryOptions: ComplexQueryOptions | undefined, operatorName: string, propertyName?: string): ASTNode[]; /** * Function to test if an operator is used within a given query. * @param query a complex query expression * @param queryOptions query options * @param operatorName name of operator to find * @param propertyName name of property referenced by the operator * @returns true if the operator is detected in the query. */ static usesOperator(query: ComplexQueryExpression, queryOptions: ComplexQueryOptions | undefined, operatorName: string, propertyName?: string): boolean; /** * Function to encode the AST back into a ComplexQuery object literal. */ encode(): ComplexQueryExpression; /** * Function to test if an item fulfills the conditions of the parsed query. */ test(item: Thing): boolean; /** * Function to encode the AST or a part of it with a custom encoder. * @param encoder function which allows the conversion of the AST into another type. * @param walkerOrAst a Walker or AST instance. If not provided the parsed AST is used. * @returns output of the encoder. */ encodePostOrder(encoder: Encoder, walkerOrAst?: Walker | AST): any; private _createMemoryEngine; } /** * Function to encode the AST or a part of it with a custom encoder. * @param encoder function which allows the conversion of the AST into another type. * @param walkerOrAst a Walker or AST instance. If not provided the parsed AST is used. * @returns output of the encoder. */ declare function encodePostOrder(encoder: Encoder, walkerOrAst: Walker | AST): any; export { ComplexQuery, ComplexQuery as default, encodePostOrder, walkerForASTNode }; export type { AST, ASTNode, ChildVisitCallback, ComplexQueryOptions, Encoder, OperatorChain, OperatorImpl, VisitCallback, Walker };