@xano/developer-mcp 1.0.53 → 1.0.56

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.
@@ -4,7 +4,7 @@ applyTo: "**/*.xs"
4
4
 
5
5
  # Syntax Reference
6
6
 
7
- Complete reference for XanoScript expressions, operators, and filters.
7
+ Complete reference for XanoScript expressions, operators, and core filters. For extended filter references, see the syntax sub-topics.
8
8
 
9
9
  > **TL;DR:** XanoScript uses `|` for filters (`$text|trim`), `~` for string concat, and standard operators (`==`, `!=`, `&&`, `||`). Filters are chainable. Error handling uses `precondition`, `try_catch`, and `throw`.
10
10
 
@@ -15,22 +15,20 @@ Complete reference for XanoScript expressions, operators, and filters.
15
15
  | [Operators](#quick-reference) | Comparison, logical, math, null-safe |
16
16
  | [Conditional Blocks](#conditional-blocks) | `conditional`, `if`/`elseif`/`else` |
17
17
  | [Expressions](#expressions) | Backtick syntax, comparisons |
18
- | [Math Filters](#math-filters) | `add`, `subtract`, `round`, `abs`, `ceil`, `floor` |
19
- | [String Filters](#string-filters) | `trim`, `to_lower`, `to_upper`, `substr`, `split`, `replace` |
20
- | [Array Filters](#array-filters) | `first`, `last`, `count`, `map`, `filter`, `reduce` |
21
- | [Array Functions](#array-functions) | `array.push`, `array.pop`, `array.map`, `array.filter`, `array.group_by` |
22
- | [Text Functions](#text-functions) | `text.contains`, `text.starts_with`, `text.trim`, `text.append`, `text.prepend` |
23
- | [Math Functions](#math-functions) | `math.add`, `math.sub`, `math.mul`, `math.div`, `math.bitwise.*` |
24
- | [Object Functions](#object-functions) | `object.keys`, `object.values`, `object.entries` |
25
18
  | [Object Filters](#object-filters) | `get`, `set`, `has`, `keys`, `values` |
26
19
  | [Type Filters](#type-filters) | `to_int`, `to_text`, `to_bool`, `json_encode` |
27
20
  | [Date/Time Filters](#datetime-filters) | `to_timestamp`, `format_timestamp` |
28
- | [Encoding Filters](#encoding-filters) | `url_encode`, `base64_encode`, `json_encode` |
29
- | [Security Filters](#security-filters) | `md5`, `sha256`, `encrypt`, `jws_encode` |
30
21
  | [DB Query Filters](#db-query-filters) | `contains`, `includes`, `between`, `within` |
31
22
  | [Error Handling](#error-handling) | `precondition`, `try_catch`, `throw` |
32
23
  | [System Variables](#system-variables) | `$env.*`, `$auth.*`, request context |
33
24
 
25
+ ### Extended Filter Sub-Topics
26
+
27
+ For detailed references on specific filter categories, use:
28
+ - `xanoscript_docs({ topic: "syntax/string-filters" })` — String filters, regex, encoding, security filters, text functions
29
+ - `xanoscript_docs({ topic: "syntax/array-filters" })` — Array filters, functional operations, array functions
30
+ - `xanoscript_docs({ topic: "syntax/functions" })` — Math filters/functions, object functions, bitwise operations
31
+
34
32
  ## CRITICAL: Filters Are Type-Specific
35
33
 
36
34
  > **Filters only work on the correct input type.** String filters and array filters are NOT interchangeable. Using the wrong filter type will produce errors or incorrect results.
@@ -50,14 +48,14 @@ Complete reference for XanoScript expressions, operators, and filters.
50
48
 
51
49
  ```
52
50
  Working with...
53
- ├── Strings? → USE STRING FILTERS ONLY (see String Filters section)
51
+ ├── Strings? → USE STRING FILTERS ONLY
54
52
  │ ├── Clean whitespace? → trim, ltrim, rtrim
55
53
  │ ├── Change case? → to_lower, to_upper, capitalize
56
54
  │ ├── Extract part? → substr (NOT slice)
57
55
  │ ├── Split to array? → split
58
56
  │ ├── Find/replace? → replace, contains
59
57
  │ └── Get length? → strlen (NOT count)
60
- ├── Arrays? → USE ARRAY FILTERS ONLY (see Array Filters section)
58
+ ├── Arrays? → USE ARRAY FILTERS ONLY
61
59
  │ ├── Get element? → first, last, get
62
60
  │ ├── Count items? → count (NOT strlen)
63
61
  │ ├── Transform all? → map (filter) or array.map (statement)
@@ -66,7 +64,7 @@ Working with...
66
64
  │ ├── Combine? → reduce
67
65
  │ ├── Reverse? → reverse (NOT available on strings)
68
66
  │ ├── Sort? → sort
69
- │ └── Statement-level ops? → See Array Functions (array.push, array.pop, etc.)
67
+ │ └── Statement-level ops? → See syntax/array-filters topic
70
68
  ├── Objects?
71
69
  │ ├── Get value? → get
72
70
  │ ├── Set value? → set
@@ -87,6 +85,8 @@ Working with...
87
85
 
88
86
  ### Variable Access Prefixes
89
87
 
88
+ > **Full reference:** See `xanoscript_docs({ topic: "essentials" })` for detailed variable access rules, reserved variables, and type names.
89
+
90
90
  | Prefix | Applies to | Shorthand? |
91
91
  |--------|-----------|------------|
92
92
  | `$input.field` | Input parameters | No — prefix always required |
@@ -95,29 +95,18 @@ Working with...
95
95
  | `$env.NAME` | Environment variables | No |
96
96
  | `$db.table.field` | DB field refs (queries) | No |
97
97
 
98
- ```xs
99
- // ❌ Wrong — input fields are NOT accessible as bare variables
100
- var $name { value = $name } // undefined; inputs live on $input
101
-
102
- // ✅ Correct — always use $input for input fields
103
- var $name { value = $input.name }
104
-
105
- // ✅ Both are valid for stack variables
106
- var $total { value = 0 }
107
- $var.total // explicit
108
- $total // shorthand — same thing
109
- ```
110
-
111
98
  ### Operators
99
+
112
100
  | Category | Operators |
113
101
  |----------|-----------|
114
102
  | Comparison | `==`, `!=`, `>`, `<`, `>=`, `<=` |
115
- | Logical | `&&`, `||`, `!` |
103
+ | Logical | `&&`, `\|\|`, `!` |
116
104
  | Math | `+`, `-`, `*`, `/`, `%` |
117
105
  | String | `~` (concat) |
118
106
  | Null-safe | `==?`, `!=?`, `>=?`, `<=?` (ignore if null) |
119
107
 
120
108
  ### Common Filters
109
+
121
110
  | Filter | Type | Purpose | Example |
122
111
  |--------|------|---------|---------|
123
112
  | `trim` | STRING | Remove whitespace | `$s\|trim` |
@@ -153,8 +142,6 @@ var $message {
153
142
 
154
143
  ```xs
155
144
  // ✅ Correct — evaluate filter first, then apply operator
156
-
157
- // ✅ Correct
158
145
  if (($arr|count) == 0) { ... }
159
146
 
160
147
  // ✅ Correct — wrap each filtered expression for concatenation
@@ -179,10 +166,10 @@ Use `conditional` blocks for if/elseif/else logic:
179
166
 
180
167
  ```xs
181
168
  conditional {
182
- if (`$status == "success"`) {
169
+ if ($status == "success") {
183
170
  var $message { value = "All good!" }
184
171
  }
185
- elseif (`$status == "pending"`) {
172
+ elseif ($status == "pending") {
186
173
  var $message { value = "Please wait..." }
187
174
  }
188
175
  else {
@@ -195,16 +182,14 @@ conditional {
195
182
 
196
183
  ### Conditional with Variable Updates
197
184
 
198
- Use conditional blocks to update a variable based on conditions:
199
-
200
185
  ```xs
201
186
  var $tier_limit { value = 100 }
202
187
 
203
188
  conditional {
204
- if ($auth.tier == "premium") {
189
+ if ($auth.tier == "premium") {
205
190
  var.update $tier_limit { value = 1000 }
206
191
  }
207
- elseif ($auth.tier == "pro") {
192
+ elseif ($auth.tier == "pro") {
208
193
  var.update $tier_limit { value = 500 }
209
194
  }
210
195
  }
@@ -214,14 +199,16 @@ conditional {
214
199
 
215
200
  ## Expressions
216
201
 
217
- Expressions are wrapped in backticks for evaluation:
202
+ Backticks enter **expression mode** use them only when you need inline evaluation of a complex expression, not for regular conditionals or variable assignments.
218
203
 
219
204
  ```xs
205
+ // ✅ Regular conditionals — no backticks needed
220
206
  conditional {
221
- if (`$input.age >= 18`) { ... }
207
+ if ($input.age >= 18) { ... }
222
208
  }
223
209
 
224
- var $total { value = `$input.qty * $input.price` }
210
+ // Variable assignment no backticks needed
211
+ var $total { value = $input.qty * $input.price }
225
212
  ```
226
213
 
227
214
  ### Comparison
@@ -250,568 +237,6 @@ $db.post.date >=? $input.start_date
250
237
 
251
238
  ---
252
239
 
253
- ## Math Filters
254
-
255
- | Filter | Example | Result |
256
- |--------|---------|--------|
257
- | `add` | `10\|add:5` | `15` |
258
- | `subtract` | `10\|subtract:3` | `7` |
259
- | `multiply` | `10\|multiply:2` | `20` |
260
- | `divide` | `10\|divide:2` | `5` |
261
- | `modulus` | `10\|modulus:3` | `1` |
262
- | `floor` | `2.7\|floor` | `2` |
263
- | `ceil` | `2.3\|ceil` | `3` |
264
- | `round` | `2.567\|round:2` | `2.57` |
265
- | `abs` | `-5\|abs` | `5` |
266
- | `sqrt` | `9\|sqrt` | `3` |
267
- | `pow` | `2\|pow:3` | `8` |
268
- | `min` | `5\|min:3` | `3` |
269
- | `max` | `5\|max:10` | `10` |
270
-
271
- ### Array Math
272
- ```xs
273
- [1,2,3,4]|sum // 10
274
- [1,2,3,4]|avg // 2.5
275
- [1,2,3,4]|product // 24
276
- [5,2,8,1]|array_min // 1
277
- [5,2,8,1]|array_max // 8
278
- ```
279
-
280
- ### Trigonometry
281
- `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `deg2rad`, `rad2deg`
282
-
283
- ---
284
-
285
- ## String Filters
286
-
287
- > **These filters operate on STRING values only.** Do not use array filters (`count`, `reverse`, `first`, `last`, `slice`) on strings. Use `strlen` for string length, `substr` for substrings.
288
-
289
- | Filter | Example | Result |
290
- |--------|---------|--------|
291
- | `trim` | `" hi "\|trim` | `"hi"` |
292
- | `ltrim` / `rtrim` | `" hi"\|ltrim` | `"hi"` |
293
- | `to_lower` | `"Hi"\|to_lower` | `"hi"` |
294
- | `to_upper` | `"Hi"\|to_upper` | `"HI"` |
295
- | `capitalize` | `"hi there"\|capitalize` | `"Hi There"` |
296
- | `strlen` | `"hello"\|strlen` | `5` |
297
- | `substr` | `"hello"\|substr:1:3` | `"ell"` |
298
- | `split` | `"a,b,c"\|split:","` | `["a","b","c"]` |
299
- | `replace` | `"hello"\|replace:"l":"x"` | `"hexxo"` |
300
- | `contains` | `"hello"\|contains:"ell"` | `true` |
301
- | `starts_with` | `"hello"\|starts_with:"he"` | `true` |
302
- | `ends_with` | `"hello"\|ends_with:"lo"` | `true` |
303
- | `concat` | `"a"\|concat:"b":"-"` | `"a-b"` |
304
-
305
- ### Case-Insensitive Variants
306
- `icontains`, `istarts_with`, `iends_with`, `iindex`
307
-
308
- ### Regex
309
- ```xs
310
- "/pattern/"|regex_matches:"subject" // Boolean match
311
- "/(\w+)/"|regex_get_first_match:"test" // First match
312
- "/\w+/"|regex_get_all_matches:"a b c" // All matches
313
- "/\s+/"|regex_replace:"-":"a b" // Replace: "a-b"
314
- ```
315
-
316
- ---
317
-
318
- ## Array Filters
319
-
320
- > **These filters operate on ARRAY values only.** Do not use string filters (`strlen`, `substr`, `split`, `replace`) on arrays. Use `count` for array length, `slice` for sub-arrays, `join` to convert to string.
321
-
322
- | Filter | Example | Result |
323
- |--------|---------|--------|
324
- | `first` | `[1,2,3]\|first` | `1` |
325
- | `last` | `[1,2,3]\|last` | `3` |
326
- | `count` | `[1,2,3]\|count` | `3` |
327
- | `reverse` | `[1,2,3]\|reverse` | `[3,2,1]` |
328
- | `unique` | `[1,1,2]\|unique` | `[1,2]` |
329
- | `flatten` | `[[1,2],[3]]\|flatten` | `[1,2,3]` |
330
- | `shuffle` | `[1,2,3]\|shuffle` | Random order |
331
- | `slice` | `[1,2,3,4]\|slice:1:2` | `[2,3]` — offset 1, length 2 |
332
- | `push` | `[1,2]\|push:3` | `[1,2,3]` |
333
- | `pop` | `[1,2,3]\|pop` | `3` |
334
- | `shift` | `[1,2,3]\|shift` | `1` |
335
- | `unshift` | `[1,2]\|unshift:0` | `[0,1,2]` |
336
- | `merge` | `[1,2]\|merge:[3,4]` | `[1,2,3,4]` |
337
- | `diff` | `[1,2,3]\|diff:[2]` | `[1,3]` |
338
- | `intersect` | `[1,2,3]\|intersect:[2,3,4]` | `[2,3]` |
339
- | `join` | `["a","b"]\|join:","` | `"a,b"` |
340
- | `range` | `\|range:1:5` | `[1,2,3,4,5]` |
341
- | `..` | `(1..5)` | `[1,2,3,4,5]` |
342
-
343
- ### Range Operator
344
-
345
- Generate numeric ranges with the `..` operator:
346
-
347
- ```xs
348
- (1..5) // [1,2,3,4,5]
349
- (0..10) // [0,1,2,3,4,5,6,7,8,9,10]
350
- ($start..$end) // Dynamic range with variables
351
- ```
352
-
353
- ### Functional Operations
354
- ```xs
355
- // Map - transform each element
356
- [{v:1},{v:2}]|map:$$.v*2 // [2,4]
357
-
358
- // Filter - keep matching elements
359
- [1,2,3,4]|filter:$$%2==0 // [2,4]
360
-
361
- // Find - first matching element
362
- [{id:1},{id:2}]|find:$$.id==2 // {id:2}
363
-
364
- // FindIndex - index of first match
365
- [{id:1},{id:2}]|findIndex:$$.id==2 // 1
366
-
367
- // Some - any element matches?
368
- [1,2,3]|some:$$>2 // true
369
-
370
- // Every - all elements match?
371
- [2,4,6]|every:$$%2==0 // true
372
-
373
- // Reduce - accumulate to single value
374
- [1,2,3,4]|reduce:$$+$result:0 // 10
375
- ```
376
-
377
- ### Array Element Access: `|get` vs `|slice`
378
-
379
- > **`|get:N`** returns a **single element** by zero-based index.
380
- > **`|slice:offset:length`** returns a **sub-array**, skipping `offset` elements and returning the next `length` elements.
381
-
382
- | Method | Use For | Example | Result |
383
- |--------|---------|---------|--------|
384
- | `\|get:N` | Single element by index (0-based) | `[10,20,30]\|get:0` | `10` |
385
- | `\|slice:offset:length` | Sub-array — skip N, take M | `[10,20,30,40]\|slice:1:2` | `[20,30]` |
386
- | `\|first` | First element | `[10,20,30]\|first` | `10` |
387
- | `\|last` | Last element | `[10,20,30]\|last` | `30` |
388
-
389
- ```xs
390
- // Single element by index
391
- var $third { value = $items|get:2 } // 0-based: 3rd element
392
-
393
- // Sub-array: skip first 10, return the next 5
394
- var $page { value = $items|slice:10:5 }
395
-
396
- // ⚠️ slice:offset:length — NOT slice:start:end
397
- // $arr|slice:2:3 → skip 2, return 3 elements (indices 2, 3, 4)
398
- // NOT "from index 2 to index 3"
399
- ```
400
-
401
- ### Grouping & Indexing
402
- ```xs
403
- // Group by property
404
- [{g:"a",v:1},{g:"b",v:2},{g:"a",v:3}]|index_by:g
405
- // {"a":[{g:"a",v:1},{g:"a",v:3}],"b":[{g:"b",v:2}]}
406
-
407
- // Sort
408
- [{n:"z"},{n:"a"}]|sort:n:text:false // Ascending by n
409
- ```
410
-
411
- ---
412
-
413
- ## Array Functions
414
-
415
- Statement-level functions for manipulating arrays within stacks. Unlike filters (e.g., `$arr|push:3`), these are standalone operations.
416
-
417
- > **Syntax note:** Functions that use a `{ by = ... }` or `{ value = ... }` block wrap the array in parentheses — e.g., `array.map ($arr) { ... }`. Functions that use an `if (...)` condition take a bare variable — e.g., `array.filter $arr if (...) as $result`.
418
-
419
- ### array.push
420
-
421
- Appends a new element to the end of an array.
422
-
423
- ```xs
424
- array.push $shopping_cart {
425
- value = "oranges"
426
- }
427
- ```
428
-
429
- ### array.unshift
430
-
431
- Inserts a new element at the beginning of an array, shifting existing elements to higher indexes.
432
-
433
- ```xs
434
- array.unshift $priority_tasks {
435
- value = "urgent meeting"
436
- }
437
- ```
438
-
439
- ### array.pop
440
-
441
- Removes and returns the last element of an array. The removed element is stored in the `as` variable.
442
-
443
- ```xs
444
- array.pop $completed_tasks as $last_finished_task
445
- ```
446
-
447
- ### array.shift
448
-
449
- Removes and returns the first element of an array. The removed element is stored in the `as` variable.
450
-
451
- ```xs
452
- array.shift $waiting_list as $next_customer
453
- ```
454
-
455
- ### array.merge
456
-
457
- Combines another array or a single value into the target array, appending all elements from the provided `value`.
458
-
459
- ```xs
460
- array.merge $active_users {
461
- value = $new_users
462
- }
463
- ```
464
-
465
- ### array.find
466
-
467
- Searches an array and returns the first element that meets the specified condition. Returns `null` if no match.
468
-
469
- ```xs
470
- array.find $customer_ages if ($this > 18) as $first_adult_age
471
- ```
472
-
473
- ### array.find_index
474
-
475
- Returns the index of the first element that satisfies the condition. Returns `-1` if no match.
476
-
477
- ```xs
478
- array.find_index $sale_prices if ($this < 20) as $first_discount_index
479
- ```
480
-
481
- ### array.has
482
-
483
- Checks if at least one element meets the condition. Returns `true` or `false`.
484
-
485
- ```xs
486
- array.has $team_roles if ($this == "manager") as $has_manager
487
- ```
488
-
489
- ### array.every
490
-
491
- Tests whether every element satisfies the condition. Returns `true` if all pass, `false` otherwise.
492
-
493
- ```xs
494
- array.every $exam_scores if ($this >= 70) as $all_passed
495
- ```
496
-
497
- ### array.filter
498
-
499
- Creates a new array containing only the elements that meet the condition.
500
-
501
- ```xs
502
- array.filter $temperatures if ($this > 32) as $above_freezing
503
- ```
504
-
505
- ### array.filter_count
506
-
507
- Counts how many elements satisfy the condition.
508
-
509
- ```xs
510
- array.filter_count $survey_responses if ($this == "yes") as $yes_count
511
- ```
512
-
513
- ### array.map
514
-
515
- Transforms each element in an array based on a specified mapping. The `by` parameter defines the transformation.
516
-
517
- ```xs
518
- array.map ($json) {
519
- by = $this.email
520
- } as $emails
521
-
522
- array.map ($json) {
523
- by = {name: $this.name, gender: $this.gender}
524
- } as $people
525
- ```
526
-
527
- ### array.partition
528
-
529
- Divides an array into two groups based on a condition. Returns an object with `true` and `false` keys.
530
-
531
- ```xs
532
- array.partition ($json) if ($this.gender == "male") as $is_male
533
- ```
534
-
535
- ### array.group_by
536
-
537
- Groups elements based on a specified key or expression. Returns an object where each key is a group.
538
-
539
- ```xs
540
- array.group_by ($users) {
541
- by = $this.gender
542
- } as $user_by_gender
543
- ```
544
-
545
- ### array.union
546
-
547
- Combines two arrays ensuring all elements are unique based on the `by` key.
548
-
549
- ```xs
550
- array.union ([1,3,5,7,9]) {
551
- value = [2,4,6,8]
552
- by = $this
553
- } as $union
554
- // Result: [1,2,3,4,5,6,7,8,9]
555
- ```
556
-
557
- ### array.difference
558
-
559
- Returns elements present in the first array but not in the second, based on the `by` key.
560
-
561
- ```xs
562
- array.difference ([1,2,3,4,5,6,7,8,9]) {
563
- value = [2,4,6,8]
564
- by = $this
565
- } as $difference
566
- // Result: [1,3,5,7,9]
567
- ```
568
-
569
- ### array.intersection
570
-
571
- Returns elements present in both arrays, based on the `by` key.
572
-
573
- ```xs
574
- array.intersection ([1,2,3,4,5,6,7,8,9]) {
575
- value = [2,4,6,8]
576
- by = $this
577
- } as $intersection
578
- // Result: [2,4,6,8]
579
- ```
580
-
581
- ---
582
-
583
- ## Text Functions
584
-
585
- Statement-level functions for text manipulation within stacks. These operate directly on variables — checking conditions (returning `true`/`false` via `as`) or mutating the variable in place.
586
-
587
- > **Syntax note:** Functions that check a condition (e.g., `text.contains`, `text.starts_with`) store the result in an `as` variable. Functions that modify text (e.g., `text.trim`, `text.append`) mutate the variable directly and do not return a value.
588
-
589
- ### text.contains
590
-
591
- Checks if a text string contains the specified value. Returns `true` if found, `false` otherwise.
592
-
593
- ```xs
594
- text.contains $log_entry {
595
- value = "error"
596
- } as $has_error
597
- ```
598
-
599
- ### text.icontains
600
-
601
- Performs a case-insensitive check to see if a text string contains the specified value.
602
-
603
- ```xs
604
- text.icontains $description {
605
- value = "error"
606
- } as $has_error
607
- ```
608
-
609
- ### text.starts_with
610
-
611
- Checks if a text string begins with the specified value.
612
-
613
- ```xs
614
- text.starts_with $message {
615
- value = "Hello"
616
- } as $starts_with_hello
617
- ```
618
-
619
- ### text.istarts_with
620
-
621
- Performs a case-insensitive check to see if a text string starts with the specified value.
622
-
623
- ```xs
624
- text.istarts_with $title {
625
- value = "intro"
626
- } as $starts_with_intro
627
- ```
628
-
629
- ### text.ends_with
630
-
631
- Checks if a text string ends with the specified value.
632
-
633
- ```xs
634
- text.ends_with $url {
635
- value = ".com"
636
- } as $is_com_domain
637
- ```
638
-
639
- ### text.iends_with
640
-
641
- Performs a case-insensitive check to see if a text string ends with the specified value.
642
-
643
- ```xs
644
- text.iends_with $filename {
645
- value = "pdf"
646
- } as $ends_with_pdf
647
- ```
648
-
649
- ### text.trim
650
-
651
- Removes characters (default is whitespace, or as specified by `value`) from both the beginning and end of a text string. Mutates the variable directly.
652
-
653
- ```xs
654
- text.trim $user_input {
655
- value = " "
656
- }
657
- ```
658
-
659
- ### text.ltrim
660
-
661
- Removes leading characters (default is whitespace, or as specified by `value`) from a text string. Mutates the variable directly.
662
-
663
- ```xs
664
- text.ltrim $user_input {
665
- value = " "
666
- }
667
- ```
668
-
669
- ### text.rtrim
670
-
671
- Removes trailing characters (default is whitespace, or as specified by `value`) from a text string. Mutates the variable directly.
672
-
673
- ```xs
674
- text.rtrim $user_input {
675
- value = " "
676
- }
677
- ```
678
-
679
- ### text.append
680
-
681
- Adds the specified value to the end of a text string. Mutates the variable directly.
682
-
683
- ```xs
684
- text.append $greeting {
685
- value = ", welcome!"
686
- }
687
- ```
688
-
689
- ### text.prepend
690
-
691
- Adds the specified value to the beginning of a text string. Mutates the variable directly.
692
-
693
- ```xs
694
- text.prepend $message {
695
- value = "Alert: "
696
- }
697
- ```
698
-
699
- ---
700
-
701
- ## Math Functions
702
-
703
- Statement-level functions for arithmetic and bitwise operations within stacks. These mutate the target variable directly and do not return a value.
704
-
705
- > **Note:** These are different from math filters (e.g., `$x|add:5`) and math domain functions (e.g., `math.add(5, 3)`). Statement-level math functions modify the variable in place.
706
-
707
- ### math.add
708
-
709
- Adds the specified value to the variable.
710
-
711
- ```xs
712
- math.add $cart_total {
713
- value = $item_price
714
- }
715
- ```
716
-
717
- ### math.sub
718
-
719
- Subtracts the specified value from the variable.
720
-
721
- ```xs
722
- math.sub $total_cost {
723
- value = $discount_amount
724
- }
725
- ```
726
-
727
- ### math.mul
728
-
729
- Multiplies the variable by the specified value.
730
-
731
- ```xs
732
- math.mul $base_price {
733
- value = $tax_rate
734
- }
735
- ```
736
-
737
- ### math.div
738
-
739
- Divides the variable by the specified value.
740
-
741
- ```xs
742
- math.div $total_time {
743
- value = $num_tasks
744
- }
745
- ```
746
-
747
- ### math.bitwise.and
748
-
749
- Performs a bitwise AND operation on the variable.
750
-
751
- ```xs
752
- math.bitwise.and $status_flags {
753
- value = $check_bit
754
- }
755
- ```
756
-
757
- ### math.bitwise.or
758
-
759
- Performs a bitwise OR operation on the variable.
760
-
761
- ```xs
762
- math.bitwise.or $permissions {
763
- value = $new_permission
764
- }
765
- ```
766
-
767
- ### math.bitwise.xor
768
-
769
- Performs a bitwise XOR operation on the variable.
770
-
771
- ```xs
772
- math.bitwise.xor $flags {
773
- value = $toggle_bit
774
- }
775
- ```
776
-
777
- ---
778
-
779
- ## Object Functions
780
-
781
- Statement-level functions for extracting object properties within stacks. These return results via the `as` variable.
782
-
783
- ### object.keys
784
-
785
- Retrieves the property keys of an object as an array.
786
-
787
- ```xs
788
- object.keys {
789
- value = $user_data
790
- } as $user_data_keys
791
- ```
792
-
793
- ### object.values
794
-
795
- Extracts the values of an object's properties into an array.
796
-
797
- ```xs
798
- object.values {
799
- value = $product_info
800
- } as $product_values
801
- ```
802
-
803
- ### object.entries
804
-
805
- Returns an array of key-value pairs from an object.
806
-
807
- ```xs
808
- object.entries {
809
- value = $settings
810
- } as $settings_pairs
811
- ```
812
-
813
- ---
814
-
815
240
  ## Object Filters
816
241
 
817
242
  | Filter | Example | Result |
@@ -858,6 +283,22 @@ null|first_notnull:0 // 0
858
283
  ""|first_notempty:"default" // "default"
859
284
  ```
860
285
 
286
+ ### Nullish Coalescing
287
+
288
+ Return right operand when left is null (not just falsy):
289
+
290
+ ```xs
291
+ $value ?? "default" // Returns "default" only if $value is null
292
+ $value || "default" // Returns "default" if $value is null, 0, "", or false
293
+ ```
294
+
295
+ ```xs
296
+ // Difference example
297
+ var $count { value = 0 }
298
+ $count ?? 10 // Returns 0 (not null)
299
+ $count || 10 // Returns 10 (0 is falsy)
300
+ ```
301
+
861
302
  ---
862
303
 
863
304
  ## Date/Time Filters
@@ -884,40 +325,6 @@ $ts|timestamp_day_of_week // Day (0=Sunday)
884
325
 
885
326
  ---
886
327
 
887
- ## Encoding Filters
888
-
889
- | Filter | Example |
890
- |--------|---------|
891
- | `json_encode` | `{a:1}\|json_encode` |
892
- | `json_decode` | `'{"a":1}'\|json_decode` |
893
- | `base64_encode` | `"hello"\|base64_encode` |
894
- | `base64_decode` | `"aGVsbG8="\|base64_decode` |
895
- | `url_encode` | `"a b"\|url_encode` |
896
- | `url_decode` | `"a%20b"\|url_decode` |
897
- | `xml_decode` | `"<a>1</a>"\|xml_decode` |
898
- | `yaml_encode` / `yaml_decode` | YAML conversion |
899
- | `hex2bin` / `bin2hex` | Hex conversion |
900
-
901
- ---
902
-
903
- ## Security Filters
904
-
905
- > **Full reference:** For security best practices, see `xanoscript_docs({ topic: "security" })`.
906
-
907
- | Filter | Example |
908
- |--------|---------|
909
- | `md5` | `"text"\|md5` |
910
- | `sha1` / `sha256` / `sha512` | Hash functions |
911
- | `hmac_sha256` | `"msg"\|hmac_sha256:"key"` |
912
- | `encrypt` | `"data"\|encrypt:"aes-256-cbc":"key":"iv"` |
913
- | `decrypt` | `$enc\|decrypt:"aes-256-cbc":"key":"iv"` |
914
- | `jws_encode` / `jws_decode` | JWT signing |
915
- | `jwe_encode` / `jwe_decode` | JWT encryption |
916
- | `secureid_encode` / `secureid_decode` | ID obfuscation |
917
- | `uuid` | `\|uuid` |
918
-
919
- ---
920
-
921
328
  ## DB Query Filters
922
329
 
923
330
  > **Full reference:** For complete database operations, see `xanoscript_docs({ topic: "database" })`.
@@ -936,10 +343,56 @@ Used in `db.query` where clauses:
936
343
  | `cosine_similarity` | `$db.vector\|cosine_similarity:$vec` | Vector similarity |
937
344
  | `l2_distance_euclidean` | `$db.vector\|l2_distance_euclidean:$vec` | Vector distance |
938
345
 
346
+ ### Database Filter Operators
347
+
348
+ Additional operators for `db.query` where clauses:
349
+
350
+ | Operator | Description | Example |
351
+ |----------|-------------|---------|
352
+ | `@>` | JSON contains | `$db.meta @> {"type": "featured"}` |
353
+ | `~` | Regex match | `$db.name ~ "^test"` |
354
+ | `!~` | Regex not match | `$db.name !~ "^draft"` |
355
+ | `not in` | Not in list | `$db.status not in ["deleted", "hidden"]` |
356
+ | `not between` | Not in range | `$db.price not between 0:10` |
357
+ | `not contains` | Array not contains | `$db.tags not contains "spam"` |
358
+ | `not includes` | String not includes | `$db.title not includes "test"` |
359
+ | `not overlaps` | Arrays don't overlap | `$db.tags not overlaps ["hidden", "draft"]` |
360
+ | `not ilike` | Case-insensitive not like | `$db.name not ilike "%test%"` |
361
+
362
+ ```xs
363
+ db.query "product" {
364
+ where = $db.product.status not in ["deleted", "archived"]
365
+ && $db.product.metadata @> {"featured": true}
366
+ && $db.product.sku ~ "^SKU-[0-9]+"
367
+ } as $products
368
+ ```
369
+
939
370
  ### Timestamp Arithmetic (DB)
371
+
940
372
  ```xs
941
373
  $db.created_at|timestamp_add_days:7
942
374
  $db.created_at|timestamp_subtract_hours:24
375
+ $db.created_at|timestamp_year // Extract year
376
+ $db.created_at|timestamp_month // Extract month (1-12)
377
+ $db.created_at|timestamp_week // Extract week number
378
+ $db.created_at|timestamp_day_of_month // Day of month (1-31)
379
+ $db.created_at|timestamp_day_of_week // Day of week (0-6)
380
+ $db.created_at|timestamp_day_of_year // Day of year (1-366)
381
+ $db.created_at|timestamp_hour // Hour (0-23)
382
+ $db.created_at|timestamp_minute // Minute (0-59)
383
+ $db.created_at|timestamp_epoch_seconds // Seconds since epoch
384
+ $db.created_at|timestamp_epoch_ms // Milliseconds since epoch
385
+ ```
386
+
387
+ ### Vector Operations (AI/ML)
388
+
389
+ > **Full reference:** For AI agents and embeddings, see `xanoscript_docs({ topic: "agents" })`.
390
+
391
+ ```xs
392
+ $db.embedding|l1_distance_manhattan:$input.vector // L1/Manhattan distance
393
+ $db.embedding|negative_inner_product:$input.vector // Negative inner product
394
+ $db.embedding|inner_product:$input.vector // Inner product
395
+ $db.boundary|covers:$input.point // Polygon covers point
943
396
  ```
944
397
 
945
398
  ---
@@ -948,7 +401,7 @@ $db.created_at|timestamp_subtract_hours:24
948
401
 
949
402
  ### Preconditions
950
403
 
951
- Validate conditions and throw typed errors:
404
+ Validate conditions and throw typed errors. See `xanoscript_docs({ topic: "essentials" })` for the error types reference table.
952
405
 
953
406
  ```xs
954
407
  precondition ($input.amount > 0) {
@@ -967,15 +420,6 @@ precondition ($user.id == $auth.id) {
967
420
  }
968
421
  ```
969
422
 
970
- ### Error Types
971
-
972
- | Type | HTTP Status | Use Case |
973
- |------|-------------|----------|
974
- | `inputerror` | 400 Bad Request | Invalid input data |
975
- | `accessdenied` | 403 Forbidden | Authorization failure |
976
- | `notfound` | 404 Not Found | Resource doesn't exist |
977
- | `standard` | 500 Internal Server Error | General errors |
978
-
979
423
  ### Throwing Errors
980
424
 
981
425
  ```xs
@@ -1054,259 +498,6 @@ var $current_branch { value = $env.$branch }
1054
498
  var $api_key { value = $env.MY_API_KEY }
1055
499
  ```
1056
500
 
1057
- ### $env Limitations
1058
-
1059
- > **Important:** `$env` variables cannot be used in `run.job` or `run.service` input blocks. Input values must be constants.
1060
-
1061
- ```xs
1062
- // ❌ Invalid - $env not allowed in run.job input
1063
- run.job "my_job" {
1064
- input {
1065
- text api_key = $env.API_KEY // Error!
1066
- }
1067
- }
1068
-
1069
- // ✅ Valid - access $env inside the stack instead
1070
- run.job "my_job" {
1071
- input {
1072
- text api_key // No default value
1073
- }
1074
- stack {
1075
- var $key { value = $env.API_KEY }
1076
- }
1077
- }
1078
- ```
1079
-
1080
- ---
1081
-
1082
- ## Additional Operators
1083
-
1084
- ### Nullish Coalescing
1085
-
1086
- Return right operand when left is null (not just falsy):
1087
-
1088
- ```xs
1089
- $value ?? "default" // Returns "default" only if $value is null
1090
- $value || "default" // Returns "default" if $value is null, 0, "", or false
1091
- ```
1092
-
1093
- ```xs
1094
- // Difference example
1095
- var $count { value = 0 }
1096
- $count ?? 10 // Returns 0 (not null)
1097
- $count || 10 // Returns 10 (0 is falsy)
1098
- ```
1099
-
1100
- ### Database Filter Operators
1101
-
1102
- Additional operators for `db.query` where clauses:
1103
-
1104
- | Operator | Description | Example |
1105
- |----------|-------------|---------|
1106
- | `@>` | JSON contains | `$db.meta @> {"type": "featured"}` |
1107
- | `~` | Regex match | `$db.name ~ "^test"` |
1108
- | `!~` | Regex not match | `$db.name !~ "^draft"` |
1109
- | `not in` | Not in list | `$db.status not in ["deleted", "hidden"]` |
1110
- | `not between` | Not in range | `$db.price not between 0:10` |
1111
- | `not contains` | Array not contains | `$db.tags not contains "spam"` |
1112
- | `not includes` | String not includes | `$db.title not includes "test"` |
1113
- | `not overlaps` | Arrays don't overlap | `$db.tags not overlaps ["hidden", "draft"]` |
1114
- | `not ilike` | Case-insensitive not like | `$db.name not ilike "%test%"` |
1115
-
1116
- ```xs
1117
- db.query "product" {
1118
- where = $db.product.status not in ["deleted", "archived"]
1119
- && $db.product.metadata @> {"featured": true}
1120
- && $db.product.sku ~ "^SKU-[0-9]+"
1121
- } as $products
1122
- ```
1123
-
1124
- ---
1125
-
1126
- ## Additional Filters
1127
-
1128
- ### Text Domain Functions
1129
-
1130
- Functional equivalents for string operations:
1131
-
1132
- ```xs
1133
- text.contains("hello world", "world") // true
1134
- text.starts_with("hello", "he") // true
1135
- text.ends_with("hello", "lo") // true
1136
- text.icontains("Hello World", "WORLD") // true (case-insensitive)
1137
- text.istarts_with("Hello", "HE") // true
1138
- text.iends_with("Hello", "LO") // true
1139
- ```
1140
-
1141
- ### Object Domain Functions
1142
-
1143
- Functional equivalents for object operations:
1144
-
1145
- ```xs
1146
- object.keys({a: 1, b: 2}) // ["a", "b"]
1147
- object.values({a: 1, b: 2}) // [1, 2]
1148
- object.entries({a: 1, b: 2}) // [{key: "a", value: 1}, {key: "b", value: 2}]
1149
- ```
1150
-
1151
- ### Math Domain Functions
1152
-
1153
- Functional equivalents for math operations:
1154
-
1155
- ```xs
1156
- math.add(5, 3) // 8
1157
- math.sub(10, 4) // 6
1158
- math.mul(3, 4) // 12
1159
- math.div(20, 5) // 4
1160
- math.mod(10, 3) // 1
1161
- ```
1162
-
1163
- ### Bitwise Operations
1164
-
1165
- ```xs
1166
- // As filters
1167
- 5|bitwise_and:3 // 1
1168
- 5|bitwise_or:3 // 7
1169
- 5|bitwise_xor:3 // 6
1170
- 5|bitwise_not // -6
1171
-
1172
- // As functions
1173
- math.bitwise.and(5, 3) // 1
1174
- math.bitwise.or(5, 3) // 7
1175
- math.bitwise.xor(5, 3) // 6
1176
- ```
1177
-
1178
- ### Logical NOT Filter
1179
-
1180
- ```xs
1181
- true|not // false
1182
- false|not // true
1183
- $condition|not // Inverts boolean
1184
- ```
1185
-
1186
- ### Array Filtering
1187
-
1188
- | Filter | Description | Example |
1189
- |--------|-------------|---------|
1190
- | `filter_empty` | Remove empty values | `$arr\|filter_empty` |
1191
- | `filter_empty_text` | Remove empty strings | `$arr\|filter_empty_text` |
1192
- | `filter_empty_array` | Remove empty arrays | `$arr\|filter_empty_array` |
1193
- | `filter_empty_object` | Remove empty objects | `$arr\|filter_empty_object` |
1194
- | `filter_null` | Remove null values | `$arr\|filter_null` |
1195
- | `filter_zero` | Remove zero values | `$arr\|filter_zero` |
1196
- | `filter_false` | Remove false values | `$arr\|filter_false` |
1197
-
1198
- ```xs
1199
- [1, null, "", 0, "text", false]|filter_empty // [1, "text"]
1200
- ["a", "", "b", ""]|filter_empty_text // ["a", "b"]
1201
- ```
1202
-
1203
- ### Array Fill Operations
1204
-
1205
- ```xs
1206
- |fill:5:"x" // ["x", "x", "x", "x", "x"]
1207
- ["a", "b"]|fill_keys:{"a": 1, "b": 2} // {a: 1, b: 2}
1208
- ```
1209
-
1210
- ### Deep Merge & Comparison
1211
-
1212
- ```xs
1213
- {a: {b: 1}}|merge_recursive:{a: {c: 2}} // {a: {b: 1, c: 2}}
1214
- [1, 2, 3]|diff_assoc:[2] // Associative diff
1215
- [1, 2, 3]|intersect_assoc:[2, 3, 4] // Associative intersect
1216
- ```
1217
-
1218
- ### Encoding Filters
1219
-
1220
- | Filter | Description | Example |
1221
- |--------|-------------|---------|
1222
- | `list_encodings` | List available encodings | `\|list_encodings` |
1223
- | `detect_encoding` | Detect string encoding | `$text\|detect_encoding` |
1224
- | `to_utf8` | Convert to UTF-8 | `$text\|to_utf8` |
1225
- | `from_utf8` | Convert from UTF-8 | `$text\|from_utf8:"ISO-8859-1"` |
1226
- | `convert_encoding` | Convert encodings | `$text\|convert_encoding:"UTF-8":"ISO-8859-1"` |
1227
-
1228
- ```xs
1229
- // CSV parsing (alternative to csv_decode)
1230
- $csv_text|csv_parse // Parse CSV string
1231
- $data|csv_create // Create CSV string
1232
-
1233
- // Query string
1234
- "a=1&b=2"|querystring_parse // {a: "1", b: "2"}
1235
- ```
1236
-
1237
- ### String Escape Filters
1238
-
1239
- | Filter | Description |
1240
- |--------|-------------|
1241
- | `addslashes` | Escape quotes and backslashes |
1242
- | `escape` | HTML escape |
1243
- | `text_escape` | Escape for text output |
1244
- | `text_unescape` | Unescape text |
1245
- | `regex_quote` | Escape regex special characters |
1246
-
1247
- ```xs
1248
- "Hello \"World\""|addslashes // "Hello \\\"World\\\""
1249
- "<script>"|escape // "&lt;script&gt;"
1250
- "^test$"|regex_quote // "\^test\$"
1251
- ```
1252
-
1253
- ### Trigonometry Examples
1254
-
1255
- ```xs
1256
- // Radians and degrees
1257
- 90|deg2rad // 1.5707963...
1258
- 1.5707963|rad2deg // 90
1259
-
1260
- // Trig functions (input in radians)
1261
- 0|sin // 0
1262
- 0|cos // 1
1263
- 0.785398|tan // ~1 (45 degrees)
1264
-
1265
- // Inverse trig
1266
- 0|asin // 0
1267
- 1|acos // 0
1268
- 1|atan // 0.785398...
1269
-
1270
- // Hyperbolic
1271
- 0|sinh // 0
1272
- 0|cosh // 1
1273
- 0|tanh // 0
1274
- ```
1275
-
1276
- ### DB Query Timestamp Filters
1277
-
1278
- Extended timestamp operations for database queries:
1279
-
1280
- ```xs
1281
- $db.created_at|timestamp_year // Extract year
1282
- $db.created_at|timestamp_month // Extract month (1-12)
1283
- $db.created_at|timestamp_week // Extract week number
1284
- $db.created_at|timestamp_day_of_month // Day of month (1-31)
1285
- $db.created_at|timestamp_day_of_week // Day of week (0-6)
1286
- $db.created_at|timestamp_day_of_year // Day of year (1-366)
1287
- $db.created_at|timestamp_hour // Hour (0-23)
1288
- $db.created_at|timestamp_minute // Minute (0-59)
1289
-
1290
- // Epoch variants
1291
- $db.created_at|timestamp_epoch_seconds // Seconds since epoch
1292
- $db.created_at|timestamp_epoch_ms // Milliseconds since epoch
1293
- ```
1294
-
1295
- ### Vector Operations (AI/ML)
1296
-
1297
- > **Full reference:** For AI agents and embeddings, see `xanoscript_docs({ topic: "agents" })`.
1298
-
1299
- Additional vector similarity functions:
1300
-
1301
- ```xs
1302
- $db.embedding|l1_distance_manhattan:$input.vector // L1/Manhattan distance
1303
- $db.embedding|negative_inner_product:$input.vector // Negative inner product
1304
- $db.embedding|inner_product:$input.vector // Inner product
1305
-
1306
- // Geo covers (for polygon containment)
1307
- $db.boundary|covers:$input.point // Polygon covers point
1308
- ```
1309
-
1310
501
  ---
1311
502
 
1312
503
  ## Related Topics
@@ -1315,8 +506,9 @@ Explore more with `xanoscript_docs({ topic: "<topic>" })`:
1315
506
 
1316
507
  | Topic | Description |
1317
508
  |-------|-------------|
1318
- | `quickstart` | Common patterns, examples, mistakes to avoid |
509
+ | `essentials` | Common patterns, mistakes to avoid, error types, type names |
510
+ | `syntax/string-filters` | String filters, regex, encoding, security filters, text functions |
511
+ | `syntax/array-filters` | Array filters, functional operations, array functions |
512
+ | `syntax/functions` | Math filters/functions, object functions, bitwise |
1319
513
  | `types` | Data types, input validation, schema definitions |
1320
514
  | `database` | All db.* operations with query examples |
1321
- | `functions` | Reusable function stacks, async patterns |
1322
- | `security` | Security best practices and authentication |