@tellaro/tql 0.1.17 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,7 @@
1
- var I = Object.defineProperty;
2
- var S = (e, t, a) => t in e ? I(e, t, { enumerable: !0, configurable: !0, writable: !0, value: a }) : e[t] = a;
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, ENRICHMENT_MUTATORS as ENRICHMENT_MUTATORS, MUTATOR_PARAMETERS as MUTATOR_PARAMETERS } from "./tokenizer.js";
5
- import { fuzzyMatch as _ } from "./fuzzyMatcher.js";
6
- import { getSchemaCache as M } from "./schemaCache.js";
7
- const E = [
1
+ import { tokenizeTql as x, COMPARISON_OPERATORS as N, LOGICAL_OPERATORS as I, AGGREGATION_FUNCTIONS as S, VISUALIZATION_TYPES as A, TYPE_HINTS as L, MUTATORS as R } from "./tokenizer.js";
2
+ import { fuzzyMatch as w } from "./fuzzyMatcher.js";
3
+ import { getSchemaCache as $ } from "./schemaCache.js";
4
+ const P = [
8
5
  {
9
6
  label: "Simple equality",
10
7
  insertText: 'field eq "value"',
@@ -107,270 +104,70 @@ const E = [
107
104
  description: "Top 10 results by count",
108
105
  category: "Stats"
109
106
  }
110
- ], U = {
111
- // Equality operators
112
- eq: { detail: "Equals", documentation: "Exact match comparison. Case-sensitive for strings.\n\nExamples:\n- status eq 'active'\n- severity eq 3\n- enabled eq true\n\nWorks with: strings, numbers, booleans, dates, IPs" },
113
- ne: { detail: "Not equals", documentation: "Match any value except the specified one.\n\nExamples:\n- status ne 'error'\n- severity ne 0\n\nUseful for filtering out specific values." },
114
- // Comparison operators
115
- gt: { detail: "Greater than", documentation: "Compare if field value is greater than the specified value.\n\nExamples:\n- severity gt 3\n- bytes gt 1000000\n- @timestamp gt '2024-01-01'\n\nWorks with: numbers, dates" },
116
- gte: { detail: "Greater than or equal", documentation: "Compare if field value is greater than or equal to the specified value.\n\nExamples:\n- risk_score gte 70\n- attempts gte 5\n\nWorks with: numbers, dates" },
117
- lt: { detail: "Less than", documentation: "Compare if field value is less than the specified value.\n\nExamples:\n- response_time lt 100\n- @timestamp lt 'now-1d'\n\nWorks with: numbers, dates" },
118
- lte: { detail: "Less than or equal", documentation: "Compare if field value is less than or equal to the specified value.\n\nExamples:\n- confidence lte 50\n- age lte 30\n\nWorks with: numbers, dates" },
119
- // String operators
120
- contains: { detail: "Contains substring", documentation: "Check if field contains the specified substring. Case-insensitive.\n\nExamples:\n- message contains 'error'\n- url contains 'admin'\n\nUseful for searching within text fields." },
121
- not_contains: { detail: "Does not contain", documentation: "Check if field does NOT contain the specified substring.\n\nExamples:\n- message not_contains 'debug'\n- path not_contains 'test'\n\nUseful for excluding noise from results." },
122
- startswith: { detail: "Starts with", documentation: "Check if field value starts with the specified prefix.\n\nExamples:\n- hostname startswith 'web-'\n- url startswith 'https://'\n\nFaster than contains for prefix matching." },
123
- not_startswith: { detail: "Does not start with", documentation: "Check if field value does NOT start with the specified prefix.\n\nExamples:\n- hostname not_startswith 'test-'\n- email not_startswith 'noreply'" },
124
- endswith: { detail: "Ends with", documentation: "Check if field value ends with the specified suffix.\n\nExamples:\n- file.name endswith '.exe'\n- email endswith '@company.com'\n\nUseful for file extension matching." },
125
- not_endswith: { detail: "Does not end with", documentation: "Check if field value does NOT end with the specified suffix.\n\nExamples:\n- file.name not_endswith '.log'\n- url not_endswith '.jpg'" },
126
- regexp: { detail: "Regular expression", documentation: "Match field value against a regular expression pattern.\n\nExamples:\n- ip regexp '^192\\\\.168\\\\..*'\n- email regexp '.*@(gmail|yahoo)\\\\.com$'\n\nUses standard regex syntax." },
127
- regex: { detail: "Regular expression", documentation: "Alias for regexp. Match using regex pattern.\n\nExamples:\n- user.name regex '^admin.*'" },
128
- not_regexp: { detail: "Not matching regex", documentation: "Match if field value does NOT match the regex.\n\nExamples:\n- file.path not_regexp '.*\\\\.tmp$'\n- message not_regexp 'DEBUG|TRACE'" },
129
- matches: { detail: "Pattern match", documentation: "Alias for regexp. Match using regex pattern.\n\nExamples:\n- hostname matches 'server[0-9]+'" },
130
- not_matches: { detail: "Not matching pattern", documentation: "Alias for not_regexp. Does NOT match the pattern." },
131
- // Range operators
132
- between: { detail: "Between range", documentation: "Check if field value is within a range (inclusive).\n\nExamples:\n- port between 1024 AND 65535\n- severity between 1 AND 5\n\nIncludes both boundary values." },
133
- not_between: { detail: "Not between range", documentation: "Check if field value is outside a range.\n\nExamples:\n- port not_between 80 AND 443\n\nExcludes values in the range." },
134
- // List operators
135
- in: { detail: "In list", documentation: "Check if field value matches any value in the list.\n\nExamples:\n- status in ['active', 'pending']\n- severity in [3, 4, 5]\n\nMore efficient than multiple OR conditions." },
136
- not_in: { detail: "Not in list", documentation: "Check if field value does NOT match any value in the list.\n\nExamples:\n- status not_in ['deleted', 'archived']\n\nUseful for exclusion lists." },
137
- // Existence operators
138
- exists: { detail: "Field exists", documentation: "Check if field exists and has a non-null value.\n\nExamples:\n- user.email exists\n- threat.indicator exists\n\nReturns false for null values or missing fields." },
139
- not_exists: { detail: "Field not exists", documentation: "Check if field is missing or has a null value.\n\nExamples:\n- error.code not_exists\n\nTrue when field is missing or explicitly null." },
140
- is: { detail: "Is null check", documentation: "Check if field value is explicitly null.\n\nExamples:\n- user.phone is null\n\nDifferent from not_exists: returns false for missing fields." },
141
- is_not: { detail: "Is not null check", documentation: "Check if field exists and is not null.\n\nExamples:\n- user.email is_not null\n\nField must exist and have a non-null value." },
142
- // Network operators
143
- cidr: { detail: "CIDR match", documentation: "Match IP addresses within a CIDR range.\n\nExamples:\n- source.ip cidr '192.168.0.0/16'\n- destination.ip cidr '10.0.0.0/8'\n\nWorks with IPv4 and IPv6." },
144
- not_cidr: { detail: "Not in CIDR", documentation: "Match IP addresses NOT within a CIDR range.\n\nExamples:\n- source.ip not_cidr '192.168.0.0/16'\n\nUseful for identifying external IPs." },
145
- // Collection operators
146
- any: { detail: "Any element matches", documentation: "True if ANY element in an array matches the condition.\n\nExamples:\n- tags any eq 'critical'\n- ports any between 1 AND 1024\n\nUseful for searching within array fields." },
147
- all: { detail: "All elements match", documentation: "True if ALL elements in an array match the condition.\n\nExamples:\n- scores all gte 70\n\nUseful for validation across arrays." },
148
- none: { detail: "No elements match", documentation: "True if NO elements in an array match the condition.\n\nExamples:\n- tags none eq 'deprecated'\n\nUseful for ensuring no bad values exist." },
149
- not_any: { detail: "Not any matches", documentation: "Negation of any - equivalent to none.\n\nTrue when no elements match." },
150
- not_all: { detail: "Not all match", documentation: "Negation of all - at least one element doesn't match.\n\nTrue when at least one element fails." },
151
- not_none: { detail: "Not none match", documentation: "Negation of none - equivalent to any.\n\nTrue when at least one element matches." }
152
- }, z = {
153
- // String mutators
154
- lowercase: {
155
- detail: "Convert to lowercase",
156
- documentation: "Transforms the field value to lowercase.\n\nExample: hostname | lowercase eq 'server01'\n\nUseful for case-insensitive comparisons."
157
- },
158
- uppercase: {
159
- detail: "Convert to uppercase",
160
- documentation: "Transforms the field value to uppercase.\n\nExample: status | uppercase eq 'ERROR'\n\nUseful for normalizing status codes."
161
- },
162
- trim: {
163
- detail: "Trim whitespace",
164
- documentation: "Removes leading and trailing whitespace from the field value.\n\nExample: message | trim contains 'error'\n\nUseful for cleaning user input or log messages."
165
- },
166
- split: {
167
- detail: "Split string into array",
168
- documentation: "Splits a string into an array using a delimiter.\n\nExample: tags | split(delimiter=',') any eq 'critical'\n\nParameters:\n- delimiter: Character(s) to split on (default: ',')\n- field: Field name to save results to"
169
- },
170
- length: {
171
- detail: "Get string/array length",
172
- documentation: "Returns the length of a string or array as a number.\n\nExample: password | length gte 8\n\nUseful for validation checks."
173
- },
174
- replace: {
175
- detail: "Replace text in string",
176
- documentation: "Replaces occurrences of a substring with another string.\n\nExample: url | replace(find='http://', replace='https://') startswith 'https'\n\nParameters:\n- find: Text to search for (required)\n- replace: Text to replace with (required)\n- field: Field name to save results to"
177
- },
178
- // Encoding mutators
179
- b64encode: {
180
- detail: "Base64 encode",
181
- documentation: "Encodes the field value to Base64.\n\nExample: payload | b64encode eq 'SGVsbG8gV29ybGQ='\n\nParameters:\n- field: Field name to save encoded result"
182
- },
183
- b64decode: {
184
- detail: "Base64 decode",
185
- documentation: "Decodes a Base64-encoded field value.\n\nExample: encoded_data | b64decode contains 'password'\n\nParameters:\n- field: Field name to save decoded result"
186
- },
187
- urldecode: {
188
- detail: "URL decode",
189
- documentation: "Decodes URL-encoded (percent-encoded) strings.\n\nExample: query_string | urldecode contains 'SELECT'\n\nUseful for analyzing web requests."
190
- },
191
- hexencode: {
192
- detail: "Hex encode",
193
- documentation: "Encodes the field value to hexadecimal.\n\nExample: data | hexencode eq '48656c6c6f'\n\nParameters:\n- field: Field name to save encoded result"
194
- },
195
- hexdecode: {
196
- detail: "Hex decode",
197
- documentation: "Decodes a hexadecimal-encoded field value.\n\nExample: hex_payload | hexdecode contains 'malware'\n\nParameters:\n- field: Field name to save decoded result"
198
- },
199
- md5: {
200
- detail: "MD5 hash",
201
- documentation: "Calculates the MD5 hash of the field value.\n\nExample: file_content | md5 eq 'd41d8cd98f00b204e9800998ecf8427e'\n\nUseful for file integrity checks."
202
- },
203
- sha256: {
204
- detail: "SHA256 hash",
205
- documentation: "Calculates the SHA256 hash of the field value.\n\nExample: file_content | sha256 in ['hash1', 'hash2']\n\nUseful for malware signature matching."
206
- },
207
- // Security mutators
208
- refang: {
209
- detail: "Refang IOC",
210
- documentation: "Converts defanged indicators back to their original form.\n\nExample: ioc | refang eq '192.168.1.1'\n\nConverts 'hxxp://evil[.]com' to 'http://evil.com'"
211
- },
212
- defang: {
213
- detail: "Defang IOC",
214
- documentation: "Converts URLs/IPs to a safe defanged form for sharing.\n\nExample: url | defang\n\nConverts 'http://evil.com' to 'hxxp://evil[.]com'"
215
- },
216
- // Network mutators
217
- is_private: {
218
- detail: "Check if IP is private",
219
- documentation: "Returns true if the IP address is in a private range (RFC1918).\n\nExample: source.ip | is_private eq true\n\nPrivate ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16"
220
- },
221
- is_global: {
222
- detail: "Check if IP is globally routable",
223
- documentation: "Returns true if the IP address is globally routable (not private/reserved).\n\nExample: destination.ip | is_global eq true\n\nUseful for filtering external connections."
224
- },
225
- // DNS mutator
226
- nslookup: {
227
- detail: "DNS lookup",
228
- documentation: "Performs DNS lookup on a hostname or reverse lookup on an IP.\n\nExample: hostname | nslookup(types=['A', 'AAAA'])\n\nParameters:\n- servers: DNS servers to query (e.g., ['1.1.1.1'])\n- types: Record types to query (A, AAAA, MX, TXT, etc.)\n- force: Force lookup even if data exists\n- save: Save results to record\n- field: Field name to save results"
229
- },
230
- // GeoIP mutators
231
- geoip_lookup: {
232
- detail: "GeoIP enrichment",
233
- documentation: "Enriches IP address with geolocation data (country, city, ASN, etc.).\n\nExample: source.ip | geoip_lookup(force=true)\n\nParameters:\n- db_path: Path to MaxMind database\n- force: Force lookup even if geo data exists\n- save: Save results to record\n- cache: Enable result caching\n- cache_ttl: Cache TTL in seconds"
234
- },
235
- geoip: {
236
- detail: "GeoIP enrichment",
237
- documentation: "Alias for geoip_lookup. Enriches IP with geolocation data.\n\nExample: destination.ip | geoip"
238
- },
239
- geo: {
240
- detail: "GeoIP enrichment",
241
- documentation: "Alias for geoip_lookup. Enriches IP with geolocation data.\n\nExample: source.ip | geo(save=true)\n\nAdds: country, city, region, coordinates, ASN info"
242
- },
243
- // List mutators
244
- any: {
245
- detail: "Any element matches",
246
- documentation: "Returns true if any element in an array matches the condition.\n\nExample: tags | any eq 'critical'\n\nUseful for checking array fields."
247
- },
248
- all: {
249
- detail: "All elements match",
250
- documentation: "Returns true if all elements in an array match the condition.\n\nExample: scores | all gte 70\n\nUseful for validation across arrays."
251
- },
252
- avg: {
253
- detail: "Average of array",
254
- documentation: "Calculates the average of numeric array elements.\n\nExample: response_times | avg lt 100\n\nUseful for performance analysis."
255
- },
256
- average: {
257
- detail: "Average of array",
258
- documentation: "Alias for avg. Calculates the average of numeric array elements."
259
- },
260
- sum: {
261
- detail: "Sum of array",
262
- documentation: "Calculates the sum of numeric array elements.\n\nExample: byte_counts | sum gt 1000000\n\nUseful for aggregate analysis."
263
- },
264
- min: {
265
- detail: "Minimum value in array",
266
- documentation: "Returns the minimum value from a numeric array.\n\nExample: temperatures | min lt 0\n\nUseful for threshold detection."
267
- },
268
- max: {
269
- detail: "Maximum value in array",
270
- documentation: "Returns the maximum value from a numeric array.\n\nExample: cpu_usage | max gt 90\n\nUseful for peak detection."
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
- }
373
- }, h = {
107
+ ], D = {
108
+ eq: { detail: "Equals", documentation: "Exact match comparison" },
109
+ ne: { detail: "Not equals", documentation: "Match any value except this one" },
110
+ gt: { detail: "Greater than", documentation: "Numeric/date comparison" },
111
+ gte: { detail: "Greater than or equal", documentation: "Numeric/date comparison" },
112
+ lt: { detail: "Less than", documentation: "Numeric/date comparison" },
113
+ lte: { detail: "Less than or equal", documentation: "Numeric/date comparison" },
114
+ contains: { detail: "Contains substring", documentation: "Case-insensitive substring match" },
115
+ not_contains: { detail: "Does not contain", documentation: "Negative substring match" },
116
+ startswith: { detail: "Starts with", documentation: "Match prefix of field value" },
117
+ not_startswith: { detail: "Does not start with", documentation: "Negative prefix match" },
118
+ endswith: { detail: "Ends with", documentation: "Match suffix of field value" },
119
+ not_endswith: { detail: "Does not end with", documentation: "Negative suffix match" },
120
+ regexp: { detail: "Regular expression", documentation: "Match using regex pattern" },
121
+ regex: { detail: "Regular expression", documentation: "Alias for regexp" },
122
+ not_regexp: { detail: "Not matching regex", documentation: "Negative regex match" },
123
+ matches: { detail: "Pattern match", documentation: "Match using pattern" },
124
+ not_matches: { detail: "Not matching pattern", documentation: "Negative pattern match" },
125
+ between: { detail: "Between range", documentation: "Usage: field between A AND B" },
126
+ not_between: { detail: "Not between range", documentation: "Exclude values in range" },
127
+ in: { detail: "In list", documentation: 'Usage: field in ["a", "b", "c"]' },
128
+ not_in: { detail: "Not in list", documentation: "Exclude values in list" },
129
+ exists: { detail: "Field exists", documentation: "Check if field has any value" },
130
+ not_exists: { detail: "Field not exists", documentation: "Check if field is missing or null" },
131
+ is: { detail: "Is null check", documentation: "Usage: field is null" },
132
+ is_not: { detail: "Is not null check", documentation: "Usage: field is_not null" },
133
+ cidr: { detail: "CIDR match", documentation: "Match IP addresses in CIDR range (IP fields only)" },
134
+ not_cidr: { detail: "Not in CIDR", documentation: "Exclude IPs in CIDR range" },
135
+ any: { detail: "Any element matches", documentation: "True if any array element matches" },
136
+ all: { detail: "All elements match", documentation: "True if all array elements match" },
137
+ none: { detail: "No elements match", documentation: "True if no array elements match" },
138
+ not_any: { detail: "Not any matches", documentation: "Negation of any" },
139
+ not_all: { detail: "Not all match", documentation: "Negation of all" },
140
+ not_none: { detail: "Not none match", documentation: "Negation of none" }
141
+ }, M = {
142
+ lowercase: { detail: "Convert to lowercase", documentation: "Transform string to lowercase" },
143
+ uppercase: { detail: "Convert to uppercase", documentation: "Transform string to uppercase" },
144
+ trim: { detail: "Trim whitespace", documentation: "Remove leading/trailing whitespace" },
145
+ split: { detail: "Split string", documentation: "Split string into array. Usage: split(delimiter)" },
146
+ length: { detail: "Get length", documentation: "Returns string/array length as number" },
147
+ replace: { detail: "Replace text", documentation: "Replace substring. Usage: replace(find, replace)" },
148
+ b64encode: { detail: "Base64 encode", documentation: "Encode value to Base64" },
149
+ b64decode: { detail: "Base64 decode", documentation: "Decode Base64 to string" },
150
+ urldecode: { detail: "URL decode", documentation: "Decode URL-encoded string" },
151
+ hexencode: { detail: "Hex encode", documentation: "Encode to hexadecimal" },
152
+ hexdecode: { detail: "Hex decode", documentation: "Decode from hexadecimal" },
153
+ md5: { detail: "MD5 hash", documentation: "Calculate MD5 hash" },
154
+ sha256: { detail: "SHA256 hash", documentation: "Calculate SHA256 hash" },
155
+ refang: { detail: "Refang IOC", documentation: "Convert defanged URL/IP to normal form" },
156
+ defang: { detail: "Defang IOC", documentation: "Convert URL/IP to safe defanged form" },
157
+ is_private: { detail: "Is private IP", documentation: "Check if IP is RFC1918/private" },
158
+ is_global: { detail: "Is global IP", documentation: "Check if IP is globally routable" },
159
+ nslookup: { detail: "DNS lookup", documentation: "Perform DNS lookup on hostname/IP" },
160
+ geoip_lookup: { detail: "GeoIP lookup", documentation: "Get geolocation data for IP" },
161
+ geoip: { detail: "GeoIP lookup", documentation: "Alias for geoip_lookup" },
162
+ geo: { detail: "GeoIP lookup", documentation: "Alias for geoip_lookup with conditions" },
163
+ any: { detail: "Any truthy", documentation: "True if any array element is truthy" },
164
+ all: { detail: "All truthy", documentation: "True if all array elements are truthy" },
165
+ avg: { detail: "Average", documentation: "Calculate average of numeric array" },
166
+ average: { detail: "Average", documentation: "Alias for avg" },
167
+ sum: { detail: "Sum", documentation: "Sum of numeric array elements" },
168
+ min: { detail: "Minimum", documentation: "Minimum value in array" },
169
+ max: { detail: "Maximum", documentation: "Maximum value in array" }
170
+ }, g = {
374
171
  // String outputs
375
172
  lowercase: "keyword",
376
173
  uppercase: "keyword",
@@ -404,7 +201,7 @@ const E = [
404
201
  geo: "object",
405
202
  // Array output (returns array of strings)
406
203
  split: "keyword"
407
- }, F = {
204
+ }, E = {
408
205
  // Universal operators (work with all types)
409
206
  eq: ["text", "keyword", "long", "integer", "double", "float", "date", "boolean", "ip"],
410
207
  ne: ["text", "keyword", "long", "integer", "double", "float", "date", "boolean", "ip"],
@@ -441,12 +238,10 @@ const E = [
441
238
  all: ["nested", "object", "keyword"],
442
239
  none: ["nested", "object", "keyword"]
443
240
  };
444
- class q {
445
- constructor() {
446
- p(this, "cache", /* @__PURE__ */ new Map());
447
- p(this, "maxSize", 50);
448
- p(this, "maxAge", 5e3);
449
- }
241
+ class U {
242
+ cache = /* @__PURE__ */ new Map();
243
+ maxSize = 50;
244
+ maxAge = 5e3;
450
245
  // 5 seconds
451
246
  get(t) {
452
247
  const a = this.cache.get(t);
@@ -465,106 +260,66 @@ class q {
465
260
  this.cache.clear();
466
261
  }
467
262
  }
468
- const v = new q();
469
- function B(e, t, a) {
263
+ const v = new U();
264
+ function z(e, t, a) {
470
265
  const i = `${e.substring(0, t)}|${t}`, o = v.get(i);
471
266
  if (o)
472
- return o.fieldName && !o.fieldType && a && (o.fieldType = f(o.fieldName, a)), o;
473
- const n = G(e, t, a);
267
+ return o.fieldName && !o.fieldType && a && (o.fieldType = p(o.fieldName, a)), o;
268
+ const n = F(e, t, a);
474
269
  return v.set(i, n), n;
475
270
  }
476
- function G(e, t, a) {
477
- var u;
478
- const o = b(e.substring(0, t)).filter((l) => l.type !== "whitespace");
271
+ function F(e, t, a) {
272
+ const o = x(e.substring(0, t)).filter((r) => r.type !== "whitespace");
479
273
  if (o.length === 0)
480
274
  return { type: "start" };
481
- 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;
275
+ const n = o[o.length - 1], s = o.length > 1 ? o[o.length - 2] : null, d = n.end === t && !e[t - 1]?.match(/\s/), l = d ? n.value : void 0;
482
276
  if (n.type === "logicalOp")
483
277
  return { type: "start" };
484
- if (n.type === "paren" && n.value === "(") {
485
- // Check if previous token is a mutator - we're inside mutator params
486
- if (r && r.type === "mutator") {
487
- const mutatorName = r.value.toLowerCase();
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 };
490
- }
278
+ if (n.type === "paren" && n.value === "(")
491
279
  return { type: "after_paren" };
492
- }
493
- // Check if we're typing inside mutator params (e.g., "geo(for" while typing "force")
494
- // Pattern: field token, preceded by "(", preceded by mutator
495
- if (n.type === "field" && r && r.type === "paren" && r.value === "(") {
496
- const mutatorToken = o.length > 2 ? o[o.length - 3] : null;
497
- if (mutatorToken && mutatorToken.type === "mutator") {
498
- const mutatorName = mutatorToken.value.toLowerCase();
499
- return { type: "mutator_params", mutatorName: mutatorName, usedParams: [], partialText: n.value };
500
- }
501
- }
502
- // Check if we're after a comma inside mutator params (e.g., "geo(force=true, ")
503
- if (n.type === "comma") {
504
- // Look back for the pattern: mutator, "(", ...params..., ","
505
- let foundMutator = null;
506
- let usedParams = [];
507
- for (let i = o.length - 2; i >= 0; i--) {
508
- const tok = o[i];
509
- if (tok.type === "paren" && tok.value === "(") {
510
- // Check if token before ( is a mutator
511
- if (i > 0 && o[i - 1].type === "mutator") {
512
- foundMutator = o[i - 1].value.toLowerCase();
513
- }
514
- break;
515
- }
516
- // Collect used parameter names (tokens that look like param=value)
517
- if (tok.type === "field") {
518
- usedParams.push(tok.value.toLowerCase());
519
- }
520
- }
521
- if (foundMutator) {
522
- return { type: "mutator_params", mutatorName: foundMutator, usedParams: usedParams, partialText: s };
523
- }
524
- }
525
280
  if (n.type === "arrow")
526
- return { type: "after_arrow", partialText: s };
281
+ return { type: "after_arrow", partialText: l };
527
282
  if (n.type === "doubleColon")
528
- return { type: "after_double_colon", partialText: s };
283
+ return { type: "after_double_colon", partialText: l };
529
284
  if (n.type === "visualization" && d)
530
- return { type: "after_arrow", partialText: s };
285
+ return { type: "after_arrow", partialText: l };
531
286
  if (n.type === "typeHint" && d)
532
- return { type: "after_double_colon", partialText: s };
287
+ return { type: "after_double_colon", partialText: l };
533
288
  if (n.type === "keyword" && n.value.toLowerCase() === "stats")
534
- return { type: "after_stats", partialText: s };
289
+ return { type: "after_stats", partialText: l };
535
290
  if (n.type === "keyword" && n.value.toLowerCase() === "by")
536
- return { type: "after_by", partialText: s };
291
+ return { type: "after_by", partialText: l };
537
292
  if (n.type === "pipe")
538
- return { type: "after_pipe", partialText: s };
293
+ return { type: "after_pipe", partialText: l };
539
294
  if (n.type === "mutator") {
540
295
  if (d)
541
- return { type: "after_pipe", partialText: s };
542
- const l = n.value.toLowerCase(), c = h[l];
296
+ return { type: "after_pipe", partialText: l };
297
+ const r = n.value.toLowerCase(), c = g[r];
543
298
  return {
544
299
  type: "after_mutator",
545
- mutatorName: l,
300
+ mutatorName: r,
546
301
  mutatorOutputType: c
547
302
  };
548
303
  }
549
304
  if (n.type === "aggregation")
550
- return d ? { type: "after_stats", partialText: s } : { type: "after_value" };
305
+ return d ? { type: "after_stats", partialText: l } : { type: "after_value" };
551
306
  if (n.type === "field") {
552
307
  if (d)
553
- return (r == null ? void 0 : r.type) === "pipe" ? { type: "after_pipe", partialText: s } : { type: "start", partialText: s };
554
- if ((r == null ? void 0 : r.type) === "pipe")
308
+ return s?.type === "pipe" ? { type: "after_pipe", partialText: l } : { type: "start", partialText: l };
309
+ if (s?.type === "pipe")
555
310
  return { type: "after_pipe", partialText: n.value };
556
- const l = f(n.value, a);
557
- return { type: "after_field", fieldName: n.value, fieldType: l };
311
+ const r = p(n.value, a);
312
+ return { type: "after_field", fieldName: n.value, fieldType: r };
558
313
  }
559
314
  if (n.type === "operator") {
560
315
  if (d) {
561
- if ((r == null ? void 0 : r.type) === "field") {
562
- const l = f(r.value, a);
563
- return { type: "after_field", fieldName: r.value, fieldType: l, partialText: s };
316
+ if (s?.type === "field") {
317
+ const r = p(s.value, a);
318
+ return { type: "after_field", fieldName: s.value, fieldType: r, partialText: l };
564
319
  }
565
- if ((r == null ? void 0 : r.type) === "mutator") {
566
- const l = r.value.toLowerCase(), c = h[l];
567
- return { type: "after_mutator", mutatorName: l, mutatorOutputType: c, partialText: s };
320
+ if (s?.type === "mutator") {
321
+ const r = s.value.toLowerCase(), c = g[r];
322
+ return { type: "after_mutator", mutatorName: r, mutatorOutputType: c, partialText: l };
568
323
  }
569
324
  }
570
325
  return { type: "after_operator", operatorName: n.value };
@@ -573,110 +328,96 @@ function G(e, t, a) {
573
328
  return d ? { type: "at_value_end" } : { type: "after_value" };
574
329
  if (n.type === "paren" && n.value === ")")
575
330
  return { type: "after_value" };
576
- if ((r == null ? void 0 : r.type) === "field" && d) {
577
- const l = f(r.value, a);
578
- return { type: "after_field", fieldName: r.value, fieldType: l, partialText: s };
331
+ if (s?.type === "field" && d) {
332
+ const r = p(s.value, a);
333
+ return { type: "after_field", fieldName: s.value, fieldType: r, partialText: l };
579
334
  }
580
- if ((r == null ? void 0 : r.type) === "mutator" && d) {
581
- const l = r.value.toLowerCase(), c = h[l];
582
- return { type: "after_mutator", mutatorName: l, mutatorOutputType: c, partialText: s };
335
+ if (s?.type === "mutator" && d) {
336
+ const r = s.value.toLowerCase(), c = g[r];
337
+ return { type: "after_mutator", mutatorName: r, mutatorOutputType: c, partialText: l };
583
338
  }
584
- return { type: "unknown", partialText: s };
339
+ return { type: "unknown", partialText: l };
585
340
  }
586
- function f(e, t) {
587
- return t ? M().getFieldType(t, e) : void 0;
341
+ function p(e, t) {
342
+ return t ? $().getFieldType(t, e) : void 0;
588
343
  }
589
- function ae(e, t = {}) {
590
- const { query: a, cursorPosition: i } = e, o = B(a, i, t.fields), n = [];
344
+ function J(e, t = {}) {
345
+ const { query: a, cursorPosition: i } = e, o = z(a, i, t.fields), n = [];
591
346
  switch (o.type) {
592
347
  case "start":
593
348
  case "after_paren":
594
- n.push(...y(t.fields, o.partialText)), n.push(N("NOT")), t.includeSnippets !== !1 && n.push(...K(t, o.partialText));
349
+ n.push(...h(t.fields, o.partialText)), n.push(O("NOT")), t.includeSnippets !== !1 && n.push(...V(t, o.partialText));
595
350
  break;
596
351
  case "after_field":
597
- n.push(...x(o.partialText, o.fieldType)), n.push(H());
352
+ n.push(...y(o.partialText, o.fieldType));
598
353
  break;
599
354
  case "after_mutator":
600
- // Check if this is an enrichment mutator (geo, nslookup, etc.)
601
- // Enrichment mutators don't need operators - they transform the field into enriched data
602
- if (o.mutatorName && ENRICHMENT_MUTATORS.includes(o.mutatorName)) {
603
- // Suggest logical operators (AND, OR) or pipe for chaining
604
- n.push(...C());
605
- n.push(H());
606
- } else {
607
- n.push(...x(o.partialText, o.mutatorOutputType));
608
- }
355
+ n.push(...y(o.partialText, o.mutatorOutputType));
609
356
  break;
610
357
  case "after_operator":
611
- n.push(...Y(o.fieldName, t));
358
+ n.push(...G(o.fieldName, t));
612
359
  break;
613
360
  case "after_value":
614
- n.push(...C());
361
+ n.push(...T());
615
362
  break;
616
363
  case "at_value_end":
617
364
  break;
618
365
  case "after_pipe":
619
- n.push(...W(o.partialText));
366
+ n.push(...j(o.partialText));
620
367
  break;
621
368
  case "after_double_colon":
622
- n.push(...Z(o.partialText));
369
+ n.push(...H(o.partialText));
623
370
  break;
624
371
  case "after_arrow":
625
- n.push(...J(o.partialText));
372
+ n.push(...Y(o.partialText));
626
373
  break;
627
374
  case "after_stats":
628
- n.push(...O(o.partialText));
375
+ n.push(...C(o.partialText));
629
376
  break;
630
377
  case "after_by":
631
- n.push(...y(t.fields, o.partialText));
632
- break;
633
- case "mutator_params":
634
- n.push(...getMutatorParameterCompletions(o.mutatorName, o.usedParams, o.partialText));
378
+ n.push(...h(t.fields, o.partialText));
635
379
  break;
636
380
  default:
637
- n.push(...y(t.fields, o.partialText)), n.push(...x(o.partialText)), n.push(...C());
381
+ n.push(...h(t.fields, o.partialText)), n.push(...y(o.partialText)), n.push(...T());
638
382
  }
639
- t.includeAggregations && o.type === "start" && n.push(...O(o.partialText));
640
- let r = n;
641
- const d = t.fuzzyMatching !== !1, s = t.minFuzzyScore ?? 0;
383
+ t.includeAggregations && o.type === "start" && n.push(...C(o.partialText));
384
+ let s = n;
385
+ const d = t.fuzzyMatching !== !1, l = t.minFuzzyScore ?? 0;
642
386
  if (o.partialText) {
643
- const u = o.partialText.toLowerCase();
387
+ const r = o.partialText.toLowerCase();
644
388
  if (d) {
645
- const l = [];
646
- for (const c of n) {
647
- const m = _(u, c.label), w = c.filterText ? _(u, c.filterText) : { matched: !1, score: 0 }, g = m.score >= w.score ? m : w;
648
- g.matched && g.score >= s && l.push({
649
- ...c,
650
- matchScore: g.score,
389
+ const c = [];
390
+ for (const u of n) {
391
+ const m = w(r, u.label), b = u.filterText ? w(r, u.filterText) : { matched: !1, score: 0 }, f = m.score >= b.score ? m : b;
392
+ f.matched && f.score >= l && c.push({
393
+ ...u,
394
+ matchScore: f.score,
651
395
  matchedIndices: m.matched ? m.matchedIndices : void 0
652
396
  });
653
397
  }
654
- r = l;
398
+ s = c;
655
399
  } else
656
- r = n.filter(
657
- (l) => {
658
- var c;
659
- return l.label.toLowerCase().includes(u) || ((c = l.filterText) == null ? void 0 : c.toLowerCase().includes(u));
660
- }
400
+ s = n.filter(
401
+ (c) => c.label.toLowerCase().includes(r) || c.filterText?.toLowerCase().includes(r)
661
402
  );
662
403
  }
663
- return r.sort((u, l) => u.matchScore !== void 0 && l.matchScore !== void 0 && l.matchScore !== u.matchScore ? l.matchScore - u.matchScore : u.sortOrder - l.sortOrder), t.maxItems && t.maxItems > 0 && (r = r.slice(0, t.maxItems)), r;
404
+ return s.sort((r, c) => r.matchScore !== void 0 && c.matchScore !== void 0 && c.matchScore !== r.matchScore ? c.matchScore - r.matchScore : r.sortOrder - c.sortOrder), t.maxItems && t.maxItems > 0 && (s = s.slice(0, t.maxItems)), s;
664
405
  }
665
- function y(e, t) {
406
+ function h(e, t) {
666
407
  if (!e || e.length === 0)
667
- return V(t);
408
+ return q(t);
668
409
  const a = [];
669
410
  for (const i of e) {
670
411
  const o = k(i);
671
412
  if (a.push(o), i.nested)
672
413
  for (const n of i.nested) {
673
- const r = k(n, i.name);
674
- a.push(r);
414
+ const s = k(n, i.name);
415
+ a.push(s);
675
416
  }
676
417
  }
677
418
  return a;
678
419
  }
679
- function V(e) {
420
+ function q(e) {
680
421
  return [
681
422
  { name: "hostname", description: "Host/machine name" },
682
423
  { name: "status", description: "Status value" },
@@ -714,16 +455,16 @@ function k(e, t) {
714
455
  sortOrder: 10
715
456
  };
716
457
  }
717
- function x(e, t) {
718
- let a = [...A];
458
+ function y(e, t) {
459
+ let a = [...N];
719
460
  return t && (a = a.filter((i) => {
720
- const o = F[i];
461
+ const o = E[i];
721
462
  return !o || o.includes(t);
722
463
  })), e && (a = a.filter((i) => i.toLowerCase().includes(e.toLowerCase()))), a.map((i, o) => {
723
- const n = U[i] || { detail: i, documentation: "" }, r = j(i, t);
464
+ const n = D[i] || { detail: i, documentation: "" }, s = B(i, t);
724
465
  return {
725
466
  label: i,
726
- insertText: r,
467
+ insertText: s,
727
468
  kind: "operator",
728
469
  detail: n.detail,
729
470
  documentation: n.documentation,
@@ -731,7 +472,7 @@ function x(e, t) {
731
472
  };
732
473
  });
733
474
  }
734
- function j(e, t) {
475
+ function B(e, t) {
735
476
  const a = [
736
477
  "contains",
737
478
  "not_contains",
@@ -746,9 +487,9 @@ function j(e, t) {
746
487
  "not_matches"
747
488
  ], i = ["exists", "not_exists"], o = ["is", "is_not"];
748
489
  if (e === "in" || e === "not_in")
749
- return T(t) ? `${e} [$1]` : `${e} ["$1"]`;
490
+ return _(t) ? `${e} [$1]` : `${e} ["$1"]`;
750
491
  if (e === "between" || e === "not_between")
751
- return T(t) ? `${e} $1 AND $2` : `${e} "$1" AND "$2"`;
492
+ return _(t) ? `${e} $1 AND $2` : `${e} "$1" AND "$2"`;
752
493
  if (o.includes(e))
753
494
  return `${e} null`;
754
495
  if (i.includes(e))
@@ -765,28 +506,32 @@ function j(e, t) {
765
506
  return `${e} "$1"`;
766
507
  case "boolean":
767
508
  return `${e} $1`;
509
+ // true or false, no quotes
768
510
  case "long":
769
511
  case "integer":
770
512
  case "double":
771
513
  case "float":
772
514
  return `${e} $1`;
515
+ // Numbers, no quotes
773
516
  case "date":
774
517
  return `${e} "$1"`;
518
+ // Dates typically quoted
775
519
  case "ip":
776
520
  return `${e} "$1"`;
521
+ // IPs quoted
777
522
  default:
778
523
  return `${e} `;
779
524
  }
780
525
  }
781
- function T(e) {
526
+ function _(e) {
782
527
  return e === "long" || e === "integer" || e === "double" || e === "float" || e === "short" || e === "byte" || e === "half_float" || e === "scaled_float" || e === "unsigned_long";
783
528
  }
784
- function C() {
785
- return L.filter((e) => e !== "NOT").map(
786
- (e, t) => N(e, t)
529
+ function T() {
530
+ return I.filter((e) => e !== "NOT").map(
531
+ (e, t) => O(e, t)
787
532
  );
788
533
  }
789
- function N(e, t = 0) {
534
+ function O(e, t = 0) {
790
535
  return {
791
536
  label: e,
792
537
  insertText: e + " ",
@@ -795,27 +540,15 @@ function N(e, t = 0) {
795
540
  sortOrder: 30 + t
796
541
  };
797
542
  }
798
- function H() {
799
- return {
800
- label: "|",
801
- insertText: "| ",
802
- kind: "operator",
803
- detail: "Pipe to mutator",
804
- documentation: "Chain field to a mutator function (e.g., hostname | lower)",
805
- sortOrder: 19
806
- // Just before operators (20+)
807
- };
808
- }
809
- function Y(e, t) {
810
- var i;
543
+ function G(e, t) {
811
544
  const a = [];
812
- return e && ((i = t == null ? void 0 : t.fieldValues) != null && i[e]) && t.fieldValues[e].forEach((n, r) => {
545
+ return e && t?.fieldValues?.[e] && t.fieldValues[e].forEach((o, n) => {
813
546
  a.push({
814
- label: n,
815
- insertText: `"${n}"`,
547
+ label: o,
548
+ insertText: `"${o}"`,
816
549
  kind: "value",
817
550
  detail: `Known value for ${e}`,
818
- sortOrder: 40 + r
551
+ sortOrder: 40 + n
819
552
  });
820
553
  }), a.push(
821
554
  {
@@ -848,8 +581,8 @@ function Y(e, t) {
848
581
  }
849
582
  ), a;
850
583
  }
851
- function K(e, t) {
852
- return E.filter((i) => !t || i.label.toLowerCase().includes(t.toLowerCase())).map((i, o) => ({
584
+ function V(e, t) {
585
+ return P.filter((i) => !t || i.label.toLowerCase().includes(t.toLowerCase())).map((i, o) => ({
853
586
  label: i.label,
854
587
  insertText: i.insertText,
855
588
  kind: "snippet",
@@ -858,60 +591,34 @@ function K(e, t) {
858
591
  sortOrder: 100 + o
859
592
  }));
860
593
  }
861
- function W(e) {
862
- return D.filter((t) => !e || t.toLowerCase().includes(e.toLowerCase())).map(
594
+ function j(e) {
595
+ return R.filter((t) => !e || t.toLowerCase().includes(e.toLowerCase())).map(
863
596
  (t, a) => {
864
- const i = z[t] || { detail: "Field mutator", documentation: "" };
865
- // Check if this mutator has parameters defined
866
- const hasParams = MUTATOR_PARAMETERS[t] && MUTATOR_PARAMETERS[t].length > 0;
867
- const isEnrichment = ENRICHMENT_MUTATORS.includes(t);
868
-
869
- // Build label and insertText
870
- let label = t;
871
- let insertText = t;
872
- let detail = i.detail;
873
-
874
- if (hasParams) {
875
- // Mutators with parameters show () in label and insert with cursor inside
876
- label = `${t}()`;
877
- insertText = `${t}($1)`;
878
- // Add param hint to detail
879
- const paramNames = MUTATOR_PARAMETERS[t].map(p => p.name).join(", ");
880
- detail = `${i.detail} - params: ${paramNames}`;
881
- } else if (isEnrichment) {
882
- // Enrichment mutators without params still get () for consistency
883
- label = `${t}()`;
884
- insertText = `${t}()`;
885
- }
886
-
597
+ const i = M[t] || { detail: "Field mutator", documentation: "" };
887
598
  return {
888
- label: label,
889
- insertText: insertText,
599
+ label: t,
600
+ insertText: t,
890
601
  kind: "mutator",
891
- detail: detail,
602
+ detail: i.detail,
892
603
  documentation: i.documentation,
893
604
  sortOrder: 60 + a
894
605
  };
895
606
  }
896
607
  );
897
608
  }
898
- function O(e) {
899
- return R.filter(
609
+ function C(e) {
610
+ return S.filter(
900
611
  (t) => !e || t.toLowerCase().includes(e.toLowerCase())
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
- });
612
+ ).map((t, a) => ({
613
+ label: t,
614
+ insertText: `${t}($1)`,
615
+ kind: "aggregation",
616
+ detail: "Aggregation function",
617
+ sortOrder: 70 + a
618
+ }));
912
619
  }
913
- function Z(e) {
914
- return P.filter(
620
+ function H(e) {
621
+ return L.filter(
915
622
  (t) => !e || t.toLowerCase().includes(e.toLowerCase())
916
623
  ).map((t, a) => ({
917
624
  label: t,
@@ -921,8 +628,8 @@ function Z(e) {
921
628
  sortOrder: 80 + a
922
629
  }));
923
630
  }
924
- function J(e) {
925
- return $.filter(
631
+ function Y(e) {
632
+ return A.filter(
926
633
  (t) => !e || t.toLowerCase().includes(e.toLowerCase())
927
634
  ).map((t, a) => ({
928
635
  label: t,
@@ -932,8 +639,8 @@ function J(e) {
932
639
  sortOrder: 90 + a
933
640
  }));
934
641
  }
935
- function ne(e, t) {
936
- const i = b(e).find(
642
+ function Q(e, t) {
643
+ const i = x(e).find(
937
644
  (o) => o.start <= t && o.end >= t && o.type !== "whitespace"
938
645
  );
939
646
  return i ? {
@@ -942,63 +649,17 @@ function ne(e, t) {
942
649
  end: i.end
943
650
  } : null;
944
651
  }
945
- function oe() {
652
+ function X() {
946
653
  return [" ", "(", ".", '"', "'", "|", ":", "="];
947
654
  }
948
- function ie(e, t, a) {
655
+ function ee(e, t, a) {
949
656
  if (a === " " || a === "(" || a === "." || a === "|" || a === ":" || a === "=") return !0;
950
- const i = b(e.substring(0, t)), o = i[i.length - 1];
657
+ const i = x(e.substring(0, t)), o = i[i.length - 1];
951
658
  return !!(o && o.type === "field" && o.value.length >= 2);
952
659
  }
953
- /**
954
- * Get mutator parameter completions
955
- * @param mutatorName - The mutator name (e.g., "geo", "nslookup")
956
- * @param usedParams - Parameters already used in the current call
957
- * @param partialText - Partial text for filtering
958
- */
959
- function getMutatorParameterCompletions(mutatorName, usedParams = [], partialText) {
960
- const params = MUTATOR_PARAMETERS[mutatorName];
961
- if (!params || params.length === 0) {
962
- return [];
963
- }
964
-
965
- // Filter out already used parameters
966
- const usedSet = new Set(usedParams.map(p => p.toLowerCase()));
967
- const availableParams = params.filter(p => !usedSet.has(p.name.toLowerCase()));
968
-
969
- // Filter by partial text if provided
970
- let filteredParams = availableParams;
971
- if (partialText) {
972
- const searchText = partialText.toLowerCase();
973
- filteredParams = availableParams.filter(p =>
974
- p.name.toLowerCase().includes(searchText)
975
- );
976
- }
977
-
978
- return filteredParams.map((param, idx) => {
979
- // Generate insert text based on parameter type
980
- let insertText = `${param.name}=`;
981
- if (param.type === "boolean") {
982
- insertText = `${param.name}=true`;
983
- } else if (param.type === "string") {
984
- insertText = `${param.name}="$1"`;
985
- } else if (param.type === "number") {
986
- insertText = `${param.name}=$1`;
987
- }
988
-
989
- return {
990
- label: param.name,
991
- insertText: insertText,
992
- kind: "property",
993
- detail: `${param.type} - ${param.description}`,
994
- documentation: param.description,
995
- sortOrder: 100 + idx
996
- };
997
- });
998
- }
999
660
  export {
1000
- oe as getCompletionTriggerCharacters,
1001
- ae as getCompletions,
1002
- ne as getWordAtPosition,
1003
- ie as shouldTriggerCompletion
661
+ X as getCompletionTriggerCharacters,
662
+ J as getCompletions,
663
+ Q as getWordAtPosition,
664
+ ee as shouldTriggerCompletion
1004
665
  };