# Taxi StdLib

> Reference documentation on functions provided in Taxi's StdLib packages

Source: https://taxilang.org/docs/language/stdlib

Taxi ships with a collections of functions for basic operations on data.

These operations are performed locally on data received from services - it does not instruct remote
services to perform these changes.

Taxi does not provide implementations of these functions, that's left to
runtimes, such as Orbital.

## Strings

A collection of functions for manipulating strings

### applyFormat
`taxi.stdlib.applyFormat`

```taxi
declare extension function applyFormat(input: Any, format: String):String
```

Applies a format string to the input value using [Java Formatter](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html) conventions.

Accepts any value (string, number, date, etc.) as input. The format string controls width, padding, precision, and alignment.

```taxi
// Zero-pad an integer to 6 digits
find { order: Order } as {
   paddedId: order.id.applyFormat('%06d')
}
```

### Examples
Formats an integer with zero-padding using `%05d`.

Query:

```taxi
find {
   formatted: String = 42.applyFormat('%05d')
}
```

Result:

```json
{
  "formatted": "00042"
}
```

Left-justifies a string in a 10-character wide field using `%-10s`.

Query:

```taxi
find {
   padded: String = 'hello'.applyFormat('%-10s')
}
```

Result:

```json
{
  "padded": "hello     "
}
```

------

### concat
`taxi.stdlib.concat`

```taxi
declare function concat(Any...):String
```

Joins all provided values into a single string, in the order they are passed. Null values are omitted.

```taxi
find { person: Person } as {
   fullName: String = concat(person.firstName, ' ', person.lastName)
}
```

### Examples
Concatenates multiple string values into a single string.

Query:

```taxi
find {
   greeting: String = concat('Hello', ', ', 'World')
}
```

Result:

```json
{
  "greeting": "Hello, World"
}
```

------

### containsPattern
`taxi.stdlib.containsPattern`

```taxi
declare extension function containsPattern(source: String, regex: String): Boolean
```

Returns `true` if any part of the source string matches the provided regular expression.

Uses partial matching — the regex does not need to match the entire string. Use `^` and `$` anchors for full-string matching.

```taxi
// Partial match — returns true if the string contains the pattern anywhere
find {
   startsWithHe: Boolean = "hello".containsPattern("^he")
   containsEll: Boolean = "hello".containsPattern("ell")
}
```

### Examples
Demonstrates partial matching: anchor patterns, substring patterns, and non-matching patterns.

Query:

```taxi
find {
   matchesStart: Boolean = "hello".containsPattern("^he")
   matchesMiddle: Boolean = "hello".containsPattern("ell")
   noMatch: Boolean = "hello".containsPattern("xyz")
}
```

Result:

```json
{
  "matchesStart": true,
  "matchesMiddle": true,
  "noMatch": false
}
```

------

### containsString
`taxi.stdlib.containsString`

```taxi
declare extension function containsString(source:String, valueToSearchFor:String):Boolean
```

Returns `true` if `source` contains `valueToSearchFor` as a substring. The match is case-sensitive.

```taxi
// Check if a description mentions a keyword
find {
   mentionsDiscount: Boolean = Description.containsString("discount")
}
```

### Examples
Checks for a case-sensitive substring match.

Query:

```taxi
find {
   hasSubstring: Boolean = "hello world".containsString("world")
   caseSensitive: Boolean = "hello world".containsString("World")
}
```

Result:

```json
{
  "hasSubstring": true,
  "caseSensitive": false
}
```

------

### endsWith
`taxi.stdlib.endsWith`

```taxi
declare extension function endsWith(source: String, valueToSearchFor:String):Boolean
```

Returns `true` if `source` ends with the specified suffix. The match is case-sensitive.

```taxi
// Check if a filename has a specific extension
find {
   isCsv: Boolean = FileName.endsWith(".csv")
}
```

### Examples
Checks whether a string ends with a given suffix, case-sensitively.

Query:

```taxi
find {
   hasSuffix: Boolean = "hello.csv".endsWith(".csv")
   nope: Boolean = "hello.csv".endsWith(".json")
}
```

Result:

```json
{
  "hasSuffix": true,
  "nope": false
}
```

------

### indexOf
`taxi.stdlib.indexOf`

```taxi
declare extension function indexOf(source:String, valueToSearchFor:String):Int
```

Returns the zero-based index of `valueToSearchFor` within `source`, or `-1` if not found.

```taxi
find { path: FilePath } as {
   dotPosition: Int = path.value.indexOf('.')
}
```

### Examples
Returns the index of a substring within a string, or `-1` if not found.

Query:

```taxi
find {
   pos: Int = indexOf('Hello World', 'World')
}
```

Result:

```json
{
  "pos": 6
}
```

------

### left
`taxi.stdlib.left`

```taxi
declare extension function left(source:String, count:Int):String
```

Returns the leftmost `count` characters from a string.

```taxi
find { account: Account } as {
   prefix: String = account.code.left(3)
}
```

### Examples
Extracts the first N characters from a string.

Query:

```taxi
find {
   firstFive: String = left('HelloWorld', 5)
}
```

Result:

```json
{
  "firstFive": "Hello"
}
```

------

### length
`taxi.stdlib.length`

```taxi
declare extension function length(String):Int
```

Returns the number of characters in the string.

```taxi
find { message: Message } as {
   charCount: Int = message.body.length()
}
```

### Examples
Returns the character count of a string.

Query:

```taxi
find {
   len: Int = length('Hello')
}
```

Result:

```json
{
  "len": 5
}
```

------

### lowerCase
`taxi.stdlib.lowerCase`

```taxi
declare extension function lowerCase(String):String
```

Converts all characters in the string to lower case.

```taxi
find { product: Product } as {
   lowerName: String = product.name.lowerCase()
}
```

### Examples
Converts a string to lower case.

Query:

```taxi
find {
   lower: String = lowerCase('HELLO WORLD')
}
```

Result:

```json
{
  "lower": "hello world"
}
```

------

### matches
`taxi.stdlib.matches`

```taxi
declare extension function matches(source: String, regex: String): Boolean
```

Returns `true` if the **entire** source string matches the provided regular expression.

Uses full-string matching — the pattern must match the entire string, not just a part of it.
Use `containsPattern` for partial (substring) matching.

```taxi
find { account: Account } as {
   isValidCode: Boolean = account.code.matches('^[A-Z]{3}-\d{4}$')
}
```

### Examples
Returns `true` only when the full string matches the regex pattern.

Query:

```taxi
find {
   fullMatch: Boolean = 'hello'.matches('^h.*o$')
   noFullMatch: Boolean = 'hello'.matches('^he')
}
```

Result:

```json
{
  "fullMatch": true,
  "noFullMatch": false
}
```

------

### mid
`taxi.stdlib.mid`

```taxi
declare extension function mid(source: String, startIndex: Int, endIndex: Int):String
```

Returns the middle of a string, starting at `startIndex` (inclusive) and ending just before `endIndex` (exclusive).

Uses zero-based indexing, identical to `String.substring()` in Java/Kotlin.

```taxi
find { order: Order } as {
   yearPart: String = order.isoDate.mid(0, 4)
}
```

### Examples
Extracts a substring using a zero-based start index (inclusive) and end index (exclusive).

Query:

```taxi
find {
   mid5: String = mid('HelloWorld', 5, 10)
}
```

Result:

```json
{
  "mid5": "World"
}
```

------

### padEnd
`taxi.stdlib.padEnd`

```taxi
declare extension function padEnd(input: String, length: Int, padWith: String):String
```

Pads the string to the specified total `length` by appending `padWith` characters at the end.

`padWith` should be a single character — if multiple characters are passed, only the first is used.

```taxi
find { product: Product } as {
   paddedCode: String = product.code.padEnd(10, ' ')
}
```

### Examples
Pads a string to the target length by appending characters on the right.

Query:

```taxi
find {
   padded: String = padEnd('hello', 10, '.')
}
```

Result:

```json
{
  "padded": "hello....."
}
```

------

### padStart
`taxi.stdlib.padStart`

```taxi
declare extension function padStart(input: String, length: Int, padWith: String):String
```

Pads the string to the specified total `length` by prepending `padWith` characters at the start.

`padWith` should be a single character — if multiple characters are passed, only the first is used.

```taxi
find { order: Order } as {
   paddedId: String = order.id.padStart(8, '0')
}
```

### Examples
Zero-pads a short string to the target length from the left.

Query:

```taxi
find {
   padded: String = padStart('42', 6, '0')
}
```

Result:

```json
{
  "padded": "000042"
}
```

------

### replace
`taxi.stdlib.replace`

```taxi
declare extension function replace(source: String, searchValue:String, replacement: String):String
```

Replaces all occurrences of `searchValue` in `source` with `replacement`, returning a new string.

```taxi
find { order: Order } as {
   cleanRef: String = order.reference.replace('-', '_')
}
```

### Examples
Replaces all occurrences of a substring with a new value.

Query:

```taxi
find {
   replaced: String = replace('Hello World', 'World', 'Taxi')
}
```

Result:

```json
{
  "replaced": "Hello Taxi"
}
```

------

### right
`taxi.stdlib.right`

```taxi
declare extension function right(source:String, count:Int):String
```

Returns the rightmost `count` characters from a string.

```taxi
find { account: Account } as {
   suffix: String = account.code.right(4)
}
```

### Examples
Extracts the last N characters from a string.

Query:

```taxi
find {
   lastFive: String = right('HelloWorld', 5)
}
```

Result:

```json
{
  "lastFive": "World"
}
```

------

### startsWith
`taxi.stdlib.startsWith`

```taxi
declare extension function startsWith(source: String, valueToSearchFor:String):Boolean
```

Returns `true` if `source` begins with the specified prefix. The match is case-sensitive.

```taxi
find { files: File[] } as {
   tempFiles: File[] = files.filter((File) -> FileName.startsWith('tmp_'))
}
```

### Examples
Returns `true` when the string begins with the specified prefix, case-sensitively.

Query:

```taxi
find {
   hasPrefix: Boolean = 'Hello World'.startsWith('Hello')
   noMatch: Boolean = 'Hello World'.startsWith('World')
}
```

Result:

```json
{
  "hasPrefix": true,
  "noMatch": false
}
```

------

### trim
`taxi.stdlib.trim`

```taxi
declare extension function trim(String):String
```

Removes leading and trailing whitespace from a string.

```taxi
find { order: Order } as {
   cleanRef: String = order.referenceCode.trim()
}
```

### Examples
Strips leading and trailing whitespace from a string.

Query:

```taxi
find {
   trimmed: String = '  hello world  '.trim()
}
```

Result:

```json
{
  "trimmed": "hello world"
}
```

------

### upperCase
`taxi.stdlib.upperCase`

```taxi
declare extension function upperCase(String):String
```

Converts all characters in the string to upper case.

```taxi
find { product: Product } as {
   upperName: String = product.name.upperCase()
}
```

### Examples
Converts a string to upper case.

Query:

```taxi
find {
   upper: String = upperCase('hello world')
}
```

Result:

```json
{
  "upper": "HELLO WORLD"
}
```

## Collections

A collection of functions for operating on collections

### all
`taxi.stdlib.all`

```taxi
declare extension function <T> all(collection: T[], predicate: (T) -> Boolean): Boolean
```

Returns `true` if every item in the collection satisfies the predicate, or `false` if any item does not.

Returns `true` for an empty collection (vacuous truth).

```taxi
// Check if every task in a sprint is complete
find { sprint: Sprint } as {
   allDone: Boolean = sprint.tasks.all((task) -> task.isComplete)
}
```

### Examples
Returns `true` when every item in the collection satisfies the predicate.

Schema:

```taxi
model Task {
   name: String
   isComplete: Boolean
}
```

Query:

```taxi
given {
   tasks: Task[] = [
      { name: 'Setup', isComplete: true },
      { name: 'Build', isComplete: true },
      { name: 'Deploy', isComplete: true }
   ]
}
find {
   allDone: Boolean = tasks.all((task: Task) -> task.isComplete)
}
```

Result:

```json
{
  "allDone": true
}
```

Returns `false` when at least one item does not satisfy the predicate.

Schema:

```taxi
model Task {
   name: String
   isComplete: Boolean
}
```

Query:

```taxi
given {
   tasks: Task[] = [
      { name: 'Setup', isComplete: true },
      { name: 'Build', isComplete: true },
      { name: 'Deploy', isComplete: false }
   ]
}
find {
   allDone: Boolean = tasks.all((task: Task) -> task.isComplete)
}
```

Result:

```json
{
  "allDone": false
}
```

------

### allOf
`taxi.stdlib.allOf`

```taxi
declare function allOf(values:Boolean...): Boolean
```

Returns `true` only if all provided boolean values are `true`. Equivalent to logical AND.

This function ensures that every condition in a set must be satisfied.

```taxi
// Check if a user can purchase a premium item
type CanPurchasePremium inherits Boolean by allOf(IsActive, HasSufficientFunds, IsVerified)
```

### Examples
This example demonstrates how to use `allOf()` to verify if a user meets all required criteria for premium access.

Schema:

```taxi
model Customer {
   name: String
   isActive: IsActive inherits Boolean
   hasSufficientFunds: HasSufficientFunds inherits Boolean
   isVerified: IsVerified inherits Boolean
}
type HasPremiumAccess inherits Boolean by allOf(IsActive, HasSufficientFunds, IsVerified)
```

Query:

```taxi
given {
   customer: Customer = {
      name: 'Bob',
      isActive: true,
      hasSufficientFunds: true,
      isVerified: true
   }
}
find {
   name: customer.name
   hasPremiumAccess: HasPremiumAccess
}
```

Result:

```json
{
  "name": "Bob",
  "hasPremiumAccess": true
}
```

------

### any
`taxi.stdlib.any`

```taxi
declare extension function <T> any(collection: T[], predicate: (T) -> Boolean): Boolean
```

Returns `true` if at least one item in the collection satisfies the predicate, or `false` if none do.

Returns `false` for an empty collection.

```taxi
// Check whether any order in a batch is flagged
find { batch: OrderBatch } as {
   needsAttention: Boolean = batch.orders.any((order) -> order.isFlagged)
}
```

### Examples
Returns `true` when at least one item satisfies the predicate.

Schema:

```taxi
model Task {
   name: String
   isComplete: Boolean
}
```

Query:

```taxi
given {
   tasks: Task[] = [
      { name: 'Setup', isComplete: true },
      { name: 'Build', isComplete: false },
      { name: 'Deploy', isComplete: false }
   ]
}
find {
   anyDone: Boolean = tasks.any((task: Task) -> task.isComplete)
}
```

Result:

```json
{
  "anyDone": true
}
```

------

### anyOf
`taxi.stdlib.anyOf`

```taxi
declare function anyOf(values:Boolean...): Boolean
```

Returns `true` if at least one of the provided boolean values is `true`. Equivalent to logical OR.

This function evaluates multiple conditions and returns true if any of them are true.

```taxi
// Check if a user has any account verification
type IsVerified inherits Boolean by anyOf(HasEmailVerification, HasPhoneVerification, HasIdVerification)
```

### Examples
Returns `true` when at least one of the provided boolean conditions is `true`. Define a computed type in the schema using `anyOf` for reuse across queries.

Schema:

```taxi
model User {
   name: String
   hasEmailVerification: HasEmailVerification inherits Boolean
   hasPhoneVerification: HasPhoneVerification inherits Boolean
   hasIdVerification: HasIdVerification inherits Boolean
}
type IsVerified inherits Boolean by anyOf(HasEmailVerification, HasPhoneVerification, HasIdVerification)
```

Query:

```taxi
given {
   user: User = {
      name: 'Alice',
      hasEmailVerification: false,
      hasPhoneVerification: true,
      hasIdVerification: false
   }
}
find {
   name: user.name
   isVerified: IsVerified
}
```

Result:

```json
{
  "name": "Alice",
  "isVerified": true
}
```

------

### append
`taxi.stdlib.append`

```taxi
declare extension function <T> append(array1: T[], array2: T[]):T[]
```

Returns a new collection containing the elements of the first array followed by the elements of the second array.

Neither input array is modified.

```taxi
find { cart: ShoppingCart } as {
   allItems: cart.regularItems.append(cart.saleItems)
}
```

### Examples
Concatenates two arrays, returning a new array with elements of the first followed by elements of the second.

Schema:

```taxi
model Bag {
   items: String[]
}
```

Query:

```taxi
given {
   bag1: Bag = { items: ['apple', 'banana'] },
   bag2: Bag = { items: ['cherry', 'date'] }
}
find {
   combined: String[] = bag1.items.append(bag2.items)
}
```

Result:

```json
{
  "combined": [
    "apple",
    "banana",
    "cherry",
    "date"
  ]
}
```

------

### collectAllInstances
`taxi.stdlib.collectAllInstances`

```taxi
declare extension function <T> collectAllInstances(collection: lang.taxi.Type<T>): T
```

Collects and merges all instances of a type from the current data context, bypassing ambiguity checks.

Without this function, a search for `T[]` will return null when multiple separate collections of `T` exist
(the result is considered ambiguous). `collectAllInstances` disables that check and concatenates all found instances
into a single collection.

```taxi
// Merge homeAddresses and workAddresses into one list
find { person: Person } as {
   allAddresses: collectAllInstances(Address)
}
```

### Examples
Merges all `Address` collections on a `Person` into a single flat list, even though they live in separate fields.

Schema:

```taxi
model Address {
   street: Street inherits String
}
model Person {
   name: Name inherits String
   homeAddresses: Address[]
   workAddresses: Address[]
}
```

Query:

```taxi
given {
   person: Person = {
      name: 'Jimmy',
      homeAddresses: [
         { street: 'Oxford St' },
         { street: 'Regent St' }
      ],
      workAddresses: [
         { street: 'Tot St' }
      ]
   }
}
find {
   name: person.name
   allAddresses: collectAllInstances(Address)
}
```

Result:

```json
{
  "name": "Jimmy",
  "allAddresses": [
    {
      "street": "Oxford St"
    },
    {
      "street": "Regent St"
    },
    {
      "street": "Tot St"
    }
  ]
}
```

------

### contains
`taxi.stdlib.contains`

```taxi
declare extension function <T> contains(collection: T[], searchTarget:T): Boolean
```

Returns `true` if the collection contains the specified search target element.

This function checks whether a given element exists within an array or collection.

```taxi
// Check if a user's roles include admin privileges
find { user: User } as {
   hasAdminAccess: user.roles.contains("ADMIN")
}
```

### Examples
Checks whether a collection contains a specific element using type-based access.

Schema:

```taxi
type Role inherits String
model User {
   username: Username inherits String
   roles: Role[]
}
```

Query:

```taxi
given {
   user: User = {
      username: 'AdminUser',
      roles: ['USER', 'EDITOR', 'ADMIN']
   }
}
find {
   username: Username
   isAdmin: Boolean = Role[].contains('ADMIN')
   isGuest: Boolean = Role[].contains('GUEST')
}
```

Result:

```json
{
  "username": "AdminUser",
  "isAdmin": true,
  "isGuest": false
}
```

------

### containsAll
`taxi.stdlib.containsAll`

```taxi
declare extension function <T> containsAll(collection: T[], searchTarget:T[]): Boolean
```

Returns `true` if the collection contains every element in the search targets array.

Returns `true` when `searchTargets` is empty (an empty set is a subset of every set).

```taxi
// Check whether a product has all required tags
find {
   hasCertified: Boolean = ProductTag[].containsAll(['certified', 'in-stock'])
}
```

**Known limitation:** When the collection uses a semantic type (e.g. `ProductTag inherits String`),
passing string literals as `searchTargets` always returns `false` due to a type comparison bug.
See `problems/containsAll.md`. Use a `String[]` collection as a workaround.

### Examples
Returns `true` when the collection contains all specified search values, `false` if any are missing.

Schema:

```taxi
model Product {
   name: String
   tags: String[]
}
```

Query:

```taxi
given {
   product: Product = { name: 'Laptop', tags: ['electronics', 'portable', 'work'] }
}
find {
   hasBothTags: Boolean = product.tags.containsAll(['electronics', 'portable'])
   missingTag: Boolean = product.tags.containsAll(['electronics', 'gaming'])
}
```

Result:

```json
{
  "hasBothTags": true,
  "missingTag": false
}
```

------

### containsAny
`taxi.stdlib.containsAny`

```taxi
declare extension function <T> containsAny(collection: T[], searchTarget:T[]): Boolean
```

Returns `true` if the collection contains at least one of the specified search targets.

Returns `true` when `searchTargets` is empty (symmetrical with `containsAll`).

```taxi
// Check whether a product has any of a set of tags
find {
   isRelevant: Boolean = ProductTag[].containsAny(['sale', 'featured', 'new'])
}
```

**Known limitation:** When the collection uses a semantic type (e.g. `ProductTag inherits String`),
passing string literals as `searchTargets` always returns `false` due to a type comparison bug.
See `problems/containsAny.md`. Use a `String[]` collection as a workaround.

### Examples
Returns `true` when the collection contains at least one of the search values, `false` when none match.

Schema:

```taxi
model Product {
   name: String
   tags: String[]
}
```

Query:

```taxi
given {
   product: Product = { name: 'Laptop', tags: ['electronics', 'portable', 'work'] }
}
find {
   hasAnyTag: Boolean = product.tags.containsAny(['gaming', 'portable'])
   hasNone: Boolean = product.tags.containsAny(['gaming', 'sports'])
}
```

Result:

```json
{
  "hasAnyTag": true,
  "hasNone": false
}
```

------

### exactlyOne
`taxi.stdlib.exactlyOne`

```taxi
declare extension function <T> exactlyOne(collection:T[]):T
```

Returns the only item from the provided collection, or throws an error if there isn't exactly one item in the collection.

This function is useful when you expect a collection to contain precisely one element and want to retrieve it.

```taxi
// Get the single active session for a user
find { user: User } as {
   currentSession: user.sessions.filter((session) -> session.isActive).exactlyOne()
}
```

### Examples
This example demonstrates how to use `exactlyOne()` to retrieve the single active session for a user.

Schema:

```taxi
model Session {
   id: SessionId inherits String
   isActive: IsActive inherits Boolean
}

model User {
   username: Username inherits String
   sessions: Session[]
}
```

Query:

```taxi
given {
   user: User = {
      username: 'ActiveUser',
      sessions: [
         { id: 'session-1', isActive: true },
         { id: 'session-2', isActive: false }
      ]
   }
}
find {
   username: user.username
   activeSessionId: SessionId = user.sessions.filter((Session) -> IsActive).exactlyOne().id
}
```

Result:

```json
{
  "username": "ActiveUser",
  "activeSessionId": "session-1"
}
```

------

### filter
`taxi.stdlib.filter`

```taxi
declare extension function <T> filter(collection:T[], callback: (T) -> Boolean):T[]
```

Returns a new collection containing only the members of the original collection that match the provided predicate.

This function is used to select a subset of elements from a collection based on a condition.

```taxi
find { store: Store } as {
   allProducts: store.products // all products
   inStockProducts: store.products.filter((product) -> product.stockLevel > 0)
   affordableProducts: store.products.filter((product) -> product.price < 50.00)
}
```

### Examples
Filters a collection by predicate, returning only matching elements. Uses type-based lambda for clean, semantic access.

Schema:

```taxi
model Friend {
   name: Name inherits String
   age: Age inherits Int
}
```

Query:

```taxi
given {
   friends: Friend[] = [
      { name: 'Jim', age: 20 },
      { name: 'Jack', age: 80 },
      { name: 'Alice', age: 75 },
      { name: 'Bob', age: 30 }
   ]
}
find {
   // Names of seniors (over 70)
   seniorFriends: Name[] = friends.filter((Age) -> Age > 70) as Name[]
   // Names of young adults (under 30)
   youngFriends: Name[] = friends.filter((Age) -> Age < 30) as Name[]
}
```

Result:

```json
{
  "seniorFriends": [
    "Jack",
    "Alice"
  ],
  "youngFriends": [
    "Jim"
  ]
}
```

------

### filterEach
`taxi.stdlib.filterEach`

```taxi
declare extension function <T> filterEach(item: T, callback: (T) -> Boolean):T?
```

Evaluates the predicate against the provided item, returning the item if the predicate returns true, or null otherwise.

This function is intended for use in filtering streams, where null values are automatically excluded.

```taxi
// Filter individual items in a pipeline
find { items: Item[] } as {
   processedItems: items.map((item) -> filterEach(item, (i) -> i.status == "READY"))
}
```

------

### first
`taxi.stdlib.first`

```taxi
declare extension function <T> first(collection: T[]):T
```

Returns the first item within the collection. Throws an error if the collection is empty.

This function retrieves the first element in an ordered collection.

```taxi
// Get the most recent transaction from a sorted list
find { account: Account } as {
   latestTransaction: account.transactions.first()
}
```

### Examples
This example demonstrates how to use `first()` to retrieve the most recent transaction for an account.

Schema:

```taxi
model Transaction {
   date: String
   amount: Decimal
   description: String
}

model Account {
   accountNumber: String
   transactions: Transaction[] // Assumed to be in descending date order
}
```

Query:

```taxi
given {
   account: Account = {
      accountNumber: 'ACC-12345',
      transactions: [
         { date: '2023-05-01', amount: 150.00, description: 'Grocery Store' },
         { date: '2023-04-28', amount: 45.99, description: 'Online Shop' },
         { date: '2023-04-25', amount: 20.00, description: 'Transfer' }
      ]
   }
}
find {
   accountNumber: account.accountNumber
   mostRecentTransaction: Transaction = account.transactions.first()
}
```

Result:

```json
{
  "accountNumber": "ACC-12345",
  "mostRecentTransaction": {
    "date": "2023-05-01",
    "amount": 150,
    "description": "Grocery Store"
  }
}
```

------

### getAtIndex
`taxi.stdlib.getAtIndex`

```taxi
declare extension function <T> getAtIndex(collection: T[], index: Int):T
```

Returns the item at the provided index in the collection. Throws an error if the index is out of bounds.

This function retrieves an element at a specific position in a collection, with zero-based indexing.

```taxi
// Get the second item in a list
find { playlist: Playlist } as {
   secondSong: playlist.songs.getAtIndex(1) // Note: index starts at 0
}
```

### Examples
Retrieves a song from a playlist by its zero-based index position.

Schema:

```taxi
model Song {
   title: Title inherits String
   artist: Artist inherits String
   duration: Duration inherits Int
}
model Playlist {
   name: PlaylistName inherits String
   songs: Song[]
}
```

Query:

```taxi
given {
   playlist: Playlist = {
      name: 'Road Trip Mix',
      songs: [
         { title: 'Highway Star', artist: 'Deep Purple', duration: 372 },
         { title: 'Born to Run', artist: 'Bruce Springsteen', duration: 270 },
         { title: 'Life in the Fast Lane', artist: 'Eagles', duration: 251 }
      ]
   }
}
find {
   playlistName: PlaylistName
   firstSong: Song = Song[].getAtIndex(0)
   secondSong: Song = Song[].getAtIndex(1)
}
```

Result:

```json
{
  "playlistName": "Road Trip Mix",
  "firstSong": {
    "title": "Highway Star",
    "artist": "Deep Purple",
    "duration": 372
  },
  "secondSong": {
    "title": "Born to Run",
    "artist": "Bruce Springsteen",
    "duration": 270
  }
}
```

------

### ifEmpty
`taxi.stdlib.ifEmpty`

```taxi
declare extension function <T> ifEmpty(source:T[], defaultValue:T[]): T[]
```

Returns the source array if it is non-empty, otherwise returns the provided default array.

```taxi
find { order: Order } as {
   tags: order.tags.ifEmpty(['untagged'])
}
```

### Examples
Returns the default array when the source is empty, or the source array when it has elements.

Schema:

```taxi
model Order {
   tags: String[]
}
```

Query:

```taxi
given {
   emptyOrder: Order = { tags: [] },
   fullOrder: Order = { tags: ['express', 'gift'] }
}
find {
   emptyTags: String[] = emptyOrder.tags.ifEmpty(['standard'])
   fullTags: String[] = fullOrder.tags.ifEmpty(['standard'])
}
```

Result:

```json
{
  "emptyTags": [
    "standard"
  ],
  "fullTags": [
    "express",
    "gift"
  ]
}
```

------

### indexOfItem
`taxi.stdlib.indexOfItem`

```taxi
declare extension function <T> indexOfItem(collection:T[], searchItem: T):Int
```

Returns the zero-based index of an item within a collection, or `-1` if the item was not found.

```taxi
find { playlist: Playlist } as {
   songPosition: Int = playlist.tracks.indexOfItem('Bohemian Rhapsody')
}
```

### Examples
Returns the index of an item in the collection, or `-1` if not found.

Schema:

```taxi
model Playlist {
   tracks: String[]
}
```

Query:

```taxi
given {
   playlist: Playlist = { tracks: ['Alpha', 'Beta', 'Gamma'] }
}
find {
   betaIndex: Int = playlist.tracks.indexOfItem('Beta')
   missingIndex: Int = playlist.tracks.indexOfItem('Delta')
}
```

Result:

```json
{
  "betaIndex": 1,
  "missingIndex": -1
}
```

------

### intersection
`taxi.stdlib.intersection`

```taxi
declare extension function <T> intersection(collectionA: T[], collectionB: T[]):T[]
```

Returns a new collection containing only the elements that are present in both of the provided collections.

This function identifies common elements between two collections.

```taxi
// Find common tags between two products
find { productA: Product, productB: Product } as {
   commonTags: intersection(productA.tags, productB.tags)
}
```

### Examples
Returns only elements present in both collections, identified by value equality.

Schema:

```taxi
type Tag inherits String
model Product {
   name: ProductName inherits String
   tags: Tag[]
}
```

Query:

```taxi
given {
   productA: Product = {
      name: 'Smartphone',
      tags: ['electronics', 'mobile', 'camera', 'touchscreen']
   },
   productB: Product = {
      name: 'Digital Camera',
      tags: ['electronics', 'camera', 'photography', 'zoom']
   }
}
find {
   productAName: productA.name
   productBName: productB.name
   commonTags: intersection(productA.tags, productB.tags)
}
```

Result:

```json
{
  "productAName": "Smartphone",
  "productBName": "Digital Camera",
  "commonTags": [
    "electronics",
    "camera"
  ]
}
```

------

### isNullOrEmpty
`taxi.stdlib.isNullOrEmpty`

```taxi
declare extension function <T> isNullOrEmpty(collection:T[]):Boolean
```

Returns `true` if the provided collection is either `null` or contains zero elements.

```taxi
find { order: Order } as {
   hasNoItems: Boolean = order.items.isNullOrEmpty()
}
```

### Examples
Returns `true` for an empty collection, `false` when the collection has elements.

Schema:

```taxi
model Bag {
   items: String[]
}
```

Query:

```taxi
given {
   emptyBag: Bag = { items: [] },
   fullBag: Bag = { items: ['apple', 'banana'] }
}
find {
   emptyCheck: Boolean = emptyBag.items.isNullOrEmpty()
   fullCheck: Boolean = fullBag.items.isNullOrEmpty()
}
```

Result:

```json
{
  "emptyCheck": true,
  "fullCheck": false
}
```

------

### joinToString
`taxi.stdlib.joinToString`

```taxi
declare extension function <T> joinToString(values:T[], separator: String = ",", prefix: String? = null, postfix: String? = null): String
```

Creates a string from all the elements separated using `separator` and using the given `prefix` and `postfix` if supplied. Null values are omitted.

```taxi
find { order: Order } as {
   tagList: String = order.tags.joinToString(', ')
}
```

### Examples
Joins array elements into a single string, with optional separator, prefix, and postfix.

Query:

```taxi
given {
   tags: String[] = ['alpha', 'beta', 'gamma']
}
find {
   joined: String = tags.joinToString(', ')
   withBrackets: String = tags.joinToString(', ', '[', ']')
}
```

Result:

```json
{
  "joined": "alpha, beta, gamma",
  "withBrackets": "[alpha, beta, gamma]"
}
```

------

### last
`taxi.stdlib.last`

```taxi
declare extension function <T> last(collection: T[]):T
```

Returns the last item within the collection. Throws an error if the collection is empty.

This function retrieves the final element in an ordered collection.

```taxi
// Get the oldest transaction from a date-sorted list
find { account: Account } as {
   oldestTransaction: account.transactions.last()
}
```

### Examples
This example demonstrates how to use `last()` to retrieve the oldest transaction for an account.

Schema:

```taxi
model Transaction {
   date: String
   amount: Decimal
   description: String
}

model Account {
   accountNumber: String
   transactions: Transaction[] // Assumed to be in descending date order (newest first)
}
```

Query:

```taxi
given {
   account: Account = {
      accountNumber: 'ACC-12345',
      transactions: [
         { date: '2023-05-01', amount: 150.00, description: 'Grocery Store' },
         { date: '2023-04-28', amount: 45.99, description: 'Online Shop' },
         { date: '2023-04-25', amount: 20.00, description: 'Transfer' }
      ]
   }
}
find {
   accountNumber: account.accountNumber
   // Using .last() against the type
   oldestTransaction: Transaction =  Transaction[].last()
   // or, alternatively, using against the property name
   alsoOldestTransaction: Transaction = account.transactions.last()
}
```

Result:

```json
{
  "accountNumber": "ACC-12345",
  "oldestTransaction": {
    "date": "2023-04-25",
    "amount": 20,
    "description": "Transfer"
  },
  "alsoOldestTransaction": {
    "date": "2023-04-25",
    "amount": 20,
    "description": "Transfer"
  }
}
```

------

### listOf
`taxi.stdlib.listOf`

```taxi
declare function <T> listOf(values:T...):T[]
```

Creates and returns an array containing all the provided values.

This function is useful for creating collections inline without having to define them separately.

```taxi
// Create a list of allowed status values
find { order: Order } as {
   isValidStatus: listOf('PENDING', 'PROCESSING', 'SHIPPED', 'DELIVERED').contains(order.status)
}
```

### Examples
Creates an inline collection to check if an order status is one of the valid values.

Schema:

```taxi
model Order {
   id: String
   status: String
}
```

Query:

```taxi
given {
   orders: Order[] = [
      { id: 'order-1', status: 'PENDING' },
      { id: 'order-2', status: 'SHIPPED' },
      { id: 'order-3', status: 'CANCELED' }
   ]
}
find {
   validOrders: Order[] = orders.filter((order:Order) ->
      listOf('PENDING', 'PROCESSING', 'SHIPPED', 'DELIVERED').contains(order.status)
   )
   invalidOrders: Order[] = orders.filter((order:Order) ->
      listOf('PENDING', 'PROCESSING', 'SHIPPED', 'DELIVERED').contains(order.status) == false
   )
}
```

Result:

```json
{
  "validOrders": [
    {
      "id": "order-1",
      "status": "PENDING"
    },
    {
      "id": "order-2",
      "status": "SHIPPED"
    }
  ],
  "invalidOrders": [
    {
      "id": "order-3",
      "status": "CANCELED"
    }
  ]
}
```

------

### none
`taxi.stdlib.none`

```taxi
declare extension function <T> none(collection: T[], predicate: (T) -> Boolean): Boolean
```

Returns `true` if none of the items in the collection satisfy the predicate.

Returns `true` for an empty collection (vacuous truth).

```taxi
// Check that no task is overdue
find { sprint: Sprint } as {
   noOverdue: Boolean = sprint.tasks.none((task) -> task.isOverdue)
}
```

### Examples
Returns `true` when no item in the collection satisfies the predicate.

Schema:

```taxi
model Task {
   name: String
   isComplete: Boolean
}
```

Query:

```taxi
given {
   tasks: Task[] = [
      { name: 'Setup', isComplete: true },
      { name: 'Build', isComplete: true },
      { name: 'Deploy', isComplete: true }
   ]
}
find {
   noneIncomplete: Boolean = tasks.none((task: Task) -> task.isComplete == false)
}
```

Result:

```json
{
  "noneIncomplete": true
}
```

------

### noneOf
`taxi.stdlib.noneOf`

```taxi
declare function noneOf(values:Boolean...): Boolean
```

Returns `true` only if all provided boolean values are `false`. Equivalent to logical NOR.

This function is useful for checking if none of multiple conditions apply.

```taxi
// Check if a user has no permissions
type NoPermissions inherits Boolean by noneOf(IsAdmin, IsEditor, IsViewer)
```

### Examples
Returns `true` when all provided boolean conditions are `false`. Uses type-based access to combine semantic boolean types.

Schema:

```taxi
type IsAdmin inherits Boolean
type IsEditor inherits Boolean
type IsViewer inherits Boolean
model User {
   username: Username inherits String
   isAdmin: IsAdmin
   isEditor: IsEditor
   isViewer: IsViewer
}
```

Query:

```taxi
given {
   user: User = {
      username: 'GuestUser',
      isAdmin: false,
      isEditor: false,
      isViewer: false
   }
}
find {
   username: Username
   hasNoAccess: Boolean = noneOf(IsAdmin, IsEditor, IsViewer)
}
```

Result:

```json
{
  "username": "GuestUser",
  "hasNoAccess": true
}
```

------

### orEmpty
`taxi.stdlib.orEmpty`

```taxi
declare extension function <T> orEmpty(source:T[]): T[]
```

Returns the source array unchanged if it is non-null, or an empty array if it is `null`.

Useful for safely chaining collection operations on potentially-null fields.

```taxi
find { user: User } as {
   roles: user.roles.orEmpty().joinToString(', ')
}
```

### Examples
Returns the collection unchanged when non-null. Use `.orEmpty()` to safely chain operations on nullable arrays.

Schema:

```taxi
model Cart {
   items: String[]
}
```

Query:

```taxi
given {
   cart: Cart = { items: ['apple', 'banana'] }
}
find {
   items: String[] = cart.items.orEmpty()
}
```

Result:

```json
{
  "items": [
    "apple",
    "banana"
  ]
}
```

------

### single
`taxi.stdlib.single`

```taxi
declare extension function <T> single(collection:T[], callback: (T) -> Boolean):T
```

Returns the first item from a collection that matches the provided predicate. Throws an error if no matching item is found.

This function is useful when you need to find a specific element in a collection based on a condition.

```taxi
// Find a product by its SKU code
find { inventory: Inventory } as {
   appleMacbook: inventory.products.single((product) -> product.sku == "MB-PRO-2023")
}
```

### Examples
Finds the single product matching the given SKU. Throws if no match or more than one match is found.

Schema:

```taxi
model Product {
   name: ProductName inherits String
   sku: SKU inherits String
   price: Price inherits Decimal
}
model Inventory {
   products: Product[]
}
```

Query:

```taxi
given {
   inventory: Inventory = {
      products: [
         { name: 'Laptop', sku: 'LT-001', price: 1200.00 },
         { name: 'Smartphone', sku: 'SP-002', price: 999.99 },
         { name: 'Tablet', sku: 'TB-003', price: 499.50 }
      ]
   }
}
find {
   smartphoneDetails: Product = inventory.products.single((product: Product) -> product.sku == 'SP-002')
}
```

Result:

```json
{
  "smartphoneDetails": {
    "name": "Smartphone",
    "sku": "SP-002",
    "price": 999.99
  }
}
```

------

### singleBy
`taxi.stdlib.singleBy`

```taxi
declare extension function <T,A> singleBy(collection:T[], groupingFunction: (T) -> A, searchValue: A):T
```

Returns the item from a collection where the value returned by the grouping function matches the search value.

Similar to `single()`, but results are first grouped by the selector function, and these results are cached
to improve future performance when querying the same collection multiple times.

```taxi
// Find a product by its SKU code using a cached search
find { inventory: Inventory } as {
   appleMacbook: inventory.products.singleBy((product) -> product.sku, "MB-PRO-2023")
}
```

### Examples
Looks up products by SKU using a cached index. Faster than `single()` when querying the same collection multiple times.

Schema:

```taxi
model Product {
   name: Name inherits String
   sku: SKU inherits String
}
model Inventory {
   products: Product[]
}
```

Query:

```taxi
given {
   inventory: Inventory = {
      products: [
         { name: 'Laptop', sku: 'LT-001' },
         { name: 'Smartphone', sku: 'SP-002' },
         { name: 'Tablet', sku: 'TB-003' }
      ]
   }
}
find {
   laptop: inventory.products.singleBy((Product) -> SKU, 'LT-001' as SKU)
   tablet: inventory.products.singleBy((Product) -> SKU, 'TB-003' as SKU)
}
```

Result:

```json
{
  "laptop": {
    "name": "Laptop",
    "sku": "LT-001"
  },
  "tablet": {
    "name": "Tablet",
    "sku": "TB-003"
  }
}
```

------

### size
`taxi.stdlib.size`

```taxi
declare extension function <T> size(collection:T[]):Int
```

Returns the number of elements in the collection.

```taxi
find { orders: Order[] } as {
   orderCount: Int = orders.size()
}
```

### Examples
Returns the number of elements in the collection.

Schema:

```taxi
model Cart {
   items: String[]
}
```

Query:

```taxi
given {
   cart: Cart = { items: ['apple', 'banana', 'cherry'] }
}
find {
   itemCount: Int = cart.items.size()
}
```

Result:

```json
{
  "itemCount": 3
}
```

## Dates

Mess about with time. Flux capacitor not included

### addDays
`taxi.stdlib.dates.addDays`

```taxi
declare function <T> addDays(T, Int):T
```

Adds the specified number of days to a date, datetime, or instant. Use a negative value to subtract days.

```taxi
// Calculate an expiry date 90 days from today
find {
   @Format("yyyy-MM-dd")
   expiresOn: Date = addDays(Date, 90)
}
```

### Examples
Adds days to a date — positive to advance, negative to go back.

Query:

```taxi
given {
   start: Date = parseDate("2024-01-15")
}
find {
   @Format("yyyy-MM-dd")
   nextWeek: Date = addDays(Date, 7)
   @Format("yyyy-MM-dd")
   lastMonth: Date = addDays(Date, -30)
}
```

Result:

```json
{
  "nextWeek": "2024-01-22",
  "lastMonth": "2023-12-16"
}
```

------

### addMinutes
`taxi.stdlib.dates.addMinutes`

```taxi
declare function <T> addMinutes(T, Int):T
```

Adds the specified number of minutes to a datetime or instant. Use a negative value to subtract minutes.

```taxi
// Schedule a meeting 30 minutes from the event start
find {
   meetingEnd: DateTime = addMinutes(DateTime, 30)
}
```

### Examples
Adds minutes to a datetime — positive to advance, negative to go back.

Query:

```taxi
given {
   start: DateTime = parseDate("2024-01-15T10:30:00")
}
find {
   @Format("yyyy-MM-dd HH:mm")
   plusFive: DateTime = addMinutes(DateTime, 5)
   @Format("yyyy-MM-dd HH:mm")
   minusTwo: DateTime = addMinutes(DateTime, -120)
}
```

Result:

```json
{
  "plusFive": "2024-01-15 10:35",
  "minusTwo": "2024-01-15 08:30"
}
```

------

### addSeconds
`taxi.stdlib.dates.addSeconds`

```taxi
declare function <T> addSeconds(T, Int):T
```

Adds the specified number of seconds to a datetime or instant. Use a negative value to subtract seconds.

```taxi
// Expire a token 3600 seconds (1 hour) from now
find {
   expiresAt: Instant = addSeconds(Instant, 3600)
}
```

### Examples
Adds seconds to an instant — positive to advance, negative to go back.

Query:

```taxi
given {
   start: Instant = parseDate("2024-01-15T10:30:00Z")
}
find {
   @Format("yyyy-MM-dd HH:mm:ss")
   plusThirty: Instant = addSeconds(Instant, 30)
   @Format("yyyy-MM-dd HH:mm:ss")
   minusTen: Instant = addSeconds(Instant, -10)
}
```

Result:

```json
{
  "plusThirty": "2024-01-15 10:30:30",
  "minusTen": "2024-01-15 10:29:50"
}
```

------

### currentDate
`taxi.stdlib.dates.currentDate`

```taxi
declare function currentDate():Date
```

Returns the current local date (no time component).

```taxi
find {
   @Format("yyyy-MM-dd")
   today: Date = currentDate()
}
```

------

### currentDateTime
`taxi.stdlib.dates.currentDateTime`

```taxi
declare function currentDateTime():DateTime
```

Returns the current local date and time.

```taxi
find {
   @Format("yyyy-MM-dd HH:mm:ss")
   now: DateTime = currentDateTime()
}
```

------

### currentTime
`taxi.stdlib.dates.currentTime`

```taxi
declare function currentTime():Time
```

Returns the current local time (no date component).

```taxi
find {
   @Format("HH:mm:ss")
   timeNow: Time = currentTime()
}
```

------

### now
`taxi.stdlib.dates.now`

```taxi
declare function now():Instant
```

Returns the current UTC instant.

The output changes every time the function is called. Use `@Format` to control how the instant is serialised in query output.

```taxi
// Stamp the current time on a record
find {
   @Format("yyyy-MM-dd'T'HH:mm:ssXXX")
   processedAt: Instant = now()
}
```

------

### parseDate
`taxi.stdlib.dates.parseDate`

```taxi
declare function <T> parseDate(String):T
```

Parses a string into a date, datetime, or instant value. The target type determines which parsing rules are applied.

Supported target types are `Date`, `DateTime`, and `Instant`. Use `@Format` on the result field to control the output serialisation format.

```taxi
// Parse an ISO date string into a Date value
find {
   @Format("yyyy-MM-dd")
   eventDate: Date = parseDate("2024-06-15")
}
```

### Examples
Parses ISO date and datetime strings into their respective Taxi date types.

Query:

```taxi
find {
   @Format("yyyy-MM-dd")
   asDate: Date = parseDate("2024-06-15")
   @Format("yyyy-MM-dd HH:mm:ss")
   asDateTime: DateTime = parseDate("2024-06-15T10:30:00")
}
```

Result:

```json
{
  "asDate": "2024-06-15",
  "asDateTime": "2024-06-15 10:30:00"
}
```

## Math

Numbers 'n' such. Maths for the brits.

### average
`taxi.stdlib.average`

```taxi
declare extension function average(values: Any[]):Decimal
```

Returns the arithmetic mean of a collection of numeric values.

All values in the collection must be of the same numeric primitive type (Int, Decimal, etc.).
Returns null if the collection is empty or contains non-numeric values.

```taxi
find { order: Order } as {
   averageItemPrice: Decimal = order.items.map((Item) -> Item::price).average()
}
```

### Examples
Computes the average score from a collection of items.

Schema:

```taxi
model Item {
   score: Score inherits Decimal
}
```

Query:

```taxi
given {
   items: Item[] = [
      { score: 80.0 },
      { score: 90.0 },
      { score: 70.0 }
   ]
}
find {
   avg: Decimal = average(items.map((item: Item) -> item.score))
}
```

Result:

```json
{
  "avg": 80
}
```

------

### max
`taxi.stdlib.max`

```taxi
declare extension function <T,A> max(collection: T[], callback: (T) -> A):A
```

Returns the maximum value in the collection, computed by applying the selector function to each element.

```taxi
find { products: Product[] } as {
   mostExpensive: Price = products.max((Product) -> Price)
}
```

### Examples
Returns the maximum price from a collection of products.

Schema:

```taxi
model Product {
   name: String
   price: Price inherits Decimal
}
```

Query:

```taxi
given {
   products: Product[] = [
      { name: 'Apple', price: 1.50 },
      { name: 'Banana', price: 0.75 },
      { name: 'Cherry', price: 3.00 }
   ]
}
find {
   maxPrice: Price = products.max((Product) -> Price)
}
```

Result:

```json
{
  "maxPrice": 3
}
```

------

### min
`taxi.stdlib.min`

```taxi
declare extension function <T,A> min(collection: T[], callback: (T) -> A):A
```

Returns the minimum value in the collection, computed by applying the selector function to each element.

```taxi
find { products: Product[] } as {
   cheapest: Price = products.min((Product) -> Price)
}
```

### Examples
Returns the minimum price from a collection of products.

Schema:

```taxi
model Product {
   name: String
   price: Price inherits Decimal
}
```

Query:

```taxi
given {
   products: Product[] = [
      { name: 'Apple', price: 1.50 },
      { name: 'Banana', price: 0.75 },
      { name: 'Cherry', price: 3.00 }
   ]
}
find {
   minPrice: Price = products.min((Product) -> Price)
}
```

Result:

```json
{
  "minPrice": 0.75
}
```

------

### round
`taxi.stdlib.round`

```taxi
declare extension function round(value: Decimal, precision: Int = 0): Decimal
```

Rounds a decimal value to the specified number of decimal places.

`precision` defaults to `0` (round to nearest integer).

```taxi
find { measurement: Measurement } as {
   rounded: Decimal = measurement.value.round(2)
}
```

### Examples
Rounds a decimal to the specified number of decimal places.

Query:

```taxi
find {
   rounded2: Decimal = round(3.14159, 2)
   rounded0: Decimal = round(3.7, 0)
}
```

Result:

```json
{
  "rounded2": 3.14,
  "rounded0": 4
}
```

------

### sum
`taxi.stdlib.sum`

```taxi
declare extension function <T,A> sum(collection: T[], callback: (T) -> A):A
```

Returns the sum of values in the collection, computed by applying the selector function to each element.

```taxi
find { order: Order } as {
   total: Price = order.items.sum((Item) -> Price)
}
```

### Examples
Sums a numeric field across all elements of a collection.

Schema:

```taxi
model Product {
   name: String
   price: Price inherits Decimal
}
```

Query:

```taxi
given {
   products: Product[] = [
      { name: 'Apple', price: 1.50 },
      { name: 'Banana', price: 0.75 },
      { name: 'Cherry', price: 3.00 }
   ]
}
find {
   totalPrice: Price = products.sum((Product) -> Price)
}
```

Result:

```json
{
  "totalPrice": 5.25
}
```

## Objects

Utilities for dealing with equality, etc

### emptyInstance
`taxi.stdlib.emptyInstance`

```taxi
declare extension function <A> emptyInstance(instanceType:lang.taxi.Type<A>): A
```

Returns an instance of the requested type with all fields set to their empty state: scalars are `null`, collections are `[]`, and nested objects are recursively emptied.

```taxi
// Create a blank template of a type
find {
   blank: MyModel = emptyInstance(MyModel)
}
```

### Examples
Creates an empty instance of a model: scalars are null and collections are empty arrays.

Schema:

```taxi
type UserTag inherits String
model User {
   name: UserName inherits String
   age: Age inherits Int
   tags: UserTag[]
}
```

Query:

```taxi
find {
   empty: User = emptyInstance(User)
}
```

Result:

```json
{
  "empty": {
    "name": null,
    "age": null,
    "tags": []
  }
}
```

------

### equals
`taxi.stdlib.equals`

```taxi
declare extension function <A,B> equals(a:A, b:B): Boolean
```

Returns `true` if two values are equal. Equality is checked by value and type — values of different semantic types are not equal even if their underlying values match.

```taxi
find {
   match: Boolean = OrderStatus.equals("PENDING")
}
```

### Examples
Compares two string values — matching pair returns true, non-matching returns false.

Query:

```taxi
find {
   same: Boolean = "hello".equals("hello")
   different: Boolean = "hello".equals("world")
}
```

Result:

```json
{
  "same": true,
  "different": false
}
```

## Enums

Utilities for enums

### enumForName
`taxi.stdlib.enumForName`

```taxi
declare extension function <T> enumForName(enumType: lang.taxi.Type<T>, enumName: String): T
```

Returns the enum member matching the provided value string. Throws if no match is found.

```taxi
// Look up an enum member by its string value
find {
   status: OrderStatus = enumForName(OrderStatus, "PENDING")
}
```

### Examples
Looks up an enum member by its string value and returns it as a typed enum.

Schema:

```taxi
enum OrderStatus { PENDING, APPROVED, REJECTED }
```

Query:

```taxi
find {
   status: OrderStatus = enumForName(OrderStatus, "PENDING")
}
```

Result:

```json
{
  "status": "PENDING"
}
```

------

### hasEnumNamed
`taxi.stdlib.hasEnumNamed`

```taxi
declare extension function <T> hasEnumNamed(enumType: lang.taxi.Type<T>, enumName: String): Boolean
```

Returns `true` if the enum has an explicitly declared member matching the provided name.

Ignores default entries — an enum with a default value will return `false` for a name that is only matched by the default, not by an explicit declaration.

```taxi
find {
   valid: Boolean = hasEnumNamed(OrderStatus, "PENDING")
}
```

### Examples
Returns true for a declared enum member name, false for a name not in the enum.

Schema:

```taxi
enum OrderStatus { PENDING, APPROVED, REJECTED }
```

Query:

```taxi
find {
   hasPending: Boolean = hasEnumNamed(OrderStatus, "PENDING")
   hasUnknown: Boolean = hasEnumNamed(OrderStatus, "UNKNOWN")
}
```

Result:

```json
{
  "hasPending": true,
  "hasUnknown": false
}
```

## Aggregations

Functions for aggregating data within transformations.

### sumOver
`vyne.aggregations.sumOver`

```taxi
declare query function sumOver(Any...):Decimal
```

A Vyne-specific aggregate function used in analytical queries to compute a running or grouped sum.

Used in `sumOver` window-style queries where values are aggregated across a result set.

```taxi
find { orders: Order[] } as {
   totalRevenue: Decimal = sumOver(Amount)
}
```

## Functional

Functions that are functionally functions. Funky

### fold
`taxi.stdlib.fold`

```taxi
declare extension function <T,A> fold(collection: T[], initial: A, callback: (T,A) -> A):A
```

Iterates over a collection, combining elements with an accumulator to produce a single result.

Unlike `reduce`, `fold` starts with an explicit `initial` value as the accumulator.

```taxi
// Compute a weighted sum
model Entry {
   weight: Weight inherits Int
   score: Score inherits Int
}
type WeightedTotal by (Entry[]) -> Entry[].fold(0, (Entry, Int) -> Int + (Weight * Score))
```

------

### map
`taxi.stdlib.map`

```taxi
declare extension function <T,A> map(collection: T[], callback: (T) -> A):A[]
```

Applies a transformation function to every element in a collection, returning a new array of the results.

If the callback is a type expression, each element is converted to that type:

```taxi
// Convert Person[] to Name[]
Person[].map((Person) -> Name)
```

If the callback is any other expression, it is evaluated against each element:

```taxi
// Return an array of uppercased titles
Film[].map((Title) -> Title.upperCase())
```

### Examples
Extracts a field from each object in a collection, returning a typed array.

Schema:

```taxi
model Product {
   name: Name inherits String
   price: Price inherits Decimal
}
```

Query:

```taxi
given {
   products: Product[] = [
      { name: 'Apple', price: 1.50 },
      { name: 'Banana', price: 0.75 },
      { name: 'Cherry', price: 3.00 }
   ]
}
find {
   names: Name[] = products.map((Product) -> Name)
}
```

Result:

```json
{
  "names": [
    "Apple",
    "Banana",
    "Cherry"
  ]
}
```

------

### reduce
`taxi.stdlib.reduce`

```taxi
declare extension function <T,A> reduce(collection: T[], callback: (T,A) -> A):A
```

Reduces a collection to a single value by applying a combining function to each element and the accumulated result.

Unlike `fold`, there is no initial value — the first element of the collection is used as the starting accumulator.

```taxi
// Sum a list of integers
find {
   total: Int = numbers.reduce((Int, Int) -> Int + Int)
}
```

## Transformations

Functions for converting between types

### convert
`taxi.stdlib.convert`

```taxi
declare extension function <T> convert(source: Any, targetType: lang.taxi.Type<T>): T
```

Converts a source value to the target type using only the data already available — no service calls are made.

This is faster than a full projection (`source as TargetType`), but less powerful: only the fields present in the source are mapped. Missing fields are not discovered from services.

```taxi
// Convert an Order to a Receipt using only the Order's own fields
find {
   receipt: Receipt = Order.convert(Receipt)
}
```

### Examples
Converts an Order to a Receipt model using only the fields present in the source, without calling any services.

Schema:

```taxi
model Order {
   id: OrderId inherits String
   amount: Amount inherits Decimal
}
model Receipt {
   id: OrderId
   amount: Amount
}
```

Query:

```taxi
given {
   order: Order = { id: 'O1', amount: 99.99 }
}
find {
   receipt: Receipt = Order.convert(Receipt)
}
```

Result:

```json
{
  "receipt": {
    "id": "O1",
    "amount": 99.99
  }
}
```

------

### toRawType
`taxi.stdlib.toRawType`

```taxi
declare extension function toRawType(source: Any):Any
```

Removes the semantic typing from a scalar value, returning it typed as its raw primitive.

Useful when you need to compare values by their raw content while ignoring their semantic type.

- For a scalar value: strips the semantic type, returning the underlying primitive.
- For an array of scalars: strips the semantic type from each element.

Not supported on objects or arrays of objects.

```taxi
find { order: Order } as {
   rawId: String = order.id.toRawType()
}
```

### Examples
Strips the semantic type from a typed scalar, returning the raw primitive value.

Schema:

```taxi
type OrderId inherits String
```

Query:

```taxi
given {
   orderId: OrderId = 'ORD-001'
}
find {
   rawId: String = orderId.toRawType()
}
```

Result:

```json
{
  "rawId": "ORD-001"
}
```

## Parsing

Functions for converting between types

### parseJson
`taxi.stdlib.parseJson`

```taxi
declare extension function <T> parseJson(source: String, type: Type<T>):T
```

Parses a JSON string into the specified type.

This is useful when a field contains a JSON payload encoded as a string (e.g., from a message queue or API response),
and you need to deserialize it into a structured type.

Computed fields and functions on the target type are evaluated after parsing.

```taxi
model Event {
   name : String
   payload : String
   parsed : Payload = parseJson(this.payload, Payload)
}
```

### Examples
Parses a JSON string embedded in a model field into a structured type.

Schema:

```taxi
model Address {
   city: String
   country: String
}
model Customer {
   name: String
   addressJson: String
   address: Address = parseJson(this.addressJson, Address)
}
```

Query:

```taxi
given {
   customer: Customer = {
      name: 'Alice',
      addressJson: '{ "city": "London", "country": "UK" }'
   }
}
find {
   name: customer.name
   address: customer.address
}
```

Result:

```json
{
  "name": "Alice",
  "address": {
    "city": "London",
    "country": "UK"
  }
}
```

## Errors

Functions for creating and handling errors

### throw
`taxi.stdlib.throw`

```taxi
declare function throw(error:Any):Nothing
```

Throws an error, halting execution. Useful for enforcing invariants inline.

```taxi
find { order: Order } as {
   status: OrderStatus = when {
      OrderStatus == 'INVALID' -> throw('Order status is invalid')
      else -> OrderStatus
   }
}
```
