@seriousme/opifex 1.11.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (542) 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 +3 -1
  6. package/client/client.ts +88 -47
  7. package/client/context.ts +79 -27
  8. package/client/deps.ts +10 -3
  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 +18 -8
  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 +13 -2
  29. package/client/store/memoryStore.ts +12 -11
  30. package/client/store/store.ts +4 -2
  31. package/deno/README.md +1 -2
  32. package/deno/tcpClient.test.ts +75 -0
  33. package/deno/tcpClient.ts +36 -18
  34. package/deno/tcpServer.test.ts +22 -21
  35. package/deno/tcpServer.ts +26 -4
  36. package/deno/tlsServer.test.ts +97 -0
  37. package/deno/tlsServer.ts +58 -0
  38. package/deno/wsServer.test.ts +93 -0
  39. package/deno/wsServer.ts +96 -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 +3 -1
  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 +47 -21
  60. package/dist/client/client.d.ts.map +1 -1
  61. package/dist/client/client.js +57 -20
  62. package/dist/client/client.js.map +1 -1
  63. package/dist/client/context.d.ts +15 -7
  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 +4 -3
  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 +3 -2
  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 +3 -3
  104. package/dist/client/store/memoryStore.d.ts.map +1 -1
  105. package/dist/client/store/memoryStore.js +3 -3
  106. package/dist/client/store/memoryStore.js.map +1 -1
  107. package/dist/client/store/store.d.ts +3 -2
  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 +24 -31
  128. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  129. package/dist/mqttConn/mqttConn.js +57 -36
  130. package/dist/mqttConn/mqttConn.js.map +1 -1
  131. package/dist/mqttPacket/AuthenticationResult.d.ts +4 -0
  132. package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
  133. package/dist/mqttPacket/AuthenticationResult.js.map +1 -1
  134. package/dist/mqttPacket/BitMask.d.ts.map +1 -1
  135. package/dist/mqttPacket/PacketType.d.ts +4 -0
  136. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  137. package/dist/mqttPacket/Properties.d.ts +4 -4
  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 +4 -5
  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 +4 -0
  145. package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
  146. package/dist/mqttPacket/auth.d.ts +7 -8
  147. package/dist/mqttPacket/auth.d.ts.map +1 -1
  148. package/dist/mqttPacket/auth.js +31 -30
  149. package/dist/mqttPacket/auth.js.map +1 -1
  150. package/dist/mqttPacket/codec.d.ts +48 -0
  151. package/dist/mqttPacket/codec.d.ts.map +1 -0
  152. package/dist/mqttPacket/codec.js +93 -0
  153. package/dist/mqttPacket/codec.js.map +1 -0
  154. package/dist/mqttPacket/connack.d.ts +11 -10
  155. package/dist/mqttPacket/connack.d.ts.map +1 -1
  156. package/dist/mqttPacket/connack.js +43 -45
  157. package/dist/mqttPacket/connack.js.map +1 -1
  158. package/dist/mqttPacket/connect.d.ts +7 -7
  159. package/dist/mqttPacket/connect.d.ts.map +1 -1
  160. package/dist/mqttPacket/connect.js +156 -157
  161. package/dist/mqttPacket/connect.js.map +1 -1
  162. package/dist/mqttPacket/decoder.d.ts +6 -16
  163. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  164. package/dist/mqttPacket/decoder.js +7 -28
  165. package/dist/mqttPacket/decoder.js.map +1 -1
  166. package/dist/mqttPacket/disconnect.d.ts +9 -8
  167. package/dist/mqttPacket/disconnect.d.ts.map +1 -1
  168. package/dist/mqttPacket/disconnect.js +41 -43
  169. package/dist/mqttPacket/disconnect.js.map +1 -1
  170. package/dist/mqttPacket/encoder.d.ts +7 -19
  171. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  172. package/dist/mqttPacket/encoder.js +5 -28
  173. package/dist/mqttPacket/encoder.js.map +1 -1
  174. package/dist/mqttPacket/mod.d.ts +21 -103
  175. package/dist/mqttPacket/mod.d.ts.map +1 -1
  176. package/dist/mqttPacket/mod.js +5 -94
  177. package/dist/mqttPacket/mod.js.map +1 -1
  178. package/dist/mqttPacket/pingreq.d.ts +6 -6
  179. package/dist/mqttPacket/pingreq.d.ts.map +1 -1
  180. package/dist/mqttPacket/pingreq.js +11 -13
  181. package/dist/mqttPacket/pingreq.js.map +1 -1
  182. package/dist/mqttPacket/pingres.d.ts +6 -6
  183. package/dist/mqttPacket/pingres.d.ts.map +1 -1
  184. package/dist/mqttPacket/pingres.js +11 -13
  185. package/dist/mqttPacket/pingres.js.map +1 -1
  186. package/dist/mqttPacket/protocolLevels.d.ts +11 -6
  187. package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
  188. package/dist/mqttPacket/protocolLevels.js +5 -1
  189. package/dist/mqttPacket/protocolLevels.js.map +1 -1
  190. package/dist/mqttPacket/pubblishAcks.d.ts +9 -10
  191. package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
  192. package/dist/mqttPacket/pubblishAcks.js +43 -45
  193. package/dist/mqttPacket/pubblishAcks.js.map +1 -1
  194. package/dist/mqttPacket/publish.d.ts +8 -7
  195. package/dist/mqttPacket/publish.d.ts.map +1 -1
  196. package/dist/mqttPacket/publish.js +53 -55
  197. package/dist/mqttPacket/publish.js.map +1 -1
  198. package/dist/mqttPacket/suback.d.ts +9 -8
  199. package/dist/mqttPacket/suback.d.ts.map +1 -1
  200. package/dist/mqttPacket/suback.js +38 -40
  201. package/dist/mqttPacket/suback.js.map +1 -1
  202. package/dist/mqttPacket/subscribe.d.ts +41 -10
  203. package/dist/mqttPacket/subscribe.d.ts.map +1 -1
  204. package/dist/mqttPacket/subscribe.js +90 -89
  205. package/dist/mqttPacket/subscribe.js.map +1 -1
  206. package/dist/mqttPacket/types.d.ts +2 -29
  207. package/dist/mqttPacket/types.d.ts.map +1 -1
  208. package/dist/mqttPacket/unsuback.d.ts +9 -8
  209. package/dist/mqttPacket/unsuback.d.ts.map +1 -1
  210. package/dist/mqttPacket/unsuback.js +32 -34
  211. package/dist/mqttPacket/unsuback.js.map +1 -1
  212. package/dist/mqttPacket/unsubscribe.d.ts +26 -8
  213. package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
  214. package/dist/mqttPacket/unsubscribe.js +45 -44
  215. package/dist/mqttPacket/unsubscribe.js.map +1 -1
  216. package/dist/mqttPacket/validators.d.ts +4 -16
  217. package/dist/mqttPacket/validators.d.ts.map +1 -1
  218. package/dist/mqttPacket/validators.js +5 -26
  219. package/dist/mqttPacket/validators.js.map +1 -1
  220. package/dist/node/tcpClient.d.ts +22 -2
  221. package/dist/node/tcpClient.d.ts.map +1 -1
  222. package/dist/node/tcpClient.js +29 -10
  223. package/dist/node/tcpClient.js.map +1 -1
  224. package/dist/node/tcpServer.d.ts +18 -0
  225. package/dist/node/tcpServer.d.ts.map +1 -1
  226. package/dist/node/tcpServer.js +21 -2
  227. package/dist/node/tcpServer.js.map +1 -1
  228. package/dist/node/tlsServer.d.ts +37 -0
  229. package/dist/node/tlsServer.d.ts.map +1 -0
  230. package/dist/node/tlsServer.js +73 -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 +45 -70
  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 +199 -25
  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 +9 -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 +32 -9
  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 +15 -9
  340. package/dist/socket/socket.d.ts.map +1 -1
  341. package/dist/socket/socket.js +66 -18
  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 +61 -41
  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 +42 -5
  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 +14 -0
  396. package/dist/web/wsClient.d.ts.map +1 -0
  397. package/dist/web/wsClient.js +33 -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 +76 -60
  409. package/mqttPacket/AuthenticationResult.ts +6 -0
  410. package/mqttPacket/PacketType.ts +5 -0
  411. package/mqttPacket/Properties.ts +8 -5
  412. package/mqttPacket/ReasonCode.ts +8 -9
  413. package/mqttPacket/RetainHandling.ts +5 -0
  414. package/mqttPacket/auth.test.ts +1 -1
  415. package/mqttPacket/auth.ts +44 -51
  416. package/mqttPacket/codec.ts +147 -0
  417. package/mqttPacket/connack.ts +63 -73
  418. package/mqttPacket/connect.test.ts +2 -2
  419. package/mqttPacket/connect.ts +178 -192
  420. package/mqttPacket/decoder.test.ts +0 -39
  421. package/mqttPacket/decoder.ts +17 -46
  422. package/mqttPacket/disconnect.ts +60 -71
  423. package/mqttPacket/encoder.test.ts +2 -2
  424. package/mqttPacket/encoder.ts +13 -46
  425. package/mqttPacket/mod.ts +48 -204
  426. package/mqttPacket/pingreq.ts +22 -28
  427. package/mqttPacket/pingres.ts +22 -28
  428. package/mqttPacket/protocolLevels.ts +12 -7
  429. package/mqttPacket/pubblishAcks.ts +61 -75
  430. package/mqttPacket/publish.ts +70 -84
  431. package/mqttPacket/publishAcks.test.ts +3 -3
  432. package/mqttPacket/suback.ts +53 -68
  433. package/mqttPacket/subscribe.ts +146 -128
  434. package/mqttPacket/types.ts +2 -35
  435. package/mqttPacket/unsuback.ts +50 -61
  436. package/mqttPacket/unsubscribe.ts +77 -72
  437. package/mqttPacket/validators.ts +5 -31
  438. package/node/socket-node-stream.test.ts +322 -0
  439. package/node/socket-node-stream.ts +174 -0
  440. package/node/tcpClient.test.ts +70 -0
  441. package/node/tcpClient.ts +33 -17
  442. package/node/tcpServer.test.ts +24 -20
  443. package/node/tcpServer.ts +29 -6
  444. package/node/tlsServer.test.ts +94 -0
  445. package/node/tlsServer.ts +97 -0
  446. package/node/wrapNodeSocket.ts +7 -30
  447. package/package.json +72 -44
  448. package/persistence/basicPersistence.ts +495 -0
  449. package/persistence/deps.ts +11 -1
  450. package/persistence/memory/memoryPersistence.ts +12 -153
  451. package/persistence/memory/memoryStorage.ts +232 -0
  452. package/persistence/mod.ts +5 -10
  453. package/persistence/persistence.test.ts +24 -0
  454. package/persistence/persistence.testing.ts +1324 -0
  455. package/persistence/persistence.ts +112 -68
  456. package/persistence/sqlite/sqliteDatabase.ts +294 -0
  457. package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
  458. package/persistence/sqlite/sqlitePersistence.ts +36 -0
  459. package/persistence/sqlite/sqliteStorage.ts +324 -0
  460. package/persistence/storage.ts +84 -0
  461. package/server/config.ts +65 -0
  462. package/server/context.ts +660 -76
  463. package/server/deps.ts +24 -5
  464. package/server/handlers/completeConnect.ts +93 -0
  465. package/server/handlers/duplicate.test.ts +196 -0
  466. package/server/handlers/handleAuth.test.ts +225 -0
  467. package/server/handlers/handleAuth.ts +88 -0
  468. package/server/handlers/handleConnect.test.ts +589 -0
  469. package/server/handlers/handleConnect.ts +201 -86
  470. package/server/handlers/handleConnect.version.test.ts +108 -0
  471. package/server/handlers/handleDisconnect.test.ts +56 -0
  472. package/server/handlers/handleDisconnect.ts +3 -3
  473. package/server/handlers/handlePacket.test.ts +24 -0
  474. package/server/handlers/handlePacket.ts +30 -8
  475. package/server/handlers/handlePingreq.test.ts +29 -0
  476. package/server/handlers/handlePuback.test.ts +28 -0
  477. package/server/handlers/handlePuback.ts +5 -8
  478. package/server/handlers/handlePubcomp.test.ts +28 -0
  479. package/server/handlers/handlePubcomp.ts +5 -4
  480. package/server/handlers/handlePublish.test.ts +471 -0
  481. package/server/handlers/handlePublish.ts +188 -35
  482. package/server/handlers/handlePubrec.test.ts +28 -0
  483. package/server/handlers/handlePubrec.ts +2 -3
  484. package/server/handlers/handlePubrel.test.ts +74 -0
  485. package/server/handlers/handlePubrel.ts +12 -2
  486. package/server/handlers/handleSubscribe.test.ts +971 -0
  487. package/server/handlers/handleSubscribe.ts +157 -39
  488. package/server/handlers/handleUnsubscribe.test.ts +79 -0
  489. package/server/handlers/handleUnsubscribe.ts +28 -4
  490. package/server/handlers/keepalive.test.ts +132 -0
  491. package/server/handlers/session.persistence.test.ts +194 -0
  492. package/server/handlers/will.delivery.test.ts +221 -0
  493. package/server/mod.ts +5 -4
  494. package/server/preconnect.test.ts +151 -0
  495. package/server/server.ts +117 -19
  496. package/socket/socket.test.ts +91 -0
  497. package/socket/socket.ts +85 -34
  498. package/timer/timer.test.ts +4 -7
  499. package/timer/timer.ts +36 -0
  500. package/tools/benchmarks/receiver.ts +51 -0
  501. package/tools/benchmarks/sender.ts +48 -0
  502. package/tools/benchmarks/utils.ts +31 -0
  503. package/tools/mqtt-compat/README.md +130 -0
  504. package/tools/mqtt-compat/broker.ts +52 -0
  505. package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
  506. package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
  507. package/trie/trie.test.ts +9 -1
  508. package/trie/trie.ts +70 -45
  509. package/utils/bufferedAsyncIterable.test.ts +92 -0
  510. package/utils/deferred.test.ts +36 -0
  511. package/utils/deferred.ts +0 -1
  512. package/utils/getOrInsertPolyFill.ts +12 -0
  513. package/utils/logger.test.ts +189 -0
  514. package/utils/logger.ts +64 -9
  515. package/utils/mod.ts +15 -1
  516. package/utils/outboundTopicAliasManager.ts +100 -0
  517. package/utils/queue.test.ts +61 -0
  518. package/utils/topicFilter.test.ts +63 -0
  519. package/utils/topicFilter.ts +61 -0
  520. package/utils/utils.ts +3 -0
  521. package/utils/validators.ts +67 -0
  522. package/web/webSocketStream.ts +97 -0
  523. package/web/wrapWebSocket.ts +52 -0
  524. package/web/wsClient.test.ts +26 -0
  525. package/web/wsClient.ts +37 -0
  526. package/benchmarks/receiver.ts +0 -35
  527. package/benchmarks/sender.ts +0 -32
  528. package/benchmarks/utils.ts +0 -9
  529. package/dev_utils/dummyConn.ts +0 -110
  530. package/dev_utils/socketPair.ts +0 -85
  531. package/dist/persistence/store.d.ts +0 -14
  532. package/dist/persistence/store.d.ts.map +0 -1
  533. package/dist/persistence/store.js +0 -2
  534. package/dist/persistence/store.js.map +0 -1
  535. package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
  536. package/dist/utils/BufferedAsyncIterable.js.map +0 -1
  537. package/examples/tcpServer.test.ts +0 -148
  538. package/persistence/memory/memoryPersistence.test.ts +0 -156
  539. package/persistence/store.ts +0 -16
  540. package/server/test/handleConnect.test.ts +0 -122
  541. package/server/test/test-handlers.ts +0 -53
  542. /package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +0 -0
package/client/client.ts CHANGED
@@ -4,21 +4,24 @@ import {
4
4
  MemoryStore,
5
5
  MQTTLevel,
6
6
  PacketType,
7
+ ReasonCode,
7
8
  } from "./deps.ts";
8
9
 
9
10
  import type {
11
+ AuthenticationResult,
10
12
  ConnectPacket,
13
+ ProtocolLevel,
11
14
  PublishPacket,
12
15
  SockConn,
16
+ Store,
13
17
  SubscribePacket,
14
- TAuthenticationResult,
15
18
  } from "./deps.ts";
16
19
 
17
- import { noop } from "../utils/utils.ts";
20
+ import { noop } from "../utils/mod.ts";
18
21
 
19
22
  import { Context } from "./context.ts";
20
- import type { TConnectionState } from "./ConnectionState.ts";
21
- import { assert } from "../utils/assert.ts";
23
+ import type { AuthenticatedResult } from "./context.ts";
24
+ import type { ConnectionState } from "./ConnectionState.ts";
22
25
  import { BufferedAsyncIterable } from "./deps.ts";
23
26
 
24
27
  /**
@@ -30,18 +33,25 @@ function generateClientId(prefix: string): string {
30
33
  return `${prefix}-${Math.random().toString().slice(-10)}`;
31
34
  }
32
35
 
33
- type ConnectOptions = Omit<
36
+ /** All properties of a connect packet, except for type and protocol name */
37
+ export type ConnectOptions = Omit<
34
38
  ConnectPacket,
35
39
  "type" | "protocolName"
36
40
  >;
37
41
 
38
42
  /** ConnectParameters define how to connect */
39
43
  export type ConnectParameters = {
44
+ /** the URL to connect to */
40
45
  url?: URL | undefined;
46
+ /** any CA Certs to trust */
41
47
  caCerts?: string[] | undefined;
48
+ /** the clients certificate */
42
49
  cert?: string | undefined;
50
+ /** the clients private key*/
43
51
  key?: string | undefined;
52
+ /** number of retries before stopping connection attempts */
44
53
  numberOfRetries?: number | undefined;
54
+ /** connect options */
45
55
  options?: ConnectOptions | undefined;
46
56
  };
47
57
 
@@ -78,12 +88,26 @@ function backOffSleep(random: boolean, attempt: number): Promise<void> {
78
88
  /** the default MQTT URL to connect to */
79
89
  export const DEFAULT_URL = "mqtt://localhost:1883/";
80
90
  /** the default protocol level to connect with*/
81
- export const DEFAULT_PROTOCOLLEVEL = MQTTLevel.v4;
91
+ export const DEFAULT_PROTOCOLLEVEL = MQTTLevel.v4 as ProtocolLevel;
82
92
  /** the default keepalive time */
83
93
  export const DEFAULT_KEEPALIVE = 60; // 60 seconds
84
94
  const DEFAULT_RETRIES = 3; // on first connect
85
95
  const CLIENTID_PREFIX = "opifex"; // on first connect
86
96
 
97
+ // convert an ErrorEvent into an Error
98
+ // NodeJS does not know ErrorEvent
99
+ function normalizeError(err: unknown): Error {
100
+ if (typeof ErrorEvent !== "undefined" && err instanceof ErrorEvent) {
101
+ return new Error(err.message);
102
+ }
103
+
104
+ if (err instanceof Error) {
105
+ return err;
106
+ }
107
+
108
+ throw err;
109
+ }
110
+
87
111
  /**
88
112
  * The Client class provides an MQTT Client that can be used to connect to
89
113
  * a MQTT broker and publish/subscribe messages.
@@ -94,59 +118,83 @@ const CLIENTID_PREFIX = "opifex"; // on first connect
94
118
  * connection type that is supported by the subclass.
95
119
  */
96
120
  export class Client {
121
+ public onAuth: (
122
+ authMethod: string,
123
+ authData: Uint8Array,
124
+ ) => AuthenticatedResult = () => {
125
+ return {
126
+ reasonCode: ReasonCode.badAuthenticationMethod,
127
+ reasonString: "No authentication method configured",
128
+ };
129
+ };
130
+ /** callback for errors */
97
131
  public onError: (err: Error) => void = noop;
132
+ /** callback for publish packets */
98
133
  public onPacket: (pkt: PublishPacket) => void | Promise<void> = noop;
134
+ /** callback once connected */
99
135
  public onConnected: () => void = noop;
136
+ /** callback once disconnected */
100
137
  public onDisconnected: () => void = noop;
138
+ /** callback when reconnecting */
101
139
  public onReconnecting: () => void = noop;
102
140
 
141
+ /** clientId prefix used when automatically generating a client Id */
103
142
  protected clientIdPrefix = CLIENTID_PREFIX;
143
+ /** number of times to retry connect */
104
144
  protected numberOfRetries = DEFAULT_RETRIES;
105
- protected url: URL = new URL(DEFAULT_URL);
145
+ /** the URL to connect to */
146
+ protected connectUrl: URL = new URL(DEFAULT_URL);
147
+ /** the keepAlive value in number of seconds */
106
148
  protected keepAlive = DEFAULT_KEEPALIVE;
149
+ /** the requested protocol level */
107
150
  protected protocolLevel = DEFAULT_PROTOCOLLEVEL;
151
+ /** try auto reconnect if connection is lost */
108
152
  protected autoReconnect = true;
109
- private caCerts?: string[] | undefined;
110
- private cert?: string | undefined;
111
- private key?: string | undefined;
112
- private clientId: string;
153
+ /** any CA Certs to trust */
154
+ protected caCerts?: string[] | undefined;
155
+ /** the clients certificate */
156
+ protected cert?: string | undefined;
157
+ /** the clients private key*/
158
+ protected key?: string | undefined;
159
+ /** the MQTT clientId */
160
+ protected clientId: string;
113
161
  private ctx: Context;
114
162
  private connectPacket?: ConnectPacket;
115
163
 
116
164
  /**
117
165
  * Creates a new MQTT client instance
118
166
  */
119
- constructor() {
120
- this.ctx = new Context(new MemoryStore(), this);
167
+ constructor(store?: Store) {
168
+ const cStore = store ? store : new MemoryStore();
169
+ this.ctx = new Context(cStore, this);
121
170
  this.clientId = generateClientId(this.clientIdPrefix);
122
171
  this.numberOfRetries = DEFAULT_RETRIES;
123
172
  }
124
173
 
125
- get connectionState(): TConnectionState {
174
+ /**
175
+ * Current connection state
176
+ * @returns connectionState as ConnectionState
177
+ */
178
+ public get connectionState(): ConnectionState {
126
179
  return this.ctx.connectionState;
127
180
  }
128
181
 
182
+ /**
183
+ * Current configured connection URL
184
+ * @returns URL object
185
+ */
186
+ public get url(): URL {
187
+ return this.connectUrl;
188
+ }
189
+
129
190
  /**
130
191
  * 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
192
  * @returns Promise resolving to a SockConn connection
138
193
  */
139
- protected createConn(
140
- protocol: string,
141
- _hostname: string,
142
- _port?: number,
143
- _caCerts?: string[],
144
- _cert?: string,
145
- _key?: string,
146
- ): Promise<SockConn> {
194
+ protected createConn(): Promise<SockConn> {
147
195
  // if you need to support alternative connection types just
148
196
  // overload this method in your subclass
149
- throw new Error(`Unsupported protocol: ${protocol}`);
197
+ throw new Error(`Unsupported protocol: ${this.url.protocol}`);
150
198
  }
151
199
 
152
200
  /**
@@ -163,16 +211,12 @@ export class Client {
163
211
  let lastMessage = new Error();
164
212
  let tryConnect = true;
165
213
  while (tryConnect) {
166
- logger.debug(`${isReconnect ? "re" : ""}connecting, attempt ${attempt}`);
214
+ logger.debug(
215
+ isReconnect ? "reconnecting, attempt" : "connecting, attempt",
216
+ attempt,
217
+ );
167
218
  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
- );
219
+ const conn = await this.createConn();
176
220
  // if we get this far we have a connection
177
221
  tryConnect =
178
222
  (await this.ctx.handleConnection(conn, this.connectPacket)) &&
@@ -182,12 +226,9 @@ export class Client {
182
226
  this.connectPacket.clean = false;
183
227
  this.ctx.close();
184
228
  } 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;
229
+ const normalizedErr = normalizeError(err);
230
+ queueMicrotask(() => this.onError(normalizedErr));
231
+ lastMessage = normalizedErr;
191
232
  logger.debug({ lastMessage });
192
233
  }
193
234
 
@@ -212,8 +253,8 @@ export class Client {
212
253
  * @param params - Connection parameters
213
254
  * @returns Promise resolving to authentication result
214
255
  */
215
- connect(params: ConnectParameters = {}): Promise<TAuthenticationResult> {
216
- this.url = params?.url || this.url;
256
+ connect(params: ConnectParameters = {}): Promise<AuthenticationResult> {
257
+ this.connectUrl = params?.url || this.connectUrl;
217
258
  this.numberOfRetries = params.numberOfRetries || this.numberOfRetries;
218
259
  this.caCerts = params?.caCerts;
219
260
  this.cert = params?.cert;
@@ -230,7 +271,7 @@ export class Client {
230
271
  type: PacketType.connect,
231
272
  ...options,
232
273
  };
233
- const deferred = new Deferred<TAuthenticationResult>();
274
+ const deferred = new Deferred<AuthenticationResult>();
234
275
  this.ctx.unresolvedConnect = deferred;
235
276
  this.doConnect();
236
277
  return deferred.promise;
package/client/context.ts CHANGED
@@ -8,37 +8,55 @@ import {
8
8
  } from "./deps.ts";
9
9
  import type {
10
10
  AnyPacket,
11
+ AuthenticationResult,
11
12
  ConnectPacket,
12
- MemoryStore,
13
13
  PacketId,
14
14
  ProtocolLevel,
15
15
  PublishPacket,
16
+ ReasonCode,
16
17
  ReturnCodes,
17
18
  SockConn,
19
+ Store,
18
20
  SubscribePacket,
19
- TAuthenticationResult,
20
21
  UnsubscribePacket,
21
22
  } from "./deps.ts";
22
23
 
23
24
  import { handlePacket } from "./handlers/handlePacket.ts";
24
- import type { TConnectionState } from "./ConnectionState.ts";
25
25
  import { ConnectionState } from "./ConnectionState.ts";
26
26
  import type { Client } from "./client.ts";
27
27
  import { assert } from "../utils/assert.ts";
28
28
 
29
+ /**
30
+ * packets not allowed during authentication
31
+ */
32
+ function blockedDuringAuthentication(pktType: PacketType) {
33
+ return (
34
+ pktType === PacketType.publish ||
35
+ pktType === PacketType.subscribe ||
36
+ pktType === PacketType.unsubscribe
37
+ );
38
+ }
39
+
40
+ /** Possible results from authHandler */
41
+ export type AuthenticatedResult = {
42
+ reasonCode: ReasonCode;
43
+ reasonString?: string;
44
+ authData?: Uint8Array;
45
+ };
46
+
29
47
  export class Context {
30
48
  mqttConn?: MqttConn;
31
- #connectionState: TConnectionState;
49
+ #connectionState: ConnectionState;
32
50
  protocolLevel: ProtocolLevel;
33
51
  pingTimer?: Timer;
34
- unresolvedConnect?: Deferred<TAuthenticationResult>;
52
+ unresolvedConnect?: Deferred<AuthenticationResult>;
35
53
  unresolvedPublish: Map<PacketId, Deferred<void>>;
36
54
  unresolvedSubscribe: Map<PacketId, Deferred<ReturnCodes>>;
37
55
  unresolvedUnSubscribe: Map<PacketId, Deferred<void>>;
38
- store: MemoryStore;
56
+ store: Store;
39
57
  #client: Client;
40
58
 
41
- constructor(store: MemoryStore, client: Client) {
59
+ constructor(store: Store, client: Client) {
42
60
  this.#client = client;
43
61
  this.store = store;
44
62
  this.#connectionState = ConnectionState.offline;
@@ -48,11 +66,11 @@ export class Context {
48
66
  this.unresolvedUnSubscribe = new Map();
49
67
  }
50
68
 
51
- get connectionState(): TConnectionState {
69
+ get connectionState(): ConnectionState {
52
70
  return this.#connectionState;
53
71
  }
54
72
 
55
- set connectionState(state: TConnectionState) {
73
+ set connectionState(state: ConnectionState) {
56
74
  this.#connectionState = state;
57
75
  switch (state) {
58
76
  case "connected":
@@ -64,6 +82,25 @@ export class Context {
64
82
  }
65
83
  }
66
84
 
85
+ authHandler(
86
+ _ctx: Context,
87
+ authMethod: string,
88
+ authData: Uint8Array,
89
+ ): AuthenticatedResult | Promise<AuthenticatedResult> {
90
+ return this.#client.onAuth(authMethod, authData);
91
+ }
92
+
93
+ setPingTimer(interval: number) {
94
+ if (this.pingTimer) {
95
+ this.pingTimer.clear();
96
+ }
97
+ this.pingTimer = new Timer(
98
+ this.sendPing.bind(this),
99
+ interval * 1000,
100
+ true,
101
+ );
102
+ }
103
+
67
104
  async connect(packet: ConnectPacket) {
68
105
  this.connectionState = ConnectionState.connecting;
69
106
  if (packet.protocolLevel === MQTTLevel.unknown) {
@@ -73,16 +110,15 @@ export class Context {
73
110
  await this.mqttConn?.send(packet);
74
111
  const keepAlive = packet.keepAlive || 0;
75
112
  if (keepAlive > 0) {
76
- this.pingTimer = new Timer(
77
- this.sendPing.bind(this),
78
- keepAlive * 1000,
79
- true,
80
- );
113
+ this.setPingTimer(keepAlive);
81
114
  }
82
115
  }
83
116
 
84
117
  async disconnect() {
85
- if (this.connectionState !== ConnectionState.connected) {
118
+ if (
119
+ this.connectionState !== ConnectionState.connected &&
120
+ this.connectionState !== ConnectionState.authenticating
121
+ ) {
86
122
  throw "Not connected";
87
123
  }
88
124
  if (this.mqttConn) {
@@ -97,14 +133,29 @@ export class Context {
97
133
  }
98
134
 
99
135
  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;
136
+ logger.debug("client.ctx.send", this.#connectionState, { packet });
137
+ if (!this.mqttConn?.isClosed) {
138
+ if (this.connectionState === ConnectionState.connected) {
139
+ await this.mqttConn?.send(packet);
140
+ this.pingTimer?.reset();
141
+ return;
142
+ }
143
+ if (
144
+ this.connectionState === ConnectionState.connecting &&
145
+ packet.type === PacketType.auth
146
+ ) {
147
+ await this.mqttConn?.send(packet);
148
+ this.pingTimer?.reset();
149
+ return;
150
+ }
151
+ if (
152
+ this.connectionState === ConnectionState.authenticating &&
153
+ !blockedDuringAuthentication(packet.type)
154
+ ) {
155
+ await this.mqttConn?.send(packet);
156
+ this.pingTimer?.reset();
157
+ return;
158
+ }
108
159
  }
109
160
  logger.debug("not connected");
110
161
  this.pingTimer?.clear();
@@ -122,6 +173,7 @@ export class Context {
122
173
  connectPacket: ConnectPacket,
123
174
  ): Promise<boolean> {
124
175
  this.mqttConn = new MqttConn({ conn });
176
+ this.mqttConn.codecOpts.protocolLevel = connectPacket.protocolLevel;
125
177
  try {
126
178
  logger.debug("Send connect packet", connectPacket);
127
179
  await this.connect(connectPacket);
@@ -136,7 +188,7 @@ export class Context {
136
188
  `Caught something that is not an instance of Error: ${err}`,
137
189
  );
138
190
  queueMicrotask(() => this.#client.onError(err));
139
- logger.debug(`error ${err}`);
191
+ logger.debug("error", err);
140
192
  if (!this.mqttConn.isClosed) {
141
193
  this.mqttConn.close();
142
194
  }
@@ -164,7 +216,7 @@ export class Context {
164
216
  await this.send(packet);
165
217
  return;
166
218
  }
167
- packet.id = this.store.nextId();
219
+ packet.id = await this.store.nextId();
168
220
  this.store.pendingOutgoing.set(packet.id, packet);
169
221
  const deferred = new Deferred<void>();
170
222
  this.unresolvedPublish.set(packet.id, deferred);
@@ -173,7 +225,7 @@ export class Context {
173
225
  }
174
226
 
175
227
  async subscribe(packet: SubscribePacket): Promise<ReturnCodes> {
176
- packet.id = this.store.nextId();
228
+ packet.id = await this.store.nextId();
177
229
  this.store.pendingOutgoing.set(packet.id, packet);
178
230
  const deferred = new Deferred<ReturnCodes>();
179
231
  this.unresolvedSubscribe.set(packet.id, deferred);
@@ -182,7 +234,7 @@ export class Context {
182
234
  }
183
235
 
184
236
  async unsubscribe(packet: UnsubscribePacket): Promise<void> {
185
- packet.id = this.store.nextId();
237
+ packet.id = await this.store.nextId();
186
238
  this.store.pendingOutgoing.set(packet.id, packet);
187
239
  const deferred = new Deferred<void>();
188
240
  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,
@@ -16,9 +17,7 @@ export type {
16
17
  ReturnCodes,
17
18
  SubackPacket,
18
19
  SubscribePacket,
19
- TAuthenticationResult,
20
20
  Topic,
21
- TReasonCode,
22
21
  UnsubackPacket,
23
22
  UnsubscribePacket,
24
23
  } from "../mqttPacket/mod.ts";
@@ -31,11 +30,19 @@ export {
31
30
  MQTTLevel,
32
31
  PacketNameByType,
33
32
  PacketType,
33
+ ReasonCode,
34
34
  ReasonCodeByNumber,
35
35
  } from "../mqttPacket/mod.ts";
36
36
 
37
37
  export { MqttConn } from "../mqttConn/mqttConn.ts";
38
- export type { SockConn } from "../socket/socket.ts";
38
+ export type {
39
+ NetAddr,
40
+ SockAddr,
41
+ SockConn,
42
+ UnixAddr,
43
+ VsockAddr,
44
+ } from "../socket/socket.ts";
39
45
  export { Timer } from "../timer/timer.ts";
40
46
  export { BufferedAsyncIterable, Deferred, logger } from "../utils/mod.ts";
41
47
  export { MemoryStore } from "./store/memoryStore.ts";
48
+ export type { Store } 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
+ });