@tellaro/tql 0.3.1 → 1.4.0
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/dist/index.js +44 -41
- package/dist/node_modules/@kurkle/color/dist/color.esm.js +442 -0
- package/dist/node_modules/chart.js/dist/chart.js +6149 -0
- package/dist/node_modules/chart.js/dist/chunks/helpers.dataset.js +1685 -0
- package/dist/node_modules/chartjs-adapter-luxon/dist/chartjs-adapter-luxon.esm.js +56 -0
- package/dist/node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.esm.js +1655 -0
- package/dist/node_modules/chartjs-plugin-datalabels/dist/chartjs-plugin-datalabels.esm.js +607 -0
- package/dist/node_modules/luxon/build/es6/luxon.js +5524 -0
- package/dist/src/builder.d.ts +62 -0
- package/dist/src/builder.js +56 -0
- package/dist/src/chart/colors.d.ts +23 -0
- package/dist/src/chart/colors.js +101 -0
- package/dist/src/chart/formatters.d.ts +17 -0
- package/dist/src/chart/formatters.js +49 -0
- package/dist/src/chart/index.d.ts +9 -0
- package/dist/src/chart/index.js +31 -0
- package/dist/src/chart/mappers.d.ts +849 -0
- package/dist/src/chart/mappers.js +613 -0
- package/dist/src/completionProvider.js +294 -165
- package/dist/src/index.d.ts +2 -1
- package/dist/src/parser.d.ts +10 -0
- package/dist/src/parser.js +41 -9
- package/dist/src/tokenizer.js +124 -103
- package/dist/src/types.d.ts +27 -3
- package/dist/src/validator.js +10 -9
- package/dist/tql.css +1 -1
- package/dist/vue/TqlAutocomplete.vue.js +2 -2
- package/dist/vue/TqlChart.vue.d.ts +2 -0
- package/dist/vue/TqlChart.vue.js +7 -0
- package/dist/vue/TqlChart.vue2.js +212 -0
- package/dist/vue/TqlInput.vue.js +2 -2
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +12 -10
- package/dist/vue/useTqlInput.js +80 -80
- package/package.json +126 -90
package/dist/src/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
|
-
export type { TqlToken, TqlTokenType, TqlExpression, TqlBinaryExpression, TqlUnaryExpression, TqlComparisonExpression, TqlCollectionExpression, TqlMutatorExpression, TqlAggregationExpression, TqlStatsExpression, TqlGroupExpression, TqlLiteral, TqlFieldReference, TqlComparisonOperator, TqlLogicalOperator, TqlCollectionOperator, TqlMutator, TqlAggregationFunction, TqlTypeHint, TqlVisualizationType, TqlParseResult, TqlParseError, TqlParseWarning, TqlErrorCode, TqlWarningCode, TqlValidationResult, TqlValidationOptions, TqlFieldType, TqlCompletionItem, TqlCompletionKind, TqlCompletionContext, TqlCompletionOptions, TqlFieldSchema, TqlSnippet, TqlInputProps, TqlInputEmits, TqlInputExpose } from './types';
|
|
9
|
+
export type { TqlToken, TqlTokenType, TqlExpression, TqlBinaryExpression, TqlUnaryExpression, TqlComparisonExpression, TqlCollectionExpression, TqlMutatorExpression, TqlAggregationExpression, TqlStatsExpression, TqlGroupExpression, TqlLiteral, TqlFieldReference, TqlComparisonOperator, TqlLogicalOperator, TqlCollectionOperator, TqlMutator, TqlAggregationFunction, TqlTypeHint, TqlVisualizationType, TqlVizParams, TqlVizHint, TqlParseResult, TqlParseError, TqlParseWarning, TqlErrorCode, TqlWarningCode, TqlValidationResult, TqlValidationOptions, TqlFieldType, TqlCompletionItem, TqlCompletionKind, TqlCompletionContext, TqlCompletionOptions, TqlFieldSchema, TqlSnippet, TqlInputProps, TqlInputEmits, TqlInputExpose } from './types';
|
|
10
10
|
export { TqlTokenizer, tokenizeTql, tokenizeTqlNoWhitespace, findTokenAtPosition, findTokensInRange, findTokenBefore, findPreviousToken, COMPARISON_OPERATORS, SYMBOL_OPERATORS, NEGATION_SYMBOL_OPERATORS, LOGICAL_OPERATORS, COLLECTION_OPERATORS, MUTATORS, AGGREGATION_FUNCTIONS, TYPE_HINTS, VISUALIZATION_TYPES, KEYWORDS } from './tokenizer';
|
|
11
11
|
export { TqlParser, parseTql, isValidTql, getTqlErrors, formatParseError } from './parser';
|
|
12
12
|
export { TqlValidator, validateTql, isValidTqlSyntax, getTqlIssues, formatValidationResult } from './validator';
|
|
@@ -15,4 +15,5 @@ export { fuzzyMatch, levenshteinDistance, findClosestMatch, fuzzyFilter, highlig
|
|
|
15
15
|
export { SchemaCache, getSchemaCache, createSchemaCache, getCachedFieldNames, getCachedFieldType, getCachedField, type CachedSchema } from './schemaCache';
|
|
16
16
|
export { ComplexityAnalyzer, analyzeComplexity, isHighComplexity, getComplexityWarnings, getComplexityMetrics } from './complexityAnalyzer';
|
|
17
17
|
export { SemanticPreview, generatePreview, getFieldUsage, getLogicTree, getUniqueFields, getOperatorSummary, formatLogicTreeNode, formatLogicTreeAscii, flattenLogicTree, getLogicTreeDepth } from './semanticPreview';
|
|
18
|
+
export { buildStatsQuery, parseVizHintString, type StatsQueryConfig, type AggregationConfig, type GroupByConfig, type VizHintConfig } from './builder';
|
|
18
19
|
export type { ComplexityScore, ComplexityWarning, ComplexityWarningType, ComplexityMetrics, ComplexityResult, ComplexityThresholds, MatchType, FieldUsage, LogicTreeNodeType, LogicTreeNode, PreviewResult, QueryHistoryEntry, UseQueryHistoryOptions } from './types';
|
package/dist/src/parser.d.ts
CHANGED
|
@@ -71,6 +71,16 @@ export declare class TqlParser {
|
|
|
71
71
|
* This allows the parser to continue and find additional errors.
|
|
72
72
|
*/
|
|
73
73
|
private createPlaceholderExpression;
|
|
74
|
+
/**
|
|
75
|
+
* Check if the token stream represents a stats query.
|
|
76
|
+
* Handles: "| stats ...", "stats ...", or starts with a filter before "| stats".
|
|
77
|
+
*/
|
|
78
|
+
private isStatsQuery;
|
|
79
|
+
/**
|
|
80
|
+
* Check if the current position is a pipe followed by "stats" keyword.
|
|
81
|
+
* Used when the filter portion parsed successfully but there are remaining tokens.
|
|
82
|
+
*/
|
|
83
|
+
private isStatsFollowingPipe;
|
|
74
84
|
}
|
|
75
85
|
/**
|
|
76
86
|
* Parse a TQL query string
|
package/dist/src/parser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tokenizeTql as u, COMPARISON_OPERATORS as c } from "./tokenizer.js";
|
|
2
|
-
const
|
|
2
|
+
const p = 50, d = /* @__PURE__ */ new Set(["logicalOp", "paren"]);
|
|
3
3
|
class v {
|
|
4
4
|
tokens;
|
|
5
5
|
allTokens;
|
|
@@ -23,11 +23,20 @@ class v {
|
|
|
23
23
|
warnings: [],
|
|
24
24
|
success: !0
|
|
25
25
|
};
|
|
26
|
+
if (this.isStatsQuery())
|
|
27
|
+
return {
|
|
28
|
+
ast: null,
|
|
29
|
+
// Stats AST is produced by the Python/Rust parser
|
|
30
|
+
tokens: this.allTokens,
|
|
31
|
+
errors: [],
|
|
32
|
+
warnings: [],
|
|
33
|
+
success: !0
|
|
34
|
+
};
|
|
26
35
|
try {
|
|
27
36
|
const e = this.parseExpression();
|
|
28
37
|
if (!this.isAtEnd()) {
|
|
29
38
|
const t = this.peek();
|
|
30
|
-
this.addError(
|
|
39
|
+
t.type === "pipe" && this.isStatsFollowingPipe() || this.addError(
|
|
31
40
|
`Unexpected token '${t.value}'`,
|
|
32
41
|
t,
|
|
33
42
|
"UNEXPECTED_TOKEN",
|
|
@@ -58,7 +67,7 @@ class v {
|
|
|
58
67
|
* Parse a full expression (lowest precedence)
|
|
59
68
|
*/
|
|
60
69
|
parseExpression() {
|
|
61
|
-
if (this.depth++, this.depth >
|
|
70
|
+
if (this.depth++, this.depth > p)
|
|
62
71
|
throw new Error("Maximum query depth exceeded");
|
|
63
72
|
try {
|
|
64
73
|
return this.parseOr();
|
|
@@ -507,7 +516,7 @@ class v {
|
|
|
507
516
|
*/
|
|
508
517
|
synchronize() {
|
|
509
518
|
for (this.advance(); !this.isAtEnd(); ) {
|
|
510
|
-
if (
|
|
519
|
+
if (d.has(this.peek().type) || this.peek().type === "paren" && this.peek().value === ")")
|
|
511
520
|
return;
|
|
512
521
|
this.advance();
|
|
513
522
|
}
|
|
@@ -538,24 +547,47 @@ class v {
|
|
|
538
547
|
end: e.end
|
|
539
548
|
};
|
|
540
549
|
}
|
|
550
|
+
/**
|
|
551
|
+
* Check if the token stream represents a stats query.
|
|
552
|
+
* Handles: "| stats ...", "stats ...", or starts with a filter before "| stats".
|
|
553
|
+
*/
|
|
554
|
+
isStatsQuery() {
|
|
555
|
+
if (this.tokens.length >= 2 && this.tokens[0].type === "pipe")
|
|
556
|
+
return this.tokens[1].type === "keyword" && this.tokens[1].value.toLowerCase() === "stats";
|
|
557
|
+
if (this.tokens.length >= 1 && this.tokens[0].type === "keyword" && this.tokens[0].value.toLowerCase() === "stats")
|
|
558
|
+
return !0;
|
|
559
|
+
for (let e = 0; e < this.tokens.length - 1; e++)
|
|
560
|
+
if (this.tokens[e].type === "pipe" && this.tokens[e + 1].type === "keyword" && this.tokens[e + 1].value.toLowerCase() === "stats")
|
|
561
|
+
return !0;
|
|
562
|
+
return !1;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Check if the current position is a pipe followed by "stats" keyword.
|
|
566
|
+
* Used when the filter portion parsed successfully but there are remaining tokens.
|
|
567
|
+
*/
|
|
568
|
+
isStatsFollowingPipe() {
|
|
569
|
+
if (this.current >= this.tokens.length || this.tokens[this.current].type !== "pipe") return !1;
|
|
570
|
+
const t = this.current + 1;
|
|
571
|
+
return t >= this.tokens.length ? !1 : this.tokens[t].type === "keyword" && this.tokens[t].value.toLowerCase() === "stats";
|
|
572
|
+
}
|
|
541
573
|
}
|
|
542
574
|
function l(i) {
|
|
543
|
-
return new v(i).parse();
|
|
575
|
+
return i ? new v(i).parse() : { ast: null, errors: [], warnings: [], tokens: [] };
|
|
544
576
|
}
|
|
545
|
-
function
|
|
577
|
+
function f(i) {
|
|
546
578
|
return l(i).success;
|
|
547
579
|
}
|
|
548
580
|
function y(i) {
|
|
549
581
|
return l(i).errors;
|
|
550
582
|
}
|
|
551
|
-
function
|
|
583
|
+
function g(i) {
|
|
552
584
|
let e = `Error at line ${i.line}, column ${i.column}: ${i.message}`;
|
|
553
585
|
return i.suggestion && (e += ` (${i.suggestion})`), e;
|
|
554
586
|
}
|
|
555
587
|
export {
|
|
556
588
|
v as TqlParser,
|
|
557
|
-
|
|
589
|
+
g as formatParseError,
|
|
558
590
|
y as getTqlErrors,
|
|
559
|
-
|
|
591
|
+
f as isValidTql,
|
|
560
592
|
l as parseTql
|
|
561
593
|
};
|
package/dist/src/tokenizer.js
CHANGED
|
@@ -2,18 +2,27 @@ const l = [
|
|
|
2
2
|
// Equality
|
|
3
3
|
"eq",
|
|
4
4
|
"ne",
|
|
5
|
+
"eq_ci",
|
|
5
6
|
// Comparison
|
|
6
7
|
"gt",
|
|
7
8
|
"gte",
|
|
8
9
|
"lt",
|
|
9
10
|
"lte",
|
|
10
|
-
// String operators
|
|
11
|
+
// String operators (case-insensitive by default)
|
|
11
12
|
"contains",
|
|
12
13
|
"not_contains",
|
|
13
14
|
"startswith",
|
|
14
15
|
"not_startswith",
|
|
15
16
|
"endswith",
|
|
16
17
|
"not_endswith",
|
|
18
|
+
// Case-sensitive string operators (explicit)
|
|
19
|
+
"contains_cs",
|
|
20
|
+
"not_contains_cs",
|
|
21
|
+
"startswith_cs",
|
|
22
|
+
"not_startswith_cs",
|
|
23
|
+
"endswith_cs",
|
|
24
|
+
"not_endswith_cs",
|
|
25
|
+
// Regex operators
|
|
17
26
|
"regexp",
|
|
18
27
|
"regex",
|
|
19
28
|
"not_regexp",
|
|
@@ -24,6 +33,8 @@ const l = [
|
|
|
24
33
|
"not_between",
|
|
25
34
|
"in",
|
|
26
35
|
"not_in",
|
|
36
|
+
"in_cs",
|
|
37
|
+
"not_in_cs",
|
|
27
38
|
// Existence operators
|
|
28
39
|
"exists",
|
|
29
40
|
"not_exists",
|
|
@@ -39,7 +50,7 @@ const l = [
|
|
|
39
50
|
"not_any",
|
|
40
51
|
"not_all",
|
|
41
52
|
"not_none"
|
|
42
|
-
],
|
|
53
|
+
], h = {
|
|
43
54
|
"==": "eq",
|
|
44
55
|
"=": "eq",
|
|
45
56
|
"!=": "ne",
|
|
@@ -48,6 +59,10 @@ const l = [
|
|
|
48
59
|
"<": "lt",
|
|
49
60
|
"<=": "lte"
|
|
50
61
|
}, u = {
|
|
62
|
+
"!in_cs": "not_in_cs",
|
|
63
|
+
"!contains_cs": "not_contains_cs",
|
|
64
|
+
"!startswith_cs": "not_startswith_cs",
|
|
65
|
+
"!endswith_cs": "not_endswith_cs",
|
|
51
66
|
"!in": "not_in",
|
|
52
67
|
"!contains": "not_contains",
|
|
53
68
|
"!startswith": "not_startswith",
|
|
@@ -61,7 +76,7 @@ const l = [
|
|
|
61
76
|
"!any": "not_any",
|
|
62
77
|
"!all": "not_all",
|
|
63
78
|
"!none": "not_none"
|
|
64
|
-
},
|
|
79
|
+
}, d = ["AND", "OR", "NOT"], p = ["ANY", "ALL", "NONE"], k = [
|
|
65
80
|
// String mutators
|
|
66
81
|
"lowercase",
|
|
67
82
|
"uppercase",
|
|
@@ -82,6 +97,9 @@ const l = [
|
|
|
82
97
|
"defang",
|
|
83
98
|
"is_private",
|
|
84
99
|
"is_global",
|
|
100
|
+
"is_multicast",
|
|
101
|
+
"is_loopback",
|
|
102
|
+
"is_link_local",
|
|
85
103
|
// DNS mutator
|
|
86
104
|
"nslookup",
|
|
87
105
|
// GeoIP mutators
|
|
@@ -125,7 +143,7 @@ const l = [
|
|
|
125
143
|
"values",
|
|
126
144
|
"unique",
|
|
127
145
|
"distinct"
|
|
128
|
-
],
|
|
146
|
+
], _ = [
|
|
129
147
|
"string",
|
|
130
148
|
"str",
|
|
131
149
|
"number",
|
|
@@ -141,11 +159,13 @@ const l = [
|
|
|
141
159
|
"list",
|
|
142
160
|
"object",
|
|
143
161
|
"geo"
|
|
144
|
-
],
|
|
162
|
+
], m = [
|
|
145
163
|
"bar",
|
|
146
164
|
"barchart",
|
|
165
|
+
"horizontal_bar",
|
|
147
166
|
"line",
|
|
148
167
|
"area",
|
|
168
|
+
"stacked_area",
|
|
149
169
|
"pie",
|
|
150
170
|
"donut",
|
|
151
171
|
"scatter",
|
|
@@ -160,24 +180,25 @@ const l = [
|
|
|
160
180
|
"stacked_bar",
|
|
161
181
|
"nested_pie",
|
|
162
182
|
"nested_donut",
|
|
163
|
-
"chord"
|
|
164
|
-
|
|
165
|
-
|
|
183
|
+
"chord",
|
|
184
|
+
"auto"
|
|
185
|
+
], w = ["by", "as", "null", "true", "false", "stats", "top", "bottom"];
|
|
186
|
+
class g {
|
|
166
187
|
input;
|
|
167
188
|
position;
|
|
168
189
|
line;
|
|
169
190
|
column;
|
|
170
191
|
tokens;
|
|
171
|
-
constructor(
|
|
172
|
-
this.input =
|
|
192
|
+
constructor(t) {
|
|
193
|
+
this.input = t ?? "", this.position = 0, this.line = 1, this.column = 1, this.tokens = [];
|
|
173
194
|
}
|
|
174
195
|
/**
|
|
175
196
|
* Tokenize the entire input string
|
|
176
197
|
*/
|
|
177
198
|
tokenize() {
|
|
178
199
|
for (this.tokens = [], this.position = 0, this.line = 1, this.column = 1; !this.isAtEnd(); ) {
|
|
179
|
-
const
|
|
180
|
-
|
|
200
|
+
const t = this.scanToken();
|
|
201
|
+
t && this.tokens.push(t);
|
|
181
202
|
}
|
|
182
203
|
return this.tokens;
|
|
183
204
|
}
|
|
@@ -187,40 +208,40 @@ class T {
|
|
|
187
208
|
scanToken() {
|
|
188
209
|
if (this.isWhitespace(this.peek()))
|
|
189
210
|
return this.scanWhitespace();
|
|
190
|
-
const
|
|
191
|
-
switch (
|
|
211
|
+
const t = this.position, n = this.line, i = this.column, e = this.advance();
|
|
212
|
+
switch (e) {
|
|
192
213
|
case "(":
|
|
193
214
|
case ")":
|
|
194
|
-
return this.makeToken("paren",
|
|
215
|
+
return this.makeToken("paren", e, t, n, i);
|
|
195
216
|
case "[":
|
|
196
217
|
case "]":
|
|
197
|
-
return this.makeToken("bracket",
|
|
218
|
+
return this.makeToken("bracket", e, t, n, i);
|
|
198
219
|
case ",":
|
|
199
|
-
return this.makeToken("comma",
|
|
220
|
+
return this.makeToken("comma", e, t, n, i);
|
|
200
221
|
case "|":
|
|
201
|
-
return this.makeToken("pipe",
|
|
222
|
+
return this.makeToken("pipe", e, t, n, i);
|
|
202
223
|
}
|
|
203
|
-
return
|
|
224
|
+
return e === "=" && this.peek() === ">" ? (this.advance(), this.makeToken("arrow", "=>", t, n, i)) : e === ":" && this.peek() === ":" ? (this.advance(), this.makeToken("doubleColon", "::", t, n, i)) : e === '"' || e === "'" ? this.scanString(e, t, n, i) : this.isDigit(e) || e === "-" && this.isDigit(this.peek()) ? this.scanNumber(t, n, i) : this.isOperatorChar(e) ? this.scanSymbolOperator(t, n, i) : this.isIdentifierStart(e) ? this.scanIdentifier(t, n, i) : this.makeToken("unknown", e, t, n, i);
|
|
204
225
|
}
|
|
205
226
|
/**
|
|
206
227
|
* Scan whitespace characters
|
|
207
228
|
*/
|
|
208
229
|
scanWhitespace() {
|
|
209
|
-
const
|
|
210
|
-
let
|
|
230
|
+
const t = this.position, n = this.line, i = this.column;
|
|
231
|
+
let e = "";
|
|
211
232
|
for (; !this.isAtEnd() && this.isWhitespace(this.peek()); ) {
|
|
212
233
|
const s = this.advance();
|
|
213
|
-
|
|
234
|
+
e += s;
|
|
214
235
|
}
|
|
215
|
-
return this.makeToken("whitespace",
|
|
236
|
+
return this.makeToken("whitespace", e, t, n, i);
|
|
216
237
|
}
|
|
217
238
|
/**
|
|
218
239
|
* Scan a string literal (single or double quoted)
|
|
219
240
|
*/
|
|
220
|
-
scanString(
|
|
241
|
+
scanString(t, n, i, e) {
|
|
221
242
|
let s = "";
|
|
222
|
-
const r =
|
|
223
|
-
for (; !this.isAtEnd() && this.peek() !==
|
|
243
|
+
const r = t;
|
|
244
|
+
for (; !this.isAtEnd() && this.peek() !== t; )
|
|
224
245
|
if (this.peek() === "\\") {
|
|
225
246
|
if (this.advance(), !this.isAtEnd()) {
|
|
226
247
|
const a = this.advance();
|
|
@@ -256,7 +277,7 @@ class T {
|
|
|
256
277
|
start: n,
|
|
257
278
|
end: this.position,
|
|
258
279
|
line: i,
|
|
259
|
-
column:
|
|
280
|
+
column: e,
|
|
260
281
|
raw: r + s
|
|
261
282
|
} : (this.advance(), {
|
|
262
283
|
type: "string",
|
|
@@ -264,88 +285,88 @@ class T {
|
|
|
264
285
|
start: n,
|
|
265
286
|
end: this.position,
|
|
266
287
|
line: i,
|
|
267
|
-
column:
|
|
268
|
-
raw:
|
|
288
|
+
column: e,
|
|
289
|
+
raw: t + s + t
|
|
269
290
|
});
|
|
270
291
|
}
|
|
271
292
|
/**
|
|
272
293
|
* Scan a numeric literal
|
|
273
294
|
*/
|
|
274
|
-
scanNumber(
|
|
275
|
-
this.position =
|
|
276
|
-
let
|
|
277
|
-
for (this.peek() === "-" && (
|
|
278
|
-
|
|
295
|
+
scanNumber(t, n, i) {
|
|
296
|
+
this.position = t, this.column = i;
|
|
297
|
+
let e = "";
|
|
298
|
+
for (this.peek() === "-" && (e += this.advance()); !this.isAtEnd() && this.isDigit(this.peek()); )
|
|
299
|
+
e += this.advance();
|
|
279
300
|
if (this.peek() === "." && this.isDigit(this.peekNext()))
|
|
280
|
-
for (
|
|
281
|
-
|
|
301
|
+
for (e += this.advance(); !this.isAtEnd() && this.isDigit(this.peek()); )
|
|
302
|
+
e += this.advance();
|
|
282
303
|
if (this.peek() === "e" || this.peek() === "E")
|
|
283
|
-
for (
|
|
284
|
-
|
|
285
|
-
return this.makeToken("number",
|
|
304
|
+
for (e += this.advance(), (this.peek() === "+" || this.peek() === "-") && (e += this.advance()); !this.isAtEnd() && this.isDigit(this.peek()); )
|
|
305
|
+
e += this.advance();
|
|
306
|
+
return this.makeToken("number", e, t, n, i);
|
|
286
307
|
}
|
|
287
308
|
/**
|
|
288
309
|
* Scan symbol-based operators (==, !=, >, >=, <, <=, !)
|
|
289
310
|
*/
|
|
290
|
-
scanSymbolOperator(
|
|
291
|
-
this.position =
|
|
292
|
-
let
|
|
311
|
+
scanSymbolOperator(t, n, i) {
|
|
312
|
+
this.position = t, this.column = i;
|
|
313
|
+
let e = this.advance();
|
|
293
314
|
if (!this.isAtEnd()) {
|
|
294
|
-
const s =
|
|
315
|
+
const s = e + this.peek();
|
|
295
316
|
if (s === "=>")
|
|
296
|
-
return this.advance(), this.makeToken("arrow", "=>",
|
|
297
|
-
(s in
|
|
317
|
+
return this.advance(), this.makeToken("arrow", "=>", t, n, i);
|
|
318
|
+
(s in h || s === "==" || s === "!=") && (e = s, this.advance());
|
|
298
319
|
}
|
|
299
|
-
if (
|
|
320
|
+
if (e === "!") {
|
|
300
321
|
const s = this.position;
|
|
301
322
|
let r = "";
|
|
302
323
|
for (; !this.isAtEnd() && this.isIdentifierChar(this.peek()); )
|
|
303
324
|
r += this.advance();
|
|
304
325
|
if (r) {
|
|
305
326
|
if ("!" + r in u)
|
|
306
|
-
return this.makeToken("operator", "!" + r,
|
|
327
|
+
return this.makeToken("operator", "!" + r, t, n, i);
|
|
307
328
|
this.position = s, this.column = i + 1;
|
|
308
329
|
}
|
|
309
330
|
}
|
|
310
|
-
return
|
|
331
|
+
return e in h || e === "==" || e === "=" || e === "!=" || e === ">" || e === ">=" || e === "<" || e === "<=" ? this.makeToken("operator", e, t, n, i) : this.makeToken("unknown", e, t, n, i);
|
|
311
332
|
}
|
|
312
333
|
/**
|
|
313
334
|
* Scan an identifier (field name, operator keyword, etc.)
|
|
314
335
|
*/
|
|
315
|
-
scanIdentifier(
|
|
316
|
-
this.position =
|
|
317
|
-
let
|
|
336
|
+
scanIdentifier(t, n, i) {
|
|
337
|
+
this.position = t, this.column = i;
|
|
338
|
+
let e = "";
|
|
318
339
|
const s = this.advance();
|
|
319
|
-
if (
|
|
320
|
-
return this.makeToken("unknown",
|
|
340
|
+
if (e += s, s === "@" && this.peek() === "@")
|
|
341
|
+
return this.makeToken("unknown", e, t, n, i);
|
|
321
342
|
let r = s;
|
|
322
343
|
for (; !this.isAtEnd() && this.isIdentifierChar(this.peek()); ) {
|
|
323
|
-
const
|
|
324
|
-
if (
|
|
325
|
-
return this.position--, this.column--,
|
|
326
|
-
|
|
344
|
+
const c = this.advance();
|
|
345
|
+
if (c === "." && r === ".")
|
|
346
|
+
return this.position--, this.column--, e = e.slice(0, -1), this.makeToken("unknown", e, t, n, i);
|
|
347
|
+
e += c, r = c;
|
|
327
348
|
}
|
|
328
|
-
|
|
329
|
-
const a = this.classifyIdentifier(
|
|
330
|
-
return this.makeToken(a,
|
|
349
|
+
e.endsWith(".") && (this.position--, this.column--, e = e.slice(0, -1));
|
|
350
|
+
const a = this.classifyIdentifier(e);
|
|
351
|
+
return this.makeToken(a, e, t, n, i);
|
|
331
352
|
}
|
|
332
353
|
/**
|
|
333
354
|
* Classify an identifier into the appropriate token type
|
|
334
355
|
*/
|
|
335
|
-
classifyIdentifier(
|
|
336
|
-
const n =
|
|
337
|
-
return
|
|
356
|
+
classifyIdentifier(t) {
|
|
357
|
+
const n = t.toUpperCase(), i = t.toLowerCase();
|
|
358
|
+
return d.includes(n) ? "logicalOp" : p.includes(n) ? "collectionOp" : i === "true" || i === "false" ? "boolean" : i === "null" ? "null" : i === "stats" ? "keyword" : l.includes(i) ? "operator" : f.includes(i) ? "aggregation" : k.includes(i) ? "mutator" : _.includes(i) ? "typeHint" : m.includes(i) ? "visualization" : w.includes(i) ? "keyword" : "field";
|
|
338
359
|
}
|
|
339
360
|
// ============================================================================
|
|
340
361
|
// Helper Methods
|
|
341
362
|
// ============================================================================
|
|
342
|
-
makeToken(
|
|
363
|
+
makeToken(t, n, i, e, s) {
|
|
343
364
|
return {
|
|
344
|
-
type:
|
|
365
|
+
type: t,
|
|
345
366
|
value: n,
|
|
346
367
|
start: i,
|
|
347
368
|
end: this.position,
|
|
348
|
-
line:
|
|
369
|
+
line: e,
|
|
349
370
|
column: s
|
|
350
371
|
};
|
|
351
372
|
}
|
|
@@ -359,81 +380,81 @@ class T {
|
|
|
359
380
|
return this.position + 1 >= this.input.length ? "\0" : this.input[this.position + 1];
|
|
360
381
|
}
|
|
361
382
|
advance() {
|
|
362
|
-
const
|
|
363
|
-
return this.position++,
|
|
364
|
-
` ? (this.line++, this.column = 1) : this.column++,
|
|
383
|
+
const t = this.input[this.position];
|
|
384
|
+
return this.position++, t === `
|
|
385
|
+
` ? (this.line++, this.column = 1) : this.column++, t;
|
|
365
386
|
}
|
|
366
|
-
isWhitespace(
|
|
367
|
-
return
|
|
368
|
-
` ||
|
|
387
|
+
isWhitespace(t) {
|
|
388
|
+
return t === " " || t === " " || t === `
|
|
389
|
+
` || t === "\r";
|
|
369
390
|
}
|
|
370
|
-
isDigit(
|
|
371
|
-
return
|
|
391
|
+
isDigit(t) {
|
|
392
|
+
return t >= "0" && t <= "9";
|
|
372
393
|
}
|
|
373
|
-
isIdentifierStart(
|
|
374
|
-
return
|
|
394
|
+
isIdentifierStart(t) {
|
|
395
|
+
return t >= "a" && t <= "z" || t >= "A" && t <= "Z" || t === "_" || t === "@";
|
|
375
396
|
}
|
|
376
397
|
/**
|
|
377
398
|
* Check if char can continue an identifier (NOT including @ which is only valid at start)
|
|
378
399
|
*/
|
|
379
|
-
isIdentifierChar(
|
|
380
|
-
return
|
|
381
|
-
|
|
400
|
+
isIdentifierChar(t) {
|
|
401
|
+
return t >= "a" && t <= "z" || t >= "A" && t <= "Z" || t === "_" || this.isDigit(t) || t === "." || // For nested field access
|
|
402
|
+
t === "-";
|
|
382
403
|
}
|
|
383
|
-
isOperatorChar(
|
|
384
|
-
return
|
|
404
|
+
isOperatorChar(t) {
|
|
405
|
+
return t === "=" || t === "!" || t === ">" || t === "<";
|
|
385
406
|
}
|
|
386
407
|
}
|
|
387
|
-
function
|
|
388
|
-
return new
|
|
408
|
+
function T(o) {
|
|
409
|
+
return new g(o).tokenize();
|
|
389
410
|
}
|
|
390
411
|
function b(o) {
|
|
391
|
-
return
|
|
412
|
+
return T(o).filter((t) => t.type !== "whitespace");
|
|
392
413
|
}
|
|
393
|
-
function v(o,
|
|
414
|
+
function v(o, t) {
|
|
394
415
|
for (const n of o)
|
|
395
|
-
if (
|
|
416
|
+
if (t >= n.start && t < n.end)
|
|
396
417
|
return n;
|
|
397
418
|
return null;
|
|
398
419
|
}
|
|
399
|
-
function O(o,
|
|
400
|
-
return o.filter((i) => i.start < n && i.end >
|
|
420
|
+
function O(o, t, n) {
|
|
421
|
+
return o.filter((i) => i.start < n && i.end > t);
|
|
401
422
|
}
|
|
402
|
-
function A(o,
|
|
423
|
+
function A(o, t) {
|
|
403
424
|
let n = null;
|
|
404
425
|
for (const i of o)
|
|
405
|
-
if (i.end <=
|
|
426
|
+
if (i.end <= t)
|
|
406
427
|
n = i;
|
|
407
428
|
else
|
|
408
429
|
break;
|
|
409
430
|
return n;
|
|
410
431
|
}
|
|
411
|
-
function E(o,
|
|
432
|
+
function E(o, t, n = !0) {
|
|
412
433
|
const i = n ? o.filter((s) => s.type !== "whitespace") : o;
|
|
413
|
-
let
|
|
434
|
+
let e = null;
|
|
414
435
|
for (const s of i)
|
|
415
|
-
if (s.end <=
|
|
416
|
-
|
|
436
|
+
if (s.end <= t)
|
|
437
|
+
e = s;
|
|
417
438
|
else
|
|
418
439
|
break;
|
|
419
|
-
return
|
|
440
|
+
return e;
|
|
420
441
|
}
|
|
421
442
|
export {
|
|
422
443
|
f as AGGREGATION_FUNCTIONS,
|
|
423
|
-
|
|
444
|
+
p as COLLECTION_OPERATORS,
|
|
424
445
|
l as COMPARISON_OPERATORS,
|
|
425
|
-
|
|
426
|
-
|
|
446
|
+
w as KEYWORDS,
|
|
447
|
+
d as LOGICAL_OPERATORS,
|
|
427
448
|
k as MUTATORS,
|
|
428
449
|
u as NEGATION_SYMBOL_OPERATORS,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
450
|
+
h as SYMBOL_OPERATORS,
|
|
451
|
+
_ as TYPE_HINTS,
|
|
452
|
+
g as TqlTokenizer,
|
|
453
|
+
m as VISUALIZATION_TYPES,
|
|
433
454
|
E as findPreviousToken,
|
|
434
455
|
v as findTokenAtPosition,
|
|
435
456
|
A as findTokenBefore,
|
|
436
457
|
O as findTokensInRange,
|
|
437
|
-
|
|
458
|
+
T as tokenizeTql,
|
|
438
459
|
b as tokenizeTqlNoWhitespace
|
|
439
460
|
};
|
package/dist/src/types.d.ts
CHANGED
|
@@ -70,6 +70,8 @@ export interface TqlStatsExpression {
|
|
|
70
70
|
topN?: number;
|
|
71
71
|
bottomN?: number;
|
|
72
72
|
visualization?: TqlVisualizationType;
|
|
73
|
+
/** Full visualization hint with type and optional parameters */
|
|
74
|
+
vizHint?: TqlVizHint;
|
|
73
75
|
start: number;
|
|
74
76
|
end: number;
|
|
75
77
|
}
|
|
@@ -95,13 +97,35 @@ export interface TqlFieldReference {
|
|
|
95
97
|
start: number;
|
|
96
98
|
end: number;
|
|
97
99
|
}
|
|
98
|
-
export type TqlComparisonOperator = "eq" | "ne" | "=" | "!=" | "==" | "gt" | "gte" | "lt" | "lte" | ">" | ">=" | "<" | "<=" | "contains" | "not_contains" | "!contains" | "startswith" | "not_startswith" | "!startswith" | "endswith" | "not_endswith" | "!endswith" | "regexp" | "regex" | "not_regexp" | "!regexp" | "matches" | "not_matches" | "!matches" | "between" | "not_between" | "!between" | "in" | "not_in" | "!in" | "exists" | "not_exists" | "!exists" | "is" | "is_not" | "!is" | "cidr" | "not_cidr" | "!cidr" | "any" | "all" | "none" | "not_any" | "not_all" | "not_none" | "!any" | "!all" | "!none";
|
|
100
|
+
export type TqlComparisonOperator = "eq" | "ne" | "=" | "!=" | "==" | "eq_ci" | "gt" | "gte" | "lt" | "lte" | ">" | ">=" | "<" | "<=" | "contains" | "not_contains" | "!contains" | "startswith" | "not_startswith" | "!startswith" | "endswith" | "not_endswith" | "!endswith" | "contains_cs" | "not_contains_cs" | "!contains_cs" | "startswith_cs" | "not_startswith_cs" | "!startswith_cs" | "endswith_cs" | "not_endswith_cs" | "!endswith_cs" | "regexp" | "regex" | "not_regexp" | "!regexp" | "matches" | "not_matches" | "!matches" | "between" | "not_between" | "!between" | "in" | "not_in" | "!in" | "in_cs" | "not_in_cs" | "!in_cs" | "exists" | "not_exists" | "!exists" | "is" | "is_not" | "!is" | "cidr" | "not_cidr" | "!cidr" | "any" | "all" | "none" | "not_any" | "not_all" | "not_none" | "!any" | "!all" | "!none";
|
|
99
101
|
export type TqlLogicalOperator = "AND" | "OR" | "NOT";
|
|
100
102
|
export type TqlCollectionOperator = "ANY" | "ALL" | "NONE";
|
|
101
|
-
export type TqlMutator = "lowercase" | "uppercase" | "trim" | "split" | "length" | "replace" | "b64encode" | "b64decode" | "urldecode" | "hexencode" | "hexdecode" | "md5" | "sha256" | "refang" | "defang" | "is_private" | "is_global" | "nslookup" | "geoip_lookup" | "geoip" | "geo" | "any" | "all" | "avg" | "average" | "sum" | "min" | "max";
|
|
103
|
+
export type TqlMutator = "lowercase" | "uppercase" | "trim" | "split" | "length" | "replace" | "b64encode" | "b64decode" | "urldecode" | "hexencode" | "hexdecode" | "md5" | "sha256" | "refang" | "defang" | "is_private" | "is_global" | "is_multicast" | "is_loopback" | "is_link_local" | "nslookup" | "geoip_lookup" | "geoip" | "geo" | "any" | "all" | "avg" | "average" | "sum" | "min" | "max";
|
|
102
104
|
export type TqlAggregationFunction = "count" | "sum" | "avg" | "average" | "mean" | "median" | "med" | "min" | "max" | "percentile" | "percentiles" | "p" | "pct" | "percentile_rank" | "percentile_ranks" | "pct_rank" | "pct_ranks" | "std" | "standard_deviation" | "unique_count" | "cardinality" | "values" | "unique" | "distinct";
|
|
103
105
|
export type TqlTypeHint = "string" | "str" | "number" | "int" | "integer" | "float" | "double" | "decimal" | "date" | "bool" | "boolean" | "array" | "list" | "object" | "geo";
|
|
104
|
-
export type TqlVisualizationType = "bar" | "barchart" | "line" | "area" | "pie" | "donut" | "scatter" | "heatmap" | "treemap" | "sunburst" | "table" | "number" | "gauge" | "map" | "grouped_bar" | "stacked_bar" | "nested_pie" | "nested_donut" | "chord";
|
|
106
|
+
export type TqlVisualizationType = "bar" | "barchart" | "horizontal_bar" | "line" | "area" | "stacked_area" | "pie" | "donut" | "scatter" | "heatmap" | "treemap" | "sunburst" | "table" | "number" | "gauge" | "map" | "grouped_bar" | "stacked_bar" | "nested_pie" | "nested_donut" | "chord" | "auto";
|
|
107
|
+
/**
|
|
108
|
+
* Visualization parameters (e.g., title="Events", stacked=true).
|
|
109
|
+
*/
|
|
110
|
+
export interface TqlVizParams {
|
|
111
|
+
title?: string;
|
|
112
|
+
x_label?: string;
|
|
113
|
+
y_label?: string;
|
|
114
|
+
legend?: string;
|
|
115
|
+
stacked?: boolean;
|
|
116
|
+
donut?: boolean;
|
|
117
|
+
fill?: boolean;
|
|
118
|
+
smooth?: boolean;
|
|
119
|
+
limit?: number;
|
|
120
|
+
[key: string]: string | number | boolean | undefined;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Full visualization hint with type and optional parameters.
|
|
124
|
+
*/
|
|
125
|
+
export interface TqlVizHint {
|
|
126
|
+
type: TqlVisualizationType;
|
|
127
|
+
params?: TqlVizParams;
|
|
128
|
+
}
|
|
105
129
|
export interface TqlParseResult {
|
|
106
130
|
ast: TqlExpression | null;
|
|
107
131
|
tokens: TqlToken[];
|