@seriousme/opifex 1.11.3 → 2.0.3

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 (531) hide show
  1. package/README.md +99 -40
  2. package/bin/conformanceServer.ts +45 -13
  3. package/bin/demoServer.ts +38 -13
  4. package/bin/mqtt.ts +2 -2
  5. package/client/ConnectionState.ts +2 -0
  6. package/client/client.ts +51 -41
  7. package/client/context.ts +75 -21
  8. package/client/deps.ts +4 -0
  9. package/client/handlers/handleAuth.test.ts +193 -0
  10. package/client/handlers/handleAuth.ts +89 -0
  11. package/client/handlers/handleConnack.test.ts +173 -0
  12. package/client/handlers/handleConnack.ts +16 -6
  13. package/client/handlers/handleDisconnect.test.ts +22 -0
  14. package/client/handlers/handleDisconnect.ts +17 -0
  15. package/client/handlers/handlePacket.test.ts +242 -0
  16. package/client/handlers/handlePacket.ts +19 -5
  17. package/client/handlers/handlePuback.test.ts +99 -0
  18. package/client/handlers/handlePuback.ts +6 -0
  19. package/client/handlers/handlePubcomp.test.ts +112 -0
  20. package/client/handlers/handlePubcomp.ts +5 -0
  21. package/client/handlers/handlePublish.test.ts +188 -0
  22. package/client/handlers/handlePubrec.test.ts +119 -0
  23. package/client/handlers/handlePubrec.ts +5 -1
  24. package/client/handlers/handlePubrel.test.ts +136 -0
  25. package/client/handlers/handleSuback.test.ts +122 -0
  26. package/client/handlers/handleSuback.ts +3 -0
  27. package/client/handlers/handleUnsuback.test.ts +101 -0
  28. package/client/mod.ts +1 -1
  29. package/client/store/memoryStore.ts +2 -2
  30. package/client/store/store.ts +3 -1
  31. package/deno/README.md +1 -2
  32. package/deno/tcpClient.test.ts +75 -0
  33. package/deno/tcpClient.ts +16 -11
  34. package/deno/tcpServer.test.ts +22 -21
  35. package/deno/tcpServer.ts +5 -0
  36. package/deno/tlsServer.test.ts +97 -0
  37. package/deno/tlsServer.ts +42 -0
  38. package/deno/wsServer.test.ts +93 -0
  39. package/deno/wsServer.ts +73 -0
  40. package/dev_utils/generateCert.ts +95 -0
  41. package/dev_utils/mockConn.ts +36 -0
  42. package/dev_utils/mockServer.ts +28 -0
  43. package/dev_utils/mod.ts +30 -3
  44. package/dev_utils/packetHelpers.ts +404 -0
  45. package/dev_utils/test-handlers.ts +98 -0
  46. package/dev_utils/timers.ts +14 -0
  47. package/dev_utils/webStreamPair.test.ts +171 -0
  48. package/dev_utils/webStreamPair.ts +143 -0
  49. package/dist/bin/conformanceServer.js +17 -12
  50. package/dist/bin/conformanceServer.js.map +1 -1
  51. package/dist/bin/demoServer.js +16 -12
  52. package/dist/bin/demoServer.js.map +1 -1
  53. package/dist/bin/mqtt.js +2 -2
  54. package/dist/bin/mqtt.js.map +1 -1
  55. package/dist/client/ConnectionState.d.ts +2 -0
  56. package/dist/client/ConnectionState.d.ts.map +1 -1
  57. package/dist/client/ConnectionState.js +2 -0
  58. package/dist/client/ConnectionState.js.map +1 -1
  59. package/dist/client/client.d.ts +13 -16
  60. package/dist/client/client.d.ts.map +1 -1
  61. package/dist/client/client.js +34 -20
  62. package/dist/client/client.js.map +1 -1
  63. package/dist/client/context.d.ts +11 -3
  64. package/dist/client/context.d.ts.map +1 -1
  65. package/dist/client/context.js +44 -12
  66. package/dist/client/context.js.map +1 -1
  67. package/dist/client/deps.d.ts +3 -2
  68. package/dist/client/deps.d.ts.map +1 -1
  69. package/dist/client/deps.js +1 -1
  70. package/dist/client/deps.js.map +1 -1
  71. package/dist/client/handlers/handleAuth.d.ts +9 -0
  72. package/dist/client/handlers/handleAuth.d.ts.map +1 -0
  73. package/dist/client/handlers/handleAuth.js +66 -0
  74. package/dist/client/handlers/handleAuth.js.map +1 -0
  75. package/dist/client/handlers/handleConnack.d.ts +2 -2
  76. package/dist/client/handlers/handleConnack.d.ts.map +1 -1
  77. package/dist/client/handlers/handleConnack.js +16 -6
  78. package/dist/client/handlers/handleConnack.js.map +1 -1
  79. package/dist/client/handlers/handleDisconnect.d.ts +11 -0
  80. package/dist/client/handlers/handleDisconnect.d.ts.map +1 -0
  81. package/dist/client/handlers/handleDisconnect.js +15 -0
  82. package/dist/client/handlers/handleDisconnect.js.map +1 -0
  83. package/dist/client/handlers/handlePacket.d.ts.map +1 -1
  84. package/dist/client/handlers/handlePacket.js +14 -3
  85. package/dist/client/handlers/handlePacket.js.map +1 -1
  86. package/dist/client/handlers/handlePuback.d.ts.map +1 -1
  87. package/dist/client/handlers/handlePuback.js +5 -0
  88. package/dist/client/handlers/handlePuback.js.map +1 -1
  89. package/dist/client/handlers/handlePubcomp.d.ts.map +1 -1
  90. package/dist/client/handlers/handlePubcomp.js +5 -0
  91. package/dist/client/handlers/handlePubcomp.js.map +1 -1
  92. package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
  93. package/dist/client/handlers/handlePubrec.js +5 -1
  94. package/dist/client/handlers/handlePubrec.js.map +1 -1
  95. package/dist/client/handlers/handleSuback.d.ts +1 -0
  96. package/dist/client/handlers/handleSuback.d.ts.map +1 -1
  97. package/dist/client/handlers/handleSuback.js +3 -0
  98. package/dist/client/handlers/handleSuback.js.map +1 -1
  99. package/dist/client/mod.d.ts +1 -1
  100. package/dist/client/mod.d.ts.map +1 -1
  101. package/dist/client/mod.js +1 -1
  102. package/dist/client/mod.js.map +1 -1
  103. package/dist/client/store/memoryStore.d.ts.map +1 -1
  104. package/dist/client/store/memoryStore.js +2 -2
  105. package/dist/client/store/memoryStore.js.map +1 -1
  106. package/dist/client/store/store.d.ts +2 -1
  107. package/dist/client/store/store.d.ts.map +1 -1
  108. package/dist/client/store/store.js +1 -1
  109. package/dist/client/store/store.js.map +1 -1
  110. package/dist/dev_utils/generateCert.d.ts +11 -0
  111. package/dist/dev_utils/generateCert.d.ts.map +1 -0
  112. package/dist/dev_utils/generateCert.js +76 -0
  113. package/dist/dev_utils/generateCert.js.map +1 -0
  114. package/dist/examples/authHandler.test.d.ts +2 -0
  115. package/dist/examples/authHandler.test.d.ts.map +1 -0
  116. package/dist/examples/authHandler.test.js +123 -0
  117. package/dist/examples/authHandler.test.js.map +1 -0
  118. package/dist/examples/mqtt.test.d.ts +2 -0
  119. package/dist/examples/mqtt.test.d.ts.map +1 -0
  120. package/dist/examples/mqtt.test.js +70 -0
  121. package/dist/examples/mqtt.test.js.map +1 -0
  122. package/dist/examples/mqtts.test.d.ts +2 -0
  123. package/dist/examples/mqtts.test.d.ts.map +1 -0
  124. package/dist/examples/mqtts.test.js +81 -0
  125. package/dist/examples/mqtts.test.js.map +1 -0
  126. package/dist/mqttConn/mqttConn.d.ts +23 -15
  127. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  128. package/dist/mqttConn/mqttConn.js +56 -35
  129. package/dist/mqttConn/mqttConn.js.map +1 -1
  130. package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
  131. package/dist/mqttPacket/BitMask.d.ts.map +1 -1
  132. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  133. package/dist/mqttPacket/Properties.d.ts +2 -2
  134. package/dist/mqttPacket/Properties.d.ts.map +1 -1
  135. package/dist/mqttPacket/Properties.js.map +1 -1
  136. package/dist/mqttPacket/ReasonCode.d.ts +1 -0
  137. package/dist/mqttPacket/ReasonCode.d.ts.map +1 -1
  138. package/dist/mqttPacket/ReasonCode.js +1 -0
  139. package/dist/mqttPacket/ReasonCode.js.map +1 -1
  140. package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
  141. package/dist/mqttPacket/auth.d.ts +3 -5
  142. package/dist/mqttPacket/auth.d.ts.map +1 -1
  143. package/dist/mqttPacket/auth.js +31 -30
  144. package/dist/mqttPacket/auth.js.map +1 -1
  145. package/dist/mqttPacket/codec.d.ts +48 -0
  146. package/dist/mqttPacket/codec.d.ts.map +1 -0
  147. package/dist/mqttPacket/codec.js +93 -0
  148. package/dist/mqttPacket/codec.js.map +1 -0
  149. package/dist/mqttPacket/connack.d.ts +4 -5
  150. package/dist/mqttPacket/connack.d.ts.map +1 -1
  151. package/dist/mqttPacket/connack.js +43 -45
  152. package/dist/mqttPacket/connack.js.map +1 -1
  153. package/dist/mqttPacket/connect.d.ts +4 -5
  154. package/dist/mqttPacket/connect.d.ts.map +1 -1
  155. package/dist/mqttPacket/connect.js +156 -157
  156. package/dist/mqttPacket/connect.js.map +1 -1
  157. package/dist/mqttPacket/decoder.d.ts +1 -13
  158. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  159. package/dist/mqttPacket/decoder.js +6 -27
  160. package/dist/mqttPacket/decoder.js.map +1 -1
  161. package/dist/mqttPacket/disconnect.d.ts +4 -5
  162. package/dist/mqttPacket/disconnect.d.ts.map +1 -1
  163. package/dist/mqttPacket/disconnect.js +41 -43
  164. package/dist/mqttPacket/disconnect.js.map +1 -1
  165. package/dist/mqttPacket/encoder.d.ts +1 -15
  166. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  167. package/dist/mqttPacket/encoder.js +4 -27
  168. package/dist/mqttPacket/encoder.js.map +1 -1
  169. package/dist/mqttPacket/mod.d.ts +21 -103
  170. package/dist/mqttPacket/mod.d.ts.map +1 -1
  171. package/dist/mqttPacket/mod.js +5 -94
  172. package/dist/mqttPacket/mod.js.map +1 -1
  173. package/dist/mqttPacket/pingreq.d.ts +4 -5
  174. package/dist/mqttPacket/pingreq.d.ts.map +1 -1
  175. package/dist/mqttPacket/pingreq.js +11 -13
  176. package/dist/mqttPacket/pingreq.js.map +1 -1
  177. package/dist/mqttPacket/pingres.d.ts +4 -5
  178. package/dist/mqttPacket/pingres.d.ts.map +1 -1
  179. package/dist/mqttPacket/pingres.js +11 -13
  180. package/dist/mqttPacket/pingres.js.map +1 -1
  181. package/dist/mqttPacket/protocolLevels.d.ts +11 -6
  182. package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
  183. package/dist/mqttPacket/protocolLevels.js +5 -1
  184. package/dist/mqttPacket/protocolLevels.js.map +1 -1
  185. package/dist/mqttPacket/pubblishAcks.d.ts +4 -5
  186. package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
  187. package/dist/mqttPacket/pubblishAcks.js +43 -45
  188. package/dist/mqttPacket/pubblishAcks.js.map +1 -1
  189. package/dist/mqttPacket/publish.d.ts +5 -5
  190. package/dist/mqttPacket/publish.d.ts.map +1 -1
  191. package/dist/mqttPacket/publish.js +53 -55
  192. package/dist/mqttPacket/publish.js.map +1 -1
  193. package/dist/mqttPacket/suback.d.ts +4 -5
  194. package/dist/mqttPacket/suback.d.ts.map +1 -1
  195. package/dist/mqttPacket/suback.js +38 -40
  196. package/dist/mqttPacket/suback.js.map +1 -1
  197. package/dist/mqttPacket/subscribe.d.ts +36 -7
  198. package/dist/mqttPacket/subscribe.d.ts.map +1 -1
  199. package/dist/mqttPacket/subscribe.js +90 -89
  200. package/dist/mqttPacket/subscribe.js.map +1 -1
  201. package/dist/mqttPacket/types.d.ts +1 -8
  202. package/dist/mqttPacket/types.d.ts.map +1 -1
  203. package/dist/mqttPacket/unsuback.d.ts +4 -5
  204. package/dist/mqttPacket/unsuback.d.ts.map +1 -1
  205. package/dist/mqttPacket/unsuback.js +32 -34
  206. package/dist/mqttPacket/unsuback.js.map +1 -1
  207. package/dist/mqttPacket/unsubscribe.d.ts +23 -6
  208. package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
  209. package/dist/mqttPacket/unsubscribe.js +45 -44
  210. package/dist/mqttPacket/unsubscribe.js.map +1 -1
  211. package/dist/mqttPacket/validators.d.ts +4 -16
  212. package/dist/mqttPacket/validators.d.ts.map +1 -1
  213. package/dist/mqttPacket/validators.js +5 -26
  214. package/dist/mqttPacket/validators.js.map +1 -1
  215. package/dist/node/tcpClient.d.ts +1 -1
  216. package/dist/node/tcpClient.d.ts.map +1 -1
  217. package/dist/node/tcpClient.js +12 -7
  218. package/dist/node/tcpClient.js.map +1 -1
  219. package/dist/node/tcpServer.d.ts.map +1 -1
  220. package/dist/node/tcpServer.js +4 -0
  221. package/dist/node/tcpServer.js.map +1 -1
  222. package/dist/node/tlsServer.d.ts +19 -0
  223. package/dist/node/tlsServer.d.ts.map +1 -0
  224. package/dist/node/tlsServer.js +58 -0
  225. package/dist/node/tlsServer.js.map +1 -0
  226. package/dist/node/wrapNodeSocket.d.ts.map +1 -1
  227. package/dist/node/wrapNodeSocket.js +6 -28
  228. package/dist/node/wrapNodeSocket.js.map +1 -1
  229. package/dist/persistence/basicPersistence.d.ts +36 -0
  230. package/dist/persistence/basicPersistence.d.ts.map +1 -0
  231. package/dist/persistence/basicPersistence.js +306 -0
  232. package/dist/persistence/basicPersistence.js.map +1 -0
  233. package/dist/persistence/deps.d.ts +3 -2
  234. package/dist/persistence/deps.d.ts.map +1 -1
  235. package/dist/persistence/deps.js +2 -1
  236. package/dist/persistence/deps.js.map +1 -1
  237. package/dist/persistence/memory/memoryPersistence.d.ts +6 -23
  238. package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
  239. package/dist/persistence/memory/memoryPersistence.js +12 -115
  240. package/dist/persistence/memory/memoryPersistence.js.map +1 -1
  241. package/dist/persistence/memory/memoryStorage.d.ts +45 -0
  242. package/dist/persistence/memory/memoryStorage.d.ts.map +1 -0
  243. package/dist/persistence/memory/memoryStorage.js +143 -0
  244. package/dist/persistence/memory/memoryStorage.js.map +1 -0
  245. package/dist/persistence/mod.d.ts +3 -3
  246. package/dist/persistence/mod.d.ts.map +1 -1
  247. package/dist/persistence/mod.js +6 -1
  248. package/dist/persistence/mod.js.map +1 -1
  249. package/dist/persistence/persistence.d.ts +44 -69
  250. package/dist/persistence/persistence.d.ts.map +1 -1
  251. package/dist/persistence/persistence.js +1 -2
  252. package/dist/persistence/persistence.js.map +1 -1
  253. package/dist/persistence/sqlite/sqliteDatabase.d.ts +46 -0
  254. package/dist/persistence/sqlite/sqliteDatabase.d.ts.map +1 -0
  255. package/dist/persistence/sqlite/sqliteDatabase.js +215 -0
  256. package/dist/persistence/sqlite/sqliteDatabase.js.map +1 -0
  257. package/dist/persistence/sqlite/sqlitePersistence.d.ts +16 -0
  258. package/dist/persistence/sqlite/sqlitePersistence.d.ts.map +1 -0
  259. package/dist/persistence/sqlite/sqlitePersistence.js +29 -0
  260. package/dist/persistence/sqlite/sqlitePersistence.js.map +1 -0
  261. package/dist/persistence/sqlite/sqliteStorage.d.ts +36 -0
  262. package/dist/persistence/sqlite/sqliteStorage.d.ts.map +1 -0
  263. package/dist/persistence/sqlite/sqliteStorage.js +194 -0
  264. package/dist/persistence/sqlite/sqliteStorage.js.map +1 -0
  265. package/dist/persistence/storage.d.ts +38 -0
  266. package/dist/persistence/storage.d.ts.map +1 -0
  267. package/dist/persistence/storage.js +5 -0
  268. package/dist/persistence/storage.js.map +1 -0
  269. package/dist/server/config.d.ts +47 -0
  270. package/dist/server/config.d.ts.map +1 -0
  271. package/dist/server/config.js +41 -0
  272. package/dist/server/config.js.map +1 -0
  273. package/dist/server/context.d.ts +198 -24
  274. package/dist/server/context.d.ts.map +1 -1
  275. package/dist/server/context.js +432 -53
  276. package/dist/server/context.js.map +1 -1
  277. package/dist/server/deps.d.ts +5 -6
  278. package/dist/server/deps.d.ts.map +1 -1
  279. package/dist/server/deps.js +2 -2
  280. package/dist/server/deps.js.map +1 -1
  281. package/dist/server/handlers/completeConnect.d.ts +8 -0
  282. package/dist/server/handlers/completeConnect.d.ts.map +1 -0
  283. package/dist/server/handlers/completeConnect.js +74 -0
  284. package/dist/server/handlers/completeConnect.js.map +1 -0
  285. package/dist/server/handlers/handleAuth.d.ts +9 -0
  286. package/dist/server/handlers/handleAuth.d.ts.map +1 -0
  287. package/dist/server/handlers/handleAuth.js +69 -0
  288. package/dist/server/handlers/handleAuth.js.map +1 -0
  289. package/dist/server/handlers/handleConnect.d.ts +2 -4
  290. package/dist/server/handlers/handleConnect.d.ts.map +1 -1
  291. package/dist/server/handlers/handleConnect.js +140 -67
  292. package/dist/server/handlers/handleConnect.js.map +1 -1
  293. package/dist/server/handlers/handleDisconnect.d.ts +1 -1
  294. package/dist/server/handlers/handleDisconnect.d.ts.map +1 -1
  295. package/dist/server/handlers/handleDisconnect.js +3 -3
  296. package/dist/server/handlers/handleDisconnect.js.map +1 -1
  297. package/dist/server/handlers/handlePacket.d.ts.map +1 -1
  298. package/dist/server/handlers/handlePacket.js +19 -6
  299. package/dist/server/handlers/handlePacket.js.map +1 -1
  300. package/dist/server/handlers/handlePuback.d.ts +1 -3
  301. package/dist/server/handlers/handlePuback.d.ts.map +1 -1
  302. package/dist/server/handlers/handlePuback.js +2 -8
  303. package/dist/server/handlers/handlePuback.js.map +1 -1
  304. package/dist/server/handlers/handlePubcomp.d.ts +1 -1
  305. package/dist/server/handlers/handlePubcomp.d.ts.map +1 -1
  306. package/dist/server/handlers/handlePubcomp.js +2 -4
  307. package/dist/server/handlers/handlePubcomp.js.map +1 -1
  308. package/dist/server/handlers/handlePublish.d.ts +1 -1
  309. package/dist/server/handlers/handlePublish.d.ts.map +1 -1
  310. package/dist/server/handlers/handlePublish.js +149 -45
  311. package/dist/server/handlers/handlePublish.js.map +1 -1
  312. package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
  313. package/dist/server/handlers/handlePubrec.js +2 -3
  314. package/dist/server/handlers/handlePubrec.js.map +1 -1
  315. package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
  316. package/dist/server/handlers/handlePubrel.js +6 -2
  317. package/dist/server/handlers/handlePubrel.js.map +1 -1
  318. package/dist/server/handlers/handleSubscribe.d.ts +1 -6
  319. package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
  320. package/dist/server/handlers/handleSubscribe.js +99 -38
  321. package/dist/server/handlers/handleSubscribe.js.map +1 -1
  322. package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
  323. package/dist/server/handlers/handleUnsubscribe.js +19 -4
  324. package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
  325. package/dist/server/mod.d.ts +3 -3
  326. package/dist/server/mod.d.ts.map +1 -1
  327. package/dist/server/mod.js +1 -1
  328. package/dist/server/mod.js.map +1 -1
  329. package/dist/server/server.d.ts +29 -6
  330. package/dist/server/server.d.ts.map +1 -1
  331. package/dist/server/server.js +84 -15
  332. package/dist/server/server.js.map +1 -1
  333. package/dist/socket/socket.d.ts +11 -9
  334. package/dist/socket/socket.d.ts.map +1 -1
  335. package/dist/socket/socket.js +66 -18
  336. package/dist/socket/socket.js.map +1 -1
  337. package/dist/timer/timer.d.ts +32 -0
  338. package/dist/timer/timer.d.ts.map +1 -1
  339. package/dist/timer/timer.js +32 -0
  340. package/dist/timer/timer.js.map +1 -1
  341. package/dist/trie/trie.d.ts +10 -5
  342. package/dist/trie/trie.d.ts.map +1 -1
  343. package/dist/trie/trie.js +61 -41
  344. package/dist/trie/trie.js.map +1 -1
  345. package/dist/utils/assert.d.ts.map +1 -1
  346. package/dist/utils/{BufferedAsyncIterable.d.ts → bufferedAsyncIterable.d.ts} +1 -1
  347. package/dist/utils/bufferedAsyncIterable.d.ts.map +1 -0
  348. package/dist/utils/{BufferedAsyncIterable.js → bufferedAsyncIterable.js} +1 -1
  349. package/dist/utils/bufferedAsyncIterable.js.map +1 -0
  350. package/dist/utils/deferred.d.ts.map +1 -1
  351. package/dist/utils/deferred.js.map +1 -1
  352. package/dist/utils/getOrInsertPolyFill.d.ts +2 -0
  353. package/dist/utils/getOrInsertPolyFill.d.ts.map +1 -0
  354. package/dist/utils/getOrInsertPolyFill.js +12 -0
  355. package/dist/utils/getOrInsertPolyFill.js.map +1 -0
  356. package/dist/utils/logger.d.ts +40 -3
  357. package/dist/utils/logger.d.ts.map +1 -1
  358. package/dist/utils/logger.js +53 -7
  359. package/dist/utils/logger.js.map +1 -1
  360. package/dist/utils/mod.d.ts +6 -1
  361. package/dist/utils/mod.d.ts.map +1 -1
  362. package/dist/utils/mod.js +5 -1
  363. package/dist/utils/mod.js.map +1 -1
  364. package/dist/utils/outboundTopicAliasManager.d.ts +52 -0
  365. package/dist/utils/outboundTopicAliasManager.d.ts.map +1 -0
  366. package/dist/utils/outboundTopicAliasManager.js +74 -0
  367. package/dist/utils/outboundTopicAliasManager.js.map +1 -0
  368. package/dist/utils/queue.d.ts.map +1 -1
  369. package/dist/utils/topicFilter.d.ts +32 -0
  370. package/dist/utils/topicFilter.d.ts.map +1 -0
  371. package/dist/utils/topicFilter.js +52 -0
  372. package/dist/utils/topicFilter.js.map +1 -0
  373. package/dist/utils/utils.d.ts +2 -0
  374. package/dist/utils/utils.d.ts.map +1 -1
  375. package/dist/utils/utils.js +2 -0
  376. package/dist/utils/utils.js.map +1 -1
  377. package/dist/utils/validators.d.ts +34 -0
  378. package/dist/utils/validators.d.ts.map +1 -0
  379. package/dist/utils/validators.js +61 -0
  380. package/dist/utils/validators.js.map +1 -0
  381. package/dist/web/webSocketStream.d.ts +29 -0
  382. package/dist/web/webSocketStream.d.ts.map +1 -0
  383. package/dist/web/webSocketStream.js +69 -0
  384. package/dist/web/webSocketStream.js.map +1 -0
  385. package/dist/web/wrapWebSocket.d.ts +12 -0
  386. package/dist/web/wrapWebSocket.d.ts.map +1 -0
  387. package/dist/web/wrapWebSocket.js +41 -0
  388. package/dist/web/wrapWebSocket.js.map +1 -0
  389. package/dist/web/wsClient.d.ts +7 -0
  390. package/dist/web/wsClient.d.ts.map +1 -0
  391. package/dist/web/wsClient.js +22 -0
  392. package/dist/web/wsClient.js.map +1 -0
  393. package/dist/web/wsClient.test.d.ts +2 -0
  394. package/dist/web/wsClient.test.d.ts.map +1 -0
  395. package/dist/web/wsClient.test.js +20 -0
  396. package/dist/web/wsClient.test.js.map +1 -0
  397. package/examples/authHandler.test.ts +164 -0
  398. package/examples/mqtt.test.ts +89 -0
  399. package/examples/mqtts.test.ts +100 -0
  400. package/examples/webSocket.test.ts +94 -0
  401. package/mqttConn/mqttConn.test.ts +9 -9
  402. package/mqttConn/mqttConn.ts +76 -44
  403. package/mqttPacket/Properties.ts +6 -3
  404. package/mqttPacket/ReasonCode.ts +2 -1
  405. package/mqttPacket/auth.test.ts +1 -1
  406. package/mqttPacket/auth.ts +41 -48
  407. package/mqttPacket/codec.ts +146 -0
  408. package/mqttPacket/connack.ts +57 -68
  409. package/mqttPacket/connect.test.ts +2 -2
  410. package/mqttPacket/connect.ts +175 -182
  411. package/mqttPacket/decoder.test.ts +0 -39
  412. package/mqttPacket/decoder.ts +8 -35
  413. package/mqttPacket/disconnect.ts +57 -68
  414. package/mqttPacket/encoder.ts +5 -40
  415. package/mqttPacket/mod.ts +48 -200
  416. package/mqttPacket/pingreq.ts +21 -27
  417. package/mqttPacket/pingres.ts +21 -27
  418. package/mqttPacket/protocolLevels.ts +12 -7
  419. package/mqttPacket/pubblishAcks.ts +56 -70
  420. package/mqttPacket/publish.ts +67 -74
  421. package/mqttPacket/suback.ts +48 -58
  422. package/mqttPacket/subscribe.ts +141 -117
  423. package/mqttPacket/types.ts +1 -9
  424. package/mqttPacket/unsuback.ts +46 -58
  425. package/mqttPacket/unsubscribe.ts +74 -63
  426. package/mqttPacket/validators.ts +5 -31
  427. package/node/socket-node-stream.test.ts +322 -0
  428. package/node/socket-node-stream.ts +174 -0
  429. package/node/tcpClient.test.ts +70 -0
  430. package/node/tcpClient.ts +13 -12
  431. package/node/tcpServer.test.ts +24 -20
  432. package/node/tcpServer.ts +6 -0
  433. package/node/tlsServer.test.ts +94 -0
  434. package/node/tlsServer.ts +81 -0
  435. package/node/wrapNodeSocket.ts +7 -30
  436. package/package.json +72 -44
  437. package/persistence/basicPersistence.ts +495 -0
  438. package/persistence/deps.ts +11 -1
  439. package/persistence/memory/memoryPersistence.ts +12 -153
  440. package/persistence/memory/memoryStorage.ts +232 -0
  441. package/persistence/mod.ts +4 -9
  442. package/persistence/persistence.test.ts +24 -0
  443. package/persistence/persistence.testing.ts +1324 -0
  444. package/persistence/persistence.ts +111 -67
  445. package/persistence/sqlite/sqliteDatabase.ts +294 -0
  446. package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
  447. package/persistence/sqlite/sqlitePersistence.ts +36 -0
  448. package/persistence/sqlite/sqliteStorage.ts +324 -0
  449. package/persistence/storage.ts +84 -0
  450. package/server/config.ts +65 -0
  451. package/server/context.ts +658 -74
  452. package/server/deps.ts +25 -5
  453. package/server/handlers/completeConnect.ts +93 -0
  454. package/server/handlers/duplicate.test.ts +196 -0
  455. package/server/handlers/handleAuth.test.ts +225 -0
  456. package/server/handlers/handleAuth.ts +88 -0
  457. package/server/handlers/handleConnect.test.ts +589 -0
  458. package/server/handlers/handleConnect.ts +201 -86
  459. package/server/handlers/handleConnect.version.test.ts +108 -0
  460. package/server/handlers/handleDisconnect.test.ts +56 -0
  461. package/server/handlers/handleDisconnect.ts +3 -3
  462. package/server/handlers/handlePacket.test.ts +24 -0
  463. package/server/handlers/handlePacket.ts +30 -8
  464. package/server/handlers/handlePingreq.test.ts +29 -0
  465. package/server/handlers/handlePuback.test.ts +28 -0
  466. package/server/handlers/handlePuback.ts +5 -8
  467. package/server/handlers/handlePubcomp.test.ts +28 -0
  468. package/server/handlers/handlePubcomp.ts +5 -4
  469. package/server/handlers/handlePublish.test.ts +471 -0
  470. package/server/handlers/handlePublish.ts +189 -35
  471. package/server/handlers/handlePubrec.test.ts +28 -0
  472. package/server/handlers/handlePubrec.ts +2 -3
  473. package/server/handlers/handlePubrel.test.ts +74 -0
  474. package/server/handlers/handlePubrel.ts +12 -2
  475. package/server/handlers/handleSubscribe.test.ts +971 -0
  476. package/server/handlers/handleSubscribe.ts +158 -39
  477. package/server/handlers/handleUnsubscribe.test.ts +79 -0
  478. package/server/handlers/handleUnsubscribe.ts +29 -5
  479. package/server/handlers/keepalive.test.ts +132 -0
  480. package/server/handlers/session.persistence.test.ts +194 -0
  481. package/server/handlers/will.delivery.test.ts +221 -0
  482. package/server/mod.ts +4 -3
  483. package/server/preconnect.test.ts +151 -0
  484. package/server/server.ts +115 -17
  485. package/socket/socket.test.ts +91 -0
  486. package/socket/socket.ts +81 -34
  487. package/timer/timer.test.ts +4 -7
  488. package/timer/timer.ts +36 -0
  489. package/tools/benchmarks/receiver.ts +51 -0
  490. package/tools/benchmarks/sender.ts +48 -0
  491. package/tools/benchmarks/utils.ts +31 -0
  492. package/tools/mqtt-compat/README.md +130 -0
  493. package/tools/mqtt-compat/broker.ts +52 -0
  494. package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
  495. package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
  496. package/trie/trie.test.ts +9 -1
  497. package/trie/trie.ts +70 -45
  498. package/utils/bufferedAsyncIterable.test.ts +92 -0
  499. package/utils/deferred.test.ts +36 -0
  500. package/utils/deferred.ts +0 -1
  501. package/utils/getOrInsertPolyFill.ts +12 -0
  502. package/utils/logger.test.ts +189 -0
  503. package/utils/logger.ts +62 -7
  504. package/utils/mod.ts +15 -1
  505. package/utils/outboundTopicAliasManager.ts +100 -0
  506. package/utils/queue.test.ts +61 -0
  507. package/utils/topicFilter.test.ts +63 -0
  508. package/utils/topicFilter.ts +61 -0
  509. package/utils/utils.ts +3 -0
  510. package/utils/validators.ts +67 -0
  511. package/web/webSocketStream.ts +97 -0
  512. package/web/wrapWebSocket.ts +52 -0
  513. package/web/wsClient.test.ts +26 -0
  514. package/web/wsClient.ts +25 -0
  515. package/benchmarks/receiver.ts +0 -35
  516. package/benchmarks/sender.ts +0 -32
  517. package/benchmarks/utils.ts +0 -9
  518. package/dev_utils/dummyConn.ts +0 -110
  519. package/dev_utils/socketPair.ts +0 -85
  520. package/dist/persistence/store.d.ts +0 -14
  521. package/dist/persistence/store.d.ts.map +0 -1
  522. package/dist/persistence/store.js +0 -2
  523. package/dist/persistence/store.js.map +0 -1
  524. package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
  525. package/dist/utils/BufferedAsyncIterable.js.map +0 -1
  526. package/examples/tcpServer.test.ts +0 -148
  527. package/persistence/memory/memoryPersistence.test.ts +0 -156
  528. package/persistence/store.ts +0 -16
  529. package/server/test/handleConnect.test.ts +0 -122
  530. package/server/test/test-handlers.ts +0 -53
  531. /package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +0 -0
@@ -0,0 +1,188 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handlePublish } from "./handlePublish.ts";
4
+ import { PacketType } from "../deps.ts";
5
+ import type { PublishPacket } from "../deps.ts";
6
+
7
+ function createMockContext() {
8
+ const sentPackets: unknown[] = [];
9
+ const receivedPublishes: PublishPacket[] = [];
10
+ return {
11
+ protocolLevel: 4 as const,
12
+ store: {
13
+ pendingOutgoing: new Map(),
14
+ pendingIncoming: new Map<number, PublishPacket>(),
15
+ pendingAckOutgoing: new Map(),
16
+ },
17
+ send: (packet: unknown) => {
18
+ sentPackets.push(packet);
19
+ },
20
+ receivePublish: (packet: PublishPacket) => {
21
+ receivedPublishes.push(packet);
22
+ },
23
+ sentPackets,
24
+ receivedPublishes,
25
+ };
26
+ }
27
+
28
+ test("handlePublish QoS 0 delivers message without acknowledgment", async () => {
29
+ const ctx = createMockContext();
30
+ const packet = {
31
+ type: PacketType.publish,
32
+ protocolLevel: 4 as const,
33
+ topic: "test/topic",
34
+ payload: new Uint8Array([1, 2, 3]),
35
+ qos: 0 as const,
36
+ retain: false,
37
+ dup: false,
38
+ } as PublishPacket;
39
+
40
+ await handlePublish(ctx as never, packet);
41
+
42
+ assert.deepStrictEqual(
43
+ ctx.receivedPublishes.length,
44
+ 1,
45
+ "Should receive publish",
46
+ );
47
+ assert.deepStrictEqual(
48
+ ctx.sentPackets.length,
49
+ 0,
50
+ "QoS 0 should not send acknowledgment",
51
+ );
52
+ });
53
+
54
+ test("handlePublish QoS 1 delivers message and sends PUBACK", async () => {
55
+ const ctx = createMockContext();
56
+ const packet = {
57
+ type: PacketType.publish,
58
+ protocolLevel: 4 as const,
59
+ topic: "test/topic",
60
+ payload: new Uint8Array([1, 2, 3]),
61
+ qos: 1 as const,
62
+ retain: false,
63
+ dup: false,
64
+ id: 1,
65
+ } as PublishPacket;
66
+
67
+ await handlePublish(ctx as never, packet);
68
+
69
+ assert.deepStrictEqual(
70
+ ctx.receivedPublishes.length,
71
+ 1,
72
+ "Should receive publish",
73
+ );
74
+ assert.deepStrictEqual(
75
+ ctx.sentPackets.length,
76
+ 1,
77
+ "Should send PUBACK",
78
+ );
79
+ assert.deepStrictEqual(
80
+ (ctx.sentPackets[0] as { type: number }).type,
81
+ PacketType.puback,
82
+ "Should send PUBACK packet",
83
+ );
84
+ assert.deepStrictEqual(
85
+ (ctx.sentPackets[0] as { id: number }).id,
86
+ 1,
87
+ "PUBACK should have same packet ID",
88
+ );
89
+ });
90
+
91
+ test("handlePublish QoS 2 stores message and sends PUBREC", async () => {
92
+ const ctx = createMockContext();
93
+ const packet = {
94
+ type: PacketType.publish,
95
+ protocolLevel: 4 as const,
96
+ topic: "test/topic",
97
+ payload: new Uint8Array([1, 2, 3]),
98
+ qos: 2 as const,
99
+ retain: false,
100
+ dup: false,
101
+ id: 2,
102
+ } as PublishPacket;
103
+
104
+ await handlePublish(ctx as never, packet);
105
+
106
+ // QoS 2: should NOT deliver message yet (waits for PUBREL)
107
+ assert.deepStrictEqual(
108
+ ctx.receivedPublishes.length,
109
+ 0,
110
+ "QoS 2 should not deliver message until PUBREL",
111
+ );
112
+
113
+ // Should store the packet
114
+ assert.deepStrictEqual(
115
+ ctx.store.pendingIncoming.has(2),
116
+ true,
117
+ "Should store incoming packet",
118
+ );
119
+
120
+ // Should send PUBREC
121
+ assert.deepStrictEqual(
122
+ ctx.sentPackets.length,
123
+ 1,
124
+ "Should send PUBREC",
125
+ );
126
+ assert.deepStrictEqual(
127
+ (ctx.sentPackets[0] as { type: number }).type,
128
+ PacketType.pubrec,
129
+ "Should send PUBREC packet",
130
+ );
131
+ assert.deepStrictEqual(
132
+ (ctx.sentPackets[0] as { id: number }).id,
133
+ 2,
134
+ "PUBREC should have same packet ID",
135
+ );
136
+ });
137
+
138
+ test("handlePublish without packet ID for QoS 1 does nothing", async () => {
139
+ const ctx = createMockContext();
140
+ const packet = {
141
+ type: PacketType.publish,
142
+ protocolLevel: 4 as const,
143
+ topic: "test/topic",
144
+ payload: new Uint8Array([1, 2, 3]),
145
+ qos: 1 as const,
146
+ retain: false,
147
+ dup: false,
148
+ // No id
149
+ } as PublishPacket;
150
+
151
+ await handlePublish(ctx as never, packet);
152
+
153
+ // Without packet ID, QoS 1/2 handling is skipped
154
+ assert.deepStrictEqual(
155
+ ctx.receivedPublishes.length,
156
+ 0,
157
+ "Should not receive without packet ID",
158
+ );
159
+ assert.deepStrictEqual(
160
+ ctx.sentPackets.length,
161
+ 0,
162
+ "Should not send without packet ID",
163
+ );
164
+ });
165
+
166
+ test("handlePublish QoS 2 without store does nothing", async () => {
167
+ const ctx = createMockContext();
168
+ (ctx as unknown as { store: null }).store = null as never;
169
+ const packet = {
170
+ type: PacketType.publish,
171
+ protocolLevel: 4 as const,
172
+ topic: "test/topic",
173
+ payload: new Uint8Array([1, 2, 3]),
174
+ qos: 2 as const,
175
+ retain: false,
176
+ dup: false,
177
+ id: 3,
178
+ } as PublishPacket;
179
+
180
+ // Should not throw, just silently skip
181
+ await handlePublish(ctx as never, packet);
182
+
183
+ assert.deepStrictEqual(
184
+ ctx.sentPackets.length,
185
+ 0,
186
+ "Should not send without store",
187
+ );
188
+ });
@@ -0,0 +1,119 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handlePubrec } from "./handlePubrec.ts";
4
+ import { PacketType, ReasonCode, ReasonCodeByNumber } from "../deps.ts";
5
+ import type { PubrecPacket } from "../deps.ts";
6
+
7
+ function createMockContext() {
8
+ const sentPackets: unknown[] = [];
9
+ return {
10
+ protocolLevel: 4 as const,
11
+ store: {
12
+ pendingOutgoing: new Map<number, unknown>(),
13
+ pendingIncoming: new Map(),
14
+ pendingAckOutgoing: new Map<number, unknown>(),
15
+ },
16
+ send: (packet: unknown) => {
17
+ sentPackets.push(packet);
18
+ },
19
+ sentPackets,
20
+ };
21
+ }
22
+
23
+ test("handlePubrec sends PUBREL for pending outgoing QoS 2", async () => {
24
+ const ctx = createMockContext();
25
+ ctx.store.pendingOutgoing.set(1, { type: PacketType.publish, id: 1 });
26
+
27
+ const packet = {
28
+ type: PacketType.pubrec,
29
+ protocolLevel: 4 as const,
30
+ id: 1,
31
+ } as PubrecPacket;
32
+
33
+ await handlePubrec(ctx as never, packet);
34
+
35
+ // Should send PUBREL
36
+ assert.deepStrictEqual(ctx.sentPackets.length, 1, "Should send PUBREL");
37
+ assert.deepStrictEqual(
38
+ (ctx.sentPackets[0] as { type: number }).type,
39
+ PacketType.pubrel,
40
+ "Should send PUBREL packet",
41
+ );
42
+ assert.deepStrictEqual(
43
+ (ctx.sentPackets[0] as { id: number }).id,
44
+ 1,
45
+ "PUBREL should have same packet ID",
46
+ );
47
+
48
+ // Should move from pendingOutgoing to pendingAckOutgoing
49
+ assert.deepStrictEqual(
50
+ ctx.store.pendingOutgoing.has(1),
51
+ false,
52
+ "Should remove from pendingOutgoing",
53
+ );
54
+ assert.deepStrictEqual(
55
+ ctx.store.pendingAckOutgoing.has(1),
56
+ true,
57
+ "Should add to pendingAckOutgoing",
58
+ );
59
+ });
60
+
61
+ test("handlePubrec ignores unknown packet ID", async () => {
62
+ const ctx = createMockContext();
63
+
64
+ const packet = {
65
+ type: PacketType.pubrec,
66
+ protocolLevel: 4 as const,
67
+ id: 999,
68
+ } as PubrecPacket;
69
+
70
+ await handlePubrec(ctx as never, packet);
71
+
72
+ assert.deepStrictEqual(
73
+ ctx.sentPackets.length,
74
+ 0,
75
+ "Should not send PUBREL for unknown ID",
76
+ );
77
+ assert.deepStrictEqual(
78
+ ctx.store.pendingAckOutgoing.has(999),
79
+ false,
80
+ "Should not add to pendingAckOutgoing",
81
+ );
82
+ });
83
+
84
+ test("handlePubrec stores PUBREL packet for retransmission", async () => {
85
+ const ctx = createMockContext();
86
+ ctx.store.pendingOutgoing.set(5, { type: PacketType.publish, id: 5 });
87
+
88
+ const packet = {
89
+ type: PacketType.pubrec,
90
+ protocolLevel: 4 as const,
91
+ id: 5,
92
+ } as PubrecPacket;
93
+
94
+ await handlePubrec(ctx as never, packet);
95
+
96
+ const storedPubrel = ctx.store.pendingAckOutgoing.get(5);
97
+ assert.ok(storedPubrel, "Should store PUBREL");
98
+ assert.deepStrictEqual(
99
+ (storedPubrel as { type: number }).type,
100
+ PacketType.pubrel,
101
+ "Stored packet should be PUBREL",
102
+ );
103
+ });
104
+
105
+ test("handlePuback processes V5 publish rejection", () => {
106
+ const ctx = createMockContext();
107
+ const reasonCode = ReasonCode.notAuthorized;
108
+ ctx.store.pendingOutgoing.set(2, {
109
+ type: PacketType.publish,
110
+ topic: "Test Pubrec",
111
+ });
112
+ assert.rejects(() =>
113
+ handlePubrec(ctx as never, {
114
+ type: PacketType.pubrec,
115
+ protocolLevel: 5,
116
+ id: 2,
117
+ reasonCode,
118
+ } as PubrecPacket), Error(ReasonCodeByNumber[reasonCode]));
119
+ });
@@ -1,5 +1,5 @@
1
1
  import type { Context } from "../context.ts";
2
- import { PacketType } from "../deps.ts";
2
+ import { PacketType, ReasonCodeByNumber } from "../deps.ts";
3
3
  import type { PubrecPacket, PubrelPacket } from "../deps.ts";
4
4
 
5
5
  /**
@@ -26,6 +26,10 @@ export async function handlePubrec(
26
26
  id,
27
27
  };
28
28
  if (ctx.store.pendingOutgoing.has(id)) {
29
+ if (packet.protocolLevel === 5 && ((packet.reasonCode ?? 0) !== 0)) {
30
+ ctx.store.pendingOutgoing.delete(id);
31
+ throw new Error(ReasonCodeByNumber[packet.reasonCode!]);
32
+ }
29
33
  ctx.store.pendingAckOutgoing.set(id, ack);
30
34
  ctx.store.pendingOutgoing.delete(id);
31
35
  await ctx.send(ack);
@@ -0,0 +1,136 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handlePubrel } from "./handlePubrel.ts";
4
+ import { PacketType } from "../deps.ts";
5
+ import type { PublishPacket, PubrelPacket } from "../deps.ts";
6
+
7
+ function createMockContext() {
8
+ const sentPackets: unknown[] = [];
9
+ const receivedPublishes: PublishPacket[] = [];
10
+ return {
11
+ protocolLevel: 4 as const,
12
+ store: {
13
+ pendingOutgoing: new Map(),
14
+ pendingIncoming: new Map<number, PublishPacket>(),
15
+ pendingAckOutgoing: new Map(),
16
+ },
17
+ send: (packet: unknown) => {
18
+ sentPackets.push(packet);
19
+ },
20
+ receivePublish: (packet: PublishPacket) => {
21
+ receivedPublishes.push(packet);
22
+ },
23
+ sentPackets,
24
+ receivedPublishes,
25
+ };
26
+ }
27
+
28
+ test("handlePubrel delivers stored message and sends PUBCOMP", async () => {
29
+ const ctx = createMockContext();
30
+ const storedPublish = {
31
+ type: PacketType.publish,
32
+ protocolLevel: 4 as const,
33
+ topic: "test/topic",
34
+ payload: new Uint8Array([1, 2, 3]),
35
+ qos: 2 as const,
36
+ retain: false,
37
+ dup: false,
38
+ id: 1,
39
+ } as PublishPacket;
40
+ ctx.store.pendingIncoming.set(1, storedPublish);
41
+
42
+ const packet = {
43
+ type: PacketType.pubrel,
44
+ protocolLevel: 4 as const,
45
+ id: 1,
46
+ } as PubrelPacket;
47
+
48
+ await handlePubrel(ctx as never, packet);
49
+
50
+ // Should deliver the message
51
+ assert.deepStrictEqual(
52
+ ctx.receivedPublishes.length,
53
+ 1,
54
+ "Should deliver stored message",
55
+ );
56
+ assert.deepStrictEqual(
57
+ ctx.receivedPublishes[0].topic,
58
+ "test/topic",
59
+ "Should deliver correct message",
60
+ );
61
+
62
+ // Should send PUBCOMP
63
+ assert.deepStrictEqual(ctx.sentPackets.length, 1, "Should send PUBCOMP");
64
+ assert.deepStrictEqual(
65
+ (ctx.sentPackets[0] as { type: number }).type,
66
+ PacketType.pubcomp,
67
+ "Should send PUBCOMP packet",
68
+ );
69
+ assert.deepStrictEqual(
70
+ (ctx.sentPackets[0] as { id: number }).id,
71
+ 1,
72
+ "PUBCOMP should have same packet ID",
73
+ );
74
+
75
+ // Should remove from pending incoming
76
+ assert.deepStrictEqual(
77
+ ctx.store.pendingIncoming.has(1),
78
+ false,
79
+ "Should remove from pendingIncoming",
80
+ );
81
+ });
82
+
83
+ test("handlePubrel ignores unknown packet ID", async () => {
84
+ const ctx = createMockContext();
85
+
86
+ const packet = {
87
+ type: PacketType.pubrel,
88
+ protocolLevel: 4 as const,
89
+ id: 999,
90
+ } as PubrelPacket;
91
+
92
+ await handlePubrel(ctx as never, packet);
93
+
94
+ assert.deepStrictEqual(
95
+ ctx.receivedPublishes.length,
96
+ 0,
97
+ "Should not deliver for unknown ID",
98
+ );
99
+ assert.deepStrictEqual(
100
+ ctx.sentPackets.length,
101
+ 0,
102
+ "Should not send PUBCOMP for unknown ID",
103
+ );
104
+ });
105
+
106
+ test("handlePubrel completes QoS 2 flow correctly", async () => {
107
+ const ctx = createMockContext();
108
+
109
+ // Simulate full QoS 2 flow - message already stored from PUBLISH
110
+ const storedPublish = {
111
+ type: PacketType.publish,
112
+ protocolLevel: 4 as const,
113
+ topic: "sensors/temp",
114
+ payload: new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]), // "Hello"
115
+ qos: 2 as const,
116
+ retain: false,
117
+ dup: false,
118
+ id: 42,
119
+ } as PublishPacket;
120
+ ctx.store.pendingIncoming.set(42, storedPublish);
121
+
122
+ await handlePubrel(ctx as never, {
123
+ type: PacketType.pubrel,
124
+ protocolLevel: 4,
125
+ id: 42,
126
+ } as PubrelPacket);
127
+
128
+ // Verify complete flow
129
+ assert.deepStrictEqual(ctx.receivedPublishes.length, 1);
130
+ assert.deepStrictEqual(ctx.receivedPublishes[0], storedPublish);
131
+ assert.deepStrictEqual(
132
+ (ctx.sentPackets[0] as { type: number }).type,
133
+ PacketType.pubcomp,
134
+ );
135
+ assert.deepStrictEqual(ctx.store.pendingIncoming.size, 0);
136
+ });
@@ -0,0 +1,122 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handleSuback } from "./handleSuback.ts";
4
+ import { PacketType } from "../deps.ts";
5
+ import type { SubackPacket } from "../deps.ts";
6
+
7
+ function createMockContext() {
8
+ const receivedSubacks: Array<{ id: number; returnCodes: number[] }> = [];
9
+ return {
10
+ protocolLevel: 4 as const,
11
+ store: {
12
+ pendingOutgoing: new Map<number, unknown>(),
13
+ pendingIncoming: new Map(),
14
+ pendingAckOutgoing: new Map(),
15
+ },
16
+ receiveSuback: (id: number, returnCodes: number[]) => {
17
+ receivedSubacks.push({ id, returnCodes });
18
+ return true;
19
+ },
20
+ receivedSubacks,
21
+ };
22
+ }
23
+
24
+ test("handleSuback removes from pending and notifies context", () => {
25
+ const ctx = createMockContext();
26
+ ctx.store.pendingOutgoing.set(1, { type: PacketType.subscribe, id: 1 });
27
+
28
+ const packet = {
29
+ type: PacketType.suback,
30
+ protocolLevel: 4 as const,
31
+ id: 1,
32
+ returnCodes: [0],
33
+ } as SubackPacket;
34
+
35
+ handleSuback(ctx as never, packet);
36
+
37
+ assert.deepStrictEqual(
38
+ ctx.store.pendingOutgoing.has(1),
39
+ false,
40
+ "Should remove from pending",
41
+ );
42
+ assert.deepStrictEqual(
43
+ ctx.receivedSubacks.length,
44
+ 1,
45
+ "Should notify context",
46
+ );
47
+ assert.deepStrictEqual(
48
+ ctx.receivedSubacks[0].id,
49
+ 1,
50
+ "Should have correct ID",
51
+ );
52
+ assert.deepStrictEqual(
53
+ ctx.receivedSubacks[0].returnCodes,
54
+ [0],
55
+ "Should pass return codes",
56
+ );
57
+ });
58
+
59
+ test("handleSuback handles multiple return codes", () => {
60
+ const ctx = createMockContext();
61
+ ctx.store.pendingOutgoing.set(2, { type: PacketType.subscribe, id: 2 });
62
+
63
+ const packet = {
64
+ type: PacketType.suback,
65
+ protocolLevel: 4 as const,
66
+ id: 2,
67
+ returnCodes: [0, 1, 2],
68
+ } as SubackPacket;
69
+
70
+ handleSuback(ctx as never, packet);
71
+
72
+ assert.deepStrictEqual(
73
+ ctx.receivedSubacks[0].returnCodes,
74
+ [0, 1, 2],
75
+ );
76
+ });
77
+
78
+ test("handleSuback handles subscription failure code", () => {
79
+ const ctx = createMockContext();
80
+ ctx.store.pendingOutgoing.set(3, { type: PacketType.subscribe, id: 3 });
81
+
82
+ const SUBSCRIPTION_FAILURE = 0x80;
83
+ const packet = {
84
+ type: PacketType.suback,
85
+ protocolLevel: 4 as const,
86
+ id: 3,
87
+ returnCodes: [0, SUBSCRIPTION_FAILURE],
88
+ } as SubackPacket;
89
+
90
+ handleSuback(ctx as never, packet);
91
+
92
+ assert.deepStrictEqual(
93
+ ctx.receivedSubacks[0].returnCodes,
94
+ [0, SUBSCRIPTION_FAILURE],
95
+ );
96
+ });
97
+
98
+ test("handleSuback handles notification for MQTT v5", () => {
99
+ const ctx = createMockContext();
100
+ ctx.store.pendingOutgoing.set(4, { type: PacketType.subscribe, id: 4 });
101
+
102
+ const packet = {
103
+ type: PacketType.suback,
104
+ protocolLevel: 5 as const,
105
+ id: 4,
106
+ reasonCodes: [0],
107
+ } as SubackPacket;
108
+
109
+ handleSuback(ctx as never, packet);
110
+
111
+ assert.deepStrictEqual(
112
+ ctx.store.pendingOutgoing.has(4),
113
+ false,
114
+ "Should remove from pending",
115
+ );
116
+
117
+ assert.deepStrictEqual(
118
+ ctx.receivedSubacks.length,
119
+ 1,
120
+ "Should notify for v5",
121
+ );
122
+ });
@@ -9,11 +9,14 @@ import type { SubackPacket } from "../deps.ts";
9
9
  * - Processes SUBACK packets sent by server to confirm SUBSCRIBE requests
10
10
  * - Removes the packet ID from pending outgoing messages
11
11
  * - Notifies the client about granted QoS levels for each subscription
12
+ * - in V5 the reason codes could carry various errors
12
13
  */
13
14
  export function handleSuback(ctx: Context, packet: SubackPacket): void {
14
15
  const id = packet.id;
15
16
  ctx.store.pendingOutgoing.delete(id);
16
17
  if (packet.protocolLevel !== 5) {
17
18
  ctx.receiveSuback(id, packet.returnCodes);
19
+ return;
18
20
  }
21
+ ctx.receiveSuback(id, packet.reasonCodes);
19
22
  }
@@ -0,0 +1,101 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handleUnsuback } from "./handleUnsuback.ts";
4
+ import { PacketType } from "../deps.ts";
5
+ import type { UnsubackPacket } from "../deps.ts";
6
+
7
+ function createMockContext() {
8
+ const receivedIds: number[] = [];
9
+ return {
10
+ protocolLevel: 4 as const,
11
+ store: {
12
+ pendingOutgoing: new Map<number, unknown>(),
13
+ pendingIncoming: new Map(),
14
+ pendingAckOutgoing: new Map(),
15
+ },
16
+ receiveUnsuback: (id: number) => {
17
+ receivedIds.push(id);
18
+ return true;
19
+ },
20
+ receivedIds,
21
+ };
22
+ }
23
+
24
+ test("handleUnsuback removes from pending and notifies context", () => {
25
+ const ctx = createMockContext();
26
+ ctx.store.pendingOutgoing.set(1, { type: PacketType.unsubscribe, id: 1 });
27
+
28
+ const packet = {
29
+ type: PacketType.unsuback,
30
+ protocolLevel: 4 as const,
31
+ id: 1,
32
+ } as UnsubackPacket;
33
+
34
+ handleUnsuback(ctx as never, packet);
35
+
36
+ assert.deepStrictEqual(
37
+ ctx.store.pendingOutgoing.has(1),
38
+ false,
39
+ "Should remove from pending",
40
+ );
41
+ assert.deepStrictEqual(
42
+ ctx.receivedIds,
43
+ [1],
44
+ "Should notify context of unsuback",
45
+ );
46
+ });
47
+
48
+ test("handleUnsuback handles non-existent packet ID gracefully", () => {
49
+ const ctx = createMockContext();
50
+
51
+ const packet = {
52
+ type: PacketType.unsuback,
53
+ protocolLevel: 4 as const,
54
+ id: 999,
55
+ } as UnsubackPacket;
56
+
57
+ // Should not throw
58
+ handleUnsuback(ctx as never, packet);
59
+
60
+ assert.deepStrictEqual(
61
+ ctx.receivedIds,
62
+ [999],
63
+ "Should still notify context",
64
+ );
65
+ });
66
+
67
+ test("handleUnsuback processes multiple UNSUBACKs correctly", () => {
68
+ const ctx = createMockContext();
69
+ ctx.store.pendingOutgoing.set(1, { type: PacketType.unsubscribe, id: 1 });
70
+ ctx.store.pendingOutgoing.set(2, { type: PacketType.unsubscribe, id: 2 });
71
+ ctx.store.pendingOutgoing.set(3, { type: PacketType.unsubscribe, id: 3 });
72
+
73
+ handleUnsuback(ctx as never, {
74
+ type: PacketType.unsuback,
75
+ protocolLevel: 4,
76
+ id: 2,
77
+ } as UnsubackPacket);
78
+
79
+ assert.deepStrictEqual(ctx.store.pendingOutgoing.has(1), true);
80
+ assert.deepStrictEqual(ctx.store.pendingOutgoing.has(2), false);
81
+ assert.deepStrictEqual(ctx.store.pendingOutgoing.has(3), true);
82
+ assert.deepStrictEqual(ctx.receivedIds, [2]);
83
+ });
84
+
85
+ test("handleUnsuback works with MQTT v5", () => {
86
+ const ctx = createMockContext();
87
+ ctx.store.pendingOutgoing.set(5, { type: PacketType.unsubscribe, id: 5 });
88
+
89
+ const packet = {
90
+ type: PacketType.unsuback,
91
+ protocolLevel: 5 as const,
92
+ id: 5,
93
+ reasonCodes: [0],
94
+ properties: {},
95
+ } as UnsubackPacket;
96
+
97
+ handleUnsuback(ctx as never, packet);
98
+
99
+ assert.deepStrictEqual(ctx.store.pendingOutgoing.has(5), false);
100
+ assert.deepStrictEqual(ctx.receivedIds, [5]);
101
+ });
package/client/mod.ts CHANGED
@@ -8,7 +8,7 @@ export {
8
8
  DEFAULT_PROTOCOLLEVEL,
9
9
  DEFAULT_URL,
10
10
  } from "./client.ts";
11
- export { MQTTLevel } from "./deps.ts";
11
+ export { MQTTLevel, ReasonCode } from "./deps.ts";
12
12
  export type { ProtocolLevel, QoS } from "./deps.ts";
13
13
  export type {
14
14
  ConnectParameters,