@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
@@ -1,35 +1,9 @@
1
- import type { Topic, TopicFilter } from "./types.ts";
2
-
3
- // deno-lint-ignore no-control-regex
4
- const invalidUTF8regEx = new RegExp(/\x00|\uFFFD/);
5
- // deno-lint-ignore no-control-regex
6
- const invalidTopicRegEx = new RegExp(/^$|\+|#|\x00|\uFFFD/);
7
- // deno-lint-ignore no-control-regex
8
- const invalidTopicFilterRegEx = new RegExp(/^$|#.|[^\/]\+|\+[^\/]|\x00|\uFFFD/);
9
-
10
1
  /**
11
- * check for invalid UTF-8 characters
12
- * @param value string to test
13
- * @returns true if the string contains invalid UTF-8 characters
2
+ * Checks for invalid UTF-8 characters or null bytes.
3
+ *
4
+ * @param value - The string to validate.
5
+ * @returns `true` if the string contains invalid UTF-8 sequences or a null byte, otherwise `false`.
14
6
  */
15
7
  export function invalidUTF8(value: string): boolean {
16
- return invalidUTF8regEx.test(value);
17
- }
18
-
19
- /**
20
- * check for invalid topic characters
21
- * @param value
22
- * @returns true if the topic is invalid
23
- */
24
- export function invalidTopic(value: Topic): boolean {
25
- return invalidTopicRegEx.test(value);
26
- }
27
-
28
- /**
29
- * check for invalid topic filter characters
30
- * @param value topic filter to test
31
- * @returns true if the topic filter is invalid
32
- */
33
- export function invalidTopicFilter(value: TopicFilter): boolean {
34
- return invalidTopicFilterRegEx.test(value);
8
+ return value.includes("\x00") || !value.isWellFormed();
35
9
  }
@@ -0,0 +1,322 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { PassThrough } from "node:stream";
4
+ import { Conn, type SockConn } from "./socket-node-stream.ts";
5
+
6
+ // Helper to create a mock SockConn using a PassThrough duplex stream
7
+ function createMockConn(): {
8
+ conn: Conn;
9
+ stream: PassThrough;
10
+ closeCalled: { count: number };
11
+ } {
12
+ const stream = new PassThrough();
13
+ const closeCalled = { count: 0 };
14
+
15
+ const sockConn: SockConn = {
16
+ stream,
17
+ close: () => {
18
+ closeCalled.count++;
19
+ },
20
+ remoteAddr: {
21
+ transport: "tcp",
22
+ hostname: "127.0.0.1",
23
+ port: 1883,
24
+ },
25
+ };
26
+
27
+ const conn = new Conn(sockConn);
28
+ return { conn, stream, closeCalled };
29
+ }
30
+
31
+ test("Conn.write - successfully writes data", async () => {
32
+ const { conn, stream } = createMockConn();
33
+ const data = new Uint8Array([0x01, 0x02, 0x03]);
34
+
35
+ const bytesWritten = await conn.write(data);
36
+ assert.equal(bytesWritten, data.length, "Number of written bytes matches");
37
+
38
+ const chunk = stream.read();
39
+ assert.deepStrictEqual(
40
+ new Uint8Array(chunk),
41
+ data,
42
+ "The stream received the correct data",
43
+ );
44
+
45
+ conn.close();
46
+ });
47
+
48
+ test("Conn.write - respects backpressure and waits for drain event", async () => {
49
+ const { conn, stream } = createMockConn();
50
+ const data = new Uint8Array([0x01, 0x02, 0x03]);
51
+
52
+ // Force stream.write to return false to simulate a full internal buffer (backpressure)
53
+ stream.write = () => false;
54
+
55
+ let writeResolved = false;
56
+ const writePromise = conn.write(data).then((bytes) => {
57
+ writeResolved = true;
58
+ return bytes;
59
+ });
60
+
61
+ // Yield execution shortly to ensure the promise hasn't resolved prematurely
62
+ await new Promise((resolve) => setImmediate(resolve));
63
+ assert.equal(
64
+ writeResolved,
65
+ false,
66
+ "Write promise should pend while backpressure is active",
67
+ );
68
+
69
+ // Emit the drain event to signal the buffer has cleared
70
+ stream.emit("drain");
71
+
72
+ const bytesWritten = await writePromise;
73
+ assert.equal(bytesWritten, data.length, "Resolves after drain event fires");
74
+ assert.equal(writeResolved, true);
75
+
76
+ conn.close();
77
+ });
78
+
79
+ test("Conn.read - reads exact number of bytes", async () => {
80
+ const { conn, stream } = createMockConn();
81
+ const data = new Uint8Array([10, 20, 30, 40, 50]);
82
+
83
+ stream.write(data);
84
+
85
+ const result = await conn.read(3);
86
+ assert.deepStrictEqual(
87
+ result,
88
+ new Uint8Array([10, 20, 30]),
89
+ "First 3 bytes match",
90
+ );
91
+
92
+ const restResult = await conn.read(2);
93
+ assert.deepStrictEqual(
94
+ restResult,
95
+ new Uint8Array([40, 50]),
96
+ "Remaining bytes match via the leftover buffer",
97
+ );
98
+
99
+ conn.close();
100
+ });
101
+
102
+ test("Conn.read - waits for async data (readable event)", async () => {
103
+ const { conn, stream } = createMockConn();
104
+
105
+ const readPromise = conn.read(2);
106
+
107
+ // Simulate network latency using setImmediate or setTimeout
108
+ await new Promise((resolve) => setTimeout(resolve, 10));
109
+ stream.write(new Uint8Array([0xAA, 0xBB]));
110
+
111
+ const result = await readPromise;
112
+ assert.deepStrictEqual(
113
+ result,
114
+ new Uint8Array([0xAA, 0xBB]),
115
+ "Data correctly received after async wait",
116
+ );
117
+
118
+ conn.close();
119
+ });
120
+
121
+ test("Conn.close - gracefully closes the connection and streams", async () => {
122
+ const { conn, stream, closeCalled } = createMockConn();
123
+
124
+ assert.equal(closeCalled.count, 0, "Closer has not been called yet");
125
+
126
+ conn.close();
127
+
128
+ assert.equal(closeCalled.count, 1, "Closer is called exactly once");
129
+ assert.equal(stream.destroyed, true, "The underlying stream is destroyed");
130
+
131
+ await assert.rejects(
132
+ conn.write(new Uint8Array([1])),
133
+ /Stream is closed or not writable/,
134
+ "Writing to a closed connection throws an error",
135
+ );
136
+
137
+ const readResult = await conn.read(1);
138
+ assert.equal(
139
+ readResult,
140
+ null,
141
+ "Reading from a closed connection returns null",
142
+ );
143
+ });
144
+
145
+ test("Conn.read - length less than 0 returns null", async () => {
146
+ const { conn } = createMockConn();
147
+
148
+ const result = await conn.read(-5);
149
+ assert.equal(result, null, "Reading with a negative length returns null");
150
+
151
+ conn.close();
152
+ });
153
+
154
+ test("Conn.read - length equal to 0 returns empty Uint8Array", async () => {
155
+ const { conn } = createMockConn();
156
+
157
+ const result = await conn.read(0);
158
+ assert.deepStrictEqual(
159
+ result,
160
+ new Uint8Array(0),
161
+ "Reading 0 bytes returns an empty Uint8Array",
162
+ );
163
+
164
+ conn.close();
165
+ });
166
+
167
+ test("Conn.read - stream errors while waiting for data (returns null)", async () => {
168
+ const { conn, stream } = createMockConn();
169
+
170
+ // Prevent Node.js from crashing due to an unhandled stream error during test execution
171
+ stream.on("error", () => {});
172
+
173
+ const readPromise = conn.read(5);
174
+
175
+ // Emit error event to invoke internal error tracking state
176
+ stream.emit("error", new Error("Network failure"));
177
+
178
+ const result = await readPromise;
179
+ assert.equal(
180
+ result,
181
+ null,
182
+ "Returns null when the stream errors out during an active read",
183
+ );
184
+
185
+ conn.close();
186
+ });
187
+
188
+ test("Conn.read - chunk is larger than requested (populates leftover)", async () => {
189
+ const { conn, stream } = createMockConn();
190
+ const largeChunk = new Uint8Array([1, 2, 3, 4, 5]);
191
+
192
+ stream.write(largeChunk);
193
+
194
+ const result1 = await conn.read(2);
195
+ assert.deepStrictEqual(
196
+ result1,
197
+ new Uint8Array([1, 2]),
198
+ "Returns the exact requested chunk size",
199
+ );
200
+
201
+ const result2 = await conn.read(2);
202
+ assert.deepStrictEqual(
203
+ result2,
204
+ new Uint8Array([3, 4]),
205
+ "Returns the next bytes from the leftover buffer",
206
+ );
207
+
208
+ const result3 = await conn.read(1);
209
+ assert.deepStrictEqual(
210
+ result3,
211
+ new Uint8Array([5]),
212
+ "Returns the last remaining byte from leftover",
213
+ );
214
+
215
+ conn.close();
216
+ });
217
+
218
+ test("Conn.read - partial leftover is not enough (combines leftover and new stream chunk)", async () => {
219
+ const { conn, stream } = createMockConn();
220
+
221
+ // 1. Write 3 bytes and read 2 (leaving 1 byte [0x03] in leftover)
222
+ stream.write(new Uint8Array([0x01, 0x02, 0x03]));
223
+ await conn.read(2);
224
+
225
+ // 2. Write new data to the stream
226
+ stream.write(new Uint8Array([0x04, 0x05]));
227
+
228
+ // 3. Request 3 bytes (needs 1 from leftover + 2 from stream)
229
+ const result = await conn.read(3);
230
+ assert.deepStrictEqual(
231
+ result,
232
+ new Uint8Array([0x03, 0x04, 0x05]),
233
+ "Combines leftover data with newly arrived stream data",
234
+ );
235
+
236
+ conn.close();
237
+ });
238
+
239
+ test("Conn.write - rejects immediately if stream.writable is false", async () => {
240
+ const { conn, stream } = createMockConn();
241
+
242
+ Object.defineProperty(stream, "writable", { value: false });
243
+
244
+ await assert.rejects(
245
+ conn.write(new Uint8Array([1, 2, 3])),
246
+ /Stream is closed or not writable/,
247
+ "Rejects immediately when stream.writable is false",
248
+ );
249
+
250
+ conn.close();
251
+ });
252
+
253
+ test("Conn.read - fulfilled entirely from leftover buffer (skips while loop)", async () => {
254
+ const { conn, stream } = createMockConn();
255
+ const data = new Uint8Array([10, 20, 30, 40, 50]);
256
+
257
+ // 1. Populate the leftover buffer by reading less than what was written
258
+ stream.write(data);
259
+ await conn.read(2); // Leaves [30, 40, 50] in leftover
260
+
261
+ // 2. Request an amount that can be fully satisfied by the leftover buffer
262
+ const result = await conn.read(2);
263
+ assert.deepStrictEqual(
264
+ result,
265
+ new Uint8Array([30, 40]),
266
+ "Successfully fulfilled entirely from the leftover buffer",
267
+ );
268
+
269
+ // 3. Verify the remaining byte is still preserved
270
+ const finalResult = await conn.read(1);
271
+ assert.deepStrictEqual(
272
+ finalResult,
273
+ new Uint8Array([50]),
274
+ "The remaining byte in leftover is still accessible",
275
+ );
276
+
277
+ conn.close();
278
+ });
279
+
280
+ test("Conn - handles unexpected stream close event from underlying resource", () => {
281
+ const { conn, stream } = createMockConn();
282
+
283
+ // Initially, the connection should not be marked as closed
284
+ assert.equal(conn["closed"], false, "Connection is open initially");
285
+
286
+ // Simulate the underlying socket/stream closing unexpectedly from the remote side
287
+ stream.emit("close");
288
+
289
+ // Verify that the permanent 'close' listener was triggered and updated the internal state
290
+ assert.equal(
291
+ conn["closed"],
292
+ true,
293
+ "Connection internally updates to closed when stream emits close",
294
+ );
295
+
296
+ // Clean up to ensure resources are disposed
297
+ conn.close();
298
+ });
299
+
300
+ test("Conn.write - rejects the promise if stream.write invokes the callback with an error", async () => {
301
+ const { conn, stream } = createMockConn();
302
+ const data = new Uint8Array([1, 2, 3]);
303
+
304
+ // Simulate a write error by overriding stream.write
305
+ // It forces the callback to be invoked with an Error object
306
+ stream.write = (_chunk, callback) => {
307
+ if (typeof callback === "function") {
308
+ // Execute the callback with an error asynchronously, mimicking Node.js behavior
309
+ setImmediate(() => callback(new Error("Write pipeline failure")));
310
+ }
311
+ return false;
312
+ };
313
+
314
+ // Verify that the conn.write Promise rejects with the exact error
315
+ await assert.rejects(
316
+ conn.write(data),
317
+ /Write pipeline failure/,
318
+ "The write promise should reject when the stream callback receives an error",
319
+ );
320
+
321
+ conn.close();
322
+ });
@@ -0,0 +1,174 @@
1
+ import type { Duplex } from "node:stream";
2
+
3
+ export type SockAddr = NetAddr | UnixAddr | VsockAddr;
4
+ export interface NetAddr {
5
+ transport: "tcp" | "udp";
6
+ hostname: string;
7
+ port: number;
8
+ }
9
+ export interface UnixAddr {
10
+ transport: "unix" | "unixpacket";
11
+ path: string;
12
+ }
13
+ export interface VsockAddr {
14
+ transport: "vsock";
15
+ cid: number;
16
+ port: number;
17
+ }
18
+
19
+ export type SockConn = {
20
+ stream: Duplex;
21
+ close: () => void;
22
+ localAddr?: SockAddr;
23
+ remoteAddr?: SockAddr;
24
+ };
25
+
26
+ export class Conn {
27
+ private stream: Duplex;
28
+ private closed: boolean;
29
+ private closer: () => void;
30
+ public remoteAddr: SockAddr | undefined;
31
+ private leftover: Uint8Array = new Uint8Array(0);
32
+
33
+ // Store bound event listeners so we can cleanly remove them later
34
+ private onStreamClose = () => {
35
+ this.closed = true;
36
+ };
37
+ private onStreamError = () => {
38
+ this.closed = true;
39
+ };
40
+
41
+ constructor(sockConn: SockConn) {
42
+ this.stream = sockConn.stream;
43
+ this.closed = false;
44
+ this.closer = sockConn.close;
45
+ this.remoteAddr = sockConn.remoteAddr;
46
+
47
+ // Attach listeners to update internal state on stream termination
48
+ this.stream.on("close", this.onStreamClose);
49
+ this.stream.on("error", this.onStreamError);
50
+ }
51
+
52
+ async read(length: number): Promise<Uint8Array | null> {
53
+ if (this.closed || length < 0) {
54
+ return null;
55
+ }
56
+
57
+ if (length === 0) {
58
+ return new Uint8Array(0);
59
+ }
60
+
61
+ const result = new Uint8Array(length);
62
+ let bytesAccumulated = 0;
63
+
64
+ // 1. Process leftover data from the previous read operation
65
+ if (this.leftover.byteLength > 0) {
66
+ const take = Math.min(this.leftover.byteLength, length);
67
+ result.set(this.leftover.subarray(0, take), bytesAccumulated);
68
+ bytesAccumulated += take;
69
+ this.leftover = this.leftover.subarray(take);
70
+ }
71
+
72
+ // 2. Loop until the requested number of bytes is accumulated
73
+ while (bytesAccumulated < length) {
74
+ if (this.closed || !this.stream.readable) {
75
+ break;
76
+ }
77
+
78
+ const chunk = this.stream.read();
79
+ if (chunk === null) {
80
+ await new Promise<void>((resolve) => {
81
+ const cleanup = () => {
82
+ this.stream.off("readable", onEvent);
83
+ this.stream.off("end", onEvent);
84
+ this.stream.off("error", onEvent);
85
+ this.stream.off("close", onEvent);
86
+ };
87
+ const onEvent = () => {
88
+ cleanup();
89
+ resolve();
90
+ };
91
+
92
+ this.stream.on("readable", onEvent);
93
+ this.stream.on("end", onEvent);
94
+ this.stream.on("error", onEvent);
95
+ this.stream.on("close", onEvent);
96
+ });
97
+
98
+ continue;
99
+ }
100
+
101
+ // 3. Process the retrieved chunk
102
+ const chunkLength = chunk.byteLength;
103
+ const needed = length - bytesAccumulated;
104
+
105
+ if (chunkLength <= needed) {
106
+ result.set(chunk, bytesAccumulated);
107
+ bytesAccumulated += chunkLength;
108
+ } else {
109
+ result.set(chunk.subarray(0, needed), bytesAccumulated);
110
+ bytesAccumulated += needed;
111
+ this.leftover = chunk.subarray(needed);
112
+ }
113
+ }
114
+
115
+ if (bytesAccumulated < length) {
116
+ return null;
117
+ }
118
+
119
+ return result;
120
+ }
121
+
122
+ write(data: Uint8Array): Promise<number> {
123
+ if (this.closed || !this.stream.writable) {
124
+ return Promise.reject(new Error("Stream is closed or not writable"));
125
+ }
126
+
127
+ return new Promise((resolve, reject) => {
128
+ // 1. Fire the write command and catch any immediate/async errors via the callback
129
+ const canWriteMore = this.stream.write(data, (err) => {
130
+ if (err) {
131
+ reject(err);
132
+ }
133
+ });
134
+
135
+ // 2. Determine when to resolve based on the return value of write()
136
+ if (canWriteMore) {
137
+ // If the buffer is not full, we can resolve immediately
138
+ resolve(data.length);
139
+ } else {
140
+ // If backpressure is triggered, we must wait for the 'drain' event
141
+ this.stream.once("drain", () => {
142
+ resolve(data.length);
143
+ });
144
+ }
145
+ });
146
+ }
147
+
148
+ close() {
149
+ if (!this.closed) {
150
+ this.closed = true;
151
+
152
+ // Clean up permanent event listeners to prevent memory leaks
153
+ this.stream.off("close", this.onStreamClose);
154
+ this.stream.off("error", this.onStreamError);
155
+
156
+ // Safely destroy the stream first, then trigger the closer callback
157
+ try {
158
+ this.stream.destroy();
159
+ // deno-coverage-ignore
160
+ } catch (_) {
161
+ // Suppress stream destruction errors
162
+ // deno-coverage-ignore
163
+ }
164
+
165
+ try {
166
+ this.closer();
167
+ // deno-coverage-ignore
168
+ } catch (_) {
169
+ // Prevent closer failures from crashing the thread
170
+ // deno-coverage-ignore
171
+ }
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,70 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+ import { getFileData, TcpClient } from "./tcpClient.ts";
7
+
8
+ // most client testing is already done in tcpServer.test.ts
9
+
10
+ test("Test getFileData - valid file, empty file and undefined", async () => {
11
+ // Create a unique temporary directory using native NodeJS path/fs utilities
12
+ const tempDir = await mkdtemp(join(tmpdir(), "mqtt-client-test-"));
13
+
14
+ const validFilePath = join(tempDir, "valid.txt");
15
+ const emptyFilePath = join(tempDir, "empty.txt");
16
+ const testContent = "Hello MQTT World!";
17
+
18
+ try {
19
+ // 1. Test with a valid file containing data
20
+ await writeFile(validFilePath, testContent, "utf-8");
21
+ const result = await getFileData(validFilePath);
22
+ assert.strictEqual(
23
+ result,
24
+ testContent,
25
+ "Should return the correct content of the file",
26
+ );
27
+
28
+ // 2. Test with an empty file
29
+ await writeFile(emptyFilePath, "", "utf-8");
30
+ const emptyResult = await getFileData(emptyFilePath);
31
+ assert.strictEqual(
32
+ emptyResult,
33
+ undefined,
34
+ "Should return undefined if the file is empty",
35
+ );
36
+ } finally {
37
+ // Clean up the temporary directory and all its contents
38
+ await rm(tempDir, { recursive: true, force: true });
39
+ }
40
+
41
+ // 3. Test with undefined filename
42
+ const undefinedResult = await getFileData(undefined);
43
+ assert.strictEqual(
44
+ undefinedResult,
45
+ undefined,
46
+ "Should return undefined immediately if filename is undefined",
47
+ );
48
+ });
49
+
50
+ test("Test createConn - unsupported protocol", async () => {
51
+ const client = new TcpClient();
52
+
53
+ // Use an unsupported protocol like 'ftp://' to trigger the throw in createConn
54
+ const invalidParams = {
55
+ url: new URL("ftp://localhost:1883"),
56
+ numberOfRetries: 0,
57
+ };
58
+
59
+ // Assert that connect rejects with the specific "Unsupported protocol" error
60
+ await assert.rejects(
61
+ async () => {
62
+ await client.connect(invalidParams);
63
+ },
64
+ {
65
+ name: "Error",
66
+ message: "Unsupported protocol: ftp:",
67
+ },
68
+ "Should throw an error when an unsupported protocol is provided",
69
+ );
70
+ });
package/node/tcpClient.ts CHANGED
@@ -65,9 +65,10 @@ export class TcpClient extends Client {
65
65
  const opts = {
66
66
  host: hostname,
67
67
  port,
68
- secureContext: (ca || key || cert)
69
- ? tls.createSecureContext({ ca, cert, key })
70
- : undefined,
68
+ ca,
69
+ key,
70
+ cert,
71
+ minVersion: "TLSv1.3" as const,
71
72
  };
72
73
  logger.debug({ hostname, port, ca, cert });
73
74
  return new Promise((resolve, reject) => {
@@ -82,16 +83,16 @@ export class TcpClient extends Client {
82
83
  });
83
84
  }
84
85
 
85
- protected override createConn(
86
- protocol: string,
87
- hostname: string,
88
- port?: number,
89
- caCerts?: string[],
90
- ): Promise<SockConn> {
91
- // if you need to support alternative connection types just
92
- // overload this method in your subclass
86
+ // overload createConn from the base client class
87
+ protected override createConn(): Promise<SockConn> {
88
+ const { protocol, hostname, port: portStr } = this.connectUrl;
89
+ const port = Number(portStr);
90
+ const caCerts = this.caCerts;
91
+ const cert = this.cert;
92
+ const key = this.key;
93
+
93
94
  if (protocol === "mqtts:") {
94
- return this.connectMQTTS(hostname, port, caCerts);
95
+ return this.connectMQTTS(hostname, port, caCerts, cert, key);
95
96
  }
96
97
  if (protocol === "mqtt:") {
97
98
  return this.connectMQTT(hostname, port);