@horizon-framework/automations-nextjs-docs 2.3.2
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/docs/ARQUITETURA.md +85 -0
- package/docs/COMO_ADICIONAR_CANAL.md +103 -0
- package/package.json +10 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Horizon Automations — Arquitetura
|
|
2
|
+
|
|
3
|
+
> Como funciona o projeto de automacoes do Horizon.
|
|
4
|
+
> Recebe leads, envia pra canais (email, CRMs), processa integrações.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Estrutura
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
apps/automations/src/
|
|
12
|
+
├── app/api/
|
|
13
|
+
│ ├── health/route.ts ← Healthcheck
|
|
14
|
+
│ └── leads/route.ts ← Orquestrador (recebe lead, envia pros canais)
|
|
15
|
+
│
|
|
16
|
+
├── core/ ← MOTORES (logica reutilizavel)
|
|
17
|
+
│ └── email-engine/ ← Motor de email (Resend + React Email)
|
|
18
|
+
│ ├── service.ts ← sendEmail() generico
|
|
19
|
+
│ └── types.ts
|
|
20
|
+
│
|
|
21
|
+
├── channels/ ← CANAIS DE ENVIO (implementacoes)
|
|
22
|
+
│ ├── email/ ← Canal: email
|
|
23
|
+
│ │ ├── templates/
|
|
24
|
+
│ │ │ └── lead-form-generic/ ← Template de lead por email
|
|
25
|
+
│ │ └── recipients.json ← Destinatarios
|
|
26
|
+
│ ├── si9/ ← Canal: CRM SI9
|
|
27
|
+
│ │ └── sender.ts ← Usa SDK @horizon-integrations/si9-crm
|
|
28
|
+
│ └── jetimob/ ← Canal: CRM Jetimob
|
|
29
|
+
│ └── sender.ts ← Usa SDK @horizon-integrations/jetimob-crm
|
|
30
|
+
│
|
|
31
|
+
└── config/ ← CONFIGURACAO
|
|
32
|
+
└── channels.ts ← Ligar/desligar canais
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Fluxo
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Frontend envia POST /api/leads
|
|
41
|
+
↓
|
|
42
|
+
route.ts (orquestrador)
|
|
43
|
+
↓ Verifica config/channels.ts (quais canais estao ativos)
|
|
44
|
+
↓ Envia em PARALELO pra todos os canais ativos
|
|
45
|
+
↓
|
|
46
|
+
channels/email/ → Envia email com template formatado
|
|
47
|
+
channels/si9/ → Envia lead pro CRM SI9 via SDK
|
|
48
|
+
channels/jetimob/ → Envia lead pro CRM Jetimob via SDK
|
|
49
|
+
↓
|
|
50
|
+
Retorna resultado combinado
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Camadas
|
|
56
|
+
|
|
57
|
+
| Camada | O que faz | Onde fica |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| **route.ts** | Recebe lead, valida, orquestra canais | app/api/leads/ |
|
|
60
|
+
| **core/** | Motores reutilizaveis (email engine) | core/ |
|
|
61
|
+
| **channels/** | Implementacao de cada destino | channels/{nome}/ |
|
|
62
|
+
| **config/** | Liga/desliga canais | config/ |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Princípios
|
|
67
|
+
|
|
68
|
+
1. **Cada canal e independente** — ligar/desligar no config sem mexer no codigo
|
|
69
|
+
2. **Canais rodam em paralelo** — Promise.all, um nao bloqueia outro
|
|
70
|
+
3. **Se um canal falha, os outros continuam** — erro e logado mas nao bloqueia
|
|
71
|
+
4. **SDK do CRM e agnóstica** — nao sabe de Horizon. O channel faz o mapeamento
|
|
72
|
+
5. **Lead-core e a fonte de verdade** — tipos e adapter vem do @horizon-framework/lead-core
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Pacotes usados
|
|
77
|
+
|
|
78
|
+
| Pacote | Pra que |
|
|
79
|
+
|---|---|
|
|
80
|
+
| @horizon-framework/lead-core | Tipos de lead, adapter generico |
|
|
81
|
+
| @horizon-modules/property-automations | Adapter de lead de imovel |
|
|
82
|
+
| @horizon-integrations/si9-crm | SDK do SI9 (sendLead) |
|
|
83
|
+
| @horizon-integrations/jetimob-crm | SDK do Jetimob |
|
|
84
|
+
| resend | Motor de envio de email |
|
|
85
|
+
| @react-email/components | Templates de email em React |
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Como Adicionar um Novo Canal de Envio de Leads
|
|
2
|
+
|
|
3
|
+
> Guia passo a passo para criar um novo canal (CRM, webhook, n8n, etc.)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Passo 1: Criar pasta do canal
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
channels/
|
|
11
|
+
└── meu-crm/
|
|
12
|
+
└── sender.ts
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Passo 2: Implementar sender.ts
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
/**
|
|
19
|
+
* Canal: Meu CRM
|
|
20
|
+
* Envia leads para a API do Meu CRM
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { sendLead } from "@horizon-integrations/meu-crm"
|
|
24
|
+
// OU se nao tem SDK:
|
|
25
|
+
// import fetch...
|
|
26
|
+
|
|
27
|
+
interface SendResult {
|
|
28
|
+
success: boolean;
|
|
29
|
+
platform: string;
|
|
30
|
+
error?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface SendParams {
|
|
34
|
+
subject?: string;
|
|
35
|
+
data: any; // FormDataInput do lead
|
|
36
|
+
meta?: any; // FormMeta
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function sendToMeuCRM(params: SendParams): Promise<SendResult> {
|
|
40
|
+
try {
|
|
41
|
+
// 1. Extrair campos do lead
|
|
42
|
+
// Usar adaptGenericLead() do lead-core ou adaptPropertyLead() do property-automations
|
|
43
|
+
|
|
44
|
+
// 2. Enviar pra API do CRM
|
|
45
|
+
const result = await sendLead({ ... }, credentials)
|
|
46
|
+
|
|
47
|
+
// 3. Retornar resultado
|
|
48
|
+
return { success: true, platform: "meu-crm" }
|
|
49
|
+
} catch (error) {
|
|
50
|
+
return { success: false, platform: "meu-crm", error: error.message }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Passo 3: Registrar no config
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// config/channels.ts
|
|
59
|
+
export const LEAD_CHANNELS = {
|
|
60
|
+
email: { enabled: true, name: "Email" },
|
|
61
|
+
jetimob: { enabled: true, name: "Jetimob CRM" },
|
|
62
|
+
si9: { enabled: true, name: "SI9 CRM" },
|
|
63
|
+
meuCrm: { enabled: true, name: "Meu CRM" }, // NOVO
|
|
64
|
+
};
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Passo 4: Integrar na rota
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// app/api/leads/route.ts
|
|
71
|
+
import { sendToMeuCRM } from "@/channels/meu-crm/sender";
|
|
72
|
+
|
|
73
|
+
// Dentro do POST handler:
|
|
74
|
+
if (LEAD_CHANNELS.meuCrm.enabled) {
|
|
75
|
+
channelNames.push("meuCrm");
|
|
76
|
+
promises.push(sendToMeuCRM({ subject, data, meta }));
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Passo 5: Configurar env vars
|
|
81
|
+
|
|
82
|
+
Adicionar no `.env.local`:
|
|
83
|
+
```
|
|
84
|
+
MEU_CRM_API_KEY=xxx
|
|
85
|
+
MEU_CRM_SECRET=xxx
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Passo 6: Testar
|
|
89
|
+
|
|
90
|
+
1. Levantar automations: `pnpm dev`
|
|
91
|
+
2. Enviar lead de teste via curl ou formulario
|
|
92
|
+
3. Verificar logs: `[Leads API] meuCrm: OK`
|
|
93
|
+
4. Verificar no painel do CRM se o lead chegou
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Dicas
|
|
98
|
+
|
|
99
|
+
- Use `adaptGenericLead()` do lead-core pra extrair campos base
|
|
100
|
+
- Use `adaptPropertyLead()` do property-automations se o lead e de imovel
|
|
101
|
+
- Use `extraFieldsToText()` pra concatenar extras num campo de texto
|
|
102
|
+
- Se o CRM tem SDK (@horizon-integrations/*), use. Se nao, faca fetch direto
|
|
103
|
+
- NUNCA hardcode credentials — sempre via env vars
|
package/package.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@horizon-framework/automations-nextjs-docs",
|
|
3
|
+
"version": "2.3.2",
|
|
4
|
+
"description": "Documentacao do projeto Horizon Automations — arquitetura de channels, leads, integracoes",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"private": false,
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
}
|
|
10
|
+
}
|