Skip to content

Paquete Compartido @repo/shared-types

Definir contratos canónicos de dominio, auth y API para evitar drift entre apps.

  • auth.ts
  • api.ts
  • domain.ts
  • dashboard.ts
  • agenda.ts
  • cartera.ts
  • catalog.ts
  • interactions.ts
  • campaigns.ts
  • kanban.ts
  • chats-unassigned.ts
  • mobile-auth.ts
  • custom-fields.ts
  • index.ts
  • Todos los módulos CRM priorizados (dashboard, agenda, campañas, chats sin asignar, interacciones, kanban) consumen contratos desde este paquete.
  • PaginatedResponse<T> se mantiene por compatibilidad con consumidores actuales de web.
  • Se evita volver a declarar tipos de dominio en apps/web/app/types o en pantallas de apps/native.
  • auth.ts es el contrato canónico de acceso BoostAPI para web y mobile.
  • mobile-auth.ts debe mantenerse alineado a auth.ts y reutilizar sus tipos, no duplicarlos.
  • BoostAuthUser incluye roleName, roleSource, IDs de rol y permissions; eso permite persistir el mismo payload normalizado en ambas apps.
  • roleName es la normalización camelCase de role_name, que sigue viniendo de BoostAPI como slug estable.
  • mobile-auth.ts ya no debe inventar una variante más pobre del contrato; debe reexportar o extender el shape canónico de auth.ts.
  • CarteraItem incluye groupId para preservar la relación operativa con BoostAPI incluso si la UI renderiza por lead/cliente.
  • CarteraAssignSellerInput usa groupIds: string[] y no leadIds.
  • CarteraAssignSellerResult devuelve:
    • assignedGroupIds
    • skippedGroupIds
  • cartera.ts también define ahora el contrato oficial de contacto para el detalle:
    • CarteraContact
    • CarteraContactChannel
    • CarteraUpdateContactInput
  • CarteraContact incluye también:
    • hasCustomFieldValues
    • customFieldValuesCount
  • cartera.ts también define ahora el contrato de la pestaña Facturas:
    • CarteraInvoice
    • CarteraGroupInvoicesPage
    • CarteraGroupInvoiceDetailResponse
    • CarteraInvoiceDetailLine
    • CarteraInvoicesSettings
    • CarteraInvoicesEmptyState
  • Esos campos existen para que web y native no tengan que adivinar si un contacto necesita cargar extras record_type = contact.
  • En facturas, el contrato compartido preserva:
    • lotes paginados por día
    • invoiceNumber para la columna principal de 3 líneas
    • invoiceUrl como dato de referencia devuelto por backend
    • un segundo contrato de drawer por invoiceId, para cargar líneas solo cuando el usuario abre el detalle
    • campos raw + normalizados en cada línea del drawer, para que web/native usen code/name/trackingName/expirationLabel sin perder compatibilidad con el backend actual
    • beneficiaryNames como array para soportar render simple o burbuja multi-valor sin reinventar mapeos por plataforma
  • Ese contrato existe para reflejar el dominio real groups -> leads -> contacts sin depender del bloque legacy Contactos.
  • Esa forma es intencional para alinear web y native con la regla de negocio actual:
    • la mutación de asignación desde cartera es por grupo
    • la propagación a leads/contactos la resuelve backend
  • Si una pantalla permite multi-selección de filas de cartera, debe transformar esos rows a groupIds únicos antes de llamar la mutación.
  • Ningún consumidor debe reintroducir una variante local basada en leadIds, porque eso rompe la semántica compartida entre apps.
  • custom-fields.ts define los contratos compartidos para:
    • estructura (CustomFieldType, CustomFieldGroup, CustomField, CustomFieldOption)
    • valores reales (CustomFieldValue, UpsertCustomFieldValueInput, UpsertGroupCustomFieldValuesInput, UpsertContactCustomFieldValuesInput)
    • catálogos (CurrencyCatalogOption, DepartmentCatalogOption, MunicipalityCatalogOption)
    • media firmada (CustomFieldMediaUploadInput, CustomFieldMediaUploadResult, CustomFieldMediaDownloadInput, CustomFieldMediaDownloadResult)
  • El detalle de cartera usa esos tipos para renderizar Informacion personalizada del cliente con campos dinámicos reales de BoostAPI.
  • CustomFieldGroup y CustomField.group ya incluyen record_type; eso permite separar en frontend:
    • secciones de group
    • secciones de contact
  • CustomFieldValue.record_type ya contempla group, lead y contact, y cartera detalle ya usa tanto group como contact.
  • client no se modela como record_type aparte dentro del paquete; la semántica compartida sigue siendo lead con zauru_id.
  • CustomField.settings sigue tipado como Record<string, unknown> | null a propósito para no romper compatibilidad cuando backend agrega keys nuevas por fase.
  • Bajo ese criterio, el paquete ya puede transportar sin cambios estructurales:
    • readonly
    • override_permission_code
    • contexts
  • Regla futura para consumidores:
    • podrán leer settings.readonly para bloquear edición
    • no deberán asumir que contexts ya filtra pantallas en backend; por ahora solo es preparación de contrato
  • Para media (image, video, pdf), el valor persistido se modela con:
    • value_text = object_key
    • value_json = metadata del archivo
  • Para media optimizada, custom-fields.ts también preserva el contrato explícito de render:
    • render_state
    • current_asset
    • active_upload
    • has_persisted_asset
  • Los consumidores deben respetar settings.depends_on_custom_field_id para campos municipality y limpiar/revalidar el valor dependiente cuando cambie el department.