@webda/ql 4.0.0-beta.2 → 4.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -2
- package/lib/WebdaQLLexer.d.ts +19 -13
- package/lib/WebdaQLLexer.d.ts.map +1 -1
- package/lib/WebdaQLLexer.js +305 -252
- package/lib/WebdaQLLexer.js.map +1 -1
- package/lib/WebdaQLParserLexer.d.ts +19 -13
- package/lib/WebdaQLParserLexer.d.ts.map +1 -1
- package/lib/WebdaQLParserLexer.js +305 -252
- package/lib/WebdaQLParserLexer.js.map +1 -1
- package/lib/WebdaQLParserListener.d.ts +89 -3
- package/lib/WebdaQLParserListener.d.ts.map +1 -1
- package/lib/WebdaQLParserListener.js +1 -1
- package/lib/WebdaQLParserListener.js.map +1 -1
- package/lib/WebdaQLParserParser.d.ts +83 -22
- package/lib/WebdaQLParserParser.d.ts.map +1 -1
- package/lib/WebdaQLParserParser.js +790 -290
- package/lib/WebdaQLParserParser.js.map +1 -1
- package/lib/WebdaQLParserVisitor.d.ts +65 -2
- package/lib/WebdaQLParserVisitor.d.ts.map +1 -1
- package/lib/WebdaQLParserVisitor.js +1 -1
- package/lib/WebdaQLParserVisitor.js.map +1 -1
- package/lib/bind.d.ts +29 -0
- package/lib/bind.d.ts.map +1 -0
- package/lib/bind.js +139 -0
- package/lib/bind.js.map +1 -0
- package/lib/bind.spec.d.ts +2 -0
- package/lib/bind.spec.d.ts.map +1 -0
- package/lib/bind.spec.js +206 -0
- package/lib/bind.spec.js.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -0
- package/lib/query.d.ts +395 -76
- package/lib/query.d.ts.map +1 -1
- package/lib/query.js +562 -91
- package/lib/query.js.map +1 -1
- package/lib/query.spec.js +593 -195
- package/lib/query.spec.js.map +1 -1
- package/lib/webdaql-string.d.ts +59 -0
- package/lib/webdaql-string.d.ts.map +1 -0
- package/lib/webdaql-string.js +112 -0
- package/lib/webdaql-string.js.map +1 -0
- package/lib/webdaql-string.spec.d.ts +2 -0
- package/lib/webdaql-string.spec.d.ts.map +1 -0
- package/lib/webdaql-string.spec.js +282 -0
- package/lib/webdaql-string.spec.js.map +1 -0
- package/package.json +34 -42
package/lib/query.d.ts
CHANGED
|
@@ -1,76 +1,123 @@
|
|
|
1
1
|
import { AbstractParseTreeVisitor, ParseTree } from "antlr4ts/tree/index.js";
|
|
2
2
|
import { WebdaQLLexer } from "./WebdaQLLexer.js";
|
|
3
|
-
import { AndLogicExpressionContext, BinaryComparisonExpressionContext, BooleanLiteralContext, ContainsExpressionContext, InExpressionContext, IntegerLiteralContext, LikeExpressionContext, LimitExpressionContext, OffsetExpressionContext, OrLogicExpressionContext, OrderExpressionContext, OrderFieldExpressionContext, SetExpressionContext, StringLiteralContext, WebdaqlContext } from "./WebdaQLParserParser.js";
|
|
3
|
+
import { AndLogicExpressionContext, AtomExpressionContext, BinaryComparisonExpressionContext, BooleanLiteralContext, ContainsExpressionContext, InExpressionContext, IntegerLiteralContext, IsNotNullExpressionContext, IsNullExpressionContext, LikeExpressionContext, LimitExpressionContext, NumberLiteralContext, OffsetExpressionContext, OrLogicExpressionContext, OrderExpressionContext, OrderFieldExpressionContext, ParameterContext, SetExpressionContext, StringLiteralContext, WebdaqlContext } from "./WebdaQLParserParser.js";
|
|
4
4
|
import { WebdaQLParserVisitor } from "./WebdaQLParserVisitor.js";
|
|
5
|
+
/**
|
|
6
|
+
* Primitive value types supported by WebdaQL expressions
|
|
7
|
+
*/
|
|
5
8
|
type value = boolean | string | number;
|
|
6
9
|
/**
|
|
7
|
-
*
|
|
10
|
+
* Strip the quotes of a WebdaQL string literal and unescape its contents.
|
|
8
11
|
*
|
|
12
|
+
* Processes the inner text (between outer quotes) with these rules, applied left-to-right:
|
|
13
|
+
* - `\\` → `\` (escaped backslash)
|
|
14
|
+
* - `\` followed by the literal's quote char → the quote char (backslash-escaped quote)
|
|
15
|
+
* - the quote char doubled → one quote char (SQL-style doubled quote)
|
|
16
|
+
* - any other `\x` → `\x` kept verbatim (so LIKE's `\%` and `\_` reach likeToRegex unchanged)
|
|
9
17
|
*
|
|
18
|
+
* @param literal - the literal including its surrounding quotes
|
|
19
|
+
* @returns the literal value
|
|
20
|
+
*/
|
|
21
|
+
export declare function unescapeStringLiteral(literal: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Represents a single ORDER BY clause field with its sort direction
|
|
10
24
|
*/
|
|
11
25
|
export interface OrderBy {
|
|
26
|
+
/** Field name (supports dot-notation for nested attributes) */
|
|
12
27
|
field: string;
|
|
28
|
+
/** Sort direction */
|
|
13
29
|
direction: "ASC" | "DESC";
|
|
14
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Prepend a condition to an existing query string using AND logic
|
|
33
|
+
*
|
|
34
|
+
* Parses both strings, merges them, and reconstructs the combined query.
|
|
35
|
+
* ORDER BY, LIMIT, and OFFSET clauses from the original query are preserved.
|
|
36
|
+
*
|
|
37
|
+
* @param query - existing query string (may include ORDER BY / LIMIT / OFFSET)
|
|
38
|
+
* @param condition - condition to prepend (filter expression only)
|
|
39
|
+
* @returns merged query string
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* PrependCondition("status = 'active' ORDER BY name LIMIT 10", "age > 18")
|
|
44
|
+
* // => 'status = "active" AND age > 18 ORDER BY name LIMIT 10'
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
15
47
|
export declare function PrependCondition(query?: string, condition?: string): string;
|
|
16
48
|
/**
|
|
17
|
-
*
|
|
49
|
+
* ANTLR parse tree visitor that builds an optimized Expression AST from the parsed tokens
|
|
18
50
|
*
|
|
19
|
-
*
|
|
51
|
+
* Converts the ANTLR parse tree into a flat, evaluatable expression tree.
|
|
52
|
+
* Automatically flattens nested AND/OR expressions of the same type to reduce depth.
|
|
20
53
|
*/
|
|
21
54
|
export declare class ExpressionBuilder extends AbstractParseTreeVisitor<Query> implements WebdaQLParserVisitor<any> {
|
|
22
55
|
/**
|
|
23
|
-
*
|
|
56
|
+
* Parsed LIMIT value, if present
|
|
24
57
|
*/
|
|
25
58
|
limit: number;
|
|
26
59
|
/**
|
|
27
|
-
*
|
|
60
|
+
* Parsed OFFSET continuation token, if present
|
|
28
61
|
*/
|
|
29
62
|
offset: string;
|
|
63
|
+
/**
|
|
64
|
+
* Parsed ORDER BY clauses, if present
|
|
65
|
+
*/
|
|
30
66
|
orderBy: OrderBy[];
|
|
31
67
|
/**
|
|
32
|
-
* Default result
|
|
33
|
-
* @returns
|
|
68
|
+
* Default result when no expression is matched (empty AND, always true)
|
|
69
|
+
* @returns an empty AND query
|
|
34
70
|
*/
|
|
35
71
|
protected defaultResult(): Query;
|
|
36
72
|
/**
|
|
37
|
-
* Get
|
|
38
|
-
* @returns
|
|
73
|
+
* Get parsed OFFSET continuation token
|
|
74
|
+
* @returns the offset token
|
|
39
75
|
*/
|
|
40
76
|
getOffset(): string;
|
|
41
77
|
/**
|
|
42
|
-
* Get
|
|
43
|
-
* @returns
|
|
78
|
+
* Get parsed LIMIT value
|
|
79
|
+
* @returns the limit value
|
|
44
80
|
*/
|
|
45
81
|
getLimit(): number;
|
|
46
82
|
/**
|
|
47
|
-
*
|
|
48
|
-
* @param ctx
|
|
83
|
+
* Visit a LIMIT clause and store the integer value
|
|
84
|
+
* @param ctx - the limit expression context
|
|
49
85
|
*/
|
|
50
86
|
visitLimitExpression(ctx: LimitExpressionContext): void;
|
|
51
87
|
/**
|
|
52
|
-
*
|
|
53
|
-
* @param ctx
|
|
88
|
+
* Visit an OFFSET clause and store the string continuation token
|
|
89
|
+
* @param ctx - the offset expression context
|
|
54
90
|
*/
|
|
55
91
|
visitOffsetExpression(ctx: OffsetExpressionContext): void;
|
|
56
92
|
/**
|
|
57
93
|
* Visit a order field expression
|
|
94
|
+
* @param ctx - the order field expression context
|
|
95
|
+
* @returns the parsed OrderBy
|
|
58
96
|
*/
|
|
59
97
|
visitOrderFieldExpression(ctx: OrderFieldExpressionContext): OrderBy;
|
|
60
98
|
/**
|
|
61
99
|
* Read the order by values
|
|
100
|
+
* @param ctx - the order expression context
|
|
62
101
|
*/
|
|
63
102
|
visitOrderExpression(ctx: OrderExpressionContext): void;
|
|
64
103
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
104
|
+
* Visit the root `webdaql` rule and build the complete Query
|
|
105
|
+
*
|
|
106
|
+
* Parses filter expression, ORDER BY, LIMIT, and OFFSET clauses.
|
|
107
|
+
* Returns an empty AND expression (always true) when no filter is present.
|
|
108
|
+
* @param ctx - the webdaql parse context
|
|
109
|
+
* @returns the built Query
|
|
68
110
|
*/
|
|
69
111
|
visitWebdaql(ctx: WebdaqlContext): Query;
|
|
70
112
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
113
|
+
* Recursively flatten nested logical expressions of the same type
|
|
114
|
+
*
|
|
115
|
+
* ANTLR produces right-recursive trees like `a AND (b AND (c AND d))`.
|
|
116
|
+
* This method flattens them into `[a, b, c, d]` so a single LogicalExpression
|
|
117
|
+
* holds all children at one level.
|
|
118
|
+
*
|
|
119
|
+
* @param ctx - an AND or OR logical expression context
|
|
120
|
+
* @returns flat array of child parse tree nodes
|
|
74
121
|
*/
|
|
75
122
|
getComparison(ctx: AndLogicExpressionContext | OrLogicExpressionContext): any[];
|
|
76
123
|
/**
|
|
@@ -78,49 +125,98 @@ export declare class ExpressionBuilder extends AbstractParseTreeVisitor<Query> i
|
|
|
78
125
|
*
|
|
79
126
|
* By default the parser is doing a AND (b AND (c AND d)) creating 3 depth expressions
|
|
80
127
|
* This visitor simplify to a AND b AND c AND d with only one Expression
|
|
128
|
+
* @param ctx - the AND logic expression context
|
|
129
|
+
* @returns the flattened AndExpression
|
|
81
130
|
*/
|
|
82
|
-
visitAndLogicExpression(ctx: AndLogicExpressionContext):
|
|
131
|
+
visitAndLogicExpression(ctx: AndLogicExpressionContext): Expression;
|
|
83
132
|
/**
|
|
84
133
|
* Implement the BinaryComparison with all methods managed
|
|
134
|
+
* @param ctx - the binary comparison context
|
|
135
|
+
* @returns the comparison expression
|
|
85
136
|
*/
|
|
86
137
|
visitBinaryComparisonExpression(ctx: BinaryComparisonExpressionContext): ComparisonExpression<ComparisonOperator>;
|
|
87
138
|
/**
|
|
88
139
|
* Visit each value of the [..., ..., ...] set
|
|
140
|
+
* @param ctx - the set expression context
|
|
141
|
+
* @returns the array of values
|
|
89
142
|
*/
|
|
90
143
|
visitSetExpression(ctx: SetExpressionContext): value[];
|
|
91
144
|
/**
|
|
92
|
-
* a LIKE
|
|
93
|
-
* @param ctx
|
|
94
|
-
* @returns
|
|
145
|
+
* Visit a LIKE expression (e.g. `field LIKE '%pattern_'`)
|
|
146
|
+
* @param ctx - the LIKE expression context
|
|
147
|
+
* @returns the comparison expression
|
|
95
148
|
*/
|
|
96
149
|
visitLikeExpression(ctx: LikeExpressionContext): ComparisonExpression<"LIKE">;
|
|
97
150
|
/**
|
|
98
151
|
* Map the a IN ['b','c']
|
|
152
|
+
* @param ctx - the IN expression context
|
|
153
|
+
* @returns the comparison expression
|
|
99
154
|
*/
|
|
100
155
|
visitInExpression(ctx: InExpressionContext): ComparisonExpression<"IN">;
|
|
101
156
|
/**
|
|
102
157
|
* Map the a CONTAINS 'b'
|
|
158
|
+
* @param ctx - the CONTAINS expression context
|
|
159
|
+
* @returns the comparison expression
|
|
103
160
|
*/
|
|
104
161
|
visitContainsExpression(ctx: ContainsExpressionContext): ComparisonExpression<"CONTAINS">;
|
|
162
|
+
/**
|
|
163
|
+
* Map the a IS NULL
|
|
164
|
+
* @param ctx - the IS NULL expression context
|
|
165
|
+
* @returns the comparison expression
|
|
166
|
+
*/
|
|
167
|
+
visitIsNullExpression(ctx: IsNullExpressionContext): ComparisonExpression<"IS NULL">;
|
|
168
|
+
/**
|
|
169
|
+
* Map the a IS NOT NULL
|
|
170
|
+
* @param ctx - the IS NOT NULL expression context
|
|
171
|
+
* @returns the comparison expression
|
|
172
|
+
*/
|
|
173
|
+
visitIsNotNullExpression(ctx: IsNotNullExpressionContext): ComparisonExpression<"IS NOT NULL">;
|
|
105
174
|
/**
|
|
106
175
|
* Get the OrExpression, regrouping all the parameters
|
|
107
176
|
*
|
|
108
177
|
* By default the parser is doing a OR (b OR (c OR d)) creating 3 depth expressions
|
|
109
178
|
* This visitor simplify to a OR b OR c OR d with only one Expression
|
|
179
|
+
* @param ctx - the OR logic expression context
|
|
180
|
+
* @returns the flattened OrExpression
|
|
110
181
|
*/
|
|
111
|
-
visitOrLogicExpression(ctx: OrLogicExpressionContext):
|
|
182
|
+
visitOrLogicExpression(ctx: OrLogicExpressionContext): Expression;
|
|
112
183
|
/**
|
|
113
|
-
*
|
|
184
|
+
* A bare atom used as an expression: only `TRUE` / `FALSE` are valid
|
|
185
|
+
* @param ctx - the atom expression context
|
|
186
|
+
* @returns the constant expression
|
|
187
|
+
* @throws {SyntaxError} for identifiers, numbers and strings
|
|
188
|
+
*/
|
|
189
|
+
visitAtomExpression(ctx: AtomExpressionContext): Expression;
|
|
190
|
+
/**
|
|
191
|
+
* Read a string literal, stripping the surrounding single or double quotes
|
|
192
|
+
* @param ctx - the string literal context
|
|
193
|
+
* @returns the unquoted string value
|
|
114
194
|
*/
|
|
115
195
|
visitStringLiteral(ctx: StringLiteralContext): string;
|
|
116
196
|
/**
|
|
117
197
|
* Read the boolean literal
|
|
198
|
+
* @param ctx - the boolean literal context
|
|
199
|
+
* @returns the boolean value
|
|
118
200
|
*/
|
|
119
201
|
visitBooleanLiteral(ctx: BooleanLiteralContext): boolean;
|
|
120
202
|
/**
|
|
121
203
|
* Read the number literal
|
|
204
|
+
* @param ctx - the integer literal context
|
|
205
|
+
* @returns the parsed integer value
|
|
122
206
|
*/
|
|
123
207
|
visitIntegerLiteral(ctx: IntegerLiteralContext): number;
|
|
208
|
+
/**
|
|
209
|
+
* Read a signed or decimal number literal
|
|
210
|
+
* @param ctx - the number literal context
|
|
211
|
+
* @returns the parsed number
|
|
212
|
+
*/
|
|
213
|
+
visitNumberLiteral(ctx: NumberLiteralContext): number;
|
|
214
|
+
/**
|
|
215
|
+
* A `?` or `:name` placeholder reaching evaluation was never bound
|
|
216
|
+
* @param ctx - the parameter context
|
|
217
|
+
* @throws {WebdaQLError} always: use `bind()` or pass the parameters to `query()`
|
|
218
|
+
*/
|
|
219
|
+
visitParameter(ctx: ParameterContext): never;
|
|
124
220
|
}
|
|
125
221
|
/**
|
|
126
222
|
* Represent a full Query
|
|
@@ -152,6 +248,9 @@ export interface Query {
|
|
|
152
248
|
*/
|
|
153
249
|
export declare abstract class Expression<T = string> {
|
|
154
250
|
operator: T;
|
|
251
|
+
/** Create a new Expression.
|
|
252
|
+
* @param operator - the expression operator
|
|
253
|
+
*/
|
|
155
254
|
constructor(operator: T);
|
|
156
255
|
/**
|
|
157
256
|
* Evaluate the expression for the target object
|
|
@@ -164,9 +263,28 @@ export declare abstract class Expression<T = string> {
|
|
|
164
263
|
*/
|
|
165
264
|
abstract toString(depth?: number): string;
|
|
166
265
|
}
|
|
167
|
-
export type ComparisonOperator = "=" | "<=" | ">=" | "<" | ">" | "!=" | "LIKE" | "IN" | "CONTAINS";
|
|
168
266
|
/**
|
|
169
|
-
*
|
|
267
|
+
* All supported comparison operators
|
|
268
|
+
*
|
|
269
|
+
* - `=` / `!=` use loose equality (`==` / `!=`)
|
|
270
|
+
* - `<`, `<=`, `>`, `>=` use standard JS comparison
|
|
271
|
+
* - `LIKE` uses SQL-style pattern matching (`%` = any chars, `_` = single char)
|
|
272
|
+
* - `IN` checks membership in a set (`field IN ['a', 'b']`)
|
|
273
|
+
* - `CONTAINS` checks if an array field contains a value (`field CONTAINS 'a'`)
|
|
274
|
+
* - `IS NULL` matches a missing, `undefined` or `null` field (`field IS NULL`)
|
|
275
|
+
* - `IS NOT NULL` matches any other value (`field IS NOT NULL`)
|
|
276
|
+
*/
|
|
277
|
+
export type ComparisonOperator = "=" | "<=" | ">=" | "<" | ">" | "!=" | "LIKE" | "IN" | "CONTAINS" | "IS NULL" | "IS NOT NULL";
|
|
278
|
+
/**
|
|
279
|
+
* Comparison operators that take no value
|
|
280
|
+
*/
|
|
281
|
+
export declare const UNARY_COMPARISON_OPERATORS: readonly ComparisonOperator[];
|
|
282
|
+
/**
|
|
283
|
+
* A leaf expression comparing an object attribute against a literal value
|
|
284
|
+
*
|
|
285
|
+
* Supports dot-notation for nested attribute access (e.g. `user.profile.name`).
|
|
286
|
+
*
|
|
287
|
+
* @typeParam T - the specific comparison operator type
|
|
170
288
|
*/
|
|
171
289
|
export declare class ComparisonExpression<T extends ComparisonOperator = ComparisonOperator> extends Expression<T> {
|
|
172
290
|
/**
|
|
@@ -178,25 +296,36 @@ export declare class ComparisonExpression<T extends ComparisonOperator = Compari
|
|
|
178
296
|
*/
|
|
179
297
|
attribute: string[];
|
|
180
298
|
/**
|
|
181
|
-
*
|
|
182
|
-
* @param
|
|
183
|
-
* @param
|
|
184
|
-
* @param value
|
|
299
|
+
* @param operator - comparison operator
|
|
300
|
+
* @param attribute - dot-notation path to the object property (e.g. `"user.name"`)
|
|
301
|
+
* @param value - literal value or array of values (for IN operator) to compare against
|
|
185
302
|
*/
|
|
186
303
|
constructor(operator: T, attribute: string, value: value | any[]);
|
|
304
|
+
/**
|
|
305
|
+
* Convert a SQL LIKE pattern to a JavaScript RegExp
|
|
306
|
+
*
|
|
307
|
+
* - `%` matches zero or more characters
|
|
308
|
+
* - `_` matches exactly one character
|
|
309
|
+
* - `\%` and `\_` are literal percent/underscore
|
|
310
|
+
* - Common regex metacharacters are escaped
|
|
311
|
+
*
|
|
312
|
+
* @param like - SQL LIKE pattern string
|
|
313
|
+
* @returns compiled RegExp
|
|
314
|
+
*/
|
|
187
315
|
static likeToRegex(like: string): RegExp;
|
|
188
316
|
/**
|
|
189
|
-
*
|
|
317
|
+
* Traverse an object using a dot-notation attribute path
|
|
190
318
|
*
|
|
191
|
-
* @param target
|
|
192
|
-
* @
|
|
319
|
+
* @param target - object to read from
|
|
320
|
+
* @param attribute - path segments (e.g. `["user", "profile", "name"]`)
|
|
321
|
+
* @returns the resolved value, or `undefined` if any segment is missing
|
|
193
322
|
*/
|
|
194
323
|
static getAttributeValue(target: any, attribute: string[]): any;
|
|
195
324
|
/**
|
|
196
325
|
* Set the value of the attribute based on the assignment
|
|
197
326
|
*
|
|
198
327
|
* If used as a Set expression
|
|
199
|
-
* @param target
|
|
328
|
+
* @param target - the object to assign to
|
|
200
329
|
*/
|
|
201
330
|
setAttributeValue(target: any): void;
|
|
202
331
|
/**
|
|
@@ -204,15 +333,21 @@ export declare class ComparisonExpression<T extends ComparisonOperator = Compari
|
|
|
204
333
|
*/
|
|
205
334
|
eval(target: any): boolean;
|
|
206
335
|
/**
|
|
207
|
-
*
|
|
336
|
+
* Serialize a value to its WebdaQL string representation
|
|
337
|
+
*
|
|
338
|
+
* Strings are double-quoted, booleans are uppercased, arrays are bracket-wrapped.
|
|
339
|
+
* @param value - the value to serialize
|
|
340
|
+
* @returns the serialized string
|
|
208
341
|
*/
|
|
209
342
|
toStringValue(value: value | value[]): string;
|
|
210
343
|
/**
|
|
211
344
|
* Allow subclass to create different display
|
|
345
|
+
* @returns the attribute string
|
|
212
346
|
*/
|
|
213
347
|
toStringAttribute(): string;
|
|
214
348
|
/**
|
|
215
349
|
* Allow subclass to create different display
|
|
350
|
+
* @returns the operator string
|
|
216
351
|
*/
|
|
217
352
|
toStringOperator(): T;
|
|
218
353
|
/**
|
|
@@ -221,19 +356,18 @@ export declare class ComparisonExpression<T extends ComparisonOperator = Compari
|
|
|
221
356
|
toString(): string;
|
|
222
357
|
}
|
|
223
358
|
/**
|
|
224
|
-
* Abstract
|
|
359
|
+
* Abstract base for logical expressions that combine child expressions (AND / OR)
|
|
225
360
|
*
|
|
226
|
-
*
|
|
361
|
+
* @typeParam T - the literal operator type (`"AND"` or `"OR"`)
|
|
227
362
|
*/
|
|
228
363
|
export declare abstract class LogicalExpression<T> extends Expression<T> {
|
|
229
364
|
/**
|
|
230
|
-
*
|
|
365
|
+
* Child expressions combined by this logical operator
|
|
231
366
|
*/
|
|
232
367
|
children: Expression[];
|
|
233
368
|
/**
|
|
234
|
-
*
|
|
235
|
-
* @param
|
|
236
|
-
* @param children
|
|
369
|
+
* @param operator - logical operator
|
|
370
|
+
* @param children - child expressions to combine
|
|
237
371
|
*/
|
|
238
372
|
constructor(operator: T, children: Expression[]);
|
|
239
373
|
/**
|
|
@@ -242,7 +376,10 @@ export declare abstract class LogicalExpression<T> extends Expression<T> {
|
|
|
242
376
|
toString(depth?: number): string;
|
|
243
377
|
}
|
|
244
378
|
/**
|
|
245
|
-
* AND
|
|
379
|
+
* Logical AND expression — evaluates to `true` only if all children are `true`
|
|
380
|
+
*
|
|
381
|
+
* Uses short-circuit evaluation: returns `false` as soon as any child fails.
|
|
382
|
+
* An empty AND (no children) evaluates to `true`.
|
|
246
383
|
*/
|
|
247
384
|
export declare class AndExpression extends LogicalExpression<"AND"> {
|
|
248
385
|
/**
|
|
@@ -255,7 +392,10 @@ export declare class AndExpression extends LogicalExpression<"AND"> {
|
|
|
255
392
|
eval(target: any): boolean;
|
|
256
393
|
}
|
|
257
394
|
/**
|
|
258
|
-
* OR
|
|
395
|
+
* Logical OR expression — evaluates to `true` if any child is `true`
|
|
396
|
+
*
|
|
397
|
+
* Uses short-circuit evaluation: returns `true` as soon as any child passes.
|
|
398
|
+
* An empty OR (no children) evaluates to `true`.
|
|
259
399
|
*/
|
|
260
400
|
export declare class OrExpression extends LogicalExpression<"OR"> {
|
|
261
401
|
/**
|
|
@@ -268,7 +408,55 @@ export declare class OrExpression extends LogicalExpression<"OR"> {
|
|
|
268
408
|
eval(target: any): boolean;
|
|
269
409
|
}
|
|
270
410
|
/**
|
|
411
|
+
* Constant expression from a `TRUE` / `FALSE` literal
|
|
412
|
+
*
|
|
413
|
+
* Constants are folded while the tree is built (see `foldLogical`), so this only
|
|
414
|
+
* remains when the whole filter is `FALSE`; a filter that is entirely `TRUE` is
|
|
415
|
+
* the match-everything `AndExpression([])`.
|
|
416
|
+
*/
|
|
417
|
+
export declare class BooleanExpression extends Expression<"TRUE" | "FALSE"> {
|
|
418
|
+
/**
|
|
419
|
+
* The constant value
|
|
420
|
+
*/
|
|
421
|
+
value: boolean;
|
|
422
|
+
/**
|
|
423
|
+
* @param value - the constant value
|
|
424
|
+
*/
|
|
425
|
+
constructor(value: boolean);
|
|
426
|
+
/**
|
|
427
|
+
* @override
|
|
428
|
+
*/
|
|
429
|
+
eval(_target: any): boolean;
|
|
430
|
+
/**
|
|
431
|
+
* @override
|
|
432
|
+
*/
|
|
433
|
+
toString(): string;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Check a query against the WebdaQL grammar without evaluating it
|
|
437
|
+
*
|
|
438
|
+
* Unlike {@link QueryValidator}, unbound `?` / `:name` parameters are accepted, so a
|
|
439
|
+
* query can be checked before its parameters are bound.
|
|
440
|
+
*
|
|
441
|
+
* @param query - the query string
|
|
442
|
+
* @throws {SyntaxError} if the query does not follow the grammar
|
|
443
|
+
*/
|
|
444
|
+
export declare function validateSyntax(query: string): void;
|
|
445
|
+
/**
|
|
446
|
+
* Parses a WebdaQL query string and provides evaluation, merging, and serialization
|
|
447
|
+
*
|
|
448
|
+
* This is the main entry point for working with WebdaQL queries. It handles:
|
|
449
|
+
* - Parsing query strings via ANTLR into an expression AST
|
|
450
|
+
* - Evaluating objects against the parsed filter
|
|
451
|
+
* - Merging multiple queries together
|
|
452
|
+
* - Serializing back to a query string
|
|
271
453
|
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```ts
|
|
456
|
+
* const validator = new QueryValidator("status = 'active' AND age > 18 LIMIT 50");
|
|
457
|
+
* validator.eval({ status: "active", age: 25 }); // true
|
|
458
|
+
* validator.getLimit(); // 50
|
|
459
|
+
* ```
|
|
272
460
|
*/
|
|
273
461
|
export declare class QueryValidator {
|
|
274
462
|
protected sql: string;
|
|
@@ -276,114 +464,245 @@ export declare class QueryValidator {
|
|
|
276
464
|
protected tree: WebdaqlContext;
|
|
277
465
|
protected query: Query;
|
|
278
466
|
protected builder: ExpressionBuilder;
|
|
467
|
+
/**
|
|
468
|
+
* Parse a WebdaQL query string
|
|
469
|
+
*
|
|
470
|
+
* @param sql - the query string to parse
|
|
471
|
+
* @param builder - expression builder to use (override for custom expression types)
|
|
472
|
+
* @throws {SyntaxError} if the query string is malformed
|
|
473
|
+
*/
|
|
279
474
|
constructor(sql: string, builder?: ExpressionBuilder);
|
|
280
475
|
/**
|
|
281
|
-
* Get
|
|
282
|
-
* @returns
|
|
476
|
+
* Get parsed OFFSET continuation token, or empty string if none
|
|
477
|
+
* @returns the offset token
|
|
283
478
|
*/
|
|
284
479
|
getOffset(): string;
|
|
480
|
+
/**
|
|
481
|
+
* Check whether the query has a non-empty filter condition
|
|
482
|
+
*
|
|
483
|
+
* An empty AND expression (no children) is considered to have no condition.
|
|
484
|
+
* @returns true if there is a filter condition
|
|
485
|
+
*/
|
|
285
486
|
hasCondition(): boolean;
|
|
487
|
+
/**
|
|
488
|
+
* Reconstruct the query string from the parsed AST
|
|
489
|
+
*
|
|
490
|
+
* Includes filter, ORDER BY, LIMIT, and OFFSET clauses.
|
|
491
|
+
* @returns the reconstructed query string
|
|
492
|
+
*/
|
|
286
493
|
toString(): string;
|
|
494
|
+
/**
|
|
495
|
+
* Merge another query string into this query
|
|
496
|
+
*
|
|
497
|
+
* Filter expressions are combined using the specified logical operator.
|
|
498
|
+
* LIMIT, OFFSET, and ORDER BY from the merged query override existing values.
|
|
499
|
+
*
|
|
500
|
+
* @param query - query string to merge in
|
|
501
|
+
* @param type - logical operator to combine filters (`"AND"` or `"OR"`)
|
|
502
|
+
* @returns `this` for chaining
|
|
503
|
+
*/
|
|
287
504
|
merge(query: string, type?: "OR" | "AND"): this;
|
|
288
505
|
/**
|
|
289
|
-
* Get
|
|
290
|
-
* @returns
|
|
506
|
+
* Get parsed LIMIT value, defaulting to 1000
|
|
507
|
+
* @returns the limit value
|
|
291
508
|
*/
|
|
292
509
|
getLimit(): number;
|
|
293
510
|
/**
|
|
294
|
-
* Get the expression
|
|
295
|
-
* @returns
|
|
511
|
+
* Get the filter expression (without LIMIT / OFFSET / ORDER BY)
|
|
512
|
+
* @returns the filter expression
|
|
296
513
|
*/
|
|
297
514
|
getExpression(): Expression;
|
|
298
515
|
/**
|
|
299
|
-
* Retrieve parsed query
|
|
300
|
-
* @returns
|
|
516
|
+
* Retrieve the full parsed query including filter, limit, offset, and orderBy
|
|
517
|
+
* @returns the full query object
|
|
301
518
|
*/
|
|
302
519
|
getQuery(): Query;
|
|
303
520
|
/**
|
|
304
521
|
* Verify if a target fit the expression
|
|
305
|
-
* @param target
|
|
306
|
-
* @returns
|
|
522
|
+
* @param target - the object to evaluate
|
|
523
|
+
* @returns true if the target matches
|
|
307
524
|
*/
|
|
308
525
|
eval(target: any): boolean;
|
|
309
526
|
/**
|
|
310
527
|
* Display parse tree back as query
|
|
311
|
-
* @param tree
|
|
312
|
-
* @returns
|
|
528
|
+
* @param tree - the parse tree to display
|
|
529
|
+
* @returns the query string representation
|
|
313
530
|
*/
|
|
314
531
|
displayTree(tree?: ParseTree): string;
|
|
315
532
|
}
|
|
316
533
|
/**
|
|
317
|
-
*
|
|
534
|
+
* A query validator that operates in assignment mode
|
|
535
|
+
*
|
|
536
|
+
* Instead of filtering objects, it assigns values to object properties.
|
|
537
|
+
* Only supports `=` (assignment) combined with `AND`. No comparisons, OR, or other operators.
|
|
538
|
+
*
|
|
539
|
+
* Protects against prototype pollution by ignoring `__proto__` attributes.
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```ts
|
|
543
|
+
* const target: any = {};
|
|
544
|
+
* new SetterValidator('name = "John" AND age = 30').eval(target);
|
|
545
|
+
* // target = { name: "John", age: 30 }
|
|
546
|
+
* ```
|
|
547
|
+
*
|
|
548
|
+
* @throws {SyntaxError} if non-assignment operators or OR expressions are used
|
|
318
549
|
*/
|
|
319
550
|
export declare class SetterValidator extends QueryValidator {
|
|
551
|
+
/**
|
|
552
|
+
* @param sql - assignment expression (e.g. `'field = "value" AND other = 10'`)
|
|
553
|
+
* @throws {SyntaxError} if the expression contains non-assignment operators
|
|
554
|
+
*/
|
|
320
555
|
constructor(sql: string);
|
|
556
|
+
/**
|
|
557
|
+
* Apply the assignments to the target object
|
|
558
|
+
*
|
|
559
|
+
* @param target - object to assign values to (mutated in place)
|
|
560
|
+
* @returns always `true`
|
|
561
|
+
*/
|
|
321
562
|
eval(target: any): boolean;
|
|
563
|
+
/**
|
|
564
|
+
* Recursively walk the expression tree and apply assignments
|
|
565
|
+
*
|
|
566
|
+
* @param target - object to assign values to
|
|
567
|
+
* @param expression - must be an AndExpression or a `=` ComparisonExpression
|
|
568
|
+
* @throws {SyntaxError} if any non-assignment expression is encountered
|
|
569
|
+
*/
|
|
322
570
|
assign(target: any, expression: Expression): void;
|
|
323
571
|
}
|
|
572
|
+
/**
|
|
573
|
+
* A query validator that supports partial object matching
|
|
574
|
+
*
|
|
575
|
+
* In partial mode, comparisons against `undefined` attributes evaluate to `true`
|
|
576
|
+
* (the missing field is ignored). This is useful for PATCH operations where only
|
|
577
|
+
* a subset of fields is provided.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```ts
|
|
581
|
+
* const v = new PartialValidator("name = 'John' AND age > 18");
|
|
582
|
+
* v.eval({ name: "John" }); // true (age is undefined, skipped)
|
|
583
|
+
* v.wasPartialMatch(); // true
|
|
584
|
+
* v.eval({ name: "John" }, false); // false (strict mode, age required)
|
|
585
|
+
* ```
|
|
586
|
+
*/
|
|
324
587
|
export declare class PartialValidator extends QueryValidator {
|
|
325
588
|
builder: PartialExpressionBuilder;
|
|
589
|
+
/**
|
|
590
|
+
* @param query - WebdaQL query string
|
|
591
|
+
* @param builder - partial expression builder (override for customization)
|
|
592
|
+
*/
|
|
326
593
|
constructor(query: string, builder?: PartialExpressionBuilder);
|
|
327
594
|
/**
|
|
328
595
|
* Eval the query
|
|
329
|
-
* @param target
|
|
330
|
-
* @param partial
|
|
331
|
-
* @returns
|
|
596
|
+
* @param target - the object to evaluate
|
|
597
|
+
* @param partial - whether to use partial matching
|
|
598
|
+
* @returns true if the target matches
|
|
332
599
|
*/
|
|
333
600
|
eval(target: any, partial?: boolean): boolean;
|
|
334
601
|
/**
|
|
335
602
|
* Return if the result ignored some fields
|
|
336
|
-
* @returns
|
|
603
|
+
* @returns true if some fields were skipped
|
|
337
604
|
*/
|
|
338
605
|
wasPartialMatch(): boolean;
|
|
339
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* A comparison expression that treats `undefined` attributes as a match in partial mode
|
|
609
|
+
*
|
|
610
|
+
* When the builder is in partial mode and the target attribute is `undefined`,
|
|
611
|
+
* evaluation returns `true` and flags the result as a partial match.
|
|
612
|
+
*
|
|
613
|
+
* @typeParam T - the specific comparison operator type
|
|
614
|
+
*/
|
|
340
615
|
export declare class PartialComparisonExpression<T extends ComparisonOperator = ComparisonOperator> extends ComparisonExpression<T> {
|
|
341
616
|
protected builder: PartialExpressionBuilder;
|
|
617
|
+
/**
|
|
618
|
+
* @param builder - the partial expression builder (used to read partial mode flag)
|
|
619
|
+
* @param op - comparison operator
|
|
620
|
+
* @param attribute - dot-notation attribute path
|
|
621
|
+
* @param value - value to compare against
|
|
622
|
+
*/
|
|
342
623
|
constructor(builder: PartialExpressionBuilder, op: T, attribute: string, value: any);
|
|
343
624
|
/**
|
|
344
625
|
* Override the eval to check if the attribute is present
|
|
345
626
|
* if not and we are in partial mode, return true
|
|
346
627
|
*
|
|
347
|
-
* @param target
|
|
348
|
-
* @returns
|
|
628
|
+
* @param target - the object to evaluate
|
|
629
|
+
* @returns true if the target matches
|
|
349
630
|
*/
|
|
350
631
|
eval(target: any): boolean;
|
|
351
632
|
}
|
|
633
|
+
/**
|
|
634
|
+
* Expression builder that creates {@link PartialComparisonExpression} nodes
|
|
635
|
+
* instead of regular {@link ComparisonExpression} nodes
|
|
636
|
+
*
|
|
637
|
+
* Used by {@link PartialValidator} to support partial object matching.
|
|
638
|
+
*/
|
|
352
639
|
export declare class PartialExpressionBuilder extends ExpressionBuilder {
|
|
353
640
|
/**
|
|
354
|
-
*
|
|
641
|
+
* Whether partial mode is active (undefined attributes treated as matching)
|
|
355
642
|
*/
|
|
356
643
|
partial: boolean;
|
|
357
644
|
/**
|
|
358
|
-
*
|
|
645
|
+
* Set to `true` during evaluation if any attribute was undefined and skipped
|
|
359
646
|
*/
|
|
360
647
|
partialMatch: boolean;
|
|
648
|
+
/**
|
|
649
|
+
* Enable or disable partial evaluation mode
|
|
650
|
+
* @param partial - whether to enable partial mode
|
|
651
|
+
*/
|
|
361
652
|
setPartial(partial: boolean): void;
|
|
653
|
+
/**
|
|
654
|
+
* Set the partial match flag (reset before each evaluation)
|
|
655
|
+
* @param partial - the partial match flag value
|
|
656
|
+
*/
|
|
362
657
|
setPartialMatch(partial: boolean): void;
|
|
363
658
|
/**
|
|
364
|
-
* a LIKE
|
|
365
|
-
* @param ctx
|
|
366
|
-
* @returns
|
|
659
|
+
* Visit a LIKE expression, returning a PartialComparisonExpression
|
|
660
|
+
* @param ctx - the LIKE expression context
|
|
661
|
+
* @returns the partial comparison expression
|
|
367
662
|
*/
|
|
368
663
|
visitLikeExpression(ctx: any): PartialComparisonExpression<"LIKE">;
|
|
369
664
|
/**
|
|
370
|
-
*
|
|
665
|
+
* Visit a binary comparison, returning a PartialComparisonExpression
|
|
666
|
+
* @param ctx - the binary comparison context
|
|
667
|
+
* @returns the partial comparison expression
|
|
371
668
|
*/
|
|
372
669
|
visitBinaryComparisonExpression(ctx: any): PartialComparisonExpression<any>;
|
|
373
670
|
/**
|
|
374
|
-
*
|
|
671
|
+
* Visit an IN expression, returning a PartialComparisonExpression
|
|
672
|
+
* @param ctx - the IN expression context
|
|
673
|
+
* @returns the partial comparison expression
|
|
375
674
|
*/
|
|
376
675
|
visitInExpression(ctx: any): PartialComparisonExpression<"IN">;
|
|
377
676
|
/**
|
|
378
|
-
*
|
|
677
|
+
* Visit a CONTAINS expression, returning a PartialComparisonExpression
|
|
678
|
+
* @param ctx - the CONTAINS expression context
|
|
679
|
+
* @returns the partial comparison expression
|
|
379
680
|
*/
|
|
380
681
|
visitContainsExpression(ctx: any): PartialComparisonExpression<"CONTAINS">;
|
|
682
|
+
/**
|
|
683
|
+
* Visit an IS NULL expression, returning a PartialComparisonExpression
|
|
684
|
+
* @param ctx - the IS NULL expression context
|
|
685
|
+
* @returns the partial comparison expression
|
|
686
|
+
*/
|
|
687
|
+
visitIsNullExpression(ctx: any): PartialComparisonExpression<"IS NULL">;
|
|
688
|
+
/**
|
|
689
|
+
* Visit an IS NOT NULL expression, returning a PartialComparisonExpression
|
|
690
|
+
* @param ctx - the IS NOT NULL expression context
|
|
691
|
+
* @returns the partial comparison expression
|
|
692
|
+
*/
|
|
693
|
+
visitIsNotNullExpression(ctx: any): PartialComparisonExpression<"IS NOT NULL">;
|
|
381
694
|
}
|
|
382
695
|
/**
|
|
383
696
|
* Remove artifact from sanitize-html inside query
|
|
384
|
-
* @param query
|
|
385
|
-
* @returns
|
|
697
|
+
* @param query - the query string to unsanitize
|
|
698
|
+
* @returns the cleaned query string
|
|
386
699
|
*/
|
|
387
700
|
export declare function unsanitize(query: string): string;
|
|
701
|
+
/**
|
|
702
|
+
* Parse a query string into a Query object
|
|
703
|
+
* @param query - the query string to parse
|
|
704
|
+
* @returns the parsed Query object
|
|
705
|
+
*/
|
|
706
|
+
export declare function parse(query: string): Query;
|
|
388
707
|
export {};
|
|
389
708
|
//# sourceMappingURL=query.d.ts.map
|