@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
@@ -0,0 +1,221 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { PacketType } from "../deps.ts";
4
+ import {
5
+ addMockClient,
6
+ connect,
7
+ disconnect,
8
+ ping,
9
+ startMockServer,
10
+ subscribe,
11
+ } from "../../dev_utils/mod.ts";
12
+
13
+ const txtEncoder = new TextEncoder();
14
+
15
+ test("MQTT-3.1.2.5: will message delivered on ungraceful disconnect", async () => {
16
+ const willTopic = "will/topic";
17
+ const payload = txtEncoder.encode("goodbye");
18
+ const { mqttConn: subscriber, mqttServer } = startMockServer();
19
+
20
+ // Subscriber connects
21
+ await connect(subscriber, { clientId: "subscriber1" });
22
+ await subscribe(subscriber, [{ topicFilter: willTopic, qos: 0 }]);
23
+
24
+ const publisher = addMockClient(mqttServer);
25
+ // Publisher connects
26
+ await connect(publisher, {
27
+ clientId: "publisher1",
28
+ will: {
29
+ topic: willTopic,
30
+ payload,
31
+ qos: 0,
32
+ retain: false,
33
+ },
34
+ });
35
+
36
+ // Force close the publisher connection without sending DISCONNECT
37
+ // This simulates an ungraceful disconnect
38
+ publisher.close();
39
+ assert.deepStrictEqual(publisher.isClosed, true, "publisher is closed");
40
+
41
+ // Subscriber should receive the will message
42
+ const { value: willMessage } = await subscriber.next();
43
+
44
+ assert.deepStrictEqual(
45
+ willMessage.type,
46
+ PacketType.publish,
47
+ "Expecting a Publish packet",
48
+ );
49
+ assert.deepStrictEqual(
50
+ willMessage.topic,
51
+ willTopic,
52
+ "Expecting correct topic",
53
+ );
54
+ assert.deepStrictEqual(
55
+ willMessage.payload,
56
+ payload,
57
+ "Expecting correct payload",
58
+ );
59
+
60
+ // Clean up
61
+ await disconnect(subscriber);
62
+ });
63
+
64
+ test("MQTT-3.1.2.5: will message NOT delivered on graceful DISCONNECT", async () => {
65
+ const willTopic = "will/topic2";
66
+ const payload = txtEncoder.encode("goodbye");
67
+ const { mqttConn: subscriber, mqttServer } = startMockServer();
68
+
69
+ // Subscriber connects
70
+ await connect(subscriber, { clientId: "subscriber2" });
71
+ await subscribe(subscriber, [{ topicFilter: willTopic, qos: 0 }]);
72
+
73
+ const publisher = addMockClient(mqttServer);
74
+ // Publisher connects
75
+ await connect(publisher, {
76
+ clientId: "publisher2",
77
+ will: {
78
+ topic: willTopic,
79
+ payload,
80
+ qos: 0,
81
+ retain: false,
82
+ },
83
+ });
84
+ // Publisher gracefully disconnects
85
+ await disconnect(publisher);
86
+
87
+ // Send PINGREQ to verify no will message was queued before it
88
+ await ping(subscriber);
89
+
90
+ // Clean up
91
+ await disconnect(subscriber);
92
+ });
93
+
94
+ test("MQTT-3.1.2.5: will message delivered with correct QoS", async () => {
95
+ const willTopic = "will/qos";
96
+ const payload = txtEncoder.encode("goodbye");
97
+ const { mqttConn: subscriber, mqttServer } = startMockServer();
98
+
99
+ // Subscriber connects
100
+ await connect(subscriber, { clientId: "subscriber3" });
101
+ await subscribe(subscriber, [{ topicFilter: willTopic, qos: 1 }]);
102
+
103
+ // Publisher connects with will message QoS 1
104
+ const publisher = addMockClient(mqttServer);
105
+ await connect(publisher, {
106
+ clientId: "publisher3",
107
+ will: {
108
+ topic: willTopic,
109
+ payload,
110
+ qos: 1,
111
+ retain: false,
112
+ },
113
+ });
114
+
115
+ // Force close the publisher connection
116
+ publisher.close();
117
+
118
+ // Subscriber should receive the will message with QoS 1
119
+ const { value: willMessage } = await subscriber.next();
120
+ assert.deepStrictEqual(willMessage.type, PacketType.publish);
121
+
122
+ assert.deepStrictEqual(
123
+ willMessage.type,
124
+ PacketType.publish,
125
+ "Expecting a Publish packet",
126
+ );
127
+ assert.deepStrictEqual(
128
+ willMessage.topic,
129
+ willTopic,
130
+ "Expecting correct topic",
131
+ );
132
+ assert.deepStrictEqual(
133
+ willMessage.qos,
134
+ 1,
135
+ "Expecting correct QoS",
136
+ );
137
+
138
+ // Clean up
139
+ await disconnect(subscriber);
140
+ });
141
+
142
+ test("MQTT-3.1.2.5: will message stored as retained when retain=true", async () => {
143
+ const willTopic = "will/retained";
144
+ const payload = txtEncoder.encode("Retained message");
145
+
146
+ const { mqttConn: subscriber, mqttServer } = startMockServer();
147
+
148
+ // Subscriber connects
149
+ await connect(subscriber, { clientId: "subscriber4" });
150
+
151
+ // Publisher connects with will retain true
152
+ const publisher = addMockClient(mqttServer);
153
+ await connect(publisher, {
154
+ clientId: "publisher4",
155
+ will: {
156
+ topic: willTopic,
157
+ payload,
158
+ qos: 0,
159
+ retain: true,
160
+ },
161
+ });
162
+
163
+ // Force close the publisher connection
164
+ publisher.close();
165
+
166
+ // Now subscribe to the topic - should receive the retained message
167
+ await subscribe(subscriber, [{ topicFilter: willTopic, qos: 0 }]);
168
+
169
+ // Should receive the retained will message
170
+ const { value: willMessage } = await subscriber.next();
171
+ assert.deepStrictEqual(
172
+ willMessage.type,
173
+ PacketType.publish,
174
+ "Expecting PUBLISH packet",
175
+ );
176
+ assert.deepStrictEqual(
177
+ willMessage.topic,
178
+ willTopic,
179
+ "Expecting correct topic",
180
+ );
181
+ assert.deepStrictEqual(willMessage.retain, true, "Expecting retain true");
182
+ assert.deepStrictEqual(
183
+ willMessage.payload,
184
+ payload,
185
+ "Expecting correct payload",
186
+ );
187
+
188
+ // Clean up
189
+ await disconnect(subscriber);
190
+ });
191
+
192
+ test("MQTT-3.1.2.5: will message to $ topic is rejected", async () => {
193
+ const willTopic = "$SYS/will";
194
+ const payload = txtEncoder.encode("System Will");
195
+ const { mqttConn: subscriber, mqttServer } = startMockServer();
196
+
197
+ // Subscriber connects
198
+ await connect(subscriber, { clientId: "subscriber5" });
199
+ await subscribe(subscriber, [{ topicFilter: willTopic, qos: 0 }]);
200
+
201
+ // Publisher connects with will message to system topic
202
+ const publisher = addMockClient(mqttServer);
203
+ await connect(publisher, {
204
+ clientId: "publisher5",
205
+ will: {
206
+ topic: willTopic,
207
+ payload,
208
+ qos: 0,
209
+ retain: false,
210
+ },
211
+ });
212
+
213
+ // Force close the publisher connection
214
+ publisher.close();
215
+
216
+ // Send PINGREQ to verify no will message was queued
217
+ await ping(subscriber);
218
+
219
+ // Clean up
220
+ await disconnect(subscriber);
221
+ });
package/server/mod.ts CHANGED
@@ -2,14 +2,15 @@
2
2
  * This module provides an MQTT Server interface see the /bin folder for examples
3
3
  * @module
4
4
  */
5
- export { AuthenticationResult } from "./deps.ts";
5
+ export { ReasonCode } from "./deps.ts";
6
6
  export type {
7
+ ConnectPacket,
7
8
  IPersistence,
9
+ ShareName,
8
10
  SockConn,
9
- TAuthenticationResult,
10
11
  Topic,
11
12
  } from "./deps.ts";
12
13
  export { MqttServer } from "./server.ts";
13
14
  export type { MqttServerOptions } from "./server.ts";
14
15
  export { Context } from "./context.ts";
15
- export type { Handlers } from "./context.ts";
16
+ export type { AuthenticatedResult, Handlers } from "./context.ts";
@@ -0,0 +1,151 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import {
4
+ connect,
5
+ delay,
6
+ disconnect,
7
+ startMockServer,
8
+ } from "../dev_utils/mod.ts";
9
+ import type { AnyPacket } from "./deps.ts";
10
+ import { MQTTLevel } from "./deps.ts";
11
+ import { PacketType } from "../mqttPacket/mod.ts";
12
+
13
+ test(
14
+ "Preconnect timer: connection closes if CONNECT not received within timeout",
15
+ { concurrency: false },
16
+ async () => {
17
+ const { mqttConn } = startMockServer({
18
+ configuration: { context: { preconnectTimeoutMs: 500 } },
19
+ });
20
+
21
+ // Wait 750 ms without sending CONNECT packet
22
+ await delay(750);
23
+
24
+ // Try to get next packet (should timeout/close)
25
+ await mqttConn.next();
26
+
27
+ // Connection should be closed
28
+ assert.deepStrictEqual(
29
+ mqttConn.isClosed,
30
+ true,
31
+ "Connection should be closed after preconnect timeout",
32
+ );
33
+ },
34
+ );
35
+
36
+ test(
37
+ "Preconnect timer: connection succeeds if CONNECT received before timeout",
38
+ { concurrency: false },
39
+ async () => {
40
+ const { mqttConn } = startMockServer({
41
+ configuration: { context: { preconnectTimeoutMs: 500 } },
42
+ });
43
+
44
+ // Wait 200 ms (before timeout)
45
+ await delay(200);
46
+
47
+ // Send CONNECT packet
48
+ await connect(mqttConn, { clientId: "preconnectTestClient" });
49
+
50
+ // Connection should still be open
51
+ assert.deepStrictEqual(
52
+ mqttConn.isClosed,
53
+ false,
54
+ "Connection should remain open after successful CONNECT",
55
+ );
56
+
57
+ // Cleanup
58
+ await disconnect(mqttConn);
59
+ },
60
+ );
61
+
62
+ test(
63
+ "Preconnect timer: connection succeeds with immediate CONNECT",
64
+ { concurrency: false },
65
+ async () => {
66
+ const { mqttConn } = startMockServer({
67
+ configuration: { context: { preconnectTimeoutMs: 500 } },
68
+ });
69
+
70
+ // Send CONNECT immediately
71
+ await connect(mqttConn, { clientId: "preconnectTestImmediate" });
72
+ await delay(750);
73
+
74
+ // Connection should be open
75
+ assert.deepStrictEqual(
76
+ mqttConn.isClosed,
77
+ false,
78
+ "Connection should remain open after immediate CONNECT",
79
+ );
80
+
81
+ // Cleanup
82
+ await disconnect(mqttConn);
83
+ },
84
+ );
85
+
86
+ test(
87
+ "Preconnect timer: closes connection at exact time",
88
+ { concurrency: false },
89
+ async () => {
90
+ const { mqttConn } = startMockServer({
91
+ configuration: { context: { preconnectTimeoutMs: 500 } },
92
+ });
93
+
94
+ // Wait just under 500 ms - should still be connected
95
+ await delay(400);
96
+
97
+ // Connection should still be open
98
+ assert.deepStrictEqual(
99
+ mqttConn.isClosed,
100
+ false,
101
+ "Connection should be open at 2.9 seconds",
102
+ );
103
+
104
+ // Wait additional 200ms to cross the 500 ms boundary
105
+ await delay(200);
106
+
107
+ // Try to interact with connection
108
+ await mqttConn.next();
109
+
110
+ // Connection should now be closed
111
+ assert.deepStrictEqual(
112
+ mqttConn.isClosed,
113
+ true,
114
+ "Connection should be closed now",
115
+ );
116
+ },
117
+ );
118
+
119
+ test("Preconnect handler: handler disconnects session", async () => {
120
+ const txtEncoder = new TextEncoder();
121
+
122
+ const connectPacket: AnyPacket = {
123
+ type: PacketType.connect,
124
+ protocolName: "MQTT",
125
+ protocolLevel: MQTTLevel.v4,
126
+ clientId: "testClient",
127
+ clean: true,
128
+ keepAlive: 0,
129
+ username: "IoTester_1",
130
+ password: txtEncoder.encode("strong_password"),
131
+ will: undefined,
132
+ };
133
+
134
+ const { mqttConn } = startMockServer({
135
+ handlers: {
136
+ preconnect: () => false,
137
+ },
138
+ });
139
+ await mqttConn.send(connectPacket);
140
+ const { value } = await mqttConn.next();
141
+ assert.deepStrictEqual(
142
+ value,
143
+ undefined,
144
+ "No connack received",
145
+ );
146
+ assert.deepStrictEqual(
147
+ mqttConn.isClosed,
148
+ true,
149
+ "Connection should be closed by the preconnect handler",
150
+ );
151
+ });
package/server/server.ts CHANGED
@@ -1,69 +1,167 @@
1
- import { AuthenticationResult, logger, MemoryPersistence } from "./deps.ts";
1
+ import { logger, MemoryPersistence, ReasonCode } from "./deps.ts";
2
2
  import { Context } from "./context.ts";
3
3
  import type { Handlers } from "./context.ts";
4
- import type { IPersistence, SockConn, Topic } from "./deps.ts";
4
+ import type { IPersistence, ShareName, SockConn, Topic } from "./deps.ts";
5
5
  import { handlePacket } from "./handlers/handlePacket.ts";
6
+ import { createConfiguration } from "./config.ts";
7
+ import type { Configuration, ConfigurationInput } from "./config.ts";
6
8
 
9
+ /**
10
+ * Default preconnect handler that unconditionally permits all connections.
11
+ * @param {SockConn} _conn - The connection.
12
+ * @returns {boolean} Always returns true
13
+ */
14
+ const defaultPreconnect = (
15
+ _conn: SockConn,
16
+ ) => (true) as const;
17
+
18
+ /**
19
+ * Default authentication handler that unconditionally permits all connections.
20
+ * @param {Context} _ctx - The connection context.
21
+ * @param {string} _clientId - The client identifier.
22
+ * @param {string} _username - The username provided by the client.
23
+ * @param {Uint8Array} _password - The password provided by the client.
24
+ * @returns {IsAuthenticatedResult} Always returns ReasonCode.success.
25
+ */
7
26
  const defaultIsAuthenticated = (
8
27
  _ctx: Context,
9
28
  _clientId: string,
10
29
  _username: string,
11
30
  _password: Uint8Array,
12
- ) => AuthenticationResult.ok;
31
+ ) => ({ reasonCode: ReasonCode.success }) as const;
32
+
33
+ const defaultProcessAuth = (
34
+ _ctx: Context,
35
+ _clientId: string,
36
+ _authMethod: string,
37
+ _authData: Uint8Array,
38
+ ) =>
39
+ ({
40
+ reasonCode: ReasonCode.badAuthenticationMethod,
41
+ reasonString: "Authentication method not supported",
42
+ }) as const;
43
+
44
+ /**
45
+ * Default authorization handler that unconditionally permits all publish operations.
46
+ * @param {Context} _ctx - The connection context.
47
+ * @param {Topic} _topic - The topic being accessed.
48
+ * @returns {boolean} Always returns true.
49
+ */
50
+ const defaultIsAuthorizedToPublish = (_ctx: Context, _topic: Topic) =>
51
+ (true) as const;
13
52
 
14
- const defaultIsAuthorized = (_ctx: Context, _topic: Topic) => true;
53
+ /**
54
+ * Default authorization handler that unconditionally permits all subscribe operations.
55
+ * @param {Context} _ctx - The connection context.
56
+ * @param {Topic} _topic - The topic being accessed.
57
+ * @param {ShareName} _shareName - The share name being accessed when using shared subscriptions
58
+ * @returns {boolean} Always returns true.
59
+ */
60
+
61
+ const defaultIsAuthorizedToSubscribe = (
62
+ _ctx: Context,
63
+ _topic: Topic,
64
+ _shareName: ShareName,
65
+ ) => (true) as const;
15
66
 
16
67
  /**
17
- * The options to configure the MqttServer
68
+ * Configuration options for creating an MqttServer instance.
18
69
  */
19
70
  export type MqttServerOptions = {
71
+ /** Optional persistence layer implementation. Defaults to MemoryPersistence. */
20
72
  persistence?: IPersistence;
73
+ /** Optional custom handlers for authentication and authorization. */
21
74
  handlers?: Handlers;
75
+ /** Optional configuration data */
76
+ configuration?: ConfigurationInput;
22
77
  };
23
78
 
24
- /** The MqttServer class provides a MQTT server with configurable persistence and
79
+ /** * The MqttServer class provides an MQTT server with configurable persistence and
25
80
  * authentication/authorization handlers.
26
81
  *
27
82
  * The default handlers are:
28
- * - isAuthenticated: always returns ok
29
- * - isAuthorizedToPublish: always returns true
30
- * - isAuthorizedToSubscribe: always returns true
83
+ * - isAuthenticated: always returns ok
84
+ * - isAuthorizedToPublish: always returns true
85
+ * - isAuthorizedToSubscribe: always returns true
31
86
  *
32
87
  * To customize the handlers, pass in a Handlers object.
33
88
  * To customize the persistence, pass in a Persistence object.
34
89
  */
35
-
36
90
  export class MqttServer {
91
+ /** The registered authentication and authorization handlers. */
37
92
  handlers: Handlers;
93
+ /** The persistence layer used for storing sessions and messages. */
38
94
  persistence: IPersistence;
95
+ /** The persistence layer used for storing sessions and messages. */
96
+ configuration: Configuration;
97
+
98
+ /**
99
+ * Initializes a new instance of the MqttServer.
100
+ * * @param {MqttServerOptions} options - The configuration options for the server.
101
+ */
39
102
  constructor({
40
103
  persistence,
41
104
  handlers,
105
+ configuration,
42
106
  }: MqttServerOptions) {
43
107
  this.persistence = persistence || new MemoryPersistence();
44
108
  this.handlers = {
109
+ preconnect: handlers?.preconnect || defaultPreconnect,
45
110
  isAuthenticated: handlers?.isAuthenticated || defaultIsAuthenticated,
111
+ processAuth: handlers?.processAuth || defaultProcessAuth,
46
112
  isAuthorizedToPublish: handlers?.isAuthorizedToPublish ||
47
- defaultIsAuthorized,
113
+ defaultIsAuthorizedToPublish,
48
114
  isAuthorizedToSubscribe: handlers?.isAuthorizedToSubscribe ||
49
- defaultIsAuthorized,
115
+ defaultIsAuthorizedToSubscribe,
50
116
  };
117
+ this.configuration = createConfiguration(configuration);
51
118
  }
52
119
 
120
+ /**
121
+ * Serve a new client connection.
122
+ * @param {SockConn} conn - The socket connection to serve.
123
+ * @returns {Promise<void>} A promise that resolves when the connection is closed.
124
+ */
53
125
  async serve(conn: SockConn): Promise<void> {
54
- const ctx = new Context(this.persistence, conn, this.handlers);
126
+ if (this.handlers.preconnect) {
127
+ if (!await this.handlers.preconnect(conn)) {
128
+ conn.close();
129
+ return;
130
+ }
131
+ }
132
+ const ctx = new Context(
133
+ this.configuration,
134
+ this.persistence,
135
+ conn,
136
+ this.handlers,
137
+ );
55
138
  if (conn.remoteAddr?.transport === "tcp") {
56
- logger.debug(`socket connected from ${conn.remoteAddr.hostname}`);
139
+ logger.debug("socket connected from", conn.remoteAddr.hostname);
57
140
  }
58
141
  try {
59
142
  for await (const packet of ctx.mqttConn) {
143
+ logger.debug("next packet");
60
144
  await handlePacket(ctx, packet);
61
145
  }
62
146
  } catch (err) {
63
- logger.debug(`Error while serving:${err}`);
147
+ logger.debug("Error while serving:", err);
64
148
  } finally {
65
- if (!ctx.mqttConn.isClosed) {
66
- ctx.close();
149
+ logger.debug("done serving for", ctx.clientId);
150
+ await ctx.close();
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Close the server and all active client connections.
156
+ * @param {boolean} cleanUp - If true, clean up client sessions on close.
157
+ */
158
+ async close(cleanUp: boolean = false): Promise<void> {
159
+ logger.debug("stopping mqttServer");
160
+ for (const [clientid, ctx] of Context.clientList) {
161
+ logger.debug("closing session for clientid:", clientid);
162
+ await ctx.close();
163
+ if (cleanUp) {
164
+ await ctx.clean();
67
165
  }
68
166
  }
69
167
  }
@@ -0,0 +1,91 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { Conn } from "./socket.ts";
4
+ import { createMockSockConn } from "../dev_utils/mod.ts";
5
+
6
+ test("Conn.read peaks and buffers partial data correctly", async () => {
7
+ const chunk1 = new Uint8Array([1, 2, 3]);
8
+ const chunk2 = new Uint8Array([4, 5, 6, 7]);
9
+ const chunk3 = new Uint8Array([8, 9]);
10
+
11
+ const mockTarget = new Uint8Array();
12
+ const sockConn = createMockSockConn([chunk1, chunk2, chunk3], mockTarget);
13
+ const conn = new Conn(sockConn);
14
+
15
+ const res1 = await conn.read(2);
16
+ assert.deepStrictEqual(res1, new Uint8Array([1, 2]));
17
+
18
+ const res2 = await conn.read(3);
19
+ assert.deepStrictEqual(res2, new Uint8Array([3, 4, 5]));
20
+
21
+ const res3 = await conn.read(4);
22
+ assert.deepStrictEqual(res3, new Uint8Array([6, 7, 8, 9]));
23
+ });
24
+
25
+ test("Conn.read returns null when stream ends before length is met", async () => {
26
+ const chunk = new Uint8Array([1, 2, 3]);
27
+ const mockTarget = new Uint8Array(0);
28
+ const sockConn = createMockSockConn([chunk], mockTarget);
29
+ const conn = new Conn(sockConn);
30
+
31
+ // asking for5 bytes, but only 3 are available in the stream
32
+ const res = await conn.read(5);
33
+ assert.deepStrictEqual(res, null);
34
+ });
35
+
36
+ test("Conn.read returns null when length <= 0", async () => {
37
+ const chunk = new Uint8Array([1, 2, 3]);
38
+ const mockTarget = new Uint8Array(0);
39
+ const sockConn = createMockSockConn([chunk], mockTarget);
40
+ const conn = new Conn(sockConn);
41
+
42
+ const res = await conn.read(-1);
43
+ assert.deepStrictEqual(res, null);
44
+ });
45
+
46
+ test("Conn.read returns empty array when length = 0", async () => {
47
+ const chunk = new Uint8Array([1, 2, 3]);
48
+ const mockTarget = new Uint8Array(0);
49
+ const sockConn = createMockSockConn([chunk], mockTarget);
50
+ const conn = new Conn(sockConn);
51
+
52
+ const res = await conn.read(0);
53
+ assert.deepStrictEqual(res?.length, 0);
54
+ });
55
+
56
+ test("Conn.write successfully forwards data to writable stream", async () => {
57
+ const dataToWrite = new Uint8Array([10, 20, 30, 40]);
58
+ const mockTarget = new Uint8Array(4);
59
+ const sockConn = createMockSockConn([], mockTarget);
60
+ const conn = new Conn(sockConn);
61
+
62
+ const bytesWritten = await conn.write(dataToWrite);
63
+
64
+ assert.deepStrictEqual(bytesWritten, 4);
65
+ assert.deepStrictEqual(mockTarget, dataToWrite);
66
+ });
67
+
68
+ test("Conn.write rejects when connection is closed", async () => {
69
+ const mockTarget = new Uint8Array(4);
70
+ const sockConn = createMockSockConn([], mockTarget);
71
+ const conn = new Conn(sockConn);
72
+
73
+ conn.close();
74
+
75
+ await assert.rejects(
76
+ conn.write(new Uint8Array([1, 2])),
77
+ /Connection closed/,
78
+ );
79
+ });
80
+
81
+ test("Conn.close closes writer, releases reader lock and sets closed flag", () => {
82
+ const mockTarget = new Uint8Array(0);
83
+ const sockConn = createMockSockConn([], mockTarget);
84
+ const conn = new Conn(sockConn);
85
+
86
+ assert.deepStrictEqual(conn.closed, false);
87
+
88
+ conn.close();
89
+
90
+ assert.deepStrictEqual(conn.closed, true);
91
+ });