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
@@ -1,6 +1,6 @@
1
+ import { signalAddressKey } from '../../../protocol/jid.js';
1
2
  import { resolvePositive } from '../../../util/coercion.js';
2
3
  import { setBoundedMapEntry } from '../../../util/collections.js';
3
- import { signalAddressKey } from '../../../util/signal-address.js';
4
4
  const DEFAULT_SIGNAL_STORE_LIMITS = Object.freeze({
5
5
  preKeys: 4096,
6
6
  sessions: 8192,
@@ -126,15 +126,27 @@ export class WaSignalMemoryStore {
126
126
  async getSession(address) {
127
127
  return this.signalSessions.get(signalAddressKey(address)) ?? null;
128
128
  }
129
+ async getSessionsBatch(addresses) {
130
+ return addresses.map((address) => this.signalSessions.get(signalAddressKey(address)) ?? null);
131
+ }
129
132
  async setSession(address, session) {
130
133
  setBoundedMapEntry(this.signalSessions, signalAddressKey(address), session, this.maxSessions);
131
134
  }
135
+ async setSessionsBatch(entries) {
136
+ for (let index = 0; index < entries.length; index += 1) {
137
+ const entry = entries[index];
138
+ setBoundedMapEntry(this.signalSessions, signalAddressKey(entry.address), entry.session, this.maxSessions);
139
+ }
140
+ }
132
141
  async deleteSession(address) {
133
142
  this.signalSessions.delete(signalAddressKey(address));
134
143
  }
135
144
  async getRemoteIdentity(address) {
136
145
  return this.remoteIdentities.get(signalAddressKey(address)) ?? null;
137
146
  }
147
+ async getRemoteIdentities(addresses) {
148
+ return addresses.map((address) => this.remoteIdentities.get(signalAddressKey(address)) ?? null);
149
+ }
138
150
  async setRemoteIdentity(address, identityKey) {
139
151
  setBoundedMapEntry(this.remoteIdentities, signalAddressKey(address), identityKey, this.maxRemoteIdentities);
140
152
  }
@@ -11,6 +11,11 @@ export class WaThreadMemoryStore {
11
11
  async upsert(record) {
12
12
  setBoundedMapEntry(this.threads, record.jid, record, this.maxThreads);
13
13
  }
14
+ async upsertBatch(records) {
15
+ for (const record of records) {
16
+ setBoundedMapEntry(this.threads, record.jid, record, this.maxThreads);
17
+ }
18
+ }
14
19
  async getByJid(jid) {
15
20
  return this.threads.get(jid) ?? null;
16
21
  }
@@ -2,8 +2,18 @@ import { APP_STATE_EMPTY_LT_HASH } from '../../../appstate/constants.js';
2
2
  import { decodeAppStateCollections, decodeAppStateFingerprint, decodeAppStateSyncKeys, encodeAppStateFingerprint } from '../../../appstate/store/sqlite.js';
3
3
  import { keyEpoch, pickActiveSyncKey } from '../../../appstate/utils.js';
4
4
  import { BaseSqliteStore } from '../../providers/sqlite/BaseSqliteStore.js';
5
- import { uint8Equal } from '../../../util/bytes.js';
5
+ import { bytesToHex, uint8Equal } from '../../../util/bytes.js';
6
6
  import { asBytes, asNumber, asString } from '../../../util/coercion.js';
7
+ function repeatSqlToken(token, count, separator) {
8
+ if (count <= 1) {
9
+ return token;
10
+ }
11
+ let out = token;
12
+ for (let index = 1; index < count; index += 1) {
13
+ out += separator + token;
14
+ }
15
+ return out;
16
+ }
7
17
  export class WaAppStateSqliteStore extends BaseSqliteStore {
8
18
  constructor(options) {
9
19
  super(options, ['appState']);
@@ -85,6 +95,25 @@ export class WaAppStateSqliteStore extends BaseSqliteStore {
85
95
  }
86
96
  return asBytes(row.key_data, 'appstate_sync_keys.key_data');
87
97
  }
98
+ async getSyncKeyDataBatch(keyIds) {
99
+ if (keyIds.length === 0) {
100
+ return [];
101
+ }
102
+ const db = await this.getConnection();
103
+ const uniqueKeyIds = [
104
+ ...new Map(keyIds.map((keyId) => [bytesToHex(keyId), keyId])).values()
105
+ ];
106
+ const placeholders = repeatSqlToken('?', uniqueKeyIds.length, ', ');
107
+ const params = [this.options.sessionId, ...uniqueKeyIds];
108
+ const rows = db.all(`SELECT key_id, key_data
109
+ FROM appstate_sync_keys
110
+ WHERE session_id = ? AND key_id IN (${placeholders})`, params);
111
+ const byKeyHex = new Map();
112
+ for (const row of rows) {
113
+ byKeyHex.set(bytesToHex(asBytes(row.key_id, 'appstate_sync_keys.key_id')), asBytes(row.key_data, 'appstate_sync_keys.key_data'));
114
+ }
115
+ return keyIds.map((keyId) => byKeyHex.get(bytesToHex(keyId)) ?? null);
116
+ }
88
117
  async getActiveSyncKey() {
89
118
  const db = await this.getConnection();
90
119
  const rows = db.all(`SELECT key_id, key_data, timestamp, fingerprint
@@ -109,6 +138,7 @@ export class WaAppStateSqliteStore extends BaseSqliteStore {
109
138
  WHERE session_id = ? AND collection = ?`, [this.options.sessionId, collection]);
110
139
  if (!versionRow) {
111
140
  return {
141
+ initialized: false,
112
142
  version: 0,
113
143
  hash: APP_STATE_EMPTY_LT_HASH,
114
144
  indexValueMap: new Map()
@@ -122,11 +152,62 @@ export class WaAppStateSqliteStore extends BaseSqliteStore {
122
152
  indexValueMap.set(asString(row.index_mac_hex, 'appstate_collection_index_values.index_mac_hex'), asBytes(row.value_mac, 'appstate_collection_index_values.value_mac'));
123
153
  }
124
154
  return {
155
+ initialized: true,
125
156
  version: asNumber(versionRow.version, 'appstate_collection_versions.version'),
126
157
  hash: asBytes(versionRow.hash, 'appstate_collection_versions.hash'),
127
158
  indexValueMap
128
159
  };
129
160
  }
161
+ async getCollectionStates(collections) {
162
+ if (collections.length === 0) {
163
+ return [];
164
+ }
165
+ const db = await this.getConnection();
166
+ const uniqueCollections = [...new Set(collections)];
167
+ const placeholders = repeatSqlToken('?', uniqueCollections.length, ', ');
168
+ const params = [this.options.sessionId, ...uniqueCollections];
169
+ const versionRows = db.all(`SELECT collection, version, hash
170
+ FROM appstate_collection_versions
171
+ WHERE session_id = ? AND collection IN (${placeholders})`, params);
172
+ const valueRows = db.all(`SELECT collection, index_mac_hex, value_mac
173
+ FROM appstate_collection_index_values
174
+ WHERE session_id = ? AND collection IN (${placeholders})`, params);
175
+ const versionsByCollection = new Map();
176
+ for (const row of versionRows) {
177
+ const collection = asString(row.collection, 'appstate_collection_versions.collection');
178
+ versionsByCollection.set(collection, {
179
+ version: asNumber(row.version, 'appstate_collection_versions.version'),
180
+ hash: asBytes(row.hash, 'appstate_collection_versions.hash')
181
+ });
182
+ }
183
+ const indexValueMaps = new Map();
184
+ for (const row of valueRows) {
185
+ const collection = asString(row.collection, 'appstate_collection_index_values.collection');
186
+ const map = indexValueMaps.get(collection);
187
+ const targetMap = map ?? new Map();
188
+ targetMap.set(asString(row.index_mac_hex, 'appstate_collection_index_values.index_mac_hex'), asBytes(row.value_mac, 'appstate_collection_index_values.value_mac'));
189
+ if (!map) {
190
+ indexValueMaps.set(collection, targetMap);
191
+ }
192
+ }
193
+ return collections.map((collection) => {
194
+ const version = versionsByCollection.get(collection);
195
+ if (!version) {
196
+ return {
197
+ initialized: false,
198
+ version: 0,
199
+ hash: APP_STATE_EMPTY_LT_HASH,
200
+ indexValueMap: new Map()
201
+ };
202
+ }
203
+ return {
204
+ initialized: true,
205
+ version: version.version,
206
+ hash: version.hash,
207
+ indexValueMap: indexValueMaps.get(collection) ?? new Map()
208
+ };
209
+ });
210
+ }
130
211
  async setCollectionStates(updates) {
131
212
  if (updates.length === 0) {
132
213
  return;
@@ -1,3 +1,4 @@
1
+ import { createSqliteTableNameSqlResolver, resolveSqliteTableNames, serializeSqliteTableNames } from '../../providers/sqlite/table-names.js';
1
2
  import { toSafeNumber } from '../../../util/primitives.js';
2
3
  import { isBunRuntime } from '../../../util/runtime.js';
3
4
  const BETTER_SQLITE3_MODULE = 'better-sqlite3';
@@ -51,21 +52,22 @@ function statementFor(db, sql) {
51
52
  }
52
53
  return statement;
53
54
  }
54
- function wrapConnection(db, driver, onClose) {
55
+ function wrapConnection(db, driver, resolveSql, onClose) {
55
56
  const statementCache = new Map();
56
57
  const cachedStatementFor = (sql) => {
57
- const cached = statementCache.get(sql);
58
+ const resolvedSql = resolveSql(sql);
59
+ const cached = statementCache.get(resolvedSql);
58
60
  if (cached) {
59
61
  return cached;
60
62
  }
61
- const statement = statementFor(db, sql);
62
- statementCache.set(sql, statement);
63
+ const statement = statementFor(db, resolvedSql);
64
+ statementCache.set(resolvedSql, statement);
63
65
  return statement;
64
66
  };
65
67
  return {
66
68
  driver,
67
69
  exec(sql) {
68
- db.exec(sql);
70
+ db.exec(resolveSql(sql));
69
71
  },
70
72
  run(sql, params) {
71
73
  const statement = cachedStatementFor(sql);
@@ -159,7 +161,7 @@ function closeDatabaseSafely(db) {
159
161
  return;
160
162
  }
161
163
  }
162
- async function openBetterSqlite(options, onClose) {
164
+ async function openBetterSqlite(options, resolveSql, onClose) {
163
165
  let loaded;
164
166
  try {
165
167
  loaded = await import(BETTER_SQLITE3_MODULE);
@@ -176,9 +178,9 @@ async function openBetterSqlite(options, onClose) {
176
178
  closeDatabaseSafely(db);
177
179
  throw error;
178
180
  }
179
- return wrapConnection(db, 'better-sqlite3', onClose);
181
+ return wrapConnection(db, 'better-sqlite3', resolveSql, onClose);
180
182
  }
181
- async function openBunSqlite(options, onClose) {
183
+ async function openBunSqlite(options, resolveSql, onClose) {
182
184
  let loaded;
183
185
  try {
184
186
  loaded = await import(BUN_SQLITE_MODULE);
@@ -201,7 +203,7 @@ async function openBunSqlite(options, onClose) {
201
203
  closeDatabaseSafely(db);
202
204
  throw error;
203
205
  }
204
- return wrapConnection(db, 'bun', onClose);
206
+ return wrapConnection(db, 'bun', resolveSql, onClose);
205
207
  }
206
208
  function resolveDriver(requested) {
207
209
  if (requested && requested !== 'auto') {
@@ -211,15 +213,18 @@ function resolveDriver(requested) {
211
213
  }
212
214
  export async function openSqliteConnection(options) {
213
215
  const driver = resolveDriver(options.driver);
216
+ const resolvedTableNames = resolveSqliteTableNames(options.tableNames);
217
+ const resolveSql = createSqliteTableNameSqlResolver(resolvedTableNames);
214
218
  const normalizedOptions = {
215
219
  ...options,
216
220
  driver,
217
- pragmas: mergePragmas(options.pragmas)
221
+ pragmas: mergePragmas(options.pragmas),
222
+ tableNames: resolvedTableNames
218
223
  };
219
224
  const cacheKey = `${driver}|${options.path}|${Object.entries(normalizedOptions.pragmas ?? {})
220
225
  .sort(([left], [right]) => left.localeCompare(right))
221
226
  .map(([key, value]) => `${key}=${String(value)}`)
222
- .join(';')}`;
227
+ .join(';')}|${serializeSqliteTableNames(resolvedTableNames)}`;
223
228
  const cached = SQLITE_CONNECTION_CACHE.get(cacheKey);
224
229
  if (cached) {
225
230
  return cached;
@@ -228,8 +233,8 @@ export async function openSqliteConnection(options) {
228
233
  SQLITE_CONNECTION_CACHE.delete(cacheKey);
229
234
  };
230
235
  const created = driver === 'bun'
231
- ? openBunSqlite(normalizedOptions, onClose)
232
- : openBetterSqlite(normalizedOptions, onClose);
236
+ ? openBunSqlite(normalizedOptions, resolveSql, onClose)
237
+ : openBetterSqlite(normalizedOptions, resolveSql, onClose);
233
238
  const guarded = created.catch((error) => {
234
239
  SQLITE_CONNECTION_CACHE.delete(cacheKey);
235
240
  throw error;
@@ -16,6 +16,37 @@ export class WaContactSqliteStore extends BaseSqliteStore {
16
16
  }
17
17
  async upsert(record) {
18
18
  const db = await this.getConnection();
19
+ this.upsertContactRow(db, record);
20
+ }
21
+ async upsertBatch(records) {
22
+ if (records.length === 0) {
23
+ return;
24
+ }
25
+ await this.withTransaction((db) => {
26
+ for (const record of records) {
27
+ this.upsertContactRow(db, record);
28
+ }
29
+ });
30
+ }
31
+ async getByJid(jid) {
32
+ const db = await this.getConnection();
33
+ const row = db.get(`SELECT jid, display_name, push_name, lid, phone_number, last_updated_ms
34
+ FROM mailbox_contacts
35
+ WHERE session_id = ? AND jid = ?`, [this.options.sessionId, jid]);
36
+ return row ? decodeContactRow(row) : null;
37
+ }
38
+ async deleteByJid(jid) {
39
+ const db = await this.getConnection();
40
+ db.run(`DELETE FROM mailbox_contacts
41
+ WHERE session_id = ? AND jid = ?`, [this.options.sessionId, jid]);
42
+ const row = db.get('SELECT changes() AS total', []);
43
+ return row ? Number(row.total) : 0;
44
+ }
45
+ async clear() {
46
+ const db = await this.getConnection();
47
+ db.run('DELETE FROM mailbox_contacts WHERE session_id = ?', [this.options.sessionId]);
48
+ }
49
+ upsertContactRow(db, record) {
19
50
  db.run(`INSERT INTO mailbox_contacts (
20
51
  session_id,
21
52
  jid,
@@ -40,22 +71,4 @@ export class WaContactSqliteStore extends BaseSqliteStore {
40
71
  record.lastUpdatedMs
41
72
  ]);
42
73
  }
43
- async getByJid(jid) {
44
- const db = await this.getConnection();
45
- const row = db.get(`SELECT jid, display_name, push_name, lid, phone_number, last_updated_ms
46
- FROM mailbox_contacts
47
- WHERE session_id = ? AND jid = ?`, [this.options.sessionId, jid]);
48
- return row ? decodeContactRow(row) : null;
49
- }
50
- async deleteByJid(jid) {
51
- const db = await this.getConnection();
52
- db.run(`DELETE FROM mailbox_contacts
53
- WHERE session_id = ? AND jid = ?`, [this.options.sessionId, jid]);
54
- const row = db.get('SELECT changes() AS total', []);
55
- return row ? Number(row.total) : 0;
56
- }
57
- async clear() {
58
- const db = await this.getConnection();
59
- db.run('DELETE FROM mailbox_contacts WHERE session_id = ?', [this.options.sessionId]);
60
- }
61
74
  }
@@ -10,13 +10,6 @@ export class WaDeviceListSqliteStore extends BaseSqliteStore {
10
10
  this.ttlMs = ttlMs;
11
11
  this.batchSize = resolvePositive(batchSize, DEFAULTS.batchSize, 'deviceList.sqlite.batchSize');
12
12
  }
13
- getTtlMs() {
14
- return this.ttlMs;
15
- }
16
- async upsertUserDevices(snapshot) {
17
- const db = await this.getConnection();
18
- this.upsertUserDevicesRow(db, snapshot);
19
- }
20
13
  async upsertUserDevicesBatch(snapshots) {
21
14
  if (snapshots.length === 0) {
22
15
  return;
@@ -27,26 +20,6 @@ export class WaDeviceListSqliteStore extends BaseSqliteStore {
27
20
  }
28
21
  });
29
22
  }
30
- async getUserDevices(userJid, nowMs = Date.now()) {
31
- const db = await this.getConnection();
32
- const row = db.get(`SELECT user_jid, device_jids_json, updated_at_ms, expires_at_ms
33
- FROM device_list_cache
34
- WHERE session_id = ? AND user_jid = ?`, [this.options.sessionId, userJid]);
35
- if (!row) {
36
- return null;
37
- }
38
- const expiresAtMs = asNumber(row.expires_at_ms, 'device_list_cache.expires_at_ms');
39
- if (expiresAtMs <= nowMs) {
40
- db.run(`DELETE FROM device_list_cache
41
- WHERE session_id = ? AND user_jid = ?`, [this.options.sessionId, userJid]);
42
- return null;
43
- }
44
- return {
45
- userJid: asString(row.user_jid, 'device_list_cache.user_jid'),
46
- deviceJids: decodeDeviceJids(row.device_jids_json),
47
- updatedAtMs: asNumber(row.updated_at_ms, 'device_list_cache.updated_at_ms')
48
- };
49
- }
50
23
  async getUserDevicesBatch(userJids, nowMs = Date.now()) {
51
24
  if (userJids.length === 0) {
52
25
  return [];
@@ -58,7 +31,7 @@ export class WaDeviceListSqliteStore extends BaseSqliteStore {
58
31
  for (let start = 0; start < uniqueUserJids.length; start += this.batchSize) {
59
32
  const end = Math.min(start + this.batchSize, uniqueUserJids.length);
60
33
  const batchLength = end - start;
61
- const placeholders = new Array(batchLength).fill('?').join(', ');
34
+ const placeholders = '?, '.repeat(batchLength).slice(0, -2);
62
35
  const params = [this.options.sessionId];
63
36
  for (let index = start; index < end; index += 1) {
64
37
  params.push(uniqueUserJids[index]);
@@ -130,7 +103,7 @@ export class WaDeviceListSqliteStore extends BaseSqliteStore {
130
103
  for (let start = 0; start < userJids.length; start += this.batchSize) {
131
104
  const end = Math.min(start + this.batchSize, userJids.length);
132
105
  const batchLength = end - start;
133
- const placeholders = new Array(batchLength).fill('?').join(', ');
106
+ const placeholders = '?, '.repeat(batchLength).slice(0, -2);
134
107
  const params = [this.options.sessionId];
135
108
  for (let index = start; index < end; index += 1) {
136
109
  params.push(userJids[index]);
@@ -146,10 +119,9 @@ function decodeDeviceJids(raw) {
146
119
  if (!Array.isArray(parsed)) {
147
120
  throw new Error('device_list_cache.device_jids_json must be an array');
148
121
  }
149
- return parsed.filter((entry) => {
150
- if (typeof entry !== 'string') {
151
- throw new Error('device_list_cache.device_jids_json entry must be string');
152
- }
153
- return true;
154
- });
122
+ const deviceJids = new Array(parsed.length);
123
+ for (let index = 0; index < parsed.length; index += 1) {
124
+ deviceJids[index] = asString(parsed[index], 'device_list_cache.device_jids_json entry');
125
+ }
126
+ return deviceJids;
155
127
  }
@@ -20,38 +20,17 @@ export class WaMessageSqliteStore extends BaseSqliteStore {
20
20
  }
21
21
  async upsert(record) {
22
22
  const db = await this.getConnection();
23
- db.run(`INSERT INTO mailbox_messages (
24
- session_id,
25
- message_id,
26
- thread_jid,
27
- sender_jid,
28
- participant_jid,
29
- from_me,
30
- timestamp_ms,
31
- enc_type,
32
- plaintext,
33
- message_bytes
34
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
35
- ON CONFLICT(session_id, message_id) DO UPDATE SET
36
- thread_jid=excluded.thread_jid,
37
- sender_jid=excluded.sender_jid,
38
- participant_jid=excluded.participant_jid,
39
- from_me=excluded.from_me,
40
- timestamp_ms=excluded.timestamp_ms,
41
- enc_type=excluded.enc_type,
42
- plaintext=excluded.plaintext,
43
- message_bytes=excluded.message_bytes`, [
44
- this.options.sessionId,
45
- record.id,
46
- record.threadJid,
47
- record.senderJid ?? null,
48
- record.participantJid ?? null,
49
- record.fromMe ? 1 : 0,
50
- record.timestampMs ?? null,
51
- record.encType ?? null,
52
- record.plaintext ?? null,
53
- record.messageBytes ?? null
54
- ]);
23
+ this.upsertMessageRow(db, record);
24
+ }
25
+ async upsertBatch(records) {
26
+ if (records.length === 0) {
27
+ return;
28
+ }
29
+ await this.withTransaction((db) => {
30
+ for (const record of records) {
31
+ this.upsertMessageRow(db, record);
32
+ }
33
+ });
55
34
  }
56
35
  async getById(id) {
57
36
  const db = await this.getConnection();
@@ -116,4 +95,38 @@ export class WaMessageSqliteStore extends BaseSqliteStore {
116
95
  const db = await this.getConnection();
117
96
  db.run('DELETE FROM mailbox_messages WHERE session_id = ?', [this.options.sessionId]);
118
97
  }
98
+ upsertMessageRow(db, record) {
99
+ db.run(`INSERT INTO mailbox_messages (
100
+ session_id,
101
+ message_id,
102
+ thread_jid,
103
+ sender_jid,
104
+ participant_jid,
105
+ from_me,
106
+ timestamp_ms,
107
+ enc_type,
108
+ plaintext,
109
+ message_bytes
110
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
111
+ ON CONFLICT(session_id, message_id) DO UPDATE SET
112
+ thread_jid=excluded.thread_jid,
113
+ sender_jid=excluded.sender_jid,
114
+ participant_jid=excluded.participant_jid,
115
+ from_me=excluded.from_me,
116
+ timestamp_ms=excluded.timestamp_ms,
117
+ enc_type=excluded.enc_type,
118
+ plaintext=excluded.plaintext,
119
+ message_bytes=excluded.message_bytes`, [
120
+ this.options.sessionId,
121
+ record.id,
122
+ record.threadJid,
123
+ record.senderJid ?? null,
124
+ record.participantJid ?? null,
125
+ record.fromMe ? 1 : 0,
126
+ record.timestampMs ?? null,
127
+ record.encType ?? null,
128
+ record.plaintext ?? null,
129
+ record.messageBytes ?? null
130
+ ]);
131
+ }
119
132
  }
@@ -293,7 +293,7 @@ function isMigrationAlreadyAppliedRace(error) {
293
293
  if (!(error instanceof Error)) {
294
294
  return false;
295
295
  }
296
- return error.message.includes('UNIQUE constraint failed: wa_migrations.id');
296
+ return /UNIQUE constraint failed: [A-Za-z_][A-Za-z0-9_]*\.id/.test(error.message);
297
297
  }
298
298
  function ensureMigrationTable(db) {
299
299
  db.exec(`
@@ -6,9 +6,6 @@ export class WaParticipantsSqliteStore extends BaseSqliteStore {
6
6
  super(options, ['participants']);
7
7
  this.ttlMs = ttlMs;
8
8
  }
9
- getTtlMs() {
10
- return this.ttlMs;
11
- }
12
9
  async upsertGroupParticipants(snapshot) {
13
10
  const db = await this.getConnection();
14
11
  db.run(`INSERT INTO group_participants_cache (
@@ -76,10 +73,5 @@ function decodeParticipants(raw) {
76
73
  if (!Array.isArray(parsed)) {
77
74
  throw new Error('group_participants_cache.participants_json must be an array');
78
75
  }
79
- return parsed.filter((entry) => {
80
- if (typeof entry !== 'string') {
81
- throw new Error('group_participants_cache.participants_json entry must be string');
82
- }
83
- return true;
84
- });
76
+ return parsed.map((entry) => asString(entry, 'group_participants_cache.participants_json entry'));
85
77
  }
@@ -113,12 +113,18 @@ export class WaRetrySqliteStore extends BaseSqliteStore {
113
113
  }
114
114
  async cleanupExpired(nowMs) {
115
115
  return this.withTransaction(async (db) => {
116
- const outboundCount = this.countRows(db, 'retry_outbound_messages', nowMs);
117
- const inboundCount = this.countRows(db, 'retry_inbound_counters', nowMs);
118
116
  db.run(`DELETE FROM retry_outbound_messages
119
117
  WHERE session_id = ? AND expires_at_ms <= ?`, [this.options.sessionId, nowMs]);
118
+ const outboundCountRow = db.get('SELECT changes() AS total', []);
119
+ const outboundCount = outboundCountRow
120
+ ? asNumber(outboundCountRow.total, 'retry_outbound_messages.changes')
121
+ : 0;
120
122
  db.run(`DELETE FROM retry_inbound_counters
121
123
  WHERE session_id = ? AND expires_at_ms <= ?`, [this.options.sessionId, nowMs]);
124
+ const inboundCountRow = db.get('SELECT changes() AS total', []);
125
+ const inboundCount = inboundCountRow
126
+ ? asNumber(inboundCountRow.total, 'retry_inbound_counters.changes')
127
+ : 0;
122
128
  return outboundCount + inboundCount;
123
129
  });
124
130
  }
@@ -132,13 +138,4 @@ export class WaRetrySqliteStore extends BaseSqliteStore {
132
138
  ]);
133
139
  });
134
140
  }
135
- countRows(db, table, nowMs) {
136
- const row = db.get(`SELECT COUNT(*) AS total
137
- FROM ${table}
138
- WHERE session_id = ? AND expires_at_ms <= ?`, [this.options.sessionId, nowMs]);
139
- if (!row) {
140
- return 0;
141
- }
142
- return asNumber(row.total, `${table}.count`);
143
- }
144
141
  }
@@ -1,4 +1,4 @@
1
- import { decodeSenderKeyDistributionRow, decodeSenderKeyRecord, decodeSqliteCount, encodeSenderKeyRecord, toSignalAddressParts } from '../../../signal/store/sqlite.js';
1
+ import { decodeSenderKeyDistributionRow, decodeSenderKeyRecord, encodeSenderKeyRecord, toSignalAddressParts } from '../../../signal/store/sqlite.js';
2
2
  import { BaseSqliteStore } from '../../providers/sqlite/BaseSqliteStore.js';
3
3
  import { asNumber, asString, resolvePositive } from '../../../util/coercion.js';
4
4
  const DEFAULTS = Object.freeze({
@@ -82,18 +82,6 @@ export class SenderKeySqliteStore extends BaseSqliteStore {
82
82
  device: asNumber(row.sender_device, 'sender_keys.sender_device')
83
83
  });
84
84
  }
85
- async getDeviceSenderKeyDistribution(groupId, sender) {
86
- const db = await this.getConnection();
87
- const target = toSignalAddressParts(sender);
88
- const row = db.get(`SELECT group_id, sender_user, sender_server, sender_device, key_id, timestamp_ms
89
- FROM sender_key_distribution
90
- WHERE session_id = ?
91
- AND group_id = ?
92
- AND sender_user = ?
93
- AND sender_server = ?
94
- AND sender_device = ?`, [this.options.sessionId, groupId, target.user, target.server, target.device]);
95
- return row ? decodeSenderKeyDistributionRow(row) : null;
96
- }
97
85
  async getDeviceSenderKeyDistributions(groupId, senders) {
98
86
  if (senders.length === 0) {
99
87
  return [];
@@ -136,14 +124,29 @@ export class SenderKeySqliteStore extends BaseSqliteStore {
136
124
  if (participants.length === 0) {
137
125
  return 0;
138
126
  }
139
- return this.withTransaction(async (db) => {
140
- let deleted = 0;
141
- for (const participant of participants) {
142
- const sender = toSignalAddressParts(participant);
143
- deleted += this.countDelete(db, 'sender_keys', sender, groupId);
144
- deleted += this.countDelete(db, 'sender_key_distribution', sender, groupId);
127
+ return this.withTransaction((db) => {
128
+ let filters = '';
129
+ const params = [this.options.sessionId, groupId];
130
+ for (let index = 0; index < participants.length; index += 1) {
131
+ if (index > 0) {
132
+ filters += ' OR ';
133
+ }
134
+ filters += '(sender_user = ? AND sender_server = ? AND sender_device = ?)';
135
+ const sender = toSignalAddressParts(participants[index]);
136
+ params.push(sender.user, sender.server, sender.device);
145
137
  }
146
- return deleted;
138
+ const where = `session_id = ? AND group_id = ? AND (${filters})`;
139
+ db.run(`DELETE FROM sender_keys WHERE ${where}`, params);
140
+ const senderCountRow = db.get('SELECT changes() AS total', []);
141
+ const senderCount = senderCountRow
142
+ ? asNumber(senderCountRow.total, 'sender_keys.changes')
143
+ : 0;
144
+ db.run(`DELETE FROM sender_key_distribution WHERE ${where}`, params);
145
+ const distributionCountRow = db.get('SELECT changes() AS total', []);
146
+ const distributionCount = distributionCountRow
147
+ ? asNumber(distributionCountRow.total, 'sender_key_distribution.changes')
148
+ : 0;
149
+ return senderCount + distributionCount;
147
150
  });
148
151
  }
149
152
  async clear() {
@@ -157,20 +160,12 @@ export class SenderKeySqliteStore extends BaseSqliteStore {
157
160
  countDelete(db, table, target, groupId) {
158
161
  const whereWithGroup = 'session_id = ? AND sender_user = ? AND sender_server = ? AND sender_device = ? AND group_id = ?';
159
162
  const whereAllGroups = 'session_id = ? AND sender_user = ? AND sender_server = ? AND sender_device = ?';
160
- const countRow = db.get(`SELECT COUNT(*) AS count
161
- FROM ${table}
162
- WHERE ${groupId ? whereWithGroup : whereAllGroups}`, groupId
163
- ? [this.options.sessionId, target.user, target.server, target.device, groupId]
164
- : [this.options.sessionId, target.user, target.server, target.device]);
165
- const count = decodeSqliteCount(countRow, `${table}.count`);
166
- if (count === 0) {
167
- return 0;
168
- }
169
163
  db.run(`DELETE FROM ${table}
170
164
  WHERE ${groupId ? whereWithGroup : whereAllGroups}`, groupId
171
165
  ? [this.options.sessionId, target.user, target.server, target.device, groupId]
172
166
  : [this.options.sessionId, target.user, target.server, target.device]);
173
- return count;
167
+ const row = db.get('SELECT changes() AS total', []);
168
+ return row ? asNumber(row.total, `${table}.changes`) : 0;
174
169
  }
175
170
  upsertSenderKeyDistributionRow(db, record, sender) {
176
171
  db.run(`INSERT INTO sender_key_distribution (