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

# Iru Query Language

> Iru Query Language (IQL) es el lenguaje de expresiones de Iru para dar forma a los valores asignados: campos, operadores, funciones de cadena, condicionales y funciones auxiliares seguras frente a nulos.

Cuando asignas lo que recibe una aplicación al iniciar sesión (el **Subject (NameID)**
de una [aplicación SAML](/es/identity/applications/saml-applications), o el **sujeto
y los claims** de una [aplicación OIDC](/es/identity/applications/oidc-applications)), cada
valor es una **expresión IQL**. IQL te permite obtener datos del perfil de un usuario y transformar
el valor antes de enviarlo.

<Info>
  **IQL** (Iru Query Language) es el lenguaje de expresiones de Iru para la **asignación**, y se usa en varios lugares:

  * Los atributos y claims que recibe una aplicación al iniciar sesión.
  * Los campos que una fuente conectada asigna a tu directorio (consulta
    [Asignación de atributos](/es/identity/directory/attribute-mapping)).
  * Las reglas de [Auto Groups](/es/identity/directory/auto-groups) y los filtros de listas.

  La misma sintaxis funciona en todos los lugares donde aparece IQL.

  IQL se basa en [CEL (Common Expression Language)](https://cel.dev), el estándar
  abierto de lenguaje de expresiones, por lo que cualquier expresión válida en CEL es válida en
  IQL.
</Info>

Mientras escribes, el editor de asignaciones sugiere los campos, funciones y
operadores disponibles, y muestra una **vista previa** en tiempo real del resultado. Una expresión debe
**superar la comprobación de tipos** en el editor y de nuevo al guardar, de modo que los errores aparecen antes de
llegar a un inicio de sesión o a una sincronización.

## Hacer referencia a tus datos

A qué haces referencia depende de dónde se ejecute la expresión:

* La **asignación de aplicaciones** parte del objeto `user`, cuyos campos son los
  [atributos de perfil](/es/identity/directory/schema) de tu directorio:

  ```
  user.email
  user.username
  user.id
  ```

  Los valores predeterminados lo reflejan: el sujeto de una aplicación OIDC es por defecto `user.id`, y el
  Subject de una aplicación SAML es por defecto `user.username`.

* La **asignación de Directory Sync** hace referencia a los **nombres de campo de la fuente**. Un identificador
  IQL válido se escribe directamente, tal como llega del sistema conectado.
  Empieza con una letra ASCII o un guion bajo, y el resto son letras ASCII,
  números y guiones bajos:

  ```
  email_work
  first_name
  ```

  Cualquier otro nombre se lee desde `__source` por su nombre exacto. Eso incluye espacios,
  símbolos, un punto dentro de un único nombre de campo, caracteres no ASCII y palabras
  clave de IQL. Por ejemplo, `__source["Email - Work"]`. Consulta
  [Transformar valores con IQL](/es/identity/directory/directory-sync#transform-values-with-iql).

Los nombres de campo **distinguen entre mayúsculas y minúsculas**. Accede a valores anidados con un punto
(`user.profile.team`), y a una lista o un mapa con `[...]` (se explica más abajo).

## Elementos básicos

| Forma | Ejemplo | Qué es |
| - | - | - |
| Campo / variable | `first_name`, `user.email` | Un valor por su nombre, o un campo de un valor. |
| Llamada a método | `user.email.upperAscii()` | Una función llamada **sobre** un valor. |
| Indexación | `parts[0]` | Un elemento de una lista por su posición, empezando por cero. |
| Clave de mapa | `entry["label"]` | El valor almacenado bajo una clave de cadena. |
| Agrupación | `(a + b) * c` | Paréntesis para controlar el orden de evaluación. |

## Literales

```
"hello"                             // string (double quotes)
'hello'                             // string (single quotes)
42                                  // whole number
3.14                                // decimal number
true   false                        // booleans
null                                // null
["a", "b", "c"]                     // list
{"label": "work", "primary": true}  // map (string keys)
```

Las cadenas admiten las secuencias de escape habituales, como `\n`, `\t`, `\\`, `\"` y `\uXXXX`.

## Operadores

<Tabs>
  <Tab title="Aritméticos">
    | Operador | Ejemplo | Qué hace |
    | - | - | - |
    | `+` | `first_name + " " + last_name` | Suma números o **une cadenas**. |
    | `-` `*` `/` | `a * b` | Resta, multiplica, divide. |
    | `%` | `a % b` | Resto (módulo). |
  </Tab>

  <Tab title="Comparación">
    | Operador | Ejemplo | Qué hace |
    | - | - | - |
    | `==` `!=` | `user.domain == "acme.com"` | Igual, distinto. |
    | `<` `<=` `>` `>=` | `user.level >= 3` | Comparaciones de orden. |
  </Tab>

  <Tab title="Lógicos">
    | Operador | Ejemplo | Qué hace |
    | - | - | - |
    | `&&` | `a && b` | Y. |
    | <code>\|\|</code> | <code>a \|\| b</code> | O. |
    | `!` | `!a` | No. |
  </Tab>

  <Tab title="Pertenencia y elección">
    | Operador | Ejemplo | Qué hace |
    | - | - | - |
    | `in` | `user.domain in ["acme.com", "acme.io"]` | Verdadero si el valor está en una lista, o si una clave está en un mapa. |
    | `? :` | `name != "" ? name : "unknown"` | Condicional: elige un valor u otro. |
  </Tab>
</Tabs>

### Precedencia

De mayor a menor prioridad. En caso de duda, añade paréntesis.

```
1) a.b   a()   a[i]   ()      // member access, calls, indexing, grouping
2) !a    -a                   // unary not, negation
3) *  /  %                    // multiply, divide, remainder
4) +  -                       // add, subtract (and string +)
5) <  <=  >  >=  in           // comparison and membership
6) ==  !=                     // equality
7) &&                         // and
8) ||                         // or
9) ? :                        // conditional
```

## Funciones de cadena

Las operaciones con cadenas se escriben como **métodos** sobre un valor, con la forma
`value.method(...)`:

| Método | Ejemplo | Qué hace |
| - | - | - |
| `upperAscii` / `lowerAscii` | `user.email.lowerAscii()` | Convierte el valor a mayúsculas o minúsculas. |
| `trim` | `first_name.trim()` | Elimina los espacios en blanco del principio y del final. |
| `split` | `user.email.split("@")` | Divide en una lista según un separador; accede a ella con `[n]`. |
| `replace` | `phone.replace("-", "")` | Sustituye cada aparición de una subcadena por otra. |
| `contains` | `user.email.contains("+")` | Verdadero si el valor contiene una subcadena. |
| `startsWith` / `endsWith` | `user.email.endsWith("@acme.com")` | Comprueba cómo empieza o termina el valor. |
| `indexOf` | `username.indexOf(".")` | Posición de una subcadena, o `-1` si no existe. |
| `matches` | `user.email.matches("^[a-z]+@acme\\.com$")` | Verdadero si el valor coincide con una expresión regular. |
| `size` | `user.email.split("@").size()` | Longitud de una cadena o lista. También disponible como `size(value)`. |

## Condicionales y valores predeterminados

El operador condicional es la forma más sencilla de proporcionar un valor alternativo cuando un valor
puede estar vacío:

```
// Use the first name, or fall back to the username when it's empty
user.firstName != "" ? user.firstName : user.username
```

Para un manejo más completo de los nulos, IQL también tiene funciones auxiliares **optional** (seguras frente a nulos), que se describen a continuación.

## Valores opcionales

Las funciones auxiliares de optional te permiten trabajar con valores que **pueden faltar** sin
provocar un error. Un *optional* contiene un valor o está vacío.

<Tabs>
  <Tab title="Crear">
    ```
    optional.of(value)            // wrap a value as an optional
    optional.ofNonZeroValue(value) // empty if the value is "zero" (see below)
    optional.none()               // an empty optional
    ```

    `ofNonZeroValue` trata como vacíos los siguientes valores: una cadena vacía `""`, `0`, `false`,
    una lista vacía `[]`, un mapa vacío `{}` y `null`.
  </Tab>

  <Tab title="Acceder de forma segura">
    ```
    value.?field     // optional field access (yields an optional)
    list[?i]         // optional index (empty instead of an error if out of range)
    ```
  </Tab>

  <Tab title="Desenvolver">
    ```
    opt.hasValue()          // true if the optional holds a value
    opt.value()             // the inner value (errors if empty)
    opt.orValue(fallback)   // the value, or the fallback if empty
    a.or(b)                 // the first of two optionals that has a value
    ```
  </Tab>

  <Tab title="Transformar">
    ```
    opt.optMap(x, expr)      // transform the inner value if present, else stay empty
    opt.optFlatMap(x, expr)  // like optMap, when expr itself returns an optional
    ```
  </Tab>
</Tabs>

```
// A default when a field is empty
optional.ofNonZeroValue(first_name).orValue("anon")

// Split an email and safely take the domain, falling back to ""
optional.ofNonZeroValue(email_work).optMap(e, e.split("@"))[?1].orValue("")
```

## Comentarios y espacios en blanco

Los espacios en blanco no son significativos, y `//` inicia un comentario que llega hasta el final de
la línea:

```
user.firstName + " " + user.lastName   // build a display name
```

## Ejemplos

```
// A field, as-is
user.email

// Upper-case the value
user.email.upperAscii()

// Build a display name from two fields
user.firstName + " " + user.lastName

// The local part of an email, before the "@"
user.email.split("@")[0]

// A field from the user's first address
user.addresses[0].city

// Choose a fallback when a field is blank
user.firstName != "" ? user.firstName : user.username

// A structured value, built as a map
{"email": user.email, "primary": true}
```

<Tip>
  Usa la **vista previa** del editor de asignaciones para confirmar que una expresión produce lo que
  esperas antes de publicarla; muestra el valor exacto que Iru enviará o almacenará.
</Tip>

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Asignación de aplicaciones" icon="arrows-left-right" href="/es/identity/applications/application-mapping">
    Asigna valores IQL a la aserción o al token que recibe una aplicación.
  </Card>

  <Card title="Asignación de atributos" icon="code" href="/es/identity/directory/attribute-mapping">
    Usa el mismo IQL para asignar una fuente conectada a tu directorio.
  </Card>

  <Card title="Grupos automáticos" icon="wand-magic-sparkles" href="/es/identity/directory/auto-groups">
    Impulsa la pertenencia a grupos con reglas IQL sobre atributos de perfil.
  </Card>

  <Card title="Atributos de perfil" icon="table-list" href="/es/identity/directory/schema">
    Los campos de `user` de los que obtienen datos tus expresiones.
  </Card>
</CardGroup>
