cdp-edge 1.24.0 → 1.24.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/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Padrão Quantum Tracking: 100% Cloudflare Edge.** Sem GTM. Sem Stape. Sem cookies de terceiros.
|
|
4
4
|
|
|
5
|
-
> **v2.
|
|
5
|
+
> **v2.3.0** — TypeScript Nativo · Worker 100% tipado · `types.ts` centralizado · `tsconfig.json` · `tsc --noEmit` zero erros · Cloudflare Workers · Meta CAPI v22.0 · GA4 MP · TikTok Events API v1.3
|
|
6
6
|
|
|
7
7
|
> ⚠️ **REGRA DE OURO (SQUAD):** Todas as atualizações, correções ou novas features devem OBRIGATORIAMENTE ser documentadas de forma sincronizada neste `README.md`, no arquivo de instruções `CLAUDE.md` e no dossiê de diretoria `CDP-EDGE-BUSINESS-BOOK.md`. Nenhuma alteração passa sem esse tripé.
|
|
8
8
|
|
|
@@ -27,28 +27,33 @@ Meu ecossistema opera como um Cérebro de Conversão Privado na borda. Quando um
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
-
## 📋 CHANGELOG v2.
|
|
30
|
+
## 📋 CHANGELOG v2.3.0 — TypeScript Nativo (12 de Abril de 2026)
|
|
31
31
|
|
|
32
32
|
### 🔷 Worker 100% TypeScript — Migração Completa
|
|
33
33
|
|
|
34
|
-
Todo o código server-side (`server-edge-tracker/`) foi migrado de JavaScript para **TypeScript nativo**. O Wrangler compila diretamente o `.ts` sem etapa de build separada.
|
|
34
|
+
Todo o código server-side (`server-edge-tracker/`) foi migrado de JavaScript para **TypeScript nativo**. O Wrangler compila diretamente o `.ts` via esbuild — sem etapa de build separada, sem configuração extra.
|
|
35
35
|
|
|
36
|
-
**
|
|
37
|
-
-
|
|
38
|
-
-
|
|
36
|
+
**Por que TypeScript muda o jogo no CDP Edge:**
|
|
37
|
+
- **Env tipado** — typos em nomes de secrets (`META_ACCESS_TOKEN`, `GEO_CACHE`, `DB`) viram erros em build time, nunca em produção
|
|
38
|
+
- **TrackPayload contratado** — o shape do payload entre browser e Worker é garantido pelo compilador
|
|
39
|
+
- **Cloudflare types nativos** — D1, KV, R2, Workers AI com autocomplete e validação de métodos
|
|
40
|
+
- **Fraud Gate e ML seguros** — `checkFraudGate(env: Env, request: Request, payload: TrackPayload)` — nenhum `undefined` passa despercebido
|
|
41
|
+
- **Refatoração segura** — renomear qualquer campo do `TrackPayload` lista automaticamente todos os pontos de quebra
|
|
42
|
+
|
|
43
|
+
**Arquivos migrados (JS → TS) — 16 módulos:**
|
|
44
|
+
- `index.ts` — entry point do Worker
|
|
45
|
+
- `types.ts` — **novo** — contratos centralizados: `Env`, `TrackPayload`, `BehavioralData`, `HotmartWebhook`, `KiwifyWebhook`, `TictoWebhook`, `QueueMessage`, `PromiseResult<T>`
|
|
39
46
|
- `modules/utils.ts`, `modules/db.ts`, `modules/intelligence.ts`
|
|
40
47
|
- `modules/dispatch/` — `meta.ts`, `ga4.ts`, `tiktok.ts`, `platforms.ts`, `whatsapp.ts`
|
|
41
48
|
- `modules/ml/` — `ltv.ts`, `fraud.ts`, `bidding.ts`, `segmentation.ts`, `logistic.ts`, `matchquality.ts`
|
|
42
49
|
|
|
43
50
|
**Infraestrutura:**
|
|
44
|
-
- `tsconfig.json`
|
|
45
|
-
- `wrangler.toml` — `main = "index.ts"` (TypeScript nativo
|
|
46
|
-
- `
|
|
47
|
-
|
|
48
|
-
**Testes de integração:**
|
|
49
|
-
- `tests/integration/setup.js` atualizado para compilar o `.ts` com esbuild em memória antes de passar ao Miniflare (esbuild já é dep transitiva do Miniflare 3)
|
|
51
|
+
- `tsconfig.json` — `target: ESNext`, `moduleResolution: "bundler"`, `strict: true`, `@cloudflare/workers-types`
|
|
52
|
+
- `wrangler.toml` — `main = "index.ts"` (TypeScript nativo via wrangler/esbuild)
|
|
53
|
+
- `contracts/types.ts` — tipos públicos exportados no pacote NPM: `QuantumEventPayload`, `AgencyContext`, `ApiVersionsConfig`
|
|
54
|
+
- `npm run typecheck` — `tsc --noEmit` (225 testes passando, zero erros de compilação)
|
|
50
55
|
|
|
51
|
-
**Breaking change:** nenhuma — API HTTP e comportamento em runtime são idênticos.
|
|
56
|
+
**Breaking change:** nenhuma — API HTTP e comportamento em runtime são idênticos. TypeScript é invisível para o Cloudflare.
|
|
52
57
|
|
|
53
58
|
---
|
|
54
59
|
|
package/package.json
CHANGED
|
@@ -218,8 +218,8 @@ export default {
|
|
|
218
218
|
META_ACCESS_TOKEN: env.META_ACCESS_TOKEN ? 'set' : 'MISSING',
|
|
219
219
|
GA4_API_SECRET: env.GA4_API_SECRET ? 'set' : 'MISSING',
|
|
220
220
|
WA_WEBHOOK_VERIFY_TOKEN: env.WA_WEBHOOK_VERIFY_TOKEN ? 'set' : 'MISSING',
|
|
221
|
-
WHATSAPP_ACCESS_TOKEN: env.WHATSAPP_ACCESS_TOKEN
|
|
222
|
-
WHATSAPP_PHONE_NUMBER_ID: env.WHATSAPP_PHONE_NUMBER_ID ? 'set' : 'not set (optional - only for auto-reply)',
|
|
221
|
+
WHATSAPP_ACCESS_TOKEN: (env.WHATSAPP_ACCESS_TOKEN || env.WA_ACCESS_TOKEN) ? 'set' : 'not set (optional - only for auto-reply)',
|
|
222
|
+
WHATSAPP_PHONE_NUMBER_ID: (env.WHATSAPP_PHONE_NUMBER_ID || env.WA_PHONE_ID) ? 'set' : 'not set (optional - only for auto-reply)',
|
|
223
223
|
WA_NOTIFY_NUMBER: env.WA_NOTIFY_NUMBER ? 'set' : 'not set (optional - only for auto-reply)',
|
|
224
224
|
TIKTOK_ACCESS_TOKEN: env.TIKTOK_ACCESS_TOKEN ? 'set' : 'not set (optional)',
|
|
225
225
|
CALLMEBOT_PHONE: env.CALLMEBOT_PHONE ? 'set' : 'not set (optional)',
|
|
@@ -40,9 +40,19 @@ interface WhatsAppMessage {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// ── Resolvedores de secrets (canônico + legado) ────────────────────────────────
|
|
44
|
+
// Meta Cloud API v22.0 usa PHONE_NUMBER_ID e ACCESS_TOKEN como termos oficiais.
|
|
45
|
+
// Suportamos ambos os nomes para compatibilidade com secrets já configurados.
|
|
46
|
+
function resolvePhoneNumberId(env: Env): string | undefined {
|
|
47
|
+
return env.WHATSAPP_PHONE_NUMBER_ID || env.WA_PHONE_ID;
|
|
48
|
+
}
|
|
49
|
+
function resolveAccessToken(env: Env): string | undefined {
|
|
50
|
+
return env.WHATSAPP_ACCESS_TOKEN || env.WA_ACCESS_TOKEN;
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
// ── sendWhatsApp — envia mensagem via Meta Cloud API ──────────────────────────
|
|
44
54
|
export async function sendWhatsApp(env: Env, tipo: string, payload: TrackPayload, options: WhatsAppOptions = {}): Promise<any> {
|
|
45
|
-
if (!env
|
|
55
|
+
if (!resolvePhoneNumberId(env) || !resolveAccessToken(env) || !env.WA_NOTIFY_NUMBER) {
|
|
46
56
|
return { skipped: 'WhatsApp não configurado' };
|
|
47
57
|
}
|
|
48
58
|
|
|
@@ -116,9 +126,11 @@ export async function sendWhatsApp(env: Env, tipo: string, payload: TrackPayload
|
|
|
116
126
|
// ── _sendWARequest — executor interno ─────────────────────────────────────────
|
|
117
127
|
async function _sendWARequest(env: Env, body: Record<string, any>): Promise<any> {
|
|
118
128
|
try {
|
|
119
|
-
const
|
|
129
|
+
const phoneNumberId = resolvePhoneNumberId(env);
|
|
130
|
+
const accessToken = resolveAccessToken(env);
|
|
131
|
+
const res = await fetch(`https://graph.facebook.com/v22.0/${phoneNumberId}/messages`, {
|
|
120
132
|
method: 'POST',
|
|
121
|
-
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${
|
|
133
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessToken}` },
|
|
122
134
|
body: JSON.stringify(body),
|
|
123
135
|
});
|
|
124
136
|
const data = await res.json();
|
|
@@ -33,8 +33,12 @@ export interface Env {
|
|
|
33
33
|
GA4_API_SECRET?: string;
|
|
34
34
|
TIKTOK_ACCESS_TOKEN?: string;
|
|
35
35
|
WA_WEBHOOK_VERIFY_TOKEN?: string;
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
// WhatsApp Cloud API — nomes canônicos (Meta Cloud API v22.0)
|
|
37
|
+
WHATSAPP_ACCESS_TOKEN?: string; // canonical: Bearer token do System User
|
|
38
|
+
WHATSAPP_PHONE_NUMBER_ID?: string; // canonical: ID numérico do número no Meta Business
|
|
39
|
+
// WhatsApp Cloud API — nomes legados (backwards compat)
|
|
40
|
+
WA_ACCESS_TOKEN?: string;
|
|
41
|
+
WA_PHONE_ID?: string;
|
|
38
42
|
WA_NOTIFY_NUMBER?: string;
|
|
39
43
|
CALLMEBOT_PHONE?: string;
|
|
40
44
|
WEBHOOK_SECRET_TICTO?: string;
|
|
@@ -17,19 +17,19 @@ workers_dev = true
|
|
|
17
17
|
# zone_name = "SEU_DOMINIO"
|
|
18
18
|
|
|
19
19
|
[[routes]]
|
|
20
|
-
pattern = "
|
|
21
|
-
zone_name = "
|
|
20
|
+
pattern = "SEU_DOMINIO/track*"
|
|
21
|
+
zone_name = "SEU_DOMINIO"
|
|
22
22
|
|
|
23
23
|
[[routes]]
|
|
24
|
-
pattern = "*.
|
|
25
|
-
zone_name = "
|
|
24
|
+
pattern = "*.SEU_DOMINIO/track*"
|
|
25
|
+
zone_name = "SEU_DOMINIO"
|
|
26
26
|
|
|
27
27
|
# ── Variáveis públicas (não são segredos) ─────────────────────────────────────
|
|
28
28
|
[vars]
|
|
29
29
|
META_PIXEL_ID = ""
|
|
30
30
|
GA4_MEASUREMENT_ID = ""
|
|
31
31
|
TIKTOK_PIXEL_ID = ""
|
|
32
|
-
SITE_DOMAIN = "
|
|
32
|
+
SITE_DOMAIN = "SEU_DOMINIO"
|
|
33
33
|
|
|
34
34
|
# ── Banco D1 ──────────────────────────────────────────────────────────────────
|
|
35
35
|
# Após criar o banco com "wrangler d1 create cdp-edge-db",
|
|
@@ -37,7 +37,7 @@ SITE_DOMAIN = "lancamentosabc.com.br"
|
|
|
37
37
|
[[d1_databases]]
|
|
38
38
|
binding = "DB"
|
|
39
39
|
database_name = "cdp-edge-db"
|
|
40
|
-
database_id = "
|
|
40
|
+
database_id = "SEU_DATABASE_ID"
|
|
41
41
|
|
|
42
42
|
# ── Queues — Retry + Dead Letter Queue ───────────────────────────────────────
|
|
43
43
|
# Produtor: worker envia eventos com falha para cdp-edge-retry
|