@omnizapi/connect 1.0.0 → 1.0.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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +75 -27
- package/dist/cjs/index.js +338 -124
- package/dist/esm/index.mjs +338 -124
- package/dist/omnizapi.min.js +1 -1
- package/dist/types/src/core/client.d.ts +1 -1
- package/dist/types/src/core/facebook-sdk.d.ts +11 -0
- package/dist/types/src/core/runtime.d.ts +18 -0
- package/dist/types/src/types/index.d.ts +3 -2
- package/examples/angular.ts +58 -0
- package/examples/basic.ts +52 -0
- package/examples/error-handling.ts +92 -0
- package/examples/react.tsx +75 -0
- package/examples/vanilla.html +60 -0
- package/examples/vue.vue +61 -0
- package/examples/with-options.ts +70 -0
- package/package.json +12 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.2] - 2026-09-10
|
|
4
|
+
|
|
5
|
+
Primeira versao documentada neste changelog; nao reconstitui o historico de releases anteriores.
|
|
6
|
+
|
|
7
|
+
### API e ciclo de vida
|
|
8
|
+
|
|
9
|
+
- `ConnectionOptions.signal?: AbortSignal` permite interromper `connect` com `OmnizapiError.code === "ABORTED"` e limpeza dos recursos da tentativa, sem expor `signal.reason`. Nao desfaz autorizacoes no provedor nem operacoes ja recebidas pelo backend.
|
|
10
|
+
- Uma tentativa ativa por pagina, inclusive entre clientes; reserva de popup `about:blank` no gesto e navegacao da mesma janela apos validar a configuracao. A selecao de fluxo nativo por `appCustom` fecha a janela provisoria; o gesto exigido pelo SDK Meta ainda depende de homologacao externa.
|
|
11
|
+
- Quarentena nativa preservada quando o login termina sem callback Meta, inclusive por timeout ou abort. Callback de cancelamento ou tardio libera somente a tentativa dona, sem exigir reload para todo cancelamento.
|
|
12
|
+
- Inicializacao rastreada pelo SDK Facebook reutilizada para o mesmo `appId` numerico, sem reinicializar silenciosamente o SDK do host; conflitos de app e inicializacao preexistente desconhecida degradam para o fluxo proxy na janela reservada (abaixo).
|
|
13
|
+
- Chamadas externas ao `FB.init` observado invalidam o app conhecido, inclusive entre versoes da biblioteca. Timeouts inconclusivos de scripts externos impedem atribuir proveniencia propria a um carregamento tardio; recursos do host nao sao removidos.
|
|
14
|
+
- `getListMessengerPages` permanece `Promise<unknown>`: o schema do servico externo nao foi confirmado. Os tipos publicos continuam importados da raiz de `@omnizapi/connect`. A chamada agora aceita um `AbortSignal` opcional como terceiro argumento; aborts rejeitam com `ABORTED` (antes `NETWORK_ERROR`) e sinais invalidos com `INVALID_OPTIONS`.
|
|
15
|
+
- Conflito de app Meta ou SDK Meta do host com inicializacao desconhecida nao rejeita mais com `INVALID_CONFIGURATION`: a tentativa degrada para o fluxo proxy na janela reservada. A quarentena de login nativo (`CONNECTION_IN_PROGRESS`) nao degrada. Para canais `appCustom`, o fallback exige o dominio/redirects da plataforma cadastrados no app do cliente.
|
|
16
|
+
- Um `FB.login` que lanca excecao sincrona libera imediatamente a quarentena nativa (nenhum dialogo abriu, nenhum callback chegara), permitindo nova tentativa sem recarregar a pagina.
|
|
17
|
+
- A janela `about:blank` passa a ser reservada no clique para todos os canais, inclusive com `direct: true`: `direct` deixa de impedir a reserva e apenas solicita o fluxo nativo no WhatsApp Meta, corrigindo o `POPUP_BLOCKED` de `direct` em outros canais. Fechar a janela reservada antes da navegacao nao cancela a tentativa; `popup_closed` so ocorre quando o fluxo ja depende da janela.
|
|
18
|
+
- A comparacao de `allowOrigins` normaliza cada entrada com `new URL(origin).origin`, aceitando entradas com barra final, path ou porta padrao.
|
|
19
|
+
- As URLs de `/connect/telegram` e `/connect/whatsapp-web` incluem `pk` (a chave publica), permitindo ao frontend de conexao restringir o `targetOrigin` da resposta as origens autorizadas do canal em vez de `*`.
|
|
20
|
+
|
|
21
|
+
### Exemplos e documentacao
|
|
22
|
+
|
|
23
|
+
- Criacao/cache de clientes movidos para o `try` do clique nos exemplos TypeScript, React, Angular e Vue, permitindo exibir erros de configuracao sem falhar na importacao/renderizacao.
|
|
24
|
+
- Exemplo de erros com mensagens tipadas exaustivas, inclusive `ABORTED`, e cancelamento controlado apenas durante a autorizacao. React usa `useRef` e cleanup com `AbortController`, sem atualizacoes apos desmontagem nem memoizacao desnecessaria.
|
|
25
|
+
- Mensagens de retry ajustadas para nao exigir reload indiscriminado nem recomendar repetir uma finalizacao cujo estado no backend e desconhecido. Nenhum exemplo registra tokens ou erros brutos.
|
|
26
|
+
- Scripts CDN e links UNPKG do README e do exemplo vanilla fixados na versao do manifesto; os exemplos locais sao os mesmos incluidos no pacote.
|
|
27
|
+
- Documentacao de `appCustom` preservada e ampliada com limites de inicializacao compartilhada e de gesto nativo; `PROVIDER_ERROR` nao e prometido para toda recusa de dominio pela Meta.
|
|
28
|
+
- Nota explicita de privacidade: `state.currentUrl` permanece a URL completa, inclusive query e fragmento, com risco de exposicao de tokens/dados sensiveis. Reduzir a origem depende de verificacao dos proxies e nao foi implementado nesta rodada.
|
|
29
|
+
- Licenca MIT completa adicionada com copyright 2026 FourPixel IT, preservando a autoria.
|
|
30
|
+
|
|
31
|
+
### Verificacao e release
|
|
32
|
+
|
|
33
|
+
- Fluxo de desenvolvimento documentado com Node.js 22 via `.nvmrc`, `npm ci` e `npm run check` para lint, unitarios, build limpo e smoke tests.
|
|
34
|
+
- Protecao de `pack`/`publish` via `prepack` e verificacao de defaults de producao Omnizapi, sem URLs customizadas embutidas no artefato de release. `npm run build` continua aceitando variaveis customizadas explicitas.
|
|
35
|
+
- Testes de navegador documentados para Chromium, Firefox e WebKit, com preparacao previa dos binarios Playwright; CI de verificacoes sem publicacao automatica. Testes simulados nao substituem integracao com Meta/proxies reais.
|
|
36
|
+
- Sincronizacao dos links versionados por `scripts/sync-version.mjs` em futuras alteracoes aprovadas com `npm version <nova-versao> --no-git-tag-version`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FourPixel IT
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
SDK Omnizapi para conectar canais Meta WhatsApp, Messenger, Instagram, Telegram e Z-API WhatsApp em aplicacoes web. Coleta o resultado da autorizacao; seu backend valida e finaliza a conexao. Nao envie secret keys ao frontend.
|
|
4
4
|
|
|
5
|
+
Versao atual: **1.0.2**. As mudancas desta versao estao no [changelog](https://unpkg.com/browse/@omnizapi/connect@1.0.2/CHANGELOG.md), disponivel com o pacote publicado.
|
|
6
|
+
|
|
5
7
|
## Instalacao e importacao
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -29,28 +31,30 @@ CommonJS: `const { Omnizapi } = require("@omnizapi/connect")`.
|
|
|
29
31
|
No navegador, o bundle expoe o global `Omnizapi`:
|
|
30
32
|
|
|
31
33
|
```html
|
|
32
|
-
<script src="https://unpkg.com/@omnizapi/connect/dist/omnizapi.min.js"></script>
|
|
34
|
+
<script src="https://unpkg.com/@omnizapi/connect@1.0.2/dist/omnizapi.min.js"></script>
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
O CDN usa uma versao fixa; homologue sua integracao antes do deploy. Imports ESM/CommonJS e `newClient` sao seguros em SSR; `connect` exige navegador e rejeita com `BROWSER_REQUIRED` no servidor. O bundle de script e exclusivo do navegador.
|
|
36
38
|
|
|
37
39
|
## Uso
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
const client = Omnizapi.newClient({ publicKey: "sua-public-key" });
|
|
41
|
-
```
|
|
41
|
+
Crie/reutilize o cliente com `Omnizapi.newClient({ publicKey: "sua-public-key" })` dentro do `try` do handler de clique, para que `INVALID_CONFIGURATION` tambem seja tratado pela UI.
|
|
42
42
|
|
|
43
|
-
Dispare `client.connect({ channelId })`
|
|
43
|
+
Dispare `client.connect({ channelId })` diretamente no clique, sem outro `await` antes, nunca durante renderizacao, montagem ou importacao. Os exemplos completos incluem UI, `try/catch/finally`, tratamento de `reason` e envio ao backend:
|
|
44
44
|
|
|
45
45
|
| Exemplo | Uso |
|
|
46
46
|
| --- | --- |
|
|
47
|
-
| [TypeScript basico](examples/basic.ts) | Botao e mensagem de status no DOM |
|
|
48
|
-
| [HTML com CDN](examples/vanilla.html) | Pagina sem bundler |
|
|
49
|
-
| [React / Next.js](examples/react.tsx) | `'use client'`,
|
|
50
|
-
| [Angular](examples/angular.ts) | Componente com guarda de navegador para SSR |
|
|
51
|
-
| [Vue](examples/vue.vue) | SFC com guarda de navegador para SSR |
|
|
52
|
-
| [Opcoes](examples/with-options.ts) | SANDBOX, URLs explicitas, logo, fluxo padrao/direto e timeout |
|
|
53
|
-
| [Erros](examples/error-handling.ts) | Mensagens para todos os motivos e codigos tipados |
|
|
47
|
+
| [TypeScript basico](https://unpkg.com/browse/@omnizapi/connect@1.0.2/examples/basic.ts) | Botao e mensagem de status no DOM |
|
|
48
|
+
| [HTML com CDN](https://unpkg.com/browse/@omnizapi/connect@1.0.2/examples/vanilla.html) | Pagina sem bundler |
|
|
49
|
+
| [React / Next.js](https://unpkg.com/browse/@omnizapi/connect@1.0.2/examples/react.tsx) | `'use client'`, UI de conexao por componente |
|
|
50
|
+
| [Angular](https://unpkg.com/browse/@omnizapi/connect@1.0.2/examples/angular.ts) | Componente com guarda de navegador para SSR |
|
|
51
|
+
| [Vue](https://unpkg.com/browse/@omnizapi/connect@1.0.2/examples/vue.vue) | SFC com guarda de navegador para SSR |
|
|
52
|
+
| [Opcoes](https://unpkg.com/browse/@omnizapi/connect@1.0.2/examples/with-options.ts) | SANDBOX, URLs explicitas, logo, fluxo padrao/direto e timeout |
|
|
53
|
+
| [Erros](https://unpkg.com/browse/@omnizapi/connect@1.0.2/examples/error-handling.ts) | Mensagens para todos os motivos e codigos tipados |
|
|
54
|
+
|
|
55
|
+
Os links abrem o codigo-fonte dos exemplos da versao 1.0.2, incluido no pacote npm. Nao sao demos hospedadas: adapte as chaves, o canal e o backend na sua aplicacao.
|
|
56
|
+
|
|
57
|
+
Os arquivos `examples/error-handling.ts` e `examples/react.tsx` demonstram `AbortSignal`. No React, o cliente fica em `useRef`, e so e criado no `try` do clique; o cleanup de `useEffect` aborta a tentativa/requisicao pendente sem atualizar a UI desmontada. O exemplo de erros usa `Record<OmnizapiErrorCode, string>` exaustivo e permite cancelar apenas a autorizacao, nao a finalizacao no backend. Nao ha botao para limpar a quarentena nativa.
|
|
54
58
|
|
|
55
59
|
Os exemplos usam `/api/connect-channel` como rota **da sua aplicacao**, nao fornecida por este pacote. Ela deve autenticar a sessao, validar o resultado e responder com HTTP 2xx somente quando a finalizacao tiver sido confirmada. Os exemplos aguardam `fetch` e verificam `response.ok` antes de exibir sucesso. Adapte a autenticacao e a protecao CSRF ao seu backend. Nao registre resultados, tokens, codigos OAuth ou erros brutos que possam conter URLs sensiveis.
|
|
56
60
|
|
|
@@ -83,13 +87,20 @@ Precedencia por URL: **props > `OMNIZAPI_API_URL` / `OMNIZAPI_FRONT_URL` no buil
|
|
|
83
87
|
| Campo | Tipo | Descricao |
|
|
84
88
|
| --- | --- | --- |
|
|
85
89
|
| `channelId` | `string` | Obrigatorio; canal a conectar |
|
|
86
|
-
| `direct` | `boolean` | Solicita Meta WhatsApp Embedded Signup sem o popup proxy; nao se aplica aos outros canais. O SDK tambem escolhe o fluxo nativo com `appCustom` ou na origem do frontend de conexao |
|
|
90
|
+
| `direct` | `boolean` | Solicita Meta WhatsApp Embedded Signup sem o popup proxy; nao se aplica aos outros canais, que sempre usam a janela reservada. O SDK tambem escolhe o fluxo nativo com `appCustom` ou na origem do frontend de conexao, e degrada para o proxy quando a pagina nao pode rodar o nativo |
|
|
87
91
|
| `getQRCode` | `() => Promise<{ connected?: boolean; value?: string }>` | Callback opcional para integracao QR com o frontend externo; veja os limites abaixo |
|
|
88
92
|
| `timeoutMs` | `number` | Prazo total positivo e finito em ms, ate `2147483647`; padrao **600000 (10 minutos)** |
|
|
93
|
+
| `signal` | `AbortSignal` | Opcional; permite interromper a tentativa via `AbortController` |
|
|
89
94
|
|
|
90
95
|
HTTP e carregamento do SDK Facebook tem limite de **30 segundos**, respeitando o prazo total restante da tentativa. O POST ao seu backend nao faz parte desse prazo e precisa de politica propria de timeout.
|
|
91
96
|
|
|
92
|
-
Ha **uma tentativa ativa por pagina**, inclusive entre clientes diferentes. Outra chamada concorrente rejeita com `CONNECTION_IN_PROGRESS`; nao implemente retry automatico para abrir popups.
|
|
97
|
+
Ha **uma tentativa ativa por pagina**, inclusive entre clientes diferentes. Outra chamada concorrente rejeita com `CONNECTION_IN_PROGRESS`; nao implemente retry automatico para abrir popups.
|
|
98
|
+
|
|
99
|
+
O SDK reserva um popup `about:blank` durante o clique, para qualquer canal (com `direct` ou sem), antes de aguardar a configuracao do canal; apos validar a resposta, navega a mesma janela. A janela provisoria e fechada ao encerrar a tentativa ou ao iniciar o fluxo nativo, inclusive quando `appCustom` seleciona o nativo sem `direct`. Fechar a janela reservada antes da navegacao nao cancela a tentativa: o fechamento so resulta em `popup_closed` quando o fluxo ja depende da janela (apos a navegacao) ou quando ela e encontrada fechada na hora de navegar. Ainda trate `POPUP_BLOCKED` e permita nova tentativa por clique. A reserva nao transfere o gesto ao `FB.login`: o fluxo nativo, apos carregar a configuracao/SDK Meta, ainda exige homologacao externa com navegadores reais.
|
|
100
|
+
|
|
101
|
+
**Cancelamento:** passe um sinal novo por tentativa. Se o sinal ja estiver abortado ou for abortado enquanto `connect` estiver pendente, a Promise rejeita com `OmnizapiError.code === "ABORTED"`, nao resolve com `reason: "cancelled"`. O SDK encerra requisicoes pendentes, timers e listeners da tentativa, fecha o popup que controla e restaura seus globais temporarios sem sobrescrever alteracoes do host, nem expor `signal.reason`. Scripts/callbacks de terceiros nao sao removidos; a observacao de um script Meta externo compartilhado pode continuar ate carregar, falhar ou atingir o limite de 30 segundos.
|
|
102
|
+
|
|
103
|
+
Abort nao desfaz uma autorizacao na Meta, nao fecha necessariamente o dialogo nativo e nao remove a quarentena de um login nativo ainda sem callback. Depois que `connect` termina, abortar esse sinal nao cancela automaticamente seu POST; o React passa o sinal tambem ao `fetch`, mas nem isso desfaz operacoes ja recebidas pelo servidor. Confira o estado no backend antes de repetir uma finalizacao sem confirmacao.
|
|
93
104
|
|
|
94
105
|
O retorno e uma uniao discriminada por `success`, nao uma confirmacao de persistencia no seu backend:
|
|
95
106
|
|
|
@@ -111,35 +122,40 @@ Resultados negativos resolvem a Promise e nao significam sempre cancelamento:
|
|
|
111
122
|
| `origin_not_allowed` | Origem da aplicacao nao autorizada para o canal |
|
|
112
123
|
| `unsupported_channel` | Tipo de canal nao suportado |
|
|
113
124
|
|
|
125
|
+
Uma pagina servida com `Cross-Origin-Opener-Policy: same-origin` faz o navegador cortar a referencia da janela popup; o SDK reporta `popup_closed` (ou `POPUP_BLOCKED`), indistinguivel de um fechamento pelo usuario. Nao ha como diferenciar os dois casos via JavaScript: permita nova tentativa por clique e, se possivel, ajuste a politica da pagina de conexao.
|
|
126
|
+
|
|
114
127
|
Falhas tecnicas rejeitam com `OmnizapiError`; use `instanceof OmnizapiError` e `error.code`, nao o texto da mensagem:
|
|
115
128
|
|
|
116
129
|
| Codigo | Significado |
|
|
117
130
|
| --- | --- |
|
|
118
131
|
| `BROWSER_REQUIRED` | Operacao exige navegador |
|
|
119
132
|
| `CONNECTION_IN_PROGRESS` | Tentativa ativa nesta pagina ou login Meta nativo anterior incompleto; veja os limites abaixo |
|
|
120
|
-
| `INVALID_CONFIGURATION` | Props ou
|
|
121
|
-
| `INVALID_OPTIONS` | Opcoes da operacao invalidas, como `channelId` com tipo incorreto ou
|
|
133
|
+
| `INVALID_CONFIGURATION` | Props, ambiente ou APIs de navegador invalidos; conflitos de app/inicializacao do SDK Meta degradam para o fluxo proxy, sem rejeitar |
|
|
134
|
+
| `INVALID_OPTIONS` | Opcoes da operacao invalidas, como `channelId` com tipo incorreto, timeout ou sinal invalido |
|
|
122
135
|
| `NETWORK_ERROR` | Falha de transporte |
|
|
123
136
|
| `HTTP_ERROR` | Resposta HTTP sem sucesso |
|
|
124
137
|
| `INVALID_RESPONSE` | Resposta da API invalida |
|
|
125
138
|
| `POPUP_BLOCKED` | Navegador impediu a abertura do popup |
|
|
126
139
|
| `TIMEOUT` | Prazo de operacao excedido |
|
|
140
|
+
| `ABORTED` | Tentativa interrompida pelo `AbortSignal` da aplicacao, com mensagem segura |
|
|
127
141
|
| `SDK_LOAD_FAILED` | Falha ao carregar/inicializar SDK do provedor |
|
|
128
142
|
| `PROVIDER_ERROR` | Erro reportado pelo provedor |
|
|
129
143
|
|
|
130
|
-
### `client.getListMessengerPages(channelId, code): Promise<unknown>`
|
|
144
|
+
### `client.getListMessengerPages(channelId, code, signal?): Promise<unknown>`
|
|
131
145
|
|
|
132
|
-
Consulta as paginas Messenger usando o codigo OAuth e o canal. Valide o retorno antes de acessa-lo: o schema externo ainda nao foi confirmado, portanto o SDK nao publica DTO de pagina. Nao use cast para inventar esse contrato, nem registre o codigo ou a resposta. A chamada tambem pode rejeitar com erro tecnico e tem timeout HTTP de 30 segundos.
|
|
146
|
+
Consulta as paginas Messenger usando o codigo OAuth e o canal. Valide o retorno antes de acessa-lo: o schema externo ainda nao foi confirmado, portanto o SDK nao publica DTO de pagina. Nao use cast para inventar esse contrato, nem registre o codigo ou a resposta. A chamada tambem pode rejeitar com erro tecnico e tem timeout HTTP de 30 segundos. O terceiro argumento aceita um `AbortSignal` opcional; um sinal abortado (antes ou durante a chamada) rejeita com `OmnizapiError.code === "ABORTED"`, e um sinal invalido rejeita com `INVALID_OPTIONS`.
|
|
133
147
|
|
|
134
148
|
## Protocolo de popup
|
|
135
149
|
|
|
136
150
|
Este contrato exige deploy coordenado do frontend/proxy e backend externos; nenhum desses servicos e alterado neste repositorio. Nao ha fallback para mensagens sem os identificadores exigidos.
|
|
137
151
|
|
|
138
|
-
1. O SDK gera `attemptId` por tentativa. Popups abertos diretamente no `frontUrl` recebem `attemptId` na query. No OAuth Messenger/Instagram, o `state` JSON e `{ currentUrl, attemptId, channelId }`; o proxy deve preserva-lo e vincula-lo a sessao autorizada, ao canal e ao tenant. `state` e query nao sao prova de autorizacao por si so.
|
|
152
|
+
1. O SDK gera `attemptId` por tentativa. Popups abertos diretamente no `frontUrl` recebem `attemptId` na query; as rotas `/connect/telegram` e `/connect/whatsapp-web` tambem recebem `pk` (a chave publica) na query, permitindo ao frontend consultar as origens autorizadas do canal e restringir o `targetOrigin` da resposta. No OAuth Messenger/Instagram, o `state` JSON e `{ currentUrl, attemptId, channelId }`; o proxy deve preserva-lo e vincula-lo a sessao autorizada, ao canal e ao tenant. `state` e query nao sao prova de autorizacao por si so.
|
|
139
153
|
2. A pagina final deve estar na origem exata de `frontUrl` e emitir da **propria janela popup** aberta pelo SDK, nao de iframe, outra janela ou backend. Ela responde ao `window.opener` usando `postMessage` com `type: 'after-connect'`, `attemptId`, `channelId`, `success` e as credenciais aplicaveis. `attemptId` e `channelId` devem corresponder exatamente a tentativa ativa.
|
|
140
154
|
3. O SDK verifica a origem exata do frontend, `event.source` igual ao popup ativo e os dois identificadores. O emissor usa `targetOrigin` igual a origem exata da aplicacao autorizada, nunca wildcard e nunca uma origem derivada de query/state nao validados.
|
|
141
155
|
4. Sucesso dos proxies Meta exige `code`; Telegram exige `botToken`. `Z_API_WHATSAPP` pode retornar sucesso autenticado sem credenciais, mas o backend deve confirmar a conexao real para aquele canal/tenant. Para negativo, envie `success: false` e o `reason` tipado aplicavel, sem credenciais.
|
|
142
156
|
|
|
157
|
+
**Privacidade de `state`: `currentUrl` continua sendo `window.location.href` COMPLETO, incluindo caminho, query e fragmento.** Esta rodada nao reduz esse valor a origem: a compatibilidade dos proxies com uma URL minimizada ainda e desconhecida. Tokens ou outros dados sensiveis na query/fragmento da pagina podem assim ser copiados para o `state` OAuth e expostos ao provedor, proxy, historico ou logs de URLs. Evite iniciar a conexao em paginas com esses dados e nao registre `state` nem URLs completas. Fica pendente verificar com os responsaveis pelos proxies se aceitam apenas a origem antes de propor qualquer mudanca coordenada desse contrato.
|
|
158
|
+
|
|
143
159
|
Mensagens com origem, janela, identificadores ou formato incorretos sao ignoradas; a tentativa continua aguardando conclusao, fechamento ou timeout. Uma mensagem de sucesso sem a credencial exigida resulta em `not_completed`.
|
|
144
160
|
|
|
145
161
|
Trecho ilustrativo **no frontend externo**, apos o servidor validar a sessao e a autorizacao da tentativa. `authorizedSession` representa dados validados pelo servidor, nao um DTO deste SDK; nao a construa lendo parametros da URL sem validacao:
|
|
@@ -158,7 +174,7 @@ if (window.opener) {
|
|
|
158
174
|
|
|
159
175
|
O Meta Embedded Signup **nativo** nao fornece `attemptId` nem uma referencia customizada da janela emissora (`event.source`) para correlacao. Ele usa a allowlist exata `https://www.facebook.com` / `https://web.facebook.com` e o callback `FB.login`. Nao se pode garantir o isolamento de eventos nativos tardios entre tentativas; essas verificacoes nao sao garantia absoluta de seguranca.
|
|
160
176
|
|
|
161
|
-
|
|
177
|
+
Um login nativo fica em quarentena ate a Meta responder o callback `FB.login` (com codigo, cancelamento ou erro) ou ate a tentativa ter sucesso. O callback, inclusive tardio, libera apenas a quarentena da tentativa a que pertence; nao libera a de outra tentativa. Fechar/cancelar o dialogo ou receber um evento de cancelamento nao garante que esse callback ja tenha chegado. Se um login terminar por timeout, abort ou cancelamento **sem callback**, novas tentativas nativas continuam em `CONNECTION_IN_PROGRESS`: aguarde o callback ou **recarregue a pagina** para tentar outro login nativo. Um callback recebido de cancelamento nao exige reload. Um `FB.login` que falha ao iniciar (excecao sincrona, sem abrir dialogo e sem callback futuro) libera a quarentena imediatamente, sem exigir reload. Essa restricao reduz o risco de atribuir a uma nova tentativa a resposta tardia de um dialogo anterior; nao se aplica aos popups proxy.
|
|
162
178
|
|
|
163
179
|
Durante uma tentativa, apenas `__omnizapiPublicKey`, `__omnizapiCurrentChannel` e `__omnizapiGetQrCode` sao publicados temporariamente para o frontend externo. Uma funcao QR no `window` da aplicacao nao atravessa origens nem e serializada por `postMessage`: o frontend precisa de uma integracao explicitamente autorizada e compativel com a politica de mesma origem. Este repositorio nao valida por si so o fluxo Z-API real nem confirma essa integracao externa.
|
|
164
180
|
|
|
@@ -170,26 +186,58 @@ Quando o canal tem app proprio (`appCustom` no `sdk-info`), o SDK muda de compor
|
|
|
170
186
|
|
|
171
187
|
| Onde no app da Meta | O que cadastrar |
|
|
172
188
|
| --- | --- |
|
|
173
|
-
| Facebook Login > Configuracoes > Dominios permitidos para o SDK do JavaScript | Todas as origens onde o seu site chama `connect` (ex.: `https://
|
|
189
|
+
| Facebook Login > Configuracoes > Dominios permitidos para o SDK do JavaScript | Todas as origens onde o seu site chama `connect` (ex.: `https://app.example.com`), e o `frontUrl` da plataforma se voce tambem conecta pelo painel |
|
|
174
190
|
| Facebook Login > Configuracoes > URIs de redirecionamento do OAuth validos | `${frontUrl}/oauth/proxy-messenger` e `${frontUrl}/oauth/proxy-instagram` da marca que voce usa (ex.: `https://app.omni.z-api.io/oauth/proxy-messenger`) |
|
|
175
191
|
| Configuracoes basicas > Dominios do app | O dominio do seu site e o da plataforma |
|
|
176
192
|
| WhatsApp > Embedded Signup | A configuracao cujo id e o `configId` cadastrado na plataforma; o app precisa ter os produtos WhatsApp, Messenger e Instagram habilitados conforme os canais que vai conectar |
|
|
177
193
|
|
|
178
|
-
Sem o dominio do seu site nos dominios do SDK, a Meta
|
|
194
|
+
Sem o dominio do seu site nos dominios do SDK, a Meta pode recusar o `FB.login`. `PROVIDER_ERROR` depende de a Meta reportar um erro ao SDK; nao e possivel garantir esse codigo para toda falha de dominio. Sem os redirects corretos, o OAuth do Messenger e do Instagram pode ser bloqueado pela Meta. Sem a origem do seu site na allowlist do canal, o SDK resolve com `origin_not_allowed` antes de navegar para a autorizacao; uma janela provisoria ja pode ter sido reservada e sera fechada.
|
|
195
|
+
|
|
196
|
+
**Inicializacao Meta:** o SDK inicializa uma vez e reutiliza o mesmo `appId` somente quando essa inicializacao foi rastreada pelo proprio SDK. Nao reinicializa silenciosamente o `FB` compartilhado com outro app: quando a pagina nao pode rodar o nativo com seguranca — `FB` do host com inicializacao desconhecida, app conflitante, `appId` retornado pela API que nao e uma string numerica valida ou inicializacao que nao pode ser observada — a tentativa **degrada para o fluxo proxy** na janela reservada, em vez de rejeitar com `INVALID_CONFIGURATION`. Se a janela reservada tiver sido fechada ou bloqueada, a tentativa termina com `popup_closed` ou `POPUP_BLOCKED`. A quarentena de login nativo (`CONNECTION_IN_PROGRESS`) nao degrada: ela protege a atribuicao de callbacks tardios da Meta.
|
|
197
|
+
|
|
198
|
+
Com o fallback, um `FB` preexistente do host (inclusive de outro app) nao impede mais a conexao: o login acontece na janela da plataforma. Para canais com `appCustom`, isso exige que o **seu** app da Meta conheca o dominio da plataforma, conforme a tabela acima; sem os redirects e dominios corretos, a Meta pode bloquear o fluxo proxy do seu app. Nao reinicialize o `FB` por fora depois que o SDK rastrear seu app. Nao presuma que `direct: false` force proxy nem que `direct: true` garanta nativo: `appCustom`, a origem do frontend e agora a disponibilidade do nativo na pagina tambem decidem o fluxo.
|
|
199
|
+
|
|
200
|
+
Em SDKs carregados pela biblioteca, chamadas externas ao `FB.init` atual sao encaminhadas normalmente, mas invalidam o app conhecido: uma conexao nativa posterior degrada para o proxy em vez de usar o app errado. Referencias ao `init` original salvas antes dessa observacao nao podem ser monitoradas. Se um script externo expirar sem falha conclusiva, seu carregamento ainda pode terminar: novos SDKs nao recebem proveniencia propria ate recarregar a pagina. O script do host nao e removido.
|
|
201
|
+
|
|
202
|
+
## Desenvolvimento e verificacao
|
|
203
|
+
|
|
204
|
+
Use **Node.js 22**, conforme `.nvmrc`, e as dependencias do lockfile:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
nvm use
|
|
208
|
+
npm ci
|
|
209
|
+
npm run check
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`npm run check` executa lint, testes unitarios, build limpo e smoke tests do pacote. Ele limpa os overrides `OMNIZAPI_API_URL` / `OMNIZAPI_FRONT_URL` no ambiente dos subprocessos, sem alterar o ambiente do chamador. A verificacao de release exige os padroes de producao Omnizapi (`https://api.omni.z-api.io` e `https://app.omni.z-api.io`), sem URLs customizadas embutidas no artefato. O lifecycle `prepack` protege automaticamente `npm pack` e `npm publish`; nao use `--ignore-scripts` para contornar essa protecao na preparacao de uma release. A CI faz verificacoes, nao publicacao automatica.
|
|
213
|
+
|
|
214
|
+
Para os testes locais de navegador, prepare antes os binarios dos tres engines:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
npm exec playwright install chromium firefox webkit
|
|
218
|
+
npm run test:browser
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`test:browser` cobre Chromium, Firefox e WebKit usando o artefato ja compilado: execute `npm run check` antes, pois esse teste nao recompila o SDK. Testes com provedores simulados nao homologam o SDK Meta, os proxies, credenciais ou canais reais; o fluxo nativo e os servicos externos continuam exigindo teste de integracao.
|
|
222
|
+
|
|
223
|
+
`npm run build` continua permitindo builds customizados com variaveis explicitas `OMNIZAPI_API_URL` e `OMNIZAPI_FRONT_URL`. Isso nao substitui o build com defaults de producao exigido pelo guard de release. As props `apiUrl` / `frontUrl` continuam sendo o modo de configurar o consumidor sem recompilar o SDK.
|
|
224
|
+
|
|
225
|
+
O hook de versao `scripts/sync-version.mjs` sincroniza os links UNPKG e scripts CDN do README/exemplo vanilla em futuras execucoes aprovadas de `npm version <nova-versao> --no-git-tag-version`. Isso nao publica o pacote.
|
|
179
226
|
|
|
180
227
|
## Checklist de deploy
|
|
181
228
|
|
|
182
|
-
- [ ]
|
|
183
|
-
- [ ]
|
|
229
|
+
- [ ] Antes de uma publicacao futura aprovada, executar as verificacoes e conferir exports default/named `Omnizapi`, tipos na raiz e `dist/omnizapi.min.js`; manter imports, versoes CDN e configuracao dos consumidores coordenados.
|
|
230
|
+
- [ ] Conferir os defaults de producao no artefato de release. Para consumidores customizados, configurar `apiUrl` / `frontUrl` nas props; conferir staging e ambas as URLs de sandbox. Variaveis no build ficam restritas a builds customizados explicitos.
|
|
184
231
|
- [ ] Manter na API as rotas existentes `GET /instances/:channelId/sdk-info` e `POST /v1/channels/:channelId/list-messenger-pages`, com autenticacao por chave publica, schema validado e sem exposicao de secrets.
|
|
185
232
|
- [ ] Manter no frontend `/oauth/proxy-cloud-api`, `/oauth/proxy-messenger`, `/oauth/proxy-instagram`, `/connect/telegram` e `/connect/whatsapp-web`, inclusive ao usar uma URL base com prefixo.
|
|
186
233
|
- [ ] Conferir a logo customizada e o asset padrao `${frontUrl}/logos/SVG/Ativo%2016.svg`, acessiveis por HTTPS e com identidade Omnizapi.
|
|
187
234
|
- [ ] Autorizar as origens exatas da aplicacao por canal e configurar CORS da API para essas origens, metodos e headers (`Authorization`, `Content-Type`). Validacao client-side nao substitui autorizacao no servidor.
|
|
188
235
|
- [ ] Cadastrar os redirects Meta exatos `${frontUrl}/oauth/proxy-messenger` e `${frontUrl}/oauth/proxy-instagram`, alem de dominios/configuracoes do Embedded Signup e app IDs corretos.
|
|
189
236
|
- [ ] Implementar preservacao de `state`, sessao autorizada e protocolo `after-connect` acima em todas as rotas; confirmar origem final, janela emissora, `attemptId`, `channelId` e `targetOrigin` exatos. Conferir politicas de navegador/COOP que possam remover `opener`.
|
|
237
|
+
- [ ] Revisar exposicao de query/fragmento em `state.currentUrl`, que permanece completo. Verificar com os proxies a compatibilidade com origem apenas antes de qualquer futura minimizacao; nao assumir suporte.
|
|
190
238
|
- [ ] Validar no backend sessao, CSRF, canal/tenant e credenciais especificas do provedor antes de finalizar; trocar/armazenar tokens somente no servidor, limitar repeticao/replay e nao aceitar `success: true` do navegador como prova suficiente.
|
|
191
|
-
- [ ] Homologar cancelamento, fechamento/bloqueio de popup, concorrencia, timeout, mensagens de origem/janela/tentativa incorretas e falhas HTTP; validar em servicos reais a integracao QR e cada canal, inclusive Z-API. Os exemplos nao substituem essa homologacao.
|
|
239
|
+
- [ ] Homologar abort, cancelamento com/sem callback Meta (inclusive tardio), fechamento/bloqueio de popup, concorrencia, timeout, conflitos de app ID (que degradam para o fluxo proxy), mensagens de origem/janela/tentativa incorretas e falhas HTTP; validar em servicos reais o gesto do login nativo, a integracao QR e cada canal, inclusive Z-API. Os exemplos nao substituem essa homologacao.
|
|
192
240
|
|
|
193
241
|
## Licenca
|
|
194
242
|
|
|
195
|
-
MIT - FourPixel IT. Autor: FourPixel IT.
|
|
243
|
+
MIT - Copyright (c) 2026 FourPixel IT. Autor: FourPixel IT. Texto completo no arquivo local `LICENSE` e na [licenca do pacote](https://unpkg.com/browse/@omnizapi/connect@1.0.2/LICENSE) apos a publicacao correspondente.
|