@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
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
@@ -58,14 +58,11 @@ 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;
65
- if (first !== undefined) {
66
- return this.matchChild(first, rest);
67
- }
68
- return [];
62
+ if (first === undefined) return [];
63
+
64
+ // Direct lookup on the reserved topic node without evaluating top-level + or #
65
+ return this.matchChild(first, rest);
69
66
  }
70
67
 
71
68
  /**
@@ -74,18 +71,31 @@ export class Trie<T> {
74
71
  * @returns Array of matched values
75
72
  */
76
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.
77
84
  if (parts.length === 0) {
78
- return this.#value ? this.#value : [];
85
+ return results.concat(this.#value);
79
86
  }
87
+
80
88
  const [first, ...rest] = parts;
81
- if (first !== undefined) {
82
- const exact = this.matchChild(first, rest);
83
- const single = this.matchChild(this.wildcardOne, rest);
84
- const subtree = this.matchChild(this.wildcardSubtree, []);
85
- const results = exact.concat(single, subtree);
86
- return results;
87
- }
88
- return [];
89
+ // deno-coverage-ignore
90
+ if (first === undefined) return [];
91
+
92
+ // 3. Exact matching child node
93
+ const exact = this.matchChild(first, rest);
94
+
95
+ // 4. Single-level wildcard ('+') matching child node
96
+ const single = this.matchChild(this.wildcardOne, rest);
97
+
98
+ return results.concat(exact, single);
89
99
  }
90
100
 
91
101
  /**
@@ -102,23 +112,22 @@ export class Trie<T> {
102
112
  * @param parts Parts of the key to add at
103
113
  * @param value The value to add
104
114
  */
105
- private _add(parts: Parts, value: T) {
115
+ private _add(parts: Parts, value: T): void {
106
116
  if (parts.length === 0) {
107
117
  this.#value = this.#value.concat(value);
108
118
  return;
109
119
  }
110
120
  const [first, ...rest] = parts;
111
- if (first !== undefined) {
112
- const child = this.#children.get(first);
113
- if (child instanceof Trie) {
114
- child._add(rest, value);
115
- } else {
116
- const node = new Trie<T>(this.looseCompare);
117
- this.#children.set(first, node);
118
- node._add(rest, value);
119
- }
121
+ // deno-coverage-ignore
122
+ if (first === undefined) return;
123
+ const child = this.#children.get(first);
124
+ if (child instanceof Trie) {
125
+ child._add(rest, value);
126
+ } else {
127
+ const node = new Trie<T>(this.looseCompare);
128
+ this.#children.set(first, node);
129
+ node._add(rest, value);
120
130
  }
121
- return;
122
131
  }
123
132
 
124
133
  /**
@@ -126,7 +135,12 @@ export class Trie<T> {
126
135
  * @param key The key to remove the value from
127
136
  * @param value The value to remove
128
137
  */
129
- 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 {
130
144
  return this._remove(key.split(this.separator), value);
131
145
  }
132
146
 
@@ -135,40 +149,51 @@ export class Trie<T> {
135
149
  * @param parts Parts of the key to remove from
136
150
  * @param value The value to remove
137
151
  */
138
- private _remove(parts: Parts, value: T): void {
152
+ private _remove(parts: Parts, value: Partial<T> | T): void {
139
153
  if (parts.length === 0) {
140
- const arr = this.#value || [];
154
+ const arr = this.#value;
141
155
  this.#value = arr.filter(this.filter(value));
142
156
  return;
143
157
  }
144
158
  const [first, ...rest] = parts;
145
- if (first !== undefined) {
146
- const node = this.#children.get(first);
147
- if (node) {
148
- node._remove(rest, value);
149
- if (node.#value.length === 0 && this.#children.size === 0) {
150
- this.#children.delete(first);
151
- }
159
+ // deno-coverage-ignore
160
+ if (first === undefined) return;
161
+ const node = this.#children.get(first);
162
+ if (node) {
163
+ node._remove(rest, value);
164
+ if (node.#value.length === 0 && node.#children.size === 0) {
165
+ this.#children.delete(first);
152
166
  }
153
167
  }
154
168
  }
155
169
 
156
170
  /**
157
171
  * Creates a filter function for removing values
158
- * @param value The value to filter against
159
- * @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)
160
175
  */
161
- private filter(value: T): (value: T, index: number, array: T[]) => boolean {
162
- if (this.looseCompare && typeof value === "object") {
176
+ private filter(value: Partial<T> | T): (item: T) => boolean {
177
+ if (typeof value === "object" && value !== null) {
163
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
164
184
  for (const key in value) {
165
- if (value[key] !== item[key]) {
166
- 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
+ }
167
190
  }
168
191
  }
169
- return false;
192
+ return false; // Remove the item (it matches all criteria in the partial object)
170
193
  };
171
194
  }
195
+
196
+ // Fallback for primitives
172
197
  return (item) => item !== value;
173
198
  }
174
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
+ });
@@ -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
 
14
- export type TLogLevel = typeof LogLevel[keyof typeof LogLevel];
19
+ /**
20
+ * Union type representing the permitted numeric log level indices.
21
+ */
22
+ export type LogLevel = typeof LogLevel[keyof typeof LogLevel];
23
+
24
+ type LogArgument = unknown | (() => unknown);
15
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
 
44
- 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;
89
+ /**
90
+ * Adjusts the current verbosity threshold, enabling or masking specific log outputs.
91
+ * @param {LogLevel} logLevel - The minimum numeric severity level threshold to output.
92
+ */
93
+ level(logLevel: LogLevel) {
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";