@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
@@ -0,0 +1,404 @@
1
+ import type { MqttConn } from "../mqttConn/mqttConn.ts";
2
+ import { withTimeout } from "./timers.ts";
3
+ import { delay } from "./timers.ts";
4
+ import { MQTTLevel, PacketType, ReasonCode } from "../mqttPacket/mod.ts";
5
+ import type {
6
+ AnyPacket,
7
+ AuthPacket,
8
+ ConnackPacket,
9
+ ConnectPacket,
10
+ DisconnectProperties,
11
+ ProtocolLevel,
12
+ PublishProperties,
13
+ QoS,
14
+ Topic,
15
+ TopicFilter,
16
+ UnsubackPacket,
17
+ } from "../mqttPacket/mod.ts";
18
+ import type {
19
+ ConnackPacketV4,
20
+ ConnackPacketV5,
21
+ } from "../mqttPacket/connack.ts";
22
+ import type { ConnectPacketV5 } from "../mqttPacket/connect.ts";
23
+ import assert from "node:assert/strict";
24
+ import { logger } from "../utils/mod.ts";
25
+
26
+ const txtEncoder = new TextEncoder();
27
+
28
+ let clientIdCounter = 1;
29
+
30
+ const PINGREQ_PACKET: AnyPacket = Object.freeze({
31
+ type: PacketType.pingreq,
32
+ protocolLevel: MQTTLevel.v4,
33
+ });
34
+
35
+ export function nextPacketWithTimeOut(
36
+ conn: MqttConn,
37
+ timeoutMs: number,
38
+ ): Promise<IteratorResult<AnyPacket> | null> {
39
+ return withTimeout(conn.next(), timeoutMs);
40
+ }
41
+
42
+ export async function checkNoPacket(mqttConn: MqttConn, timeoutMs = 10) {
43
+ const result = await nextPacketWithTimeOut(mqttConn, timeoutMs);
44
+ assert.equal(result, null, "no packet received");
45
+ }
46
+
47
+ async function baseConnect(mqttConn: MqttConn, {
48
+ level = MQTTLevel.v4 as ProtocolLevel,
49
+ clientId = `testClient-${clientIdCounter++}`,
50
+ username = "IoTester_1",
51
+ password = "strong_password",
52
+ keepAlive = 0,
53
+ clean = true,
54
+ will = undefined as ConnectPacket["will"],
55
+ properties = {},
56
+ checkAck = true,
57
+ } = {}): Promise<ConnackPacket | AuthPacket> {
58
+ mqttConn.codecOpts.protocolLevel = level;
59
+ const connectPacket: ConnectPacket = {
60
+ type: PacketType.connect,
61
+ protocolName: "MQTT",
62
+ protocolLevel: level,
63
+ clientId,
64
+ clean,
65
+ keepAlive,
66
+ username,
67
+ password: password !== "" ? txtEncoder.encode(password) : undefined,
68
+ will,
69
+ };
70
+ if (connectPacket.protocolLevel === MQTTLevel.v5) {
71
+ connectPacket.properties = properties;
72
+ }
73
+ logger.verbose("connectHelper: sending connect");
74
+ logger.debug({ connectPacket });
75
+
76
+ mqttConn.send(connectPacket);
77
+ const { value: connack } = await mqttConn.next();
78
+ logger.verbose("connectHelper: connack", connack);
79
+ if (checkAck) {
80
+ assert.deepStrictEqual(
81
+ connack.type,
82
+ PacketType.connack,
83
+ "Expected CONNACK",
84
+ );
85
+ }
86
+ mqttConn.codecOpts.protocolLevel = level;
87
+ return connack;
88
+ }
89
+
90
+ export async function connect(mqttConn: MqttConn, {
91
+ level = MQTTLevel.v4,
92
+ clientId = `testClient-${clientIdCounter++}`,
93
+ username = "IoTester_1",
94
+ password = "strong_password",
95
+ keepAlive = 0,
96
+ clean = true,
97
+ will = undefined as ConnectPacket["will"],
98
+ checkAck = true,
99
+ } = {}): Promise<ConnackPacketV4> {
100
+ return await baseConnect(mqttConn, {
101
+ level,
102
+ clientId,
103
+ username,
104
+ password,
105
+ keepAlive,
106
+ clean,
107
+ will,
108
+ checkAck,
109
+ }) as ConnackPacketV4;
110
+ }
111
+
112
+ export async function connect5(mqttConn: MqttConn, {
113
+ clientId = `testClient-${clientIdCounter++}`,
114
+ username = "IoTester_1",
115
+ password = "strong_password",
116
+ keepAlive = 0,
117
+ clean = true,
118
+ will = undefined as ConnectPacket["will"],
119
+ properties = {} as ConnectPacketV5["properties"],
120
+ checkAck = true,
121
+ } = {}): Promise<ConnackPacketV5> {
122
+ return await baseConnect(mqttConn, {
123
+ level: MQTTLevel.v5,
124
+ clientId,
125
+ username,
126
+ password,
127
+ keepAlive,
128
+ clean,
129
+ will,
130
+ properties,
131
+ checkAck,
132
+ }) as ConnackPacketV5;
133
+ }
134
+
135
+ export async function auth(mqttConn: MqttConn, {
136
+ reasonCode = ReasonCode.continueAuthentication,
137
+ authMethod = "SCRAM-SHA-256",
138
+ authData = new Uint8Array([1]),
139
+ noMethod = false,
140
+ noData = false,
141
+ } = {}) {
142
+ const authPacket: AuthPacket = {
143
+ type: PacketType.auth,
144
+ protocolLevel: 5,
145
+ reasonCode,
146
+ properties: {
147
+ authenticationMethod: noMethod ? undefined : authMethod,
148
+ authenticationData: noData ? undefined : authData,
149
+ },
150
+ };
151
+ await mqttConn.send(authPacket);
152
+ const { value } = await mqttConn.next();
153
+ return value;
154
+ }
155
+
156
+ export async function subscribe(
157
+ subscriber: MqttConn,
158
+ subscriptions: {
159
+ topicFilter: TopicFilter;
160
+ qos: QoS;
161
+ }[],
162
+ {
163
+ id = 24,
164
+ checkAcks = true,
165
+ } = {},
166
+ ) {
167
+ const subscribePacket = {
168
+ type: PacketType.subscribe,
169
+ protocolLevel: MQTTLevel.v4,
170
+ id,
171
+ subscriptions,
172
+ };
173
+
174
+ subscriber.send(subscribePacket);
175
+
176
+ const { value: packet } = await subscriber.next();
177
+ if (checkAcks) {
178
+ assert.equal(packet.type, PacketType.suback, "Expected SUBACK");
179
+ assert.equal(packet.id, id, "SUBACK ID should match SUBSCRIBE ID");
180
+ const results = packet.returnCodes || packet.reasonCodes;
181
+ assert.equal(results.length, subscriptions.length, "ACK count match");
182
+ for (let i = 0; i < results.length; i++) {
183
+ assert.equal(results[i], subscriptions[i].qos);
184
+ }
185
+ }
186
+ return packet;
187
+ }
188
+
189
+ export async function subscribe5(
190
+ subscriber: MqttConn,
191
+ subscriptions: {
192
+ topicFilter: TopicFilter;
193
+ qos: QoS;
194
+ noLocal?: boolean;
195
+ retainAsPublished?: boolean;
196
+ retainHandling?: number;
197
+ }[],
198
+ {
199
+ id = 24,
200
+ subscriptionIdentifier = undefined as number | undefined,
201
+ checkAcks = true,
202
+ } = {},
203
+ ) {
204
+ const properties = subscriptionIdentifier !== undefined
205
+ ? { subscriptionIdentifier }
206
+ : {};
207
+
208
+ const subscribePacket = {
209
+ type: PacketType.subscribe,
210
+ protocolLevel: MQTTLevel.v5,
211
+ id,
212
+ subscriptions,
213
+ properties,
214
+ };
215
+
216
+ subscriber.send(subscribePacket);
217
+ logger.debug("subscribe helper: sent subscription request");
218
+
219
+ const { value: packet } = await subscriber.next();
220
+ assert.equal(packet.type, PacketType.suback, "Expected SUBACK");
221
+ assert.equal(packet.id, id, "SUBACK ID should match SUBSCRIBE ID");
222
+ logger.debug("subscribe helper: received SubAck");
223
+
224
+ if (checkAcks) {
225
+ const results = packet.returnCodes || packet.reasonCodes;
226
+ assert.equal(results.length, subscriptions.length, "ACK count match");
227
+ for (let i = 0; i < results.length; i++) {
228
+ assert.equal(results[i], subscriptions[i].qos);
229
+ }
230
+ }
231
+ logger.debug("subscribe helper: acks ok");
232
+ return packet;
233
+ }
234
+
235
+ export async function unsubscribe(
236
+ subscriber: MqttConn,
237
+ topicFilters: TopicFilter[],
238
+ {
239
+ level = MQTTLevel.v4,
240
+ id = 24,
241
+ } = {},
242
+ ) {
243
+ subscriber.send({
244
+ type: PacketType.unsubscribe,
245
+ protocolLevel: level,
246
+ id,
247
+ topicFilters,
248
+ });
249
+ const { value: packet } = await subscriber.next();
250
+ assert.equal(packet.type, PacketType.unsuback, "Expected UNSUBACK");
251
+ assert.equal(packet.protocolLevel, level, "received expected level");
252
+ assert.equal(packet.id, id, "UNSUBACK ID should match UNSUBSCRIBE ID");
253
+ }
254
+
255
+ export async function unsubscribe5(
256
+ subscriber: MqttConn,
257
+ topicFilters: TopicFilter[],
258
+ { id = 24 } = {},
259
+ ): Promise<UnsubackPacket> {
260
+ subscriber.send({
261
+ type: PacketType.unsubscribe,
262
+ protocolLevel: MQTTLevel.v5,
263
+ id,
264
+ topicFilters,
265
+ });
266
+ const { value: packet } = await subscriber.next();
267
+ assert.equal(packet.type, PacketType.unsuback, "Expected UNSUBACK");
268
+ assert.equal(packet.protocolLevel, MQTTLevel.v5, "received expected level");
269
+ assert.equal(packet.id, id, "UNSUBACK ID should match UNSUBSCRIBE ID");
270
+ return packet;
271
+ }
272
+
273
+ export async function publish(
274
+ publisher: MqttConn,
275
+ topic: Topic,
276
+ qos: QoS,
277
+ {
278
+ level = MQTTLevel.v4 as ProtocolLevel,
279
+ id = 22,
280
+ payload = "payload",
281
+ retain = false,
282
+ properties = {},
283
+ checkAcks = true,
284
+ } = {},
285
+ ) {
286
+ const encodedPayload = txtEncoder.encode(payload);
287
+
288
+ await publisher.send({
289
+ type: PacketType.publish,
290
+ protocolLevel: level,
291
+ id,
292
+ topic,
293
+ qos,
294
+ payload: encodedPayload,
295
+ retain,
296
+ properties,
297
+ });
298
+ logger.debug("publish helper: sent publish");
299
+ if (!checkAcks || qos === 0) return;
300
+
301
+ const { value: ackPacket } = await publisher.next();
302
+ const expectedAckType = qos === 1 ? PacketType.puback : PacketType.pubrec;
303
+ assert.equal(ackPacket.type, expectedAckType, "received expected ack");
304
+ assert.equal(ackPacket.protocolLevel, level, "received expected level");
305
+ assert.equal(ackPacket.id, id, "packetid matches");
306
+ logger.debug("publish helper: received pubAck");
307
+
308
+ if (qos === 1) return ackPacket;
309
+
310
+ publisher.send({
311
+ type: PacketType.pubrel,
312
+ protocolLevel: level,
313
+ id,
314
+ });
315
+
316
+ const { value: compPacket } = await publisher.next();
317
+ assert.equal(
318
+ compPacket.type,
319
+ PacketType.pubcomp,
320
+ "received expected pubcomp",
321
+ );
322
+ assert.equal(compPacket.id, id, "packetid of pubcomp matches");
323
+ }
324
+
325
+ export function publish5(
326
+ publisher: MqttConn,
327
+ topic: Topic,
328
+ qos: QoS,
329
+ opts?: {
330
+ id?: number;
331
+ payload?: string;
332
+ retain?: boolean;
333
+ properties?: PublishProperties;
334
+ checkAcks?: boolean;
335
+ },
336
+ ) {
337
+ return publish(
338
+ publisher,
339
+ topic,
340
+ qos,
341
+ Object.assign({}, opts, { level: MQTTLevel.v5 }),
342
+ );
343
+ }
344
+
345
+ export async function disconnect(
346
+ mqttConn: MqttConn,
347
+ { level = MQTTLevel.v4 } = {},
348
+ ) {
349
+ mqttConn.send({
350
+ type: PacketType.disconnect,
351
+ protocolLevel: level,
352
+ });
353
+ await mqttConn.next();
354
+
355
+ assert.strictEqual(
356
+ mqttConn.isClosed,
357
+ true,
358
+ "Expected connection to be closed",
359
+ );
360
+ }
361
+
362
+ export async function disconnect5(mqttConn: MqttConn, opts?: {
363
+ reasonCode?: number;
364
+ properties?: DisconnectProperties;
365
+ }) {
366
+ const packet = {
367
+ type: PacketType.disconnect,
368
+ protocolLevel: MQTTLevel.v5,
369
+ reasonCode: opts?.reasonCode,
370
+ properties: opts?.properties,
371
+ };
372
+
373
+ mqttConn.send(packet);
374
+ await mqttConn.next();
375
+ await mqttConn.next();
376
+
377
+ assert.strictEqual(
378
+ mqttConn.isClosed,
379
+ true,
380
+ "Expected connection to be closed",
381
+ );
382
+ }
383
+
384
+ export async function ping(mqttConn: MqttConn) {
385
+ mqttConn.send(PINGREQ_PACKET);
386
+ const { value: pingres } = await mqttConn.next();
387
+ assert.strictEqual(pingres.type, PacketType.pingres);
388
+ }
389
+
390
+ export async function receiveMessages(conn: MqttConn) {
391
+ const received = Array.fromAsync(conn);
392
+ await delay(10);
393
+ await disconnect(conn);
394
+ const messages = await received;
395
+ return messages;
396
+ }
397
+
398
+ export async function receiveMessages5(conn: MqttConn) {
399
+ const received = Array.fromAsync(conn);
400
+ await delay(10);
401
+ await disconnect5(conn);
402
+ const messages = await received;
403
+ return messages;
404
+ }
@@ -0,0 +1,98 @@
1
+ import { ReasonCode } from "../server/mod.ts";
2
+ import { logger } from "../utils/mod.ts";
3
+ import type {
4
+ AuthenticatedResult,
5
+ Context,
6
+ ShareName,
7
+ Topic,
8
+ } from "../server/mod.ts";
9
+
10
+ const utf8Decoder = new TextDecoder();
11
+ const userTable = new Map();
12
+ userTable.set("IoTester_1", "strong_password");
13
+ userTable.set("IoTester_2", "strong_password");
14
+ const strictUsername = new RegExp(/^[a-zA-Z0-9]{0,23}$/);
15
+
16
+ function isAuthenticated(
17
+ _ctx: Context,
18
+ clientId: string,
19
+ username: string,
20
+ password: Uint8Array,
21
+ ): AuthenticatedResult {
22
+ const pwd = utf8Decoder.decode(password);
23
+ logger.debug(
24
+ `Verifying authentication of client '${clientId}' with username '${username}'`,
25
+ );
26
+
27
+ if (!userTable.has(username)) {
28
+ if (!strictUsername.test(username)) {
29
+ return { reasonCode: ReasonCode.success };
30
+ }
31
+ }
32
+
33
+ const pass = userTable.get(username);
34
+ if (pwd === pass) {
35
+ return { reasonCode: ReasonCode.success };
36
+ }
37
+ return {
38
+ reasonCode: ReasonCode.badUserNameOrPassword,
39
+ reasonString: "Bad username or password",
40
+ };
41
+ }
42
+
43
+ function processAuth(
44
+ _ctx: Context,
45
+ _clientId: string,
46
+ _authMethod: string,
47
+ _authData: Uint8Array,
48
+ ) {
49
+ return {
50
+ reasonCode: ReasonCode.badAuthenticationMethod,
51
+ reasonString: "Authentication method not supported",
52
+ };
53
+ }
54
+
55
+ function isAuthorizedToPublish(ctx: Context, topic: Topic): boolean {
56
+ logger.debug(
57
+ "Checking authorization of client",
58
+ ctx.clientId,
59
+ "to publish on topic",
60
+ topic,
61
+ );
62
+ if (topic === "topic/unauthorized") {
63
+ return false;
64
+ }
65
+ return true;
66
+ }
67
+ function isAuthorizedToSubscribe(
68
+ ctx: Context,
69
+ topic: Topic,
70
+ shareName: ShareName,
71
+ ): boolean {
72
+ logger.debug(
73
+ "Checking authorization of client",
74
+ ctx.clientId,
75
+ "to subscribe to topic",
76
+ topic,
77
+ "using shareName",
78
+ shareName,
79
+ );
80
+ if (topic === "topic/unauthorized") {
81
+ return false;
82
+ }
83
+ return true;
84
+ }
85
+
86
+ export const handlers = {
87
+ isAuthenticated,
88
+ processAuth,
89
+ isAuthorizedToPublish,
90
+ isAuthorizedToSubscribe,
91
+ };
92
+
93
+ export function isAuthenticatedBroker(
94
+ ctx: Context,
95
+ ): AuthenticatedResult {
96
+ ctx.isBroker = true;
97
+ return { reasonCode: ReasonCode.success };
98
+ }
@@ -6,6 +6,9 @@
6
6
  // This will also work on Deno:
7
7
  // https://docs.deno.com/api/node/timers/#namespace_setimmediate
8
8
  import { setImmediate } from "node:timers";
9
+ import { setTimeout as delay } from "node:timers/promises";
10
+ import type { AnyPacket } from "../mqttPacket/mod.ts";
11
+ export { delay };
9
12
 
10
13
  let taskCounter = 0;
11
14
 
@@ -49,3 +52,14 @@ export const resolveAsap = (): Promise<void> => {
49
52
  export const resolveNextTick = (): Promise<void> => {
50
53
  return new Promise((resolve) => setImmediate(resolve));
51
54
  };
55
+
56
+ /**
57
+ * Races a promise to test timeouts
58
+ */
59
+ export function withTimeout(
60
+ promise: Promise<IteratorResult<AnyPacket>>,
61
+ timeoutMs: number,
62
+ ): Promise<IteratorResult<AnyPacket> | null> {
63
+ const timeoutPromise = delay(timeoutMs, null);
64
+ return Promise.race([promise, timeoutPromise]);
65
+ }
@@ -0,0 +1,171 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert";
3
+ import { createWebStreamPair } from "./webStreamPair.ts";
4
+
5
+ test("Echo server shuts down cleanly when client closes input", async () => {
6
+ const { input, output } = createWebStreamPair();
7
+
8
+ const echoPromise = output.readable.pipeTo(output.writable);
9
+
10
+ const writer = input.writable.getWriter();
11
+ const reader = input.readable.getReader();
12
+
13
+ // Client closes their side
14
+ await writer.close();
15
+
16
+ // The echo server's pipeTo should resolve and finish successfully
17
+ await assert.doesNotReject(echoPromise);
18
+
19
+ // The client's reader should now receive the end-of-stream signal
20
+ const { done } = await reader.read();
21
+ assert.strictEqual(done, true);
22
+
23
+ writer.releaseLock();
24
+ reader.releaseLock();
25
+ });
26
+
27
+ test("Data written to input.writable arrives at output.readable", async () => {
28
+ const { input, output } = createWebStreamPair();
29
+
30
+ const echoPromise = output.readable.pipeTo(output.writable);
31
+
32
+ const writer = input.writable.getWriter();
33
+ const reader = input.readable.getReader();
34
+
35
+ const encoder = new TextEncoder();
36
+ const decoder = new TextDecoder();
37
+
38
+ // Write data to the input side
39
+ await writer.write(encoder.encode("Hello streaming world!"));
40
+ await writer.close(); // Close the stream after writing
41
+
42
+ // The echo server's pipeTo should resolve and finish successfully
43
+ await assert.doesNotReject(echoPromise);
44
+
45
+ // Read the data from the input side
46
+ const chunks: Uint8Array[] = [];
47
+
48
+ while (true) {
49
+ const { value, done } = await reader.read();
50
+ if (done) break;
51
+ if (value) chunks.push(value);
52
+ }
53
+
54
+ // Combine chunks and decode to string
55
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
56
+ const resultUint8 = new Uint8Array(totalLength);
57
+ let offset = 0;
58
+ for (const chunk of chunks) {
59
+ resultUint8.set(chunk, offset);
60
+ offset += chunk.length;
61
+ }
62
+
63
+ const readText = decoder.decode(resultUint8);
64
+
65
+ // Verify the text matches exactly
66
+ assert.strictEqual(readText, "Hello streaming world!");
67
+ reader.releaseLock();
68
+ });
69
+
70
+ test("Data can be written and read sequentially before closing", async () => {
71
+ const { input, output } = createWebStreamPair();
72
+ const echoPromise = output.readable.pipeTo(output.writable);
73
+
74
+ const writer = input.writable.getWriter();
75
+ const reader = input.readable.getReader();
76
+
77
+ const encoder = new TextEncoder();
78
+ const decoder = new TextDecoder();
79
+
80
+ // 1. First Write & Read chunk
81
+ await writer.write(encoder.encode("Chunk 1"));
82
+ const result1 = await reader.read();
83
+ assert.strictEqual(result1.done, false);
84
+ assert.strictEqual(decoder.decode(result1.value), "Chunk 1");
85
+
86
+ // 2. Second Write & Read chunk
87
+ await writer.write(encoder.encode("Chunk 2"));
88
+ const result2 = await reader.read();
89
+ assert.strictEqual(result2.done, false);
90
+ assert.strictEqual(decoder.decode(result2.value), "Chunk 2");
91
+
92
+ // 3. Now we close the writable side mid-stream
93
+ await writer.close();
94
+
95
+ // The echo server's pipeTo should resolve and finish successfully
96
+ await assert.doesNotReject(echoPromise);
97
+
98
+ // 4. Verify that the readable side now registers the close signal
99
+ const finalResult = await reader.read();
100
+ assert.strictEqual(finalResult.done, true);
101
+ assert.strictEqual(finalResult.value, undefined);
102
+
103
+ writer.releaseLock();
104
+ reader.releaseLock();
105
+ });
106
+
107
+ test("Client detects when the echo server abruptly closes its end", async () => {
108
+ const { input, output } = createWebStreamPair();
109
+ const encoder = new TextEncoder();
110
+
111
+ // Set up a manual echo server so we can manipulate its controls
112
+ const serverReader = output.readable.getReader();
113
+ const serverWriter = output.writable.getWriter();
114
+
115
+ // Start a basic manual loop in the background
116
+ const serverLoop = (async () => {
117
+ try {
118
+ while (true) {
119
+ const { value, done } = await serverReader.read();
120
+ if (done) break;
121
+ await serverWriter.write(value);
122
+ }
123
+ } finally {
124
+ serverReader.releaseLock();
125
+ serverWriter.releaseLock();
126
+ }
127
+ })();
128
+
129
+ const clientWriter = input.writable.getWriter();
130
+ const clientReader = input.readable.getReader();
131
+
132
+ // --- Simulate Server Shutdown ---
133
+ // The echo server decides to close its writing side out of nowhere
134
+ try {
135
+ await serverWriter.close();
136
+ await serverReader.cancel();
137
+ await serverLoop;
138
+
139
+ const first = await clientReader.read();
140
+ assert.strictEqual(first.done, true);
141
+
142
+ await assert.rejects(
143
+ () => clientWriter.write(encoder.encode("Is anyone there?")),
144
+ /close|invalid/i,
145
+ );
146
+ } finally {
147
+ clientWriter.releaseLock();
148
+ clientReader.releaseLock();
149
+ }
150
+ });
151
+
152
+ test("Repeated close and cancel calls are idempotent", async () => {
153
+ const { input, output } = createWebStreamPair();
154
+
155
+ const inputWriter = input.writable.getWriter();
156
+ const inputReader = input.readable.getReader();
157
+ const outputWriter = output.writable.getWriter();
158
+ const outputReader = output.readable.getReader();
159
+
160
+ await Promise.allSettled([
161
+ inputWriter.close(),
162
+ outputWriter.close(),
163
+ inputReader.cancel(),
164
+ outputReader.cancel(),
165
+ ]);
166
+
167
+ inputWriter.releaseLock();
168
+ inputReader.releaseLock();
169
+ outputWriter.releaseLock();
170
+ outputReader.releaseLock();
171
+ });