Metadata-Version: 2.4
Name: cartagon-monday-client
Version: 2.3.2607
Summary: Cliente Python para integraciones con la API GraphQL de Monday.com
Author-email: Miguel Díaz <mpsdiaz@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/tu-usuario/cartagon-monday-client
Project-URL: Documentation, https://github.com/tu-usuario/cartagon-monday-client#readme
Project-URL: Source, https://github.com/tu-usuario/cartagon-monday-client
Project-URL: Bug Tracker, https://github.com/tu-usuario/cartagon-monday-client/issues
Keywords: monday,monday.com,graphql,api,cliente,integración
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: responses>=0.18; extra == "dev"

# cartagon-monday-client

Cliente **Python** para integraciones con la **API GraphQL de Monday.com**.  
Proporciona una capa de alto nivel sobre GraphQL con:

- Manejo automático de **reintentos**:
  - HTTP `5xx`, `403`
  - `401/404` transitorios
  - Errores de **complejidad** (`COMPLEXITY_BUDGET_EXHAUSTED`) respetando `retry_in_seconds` cuando está disponible
- Paginación automática con `items_page` → `next_items_page`
- Utilidades de alto nivel para crear, actualizar y consultar ítems, subítems, usuarios y notificaciones
- Validación de tipos antes de llamar a la API
- Type hints completos — compatible con mypy y pyright

> **Requisitos**: Python **3.10+**

---

```bash
pip install cartagon-monday-client
```

Importación:

```python
from monday_client import MondayClient

token = "TU_API_TOKEN"
client = MondayClient(api_key=token)

# 1) Probar conexión
print(client.test_connection())  # True si el token es válido

# 2) Listar tableros
boards = client.get_boards(limit=5, page=1)
for b in boards:
    print(f"{b['id']}: {b['name']}")

# 3) Obtener todos los ítems de un tablero (paginación automática)
items = client.get_all_items(board_id=123456789, limit=100)
print("Total ítems:", len(items))

# 4) Obtener ítems de un grupo concreto
items = client.get_all_items(board_id=123456789, group_id="topics")
print("Ítems del grupo:", len(items))

# 5) Obtener ítems incluyendo subítems
items = client.get_all_items(
    board_id=123456789,
    subitems="subitems { id name column_values { value } }"
)

# 6) Crear un ítem
item = client.create_item(
    board_id=123456789,
    item_name="Tarea de ejemplo",
    columns=[
        {"id": "status", "type": "status", "value": "Working on it"},
        {"id": "date", "type": "date", "value": {"date": "2025-09-25"}}
    ]
)
print("Ítem creado:", item)

# 7) Crear múltiples ítems en bloque
results = client.bulk_create_items([
    {
        "board_id": 123456789,
        "item_name": "Lead A",
        "group_id": "topics",
        "columns": [{"id": "status", "type": "status", "value": "Working on it"}]
    },
    {
        "board_id": 123456789,
        "item_name": "Lead B",
        "columns": {"status": {"label": "Done"}}
    },
])
print("Ítems creados:", results)

# 8) Crear un subítem
subitem = client.create_subitem(
    parent_item_id=987654321,
    subitem_name="Subtarea",
    columns=[{"id": "text", "type": "text", "value": "Detalle"}]
)

# 9) Actualizar columnas
client.update_simple_column_value(
    item_id=987654321,
    board_id=123456789,
    column_id="text_column",
    value="Texto actualizado"
)

client.update_multiple_column_values(
    item_id=987654321,
    board_id=123456789,
    columns=[
        {"id": "status", "type": "status", "value": "Done"},
        {"id": "priority", "type": "dropdown", "value": ["High"]}
    ]
)

# 10) Obtener usuarios
users = client.get_users(limit=10)
print("Usuarios:", len(users))

# 11) Enviar una notificación
client.send_notification(
    user_id=12345,
    target_id=987654321,
    target_type="Post",
    text="Revisa este ítem"
)

# 12) Obtener el tablero padre de un ítem
board_id = client.get_parent_board(item_id=987654321)

# 13) Trabajar con grupos
groups = client.get_groups(board_id=123456789)
for g in groups:
    print(f"{g['id']}: {g['title']}")

new_group = client.create_group(board_id=123456789, group_name="Sprint 1")
print("Grupo creado:", new_group)

client.delete_group(board_id=123456789, group_id="sprint_1")
```

---

## API de `MondayClient`

### `execute_query(query: str, *, return_key: str | None = None, variables: dict | None = None, timeout: float | None = None, log_query_preview: bool = False) -> dict`
Ejecuta una query/mutación GraphQL y devuelve `data` (o `data[return_key]`).

---

### `test_connection() -> bool`
Consulta `me` y devuelve True si la API responde con un usuario válido.

---

### `get_boards(limit: int = 10, page: int = 1, fields: list[str] | str | None = None, workspace_id: int | str | list[int | str] | None = None) -> list[dict]`
Devuelve tableros con paginación simple.
- `fields` por defecto: `["id","name","workspace_id","state","board_kind"]`.
- `workspace_id`: filtra por uno o varios workspaces. Acepta un ID o una lista de IDs. Si es `None`, devuelve tableros de todos los workspaces accesibles.

---

### `get_all_items(board_id: int, limit: int = 50, *, fields: list[str] | str | None = None, columns_ids: list[str] | None = None, subitems: str | None = None, group_id: str | None = None) -> list[dict]`
Devuelve **todos** los ítems de un tablero (o de un grupo concreto), paginando con `cursor`.
- Si `fields` es None, usa `id`, `name` y `column_values { ALL_COLUMNS_FRAGMENT }`.
- Si `columns_ids` se pasa, aplica filtro `ids:[...]` en `column_values`.
- Si `subitems` se usa, añade un bloque GraphQL de subitems a la query.
- Si `group_id` se indica, filtra los ítems al grupo con ese ID; si el grupo no existe devuelve `[]`.
---

### `create_item(board_id: int, item_name: str, *, group_id: str | None = None, columns: list[dict] | dict | None = None, fail_on_duplicate: bool = True, create_labels_if_missing: bool = True, return_fields: list[str] | str | None = None) -> dict`
Crea un ítem.  
- Acepta `columns` en bruto y los normaliza con `create_column_values`.  
- `return_fields`: por defecto `"id"`.

---

### `bulk_create_items(items: list[dict], *, create_labels_if_missing: bool = True, return_fields: list[str] | str | None = None, batch_size: int = 5) -> list[dict]`
Crea múltiples ítems en una o varias mutaciones GraphQL usando aliases.
- Cada dict de `items` requiere `board_id` e `item_name`; acepta además `group_id`, `columns` y `fail_on_duplicate`.
- `columns` admite la misma forma que `create_item` (list[dict] o dict ya renderizado).
- `batch_size` controla cuántos ítems se agrupan por mutación (por defecto 5). Los resultados se devuelven en el mismo orden que la lista de entrada.

---

### `create_subitem(parent_item_id: int, subitem_name: str, *, columns: list[dict] | dict | None = None, fail_on_duplicate: bool = True, create_labels_if_missing: bool = True, return_fields: list[str] | str | None = None) -> dict`
Crea un subítem bajo un ítem padre.  
- Acepta `columns` en bruto o dict ya renderizado.  
- `return_fields`: por defecto `"id"`.

---

### `update_simple_column_value(item_id: int, board_id: int, column_id: str, value: str, *, return_fields: list[str] | str | None = None) -> dict`
Actualiza **una** columna simple.  
- `value` es obligatorio; usa `""` para limpiar.  
- Si la columna espera JSON, pásalo serializado como string (ej: `'{"date":"2025-09-25"}'`).

---

### `update_multiple_column_values(item_id: int, board_id: int, columns: list[dict] | dict, *, fail_on_duplicate: bool = True, create_labels_if_missing: bool = True, return_fields: list[str] | str | None = None) -> dict`
Actualiza **varias columnas** en un único llamado.  
- Normaliza `columns` con `create_column_values`.  
- Internamente hace doble `json.dumps` para `column_values`.  

---

### `get_items_by_column_value(board_id: int, column_id: str, value: str, fields: list[str] | None = None, operator: str = "contains_text", limit: int = 200) -> list[dict]`
Filtra ítems por valor en una columna, con `query_params.rules`.  
- Pagina con `cursor` hasta agotar resultados.  
- Soporta operadores: `any_of`, `not_any_of`, `is_empty`, `contains_text`, `greater_than`, `between`, etc.

---

### `get_item(item_id: int, subitems: str | None = None, columns_ids: list[str] | None = None, get_group: bool = False) -> dict`
Obtiene un ítem por ID.
- Limita columnas si pasas `columns_ids`.
- Obtiene subitems si se le pasa `subitems` (ej: `"subitems { id name }"`).
- Si `get_group=True` se devuelve el id y título del grupo al que pertenece el ítem.

---

### `get_groups(board_id: int | str, *, fields: list[str] | str | None = None) -> list[dict]`
Devuelve los grupos de un tablero.
- `fields` por defecto: `["id", "title"]`.

---

### `create_group(board_id: int | str, group_name: str, *, return_fields: list[str] | str | None = None) -> dict`
Crea un grupo en un tablero.
- `return_fields` por defecto: `"id\ntitle"`.

---

### `delete_group(board_id: int | str, group_id: str) -> bool`
Elimina un grupo de un tablero. Devuelve `True` si se eliminó correctamente.
- Lanza `MondayAPIError` con código `NOT_FOUND` si el grupo no existe en el tablero.

---

### Otras utilidades
- `board_columns(board_id: int | str)`: devuelve columnas de un board (`id`, `title`, `type`).
- `item_columns(item_id: int | str)`: devuelve columnas de un ítem con su metadata (`id`, `title`, `type`).
- `subitems_columns(board_id: int | str)`: columnas de subitems de un board (crea y borra un subitem temporal internamente).
- `delete_item(item_id: int | str) -> bool`: elimina un ítem; devuelve `True` si se eliminó correctamente.
- `create_item_update(item_id: int | str, body: str, mention_user: list[dict] | None = None) -> dict`: crea un update en un ítem.
- `create_column_values(columns: list[dict], *, fail_on_duplicate: bool = True) -> dict`: helper para normalizar `column_values`.
- `get_users(limit: int | None = None, page: int | None = None, fields: list[str] | str | None = None) -> list[dict]`: devuelve usuarios.
- `get_parent_board(item_id: int | str) -> int | str`: devuelve el id del tablero al que pertenece un ítem.
- `send_notification(user_id: int | str, target_id: int | str, target_type: str, text: str) -> str`: envía una notificación al usuario objetivo. `target_type` acepta `"Post"` o `"Project"`.

---

## Manejo de errores

Todos los errores de la librería lanzan `MondayAPIError` con tres atributos:

```python
try:
    client.get_item(item_id=123)
except MondayAPIError as e:
    print(e.error_code)     # "NOT_FOUND", "INVALID_RESPONSE", código HTTP, etc.
    print(e.error_message)  # descripción del error
    print(e.query)          # query GraphQL que lo provocó
```

- **Errores retriables**: HTTP 5xx, 403, 401/404 transitorios, `ComplexityException`.  
- **Errores no retriables**: otros errores GraphQL (ej. `InvalidBoardIdException`).  
- Si se agotan los reintentos → se lanza `MondayAPIError`.

---

## Licencia

**MIT** — ver archivo `LICENSE`.

---

## Enlaces

- PyPI: https://pypi.org/project/cartagon-monday-client/
