@adatechnology/meta-whatsapp-contracts 0.2.0-rc.0 → 0.2.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +67 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +254 -1740
- package/dist/index.d.ts +254 -1740
- package/dist/index.js +59 -2
- package/dist/index.js.map +1 -1
- package/dist/testing/index.cjs +170 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +74 -0
- package/dist/testing/index.d.ts +74 -0
- package/dist/testing/index.js +137 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/webhook.types-PxhpmpzC.d.cts +1678 -0
- package/dist/webhook.types-PxhpmpzC.d.ts +1678 -0
- package/package.json +17 -1
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -20,20 +21,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
21
|
// src/index.ts
|
|
21
22
|
var index_exports = {};
|
|
22
23
|
__export(index_exports, {
|
|
24
|
+
AudioNotIngestedError: () => AudioNotIngestedError,
|
|
23
25
|
CROSS_FLOW_PREFIX: () => CROSS_FLOW_PREFIX,
|
|
24
26
|
ConfigMissingError: () => ConfigMissingError,
|
|
25
27
|
DuplicateWebhookDeliveryError: () => DuplicateWebhookDeliveryError,
|
|
28
|
+
FLOW_ACTION_KIND: () => FLOW_ACTION_KIND,
|
|
26
29
|
InvalidWebhookSignatureError: () => InvalidWebhookSignatureError,
|
|
27
30
|
META_WHATSAPP_ERROR_CODES: () => META_WHATSAPP_ERROR_CODES,
|
|
31
|
+
MessageNotAudioError: () => MessageNotAudioError,
|
|
28
32
|
MetaWhatsAppError: () => MetaWhatsAppError,
|
|
33
|
+
PREVIEW_MEDIA_ID_PREFIX: () => PREVIEW_MEDIA_ID_PREFIX,
|
|
29
34
|
SessionNotFoundError: () => SessionNotFoundError,
|
|
30
35
|
TemplateNotConfiguredError: () => TemplateNotConfiguredError,
|
|
36
|
+
TranscriptionDisabledError: () => TranscriptionDisabledError,
|
|
31
37
|
WindowExpiredError: () => WindowExpiredError,
|
|
32
38
|
crossFlowKey: () => crossFlowKey,
|
|
33
39
|
flowGraphNodesSchema: () => flowGraphNodesSchema,
|
|
34
40
|
flowNodeDataSchema: () => flowNodeDataSchema,
|
|
35
41
|
flowNodeNextSchema: () => flowNodeNextSchema,
|
|
36
42
|
isCrossFlowTarget: () => isCrossFlowTarget,
|
|
43
|
+
resolvePreviewUploadId: () => resolvePreviewUploadId,
|
|
44
|
+
toPreviewMediaId: () => toPreviewMediaId,
|
|
37
45
|
whatsAppInteractiveSchema: () => whatsAppInteractiveSchema,
|
|
38
46
|
whatsAppMediaSchema: () => whatsAppMediaSchema,
|
|
39
47
|
whatsAppMessageEchoSchema: () => whatsAppMessageEchoSchema,
|
|
@@ -140,6 +148,12 @@ var whatsAppWebhookPayloadSchema = import_zod.z.object({
|
|
|
140
148
|
|
|
141
149
|
// src/flow.types.ts
|
|
142
150
|
var import_zod2 = require("zod");
|
|
151
|
+
var FLOW_ACTION_KIND = {
|
|
152
|
+
HANDOFF: "handoff",
|
|
153
|
+
RATE_LIMITED_HANDOFF: "rate_limited_handoff",
|
|
154
|
+
SEND_PRODUCT_LIST: "send_product_list",
|
|
155
|
+
SEND_MEDIA: "send_media"
|
|
156
|
+
};
|
|
143
157
|
var CROSS_FLOW_PREFIX = "flow:";
|
|
144
158
|
var isCrossFlowTarget = /* @__PURE__ */ __name((target) => target.startsWith(CROSS_FLOW_PREFIX), "isCrossFlowTarget");
|
|
145
159
|
var crossFlowKey = /* @__PURE__ */ __name((target) => target.slice(CROSS_FLOW_PREFIX.length), "crossFlowKey");
|
|
@@ -174,7 +188,7 @@ var flowNodeDataSchema = import_zod2.z.object({
|
|
|
174
188
|
import_zod2.z.string()
|
|
175
189
|
])).optional(),
|
|
176
190
|
actionKind: import_zod2.z.string().optional(),
|
|
177
|
-
|
|
191
|
+
actionParams: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
|
|
178
192
|
directMessage: import_zod2.z.string().optional(),
|
|
179
193
|
fallbackMessage: import_zod2.z.string().optional(),
|
|
180
194
|
conditionContextKey: import_zod2.z.string().optional(),
|
|
@@ -215,7 +229,10 @@ var META_WHATSAPP_ERROR_CODES = {
|
|
|
215
229
|
DUPLICATE_DELIVERY: "META_WHATSAPP_DUPLICATE_DELIVERY",
|
|
216
230
|
CONFIG_MISSING: "META_WHATSAPP_CONFIG_MISSING",
|
|
217
231
|
TEMPLATE_NOT_CONFIGURED: "META_WHATSAPP_TEMPLATE_NOT_CONFIGURED",
|
|
218
|
-
SESSION_NOT_FOUND: "META_WHATSAPP_SESSION_NOT_FOUND"
|
|
232
|
+
SESSION_NOT_FOUND: "META_WHATSAPP_SESSION_NOT_FOUND",
|
|
233
|
+
AUDIO_NOT_INGESTED: "META_WHATSAPP_AUDIO_NOT_INGESTED",
|
|
234
|
+
MESSAGE_NOT_AUDIO: "META_WHATSAPP_MESSAGE_NOT_AUDIO",
|
|
235
|
+
TRANSCRIPTION_DISABLED: "META_WHATSAPP_TRANSCRIPTION_DISABLED"
|
|
219
236
|
};
|
|
220
237
|
var WindowExpiredError = class extends MetaWhatsAppError {
|
|
221
238
|
static {
|
|
@@ -274,22 +291,70 @@ var SessionNotFoundError = class extends MetaWhatsAppError {
|
|
|
274
291
|
});
|
|
275
292
|
}
|
|
276
293
|
};
|
|
294
|
+
var AudioNotIngestedError = class extends MetaWhatsAppError {
|
|
295
|
+
static {
|
|
296
|
+
__name(this, "AudioNotIngestedError");
|
|
297
|
+
}
|
|
298
|
+
constructor(messageId) {
|
|
299
|
+
super("\xC1udio ainda est\xE1 sendo copiado \u2014 tente novamente em alguns segundos.", 409, META_WHATSAPP_ERROR_CODES.AUDIO_NOT_INGESTED, {
|
|
300
|
+
messageId
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
var TranscriptionDisabledError = class extends MetaWhatsAppError {
|
|
305
|
+
static {
|
|
306
|
+
__name(this, "TranscriptionDisabledError");
|
|
307
|
+
}
|
|
308
|
+
constructor() {
|
|
309
|
+
super("Transcri\xE7\xE3o de \xE1udio est\xE1 desligada para esta empresa.", 409, META_WHATSAPP_ERROR_CODES.TRANSCRIPTION_DISABLED);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
var MessageNotAudioError = class extends MetaWhatsAppError {
|
|
313
|
+
static {
|
|
314
|
+
__name(this, "MessageNotAudioError");
|
|
315
|
+
}
|
|
316
|
+
constructor(messageId, type) {
|
|
317
|
+
super(`Mensagem ${messageId} \xE9 do tipo "${type}" \u2014 s\xF3 \xE1udio \xE9 transcrito.`, 422, META_WHATSAPP_ERROR_CODES.MESSAGE_NOT_AUDIO, {
|
|
318
|
+
messageId,
|
|
319
|
+
type
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
// src/previewMedia.types.ts
|
|
325
|
+
var PREVIEW_MEDIA_ID_PREFIX = "preview-upload:";
|
|
326
|
+
function toPreviewMediaId(uploadId) {
|
|
327
|
+
return `${PREVIEW_MEDIA_ID_PREFIX}${uploadId}`;
|
|
328
|
+
}
|
|
329
|
+
__name(toPreviewMediaId, "toPreviewMediaId");
|
|
330
|
+
function resolvePreviewUploadId(mediaId) {
|
|
331
|
+
if (!mediaId.startsWith(PREVIEW_MEDIA_ID_PREFIX)) return void 0;
|
|
332
|
+
return mediaId.slice(PREVIEW_MEDIA_ID_PREFIX.length) || void 0;
|
|
333
|
+
}
|
|
334
|
+
__name(resolvePreviewUploadId, "resolvePreviewUploadId");
|
|
277
335
|
// Annotate the CommonJS export names for ESM import in node:
|
|
278
336
|
0 && (module.exports = {
|
|
337
|
+
AudioNotIngestedError,
|
|
279
338
|
CROSS_FLOW_PREFIX,
|
|
280
339
|
ConfigMissingError,
|
|
281
340
|
DuplicateWebhookDeliveryError,
|
|
341
|
+
FLOW_ACTION_KIND,
|
|
282
342
|
InvalidWebhookSignatureError,
|
|
283
343
|
META_WHATSAPP_ERROR_CODES,
|
|
344
|
+
MessageNotAudioError,
|
|
284
345
|
MetaWhatsAppError,
|
|
346
|
+
PREVIEW_MEDIA_ID_PREFIX,
|
|
285
347
|
SessionNotFoundError,
|
|
286
348
|
TemplateNotConfiguredError,
|
|
349
|
+
TranscriptionDisabledError,
|
|
287
350
|
WindowExpiredError,
|
|
288
351
|
crossFlowKey,
|
|
289
352
|
flowGraphNodesSchema,
|
|
290
353
|
flowNodeDataSchema,
|
|
291
354
|
flowNodeNextSchema,
|
|
292
355
|
isCrossFlowTarget,
|
|
356
|
+
resolvePreviewUploadId,
|
|
357
|
+
toPreviewMediaId,
|
|
293
358
|
whatsAppInteractiveSchema,
|
|
294
359
|
whatsAppMediaSchema,
|
|
295
360
|
whatsAppMessageEchoSchema,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/webhook.types.ts","../src/flow.types.ts","../src/errors.ts"],"sourcesContent":["export {\n whatsAppMediaSchema,\n whatsAppInteractiveSchema,\n whatsAppOrderSchema,\n whatsAppMessageSchema,\n whatsAppMessageEchoSchema,\n whatsAppMessageStatusSchema,\n whatsAppStatusSchema,\n whatsAppWebhookPayloadSchema,\n} from './webhook.types'\nexport type {\n WhatsAppMedia,\n WhatsAppInteractive,\n WhatsAppOrder,\n WhatsAppMessage,\n WhatsAppMessageEcho,\n WhatsAppMessageStatusValue,\n WhatsAppStatus,\n WhatsAppWebhookPayload,\n} from './webhook.types'\n\nexport type {\n SessionState,\n SessionMode,\n MessageDirection,\n MessageSender,\n MessageStatus,\n ConversationSession,\n ConversationMessage,\n ConversationSummary,\n ListConversationsParams,\n ListMessagesParams,\n} from './conversation.types'\n\nexport {\n CROSS_FLOW_PREFIX,\n isCrossFlowTarget,\n crossFlowKey,\n flowNodeNextSchema,\n flowNodeDataSchema,\n flowGraphNodesSchema,\n} from './flow.types'\nexport type {\n FlowNodeType,\n FlowQuestionType,\n FlowActionKind,\n FlowConditionOperator,\n FlowNodeNext,\n FlowNodeData,\n FlowGraphData,\n FlowGraphSummary,\n LiveFlowPosition,\n} from './flow.types'\n\nexport type {\n WhatsAppSettings,\n TemplateVariablesMap,\n TemplateConfig,\n WhatsAppTemplateSummary,\n CreateTemplateResult,\n} from './settings.types'\n\nexport type { MetaWhatsAppHooks, MessageHookOutcome } from './events'\n\nexport type {\n ChannelAdapterInterface,\n SubjectResolverInterface,\n CatalogProduct,\n CatalogPort,\n ObjectStorageInterface,\n RealtimeNotifierInterface,\n FlowActionHandler,\n FlowActionResult,\n FlowActionRegistry,\n} from './providers'\n\nexport {\n MetaWhatsAppError,\n META_WHATSAPP_ERROR_CODES,\n WindowExpiredError,\n InvalidWebhookSignatureError,\n DuplicateWebhookDeliveryError,\n ConfigMissingError,\n TemplateNotConfiguredError,\n SessionNotFoundError,\n} from './errors'\n","import { z } from 'zod'\n\n// Extraído de financiamento-imobiliario-bot/apps/api/src/modules/webhook/application/use-cases/\n// ReceiveWhatsAppWebhook.use-case.ts:39-113 — shape real do payload da Cloud API da Meta.\n\nexport const whatsAppMediaSchema = z.object({\n id: z.string(),\n mime_type: z.string(),\n sha256: z.string().optional(),\n caption: z.string().optional(),\n filename: z.string().optional(),\n})\nexport type WhatsAppMedia = z.infer<typeof whatsAppMediaSchema>\n\nexport const whatsAppInteractiveSchema = z.object({\n type: z.string(),\n button_reply: z.object({ id: z.string(), title: z.string() }).optional(),\n list_reply: z.object({ id: z.string(), title: z.string() }).optional(),\n})\nexport type WhatsAppInteractive = z.infer<typeof whatsAppInteractiveSchema>\n\nexport const whatsAppOrderSchema = z.object({\n catalog_id: z.string(),\n text: z.string().optional(),\n product_items: z.array(\n z.object({\n product_retailer_id: z.string(),\n quantity: z.number(),\n item_price: z.number(),\n currency: z.string(),\n }),\n ),\n})\nexport type WhatsAppOrder = z.infer<typeof whatsAppOrderSchema>\n\nexport const whatsAppMessageSchema = z.object({\n id: z.string(),\n from: z.string(),\n type: z.string(),\n text: z.object({ body: z.string() }).optional(),\n image: whatsAppMediaSchema.optional(),\n audio: whatsAppMediaSchema.optional(),\n video: whatsAppMediaSchema.optional(),\n document: whatsAppMediaSchema.optional(),\n sticker: whatsAppMediaSchema.optional(),\n interactive: whatsAppInteractiveSchema.optional(),\n // Pedido enviado pelo carrinho do catálogo (WhatsApp Commerce)\n order: whatsAppOrderSchema.optional(),\n // Presente quando o cliente abre um item do catálogo e manda mensagem pela página do produto\n context: z\n .object({\n from: z.string().optional(),\n id: z.string().optional(),\n referred_product: z.object({ catalog_id: z.string(), product_retailer_id: z.string() }).optional(),\n })\n .optional(),\n timestamp: z.string(),\n})\nexport type WhatsAppMessage = z.infer<typeof whatsAppMessageSchema>\n\nexport const whatsAppMessageEchoSchema = z.object({\n id: z.string(),\n from: z.string(),\n timestamp: z.string(),\n type: z.string(),\n})\nexport type WhatsAppMessageEcho = z.infer<typeof whatsAppMessageEchoSchema>\n\nexport const whatsAppMessageStatusSchema = z.enum(['sent', 'delivered', 'read', 'failed'])\nexport type WhatsAppMessageStatusValue = z.infer<typeof whatsAppMessageStatusSchema>\n\nexport const whatsAppStatusSchema = z.object({\n id: z.string(),\n status: whatsAppMessageStatusSchema,\n timestamp: z.string(),\n recipient_id: z.string().optional(),\n})\nexport type WhatsAppStatus = z.infer<typeof whatsAppStatusSchema>\n\nexport const whatsAppWebhookPayloadSchema = z.object({\n object: z.string(),\n entry: z.array(\n z.object({\n id: z.string(),\n changes: z.array(\n z.object({\n value: z.object({\n messaging_product: z.string(),\n messages: z.array(whatsAppMessageSchema).optional(),\n message_echoes: z.array(whatsAppMessageEchoSchema).optional(),\n statuses: z.array(whatsAppStatusSchema).optional(),\n metadata: z.object({ display_phone_number: z.string(), phone_number_id: z.string() }).optional(),\n }),\n }),\n ),\n }),\n ),\n})\nexport type WhatsAppWebhookPayload = z.infer<typeof whatsAppWebhookPayloadSchema>\n","// Mesmo shape de dados do editor visual (@adatechnology/conversations-ui/flows) — o backend\n// interpreta/persiste o grafo, o frontend edita; os dois lados precisam concordar no formato.\n// `FlowActionKind` é string aberta (não union fechada): o host registra os próprios actions\n// (ex.: 'trigger_simulation' no bot) via registerFlowAction() no módulo (T4.3) — o pacote nunca\n// assume nenhum caso de negócio específico.\nimport { z } from 'zod'\n\nexport type FlowNodeType = 'question' | 'entrada_choice' | 'action' | 'menu' | 'condition'\nexport type FlowQuestionType = 'text' | 'money' | 'date' | 'int' | 'cpf' | 'choice'\nexport type FlowActionKind = string\nexport type FlowConditionOperator = '>' | '>=' | '<' | '<=' | '==' | '!=' | 'contains'\nexport type FlowNodeNext = string | { byAnswer: Record<string, string>; default: string }\n\n// Destinos \"flow:<key>\" são saltos para outro fluxo — mesma convenção usada pelo editor visual\n// (conversations-ui/flows/flowGraph.ts); backend e frontend precisam concordar no formato.\nexport const CROSS_FLOW_PREFIX = 'flow:'\nexport const isCrossFlowTarget = (target: string): boolean => target.startsWith(CROSS_FLOW_PREFIX)\nexport const crossFlowKey = (target: string): string => target.slice(CROSS_FLOW_PREFIX.length)\n\nexport type FlowNodeData = {\n id: string\n type: FlowNodeType\n contextKey?: string\n questionType?: FlowQuestionType\n question?: string\n options?: [string, string][]\n actionKind?: FlowActionKind\n simulationTemplate?: Record<string, string>\n directMessage?: string\n fallbackMessage?: string\n conditionContextKey?: string\n conditionOperator?: FlowConditionOperator\n conditionValue?: string\n position?: { x: number; y: number }\n next?: FlowNodeNext\n}\n\nexport interface FlowGraphData {\n key: string\n label: string\n startNodeId: string\n version: number\n nodes: Record<string, FlowNodeData>\n}\n\nexport interface FlowGraphSummary {\n key: string\n label: string\n nodeCount: number\n showInMenu: boolean\n menuOptionLabel?: string\n updatedAt: string\n}\n\n// Retorno de GetLiveFlowPositions (T4.2) — quantas sessões ativas estão em cada nó agora,\n// usado pelo editor para desenhar o \"liveCount\" nos cards (FlowNodeCardData.liveCount).\nexport interface LiveFlowPosition {\n flowKey: string\n nodeId: string\n count: number\n}\n\n// Validação de runtime do grafo. O `nodes` é um jsonb que entrou pelo editor (dado de origem\n// cliente) e sai do banco como `unknown` — sem parse, um grafo malformado só se manifestaria\n// como comportamento estranho lá dentro do interpretador, longe da causa.\n//\n// Permissivo de propósito em dois pontos: `actionKind` é string aberta (o host registra os\n// seus) e `.passthrough()` deixa passar campos extras — um grafo salvo por uma versão mais nova\n// do editor não pode ficar irrecuperável numa versão mais antiga do módulo.\nexport const flowNodeNextSchema = z.union([\n z.string(),\n z.object({ byAnswer: z.record(z.string(), z.string()), default: z.string() }),\n])\n\nexport const flowNodeDataSchema = z\n .object({\n id: z.string(),\n type: z.enum(['question', 'entrada_choice', 'action', 'menu', 'condition']),\n contextKey: z.string().optional(),\n questionType: z.enum(['text', 'money', 'date', 'int', 'cpf', 'choice']).optional(),\n question: z.string().optional(),\n options: z.array(z.tuple([z.string(), z.string()])).optional(),\n actionKind: z.string().optional(),\n simulationTemplate: z.record(z.string(), z.string()).optional(),\n directMessage: z.string().optional(),\n fallbackMessage: z.string().optional(),\n conditionContextKey: z.string().optional(),\n conditionOperator: z.enum(['>', '>=', '<', '<=', '==', '!=', 'contains']).optional(),\n conditionValue: z.string().optional(),\n position: z.object({ x: z.number(), y: z.number() }).optional(),\n next: flowNodeNextSchema.optional(),\n })\n .passthrough()\n\nexport const flowGraphNodesSchema = z.record(z.string(), flowNodeDataSchema)\n","// Hierarquia de erros do módulo — não depende do framework de erros do host (nenhum DomainError\n// importado); o host mapeia estes para o seu próprio formato de resposta no exception filter.\nexport class MetaWhatsAppError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly code: string,\n public readonly details?: Record<string, unknown>,\n ) {\n super(message)\n this.name = 'MetaWhatsAppError'\n }\n}\n\nexport const META_WHATSAPP_ERROR_CODES = {\n WINDOW_EXPIRED: 'META_WHATSAPP_WINDOW_EXPIRED',\n INVALID_SIGNATURE: 'META_WHATSAPP_INVALID_SIGNATURE',\n DUPLICATE_DELIVERY: 'META_WHATSAPP_DUPLICATE_DELIVERY',\n CONFIG_MISSING: 'META_WHATSAPP_CONFIG_MISSING',\n TEMPLATE_NOT_CONFIGURED: 'META_WHATSAPP_TEMPLATE_NOT_CONFIGURED',\n SESSION_NOT_FOUND: 'META_WHATSAPP_SESSION_NOT_FOUND',\n} as const\n\nexport class WindowExpiredError extends MetaWhatsAppError {\n constructor(public readonly hoursSinceLastMessage?: number) {\n super(\n 'Janela de 24h expirada — não é possível enviar mensagem para este contato fora de template.',\n 400,\n META_WHATSAPP_ERROR_CODES.WINDOW_EXPIRED,\n { hoursSinceLastMessage },\n )\n }\n}\n\n// Assinatura HMAC do webhook não confere — Meta ou um terceiro tentando forjar uma entrega.\nexport class InvalidWebhookSignatureError extends MetaWhatsAppError {\n constructor() {\n super('Assinatura do webhook inválida.', 401, META_WHATSAPP_ERROR_CODES.INVALID_SIGNATURE)\n }\n}\n\n// Meta reenviou uma entrega dentro da janela de replay (nonce já visto) — não é erro do\n// cliente, é comportamento esperado da Cloud API; o host deve responder 200 e ignorar.\nexport class DuplicateWebhookDeliveryError extends MetaWhatsAppError {\n constructor(nonce: string) {\n super('Entrega de webhook duplicada.', 409, META_WHATSAPP_ERROR_CODES.DUPLICATE_DELIVERY, { nonce })\n }\n}\n\nexport class ConfigMissingError extends MetaWhatsAppError {\n constructor(missingField: string) {\n super(`Configuração do WhatsApp ausente: ${missingField}.`, 503, META_WHATSAPP_ERROR_CODES.CONFIG_MISSING, {\n missingField,\n })\n }\n}\n\nexport class TemplateNotConfiguredError extends MetaWhatsAppError {\n constructor() {\n super(\n 'Nenhum template de WhatsApp configurado para reabertura de janela.',\n 503,\n META_WHATSAPP_ERROR_CODES.TEMPLATE_NOT_CONFIGURED,\n )\n }\n}\n\nexport class SessionNotFoundError extends MetaWhatsAppError {\n constructor(whatsappNumber: string) {\n super(\n `Sessão de conversa não encontrada para ${whatsappNumber}.`,\n 404,\n META_WHATSAPP_ERROR_CODES.SESSION_NOT_FOUND,\n { whatsappNumber },\n )\n }\n}\n"],"mappings":"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","names":["whatsAppMediaSchema","z","object","id","string","mime_type","sha256","optional","caption","filename","whatsAppInteractiveSchema","type","button_reply","title","list_reply","whatsAppOrderSchema","catalog_id","text","product_items","array","product_retailer_id","quantity","number","item_price","currency","whatsAppMessageSchema","from","body","image","audio","video","document","sticker","interactive","order","context","referred_product","timestamp","whatsAppMessageEchoSchema","whatsAppMessageStatusSchema","enum","whatsAppStatusSchema","status","recipient_id","whatsAppWebhookPayloadSchema","entry","changes","value","messaging_product","messages","message_echoes","statuses","metadata","display_phone_number","phone_number_id","import_zod","CROSS_FLOW_PREFIX","isCrossFlowTarget","target","startsWith","crossFlowKey","slice","length","flowNodeNextSchema","z","union","string","object","byAnswer","record","default","flowNodeDataSchema","id","type","enum","contextKey","optional","questionType","question","options","array","tuple","actionKind","simulationTemplate","directMessage","fallbackMessage","conditionContextKey","conditionOperator","conditionValue","position","x","number","y","next","passthrough","flowGraphNodesSchema","MetaWhatsAppError","Error","message","statusCode","code","details","name","META_WHATSAPP_ERROR_CODES","WINDOW_EXPIRED","INVALID_SIGNATURE","DUPLICATE_DELIVERY","CONFIG_MISSING","TEMPLATE_NOT_CONFIGURED","SESSION_NOT_FOUND","WindowExpiredError","hoursSinceLastMessage","InvalidWebhookSignatureError","DuplicateWebhookDeliveryError","nonce","ConfigMissingError","missingField","TemplateNotConfiguredError","SessionNotFoundError","whatsappNumber"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/webhook.types.ts","../src/flow.types.ts","../src/errors.ts","../src/previewMedia.types.ts"],"sourcesContent":["export {\n whatsAppMediaSchema,\n whatsAppInteractiveSchema,\n whatsAppOrderSchema,\n whatsAppMessageSchema,\n whatsAppMessageEchoSchema,\n whatsAppMessageStatusSchema,\n whatsAppStatusSchema,\n whatsAppWebhookPayloadSchema,\n} from './webhook.types'\nexport type {\n WhatsAppMedia,\n WhatsAppInteractive,\n WhatsAppOrder,\n WhatsAppMessage,\n WhatsAppMessageEcho,\n WhatsAppMessageStatusValue,\n WhatsAppStatus,\n WhatsAppWebhookPayload,\n} from './webhook.types'\n\nexport type {\n SessionState,\n SessionMode,\n MessageDirection,\n MessageSender,\n MessageStatus,\n ConversationSession,\n ConversationMessage,\n ConversationSummary,\n ListConversationsParams,\n ListMessagesParams,\n} from './conversation.types'\n\nexport {\n CROSS_FLOW_PREFIX,\n FLOW_ACTION_KIND,\n isCrossFlowTarget,\n crossFlowKey,\n flowNodeNextSchema,\n flowNodeDataSchema,\n flowGraphNodesSchema,\n} from './flow.types'\nexport type {\n FlowNodeType,\n FlowQuestionType,\n FlowActionKind,\n FlowConditionOperator,\n FlowNodeNext,\n FlowNodeData,\n FlowGraphData,\n FlowGraphSummary,\n LiveFlowPosition,\n} from './flow.types'\n\nexport type {\n WhatsAppSettings,\n TranscriptionMode,\n TemplateVariablesMap,\n TemplateConfig,\n WhatsAppTemplateSummary,\n CreateTemplateResult,\n} from './settings.types'\n\nexport type {\n MetaWhatsAppHooks,\n MessageHookOutcome,\n InboundMediaDescriptor,\n TranscriptionDeferredDescriptor,\n} from './events'\n\nexport type {\n ChannelAdapterInterface,\n SubjectResolverInterface,\n CatalogProduct,\n CatalogPort,\n ObjectStorageInterface,\n RealtimeNotifierInterface,\n CacheInterface,\n FlowActionHandler,\n FlowActionResult,\n FlowActionRegistry,\n} from './providers'\n\nexport {\n MetaWhatsAppError,\n META_WHATSAPP_ERROR_CODES,\n WindowExpiredError,\n InvalidWebhookSignatureError,\n DuplicateWebhookDeliveryError,\n ConfigMissingError,\n TemplateNotConfiguredError,\n SessionNotFoundError,\n AudioNotIngestedError,\n MessageNotAudioError,\n TranscriptionDisabledError,\n} from './errors'\n\nexport { PREVIEW_MEDIA_ID_PREFIX, toPreviewMediaId, resolvePreviewUploadId } from './previewMedia.types'\n","import { z } from 'zod'\n\n// Extraído de financiamento-imobiliario-bot/apps/api/src/modules/webhook/application/use-cases/\n// ReceiveWhatsAppWebhook.use-case.ts:39-113 — shape real do payload da Cloud API da Meta.\n\nexport const whatsAppMediaSchema = z.object({\n id: z.string(),\n mime_type: z.string(),\n sha256: z.string().optional(),\n caption: z.string().optional(),\n filename: z.string().optional(),\n})\nexport type WhatsAppMedia = z.infer<typeof whatsAppMediaSchema>\n\nexport const whatsAppInteractiveSchema = z.object({\n type: z.string(),\n button_reply: z.object({ id: z.string(), title: z.string() }).optional(),\n list_reply: z.object({ id: z.string(), title: z.string() }).optional(),\n})\nexport type WhatsAppInteractive = z.infer<typeof whatsAppInteractiveSchema>\n\nexport const whatsAppOrderSchema = z.object({\n catalog_id: z.string(),\n text: z.string().optional(),\n product_items: z.array(\n z.object({\n product_retailer_id: z.string(),\n quantity: z.number(),\n item_price: z.number(),\n currency: z.string(),\n }),\n ),\n})\nexport type WhatsAppOrder = z.infer<typeof whatsAppOrderSchema>\n\nexport const whatsAppMessageSchema = z.object({\n id: z.string(),\n from: z.string(),\n type: z.string(),\n text: z.object({ body: z.string() }).optional(),\n image: whatsAppMediaSchema.optional(),\n audio: whatsAppMediaSchema.optional(),\n video: whatsAppMediaSchema.optional(),\n document: whatsAppMediaSchema.optional(),\n sticker: whatsAppMediaSchema.optional(),\n interactive: whatsAppInteractiveSchema.optional(),\n // Pedido enviado pelo carrinho do catálogo (WhatsApp Commerce)\n order: whatsAppOrderSchema.optional(),\n // Presente quando o cliente abre um item do catálogo e manda mensagem pela página do produto\n context: z\n .object({\n from: z.string().optional(),\n id: z.string().optional(),\n referred_product: z.object({ catalog_id: z.string(), product_retailer_id: z.string() }).optional(),\n })\n .optional(),\n timestamp: z.string(),\n})\nexport type WhatsAppMessage = z.infer<typeof whatsAppMessageSchema>\n\nexport const whatsAppMessageEchoSchema = z.object({\n id: z.string(),\n from: z.string(),\n timestamp: z.string(),\n type: z.string(),\n})\nexport type WhatsAppMessageEcho = z.infer<typeof whatsAppMessageEchoSchema>\n\nexport const whatsAppMessageStatusSchema = z.enum(['sent', 'delivered', 'read', 'failed'])\nexport type WhatsAppMessageStatusValue = z.infer<typeof whatsAppMessageStatusSchema>\n\nexport const whatsAppStatusSchema = z.object({\n id: z.string(),\n status: whatsAppMessageStatusSchema,\n timestamp: z.string(),\n recipient_id: z.string().optional(),\n})\nexport type WhatsAppStatus = z.infer<typeof whatsAppStatusSchema>\n\nexport const whatsAppWebhookPayloadSchema = z.object({\n object: z.string(),\n entry: z.array(\n z.object({\n id: z.string(),\n changes: z.array(\n z.object({\n value: z.object({\n messaging_product: z.string(),\n messages: z.array(whatsAppMessageSchema).optional(),\n message_echoes: z.array(whatsAppMessageEchoSchema).optional(),\n statuses: z.array(whatsAppStatusSchema).optional(),\n metadata: z.object({ display_phone_number: z.string(), phone_number_id: z.string() }).optional(),\n }),\n }),\n ),\n }),\n ),\n})\nexport type WhatsAppWebhookPayload = z.infer<typeof whatsAppWebhookPayloadSchema>\n","// Mesmo shape de dados do editor visual (@adatechnology/conversations-ui/flows) — o backend\n// interpreta/persiste o grafo, o frontend edita; os dois lados precisam concordar no formato.\n// `FlowActionKind` é string aberta (não union fechada): o host registra os próprios actions\n// (ex.: 'trigger_simulation' no bot) via registerFlowAction() no módulo (T4.3) — o pacote nunca\n// assume nenhum caso de negócio específico.\nimport { z } from 'zod'\n\nexport type FlowNodeType = 'question' | 'entrada_choice' | 'action' | 'menu' | 'condition'\nexport type FlowQuestionType = 'text' | 'money' | 'date' | 'int' | 'cpf' | 'choice'\nexport type FlowActionKind = string\n\n// Os únicos `actionKind` que o próprio pacote implementa — todo o resto é do host. Ficam aqui, e\n// não no editor, porque o mesmo literal é usado nos dois lados (o editor oferece na paleta, o\n// módulo registra o handler) e duas cópias divergem sem nada acusar.\nexport const FLOW_ACTION_KIND = {\n HANDOFF: 'handoff',\n RATE_LIMITED_HANDOFF: 'rate_limited_handoff',\n SEND_PRODUCT_LIST: 'send_product_list',\n SEND_MEDIA: 'send_media',\n} as const\nexport type FlowConditionOperator = '>' | '>=' | '<' | '<=' | '==' | '!=' | 'contains'\nexport type FlowNodeNext = string | { byAnswer: Record<string, string>; default: string }\n\n// Destinos \"flow:<key>\" são saltos para outro fluxo — mesma convenção usada pelo editor visual\n// (conversations-ui/flows/flowGraph.ts); backend e frontend precisam concordar no formato.\nexport const CROSS_FLOW_PREFIX = 'flow:'\nexport const isCrossFlowTarget = (target: string): boolean => target.startsWith(CROSS_FLOW_PREFIX)\nexport const crossFlowKey = (target: string): string => target.slice(CROSS_FLOW_PREFIX.length)\n\nexport type FlowNodeData = {\n id: string\n type: FlowNodeType\n // Apelido do nó no editor. Só rótulo: o motor do bot ignora, e serve pra distinguir dois nós do\n // mesmo tipo (\"Enviar tabela de juros\" x \"Enviar contrato\") que sem isso ficam idênticos no card.\n label?: string\n contextKey?: string\n questionType?: FlowQuestionType\n question?: string\n options?: [string, string][]\n actionKind?: FlowActionKind\n // Parâmetros arbitrários que o nó carrega para o handler registrado em `actionKind`. O pacote\n // nunca os interpreta — é o que permite um nó de ação ser configurado pelo editor sem que o\n // vocabulário do produto (o antigo `simulationTemplate`) vaze para dentro do contrato.\n actionParams?: Record<string, unknown>\n directMessage?: string\n fallbackMessage?: string\n conditionContextKey?: string\n conditionOperator?: FlowConditionOperator\n conditionValue?: string\n position?: { x: number; y: number }\n next?: FlowNodeNext\n}\n\nexport interface FlowGraphData {\n key: string\n label: string\n startNodeId: string\n version: number\n nodes: Record<string, FlowNodeData>\n}\n\nexport interface FlowGraphSummary {\n key: string\n label: string\n nodeCount: number\n showInMenu: boolean\n menuOptionLabel?: string\n updatedAt: string\n}\n\n// Retorno de GetLiveFlowPositions (T4.2) — quantas sessões ativas estão em cada nó agora,\n// usado pelo editor para desenhar o \"liveCount\" nos cards (FlowNodeCardData.liveCount).\nexport interface LiveFlowPosition {\n flowKey: string\n nodeId: string\n count: number\n}\n\n// Validação de runtime do grafo. O `nodes` é um jsonb que entrou pelo editor (dado de origem\n// cliente) e sai do banco como `unknown` — sem parse, um grafo malformado só se manifestaria\n// como comportamento estranho lá dentro do interpretador, longe da causa.\n//\n// Permissivo de propósito em dois pontos: `actionKind` é string aberta (o host registra os\n// seus) e `.passthrough()` deixa passar campos extras — um grafo salvo por uma versão mais nova\n// do editor não pode ficar irrecuperável numa versão mais antiga do módulo.\nexport const flowNodeNextSchema = z.union([\n z.string(),\n z.object({ byAnswer: z.record(z.string(), z.string()), default: z.string() }),\n])\n\nexport const flowNodeDataSchema = z\n .object({\n id: z.string(),\n type: z.enum(['question', 'entrada_choice', 'action', 'menu', 'condition']),\n contextKey: z.string().optional(),\n questionType: z.enum(['text', 'money', 'date', 'int', 'cpf', 'choice']).optional(),\n question: z.string().optional(),\n options: z.array(z.tuple([z.string(), z.string()])).optional(),\n actionKind: z.string().optional(),\n actionParams: z.record(z.string(), z.unknown()).optional(),\n directMessage: z.string().optional(),\n fallbackMessage: z.string().optional(),\n conditionContextKey: z.string().optional(),\n conditionOperator: z.enum(['>', '>=', '<', '<=', '==', '!=', 'contains']).optional(),\n conditionValue: z.string().optional(),\n position: z.object({ x: z.number(), y: z.number() }).optional(),\n next: flowNodeNextSchema.optional(),\n })\n .passthrough()\n\nexport const flowGraphNodesSchema = z.record(z.string(), flowNodeDataSchema)\n","// Hierarquia de erros do módulo — não depende do framework de erros do host (nenhum DomainError\n// importado); o host mapeia estes para o seu próprio formato de resposta no exception filter.\nexport class MetaWhatsAppError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly code: string,\n public readonly details?: Record<string, unknown>,\n ) {\n super(message)\n this.name = 'MetaWhatsAppError'\n }\n}\n\nexport const META_WHATSAPP_ERROR_CODES = {\n WINDOW_EXPIRED: 'META_WHATSAPP_WINDOW_EXPIRED',\n INVALID_SIGNATURE: 'META_WHATSAPP_INVALID_SIGNATURE',\n DUPLICATE_DELIVERY: 'META_WHATSAPP_DUPLICATE_DELIVERY',\n CONFIG_MISSING: 'META_WHATSAPP_CONFIG_MISSING',\n TEMPLATE_NOT_CONFIGURED: 'META_WHATSAPP_TEMPLATE_NOT_CONFIGURED',\n SESSION_NOT_FOUND: 'META_WHATSAPP_SESSION_NOT_FOUND',\n AUDIO_NOT_INGESTED: 'META_WHATSAPP_AUDIO_NOT_INGESTED',\n MESSAGE_NOT_AUDIO: 'META_WHATSAPP_MESSAGE_NOT_AUDIO',\n TRANSCRIPTION_DISABLED: 'META_WHATSAPP_TRANSCRIPTION_DISABLED',\n} as const\n\nexport class WindowExpiredError extends MetaWhatsAppError {\n constructor(public readonly hoursSinceLastMessage?: number) {\n super(\n 'Janela de 24h expirada — não é possível enviar mensagem para este contato fora de template.',\n 400,\n META_WHATSAPP_ERROR_CODES.WINDOW_EXPIRED,\n { hoursSinceLastMessage },\n )\n }\n}\n\n// Assinatura HMAC do webhook não confere — Meta ou um terceiro tentando forjar uma entrega.\nexport class InvalidWebhookSignatureError extends MetaWhatsAppError {\n constructor() {\n super('Assinatura do webhook inválida.', 401, META_WHATSAPP_ERROR_CODES.INVALID_SIGNATURE)\n }\n}\n\n// Meta reenviou uma entrega dentro da janela de replay (nonce já visto) — não é erro do\n// cliente, é comportamento esperado da Cloud API; o host deve responder 200 e ignorar.\nexport class DuplicateWebhookDeliveryError extends MetaWhatsAppError {\n constructor(nonce: string) {\n super('Entrega de webhook duplicada.', 409, META_WHATSAPP_ERROR_CODES.DUPLICATE_DELIVERY, { nonce })\n }\n}\n\nexport class ConfigMissingError extends MetaWhatsAppError {\n constructor(missingField: string) {\n super(`Configuração do WhatsApp ausente: ${missingField}.`, 503, META_WHATSAPP_ERROR_CODES.CONFIG_MISSING, {\n missingField,\n })\n }\n}\n\nexport class TemplateNotConfiguredError extends MetaWhatsAppError {\n constructor() {\n super(\n 'Nenhum template de WhatsApp configurado para reabertura de janela.',\n 503,\n META_WHATSAPP_ERROR_CODES.TEMPLATE_NOT_CONFIGURED,\n )\n }\n}\n\nexport class SessionNotFoundError extends MetaWhatsAppError {\n constructor(whatsappNumber: string) {\n super(\n `Sessão de conversa não encontrada para ${whatsappNumber}.`,\n 404,\n META_WHATSAPP_ERROR_CODES.SESSION_NOT_FOUND,\n { whatsappNumber },\n )\n }\n}\n\n/**\n * Pediram transcrição de um áudio que ainda não foi copiado da Meta para o storage.\n *\n * 409 e não 404: a mensagem existe e o áudio vai chegar — a ingestão é assíncrona e o atendente\n * simplesmente clicou antes de ela terminar. É o único erro de transcrição em que \"tente de novo em\n * alguns segundos\" é a orientação correta para a interface.\n */\nexport class AudioNotIngestedError extends MetaWhatsAppError {\n constructor(messageId: string) {\n super(\n 'Áudio ainda está sendo copiado — tente novamente em alguns segundos.',\n 409,\n META_WHATSAPP_ERROR_CODES.AUDIO_NOT_INGESTED,\n { messageId },\n )\n }\n}\n\n/**\n * Transcrição está desligada para esta empresa.\n *\n * Guarda de última linha, não o caminho normal: o painel lê as configurações e nem desenha o botão\n * quando está desligado. Existe para o caso de a tela estar com dado velho, ou de alguém chamar a\n * rota direto — e é `409` (estado atual conflita com a operação), não `403`: ninguém está sem\n * permissão, o recurso está desligado por escolha e liga a qualquer momento.\n */\nexport class TranscriptionDisabledError extends MetaWhatsAppError {\n constructor() {\n super(\n 'Transcrição de áudio está desligada para esta empresa.',\n 409,\n META_WHATSAPP_ERROR_CODES.TRANSCRIPTION_DISABLED,\n )\n }\n}\n\n/** Pediram transcrição de mensagem que não é áudio. Nunca melhora com retentativa. */\nexport class MessageNotAudioError extends MetaWhatsAppError {\n constructor(messageId: string, type: string) {\n super(\n `Mensagem ${messageId} é do tipo \"${type}\" — só áudio é transcrito.`,\n 422,\n META_WHATSAPP_ERROR_CODES.MESSAGE_NOT_AUDIO,\n { messageId, type },\n )\n }\n}\n","/**\n * Mídia que veio do simulador de conversa, não da Meta.\n *\n * Vive no `contracts` porque é literalmente um contrato entre as duas pontas: o front gera o id, o\n * backend o resolve. Nasceu duplicado num produto (duas constantes iguais, cada uma com um\n * comentário pedindo \"precisa bater com a outra\") e por isso o segundo produto não herdou nada —\n * este pacote é o único lugar em que os dois lados já se encontram.\n *\n * O simulador manda **webhook**, e webhook da Meta carrega referência de mídia (um id), nunca o\n * binário. Então o arquivo gravado no navegador precisa existir em algum lugar que o servidor\n * alcance, e o id precisa dizer onde — é essa a convenção deste arquivo.\n *\n * Existe no pacote, e não em cada host, porque a convenção tem DOIS lados que precisam concordar\n * (quem gera o id no front, quem o resolve no backend). Onde ela ficou no host, o resultado foi\n * exatamente o previsível: duas constantes iguais em pacotes diferentes, cada uma com um comentário\n * pedindo \"precisa bater com a outra\" — e o segundo produto não herdou nada e ficou sem o recurso.\n */\n\n/**\n * Prefixo que marca o id como local.\n *\n * Dois-pontos no fim de propósito: id da Meta é alfanumérico com `_` e `-`, então o separador torna\n * a colisão impossível em vez de improvável.\n */\nexport const PREVIEW_MEDIA_ID_PREFIX = 'preview-upload:'\n\n/** Monta o id que o simulador manda no webhook. */\nexport function toPreviewMediaId(uploadId: string): string {\n return `${PREVIEW_MEDIA_ID_PREFIX}${uploadId}`\n}\n\n/**\n * `uploadId` embutido no id, ou `undefined` quando a mídia veio mesmo da Meta.\n *\n * Devolver `undefined` para id sem prefixo é o que mantém o caminho normal intacto: o adaptador só\n * desvia para o storage quando o prefixo está lá.\n */\nexport function resolvePreviewUploadId(mediaId: string): string | undefined {\n if (!mediaId.startsWith(PREVIEW_MEDIA_ID_PREFIX)) return undefined\n return mediaId.slice(PREVIEW_MEDIA_ID_PREFIX.length) || undefined\n}\n"],"mappings":"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","names":["whatsAppMediaSchema","z","object","id","string","mime_type","sha256","optional","caption","filename","whatsAppInteractiveSchema","type","button_reply","title","list_reply","whatsAppOrderSchema","catalog_id","text","product_items","array","product_retailer_id","quantity","number","item_price","currency","whatsAppMessageSchema","from","body","image","audio","video","document","sticker","interactive","order","context","referred_product","timestamp","whatsAppMessageEchoSchema","whatsAppMessageStatusSchema","enum","whatsAppStatusSchema","status","recipient_id","whatsAppWebhookPayloadSchema","entry","changes","value","messaging_product","messages","message_echoes","statuses","metadata","display_phone_number","phone_number_id","import_zod","FLOW_ACTION_KIND","HANDOFF","RATE_LIMITED_HANDOFF","SEND_PRODUCT_LIST","SEND_MEDIA","CROSS_FLOW_PREFIX","isCrossFlowTarget","target","startsWith","crossFlowKey","slice","length","flowNodeNextSchema","z","union","string","object","byAnswer","record","default","flowNodeDataSchema","id","type","enum","contextKey","optional","questionType","question","options","array","tuple","actionKind","actionParams","unknown","directMessage","fallbackMessage","conditionContextKey","conditionOperator","conditionValue","position","x","number","y","next","passthrough","flowGraphNodesSchema","MetaWhatsAppError","Error","message","statusCode","code","details","name","META_WHATSAPP_ERROR_CODES","WINDOW_EXPIRED","INVALID_SIGNATURE","DUPLICATE_DELIVERY","CONFIG_MISSING","TEMPLATE_NOT_CONFIGURED","SESSION_NOT_FOUND","AUDIO_NOT_INGESTED","MESSAGE_NOT_AUDIO","TRANSCRIPTION_DISABLED","WindowExpiredError","hoursSinceLastMessage","InvalidWebhookSignatureError","DuplicateWebhookDeliveryError","nonce","ConfigMissingError","missingField","TemplateNotConfiguredError","SessionNotFoundError","whatsappNumber","AudioNotIngestedError","messageId","TranscriptionDisabledError","MessageNotAudioError","type","PREVIEW_MEDIA_ID_PREFIX","toPreviewMediaId","uploadId","resolvePreviewUploadId","mediaId","startsWith","undefined","slice","length"]}
|