@tellaro/tql 0.1.15 → 0.1.17
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/src/completionProvider.js +114 -8
- package/dist/src/parser.js +22 -4
- package/dist/src/tokenizer.js +53 -39
- package/dist/src/validator.js +115 -1
- package/dist/style.css +1 -1
- package/dist/vue/TqlInput.vue2.js +21 -3
- package/package.json +1 -1
|
@@ -269,6 +269,107 @@ const E = [
|
|
|
269
269
|
detail: "Maximum value in array",
|
|
270
270
|
documentation: "Returns the maximum value from a numeric array.\n\nExample: cpu_usage | max gt 90\n\nUseful for peak detection."
|
|
271
271
|
}
|
|
272
|
+
}, aggregationDocs = {
|
|
273
|
+
// Counting aggregations
|
|
274
|
+
count: {
|
|
275
|
+
detail: "Count records",
|
|
276
|
+
documentation: "Counts the number of records or non-null field values.\n\nExamples:\n- | stats count()\n- | stats count(user_id) by status\n\nReturns: Integer count"
|
|
277
|
+
},
|
|
278
|
+
unique_count: {
|
|
279
|
+
detail: "Count unique values",
|
|
280
|
+
documentation: "Counts distinct values in a field.\n\nExamples:\n- | stats unique_count(source.ip)\n- | stats unique_count(user.name) by department\n\nReturns: Integer count of unique values"
|
|
281
|
+
},
|
|
282
|
+
cardinality: {
|
|
283
|
+
detail: "Cardinality (unique count)",
|
|
284
|
+
documentation: "Alias for unique_count. Counts distinct values in a field.\n\nExamples:\n- | stats cardinality(user_id)\n\nReturns: Integer count of unique values"
|
|
285
|
+
},
|
|
286
|
+
// Numeric aggregations
|
|
287
|
+
sum: {
|
|
288
|
+
detail: "Sum of values",
|
|
289
|
+
documentation: "Calculates the sum of numeric field values.\n\nExamples:\n- | stats sum(bytes) by hostname\n- | stats sum(request.size)\n\nReturns: Numeric sum"
|
|
290
|
+
},
|
|
291
|
+
min: {
|
|
292
|
+
detail: "Minimum value",
|
|
293
|
+
documentation: "Returns the minimum value from a numeric or date field.\n\nExamples:\n- | stats min(response_time) by endpoint\n- | stats min(@timestamp)\n\nReturns: Minimum value"
|
|
294
|
+
},
|
|
295
|
+
max: {
|
|
296
|
+
detail: "Maximum value",
|
|
297
|
+
documentation: "Returns the maximum value from a numeric or date field.\n\nExamples:\n- | stats max(cpu_usage) by host\n- | stats max(@timestamp)\n\nReturns: Maximum value"
|
|
298
|
+
},
|
|
299
|
+
avg: {
|
|
300
|
+
detail: "Average value",
|
|
301
|
+
documentation: "Calculates the arithmetic mean of numeric field values.\n\nExamples:\n- | stats avg(response_time) by service\n- | stats avg(score)\n\nReturns: Numeric average"
|
|
302
|
+
},
|
|
303
|
+
average: {
|
|
304
|
+
detail: "Average value",
|
|
305
|
+
documentation: "Alias for avg. Calculates the arithmetic mean.\n\nExamples:\n- | stats average(latency) by region"
|
|
306
|
+
},
|
|
307
|
+
mean: {
|
|
308
|
+
detail: "Mean value",
|
|
309
|
+
documentation: "Alias for avg. Calculates the arithmetic mean.\n\nExamples:\n- | stats mean(temperature) by sensor_id"
|
|
310
|
+
},
|
|
311
|
+
median: {
|
|
312
|
+
detail: "Median value",
|
|
313
|
+
documentation: "Returns the median (50th percentile) of numeric values.\n\nExamples:\n- | stats median(response_time) by endpoint\n\nReturns: Median value (50th percentile)"
|
|
314
|
+
},
|
|
315
|
+
med: {
|
|
316
|
+
detail: "Median value",
|
|
317
|
+
documentation: "Alias for median. Returns the 50th percentile.\n\nExamples:\n- | stats med(latency)"
|
|
318
|
+
},
|
|
319
|
+
std: {
|
|
320
|
+
detail: "Standard deviation",
|
|
321
|
+
documentation: "Calculates the standard deviation of numeric values.\n\nExamples:\n- | stats std(response_time) by service\n\nReturns: Standard deviation"
|
|
322
|
+
},
|
|
323
|
+
standard_deviation: {
|
|
324
|
+
detail: "Standard deviation",
|
|
325
|
+
documentation: "Alias for std. Calculates the standard deviation.\n\nExamples:\n- | stats standard_deviation(score) by category"
|
|
326
|
+
},
|
|
327
|
+
// Percentile functions
|
|
328
|
+
percentile: {
|
|
329
|
+
detail: "Percentile value",
|
|
330
|
+
documentation: "Returns a specific percentile of numeric values.\n\nExamples:\n- | stats percentile(response_time, 95) by endpoint\n- | stats percentile(latency, 99)\n\nParameters: field, percentile (0-100)"
|
|
331
|
+
},
|
|
332
|
+
percentiles: {
|
|
333
|
+
detail: "Multiple percentiles",
|
|
334
|
+
documentation: "Returns multiple percentiles at once.\n\nExamples:\n- | stats percentiles(response_time, [50, 90, 95, 99])\n\nParameters: field, array of percentiles"
|
|
335
|
+
},
|
|
336
|
+
p: {
|
|
337
|
+
detail: "Percentile (shorthand)",
|
|
338
|
+
documentation: "Shorthand for percentile function.\n\nExamples:\n- | stats p(latency, 95) by service"
|
|
339
|
+
},
|
|
340
|
+
pct: {
|
|
341
|
+
detail: "Percentile (shorthand)",
|
|
342
|
+
documentation: "Shorthand for percentile function.\n\nExamples:\n- | stats pct(response_time, 99)"
|
|
343
|
+
},
|
|
344
|
+
percentile_rank: {
|
|
345
|
+
detail: "Percentile rank",
|
|
346
|
+
documentation: "Returns the percentile rank of a specific value.\n\nExamples:\n- | stats percentile_rank(response_time, 100) by endpoint\n\nReturns: What percentile the given value falls into"
|
|
347
|
+
},
|
|
348
|
+
percentile_ranks: {
|
|
349
|
+
detail: "Multiple percentile ranks",
|
|
350
|
+
documentation: "Returns percentile ranks for multiple values.\n\nExamples:\n- | stats percentile_ranks(latency, [50, 100, 200])"
|
|
351
|
+
},
|
|
352
|
+
pct_rank: {
|
|
353
|
+
detail: "Percentile rank (shorthand)",
|
|
354
|
+
documentation: "Shorthand for percentile_rank.\n\nExamples:\n- | stats pct_rank(response_time, 100)"
|
|
355
|
+
},
|
|
356
|
+
pct_ranks: {
|
|
357
|
+
detail: "Percentile ranks (shorthand)",
|
|
358
|
+
documentation: "Shorthand for percentile_ranks.\n\nExamples:\n- | stats pct_ranks(latency, [50, 100])"
|
|
359
|
+
},
|
|
360
|
+
// Unique values
|
|
361
|
+
values: {
|
|
362
|
+
detail: "Unique values list",
|
|
363
|
+
documentation: "Returns a list of unique values for a field.\n\nExamples:\n- | stats values(status) by hostname\n\nReturns: Array of unique values"
|
|
364
|
+
},
|
|
365
|
+
unique: {
|
|
366
|
+
detail: "Unique values list",
|
|
367
|
+
documentation: "Alias for values. Returns a list of unique values.\n\nExamples:\n- | stats unique(user.name) by department"
|
|
368
|
+
},
|
|
369
|
+
distinct: {
|
|
370
|
+
detail: "Distinct values list",
|
|
371
|
+
documentation: "Alias for values. Returns a list of distinct values.\n\nExamples:\n- | stats distinct(source.ip)"
|
|
372
|
+
}
|
|
272
373
|
}, h = {
|
|
273
374
|
// String outputs
|
|
274
375
|
lowercase: "keyword",
|
|
@@ -384,7 +485,8 @@ function G(e, t, a) {
|
|
|
384
485
|
// Check if previous token is a mutator - we're inside mutator params
|
|
385
486
|
if (r && r.type === "mutator") {
|
|
386
487
|
const mutatorName = r.value.toLowerCase();
|
|
387
|
-
|
|
488
|
+
// Don't use "(" as partialText - we want to show all params when cursor is right after (
|
|
489
|
+
return { type: "mutator_params", mutatorName: mutatorName, usedParams: [], partialText: undefined };
|
|
388
490
|
}
|
|
389
491
|
return { type: "after_paren" };
|
|
390
492
|
}
|
|
@@ -796,13 +898,17 @@ function W(e) {
|
|
|
796
898
|
function O(e) {
|
|
797
899
|
return R.filter(
|
|
798
900
|
(t) => !e || t.toLowerCase().includes(e.toLowerCase())
|
|
799
|
-
).map((t, a) =>
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
901
|
+
).map((t, a) => {
|
|
902
|
+
const docs = aggregationDocs[t] || { detail: "Aggregation function", documentation: "" };
|
|
903
|
+
return {
|
|
904
|
+
label: t,
|
|
905
|
+
insertText: `${t}($1)`,
|
|
906
|
+
kind: "aggregation",
|
|
907
|
+
detail: docs.detail,
|
|
908
|
+
documentation: docs.documentation,
|
|
909
|
+
sortOrder: 70 + a
|
|
910
|
+
};
|
|
911
|
+
});
|
|
806
912
|
}
|
|
807
913
|
function Z(e) {
|
|
808
914
|
return P.filter(
|
package/dist/src/parser.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
var c = Object.defineProperty;
|
|
2
2
|
var d = (r, e, t) => e in r ? c(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
3
|
var o = (r, e, t) => d(r, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
-
import { tokenizeTql as p, COMPARISON_OPERATORS as v, ENRICHMENT_MUTATORS as ENRICHMENT_MUTATORS } from "./tokenizer.js";
|
|
4
|
+
import { tokenizeTql as p, COMPARISON_OPERATORS as v, ENRICHMENT_MUTATORS as ENRICHMENT_MUTATORS, MUTATORS as ALL_MUTATORS } from "./tokenizer.js";
|
|
5
|
+
import { suggestOperator as suggestOp, suggestMutator as suggestMut } from "./validator.js";
|
|
5
6
|
const f = 50, k = /* @__PURE__ */ new Set(["logicalOp", "paren"]);
|
|
6
7
|
class y {
|
|
7
8
|
constructor(e) {
|
|
@@ -204,7 +205,9 @@ class y {
|
|
|
204
205
|
n.push(s.value.toLowerCase());
|
|
205
206
|
} else if (this.check("field")) {
|
|
206
207
|
const s = this.advance();
|
|
207
|
-
n.push(s.value.toLowerCase())
|
|
208
|
+
n.push(s.value.toLowerCase());
|
|
209
|
+
const suggestion = suggestMut(s.value);
|
|
210
|
+
this.addWarning(`Unknown mutator '${s.value}'`, s, suggestion ? `Did you mean: ${suggestion}?` : "Valid mutators: lowercase, uppercase, trim, geo, nslookup, etc.");
|
|
208
211
|
} else {
|
|
209
212
|
const s = this.isAtEnd() ? this.previous() : this.peek();
|
|
210
213
|
this.addError(
|
|
@@ -257,7 +260,14 @@ class y {
|
|
|
257
260
|
end: t.end
|
|
258
261
|
};
|
|
259
262
|
}
|
|
260
|
-
const i = this.advance()
|
|
263
|
+
const i = this.advance();
|
|
264
|
+
let a = this.normalizeOperator(i.value);
|
|
265
|
+
// Handle unknown operator with suggestions
|
|
266
|
+
if (typeof a === 'object' && a.unknown) {
|
|
267
|
+
const suggestionMsg = a.suggestion ? `Did you mean: ${a.suggestion}?` : "Valid operators: eq, ne, contains, startswith, gt, lt, etc.";
|
|
268
|
+
this.addWarning(`Unknown operator '${a.value}'`, i, suggestionMsg);
|
|
269
|
+
a = a.value; // Use the original value
|
|
270
|
+
}
|
|
261
271
|
if (a === "exists" || a === "not_exists")
|
|
262
272
|
return {
|
|
263
273
|
type: "comparison",
|
|
@@ -470,7 +480,15 @@ class y {
|
|
|
470
480
|
starts_with: "startswith",
|
|
471
481
|
ends_with: "endswith"
|
|
472
482
|
};
|
|
473
|
-
|
|
483
|
+
if (t in a) return a[t];
|
|
484
|
+
// Check if this is a valid operator, if not add a warning with suggestions
|
|
485
|
+
if (!v.includes(t)) {
|
|
486
|
+
const suggestion = suggestOp(t);
|
|
487
|
+
// Return the original value but note that it might be invalid
|
|
488
|
+
// The warning will be added by the caller if needed
|
|
489
|
+
return { value: t, unknown: true, suggestion };
|
|
490
|
+
}
|
|
491
|
+
return t;
|
|
474
492
|
}
|
|
475
493
|
isAtEnd() {
|
|
476
494
|
return this.current >= this.tokens.length;
|
package/dist/src/tokenizer.js
CHANGED
|
@@ -14,81 +14,93 @@ const ENRICHMENT_MUTATORS = [
|
|
|
14
14
|
// e.g., geo(force=true, save=true)
|
|
15
15
|
// Synced with Python TQL ALLOWED_MUTATORS definition
|
|
16
16
|
const MUTATOR_PARAMETERS = {
|
|
17
|
-
// String mutators
|
|
17
|
+
// String transformation mutators
|
|
18
|
+
lowercase: [
|
|
19
|
+
{ name: "field", type: "string", description: "Field name to save the lowercase result. Default: transforms value in-place for comparison only (not persisted)" }
|
|
20
|
+
],
|
|
21
|
+
uppercase: [
|
|
22
|
+
{ name: "field", type: "string", description: "Field name to save the uppercase result. Default: transforms value in-place for comparison only (not persisted)" }
|
|
23
|
+
],
|
|
24
|
+
trim: [
|
|
25
|
+
{ name: "field", type: "string", description: "Field name to save the trimmed result. Default: transforms value in-place for comparison only (not persisted)" }
|
|
26
|
+
],
|
|
18
27
|
split: [
|
|
19
|
-
{ name: "delimiter", type: "string", description: "
|
|
20
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
28
|
+
{ name: "delimiter", type: "string", description: "Character(s) to split on. Default: comma (',')" },
|
|
29
|
+
{ name: "field", type: "string", description: "Field name to save array result. Default: returns array for comparison only (not persisted)" }
|
|
21
30
|
],
|
|
22
31
|
length: [
|
|
23
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
32
|
+
{ name: "field", type: "string", description: "Field name to save the length. Default: returns length for comparison only (not persisted)" }
|
|
24
33
|
],
|
|
25
34
|
replace: [
|
|
26
|
-
{ name: "find", type: "string", description: "Text to
|
|
35
|
+
{ name: "find", type: "string", description: "Text to search for (required)" },
|
|
27
36
|
{ name: "replace", type: "string", description: "Text to replace with (required)" },
|
|
28
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
37
|
+
{ name: "field", type: "string", description: "Field name to save result. Default: returns replaced string for comparison only (not persisted)" }
|
|
29
38
|
],
|
|
30
39
|
// Security mutators
|
|
31
40
|
refang: [
|
|
32
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
41
|
+
{ name: "field", type: "string", description: "Field name to save the refanged result. Default: returns refanged value for comparison only" }
|
|
33
42
|
],
|
|
34
43
|
defang: [
|
|
35
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
44
|
+
{ name: "field", type: "string", description: "Field name to save the defanged result. Default: returns defanged value for comparison only" }
|
|
36
45
|
],
|
|
37
46
|
// Encoding mutators
|
|
38
47
|
b64encode: [
|
|
39
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
48
|
+
{ name: "field", type: "string", description: "Field name to save encoded result. Default: returns encoded value for comparison only" }
|
|
40
49
|
],
|
|
41
50
|
b64decode: [
|
|
42
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
51
|
+
{ name: "field", type: "string", description: "Field name to save decoded result. Default: returns decoded value for comparison only" }
|
|
43
52
|
],
|
|
44
53
|
urldecode: [
|
|
45
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
54
|
+
{ name: "field", type: "string", description: "Field name to save decoded result. Default: returns decoded value for comparison only" }
|
|
46
55
|
],
|
|
47
56
|
hexencode: [
|
|
48
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
57
|
+
{ name: "field", type: "string", description: "Field name to save hex-encoded result. Default: returns encoded value for comparison only" }
|
|
49
58
|
],
|
|
50
59
|
hexdecode: [
|
|
51
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
60
|
+
{ name: "field", type: "string", description: "Field name to save hex-decoded result. Default: returns decoded value for comparison only" }
|
|
52
61
|
],
|
|
53
62
|
md5: [
|
|
54
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
63
|
+
{ name: "field", type: "string", description: "Field name to save the MD5 hash. Default: returns hash for comparison only" }
|
|
55
64
|
],
|
|
56
65
|
sha256: [
|
|
57
|
-
{ name: "field", type: "string", description: "Field name to save
|
|
66
|
+
{ name: "field", type: "string", description: "Field name to save the SHA256 hash. Default: returns hash for comparison only" }
|
|
58
67
|
],
|
|
68
|
+
// Network mutators - no parameters, return boolean
|
|
69
|
+
is_private: [], // Returns boolean indicating if IP is in RFC1918 private ranges
|
|
70
|
+
is_global: [], // Returns boolean indicating if IP is globally routable
|
|
59
71
|
// DNS mutator
|
|
60
72
|
nslookup: [
|
|
61
|
-
{ name: "servers", type: "array", description: "DNS servers to query
|
|
62
|
-
{ name: "types", type: "array", description: "DNS record types to query (
|
|
73
|
+
{ name: "servers", type: "array", description: "DNS servers to query. Default: system DNS servers" },
|
|
74
|
+
{ name: "types", type: "array", description: "DNS record types to query (A, AAAA, MX, TXT, etc.). Default: ['A']" },
|
|
63
75
|
{ name: "append_field", type: "string", description: "Field name to append results to" },
|
|
64
|
-
{ name: "force", type: "boolean", description: "Force lookup even if DNS data already exists" },
|
|
65
|
-
{ name: "save", type: "boolean", description: "Save results to the record" },
|
|
66
|
-
{ name: "field", type: "string", description: "Field name to save results to" }
|
|
76
|
+
{ name: "force", type: "boolean", description: "Force lookup even if DNS data already exists. Default: false" },
|
|
77
|
+
{ name: "save", type: "boolean", description: "Save results to the record. Default: true" },
|
|
78
|
+
{ name: "field", type: "string", description: "Field name to save results to. Default: appends .dns to source field" }
|
|
67
79
|
],
|
|
68
80
|
// GeoIP mutators
|
|
69
81
|
geo: [
|
|
70
|
-
{ name: "db_path", type: "string", description: "Path to MaxMind GeoIP database" },
|
|
71
|
-
{ name: "force", type: "boolean", description: "Force lookup even if geo data
|
|
72
|
-
{ name: "save", type: "boolean", description: "Save
|
|
73
|
-
{ name: "field", type: "string", description: "Field name
|
|
74
|
-
{ name: "cache", type: "boolean", description: "Enable caching of lookup results" },
|
|
75
|
-
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds" }
|
|
82
|
+
{ name: "db_path", type: "string", description: "Path to MaxMind GeoIP database. Default: uses system-configured path" },
|
|
83
|
+
{ name: "force", type: "boolean", description: "Force lookup even if geo data exists. Default: false (skips if data exists)" },
|
|
84
|
+
{ name: "save", type: "boolean", description: "Save enrichment to the record. Default: true" },
|
|
85
|
+
{ name: "field", type: "string", description: "Field name prefix for geo data. Default: appends .geo to source field" },
|
|
86
|
+
{ name: "cache", type: "boolean", description: "Enable caching of lookup results. Default: true" },
|
|
87
|
+
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds. Default: 3600 (1 hour)" }
|
|
76
88
|
],
|
|
77
89
|
geoip: [
|
|
78
|
-
{ name: "db_path", type: "string", description: "Path to MaxMind GeoIP database" },
|
|
79
|
-
{ name: "force", type: "boolean", description: "Force lookup even if geo data
|
|
80
|
-
{ name: "save", type: "boolean", description: "Save
|
|
81
|
-
{ name: "field", type: "string", description: "Field name
|
|
82
|
-
{ name: "cache", type: "boolean", description: "Enable caching of lookup results" },
|
|
83
|
-
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds" }
|
|
90
|
+
{ name: "db_path", type: "string", description: "Path to MaxMind GeoIP database. Default: uses system-configured path" },
|
|
91
|
+
{ name: "force", type: "boolean", description: "Force lookup even if geo data exists. Default: false (skips if data exists)" },
|
|
92
|
+
{ name: "save", type: "boolean", description: "Save enrichment to the record. Default: true" },
|
|
93
|
+
{ name: "field", type: "string", description: "Field name prefix for geo data. Default: appends .geo to source field" },
|
|
94
|
+
{ name: "cache", type: "boolean", description: "Enable caching of lookup results. Default: true" },
|
|
95
|
+
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds. Default: 3600 (1 hour)" }
|
|
84
96
|
],
|
|
85
97
|
geoip_lookup: [
|
|
86
|
-
{ name: "db_path", type: "string", description: "Path to MaxMind GeoIP database" },
|
|
87
|
-
{ name: "force", type: "boolean", description: "Force lookup even if geo data
|
|
88
|
-
{ name: "save", type: "boolean", description: "Save
|
|
89
|
-
{ name: "field", type: "string", description: "Field name
|
|
90
|
-
{ name: "cache", type: "boolean", description: "Enable caching of lookup results" },
|
|
91
|
-
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds" }
|
|
98
|
+
{ name: "db_path", type: "string", description: "Path to MaxMind GeoIP database. Default: uses system-configured path" },
|
|
99
|
+
{ name: "force", type: "boolean", description: "Force lookup even if geo data exists. Default: false (skips if data exists)" },
|
|
100
|
+
{ name: "save", type: "boolean", description: "Save enrichment to the record. Default: true" },
|
|
101
|
+
{ name: "field", type: "string", description: "Field name prefix for geo data. Default: appends .geo to source field" },
|
|
102
|
+
{ name: "cache", type: "boolean", description: "Enable caching of lookup results. Default: true" },
|
|
103
|
+
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds. Default: 3600 (1 hour)" }
|
|
92
104
|
]
|
|
93
105
|
};
|
|
94
106
|
const p = [
|
|
@@ -233,7 +245,9 @@ const p = [
|
|
|
233
245
|
"array",
|
|
234
246
|
"list",
|
|
235
247
|
"object",
|
|
236
|
-
"geo"
|
|
248
|
+
"geo",
|
|
249
|
+
"geo_point",
|
|
250
|
+
"ip"
|
|
237
251
|
], T = [
|
|
238
252
|
"bar",
|
|
239
253
|
"barchart",
|
package/dist/src/validator.js
CHANGED
|
@@ -2,6 +2,7 @@ var b = Object.defineProperty;
|
|
|
2
2
|
var u = (s, e, t) => e in s ? b(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
|
|
3
3
|
var r = (s, e, t) => u(s, typeof e != "symbol" ? e + "" : e, t);
|
|
4
4
|
import { parseTql as c } from "./parser.js";
|
|
5
|
+
import { COMPARISON_OPERATORS, MUTATORS } from "./tokenizer.js";
|
|
5
6
|
const f = {
|
|
6
7
|
// Equality (all types)
|
|
7
8
|
eq: ["text", "keyword", "long", "integer", "double", "float", "date", "boolean", "ip", "nested", "object", "geo_point"],
|
|
@@ -229,6 +230,65 @@ class y {
|
|
|
229
230
|
"Check the regex syntax"
|
|
230
231
|
);
|
|
231
232
|
}
|
|
233
|
+
// CIDR notation validation
|
|
234
|
+
if ((e.operator === "cidr" || e.operator === "not_cidr" || e.operator === "!cidr") && !Array.isArray(e.value) && e.value.valueType === "string" && typeof e.value.value == "string") {
|
|
235
|
+
const cidrValue = e.value.value;
|
|
236
|
+
const ipv4CidrRegex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/;
|
|
237
|
+
const ipv6CidrRegex = /^([0-9a-fA-F:]+)\/(\d{1,3})$/;
|
|
238
|
+
const ipv4Match = cidrValue.match(ipv4CidrRegex);
|
|
239
|
+
const ipv6Match = cidrValue.match(ipv6CidrRegex);
|
|
240
|
+
if (ipv4Match) {
|
|
241
|
+
// Validate IPv4 octets (0-255) and prefix (0-32)
|
|
242
|
+
const octets = [parseInt(ipv4Match[1]), parseInt(ipv4Match[2]), parseInt(ipv4Match[3]), parseInt(ipv4Match[4])];
|
|
243
|
+
const prefix = parseInt(ipv4Match[5]);
|
|
244
|
+
const invalidOctet = octets.find(o => o > 255);
|
|
245
|
+
if (invalidOctet !== undefined) {
|
|
246
|
+
this.addError(
|
|
247
|
+
`Invalid CIDR notation: octet value ${invalidOctet} exceeds 255`,
|
|
248
|
+
e.value.start,
|
|
249
|
+
e.value.end,
|
|
250
|
+
1,
|
|
251
|
+
1,
|
|
252
|
+
"INVALID_CIDR",
|
|
253
|
+
"IPv4 octets must be 0-255 (e.g., 192.168.0.0/24)"
|
|
254
|
+
);
|
|
255
|
+
} else if (prefix > 32) {
|
|
256
|
+
this.addError(
|
|
257
|
+
`Invalid CIDR notation: prefix /${prefix} exceeds maximum /32 for IPv4`,
|
|
258
|
+
e.value.start,
|
|
259
|
+
e.value.end,
|
|
260
|
+
1,
|
|
261
|
+
1,
|
|
262
|
+
"INVALID_CIDR",
|
|
263
|
+
"IPv4 CIDR prefix must be 0-32"
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
} else if (ipv6Match) {
|
|
267
|
+
// Validate IPv6 prefix (0-128)
|
|
268
|
+
const prefix = parseInt(ipv6Match[2]);
|
|
269
|
+
if (prefix > 128) {
|
|
270
|
+
this.addError(
|
|
271
|
+
`Invalid CIDR notation: prefix /${prefix} exceeds maximum /128 for IPv6`,
|
|
272
|
+
e.value.start,
|
|
273
|
+
e.value.end,
|
|
274
|
+
1,
|
|
275
|
+
1,
|
|
276
|
+
"INVALID_CIDR",
|
|
277
|
+
"IPv6 CIDR prefix must be 0-128"
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
this.addError(
|
|
282
|
+
`Invalid CIDR notation: ${cidrValue}`,
|
|
283
|
+
e.value.start,
|
|
284
|
+
e.value.end,
|
|
285
|
+
1,
|
|
286
|
+
1,
|
|
287
|
+
"INVALID_CIDR",
|
|
288
|
+
"Use format like 192.168.0.0/24 (IPv4) or 2001:db8::/32 (IPv6)"
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
232
292
|
}
|
|
233
293
|
/**
|
|
234
294
|
* Suggest a similar field name using Levenshtein distance
|
|
@@ -243,6 +303,36 @@ class y {
|
|
|
243
303
|
}
|
|
244
304
|
return t;
|
|
245
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Suggest a similar operator using Levenshtein distance
|
|
308
|
+
* @param {string} input - The mistyped operator
|
|
309
|
+
* @param {number} maxDistance - Maximum edit distance to consider (default: 2)
|
|
310
|
+
* @returns {string|null} - Suggested operator(s) or null
|
|
311
|
+
*/
|
|
312
|
+
suggestOperator(input, maxDistance = 2) {
|
|
313
|
+
const suggestions = COMPARISON_OPERATORS
|
|
314
|
+
.map(op => ({ op, distance: this.levenshteinDistance(input.toLowerCase(), op.toLowerCase()) }))
|
|
315
|
+
.filter(s => s.distance <= maxDistance && s.distance > 0)
|
|
316
|
+
.sort((a, b) => a.distance - b.distance)
|
|
317
|
+
.slice(0, 3)
|
|
318
|
+
.map(s => s.op);
|
|
319
|
+
return suggestions.length > 0 ? suggestions.join(", ") : null;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Suggest a similar mutator using Levenshtein distance
|
|
323
|
+
* @param {string} input - The mistyped mutator
|
|
324
|
+
* @param {number} maxDistance - Maximum edit distance to consider (default: 2)
|
|
325
|
+
* @returns {string|null} - Suggested mutator(s) or null
|
|
326
|
+
*/
|
|
327
|
+
suggestMutator(input, maxDistance = 2) {
|
|
328
|
+
const suggestions = MUTATORS
|
|
329
|
+
.map(m => ({ m, distance: this.levenshteinDistance(input.toLowerCase(), m.toLowerCase()) }))
|
|
330
|
+
.filter(s => s.distance <= maxDistance && s.distance > 0)
|
|
331
|
+
.sort((a, b) => a.distance - b.distance)
|
|
332
|
+
.slice(0, 3)
|
|
333
|
+
.map(s => s.m);
|
|
334
|
+
return suggestions.length > 0 ? suggestions.join(", ") : null;
|
|
335
|
+
}
|
|
246
336
|
/**
|
|
247
337
|
* Calculate Levenshtein distance between two strings
|
|
248
338
|
*/
|
|
@@ -306,10 +396,34 @@ function v(s) {
|
|
|
306
396
|
return e.join(`
|
|
307
397
|
`);
|
|
308
398
|
}
|
|
399
|
+
/**
|
|
400
|
+
* Standalone function to suggest similar operators
|
|
401
|
+
* @param {string} input - The mistyped operator
|
|
402
|
+
* @param {number} maxDistance - Maximum edit distance to consider (default: 2)
|
|
403
|
+
* @returns {string|null} - Suggested operator(s) or null
|
|
404
|
+
*/
|
|
405
|
+
function suggestOperator(input, maxDistance = 2) {
|
|
406
|
+
const validator = new y();
|
|
407
|
+
return validator.suggestOperator(input, maxDistance);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Standalone function to suggest similar mutators
|
|
412
|
+
* @param {string} input - The mistyped mutator
|
|
413
|
+
* @param {number} maxDistance - Maximum edit distance to consider (default: 2)
|
|
414
|
+
* @returns {string|null} - Suggested mutator(s) or null
|
|
415
|
+
*/
|
|
416
|
+
function suggestMutator(input, maxDistance = 2) {
|
|
417
|
+
const validator = new y();
|
|
418
|
+
return validator.suggestMutator(input, maxDistance);
|
|
419
|
+
}
|
|
420
|
+
|
|
309
421
|
export {
|
|
310
422
|
y as TqlValidator,
|
|
311
423
|
v as formatValidationResult,
|
|
312
424
|
m as getTqlIssues,
|
|
313
425
|
_ as isValidTqlSyntax,
|
|
314
|
-
g as validateTql
|
|
426
|
+
g as validateTql,
|
|
427
|
+
suggestOperator,
|
|
428
|
+
suggestMutator
|
|
315
429
|
};
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.tql-autocomplete-dropdown[data-v-e29dd6a7]{position:fixed;top:var(--dropdown-top);left:var(--dropdown-left);z-index:9999;min-width:280px;max-width:450px;max-height:var(--dropdown-max-height);background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #ddd);border-radius:var(--border-radius, 6px);box-shadow:0 4px 16px #00000026;overflow:hidden;display:flex;flex-direction:column}.tql-completion-list[data-v-e29dd6a7]{overflow-y:auto;max-height:calc(var(--dropdown-max-height) - 60px)}.tql-completion-item[data-v-e29dd6a7]{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background-color .15s}.tql-completion-item[data-v-e29dd6a7]:hover,.tql-completion-item.selected[data-v-e29dd6a7]{background:var(--highlight-bg, #f0f0f0)}.tql-completion-icon[data-v-e29dd6a7]{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:4px;font-size:.75rem}.tql-completion-icon.tql-completion-kind-field[data-v-e29dd6a7]{background:var(--blue-100, #e3f2fd);color:var(--blue-600, #1e88e5)}.tql-completion-icon.tql-completion-kind-operator[data-v-e29dd6a7]{background:var(--pink-100, #fce4ec);color:var(--pink-600, #d81b60)}.tql-completion-icon.tql-completion-kind-value[data-v-e29dd6a7]{background:var(--green-100, #e8f5e9);color:var(--green-600, #43a047)}.tql-completion-icon.tql-completion-kind-keyword[data-v-e29dd6a7]{background:var(--purple-100, #f3e5f5);color:var(--purple-600, #8e24aa)}.tql-completion-icon.tql-completion-kind-snippet[data-v-e29dd6a7]{background:var(--orange-100, #fff3e0);color:var(--orange-600, #fb8c00)}.tql-completion-icon.tql-completion-kind-mutator[data-v-e29dd6a7]{background:var(--cyan-100, #e0f7fa);color:var(--cyan-600, #00acc1)}.tql-completion-icon.tql-completion-kind-aggregation[data-v-e29dd6a7]{background:var(--indigo-100, #e8eaf6);color:var(--indigo-600, #3949ab)}.tql-completion-icon.tql-completion-kind-logicalOp[data-v-e29dd6a7]{background:var(--yellow-100, #fffde7);color:var(--yellow-700, #fbc02d)}.tql-completion-icon.tql-completion-kind-typeHint[data-v-e29dd6a7]{background:var(--teal-100, #e0f2f1);color:var(--teal-600, #00897b)}.tql-completion-icon.tql-completion-kind-visualization[data-v-e29dd6a7]{background:var(--red-100, #ffebee);color:var(--red-600, #e53935)}.tql-completion-content[data-v-e29dd6a7]{flex:1;display:flex;flex-direction:column;min-width:0}.tql-completion-label[data-v-e29dd6a7]{font-family:Courier New,monospace;font-size:.875rem;font-weight:500;color:var(--text-color, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tql-completion-detail[data-v-e29dd6a7]{font-size:.75rem;color:var(--text-color-secondary, #666);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tql-completion-kind-badge[data-v-e29dd6a7]{font-size:.625rem;padding:.125rem .375rem;background:var(--surface-100, #f5f5f5);border-radius:3px;color:var(--text-color-secondary, #666);text-transform:uppercase;letter-spacing:.025em}.tql-completion-docs[data-v-e29dd6a7]{padding:.5rem .75rem;border-top:1px solid var(--surface-border, #ddd);background:var(--surface-50, #fafafa);font-size:.75rem;color:var(--text-color-secondary, #666);max-height:60px;overflow-y:auto}.tql-preview[data-v-bae811e6]{font-family:ui-monospace,monospace;font-size:13px;line-height:1.5;padding:12px;border:1px solid var(--tql-preview-border, #e0e0e0);border-radius:6px;background:var(--tql-preview-bg, #fafafa)}.tql-preview--compact[data-v-bae811e6]{padding:8px;font-size:12px}.tql-preview--empty[data-v-bae811e6]{color:var(--tql-preview-muted, #888)}.tql-preview__empty[data-v-bae811e6]{text-align:center;padding:20px}.tql-preview__complexity[data-v-bae811e6]{display:flex;align-items:center;gap:12px;margin-bottom:12px}.tql-preview__complexity-badge[data-v-bae811e6]{padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;text-transform:uppercase}.tql-preview--low .tql-preview__complexity-badge[data-v-bae811e6]{background:var(--tql-preview-low-bg, #e8f5e9);color:var(--tql-preview-low-text, #2e7d32)}.tql-preview--medium .tql-preview__complexity-badge[data-v-bae811e6]{background:var(--tql-preview-medium-bg, #fff3e0);color:var(--tql-preview-medium-text, #e65100)}.tql-preview--high .tql-preview__complexity-badge[data-v-bae811e6]{background:var(--tql-preview-high-bg, #ffebee);color:var(--tql-preview-high-text, #c62828)}.tql-preview__field-count[data-v-bae811e6]{color:var(--tql-preview-muted, #666);font-size:12px}.tql-preview__warnings[data-v-bae811e6]{margin-bottom:12px}.tql-preview__warning[data-v-bae811e6]{display:flex;align-items:flex-start;gap:8px;padding:6px 8px;border-radius:4px;margin-bottom:4px}.tql-preview__warning--info[data-v-bae811e6]{background:var(--tql-preview-info-bg, #e3f2fd);color:var(--tql-preview-info-text, #1565c0)}.tql-preview__warning--warning[data-v-bae811e6]{background:var(--tql-preview-warning-bg, #fff3e0);color:var(--tql-preview-warning-text, #e65100)}.tql-preview__warning--error[data-v-bae811e6]{background:var(--tql-preview-error-bg, #ffebee);color:var(--tql-preview-error-text, #c62828)}.tql-preview__warning-icon[data-v-bae811e6]{font-weight:700;width:16px;text-align:center}.tql-preview__warning-text[data-v-bae811e6]{flex:1}.tql-preview__suggestions[data-v-bae811e6]{margin-bottom:12px;padding:8px;background:var(--tql-preview-suggestion-bg, #f5f5f5);border-radius:4px}.tql-preview__suggestions-header[data-v-bae811e6]{font-weight:600;margin-bottom:4px;color:var(--tql-preview-header, #333)}.tql-preview__suggestions-list[data-v-bae811e6]{margin:0;padding-left:20px}.tql-preview__suggestion[data-v-bae811e6]{color:var(--tql-preview-muted, #666);margin:2px 0}.tql-preview__tree[data-v-bae811e6]{margin-bottom:12px}.tql-preview__tree-header[data-v-bae811e6],.tql-preview__fields-header[data-v-bae811e6],.tql-preview__operators-header[data-v-bae811e6]{font-weight:600;margin-bottom:8px;color:var(--tql-preview-header, #333);font-size:12px;text-transform:uppercase;letter-spacing:.5px}.tql-preview__tree-content[data-v-bae811e6]{border:1px solid var(--tql-preview-tree-border, #e0e0e0);border-radius:4px;background:var(--tql-preview-tree-bg, #fff);padding:8px}.tql-preview__node[data-v-bae811e6]{margin:2px 0}.tql-preview__node-content[data-v-bae811e6]{display:flex;align-items:center;gap:4px;padding:2px 4px;border-radius:3px;cursor:pointer}.tql-preview__node-content[data-v-bae811e6]:hover{background:var(--tql-preview-node-hover, #f0f0f0)}.tql-preview__node-toggle[data-v-bae811e6]{width:16px;height:16px;border:none;background:var(--tql-preview-toggle-bg, #e0e0e0);border-radius:3px;cursor:pointer;font-size:12px;line-height:1;display:flex;align-items:center;justify-content:center}.tql-preview__node-toggle[data-v-bae811e6]:hover{background:var(--tql-preview-toggle-hover, #d0d0d0)}.tql-preview__node-toggle--leaf[data-v-bae811e6]{visibility:hidden}.tql-preview__node-type[data-v-bae811e6]{font-weight:600;color:var(--tql-preview-node-type, #666)}.tql-preview__node--and .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-and, #1976d2)}.tql-preview__node--or .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-or, #7b1fa2)}.tql-preview__node--not .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-not, #c62828)}.tql-preview__node--group .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-group, #666)}.tql-preview__node-label[data-v-bae811e6]{flex:1}.tql-preview__fields-list[data-v-bae811e6]{display:flex;flex-direction:column;gap:4px}.tql-preview__field[data-v-bae811e6]{display:flex;align-items:center;gap:6px;padding:4px 8px;background:var(--tql-preview-field-bg, #fff);border:1px solid var(--tql-preview-field-border, #e0e0e0);border-radius:4px;cursor:pointer}.tql-preview__field[data-v-bae811e6]:hover{background:var(--tql-preview-field-hover, #f5f5f5)}.tql-preview__field-name[data-v-bae811e6]{font-weight:600;color:var(--tql-preview-field-name, #1976d2)}.tql-preview__field-mutators[data-v-bae811e6]{color:var(--tql-preview-mutator, #7b1fa2)}.tql-preview__field-operator[data-v-bae811e6]{color:var(--tql-preview-operator, #666)}.tql-preview__field-value[data-v-bae811e6]{color:var(--tql-preview-value, #2e7d32)}.tql-preview__match-type[data-v-bae811e6]{margin-left:auto;padding:1px 4px;border-radius:3px;font-size:10px;font-weight:600;background:var(--tql-preview-match-bg, #f0f0f0)}.tql-preview__match-type--exact[data-v-bae811e6]{background:var(--tql-preview-match-exact-bg, #e8f5e9);color:var(--tql-preview-match-exact, #2e7d32)}.tql-preview__match-type--wildcard[data-v-bae811e6]{background:var(--tql-preview-match-wildcard-bg, #fff3e0);color:var(--tql-preview-match-wildcard, #e65100)}.tql-preview__match-type--regex[data-v-bae811e6]{background:var(--tql-preview-match-regex-bg, #fce4ec);color:var(--tql-preview-match-regex, #c2185b)}.tql-preview__match-type--range[data-v-bae811e6]{background:var(--tql-preview-match-range-bg, #e3f2fd);color:var(--tql-preview-match-range, #1565c0)}.tql-preview__match-type--cidr[data-v-bae811e6]{background:var(--tql-preview-match-cidr-bg, #f3e5f5);color:var(--tql-preview-match-cidr, #7b1fa2)}.tql-preview__operators-list[data-v-bae811e6]{display:flex;flex-wrap:wrap;gap:8px}.tql-preview__operator[data-v-bae811e6]{padding:2px 6px;background:var(--tql-preview-op-bg, #f0f0f0);border-radius:3px;font-size:11px}.tql-input-wrapper[data-v-c7135df3]{position:relative;display:flex;align-items:flex-start;border:1px solid var(--surface-border, #ddd);border-radius:var(--border-radius, 6px);background:var(--surface-ground, #fff);transition:border-color .2s,box-shadow .2s}.tql-input-wrapper.tql-input-has-min-height[data-v-c7135df3],.tql-input-wrapper.tql-input-has-min-height .tql-input[data-v-c7135df3]{min-height:var(--tql-min-height)}.tql-input-wrapper.tql-input-focused[data-v-c7135df3]{border-color:var(--primary-color, #3b82f6);box-shadow:0 0 0 2px var(--primary-100, rgba(59, 130, 246, .2))}.tql-input-wrapper.tql-input-invalid[data-v-c7135df3]{border-color:var(--red-500, #ef4444)}.tql-input-wrapper.tql-input-invalid.tql-input-focused[data-v-c7135df3]{box-shadow:0 0 0 2px var(--red-100, rgba(239, 68, 68, .2))}.tql-input-wrapper.tql-input-disabled[data-v-c7135df3]{opacity:.6;cursor:not-allowed}.tql-highlight-layer[data-v-c7135df3]{position:absolute;top:0;left:0;right:0;bottom:0;padding:.5rem .75rem;pointer-events:none;white-space:pre-wrap;word-wrap:break-word;font-family:Courier New,monospace;font-size:.875rem;line-height:1.5;overflow:hidden}.tql-input-multiline .tql-highlight-layer[data-v-c7135df3]{overflow-y:auto}.tql-input[data-v-c7135df3]{flex:1;width:100%;padding:.5rem 8rem .5rem .75rem;border:none;background:transparent;font-family:Courier New,monospace;font-size:.875rem;line-height:1.5;color:var(--text-color, #333);outline:none;resize:none}.tql-input.tql-input-highlighted[data-v-c7135df3]{color:transparent;caret-color:var(--text-color, #333)}.tql-input[data-v-c7135df3]::placeholder{color:var(--text-color-secondary, #666);opacity:.7}.tql-input[data-v-c7135df3]:disabled{cursor:not-allowed}.tql-token-field[data-v-c7135df3]{color:var(--tql-field-color, var(--blue-600, #2563eb))}.tql-token-operator[data-v-c7135df3]{color:var(--tql-operator-color, var(--pink-600, #db2777));font-weight:500}.tql-token-logicalOp[data-v-c7135df3]{color:var(--tql-logical-color, var(--purple-600, #9333ea));font-weight:600}.tql-token-collectionOp[data-v-c7135df3]{color:var(--tql-collection-color, var(--indigo-600, #4f46e5));font-weight:600}.tql-token-string[data-v-c7135df3]{color:var(--tql-string-color, var(--green-600, #16a34a))}.tql-token-number[data-v-c7135df3]{color:var(--tql-number-color, var(--orange-600, #ea580c))}.tql-token-boolean[data-v-c7135df3]{color:var(--tql-boolean-color, var(--cyan-600, #0891b2))}.tql-token-null[data-v-c7135df3]{color:var(--tql-null-color, var(--gray-500, #6b7280));font-style:italic}.tql-token-mutator[data-v-c7135df3]{color:var(--tql-mutator-color, var(--teal-600, #0d9488));font-style:italic}.tql-token-aggregation[data-v-c7135df3]{color:var(--tql-aggregation-color, var(--indigo-600, #4f46e5))}.tql-token-keyword[data-v-c7135df3]{color:var(--tql-keyword-color, var(--purple-500, #a855f7))}.tql-token-typeHint[data-v-c7135df3]{color:var(--tql-typehint-color, var(--teal-500, #14b8a6))}.tql-token-visualization[data-v-c7135df3]{color:var(--tql-viz-color, var(--red-500, #ef4444))}.tql-token-arrow[data-v-c7135df3]{color:var(--tql-arrow-color, var(--gray-600, #4b5563));font-weight:600}.tql-token-doubleColon[data-v-c7135df3]{color:var(--tql-colon-color, var(--gray-500, #6b7280))}.tql-token-paren[data-v-c7135df3],.tql-token-bracket[data-v-c7135df3]{color:var(--tql-bracket-color, var(--gray-600, #4b5563))}.tql-token-error[data-v-c7135df3]{color:var(--tql-error-color, var(--red-600, #dc2626));text-decoration:wavy underline;text-decoration-color:var(--red-400, #f87171)}.tql-token-error-range[data-v-c7135df3]{background-color:var(--red-50, #fef2f2)}.tql-token-unknown[data-v-c7135df3]{color:var(--text-color-secondary, #666)}.tql-validation-icon[data-v-c7135df3]{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);display:flex;align-items:center;justify-content:center}.tql-input-multiline .tql-validation-icon[data-v-c7135df3]{top:.75rem;transform:none}.tql-icon-valid[data-v-c7135df3]{color:var(--green-500, #22c55e)}.tql-icon-invalid[data-v-c7135df3]{color:var(--red-500, #ef4444)}.tql-icon-clickable[data-v-c7135df3]{cursor:pointer;transition:transform .2s}.tql-icon-clickable[data-v-c7135df3]:hover{transform:scale(1.2)}.tql-icon-clickable[data-v-c7135df3]:focus{outline:2px solid var(--primary-color, #3b82f6);outline-offset:2px;border-radius:50%}.tql-snippet-button[data-v-c7135df3]{position:absolute;right:2rem;top:50%;transform:translateY(-50%);padding:.25rem;border:none;background:transparent;color:var(--text-color-secondary, #666);cursor:pointer;border-radius:var(--border-radius, 6px);transition:color .2s,background-color .2s}.tql-snippet-button[data-v-c7135df3]:hover{color:var(--primary-color, #3b82f6);background:var(--surface-100, #f5f5f5)}.tql-input-multiline .tql-snippet-button[data-v-c7135df3]{top:.75rem;transform:none}.tql-input-resizable-textarea[data-v-c7135df3]{resize:vertical;min-height:80px}.tql-input-wrapper.tql-input-resizable[data-v-c7135df3]{height:auto}.tql-input-wrapper.tql-input-resizable .tql-highlight-layer[data-v-c7135df3]{height:100%}.tql-validation-messages[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--red-200, #fecaca);border-radius:var(--border-radius, 6px);padding:.5rem;z-index:10;box-shadow:0 2px 8px #0000001a}.tql-input-autocomplete-active .tql-validation-messages[data-v-c7135df3],.tql-input-autocomplete-active .tql-complexity-warnings[data-v-c7135df3],.tql-input-autocomplete-active .tql-history-dropdown[data-v-c7135df3],.tql-input-autocomplete-active .tql-preview-panel[data-v-c7135df3]{display:none!important}.tql-error-message[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem;color:var(--red-600, #dc2626)}.tql-error-message i[data-v-c7135df3]{margin-top:.125rem;font-size:.75rem}.tql-error-suggestion[data-v-c7135df3]{display:block;color:var(--text-color-secondary, #666);font-style:italic;margin-left:1.25rem}.sr-only[data-v-c7135df3]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.tql-toolbar[data-v-c7135df3]{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:.25rem}.tql-input-multiline .tql-toolbar[data-v-c7135df3]{top:.5rem;transform:none}.tql-toolbar-button[data-v-c7135df3]{padding:.25rem;border:none;background:transparent;color:var(--text-color-secondary, #666);cursor:pointer;border-radius:var(--border-radius, 4px);transition:color .2s,background-color .2s;display:flex;align-items:center;justify-content:center}.tql-toolbar-button[data-v-c7135df3]:hover{color:var(--primary-color, #3b82f6);background:var(--surface-100, #f5f5f5)}.tql-toolbar-button--active[data-v-c7135df3]{color:var(--primary-color, #3b82f6);background:var(--primary-100, rgba(59, 130, 246, .1))}.tql-validation-status[data-v-c7135df3]{display:flex;align-items:center}.tql-complexity-badge[data-v-c7135df3]{display:flex;align-items:center;gap:.25rem;padding:.125rem .5rem;border-radius:9999px;font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.025em}.tql-complexity-low[data-v-c7135df3]{background:var(--green-100, #dcfce7);color:var(--green-700, #15803d)}.tql-complexity-medium[data-v-c7135df3]{background:var(--yellow-100, #fef9c3);color:var(--yellow-700, #a16207)}.tql-complexity-high[data-v-c7135df3]{background:var(--red-100, #fee2e2);color:var(--red-700, #b91c1c)}.tql-complexity-count[data-v-c7135df3]{display:inline-flex;align-items:center;justify-content:center;min-width:1rem;height:1rem;padding:0 .25rem;border-radius:9999px;background:currentColor;color:#fff;font-size:.5rem}.tql-complexity-low .tql-complexity-count[data-v-c7135df3]{background:var(--green-600, #16a34a)}.tql-complexity-medium .tql-complexity-count[data-v-c7135df3]{background:var(--yellow-600, #ca8a04)}.tql-complexity-high .tql-complexity-count[data-v-c7135df3]{background:var(--red-600, #dc2626)}.tql-complexity-warnings[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 6px);padding:.5rem;z-index:9;box-shadow:0 2px 8px #0000001a}.tql-complexity-warning[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem}.tql-complexity-warning i[data-v-c7135df3]{margin-top:.125rem;font-size:.75rem}.tql-complexity-warning--info[data-v-c7135df3]{color:var(--blue-600, #2563eb)}.tql-complexity-warning--warning[data-v-c7135df3]{color:var(--yellow-600, #ca8a04)}.tql-complexity-warning--error[data-v-c7135df3]{color:var(--red-600, #dc2626)}.tql-complexity-suggestions[data-v-c7135df3]{margin-top:.5rem;padding-top:.5rem;border-top:1px solid var(--surface-border, #e0e0e0)}.tql-complexity-suggestion[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem;color:var(--text-color-secondary, #666)}.tql-complexity-suggestion i[data-v-c7135df3]{color:var(--yellow-500, #eab308)}.tql-history-dropdown[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 6px);z-index:20;box-shadow:0 4px 12px #00000026;max-height:300px;overflow:hidden;display:flex;flex-direction:column}.tql-history-header[data-v-c7135df3]{padding:.5rem;border-bottom:1px solid var(--surface-border, #e0e0e0)}.tql-history-search[data-v-c7135df3]{width:100%;padding:.375rem .5rem;border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 4px);font-size:.75rem;outline:none}.tql-history-search[data-v-c7135df3]:focus{border-color:var(--primary-color, #3b82f6)}.tql-history-list[data-v-c7135df3]{overflow-y:auto;flex:1}.tql-history-item[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.5rem;cursor:pointer;border-bottom:1px solid var(--surface-50, #f9fafb);transition:background-color .15s}.tql-history-item[data-v-c7135df3]:hover{background:var(--surface-100, #f5f5f5)}.tql-history-item--favorite[data-v-c7135df3]{background:var(--yellow-50, #fefce8)}.tql-history-item--favorite[data-v-c7135df3]:hover{background:var(--yellow-100, #fef9c3)}.tql-history-favorite[data-v-c7135df3]{padding:.125rem;border:none;background:transparent;color:var(--text-color-secondary, #999);cursor:pointer;flex-shrink:0}.tql-history-favorite[data-v-c7135df3]:hover,.tql-history-item--favorite .tql-history-favorite[data-v-c7135df3]{color:var(--yellow-500, #eab308)}.tql-history-content[data-v-c7135df3]{flex:1;min-width:0}.tql-history-label[data-v-c7135df3]{font-size:.6875rem;font-weight:600;color:var(--text-color, #333);margin-bottom:.125rem}.tql-history-query[data-v-c7135df3]{font-family:Courier New,monospace;font-size:.6875rem;color:var(--text-color-secondary, #666);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tql-history-time[data-v-c7135df3]{font-size:.625rem;color:var(--text-color-secondary, #999);flex-shrink:0}.tql-history-empty[data-v-c7135df3]{padding:1rem;text-align:center;color:var(--text-color-secondary, #666);font-size:.75rem}.tql-preview-panel[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 6px);z-index:15;box-shadow:0 4px 12px #00000026;max-height:400px;overflow:hidden;display:flex;flex-direction:column}.tql-preview-header[data-v-c7135df3]{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;border-bottom:1px solid var(--surface-border, #e0e0e0);font-size:.75rem;font-weight:600;color:var(--text-color, #333)}.tql-preview-close[data-v-c7135df3]{padding:.125rem;border:none;background:transparent;color:var(--text-color-secondary, #666);cursor:pointer;border-radius:var(--border-radius, 4px)}.tql-preview-close[data-v-c7135df3]:hover{background:var(--surface-100, #f5f5f5);color:var(--text-color, #333)}.tql-preview-panel[data-v-c7135df3] .tql-preview{border:none;border-radius:0;max-height:350px;overflow-y:auto}.tql-validation-messages-portal{position:fixed;top:var(--tql-msg-top, 0);left:var(--tql-msg-left, 0);width:var(--tql-msg-width, auto);z-index:9998;background:var(--surface-overlay, #fff);border:2px solid var(--red-500, #ef4444);border-radius:var(--border-radius, 6px);padding:.5rem;box-shadow:0 4px 12px #00000026}.tql-validation-messages-portal .tql-error-message{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem;color:var(--red-600, #dc2626)}.tql-validation-messages-portal .tql-error-message i{margin-top:.125rem;font-size:.75rem}.tql-validation-messages-portal .tql-error-suggestion{display:block;color:var(--text-color-secondary, #6b7280);font-style:italic;margin-left:1.25rem}
|
|
1
|
+
.tql-autocomplete-dropdown[data-v-e29dd6a7]{position:fixed;top:var(--dropdown-top);left:var(--dropdown-left);z-index:9999;min-width:280px;max-width:450px;max-height:var(--dropdown-max-height);background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #ddd);border-radius:var(--border-radius, 6px);box-shadow:0 4px 16px #00000026;overflow:hidden;display:flex;flex-direction:column}.tql-completion-list[data-v-e29dd6a7]{overflow-y:auto;max-height:calc(var(--dropdown-max-height) - 60px)}.tql-completion-item[data-v-e29dd6a7]{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background-color .15s}.tql-completion-item[data-v-e29dd6a7]:hover,.tql-completion-item.selected[data-v-e29dd6a7]{background:var(--highlight-bg, #f0f0f0)}.tql-completion-icon[data-v-e29dd6a7]{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:4px;font-size:.75rem}.tql-completion-icon.tql-completion-kind-field[data-v-e29dd6a7]{background:var(--blue-100, #e3f2fd);color:var(--blue-600, #1e88e5)}.tql-completion-icon.tql-completion-kind-operator[data-v-e29dd6a7]{background:var(--pink-100, #fce4ec);color:var(--pink-600, #d81b60)}.tql-completion-icon.tql-completion-kind-value[data-v-e29dd6a7]{background:var(--green-100, #e8f5e9);color:var(--green-600, #43a047)}.tql-completion-icon.tql-completion-kind-keyword[data-v-e29dd6a7]{background:var(--purple-100, #f3e5f5);color:var(--purple-600, #8e24aa)}.tql-completion-icon.tql-completion-kind-snippet[data-v-e29dd6a7]{background:var(--orange-100, #fff3e0);color:var(--orange-600, #fb8c00)}.tql-completion-icon.tql-completion-kind-mutator[data-v-e29dd6a7]{background:var(--cyan-100, #e0f7fa);color:var(--cyan-600, #00acc1)}.tql-completion-icon.tql-completion-kind-aggregation[data-v-e29dd6a7]{background:var(--indigo-100, #e8eaf6);color:var(--indigo-600, #3949ab)}.tql-completion-icon.tql-completion-kind-logicalOp[data-v-e29dd6a7]{background:var(--yellow-100, #fffde7);color:var(--yellow-700, #fbc02d)}.tql-completion-icon.tql-completion-kind-typeHint[data-v-e29dd6a7]{background:var(--teal-100, #e0f2f1);color:var(--teal-600, #00897b)}.tql-completion-icon.tql-completion-kind-visualization[data-v-e29dd6a7]{background:var(--red-100, #ffebee);color:var(--red-600, #e53935)}.tql-completion-content[data-v-e29dd6a7]{flex:1;display:flex;flex-direction:column;min-width:0}.tql-completion-label[data-v-e29dd6a7]{font-family:Courier New,monospace;font-size:.875rem;font-weight:500;color:var(--text-color, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tql-completion-detail[data-v-e29dd6a7]{font-size:.75rem;color:var(--text-color-secondary, #666);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tql-completion-kind-badge[data-v-e29dd6a7]{font-size:.625rem;padding:.125rem .375rem;background:var(--surface-100, #f5f5f5);border-radius:3px;color:var(--text-color-secondary, #666);text-transform:uppercase;letter-spacing:.025em}.tql-completion-docs[data-v-e29dd6a7]{padding:.5rem .75rem;border-top:1px solid var(--surface-border, #ddd);background:var(--surface-50, #fafafa);font-size:.75rem;color:var(--text-color-secondary, #666);max-height:60px;overflow-y:auto}.tql-preview[data-v-bae811e6]{font-family:ui-monospace,monospace;font-size:13px;line-height:1.5;padding:12px;border:1px solid var(--tql-preview-border, #e0e0e0);border-radius:6px;background:var(--tql-preview-bg, #fafafa)}.tql-preview--compact[data-v-bae811e6]{padding:8px;font-size:12px}.tql-preview--empty[data-v-bae811e6]{color:var(--tql-preview-muted, #888)}.tql-preview__empty[data-v-bae811e6]{text-align:center;padding:20px}.tql-preview__complexity[data-v-bae811e6]{display:flex;align-items:center;gap:12px;margin-bottom:12px}.tql-preview__complexity-badge[data-v-bae811e6]{padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;text-transform:uppercase}.tql-preview--low .tql-preview__complexity-badge[data-v-bae811e6]{background:var(--tql-preview-low-bg, #e8f5e9);color:var(--tql-preview-low-text, #2e7d32)}.tql-preview--medium .tql-preview__complexity-badge[data-v-bae811e6]{background:var(--tql-preview-medium-bg, #fff3e0);color:var(--tql-preview-medium-text, #e65100)}.tql-preview--high .tql-preview__complexity-badge[data-v-bae811e6]{background:var(--tql-preview-high-bg, #ffebee);color:var(--tql-preview-high-text, #c62828)}.tql-preview__field-count[data-v-bae811e6]{color:var(--tql-preview-muted, #666);font-size:12px}.tql-preview__warnings[data-v-bae811e6]{margin-bottom:12px}.tql-preview__warning[data-v-bae811e6]{display:flex;align-items:flex-start;gap:8px;padding:6px 8px;border-radius:4px;margin-bottom:4px}.tql-preview__warning--info[data-v-bae811e6]{background:var(--tql-preview-info-bg, #e3f2fd);color:var(--tql-preview-info-text, #1565c0)}.tql-preview__warning--warning[data-v-bae811e6]{background:var(--tql-preview-warning-bg, #fff3e0);color:var(--tql-preview-warning-text, #e65100)}.tql-preview__warning--error[data-v-bae811e6]{background:var(--tql-preview-error-bg, #ffebee);color:var(--tql-preview-error-text, #c62828)}.tql-preview__warning-icon[data-v-bae811e6]{font-weight:700;width:16px;text-align:center}.tql-preview__warning-text[data-v-bae811e6]{flex:1}.tql-preview__suggestions[data-v-bae811e6]{margin-bottom:12px;padding:8px;background:var(--tql-preview-suggestion-bg, #f5f5f5);border-radius:4px}.tql-preview__suggestions-header[data-v-bae811e6]{font-weight:600;margin-bottom:4px;color:var(--tql-preview-header, #333)}.tql-preview__suggestions-list[data-v-bae811e6]{margin:0;padding-left:20px}.tql-preview__suggestion[data-v-bae811e6]{color:var(--tql-preview-muted, #666);margin:2px 0}.tql-preview__tree[data-v-bae811e6]{margin-bottom:12px}.tql-preview__tree-header[data-v-bae811e6],.tql-preview__fields-header[data-v-bae811e6],.tql-preview__operators-header[data-v-bae811e6]{font-weight:600;margin-bottom:8px;color:var(--tql-preview-header, #333);font-size:12px;text-transform:uppercase;letter-spacing:.5px}.tql-preview__tree-content[data-v-bae811e6]{border:1px solid var(--tql-preview-tree-border, #e0e0e0);border-radius:4px;background:var(--tql-preview-tree-bg, #fff);padding:8px}.tql-preview__node[data-v-bae811e6]{margin:2px 0}.tql-preview__node-content[data-v-bae811e6]{display:flex;align-items:center;gap:4px;padding:2px 4px;border-radius:3px;cursor:pointer}.tql-preview__node-content[data-v-bae811e6]:hover{background:var(--tql-preview-node-hover, #f0f0f0)}.tql-preview__node-toggle[data-v-bae811e6]{width:16px;height:16px;border:none;background:var(--tql-preview-toggle-bg, #e0e0e0);border-radius:3px;cursor:pointer;font-size:12px;line-height:1;display:flex;align-items:center;justify-content:center}.tql-preview__node-toggle[data-v-bae811e6]:hover{background:var(--tql-preview-toggle-hover, #d0d0d0)}.tql-preview__node-toggle--leaf[data-v-bae811e6]{visibility:hidden}.tql-preview__node-type[data-v-bae811e6]{font-weight:600;color:var(--tql-preview-node-type, #666)}.tql-preview__node--and .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-and, #1976d2)}.tql-preview__node--or .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-or, #7b1fa2)}.tql-preview__node--not .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-not, #c62828)}.tql-preview__node--group .tql-preview__node-type[data-v-bae811e6]{color:var(--tql-preview-group, #666)}.tql-preview__node-label[data-v-bae811e6]{flex:1}.tql-preview__fields-list[data-v-bae811e6]{display:flex;flex-direction:column;gap:4px}.tql-preview__field[data-v-bae811e6]{display:flex;align-items:center;gap:6px;padding:4px 8px;background:var(--tql-preview-field-bg, #fff);border:1px solid var(--tql-preview-field-border, #e0e0e0);border-radius:4px;cursor:pointer}.tql-preview__field[data-v-bae811e6]:hover{background:var(--tql-preview-field-hover, #f5f5f5)}.tql-preview__field-name[data-v-bae811e6]{font-weight:600;color:var(--tql-preview-field-name, #1976d2)}.tql-preview__field-mutators[data-v-bae811e6]{color:var(--tql-preview-mutator, #7b1fa2)}.tql-preview__field-operator[data-v-bae811e6]{color:var(--tql-preview-operator, #666)}.tql-preview__field-value[data-v-bae811e6]{color:var(--tql-preview-value, #2e7d32)}.tql-preview__match-type[data-v-bae811e6]{margin-left:auto;padding:1px 4px;border-radius:3px;font-size:10px;font-weight:600;background:var(--tql-preview-match-bg, #f0f0f0)}.tql-preview__match-type--exact[data-v-bae811e6]{background:var(--tql-preview-match-exact-bg, #e8f5e9);color:var(--tql-preview-match-exact, #2e7d32)}.tql-preview__match-type--wildcard[data-v-bae811e6]{background:var(--tql-preview-match-wildcard-bg, #fff3e0);color:var(--tql-preview-match-wildcard, #e65100)}.tql-preview__match-type--regex[data-v-bae811e6]{background:var(--tql-preview-match-regex-bg, #fce4ec);color:var(--tql-preview-match-regex, #c2185b)}.tql-preview__match-type--range[data-v-bae811e6]{background:var(--tql-preview-match-range-bg, #e3f2fd);color:var(--tql-preview-match-range, #1565c0)}.tql-preview__match-type--cidr[data-v-bae811e6]{background:var(--tql-preview-match-cidr-bg, #f3e5f5);color:var(--tql-preview-match-cidr, #7b1fa2)}.tql-preview__operators-list[data-v-bae811e6]{display:flex;flex-wrap:wrap;gap:8px}.tql-preview__operator[data-v-bae811e6]{padding:2px 6px;background:var(--tql-preview-op-bg, #f0f0f0);border-radius:3px;font-size:11px}.tql-input-wrapper[data-v-c7135df3]{position:relative;display:flex;align-items:flex-start;border:1px solid var(--surface-border, #ddd);border-radius:var(--border-radius, 6px);background:var(--surface-ground, #fff);transition:border-color .2s,box-shadow .2s}.tql-input-wrapper.tql-input-has-min-height[data-v-c7135df3],.tql-input-wrapper.tql-input-has-min-height .tql-input[data-v-c7135df3]{min-height:var(--tql-min-height)}.tql-input-wrapper.tql-input-focused[data-v-c7135df3]{border-color:var(--primary-color, #3b82f6);box-shadow:0 0 0 2px var(--primary-100, rgba(59, 130, 246, .2))}.tql-input-wrapper.tql-input-invalid[data-v-c7135df3]{border-color:var(--red-500, #ef4444)}.tql-input-wrapper.tql-input-invalid.tql-input-focused[data-v-c7135df3]{box-shadow:0 0 0 2px var(--red-100, rgba(239, 68, 68, .2))}.tql-input-wrapper.tql-input-valid[data-v-c7135df3]{border-color:var(--tql-valid-color, var(--green-500, #22c55e))}.tql-input-wrapper.tql-input-valid.tql-input-focused[data-v-c7135df3]{box-shadow:0 0 0 2px var(--green-100, rgba(34, 197, 94, .2))}.tql-input-wrapper.tql-input-slow[data-v-c7135df3]{border-color:var(--tql-slow-color, var(--yellow-500, #eab308))}.tql-input-wrapper.tql-input-slow.tql-input-focused[data-v-c7135df3]{box-shadow:0 0 0 2px var(--yellow-100, rgba(234, 179, 8, .2))}.tql-slow-indicator[data-v-c7135df3]{color:var(--tql-slow-color, var(--yellow-500, #eab308));margin-left:4px;cursor:help}.tql-input-wrapper.tql-input-disabled[data-v-c7135df3]{opacity:.6;cursor:not-allowed}.tql-highlight-layer[data-v-c7135df3]{position:absolute;top:0;left:0;right:0;bottom:0;padding:.5rem .75rem;pointer-events:none;white-space:pre-wrap;word-wrap:break-word;font-family:Courier New,monospace;font-size:.875rem;line-height:1.5;overflow:hidden}.tql-input-multiline .tql-highlight-layer[data-v-c7135df3]{overflow-y:auto}.tql-input[data-v-c7135df3]{flex:1;width:100%;padding:.5rem 8rem .5rem .75rem;border:none;background:transparent;font-family:Courier New,monospace;font-size:.875rem;line-height:1.5;color:var(--text-color, #333);outline:none;resize:none}.tql-input.tql-input-highlighted[data-v-c7135df3]{color:transparent;caret-color:var(--text-color, #333)}.tql-input[data-v-c7135df3]::placeholder{color:var(--text-color-secondary, #666);opacity:.7}.tql-input[data-v-c7135df3]:disabled{cursor:not-allowed}.tql-token-field[data-v-c7135df3]{color:var(--tql-field-color, var(--blue-600, #2563eb))}.tql-token-operator[data-v-c7135df3]{color:var(--tql-operator-color, var(--pink-600, #db2777));font-weight:500}.tql-token-logicalOp[data-v-c7135df3]{color:var(--tql-logical-color, var(--purple-600, #9333ea));font-weight:600}.tql-token-collectionOp[data-v-c7135df3]{color:var(--tql-collection-color, var(--indigo-600, #4f46e5));font-weight:600}.tql-token-string[data-v-c7135df3]{color:var(--tql-string-color, var(--green-600, #16a34a))}.tql-token-number[data-v-c7135df3]{color:var(--tql-number-color, var(--orange-600, #ea580c))}.tql-token-boolean[data-v-c7135df3]{color:var(--tql-boolean-color, var(--cyan-600, #0891b2))}.tql-token-null[data-v-c7135df3]{color:var(--tql-null-color, var(--gray-500, #6b7280));font-style:italic}.tql-token-mutator[data-v-c7135df3]{color:var(--tql-mutator-color, var(--teal-600, #0d9488));font-style:italic}.tql-token-aggregation[data-v-c7135df3]{color:var(--tql-aggregation-color, var(--indigo-600, #4f46e5))}.tql-token-keyword[data-v-c7135df3]{color:var(--tql-keyword-color, var(--purple-500, #a855f7))}.tql-token-typeHint[data-v-c7135df3]{color:var(--tql-typehint-color, var(--teal-500, #14b8a6))}.tql-token-visualization[data-v-c7135df3]{color:var(--tql-viz-color, var(--red-500, #ef4444))}.tql-token-arrow[data-v-c7135df3]{color:var(--tql-arrow-color, var(--gray-600, #4b5563));font-weight:600}.tql-token-doubleColon[data-v-c7135df3]{color:var(--tql-colon-color, var(--gray-500, #6b7280))}.tql-token-paren[data-v-c7135df3],.tql-token-bracket[data-v-c7135df3]{color:var(--tql-bracket-color, var(--gray-600, #4b5563))}.tql-token-error[data-v-c7135df3]{color:var(--tql-error-color, var(--red-600, #dc2626));text-decoration:wavy underline;text-decoration-color:var(--red-400, #f87171)}.tql-token-error-range[data-v-c7135df3]{background-color:var(--red-50, #fef2f2)}.tql-token-unknown[data-v-c7135df3]{color:var(--text-color-secondary, #666)}.tql-validation-icon[data-v-c7135df3]{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);display:flex;align-items:center;justify-content:center}.tql-input-multiline .tql-validation-icon[data-v-c7135df3]{top:.75rem;transform:none}.tql-icon-valid[data-v-c7135df3]{color:var(--green-500, #22c55e)}.tql-icon-invalid[data-v-c7135df3]{color:var(--red-500, #ef4444)}.tql-icon-clickable[data-v-c7135df3]{cursor:pointer;transition:transform .2s}.tql-icon-clickable[data-v-c7135df3]:hover{transform:scale(1.2)}.tql-icon-clickable[data-v-c7135df3]:focus{outline:2px solid var(--primary-color, #3b82f6);outline-offset:2px;border-radius:50%}.tql-snippet-button[data-v-c7135df3]{position:absolute;right:2rem;top:50%;transform:translateY(-50%);padding:.25rem;border:none;background:transparent;color:var(--text-color-secondary, #666);cursor:pointer;border-radius:var(--border-radius, 6px);transition:color .2s,background-color .2s}.tql-snippet-button[data-v-c7135df3]:hover{color:var(--primary-color, #3b82f6);background:var(--surface-100, #f5f5f5)}.tql-input-multiline .tql-snippet-button[data-v-c7135df3]{top:.75rem;transform:none}.tql-input-resizable-textarea[data-v-c7135df3]{resize:vertical;min-height:80px}.tql-input-wrapper.tql-input-resizable[data-v-c7135df3]{height:auto}.tql-input-wrapper.tql-input-resizable .tql-highlight-layer[data-v-c7135df3]{height:100%}.tql-validation-messages[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--red-200, #fecaca);border-radius:var(--border-radius, 6px);padding:.5rem;z-index:10;box-shadow:0 2px 8px #0000001a}.tql-input-autocomplete-active .tql-validation-messages[data-v-c7135df3],.tql-input-autocomplete-active .tql-complexity-warnings[data-v-c7135df3],.tql-input-autocomplete-active .tql-history-dropdown[data-v-c7135df3],.tql-input-autocomplete-active .tql-preview-panel[data-v-c7135df3]{display:none!important}.tql-error-message[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem;color:var(--red-600, #dc2626)}.tql-error-message i[data-v-c7135df3]{margin-top:.125rem;font-size:.75rem}.tql-error-suggestion[data-v-c7135df3]{display:block;color:var(--text-color-secondary, #666);font-style:italic;margin-left:1.25rem}.sr-only[data-v-c7135df3]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.tql-toolbar[data-v-c7135df3]{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:.25rem}.tql-input-multiline .tql-toolbar[data-v-c7135df3]{top:.5rem;transform:none}.tql-toolbar-button[data-v-c7135df3]{padding:.25rem;border:none;background:transparent;color:var(--text-color-secondary, #666);cursor:pointer;border-radius:var(--border-radius, 4px);transition:color .2s,background-color .2s;display:flex;align-items:center;justify-content:center}.tql-toolbar-button[data-v-c7135df3]:hover{color:var(--primary-color, #3b82f6);background:var(--surface-100, #f5f5f5)}.tql-toolbar-button--active[data-v-c7135df3]{color:var(--primary-color, #3b82f6);background:var(--primary-100, rgba(59, 130, 246, .1))}.tql-validation-status[data-v-c7135df3]{display:flex;align-items:center}.tql-complexity-badge[data-v-c7135df3]{display:flex;align-items:center;gap:.25rem;padding:.125rem .5rem;border-radius:9999px;font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.025em}.tql-complexity-low[data-v-c7135df3]{background:var(--green-100, #dcfce7);color:var(--green-700, #15803d)}.tql-complexity-medium[data-v-c7135df3]{background:var(--yellow-100, #fef9c3);color:var(--yellow-700, #a16207)}.tql-complexity-high[data-v-c7135df3]{background:var(--red-100, #fee2e2);color:var(--red-700, #b91c1c)}.tql-complexity-count[data-v-c7135df3]{display:inline-flex;align-items:center;justify-content:center;min-width:1rem;height:1rem;padding:0 .25rem;border-radius:9999px;background:currentColor;color:#fff;font-size:.5rem}.tql-complexity-low .tql-complexity-count[data-v-c7135df3]{background:var(--green-600, #16a34a)}.tql-complexity-medium .tql-complexity-count[data-v-c7135df3]{background:var(--yellow-600, #ca8a04)}.tql-complexity-high .tql-complexity-count[data-v-c7135df3]{background:var(--red-600, #dc2626)}.tql-complexity-warnings[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 6px);padding:.5rem;z-index:9;box-shadow:0 2px 8px #0000001a}.tql-complexity-warning[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem}.tql-complexity-warning i[data-v-c7135df3]{margin-top:.125rem;font-size:.75rem}.tql-complexity-warning--info[data-v-c7135df3]{color:var(--blue-600, #2563eb)}.tql-complexity-warning--warning[data-v-c7135df3]{color:var(--yellow-600, #ca8a04)}.tql-complexity-warning--error[data-v-c7135df3]{color:var(--red-600, #dc2626)}.tql-complexity-suggestions[data-v-c7135df3]{margin-top:.5rem;padding-top:.5rem;border-top:1px solid var(--surface-border, #e0e0e0)}.tql-complexity-suggestion[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem;color:var(--text-color-secondary, #666)}.tql-complexity-suggestion i[data-v-c7135df3]{color:var(--yellow-500, #eab308)}.tql-history-dropdown[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 6px);z-index:20;box-shadow:0 4px 12px #00000026;max-height:300px;overflow:hidden;display:flex;flex-direction:column}.tql-history-header[data-v-c7135df3]{padding:.5rem;border-bottom:1px solid var(--surface-border, #e0e0e0)}.tql-history-search[data-v-c7135df3]{width:100%;padding:.375rem .5rem;border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 4px);font-size:.75rem;outline:none}.tql-history-search[data-v-c7135df3]:focus{border-color:var(--primary-color, #3b82f6)}.tql-history-list[data-v-c7135df3]{overflow-y:auto;flex:1}.tql-history-item[data-v-c7135df3]{display:flex;align-items:flex-start;gap:.5rem;padding:.5rem;cursor:pointer;border-bottom:1px solid var(--surface-50, #f9fafb);transition:background-color .15s}.tql-history-item[data-v-c7135df3]:hover{background:var(--surface-100, #f5f5f5)}.tql-history-item--favorite[data-v-c7135df3]{background:var(--yellow-50, #fefce8)}.tql-history-item--favorite[data-v-c7135df3]:hover{background:var(--yellow-100, #fef9c3)}.tql-history-favorite[data-v-c7135df3]{padding:.125rem;border:none;background:transparent;color:var(--text-color-secondary, #999);cursor:pointer;flex-shrink:0}.tql-history-favorite[data-v-c7135df3]:hover,.tql-history-item--favorite .tql-history-favorite[data-v-c7135df3]{color:var(--yellow-500, #eab308)}.tql-history-content[data-v-c7135df3]{flex:1;min-width:0}.tql-history-label[data-v-c7135df3]{font-size:.6875rem;font-weight:600;color:var(--text-color, #333);margin-bottom:.125rem}.tql-history-query[data-v-c7135df3]{font-family:Courier New,monospace;font-size:.6875rem;color:var(--text-color-secondary, #666);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tql-history-time[data-v-c7135df3]{font-size:.625rem;color:var(--text-color-secondary, #999);flex-shrink:0}.tql-history-empty[data-v-c7135df3]{padding:1rem;text-align:center;color:var(--text-color-secondary, #666);font-size:.75rem}.tql-preview-panel[data-v-c7135df3]{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background:var(--surface-overlay, #fff);border:1px solid var(--surface-border, #e0e0e0);border-radius:var(--border-radius, 6px);z-index:15;box-shadow:0 4px 12px #00000026;max-height:400px;overflow:hidden;display:flex;flex-direction:column}.tql-preview-header[data-v-c7135df3]{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;border-bottom:1px solid var(--surface-border, #e0e0e0);font-size:.75rem;font-weight:600;color:var(--text-color, #333)}.tql-preview-close[data-v-c7135df3]{padding:.125rem;border:none;background:transparent;color:var(--text-color-secondary, #666);cursor:pointer;border-radius:var(--border-radius, 4px)}.tql-preview-close[data-v-c7135df3]:hover{background:var(--surface-100, #f5f5f5);color:var(--text-color, #333)}.tql-preview-panel[data-v-c7135df3] .tql-preview{border:none;border-radius:0;max-height:350px;overflow-y:auto}.tql-validation-messages-portal{position:fixed;top:var(--tql-msg-top, 0);left:var(--tql-msg-left, 0);width:var(--tql-msg-width, auto);z-index:9998;background:var(--surface-overlay, #fff);border:2px solid var(--red-500, #ef4444);border-radius:var(--border-radius, 6px);padding:.5rem;box-shadow:0 4px 12px #00000026}.tql-validation-messages-portal .tql-error-message{display:flex;align-items:flex-start;gap:.5rem;padding:.25rem 0;font-size:.75rem;color:var(--red-600, #dc2626)}.tql-validation-messages-portal .tql-error-message i{margin-top:.125rem;font-size:.75rem}.tql-validation-messages-portal .tql-error-suggestion{display:block;color:var(--text-color-secondary, #6b7280);font-style:italic;margin-left:1.25rem}
|
|
@@ -4,6 +4,7 @@ import st from "./components/TqlPreview.vue.js";
|
|
|
4
4
|
import { useTqlInput as ut } from "./useTqlInput.js";
|
|
5
5
|
import { useQueryHistory as rt } from "./composables/useQueryHistory.js";
|
|
6
6
|
import { analyzeComplexity as ct } from "../src/complexityAnalyzer.js";
|
|
7
|
+
import { ENRICHMENT_MUTATORS as SLOW_MUTATORS } from "../src/tokenizer.js";
|
|
7
8
|
const dt = {
|
|
8
9
|
key: 0,
|
|
9
10
|
class: "tql-highlight-layer",
|
|
@@ -107,7 +108,17 @@ const dt = {
|
|
|
107
108
|
low: "Low",
|
|
108
109
|
medium: "Medium",
|
|
109
110
|
high: "High"
|
|
110
|
-
}[g.value.score] || ""),
|
|
111
|
+
}[g.value.score] || ""), queryState = H(() => {
|
|
112
|
+
if (!u.value.trim()) return "empty";
|
|
113
|
+
if (E.value) return "invalid";
|
|
114
|
+
// Check for enrichment/slow mutators in tokens
|
|
115
|
+
const hasSlow = Ie.value.some(t =>
|
|
116
|
+
t.type === "mutator" && SLOW_MUTATORS.includes(t.value.toLowerCase())
|
|
117
|
+
);
|
|
118
|
+
if (hasSlow) return "slow";
|
|
119
|
+
if (ie.value) return "valid";
|
|
120
|
+
return "unknown";
|
|
121
|
+
}), ve = H(() => $ ? T.value.trim() ? $.searchHistory(T.value).slice(0, 10) : $.getRecentQueries(10) : []);
|
|
111
122
|
function Qe(e) {
|
|
112
123
|
u.value = e.query, q("update:modelValue", e.query), ce(e.query), D.value = !1, T.value = "", P(() => {
|
|
113
124
|
var t;
|
|
@@ -397,6 +408,8 @@ const dt = {
|
|
|
397
408
|
{
|
|
398
409
|
"tql-input-focused": x.value,
|
|
399
410
|
"tql-input-invalid": r(E) && n.showValidation,
|
|
411
|
+
"tql-input-valid": queryState.value === "valid" && n.showValidation && u.value.trim(),
|
|
412
|
+
"tql-input-slow": queryState.value === "slow" && n.showValidation && u.value.trim(),
|
|
400
413
|
"tql-input-disabled": n.disabled,
|
|
401
414
|
"tql-input-multiline": n.multiline,
|
|
402
415
|
"tql-input-autocomplete-active": r(C),
|
|
@@ -506,8 +519,13 @@ const dt = {
|
|
|
506
519
|
c("i", { class: "pi pi-code" }, null, -1)
|
|
507
520
|
])])) : m("", !0),
|
|
508
521
|
n.showValidation && u.value ? (a(), s("div", gt, [
|
|
509
|
-
|
|
510
|
-
key:
|
|
522
|
+
queryState.value === "slow" ? (a(), s("i", {
|
|
523
|
+
key: 0,
|
|
524
|
+
class: "pi pi-clock tql-slow-indicator",
|
|
525
|
+
title: "This query uses enrichment mutators (geo, nslookup) which require post-processing and may be slower"
|
|
526
|
+
})) : m("", !0),
|
|
527
|
+
r(ie) && queryState.value !== "slow" ? (a(), s("i", { key: 1, class: "pi pi-check-circle tql-icon-valid", "aria-label": "Query is valid" })) : queryState.value === "slow" && r(ie) ? (a(), s("i", { key: 2, class: "pi pi-check-circle tql-icon-valid", "aria-label": "Query is valid (with enrichment)" })) : (a(), s("i", {
|
|
528
|
+
key: 3,
|
|
511
529
|
class: "pi pi-exclamation-circle tql-icon-invalid tql-icon-clickable",
|
|
512
530
|
role: "button",
|
|
513
531
|
tabindex: "0",
|