@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
package/trie/trie.test.ts CHANGED
@@ -141,7 +141,15 @@ test("Removal of object values works", () => {
141
141
  assert.ok(includesAll(root.match("foo/bar"), [c1, c2]), "two items found");
142
142
  root.remove("foo/bar", c2);
143
143
  assert.ok(includesAll(root.match("foo/bar"), [c1]), "one item found");
144
- root.remove("foo/bar", { a: 1, b: 2, c: 3 });
144
+ // partial filter
145
+ root.remove("foo/bar", { a: 1 });
145
146
  assert.ok(includesAll(root.match("foo/bar"), []), "empty array");
146
147
  assert.deepStrictEqual(root.match("foo/bar").length, 0, "matches left");
147
148
  });
149
+
150
+ test("Overlapping topics with empty levels works", () => {
151
+ const root = new Trie<number>();
152
+ root.add("foo/bar", 2);
153
+ root.add("foo/bar/#", 3);
154
+ assert.ok(includesAll(root.match("foo/bar"), [2, 3]), "two items found");
155
+ });
package/trie/trie.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * @description A Trie data structure implementation that supports wildcard matching
4
4
  * @template T The type of values stored in the trie
5
5
  */
6
- type Parts = string[];
6
+ export type Parts = string[];
7
7
 
8
8
  /**
9
9
  * Trie class for storing and matching hierarchical key-value pairs with wildcard support
@@ -46,7 +46,7 @@ export class Trie<T> {
46
46
  */
47
47
  match(key: string): T[] {
48
48
  const parts = key.split(this.separator);
49
- if (parts.length > 0 && parts[0].charAt(0) === this.reservedPrefix) {
49
+ if (parts.length > 0 && parts[0]?.charAt(0) === this.reservedPrefix) {
50
50
  return this._matchPrefix(parts);
51
51
  }
52
52
  return this._match(parts);
@@ -58,10 +58,10 @@ export class Trie<T> {
58
58
  * @returns Array of matched values
59
59
  */
60
60
  private _matchPrefix(parts: Parts): Array<T> {
61
- if (parts.length === 0) {
62
- return this.#value ? this.#value : [];
63
- }
64
61
  const [first, ...rest] = parts;
62
+ if (first === undefined) return [];
63
+
64
+ // Direct lookup on the reserved topic node without evaluating top-level + or #
65
65
  return this.matchChild(first, rest);
66
66
  }
67
67
 
@@ -71,15 +71,31 @@ export class Trie<T> {
71
71
  * @returns Array of matched values
72
72
  */
73
73
  private _match(parts: Parts): Array<T> {
74
+ let results: Array<T> = [];
75
+
76
+ // 1. Check if there is a multi-level wildcard ('#') at this level.
77
+ // In MQTT, 'a/#' matches 'a', 'a/b', 'a/b/c', etc.
78
+ const subtreeNode = this.#children.get(this.wildcardSubtree);
79
+ if (subtreeNode) {
80
+ results = results.concat(subtreeNode.#value);
81
+ }
82
+
83
+ // 2. Base case: we reached the end of the topic parts.
74
84
  if (parts.length === 0) {
75
- return this.#value ? this.#value : [];
85
+ return results.concat(this.#value);
76
86
  }
87
+
77
88
  const [first, ...rest] = parts;
89
+ // deno-coverage-ignore
90
+ if (first === undefined) return [];
91
+
92
+ // 3. Exact matching child node
78
93
  const exact = this.matchChild(first, rest);
94
+
95
+ // 4. Single-level wildcard ('+') matching child node
79
96
  const single = this.matchChild(this.wildcardOne, rest);
80
- const subtree = this.matchChild(this.wildcardSubtree, []);
81
- const results = exact.concat(single, subtree);
82
- return results;
97
+
98
+ return results.concat(exact, single);
83
99
  }
84
100
 
85
101
  /**
@@ -96,12 +112,14 @@ export class Trie<T> {
96
112
  * @param parts Parts of the key to add at
97
113
  * @param value The value to add
98
114
  */
99
- private _add(parts: Parts, value: T) {
115
+ private _add(parts: Parts, value: T): void {
100
116
  if (parts.length === 0) {
101
117
  this.#value = this.#value.concat(value);
102
118
  return;
103
119
  }
104
120
  const [first, ...rest] = parts;
121
+ // deno-coverage-ignore
122
+ if (first === undefined) return;
105
123
  const child = this.#children.get(first);
106
124
  if (child instanceof Trie) {
107
125
  child._add(rest, value);
@@ -110,7 +128,6 @@ export class Trie<T> {
110
128
  this.#children.set(first, node);
111
129
  node._add(rest, value);
112
130
  }
113
- return;
114
131
  }
115
132
 
116
133
  /**
@@ -118,7 +135,12 @@ export class Trie<T> {
118
135
  * @param key The key to remove the value from
119
136
  * @param value The value to remove
120
137
  */
121
- remove(key: string, value: T): void {
138
+ /**
139
+ * Removes a value from the trie at the specified key
140
+ * @param key The key to remove the value from
141
+ * @param value The value (or partial object) to remove
142
+ */
143
+ remove(key: string, value: Partial<T> | T): void {
122
144
  return this._remove(key.split(this.separator), value);
123
145
  }
124
146
 
@@ -127,17 +149,19 @@ export class Trie<T> {
127
149
  * @param parts Parts of the key to remove from
128
150
  * @param value The value to remove
129
151
  */
130
- private _remove(parts: Parts, value: T): void {
152
+ private _remove(parts: Parts, value: Partial<T> | T): void {
131
153
  if (parts.length === 0) {
132
- const arr = this.#value || [];
154
+ const arr = this.#value;
133
155
  this.#value = arr.filter(this.filter(value));
134
156
  return;
135
157
  }
136
158
  const [first, ...rest] = parts;
159
+ // deno-coverage-ignore
160
+ if (first === undefined) return;
137
161
  const node = this.#children.get(first);
138
162
  if (node) {
139
163
  node._remove(rest, value);
140
- if (node.#value.length === 0 && this.#children.size === 0) {
164
+ if (node.#value.length === 0 && node.#children.size === 0) {
141
165
  this.#children.delete(first);
142
166
  }
143
167
  }
@@ -145,20 +169,31 @@ export class Trie<T> {
145
169
 
146
170
  /**
147
171
  * Creates a filter function for removing values
148
- * @param value The value to filter against
149
- * @returns Filter function
172
+ * Supports partial object matching when looseCompare is enabled or when matching objects.
173
+ * @param value The value (or partial value) to filter against
174
+ * @returns Filter function (returns true to KEEP the item, false to REMOVE it)
150
175
  */
151
- private filter(value: T): (value: T, index: number, array: T[]) => boolean {
152
- if (this.looseCompare && typeof value === "object") {
176
+ private filter(value: Partial<T> | T): (item: T) => boolean {
177
+ if (typeof value === "object" && value !== null) {
153
178
  return (item) => {
179
+ if (typeof item !== "object" || item === null) {
180
+ return true; // Keep if the stored item isn't an object but we are filtering by one
181
+ }
182
+
183
+ // Check if every key-value pair in our filter object matches the stored item
154
184
  for (const key in value) {
155
- if (value[key] !== item[key]) {
156
- return true;
185
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
186
+ // If the stored item has a different value (or doesn't have the key), it's not a match
187
+ if (item[key] !== value[key]) {
188
+ return true; // Keep the item (no match)
189
+ }
157
190
  }
158
191
  }
159
- return false;
192
+ return false; // Remove the item (it matches all criteria in the partial object)
160
193
  };
161
194
  }
195
+
196
+ // Fallback for primitives
162
197
  return (item) => item !== value;
163
198
  }
164
199
  }
@@ -0,0 +1,92 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert";
3
+ import { BufferedAsyncIterable } from "./bufferedAsyncIterable.ts";
4
+
5
+ test("should initialize with correct default state", () => {
6
+ const iterable = new BufferedAsyncIterable<number>();
7
+ assert.strictEqual(iterable.isDone, false);
8
+ });
9
+
10
+ test("should handle immediate push and pull via next()", () => {
11
+ const iterable = new BufferedAsyncIterable<string>();
12
+
13
+ iterable.push("hello");
14
+ const result = iterable.next();
15
+
16
+ assert.strictEqual(result, "hello");
17
+ });
18
+
19
+ test("should resolve a pending next() call when data is pushed later", async () => {
20
+ const iterable = new BufferedAsyncIterable<number>();
21
+
22
+ const pendingPromise = iterable.next() as Promise<number>;
23
+
24
+ // The promise should resolve once we push data
25
+ iterable.push(42);
26
+
27
+ const result = await pendingPromise;
28
+ assert.strictEqual(result, 42);
29
+ });
30
+
31
+ test("should work correctly with for-await-of loop", async () => {
32
+ const iterable = new BufferedAsyncIterable<number>();
33
+ const items: number[] = [];
34
+
35
+ iterable.push(1);
36
+ iterable.push(2);
37
+
38
+ // Read items asynchronously
39
+ const consumer = async () => {
40
+ try {
41
+ for await (const item of iterable) {
42
+ items.push(item);
43
+ }
44
+ } catch (err) {
45
+ // Expecting a 'Closed' error to break the loop when close() is called
46
+ assert.match((err as Error).message, /closed/i);
47
+ }
48
+ };
49
+
50
+ const consumerPromise = consumer();
51
+
52
+ // Allow the event loop to process the items, then close the iterable
53
+ await new Promise((resolve) => setTimeout(resolve, 10));
54
+ iterable.close();
55
+
56
+ await consumerPromise;
57
+
58
+ assert.deepStrictEqual(items, [1, 2]);
59
+ });
60
+
61
+ test("should reject pending promises and throw when closed", async () => {
62
+ const iterable = new BufferedAsyncIterable<number>();
63
+
64
+ const pendingPromise = iterable.next() as Promise<number>;
65
+
66
+ iterable.close("custom close reason");
67
+
68
+ // The outstanding promise should now reject
69
+ await assert.rejects(pendingPromise, /custom close reason/);
70
+
71
+ // Subsequent calls to next() should instantly throw
72
+ assert.throws(() => iterable.next(), /Closed/);
73
+ });
74
+
75
+ test("should apply backpressure when buffer size is exceeded", async () => {
76
+ // Set a very small buffer size of 1 to easily trigger backpressure
77
+ const iterable = new BufferedAsyncIterable<number>(1);
78
+
79
+ // First item fills the queue size to 1 (equal to bufferSize, no backpressure yet)
80
+ iterable.push(1);
81
+
82
+ // Second item exceeds bufferSize (size becomes 2), returning a backpressure promise
83
+ const backpressurePromise = iterable.push(2);
84
+
85
+ assert.ok(
86
+ backpressurePromise instanceof Promise,
87
+ "Should return a promise due to backpressure",
88
+ );
89
+
90
+ // Wait for the backpressure timeout to resolve (proportional to buffer size, 2ms)
91
+ await backpressurePromise;
92
+ });
@@ -20,7 +20,7 @@ export class BufferedAsyncIterable<T> implements AsyncIterable<T> {
20
20
 
21
21
  private done = false;
22
22
 
23
- #next?: Deferred<T>;
23
+ #next?: Deferred<T> | undefined;
24
24
 
25
25
  constructor(bufferSize: number = 2048) {
26
26
  this.buffer = new ArrayQueue();
@@ -0,0 +1,36 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert";
3
+ import { Deferred } from "./deferred.ts"; // Note the .js extension if you are using ESM
4
+
5
+ test("should initialize with a pending promise", async () => {
6
+ const deferred = new Deferred<string>();
7
+
8
+ assert.ok(deferred.promise instanceof Promise);
9
+
10
+ // Verify it is indeed pending by racing it against a fast timeout
11
+ const timeout = new Promise((_, reject) =>
12
+ setTimeout(() => reject(new Error("Timeout")), 10)
13
+ );
14
+ await assert.rejects(Promise.race([deferred.promise, timeout]), /Timeout/);
15
+ });
16
+
17
+ test("should resolve the promise when resolve() is called", async () => {
18
+ const deferred = new Deferred<number>();
19
+
20
+ deferred.resolve(123);
21
+
22
+ const result = await deferred.promise;
23
+ assert.strictEqual(result, 123);
24
+ });
25
+
26
+ test("should reject the promise when reject() is called", async () => {
27
+ const deferred = new Deferred<void>();
28
+ const testError = new Error("Something went wrong");
29
+
30
+ deferred.reject(testError);
31
+
32
+ await assert.rejects(deferred.promise, (err: Error) => {
33
+ assert.strictEqual(err.message, "Something went wrong");
34
+ return true;
35
+ });
36
+ });
package/utils/deferred.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Create a promise that can be resolved/rejected later
3
3
  */
4
-
5
4
  export class Deferred<T> {
6
5
  promise: Promise<T>;
7
6
  resolve!: (val: T) => void;
@@ -0,0 +1,12 @@
1
+ /*
2
+ Node 26 has getOrInsert by default.
3
+ This is a polyfill for older versions
4
+ */
5
+
6
+ export function getOrInsert<K, V>(map: Map<K, V>, key: K, defaultValue: V): V {
7
+ if (map.has(key)) {
8
+ return map.get(key)!;
9
+ }
10
+ map.set(key, defaultValue);
11
+ return defaultValue;
12
+ }
@@ -0,0 +1,189 @@
1
+ import { mock, test } from "node:test";
2
+ import assert from "node:assert";
3
+ import { Logger, logger, LogLevel } from "./logger.ts";
4
+
5
+ // Helper to check if a function is the 'noop' function
6
+ // deno-lint-ignore ban-types
7
+ const isNoop = (fn: Function) =>
8
+ fn.name === "noop" || fn.toString().includes("noop");
9
+
10
+ test("default initialization", () => {
11
+ const testLogger = new Logger();
12
+
13
+ // By default, error, warn, and info should be active, while verbose/debug should be noop
14
+ assert.strictEqual(typeof testLogger.error, "function");
15
+ assert.strictEqual(typeof testLogger.warn, "function");
16
+ assert.strictEqual(typeof testLogger.info, "function");
17
+
18
+ assert.strictEqual(
19
+ isNoop(testLogger.verbose),
20
+ true,
21
+ "Verbose should be noop by default",
22
+ );
23
+ assert.strictEqual(
24
+ isNoop(testLogger.debug),
25
+ true,
26
+ "Debug should be noop by default",
27
+ );
28
+ });
29
+
30
+ test("level(LogLevel.error) activates only error", () => {
31
+ const testLogger = new Logger();
32
+ testLogger.level(LogLevel.error);
33
+
34
+ assert.strictEqual(
35
+ isNoop(testLogger.warn),
36
+ true,
37
+ "Warn should be noop at error level",
38
+ );
39
+ assert.strictEqual(
40
+ isNoop(testLogger.info),
41
+ true,
42
+ "Info should be noop at error level",
43
+ );
44
+ assert.strictEqual(
45
+ isNoop(testLogger.verbose),
46
+ true,
47
+ "Verbose should be noop at error level",
48
+ );
49
+ assert.strictEqual(
50
+ isNoop(testLogger.debug),
51
+ true,
52
+ "Debug should be noop at error level",
53
+ );
54
+ });
55
+
56
+ test("level(LogLevel.info) activates warn and info", () => {
57
+ const testLogger = new Logger();
58
+ testLogger.level(LogLevel.info);
59
+
60
+ assert.strictEqual(
61
+ isNoop(testLogger.warn),
62
+ false,
63
+ "Warn should be active at info level",
64
+ );
65
+ assert.strictEqual(
66
+ isNoop(testLogger.info),
67
+ false,
68
+ "Info should be active at info level",
69
+ );
70
+ assert.strictEqual(
71
+ isNoop(testLogger.verbose),
72
+ true,
73
+ "Verbose should be noop at info level",
74
+ );
75
+ assert.strictEqual(
76
+ isNoop(testLogger.debug),
77
+ true,
78
+ "Debug should be noop at info level",
79
+ );
80
+ });
81
+
82
+ test("level(LogLevel.debug) activates all loggers", () => {
83
+ const testLogger = new Logger();
84
+ testLogger.level(LogLevel.debug);
85
+
86
+ assert.strictEqual(isNoop(testLogger.warn), false);
87
+ assert.strictEqual(isNoop(testLogger.info), false);
88
+ assert.strictEqual(isNoop(testLogger.verbose), false);
89
+ assert.strictEqual(isNoop(testLogger.debug), false);
90
+ });
91
+
92
+ test("verify that log functions actually execute logging", () => {
93
+ const testLogger = new Logger();
94
+
95
+ // deno-lint-ignore no-explicit-any
96
+ const debugSpy = mock.method(testLogger as any, "defaultDebug");
97
+ // set the level, this will connect the spy
98
+ testLogger.level(LogLevel.debug);
99
+
100
+ testLogger.debug("Test debug message");
101
+
102
+ // check if the spy was called
103
+ assert.strictEqual(
104
+ debugSpy.mock.calls.length,
105
+ 1,
106
+ "The log method should be called exactly once",
107
+ );
108
+
109
+ // and if the parameters were passed correcty
110
+ assert.deepStrictEqual(debugSpy.mock.calls[0].arguments, [
111
+ "Test debug message",
112
+ ]);
113
+
114
+ // cleaunup the mock and restore state to normal
115
+ mock.restoreAll();
116
+ });
117
+
118
+ test("verify that the exported logger is an instance", () => {
119
+ assert.strictEqual(
120
+ logger instanceof Logger,
121
+ true,
122
+ "The exported logger must be a Logger instance",
123
+ );
124
+ });
125
+
126
+ test("should always return the exact same instance (Reference Check)", () => {
127
+ const firstImport = logger;
128
+ const secondImport = logger;
129
+
130
+ // Verify both references point to the exact same object in memory
131
+ assert.strictEqual(
132
+ firstImport,
133
+ secondImport,
134
+ "The exported logger must be a strict singleton reference",
135
+ );
136
+ });
137
+
138
+ test("should share state across the application (State Check)", () => {
139
+ // 1. Change the log level to Error
140
+ logger.level(LogLevel.error);
141
+
142
+ // 2. Verify the state change is reflected globally (debug should now be noop)
143
+ assert.strictEqual(
144
+ isNoop(logger.debug),
145
+ true,
146
+ "State changes should reflect globally",
147
+ );
148
+
149
+ // 3. Change it back to Debug and verify again
150
+ logger.level(LogLevel.debug);
151
+ assert.strictEqual(
152
+ isNoop(logger.debug),
153
+ false,
154
+ "State changes should reflect globally",
155
+ );
156
+ });
157
+
158
+ test("should not be the same as a newly instantiated Logger", () => {
159
+ const newInstance = new Logger();
160
+
161
+ // The singleton instance must be completely unique from manually created instances
162
+ assert.notStrictEqual(
163
+ logger,
164
+ newInstance,
165
+ "The singleton instance must be unique from new Logger() instances",
166
+ );
167
+ });
168
+
169
+ test("should perform lazy evaluation of log arguments", () => {
170
+ const testLogger = new Logger();
171
+ testLogger.level(LogLevel.debug);
172
+
173
+ let evaluationCount = 0;
174
+
175
+ const lazyArg = () => {
176
+ evaluationCount++;
177
+ return "Lazy evaluated message";
178
+ };
179
+
180
+ // Call debug with a lazy argument
181
+ testLogger.debug(lazyArg);
182
+
183
+ // The lazy argument should have been evaluated exactly once
184
+ assert.strictEqual(
185
+ evaluationCount,
186
+ 1,
187
+ "The lazy argument should be evaluated exactly once",
188
+ );
189
+ });
package/utils/logger.ts CHANGED
@@ -1,20 +1,32 @@
1
1
  import { noop } from "./utils.ts";
2
2
 
3
3
  /**
4
- * The available log levels
4
+ * The available log levels used to filter messages.
5
5
  */
6
6
  export const LogLevel = {
7
+ /** Crucial application errors or failures. */
7
8
  error: 0,
9
+ /** Non-fatal warnings that indicate unexpected behavior. */
8
10
  warn: 1,
11
+ /** Informational statements highlighting general operational flow. */
9
12
  info: 2,
13
+ /** Detailed tracing and comprehensive runtime statements. */
10
14
  verbose: 3,
15
+ /** High-density internal troubleshooting logs. */
11
16
  debug: 4,
12
17
  } as const;
13
18
 
19
+ /**
20
+ * Union type representing the permitted numeric log level indices.
21
+ */
14
22
  export type TLogLevel = typeof LogLevel[keyof typeof LogLevel];
15
23
 
24
+ type LogArgument = unknown | (() => unknown);
25
+
16
26
  /**
17
- * Simple logger class
27
+ * Simple logger class providing level-configurable output routing.
28
+ * @class Logger
29
+ *
18
30
  * @example
19
31
  * ```ts
20
32
  * const logger = new Logger();
@@ -27,30 +39,73 @@ export type TLogLevel = typeof LogLevel[keyof typeof LogLevel];
27
39
  * ```
28
40
  */
29
41
  export class Logger {
42
+ /** Native console reference used to output critical errors. */
30
43
  private defaultError = console.error;
44
+ /** Native console reference used to output warning flags. */
31
45
  private defaultWarn = console.warn;
46
+ /** Native console reference used to output standard runtime indicators. */
32
47
  private defaultInfo = console.info;
48
+ /** Native console reference used to track granular metrics and details. */
33
49
  private defaultVerbose = console.log;
50
+ /** Native console reference used to step through highly specific operations. */
34
51
  private defaultDebug = console.log;
35
52
 
53
+ /** Flag indicating if error messages should be logged. */
54
+ isError = true;
55
+ /** Flag indicating if warning messages should be logged. */
56
+ isWarn = true;
57
+ /** Flag indicating if informational messages should be logged. */
58
+ isInfo = true;
59
+ /** Flag indicating if verbose messages should be logged. */
60
+ isVerbose = false;
61
+ /** Flag indicating if debug messages should be logged. */
62
+ isDebug = false;
63
+
64
+ /** Log an error message to the standard error stream. */
36
65
  error: typeof console.log = this.defaultError;
66
+ /** Log a warning message if the active log level permits. */
37
67
  warn: typeof console.log = this.defaultWarn;
68
+ /** Log an informational status update if the active log level permits. */
38
69
  info: typeof console.log = this.defaultInfo;
70
+ /** Log extended telemetry notes if the active log level permits. */
39
71
  verbose: typeof console.log = noop;
72
+ /** Log debug parameters and objects if the active log level permits. */
40
73
  debug: typeof console.log = noop;
41
74
 
75
+ /** Creates a wrapper function that evaluates lazy log arguments before invoking the target logging function. */
76
+ // deno-lint-ignore no-explicit-any
77
+ private createLogFn(targetFn: (...args: any[]) => void) {
78
+ return (...args: LogArgument[]) => {
79
+ const evaluated = args.map((
80
+ arg,
81
+ ) => (typeof arg === "function" ? arg() : arg));
82
+ targetFn(...evaluated);
83
+ };
84
+ }
85
+
86
+ /** Create a new Logger instance. */
42
87
  constructor() {}
43
88
 
89
+ /**
90
+ * Adjusts the current verbosity threshold, enabling or masking specific log outputs.
91
+ * @param {TLogLevel} logLevel - The minimum numeric severity level threshold to output.
92
+ */
44
93
  level(logLevel: TLogLevel) {
45
- this.warn = logLevel > 0 ? this.defaultWarn : noop;
46
- this.info = logLevel > 1 ? this.defaultInfo : noop;
47
- this.verbose = logLevel > 2 ? this.defaultVerbose : noop;
48
- this.debug = logLevel > 3 ? this.defaultDebug : noop;
94
+ this.isWarn = logLevel >= LogLevel.warn;
95
+ this.isInfo = logLevel >= LogLevel.info;
96
+ this.isVerbose = logLevel >= LogLevel.verbose;
97
+ this.isDebug = logLevel >= LogLevel.debug;
98
+ this.warn = this.isWarn ? this.createLogFn(this.defaultWarn) : noop;
99
+ this.info = this.isInfo ? this.createLogFn(this.defaultInfo) : noop;
100
+ this.verbose = this.isVerbose
101
+ ? this.createLogFn(this.defaultVerbose)
102
+ : noop;
103
+ this.debug = this.isDebug ? this.createLogFn(this.defaultDebug) : noop;
49
104
  }
50
105
  }
51
106
 
52
107
  /**
53
- * logger provides a singleton logger instance
108
+ * Provides a single pre-configured global logger instance.
54
109
  * @example
55
110
  * ```ts
56
111
  * import { logger } from "./utils/logger.ts";
package/utils/mod.ts CHANGED
@@ -5,4 +5,18 @@
5
5
  export { assert } from "./assert.ts";
6
6
  export { Deferred } from "./deferred.ts";
7
7
  export { Logger, logger, LogLevel } from "./logger.ts";
8
- export { BufferedAsyncIterable } from "./BufferedAsyncIterable.ts";
8
+ export { BufferedAsyncIterable } from "./bufferedAsyncIterable.ts";
9
+ export {
10
+ joinTopicFilter,
11
+ parseTopicFilter,
12
+ topicFilterToRegExp,
13
+ } from "./topicFilter.ts";
14
+ export { OutboundTopicAliasManager } from "./outboundTopicAliasManager.ts";
15
+ export type { OutboundTopicAlias } from "./outboundTopicAliasManager.ts";
16
+ export {
17
+ hasWildcards,
18
+ invalidmaxTopicLevels,
19
+ invalidTopic,
20
+ invalidTopicFilter,
21
+ } from "./validators.ts";
22
+ export { delay, noop } from "./utils.ts";