zapo-js 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/README.md +12 -7
  2. package/dist/appstate/WaAppStateCrypto.js +18 -25
  3. package/dist/appstate/WaAppStateSyncClient.js +181 -114
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
  5. package/dist/appstate/constants.js +4 -3
  6. package/dist/appstate/utils.js +10 -30
  7. package/dist/auth/WaAuthClient.js +48 -55
  8. package/dist/auth/flow/WaAuthCredentialsFlow.js +21 -14
  9. package/dist/auth/index.js +1 -3
  10. package/dist/auth/pairing/WaPairingFlow.js +21 -23
  11. package/dist/auth/pairing/WaQrFlow.js +37 -24
  12. package/dist/client/WaClient.js +103 -276
  13. package/dist/client/WaClientFactory.js +227 -110
  14. package/dist/client/connection/WaConnectionManager.js +292 -0
  15. package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
  16. package/dist/client/connection/WaReceiptQueue.js +51 -0
  17. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
  18. package/dist/client/coordinators/WaGroupCoordinator.js +27 -17
  19. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
  20. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +231 -686
  21. package/dist/client/coordinators/WaRetryCoordinator.js +70 -37
  22. package/dist/client/dirty.js +35 -29
  23. package/dist/client/events/chat.js +4 -3
  24. package/dist/client/events/group.js +59 -36
  25. package/dist/client/history-sync.js +53 -63
  26. package/dist/client/incoming.js +23 -20
  27. package/dist/client/mailbox.js +8 -8
  28. package/dist/client/messages.js +4 -4
  29. package/dist/client/messaging/fanout.js +189 -0
  30. package/dist/client/messaging/key-protocol.js +130 -0
  31. package/dist/client/messaging/participants.js +191 -0
  32. package/dist/crypto/core/hkdf.js +3 -8
  33. package/dist/crypto/core/index.js +1 -4
  34. package/dist/crypto/core/keys.js +2 -3
  35. package/dist/crypto/core/primitives.js +12 -15
  36. package/dist/crypto/core/random.js +7 -26
  37. package/dist/crypto/curves/Ed25519.js +7 -8
  38. package/dist/crypto/curves/X25519.js +13 -16
  39. package/dist/crypto/index.js +0 -5
  40. package/dist/esm/appstate/WaAppStateCrypto.js +6 -13
  41. package/dist/esm/appstate/WaAppStateSyncClient.js +174 -107
  42. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
  43. package/dist/esm/appstate/constants.js +3 -2
  44. package/dist/esm/appstate/utils.js +8 -27
  45. package/dist/esm/auth/WaAuthClient.js +48 -55
  46. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +21 -14
  47. package/dist/esm/auth/index.js +0 -1
  48. package/dist/esm/auth/pairing/WaPairingFlow.js +14 -16
  49. package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
  50. package/dist/esm/client/WaClient.js +103 -276
  51. package/dist/esm/client/WaClientFactory.js +227 -110
  52. package/dist/esm/client/connection/WaConnectionManager.js +288 -0
  53. package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
  54. package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
  55. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
  56. package/dist/esm/client/coordinators/WaGroupCoordinator.js +20 -10
  57. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
  58. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +232 -687
  59. package/dist/esm/client/coordinators/WaRetryCoordinator.js +71 -38
  60. package/dist/esm/client/dirty.js +30 -24
  61. package/dist/esm/client/events/chat.js +4 -3
  62. package/dist/esm/client/events/group.js +50 -28
  63. package/dist/esm/client/history-sync.js +50 -60
  64. package/dist/esm/client/incoming.js +23 -20
  65. package/dist/esm/client/mailbox.js +8 -8
  66. package/dist/esm/client/messages.js +1 -1
  67. package/dist/esm/client/messaging/fanout.js +186 -0
  68. package/dist/esm/client/messaging/key-protocol.js +127 -0
  69. package/dist/esm/client/messaging/participants.js +188 -0
  70. package/dist/esm/crypto/core/hkdf.js +3 -8
  71. package/dist/esm/crypto/core/index.js +0 -1
  72. package/dist/esm/crypto/core/keys.js +2 -3
  73. package/dist/esm/crypto/core/primitives.js +12 -15
  74. package/dist/esm/crypto/core/random.js +6 -25
  75. package/dist/esm/crypto/curves/Ed25519.js +4 -5
  76. package/dist/esm/crypto/curves/X25519.js +10 -13
  77. package/dist/esm/crypto/index.js +0 -2
  78. package/dist/esm/infra/log/ConsoleLogger.js +18 -17
  79. package/dist/esm/infra/log/PinoLogger.js +15 -9
  80. package/dist/esm/infra/log/types.js +11 -1
  81. package/dist/esm/infra/perf/BoundedTaskQueue.js +13 -17
  82. package/dist/esm/media/WaMediaCrypto.js +2 -4
  83. package/dist/esm/media/WaMediaTransferClient.js +226 -58
  84. package/dist/esm/media/conn.js +10 -6
  85. package/dist/esm/media/constants.js +4 -1
  86. package/dist/esm/message/WaMessageClient.js +4 -13
  87. package/dist/esm/message/ack.js +6 -6
  88. package/dist/esm/message/addon-crypto.js +59 -0
  89. package/dist/esm/message/incoming.js +106 -111
  90. package/dist/esm/message/index.js +2 -0
  91. package/dist/esm/message/reporting-token.js +438 -0
  92. package/dist/esm/message/use-case-secret.js +49 -0
  93. package/dist/esm/protocol/appstate.js +58 -0
  94. package/dist/esm/protocol/constants.js +2 -1
  95. package/dist/esm/protocol/index.js +2 -10
  96. package/dist/esm/protocol/jid.js +63 -51
  97. package/dist/esm/protocol/media.js +3 -3
  98. package/dist/esm/protocol/nodes.js +2 -0
  99. package/dist/esm/protocol/usync.js +11 -0
  100. package/dist/esm/retry/index.js +1 -0
  101. package/dist/esm/retry/outbound.js +4 -5
  102. package/dist/esm/retry/parse.js +58 -76
  103. package/dist/esm/retry/replay.js +48 -49
  104. package/dist/esm/retry/tracker.js +56 -0
  105. package/dist/esm/signal/api/SignalDeviceSyncApi.js +249 -82
  106. package/dist/esm/signal/api/SignalDigestSyncApi.js +6 -1
  107. package/dist/esm/signal/api/SignalIdentitySyncApi.js +49 -34
  108. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +70 -62
  109. package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -30
  110. package/dist/esm/signal/crypto/WaAdvSignature.js +3 -5
  111. package/dist/esm/signal/group/SenderKeyChain.js +28 -23
  112. package/dist/esm/signal/group/SenderKeyCodec.js +2 -4
  113. package/dist/esm/signal/group/SenderKeyManager.js +26 -16
  114. package/dist/esm/signal/index.js +1 -0
  115. package/dist/esm/signal/session/SignalProtocol.js +49 -14
  116. package/dist/esm/signal/session/SignalRatchet.js +24 -15
  117. package/dist/esm/signal/session/SignalSession.js +14 -9
  118. package/dist/esm/signal/session/resolver.js +186 -0
  119. package/dist/esm/signal/store/sqlite.js +16 -37
  120. package/dist/esm/store/createStore.js +16 -18
  121. package/dist/esm/store/noop.store.js +3 -6
  122. package/dist/esm/store/providers/memory/appstate.store.js +30 -6
  123. package/dist/esm/store/providers/memory/contact.store.js +5 -0
  124. package/dist/esm/store/providers/memory/device-list.store.js +3 -30
  125. package/dist/esm/store/providers/memory/message.store.js +11 -5
  126. package/dist/esm/store/providers/memory/participants.store.js +1 -8
  127. package/dist/esm/store/providers/memory/sender-key.store.js +5 -7
  128. package/dist/esm/store/providers/memory/signal.store.js +13 -1
  129. package/dist/esm/store/providers/memory/thread.store.js +5 -0
  130. package/dist/esm/store/providers/sqlite/appstate.store.js +82 -1
  131. package/dist/esm/store/providers/sqlite/connection.js +18 -13
  132. package/dist/esm/store/providers/sqlite/contact.store.js +31 -18
  133. package/dist/esm/store/providers/sqlite/device-list.store.js +7 -35
  134. package/dist/esm/store/providers/sqlite/message.store.js +45 -32
  135. package/dist/esm/store/providers/sqlite/migrations.js +1 -1
  136. package/dist/esm/store/providers/sqlite/participants.store.js +1 -9
  137. package/dist/esm/store/providers/sqlite/retry.store.js +8 -11
  138. package/dist/esm/store/providers/sqlite/sender-key.store.js +25 -30
  139. package/dist/esm/store/providers/sqlite/signal.store.js +104 -22
  140. package/dist/esm/store/providers/sqlite/table-names.js +107 -0
  141. package/dist/esm/store/providers/sqlite/thread.store.js +35 -22
  142. package/dist/esm/transport/WaComms.js +25 -23
  143. package/dist/esm/transport/WaWebSocket.js +115 -12
  144. package/dist/esm/transport/binary/decoder.js +4 -4
  145. package/dist/esm/transport/binary/encoder.js +12 -4
  146. package/dist/esm/transport/index.js +1 -0
  147. package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
  148. package/dist/esm/transport/node/WaNodeOrchestrator.js +2 -4
  149. package/dist/esm/transport/node/WaNodeTransport.js +0 -3
  150. package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
  151. package/dist/esm/transport/node/builders/index.js +2 -1
  152. package/dist/esm/transport/node/builders/message.js +9 -0
  153. package/dist/esm/transport/node/builders/pairing.js +4 -5
  154. package/dist/esm/transport/node/builders/usync.js +41 -0
  155. package/dist/esm/transport/node/helpers.js +107 -5
  156. package/dist/esm/transport/node/usync.js +35 -0
  157. package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
  158. package/dist/esm/transport/noise/WaNoiseCert.js +3 -6
  159. package/dist/esm/transport/noise/WaNoiseSession.js +17 -10
  160. package/dist/esm/transport/proxy.js +27 -0
  161. package/dist/esm/transport/stream/parse.js +13 -48
  162. package/dist/esm/util/bytes.js +50 -32
  163. package/dist/esm/util/coercion.js +6 -14
  164. package/dist/esm/util/primitives.js +39 -14
  165. package/dist/infra/log/ConsoleLogger.js +18 -17
  166. package/dist/infra/log/PinoLogger.js +15 -9
  167. package/dist/infra/log/types.js +12 -0
  168. package/dist/infra/perf/BoundedTaskQueue.js +13 -17
  169. package/dist/media/WaMediaCrypto.js +1 -3
  170. package/dist/media/WaMediaTransferClient.js +259 -58
  171. package/dist/media/conn.js +10 -6
  172. package/dist/media/constants.js +4 -1
  173. package/dist/message/WaMessageClient.js +5 -14
  174. package/dist/message/ack.js +6 -6
  175. package/dist/message/addon-crypto.js +65 -0
  176. package/dist/message/incoming.js +104 -109
  177. package/dist/message/index.js +2 -0
  178. package/dist/message/reporting-token.js +443 -0
  179. package/dist/message/use-case-secret.js +55 -0
  180. package/dist/protocol/appstate.js +59 -1
  181. package/dist/protocol/constants.js +7 -1
  182. package/dist/protocol/index.js +20 -42
  183. package/dist/protocol/jid.js +64 -51
  184. package/dist/protocol/media.js +3 -3
  185. package/dist/protocol/nodes.js +2 -0
  186. package/dist/protocol/usync.js +14 -0
  187. package/dist/retry/index.js +3 -1
  188. package/dist/retry/outbound.js +6 -7
  189. package/dist/retry/parse.js +57 -75
  190. package/dist/retry/replay.js +46 -47
  191. package/dist/retry/tracker.js +59 -0
  192. package/dist/signal/api/SignalDeviceSyncApi.js +247 -80
  193. package/dist/signal/api/SignalDigestSyncApi.js +6 -1
  194. package/dist/signal/api/SignalIdentitySyncApi.js +49 -34
  195. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +67 -59
  196. package/dist/signal/api/SignalSessionSyncApi.js +23 -30
  197. package/dist/signal/crypto/WaAdvSignature.js +2 -4
  198. package/dist/signal/group/SenderKeyChain.js +27 -22
  199. package/dist/signal/group/SenderKeyCodec.js +1 -3
  200. package/dist/signal/group/SenderKeyManager.js +26 -16
  201. package/dist/signal/index.js +3 -1
  202. package/dist/signal/session/SignalProtocol.js +49 -14
  203. package/dist/signal/session/SignalRatchet.js +24 -15
  204. package/dist/signal/session/SignalSession.js +14 -9
  205. package/dist/signal/session/resolver.js +189 -0
  206. package/dist/signal/store/sqlite.js +16 -37
  207. package/dist/store/createStore.js +16 -18
  208. package/dist/store/noop.store.js +3 -6
  209. package/dist/store/providers/memory/appstate.store.js +28 -4
  210. package/dist/store/providers/memory/contact.store.js +5 -0
  211. package/dist/store/providers/memory/device-list.store.js +3 -30
  212. package/dist/store/providers/memory/message.store.js +11 -5
  213. package/dist/store/providers/memory/participants.store.js +1 -8
  214. package/dist/store/providers/memory/sender-key.store.js +8 -10
  215. package/dist/store/providers/memory/signal.store.js +21 -9
  216. package/dist/store/providers/memory/thread.store.js +5 -0
  217. package/dist/store/providers/sqlite/appstate.store.js +81 -0
  218. package/dist/store/providers/sqlite/connection.js +18 -13
  219. package/dist/store/providers/sqlite/contact.store.js +31 -18
  220. package/dist/store/providers/sqlite/device-list.store.js +7 -35
  221. package/dist/store/providers/sqlite/message.store.js +45 -32
  222. package/dist/store/providers/sqlite/migrations.js +1 -1
  223. package/dist/store/providers/sqlite/participants.store.js +1 -9
  224. package/dist/store/providers/sqlite/retry.store.js +8 -11
  225. package/dist/store/providers/sqlite/sender-key.store.js +24 -29
  226. package/dist/store/providers/sqlite/signal.store.js +105 -23
  227. package/dist/store/providers/sqlite/table-names.js +113 -0
  228. package/dist/store/providers/sqlite/thread.store.js +35 -22
  229. package/dist/transport/WaComms.js +27 -25
  230. package/dist/transport/WaWebSocket.js +148 -12
  231. package/dist/transport/binary/decoder.js +4 -4
  232. package/dist/transport/binary/encoder.js +12 -4
  233. package/dist/transport/index.js +7 -1
  234. package/dist/transport/keepalive/WaKeepAlive.js +1 -7
  235. package/dist/transport/node/WaNodeOrchestrator.js +2 -4
  236. package/dist/transport/node/WaNodeTransport.js +0 -3
  237. package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
  238. package/dist/transport/node/builders/index.js +12 -9
  239. package/dist/transport/node/builders/message.js +9 -0
  240. package/dist/transport/node/builders/pairing.js +4 -5
  241. package/dist/transport/node/builders/usync.js +45 -0
  242. package/dist/transport/node/helpers.js +112 -4
  243. package/dist/transport/node/usync.js +38 -0
  244. package/dist/transport/noise/WaFrameCodec.js +47 -32
  245. package/dist/transport/noise/WaNoiseCert.js +5 -8
  246. package/dist/transport/noise/WaNoiseSession.js +17 -10
  247. package/dist/transport/proxy.js +34 -0
  248. package/dist/transport/stream/parse.js +17 -53
  249. package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
  250. package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
  251. package/dist/types/appstate/constants.d.ts +1 -0
  252. package/dist/types/appstate/store/sqlite.d.ts +4 -18
  253. package/dist/types/appstate/utils.d.ts +0 -1
  254. package/dist/types/auth/WaAuthClient.d.ts +10 -12
  255. package/dist/types/auth/index.d.ts +0 -2
  256. package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
  257. package/dist/types/auth/types.d.ts +6 -9
  258. package/dist/types/client/WaClient.d.ts +27 -25
  259. package/dist/types/client/WaClientFactory.d.ts +22 -23
  260. package/dist/types/client/connection/WaConnectionManager.d.ts +64 -0
  261. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
  262. package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
  263. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
  264. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +0 -1
  265. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +18 -41
  266. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +2 -0
  267. package/dist/types/client/dirty.d.ts +1 -0
  268. package/dist/types/client/events/group.d.ts +2 -1
  269. package/dist/types/client/index.d.ts +1 -1
  270. package/dist/types/client/messaging/fanout.d.ts +14 -0
  271. package/dist/types/client/messaging/key-protocol.d.ts +18 -0
  272. package/dist/types/client/messaging/participants.d.ts +13 -0
  273. package/dist/types/client/types.d.ts +24 -1
  274. package/dist/types/crypto/core/hkdf.d.ts +0 -6
  275. package/dist/types/crypto/core/index.d.ts +0 -1
  276. package/dist/types/crypto/core/random.d.ts +1 -7
  277. package/dist/types/crypto/index.d.ts +0 -2
  278. package/dist/types/index.d.ts +1 -1
  279. package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
  280. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  281. package/dist/types/infra/log/types.d.ts +1 -0
  282. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
  283. package/dist/types/media/WaMediaTransferClient.d.ts +13 -3
  284. package/dist/types/media/types.d.ts +5 -0
  285. package/dist/types/message/addon-crypto.d.ts +25 -0
  286. package/dist/types/message/index.d.ts +2 -0
  287. package/dist/types/message/reporting-token.d.ts +19 -0
  288. package/dist/types/message/use-case-secret.d.ts +20 -0
  289. package/dist/types/protocol/appstate.d.ts +58 -0
  290. package/dist/types/protocol/constants.d.ts +2 -1
  291. package/dist/types/protocol/index.d.ts +2 -10
  292. package/dist/types/protocol/jid.d.ts +3 -3
  293. package/dist/types/protocol/nodes.d.ts +2 -0
  294. package/dist/types/protocol/usync.d.ts +11 -0
  295. package/dist/types/retry/index.d.ts +1 -0
  296. package/dist/types/retry/replay.d.ts +0 -4
  297. package/dist/types/retry/tracker.d.ts +19 -0
  298. package/dist/types/retry/types.d.ts +4 -3
  299. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +13 -1
  300. package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
  301. package/dist/types/signal/index.d.ts +1 -0
  302. package/dist/types/signal/session/SignalProtocol.d.ts +9 -0
  303. package/dist/types/signal/session/resolver.d.ts +17 -0
  304. package/dist/types/store/contracts/appstate.store.d.ts +3 -0
  305. package/dist/types/store/contracts/contact.store.d.ts +1 -0
  306. package/dist/types/store/contracts/device-list.store.d.ts +0 -3
  307. package/dist/types/store/contracts/message.store.d.ts +1 -0
  308. package/dist/types/store/contracts/participants.store.d.ts +0 -1
  309. package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
  310. package/dist/types/store/contracts/signal.store.d.ts +6 -0
  311. package/dist/types/store/contracts/thread.store.d.ts +1 -0
  312. package/dist/types/store/index.d.ts +1 -1
  313. package/dist/types/store/providers/memory/appstate.store.d.ts +2 -0
  314. package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
  315. package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
  316. package/dist/types/store/providers/memory/message.store.d.ts +1 -0
  317. package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
  318. package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
  319. package/dist/types/store/providers/memory/signal.store.d.ts +6 -0
  320. package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
  321. package/dist/types/store/providers/sqlite/appstate.store.d.ts +2 -0
  322. package/dist/types/store/providers/sqlite/contact.store.d.ts +2 -0
  323. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -3
  324. package/dist/types/store/providers/sqlite/message.store.d.ts +2 -0
  325. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -1
  326. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -1
  327. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -1
  328. package/dist/types/store/providers/sqlite/signal.store.d.ts +7 -0
  329. package/dist/types/store/providers/sqlite/table-names.d.ts +5 -0
  330. package/dist/types/store/providers/sqlite/thread.store.d.ts +2 -0
  331. package/dist/types/store/types.d.ts +3 -0
  332. package/dist/types/transport/WaWebSocket.d.ts +3 -0
  333. package/dist/types/transport/index.d.ts +2 -1
  334. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
  335. package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
  336. package/dist/types/transport/node/builders/group.d.ts +4 -6
  337. package/dist/types/transport/node/builders/index.d.ts +2 -1
  338. package/dist/types/transport/node/builders/message.d.ts +14 -25
  339. package/dist/types/transport/node/builders/retry.d.ts +2 -4
  340. package/dist/types/transport/node/builders/usync.d.ts +21 -0
  341. package/dist/types/transport/node/helpers.d.ts +8 -0
  342. package/dist/types/transport/node/usync.d.ts +2 -0
  343. package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
  344. package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -0
  345. package/dist/types/transport/proxy.d.ts +6 -0
  346. package/dist/types/transport/stream/parse.d.ts +0 -1
  347. package/dist/types/transport/types.d.ts +18 -1
  348. package/dist/types/util/bytes.d.ts +5 -0
  349. package/dist/types/util/primitives.d.ts +3 -0
  350. package/dist/util/bytes.js +55 -33
  351. package/dist/util/coercion.js +6 -14
  352. package/dist/util/primitives.js +42 -14
  353. package/package.json +27 -9
  354. package/proto/index.d.ts +1090 -1048
  355. package/proto/index.js +1 -1
  356. package/scripts/check-node-version.cjs +0 -1
  357. package/dist/crypto/core/encoding.js +0 -29
  358. package/dist/esm/crypto/core/encoding.js +0 -25
  359. package/dist/esm/util/base64.js +0 -18
  360. package/dist/esm/util/signal-address.js +0 -5
  361. package/dist/types/crypto/core/encoding.d.ts +0 -11
  362. package/dist/types/util/base64.d.ts +0 -4
  363. package/dist/types/util/signal-address.d.ts +0 -2
  364. package/dist/util/base64.js +0 -24
  365. package/dist/util/signal-address.js +0 -8
  366. /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
@@ -4,27 +4,95 @@ import { WaMediaCrypto } from './WaMediaCrypto.js';
4
4
  import { WA_DEFAULTS } from '../protocol/constants.js';
5
5
  import { EMPTY_BYTES, readAllBytes } from '../util/bytes.js';
6
6
  import { toError } from '../util/primitives.js';
7
+ const GOT_OPTIONAL_MODULE = 'got';
8
+ function normalizeHeaderRecord(headers) {
9
+ if (!headers) {
10
+ return {};
11
+ }
12
+ const normalized = {};
13
+ for (const key in headers) {
14
+ normalized[key.toLowerCase()] = headers[key];
15
+ }
16
+ return normalized;
17
+ }
18
+ function asOptionalGotModule(loaded) {
19
+ if (loaded && typeof loaded === 'object') {
20
+ const direct = loaded.stream;
21
+ if (typeof direct === 'function') {
22
+ return loaded;
23
+ }
24
+ const fallback = loaded.default;
25
+ if (fallback &&
26
+ typeof fallback === 'object' &&
27
+ 'stream' in fallback &&
28
+ typeof fallback.stream === 'function') {
29
+ return fallback;
30
+ }
31
+ if (typeof fallback === 'function' && 'stream' in fallback) {
32
+ const maybeStream = fallback.stream;
33
+ if (typeof maybeStream === 'function') {
34
+ return fallback;
35
+ }
36
+ }
37
+ }
38
+ if (typeof loaded === 'function' && 'stream' in loaded) {
39
+ const maybeStream = loaded.stream;
40
+ if (typeof maybeStream === 'function') {
41
+ return loaded;
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+ async function loadOptionalGotModule() {
47
+ try {
48
+ const loaded = await import(GOT_OPTIONAL_MODULE);
49
+ const module = asOptionalGotModule(loaded);
50
+ if (module) {
51
+ return module;
52
+ }
53
+ throw new Error('invalid got module export');
54
+ }
55
+ catch (error) {
56
+ const normalized = toError(error);
57
+ const code = normalized.code;
58
+ const message = normalized.message ?? '';
59
+ const isModuleNotFound = (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') &&
60
+ (message.includes(`'${GOT_OPTIONAL_MODULE}'`) ||
61
+ message.includes(`"${GOT_OPTIONAL_MODULE}"`));
62
+ if (isModuleNotFound) {
63
+ throw new Error('optional dependency "got" is not installed. Install with: npm i got');
64
+ }
65
+ throw normalized;
66
+ }
67
+ }
7
68
  export class WaMediaTransferClient {
8
69
  constructor(options = {}) {
9
70
  this.logger = options.logger;
10
71
  this.defaultHosts = options.defaultHosts ?? DEFAULT_MEDIA_HOSTS;
11
72
  this.defaultTimeoutMs = options.defaultTimeoutMs ?? WA_DEFAULTS.MEDIA_TIMEOUT_MS;
12
73
  this.defaultMaxReadBytes = options.defaultMaxReadBytes;
13
- this.defaultHeaders = options.defaultHeaders ?? {};
74
+ this.defaultHeaders = normalizeHeaderRecord(options.defaultHeaders);
75
+ this.defaultUploadDispatcher = options.defaultUploadDispatcher;
76
+ this.defaultDownloadDispatcher = options.defaultDownloadDispatcher;
77
+ this.defaultUploadAgent = options.defaultUploadAgent;
78
+ this.defaultDownloadAgent = options.defaultDownloadAgent;
79
+ this.gotModulePromise = null;
14
80
  }
15
81
  async downloadStream(request) {
16
82
  const { urls, headers, timeoutMs } = this.resolveTransferRequest(request);
83
+ const dispatcher = request.dispatcher ?? this.defaultDownloadDispatcher;
84
+ const agent = request.agent ?? this.defaultDownloadAgent;
17
85
  this.logger?.debug('media download stream start', {
18
86
  urls: urls.length,
19
87
  timeoutMs
20
88
  });
21
89
  return this.executeTransfer(urls, timeoutMs, request.signal, {
22
90
  responseLog: 'media download stream response',
23
- send: (url, signal) => fetch(url, {
91
+ send: (url, signal) => this.transferRequest(url, {
24
92
  method: 'GET',
25
93
  headers,
26
94
  signal
27
- })
95
+ }, dispatcher, agent)
28
96
  });
29
97
  }
30
98
  async downloadBytes(request) {
@@ -43,6 +111,8 @@ export class WaMediaTransferClient {
43
111
  ? String(request.contentLength)
44
112
  : undefined
45
113
  });
114
+ const dispatcher = request.dispatcher ?? this.defaultUploadDispatcher;
115
+ const agent = request.agent ?? this.defaultUploadAgent;
46
116
  const uploadUrls = bodyIsBytes ? urls : urls.slice(0, 1);
47
117
  if (!bodyIsBytes && urls.length > 1) {
48
118
  this.logger?.warn('upload stream fallback disabled for non-replayable body', {
@@ -59,20 +129,20 @@ export class WaMediaTransferClient {
59
129
  responseLog: 'media upload stream response',
60
130
  send: async (url, signal) => {
61
131
  if (bodyIsBytes) {
62
- return fetch(url, {
132
+ return this.transferRequest(url, {
63
133
  method,
64
134
  headers,
65
135
  signal,
66
136
  body: request.body
67
- });
137
+ }, dispatcher, agent);
68
138
  }
69
- return fetch(url, {
139
+ return this.transferRequest(url, {
70
140
  method,
71
141
  headers,
72
142
  signal,
73
143
  body: request.body,
74
144
  duplex: 'half'
75
- });
145
+ }, dispatcher, agent);
76
146
  }
77
147
  });
78
148
  }
@@ -89,6 +159,8 @@ export class WaMediaTransferClient {
89
159
  directPath: request.directPath,
90
160
  hosts: request.hosts,
91
161
  headers: request.headers,
162
+ dispatcher: request.dispatcher,
163
+ agent: request.agent,
92
164
  timeoutMs: request.timeoutMs,
93
165
  signal: request.signal,
94
166
  method: request.method,
@@ -118,10 +190,8 @@ export class WaMediaTransferClient {
118
190
  });
119
191
  const decrypted = await this.downloadAndDecryptStream(request);
120
192
  try {
121
- const [plaintext] = await Promise.all([
122
- this.readAllBytesWithLimit(decrypted.plaintext, request.maxBytes),
123
- decrypted.metadata
124
- ]);
193
+ const plaintext = await this.readAllBytesWithLimit(decrypted.plaintext, request.maxBytes);
194
+ await decrypted.metadata;
125
195
  this.logger?.info('media encrypted download completed', {
126
196
  byteLength: plaintext.byteLength
127
197
  });
@@ -157,11 +227,133 @@ export class WaMediaTransferClient {
157
227
  }
158
228
  return this.readAllBytesWithLimit(response.body, maxBytes);
159
229
  }
230
+ async transferRequest(url, init, dispatcher, agent) {
231
+ if (agent) {
232
+ return this.gotWithAgent(url, init, agent);
233
+ }
234
+ return this.fetchWithDispatcher(url, init, dispatcher);
235
+ }
236
+ async fetchWithDispatcher(url, init, dispatcher) {
237
+ const response = !dispatcher
238
+ ? await fetch(url, init)
239
+ : await fetch(url, {
240
+ ...init,
241
+ dispatcher
242
+ });
243
+ return this.toFetchTransferResponse(response);
244
+ }
245
+ toFetchTransferResponse(response) {
246
+ return {
247
+ status: response.status,
248
+ ok: response.ok,
249
+ headers: this.headersToRecord(response.headers),
250
+ body: response.body
251
+ ? Readable.fromWeb(response.body)
252
+ : null,
253
+ cancel: async () => {
254
+ if (!response.body) {
255
+ return;
256
+ }
257
+ try {
258
+ await response.body.cancel();
259
+ }
260
+ catch {
261
+ // ignore cancel errors from remote resets
262
+ }
263
+ }
264
+ };
265
+ }
266
+ async gotWithAgent(url, init, agent) {
267
+ const got = await this.loadGotModule();
268
+ const urlObj = new URL(url);
269
+ const gotAgent = urlObj.protocol === 'http:'
270
+ ? { http: agent }
271
+ : urlObj.protocol === 'https:'
272
+ ? { https: agent }
273
+ : { http: agent, https: agent };
274
+ return new Promise((resolve, reject) => {
275
+ const request = got.stream(url, {
276
+ method: init.method,
277
+ headers: (init.headers ?? {}),
278
+ body: init.body,
279
+ signal: init.signal,
280
+ throwHttpErrors: false,
281
+ retry: { limit: 0 },
282
+ agent: gotAgent
283
+ });
284
+ const onError = (error) => {
285
+ request.off('response', onResponse);
286
+ reject(toError(error));
287
+ };
288
+ const onResponse = (incoming) => {
289
+ request.off('error', onError);
290
+ resolve(this.toGotTransferResponse(incoming));
291
+ };
292
+ request.once('error', onError);
293
+ request.once('response', onResponse);
294
+ });
295
+ }
296
+ async loadGotModule() {
297
+ if (!this.gotModulePromise) {
298
+ this.gotModulePromise = loadOptionalGotModule().catch((error) => {
299
+ this.gotModulePromise = null;
300
+ throw error;
301
+ });
302
+ }
303
+ return this.gotModulePromise;
304
+ }
305
+ toGotTransferResponse(incoming) {
306
+ if (!incoming || typeof incoming !== 'object') {
307
+ throw new Error('invalid got response object');
308
+ }
309
+ const stream = incoming;
310
+ const status = typeof stream.statusCode === 'number' &&
311
+ Number.isFinite(stream.statusCode) &&
312
+ stream.statusCode >= 100 &&
313
+ stream.statusCode <= 599
314
+ ? stream.statusCode
315
+ : 500;
316
+ const headers = {};
317
+ if (stream.headers && typeof stream.headers === 'object') {
318
+ const input = stream.headers;
319
+ for (const key in input) {
320
+ const value = input[key];
321
+ if (typeof value === 'string') {
322
+ headers[key] = value;
323
+ continue;
324
+ }
325
+ if (Array.isArray(value)) {
326
+ headers[key] = value.join(', ');
327
+ continue;
328
+ }
329
+ if (value !== undefined && value !== null) {
330
+ headers[key] = String(value);
331
+ }
332
+ }
333
+ }
334
+ return {
335
+ status,
336
+ ok: status >= 200 && status < 300,
337
+ headers,
338
+ body: stream,
339
+ cancel: async () => {
340
+ stream.destroy();
341
+ }
342
+ };
343
+ }
160
344
  resolveTransferRequest(request, extraHeaders) {
161
- const headers = this.mergeHeaders(request.headers);
162
- for (const [key, value] of Object.entries(extraHeaders ?? {})) {
163
- if (value !== undefined) {
164
- headers[key.toLowerCase()] = value;
345
+ const headers = { ...this.defaultHeaders };
346
+ if (request.headers) {
347
+ for (const key in request.headers) {
348
+ headers[key.toLowerCase()] = request.headers[key];
349
+ }
350
+ }
351
+ if (extraHeaders) {
352
+ for (const key in extraHeaders) {
353
+ const value = extraHeaders[key];
354
+ if (value !== undefined) {
355
+ headers[key.toLowerCase()] = value;
356
+ }
165
357
  }
166
358
  }
167
359
  return {
@@ -174,9 +366,9 @@ export class WaMediaTransferClient {
174
366
  const result = await this.fetchWithFallback(urls, timeoutMs, signal, options.send);
175
367
  this.logger?.trace(options.responseLog, {
176
368
  url: result.url,
177
- status: result.response.status
369
+ status: result.status
178
370
  });
179
- return this.toResponse(result.url, result.response);
371
+ return result;
180
372
  }
181
373
  async prepareEncryptedUpload(request, mediaKey) {
182
374
  if (request.plaintext instanceof Uint8Array) {
@@ -219,34 +411,26 @@ export class WaMediaTransferClient {
219
411
  }
220
412
  resolveUrls(url, directPath, hosts) {
221
413
  const resolved = [];
222
- if (url) {
414
+ if (url && resolved.indexOf(url) === -1)
223
415
  resolved.push(url);
224
- }
225
416
  if (directPath) {
226
417
  if (directPath.startsWith('https://') || directPath.startsWith('http://')) {
227
- resolved.push(directPath);
418
+ if (resolved.indexOf(directPath) === -1)
419
+ resolved.push(directPath);
228
420
  }
229
421
  else {
230
422
  const normalizedPath = directPath.startsWith('/') ? directPath : `/${directPath}`;
231
423
  for (const host of hosts ?? this.defaultHosts) {
232
- resolved.push(`https://${host}${normalizedPath}`);
424
+ const candidate = `https://${host}${normalizedPath}`;
425
+ if (resolved.indexOf(candidate) === -1)
426
+ resolved.push(candidate);
233
427
  }
234
428
  }
235
429
  }
236
430
  if (resolved.length === 0) {
237
431
  throw new Error('missing transfer url/directPath');
238
432
  }
239
- return Array.from(new Set(resolved));
240
- }
241
- mergeHeaders(headers) {
242
- const merged = {};
243
- for (const [key, value] of Object.entries(this.defaultHeaders)) {
244
- merged[key.toLowerCase()] = value;
245
- }
246
- for (const [key, value] of Object.entries(headers ?? {})) {
247
- merged[key.toLowerCase()] = value;
248
- }
249
- return merged;
433
+ return resolved;
250
434
  }
251
435
  readAllBytesWithLimit(stream, maxBytes) {
252
436
  return readAllBytes(stream, {
@@ -262,9 +446,15 @@ export class WaMediaTransferClient {
262
446
  const response = await send(url, abort.signal);
263
447
  const shouldFallback = response.status >= 500 && index < urls.length - 1;
264
448
  if (!shouldFallback) {
265
- return { url, response };
449
+ return {
450
+ url,
451
+ status: response.status,
452
+ ok: response.ok,
453
+ headers: response.headers,
454
+ body: response.body
455
+ };
266
456
  }
267
- await this.cancelWebBody(response.body);
457
+ await response.cancel();
268
458
  this.logger?.warn('transfer fallback to next host', {
269
459
  url,
270
460
  status: response.status
@@ -316,35 +506,13 @@ export class WaMediaTransferClient {
316
506
  }
317
507
  };
318
508
  }
319
- toResponse(url, response) {
320
- return {
321
- url,
322
- status: response.status,
323
- ok: response.ok,
324
- headers: this.headersToRecord(response.headers),
325
- body: response.body
326
- ? Readable.fromWeb(response.body)
327
- : null
328
- };
329
- }
330
509
  headersToRecord(headers) {
331
510
  const output = {};
332
- for (const [key, value] of headers.entries()) {
511
+ headers.forEach((value, key) => {
333
512
  output[key] = value;
334
- }
513
+ });
335
514
  return output;
336
515
  }
337
- async cancelWebBody(body) {
338
- if (!body) {
339
- return;
340
- }
341
- try {
342
- await body.cancel();
343
- }
344
- catch {
345
- // ignore cancel errors from remote resets
346
- }
347
- }
348
516
  async drainBody(body) {
349
517
  if (!body) {
350
518
  return;
@@ -16,12 +16,16 @@ export function parseMediaConnResponse(node, nowMs) {
16
16
  throw new Error('media_conn response has invalid ttl');
17
17
  }
18
18
  const expiresAtMs = ttlRaw >= 1000000000 ? ttlRaw * 1000 : nowMs + ttlRaw * 1000;
19
- const hosts = getNodeChildrenByTag(mediaConnNode, WA_NODE_TAGS.HOST)
20
- .map((host) => ({
21
- hostname: host.attrs.hostname ?? '',
22
- isFallback: host.attrs.type === 'fallback'
23
- }))
24
- .filter((host) => host.hostname.length > 0);
19
+ const hosts = [];
20
+ for (const host of getNodeChildrenByTag(mediaConnNode, WA_NODE_TAGS.HOST)) {
21
+ const hostname = host.attrs.hostname;
22
+ if (hostname) {
23
+ hosts.push({
24
+ hostname,
25
+ isFallback: host.attrs.type === 'fallback'
26
+ });
27
+ }
28
+ }
25
29
  if (hosts.length === 0) {
26
30
  throw new Error('media_conn response contains no hosts');
27
31
  }
@@ -1,4 +1,7 @@
1
- export const DEFAULT_MEDIA_HOSTS = ['mmg.whatsapp.net', 'mmg-fallback.whatsapp.net'];
1
+ export const DEFAULT_MEDIA_HOSTS = Object.freeze([
2
+ 'mmg.whatsapp.net',
3
+ 'mmg-fallback.whatsapp.net'
4
+ ]);
2
5
  export const MEDIA_CONN_CACHE_GRACE_MS = 30000;
3
6
  export const MEDIA_HKDF_SIZE = 112;
4
7
  export const IV_SIZE = 16;
@@ -1,8 +1,8 @@
1
1
  import { describeAckNode, isAckOrReceiptNode, isNegativeAckNode, isRetryableNegativeAck } from './ack.js';
2
2
  import { WA_DEFAULTS, WA_MESSAGE_TAGS, WA_MESSAGE_TYPES, WA_NODE_TAGS } from '../protocol/constants.js';
3
- import { parseOptionalInt } from '../transport/stream/parse.js';
4
3
  import { delay } from '../util/async.js';
5
- import { toError } from '../util/primitives.js';
4
+ import { parseOptionalInt, toError } from '../util/primitives.js';
5
+ const WA_RETRYABLE_PUBLISH_ERROR_RE = /timeout|socket|connection|closed/i;
6
6
  class MessagePublishNackError extends Error {
7
7
  constructor(message, retryable) {
8
8
  super(message);
@@ -102,12 +102,7 @@ export class WaMessageClient {
102
102
  }
103
103
  async sendEncrypted(input) {
104
104
  const node = this.buildEncryptedMessageNode(input);
105
- this.logger.debug('encrypted message sent without waiting for ack', {
106
- to: node.attrs.to,
107
- type: node.attrs.type,
108
- id: node.attrs.id
109
- });
110
- await this.sendNode(node);
105
+ await this.sendMessageNode(node);
111
106
  }
112
107
  buildEncryptedMessageNode(input) {
113
108
  const attrs = {
@@ -186,11 +181,7 @@ export class WaMessageClient {
186
181
  });
187
182
  }
188
183
  isRetryablePublishError(error) {
189
- const message = error.message.toLowerCase();
190
- return (message.includes('timeout') ||
191
- message.includes('socket') ||
192
- message.includes('connection') ||
193
- message.includes('closed'));
184
+ return WA_RETRYABLE_PUBLISH_ERROR_RE.test(error.message);
194
185
  }
195
186
  extractAckMetadata(ackNode) {
196
187
  const addressingModeRaw = ackNode.attrs.addressing_mode;
@@ -25,22 +25,22 @@ export function isRetryableNegativeAck(node) {
25
25
  return false;
26
26
  }
27
27
  export function describeAckNode(node) {
28
- const parts = [`tag=${node.tag}`];
28
+ let description = `tag=${node.tag}`;
29
29
  const id = node.attrs.id;
30
30
  const type = node.attrs.type;
31
31
  const ackClass = node.attrs.class;
32
32
  const code = node.attrs.code;
33
33
  if (id) {
34
- parts.push(`id=${id}`);
34
+ description += ` id=${id}`;
35
35
  }
36
36
  if (type) {
37
- parts.push(`type=${type}`);
37
+ description += ` type=${type}`;
38
38
  }
39
39
  if (ackClass) {
40
- parts.push(`class=${ackClass}`);
40
+ description += ` class=${ackClass}`;
41
41
  }
42
42
  if (code) {
43
- parts.push(`code=${code}`);
43
+ description += ` code=${code}`;
44
44
  }
45
- return parts.join(' ');
45
+ return description;
46
46
  }
@@ -0,0 +1,59 @@
1
+ import { aesGcmDecrypt, aesGcmEncrypt, importAesGcmKey } from '../crypto/index.js';
2
+ import { assertMessageSecret, createUseCaseSecret, WA_USE_CASE_SECRET_MODIFICATION_TYPES } from './use-case-secret.js';
3
+ import { EMPTY_BYTES, TEXT_ENCODER, toBytesView } from '../util/bytes.js';
4
+ const WA_ADDON_ENCRYPTION_NONCE_BYTES = 12;
5
+ export function shouldUseAddonAdditionalData(modificationType) {
6
+ return (modificationType === WA_USE_CASE_SECRET_MODIFICATION_TYPES.POLL_VOTE ||
7
+ modificationType === WA_USE_CASE_SECRET_MODIFICATION_TYPES.EVENT_RESPONSE);
8
+ }
9
+ export function buildAddonAdditionalData(stanzaId, addOnSenderJid) {
10
+ if (!stanzaId.trim()) {
11
+ throw new Error('stanza id must be a non-empty string');
12
+ }
13
+ if (!addOnSenderJid.trim()) {
14
+ throw new Error('addon sender jid must be a non-empty string');
15
+ }
16
+ return TEXT_ENCODER.encode(`${stanzaId}\u0000${addOnSenderJid}`);
17
+ }
18
+ export async function encryptAddonPayload(input) {
19
+ const secret = await createUseCaseSecret({
20
+ messageSecret: assertMessageSecret(input.messageSecret),
21
+ stanzaId: input.stanzaId,
22
+ parentMsgOriginalSender: input.parentMsgOriginalSender,
23
+ modificationSender: input.modificationSender,
24
+ modificationType: input.modificationType
25
+ });
26
+ const key = await importAesGcmKey(secret, ['encrypt']);
27
+ const iv = assertAddonIv(input.iv);
28
+ const additionalData = resolveAddonAdditionalData(input);
29
+ return aesGcmEncrypt(key, iv, toBytesView(input.payload), additionalData);
30
+ }
31
+ export async function decryptAddonPayload(input) {
32
+ const secret = await createUseCaseSecret({
33
+ messageSecret: assertMessageSecret(input.messageSecret),
34
+ stanzaId: input.stanzaId,
35
+ parentMsgOriginalSender: input.parentMsgOriginalSender,
36
+ modificationSender: input.modificationSender,
37
+ modificationType: input.modificationType
38
+ });
39
+ const key = await importAesGcmKey(secret, ['decrypt']);
40
+ const iv = assertAddonIv(input.iv);
41
+ const additionalData = resolveAddonAdditionalData(input);
42
+ return aesGcmDecrypt(key, iv, toBytesView(input.ciphertext), additionalData);
43
+ }
44
+ function assertAddonIv(iv) {
45
+ const normalized = toBytesView(iv);
46
+ if (normalized.byteLength !== WA_ADDON_ENCRYPTION_NONCE_BYTES) {
47
+ throw new Error(`addon iv must be ${WA_ADDON_ENCRYPTION_NONCE_BYTES} bytes (got ${normalized.byteLength})`);
48
+ }
49
+ return normalized;
50
+ }
51
+ function resolveAddonAdditionalData(input) {
52
+ if (input.additionalData) {
53
+ return toBytesView(input.additionalData);
54
+ }
55
+ if (!shouldUseAddonAdditionalData(input.modificationType)) {
56
+ return EMPTY_BYTES;
57
+ }
58
+ return buildAddonAdditionalData(input.stanzaId, input.modificationSender);
59
+ }