Contrato GraphQL
packages/graphql-contract/schema.graphql — 133 tipos, 38 consultas,
74 mutaciones, 4 suscripciones.
Es la frontera, no una consecuencia
El contrato se escribió antes que el servidor y que los clientes. Eso permitió construir backend, web y móvil en paralelo sin esperarse, y obliga a que la API se diseñe pensando en quien la consume y no en cómo está guardado el dato.
El servidor lo implementa; los clientes generan sus tipos desde él. Si algo no está en el contrato, no existe.
Convenciones
- Enums en
SCREAMING_SNAKE, réplica de los de la base. - Duraciones en la unidad que declara su nombre (
...Minutes,...Hours) y siempre en tiempo hábil. - Paginación por desplazamiento (
page/pageSize, máximo 200). Lo que necesitan la tabla de escritorio y el scroll infinito del móvil, sin el coste de mantener cursores. Decimalviaja como cadena. Los importes no pasan porf64ni por elnumberde JavaScript.
Verificación de que servidor y contrato coinciden
crm-api export-schema packages/graphql-contract/schema.generated.graphql
Y comparar. Hoy: 133 tipos, cero diferencias de campos.
Campos que se añadieron al construir las interfaces
Nueve, todos aditivos. Son los huecos que sólo se ven cuando alguien intenta usar la API de verdad:
| Campo | Por qué faltaba |
|---|---|
Campaign.attributionDays | Se aceptaba al crear pero no se devolvía: editar una campaña le cambiaba silenciosamente la ventana de atribución |
ProductPerformanceRow.customerCount | Estaba en un tipo hermano y no en la fila del ranking |
CustomerAssetInput.isActive, deleteCustomerAsset | No había forma de dar de baja una máquina sin perder su historial |
ProductSort, WarrantySort, PartRequestSort | Tres listados sin ordenación |
FollowupResultInput.latitude/longitude | Cerrar una visita con ubicación exigía dos llamadas sin atomicidad |
assignableUsers | Un asesor no podía listar compañeros para reasignar un ticket |
unreadConversationCount | El móvil traía una página entera para leer un número |