import { z } from 'zod' import type { UnknownMessage } from '../types/index.ts' import './utils/validate.ts' import type { WebhookTypes } from '../types/webhook.ts' export const contactsSchema = z.object({ identity: z.string().identity(), name: z.string().optional(), group: z.string().optional(), city: z.string().optional(), email: z.string().optional(), phoneNumber: z.string().optional(), source: z.string().optional(), taxDocument: z.string().optional(), extras: z.record(z.string(), z.string().or(z.null())).optional(), }) export const messagesSchema = z .object({ id: z.string(), type: z.string(), from: z.string().identity(), to: z.string().identity(), pp: z.string().identity().optional(), content: z.unknown(), metadata: z.record(z.string(), z.string().or(z.null())).optional(), }) .transform( (message) => message as UnknownMessage & { from: NonNullable to: NonNullable }, ) export const eventtrackingsSchema = z.object({ identity: z.string().identity().optional(), messageId: z.string().optional(), category: z.string(), action: z.string(), extras: z.record(z.string(), z.string().or(z.null())).optional(), }) // TODO: add support for ticket once it's released // https://help.blip.ai/hc/pt-br/articles/29187147295767-Formato-dos-envios-no-webhook // The order is important here. We must try to parse more specific types first. // e.g., if contact came before event, no event would be ever caught as such export const blipWebhookSchema = eventtrackingsSchema.or(messagesSchema).or(contactsSchema) export const isWebhookType = (type: T, data: unknown): data is WebhookTypes[T] => { switch (type) { case 'contacts': return !eventtrackingsSchema.safeParse(data).success && contactsSchema.safeParse(data).success case 'messages': return messagesSchema.safeParse(data).success case 'eventtrackings': return eventtrackingsSchema.safeParse(data).success default: return false } }