@seriousme/opifex 1.11.2 → 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 (538) hide show
  1. package/LICENSE.txt +1 -1
  2. package/README.md +102 -43
  3. package/bin/conformanceServer.ts +45 -13
  4. package/bin/demoServer.ts +38 -13
  5. package/bin/mqtt.ts +52 -30
  6. package/client/ConnectionState.ts +2 -0
  7. package/client/client.ts +57 -47
  8. package/client/context.ts +75 -21
  9. package/client/deps.ts +5 -0
  10. package/client/handlers/handleAuth.test.ts +193 -0
  11. package/client/handlers/handleAuth.ts +89 -0
  12. package/client/handlers/handleConnack.test.ts +173 -0
  13. package/client/handlers/handleConnack.ts +16 -6
  14. package/client/handlers/handleDisconnect.test.ts +22 -0
  15. package/client/handlers/handleDisconnect.ts +17 -0
  16. package/client/handlers/handlePacket.test.ts +242 -0
  17. package/client/handlers/handlePacket.ts +19 -5
  18. package/client/handlers/handlePuback.test.ts +99 -0
  19. package/client/handlers/handlePuback.ts +6 -0
  20. package/client/handlers/handlePubcomp.test.ts +112 -0
  21. package/client/handlers/handlePubcomp.ts +5 -0
  22. package/client/handlers/handlePublish.test.ts +188 -0
  23. package/client/handlers/handlePubrec.test.ts +119 -0
  24. package/client/handlers/handlePubrec.ts +5 -1
  25. package/client/handlers/handlePubrel.test.ts +136 -0
  26. package/client/handlers/handleSuback.test.ts +122 -0
  27. package/client/handlers/handleSuback.ts +3 -0
  28. package/client/handlers/handleUnsuback.test.ts +101 -0
  29. package/client/mod.ts +2 -2
  30. package/client/store/memoryStore.ts +2 -2
  31. package/client/store/store.ts +3 -1
  32. package/deno/README.md +1 -2
  33. package/deno/tcpClient.test.ts +75 -0
  34. package/deno/tcpClient.ts +16 -11
  35. package/deno/tcpServer.test.ts +22 -21
  36. package/deno/tcpServer.ts +5 -0
  37. package/deno/tlsServer.test.ts +97 -0
  38. package/deno/tlsServer.ts +42 -0
  39. package/deno/wsServer.test.ts +93 -0
  40. package/deno/wsServer.ts +73 -0
  41. package/dev_utils/generateCert.ts +95 -0
  42. package/dev_utils/mockConn.ts +36 -0
  43. package/dev_utils/mockServer.ts +28 -0
  44. package/dev_utils/mod.ts +30 -2
  45. package/dev_utils/packetHelpers.ts +404 -0
  46. package/dev_utils/test-handlers.ts +98 -0
  47. package/dev_utils/timers.ts +14 -0
  48. package/dev_utils/webStreamPair.test.ts +171 -0
  49. package/dev_utils/webStreamPair.ts +143 -0
  50. package/dist/bin/conformanceServer.js +17 -12
  51. package/dist/bin/conformanceServer.js.map +1 -1
  52. package/dist/bin/demoServer.js +16 -12
  53. package/dist/bin/demoServer.js.map +1 -1
  54. package/dist/bin/mqtt.js +19 -16
  55. package/dist/bin/mqtt.js.map +1 -1
  56. package/dist/client/ConnectionState.d.ts +2 -0
  57. package/dist/client/ConnectionState.d.ts.map +1 -1
  58. package/dist/client/ConnectionState.js +2 -0
  59. package/dist/client/ConnectionState.js.map +1 -1
  60. package/dist/client/client.d.ts +19 -22
  61. package/dist/client/client.d.ts.map +1 -1
  62. package/dist/client/client.js +34 -20
  63. package/dist/client/client.js.map +1 -1
  64. package/dist/client/context.d.ts +11 -3
  65. package/dist/client/context.d.ts.map +1 -1
  66. package/dist/client/context.js +44 -12
  67. package/dist/client/context.js.map +1 -1
  68. package/dist/client/deps.d.ts +3 -2
  69. package/dist/client/deps.d.ts.map +1 -1
  70. package/dist/client/deps.js +1 -1
  71. package/dist/client/deps.js.map +1 -1
  72. package/dist/client/handlers/handleAuth.d.ts +9 -0
  73. package/dist/client/handlers/handleAuth.d.ts.map +1 -0
  74. package/dist/client/handlers/handleAuth.js +66 -0
  75. package/dist/client/handlers/handleAuth.js.map +1 -0
  76. package/dist/client/handlers/handleConnack.d.ts +2 -2
  77. package/dist/client/handlers/handleConnack.d.ts.map +1 -1
  78. package/dist/client/handlers/handleConnack.js +16 -6
  79. package/dist/client/handlers/handleConnack.js.map +1 -1
  80. package/dist/client/handlers/handleDisconnect.d.ts +11 -0
  81. package/dist/client/handlers/handleDisconnect.d.ts.map +1 -0
  82. package/dist/client/handlers/handleDisconnect.js +15 -0
  83. package/dist/client/handlers/handleDisconnect.js.map +1 -0
  84. package/dist/client/handlers/handlePacket.d.ts.map +1 -1
  85. package/dist/client/handlers/handlePacket.js +14 -3
  86. package/dist/client/handlers/handlePacket.js.map +1 -1
  87. package/dist/client/handlers/handlePuback.d.ts.map +1 -1
  88. package/dist/client/handlers/handlePuback.js +5 -0
  89. package/dist/client/handlers/handlePuback.js.map +1 -1
  90. package/dist/client/handlers/handlePubcomp.d.ts.map +1 -1
  91. package/dist/client/handlers/handlePubcomp.js +5 -0
  92. package/dist/client/handlers/handlePubcomp.js.map +1 -1
  93. package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
  94. package/dist/client/handlers/handlePubrec.js +5 -1
  95. package/dist/client/handlers/handlePubrec.js.map +1 -1
  96. package/dist/client/handlers/handleSuback.d.ts +1 -0
  97. package/dist/client/handlers/handleSuback.d.ts.map +1 -1
  98. package/dist/client/handlers/handleSuback.js +3 -0
  99. package/dist/client/handlers/handleSuback.js.map +1 -1
  100. package/dist/client/mod.d.ts +2 -2
  101. package/dist/client/mod.d.ts.map +1 -1
  102. package/dist/client/mod.js +1 -1
  103. package/dist/client/mod.js.map +1 -1
  104. package/dist/client/store/memoryStore.d.ts.map +1 -1
  105. package/dist/client/store/memoryStore.js +2 -2
  106. package/dist/client/store/memoryStore.js.map +1 -1
  107. package/dist/client/store/store.d.ts +2 -1
  108. package/dist/client/store/store.d.ts.map +1 -1
  109. package/dist/client/store/store.js +1 -1
  110. package/dist/client/store/store.js.map +1 -1
  111. package/dist/dev_utils/generateCert.d.ts +11 -0
  112. package/dist/dev_utils/generateCert.d.ts.map +1 -0
  113. package/dist/dev_utils/generateCert.js +76 -0
  114. package/dist/dev_utils/generateCert.js.map +1 -0
  115. package/dist/examples/authHandler.test.d.ts +2 -0
  116. package/dist/examples/authHandler.test.d.ts.map +1 -0
  117. package/dist/examples/authHandler.test.js +123 -0
  118. package/dist/examples/authHandler.test.js.map +1 -0
  119. package/dist/examples/mqtt.test.d.ts +2 -0
  120. package/dist/examples/mqtt.test.d.ts.map +1 -0
  121. package/dist/examples/mqtt.test.js +70 -0
  122. package/dist/examples/mqtt.test.js.map +1 -0
  123. package/dist/examples/mqtts.test.d.ts +2 -0
  124. package/dist/examples/mqtts.test.d.ts.map +1 -0
  125. package/dist/examples/mqtts.test.js +81 -0
  126. package/dist/examples/mqtts.test.js.map +1 -0
  127. package/dist/mqttConn/mqttConn.d.ts +25 -16
  128. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  129. package/dist/mqttConn/mqttConn.js +69 -40
  130. package/dist/mqttConn/mqttConn.js.map +1 -1
  131. package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
  132. package/dist/mqttPacket/BitMask.d.ts +12 -11
  133. package/dist/mqttPacket/BitMask.d.ts.map +1 -1
  134. package/dist/mqttPacket/BitMask.js +10 -18
  135. package/dist/mqttPacket/BitMask.js.map +1 -1
  136. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  137. package/dist/mqttPacket/Properties.d.ts +2 -2
  138. package/dist/mqttPacket/Properties.d.ts.map +1 -1
  139. package/dist/mqttPacket/Properties.js.map +1 -1
  140. package/dist/mqttPacket/ReasonCode.d.ts +1 -0
  141. package/dist/mqttPacket/ReasonCode.d.ts.map +1 -1
  142. package/dist/mqttPacket/ReasonCode.js +1 -0
  143. package/dist/mqttPacket/ReasonCode.js.map +1 -1
  144. package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
  145. package/dist/mqttPacket/auth.d.ts +3 -5
  146. package/dist/mqttPacket/auth.d.ts.map +1 -1
  147. package/dist/mqttPacket/auth.js +31 -30
  148. package/dist/mqttPacket/auth.js.map +1 -1
  149. package/dist/mqttPacket/codec.d.ts +48 -0
  150. package/dist/mqttPacket/codec.d.ts.map +1 -0
  151. package/dist/mqttPacket/codec.js +93 -0
  152. package/dist/mqttPacket/codec.js.map +1 -0
  153. package/dist/mqttPacket/connack.d.ts +4 -5
  154. package/dist/mqttPacket/connack.d.ts.map +1 -1
  155. package/dist/mqttPacket/connack.js +43 -45
  156. package/dist/mqttPacket/connack.js.map +1 -1
  157. package/dist/mqttPacket/connect.d.ts +26 -27
  158. package/dist/mqttPacket/connect.d.ts.map +1 -1
  159. package/dist/mqttPacket/connect.js +156 -157
  160. package/dist/mqttPacket/connect.js.map +1 -1
  161. package/dist/mqttPacket/decoder.d.ts +1 -13
  162. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  163. package/dist/mqttPacket/decoder.js +7 -28
  164. package/dist/mqttPacket/decoder.js.map +1 -1
  165. package/dist/mqttPacket/disconnect.d.ts +4 -5
  166. package/dist/mqttPacket/disconnect.d.ts.map +1 -1
  167. package/dist/mqttPacket/disconnect.js +41 -43
  168. package/dist/mqttPacket/disconnect.js.map +1 -1
  169. package/dist/mqttPacket/encoder.d.ts +1 -15
  170. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  171. package/dist/mqttPacket/encoder.js +4 -27
  172. package/dist/mqttPacket/encoder.js.map +1 -1
  173. package/dist/mqttPacket/length.js +1 -1
  174. package/dist/mqttPacket/length.js.map +1 -1
  175. package/dist/mqttPacket/mod.d.ts +21 -103
  176. package/dist/mqttPacket/mod.d.ts.map +1 -1
  177. package/dist/mqttPacket/mod.js +5 -94
  178. package/dist/mqttPacket/mod.js.map +1 -1
  179. package/dist/mqttPacket/pingreq.d.ts +4 -5
  180. package/dist/mqttPacket/pingreq.d.ts.map +1 -1
  181. package/dist/mqttPacket/pingreq.js +11 -13
  182. package/dist/mqttPacket/pingreq.js.map +1 -1
  183. package/dist/mqttPacket/pingres.d.ts +4 -5
  184. package/dist/mqttPacket/pingres.d.ts.map +1 -1
  185. package/dist/mqttPacket/pingres.js +11 -13
  186. package/dist/mqttPacket/pingres.js.map +1 -1
  187. package/dist/mqttPacket/protocolLevels.d.ts +11 -6
  188. package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
  189. package/dist/mqttPacket/protocolLevels.js +5 -1
  190. package/dist/mqttPacket/protocolLevels.js.map +1 -1
  191. package/dist/mqttPacket/pubblishAcks.d.ts +9 -10
  192. package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
  193. package/dist/mqttPacket/pubblishAcks.js +43 -45
  194. package/dist/mqttPacket/pubblishAcks.js.map +1 -1
  195. package/dist/mqttPacket/publish.d.ts +14 -14
  196. package/dist/mqttPacket/publish.d.ts.map +1 -1
  197. package/dist/mqttPacket/publish.js +53 -55
  198. package/dist/mqttPacket/publish.js.map +1 -1
  199. package/dist/mqttPacket/suback.d.ts +4 -5
  200. package/dist/mqttPacket/suback.d.ts.map +1 -1
  201. package/dist/mqttPacket/suback.js +38 -40
  202. package/dist/mqttPacket/suback.js.map +1 -1
  203. package/dist/mqttPacket/subscribe.d.ts +36 -7
  204. package/dist/mqttPacket/subscribe.d.ts.map +1 -1
  205. package/dist/mqttPacket/subscribe.js +90 -89
  206. package/dist/mqttPacket/subscribe.js.map +1 -1
  207. package/dist/mqttPacket/types.d.ts +1 -8
  208. package/dist/mqttPacket/types.d.ts.map +1 -1
  209. package/dist/mqttPacket/unsuback.d.ts +4 -5
  210. package/dist/mqttPacket/unsuback.d.ts.map +1 -1
  211. package/dist/mqttPacket/unsuback.js +32 -34
  212. package/dist/mqttPacket/unsuback.js.map +1 -1
  213. package/dist/mqttPacket/unsubscribe.d.ts +23 -6
  214. package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
  215. package/dist/mqttPacket/unsubscribe.js +45 -44
  216. package/dist/mqttPacket/unsubscribe.js.map +1 -1
  217. package/dist/mqttPacket/validators.d.ts +4 -16
  218. package/dist/mqttPacket/validators.d.ts.map +1 -1
  219. package/dist/mqttPacket/validators.js +5 -26
  220. package/dist/mqttPacket/validators.js.map +1 -1
  221. package/dist/node/tcpClient.d.ts +1 -1
  222. package/dist/node/tcpClient.d.ts.map +1 -1
  223. package/dist/node/tcpClient.js +12 -7
  224. package/dist/node/tcpClient.js.map +1 -1
  225. package/dist/node/tcpServer.d.ts.map +1 -1
  226. package/dist/node/tcpServer.js +4 -0
  227. package/dist/node/tcpServer.js.map +1 -1
  228. package/dist/node/tlsServer.d.ts +19 -0
  229. package/dist/node/tlsServer.d.ts.map +1 -0
  230. package/dist/node/tlsServer.js +58 -0
  231. package/dist/node/tlsServer.js.map +1 -0
  232. package/dist/node/wrapNodeSocket.d.ts.map +1 -1
  233. package/dist/node/wrapNodeSocket.js +6 -28
  234. package/dist/node/wrapNodeSocket.js.map +1 -1
  235. package/dist/persistence/basicPersistence.d.ts +36 -0
  236. package/dist/persistence/basicPersistence.d.ts.map +1 -0
  237. package/dist/persistence/basicPersistence.js +306 -0
  238. package/dist/persistence/basicPersistence.js.map +1 -0
  239. package/dist/persistence/deps.d.ts +3 -2
  240. package/dist/persistence/deps.d.ts.map +1 -1
  241. package/dist/persistence/deps.js +2 -1
  242. package/dist/persistence/deps.js.map +1 -1
  243. package/dist/persistence/memory/memoryPersistence.d.ts +6 -23
  244. package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
  245. package/dist/persistence/memory/memoryPersistence.js +12 -115
  246. package/dist/persistence/memory/memoryPersistence.js.map +1 -1
  247. package/dist/persistence/memory/memoryStorage.d.ts +45 -0
  248. package/dist/persistence/memory/memoryStorage.d.ts.map +1 -0
  249. package/dist/persistence/memory/memoryStorage.js +143 -0
  250. package/dist/persistence/memory/memoryStorage.js.map +1 -0
  251. package/dist/persistence/mod.d.ts +3 -3
  252. package/dist/persistence/mod.d.ts.map +1 -1
  253. package/dist/persistence/mod.js +6 -1
  254. package/dist/persistence/mod.js.map +1 -1
  255. package/dist/persistence/persistence.d.ts +44 -69
  256. package/dist/persistence/persistence.d.ts.map +1 -1
  257. package/dist/persistence/persistence.js +1 -2
  258. package/dist/persistence/persistence.js.map +1 -1
  259. package/dist/persistence/sqlite/sqliteDatabase.d.ts +46 -0
  260. package/dist/persistence/sqlite/sqliteDatabase.d.ts.map +1 -0
  261. package/dist/persistence/sqlite/sqliteDatabase.js +215 -0
  262. package/dist/persistence/sqlite/sqliteDatabase.js.map +1 -0
  263. package/dist/persistence/sqlite/sqlitePersistence.d.ts +16 -0
  264. package/dist/persistence/sqlite/sqlitePersistence.d.ts.map +1 -0
  265. package/dist/persistence/sqlite/sqlitePersistence.js +29 -0
  266. package/dist/persistence/sqlite/sqlitePersistence.js.map +1 -0
  267. package/dist/persistence/sqlite/sqliteStorage.d.ts +36 -0
  268. package/dist/persistence/sqlite/sqliteStorage.d.ts.map +1 -0
  269. package/dist/persistence/sqlite/sqliteStorage.js +194 -0
  270. package/dist/persistence/sqlite/sqliteStorage.js.map +1 -0
  271. package/dist/persistence/storage.d.ts +38 -0
  272. package/dist/persistence/storage.d.ts.map +1 -0
  273. package/dist/persistence/storage.js +5 -0
  274. package/dist/persistence/storage.js.map +1 -0
  275. package/dist/server/config.d.ts +47 -0
  276. package/dist/server/config.d.ts.map +1 -0
  277. package/dist/server/config.js +41 -0
  278. package/dist/server/config.js.map +1 -0
  279. package/dist/server/context.d.ts +198 -24
  280. package/dist/server/context.d.ts.map +1 -1
  281. package/dist/server/context.js +432 -53
  282. package/dist/server/context.js.map +1 -1
  283. package/dist/server/deps.d.ts +5 -6
  284. package/dist/server/deps.d.ts.map +1 -1
  285. package/dist/server/deps.js +2 -2
  286. package/dist/server/deps.js.map +1 -1
  287. package/dist/server/handlers/completeConnect.d.ts +8 -0
  288. package/dist/server/handlers/completeConnect.d.ts.map +1 -0
  289. package/dist/server/handlers/completeConnect.js +74 -0
  290. package/dist/server/handlers/completeConnect.js.map +1 -0
  291. package/dist/server/handlers/handleAuth.d.ts +9 -0
  292. package/dist/server/handlers/handleAuth.d.ts.map +1 -0
  293. package/dist/server/handlers/handleAuth.js +69 -0
  294. package/dist/server/handlers/handleAuth.js.map +1 -0
  295. package/dist/server/handlers/handleConnect.d.ts +2 -4
  296. package/dist/server/handlers/handleConnect.d.ts.map +1 -1
  297. package/dist/server/handlers/handleConnect.js +140 -67
  298. package/dist/server/handlers/handleConnect.js.map +1 -1
  299. package/dist/server/handlers/handleDisconnect.d.ts +1 -1
  300. package/dist/server/handlers/handleDisconnect.d.ts.map +1 -1
  301. package/dist/server/handlers/handleDisconnect.js +3 -3
  302. package/dist/server/handlers/handleDisconnect.js.map +1 -1
  303. package/dist/server/handlers/handlePacket.d.ts.map +1 -1
  304. package/dist/server/handlers/handlePacket.js +19 -6
  305. package/dist/server/handlers/handlePacket.js.map +1 -1
  306. package/dist/server/handlers/handlePuback.d.ts +1 -3
  307. package/dist/server/handlers/handlePuback.d.ts.map +1 -1
  308. package/dist/server/handlers/handlePuback.js +2 -8
  309. package/dist/server/handlers/handlePuback.js.map +1 -1
  310. package/dist/server/handlers/handlePubcomp.d.ts +1 -1
  311. package/dist/server/handlers/handlePubcomp.d.ts.map +1 -1
  312. package/dist/server/handlers/handlePubcomp.js +2 -4
  313. package/dist/server/handlers/handlePubcomp.js.map +1 -1
  314. package/dist/server/handlers/handlePublish.d.ts +1 -1
  315. package/dist/server/handlers/handlePublish.d.ts.map +1 -1
  316. package/dist/server/handlers/handlePublish.js +149 -45
  317. package/dist/server/handlers/handlePublish.js.map +1 -1
  318. package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
  319. package/dist/server/handlers/handlePubrec.js +2 -3
  320. package/dist/server/handlers/handlePubrec.js.map +1 -1
  321. package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
  322. package/dist/server/handlers/handlePubrel.js +6 -2
  323. package/dist/server/handlers/handlePubrel.js.map +1 -1
  324. package/dist/server/handlers/handleSubscribe.d.ts +1 -6
  325. package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
  326. package/dist/server/handlers/handleSubscribe.js +99 -38
  327. package/dist/server/handlers/handleSubscribe.js.map +1 -1
  328. package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
  329. package/dist/server/handlers/handleUnsubscribe.js +19 -4
  330. package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
  331. package/dist/server/mod.d.ts +3 -3
  332. package/dist/server/mod.d.ts.map +1 -1
  333. package/dist/server/mod.js +1 -1
  334. package/dist/server/mod.js.map +1 -1
  335. package/dist/server/server.d.ts +29 -6
  336. package/dist/server/server.d.ts.map +1 -1
  337. package/dist/server/server.js +84 -15
  338. package/dist/server/server.js.map +1 -1
  339. package/dist/socket/socket.d.ts +11 -9
  340. package/dist/socket/socket.d.ts.map +1 -1
  341. package/dist/socket/socket.js +67 -15
  342. package/dist/socket/socket.js.map +1 -1
  343. package/dist/timer/timer.d.ts +32 -0
  344. package/dist/timer/timer.d.ts.map +1 -1
  345. package/dist/timer/timer.js +32 -0
  346. package/dist/timer/timer.js.map +1 -1
  347. package/dist/trie/trie.d.ts +10 -5
  348. package/dist/trie/trie.d.ts.map +1 -1
  349. package/dist/trie/trie.js +47 -17
  350. package/dist/trie/trie.js.map +1 -1
  351. package/dist/utils/assert.d.ts.map +1 -1
  352. package/dist/utils/{BufferedAsyncIterable.d.ts → bufferedAsyncIterable.d.ts} +1 -1
  353. package/dist/utils/bufferedAsyncIterable.d.ts.map +1 -0
  354. package/dist/utils/{BufferedAsyncIterable.js → bufferedAsyncIterable.js} +1 -1
  355. package/dist/utils/bufferedAsyncIterable.js.map +1 -0
  356. package/dist/utils/deferred.d.ts.map +1 -1
  357. package/dist/utils/deferred.js.map +1 -1
  358. package/dist/utils/getOrInsertPolyFill.d.ts +2 -0
  359. package/dist/utils/getOrInsertPolyFill.d.ts.map +1 -0
  360. package/dist/utils/getOrInsertPolyFill.js +12 -0
  361. package/dist/utils/getOrInsertPolyFill.js.map +1 -0
  362. package/dist/utils/logger.d.ts +40 -3
  363. package/dist/utils/logger.d.ts.map +1 -1
  364. package/dist/utils/logger.js +53 -7
  365. package/dist/utils/logger.js.map +1 -1
  366. package/dist/utils/mod.d.ts +6 -1
  367. package/dist/utils/mod.d.ts.map +1 -1
  368. package/dist/utils/mod.js +5 -1
  369. package/dist/utils/mod.js.map +1 -1
  370. package/dist/utils/outboundTopicAliasManager.d.ts +52 -0
  371. package/dist/utils/outboundTopicAliasManager.d.ts.map +1 -0
  372. package/dist/utils/outboundTopicAliasManager.js +74 -0
  373. package/dist/utils/outboundTopicAliasManager.js.map +1 -0
  374. package/dist/utils/queue.d.ts.map +1 -1
  375. package/dist/utils/topicFilter.d.ts +32 -0
  376. package/dist/utils/topicFilter.d.ts.map +1 -0
  377. package/dist/utils/topicFilter.js +52 -0
  378. package/dist/utils/topicFilter.js.map +1 -0
  379. package/dist/utils/utils.d.ts +2 -0
  380. package/dist/utils/utils.d.ts.map +1 -1
  381. package/dist/utils/utils.js +2 -0
  382. package/dist/utils/utils.js.map +1 -1
  383. package/dist/utils/validators.d.ts +34 -0
  384. package/dist/utils/validators.d.ts.map +1 -0
  385. package/dist/utils/validators.js +61 -0
  386. package/dist/utils/validators.js.map +1 -0
  387. package/dist/web/webSocketStream.d.ts +29 -0
  388. package/dist/web/webSocketStream.d.ts.map +1 -0
  389. package/dist/web/webSocketStream.js +69 -0
  390. package/dist/web/webSocketStream.js.map +1 -0
  391. package/dist/web/wrapWebSocket.d.ts +12 -0
  392. package/dist/web/wrapWebSocket.d.ts.map +1 -0
  393. package/dist/web/wrapWebSocket.js +41 -0
  394. package/dist/web/wrapWebSocket.js.map +1 -0
  395. package/dist/web/wsClient.d.ts +7 -0
  396. package/dist/web/wsClient.d.ts.map +1 -0
  397. package/dist/web/wsClient.js +22 -0
  398. package/dist/web/wsClient.js.map +1 -0
  399. package/dist/web/wsClient.test.d.ts +2 -0
  400. package/dist/web/wsClient.test.d.ts.map +1 -0
  401. package/dist/web/wsClient.test.js +20 -0
  402. package/dist/web/wsClient.test.js.map +1 -0
  403. package/examples/authHandler.test.ts +164 -0
  404. package/examples/mqtt.test.ts +89 -0
  405. package/examples/mqtts.test.ts +100 -0
  406. package/examples/webSocket.test.ts +94 -0
  407. package/mqttConn/mqttConn.test.ts +9 -9
  408. package/mqttConn/mqttConn.ts +91 -49
  409. package/mqttPacket/BitMask.ts +11 -19
  410. package/mqttPacket/Properties.ts +6 -3
  411. package/mqttPacket/ReasonCode.ts +2 -1
  412. package/mqttPacket/auth.test.ts +1 -1
  413. package/mqttPacket/auth.ts +41 -48
  414. package/mqttPacket/codec.ts +146 -0
  415. package/mqttPacket/connack.ts +57 -68
  416. package/mqttPacket/connect.test.ts +2 -2
  417. package/mqttPacket/connect.ts +197 -204
  418. package/mqttPacket/decoder.test.ts +0 -39
  419. package/mqttPacket/decoder.ts +9 -36
  420. package/mqttPacket/disconnect.ts +57 -68
  421. package/mqttPacket/encoder.ts +5 -40
  422. package/mqttPacket/length.ts +1 -1
  423. package/mqttPacket/mod.ts +48 -200
  424. package/mqttPacket/pingreq.ts +21 -27
  425. package/mqttPacket/pingres.ts +21 -27
  426. package/mqttPacket/protocolLevels.ts +12 -7
  427. package/mqttPacket/pubblishAcks.ts +68 -77
  428. package/mqttPacket/publish.ts +76 -83
  429. package/mqttPacket/suback.ts +48 -58
  430. package/mqttPacket/subscribe.ts +141 -117
  431. package/mqttPacket/types.ts +1 -9
  432. package/mqttPacket/unsuback.ts +46 -58
  433. package/mqttPacket/unsubscribe.ts +74 -63
  434. package/mqttPacket/validators.ts +5 -31
  435. package/node/socket-node-stream.test.ts +322 -0
  436. package/node/socket-node-stream.ts +174 -0
  437. package/node/tcpClient.test.ts +70 -0
  438. package/node/tcpClient.ts +13 -12
  439. package/node/tcpServer.test.ts +24 -20
  440. package/node/tcpServer.ts +6 -0
  441. package/node/tlsServer.test.ts +94 -0
  442. package/node/tlsServer.ts +81 -0
  443. package/node/wrapNodeSocket.ts +7 -30
  444. package/package.json +73 -45
  445. package/persistence/basicPersistence.ts +495 -0
  446. package/persistence/deps.ts +11 -1
  447. package/persistence/memory/memoryPersistence.ts +12 -152
  448. package/persistence/memory/memoryStorage.ts +232 -0
  449. package/persistence/mod.ts +4 -4
  450. package/persistence/persistence.test.ts +24 -0
  451. package/persistence/persistence.testing.ts +1324 -0
  452. package/persistence/persistence.ts +111 -67
  453. package/persistence/sqlite/sqliteDatabase.ts +294 -0
  454. package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
  455. package/persistence/sqlite/sqlitePersistence.ts +36 -0
  456. package/persistence/sqlite/sqliteStorage.ts +324 -0
  457. package/persistence/storage.ts +84 -0
  458. package/server/config.ts +65 -0
  459. package/server/context.ts +658 -74
  460. package/server/deps.ts +25 -5
  461. package/server/handlers/completeConnect.ts +93 -0
  462. package/server/handlers/duplicate.test.ts +196 -0
  463. package/server/handlers/handleAuth.test.ts +225 -0
  464. package/server/handlers/handleAuth.ts +88 -0
  465. package/server/handlers/handleConnect.test.ts +589 -0
  466. package/server/handlers/handleConnect.ts +201 -86
  467. package/server/handlers/handleConnect.version.test.ts +108 -0
  468. package/server/handlers/handleDisconnect.test.ts +56 -0
  469. package/server/handlers/handleDisconnect.ts +3 -3
  470. package/server/handlers/handlePacket.test.ts +24 -0
  471. package/server/handlers/handlePacket.ts +30 -8
  472. package/server/handlers/handlePingreq.test.ts +29 -0
  473. package/server/handlers/handlePuback.test.ts +28 -0
  474. package/server/handlers/handlePuback.ts +5 -8
  475. package/server/handlers/handlePubcomp.test.ts +28 -0
  476. package/server/handlers/handlePubcomp.ts +5 -4
  477. package/server/handlers/handlePublish.test.ts +471 -0
  478. package/server/handlers/handlePublish.ts +189 -35
  479. package/server/handlers/handlePubrec.test.ts +28 -0
  480. package/server/handlers/handlePubrec.ts +2 -3
  481. package/server/handlers/handlePubrel.test.ts +74 -0
  482. package/server/handlers/handlePubrel.ts +12 -2
  483. package/server/handlers/handleSubscribe.test.ts +971 -0
  484. package/server/handlers/handleSubscribe.ts +158 -39
  485. package/server/handlers/handleUnsubscribe.test.ts +79 -0
  486. package/server/handlers/handleUnsubscribe.ts +29 -5
  487. package/server/handlers/keepalive.test.ts +132 -0
  488. package/server/handlers/session.persistence.test.ts +194 -0
  489. package/server/handlers/will.delivery.test.ts +221 -0
  490. package/server/mod.ts +4 -3
  491. package/server/preconnect.test.ts +151 -0
  492. package/server/server.ts +115 -17
  493. package/socket/socket.test.ts +91 -0
  494. package/socket/socket.ts +81 -31
  495. package/timer/timer.test.ts +4 -7
  496. package/timer/timer.ts +36 -0
  497. package/tools/benchmarks/receiver.ts +51 -0
  498. package/tools/benchmarks/sender.ts +48 -0
  499. package/tools/benchmarks/utils.ts +31 -0
  500. package/tools/mqtt-compat/README.md +130 -0
  501. package/tools/mqtt-compat/broker.ts +52 -0
  502. package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
  503. package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
  504. package/trie/trie.test.ts +9 -1
  505. package/trie/trie.ts +57 -22
  506. package/utils/bufferedAsyncIterable.test.ts +92 -0
  507. package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +1 -1
  508. package/utils/deferred.test.ts +36 -0
  509. package/utils/deferred.ts +0 -1
  510. package/utils/getOrInsertPolyFill.ts +12 -0
  511. package/utils/logger.test.ts +189 -0
  512. package/utils/logger.ts +62 -7
  513. package/utils/mod.ts +15 -1
  514. package/utils/outboundTopicAliasManager.ts +100 -0
  515. package/utils/queue.test.ts +61 -0
  516. package/utils/topicFilter.test.ts +63 -0
  517. package/utils/topicFilter.ts +61 -0
  518. package/utils/utils.ts +3 -0
  519. package/utils/validators.ts +67 -0
  520. package/web/webSocketStream.ts +97 -0
  521. package/web/wrapWebSocket.ts +52 -0
  522. package/web/wsClient.test.ts +26 -0
  523. package/web/wsClient.ts +25 -0
  524. package/benchmarks/receiver.ts +0 -35
  525. package/benchmarks/sender.ts +0 -32
  526. package/benchmarks/utils.ts +0 -9
  527. package/dev_utils/dummyConn.ts +0 -110
  528. package/dist/persistence/store.d.ts +0 -13
  529. package/dist/persistence/store.d.ts.map +0 -1
  530. package/dist/persistence/store.js +0 -2
  531. package/dist/persistence/store.js.map +0 -1
  532. package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
  533. package/dist/utils/BufferedAsyncIterable.js.map +0 -1
  534. package/examples/tcpServer.test.ts +0 -148
  535. package/persistence/memory/memoryPersistence.test.ts +0 -156
  536. package/persistence/store.ts +0 -15
  537. package/server/test/handleConnect.test.ts +0 -130
  538. package/server/test/test-handlers.ts +0 -53
package/client/client.ts CHANGED
@@ -4,21 +4,23 @@ import {
4
4
  MemoryStore,
5
5
  MQTTLevel,
6
6
  PacketType,
7
+ ReasonCode,
7
8
  } from "./deps.ts";
8
9
 
9
10
  import type {
10
11
  ConnectPacket,
12
+ IStore,
11
13
  PublishPacket,
12
14
  SockConn,
13
15
  SubscribePacket,
14
16
  TAuthenticationResult,
15
17
  } from "./deps.ts";
16
18
 
17
- import { noop } from "../utils/utils.ts";
19
+ import { noop } from "../utils/mod.ts";
18
20
 
19
21
  import { Context } from "./context.ts";
22
+ import type { AuthenticatedResult } from "./context.ts";
20
23
  import type { TConnectionState } from "./ConnectionState.ts";
21
- import { assert } from "../utils/assert.ts";
22
24
  import { BufferedAsyncIterable } from "./deps.ts";
23
25
 
24
26
  /**
@@ -37,12 +39,12 @@ type ConnectOptions = Omit<
37
39
 
38
40
  /** ConnectParameters define how to connect */
39
41
  export type ConnectParameters = {
40
- url?: URL;
41
- caCerts?: string[];
42
- cert?: string;
43
- key?: string;
44
- numberOfRetries?: number;
45
- options?: ConnectOptions;
42
+ url?: URL | undefined;
43
+ caCerts?: string[] | undefined;
44
+ cert?: string | undefined;
45
+ key?: string | undefined;
46
+ numberOfRetries?: number | undefined;
47
+ options?: ConnectOptions | undefined;
46
48
  };
47
49
 
48
50
  /** PublishParameters define how a message should be published */
@@ -84,6 +86,20 @@ export const DEFAULT_KEEPALIVE = 60; // 60 seconds
84
86
  const DEFAULT_RETRIES = 3; // on first connect
85
87
  const CLIENTID_PREFIX = "opifex"; // on first connect
86
88
 
89
+ // convert an ErrorEvent into an Error
90
+ // NodeJS does not know ErrorEvent
91
+ function normalizeError(err: unknown): Error {
92
+ if (typeof ErrorEvent !== "undefined" && err instanceof ErrorEvent) {
93
+ return new Error(err.message);
94
+ }
95
+
96
+ if (err instanceof Error) {
97
+ return err;
98
+ }
99
+
100
+ throw err;
101
+ }
102
+
87
103
  /**
88
104
  * The Client class provides an MQTT Client that can be used to connect to
89
105
  * a MQTT broker and publish/subscribe messages.
@@ -94,6 +110,15 @@ const CLIENTID_PREFIX = "opifex"; // on first connect
94
110
  * connection type that is supported by the subclass.
95
111
  */
96
112
  export class Client {
113
+ public onAuth: (
114
+ authMethod: string,
115
+ authData: Uint8Array,
116
+ ) => AuthenticatedResult = () => {
117
+ return {
118
+ reasonCode: ReasonCode.badAuthenticationMethod,
119
+ reasonString: "No authentication method configured",
120
+ };
121
+ };
97
122
  public onError: (err: Error) => void = noop;
98
123
  public onPacket: (pkt: PublishPacket) => void | Promise<void> = noop;
99
124
  public onConnected: () => void = noop;
@@ -102,51 +127,43 @@ export class Client {
102
127
 
103
128
  protected clientIdPrefix = CLIENTID_PREFIX;
104
129
  protected numberOfRetries = DEFAULT_RETRIES;
105
- protected url: URL = new URL(DEFAULT_URL);
130
+ protected connectUrl: URL = new URL(DEFAULT_URL);
106
131
  protected keepAlive = DEFAULT_KEEPALIVE;
107
132
  protected protocolLevel = DEFAULT_PROTOCOLLEVEL;
108
133
  protected autoReconnect = true;
109
- private caCerts?: string[];
110
- private cert?: string;
111
- private key?: string;
112
- private clientId: string;
134
+ protected caCerts?: string[] | undefined;
135
+ protected cert?: string | undefined;
136
+ protected key?: string | undefined;
137
+ protected clientId: string;
113
138
  private ctx: Context;
114
139
  private connectPacket?: ConnectPacket;
115
140
 
116
141
  /**
117
142
  * Creates a new MQTT client instance
118
143
  */
119
- constructor() {
120
- this.ctx = new Context(new MemoryStore(), this);
144
+ constructor(store?: IStore) {
145
+ const cStore = store ? store : new MemoryStore();
146
+ this.ctx = new Context(cStore, this);
121
147
  this.clientId = generateClientId(this.clientIdPrefix);
122
148
  this.numberOfRetries = DEFAULT_RETRIES;
123
149
  }
124
150
 
125
- get connectionState(): TConnectionState {
151
+ public get connectionState(): TConnectionState {
126
152
  return this.ctx.connectionState;
127
153
  }
128
154
 
155
+ public get url(): URL {
156
+ return this.connectUrl;
157
+ }
158
+
129
159
  /**
130
160
  * Creates a new connection to the MQTT broker
131
- * @param protocol - The protocol to use (mqtt, mqtts, etc)
132
- * @param _hostname - The hostname to connect to
133
- * @param _port - The port to connect to
134
- * @param _caCerts - Optional CA certificates
135
- * @param _cert - Optional client certificate
136
- * @param _key - Optional client key
137
161
  * @returns Promise resolving to a SockConn connection
138
162
  */
139
- protected createConn(
140
- protocol: string,
141
- _hostname: string,
142
- _port?: number,
143
- _caCerts?: string[],
144
- _cert?: string,
145
- _key?: string,
146
- ): Promise<SockConn> {
163
+ protected createConn(): Promise<SockConn> {
147
164
  // if you need to support alternative connection types just
148
165
  // overload this method in your subclass
149
- throw new Error(`Unsupported protocol: ${protocol}`);
166
+ throw new Error(`Unsupported protocol: ${this.url.protocol}`);
150
167
  }
151
168
 
152
169
  /**
@@ -163,16 +180,12 @@ export class Client {
163
180
  let lastMessage = new Error();
164
181
  let tryConnect = true;
165
182
  while (tryConnect) {
166
- logger.debug(`${isReconnect ? "re" : ""}connecting, attempt ${attempt}`);
183
+ logger.debug(
184
+ isReconnect ? "reconnecting, attempt" : "connecting, attempt",
185
+ attempt,
186
+ );
167
187
  try {
168
- const conn = await this.createConn(
169
- this.url.protocol,
170
- this.url.hostname,
171
- Number(this.url.port) ?? undefined,
172
- this.caCerts,
173
- this.cert,
174
- this.key,
175
- );
188
+ const conn = await this.createConn();
176
189
  // if we get this far we have a connection
177
190
  tryConnect =
178
191
  (await this.ctx.handleConnection(conn, this.connectPacket)) &&
@@ -182,12 +195,9 @@ export class Client {
182
195
  this.connectPacket.clean = false;
183
196
  this.ctx.close();
184
197
  } catch (err) {
185
- assert(
186
- err instanceof Error,
187
- `Caught something that is not an instance of Error: ${err}`,
188
- );
189
- queueMicrotask(() => this.onError(err));
190
- lastMessage = err;
198
+ const normalizedErr = normalizeError(err);
199
+ queueMicrotask(() => this.onError(normalizedErr));
200
+ lastMessage = normalizedErr;
191
201
  logger.debug({ lastMessage });
192
202
  }
193
203
 
@@ -213,7 +223,7 @@ export class Client {
213
223
  * @returns Promise resolving to authentication result
214
224
  */
215
225
  connect(params: ConnectParameters = {}): Promise<TAuthenticationResult> {
216
- this.url = params?.url || this.url;
226
+ this.connectUrl = params?.url || this.connectUrl;
217
227
  this.numberOfRetries = params.numberOfRetries || this.numberOfRetries;
218
228
  this.caCerts = params?.caCerts;
219
229
  this.cert = params?.cert;
package/client/context.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  import type {
10
10
  AnyPacket,
11
11
  ConnectPacket,
12
- MemoryStore,
12
+ IStore,
13
13
  PacketId,
14
14
  ProtocolLevel,
15
15
  PublishPacket,
@@ -17,6 +17,8 @@ import type {
17
17
  SockConn,
18
18
  SubscribePacket,
19
19
  TAuthenticationResult,
20
+ TPacketType,
21
+ TReasonCode,
20
22
  UnsubscribePacket,
21
23
  } from "./deps.ts";
22
24
 
@@ -26,6 +28,24 @@ import { ConnectionState } from "./ConnectionState.ts";
26
28
  import type { Client } from "./client.ts";
27
29
  import { assert } from "../utils/assert.ts";
28
30
 
31
+ /**
32
+ * packets not allowed during authentication
33
+ */
34
+ function blockedDuringAuthentication(pktType: TPacketType) {
35
+ return (
36
+ pktType === PacketType.publish ||
37
+ pktType === PacketType.subscribe ||
38
+ pktType === PacketType.unsubscribe
39
+ );
40
+ }
41
+
42
+ /** Possible results from authHandler */
43
+ export type AuthenticatedResult = {
44
+ reasonCode: TReasonCode;
45
+ reasonString?: string;
46
+ authData?: Uint8Array;
47
+ };
48
+
29
49
  export class Context {
30
50
  mqttConn?: MqttConn;
31
51
  #connectionState: TConnectionState;
@@ -35,10 +55,10 @@ export class Context {
35
55
  unresolvedPublish: Map<PacketId, Deferred<void>>;
36
56
  unresolvedSubscribe: Map<PacketId, Deferred<ReturnCodes>>;
37
57
  unresolvedUnSubscribe: Map<PacketId, Deferred<void>>;
38
- store: MemoryStore;
58
+ store: IStore;
39
59
  #client: Client;
40
60
 
41
- constructor(store: MemoryStore, client: Client) {
61
+ constructor(store: IStore, client: Client) {
42
62
  this.#client = client;
43
63
  this.store = store;
44
64
  this.#connectionState = ConnectionState.offline;
@@ -64,6 +84,25 @@ export class Context {
64
84
  }
65
85
  }
66
86
 
87
+ authHandler(
88
+ _ctx: Context,
89
+ authMethod: string,
90
+ authData: Uint8Array,
91
+ ): AuthenticatedResult | Promise<AuthenticatedResult> {
92
+ return this.#client.onAuth(authMethod, authData);
93
+ }
94
+
95
+ setPingTimer(interval: number) {
96
+ if (this.pingTimer) {
97
+ this.pingTimer.clear();
98
+ }
99
+ this.pingTimer = new Timer(
100
+ this.sendPing.bind(this),
101
+ interval * 1000,
102
+ true,
103
+ );
104
+ }
105
+
67
106
  async connect(packet: ConnectPacket) {
68
107
  this.connectionState = ConnectionState.connecting;
69
108
  if (packet.protocolLevel === MQTTLevel.unknown) {
@@ -73,16 +112,15 @@ export class Context {
73
112
  await this.mqttConn?.send(packet);
74
113
  const keepAlive = packet.keepAlive || 0;
75
114
  if (keepAlive > 0) {
76
- this.pingTimer = new Timer(
77
- this.sendPing.bind(this),
78
- keepAlive * 1000,
79
- true,
80
- );
115
+ this.setPingTimer(keepAlive);
81
116
  }
82
117
  }
83
118
 
84
119
  async disconnect() {
85
- if (this.connectionState !== ConnectionState.connected) {
120
+ if (
121
+ this.connectionState !== ConnectionState.connected &&
122
+ this.connectionState !== ConnectionState.authenticating
123
+ ) {
86
124
  throw "Not connected";
87
125
  }
88
126
  if (this.mqttConn) {
@@ -97,14 +135,29 @@ export class Context {
97
135
  }
98
136
 
99
137
  async send(packet: AnyPacket) {
100
- logger.debug({ send: packet });
101
- if (
102
- this.connectionState === ConnectionState.connected &&
103
- !this.mqttConn?.isClosed
104
- ) {
105
- await this.mqttConn?.send(packet);
106
- this.pingTimer?.reset();
107
- return;
138
+ logger.debug("client.ctx.send", this.#connectionState, { packet });
139
+ if (!this.mqttConn?.isClosed) {
140
+ if (this.connectionState === ConnectionState.connected) {
141
+ await this.mqttConn?.send(packet);
142
+ this.pingTimer?.reset();
143
+ return;
144
+ }
145
+ if (
146
+ this.connectionState === ConnectionState.connecting &&
147
+ packet.type === PacketType.auth
148
+ ) {
149
+ await this.mqttConn?.send(packet);
150
+ this.pingTimer?.reset();
151
+ return;
152
+ }
153
+ if (
154
+ this.connectionState === ConnectionState.authenticating &&
155
+ !blockedDuringAuthentication(packet.type)
156
+ ) {
157
+ await this.mqttConn?.send(packet);
158
+ this.pingTimer?.reset();
159
+ return;
160
+ }
108
161
  }
109
162
  logger.debug("not connected");
110
163
  this.pingTimer?.clear();
@@ -122,6 +175,7 @@ export class Context {
122
175
  connectPacket: ConnectPacket,
123
176
  ): Promise<boolean> {
124
177
  this.mqttConn = new MqttConn({ conn });
178
+ this.mqttConn.codecOpts.protocolLevel = connectPacket.protocolLevel;
125
179
  try {
126
180
  logger.debug("Send connect packet", connectPacket);
127
181
  await this.connect(connectPacket);
@@ -136,7 +190,7 @@ export class Context {
136
190
  `Caught something that is not an instance of Error: ${err}`,
137
191
  );
138
192
  queueMicrotask(() => this.#client.onError(err));
139
- logger.debug(`error ${err}`);
193
+ logger.debug("error", err);
140
194
  if (!this.mqttConn.isClosed) {
141
195
  this.mqttConn.close();
142
196
  }
@@ -164,7 +218,7 @@ export class Context {
164
218
  await this.send(packet);
165
219
  return;
166
220
  }
167
- packet.id = this.store.nextId();
221
+ packet.id = await this.store.nextId();
168
222
  this.store.pendingOutgoing.set(packet.id, packet);
169
223
  const deferred = new Deferred<void>();
170
224
  this.unresolvedPublish.set(packet.id, deferred);
@@ -173,7 +227,7 @@ export class Context {
173
227
  }
174
228
 
175
229
  async subscribe(packet: SubscribePacket): Promise<ReturnCodes> {
176
- packet.id = this.store.nextId();
230
+ packet.id = await this.store.nextId();
177
231
  this.store.pendingOutgoing.set(packet.id, packet);
178
232
  const deferred = new Deferred<ReturnCodes>();
179
233
  this.unresolvedSubscribe.set(packet.id, deferred);
@@ -182,7 +236,7 @@ export class Context {
182
236
  }
183
237
 
184
238
  async unsubscribe(packet: UnsubscribePacket): Promise<void> {
185
- packet.id = this.store.nextId();
239
+ packet.id = await this.store.nextId();
186
240
  this.store.pendingOutgoing.set(packet.id, packet);
187
241
  const deferred = new Deferred<void>();
188
242
  this.unresolvedUnSubscribe.set(packet.id, deferred);
package/client/deps.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type {
2
2
  AnyPacket,
3
+ AuthPacket,
3
4
  ConnackPacket,
4
5
  ConnectPacket,
5
6
  DisconnectPacket,
@@ -12,11 +13,13 @@ export type {
12
13
  PublishPacket,
13
14
  PubrecPacket,
14
15
  PubrelPacket,
16
+ QoS,
15
17
  ReturnCodes,
16
18
  SubackPacket,
17
19
  SubscribePacket,
18
20
  TAuthenticationResult,
19
21
  Topic,
22
+ TPacketType,
20
23
  TReasonCode,
21
24
  UnsubackPacket,
22
25
  UnsubscribePacket,
@@ -30,6 +33,7 @@ export {
30
33
  MQTTLevel,
31
34
  PacketNameByType,
32
35
  PacketType,
36
+ ReasonCode,
33
37
  ReasonCodeByNumber,
34
38
  } from "../mqttPacket/mod.ts";
35
39
 
@@ -38,3 +42,4 @@ export type { SockConn } from "../socket/socket.ts";
38
42
  export { Timer } from "../timer/timer.ts";
39
43
  export { BufferedAsyncIterable, Deferred, logger } from "../utils/mod.ts";
40
44
  export { MemoryStore } from "./store/memoryStore.ts";
45
+ export type { IStore } from "./store/store.ts";
@@ -0,0 +1,193 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handleAuth } from "./handleAuth.ts";
4
+ import { ConnectionState } from "../ConnectionState.ts";
5
+ import { PacketType, ReasonCode } from "../deps.ts";
6
+ import type { AuthPacket } from "../deps.ts";
7
+ import type { AuthenticatedResult } from "../context.ts";
8
+ import { Deferred } from "../../utils/mod.ts";
9
+
10
+ function createMockContext() {
11
+ const sentPackets: unknown[] = [];
12
+ return {
13
+ connectionState: ConnectionState.connecting as string,
14
+ pingTimer: { clear: () => {} },
15
+ unresolvedConnect: new Deferred<number>(),
16
+ authHandler: (
17
+ _ctx: unknown,
18
+ _authMethod: string,
19
+ _authData: Uint8Array,
20
+ ): Promise<AuthenticatedResult> => {
21
+ return Promise.resolve({
22
+ reasonCode: ReasonCode.continueAuthentication,
23
+ authData: new Uint8Array([1, 2, 3]),
24
+ });
25
+ },
26
+ send: (packet: unknown) => {
27
+ sentPackets.push(packet);
28
+ },
29
+ sentPackets,
30
+ };
31
+ }
32
+
33
+ test("handleAuth sets connected state on ReasonCode.success", async () => {
34
+ const ctx = createMockContext();
35
+ const packet: AuthPacket = {
36
+ type: PacketType.auth,
37
+ protocolLevel: 5 as const,
38
+ reasonCode: ReasonCode.success,
39
+ };
40
+
41
+ await handleAuth(ctx as never, packet);
42
+
43
+ assert.deepStrictEqual(
44
+ ctx.connectionState,
45
+ ConnectionState.connected,
46
+ "Should set connection state to connected when reasonCode is success",
47
+ );
48
+ });
49
+
50
+ test("handleAuth handles authentication failure when connecting", async () => {
51
+ const ctx = createMockContext();
52
+ ctx.connectionState = ConnectionState.connecting;
53
+
54
+ const packet: AuthPacket = {
55
+ type: PacketType.auth,
56
+ protocolLevel: 5 as const,
57
+ reasonCode: ReasonCode.badAuthenticationMethod,
58
+ };
59
+
60
+ await handleAuth(ctx as never, packet);
61
+
62
+ assert.deepStrictEqual(
63
+ ctx.connectionState,
64
+ ConnectionState.disconnecting,
65
+ "Should transition state to disconnecting on failure during connect",
66
+ );
67
+
68
+ await assert.rejects(
69
+ ctx.unresolvedConnect.promise,
70
+ /Connect failed/,
71
+ "Should reject unresolvedConnect with connect failed error",
72
+ );
73
+ });
74
+
75
+ test("handleAuth throws error on authentication failure when connected", async () => {
76
+ const ctx = createMockContext();
77
+ ctx.connectionState = ConnectionState.connected;
78
+
79
+ const packet: AuthPacket = {
80
+ type: PacketType.auth,
81
+ protocolLevel: 5 as const,
82
+ reasonCode: ReasonCode.badAuthenticationMethod,
83
+ };
84
+
85
+ await assert.rejects(
86
+ async () => {
87
+ await handleAuth(ctx as never, packet);
88
+ },
89
+ Error,
90
+ "Should throw an error if reasonCode indicates failure after already connected",
91
+ );
92
+ });
93
+
94
+ test("handleAuth throws error if authMethod or authData is missing", async () => {
95
+ const ctx = createMockContext();
96
+ const packet: AuthPacket = {
97
+ type: PacketType.auth,
98
+ protocolLevel: 5 as const,
99
+ reasonCode: ReasonCode.continueAuthentication,
100
+ properties: {
101
+ authenticationMethod: "SCRAM-SHA-256",
102
+ // authenticationData missing
103
+ },
104
+ };
105
+
106
+ await assert.rejects(
107
+ async () => {
108
+ await handleAuth(ctx as never, packet);
109
+ },
110
+ /Auth method and\/or Auth data missing/,
111
+ "Should throw when missing required auth properties",
112
+ );
113
+ });
114
+
115
+ test("handleAuth transitions state and sends response packet on continueAuthentication success", async () => {
116
+ const ctx = createMockContext();
117
+ ctx.connectionState = ConnectionState.connected;
118
+
119
+ ctx.authHandler = () =>
120
+ Promise.resolve({
121
+ reasonCode: ReasonCode.continueAuthentication,
122
+ authData: new Uint8Array([4, 5, 6]),
123
+ reasonString: "Continue",
124
+ });
125
+
126
+ const packet: AuthPacket = {
127
+ type: PacketType.auth,
128
+ protocolLevel: 5 as const,
129
+ reasonCode: ReasonCode.continueAuthentication,
130
+ properties: {
131
+ authenticationMethod: "SCRAM-SHA-256",
132
+ authenticationData: new Uint8Array([1, 2, 3]),
133
+ },
134
+ };
135
+
136
+ await handleAuth(ctx as never, packet);
137
+
138
+ assert.deepStrictEqual(
139
+ ctx.connectionState,
140
+ ConnectionState.authenticating,
141
+ "Should transition connection state to authenticating",
142
+ );
143
+ assert.deepStrictEqual(
144
+ ctx.sentPackets.length,
145
+ 1,
146
+ "Should send a response auth packet",
147
+ );
148
+ assert.deepStrictEqual(ctx.sentPackets[0], {
149
+ type: PacketType.auth,
150
+ protocolLevel: 5,
151
+ reasonCode: ReasonCode.continueAuthentication,
152
+ properties: {
153
+ authenticationMethod: "SCRAM-SHA-256",
154
+ authenticationData: new Uint8Array([4, 5, 6]),
155
+ reasonString: "Continue",
156
+ },
157
+ });
158
+ });
159
+
160
+ test("handleAuth handles failure result from authHandler", async () => {
161
+ const ctx = createMockContext();
162
+ ctx.connectionState = ConnectionState.connecting;
163
+
164
+ ctx.authHandler = () =>
165
+ Promise.resolve({
166
+ reasonCode: ReasonCode.notAuthorized,
167
+ reasonString: "Not authorized to proceed",
168
+ });
169
+
170
+ const packet: AuthPacket = {
171
+ type: PacketType.auth,
172
+ protocolLevel: 5 as const,
173
+ reasonCode: ReasonCode.continueAuthentication,
174
+ properties: {
175
+ authenticationMethod: "SCRAM-SHA-256",
176
+ authenticationData: new Uint8Array([1, 2, 3]),
177
+ },
178
+ };
179
+
180
+ await handleAuth(ctx as never, packet);
181
+
182
+ assert.deepStrictEqual(
183
+ ctx.connectionState,
184
+ ConnectionState.disconnecting,
185
+ "Should set state to disconnecting on authHandler failure",
186
+ );
187
+
188
+ await assert.rejects(
189
+ ctx.unresolvedConnect.promise,
190
+ /Connect failed: Not authorized to proceed/,
191
+ "Should reject unresolvedConnect with the reasonString provided by authHandler",
192
+ );
193
+ });
@@ -0,0 +1,89 @@
1
+ import type { AuthenticatedResult, Context } from "../context.ts";
2
+ import { ConnectionState } from "../ConnectionState.ts";
3
+ import { PacketType, ReasonCode, ReasonCodeByNumber } from "../deps.ts";
4
+ import type { AuthPacket } from "../deps.ts";
5
+
6
+ /**
7
+ * Handle error
8
+ */
9
+
10
+ function handleError(ctx: Context, errMsg: string) {
11
+ if (ctx.connectionState === ConnectionState.connecting) {
12
+ const err = new Error(
13
+ `Connect failed: ${errMsg}`,
14
+ );
15
+ ctx.connectionState = ConnectionState.disconnecting;
16
+ ctx.pingTimer?.clear();
17
+ ctx.unresolvedConnect?.reject(err);
18
+ return;
19
+ }
20
+ throw new Error(errMsg);
21
+ }
22
+
23
+ /**
24
+ * Handle success
25
+ */
26
+
27
+ async function handleResult(
28
+ ctx: Context,
29
+ authMethod: string,
30
+ result: AuthenticatedResult,
31
+ ) {
32
+ await ctx.send({
33
+ type: PacketType.auth,
34
+ protocolLevel: 5,
35
+ reasonCode: result.reasonCode,
36
+ properties: result.authData
37
+ ? {
38
+ authenticationMethod: authMethod,
39
+ authenticationData: result.authData,
40
+ reasonString: result.reasonString,
41
+ }
42
+ : {},
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Handles v5 Auth packet
48
+ * @param ctx - The connection context containing send method
49
+ * @returns Promise that resolves
50
+ */
51
+
52
+ export async function handleAuth(
53
+ ctx: Context,
54
+ authPacket: AuthPacket,
55
+ ): Promise<void> {
56
+ const reasonCode = authPacket.reasonCode;
57
+ if (reasonCode === ReasonCode.success) {
58
+ // we are connected again
59
+ ctx.connectionState = ConnectionState.connected;
60
+ return;
61
+ }
62
+
63
+ if (reasonCode !== ReasonCode.continueAuthentication) {
64
+ // something went wrong
65
+ handleError(ctx, ReasonCodeByNumber[reasonCode]);
66
+ return;
67
+ }
68
+
69
+ // we need to send something back
70
+ if (ctx.connectionState === ConnectionState.connected) {
71
+ // pauze auther activities
72
+ ctx.connectionState = ConnectionState.authenticating;
73
+ }
74
+
75
+ const authMethod = authPacket.properties?.authenticationMethod;
76
+ const authData = authPacket.properties?.authenticationData;
77
+ if (!(authMethod && authData)) {
78
+ throw new Error("Auth method and/or Auth data missing");
79
+ }
80
+ const result = await ctx.authHandler(
81
+ ctx,
82
+ authMethod,
83
+ authData,
84
+ );
85
+ if (result.reasonCode === ReasonCode.continueAuthentication) {
86
+ return handleResult(ctx, authMethod, result);
87
+ }
88
+ return handleError(ctx, result.reasonString || "Error during authentication");
89
+ }