@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
- n.push(...x(o.partialText, o.mutatorOutputType));
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: t,
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,
@@ -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}`,
@@ -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.
@@ -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.11",
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",