@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,589 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import {
4
+ AuthenticationResult,
5
+ MQTTLevel,
6
+ PacketType,
7
+ ReasonCode,
8
+ } from "../deps.ts";
9
+ import {
10
+ addMockClient,
11
+ connect,
12
+ connect5,
13
+ disconnect,
14
+ disconnect5,
15
+ ping,
16
+ publish,
17
+ startMockServer,
18
+ subscribe,
19
+ } from "../../dev_utils/mod.ts";
20
+ import { createConfiguration } from "../config.ts";
21
+
22
+ const configuration = createConfiguration();
23
+ const txtEncoder = new TextEncoder();
24
+
25
+ test("Authentication with valid username and password works", async () => {
26
+ const { mqttConn } = startMockServer();
27
+ const connack = await connect(mqttConn);
28
+ assert.deepStrictEqual(
29
+ connack.returnCode,
30
+ AuthenticationResult.ok,
31
+ "Expected OK",
32
+ );
33
+ await disconnect(mqttConn);
34
+ });
35
+
36
+ test("Authentication with invalid username fails", async () => {
37
+ const { mqttConn } = startMockServer();
38
+ const connack = await connect(mqttConn, { username: "wrong" });
39
+
40
+ assert.deepStrictEqual(
41
+ connack.returnCode,
42
+ AuthenticationResult.badUsernameOrPassword,
43
+ "Expected badUsernameOrPassword",
44
+ );
45
+
46
+ await mqttConn.next();
47
+ assert.deepStrictEqual(
48
+ mqttConn.isClosed,
49
+ true,
50
+ "Expected connection to be closed",
51
+ );
52
+ });
53
+
54
+ test("Authentication with invalid password fails", async () => {
55
+ const { mqttConn } = startMockServer();
56
+ const connack = await connect(mqttConn, { password: "" });
57
+
58
+ assert.deepStrictEqual(
59
+ connack.returnCode,
60
+ AuthenticationResult.badUsernameOrPassword,
61
+ "Expected badUsernameOrPassword",
62
+ );
63
+
64
+ await mqttConn.next();
65
+ assert.deepStrictEqual(
66
+ mqttConn.isClosed,
67
+ true,
68
+ "Expected connection to be closed",
69
+ );
70
+ });
71
+
72
+ test("Two connect messages on same connection closes connection", async () => {
73
+ const { mqttConn } = startMockServer();
74
+
75
+ const connack = await connect(mqttConn);
76
+ assert.deepStrictEqual(
77
+ connack.returnCode,
78
+ AuthenticationResult.ok,
79
+ "Expected OK",
80
+ );
81
+
82
+ const connack2 = await connect(mqttConn, { checkAck: false });
83
+ assert.deepStrictEqual(connack2, undefined, "Expected no second connack");
84
+ assert.deepStrictEqual(
85
+ mqttConn.isClosed,
86
+ true,
87
+ "Expected connection to be closed",
88
+ );
89
+ });
90
+
91
+ test("Second session with same client id closes the first", async () => {
92
+ const clientId = "doubleClient";
93
+ const { mqttConn: mqttConn1, mqttServer } = startMockServer();
94
+ // start first client
95
+ await connect(mqttConn1, { clientId });
96
+
97
+ // start second client with same id
98
+ const mqttConn2 = addMockClient(mqttServer);
99
+ await connect(mqttConn2, { clientId });
100
+
101
+ await mqttConn1.next();
102
+ assert.deepStrictEqual(
103
+ mqttConn1.isClosed,
104
+ true,
105
+ "Expected first connection to be closed",
106
+ );
107
+ assert.deepStrictEqual(
108
+ mqttConn2.isClosed,
109
+ false,
110
+ "Expected second connection not to be closed",
111
+ );
112
+ await disconnect(mqttConn2);
113
+ });
114
+
115
+ test("Redelivery on reconnect after failed delivery", async () => {
116
+ const clientId = "redeliveryClient";
117
+ const topic = "no/retained/here";
118
+ const { mqttConn: mqttConn1, mqttServer } = startMockServer();
119
+ // start first client, clean needs to be false or else client state whill be wiped on disconnect
120
+ await connect(mqttConn1, { clientId, clean: false });
121
+ // Subscribe to topic with no retained message
122
+ await subscribe(mqttConn1, [{ topicFilter: topic, qos: 1 }]);
123
+ // the first packet returned will be the publish, not the ack.
124
+ await publish(mqttConn1, topic, 1, { checkAcks: false });
125
+ // first reception on our subscription
126
+ const { value: publishPacket } = await mqttConn1.next();
127
+ assert.deepStrictEqual(
128
+ publishPacket.type,
129
+ PacketType.publish,
130
+ "received publish packet again",
131
+ );
132
+ const publishId = publishPacket.id;
133
+ await mqttConn1.next(); // the puback on the publish we sent out
134
+ await disconnect(mqttConn1);
135
+ assert.deepStrictEqual(
136
+ mqttConn1.isClosed,
137
+ true,
138
+ "Expected first connection to be closed",
139
+ );
140
+ // connect again with same clientId
141
+ const mqttConn2 = addMockClient(mqttServer);
142
+ await connect(mqttConn2, { clientId, clean: false });
143
+ // expect published packet to be redelivered because we did not ack
144
+ const { value: packet } = await mqttConn2.next();
145
+ assert.deepStrictEqual(
146
+ packet.type,
147
+ PacketType.publish,
148
+ "received publish packet again",
149
+ );
150
+ assert.deepStrictEqual(
151
+ packet.id,
152
+ publishId,
153
+ "packetid is the same as on original delivery",
154
+ );
155
+ await disconnect(mqttConn2);
156
+ });
157
+
158
+ test("Delivery of messages with QoS 1 or QoS2 received while offline", async () => {
159
+ const clientId = "offlineClient";
160
+ const { mqttConn: mqttConn1, mqttServer } = startMockServer();
161
+ // start first client
162
+ await connect(mqttConn1, { clientId, clean: false });
163
+ // Subscribe to topic with no retained message
164
+ await subscribe(mqttConn1, [{ topicFilter: "offline/+", qos: 1 }]);
165
+ // hangup
166
+ await disconnect(mqttConn1);
167
+
168
+ // connect the publisher
169
+ const mqttConn2 = addMockClient(mqttServer);
170
+ await connect(mqttConn2, { clientId: "publisher" });
171
+ await publish(mqttConn2, "offline/q0", 0, { id: 10 });
172
+ await publish(mqttConn2, "offline/q1", 1, { id: 11 });
173
+ await publish(mqttConn2, "offline/q2", 2, { id: 12 });
174
+ await disconnect(mqttConn2);
175
+
176
+ // connect again with same clientId as the initial connect
177
+ const mqttConn3 = addMockClient(mqttServer);
178
+ await connect(mqttConn3, { clientId, clean: false });
179
+ // expect published packet that was delivered while offline
180
+ const { value: packetQos1 } = await mqttConn3.next();
181
+ assert.deepStrictEqual(
182
+ packetQos1.type,
183
+ PacketType.publish,
184
+ "received publish packet",
185
+ );
186
+ assert.deepStrictEqual(
187
+ packetQos1.topic,
188
+ "offline/q1",
189
+ "topic is expected",
190
+ );
191
+ const { value: packetQos2 } = await mqttConn3.next();
192
+ assert.deepStrictEqual(
193
+ packetQos2.type,
194
+ PacketType.publish,
195
+ "received publish packet",
196
+ );
197
+ assert.deepStrictEqual(
198
+ packetQos2.topic,
199
+ "offline/q2",
200
+ "topic is expected",
201
+ );
202
+ await ping(mqttConn3);
203
+ await disconnect(mqttConn3);
204
+ });
205
+
206
+ test("Delivery of messages with QoS 1 or QoS2 not received while offline when clean = true", async () => {
207
+ const clientId = "offlineClient";
208
+ const { mqttConn: mqttConn1, mqttServer } = startMockServer();
209
+ // start first client
210
+ await connect(mqttConn1, { clientId, clean: true });
211
+ // Subscribe to topic with no retained message
212
+ await subscribe(mqttConn1, [{ topicFilter: "offline/+", qos: 1 }]);
213
+ // hangup
214
+ await disconnect(mqttConn1);
215
+
216
+ // connect the publisher
217
+ const mqttConn2 = addMockClient(mqttServer);
218
+ await connect(mqttConn2, { clientId: "publisher" });
219
+ await publish(mqttConn2, "offline/q0", 0, { id: 10 });
220
+ await publish(mqttConn2, "offline/q1", 1, { id: 11 });
221
+ await publish(mqttConn2, "offline/q2", 2, { id: 12 });
222
+ await disconnect(mqttConn2);
223
+
224
+ // connect again with same clientId as the initial connect,but now with clean = false, just to check
225
+ const mqttConn3 = addMockClient(mqttServer);
226
+ await connect(mqttConn3, { clientId, clean: false });
227
+ // expect no published packet to be delivered while offline
228
+ await ping(mqttConn3);
229
+ await disconnect(mqttConn3);
230
+ });
231
+
232
+ test("V5: Connect V5 works", async () => {
233
+ const { mqttConn } = startMockServer();
234
+ const connack = await connect5(mqttConn, { clientId: "" });
235
+ assert.deepEqual(connack.reasonCode, 0, "Reason code 0 is expected");
236
+ const props = connack.properties;
237
+ const cfg = configuration.context;
238
+ assert.equal(
239
+ props?.maximumQos,
240
+ cfg.maximumQos,
241
+ "Props contain configuration data",
242
+ );
243
+ assert.equal(
244
+ props?.assignedClientIdentifier?.startsWith("Opifex-"),
245
+ true,
246
+ "Client identifier is assigned",
247
+ );
248
+
249
+ await disconnect5(mqttConn);
250
+ await mqttConn.next();
251
+ assert.strictEqual(mqttConn.isClosed, true);
252
+ });
253
+
254
+ test("V5: Fails on unsupported protocol level and returns V5 ReasonCode", async () => {
255
+ const { mqttConn } = startMockServer({
256
+ configuration: { context: { protocols: [MQTTLevel.v4] } },
257
+ });
258
+
259
+ const connack = await connect5(mqttConn, {
260
+ clientId: "v5Client",
261
+ });
262
+ assert.strictEqual(
263
+ connack.reasonCode,
264
+ ReasonCode.unsupportedProtocolVersion,
265
+ );
266
+
267
+ await mqttConn.next();
268
+ assert.strictEqual(mqttConn.isClosed, true);
269
+ });
270
+
271
+ test("Will Packet: Retain not supported returns retainNotSupported", async () => {
272
+ const { mqttConn } = startMockServer({
273
+ configuration: { context: { retainAvailable: false } },
274
+ });
275
+
276
+ const connack = await connect(mqttConn, {
277
+ will: {
278
+ topic: "will/topic",
279
+ payload: txtEncoder.encode("payload"),
280
+ qos: 0,
281
+ retain: true,
282
+ },
283
+ });
284
+
285
+ assert.strictEqual(
286
+ connack.returnCode,
287
+ AuthenticationResult.serverUnavailable,
288
+ );
289
+
290
+ await mqttConn.next();
291
+ assert.strictEqual(mqttConn.isClosed, true);
292
+ });
293
+
294
+ test("V5 Will Packet: unauthorized will topic returns notAuthorized", async () => {
295
+ const { mqttConn } = startMockServer({
296
+ handlers: {
297
+ isAuthorizedToPublish: () => false,
298
+ },
299
+ });
300
+
301
+ const connack = await connect5(mqttConn, {
302
+ will: {
303
+ topic: "will/topic",
304
+ payload: txtEncoder.encode("payload"),
305
+ qos: 0,
306
+ retain: false,
307
+ },
308
+ });
309
+
310
+ assert.strictEqual(
311
+ connack.reasonCode,
312
+ ReasonCode.notAuthorized,
313
+ );
314
+
315
+ await mqttConn.next();
316
+ assert.strictEqual(mqttConn.isClosed, true);
317
+ });
318
+
319
+ test("V5 Will Packet: QoS exceeds maximumQos returns qosNotSupported", async () => {
320
+ const { mqttConn } = startMockServer({
321
+ configuration: { context: { maximumQos: 1 } },
322
+ });
323
+
324
+ const connack = await connect5(mqttConn, {
325
+ will: {
326
+ topic: "will/topic",
327
+ payload: txtEncoder.encode("payload"),
328
+ qos: 2, // Exceeds max QoS 1
329
+ retain: false,
330
+ },
331
+ });
332
+
333
+ assert.strictEqual(
334
+ connack.reasonCode,
335
+ ReasonCode.qosNotSupported,
336
+ );
337
+
338
+ await mqttConn.next();
339
+ assert.strictEqual(mqttConn.isClosed, true);
340
+ });
341
+
342
+ test("V5 Will Packet: willDelayInterval greater than sessionExpiryInterval fails", async () => {
343
+ const { mqttConn } = startMockServer();
344
+
345
+ const connack = await connect5(mqttConn, {
346
+ clientId: "v5WillClient",
347
+ properties: {
348
+ sessionExpiryInterval: 100,
349
+ },
350
+ will: {
351
+ topic: "will/topic",
352
+ payload: txtEncoder.encode("payload"),
353
+ qos: 0,
354
+ retain: false,
355
+ properties: {
356
+ willDelayInterval: 200, // Greater than sessionExpiryInterval (100)
357
+ },
358
+ },
359
+ });
360
+
361
+ assert.strictEqual(
362
+ connack.reasonCode,
363
+ ReasonCode.payloadFormatInvalid,
364
+ );
365
+
366
+ await mqttConn.next();
367
+ assert.strictEqual(mqttConn.isClosed, true);
368
+ });
369
+
370
+ test("V5: sessionExpiryInterval capped to maxSessionExpiryInterval", async () => {
371
+ const { mqttConn } = startMockServer({
372
+ configuration: { context: { maxSessionExpiryInterval: 300 } },
373
+ });
374
+ const connack = await connect5(mqttConn, {
375
+ clientId: "cappedSessionClient",
376
+ clean: false,
377
+ properties: {
378
+ sessionExpiryInterval: 1000, // Greater than maxSessionExpiryInterval (300)
379
+ },
380
+ });
381
+
382
+ assert.strictEqual(connack.reasonCode, ReasonCode.success);
383
+ assert.strictEqual(connack.properties?.sessionExpiryInterval, 300);
384
+
385
+ await disconnect5(mqttConn);
386
+ });
387
+
388
+ test("V5: Reason string returned in properties when provideReasonStrings is true", async () => {
389
+ const { mqttConn } = startMockServer({
390
+ configuration: {
391
+ context: {
392
+ provideReasonStrings: true,
393
+ protocols: [MQTTLevel.v4],
394
+ },
395
+ },
396
+ });
397
+ const connack = await connect5(mqttConn, {});
398
+ assert.strictEqual(
399
+ connack.reasonCode,
400
+ ReasonCode.unsupportedProtocolVersion,
401
+ );
402
+ assert.strictEqual(
403
+ connack.properties?.reasonString,
404
+ "Protocol version 5 is not supported",
405
+ );
406
+
407
+ await mqttConn.next();
408
+ assert.strictEqual(mqttConn.isClosed, true);
409
+ });
410
+
411
+ test("reasonToReturnCode branch coverage for V4 status mappings", async () => {
412
+ const testCases = [
413
+ {
414
+ reasonCode: ReasonCode.clientIdentifierNotValid,
415
+ expectedReturnCode: AuthenticationResult.rejectedUsername,
416
+ },
417
+ {
418
+ reasonCode: ReasonCode.badAuthenticationMethod,
419
+ expectedReturnCode: AuthenticationResult.badUsernameOrPassword,
420
+ },
421
+ {
422
+ reasonCode: ReasonCode.banned,
423
+ expectedReturnCode: AuthenticationResult.notAuthorized,
424
+ },
425
+ {
426
+ reasonCode: ReasonCode.packetIdentifierNotFound, // Unmapped fallback
427
+ expectedReturnCode: AuthenticationResult.serverUnavailable,
428
+ },
429
+ ];
430
+
431
+ for (const tc of testCases) {
432
+ const { mqttConn } = startMockServer({
433
+ handlers: {
434
+ isAuthenticated: () => ({ reasonCode: tc.reasonCode }),
435
+ },
436
+ });
437
+
438
+ const connack = await connect(mqttConn);
439
+ assert.strictEqual(
440
+ connack.returnCode,
441
+ tc.expectedReturnCode,
442
+ `ReasonCode ${tc.reasonCode} should map to returnCode ${tc.expectedReturnCode}`,
443
+ );
444
+
445
+ await mqttConn.next();
446
+ assert.strictEqual(mqttConn.isClosed, true);
447
+ }
448
+ });
449
+
450
+ test("Will Packet: Empty topic fails with topicNameInvalid", async () => {
451
+ const { mqttConn } = startMockServer();
452
+
453
+ const connack = await connect5(mqttConn, {
454
+ will: {
455
+ topic: "",
456
+ payload: txtEncoder.encode("payload"),
457
+ qos: 0,
458
+ retain: false,
459
+ },
460
+ });
461
+
462
+ assert.strictEqual(connack.reasonCode, ReasonCode.topicNameInvalid);
463
+ await mqttConn.next();
464
+ assert.strictEqual(mqttConn.isClosed, true);
465
+ });
466
+
467
+ test("Will Packet: Invalid wildcard topic filter fails validation", async () => {
468
+ const { mqttConn } = startMockServer();
469
+
470
+ const connack = await connect5(mqttConn, {
471
+ will: {
472
+ topic: "invalid/+/will",
473
+ payload: txtEncoder.encode("payload"),
474
+ qos: 0,
475
+ retain: false,
476
+ },
477
+ });
478
+
479
+ assert.strictEqual(connack.reasonCode, ReasonCode.topicNameInvalid);
480
+ await mqttConn.next();
481
+ assert.strictEqual(mqttConn.isClosed, true);
482
+ });
483
+
484
+ test("Will Packet: Topic level count exceeding maxTopicLevels fails validation", async () => {
485
+ const { mqttConn } = startMockServer({
486
+ configuration: { context: { maxTopicLevels: 1 } },
487
+ });
488
+
489
+ const connack = await connect5(mqttConn, {
490
+ will: {
491
+ topic: "level1/level2", // 2 levels exceeds limit of 1
492
+ payload: txtEncoder.encode("payload"),
493
+ qos: 0,
494
+ retain: false,
495
+ },
496
+ });
497
+
498
+ assert.strictEqual(connack.reasonCode, ReasonCode.topicNameInvalid);
499
+ await mqttConn.next();
500
+ assert.strictEqual(mqttConn.isClosed, true);
501
+ });
502
+
503
+ test("V4 Will Packet: Unauthorized Will topic maps to V4 returnCode", async () => {
504
+ const { mqttConn } = startMockServer({
505
+ handlers: {
506
+ isAuthorizedToPublish: () => false,
507
+ },
508
+ });
509
+
510
+ const connack = await connect(mqttConn, {
511
+ will: {
512
+ topic: "unauthorized/will",
513
+ payload: txtEncoder.encode("payload"),
514
+ qos: 0,
515
+ retain: false,
516
+ },
517
+ });
518
+
519
+ assert.strictEqual(
520
+ connack.returnCode,
521
+ AuthenticationResult.notAuthorized,
522
+ );
523
+ await mqttConn.next();
524
+ assert.strictEqual(mqttConn.isClosed, true);
525
+ });
526
+
527
+ test("V5 Will Packet: Valid willDelayInterval when sessionExpiryInterval is omitted or sufficient", async () => {
528
+ const { mqttConn } = startMockServer();
529
+
530
+ const connack = await connect5(mqttConn, {
531
+ properties: {
532
+ sessionExpiryInterval: 300,
533
+ },
534
+ will: {
535
+ topic: "will/topic",
536
+ payload: txtEncoder.encode("payload"),
537
+ qos: 0,
538
+ retain: false,
539
+ properties: {
540
+ willDelayInterval: 100, // Valid since 100 <= 300
541
+ },
542
+ },
543
+ });
544
+
545
+ assert.strictEqual(connack.reasonCode, ReasonCode.success);
546
+ await disconnect5(mqttConn);
547
+ });
548
+
549
+ test("V5: Assigned clientId omitted from CONNACK when client provides explicit clientId", async () => {
550
+ const { mqttConn } = startMockServer();
551
+
552
+ const connack = await connect5(mqttConn, {
553
+ clientId: "explicit-client-id",
554
+ });
555
+
556
+ assert.strictEqual(connack.reasonCode, ReasonCode.success);
557
+ assert.strictEqual(
558
+ connack.properties?.assignedClientIdentifier,
559
+ undefined,
560
+ "Expected assignedClientIdentifier to be omitted",
561
+ );
562
+
563
+ await disconnect5(mqttConn);
564
+ });
565
+
566
+ test("V5: Reason string omitted when provideReasonStrings is false", async () => {
567
+ const { mqttConn } = startMockServer({
568
+ configuration: {
569
+ context: {
570
+ provideReasonStrings: false,
571
+ protocols: [MQTTLevel.v4], // Force failure to evaluate error properties
572
+ },
573
+ },
574
+ });
575
+
576
+ const connack = await connect5(mqttConn, {});
577
+ assert.strictEqual(
578
+ connack.reasonCode,
579
+ ReasonCode.unsupportedProtocolVersion,
580
+ );
581
+ assert.strictEqual(
582
+ connack.properties?.reasonString,
583
+ undefined,
584
+ "Reason string should be omitted when provideReasonStrings is false",
585
+ );
586
+
587
+ await mqttConn.next();
588
+ assert.strictEqual(mqttConn.isClosed, true);
589
+ });