zapo-js 0.1.2 → 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 (468) hide show
  1. package/README.md +12 -4
  2. package/dist/appstate/WaAppStateCrypto.js +1 -1
  3. package/dist/appstate/WaAppStateSyncClient.js +138 -93
  4. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  5. package/dist/appstate/index.js +8 -6
  6. package/dist/appstate/utils.js +0 -5
  7. package/dist/auth/WaAuthClient.js +36 -47
  8. package/dist/auth/flow/WaAuthCredentialsFlow.js +7 -7
  9. package/dist/auth/index.js +1 -6
  10. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  11. package/dist/auth/pairing/WaPairingFlow.js +13 -3
  12. package/dist/client/WaClient.js +225 -101
  13. package/dist/client/WaClientFactory.js +294 -44
  14. package/dist/client/connection/WaConnectionManager.js +19 -10
  15. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  16. package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
  17. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
  18. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +292 -99
  19. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  20. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  21. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  22. package/dist/client/coordinators/WaRetryCoordinator.js +179 -27
  23. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  24. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  25. package/dist/client/dirty.js +40 -20
  26. package/dist/client/events/devices.js +72 -0
  27. package/dist/client/events/group.js +3 -11
  28. package/dist/client/events/identity.js +22 -0
  29. package/dist/client/events/privacy-token.js +39 -0
  30. package/dist/client/history-sync.js +50 -9
  31. package/dist/client/incoming.js +37 -7
  32. package/dist/client/mailbox.js +24 -23
  33. package/dist/client/messages.js +107 -31
  34. package/dist/client/messaging/fanout.js +21 -11
  35. package/dist/client/messaging/participants.js +6 -4
  36. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  37. package/dist/client/tokens/cs-token.js +50 -0
  38. package/dist/client/tokens/tc-token.js +25 -0
  39. package/dist/crypto/core/index.js +2 -2
  40. package/dist/crypto/core/keys.js +4 -4
  41. package/dist/crypto/core/nonce.js +2 -0
  42. package/dist/crypto/core/primitives.js +0 -8
  43. package/dist/crypto/core/random.js +22 -0
  44. package/dist/crypto/curves/X25519.js +25 -6
  45. package/dist/crypto/index.js +3 -0
  46. package/dist/crypto/math/constants.js +13 -36
  47. package/dist/crypto/math/edwards.js +171 -44
  48. package/dist/crypto/math/fe.js +706 -0
  49. package/dist/crypto/math/mod.js +10 -3
  50. package/dist/esm/appstate/WaAppStateCrypto.js +1 -1
  51. package/dist/esm/appstate/WaAppStateSyncClient.js +138 -93
  52. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  53. package/dist/esm/appstate/index.js +2 -2
  54. package/dist/esm/appstate/utils.js +2 -5
  55. package/dist/esm/auth/WaAuthClient.js +36 -47
  56. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +7 -7
  57. package/dist/esm/auth/index.js +0 -2
  58. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  59. package/dist/esm/auth/pairing/WaPairingFlow.js +14 -4
  60. package/dist/esm/client/WaClient.js +225 -101
  61. package/dist/esm/client/WaClientFactory.js +295 -45
  62. package/dist/esm/client/connection/WaConnectionManager.js +19 -10
  63. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  64. package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
  65. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
  66. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +295 -102
  67. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  68. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  69. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  70. package/dist/esm/client/coordinators/WaRetryCoordinator.js +181 -29
  71. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  72. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  73. package/dist/esm/client/dirty.js +40 -20
  74. package/dist/esm/client/events/devices.js +68 -0
  75. package/dist/esm/client/events/group.js +3 -11
  76. package/dist/esm/client/events/identity.js +19 -0
  77. package/dist/esm/client/events/privacy-token.js +36 -0
  78. package/dist/esm/client/history-sync.js +50 -9
  79. package/dist/esm/client/incoming.js +38 -8
  80. package/dist/esm/client/mailbox.js +24 -23
  81. package/dist/esm/client/messages.js +108 -32
  82. package/dist/esm/client/messaging/fanout.js +22 -12
  83. package/dist/esm/client/messaging/participants.js +6 -4
  84. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  85. package/dist/esm/client/tokens/cs-token.js +46 -0
  86. package/dist/esm/client/tokens/tc-token.js +18 -0
  87. package/dist/esm/crypto/core/index.js +2 -2
  88. package/dist/esm/crypto/core/keys.js +1 -1
  89. package/dist/esm/crypto/core/nonce.js +2 -0
  90. package/dist/esm/crypto/core/primitives.js +0 -7
  91. package/dist/esm/crypto/core/random.js +22 -1
  92. package/dist/esm/crypto/curves/X25519.js +25 -6
  93. package/dist/esm/crypto/index.js +1 -0
  94. package/dist/esm/crypto/math/constants.js +12 -35
  95. package/dist/esm/crypto/math/edwards.js +174 -47
  96. package/dist/esm/crypto/math/fe.js +691 -0
  97. package/dist/esm/crypto/math/mod.js +10 -1
  98. package/dist/esm/index.js +1 -1
  99. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  100. package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
  101. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  102. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  103. package/dist/esm/infra/perf/StoreLock.js +77 -0
  104. package/dist/esm/media/WaMediaCrypto.js +95 -13
  105. package/dist/esm/media/WaMediaTransferClient.js +39 -47
  106. package/dist/esm/media/constants.js +2 -1
  107. package/dist/esm/message/WaMessageClient.js +26 -19
  108. package/dist/esm/message/content.js +195 -9
  109. package/dist/esm/message/icdc.js +76 -0
  110. package/dist/esm/message/incoming.js +24 -12
  111. package/dist/esm/message/phash.js +3 -1
  112. package/dist/esm/message/reporting-token.js +14 -27
  113. package/dist/esm/protocol/appstate.js +9 -40
  114. package/dist/esm/protocol/browser.js +10 -18
  115. package/dist/esm/protocol/constants.js +5 -3
  116. package/dist/esm/protocol/defaults.js +6 -0
  117. package/dist/esm/protocol/index.js +1 -2
  118. package/dist/esm/protocol/jid.js +105 -36
  119. package/dist/esm/protocol/message.js +61 -1
  120. package/dist/esm/protocol/nodes.js +2 -0
  121. package/dist/esm/protocol/notification.js +3 -1
  122. package/dist/esm/protocol/privacy-token.js +17 -0
  123. package/dist/esm/protocol/privacy.js +55 -0
  124. package/dist/esm/protocol/stream.js +26 -1
  125. package/dist/esm/retry/codec.js +216 -0
  126. package/dist/esm/retry/constants.js +1 -1
  127. package/dist/esm/retry/index.js +2 -2
  128. package/dist/esm/retry/parse.js +50 -30
  129. package/dist/esm/retry/replay.js +11 -7
  130. package/dist/esm/retry/tracker.js +50 -12
  131. package/dist/esm/signal/api/SignalDeviceSyncApi.js +49 -32
  132. package/dist/esm/signal/api/SignalDigestSyncApi.js +13 -9
  133. package/dist/esm/signal/api/SignalIdentitySyncApi.js +26 -11
  134. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +18 -7
  135. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  136. package/dist/esm/signal/api/SignalSessionSyncApi.js +16 -7
  137. package/dist/esm/signal/api/result-map.js +10 -0
  138. package/dist/esm/signal/constants.js +0 -4
  139. package/dist/esm/signal/crypto/WaAdvSignature.js +12 -6
  140. package/dist/esm/signal/{store/sqlite.js → encoding.js} +78 -24
  141. package/dist/esm/signal/group/SenderKeyCodec.js +3 -2
  142. package/dist/esm/signal/group/SenderKeyManager.js +125 -106
  143. package/dist/esm/signal/index.js +1 -0
  144. package/dist/esm/signal/registration/keygen.js +6 -2
  145. package/dist/esm/signal/registration/utils.js +1 -0
  146. package/dist/esm/signal/session/SignalProtocol.js +150 -74
  147. package/dist/esm/signal/session/resolver.js +137 -102
  148. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  149. package/dist/esm/store/createStore.js +101 -187
  150. package/dist/esm/store/index.js +1 -10
  151. package/dist/esm/store/locks/appstate.lock.js +26 -0
  152. package/dist/esm/store/locks/auth.lock.js +15 -0
  153. package/dist/esm/store/locks/contact.lock.js +20 -0
  154. package/dist/esm/store/locks/device-list.lock.js +20 -0
  155. package/dist/esm/store/locks/message.lock.js +21 -0
  156. package/dist/esm/store/locks/participants.lock.js +20 -0
  157. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  158. package/dist/esm/store/locks/retry.lock.js +29 -0
  159. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  160. package/dist/esm/store/locks/signal.lock.js +63 -0
  161. package/dist/esm/store/locks/thread.lock.js +21 -0
  162. package/dist/esm/store/noop.store.js +1 -1
  163. package/dist/esm/store/providers/memory/appstate.store.js +22 -24
  164. package/dist/esm/store/providers/memory/device-list.store.js +10 -5
  165. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  166. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  167. package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
  168. package/dist/esm/store/providers/memory/signal.store.js +36 -19
  169. package/dist/esm/transport/WaComms.js +3 -1
  170. package/dist/esm/transport/WaWebSocket.js +0 -6
  171. package/dist/esm/transport/binary/constants.js +0 -30
  172. package/dist/esm/transport/binary/decoder.js +4 -4
  173. package/dist/esm/transport/binary/encoder.js +8 -15
  174. package/dist/esm/transport/binary/index.js +0 -1
  175. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -19
  176. package/dist/esm/transport/node/builders/business.js +129 -0
  177. package/dist/esm/transport/node/builders/global.js +370 -0
  178. package/dist/esm/transport/node/builders/index.js +5 -2
  179. package/dist/esm/transport/node/builders/message.js +63 -239
  180. package/dist/esm/transport/node/builders/pairing.js +0 -24
  181. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  182. package/dist/esm/transport/node/builders/privacy.js +48 -0
  183. package/dist/esm/transport/node/builders/profile.js +70 -0
  184. package/dist/esm/transport/node/builders/retry.js +10 -22
  185. package/dist/esm/transport/node/builders/usync.js +6 -2
  186. package/dist/esm/transport/node/helpers.js +19 -1
  187. package/dist/esm/transport/node/usync.js +3 -33
  188. package/dist/esm/transport/node/xml.js +35 -14
  189. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  190. package/dist/esm/transport/noise/WaNoiseCert.js +3 -3
  191. package/dist/esm/transport/noise/WaNoiseSession.js +64 -23
  192. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  193. package/dist/esm/transport/stream/parse.js +8 -4
  194. package/dist/esm/util/bytes.js +22 -18
  195. package/dist/esm/util/index.js +5 -0
  196. package/dist/esm/util/primitives.js +3 -2
  197. package/dist/index.js +7 -1
  198. package/dist/infra/perf/BackgroundQueue.js +482 -0
  199. package/dist/infra/perf/BoundedTaskQueue.js +3 -1
  200. package/dist/infra/perf/PromiseDedup.js +24 -0
  201. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  202. package/dist/infra/perf/StoreLock.js +81 -0
  203. package/dist/media/WaMediaCrypto.js +94 -12
  204. package/dist/media/WaMediaTransferClient.js +39 -47
  205. package/dist/media/constants.js +2 -1
  206. package/dist/message/WaMessageClient.js +26 -19
  207. package/dist/message/content.js +198 -9
  208. package/dist/message/icdc.js +81 -0
  209. package/dist/message/incoming.js +24 -12
  210. package/dist/message/phash.js +3 -1
  211. package/dist/message/reporting-token.js +14 -28
  212. package/dist/protocol/appstate.js +10 -41
  213. package/dist/protocol/browser.js +10 -18
  214. package/dist/protocol/constants.js +21 -2
  215. package/dist/protocol/defaults.js +6 -0
  216. package/dist/protocol/index.js +8 -5
  217. package/dist/protocol/jid.js +111 -36
  218. package/dist/protocol/message.js +62 -2
  219. package/dist/protocol/nodes.js +2 -0
  220. package/dist/protocol/notification.js +3 -1
  221. package/dist/protocol/privacy-token.js +20 -0
  222. package/dist/protocol/privacy.js +58 -0
  223. package/dist/protocol/stream.js +27 -2
  224. package/dist/retry/codec.js +220 -0
  225. package/dist/retry/constants.js +1 -1
  226. package/dist/retry/index.js +5 -5
  227. package/dist/retry/parse.js +51 -30
  228. package/dist/retry/replay.js +10 -6
  229. package/dist/retry/tracker.js +50 -12
  230. package/dist/signal/api/SignalDeviceSyncApi.js +48 -31
  231. package/dist/signal/api/SignalDigestSyncApi.js +13 -9
  232. package/dist/signal/api/SignalIdentitySyncApi.js +25 -10
  233. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
  234. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  235. package/dist/signal/api/SignalSessionSyncApi.js +16 -7
  236. package/dist/signal/api/result-map.js +13 -0
  237. package/dist/signal/constants.js +1 -5
  238. package/dist/signal/crypto/WaAdvSignature.js +11 -5
  239. package/dist/signal/{store/sqlite.js → encoding.js} +79 -25
  240. package/dist/signal/group/SenderKeyCodec.js +4 -3
  241. package/dist/signal/group/SenderKeyManager.js +125 -106
  242. package/dist/signal/index.js +13 -1
  243. package/dist/signal/registration/keygen.js +6 -2
  244. package/dist/signal/registration/utils.js +1 -0
  245. package/dist/signal/session/SignalProtocol.js +150 -74
  246. package/dist/signal/session/resolver.js +135 -100
  247. package/dist/store/contracts/privacy-token.store.js +2 -0
  248. package/dist/store/createStore.js +101 -187
  249. package/dist/store/index.js +15 -33
  250. package/dist/store/locks/appstate.lock.js +29 -0
  251. package/dist/store/locks/auth.lock.js +18 -0
  252. package/dist/store/locks/contact.lock.js +23 -0
  253. package/dist/store/locks/device-list.lock.js +23 -0
  254. package/dist/store/locks/message.lock.js +24 -0
  255. package/dist/store/locks/participants.lock.js +23 -0
  256. package/dist/store/locks/privacy-token.lock.js +21 -0
  257. package/dist/store/locks/retry.lock.js +32 -0
  258. package/dist/store/locks/sender-key.lock.js +55 -0
  259. package/dist/store/locks/signal.lock.js +66 -0
  260. package/dist/store/locks/thread.lock.js +24 -0
  261. package/dist/store/noop.store.js +1 -1
  262. package/dist/store/providers/memory/appstate.store.js +22 -24
  263. package/dist/store/providers/memory/device-list.store.js +10 -5
  264. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  265. package/dist/store/providers/memory/retry.store.js +77 -2
  266. package/dist/store/providers/memory/sender-key.store.js +6 -1
  267. package/dist/store/providers/memory/signal.store.js +36 -19
  268. package/dist/transport/WaComms.js +3 -1
  269. package/dist/transport/WaWebSocket.js +0 -6
  270. package/dist/transport/binary/constants.js +1 -31
  271. package/dist/transport/binary/decoder.js +4 -4
  272. package/dist/transport/binary/encoder.js +8 -15
  273. package/dist/transport/binary/index.js +0 -4
  274. package/dist/transport/node/WaNodeOrchestrator.js +24 -18
  275. package/dist/transport/node/builders/business.js +137 -0
  276. package/dist/transport/node/builders/global.js +375 -0
  277. package/dist/transport/node/builders/index.js +18 -9
  278. package/dist/transport/node/builders/message.js +64 -245
  279. package/dist/transport/node/builders/pairing.js +0 -26
  280. package/dist/transport/node/builders/privacy-token.js +46 -0
  281. package/dist/transport/node/builders/privacy.js +55 -0
  282. package/dist/transport/node/builders/profile.js +78 -0
  283. package/dist/transport/node/builders/retry.js +9 -21
  284. package/dist/transport/node/builders/usync.js +6 -2
  285. package/dist/transport/node/helpers.js +20 -1
  286. package/dist/transport/node/usync.js +2 -32
  287. package/dist/transport/node/xml.js +35 -14
  288. package/dist/transport/noise/WaClientPayload.js +13 -13
  289. package/dist/transport/noise/WaNoiseCert.js +2 -2
  290. package/dist/transport/noise/WaNoiseSession.js +64 -23
  291. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  292. package/dist/transport/stream/parse.js +7 -3
  293. package/dist/types/appstate/encoding.d.ts +7 -0
  294. package/dist/types/appstate/index.d.ts +3 -3
  295. package/dist/types/appstate/utils.d.ts +0 -2
  296. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  297. package/dist/types/auth/index.d.ts +0 -2
  298. package/dist/types/auth/types.d.ts +1 -0
  299. package/dist/types/client/WaClient.d.ts +27 -12
  300. package/dist/types/client/WaClientFactory.d.ts +12 -4
  301. package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
  302. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  303. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -1
  304. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +14 -0
  305. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  306. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  307. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  308. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +6 -0
  309. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  310. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  311. package/dist/types/client/events/devices.d.ts +20 -0
  312. package/dist/types/client/events/identity.d.ts +9 -0
  313. package/dist/types/client/events/privacy-token.d.ts +7 -0
  314. package/dist/types/client/history-sync.d.ts +9 -6
  315. package/dist/types/client/incoming.d.ts +3 -1
  316. package/dist/types/client/index.d.ts +1 -1
  317. package/dist/types/client/mailbox.d.ts +3 -5
  318. package/dist/types/client/messages.d.ts +1 -2
  319. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  320. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  321. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  322. package/dist/types/client/types.d.ts +51 -3
  323. package/dist/types/crypto/core/index.d.ts +2 -2
  324. package/dist/types/crypto/core/nonce.d.ts +2 -0
  325. package/dist/types/crypto/core/primitives.d.ts +0 -1
  326. package/dist/types/crypto/core/random.d.ts +1 -0
  327. package/dist/types/crypto/index.d.ts +1 -0
  328. package/dist/types/crypto/math/constants.d.ts +4 -2
  329. package/dist/types/crypto/math/fe.d.ts +30 -0
  330. package/dist/types/crypto/math/mod.d.ts +0 -2
  331. package/dist/types/crypto/math/types.d.ts +11 -4
  332. package/dist/types/index.d.ts +5 -3
  333. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  334. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  335. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  336. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  337. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  338. package/dist/types/media/WaMediaTransferClient.d.ts +3 -12
  339. package/dist/types/media/constants.d.ts +1 -1
  340. package/dist/types/media/index.d.ts +1 -1
  341. package/dist/types/media/types.d.ts +10 -2
  342. package/dist/types/message/content.d.ts +8 -0
  343. package/dist/types/message/icdc.d.ts +13 -0
  344. package/dist/types/message/reporting-token.d.ts +0 -1
  345. package/dist/types/message/types.d.ts +45 -6
  346. package/dist/types/protocol/appstate.d.ts +0 -11
  347. package/dist/types/protocol/constants.d.ts +7 -3
  348. package/dist/types/protocol/defaults.d.ts +6 -0
  349. package/dist/types/protocol/index.d.ts +1 -2
  350. package/dist/types/protocol/jid.d.ts +19 -2
  351. package/dist/types/protocol/message.d.ts +60 -0
  352. package/dist/types/protocol/nodes.d.ts +2 -0
  353. package/dist/types/protocol/notification.d.ts +2 -0
  354. package/dist/types/protocol/privacy-token.d.ts +17 -0
  355. package/dist/types/protocol/privacy.d.ts +75 -0
  356. package/dist/types/protocol/stream.d.ts +30 -0
  357. package/dist/types/retry/codec.d.ts +3 -0
  358. package/dist/types/retry/index.d.ts +3 -3
  359. package/dist/types/retry/parse.d.ts +5 -2
  360. package/dist/types/retry/tracker.d.ts +1 -0
  361. package/dist/types/retry/types.d.ts +6 -1
  362. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
  363. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  364. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  365. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  366. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  367. package/dist/types/signal/api/result-map.d.ts +1 -0
  368. package/dist/types/signal/constants.d.ts +0 -3
  369. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  370. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  371. package/dist/types/signal/index.d.ts +2 -0
  372. package/dist/types/signal/session/SignalProtocol.d.ts +10 -4
  373. package/dist/types/signal/session/resolver.d.ts +7 -2
  374. package/dist/types/store/contracts/appstate.store.d.ts +1 -1
  375. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  376. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  377. package/dist/types/store/contracts/signal.store.d.ts +7 -0
  378. package/dist/types/store/createStore.d.ts +1 -1
  379. package/dist/types/store/index.d.ts +5 -13
  380. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  381. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  382. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  383. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  384. package/dist/types/store/locks/message.lock.d.ts +3 -0
  385. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  386. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  387. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  388. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  389. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  390. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  391. package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
  392. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  393. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  394. package/dist/types/store/providers/memory/signal.store.d.ts +2 -1
  395. package/dist/types/store/types.d.ts +49 -61
  396. package/dist/types/transport/WaWebSocket.d.ts +0 -1
  397. package/dist/types/transport/binary/constants.d.ts +0 -30
  398. package/dist/types/transport/binary/index.d.ts +0 -1
  399. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  400. package/dist/types/transport/node/builders/business.d.ts +29 -0
  401. package/dist/types/transport/node/builders/global.d.ts +102 -0
  402. package/dist/types/transport/node/builders/index.d.ts +5 -2
  403. package/dist/types/transport/node/builders/message.d.ts +8 -7
  404. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  405. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  406. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  407. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  408. package/dist/types/transport/node/builders/retry.d.ts +0 -1
  409. package/dist/types/transport/node/helpers.d.ts +5 -0
  410. package/dist/types/transport/noise/WaNoiseSession.d.ts +3 -2
  411. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  412. package/dist/types/util/bytes.d.ts +1 -1
  413. package/dist/types/util/index.d.ts +5 -0
  414. package/dist/types/util/primitives.d.ts +0 -1
  415. package/dist/util/bytes.js +22 -18
  416. package/dist/util/index.js +23 -0
  417. package/dist/util/primitives.js +2 -2
  418. package/package.json +29 -7
  419. package/proto/index.js +1 -1
  420. package/dist/crypto/core/constants.js +0 -4
  421. package/dist/esm/crypto/core/constants.js +0 -1
  422. package/dist/esm/retry/outbound.js +0 -82
  423. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  424. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
  425. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  426. package/dist/esm/store/providers/sqlite/connection.js +0 -245
  427. package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
  428. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
  429. package/dist/esm/store/providers/sqlite/message.store.js +0 -132
  430. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  431. package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
  432. package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
  433. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
  434. package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
  435. package/dist/esm/store/providers/sqlite/table-names.js +0 -107
  436. package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
  437. package/dist/retry/outbound.js +0 -87
  438. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  439. package/dist/store/providers/sqlite/appstate.store.js +0 -254
  440. package/dist/store/providers/sqlite/auth.store.js +0 -180
  441. package/dist/store/providers/sqlite/connection.js +0 -281
  442. package/dist/store/providers/sqlite/contact.store.js +0 -78
  443. package/dist/store/providers/sqlite/device-list.store.js +0 -131
  444. package/dist/store/providers/sqlite/message.store.js +0 -136
  445. package/dist/store/providers/sqlite/migrations.js +0 -350
  446. package/dist/store/providers/sqlite/participants.store.js +0 -81
  447. package/dist/store/providers/sqlite/retry.store.js +0 -145
  448. package/dist/store/providers/sqlite/sender-key.store.js +0 -202
  449. package/dist/store/providers/sqlite/signal.store.js +0 -439
  450. package/dist/store/providers/sqlite/table-names.js +0 -113
  451. package/dist/store/providers/sqlite/thread.store.js +0 -89
  452. package/dist/types/appstate/store/sqlite.d.ts +0 -7
  453. package/dist/types/crypto/core/constants.d.ts +0 -1
  454. package/dist/types/retry/outbound.d.ts +0 -4
  455. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  456. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
  457. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  458. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  459. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
  460. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
  461. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
  462. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  463. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
  464. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
  465. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
  466. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
  467. package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
  468. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEVICE_NOTIFICATION_ACTIONS = void 0;
4
+ exports.parseDeviceNotification = parseDeviceNotification;
5
+ const jid_1 = require("../../protocol/jid");
6
+ const helpers_1 = require("../../transport/node/helpers");
7
+ exports.DEVICE_NOTIFICATION_ACTIONS = Object.freeze({
8
+ ADD: 'add',
9
+ REMOVE: 'remove',
10
+ UPDATE: 'update'
11
+ });
12
+ function parseDeviceNotification(node) {
13
+ const stanzaId = node.attrs.id;
14
+ const fromJid = node.attrs.from;
15
+ if (!stanzaId || !fromJid) {
16
+ return null;
17
+ }
18
+ let action;
19
+ let actionNode;
20
+ if ((0, helpers_1.findNodeChild)(node, exports.DEVICE_NOTIFICATION_ACTIONS.REMOVE)) {
21
+ action = exports.DEVICE_NOTIFICATION_ACTIONS.REMOVE;
22
+ actionNode = (0, helpers_1.findNodeChild)(node, exports.DEVICE_NOTIFICATION_ACTIONS.REMOVE);
23
+ }
24
+ else if ((0, helpers_1.findNodeChild)(node, exports.DEVICE_NOTIFICATION_ACTIONS.ADD)) {
25
+ action = exports.DEVICE_NOTIFICATION_ACTIONS.ADD;
26
+ actionNode = (0, helpers_1.findNodeChild)(node, exports.DEVICE_NOTIFICATION_ACTIONS.ADD);
27
+ }
28
+ else if ((0, helpers_1.findNodeChild)(node, exports.DEVICE_NOTIFICATION_ACTIONS.UPDATE)) {
29
+ action = exports.DEVICE_NOTIFICATION_ACTIONS.UPDATE;
30
+ actionNode = (0, helpers_1.findNodeChild)(node, exports.DEVICE_NOTIFICATION_ACTIONS.UPDATE);
31
+ }
32
+ else {
33
+ return null;
34
+ }
35
+ const devices = [];
36
+ if (action !== exports.DEVICE_NOTIFICATION_ACTIONS.UPDATE && actionNode) {
37
+ const deviceNodes = (0, helpers_1.getNodeChildrenByTag)(actionNode, 'device');
38
+ for (let index = 0; index < deviceNodes.length; index += 1) {
39
+ const deviceNode = deviceNodes[index];
40
+ const jidAttr = deviceNode.attrs.jid;
41
+ if (!jidAttr) {
42
+ continue;
43
+ }
44
+ let deviceId;
45
+ try {
46
+ deviceId = (0, jid_1.parseSignalAddressFromJid)(jidAttr).device;
47
+ }
48
+ catch {
49
+ continue;
50
+ }
51
+ const keyIndexAttr = deviceNode.attrs['key-index'];
52
+ const parsedKeyIndex = keyIndexAttr === undefined ? null : Number.parseInt(keyIndexAttr, 10);
53
+ const keyIndex = parsedKeyIndex !== null &&
54
+ Number.isSafeInteger(parsedKeyIndex) &&
55
+ parsedKeyIndex >= 0
56
+ ? parsedKeyIndex
57
+ : null;
58
+ devices[devices.length] = {
59
+ deviceId,
60
+ keyIndex
61
+ };
62
+ }
63
+ }
64
+ return {
65
+ action,
66
+ stanzaId,
67
+ fromJid,
68
+ lid: node.attrs.lid,
69
+ hash: action === exports.DEVICE_NOTIFICATION_ACTIONS.UPDATE ? actionNode?.attrs.hash : undefined,
70
+ devices
71
+ };
72
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseParticipants = parseParticipants;
4
4
  exports.parseGroupNotificationEvents = parseGroupNotificationEvents;
5
+ const incoming_1 = require("../incoming");
5
6
  const constants_1 = require("../../protocol/constants");
6
7
  const nodes_1 = require("../../protocol/nodes");
7
8
  const helpers_1 = require("../../transport/node/helpers");
@@ -103,15 +104,6 @@ function createBaseGroupEvent(notificationNode, actionNode) {
103
104
  timestampSeconds: (0, primitives_1.parseOptionalInt)(notificationNode.attrs.t)
104
105
  };
105
106
  }
106
- function createUnhandledStanzaEvent(notificationNode, reason) {
107
- return {
108
- rawNode: notificationNode,
109
- stanzaId: notificationNode.attrs.id,
110
- chatJid: notificationNode.attrs.from,
111
- stanzaType: notificationNode.attrs.type,
112
- reason
113
- };
114
- }
115
107
  function parseCreateGroupAction(notificationNode, actionNode) {
116
108
  const groupNode = (0, helpers_1.findNodeChild)(actionNode, nodes_1.WA_NODE_TAGS.GROUP);
117
109
  if (!groupNode) {
@@ -417,13 +409,13 @@ function parseGroupNotificationEvents(notificationNode) {
417
409
  try {
418
410
  const parsedEvent = parseGroupActionNode(notificationNode, actionNode);
419
411
  if (!parsedEvent) {
420
- unhandled.push(createUnhandledStanzaEvent(notificationNode, `notification.${constants_1.WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.not_supported`));
412
+ unhandled.push((0, incoming_1.createUnhandledIncomingNodeEvent)(notificationNode, `notification.${constants_1.WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.not_supported`));
421
413
  continue;
422
414
  }
423
415
  events.push(parsedEvent);
424
416
  }
425
417
  catch {
426
- unhandled.push(createUnhandledStanzaEvent(notificationNode, `notification.${constants_1.WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.parse_failed`));
418
+ unhandled.push((0, incoming_1.createUnhandledIncomingNodeEvent)(notificationNode, `notification.${constants_1.WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.parse_failed`));
427
419
  }
428
420
  }
429
421
  return {
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseIdentityChangeNotification = parseIdentityChangeNotification;
4
+ const helpers_1 = require("../../transport/node/helpers");
5
+ function parseIdentityChangeNotification(node) {
6
+ const child = (0, helpers_1.getFirstNodeChild)(node);
7
+ if (!child || child.tag !== 'identity') {
8
+ return null;
9
+ }
10
+ const fromJid = node.attrs.from;
11
+ const stanzaId = node.attrs.id;
12
+ if (!fromJid || !stanzaId) {
13
+ return null;
14
+ }
15
+ return {
16
+ fromJid,
17
+ stanzaId,
18
+ displayName: node.attrs.display_name,
19
+ lid: node.attrs.lid,
20
+ offline: node.attrs.offline
21
+ };
22
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePrivacyTokenNotification = parsePrivacyTokenNotification;
4
+ const privacy_token_1 = require("../../protocol/privacy-token");
5
+ const helpers_1 = require("../../transport/node/helpers");
6
+ const bytes_1 = require("../../util/bytes");
7
+ const coercion_1 = require("../../util/coercion");
8
+ function parsePrivacyTokenNotification(node) {
9
+ const tokensNode = (0, helpers_1.findNodeChild)(node, privacy_token_1.WA_PRIVACY_TOKEN_TAGS.TOKENS);
10
+ if (!tokensNode) {
11
+ return [];
12
+ }
13
+ const children = (0, helpers_1.getNodeChildren)(tokensNode);
14
+ const result = [];
15
+ for (let i = 0; i < children.length; i += 1) {
16
+ const child = children[i];
17
+ if (child.tag !== privacy_token_1.WA_PRIVACY_TOKEN_TAGS.TOKEN) {
18
+ continue;
19
+ }
20
+ const type = child.attrs.type;
21
+ if (!type) {
22
+ continue;
23
+ }
24
+ const rawTimestamp = child.attrs.t;
25
+ if (!rawTimestamp) {
26
+ continue;
27
+ }
28
+ const content = child.content;
29
+ if (!(content instanceof Uint8Array)) {
30
+ continue;
31
+ }
32
+ result[result.length] = {
33
+ type,
34
+ tokenBytes: (0, bytes_1.toBytesView)(content),
35
+ timestampS: (0, coercion_1.asNumber)(Number(rawTimestamp), 'privacy_token.t')
36
+ };
37
+ }
38
+ return result;
39
+ }
@@ -13,6 +13,7 @@ const HANDLED_SYNC_TYPES = new Set([
13
13
  _proto_1.proto.Message.HistorySyncType.FULL,
14
14
  _proto_1.proto.Message.HistorySyncType.PUSH_NAME
15
15
  ]);
16
+ const HISTORY_SYNC_MAX_PENDING_WRITES = 1024;
16
17
  async function processHistorySyncNotification(deps, notification) {
17
18
  const syncType = notification.syncType;
18
19
  if (syncType === null || syncType === undefined || !HANDLED_SYNC_TYPES.has(syncType)) {
@@ -30,19 +31,20 @@ async function processHistorySyncNotification(deps, notification) {
30
31
  pushnames: historySync.pushnames.length
31
32
  });
32
33
  const nowMs = Date.now();
33
- const contacts = [];
34
+ const pendingWrites = [];
34
35
  for (const pn of historySync.pushnames) {
35
36
  if (!pn.id) {
36
37
  continue;
37
38
  }
38
- contacts.push({
39
+ pendingWrites[pendingWrites.length] = deps.writeBehind.persistContactAsync({
39
40
  jid: pn.id,
40
41
  pushName: pn.pushname ?? undefined,
41
42
  lastUpdatedMs: nowMs
42
43
  });
44
+ if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
45
+ await flushPendingWrites(pendingWrites);
46
+ }
43
47
  }
44
- const threads = [];
45
- const messages = [];
46
48
  let messagesCount = 0;
47
49
  for (const conversation of historySync.conversations) {
48
50
  const threadJid = conversation.id;
@@ -50,7 +52,7 @@ async function processHistorySyncNotification(deps, notification) {
50
52
  deps.logger.debug('skipping history sync conversation without thread jid');
51
53
  continue;
52
54
  }
53
- threads.push({
55
+ pendingWrites[pendingWrites.length] = deps.writeBehind.persistThreadAsync({
54
56
  jid: threadJid,
55
57
  name: conversation.name ?? undefined,
56
58
  unreadCount: conversation.unreadCount ?? undefined,
@@ -60,13 +62,16 @@ async function processHistorySyncNotification(deps, notification) {
60
62
  markedAsUnread: conversation.markedAsUnread ?? undefined,
61
63
  ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
62
64
  });
65
+ if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
66
+ await flushPendingWrites(pendingWrites);
67
+ }
63
68
  for (const histMsg of conversation.messages ?? []) {
64
69
  const webMsg = histMsg.message;
65
70
  if (!webMsg?.key?.id) {
66
71
  continue;
67
72
  }
68
73
  const timestampMs = (0, primitives_1.longToNumber)(webMsg.messageTimestamp) * 1000;
69
- messages.push({
74
+ pendingWrites[pendingWrites.length] = deps.writeBehind.persistMessageAsync({
70
75
  id: webMsg.key.id,
71
76
  threadJid,
72
77
  senderJid: webMsg.key.participant ?? undefined,
@@ -76,12 +81,35 @@ async function processHistorySyncNotification(deps, notification) {
76
81
  ? _proto_1.proto.Message.encode(webMsg.message).finish()
77
82
  : undefined
78
83
  });
84
+ if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
85
+ await flushPendingWrites(pendingWrites);
86
+ }
79
87
  messagesCount += 1;
80
88
  }
81
89
  }
82
- await deps.contactStore.upsertBatch(contacts);
83
- await deps.threadStore.upsertBatch(threads);
84
- await deps.messageStore.upsertBatch(messages);
90
+ if (deps.onPrivacyTokens) {
91
+ const tokenConversations = [];
92
+ for (const conversation of historySync.conversations) {
93
+ if (!conversation.id)
94
+ continue;
95
+ if (conversation.tcToken ||
96
+ conversation.tcTokenTimestamp ||
97
+ conversation.tcTokenSenderTimestamp) {
98
+ tokenConversations[tokenConversations.length] = {
99
+ jid: conversation.id,
100
+ tcToken: conversation.tcToken,
101
+ tcTokenTimestamp: (0, primitives_1.longToNumber)(conversation.tcTokenTimestamp) || undefined,
102
+ tcTokenSenderTimestamp: (0, primitives_1.longToNumber)(conversation.tcTokenSenderTimestamp) || undefined
103
+ };
104
+ }
105
+ }
106
+ if (tokenConversations.length > 0) {
107
+ pendingWrites[pendingWrites.length] = deps.onPrivacyTokens(tokenConversations);
108
+ }
109
+ }
110
+ if (deps.onNctSalt && historySync.nctSalt) {
111
+ pendingWrites[pendingWrites.length] = deps.onNctSalt(historySync.nctSalt);
112
+ }
85
113
  const event = {
86
114
  syncType,
87
115
  messagesCount,
@@ -90,8 +118,21 @@ async function processHistorySyncNotification(deps, notification) {
90
118
  chunkOrder: historySync.chunkOrder ?? undefined,
91
119
  progress: historySync.progress ?? undefined
92
120
  };
121
+ await flushPendingWrites(pendingWrites);
93
122
  deps.emitEvent('history_sync_chunk', event);
94
123
  }
124
+ async function flushPendingWrites(pendingWrites) {
125
+ if (pendingWrites.length === 0) {
126
+ return;
127
+ }
128
+ const pendingCount = pendingWrites.length;
129
+ const batch = new Array(pendingCount);
130
+ for (let index = 0; index < pendingCount; index += 1) {
131
+ batch[index] = pendingWrites[index];
132
+ }
133
+ pendingWrites.length = 0;
134
+ await Promise.all(batch);
135
+ }
95
136
  async function downloadHistorySyncBlob(deps, notification) {
96
137
  if (notification.initialHistBootstrapInlinePayload) {
97
138
  return (0, bytes_1.decodeProtoBytes)(notification.initialHistBootstrapInlinePayload, 'initialHistBootstrapInlinePayload');
@@ -9,10 +9,17 @@ exports.createInfoBulletinNotificationEvent = createInfoBulletinNotificationEven
9
9
  exports.createUnhandledIncomingNodeEvent = createUnhandledIncomingNodeEvent;
10
10
  const group_1 = require("./events/group");
11
11
  const constants_1 = require("../protocol/constants");
12
- const message_1 = require("../transport/node/builders/message");
13
- const pairing_1 = require("../transport/node/builders/pairing");
12
+ const global_1 = require("../transport/node/builders/global");
14
13
  const helpers_1 = require("../transport/node/helpers");
15
14
  const primitives_1 = require("../util/primitives");
15
+ const FAILURE_REASON_TO_DISCONNECT = {
16
+ 401: constants_1.WA_DISCONNECT_REASONS.FAILURE_NOT_AUTHORIZED,
17
+ 403: constants_1.WA_DISCONNECT_REASONS.FAILURE_LOCKED,
18
+ 406: constants_1.WA_DISCONNECT_REASONS.FAILURE_BANNED,
19
+ 405: constants_1.WA_DISCONNECT_REASONS.FAILURE_CLIENT_TOO_OLD,
20
+ 409: constants_1.WA_DISCONNECT_REASONS.FAILURE_BAD_USER_AGENT,
21
+ 503: constants_1.WA_DISCONNECT_REASONS.FAILURE_SERVICE_UNAVAILABLE
22
+ };
16
23
  const LOGOUT_FAILURE_REASONS = new Set([401, 403, 406]);
17
24
  const DISCONNECT_FAILURE_REASONS = new Set([405, 409, 503]);
18
25
  const CORE_NOTIFICATION_TYPES = new Set([
@@ -39,6 +46,8 @@ const OUT_OF_SCOPE_NOTIFICATION_TYPES = new Set([
39
46
  'waffle',
40
47
  'hosted'
41
48
  ]);
49
+ const NOTIFICATION_TYPES_WITH_PARTICIPANT_ACK = new Set(['mediaretry', 'psa']);
50
+ const NOTIFICATION_TYPES_WITHOUT_TYPE_ACK = new Set(['encrypt', 'devices']);
42
51
  function createIncomingBaseEvent(node) {
43
52
  return {
44
53
  rawNode: node,
@@ -72,7 +81,9 @@ function classifyNotificationType(notificationType) {
72
81
  }
73
82
  async function applyFailureAction(options, reason, clearStoredCredentials) {
74
83
  try {
75
- await options.disconnect();
84
+ options.stopComms();
85
+ const disconnectReason = FAILURE_REASON_TO_DISCONNECT[reason] ?? constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_OTHER;
86
+ await options.disconnect(disconnectReason, clearStoredCredentials, reason);
76
87
  if (clearStoredCredentials) {
77
88
  await options.clearStoredCredentials();
78
89
  }
@@ -117,11 +128,19 @@ function createIncomingReceiptHandler(options) {
117
128
  await options.handleIncomingRetryReceipt(node);
118
129
  }
119
130
  else {
120
- await sendSafeAck(options.logger, options.sendNode, (0, message_1.buildInboundRetryReceiptAckNode)(node));
131
+ await sendSafeAck(options.logger, options.sendNode, (0, global_1.buildAckNode)({
132
+ kind: 'receipt',
133
+ node,
134
+ retryType: true
135
+ }));
121
136
  }
122
137
  return true;
123
138
  }
124
- await sendSafeAck(options.logger, options.sendNode, (0, message_1.buildInboundReceiptAckNode)(node));
139
+ await sendSafeAck(options.logger, options.sendNode, (0, global_1.buildAckNode)({
140
+ kind: 'receipt',
141
+ node,
142
+ includeParticipant: receiptType !== 'server-error'
143
+ }));
125
144
  return true;
126
145
  };
127
146
  }
@@ -147,6 +166,8 @@ function createIncomingFailureHandler(options) {
147
166
  function createIncomingNotificationHandler(options) {
148
167
  return async (node) => {
149
168
  const notificationType = node.attrs.type ?? '';
169
+ const includeParticipantInAck = NOTIFICATION_TYPES_WITH_PARTICIPANT_ACK.has(notificationType);
170
+ const includeTypeInAck = !NOTIFICATION_TYPES_WITHOUT_TYPE_ACK.has(notificationType);
150
171
  const classification = classifyNotificationType(notificationType);
151
172
  const firstChildTag = (0, helpers_1.getFirstNodeChild)(node)?.tag;
152
173
  const baseEvent = createIncomingBaseEvent(node);
@@ -181,7 +202,12 @@ function createIncomingNotificationHandler(options) {
181
202
  reason: `notification.${notificationType || 'unknown'}.not_supported`
182
203
  });
183
204
  }
184
- await sendSafeAck(options.logger, options.sendNode, (0, pairing_1.buildNotificationAckNode)(node));
205
+ await sendSafeAck(options.logger, options.sendNode, (0, global_1.buildAckNode)({
206
+ kind: 'notification',
207
+ node,
208
+ includeParticipant: includeParticipantInAck,
209
+ includeType: includeTypeInAck
210
+ }));
185
211
  if (notificationType === 'server_sync' && serverSyncCollections.length > 0) {
186
212
  const collectionsCsv = serverSyncCollections.join(',');
187
213
  if (!options.syncAppState) {
@@ -219,7 +245,11 @@ function createIncomingGroupNotificationHandler(options) {
219
245
  reason: `notification.${constants_1.WA_NOTIFICATION_TYPES.GROUP}.empty`
220
246
  });
221
247
  }
222
- await sendSafeAck(options.logger, options.sendNode, (0, pairing_1.buildNotificationAckNode)(node));
248
+ await sendSafeAck(options.logger, options.sendNode, (0, global_1.buildAckNode)({
249
+ kind: 'notification',
250
+ node,
251
+ includeParticipant: true
252
+ }));
223
253
  return true;
224
254
  };
225
255
  }
@@ -3,16 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.persistIncomingMailboxEntities = persistIncomingMailboxEntities;
4
4
  const _proto_1 = require("../proto.js");
5
5
  const primitives_1 = require("../util/primitives");
6
- async function persistContacts(contactStore, event, nowMs) {
7
- const candidateJids = [event.senderJid, event.rawNode.attrs.participant].filter((jid) => !!jid);
8
- if (candidateJids.length === 0) {
6
+ function persistContacts(writeBehind, event, nowMs) {
7
+ const senderJid = event.senderJid;
8
+ const participantJid = event.rawNode.attrs.participant;
9
+ if (!senderJid && !participantJid) {
9
10
  return;
10
11
  }
11
- const contacts = [...new Set(candidateJids)].map((jid) => ({ jid, lastUpdatedMs: nowMs }));
12
- await contactStore.upsertBatch(contacts);
12
+ if (senderJid) {
13
+ writeBehind.persistContact({ jid: senderJid, lastUpdatedMs: nowMs });
14
+ }
15
+ if (participantJid && participantJid !== senderJid) {
16
+ writeBehind.persistContact({ jid: participantJid, lastUpdatedMs: nowMs });
17
+ }
13
18
  }
14
- async function persistIncomingMailboxEntities(options) {
15
- const { logger, contactStore, messageStore, event } = options;
19
+ function persistIncomingMailboxEntities(options) {
20
+ const { logger, writeBehind, event } = options;
16
21
  const { stanzaId, chatJid } = event;
17
22
  if (!stanzaId || !chatJid) {
18
23
  return;
@@ -22,22 +27,18 @@ async function persistIncomingMailboxEntities(options) {
22
27
  const messageBytes = event.message
23
28
  ? _proto_1.proto.Message.encode(event.message).finish()
24
29
  : undefined;
25
- await Promise.all([
26
- messageStore.upsert({
27
- id: stanzaId,
28
- threadJid: chatJid,
29
- senderJid: event.senderJid,
30
- participantJid: event.rawNode.attrs.participant,
31
- fromMe: false,
32
- timestampMs: event.timestampSeconds === undefined
33
- ? undefined
34
- : event.timestampSeconds * 1000,
35
- encType: event.encryptionType,
36
- plaintext: event.plaintext,
37
- messageBytes
38
- }),
39
- persistContacts(contactStore, event, nowMs)
40
- ]);
30
+ writeBehind.persistMessage({
31
+ id: stanzaId,
32
+ threadJid: chatJid,
33
+ senderJid: event.senderJid,
34
+ participantJid: event.rawNode.attrs.participant,
35
+ fromMe: false,
36
+ timestampMs: event.timestampSeconds === undefined ? undefined : event.timestampSeconds * 1000,
37
+ encType: event.encryptionType,
38
+ plaintext: event.plaintext,
39
+ messageBytes
40
+ });
41
+ persistContacts(writeBehind, event, nowMs);
41
42
  }
42
43
  catch (error) {
43
44
  logger.warn('failed to persist incoming mailbox entities', {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildMediaMessageContent = buildMediaMessageContent;
4
4
  exports.getMediaConn = getMediaConn;
5
+ const node_fs_1 = require("node:fs");
5
6
  const conn_1 = require("../media/conn");
6
7
  const constants_1 = require("../media/constants");
7
8
  const WaMediaCrypto_1 = require("../media/WaMediaCrypto");
@@ -9,7 +10,6 @@ const content_1 = require("../message/content");
9
10
  const constants_2 = require("../protocol/constants");
10
11
  const media_1 = require("../transport/node/builders/media");
11
12
  const bytes_1 = require("../util/bytes");
12
- const bytes_2 = require("../util/bytes");
13
13
  const primitives_1 = require("../util/primitives");
14
14
  async function buildMediaMessageContent(options, content) {
15
15
  if (typeof content === 'string') {
@@ -35,15 +35,29 @@ async function getMediaConn(options, forceRefresh = false) {
35
35
  options.setMediaConnCache(mediaConn);
36
36
  return mediaConn;
37
37
  }
38
+ function resolveUploadType(content) {
39
+ if (content.type === 'video' && content.gifPlayback)
40
+ return 'gif';
41
+ if (content.type === 'audio' && content.ptt)
42
+ return 'ptt';
43
+ return content.type;
44
+ }
45
+ function isReadableStream(value) {
46
+ return (!!value &&
47
+ typeof value === 'object' &&
48
+ 'pipe' in value &&
49
+ typeof value.pipe === 'function');
50
+ }
38
51
  async function buildMediaMessage(options, content) {
39
- const mediaBytes = (0, bytes_2.toBytesView)(content.media);
40
- const uploaded = await uploadMedia(options, content, mediaBytes);
52
+ const uploaded = isReadableStream(content.media)
53
+ ? await uploadMediaStream(options, content, content.media)
54
+ : await uploadMediaBytes(options, content, (0, bytes_1.toBytesView)(content.media));
41
55
  const mediaKeyTimestamp = Math.floor(Date.now() / 1000);
42
56
  const common = {
43
57
  url: uploaded.url,
44
58
  mimetype: content.mimetype,
45
59
  fileSha256: uploaded.fileSha256,
46
- fileLength: mediaBytes.byteLength,
60
+ fileLength: uploaded.fileLength,
47
61
  mediaKey: uploaded.mediaKey,
48
62
  fileEncSha256: uploaded.fileEncSha256,
49
63
  directPath: uploaded.directPath,
@@ -71,6 +85,15 @@ async function buildMediaMessage(options, content) {
71
85
  metadataUrl: uploaded.metadataUrl
72
86
  }
73
87
  };
88
+ case 'ptv':
89
+ return {
90
+ ptvMessage: {
91
+ ...common,
92
+ seconds: content.seconds,
93
+ width: content.width,
94
+ height: content.height
95
+ }
96
+ };
74
97
  case 'audio':
75
98
  return {
76
99
  audioMessage: {
@@ -97,24 +120,46 @@ async function buildMediaMessage(options, content) {
97
120
  }
98
121
  };
99
122
  default:
100
- throw new Error(`unsupported media type: ${content.type}`);
123
+ throw new Error(`unsupported media message type: ${String(content.type)}`);
124
+ }
125
+ }
126
+ function buildUploadUrl(host, uploadType, auth, fileEncSha256) {
127
+ const hashToken = (0, bytes_1.bytesToBase64UrlSafe)(fileEncSha256);
128
+ const uploadPath = constants_1.MEDIA_UPLOAD_PATHS[uploadType];
129
+ if (!uploadPath) {
130
+ throw new Error(`unknown media upload type: ${String(uploadType)}`);
101
131
  }
132
+ return `https://${host}${uploadPath}/${hashToken}?auth=${encodeURIComponent(auth)}&token=${encodeURIComponent(hashToken)}`;
102
133
  }
103
- async function uploadMedia(options, content, mediaBytes) {
134
+ function parseUploadResponse(body, status) {
135
+ if (status < 200 || status >= 300) {
136
+ throw new Error(`media upload failed with status ${status}`);
137
+ }
138
+ let parsed;
139
+ try {
140
+ parsed = JSON.parse(bytes_1.TEXT_DECODER.decode(body));
141
+ }
142
+ catch (error) {
143
+ throw new Error(`media upload returned invalid json: ${(0, primitives_1.toError)(error).message}`);
144
+ }
145
+ if (!parsed.url || !parsed.direct_path) {
146
+ throw new Error('media upload response missing url/direct_path');
147
+ }
148
+ return {
149
+ url: parsed.url,
150
+ directPath: parsed.direct_path,
151
+ ...(parsed.metadata_url ? { metadataUrl: parsed.metadata_url } : {})
152
+ };
153
+ }
154
+ async function uploadMediaBytes(options, content, mediaBytes) {
155
+ const uploadType = resolveUploadType(content);
104
156
  const mediaKey = await WaMediaCrypto_1.WaMediaCrypto.generateMediaKey();
105
- const uploadType = content.type === 'video' && content.gifPlayback
106
- ? 'gif'
107
- : content.type === 'audio' && content.ptt
108
- ? 'ptt'
109
- : content.type;
110
157
  const [encrypted, mediaConn] = await Promise.all([
111
158
  WaMediaCrypto_1.WaMediaCrypto.encryptBytes(uploadType, mediaKey, mediaBytes),
112
159
  getMediaConn(options)
113
160
  ]);
114
161
  const selectedHost = mediaConn.hosts.find((host) => !host.isFallback)?.hostname ?? mediaConn.hosts[0].hostname;
115
- const uploadPath = constants_1.MEDIA_UPLOAD_PATHS[uploadType];
116
- const hashToken = (0, bytes_1.bytesToBase64UrlSafe)(encrypted.fileEncSha256);
117
- const uploadUrl = `https://${selectedHost}${uploadPath}/${hashToken}?auth=${encodeURIComponent(mediaConn.auth)}&token=${encodeURIComponent(hashToken)}`;
162
+ const uploadUrl = buildUploadUrl(selectedHost, uploadType, mediaConn.auth, encrypted.fileEncSha256);
118
163
  options.logger.debug('sending media upload request', {
119
164
  mediaType: content.type,
120
165
  uploadType,
@@ -127,26 +172,57 @@ async function uploadMedia(options, content, mediaBytes) {
127
172
  contentLength: encrypted.ciphertextHmac.byteLength,
128
173
  contentType: content.mimetype
129
174
  });
130
- const uploadBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
131
- if (!uploadResponse.ok) {
132
- throw new Error(`media upload failed with status ${uploadResponse.status}`);
133
- }
134
- let parsedBody;
135
- try {
136
- parsedBody = JSON.parse(bytes_2.TEXT_DECODER.decode(uploadBody));
137
- }
138
- catch (error) {
139
- throw new Error(`media upload returned invalid json: ${(0, primitives_1.toError)(error).message}`);
140
- }
141
- if (!parsedBody.url || !parsedBody.direct_path) {
142
- throw new Error('media upload response missing url/direct_path');
143
- }
175
+ const responseBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
176
+ const parsed = parseUploadResponse(responseBody, uploadResponse.status);
144
177
  return {
145
- url: parsedBody.url,
146
- directPath: parsedBody.direct_path,
178
+ ...parsed,
147
179
  mediaKey,
148
180
  fileSha256: encrypted.fileSha256,
149
181
  fileEncSha256: encrypted.fileEncSha256,
150
- ...(parsedBody.metadata_url ? { metadataUrl: parsedBody.metadata_url } : {})
182
+ fileLength: mediaBytes.byteLength
151
183
  };
152
184
  }
185
+ async function uploadMediaStream(options, content, stream) {
186
+ const uploadType = resolveUploadType(content);
187
+ const mediaKey = await WaMediaCrypto_1.WaMediaCrypto.generateMediaKey();
188
+ const encResult = await WaMediaCrypto_1.WaMediaCrypto.encryptToFile(uploadType, mediaKey, stream);
189
+ let readStream;
190
+ try {
191
+ const mediaConn = await getMediaConn(options);
192
+ const selectedHost = mediaConn.hosts.find((host) => !host.isFallback)?.hostname ??
193
+ mediaConn.hosts[0].hostname;
194
+ const uploadUrl = buildUploadUrl(selectedHost, uploadType, mediaConn.auth, encResult.fileEncSha256);
195
+ options.logger.debug('sending media stream upload request', {
196
+ mediaType: content.type,
197
+ uploadType,
198
+ host: selectedHost,
199
+ encryptedSize: encResult.fileSize
200
+ });
201
+ readStream = (0, node_fs_1.createReadStream)(encResult.filePath);
202
+ const uploadResponse = await options.mediaTransfer.uploadStream({
203
+ url: uploadUrl,
204
+ method: 'POST',
205
+ body: readStream,
206
+ contentLength: encResult.fileSize,
207
+ contentType: content.mimetype
208
+ });
209
+ const responseBody = await options.mediaTransfer.readResponseBytes(uploadResponse);
210
+ const parsed = parseUploadResponse(responseBody, uploadResponse.status);
211
+ return {
212
+ ...parsed,
213
+ mediaKey,
214
+ fileSha256: encResult.fileSha256,
215
+ fileEncSha256: encResult.fileEncSha256,
216
+ fileLength: encResult.plaintextLength
217
+ };
218
+ }
219
+ finally {
220
+ if (readStream && !readStream.closed) {
221
+ await new Promise((resolve) => {
222
+ readStream.once('close', resolve);
223
+ readStream.destroy();
224
+ });
225
+ }
226
+ await WaMediaCrypto_1.WaMediaCrypto.cleanupEncryptedFile(encResult.filePath);
227
+ }
228
+ }