WaClient sem fazer fork dele. Um plugin pode conectar-se ao pipeline de stanzas de entrada, expor seu próprio coordinator em client[exposeAs], contribuir com eventos tipados em client.on e fazer limpeza no disconnect — tudo com inferência completa de TypeScript, sem augmentation global de módulo.
@zapo-js/voip é a implementação de referência; veja o guia de VoIP para o que parece um plugin finalizado.
O que é um plugin
Cada plugin é um valorWaClientPluginDefinition passado pela opção plugins:
- Plugins de comportamento rodam efeitos colaterais (registram handlers de stanza, ouvem eventos, agendam trabalho) e não expõem nada no client.
- Plugins de exposição também publicam um valor em
client[exposeAs]— tipicamente um objeto coordinator, comoclient.voip.
client.on / client.once / client.off apenas quando o plugin está no array plugins. A inferência é derivada do valor: se o plugin não estiver instalado, o nome do evento não existe no tipo do client.
Autoria de um plugin
UsedefineWaClientPlugin para autoria com tipos seguros. Ele tem duas sobrecargas.
Plugin de comportamento
Plugin de exposição
A sobrecarga de exposição recebe três parâmetros de tipo: a chaveexposeAs como literal string, o tipo do valor retornado por setup e o mapa de eventos. A inferência flui do valor de volta para client.on e client[exposeAs]:
metricsPlugin() em plugins, client.metrics é tipado como Metrics e client.on('metrics_tick', ...) é verificado contra MetricsEvents.
O parâmetro
exposeAs é restrito a K extends keyof WaClient ? never : K. Tentar expor um nome que já existe no client — 'message', 'group', 'voip' se voip também estiver instalado — é um erro de TypeScript no call site.Contexto do plugin
setup recebe um WaClientPluginContext:
Handlers de entrada
registerIncomingHandler({ tag, prepend, handler }) permite interceptar uma tag específica de stanza ('message', 'iq', 'call', 'ack', 'receipt', …). Retorne true de handler para sinalizar que você cuidou da stanza (o core client não vai dar ack novamente); retorne false para deixar o resto do pipeline rodar.
registerIncomingStanzaFilter roda ainda mais cedo e pode descartar stanzas inteiramente.
Extensão de eventos tipados
Plugins encadeiam seus eventos no host client por meio de um marcador fantasma__pluginEvents carregado pelo valor de retorno de defineWaClientPlugin. O terceiro parâmetro genérico é o mapa de eventos:
WaClient é derivado da tupla plugins via WaClientPluginEventsFromPlugins. O efeito prático: um evento voip_* existe em client.on apenas quando voipPlugin() está em plugins.
WaClient diferente no mesmo projeto não herda eventos de plugins estranhos.
Ciclo de vida
Plugins instalam durantenew WaClient(...):
- O client é construído e seus coordinators são conectados.
installWaClientPluginsitera o arraypluginsem ordem. Para cada plugin:- O
idé verificado contra ids vistos anteriormente. - Se
exposeAsestiver definido, o nome é verificado contra outros plugins e contra membros existentes doWaClient. setup(ctx)roda. O valor de retorno (para plugins de exposição) é publicado como um getter não-configurável e não-gravável no client.
- O
- No
client.disconnect(), depois que os handlers de entrada drenam, os callbacks dedisposeregistrados rodam em ordem reversa (LIFO). Um dispose que lança é logado e o resto ainda roda. - No próximo
client.connect(), os plugins são reinstalados do zero — odisconnect()anterior os disposeou, então oconnect()rodasetup(ctx)novamente. Os accessorsclient[exposeAs]continuam funcionando entre reconexões (eles resolvem contra a instância de coordinator recém-instalada), esetupvê um contexto limpo a cada vez.
Condições de erro
installWaClientPlugins lança sincronamente durante a construção do client nestes casos:
idduplicado —"duplicate wa client plugin id: <id>". Cada plugin precisa ter um id único no arrayplugins.exposeAsduplicado —"duplicate wa client plugin exposeAs: <name>". Dois plugins de exposição não podem publicar o mesmo nome.- Colisão com um built-in —
"wa client plugin exposeAs \"<name>\" collides with a reserved client member". TentarexposeAs: 'message','group','on', etc. falha em runtime (e em compile time via a guardakeyof WaClient).
Veja também
Guia de VoIP
Faça e receba chamadas do WhatsApp via
@zapo-js/voip, o plugin de referência.Configuração
Onde
plugins fica em WaClientOptions.