> For the complete documentation index, see [llms.txt](https://docs.adiom.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.adiom.io/enterprise/running-dsynct/cel-reference.md).

# CEL Reference

This is a reference for Common Expression Language (CEL) methods, functions, and macros available in Dsynct transformations.

## Methods

### bytes

| Method         | Return Type |
| -------------- | ----------- |
| `bytes.size()` | `int`       |

### google.protobuf.Duration

| Method                                       | Return Type |
| -------------------------------------------- | ----------- |
| `google.protobuf.Duration.getHours()`        | `int`       |
| `google.protobuf.Duration.getMilliseconds()` | `int`       |
| `google.protobuf.Duration.getMinutes()`      | `int`       |
| `google.protobuf.Duration.getSeconds()`      | `int`       |

### google.protobuf.Timestamp

| Method                                              | Return Type |
| --------------------------------------------------- | ----------- |
| `google.protobuf.Timestamp.getDate()`               | `int`       |
| `google.protobuf.Timestamp.getDate(string)`         | `int`       |
| `google.protobuf.Timestamp.getDayOfMonth()`         | `int`       |
| `google.protobuf.Timestamp.getDayOfMonth(string)`   | `int`       |
| `google.protobuf.Timestamp.getDayOfWeek()`          | `int`       |
| `google.protobuf.Timestamp.getDayOfWeek(string)`    | `int`       |
| `google.protobuf.Timestamp.getDayOfYear()`          | `int`       |
| `google.protobuf.Timestamp.getDayOfYear(string)`    | `int`       |
| `google.protobuf.Timestamp.getFullYear()`           | `int`       |
| `google.protobuf.Timestamp.getFullYear(string)`     | `int`       |
| `google.protobuf.Timestamp.getHours()`              | `int`       |
| `google.protobuf.Timestamp.getHours(string)`        | `int`       |
| `google.protobuf.Timestamp.getMilliseconds()`       | `int`       |
| `google.protobuf.Timestamp.getMilliseconds(string)` | `int`       |
| `google.protobuf.Timestamp.getMinutes()`            | `int`       |
| `google.protobuf.Timestamp.getMinutes(string)`      | `int`       |
| `google.protobuf.Timestamp.getMonth()`              | `int`       |
| `google.protobuf.Timestamp.getMonth(string)`        | `int`       |
| `google.protobuf.Timestamp.getSeconds()`            | `int`       |
| `google.protobuf.Timestamp.getSeconds(string)`      | `int`       |

### list

| Method                                   | Return Type                       |
| ---------------------------------------- | --------------------------------- |
| `list<A>.size()`                         | `int`                             |
| `list<T>.distinct()`                     | `list<T>`                         |
| `list<T>.reverse()`                      | `list<T>`                         |
| `list<T>.slice(int, int)`                | `list<T>`                         |
| `list<V>.first()`                        | `optional_type<V>`                |
| `list<V>.last()`                         | `optional_type<V>`                |
| `list<bool>.sort()`                      | `list<bool>`                      |
| `list<bytes>.sort()`                     | `list<bytes>`                     |
| `list<double>.sort()`                    | `list<double>`                    |
| `list<dyn>.flatten(int)`                 | `list<dyn>`                       |
| `list<google.protobuf.Duration>.sort()`  | `list<google.protobuf.Duration>`  |
| `list<google.protobuf.Timestamp>.sort()` | `list<google.protobuf.Timestamp>` |
| `list<int>.sort()`                       | `list<int>`                       |
| `list<list<T>>.flatten()`                | `list<T>`                         |
| `list<optional_type<V>>.unwrapOpt()`     | `list<V>`                         |
| `list<string>.join()`                    | `string`                          |
| `list<string>.join(string)`              | `string`                          |
| `list<string>.sort()`                    | `list<string>`                    |
| `list<uint>.sort()`                      | `list<uint>`                      |

### map

| Method             | Return Type |
| ------------------ | ----------- |
| `map<A, B>.size()` | `int`       |

### optional\_type

| Method                                  | Return Type        |
| --------------------------------------- | ------------------ |
| `optional_type<V>.hasValue()`           | `bool`             |
| `optional_type<V>.or(optional_type<V>)` | `optional_type<V>` |
| `optional_type<V>.orValue(V)`           | `V`                |
| `optional_type<V>.value()`              | `V`                |

### string

| Method                                | Return Type    |
| ------------------------------------- | -------------- |
| `string.charAt(int)`                  | `string`       |
| `string.contains(string)`             | `bool`         |
| `string.endsWith(string)`             | `bool`         |
| `string.format(list<dyn>)`            | `string`       |
| `string.indexOf(string)`              | `int`          |
| `string.indexOf(string, int)`         | `int`          |
| `string.lastIndexOf(string)`          | `int`          |
| `string.lastIndexOf(string, int)`     | `int`          |
| `string.lowerAscii()`                 | `string`       |
| `string.matches(string)`              | `bool`         |
| `string.replace(string, string)`      | `string`       |
| `string.replace(string, string, int)` | `string`       |
| `string.reverse()`                    | `string`       |
| `string.size()`                       | `int`          |
| `string.split(string)`                | `list<string>` |
| `string.split(string, int)`           | `list<string>` |
| `string.startsWith(string)`           | `bool`         |
| `string.substring(int)`               | `string`       |
| `string.substring(int, int)`          | `string`       |
| `string.trim()`                       | `string`       |
| `string.upperAscii()`                 | `string`       |

## Functions

### Base64

| Function                | Return Type |
| ----------------------- | ----------- |
| `base64.decode(string)` | `bytes`     |
| `base64.encode(bytes)`  | `string`    |

### Byte Order

| Function             | Return Type |
| -------------------- | ----------- |
| `be_to_int32(dyn)`   | `dyn`       |
| `be_to_int64(dyn)`   | `dyn`       |
| `reverse_bytes(dyn)` | `bytes`     |
| `to_be_int32(dyn)`   | `bytes`     |
| `to_be_int64(dyn)`   | `bytes`     |

### BSON

| Function                      | Return Type |
| ----------------------------- | ----------- |
| `bson_decimal128(dyn)`        | `dyn`       |
| `bson_decimal128_string(dyn)` | `string`    |
| `bson_object_id_string(dyn)`  | `string`    |
| `bson_uuid(dyn)`              | `dyn`       |
| `bson_uuid_string(dyn)`       | `string`    |

### Type Conversion

| Function                            | Return Type |
| ----------------------------------- | ----------- |
| `bool(bool)`                        | `bool`      |
| `bool(string)`                      | `bool`      |
| `bytes(bytes)`                      | `bytes`     |
| `bytes(string)`                     | `bytes`     |
| `double(double)`                    | `double`    |
| `double(int)`                       | `double`    |
| `double(string)`                    | `double`    |
| `double(uint)`                      | `double`    |
| `dyn(A)`                            | `dyn`       |
| `int(double)`                       | `int`       |
| `int(google.protobuf.Duration)`     | `int`       |
| `int(google.protobuf.Timestamp)`    | `int`       |
| `int(int)`                          | `int`       |
| `int(string)`                       | `int`       |
| `int(uint)`                         | `int`       |
| `string(bool)`                      | `string`    |
| `string(bytes)`                     | `string`    |
| `string(double)`                    | `string`    |
| `string(google.protobuf.Duration)`  | `string`    |
| `string(google.protobuf.Timestamp)` | `string`    |
| `string(int)`                       | `string`    |
| `string(string)`                    | `string`    |
| `string(uint)`                      | `string`    |
| `type(A)`                           | `type<A>`   |
| `uint(double)`                      | `uint`      |
| `uint(int)`                         | `uint`      |
| `uint(string)`                      | `uint`      |
| `uint(uint)`                        | `uint`      |

### Duration and Timestamp

| Function                               | Return Type                 |
| -------------------------------------- | --------------------------- |
| `duration(google.protobuf.Duration)`   | `google.protobuf.Duration`  |
| `duration(int)`                        | `google.protobuf.Duration`  |
| `duration(string)`                     | `google.protobuf.Duration`  |
| `timestamp(google.protobuf.Timestamp)` | `google.protobuf.Timestamp` |
| `timestamp(int)`                       | `google.protobuf.Timestamp` |
| `timestamp(string)`                    | `google.protobuf.Timestamp` |
| `now_millis()`                         | `int`                       |
| `now_nanos()`                          | `int`                       |

### JSON

| Function           | Return Type |
| ------------------ | ----------- |
| `json_decode(dyn)` | `dyn`       |
| `json_encode(dyn)` | `dyn`       |
| `json_number(dyn)` | `dyn`       |

### Collections

| Function                            | Return Type |
| ----------------------------------- | ----------- |
| `in(A, list<A>)`                    | `bool`      |
| `in(A, map<A, B>)`                  | `bool`      |
| `lists.range(int)`                  | `list<int>` |
| `sets.contains(list<T>, list<T>)`   | `bool`      |
| `sets.equivalent(list<T>, list<T>)` | `bool`      |
| `sets.intersects(list<T>, list<T>)` | `bool`      |
| `size(bytes)`                       | `int`       |
| `size(list<A>)`                     | `int`       |
| `size(map<A, B>)`                   | `int`       |
| `size(string)`                      | `int`       |

### Math

| Function                        | Return Type |
| ------------------------------- | ----------- |
| `math.abs(double)`              | `double`    |
| `math.abs(int)`                 | `int`       |
| `math.abs(uint)`                | `uint`      |
| `math.bitAnd(int, int)`         | `int`       |
| `math.bitAnd(uint, uint)`       | `uint`      |
| `math.bitNot(int)`              | `int`       |
| `math.bitNot(uint)`             | `uint`      |
| `math.bitOr(int, int)`          | `int`       |
| `math.bitOr(uint, uint)`        | `uint`      |
| `math.bitShiftLeft(int, int)`   | `int`       |
| `math.bitShiftLeft(uint, int)`  | `uint`      |
| `math.bitShiftRight(int, int)`  | `int`       |
| `math.bitShiftRight(uint, int)` | `uint`      |
| `math.bitXor(int, int)`         | `int`       |
| `math.bitXor(uint, uint)`       | `uint`      |
| `math.ceil(double)`             | `double`    |
| `math.floor(double)`            | `double`    |
| `math.isFinite(double)`         | `bool`      |
| `math.isInf(double)`            | `bool`      |
| `math.isNaN(double)`            | `bool`      |
| `math.round(double)`            | `double`    |
| `math.sign(double)`             | `double`    |
| `math.sign(int)`                | `int`       |
| `math.sign(uint)`               | `uint`      |
| `math.sqrt(double)`             | `double`    |
| `math.sqrt(int)`                | `double`    |
| `math.sqrt(uint)`               | `double`    |
| `math.trunc(double)`            | `double`    |

### Hashing

| Function      | Return Type |
| ------------- | ----------- |
| `md5(dyn)`    | `bytes`     |
| `sha1(dyn)`   | `bytes`     |
| `sha256(dyn)` | `bytes`     |

### Optional

| Function                                  | Return Type        |
| ----------------------------------------- | ------------------ |
| `optional.none()`                         | `optional_type<V>` |
| `optional.of(V)`                          | `optional_type<V>` |
| `optional.ofNonZeroValue(V)`              | `optional_type<V>` |
| `optional.unwrap(list<optional_type<V>>)` | `list<V>`          |

### Regex

| Function                                     | Return Type             |
| -------------------------------------------- | ----------------------- |
| `matches(string, string)`                    | `bool`                  |
| `regex.extract(string, string)`              | `optional_type<string>` |
| `regex.extractAll(string, string)`           | `list<string>`          |
| `regex.replace(string, string, string)`      | `string`                |
| `regex.replace(string, string, string, int)` | `string`                |

### Strings

| Function                | Return Type |
| ----------------------- | ----------- |
| `strings.quote(string)` | `string`    |

### UUID

| Function                   | Return Type |
| -------------------------- | ----------- |
| `uuid_v3_bytes(dyn, dyn)`  | `bytes`     |
| `uuid_v3_string(dyn, dyn)` | `string`    |
| `uuid_v4_bytes()`          | `bytes`     |
| `uuid_v4_string()`         | `string`    |
| `uuid_v5_bytes(dyn, dyn)`  | `bytes`     |
| `uuid_v5_string(dyn, dyn)` | `string`    |

## Macros

Macros are special constructs that are expanded at parse time and provide control flow and comprehension capabilities that cannot be expressed as regular functions.

### has

Tests whether a field is available on a message or key exists in a map.

**Signature:** `has(e.f)` -> `bool`

**Examples:**

```cel
has(user.address)           // true if 'address' field exists in the 'user' message
has(m.key_name)             // true if map 'm' has a key named 'key_name'
has(order.items)            // false if 'items' field is not set
```

### all

Tests whether all elements in a list or all keys in a map satisfy the given predicate. Behaves consistently with logical AND, including short-circuit evaluation and error absorption.

**Signatures:**

* `list(A).all(x, predicate)` -> `bool`
* `map(A, B).all(x, predicate)` -> `bool`

**Examples:**

```cel
[1, 2, 3].all(x, x > 0)                          // true
[1, 2, 0].all(x, x > 0)                          // false
['apple', 'banana'].all(fruit, fruit.size() > 3) // true
{'a': 1, 'b': 2}.all(key, key != 'b')            // false
```

### exists

Tests whether any element in a list or any key in a map satisfies the predicate. Behaves consistently with logical OR, including short-circuit evaluation and error absorption.

**Signatures:**

* `list(A).exists(x, predicate)` -> `bool`
* `map(A, B).exists(x, predicate)` -> `bool`

**Examples:**

```cel
[1, 2, 3].exists(i, i % 2 != 0)                     // true
[].exists(i, i > 0)                                 // false
[0, -1, 5].exists(num, num < 0)                     // true
{'x': 'foo', 'y': 'bar'}.exists(key, key == 'x')    // true
```

### exists\_one

Tests whether exactly one element in a list or key in a map satisfies the predicate. Does not short-circuit to ensure exactly one match.

**Signatures:**

* `list(A).exists_one(x, predicate)` -> `bool`
* `map(A, B).exists_one(x, predicate)` -> `bool`

**Examples:**

```cel
[1, 2, 2].exists_one(i, i < 2)                              // true (only 1 is < 2)
[1, 2, 3, 4].exists_one(num, num % 2 == 0)                  // false (2 and 4 are even)
{'a': 'hello', 'aa': 'world'}.exists_one(k, k.startsWith('a')) // false (both match)
```

### map

Transforms each element in a list or each key in a map by applying an expression. The three-argument form transforms all elements; the four-argument form only transforms elements matching a filter predicate.

**Signatures:**

* `list(A).map(x, transform)` -> `list(T)`
* `list(A).map(x, filter, transform)` -> `list(T)`
* `map(A, B).map(x, transform)` -> `list(T)`
* `map(A, B).map(x, filter, transform)` -> `list(T)`

**Examples:**

```cel
[1, 2, 3].map(x, x * 2)                              // [2, 4, 6]
[5, 10, 15].map(x, x / 5)                            // [1, 2, 3]
['apple', 'banana'].map(fruit, fruit.upperAscii())   // ['APPLE', 'BANANA']
[1, 2, 3, 4].map(num, num % 2 == 0, num * 2)         // [4, 8] (only even numbers)
```

### filter

Returns a list containing only the elements from the input list or keys from a map that satisfy the predicate.

**Signatures:**

* `list(A).filter(x, predicate)` -> `list(A)`
* `map(A, B).filter(x, predicate)` -> `list(A)`

**Examples:**

```cel
[1, 2, 3].filter(x, x > 1)                           // [2, 3]
['cat', 'dog', 'bird', 'fish'].filter(pet, pet.size() == 3) // ['cat', 'dog']
{'a': 1, 'b': 2, 'c': 3}.filter(key, key != 'b')     // ['a', 'c']
```

### cel.bind

Binds an identifier to an initialization expression for use in a subsequent result expression. Useful for avoiding repeated computation of complex sub-expressions.

**Signature:** `cel.bind(varName, initExpr, resultExpr)`

**Examples:**

```cel
cel.bind(x, self.field1 + self.field2, x * x)        // computes sum once, then squares it
cel.bind(name, user.firstName + ' ' + user.lastName, name.size() > 0 && name != 'Anonymous')
```

### optMap

Applies a transformation to the value inside an optional if it has a value, otherwise returns `optional.none()`.

**Signature:** `optional(V).optMap(x, transform)` -> `optional(T)`

**Examples:**

```cel
optional.of(5).optMap(x, x * 2)       // optional.of(10)
optional.none().optMap(x, x * 2)     // optional.none()
```

### optFlatMap

Like `optMap`, but the transformation must return an optional. Useful for chaining optional operations without nested optionals.

**Signature:** `optional(V).optFlatMap(x, transform)` -> `optional(T)`

**Examples:**

```cel
optional.of(5).optFlatMap(x, optional.of(x * 2))    // optional.of(10)
optional.of(5).optFlatMap(x, optional.none())      // optional.none()
```

### math.least

Returns the minimum value from a variable number of arguments. All arguments must be numeric (int, uint, or double).

**Signature:** `math.least(arg1, arg2, ...)` -> `double|int|uint`

**Examples:**

```cel
math.least(1, 2, 3)          // 1
math.least(3.14, 2.71, 1.0)  // 1.0
math.least(5u, 3u, 8u)       // 3u
```

### math.greatest

Returns the maximum value from a variable number of arguments. All arguments must be numeric (int, uint, or double).

**Signature:** `math.greatest(arg1, arg2, ...)` -> `double|int|uint`

**Examples:**

```cel
math.greatest(1, 2, 3)          // 3
math.greatest(3.14, 2.71, 1.0)  // 3.14
math.greatest(5u, 3u, 8u)       // 8u
```

### sortBy

Sorts a list by a key expression. Each element is transformed by the key expression, and the list is sorted by those keys.

**Signature:** `list(T).sortBy(x, keyExpr)` -> `list(T)`

**Examples:**

```cel
[{'name': 'bob', 'age': 30}, {'name': 'alice', 'age': 25}].sortBy(p, p.age)
// [{'name': 'alice', 'age': 25}, {'name': 'bob', 'age': 30}]

['banana', 'apple', 'cherry'].sortBy(s, s.size())
// ['apple', 'banana', 'cherry'] (sorted by string length)
```
