@whanext/core 0.19.5 → 0.19.8

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 CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.8
4
+
5
+ ### Fixed
6
+ - The Zapo mailbox (`messages`, `threads`, and `contacts`) is now persisted in the shared SQLite store and full history sync is enabled. This lets Zapo retain parent message secrets required to decrypt `secretEncryptedMessage` edit addons after restart/offline resume.
7
+ - History sync now hydrates the trusted-contact/privacy-token state used by Zapo when preparing outgoing messages, including history-derived token metadata and NCT salt that can be required for `tctoken`/`cstoken` generation. Historical/bootstrap messages are still filtered by WhaNext and do not become live command events unless `processOfflineMessages` is explicitly enabled.
8
+ - WhatsApp negative publish ACK `463` is normalized as `MESSAGE_REACHOUT_LOCKED` with `ackCode: 463` instead of surfacing as `UNKNOWN_ERROR`, allowing consumers to avoid retry/error-reply loops while the account is reach-out time-locked.
9
+
10
+ ### Compatibility
11
+ - Public message/edit/delete event shapes are unchanged.
12
+ - Existing shared multi-account stores are reused in place; the mailbox domains are created inside the same `state.sqlite` and remain isolated by `sessionId`.
13
+ - The first connection after this update may perform a larger history sync because mailbox persistence is now enabled deliberately.
14
+
15
+ ## 0.19.7
16
+
17
+ ### Fixed
18
+ - Zapo edit/revoke protocol mutations are now processed sequentially in arrival order. Back-to-back `MESSAGE_EDIT` -> `REVOKE` events can no longer race and make `messageDeleted.message` expose the pre-edit snapshot.
19
+ - Protocol mutations discovered through the regular `message` event use the same ordered queue as native `message_protocol` events, preserving consistent AntiEdit/AntiDelete behavior across both Zapo delivery shapes.
20
+
21
+ ## 0.19.6
22
+
23
+ ### Fixed
24
+ - Multi-account Zapo sessions now share a single SQLite store per sibling auth root and stay isolated by stable `sessionId`, matching Zapo's multi-session model.
25
+ - Existing per-account `state.sqlite` sessions are migrated into the shared store on first use; removing one account auth directory resets only that account instead of affecting sibling sessions.
26
+ - Zapo session/store handles are released on disconnect and terminal connection failures, preventing failed/restarted accounts from leaving stale SQLite resources behind.
27
+ - Fatal disconnects such as `401`/`516` stop the reconnect loop and surface `AUTH_EXPIRED`; routine `515` reconnects immediately and `402` uses an extended backoff.
28
+ - Passkey-gated linking now fails fast with `AUTH_PASSKEY_REQUIRED` when Zapo reports `auth_passkey_required` without a signer, instead of hanging until the login timeout.
29
+ - `messageDeleted` and `messageEdited` can restore the previous message from a bounded persistent snapshot archive in `whanext-messages.sqlite` when the in-memory cache no longer contains it, including after cache eviction or a process restart.
30
+ - Persistent mutation snapshots are isolated per `sessionId`, retained for up to 7 days, and capped at 20,000 messages per session to avoid unbounded storage growth.
31
+
32
+ ### Compatibility
33
+ - Public `messageDeleted` / `messageEdited` event shapes are unchanged.
34
+ - Existing single-account custom auth paths keep their previous per-directory SQLite layout.
35
+ - `messages` remains disabled in the Zapo mailbox store; WhaNext persists only the compact message snapshot needed for edit/delete recovery in its own SQLite file.
36
+
3
37
  ## 0.19.5
4
38
 
5
39
  ### Fixed
@@ -33,12 +33,12 @@ npm install wa-store-migrate
33
33
 
34
34
  A conversão oficial lê `{ creds, keys }` do auth multifile, chama `migrate({ from: 'baileys', to: 'zapo', data })` e grava o resultado em um store Zapo novo. Consulte o guia oficial **Migrating from Baileys** do Zapo para usar o exemplo atualizado da versão que estiver instalada.
35
35
 
36
- No WhaNext, o destino deve ser o `state.sqlite` dentro do diretório `auth` da conta. O `sessionId` precisa ser estável:
36
+ No WhaNext, o `sessionId` precisa ser estável:
37
37
 
38
38
  - `default` em `create()` quando `accountId` não é informado;
39
39
  - o `id` da conta em `createMulti()`.
40
40
 
41
- Converta cada conta separadamente quando usar multi-account.
41
+ Em uma conta única com caminho `auth` customizado, o destino continua sendo `<auth>/state.sqlite`. Em multi-account, uma conversão antiga gravada em `<authRoot>/<id>/state.sqlite` é detectada e consolidada automaticamente no store compartilhado `<authRoot>/state.sqlite` na primeira inicialização da v0.19.6. Converta cada conta separadamente; o provider faz a consolidação sem misturar os `sessionId`s.
42
42
 
43
43
  ## Mensagens recebidas após reconexão
44
44
 
package/README.md CHANGED
@@ -141,7 +141,7 @@ Nesse exemplo, `&open`, `!open`, `.abrir`, `&a` e `a` funcionam. `open` e `abrir
141
141
 
142
142
  ## Múltiplas contas
143
143
 
144
- Para manter duas, três ou mais contas de WhatsApp no mesmo processo, use `createMulti()`. Cada conta possui conexão, sessão, cache, reconexão e identidade próprios. A instância conjunta apenas coordena essas aplicações independentes.
144
+ Para manter duas, três ou mais contas de WhatsApp no mesmo processo, use `createMulti()`. Cada conta possui conexão, `sessionId`, cache, reconexão e identidade próprios. No provider Zapo, contas irmãs compartilham o mesmo backend SQLite e permanecem isoladas pelo `sessionId`, evitando abrir um store concorrente por número.
145
145
 
146
146
  ```ts
147
147
  import {
@@ -179,7 +179,7 @@ await multi.login({
179
179
  });
180
180
  ```
181
181
 
182
- Quando `auth` não é informado na conta, o WhaNext cria automaticamente caminhos separados como `./sessions/principal`, `./sessions/secundaria` e `./sessions/terceira`. O mesmo diretório de sessão não pode ser usado por duas contas do provider padrão.
182
+ Quando `auth` não é informado na conta, o WhaNext cria automaticamente caminhos separados como `./sessions/principal`, `./sessions/secundaria` e `./sessions/terceira`. Esses diretórios continuam identificando cada conta, enquanto o provider usa `./sessions/state.sqlite` como store compartilhado. O mesmo `id`/`sessionId` não deve ser usado por duas contas diferentes.
183
183
 
184
184
  Uma conta específica continua sendo um `WhaNextApp` completo:
185
185
 
@@ -197,7 +197,7 @@ if (principal?.isReady) {
197
197
 
198
198
  ## Mensagens apagadas
199
199
 
200
- Revogações recebidas pelo WhatsApp são expostas pelo evento `messageDeleted`. Quando a mensagem original ainda estiver no cache recente, o payload inclui `message`, que pode ser republicada ou usada para baixar a mídia pelas APIs existentes.
200
+ Revogações recebidas pelo WhatsApp são expostas pelo evento `messageDeleted`. O provider mantém em `whanext-messages.sqlite` um snapshot compacto e persistente das mensagens recentes para recuperar `message` mesmo após expulsão do cache em memória ou reinício do processo. O snapshot é isolado por `sessionId`, retido por até 7 dias e limitado às 20.000 mensagens mais recentes por sessão.
201
201
 
202
202
  ```ts
203
203
  app.on('messageDeleted', async ({ message, deletedByMe }) => {
@@ -211,7 +211,7 @@ O evento também informa `deletedById` quando o WhatsApp fornece a identidade re
211
211
 
212
212
  ## Mensagens editadas
213
213
 
214
- Edições recebidas pelo WhatsApp são expostas pelo evento `messageEdited`. A partir da 0.17.1, o provider inclui suporte ao envelope criptografado `secretEncryptedMessage` usado atualmente pelo WhatsApp para edições. Quando a versão anterior ainda estiver no cache recente, o payload inclui `previous`; `message` contém a versão atual.
214
+ Edições recebidas pelo WhatsApp são expostas pelo evento `messageEdited`. O provider inclui suporte ao envelope criptografado `secretEncryptedMessage` e mantém um snapshot compacto persistente para recuperar `previous` quando a versão anterior saiu do cache em memória ou após reinício do processo. `message` contém a versão atual.
215
215
 
216
216
  ```ts
217
217
  app.on('messageEdited', async ({ previous, message, editedByMe }) => {
@@ -221,7 +221,7 @@ app.on('messageEdited', async ({ previous, message, editedByMe }) => {
221
221
  });
222
222
  ```
223
223
 
224
- Após cada edição, a nova versão substitui a anterior no cache recente. Assim, edições consecutivas da mesma mensagem sempre comparam a versão atual com a imediatamente anterior.
224
+ Após cada edição, a nova versão substitui a anterior no cache e no snapshot persistente. Assim, edições consecutivas da mesma mensagem comparam a versão atual com a imediatamente anterior.
225
225
 
226
226
  ## Logging
227
227
 
package/dist/index.d.ts CHANGED
@@ -610,7 +610,7 @@ declare class DeferredReply {
610
610
  delete(): Promise<void>;
611
611
  }
612
612
 
613
- type WhaNextErrorCode = 'AUTH_INVALID_PHONE' | 'AUTH_EXPIRED' | 'CONNECTION_CLOSED' | 'CONNECTION_FAILED' | 'GROUP_NOT_FOUND' | 'MEMBER_NOT_FOUND' | 'BOT_NOT_ADMIN' | 'MESSAGE_NOT_FOUND' | 'MEDIA_NOT_AVAILABLE' | 'MUTE_DISABLED' | 'STORAGE_ERROR' | 'ARGUMENT_MISSING' | 'ARGUMENT_INVALID' | 'COMMAND_NOT_ALLOWED' | 'COMMAND_COOLDOWN' | 'COMMAND_BUSY' | 'COMMAND_LOAD_FAILED' | 'PROVIDER_ERROR' | 'UNKNOWN_ERROR';
613
+ type WhaNextErrorCode = 'AUTH_INVALID_PHONE' | 'AUTH_EXPIRED' | 'AUTH_PASSKEY_REQUIRED' | 'CONNECTION_CLOSED' | 'CONNECTION_FAILED' | 'GROUP_NOT_FOUND' | 'MEMBER_NOT_FOUND' | 'BOT_NOT_ADMIN' | 'MESSAGE_NOT_FOUND' | 'MEDIA_NOT_AVAILABLE' | 'MESSAGE_REACHOUT_LOCKED' | 'MUTE_DISABLED' | 'STORAGE_ERROR' | 'ARGUMENT_MISSING' | 'ARGUMENT_INVALID' | 'COMMAND_NOT_ALLOWED' | 'COMMAND_COOLDOWN' | 'COMMAND_BUSY' | 'COMMAND_LOAD_FAILED' | 'PROVIDER_ERROR' | 'UNKNOWN_ERROR';
614
614
  interface WhaNextErrorOptions {
615
615
  cause?: unknown;
616
616
  context?: Readonly<Record<string, unknown>>;