/** * El trigger de HubSpot (`serviceConfig.hubspot`, 2026-10-10): qué cambios del * CRM de la cuenta conectada lo disparan. En un solo sitio para el DTO del * api, la pantalla del dashboard y la app de HubSpot (sus suscripciones). * * ## De dónde llegan * * Las suscripciones de webhook de HubSpot son de la APP, no de cada cuenta: * la app de HostWebhook recibe en una sola URL los eventos de TODAS las * cuentas que la instalaron, cada uno con su `portalId`, y el api reparte * cada evento a los triggers activos de esa cuenta. Por eso aquí sólo se * elige QUÉ eventos; la cuenta la dice la credencial. * * ## Las propiedades, fijas * * En HubSpot el «cambió una propiedad» se suscribe propiedad a propiedad, en * el fichero de la app (`webhooks-hsmeta.json`), y cambiarlo es subir otra * versión. Decisión de Ariel (2026-10-10): un conjunto fijo de las comunes * ({@link HUBSPOT_TRIGGER_PROPIEDADES_VIGILADAS}); las personalizadas de cada * cuenta, más adelante. ⚠️ La app tiene que suscribir EXACTAMENTE estas: una * que esté aquí y no allí no llegaría nunca. * * ## El registro entero * * El evento de HubSpot sólo trae el id (y, si cambió una propiedad, su nuevo * valor). El api pide el registro antes de entregarlo, con * {@link HUBSPOT_TRIGGER_PROPIEDADES_DEL_REGISTRO} y las que añada el trigger * (`extraProperties`). De uno borrado sólo queda el id. * * ## Nada viene elegido * * `events` no tiene defecto: `null` (o vacío) = sin contestar, y Activate no * se deja pulsar hasta que haya al menos uno ({@link hubspotTriggerSinContestar}). * * ## Lo que se añadió para terminarlo (2026-10-11, decisiones de Ariel) * * - **Cualquier propiedad** (`watchProperties`): las personalizadas de la * cuenta y las que no están en la lista fija. No caben en el fichero de la * app —son de cada cuenta—, así que van por el «webhooks journal» de * HubSpot: una suscripción por cuenta y objeto que el api crea al activar, * y un sondeo del journal de la app entera. Medido el 2026-10-10: la app * consigue su token de journal. * - **El valor de antes** (`previousValue`) en todo cambio de propiedad: sale * del historial de la propiedad al leer el registro. * - **Conversaciones**: «New incoming message» y «New outgoing message», del * webhook `conversation.newMessage` de la app (`hubEvents`). * - **Formularios**: «Form submitted». HubSpot no tiene webhook de envíos: se * sondea cada 5 minutos y, además, se adelanta cuando un contacto convierte * (cambia su `recent_conversion_date`, suscrita en la app para eso). */ /** El `service` del trigger. */ export declare const HUBSPOT_TRIGGER_SERVICE = "hubspot"; /** El objeto tal como lo nombra el `subscriptionType` de HubSpot. */ export declare const HUBSPOT_TRIGGER_OBJETOS: readonly ["contact", "company", "deal", "ticket"]; export type HubspotTriggerObjeto = (typeof HUBSPOT_TRIGGER_OBJETOS)[number]; /** Los eventos de cada objeto, salvo el cambio de propiedad. */ export declare const HUBSPOT_TRIGGER_ACCIONES: readonly ["creation", "deletion", "merge", "restore", "associationChange"]; /** Lo que vigila el «cambió una propiedad», por objeto, con su nombre en pantalla. */ export declare const HUBSPOT_TRIGGER_PROPIEDADES_VIGILADAS: Readonly>>; /** Las propiedades que trae el registro de cada evento, además de las elegidas. */ export declare const HUBSPOT_TRIGGER_PROPIEDADES_DEL_REGISTRO: Readonly>>; /** El permiso de lectura de la app que cubre los eventos de cada objeto. */ export declare const HUBSPOT_TRIGGER_PERMISO: Readonly>; /** El objeto del CRM (para la API) de cada objeto del trigger. */ export declare const HUBSPOT_TRIGGER_OBJETO_DE_LA_API: Readonly>; export interface HubspotTriggerEventSpec { /** * El evento: el `subscriptionType` de HubSpot (`contact.creation`), o, para * un cambio de propiedad, `.propertyChange:`. */ type: string; label: string; description: string; } /** Los grupos que no son un objeto del CRM. */ export type HubspotTriggerGrupo = HubspotTriggerObjeto | 'conversation' | 'form'; export interface HubspotTriggerEventGroup { objeto: HubspotTriggerGrupo; label: string; permiso: string; events: ReadonlyArray; } /** La clave de un cambio de propiedad. */ export declare function hubspotEventoDePropiedad(objeto: HubspotTriggerObjeto, propiedad: string): string; /** Los dos de un mensaje nuevo: HubSpot manda uno solo, y la dirección se lee del mensaje. */ export declare const HUBSPOT_TRIGGER_MENSAJE_ENTRANTE = "conversation.newMessage:incoming"; export declare const HUBSPOT_TRIGGER_MENSAJE_SALIENTE = "conversation.newMessage:outgoing"; /** El evento de HubSpot detrás de los dos. */ export declare const HUBSPOT_TRIGGER_EVENTO_DE_MENSAJE = "conversation.newMessage"; /** «Form submitted»: no es un webhook de HubSpot, se sondea. */ export declare const HUBSPOT_TRIGGER_FORMULARIO_ENVIADO = "form.submission"; /** * La propiedad que la app vigila para adelantar el sondeo de formularios: * HubSpot la pone al día cada vez que un contacto envía un formulario. No es * un evento que se elija. */ export declare const HUBSPOT_TRIGGER_PROPIEDAD_DE_CONVERSION = "recent_conversion_date"; /** El permiso que cubre cada grupo que no es del CRM. */ export declare const HUBSPOT_TRIGGER_PERMISO_DE_CONVERSACIONES = "conversations.read"; export declare const HUBSPOT_TRIGGER_PERMISO_DE_FORMULARIOS = "forms"; /** Los eventos que se pueden elegir, por objeto y en el orden de la pantalla. */ export declare const HUBSPOT_TRIGGER_EVENT_GROUPS: ReadonlyArray; /** Todos los eventos, en el orden de la pantalla. */ export declare const HUBSPOT_TRIGGER_EVENTS: ReadonlyArray; /** El spec de cada evento, para el nombre en pantalla y los logs. */ export declare const HUBSPOT_TRIGGER_EVENT_BY_TYPE: Readonly>; /** * Las suscripciones que la app de HubSpot tiene que tener, en el formato de * `legacyCrmObjects` de `webhooks-hsmeta.json`. Las cinco acciones de cada * objeto más un `propertyChange` por propiedad vigilada. */ export declare function hubspotSuscripcionesDeLaApp(): Array<{ subscriptionType: string; propertyName?: string; active: true; }>; /** * Las suscripciones de `hubEvents` de `webhooks-hsmeta.json`: los eventos que * no son de un objeto del CRM. Hoy, el mensaje nuevo de una conversación. */ export declare function hubspotEventosDelHubDeLaApp(): Array<{ subscriptionType: string; active: true; }>; /** * La clave de evento del trigger para un evento que mandó HubSpot, o `null` * si no es de los que se pueden elegir (un objeto o una propiedad que no * vigilamos). */ export declare function hubspotClaveDelEvento(ev: { subscriptionType?: unknown; propertyName?: unknown; }): string | null; export interface HubspotTriggerConfig { /** Sin defecto: `null` o vacío = sin contestar. */ events: string[] | null; /** Más propiedades que traer en el registro, por objeto. */ extraProperties?: Partial> | null; /** * Más propiedades que VIGILAR, por objeto: las personalizadas de la cuenta * o cualquiera que no esté en {@link HUBSPOT_TRIGGER_PROPIEDADES_VIGILADAS}. * Llegan por el journal de HubSpot, con la misma forma que las fijas. */ watchProperties?: Partial> | null; /** Los formularios de «Form submitted», por su id. */ forms?: string[] | null; } /** Lo más de propiedades extra por objeto. */ export declare const HUBSPOT_TRIGGER_EXTRA_MAXIMO = 50; /** Lo más de propiedades vigiladas de más por objeto. */ export declare const HUBSPOT_TRIGGER_VIGILADAS_MAXIMO = 25; /** Lo más de formularios por trigger. */ export declare const HUBSPOT_TRIGGER_FORMULARIOS_MAXIMO = 10; /** * Las propiedades vigiladas de más de un trigger, por objeto: sin nombres * raros, sin las fijas (ésas ya llegan por el webhook) y sin repetidas. */ export declare function hubspotPropiedadesVigiladasDeMas(cfg: Partial | null | undefined): Partial>; /** Los formularios elegidos, sin ids raros ni repetidos. */ export declare function hubspotFormulariosDelTrigger(cfg: Partial | null | undefined): string[]; /** * Lo que falta por contestar antes de activar. Vacío = se puede activar. Un * evento que no está en la lista no cuenta como contestado: no llegaría nunca. * Una propiedad vigilada de más cuenta como evento. «Form submitted» sin * formularios elegidos no se contesta. */ export declare function hubspotTriggerSinContestar(cfg: Partial | null | undefined): string[];