> ## Documentation Index
> Fetch the complete documentation index at: https://docs.artu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Utilities

> Filter helpers, pagination utilities, and type guards exported by the TypeScript SDK

The SDK exports a set of utility functions for building filters, working with paginated results, and narrowing types at runtime.

For Mexico-specific validators (RFC, CURP, CLABE), see the [Mexico page](/scopes/mexico).

***

## Filter Utilities

Import filter helpers from the main entry point:

```typescript theme={null}
import {
  // String filters
  contains,
  startsWith,
  endsWith,
  equals,
  notEquals,
  // Array filters
  oneOf,
  notOneOf,
  // Date filters
  dateRange,
  after,
  before,
  onOrAfter,
  onOrBefore,
  // Number filters
  numberRange,
  greaterThan,
  lessThan,
  atLeast,
  atMost,
  // Boolean filters
  isTrue,
  isFalse,
  // Null filters
  isNull,
  isNotNull,
} from "@artu-ai/compliance-sdk";
```

### String Filters

#### `contains(value)`

Match if a field contains the given substring.

```typescript theme={null}
contains(value: string): { contains: string }
```

```typescript theme={null}
sdk.clients.list({ filter: { name: contains("García") } });
// Matches: "Juan García", "García López"
```

#### `startsWith(value)`

Match if a field starts with the given prefix.

```typescript theme={null}
startsWith(value: string): { startsWith: string }
```

#### `endsWith(value)`

Match if a field ends with the given suffix.

```typescript theme={null}
endsWith(value: string): { endsWith: string }
```

```typescript theme={null}
sdk.clients.list({ filter: { email: endsWith("@company.com") } });
```

#### `equals(value)`

Exact match (case-sensitive).

```typescript theme={null}
equals<T>(value: T): { eq: T }
```

```typescript theme={null}
sdk.clients.list({ filter: { externalId: equals("crm-001") } });
```

#### `notEquals(value)`

Not equal.

```typescript theme={null}
notEquals<T>(value: T): { neq: T }
```

### Array Filters

#### `oneOf(...values)`

Match any of the provided values (OR).

```typescript theme={null}
oneOf<T>(...values: T[]): { in: T[] }
```

```typescript theme={null}
sdk.clients.list({ filter: { type: oneOf("individual", "company") } });
```

#### `notOneOf(...values)`

Exclude all provided values.

```typescript theme={null}
notOneOf<T>(...values: T[]): { nin: T[] }
```

```typescript theme={null}
sdk.clients.list({ filter: { status: notOneOf("deleted", "archived") } });
```

### Date Filters

#### `dateRange(start?, end?)`

Inclusive date range.

```typescript theme={null}
dateRange(start?: Date, end?: Date): { gte?: string; lte?: string }
```

```typescript theme={null}
sdk.transactions.list({
  filter: { createdAt: dateRange(new Date("2024-01-01"), new Date("2024-12-31")) },
});
```

#### `after(date)` / `before(date)`

Exclusive date comparisons.

```typescript theme={null}
after(date: Date): { gt: string }
before(date: Date): { lt: string }
```

#### `onOrAfter(date)` / `onOrBefore(date)`

Inclusive date comparisons.

```typescript theme={null}
onOrAfter(date: Date): { gte: string }
onOrBefore(date: Date): { lte: string }
```

### Number Filters

#### `numberRange(min?, max?)`

Inclusive number range.

```typescript theme={null}
numberRange(min?: number, max?: number): { gte?: number; lte?: number }
```

```typescript theme={null}
sdk.transactions.list({ filter: { amount: numberRange(1000, 10000) } });
```

#### `greaterThan(value)` / `lessThan(value)`

Exclusive number comparisons.

```typescript theme={null}
greaterThan(value: number): { gt: number }
lessThan(value: number): { lt: number }
```

#### `atLeast(value)` / `atMost(value)`

Inclusive number comparisons.

```typescript theme={null}
atLeast(value: number): { gte: number }
atMost(value: number): { lte: number }
```

### Boolean Filters

#### `isTrue()` / `isFalse()`

```typescript theme={null}
isTrue(): { eq: true }
isFalse(): { eq: false }
```

```typescript theme={null}
sdk.bankAccounts.list({ filter: { isActive: isTrue() } });
```

### Null Filters

#### `isNull()` / `isNotNull()`

```typescript theme={null}
isNull(): { eq: null }
isNotNull(): { neq: null }
```

```typescript theme={null}
sdk.clients.list({ filter: { deletedAt: isNull() } });
```

***

## Pagination Utilities

Import pagination helpers from the main entry point:

```typescript theme={null}
import {
  collectAll,
  collectUpTo,
  getFirst,
  DEFAULT_PAGE_SIZE,
  MAX_PAGE_SIZE,
} from "@artu-ai/compliance-sdk";
```

### Constants

| Constant            | Value | Description                      |
| ------------------- | ----- | -------------------------------- |
| `DEFAULT_PAGE_SIZE` | `20`  | Default page size for list calls |
| `MAX_PAGE_SIZE`     | `200` | Maximum allowed page size        |

### `collectAll(iterator)`

Collects all items from an async iterator into an array. Use with caution on large datasets.

```typescript theme={null}
collectAll<T>(iterator: AsyncGenerator<T, void, undefined>): Promise<T[]>
```

```typescript theme={null}
const allClients = await collectAll(sdk.clients.iterate());
console.log(`Total: ${allClients.length}`);
```

### `collectUpTo(iterator, maxItems)`

Collects up to `maxItems` from an iterator.

```typescript theme={null}
collectUpTo<T>(iterator: AsyncGenerator<T, void, undefined>, maxItems: number): Promise<T[]>
```

```typescript theme={null}
const first100 = await collectUpTo(sdk.clients.iterate(), 100);
```

### `getFirst(iterator)`

Returns the first item from an iterator, or `undefined` if empty.

```typescript theme={null}
getFirst<T>(iterator: AsyncGenerator<T, void, undefined>): Promise<T | undefined>
```

```typescript theme={null}
const first = await getFirst(sdk.clients.iterate({ filter: { type: "individual" } }));
```

### Manual Cursor Pagination

```typescript theme={null}
let cursor: string | undefined;

do {
  const { data, pagination } = await sdk.clients.list({ cursor, limit: 100 });
  await processBatch(data);
  cursor = pagination.nextCursor;
} while (cursor);
```

### Async Iterator Pattern

```typescript theme={null}
// Automatically handles cursor pagination
for await (const client of sdk.clients.iterate({ filter: { type: "individual" } })) {
  await processClient(client);
}

// Early exit
let count = 0;
for await (const client of sdk.clients.iterate()) {
  await processClient(client);
  if (++count >= 500) break;
}
```

***

## Type Guards

Type guards narrow model types at runtime and give access to scope-specific fields without unsafe casts.

### Base Type Guards

```typescript theme={null}
import {
  isClient,
  isIndividual,
  isCompany,
  isTrust,
  isTransaction,
  isBankAccount,
  isAlert,
  isAlertItem,
  isAddress,
  isLinkedClient,
  isAPIError,
  isUploadError,
} from "@artu-ai/compliance-sdk";
```

| Guard            | Narrows to             |
| ---------------- | ---------------------- |
| `isClient`       | `Client` model         |
| `isIndividual`   | Individual client      |
| `isCompany`      | Company client         |
| `isTrust`        | Trust client           |
| `isTransaction`  | `Transaction` model    |
| `isBankAccount`  | `BankAccount` model    |
| `isAlert`        | `Alert` model          |
| `isAlertItem`    | `AlertItem` model      |
| `isAddress`      | `Address` model        |
| `isLinkedClient` | `LinkedClient` model   |
| `isAPIError`     | `APIError` subclass    |
| `isUploadError`  | `UploadError` subclass |

```typescript theme={null}
if (isClient(value)) {
  console.log(value.name);
}

if (isIndividual(client)) {
  console.log(client.birthDate);
}

if (isCompany(client)) {
  console.log(client.incorporationDate);
}
```

### Scoped Type Guards

Each scope sub-export provides type guards for that scope's model types, available both as direct named exports and via a `TypeGuards` namespace object:

<Tabs>
  <Tab title="Mexico">
    ```typescript theme={null}
    import { isClient, isTransaction, TypeGuards } from "@artu-ai/compliance-sdk/mx";

    if (isClient(client)) {
      console.log(client.rfc);
      console.log(client.curp);
    }

    // Or via the namespace
    if (TypeGuards.isClient(client)) {
      console.log(client.rfc);
    }
    ```
  </Tab>

  <Tab title="Mexico ARI">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/ari";

    if (isTransaction(txn)) {
      console.log(txn.operationType);
    }
    ```
  </Tab>

  <Tab title="Mexico AVI">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/avi";

    if (isClient(client)) {
      console.log(client.username);
    }

    if (isTransaction(txn)) {
      console.log(txn.operationType);
      console.log(txn.hash);
    }
    ```
  </Tab>

  <Tab title="Mexico INM">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/inm";

    if (isTransaction(txn)) {
      console.log(txn.operationType);
      console.log(txn.figuraCliente);
    }
    ```
  </Tab>

  <Tab title="Mexico JYS">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/jys";

    if (isTransaction(txn)) {
      console.log(txn.operationType);
      console.log(txn.businessLine);
    }
    ```
  </Tab>

  <Tab title="Mexico MJR">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/mjr";

    if (isTransaction(txn)) {
      console.log(txn.operationType);
      console.log(txn.operationPostalCode);
    }
    ```
  </Tab>

  <Tab title="Mexico MPC">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/mpc";

    if (isTransaction(txn)) {
      console.log(txn.operationType);
      console.log(txn.postalCode);
    }
    ```
  </Tab>

  <Tab title="Mexico TSC">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/tsc";

    if (isTransaction(txn)) {
      console.log(txn.cardType);
      console.log(txn.idNumber);
    }
    ```
  </Tab>

  <Tab title="Mexico VEH">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/av/veh";

    if (isTransaction(txn)) {
      console.log(txn.operationType);
      console.log(txn.postalCode);
    }
    ```
  </Tab>

  <Tab title="Mexico CNBV Transmisor">
    ```typescript theme={null}
    import { isClient, isTransaction } from "@artu-ai/compliance-sdk/mx/cnbv/transmisor";

    if (isClient(client)) {
      console.log(client.numeroCuenta);
      console.log(client.claveSujetoObligado);
    }

    if (isTransaction(txn)) {
      console.log(txn.tipoOperacion);
      console.log(txn.instrumentoMonetario);
    }
    ```
  </Tab>
</Tabs>

### Mexico Document Guards

```typescript theme={null}
import {
  isDocument,
  isIneFront,
  isIneBack,
  isPassport,
  isCurp,
  isRfcConstancia,
  isAddressProof,
  isActaConstitutiva,
  isPoderNotarial,
} from "@artu-ai/compliance-sdk/mx";

if (isIneFront(doc)) {
  console.log(doc.fields.cic);
  console.log(doc.fields.claveElector);
}

if (isRfcConstancia(doc)) {
  console.log(doc.fields.rfc);
  console.log(doc.fields.regimenFiscal);
}
```

### Conditional Processing Pattern

```typescript theme={null}
import { isClient } from "@artu-ai/compliance-sdk/mx";
import { isClient as isAVIClient } from "@artu-ai/compliance-sdk/mx/av/avi";

async function processClient(client: Client) {
  if (isClient(client)) {
    await validateRfc(client.rfc);

    if (isAVIClient(client)) {
      await validatePlatform(client.dominioPlataforma);
    }
  }
}
```

### Error Type Guards

```typescript theme={null}
import { isAPIError, isUploadError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.retrieve("id");
} catch (error) {
  if (isAPIError(error)) {
    console.log("API error:", error.statusCode, error.requestId);
  } else if (isUploadError(error)) {
    console.log("Upload failed at stage:", error.stage);
  }
}
```
