@tellaro/tql 0.1.11 → 0.1.13
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var I = Object.defineProperty;
|
|
2
2
|
var S = (e, t, a) => t in e ? I(e, t, { enumerable: !0, configurable: !0, writable: !0, value: a }) : e[t] = a;
|
|
3
3
|
var p = (e, t, a) => S(e, typeof t != "symbol" ? t + "" : t, a);
|
|
4
|
-
import { tokenizeTql as b, COMPARISON_OPERATORS as A, LOGICAL_OPERATORS as L, AGGREGATION_FUNCTIONS as R, VISUALIZATION_TYPES as $, TYPE_HINTS as P, MUTATORS as D } from "./tokenizer.js";
|
|
4
|
+
import { tokenizeTql as b, COMPARISON_OPERATORS as A, LOGICAL_OPERATORS as L, AGGREGATION_FUNCTIONS as R, VISUALIZATION_TYPES as $, TYPE_HINTS as P, MUTATORS as D, ENRICHMENT_MUTATORS as ENRICHMENT_MUTATORS, MUTATOR_PARAMETERS as MUTATOR_PARAMETERS } from "./tokenizer.js";
|
|
5
5
|
import { fuzzyMatch as _ } from "./fuzzyMatcher.js";
|
|
6
6
|
import { getSchemaCache as M } from "./schemaCache.js";
|
|
7
7
|
const E = [
|
|
@@ -281,8 +281,14 @@ function G(e, t, a) {
|
|
|
281
281
|
const n = o[o.length - 1], r = o.length > 1 ? o[o.length - 2] : null, d = n.end === t && !((u = e[t - 1]) != null && u.match(/\s/)), s = d ? n.value : void 0;
|
|
282
282
|
if (n.type === "logicalOp")
|
|
283
283
|
return { type: "start" };
|
|
284
|
-
if (n.type === "paren" && n.value === "(")
|
|
284
|
+
if (n.type === "paren" && n.value === "(") {
|
|
285
|
+
// Check if previous token is a mutator - we're inside mutator params
|
|
286
|
+
if (r && r.type === "mutator") {
|
|
287
|
+
const mutatorName = r.value.toLowerCase();
|
|
288
|
+
return { type: "mutator_params", mutatorName: mutatorName, usedParams: [], partialText: s };
|
|
289
|
+
}
|
|
285
290
|
return { type: "after_paren" };
|
|
291
|
+
}
|
|
286
292
|
if (n.type === "arrow")
|
|
287
293
|
return { type: "after_arrow", partialText: s };
|
|
288
294
|
if (n.type === "doubleColon")
|
|
@@ -358,7 +364,15 @@ function ae(e, t = {}) {
|
|
|
358
364
|
n.push(...x(o.partialText, o.fieldType)), n.push(H());
|
|
359
365
|
break;
|
|
360
366
|
case "after_mutator":
|
|
361
|
-
|
|
367
|
+
// Check if this is an enrichment mutator (geo, nslookup, etc.)
|
|
368
|
+
// Enrichment mutators don't need operators - they transform the field into enriched data
|
|
369
|
+
if (o.mutatorName && ENRICHMENT_MUTATORS.includes(o.mutatorName)) {
|
|
370
|
+
// Suggest logical operators (AND, OR) or pipe for chaining
|
|
371
|
+
n.push(...C());
|
|
372
|
+
n.push(H());
|
|
373
|
+
} else {
|
|
374
|
+
n.push(...x(o.partialText, o.mutatorOutputType));
|
|
375
|
+
}
|
|
362
376
|
break;
|
|
363
377
|
case "after_operator":
|
|
364
378
|
n.push(...Y(o.fieldName, t));
|
|
@@ -383,6 +397,9 @@ function ae(e, t = {}) {
|
|
|
383
397
|
case "after_by":
|
|
384
398
|
n.push(...y(t.fields, o.partialText));
|
|
385
399
|
break;
|
|
400
|
+
case "mutator_params":
|
|
401
|
+
n.push(...getMutatorParameterCompletions(o.mutatorName, o.usedParams, o.partialText));
|
|
402
|
+
break;
|
|
386
403
|
default:
|
|
387
404
|
n.push(...y(t.fields, o.partialText)), n.push(...x(o.partialText)), n.push(...C());
|
|
388
405
|
}
|
|
@@ -612,9 +629,21 @@ function W(e) {
|
|
|
612
629
|
return D.filter((t) => !e || t.toLowerCase().includes(e.toLowerCase())).map(
|
|
613
630
|
(t, a) => {
|
|
614
631
|
const i = z[t] || { detail: "Field mutator", documentation: "" };
|
|
632
|
+
// Check if this is an enrichment mutator that supports parameters
|
|
633
|
+
const isEnrichment = ENRICHMENT_MUTATORS.includes(t);
|
|
634
|
+
const hasParams = MUTATOR_PARAMETERS[t] && MUTATOR_PARAMETERS[t].length > 0;
|
|
635
|
+
// Enrichment mutators with params get () inserted, cursor inside
|
|
636
|
+
// Enrichment mutators without params get () inserted, cursor after
|
|
637
|
+
// Regular mutators get no parens
|
|
638
|
+
let insertText = t;
|
|
639
|
+
if (isEnrichment && hasParams) {
|
|
640
|
+
insertText = `${t}($1)`;
|
|
641
|
+
} else if (isEnrichment) {
|
|
642
|
+
insertText = `${t}()`;
|
|
643
|
+
}
|
|
615
644
|
return {
|
|
616
645
|
label: t,
|
|
617
|
-
insertText:
|
|
646
|
+
insertText: insertText,
|
|
618
647
|
kind: "mutator",
|
|
619
648
|
detail: i.detail,
|
|
620
649
|
documentation: i.documentation,
|
|
@@ -674,6 +703,52 @@ function ie(e, t, a) {
|
|
|
674
703
|
const i = b(e.substring(0, t)), o = i[i.length - 1];
|
|
675
704
|
return !!(o && o.type === "field" && o.value.length >= 2);
|
|
676
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* Get mutator parameter completions
|
|
708
|
+
* @param mutatorName - The mutator name (e.g., "geo", "nslookup")
|
|
709
|
+
* @param usedParams - Parameters already used in the current call
|
|
710
|
+
* @param partialText - Partial text for filtering
|
|
711
|
+
*/
|
|
712
|
+
function getMutatorParameterCompletions(mutatorName, usedParams = [], partialText) {
|
|
713
|
+
const params = MUTATOR_PARAMETERS[mutatorName];
|
|
714
|
+
if (!params || params.length === 0) {
|
|
715
|
+
return [];
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Filter out already used parameters
|
|
719
|
+
const usedSet = new Set(usedParams.map(p => p.toLowerCase()));
|
|
720
|
+
const availableParams = params.filter(p => !usedSet.has(p.name.toLowerCase()));
|
|
721
|
+
|
|
722
|
+
// Filter by partial text if provided
|
|
723
|
+
let filteredParams = availableParams;
|
|
724
|
+
if (partialText) {
|
|
725
|
+
const searchText = partialText.toLowerCase();
|
|
726
|
+
filteredParams = availableParams.filter(p =>
|
|
727
|
+
p.name.toLowerCase().includes(searchText)
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
return filteredParams.map((param, idx) => {
|
|
732
|
+
// Generate insert text based on parameter type
|
|
733
|
+
let insertText = `${param.name}=`;
|
|
734
|
+
if (param.type === "boolean") {
|
|
735
|
+
insertText = `${param.name}=true`;
|
|
736
|
+
} else if (param.type === "string") {
|
|
737
|
+
insertText = `${param.name}="$1"`;
|
|
738
|
+
} else if (param.type === "number") {
|
|
739
|
+
insertText = `${param.name}=$1`;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
return {
|
|
743
|
+
label: param.name,
|
|
744
|
+
insertText: insertText,
|
|
745
|
+
kind: "property",
|
|
746
|
+
detail: `${param.type} - ${param.description}`,
|
|
747
|
+
documentation: param.description,
|
|
748
|
+
sortOrder: 100 + idx
|
|
749
|
+
};
|
|
750
|
+
});
|
|
751
|
+
}
|
|
677
752
|
export {
|
|
678
753
|
oe as getCompletionTriggerCharacters,
|
|
679
754
|
ae as getCompletions,
|
package/dist/src/parser.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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 } from "./tokenizer.js";
|
|
4
|
+
import { tokenizeTql as p, COMPARISON_OPERATORS as v, ENRICHMENT_MUTATORS as ENRICHMENT_MUTATORS } from "./tokenizer.js";
|
|
5
5
|
const f = 50, k = /* @__PURE__ */ new Set(["logicalOp", "paren"]);
|
|
6
6
|
class y {
|
|
7
7
|
constructor(e) {
|
|
@@ -220,6 +220,22 @@ class y {
|
|
|
220
220
|
mutators: n,
|
|
221
221
|
end: this.previous().end
|
|
222
222
|
}), !this.check("operator")) {
|
|
223
|
+
// Check if the last mutator is an enrichment mutator (geo, nslookup, etc.)
|
|
224
|
+
// Enrichment mutators don't require an operator - they transform the field into enriched data
|
|
225
|
+
const lastMutator = n.length > 0 ? n[n.length - 1] : null;
|
|
226
|
+
const isEnrichmentMutator = lastMutator && ENRICHMENT_MUTATORS.includes(lastMutator);
|
|
227
|
+
|
|
228
|
+
if (isEnrichmentMutator) {
|
|
229
|
+
// Return a valid enrichment expression without error
|
|
230
|
+
return {
|
|
231
|
+
type: "enrichment",
|
|
232
|
+
field: t,
|
|
233
|
+
mutator: lastMutator,
|
|
234
|
+
start: t.start,
|
|
235
|
+
end: t.end
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
223
239
|
const s = this.isAtEnd() ? this.previous() : this.peek(), h = n.length > 0 ? `'${e.value}' with mutator` : `'${e.value}'`;
|
|
224
240
|
return this.addError(
|
|
225
241
|
`Expected operator after field ${h}`,
|
package/dist/src/tokenizer.d.ts
CHANGED
|
@@ -20,6 +20,20 @@ export declare const COLLECTION_OPERATORS: TqlCollectionOperator[];
|
|
|
20
20
|
* Synchronized with Python/Rust implementations.
|
|
21
21
|
*/
|
|
22
22
|
export declare const MUTATORS: TqlMutator[];
|
|
23
|
+
/**
|
|
24
|
+
* Enrichment mutators that don't require an operator after them.
|
|
25
|
+
* These mutators transform the field into an enriched object/value that stands alone.
|
|
26
|
+
*/
|
|
27
|
+
export declare const ENRICHMENT_MUTATORS: string[];
|
|
28
|
+
/**
|
|
29
|
+
* Parameters available for mutators that support function call syntax.
|
|
30
|
+
*/
|
|
31
|
+
export interface MutatorParameter {
|
|
32
|
+
name: string;
|
|
33
|
+
type: 'boolean' | 'string' | 'number';
|
|
34
|
+
description: string;
|
|
35
|
+
}
|
|
36
|
+
export declare const MUTATOR_PARAMETERS: Record<string, MutatorParameter[]>;
|
|
23
37
|
/**
|
|
24
38
|
* All aggregation functions supported by TQL.
|
|
25
39
|
* Synchronized with Python/Rust implementations.
|
package/dist/src/tokenizer.js
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
var l = Object.defineProperty;
|
|
2
2
|
var u = (o, e, n) => e in o ? l(o, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : o[e] = n;
|
|
3
3
|
var a = (o, e, n) => u(o, typeof e != "symbol" ? e + "" : e, n);
|
|
4
|
+
// Enrichment mutators that don't require an operator after them
|
|
5
|
+
// These mutators transform the field into an enriched object/value that stands alone
|
|
6
|
+
const ENRICHMENT_MUTATORS = [
|
|
7
|
+
"geo",
|
|
8
|
+
"geoip",
|
|
9
|
+
"geoip_lookup",
|
|
10
|
+
"nslookup"
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
// Parameters available for mutators that support function call syntax
|
|
14
|
+
// e.g., geo(force=true, save=true)
|
|
15
|
+
const MUTATOR_PARAMETERS = {
|
|
16
|
+
geo: [
|
|
17
|
+
{ name: "force", type: "boolean", description: "Force lookup even if geo data already exists" },
|
|
18
|
+
{ name: "save", type: "boolean", description: "Save results to the record" },
|
|
19
|
+
{ name: "field", type: "string", description: "Field name to save results to" },
|
|
20
|
+
{ name: "cache", type: "boolean", description: "Enable caching of lookup results" },
|
|
21
|
+
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds" }
|
|
22
|
+
],
|
|
23
|
+
geoip: [
|
|
24
|
+
{ name: "force", type: "boolean", description: "Force lookup even if geo data already exists" },
|
|
25
|
+
{ name: "save", type: "boolean", description: "Save results to the record" },
|
|
26
|
+
{ name: "field", type: "string", description: "Field name to save results to" },
|
|
27
|
+
{ name: "cache", type: "boolean", description: "Enable caching of lookup results" },
|
|
28
|
+
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds" }
|
|
29
|
+
],
|
|
30
|
+
geoip_lookup: [
|
|
31
|
+
{ name: "force", type: "boolean", description: "Force lookup even if geo data already exists" },
|
|
32
|
+
{ name: "save", type: "boolean", description: "Save results to the record" },
|
|
33
|
+
{ name: "field", type: "string", description: "Field name to save results to" },
|
|
34
|
+
{ name: "cache", type: "boolean", description: "Enable caching of lookup results" },
|
|
35
|
+
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds" }
|
|
36
|
+
],
|
|
37
|
+
nslookup: [
|
|
38
|
+
{ name: "record_type", type: "string", description: "DNS record type (A, AAAA, MX, etc.)" },
|
|
39
|
+
{ name: "cache", type: "boolean", description: "Enable caching of lookup results" },
|
|
40
|
+
{ name: "cache_ttl", type: "number", description: "Cache TTL in seconds" }
|
|
41
|
+
],
|
|
42
|
+
split: [
|
|
43
|
+
{ name: "delimiter", type: "string", description: "Delimiter to split on (default: comma)" }
|
|
44
|
+
],
|
|
45
|
+
replace: [
|
|
46
|
+
{ name: "find", type: "string", description: "Text to find" },
|
|
47
|
+
{ name: "replace", type: "string", description: "Text to replace with" }
|
|
48
|
+
]
|
|
49
|
+
};
|
|
4
50
|
const p = [
|
|
5
51
|
// Equality
|
|
6
52
|
"eq",
|
|
@@ -413,9 +459,11 @@ export {
|
|
|
413
459
|
_ as AGGREGATION_FUNCTIONS,
|
|
414
460
|
f as COLLECTION_OPERATORS,
|
|
415
461
|
p as COMPARISON_OPERATORS,
|
|
462
|
+
ENRICHMENT_MUTATORS,
|
|
416
463
|
w as KEYWORDS,
|
|
417
464
|
k as LOGICAL_OPERATORS,
|
|
418
465
|
m as MUTATORS,
|
|
466
|
+
MUTATOR_PARAMETERS,
|
|
419
467
|
d as NEGATION_SYMBOL_OPERATORS,
|
|
420
468
|
c as SYMBOL_OPERATORS,
|
|
421
469
|
g as TYPE_HINTS,
|
|
@@ -104,8 +104,7 @@ const U = ["id", "aria-activedescendant"], V = { class: "tql-completion-list" },
|
|
|
104
104
|
role: "listbox",
|
|
105
105
|
"aria-label": "TQL completions",
|
|
106
106
|
"aria-activedescendant": o.items[e.value] ? `${o.id}-option-${e.value}` : void 0,
|
|
107
|
-
onPointerdown: r[0] || (r[0] = A(() => {
|
|
108
|
-
}, ["stop"]))
|
|
107
|
+
onPointerdown: r[0] || (r[0] = A((evt) => { evt.preventDefault(); }, ["stop", "prevent"]))
|
|
109
108
|
}, [
|
|
110
109
|
u("div", V, [
|
|
111
110
|
(l(!0), s(I, null, K(o.items, (n, p) => (l(), s("div", {
|
|
@@ -114,7 +113,7 @@ const U = ["id", "aria-activedescendant"], V = { class: "tql-completion-list" },
|
|
|
114
113
|
class: f(["tql-completion-item", { selected: p === e.value }]),
|
|
115
114
|
role: "option",
|
|
116
115
|
"aria-selected": p === e.value,
|
|
117
|
-
onClick: (E) => a("select", n),
|
|
116
|
+
onClick: (E) => { E.preventDefault(); E.stopPropagation(); a("select", n); },
|
|
118
117
|
onMouseenter: (E) => e.value = p
|
|
119
118
|
}, [
|
|
120
119
|
u("span", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellaro/tql",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Tellaro Query Language (TQL) parser, validator, and autocomplete for JavaScript/TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,17 +23,11 @@
|
|
|
23
23
|
"README.md"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "vite build",
|
|
27
26
|
"test": "vitest run",
|
|
28
27
|
"test:watch": "vitest",
|
|
29
28
|
"test:shared": "vitest run --grep 'shared-fixtures'",
|
|
30
29
|
"test:e2e": "playwright test",
|
|
31
|
-
"test:e2e:ui": "playwright test --ui"
|
|
32
|
-
"playground:serve": "vite --config vite.playground.config.ts --port 5174",
|
|
33
|
-
"playground:dev": "vite --config vite.playground.config.ts",
|
|
34
|
-
"lint": "eslint src vue tests --ext .ts,.vue",
|
|
35
|
-
"typecheck": "vue-tsc --noEmit",
|
|
36
|
-
"prepublishOnly": "npm run build"
|
|
30
|
+
"test:e2e:ui": "playwright test --ui"
|
|
37
31
|
},
|
|
38
32
|
"repository": {
|
|
39
33
|
"type": "git",
|