@abaktiar/ql-parser
Version:
Framework-agnostic QL (Query Language) parser and builder for creating complex queries with support for logical operators, parameterized functions, and ORDER BY clauses
238 lines (208 loc) • 6.42 kB
TypeScript
/**
* Count total conditions in an expression
*/
export declare function countConditions(expr: QLExpression): number;
export declare type FieldType = 'text' | 'number' | 'date' | 'datetime' | 'boolean' | 'option' | 'multiselect' | 'user';
/**
* Get all field names used in an expression
*/
export declare function getUsedFields(expr: QLExpression): string[];
/**
* Helper functions to work with QL expressions and convert them to database queries
*/
export declare function isCondition(expr: QLExpression): expr is QLCondition;
export declare function isLogicalGroup(expr: QLExpression): expr is QLLogicalGroup;
export declare type LogicalOperatorType = 'AND' | 'OR' | 'NOT';
export declare type OperatorType = '=' | '!=' | '>' | '<' | '>=' | '<=' | '~' | '!~' | 'IN' | 'NOT IN' | 'IS EMPTY' | 'IS NOT EMPTY' | 'WAS' | 'WAS IN' | 'WAS NOT IN' | 'CHANGED';
export declare interface ParseContext {
input: string;
position: number;
tokens: QLToken[];
currentToken?: QLToken;
expectingField: boolean;
expectingOperator: boolean;
expectingValue: boolean;
expectingLogical: boolean;
parenthesesLevel: number;
inOrderBy: boolean;
lastField?: string;
}
/**
* Pretty print expression for debugging
*/
export declare function printExpression(expr: QLExpression, indent?: number): string;
export declare interface QLCondition {
field: string;
operator: OperatorType;
value?: string | string[];
not?: boolean;
}
export declare type QLExpression = QLCondition | QLLogicalGroup;
/**
* Enhanced QL Expression Parser
* Builds hierarchical expression trees that properly represent logical grouping
*/
export declare class QLExpressionParser {
private tokens;
private position;
parse(tokens: QLToken[]): QLExpression | null;
private parseExpression;
private parseOrExpression;
private parseAndExpression;
private parsePrimaryExpression;
private parseCondition;
private parseValue;
private parseFunctionCall;
private parseInList;
private operatorRequiresValue;
private current;
private advance;
private isLogicalGroup;
}
export declare interface QLField {
name: string;
displayName: string;
type: FieldType;
operators: OperatorType[];
sortable?: boolean;
description?: string;
options?: QLValue[];
asyncValueSuggestions?: boolean;
}
export declare interface QLFunction {
name: string;
displayName: string;
description?: string;
parameters?: {
name: string;
type: FieldType;
required: boolean;
description?: string;
}[];
}
export declare interface QLInputConfig {
fields: QLField[];
functions?: QLFunction[];
operators?: OperatorType[];
logicalOperators?: LogicalOperatorType[];
keywords?: string[];
maxSuggestions?: number;
debounceMs?: number;
caseSensitive?: boolean;
allowParentheses?: boolean;
allowOrderBy?: boolean;
allowFunctions?: boolean;
}
export declare interface QLInputProps {
value?: string;
onChange?: (value: string, query: QLQuery) => void;
onExecute?: (query: QLQuery) => void;
config: QLInputConfig;
placeholder?: string;
disabled?: boolean;
className?: string;
showSearchIcon?: boolean;
showClearIcon?: boolean;
getAsyncValueSuggestions?: (field: string, typedValue: string) => Promise<QLValue[]>;
getPredefinedValueSuggestions?: (field: string) => QLValue[];
}
export declare interface QLInputState {
value: string;
tokens: QLToken[];
suggestions: QLSuggestion[];
showSuggestions: boolean;
selectedSuggestionIndex: number;
cursorPosition: number;
query: QLQuery;
validationErrors: ValidationError[];
isLoading: boolean;
justSelectedSuggestion: boolean;
}
export declare interface QLLogicalGroup {
operator: LogicalOperatorType;
conditions: (QLCondition | QLLogicalGroup)[];
not?: boolean;
}
export declare interface QLOrderBy {
field: string;
direction: SortDirection;
}
export declare class QLParser {
constructor(_config: QLInputConfig);
/**
* Tokenize the input string into QL tokens
*/
tokenize(input: string): QLToken[];
/**
* Classify unknown tokens based on context
*/
private classifyTokens;
/**
* Parse tokens into a QL query object
*/
parse(input: string): QLQuery;
private splitQuery;
private parseOrderBy;
}
export declare interface QLQuery {
where?: QLExpression;
orderBy?: QLOrderBy[];
raw: string;
valid: boolean;
errors: string[];
}
export declare interface QLSuggestion {
type: 'field' | 'operator' | 'value' | 'logical' | 'keyword' | 'function' | 'parenthesis' | 'comma';
value: string;
displayValue?: string;
description?: string;
insertText?: string;
category?: string;
}
export declare interface QLToken {
type: 'field' | 'operator' | 'value' | 'logical' | 'keyword' | 'function' | 'parenthesis' | 'comma' | 'whitespace' | 'unknown';
value: string;
start: number;
end: number;
valid?: boolean;
error?: string;
}
export declare interface QLValue {
value: string;
displayValue?: string;
description?: string;
}
export declare type SortDirection = 'ASC' | 'DESC';
export declare interface SuggestionContext {
input: string;
cursorPosition: number;
tokens: QLToken[];
currentToken?: QLToken;
previousToken?: QLToken;
nextToken?: QLToken;
expectingField: boolean;
expectingOperator: boolean;
expectingValue: boolean;
expectingLogical: boolean;
inOrderBy: boolean;
parenthesesLevel: number;
inInList: boolean;
lastField?: string;
lastOperator?: string;
partialInput?: string;
}
/**
* Convert QL expression to Mongoose query
*/
export declare function toMongooseQuery(expr: QLExpression): any;
/**
* Convert QL expression to SQL WHERE clause
*/
export declare function toSQLQuery(expr: QLExpression): string;
export declare interface ValidationError {
message: string;
start: number;
end: number;
severity: 'error' | 'warning';
}
export { }