zapo-js 0.1.1 → 0.2.0

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.
Files changed (589) hide show
  1. package/README.md +20 -4
  2. package/dist/appstate/WaAppStateCrypto.js +19 -26
  3. package/dist/appstate/WaAppStateSyncClient.js +293 -181
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
  5. package/dist/appstate/constants.js +4 -3
  6. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  7. package/dist/appstate/index.js +8 -6
  8. package/dist/appstate/utils.js +9 -34
  9. package/dist/auth/WaAuthClient.js +43 -61
  10. package/dist/auth/flow/WaAuthCredentialsFlow.js +22 -15
  11. package/dist/auth/index.js +1 -8
  12. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  13. package/dist/auth/pairing/WaPairingFlow.js +34 -26
  14. package/dist/auth/pairing/WaQrFlow.js +37 -24
  15. package/dist/client/WaClient.js +275 -324
  16. package/dist/client/WaClientFactory.js +500 -133
  17. package/dist/client/connection/WaConnectionManager.js +301 -0
  18. package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
  19. package/dist/client/connection/WaReceiptQueue.js +51 -0
  20. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
  21. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  22. package/dist/client/coordinators/WaGroupCoordinator.js +30 -16
  23. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  24. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +439 -701
  25. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  26. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  27. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  28. package/dist/client/coordinators/WaRetryCoordinator.js +242 -57
  29. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  30. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  31. package/dist/client/dirty.js +74 -48
  32. package/dist/client/events/chat.js +4 -3
  33. package/dist/client/events/devices.js +72 -0
  34. package/dist/client/events/group.js +62 -47
  35. package/dist/client/events/identity.js +22 -0
  36. package/dist/client/events/privacy-token.js +39 -0
  37. package/dist/client/history-sync.js +94 -63
  38. package/dist/client/incoming.js +60 -27
  39. package/dist/client/mailbox.js +24 -23
  40. package/dist/client/messages.js +107 -31
  41. package/dist/client/messaging/fanout.js +199 -0
  42. package/dist/client/messaging/key-protocol.js +130 -0
  43. package/dist/client/messaging/participants.js +193 -0
  44. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  45. package/dist/client/tokens/cs-token.js +50 -0
  46. package/dist/client/tokens/tc-token.js +25 -0
  47. package/dist/crypto/core/hkdf.js +3 -8
  48. package/dist/crypto/core/index.js +2 -5
  49. package/dist/crypto/core/keys.js +6 -7
  50. package/dist/crypto/core/nonce.js +2 -0
  51. package/dist/crypto/core/primitives.js +12 -23
  52. package/dist/crypto/core/random.js +26 -23
  53. package/dist/crypto/curves/Ed25519.js +7 -8
  54. package/dist/crypto/curves/X25519.js +38 -22
  55. package/dist/crypto/index.js +1 -3
  56. package/dist/crypto/math/constants.js +13 -36
  57. package/dist/crypto/math/edwards.js +171 -44
  58. package/dist/crypto/math/fe.js +706 -0
  59. package/dist/crypto/math/mod.js +10 -3
  60. package/dist/esm/appstate/WaAppStateCrypto.js +7 -14
  61. package/dist/esm/appstate/WaAppStateSyncClient.js +284 -172
  62. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
  63. package/dist/esm/appstate/constants.js +3 -2
  64. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  65. package/dist/esm/appstate/index.js +2 -2
  66. package/dist/esm/appstate/utils.js +8 -30
  67. package/dist/esm/auth/WaAuthClient.js +43 -61
  68. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +22 -15
  69. package/dist/esm/auth/index.js +0 -3
  70. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  71. package/dist/esm/auth/pairing/WaPairingFlow.js +28 -20
  72. package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
  73. package/dist/esm/client/WaClient.js +275 -324
  74. package/dist/esm/client/WaClientFactory.js +501 -134
  75. package/dist/esm/client/connection/WaConnectionManager.js +297 -0
  76. package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
  77. package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
  78. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
  79. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  80. package/dist/esm/client/coordinators/WaGroupCoordinator.js +23 -9
  81. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  82. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +443 -705
  83. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  84. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  85. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  86. package/dist/esm/client/coordinators/WaRetryCoordinator.js +244 -59
  87. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  88. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  89. package/dist/esm/client/dirty.js +69 -43
  90. package/dist/esm/client/events/chat.js +4 -3
  91. package/dist/esm/client/events/devices.js +68 -0
  92. package/dist/esm/client/events/group.js +53 -39
  93. package/dist/esm/client/events/identity.js +19 -0
  94. package/dist/esm/client/events/privacy-token.js +36 -0
  95. package/dist/esm/client/history-sync.js +91 -60
  96. package/dist/esm/client/incoming.js +61 -28
  97. package/dist/esm/client/mailbox.js +24 -23
  98. package/dist/esm/client/messages.js +108 -32
  99. package/dist/esm/client/messaging/fanout.js +196 -0
  100. package/dist/esm/client/messaging/key-protocol.js +127 -0
  101. package/dist/esm/client/messaging/participants.js +190 -0
  102. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  103. package/dist/esm/client/tokens/cs-token.js +46 -0
  104. package/dist/esm/client/tokens/tc-token.js +18 -0
  105. package/dist/esm/crypto/core/hkdf.js +3 -8
  106. package/dist/esm/crypto/core/index.js +2 -3
  107. package/dist/esm/crypto/core/keys.js +3 -4
  108. package/dist/esm/crypto/core/nonce.js +2 -0
  109. package/dist/esm/crypto/core/primitives.js +12 -22
  110. package/dist/esm/crypto/core/random.js +25 -23
  111. package/dist/esm/crypto/curves/Ed25519.js +4 -5
  112. package/dist/esm/crypto/curves/X25519.js +35 -19
  113. package/dist/esm/crypto/index.js +0 -1
  114. package/dist/esm/crypto/math/constants.js +12 -35
  115. package/dist/esm/crypto/math/edwards.js +174 -47
  116. package/dist/esm/crypto/math/fe.js +691 -0
  117. package/dist/esm/crypto/math/mod.js +10 -1
  118. package/dist/esm/index.js +1 -1
  119. package/dist/esm/infra/log/ConsoleLogger.js +18 -17
  120. package/dist/esm/infra/log/PinoLogger.js +15 -9
  121. package/dist/esm/infra/log/types.js +11 -1
  122. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  123. package/dist/esm/infra/perf/BoundedTaskQueue.js +16 -18
  124. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  125. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  126. package/dist/esm/infra/perf/StoreLock.js +77 -0
  127. package/dist/esm/media/WaMediaCrypto.js +96 -16
  128. package/dist/esm/media/WaMediaTransferClient.js +251 -91
  129. package/dist/esm/media/conn.js +10 -6
  130. package/dist/esm/media/constants.js +6 -2
  131. package/dist/esm/message/WaMessageClient.js +30 -32
  132. package/dist/esm/message/ack.js +6 -6
  133. package/dist/esm/message/addon-crypto.js +59 -0
  134. package/dist/esm/message/content.js +195 -9
  135. package/dist/esm/message/icdc.js +76 -0
  136. package/dist/esm/message/incoming.js +129 -122
  137. package/dist/esm/message/index.js +2 -0
  138. package/dist/esm/message/phash.js +3 -1
  139. package/dist/esm/message/reporting-token.js +425 -0
  140. package/dist/esm/message/use-case-secret.js +49 -0
  141. package/dist/esm/protocol/appstate.js +27 -0
  142. package/dist/esm/protocol/browser.js +10 -18
  143. package/dist/esm/protocol/constants.js +6 -3
  144. package/dist/esm/protocol/defaults.js +6 -0
  145. package/dist/esm/protocol/index.js +2 -11
  146. package/dist/esm/protocol/jid.js +133 -52
  147. package/dist/esm/protocol/media.js +3 -3
  148. package/dist/esm/protocol/message.js +61 -1
  149. package/dist/esm/protocol/nodes.js +4 -0
  150. package/dist/esm/protocol/notification.js +3 -1
  151. package/dist/esm/protocol/privacy-token.js +17 -0
  152. package/dist/esm/protocol/privacy.js +55 -0
  153. package/dist/esm/protocol/stream.js +26 -1
  154. package/dist/esm/protocol/usync.js +11 -0
  155. package/dist/esm/retry/codec.js +216 -0
  156. package/dist/esm/retry/constants.js +1 -1
  157. package/dist/esm/retry/index.js +3 -2
  158. package/dist/esm/retry/parse.js +88 -86
  159. package/dist/esm/retry/replay.js +54 -51
  160. package/dist/esm/retry/tracker.js +94 -0
  161. package/dist/esm/signal/api/SignalDeviceSyncApi.js +276 -92
  162. package/dist/esm/signal/api/SignalDigestSyncApi.js +17 -8
  163. package/dist/esm/signal/api/SignalIdentitySyncApi.js +67 -37
  164. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +86 -67
  165. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  166. package/dist/esm/signal/api/SignalSessionSyncApi.js +36 -34
  167. package/dist/esm/signal/api/result-map.js +10 -0
  168. package/dist/esm/signal/constants.js +0 -4
  169. package/dist/esm/signal/crypto/WaAdvSignature.js +13 -9
  170. package/dist/esm/signal/{store/sqlite.js → encoding.js} +93 -60
  171. package/dist/esm/signal/group/SenderKeyChain.js +28 -23
  172. package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
  173. package/dist/esm/signal/group/SenderKeyManager.js +144 -115
  174. package/dist/esm/signal/index.js +2 -0
  175. package/dist/esm/signal/registration/keygen.js +6 -2
  176. package/dist/esm/signal/registration/utils.js +1 -0
  177. package/dist/esm/signal/session/SignalProtocol.js +164 -53
  178. package/dist/esm/signal/session/SignalRatchet.js +24 -15
  179. package/dist/esm/signal/session/SignalSession.js +14 -9
  180. package/dist/esm/signal/session/resolver.js +221 -0
  181. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  182. package/dist/esm/store/createStore.js +100 -188
  183. package/dist/esm/store/index.js +1 -10
  184. package/dist/esm/store/locks/appstate.lock.js +26 -0
  185. package/dist/esm/store/locks/auth.lock.js +15 -0
  186. package/dist/esm/store/locks/contact.lock.js +20 -0
  187. package/dist/esm/store/locks/device-list.lock.js +20 -0
  188. package/dist/esm/store/locks/message.lock.js +21 -0
  189. package/dist/esm/store/locks/participants.lock.js +20 -0
  190. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  191. package/dist/esm/store/locks/retry.lock.js +29 -0
  192. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  193. package/dist/esm/store/locks/signal.lock.js +63 -0
  194. package/dist/esm/store/locks/thread.lock.js +21 -0
  195. package/dist/esm/store/noop.store.js +4 -7
  196. package/dist/esm/store/providers/memory/appstate.store.js +38 -16
  197. package/dist/esm/store/providers/memory/contact.store.js +5 -0
  198. package/dist/esm/store/providers/memory/device-list.store.js +12 -34
  199. package/dist/esm/store/providers/memory/message.store.js +11 -5
  200. package/dist/esm/store/providers/memory/participants.store.js +1 -8
  201. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  202. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  203. package/dist/esm/store/providers/memory/sender-key.store.js +11 -8
  204. package/dist/esm/store/providers/memory/signal.store.js +47 -18
  205. package/dist/esm/store/providers/memory/thread.store.js +5 -0
  206. package/dist/esm/transport/WaComms.js +28 -24
  207. package/dist/esm/transport/WaWebSocket.js +115 -18
  208. package/dist/esm/transport/binary/constants.js +0 -30
  209. package/dist/esm/transport/binary/decoder.js +8 -8
  210. package/dist/esm/transport/binary/encoder.js +10 -9
  211. package/dist/esm/transport/binary/index.js +0 -1
  212. package/dist/esm/transport/index.js +1 -0
  213. package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
  214. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -21
  215. package/dist/esm/transport/node/WaNodeTransport.js +0 -3
  216. package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
  217. package/dist/esm/transport/node/builders/business.js +129 -0
  218. package/dist/esm/transport/node/builders/global.js +370 -0
  219. package/dist/esm/transport/node/builders/index.js +7 -3
  220. package/dist/esm/transport/node/builders/message.js +63 -230
  221. package/dist/esm/transport/node/builders/pairing.js +2 -27
  222. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  223. package/dist/esm/transport/node/builders/privacy.js +48 -0
  224. package/dist/esm/transport/node/builders/profile.js +70 -0
  225. package/dist/esm/transport/node/builders/retry.js +10 -22
  226. package/dist/esm/transport/node/builders/usync.js +45 -0
  227. package/dist/esm/transport/node/helpers.js +125 -5
  228. package/dist/esm/transport/node/usync.js +5 -0
  229. package/dist/esm/transport/node/xml.js +35 -14
  230. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  231. package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
  232. package/dist/esm/transport/noise/WaNoiseCert.js +4 -7
  233. package/dist/esm/transport/noise/WaNoiseSession.js +77 -29
  234. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  235. package/dist/esm/transport/proxy.js +27 -0
  236. package/dist/esm/transport/stream/parse.js +17 -48
  237. package/dist/esm/util/bytes.js +67 -45
  238. package/dist/esm/util/coercion.js +6 -14
  239. package/dist/esm/util/index.js +5 -0
  240. package/dist/esm/util/primitives.js +40 -14
  241. package/dist/index.js +7 -1
  242. package/dist/infra/log/ConsoleLogger.js +18 -17
  243. package/dist/infra/log/PinoLogger.js +15 -9
  244. package/dist/infra/log/types.js +12 -0
  245. package/dist/infra/perf/BackgroundQueue.js +482 -0
  246. package/dist/infra/perf/BoundedTaskQueue.js +16 -18
  247. package/dist/infra/perf/PromiseDedup.js +24 -0
  248. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  249. package/dist/infra/perf/StoreLock.js +81 -0
  250. package/dist/media/WaMediaCrypto.js +95 -15
  251. package/dist/media/WaMediaTransferClient.js +284 -91
  252. package/dist/media/conn.js +10 -6
  253. package/dist/media/constants.js +6 -2
  254. package/dist/message/WaMessageClient.js +31 -33
  255. package/dist/message/ack.js +6 -6
  256. package/dist/message/addon-crypto.js +65 -0
  257. package/dist/message/content.js +198 -9
  258. package/dist/message/icdc.js +81 -0
  259. package/dist/message/incoming.js +127 -120
  260. package/dist/message/index.js +2 -0
  261. package/dist/message/phash.js +3 -1
  262. package/dist/message/reporting-token.js +429 -0
  263. package/dist/message/use-case-secret.js +55 -0
  264. package/dist/protocol/appstate.js +28 -1
  265. package/dist/protocol/browser.js +10 -18
  266. package/dist/protocol/constants.js +26 -1
  267. package/dist/protocol/defaults.js +6 -0
  268. package/dist/protocol/index.js +23 -42
  269. package/dist/protocol/jid.js +140 -52
  270. package/dist/protocol/media.js +3 -3
  271. package/dist/protocol/message.js +62 -2
  272. package/dist/protocol/nodes.js +4 -0
  273. package/dist/protocol/notification.js +3 -1
  274. package/dist/protocol/privacy-token.js +20 -0
  275. package/dist/protocol/privacy.js +58 -0
  276. package/dist/protocol/stream.js +27 -2
  277. package/dist/protocol/usync.js +14 -0
  278. package/dist/retry/codec.js +220 -0
  279. package/dist/retry/constants.js +1 -1
  280. package/dist/retry/index.js +7 -5
  281. package/dist/retry/parse.js +88 -85
  282. package/dist/retry/replay.js +52 -49
  283. package/dist/retry/tracker.js +97 -0
  284. package/dist/signal/api/SignalDeviceSyncApi.js +273 -89
  285. package/dist/signal/api/SignalDigestSyncApi.js +17 -8
  286. package/dist/signal/api/SignalIdentitySyncApi.js +66 -36
  287. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +82 -63
  288. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  289. package/dist/signal/api/SignalSessionSyncApi.js +36 -34
  290. package/dist/signal/api/result-map.js +13 -0
  291. package/dist/signal/constants.js +1 -5
  292. package/dist/signal/crypto/WaAdvSignature.js +11 -7
  293. package/dist/signal/{store/sqlite.js → encoding.js} +94 -61
  294. package/dist/signal/group/SenderKeyChain.js +27 -22
  295. package/dist/signal/group/SenderKeyCodec.js +5 -6
  296. package/dist/signal/group/SenderKeyManager.js +144 -115
  297. package/dist/signal/index.js +15 -1
  298. package/dist/signal/registration/keygen.js +6 -2
  299. package/dist/signal/registration/utils.js +1 -0
  300. package/dist/signal/session/SignalProtocol.js +164 -53
  301. package/dist/signal/session/SignalRatchet.js +24 -15
  302. package/dist/signal/session/SignalSession.js +14 -9
  303. package/dist/signal/session/resolver.js +224 -0
  304. package/dist/store/contracts/privacy-token.store.js +2 -0
  305. package/dist/store/createStore.js +100 -188
  306. package/dist/store/index.js +15 -33
  307. package/dist/store/locks/appstate.lock.js +29 -0
  308. package/dist/store/locks/auth.lock.js +18 -0
  309. package/dist/store/locks/contact.lock.js +23 -0
  310. package/dist/store/locks/device-list.lock.js +23 -0
  311. package/dist/store/locks/message.lock.js +24 -0
  312. package/dist/store/locks/participants.lock.js +23 -0
  313. package/dist/store/locks/privacy-token.lock.js +21 -0
  314. package/dist/store/locks/retry.lock.js +32 -0
  315. package/dist/store/locks/sender-key.lock.js +55 -0
  316. package/dist/store/locks/signal.lock.js +66 -0
  317. package/dist/store/locks/thread.lock.js +24 -0
  318. package/dist/store/noop.store.js +4 -7
  319. package/dist/store/providers/memory/appstate.store.js +36 -14
  320. package/dist/store/providers/memory/contact.store.js +5 -0
  321. package/dist/store/providers/memory/device-list.store.js +12 -34
  322. package/dist/store/providers/memory/message.store.js +11 -5
  323. package/dist/store/providers/memory/participants.store.js +1 -8
  324. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  325. package/dist/store/providers/memory/retry.store.js +77 -2
  326. package/dist/store/providers/memory/sender-key.store.js +14 -11
  327. package/dist/store/providers/memory/signal.store.js +54 -25
  328. package/dist/store/providers/memory/thread.store.js +5 -0
  329. package/dist/transport/WaComms.js +30 -26
  330. package/dist/transport/WaWebSocket.js +148 -18
  331. package/dist/transport/binary/constants.js +1 -31
  332. package/dist/transport/binary/decoder.js +8 -8
  333. package/dist/transport/binary/encoder.js +10 -9
  334. package/dist/transport/binary/index.js +0 -4
  335. package/dist/transport/index.js +7 -1
  336. package/dist/transport/keepalive/WaKeepAlive.js +1 -7
  337. package/dist/transport/node/WaNodeOrchestrator.js +25 -21
  338. package/dist/transport/node/WaNodeTransport.js +0 -3
  339. package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
  340. package/dist/transport/node/builders/business.js +137 -0
  341. package/dist/transport/node/builders/global.js +375 -0
  342. package/dist/transport/node/builders/index.js +29 -17
  343. package/dist/transport/node/builders/message.js +64 -236
  344. package/dist/transport/node/builders/pairing.js +2 -29
  345. package/dist/transport/node/builders/privacy-token.js +46 -0
  346. package/dist/transport/node/builders/privacy.js +55 -0
  347. package/dist/transport/node/builders/profile.js +78 -0
  348. package/dist/transport/node/builders/retry.js +9 -21
  349. package/dist/transport/node/builders/usync.js +49 -0
  350. package/dist/transport/node/helpers.js +131 -4
  351. package/dist/transport/node/usync.js +8 -0
  352. package/dist/transport/node/xml.js +35 -14
  353. package/dist/transport/noise/WaClientPayload.js +13 -13
  354. package/dist/transport/noise/WaFrameCodec.js +47 -32
  355. package/dist/transport/noise/WaNoiseCert.js +5 -8
  356. package/dist/transport/noise/WaNoiseSession.js +77 -29
  357. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  358. package/dist/transport/proxy.js +34 -0
  359. package/dist/transport/stream/parse.js +20 -52
  360. package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
  361. package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
  362. package/dist/types/appstate/constants.d.ts +1 -0
  363. package/dist/types/appstate/encoding.d.ts +7 -0
  364. package/dist/types/appstate/index.d.ts +3 -3
  365. package/dist/types/appstate/utils.d.ts +0 -3
  366. package/dist/types/auth/WaAuthClient.d.ts +10 -12
  367. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  368. package/dist/types/auth/index.d.ts +0 -4
  369. package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
  370. package/dist/types/auth/types.d.ts +7 -9
  371. package/dist/types/client/WaClient.d.ts +42 -25
  372. package/dist/types/client/WaClientFactory.d.ts +33 -26
  373. package/dist/types/client/connection/WaConnectionManager.d.ts +66 -0
  374. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
  375. package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
  376. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
  377. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  378. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -2
  379. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -38
  380. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  381. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  382. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  383. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +8 -0
  384. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  385. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  386. package/dist/types/client/dirty.d.ts +1 -0
  387. package/dist/types/client/events/devices.d.ts +20 -0
  388. package/dist/types/client/events/group.d.ts +2 -1
  389. package/dist/types/client/events/identity.d.ts +9 -0
  390. package/dist/types/client/events/privacy-token.d.ts +7 -0
  391. package/dist/types/client/history-sync.d.ts +9 -6
  392. package/dist/types/client/incoming.d.ts +3 -1
  393. package/dist/types/client/index.d.ts +1 -1
  394. package/dist/types/client/mailbox.d.ts +3 -5
  395. package/dist/types/client/messages.d.ts +1 -2
  396. package/dist/types/client/messaging/fanout.d.ts +14 -0
  397. package/dist/types/client/messaging/key-protocol.d.ts +18 -0
  398. package/dist/types/client/messaging/participants.d.ts +13 -0
  399. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  400. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  401. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  402. package/dist/types/client/types.d.ts +75 -4
  403. package/dist/types/crypto/core/hkdf.d.ts +0 -6
  404. package/dist/types/crypto/core/index.d.ts +2 -3
  405. package/dist/types/crypto/core/nonce.d.ts +2 -0
  406. package/dist/types/crypto/core/primitives.d.ts +0 -1
  407. package/dist/types/crypto/core/random.d.ts +2 -7
  408. package/dist/types/crypto/index.d.ts +0 -1
  409. package/dist/types/crypto/math/constants.d.ts +4 -2
  410. package/dist/types/crypto/math/fe.d.ts +30 -0
  411. package/dist/types/crypto/math/mod.d.ts +0 -2
  412. package/dist/types/crypto/math/types.d.ts +11 -4
  413. package/dist/types/index.d.ts +5 -3
  414. package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
  415. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  416. package/dist/types/infra/log/types.d.ts +1 -0
  417. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  418. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
  419. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  420. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  421. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  422. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  423. package/dist/types/media/WaMediaTransferClient.d.ts +16 -15
  424. package/dist/types/media/constants.d.ts +1 -1
  425. package/dist/types/media/index.d.ts +1 -1
  426. package/dist/types/media/types.d.ts +15 -2
  427. package/dist/types/message/addon-crypto.d.ts +25 -0
  428. package/dist/types/message/content.d.ts +8 -0
  429. package/dist/types/message/icdc.d.ts +13 -0
  430. package/dist/types/message/index.d.ts +2 -0
  431. package/dist/types/message/reporting-token.d.ts +18 -0
  432. package/dist/types/message/types.d.ts +45 -6
  433. package/dist/types/message/use-case-secret.d.ts +20 -0
  434. package/dist/types/protocol/appstate.d.ts +47 -0
  435. package/dist/types/protocol/constants.d.ts +8 -3
  436. package/dist/types/protocol/defaults.d.ts +6 -0
  437. package/dist/types/protocol/index.d.ts +2 -11
  438. package/dist/types/protocol/jid.d.ts +22 -5
  439. package/dist/types/protocol/message.d.ts +60 -0
  440. package/dist/types/protocol/nodes.d.ts +4 -0
  441. package/dist/types/protocol/notification.d.ts +2 -0
  442. package/dist/types/protocol/privacy-token.d.ts +17 -0
  443. package/dist/types/protocol/privacy.d.ts +75 -0
  444. package/dist/types/protocol/stream.d.ts +30 -0
  445. package/dist/types/protocol/usync.d.ts +11 -0
  446. package/dist/types/retry/codec.d.ts +3 -0
  447. package/dist/types/retry/index.d.ts +4 -3
  448. package/dist/types/retry/parse.d.ts +5 -2
  449. package/dist/types/retry/replay.d.ts +0 -4
  450. package/dist/types/retry/tracker.d.ts +20 -0
  451. package/dist/types/retry/types.d.ts +10 -4
  452. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +15 -2
  453. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  454. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  455. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  456. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  457. package/dist/types/signal/api/result-map.d.ts +1 -0
  458. package/dist/types/signal/constants.d.ts +0 -3
  459. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  460. package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
  461. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  462. package/dist/types/signal/index.d.ts +3 -0
  463. package/dist/types/signal/session/SignalProtocol.d.ts +19 -4
  464. package/dist/types/signal/session/resolver.d.ts +22 -0
  465. package/dist/types/store/contracts/appstate.store.d.ts +4 -1
  466. package/dist/types/store/contracts/contact.store.d.ts +1 -0
  467. package/dist/types/store/contracts/device-list.store.d.ts +0 -3
  468. package/dist/types/store/contracts/message.store.d.ts +1 -0
  469. package/dist/types/store/contracts/participants.store.d.ts +0 -1
  470. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  471. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  472. package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
  473. package/dist/types/store/contracts/signal.store.d.ts +13 -0
  474. package/dist/types/store/contracts/thread.store.d.ts +1 -0
  475. package/dist/types/store/createStore.d.ts +1 -1
  476. package/dist/types/store/index.d.ts +5 -13
  477. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  478. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  479. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  480. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  481. package/dist/types/store/locks/message.lock.d.ts +3 -0
  482. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  483. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  484. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  485. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  486. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  487. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  488. package/dist/types/store/providers/memory/appstate.store.d.ts +3 -1
  489. package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
  490. package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
  491. package/dist/types/store/providers/memory/message.store.d.ts +1 -0
  492. package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
  493. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  494. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  495. package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
  496. package/dist/types/store/providers/memory/signal.store.d.ts +8 -1
  497. package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
  498. package/dist/types/store/types.d.ts +49 -58
  499. package/dist/types/transport/WaWebSocket.d.ts +3 -1
  500. package/dist/types/transport/binary/constants.d.ts +0 -30
  501. package/dist/types/transport/binary/index.d.ts +0 -1
  502. package/dist/types/transport/index.d.ts +2 -1
  503. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
  504. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  505. package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
  506. package/dist/types/transport/node/builders/business.d.ts +29 -0
  507. package/dist/types/transport/node/builders/global.d.ts +102 -0
  508. package/dist/types/transport/node/builders/group.d.ts +4 -6
  509. package/dist/types/transport/node/builders/index.d.ts +7 -3
  510. package/dist/types/transport/node/builders/message.d.ts +20 -30
  511. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  512. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  513. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  514. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  515. package/dist/types/transport/node/builders/retry.d.ts +2 -5
  516. package/dist/types/transport/node/builders/usync.d.ts +21 -0
  517. package/dist/types/transport/node/helpers.d.ts +13 -0
  518. package/dist/types/transport/node/usync.d.ts +2 -0
  519. package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
  520. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  521. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  522. package/dist/types/transport/proxy.d.ts +6 -0
  523. package/dist/types/transport/stream/parse.d.ts +0 -1
  524. package/dist/types/transport/types.d.ts +18 -1
  525. package/dist/types/util/bytes.d.ts +5 -0
  526. package/dist/types/util/index.d.ts +5 -0
  527. package/dist/types/util/primitives.d.ts +2 -0
  528. package/dist/util/bytes.js +72 -46
  529. package/dist/util/coercion.js +6 -14
  530. package/dist/util/index.js +23 -0
  531. package/dist/util/primitives.js +42 -14
  532. package/package.json +52 -9
  533. package/proto/index.js +1 -1
  534. package/dist/crypto/core/constants.js +0 -4
  535. package/dist/crypto/core/encoding.js +0 -29
  536. package/dist/esm/crypto/core/constants.js +0 -1
  537. package/dist/esm/crypto/core/encoding.js +0 -25
  538. package/dist/esm/retry/outbound.js +0 -83
  539. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  540. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -169
  541. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  542. package/dist/esm/store/providers/sqlite/connection.js +0 -240
  543. package/dist/esm/store/providers/sqlite/contact.store.js +0 -61
  544. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -155
  545. package/dist/esm/store/providers/sqlite/message.store.js +0 -119
  546. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  547. package/dist/esm/store/providers/sqlite/participants.store.js +0 -85
  548. package/dist/esm/store/providers/sqlite/retry.store.js +0 -144
  549. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -203
  550. package/dist/esm/store/providers/sqlite/signal.store.js +0 -353
  551. package/dist/esm/store/providers/sqlite/thread.store.js +0 -72
  552. package/dist/esm/util/base64.js +0 -18
  553. package/dist/esm/util/signal-address.js +0 -5
  554. package/dist/retry/outbound.js +0 -88
  555. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  556. package/dist/store/providers/sqlite/appstate.store.js +0 -173
  557. package/dist/store/providers/sqlite/auth.store.js +0 -180
  558. package/dist/store/providers/sqlite/connection.js +0 -276
  559. package/dist/store/providers/sqlite/contact.store.js +0 -65
  560. package/dist/store/providers/sqlite/device-list.store.js +0 -159
  561. package/dist/store/providers/sqlite/message.store.js +0 -123
  562. package/dist/store/providers/sqlite/migrations.js +0 -350
  563. package/dist/store/providers/sqlite/participants.store.js +0 -89
  564. package/dist/store/providers/sqlite/retry.store.js +0 -148
  565. package/dist/store/providers/sqlite/sender-key.store.js +0 -207
  566. package/dist/store/providers/sqlite/signal.store.js +0 -357
  567. package/dist/store/providers/sqlite/thread.store.js +0 -76
  568. package/dist/types/appstate/store/sqlite.d.ts +0 -21
  569. package/dist/types/crypto/core/constants.d.ts +0 -1
  570. package/dist/types/crypto/core/encoding.d.ts +0 -11
  571. package/dist/types/retry/outbound.d.ts +0 -4
  572. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  573. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -15
  574. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  575. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  576. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -10
  577. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -18
  578. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -11
  579. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  580. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -13
  581. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -16
  582. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -25
  583. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -46
  584. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -11
  585. package/dist/types/util/base64.d.ts +0 -4
  586. package/dist/types/util/signal-address.d.ts +0 -2
  587. package/dist/util/base64.js +0 -24
  588. package/dist/util/signal-address.js +0 -8
  589. /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
@@ -1,8 +1,7 @@
1
1
  import { promisify } from 'node:util';
2
2
  import { unzip } from 'node:zlib';
3
3
  import { proto } from '../proto.js';
4
- import { decodeProtoBytes } from '../util/base64.js';
5
- import { toBytesView } from '../util/bytes.js';
4
+ import { decodeProtoBytes, toBytesView } from '../util/bytes.js';
6
5
  import { longToNumber } from '../util/primitives.js';
7
6
  const unzipAsync = promisify(unzip);
8
7
  const HANDLED_SYNC_TYPES = new Set([
@@ -11,6 +10,7 @@ const HANDLED_SYNC_TYPES = new Set([
11
10
  proto.Message.HistorySyncType.FULL,
12
11
  proto.Message.HistorySyncType.PUSH_NAME
13
12
  ]);
13
+ const HISTORY_SYNC_MAX_PENDING_WRITES = 1024;
14
14
  export async function processHistorySyncNotification(deps, notification) {
15
15
  const syncType = notification.syncType;
16
16
  if (syncType === null || syncType === undefined || !HANDLED_SYNC_TYPES.has(syncType)) {
@@ -28,15 +28,85 @@ export async function processHistorySyncNotification(deps, notification) {
28
28
  pushnames: historySync.pushnames.length
29
29
  });
30
30
  const nowMs = Date.now();
31
+ const pendingWrites = [];
32
+ for (const pn of historySync.pushnames) {
33
+ if (!pn.id) {
34
+ continue;
35
+ }
36
+ pendingWrites[pendingWrites.length] = deps.writeBehind.persistContactAsync({
37
+ jid: pn.id,
38
+ pushName: pn.pushname ?? undefined,
39
+ lastUpdatedMs: nowMs
40
+ });
41
+ if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
42
+ await flushPendingWrites(pendingWrites);
43
+ }
44
+ }
31
45
  let messagesCount = 0;
32
- const conversationPromises = [];
33
46
  for (const conversation of historySync.conversations) {
34
- conversationPromises.push(persistConversation(deps, conversation, nowMs).then((count) => {
35
- messagesCount += count;
36
- }));
47
+ const threadJid = conversation.id;
48
+ if (!threadJid) {
49
+ deps.logger.debug('skipping history sync conversation without thread jid');
50
+ continue;
51
+ }
52
+ pendingWrites[pendingWrites.length] = deps.writeBehind.persistThreadAsync({
53
+ jid: threadJid,
54
+ name: conversation.name ?? undefined,
55
+ unreadCount: conversation.unreadCount ?? undefined,
56
+ archived: conversation.archived ?? undefined,
57
+ pinned: conversation.pinned ?? undefined,
58
+ muteEndMs: longToNumber(conversation.muteEndTime) || undefined,
59
+ markedAsUnread: conversation.markedAsUnread ?? undefined,
60
+ ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
61
+ });
62
+ if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
63
+ await flushPendingWrites(pendingWrites);
64
+ }
65
+ for (const histMsg of conversation.messages ?? []) {
66
+ const webMsg = histMsg.message;
67
+ if (!webMsg?.key?.id) {
68
+ continue;
69
+ }
70
+ const timestampMs = longToNumber(webMsg.messageTimestamp) * 1000;
71
+ pendingWrites[pendingWrites.length] = deps.writeBehind.persistMessageAsync({
72
+ id: webMsg.key.id,
73
+ threadJid,
74
+ senderJid: webMsg.key.participant ?? undefined,
75
+ fromMe: webMsg.key.fromMe === true,
76
+ timestampMs: timestampMs || undefined,
77
+ messageBytes: webMsg.message
78
+ ? proto.Message.encode(webMsg.message).finish()
79
+ : undefined
80
+ });
81
+ if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
82
+ await flushPendingWrites(pendingWrites);
83
+ }
84
+ messagesCount += 1;
85
+ }
86
+ }
87
+ if (deps.onPrivacyTokens) {
88
+ const tokenConversations = [];
89
+ for (const conversation of historySync.conversations) {
90
+ if (!conversation.id)
91
+ continue;
92
+ if (conversation.tcToken ||
93
+ conversation.tcTokenTimestamp ||
94
+ conversation.tcTokenSenderTimestamp) {
95
+ tokenConversations[tokenConversations.length] = {
96
+ jid: conversation.id,
97
+ tcToken: conversation.tcToken,
98
+ tcTokenTimestamp: longToNumber(conversation.tcTokenTimestamp) || undefined,
99
+ tcTokenSenderTimestamp: longToNumber(conversation.tcTokenSenderTimestamp) || undefined
100
+ };
101
+ }
102
+ }
103
+ if (tokenConversations.length > 0) {
104
+ pendingWrites[pendingWrites.length] = deps.onPrivacyTokens(tokenConversations);
105
+ }
106
+ }
107
+ if (deps.onNctSalt && historySync.nctSalt) {
108
+ pendingWrites[pendingWrites.length] = deps.onNctSalt(historySync.nctSalt);
37
109
  }
38
- const pushnamePromise = persistPushnames(deps, historySync.pushnames, nowMs);
39
- await Promise.all([...conversationPromises, pushnamePromise]);
40
110
  const event = {
41
111
  syncType,
42
112
  messagesCount,
@@ -45,8 +115,21 @@ export async function processHistorySyncNotification(deps, notification) {
45
115
  chunkOrder: historySync.chunkOrder ?? undefined,
46
116
  progress: historySync.progress ?? undefined
47
117
  };
118
+ await flushPendingWrites(pendingWrites);
48
119
  deps.emitEvent('history_sync_chunk', event);
49
120
  }
121
+ async function flushPendingWrites(pendingWrites) {
122
+ if (pendingWrites.length === 0) {
123
+ return;
124
+ }
125
+ const pendingCount = pendingWrites.length;
126
+ const batch = new Array(pendingCount);
127
+ for (let index = 0; index < pendingCount; index += 1) {
128
+ batch[index] = pendingWrites[index];
129
+ }
130
+ pendingWrites.length = 0;
131
+ await Promise.all(batch);
132
+ }
50
133
  async function downloadHistorySyncBlob(deps, notification) {
51
134
  if (notification.initialHistBootstrapInlinePayload) {
52
135
  return decodeProtoBytes(notification.initialHistBootstrapInlinePayload, 'initialHistBootstrapInlinePayload');
@@ -65,55 +148,3 @@ async function downloadHistorySyncBlob(deps, notification) {
65
148
  fileEncSha256
66
149
  });
67
150
  }
68
- async function persistConversation(deps, conversation, _nowMs) {
69
- const threadJid = conversation.id;
70
- if (!threadJid) {
71
- deps.logger.debug('skipping history sync conversation without thread jid');
72
- return 0;
73
- }
74
- const messages = conversation.messages ?? [];
75
- const messageRecords = [];
76
- for (const histMsg of messages) {
77
- const webMsg = histMsg.message;
78
- if (!webMsg?.key?.id) {
79
- continue;
80
- }
81
- const timestampMs = longToNumber(webMsg.messageTimestamp) * 1000;
82
- const messageBytes = webMsg.message
83
- ? proto.Message.encode(webMsg.message).finish()
84
- : undefined;
85
- messageRecords.push({
86
- id: webMsg.key.id,
87
- threadJid,
88
- senderJid: webMsg.key.participant ?? undefined,
89
- fromMe: webMsg.key.fromMe === true,
90
- timestampMs: timestampMs || undefined,
91
- messageBytes
92
- });
93
- }
94
- const threadPromise = deps.threadStore.upsert({
95
- jid: threadJid,
96
- name: conversation.name ?? undefined,
97
- unreadCount: conversation.unreadCount ?? undefined,
98
- archived: conversation.archived ?? undefined,
99
- pinned: conversation.pinned ?? undefined,
100
- muteEndMs: longToNumber(conversation.muteEndTime) || undefined,
101
- markedAsUnread: conversation.markedAsUnread ?? undefined,
102
- ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
103
- });
104
- const messagePromises = messageRecords.map((record) => deps.messageStore.upsert(record));
105
- await Promise.all([threadPromise, ...messagePromises]);
106
- return messageRecords.length;
107
- }
108
- async function persistPushnames(deps, pushnames, nowMs) {
109
- if (pushnames.length === 0) {
110
- return;
111
- }
112
- await Promise.all(pushnames
113
- .filter((pn) => !!pn.id)
114
- .map((pn) => deps.contactStore.upsert({
115
- jid: pn.id,
116
- pushName: pn.pushname ?? undefined,
117
- lastUpdatedMs: nowMs
118
- })));
119
- }
@@ -1,10 +1,16 @@
1
1
  import { parseGroupNotificationEvents } from './events/group.js';
2
- import { WA_NODE_TAGS, WA_NOTIFICATION_TYPES } from '../protocol/constants.js';
3
- import { buildInboundReceiptAckNode, buildInboundRetryReceiptAckNode } from '../transport/node/builders/message.js';
4
- import { buildNotificationAckNode } from '../transport/node/builders/pairing.js';
5
- import { getFirstNodeChild, getNodeChildrenByTag } from '../transport/node/helpers.js';
6
- import { parseOptionalInt } from '../transport/stream/parse.js';
7
- import { toError } from '../util/primitives.js';
2
+ import { WA_DISCONNECT_REASONS, WA_NODE_TAGS, WA_NOTIFICATION_TYPES } from '../protocol/constants.js';
3
+ import { buildAckNode } from '../transport/node/builders/global.js';
4
+ import { getFirstNodeChild, getNodeChildrenNonEmptyAttrValuesByTag } from '../transport/node/helpers.js';
5
+ import { parseOptionalInt, toError } from '../util/primitives.js';
6
+ const FAILURE_REASON_TO_DISCONNECT = {
7
+ 401: WA_DISCONNECT_REASONS.FAILURE_NOT_AUTHORIZED,
8
+ 403: WA_DISCONNECT_REASONS.FAILURE_LOCKED,
9
+ 406: WA_DISCONNECT_REASONS.FAILURE_BANNED,
10
+ 405: WA_DISCONNECT_REASONS.FAILURE_CLIENT_TOO_OLD,
11
+ 409: WA_DISCONNECT_REASONS.FAILURE_BAD_USER_AGENT,
12
+ 503: WA_DISCONNECT_REASONS.FAILURE_SERVICE_UNAVAILABLE
13
+ };
8
14
  const LOGOUT_FAILURE_REASONS = new Set([401, 403, 406]);
9
15
  const DISCONNECT_FAILURE_REASONS = new Set([405, 409, 503]);
10
16
  const CORE_NOTIFICATION_TYPES = new Set([
@@ -31,6 +37,8 @@ const OUT_OF_SCOPE_NOTIFICATION_TYPES = new Set([
31
37
  'waffle',
32
38
  'hosted'
33
39
  ]);
40
+ const NOTIFICATION_TYPES_WITH_PARTICIPANT_ACK = new Set(['mediaretry', 'psa']);
41
+ const NOTIFICATION_TYPES_WITHOUT_TYPE_ACK = new Set(['encrypt', 'devices']);
34
42
  export function createIncomingBaseEvent(node) {
35
43
  return {
36
44
  rawNode: node,
@@ -64,7 +72,9 @@ function classifyNotificationType(notificationType) {
64
72
  }
65
73
  async function applyFailureAction(options, reason, clearStoredCredentials) {
66
74
  try {
67
- await options.disconnect();
75
+ options.stopComms();
76
+ const disconnectReason = FAILURE_REASON_TO_DISCONNECT[reason] ?? WA_DISCONNECT_REASONS.STREAM_ERROR_OTHER;
77
+ await options.disconnect(disconnectReason, clearStoredCredentials, reason);
68
78
  if (clearStoredCredentials) {
69
79
  await options.clearStoredCredentials();
70
80
  }
@@ -109,11 +119,19 @@ export function createIncomingReceiptHandler(options) {
109
119
  await options.handleIncomingRetryReceipt(node);
110
120
  }
111
121
  else {
112
- await sendSafeAck(options.logger, options.sendNode, buildInboundRetryReceiptAckNode(node));
122
+ await sendSafeAck(options.logger, options.sendNode, buildAckNode({
123
+ kind: 'receipt',
124
+ node,
125
+ retryType: true
126
+ }));
113
127
  }
114
128
  return true;
115
129
  }
116
- await sendSafeAck(options.logger, options.sendNode, buildInboundReceiptAckNode(node));
130
+ await sendSafeAck(options.logger, options.sendNode, buildAckNode({
131
+ kind: 'receipt',
132
+ node,
133
+ includeParticipant: receiptType !== 'server-error'
134
+ }));
117
135
  return true;
118
136
  };
119
137
  }
@@ -139,49 +157,59 @@ export function createIncomingFailureHandler(options) {
139
157
  export function createIncomingNotificationHandler(options) {
140
158
  return async (node) => {
141
159
  const notificationType = node.attrs.type ?? '';
160
+ const includeParticipantInAck = NOTIFICATION_TYPES_WITH_PARTICIPANT_ACK.has(notificationType);
161
+ const includeTypeInAck = !NOTIFICATION_TYPES_WITHOUT_TYPE_ACK.has(notificationType);
142
162
  const classification = classifyNotificationType(notificationType);
143
163
  const firstChildTag = getFirstNodeChild(node)?.tag;
164
+ const baseEvent = createIncomingBaseEvent(node);
144
165
  const serverSyncCollections = notificationType === 'server_sync'
145
- ? getNodeChildrenByTag(node, WA_NODE_TAGS.COLLECTION)
146
- .map((collectionNode) => collectionNode.attrs.name)
147
- .filter((name) => typeof name === 'string' && name.length > 0)
166
+ ? getNodeChildrenNonEmptyAttrValuesByTag(node, WA_NODE_TAGS.COLLECTION, 'name')
148
167
  : [];
168
+ let details;
169
+ if (firstChildTag || serverSyncCollections.length > 0) {
170
+ details = {};
171
+ if (firstChildTag) {
172
+ details.firstChildTag = firstChildTag;
173
+ }
174
+ if (serverSyncCollections.length > 0) {
175
+ details.collections = serverSyncCollections;
176
+ }
177
+ }
149
178
  options.emitIncomingNotification({
150
- ...createIncomingBaseEvent(node),
179
+ ...baseEvent,
151
180
  notificationType,
152
181
  classification,
153
- details: firstChildTag || serverSyncCollections.length > 0
154
- ? {
155
- ...(firstChildTag ? { firstChildTag } : {}),
156
- ...(serverSyncCollections.length > 0
157
- ? { collections: serverSyncCollections }
158
- : {})
159
- }
160
- : undefined
182
+ details
161
183
  });
162
184
  if (classification === 'out_of_scope') {
163
185
  options.emitUnhandledStanza({
164
- ...createIncomingBaseEvent(node),
186
+ ...baseEvent,
165
187
  reason: `notification.${notificationType}.out_of_scope`
166
188
  });
167
189
  }
168
190
  else if (classification === 'unknown') {
169
191
  options.emitUnhandledStanza({
170
- ...createIncomingBaseEvent(node),
192
+ ...baseEvent,
171
193
  reason: `notification.${notificationType || 'unknown'}.not_supported`
172
194
  });
173
195
  }
174
- await sendSafeAck(options.logger, options.sendNode, buildNotificationAckNode(node));
196
+ await sendSafeAck(options.logger, options.sendNode, buildAckNode({
197
+ kind: 'notification',
198
+ node,
199
+ includeParticipant: includeParticipantInAck,
200
+ includeType: includeTypeInAck
201
+ }));
175
202
  if (notificationType === 'server_sync' && serverSyncCollections.length > 0) {
203
+ const collectionsCsv = serverSyncCollections.join(',');
176
204
  if (!options.syncAppState) {
177
205
  options.logger.warn('received server_sync notification without app-state sync runtime', {
178
- collections: serverSyncCollections.join(',')
206
+ collections: collectionsCsv
179
207
  });
180
208
  return true;
181
209
  }
182
210
  void options.syncAppState().catch((error) => {
183
211
  options.logger.warn('failed to sync app-state after server_sync notification', {
184
- collections: serverSyncCollections.join(','),
212
+ collections: collectionsCsv,
185
213
  message: toError(error).message
186
214
  });
187
215
  });
@@ -194,6 +222,7 @@ export function createIncomingGroupNotificationHandler(options) {
194
222
  if (node.attrs.type !== WA_NOTIFICATION_TYPES.GROUP) {
195
223
  return false;
196
224
  }
225
+ const baseEvent = createIncomingBaseEvent(node);
197
226
  const parsed = parseGroupNotificationEvents(node);
198
227
  for (const event of parsed.events) {
199
228
  options.emitGroupEvent(event);
@@ -203,11 +232,15 @@ export function createIncomingGroupNotificationHandler(options) {
203
232
  }
204
233
  if (parsed.events.length === 0 && parsed.unhandled.length === 0) {
205
234
  options.emitUnhandledStanza({
206
- ...createIncomingBaseEvent(node),
235
+ ...baseEvent,
207
236
  reason: `notification.${WA_NOTIFICATION_TYPES.GROUP}.empty`
208
237
  });
209
238
  }
210
- await sendSafeAck(options.logger, options.sendNode, buildNotificationAckNode(node));
239
+ await sendSafeAck(options.logger, options.sendNode, buildAckNode({
240
+ kind: 'notification',
241
+ node,
242
+ includeParticipant: true
243
+ }));
211
244
  return true;
212
245
  };
213
246
  }
@@ -1,17 +1,20 @@
1
1
  import { proto } from '../proto.js';
2
2
  import { toError } from '../util/primitives.js';
3
- async function persistContacts(contactStore, event, nowMs) {
4
- const candidateJids = new Set();
5
- if (event.senderJid) {
6
- candidateJids.add(event.senderJid);
3
+ function persistContacts(writeBehind, event, nowMs) {
4
+ const senderJid = event.senderJid;
5
+ const participantJid = event.rawNode.attrs.participant;
6
+ if (!senderJid && !participantJid) {
7
+ return;
8
+ }
9
+ if (senderJid) {
10
+ writeBehind.persistContact({ jid: senderJid, lastUpdatedMs: nowMs });
7
11
  }
8
- if (event.rawNode.attrs.participant) {
9
- candidateJids.add(event.rawNode.attrs.participant);
12
+ if (participantJid && participantJid !== senderJid) {
13
+ writeBehind.persistContact({ jid: participantJid, lastUpdatedMs: nowMs });
10
14
  }
11
- await Promise.all(Array.from(candidateJids, (jid) => contactStore.upsert({ jid, lastUpdatedMs: nowMs })));
12
15
  }
13
- export async function persistIncomingMailboxEntities(options) {
14
- const { logger, contactStore, messageStore, event } = options;
16
+ export function persistIncomingMailboxEntities(options) {
17
+ const { logger, writeBehind, event } = options;
15
18
  const { stanzaId, chatJid } = event;
16
19
  if (!stanzaId || !chatJid) {
17
20
  return;
@@ -21,20 +24,18 @@ export async function persistIncomingMailboxEntities(options) {
21
24
  const messageBytes = event.message
22
25
  ? proto.Message.encode(event.message).finish()
23
26
  : undefined;
24
- await Promise.all([
25
- messageStore.upsert({
26
- id: stanzaId,
27
- threadJid: chatJid,
28
- senderJid: event.senderJid,
29
- participantJid: event.rawNode.attrs.participant,
30
- fromMe: false,
31
- timestampMs: event.timestampSeconds === undefined ? undefined : event.timestampSeconds * 1000,
32
- encType: event.encryptionType,
33
- plaintext: event.plaintext,
34
- messageBytes
35
- }),
36
- persistContacts(contactStore, event, nowMs)
37
- ]);
27
+ writeBehind.persistMessage({
28
+ id: stanzaId,
29
+ threadJid: chatJid,
30
+ senderJid: event.senderJid,
31
+ participantJid: event.rawNode.attrs.participant,
32
+ fromMe: false,
33
+ timestampMs: event.timestampSeconds === undefined ? undefined : event.timestampSeconds * 1000,
34
+ encType: event.encryptionType,
35
+ plaintext: event.plaintext,
36
+ messageBytes
37
+ });
38
+ persistContacts(writeBehind, event, nowMs);
38
39
  }
39
40
  catch (error) {
40
41
  logger.warn('failed to persist incoming mailbox entities', {
@@ -1,11 +1,11 @@
1
+ import { createReadStream } from 'node:fs';
1
2
  import { parseMediaConnResponse } from '../media/conn.js';
2
3
  import { MEDIA_CONN_CACHE_GRACE_MS, MEDIA_UPLOAD_PATHS } from '../media/constants.js';
3
4
  import { WaMediaCrypto } from '../media/WaMediaCrypto.js';
4
5
  import { isSendMediaMessage } from '../message/content.js';
5
6
  import { WA_DEFAULTS } from '../protocol/constants.js';
6
7
  import { buildMediaConnIq } from '../transport/node/builders/media.js';
7
- import { bytesToBase64UrlSafe } from '../util/base64.js';
8
- import { TEXT_DECODER, toBytesView } from '../util/bytes.js';
8
+ import { bytesToBase64UrlSafe, TEXT_DECODER, toBytesView } from '../util/bytes.js';
9
9
  import { toError } from '../util/primitives.js';
10
10
  export async function buildMediaMessageContent(options, content) {
11
11
  if (typeof content === 'string') {
@@ -31,15 +31,29 @@ export async function getMediaConn(options, forceRefresh = false) {
31
31
  options.setMediaConnCache(mediaConn);
32
32
  return mediaConn;
33
33
  }
34
+ function resolveUploadType(content) {
35
+ if (content.type === 'video' && content.gifPlayback)
36
+ return 'gif';
37
+ if (content.type === 'audio' && content.ptt)
38
+ return 'ptt';
39
+ return content.type;
40
+ }
41
+ function isReadableStream(value) {
42
+ return (!!value &&
43
+ typeof value === 'object' &&
44
+ 'pipe' in value &&
45
+ typeof value.pipe === 'function');
46
+ }
34
47
  async function buildMediaMessage(options, content) {
35
- const mediaBytes = toBytesView(content.media);
36
- const uploaded = await uploadMedia(options, content, mediaBytes);
48
+ const uploaded = isReadableStream(content.media)
49
+ ? await uploadMediaStream(options, content, content.media)
50
+ : await uploadMediaBytes(options, content, toBytesView(content.media));
37
51
  const mediaKeyTimestamp = Math.floor(Date.now() / 1000);
38
52
  const common = {
39
53
  url: uploaded.url,
40
54
  mimetype: content.mimetype,
41
55
  fileSha256: uploaded.fileSha256,
42
- fileLength: mediaBytes.byteLength,
56
+ fileLength: uploaded.fileLength,
43
57
  mediaKey: uploaded.mediaKey,
44
58
  fileEncSha256: uploaded.fileEncSha256,
45
59
  directPath: uploaded.directPath,
@@ -67,6 +81,15 @@ async function buildMediaMessage(options, content) {
67
81
  metadataUrl: uploaded.metadataUrl
68
82
  }
69
83
  };
84
+ case 'ptv':
85
+ return {
86
+ ptvMessage: {
87
+ ...common,
88
+ seconds: content.seconds,
89
+ width: content.width,
90
+ height: content.height
91
+ }
92
+ };
70
93
  case 'audio':
71
94
  return {
72
95
  audioMessage: {
@@ -93,24 +116,46 @@ async function buildMediaMessage(options, content) {
93
116
  }
94
117
  };
95
118
  default:
96
- throw new Error(`unsupported media type: ${content.type}`);
119
+ throw new Error(`unsupported media message type: ${String(content.type)}`);
120
+ }
121
+ }
122
+ function buildUploadUrl(host, uploadType, auth, fileEncSha256) {
123
+ const hashToken = bytesToBase64UrlSafe(fileEncSha256);
124
+ const uploadPath = MEDIA_UPLOAD_PATHS[uploadType];
125
+ if (!uploadPath) {
126
+ throw new Error(`unknown media upload type: ${String(uploadType)}`);
97
127
  }
128
+ return `https://${host}${uploadPath}/${hashToken}?auth=${encodeURIComponent(auth)}&token=${encodeURIComponent(hashToken)}`;
98
129
  }
99
- async function uploadMedia(options, content, mediaBytes) {
130
+ function parseUploadResponse(body, status) {
131
+ if (status < 200 || status >= 300) {
132
+ throw new Error(`media upload failed with status ${status}`);
133
+ }
134
+ let parsed;
135
+ try {
136
+ parsed = JSON.parse(TEXT_DECODER.decode(body));
137
+ }
138
+ catch (error) {
139
+ throw new Error(`media upload returned invalid json: ${toError(error).message}`);
140
+ }
141
+ if (!parsed.url || !parsed.direct_path) {
142
+ throw new Error('media upload response missing url/direct_path');
143
+ }
144
+ return {
145
+ url: parsed.url,
146
+ directPath: parsed.direct_path,
147
+ ...(parsed.metadata_url ? { metadataUrl: parsed.metadata_url } : {})
148
+ };
149
+ }
150
+ async function uploadMediaBytes(options, content, mediaBytes) {
151
+ const uploadType = resolveUploadType(content);
100
152
  const mediaKey = await WaMediaCrypto.generateMediaKey();
101
- const uploadType = content.type === 'video' && content.gifPlayback
102
- ? 'gif'
103
- : content.type === 'audio' && content.ptt
104
- ? 'ptt'
105
- : content.type;
106
153
  const [encrypted, mediaConn] = await Promise.all([
107
154
  WaMediaCrypto.encryptBytes(uploadType, mediaKey, mediaBytes),
108
155
  getMediaConn(options)
109
156
  ]);
110
157
  const selectedHost = mediaConn.hosts.find((host) => !host.isFallback)?.hostname ?? mediaConn.hosts[0].hostname;
111
- const uploadPath = MEDIA_UPLOAD_PATHS[uploadType];
112
- const hashToken = bytesToBase64UrlSafe(encrypted.fileEncSha256);
113
- const uploadUrl = `https://${selectedHost}${uploadPath}/${hashToken}?auth=${encodeURIComponent(mediaConn.auth)}&token=${encodeURIComponent(hashToken)}`;
158
+ const uploadUrl = buildUploadUrl(selectedHost, uploadType, mediaConn.auth, encrypted.fileEncSha256);
114
159
  options.logger.debug('sending media upload request', {
115
160
  mediaType: content.type,
116
161
  uploadType,
@@ -123,26 +168,57 @@ async function uploadMedia(options, content, mediaBytes) {
123
168
  contentLength: encrypted.ciphertextHmac.byteLength,
124
169
  contentType: content.mimetype
125
170
  });
126
- const uploadBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
127
- if (!uploadResponse.ok) {
128
- throw new Error(`media upload failed with status ${uploadResponse.status}`);
129
- }
130
- let parsedBody;
131
- try {
132
- parsedBody = JSON.parse(TEXT_DECODER.decode(uploadBody));
133
- }
134
- catch (error) {
135
- throw new Error(`media upload returned invalid json: ${toError(error).message}`);
136
- }
137
- if (!parsedBody.url || !parsedBody.direct_path) {
138
- throw new Error('media upload response missing url/direct_path');
139
- }
171
+ const responseBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
172
+ const parsed = parseUploadResponse(responseBody, uploadResponse.status);
140
173
  return {
141
- url: parsedBody.url,
142
- directPath: parsedBody.direct_path,
174
+ ...parsed,
143
175
  mediaKey,
144
176
  fileSha256: encrypted.fileSha256,
145
177
  fileEncSha256: encrypted.fileEncSha256,
146
- ...(parsedBody.metadata_url ? { metadataUrl: parsedBody.metadata_url } : {})
178
+ fileLength: mediaBytes.byteLength
147
179
  };
148
180
  }
181
+ async function uploadMediaStream(options, content, stream) {
182
+ const uploadType = resolveUploadType(content);
183
+ const mediaKey = await WaMediaCrypto.generateMediaKey();
184
+ const encResult = await WaMediaCrypto.encryptToFile(uploadType, mediaKey, stream);
185
+ let readStream;
186
+ try {
187
+ const mediaConn = await getMediaConn(options);
188
+ const selectedHost = mediaConn.hosts.find((host) => !host.isFallback)?.hostname ??
189
+ mediaConn.hosts[0].hostname;
190
+ const uploadUrl = buildUploadUrl(selectedHost, uploadType, mediaConn.auth, encResult.fileEncSha256);
191
+ options.logger.debug('sending media stream upload request', {
192
+ mediaType: content.type,
193
+ uploadType,
194
+ host: selectedHost,
195
+ encryptedSize: encResult.fileSize
196
+ });
197
+ readStream = createReadStream(encResult.filePath);
198
+ const uploadResponse = await options.mediaTransfer.uploadStream({
199
+ url: uploadUrl,
200
+ method: 'POST',
201
+ body: readStream,
202
+ contentLength: encResult.fileSize,
203
+ contentType: content.mimetype
204
+ });
205
+ const responseBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
206
+ const parsed = parseUploadResponse(responseBody, uploadResponse.status);
207
+ return {
208
+ ...parsed,
209
+ mediaKey,
210
+ fileSha256: encResult.fileSha256,
211
+ fileEncSha256: encResult.fileEncSha256,
212
+ fileLength: encResult.plaintextLength
213
+ };
214
+ }
215
+ finally {
216
+ if (readStream && !readStream.closed) {
217
+ await new Promise((resolve) => {
218
+ readStream.once('close', resolve);
219
+ readStream.destroy();
220
+ });
221
+ }
222
+ await WaMediaCrypto.cleanupEncryptedFile(encResult.filePath);
223
+ }
224
+ }