@seriousme/opifex 1.11.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (542) hide show
  1. package/README.md +99 -40
  2. package/bin/conformanceServer.ts +45 -13
  3. package/bin/demoServer.ts +38 -13
  4. package/bin/mqtt.ts +2 -2
  5. package/client/ConnectionState.ts +3 -1
  6. package/client/client.ts +88 -47
  7. package/client/context.ts +79 -27
  8. package/client/deps.ts +10 -3
  9. package/client/handlers/handleAuth.test.ts +193 -0
  10. package/client/handlers/handleAuth.ts +89 -0
  11. package/client/handlers/handleConnack.test.ts +173 -0
  12. package/client/handlers/handleConnack.ts +18 -8
  13. package/client/handlers/handleDisconnect.test.ts +22 -0
  14. package/client/handlers/handleDisconnect.ts +17 -0
  15. package/client/handlers/handlePacket.test.ts +242 -0
  16. package/client/handlers/handlePacket.ts +19 -5
  17. package/client/handlers/handlePuback.test.ts +99 -0
  18. package/client/handlers/handlePuback.ts +6 -0
  19. package/client/handlers/handlePubcomp.test.ts +112 -0
  20. package/client/handlers/handlePubcomp.ts +5 -0
  21. package/client/handlers/handlePublish.test.ts +188 -0
  22. package/client/handlers/handlePubrec.test.ts +119 -0
  23. package/client/handlers/handlePubrec.ts +5 -1
  24. package/client/handlers/handlePubrel.test.ts +136 -0
  25. package/client/handlers/handleSuback.test.ts +122 -0
  26. package/client/handlers/handleSuback.ts +3 -0
  27. package/client/handlers/handleUnsuback.test.ts +101 -0
  28. package/client/mod.ts +13 -2
  29. package/client/store/memoryStore.ts +12 -11
  30. package/client/store/store.ts +4 -2
  31. package/deno/README.md +1 -2
  32. package/deno/tcpClient.test.ts +75 -0
  33. package/deno/tcpClient.ts +36 -18
  34. package/deno/tcpServer.test.ts +22 -21
  35. package/deno/tcpServer.ts +26 -4
  36. package/deno/tlsServer.test.ts +97 -0
  37. package/deno/tlsServer.ts +58 -0
  38. package/deno/wsServer.test.ts +93 -0
  39. package/deno/wsServer.ts +96 -0
  40. package/dev_utils/generateCert.ts +95 -0
  41. package/dev_utils/mockConn.ts +36 -0
  42. package/dev_utils/mockServer.ts +28 -0
  43. package/dev_utils/mod.ts +30 -3
  44. package/dev_utils/packetHelpers.ts +404 -0
  45. package/dev_utils/test-handlers.ts +98 -0
  46. package/dev_utils/timers.ts +14 -0
  47. package/dev_utils/webStreamPair.test.ts +171 -0
  48. package/dev_utils/webStreamPair.ts +143 -0
  49. package/dist/bin/conformanceServer.js +17 -12
  50. package/dist/bin/conformanceServer.js.map +1 -1
  51. package/dist/bin/demoServer.js +16 -12
  52. package/dist/bin/demoServer.js.map +1 -1
  53. package/dist/bin/mqtt.js +2 -2
  54. package/dist/bin/mqtt.js.map +1 -1
  55. package/dist/client/ConnectionState.d.ts +3 -1
  56. package/dist/client/ConnectionState.d.ts.map +1 -1
  57. package/dist/client/ConnectionState.js +2 -0
  58. package/dist/client/ConnectionState.js.map +1 -1
  59. package/dist/client/client.d.ts +47 -21
  60. package/dist/client/client.d.ts.map +1 -1
  61. package/dist/client/client.js +57 -20
  62. package/dist/client/client.js.map +1 -1
  63. package/dist/client/context.d.ts +15 -7
  64. package/dist/client/context.d.ts.map +1 -1
  65. package/dist/client/context.js +44 -12
  66. package/dist/client/context.js.map +1 -1
  67. package/dist/client/deps.d.ts +4 -3
  68. package/dist/client/deps.d.ts.map +1 -1
  69. package/dist/client/deps.js +1 -1
  70. package/dist/client/deps.js.map +1 -1
  71. package/dist/client/handlers/handleAuth.d.ts +9 -0
  72. package/dist/client/handlers/handleAuth.d.ts.map +1 -0
  73. package/dist/client/handlers/handleAuth.js +66 -0
  74. package/dist/client/handlers/handleAuth.js.map +1 -0
  75. package/dist/client/handlers/handleConnack.d.ts +2 -2
  76. package/dist/client/handlers/handleConnack.d.ts.map +1 -1
  77. package/dist/client/handlers/handleConnack.js +16 -6
  78. package/dist/client/handlers/handleConnack.js.map +1 -1
  79. package/dist/client/handlers/handleDisconnect.d.ts +11 -0
  80. package/dist/client/handlers/handleDisconnect.d.ts.map +1 -0
  81. package/dist/client/handlers/handleDisconnect.js +15 -0
  82. package/dist/client/handlers/handleDisconnect.js.map +1 -0
  83. package/dist/client/handlers/handlePacket.d.ts.map +1 -1
  84. package/dist/client/handlers/handlePacket.js +14 -3
  85. package/dist/client/handlers/handlePacket.js.map +1 -1
  86. package/dist/client/handlers/handlePuback.d.ts.map +1 -1
  87. package/dist/client/handlers/handlePuback.js +5 -0
  88. package/dist/client/handlers/handlePuback.js.map +1 -1
  89. package/dist/client/handlers/handlePubcomp.d.ts.map +1 -1
  90. package/dist/client/handlers/handlePubcomp.js +5 -0
  91. package/dist/client/handlers/handlePubcomp.js.map +1 -1
  92. package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
  93. package/dist/client/handlers/handlePubrec.js +5 -1
  94. package/dist/client/handlers/handlePubrec.js.map +1 -1
  95. package/dist/client/handlers/handleSuback.d.ts +1 -0
  96. package/dist/client/handlers/handleSuback.d.ts.map +1 -1
  97. package/dist/client/handlers/handleSuback.js +3 -0
  98. package/dist/client/handlers/handleSuback.js.map +1 -1
  99. package/dist/client/mod.d.ts +3 -2
  100. package/dist/client/mod.d.ts.map +1 -1
  101. package/dist/client/mod.js +1 -1
  102. package/dist/client/mod.js.map +1 -1
  103. package/dist/client/store/memoryStore.d.ts +3 -3
  104. package/dist/client/store/memoryStore.d.ts.map +1 -1
  105. package/dist/client/store/memoryStore.js +3 -3
  106. package/dist/client/store/memoryStore.js.map +1 -1
  107. package/dist/client/store/store.d.ts +3 -2
  108. package/dist/client/store/store.d.ts.map +1 -1
  109. package/dist/client/store/store.js +1 -1
  110. package/dist/client/store/store.js.map +1 -1
  111. package/dist/dev_utils/generateCert.d.ts +11 -0
  112. package/dist/dev_utils/generateCert.d.ts.map +1 -0
  113. package/dist/dev_utils/generateCert.js +76 -0
  114. package/dist/dev_utils/generateCert.js.map +1 -0
  115. package/dist/examples/authHandler.test.d.ts +2 -0
  116. package/dist/examples/authHandler.test.d.ts.map +1 -0
  117. package/dist/examples/authHandler.test.js +123 -0
  118. package/dist/examples/authHandler.test.js.map +1 -0
  119. package/dist/examples/mqtt.test.d.ts +2 -0
  120. package/dist/examples/mqtt.test.d.ts.map +1 -0
  121. package/dist/examples/mqtt.test.js +70 -0
  122. package/dist/examples/mqtt.test.js.map +1 -0
  123. package/dist/examples/mqtts.test.d.ts +2 -0
  124. package/dist/examples/mqtts.test.d.ts.map +1 -0
  125. package/dist/examples/mqtts.test.js +81 -0
  126. package/dist/examples/mqtts.test.js.map +1 -0
  127. package/dist/mqttConn/mqttConn.d.ts +24 -31
  128. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  129. package/dist/mqttConn/mqttConn.js +57 -36
  130. package/dist/mqttConn/mqttConn.js.map +1 -1
  131. package/dist/mqttPacket/AuthenticationResult.d.ts +4 -0
  132. package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
  133. package/dist/mqttPacket/AuthenticationResult.js.map +1 -1
  134. package/dist/mqttPacket/BitMask.d.ts.map +1 -1
  135. package/dist/mqttPacket/PacketType.d.ts +4 -0
  136. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  137. package/dist/mqttPacket/Properties.d.ts +4 -4
  138. package/dist/mqttPacket/Properties.d.ts.map +1 -1
  139. package/dist/mqttPacket/Properties.js.map +1 -1
  140. package/dist/mqttPacket/ReasonCode.d.ts +4 -5
  141. package/dist/mqttPacket/ReasonCode.d.ts.map +1 -1
  142. package/dist/mqttPacket/ReasonCode.js +1 -0
  143. package/dist/mqttPacket/ReasonCode.js.map +1 -1
  144. package/dist/mqttPacket/RetainHandling.d.ts +4 -0
  145. package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
  146. package/dist/mqttPacket/auth.d.ts +7 -8
  147. package/dist/mqttPacket/auth.d.ts.map +1 -1
  148. package/dist/mqttPacket/auth.js +31 -30
  149. package/dist/mqttPacket/auth.js.map +1 -1
  150. package/dist/mqttPacket/codec.d.ts +48 -0
  151. package/dist/mqttPacket/codec.d.ts.map +1 -0
  152. package/dist/mqttPacket/codec.js +93 -0
  153. package/dist/mqttPacket/codec.js.map +1 -0
  154. package/dist/mqttPacket/connack.d.ts +11 -10
  155. package/dist/mqttPacket/connack.d.ts.map +1 -1
  156. package/dist/mqttPacket/connack.js +43 -45
  157. package/dist/mqttPacket/connack.js.map +1 -1
  158. package/dist/mqttPacket/connect.d.ts +7 -7
  159. package/dist/mqttPacket/connect.d.ts.map +1 -1
  160. package/dist/mqttPacket/connect.js +156 -157
  161. package/dist/mqttPacket/connect.js.map +1 -1
  162. package/dist/mqttPacket/decoder.d.ts +6 -16
  163. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  164. package/dist/mqttPacket/decoder.js +7 -28
  165. package/dist/mqttPacket/decoder.js.map +1 -1
  166. package/dist/mqttPacket/disconnect.d.ts +9 -8
  167. package/dist/mqttPacket/disconnect.d.ts.map +1 -1
  168. package/dist/mqttPacket/disconnect.js +41 -43
  169. package/dist/mqttPacket/disconnect.js.map +1 -1
  170. package/dist/mqttPacket/encoder.d.ts +7 -19
  171. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  172. package/dist/mqttPacket/encoder.js +5 -28
  173. package/dist/mqttPacket/encoder.js.map +1 -1
  174. package/dist/mqttPacket/mod.d.ts +21 -103
  175. package/dist/mqttPacket/mod.d.ts.map +1 -1
  176. package/dist/mqttPacket/mod.js +5 -94
  177. package/dist/mqttPacket/mod.js.map +1 -1
  178. package/dist/mqttPacket/pingreq.d.ts +6 -6
  179. package/dist/mqttPacket/pingreq.d.ts.map +1 -1
  180. package/dist/mqttPacket/pingreq.js +11 -13
  181. package/dist/mqttPacket/pingreq.js.map +1 -1
  182. package/dist/mqttPacket/pingres.d.ts +6 -6
  183. package/dist/mqttPacket/pingres.d.ts.map +1 -1
  184. package/dist/mqttPacket/pingres.js +11 -13
  185. package/dist/mqttPacket/pingres.js.map +1 -1
  186. package/dist/mqttPacket/protocolLevels.d.ts +11 -6
  187. package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
  188. package/dist/mqttPacket/protocolLevels.js +5 -1
  189. package/dist/mqttPacket/protocolLevels.js.map +1 -1
  190. package/dist/mqttPacket/pubblishAcks.d.ts +9 -10
  191. package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
  192. package/dist/mqttPacket/pubblishAcks.js +43 -45
  193. package/dist/mqttPacket/pubblishAcks.js.map +1 -1
  194. package/dist/mqttPacket/publish.d.ts +8 -7
  195. package/dist/mqttPacket/publish.d.ts.map +1 -1
  196. package/dist/mqttPacket/publish.js +53 -55
  197. package/dist/mqttPacket/publish.js.map +1 -1
  198. package/dist/mqttPacket/suback.d.ts +9 -8
  199. package/dist/mqttPacket/suback.d.ts.map +1 -1
  200. package/dist/mqttPacket/suback.js +38 -40
  201. package/dist/mqttPacket/suback.js.map +1 -1
  202. package/dist/mqttPacket/subscribe.d.ts +41 -10
  203. package/dist/mqttPacket/subscribe.d.ts.map +1 -1
  204. package/dist/mqttPacket/subscribe.js +90 -89
  205. package/dist/mqttPacket/subscribe.js.map +1 -1
  206. package/dist/mqttPacket/types.d.ts +2 -29
  207. package/dist/mqttPacket/types.d.ts.map +1 -1
  208. package/dist/mqttPacket/unsuback.d.ts +9 -8
  209. package/dist/mqttPacket/unsuback.d.ts.map +1 -1
  210. package/dist/mqttPacket/unsuback.js +32 -34
  211. package/dist/mqttPacket/unsuback.js.map +1 -1
  212. package/dist/mqttPacket/unsubscribe.d.ts +26 -8
  213. package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
  214. package/dist/mqttPacket/unsubscribe.js +45 -44
  215. package/dist/mqttPacket/unsubscribe.js.map +1 -1
  216. package/dist/mqttPacket/validators.d.ts +4 -16
  217. package/dist/mqttPacket/validators.d.ts.map +1 -1
  218. package/dist/mqttPacket/validators.js +5 -26
  219. package/dist/mqttPacket/validators.js.map +1 -1
  220. package/dist/node/tcpClient.d.ts +22 -2
  221. package/dist/node/tcpClient.d.ts.map +1 -1
  222. package/dist/node/tcpClient.js +29 -10
  223. package/dist/node/tcpClient.js.map +1 -1
  224. package/dist/node/tcpServer.d.ts +18 -0
  225. package/dist/node/tcpServer.d.ts.map +1 -1
  226. package/dist/node/tcpServer.js +21 -2
  227. package/dist/node/tcpServer.js.map +1 -1
  228. package/dist/node/tlsServer.d.ts +37 -0
  229. package/dist/node/tlsServer.d.ts.map +1 -0
  230. package/dist/node/tlsServer.js +73 -0
  231. package/dist/node/tlsServer.js.map +1 -0
  232. package/dist/node/wrapNodeSocket.d.ts.map +1 -1
  233. package/dist/node/wrapNodeSocket.js +6 -28
  234. package/dist/node/wrapNodeSocket.js.map +1 -1
  235. package/dist/persistence/basicPersistence.d.ts +36 -0
  236. package/dist/persistence/basicPersistence.d.ts.map +1 -0
  237. package/dist/persistence/basicPersistence.js +306 -0
  238. package/dist/persistence/basicPersistence.js.map +1 -0
  239. package/dist/persistence/deps.d.ts +3 -2
  240. package/dist/persistence/deps.d.ts.map +1 -1
  241. package/dist/persistence/deps.js +2 -1
  242. package/dist/persistence/deps.js.map +1 -1
  243. package/dist/persistence/memory/memoryPersistence.d.ts +6 -23
  244. package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
  245. package/dist/persistence/memory/memoryPersistence.js +12 -115
  246. package/dist/persistence/memory/memoryPersistence.js.map +1 -1
  247. package/dist/persistence/memory/memoryStorage.d.ts +45 -0
  248. package/dist/persistence/memory/memoryStorage.d.ts.map +1 -0
  249. package/dist/persistence/memory/memoryStorage.js +143 -0
  250. package/dist/persistence/memory/memoryStorage.js.map +1 -0
  251. package/dist/persistence/mod.d.ts +3 -3
  252. package/dist/persistence/mod.d.ts.map +1 -1
  253. package/dist/persistence/mod.js +6 -1
  254. package/dist/persistence/mod.js.map +1 -1
  255. package/dist/persistence/persistence.d.ts +45 -70
  256. package/dist/persistence/persistence.d.ts.map +1 -1
  257. package/dist/persistence/persistence.js +1 -2
  258. package/dist/persistence/persistence.js.map +1 -1
  259. package/dist/persistence/sqlite/sqliteDatabase.d.ts +46 -0
  260. package/dist/persistence/sqlite/sqliteDatabase.d.ts.map +1 -0
  261. package/dist/persistence/sqlite/sqliteDatabase.js +215 -0
  262. package/dist/persistence/sqlite/sqliteDatabase.js.map +1 -0
  263. package/dist/persistence/sqlite/sqlitePersistence.d.ts +16 -0
  264. package/dist/persistence/sqlite/sqlitePersistence.d.ts.map +1 -0
  265. package/dist/persistence/sqlite/sqlitePersistence.js +29 -0
  266. package/dist/persistence/sqlite/sqlitePersistence.js.map +1 -0
  267. package/dist/persistence/sqlite/sqliteStorage.d.ts +36 -0
  268. package/dist/persistence/sqlite/sqliteStorage.d.ts.map +1 -0
  269. package/dist/persistence/sqlite/sqliteStorage.js +194 -0
  270. package/dist/persistence/sqlite/sqliteStorage.js.map +1 -0
  271. package/dist/persistence/storage.d.ts +38 -0
  272. package/dist/persistence/storage.d.ts.map +1 -0
  273. package/dist/persistence/storage.js +5 -0
  274. package/dist/persistence/storage.js.map +1 -0
  275. package/dist/server/config.d.ts +47 -0
  276. package/dist/server/config.d.ts.map +1 -0
  277. package/dist/server/config.js +41 -0
  278. package/dist/server/config.js.map +1 -0
  279. package/dist/server/context.d.ts +199 -25
  280. package/dist/server/context.d.ts.map +1 -1
  281. package/dist/server/context.js +432 -53
  282. package/dist/server/context.js.map +1 -1
  283. package/dist/server/deps.d.ts +5 -6
  284. package/dist/server/deps.d.ts.map +1 -1
  285. package/dist/server/deps.js +2 -2
  286. package/dist/server/deps.js.map +1 -1
  287. package/dist/server/handlers/completeConnect.d.ts +9 -0
  288. package/dist/server/handlers/completeConnect.d.ts.map +1 -0
  289. package/dist/server/handlers/completeConnect.js +74 -0
  290. package/dist/server/handlers/completeConnect.js.map +1 -0
  291. package/dist/server/handlers/handleAuth.d.ts +9 -0
  292. package/dist/server/handlers/handleAuth.d.ts.map +1 -0
  293. package/dist/server/handlers/handleAuth.js +69 -0
  294. package/dist/server/handlers/handleAuth.js.map +1 -0
  295. package/dist/server/handlers/handleConnect.d.ts +2 -4
  296. package/dist/server/handlers/handleConnect.d.ts.map +1 -1
  297. package/dist/server/handlers/handleConnect.js +140 -67
  298. package/dist/server/handlers/handleConnect.js.map +1 -1
  299. package/dist/server/handlers/handleDisconnect.d.ts +1 -1
  300. package/dist/server/handlers/handleDisconnect.d.ts.map +1 -1
  301. package/dist/server/handlers/handleDisconnect.js +3 -3
  302. package/dist/server/handlers/handleDisconnect.js.map +1 -1
  303. package/dist/server/handlers/handlePacket.d.ts.map +1 -1
  304. package/dist/server/handlers/handlePacket.js +19 -6
  305. package/dist/server/handlers/handlePacket.js.map +1 -1
  306. package/dist/server/handlers/handlePuback.d.ts +1 -3
  307. package/dist/server/handlers/handlePuback.d.ts.map +1 -1
  308. package/dist/server/handlers/handlePuback.js +2 -8
  309. package/dist/server/handlers/handlePuback.js.map +1 -1
  310. package/dist/server/handlers/handlePubcomp.d.ts +1 -1
  311. package/dist/server/handlers/handlePubcomp.d.ts.map +1 -1
  312. package/dist/server/handlers/handlePubcomp.js +2 -4
  313. package/dist/server/handlers/handlePubcomp.js.map +1 -1
  314. package/dist/server/handlers/handlePublish.d.ts +1 -1
  315. package/dist/server/handlers/handlePublish.d.ts.map +1 -1
  316. package/dist/server/handlers/handlePublish.js +149 -45
  317. package/dist/server/handlers/handlePublish.js.map +1 -1
  318. package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
  319. package/dist/server/handlers/handlePubrec.js +2 -3
  320. package/dist/server/handlers/handlePubrec.js.map +1 -1
  321. package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
  322. package/dist/server/handlers/handlePubrel.js +6 -2
  323. package/dist/server/handlers/handlePubrel.js.map +1 -1
  324. package/dist/server/handlers/handleSubscribe.d.ts +1 -6
  325. package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
  326. package/dist/server/handlers/handleSubscribe.js +99 -38
  327. package/dist/server/handlers/handleSubscribe.js.map +1 -1
  328. package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
  329. package/dist/server/handlers/handleUnsubscribe.js +19 -4
  330. package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
  331. package/dist/server/mod.d.ts +3 -3
  332. package/dist/server/mod.d.ts.map +1 -1
  333. package/dist/server/mod.js +1 -1
  334. package/dist/server/mod.js.map +1 -1
  335. package/dist/server/server.d.ts +32 -9
  336. package/dist/server/server.d.ts.map +1 -1
  337. package/dist/server/server.js +84 -15
  338. package/dist/server/server.js.map +1 -1
  339. package/dist/socket/socket.d.ts +15 -9
  340. package/dist/socket/socket.d.ts.map +1 -1
  341. package/dist/socket/socket.js +66 -18
  342. package/dist/socket/socket.js.map +1 -1
  343. package/dist/timer/timer.d.ts +32 -0
  344. package/dist/timer/timer.d.ts.map +1 -1
  345. package/dist/timer/timer.js +32 -0
  346. package/dist/timer/timer.js.map +1 -1
  347. package/dist/trie/trie.d.ts +10 -5
  348. package/dist/trie/trie.d.ts.map +1 -1
  349. package/dist/trie/trie.js +61 -41
  350. package/dist/trie/trie.js.map +1 -1
  351. package/dist/utils/assert.d.ts.map +1 -1
  352. package/dist/utils/{BufferedAsyncIterable.d.ts → bufferedAsyncIterable.d.ts} +1 -1
  353. package/dist/utils/bufferedAsyncIterable.d.ts.map +1 -0
  354. package/dist/utils/{BufferedAsyncIterable.js → bufferedAsyncIterable.js} +1 -1
  355. package/dist/utils/bufferedAsyncIterable.js.map +1 -0
  356. package/dist/utils/deferred.d.ts.map +1 -1
  357. package/dist/utils/deferred.js.map +1 -1
  358. package/dist/utils/getOrInsertPolyFill.d.ts +2 -0
  359. package/dist/utils/getOrInsertPolyFill.d.ts.map +1 -0
  360. package/dist/utils/getOrInsertPolyFill.js +12 -0
  361. package/dist/utils/getOrInsertPolyFill.js.map +1 -0
  362. package/dist/utils/logger.d.ts +42 -5
  363. package/dist/utils/logger.d.ts.map +1 -1
  364. package/dist/utils/logger.js +53 -7
  365. package/dist/utils/logger.js.map +1 -1
  366. package/dist/utils/mod.d.ts +6 -1
  367. package/dist/utils/mod.d.ts.map +1 -1
  368. package/dist/utils/mod.js +5 -1
  369. package/dist/utils/mod.js.map +1 -1
  370. package/dist/utils/outboundTopicAliasManager.d.ts +52 -0
  371. package/dist/utils/outboundTopicAliasManager.d.ts.map +1 -0
  372. package/dist/utils/outboundTopicAliasManager.js +74 -0
  373. package/dist/utils/outboundTopicAliasManager.js.map +1 -0
  374. package/dist/utils/queue.d.ts.map +1 -1
  375. package/dist/utils/topicFilter.d.ts +32 -0
  376. package/dist/utils/topicFilter.d.ts.map +1 -0
  377. package/dist/utils/topicFilter.js +52 -0
  378. package/dist/utils/topicFilter.js.map +1 -0
  379. package/dist/utils/utils.d.ts +2 -0
  380. package/dist/utils/utils.d.ts.map +1 -1
  381. package/dist/utils/utils.js +2 -0
  382. package/dist/utils/utils.js.map +1 -1
  383. package/dist/utils/validators.d.ts +34 -0
  384. package/dist/utils/validators.d.ts.map +1 -0
  385. package/dist/utils/validators.js +61 -0
  386. package/dist/utils/validators.js.map +1 -0
  387. package/dist/web/webSocketStream.d.ts +29 -0
  388. package/dist/web/webSocketStream.d.ts.map +1 -0
  389. package/dist/web/webSocketStream.js +69 -0
  390. package/dist/web/webSocketStream.js.map +1 -0
  391. package/dist/web/wrapWebSocket.d.ts +12 -0
  392. package/dist/web/wrapWebSocket.d.ts.map +1 -0
  393. package/dist/web/wrapWebSocket.js +41 -0
  394. package/dist/web/wrapWebSocket.js.map +1 -0
  395. package/dist/web/wsClient.d.ts +14 -0
  396. package/dist/web/wsClient.d.ts.map +1 -0
  397. package/dist/web/wsClient.js +33 -0
  398. package/dist/web/wsClient.js.map +1 -0
  399. package/dist/web/wsClient.test.d.ts +2 -0
  400. package/dist/web/wsClient.test.d.ts.map +1 -0
  401. package/dist/web/wsClient.test.js +20 -0
  402. package/dist/web/wsClient.test.js.map +1 -0
  403. package/examples/authHandler.test.ts +164 -0
  404. package/examples/mqtt.test.ts +89 -0
  405. package/examples/mqtts.test.ts +100 -0
  406. package/examples/webSocket.test.ts +94 -0
  407. package/mqttConn/mqttConn.test.ts +9 -9
  408. package/mqttConn/mqttConn.ts +76 -60
  409. package/mqttPacket/AuthenticationResult.ts +6 -0
  410. package/mqttPacket/PacketType.ts +5 -0
  411. package/mqttPacket/Properties.ts +8 -5
  412. package/mqttPacket/ReasonCode.ts +8 -9
  413. package/mqttPacket/RetainHandling.ts +5 -0
  414. package/mqttPacket/auth.test.ts +1 -1
  415. package/mqttPacket/auth.ts +44 -51
  416. package/mqttPacket/codec.ts +147 -0
  417. package/mqttPacket/connack.ts +63 -73
  418. package/mqttPacket/connect.test.ts +2 -2
  419. package/mqttPacket/connect.ts +178 -192
  420. package/mqttPacket/decoder.test.ts +0 -39
  421. package/mqttPacket/decoder.ts +17 -46
  422. package/mqttPacket/disconnect.ts +60 -71
  423. package/mqttPacket/encoder.test.ts +2 -2
  424. package/mqttPacket/encoder.ts +13 -46
  425. package/mqttPacket/mod.ts +48 -204
  426. package/mqttPacket/pingreq.ts +22 -28
  427. package/mqttPacket/pingres.ts +22 -28
  428. package/mqttPacket/protocolLevels.ts +12 -7
  429. package/mqttPacket/pubblishAcks.ts +61 -75
  430. package/mqttPacket/publish.ts +70 -84
  431. package/mqttPacket/publishAcks.test.ts +3 -3
  432. package/mqttPacket/suback.ts +53 -68
  433. package/mqttPacket/subscribe.ts +146 -128
  434. package/mqttPacket/types.ts +2 -35
  435. package/mqttPacket/unsuback.ts +50 -61
  436. package/mqttPacket/unsubscribe.ts +77 -72
  437. package/mqttPacket/validators.ts +5 -31
  438. package/node/socket-node-stream.test.ts +322 -0
  439. package/node/socket-node-stream.ts +174 -0
  440. package/node/tcpClient.test.ts +70 -0
  441. package/node/tcpClient.ts +33 -17
  442. package/node/tcpServer.test.ts +24 -20
  443. package/node/tcpServer.ts +29 -6
  444. package/node/tlsServer.test.ts +94 -0
  445. package/node/tlsServer.ts +97 -0
  446. package/node/wrapNodeSocket.ts +7 -30
  447. package/package.json +72 -44
  448. package/persistence/basicPersistence.ts +495 -0
  449. package/persistence/deps.ts +11 -1
  450. package/persistence/memory/memoryPersistence.ts +12 -153
  451. package/persistence/memory/memoryStorage.ts +232 -0
  452. package/persistence/mod.ts +5 -10
  453. package/persistence/persistence.test.ts +24 -0
  454. package/persistence/persistence.testing.ts +1324 -0
  455. package/persistence/persistence.ts +112 -68
  456. package/persistence/sqlite/sqliteDatabase.ts +294 -0
  457. package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
  458. package/persistence/sqlite/sqlitePersistence.ts +36 -0
  459. package/persistence/sqlite/sqliteStorage.ts +324 -0
  460. package/persistence/storage.ts +84 -0
  461. package/server/config.ts +65 -0
  462. package/server/context.ts +660 -76
  463. package/server/deps.ts +24 -5
  464. package/server/handlers/completeConnect.ts +93 -0
  465. package/server/handlers/duplicate.test.ts +196 -0
  466. package/server/handlers/handleAuth.test.ts +225 -0
  467. package/server/handlers/handleAuth.ts +88 -0
  468. package/server/handlers/handleConnect.test.ts +589 -0
  469. package/server/handlers/handleConnect.ts +201 -86
  470. package/server/handlers/handleConnect.version.test.ts +108 -0
  471. package/server/handlers/handleDisconnect.test.ts +56 -0
  472. package/server/handlers/handleDisconnect.ts +3 -3
  473. package/server/handlers/handlePacket.test.ts +24 -0
  474. package/server/handlers/handlePacket.ts +30 -8
  475. package/server/handlers/handlePingreq.test.ts +29 -0
  476. package/server/handlers/handlePuback.test.ts +28 -0
  477. package/server/handlers/handlePuback.ts +5 -8
  478. package/server/handlers/handlePubcomp.test.ts +28 -0
  479. package/server/handlers/handlePubcomp.ts +5 -4
  480. package/server/handlers/handlePublish.test.ts +471 -0
  481. package/server/handlers/handlePublish.ts +188 -35
  482. package/server/handlers/handlePubrec.test.ts +28 -0
  483. package/server/handlers/handlePubrec.ts +2 -3
  484. package/server/handlers/handlePubrel.test.ts +74 -0
  485. package/server/handlers/handlePubrel.ts +12 -2
  486. package/server/handlers/handleSubscribe.test.ts +971 -0
  487. package/server/handlers/handleSubscribe.ts +157 -39
  488. package/server/handlers/handleUnsubscribe.test.ts +79 -0
  489. package/server/handlers/handleUnsubscribe.ts +28 -4
  490. package/server/handlers/keepalive.test.ts +132 -0
  491. package/server/handlers/session.persistence.test.ts +194 -0
  492. package/server/handlers/will.delivery.test.ts +221 -0
  493. package/server/mod.ts +5 -4
  494. package/server/preconnect.test.ts +151 -0
  495. package/server/server.ts +117 -19
  496. package/socket/socket.test.ts +91 -0
  497. package/socket/socket.ts +85 -34
  498. package/timer/timer.test.ts +4 -7
  499. package/timer/timer.ts +36 -0
  500. package/tools/benchmarks/receiver.ts +51 -0
  501. package/tools/benchmarks/sender.ts +48 -0
  502. package/tools/benchmarks/utils.ts +31 -0
  503. package/tools/mqtt-compat/README.md +130 -0
  504. package/tools/mqtt-compat/broker.ts +52 -0
  505. package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
  506. package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
  507. package/trie/trie.test.ts +9 -1
  508. package/trie/trie.ts +70 -45
  509. package/utils/bufferedAsyncIterable.test.ts +92 -0
  510. package/utils/deferred.test.ts +36 -0
  511. package/utils/deferred.ts +0 -1
  512. package/utils/getOrInsertPolyFill.ts +12 -0
  513. package/utils/logger.test.ts +189 -0
  514. package/utils/logger.ts +64 -9
  515. package/utils/mod.ts +15 -1
  516. package/utils/outboundTopicAliasManager.ts +100 -0
  517. package/utils/queue.test.ts +61 -0
  518. package/utils/topicFilter.test.ts +63 -0
  519. package/utils/topicFilter.ts +61 -0
  520. package/utils/utils.ts +3 -0
  521. package/utils/validators.ts +67 -0
  522. package/web/webSocketStream.ts +97 -0
  523. package/web/wrapWebSocket.ts +52 -0
  524. package/web/wsClient.test.ts +26 -0
  525. package/web/wsClient.ts +37 -0
  526. package/benchmarks/receiver.ts +0 -35
  527. package/benchmarks/sender.ts +0 -32
  528. package/benchmarks/utils.ts +0 -9
  529. package/dev_utils/dummyConn.ts +0 -110
  530. package/dev_utils/socketPair.ts +0 -85
  531. package/dist/persistence/store.d.ts +0 -14
  532. package/dist/persistence/store.d.ts.map +0 -1
  533. package/dist/persistence/store.js +0 -2
  534. package/dist/persistence/store.js.map +0 -1
  535. package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
  536. package/dist/utils/BufferedAsyncIterable.js.map +0 -1
  537. package/examples/tcpServer.test.ts +0 -148
  538. package/persistence/memory/memoryPersistence.test.ts +0 -156
  539. package/persistence/store.ts +0 -16
  540. package/server/test/handleConnect.test.ts +0 -122
  541. package/server/test/test-handlers.ts +0 -53
  542. /package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +0 -0
@@ -0,0 +1,89 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { TcpClient } from "@seriousme/opifex/tcpClient";
4
+ import { TcpServer } from "@seriousme/opifex/tcpServer";
5
+ import { delay, logger, LogLevel } from "@seriousme/opifex/utils";
6
+ import type { PublishPacket, QoS } from "@seriousme/opifex/mqttPacket";
7
+
8
+ logger.level(LogLevel.info);
9
+
10
+ test("Test pubSub using TCP client and server using memoryPersistence", async function () {
11
+ const server = new TcpServer({ port: 0 }, {
12
+ // just an example on how to configure the server
13
+ configuration: { context: { maximumConnectPacketSize: 3000 } },
14
+ });
15
+ server.start();
16
+
17
+ assert.deepStrictEqual(
18
+ server.port !== undefined,
19
+ true,
20
+ "server runs a a random port",
21
+ );
22
+ logger.info(
23
+ `TCP server running on port: ${server.port}, address: ${server.address}`,
24
+ );
25
+
26
+ const params = {
27
+ url: new URL(`mqtt://${server.address}:${server.port}`),
28
+ numberOfRetries: 0,
29
+ };
30
+
31
+ const client = new TcpClient();
32
+ await client.connect(params);
33
+ logger.info("Client connected to server at", client.url);
34
+
35
+ const publishSet: { topic: string; qos: QoS }[] = [
36
+ { topic: "t0@q0", qos: 0 },
37
+ { topic: "t1@q0", qos: 0 },
38
+ { topic: "t2@q0", qos: 0 },
39
+ { topic: "t0@q1", qos: 1 },
40
+ { topic: "t1@q1", qos: 1 },
41
+ { topic: "t2@q1", qos: 1 },
42
+ { topic: "t0@q2", qos: 2 },
43
+ { topic: "t1@q2", qos: 2 },
44
+ { topic: "t2@q2", qos: 2 },
45
+ ];
46
+
47
+ const subscriptions = publishSet.map((item) => ({
48
+ topicFilter: item.topic,
49
+ qos: item.qos,
50
+ }));
51
+ await client.subscribe({
52
+ subscriptions,
53
+ });
54
+
55
+ // the IIFE ensures message reception runs in parallel
56
+ logger.info("Start receiving");
57
+ const received: PublishPacket[] = [];
58
+ (async function () {
59
+ for await (const item of client.messages()) {
60
+ logger.verbose("Receiving:", item.topic, "--", item.qos);
61
+ received.push(item);
62
+ }
63
+ })();
64
+ // end of IIFE
65
+ for (const item of publishSet) {
66
+ logger.verbose("Publishing:", item.topic, "--", item.qos);
67
+ await client.publish({
68
+ topic: item.topic,
69
+ qos: item.qos,
70
+ payload: new Uint8Array([0x01]),
71
+ });
72
+ }
73
+
74
+ await delay(100);
75
+ logger.info("Disconnect client");
76
+ await client.disconnect();
77
+
78
+ logger.info("Check completeness");
79
+ for (const item of publishSet) {
80
+ const found = received.find((f) =>
81
+ f.topic == item.topic && f.qos === item.qos
82
+ );
83
+ logger.verbose("Found:", item.topic, "--", item.qos);
84
+ assert(found, `${item.topic} -- ${item.qos}`);
85
+ }
86
+
87
+ logger.info("Stop server");
88
+ server.stop();
89
+ });
@@ -0,0 +1,100 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { TcpClient } from "@seriousme/opifex/tcpClient";
4
+ import { TlsServer } from "@seriousme/opifex/tlsServer";
5
+ import { SqlitePersistence } from "@seriousme/opifex/persistence";
6
+ import { delay, logger, LogLevel } from "@seriousme/opifex/utils";
7
+ import type { PublishPacket, QoS } from "@seriousme/opifex/mqttPacket";
8
+ import { generateLocalhostCerts } from "../dev_utils/generateCert.ts";
9
+
10
+ logger.level(LogLevel.info);
11
+
12
+ test("Test pubSub using TLS client and server and sqlitePersistence", async function () {
13
+ // the localhost certs generate here are great for testing but lack securiity
14
+ // use something like LetsEncrypt for any serious server
15
+ // generateLocalhostCerts is a dev tool and relies on node-forge as a (dev)dependency
16
+ const { key, cert, caCert } = generateLocalhostCerts();
17
+ const dbFile = ":memory:";
18
+ // .start() combines instance creation and async initialization
19
+ const persistence = await SqlitePersistence.start(dbFile);
20
+ const server = new TlsServer({ port: 0, key, cert }, { persistence });
21
+ server.start();
22
+
23
+ assert.deepStrictEqual(
24
+ server.port !== undefined,
25
+ true,
26
+ "TLS server runs on a random port",
27
+ );
28
+ logger.info(
29
+ `TLS server running on port: ${server.port}, address: ${server.address}`,
30
+ );
31
+ // pick the correct hostname
32
+ const hostname = server.address === "0.0.0.0" ? "127.0.0.1" : server.address;
33
+
34
+ const params = {
35
+ url: new URL(`mqtts://${hostname}:${server.port}`),
36
+ numberOfRetries: 0,
37
+ // since we signed our server cert ourselves we need to add the caCert
38
+ // this is not required if you use a public Certificate Authority
39
+ caCerts: [caCert],
40
+ };
41
+
42
+ const client = new TcpClient();
43
+ await client.connect(params);
44
+ logger.info("Client connected to server at", client.url);
45
+
46
+ const publishSet: { topic: string; qos: QoS }[] = [
47
+ { topic: "t0@q0", qos: 0 },
48
+ { topic: "t1@q0", qos: 0 },
49
+ { topic: "t2@q0", qos: 0 },
50
+ { topic: "t0@q1", qos: 1 },
51
+ { topic: "t1@q1", qos: 1 },
52
+ { topic: "t2@q1", qos: 1 },
53
+ { topic: "t0@q2", qos: 2 },
54
+ { topic: "t1@q2", qos: 2 },
55
+ { topic: "t2@q2", qos: 2 },
56
+ ];
57
+
58
+ const subscriptions = publishSet.map((item) => ({
59
+ topicFilter: item.topic,
60
+ qos: item.qos,
61
+ }));
62
+ await client.subscribe({
63
+ subscriptions,
64
+ });
65
+
66
+ // the IIFE ensures message reception runs in parallel
67
+ logger.info("Start receiving");
68
+ const received: PublishPacket[] = [];
69
+ (async function () {
70
+ for await (const item of client.messages()) {
71
+ logger.verbose("Receiving:", item.topic, "--", item.qos);
72
+ received.push(item);
73
+ }
74
+ })();
75
+ // end of IIFE
76
+ for (const item of publishSet) {
77
+ logger.verbose("Publishing:", item.topic, "--", item.qos);
78
+ await client.publish({
79
+ topic: item.topic,
80
+ qos: item.qos,
81
+ payload: new Uint8Array([0x01]),
82
+ });
83
+ }
84
+
85
+ await delay(100);
86
+ logger.info("Disconnect client");
87
+ await client.disconnect();
88
+
89
+ logger.info("Check completeness");
90
+ for (const item of publishSet) {
91
+ const found = received.find((f) =>
92
+ f.topic == item.topic && f.qos === item.qos
93
+ );
94
+ logger.verbose("Found:", item.topic, "--", item.qos);
95
+ assert(found, `${item.topic} -- ${item.qos}`);
96
+ }
97
+
98
+ logger.info("Stop server");
99
+ server.stop();
100
+ });
@@ -0,0 +1,94 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { delay, logger, LogLevel } from "@seriousme/opifex/utils";
4
+
5
+ import type { PublishPacket, QoS } from "@seriousme/opifex/mqttPacket";
6
+
7
+ logger.level(LogLevel.info);
8
+
9
+ test("Deno: Test pubSub using WebSocket client and server and memoryPersistence", async function () {
10
+ // Nodejs does not natively support WebSockets so we only import Websocket client and server here
11
+ if (typeof Deno !== "undefined") {
12
+ const { WsClient } = await import("@seriousme/opifex/wsClient");
13
+ const { WsServer } = await import("@seriousme/opifex/wsServer");
14
+ const server = new WsServer({ port: 0 }, {});
15
+ server.start();
16
+
17
+ assert.deepStrictEqual(
18
+ server.port !== undefined,
19
+ true,
20
+ "WebSocket server runs on a random port",
21
+ );
22
+ logger.info(
23
+ `WebSocket server running on port: ${server.port}, address: ${server.address}`,
24
+ );
25
+ // pick the correct hostname
26
+ const hostname = server.address === "0.0.0.0"
27
+ ? "127.0.0.1"
28
+ : server.address;
29
+
30
+ const params = {
31
+ url: new URL(`ws://${hostname}:${server.port}`),
32
+ numberOfRetries: 0,
33
+ };
34
+
35
+ const client = new WsClient();
36
+ await client.connect(params);
37
+ logger.info("Client connected to server at", client.url);
38
+
39
+ const publishSet: { topic: string; qos: QoS }[] = [
40
+ { topic: "t0@q0", qos: 0 },
41
+ { topic: "t1@q0", qos: 0 },
42
+ { topic: "t2@q0", qos: 0 },
43
+ { topic: "t0@q1", qos: 1 },
44
+ { topic: "t1@q1", qos: 1 },
45
+ { topic: "t2@q1", qos: 1 },
46
+ { topic: "t0@q2", qos: 2 },
47
+ { topic: "t1@q2", qos: 2 },
48
+ { topic: "t2@q2", qos: 2 },
49
+ ];
50
+
51
+ const subscriptions = publishSet.map((item) => ({
52
+ topicFilter: item.topic,
53
+ qos: item.qos,
54
+ }));
55
+ await client.subscribe({
56
+ subscriptions,
57
+ });
58
+
59
+ // the IIFE ensures message reception runs in parallel
60
+ logger.info("Start receiving");
61
+ const received: PublishPacket[] = [];
62
+ (async function () {
63
+ for await (const item of client.messages()) {
64
+ logger.verbose("Receiving:", item.topic, "--", item.qos);
65
+ received.push(item);
66
+ }
67
+ })();
68
+ // end of IIFE
69
+ for (const item of publishSet) {
70
+ logger.verbose("Publishing:", item.topic, "--", item.qos);
71
+ await client.publish({
72
+ topic: item.topic,
73
+ qos: item.qos,
74
+ payload: new Uint8Array([0x01]),
75
+ });
76
+ }
77
+
78
+ await delay(100);
79
+ logger.info("Disconnect client");
80
+ await client.disconnect();
81
+
82
+ logger.info("Check completeness");
83
+ for (const item of publishSet) {
84
+ const found = received.find((f) =>
85
+ f.topic == item.topic && f.qos === item.qos
86
+ );
87
+ logger.verbose("Found:", item.topic, "--", item.qos);
88
+ assert(found, `${item.topic} -- ${item.qos}`);
89
+ }
90
+
91
+ logger.info("Stop server");
92
+ server.stop();
93
+ }
94
+ });
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { test } from "node:test";
3
- import { makeDummySockConn } from "../dev_utils/mod.ts";
3
+ import { createMockSockConn } from "../dev_utils/mod.ts";
4
4
  import { encode, MQTTLevel, PacketType } from "../mqttPacket/mod.ts";
5
5
  import { MqttConn, MqttConnError } from "./mqttConn.ts";
6
6
  import type { AnyPacket, CodecOpts } from "../mqttPacket/mod.ts";
@@ -50,7 +50,7 @@ test("MqttConn should act as asyncIterator", async () => {
50
50
  const publish = encode(publishPacket, codecOptsV4);
51
51
  const disconnect = encode(disconnectPacket, codecOptsV4);
52
52
 
53
- const conn = makeDummySockConn(
53
+ const conn = createMockSockConn(
54
54
  [connect, publish, disconnect],
55
55
  new Uint8Array(),
56
56
  );
@@ -62,13 +62,13 @@ test("MqttConn should act as asyncIterator", async () => {
62
62
  }
63
63
 
64
64
  assert.deepStrictEqual(packets.length, 3);
65
- assert.deepStrictEqual(packets[0], connectPacket);
66
- assert.deepStrictEqual(packets[1], publishPacket);
67
- assert.deepStrictEqual(packets[2], disconnectPacket);
65
+ assert.deepStrictEqual(packets[0], connectPacket, "has connect packet");
66
+ assert.deepStrictEqual(packets[1], publishPacket, "has publish packet");
67
+ assert.deepStrictEqual(packets[2], disconnectPacket, "has disconnect packet");
68
68
  });
69
69
 
70
70
  test("MqttConn should close on malformed length", async () => {
71
- const conn = makeDummySockConn([new Uint8Array([1, 175])], new Uint8Array());
71
+ const conn = createMockSockConn([new Uint8Array([1, 175])], new Uint8Array());
72
72
  const mqttConn = new MqttConn({ conn });
73
73
 
74
74
  const packets: AnyPacket[] = [];
@@ -86,7 +86,7 @@ test("MqttConn should close on failed packets", async () => {
86
86
  const publish = encode(publishPacket, codecOptsV4);
87
87
  const brokenPublish = publish.slice(0, 7);
88
88
 
89
- const conn = makeDummySockConn([connect, brokenPublish], new Uint8Array());
89
+ const conn = createMockSockConn([connect, brokenPublish], new Uint8Array());
90
90
  const mqttConn = new MqttConn({ conn });
91
91
 
92
92
  const packets: AnyPacket[] = [];
@@ -103,7 +103,7 @@ test("MqttConn should close on failed packets", async () => {
103
103
  test("MqttConn should close on packets too large", async () => {
104
104
  const connect = encode(connectPacket, codecOptsV4);
105
105
 
106
- const conn = makeDummySockConn([connect], new Uint8Array());
106
+ const conn = createMockSockConn([connect], new Uint8Array());
107
107
  const mqttConn = new MqttConn({ conn, maxIncomingPacketSize: 20 });
108
108
 
109
109
  const packets: AnyPacket[] = [];
@@ -119,7 +119,7 @@ test("MqttConn should close on packets too large", async () => {
119
119
  test("MqttConn should be writable", async () => {
120
120
  const connect = encode(connectPacket, codecOptsV4);
121
121
  const writer = new Uint8Array(24);
122
- const conn = makeDummySockConn([connect], writer);
122
+ const conn = createMockSockConn([connect], writer);
123
123
  const mqttConn = new MqttConn({ conn });
124
124
  await mqttConn.send(connectPacket);
125
125
  assert.deepStrictEqual(writer, connect);
@@ -6,7 +6,6 @@ import type {
6
6
  AnyPacket,
7
7
  CodecOpts,
8
8
  LengthDecoderResult,
9
- ProtocolLevel,
10
9
  } from "../mqttPacket/mod.ts";
11
10
 
12
11
  import {
@@ -26,26 +25,19 @@ import { Conn } from "../socket/socket.ts";
26
25
  export const MqttConnError = {
27
26
  invalidPacket: "Invalid Packet",
28
27
  packetTooLarge: "Packet too large",
28
+ connectPacketTooLarge: "Connect Packet too large",
29
29
  UnexpectedEof: "Unexpected EOF",
30
30
  } as const;
31
31
 
32
- const DEFAULT_MAX_PACKETSIZE = 2 * 1024 * 1024; // 2MB
32
+ const DEFAULT_MAX_PACKETSIZE = 4 * 1024; // 4Kb
33
33
 
34
- /**
35
- * Interface for MQTT connection handling
36
- */
37
- export interface IMqttConn extends AsyncIterable<AnyPacket> {
38
- /** Underlying connection */
39
- readonly conn: Conn;
40
- /** Whether connection is closed */
41
- readonly isClosed: boolean;
42
- /** Reason for connection closure if any */
43
- readonly reason: string | undefined;
44
- /** Send an MQTT packet */
45
- send(data: AnyPacket): Promise<void>;
46
- /** Close the connection */
47
- close(): void;
48
- }
34
+ export type SendResult =
35
+ | { sent: true }
36
+ | {
37
+ sent: false;
38
+ reason: "packetTooLarge" | "connectionClosed";
39
+ size?: number;
40
+ };
49
41
 
50
42
  /**
51
43
  * Read a single byte from the connection
@@ -54,12 +46,11 @@ export interface IMqttConn extends AsyncIterable<AnyPacket> {
54
46
  * @throws Error if EOF reached unexpectedly
55
47
  */
56
48
  async function readByte(conn: Conn): Promise<number> {
57
- const buf = new Uint8Array(1);
58
- const bytesRead = await conn.read(buf);
59
- assert(bytesRead !== null, MqttConnError.UnexpectedEof);
60
- assert(bytesRead !== undefined, MqttConnError.UnexpectedEof);
61
- assert(bytesRead !== 0, MqttConnError.UnexpectedEof);
62
- return buf[0] || 0;
49
+ const buff = await conn.read(1);
50
+ assert(buff !== null, MqttConnError.UnexpectedEof);
51
+ assert(buff !== undefined, MqttConnError.UnexpectedEof);
52
+ assert(buff.byteLength !== 0, MqttConnError.UnexpectedEof);
53
+ return buff[0] || 0;
63
54
  }
64
55
 
65
56
  /**
@@ -68,31 +59,30 @@ async function readByte(conn: Conn): Promise<number> {
68
59
  * @param buf Buffer to read into
69
60
  * @throws Error if EOF reached unexpectedly
70
61
  */
71
- async function readFull(conn: Conn, buf: Uint8Array): Promise<void> {
72
- let bytesRead = 0;
73
- while (bytesRead < buf.length) {
74
- const read = await conn.read(buf.subarray(bytesRead));
75
- assert(read !== null, MqttConnError.UnexpectedEof);
76
- assert(read !== 0, MqttConnError.UnexpectedEof);
77
- bytesRead += read;
78
- }
62
+ async function readFull(conn: Conn, length: number): Promise<Uint8Array> {
63
+ const buff = await conn.read(length);
64
+ assert(buff !== null, MqttConnError.UnexpectedEof);
65
+ assert(buff.byteLength === length, MqttConnError.UnexpectedEof);
66
+ return buff;
79
67
  }
80
68
 
81
69
  /**
82
70
  * Read a complete MQTT packet from the connection
83
71
  * @param conn Connection to read from
84
- * @param maxIncomingPacketSize Maximum allowed packet size
72
+ * @param codecOpts the CodecOpts
85
73
  * @returns Decoded MQTT packet
86
74
  * @throws Error if packet is invalid or too large
87
75
  */
88
76
  export async function readPacket(
89
77
  conn: Conn,
90
78
  codecOpts: CodecOpts,
79
+ maxConnectPacketSize: number,
91
80
  ): Promise<AnyPacket> {
92
81
  // fixed header is 1 byte of type + flags
93
82
  // + a maximum of 4 bytes to encode the remaining length
94
83
  const decodeLength = getLengthDecoder();
95
84
  const firstByte = await readByte(conn);
85
+ const isConnect = (firstByte >> 4) === 1;
96
86
  let result: LengthDecoderResult;
97
87
  do {
98
88
  const byte = await readByte(conn);
@@ -100,25 +90,32 @@ export async function readPacket(
100
90
  } while (!result.done);
101
91
 
102
92
  const remainingLength = result.length;
93
+ if (isConnect) {
94
+ assert(
95
+ remainingLength < maxConnectPacketSize - 1,
96
+ MqttConnError.connectPacketTooLarge,
97
+ );
98
+ }
103
99
  const maxIncomingPacketSize = codecOpts.maxIncomingPacketSize;
104
100
  assert(
105
101
  remainingLength < maxIncomingPacketSize - 1,
106
102
  MqttConnError.packetTooLarge,
107
103
  );
108
- const packetBuf = new Uint8Array(remainingLength);
109
104
  // read the rest of the packet
110
- await readFull(conn, packetBuf);
105
+ const packetBuf = await readFull(conn, remainingLength);
111
106
  const packet = decodePayload(firstByte, packetBuf, codecOpts);
112
107
  assert(packet !== null, MqttConnError.UnexpectedEof);
113
108
  return packet;
114
109
  }
115
110
 
116
111
  /**
117
- * MQTT Connection class implementing IMqttConn interface
112
+ * MQTT Connection class
118
113
  */
119
- export class MqttConn implements IMqttConn {
114
+ export class MqttConn {
120
115
  /** Underlying connection */
121
116
  readonly conn: Conn;
117
+ /** Maximum Connect packet size */
118
+ readonly maxConnectPacketSize: number;
122
119
  /** codecOpts */
123
120
  codecOpts: CodecOpts;
124
121
  /** Reason for connection closure if any */
@@ -130,24 +127,25 @@ export class MqttConn implements IMqttConn {
130
127
  * Create new MQTT connection
131
128
  * @param options Connection options
132
129
  * @param options.conn Underlying socket connection
133
- * @param options.maxIncomingPacketSize Maximum allowed incoming packet size (default 2MB)
134
- * @param options.maxOutGoingPacketSize Maximum allowed outgoing packet size (default 2MB)
130
+ * @param options.maxConnectPacketSize Maximum allowed connect packet size
131
+ * @param options.maxIncomingPacketSize Maximum allowed incoming packet size
132
+ * @param options.maxOutGoingPacketSize Maximum allowed outgoing packet size
135
133
  * @param options.protocolLevel Supported protocolLevel
136
134
  */
137
- constructor({
138
- conn,
139
- maxIncomingPacketSize = DEFAULT_MAX_PACKETSIZE,
140
- protocolLevel = MQTTLevel.unknown,
141
- }: {
142
- conn: SockConn;
143
- maxIncomingPacketSize?: number;
144
- protocolLevel?: ProtocolLevel;
145
- }) {
146
- this.conn = new Conn(conn);
135
+ constructor(
136
+ options:
137
+ & { conn: SockConn; maxConnectPacketSize?: number }
138
+ & Partial<CodecOpts>,
139
+ ) {
140
+ this.conn = new Conn(options.conn);
141
+ this.maxConnectPacketSize = options.maxConnectPacketSize ??
142
+ DEFAULT_MAX_PACKETSIZE;
147
143
  this.codecOpts = {
148
- maxIncomingPacketSize,
149
- maxOutgoingPacketSize: maxIncomingPacketSize,
150
- protocolLevel,
144
+ maxIncomingPacketSize: options.maxIncomingPacketSize ??
145
+ DEFAULT_MAX_PACKETSIZE,
146
+ maxOutgoingPacketSize: options.maxOutgoingPacketSize ??
147
+ DEFAULT_MAX_PACKETSIZE,
148
+ protocolLevel: options.protocolLevel ?? MQTTLevel.unknown,
151
149
  };
152
150
  }
153
151
 
@@ -174,7 +172,11 @@ export class MqttConn implements IMqttConn {
174
172
  async #receive(): Promise<AnyPacket | undefined> {
175
173
  if (!this._isClosed) {
176
174
  try {
177
- return await readPacket(this.conn, this.codecOpts);
175
+ return await readPacket(
176
+ this.conn,
177
+ this.codecOpts,
178
+ this.maxConnectPacketSize,
179
+ );
178
180
  } catch (err) {
179
181
  if (err instanceof Error) {
180
182
  if (err.name === "PartialReadError") {
@@ -190,6 +192,7 @@ export class MqttConn implements IMqttConn {
190
192
  return Promise.resolve(undefined);
191
193
  }
192
194
 
195
+ /** Return next packet. */
193
196
  async next(): Promise<IteratorResult<AnyPacket>> {
194
197
  const packet = await this.#receive();
195
198
 
@@ -200,23 +203,36 @@ export class MqttConn implements IMqttConn {
200
203
  return { value: undefined, done: true };
201
204
  }
202
205
 
206
+ /** Async iterator. */
203
207
  [Symbol.asyncIterator](): this {
204
208
  return this;
205
209
  }
206
210
 
207
- /**
211
+ /*
208
212
  * Send an MQTT packet
209
213
  * @param data Packet to send
210
214
  */
211
- async send(data: AnyPacket): Promise<void> {
212
- try {
213
- await this.conn.write(encode(data, this.codecOpts));
214
- } catch (err) {
215
- if (err instanceof Error) {
216
- this._reason = err.message;
215
+ async send(data: AnyPacket): Promise<SendResult> {
216
+ if (!this._isClosed) {
217
+ try {
218
+ const encoded = encode(data, this.codecOpts);
219
+ if (encoded.byteLength > this.codecOpts.maxOutgoingPacketSize) {
220
+ return {
221
+ sent: false,
222
+ reason: "packetTooLarge",
223
+ size: encoded.byteLength,
224
+ };
225
+ }
226
+ await this.conn.write(encoded);
227
+ return { sent: true };
228
+ } catch (err) {
229
+ if (err instanceof Error) {
230
+ this._reason = err.message;
231
+ }
232
+ this.close();
217
233
  }
218
- this.close();
219
234
  }
235
+ return { sent: false, reason: "connectionClosed" };
220
236
  }
221
237
 
222
238
  /** Whether connection is closed */
@@ -10,6 +10,12 @@ export const AuthenticationResult = {
10
10
  notAuthorized: 5,
11
11
  } as const;
12
12
 
13
+ /**
14
+ * Type to limit authentication result to valid values
15
+ */
16
+ export type AuthenticationResult =
17
+ typeof AuthenticationResult[keyof typeof AuthenticationResult];
18
+
13
19
  /**
14
20
  * Reverse lookup for AuthenticationResult
15
21
  */
@@ -26,3 +26,8 @@ export const PacketType = {
26
26
  export const PacketNameByType: Record<number, string> = Object.fromEntries(
27
27
  Object.entries(PacketType).map(([k, v]) => [v, k]),
28
28
  );
29
+
30
+ /**
31
+ * Type to limit packet type to valid values
32
+ */
33
+ export type PacketType = typeof PacketType[keyof typeof PacketType];
@@ -6,7 +6,7 @@ export const PropertySetType = {
6
6
  will: 100,
7
7
  } as const;
8
8
 
9
- export type TPropertySetType =
9
+ export type PropertySetType =
10
10
  typeof PropertySetType[keyof typeof PropertySetType];
11
11
 
12
12
  export const propertyKind = {
@@ -117,11 +117,14 @@ export type ValidPropertyNumber =
117
117
  (typeof propertyToId)[keyof typeof propertyToId];
118
118
  // Then, create a mapped type that iterates over the property names
119
119
  // and uses propertyToKind to look up the correct TypeScript type.
120
+ // properties are optional, but can also hold "undefined"
120
121
 
121
122
  type AllMqttv5Properties = {
122
- [K in PropertyNames]?: Mqttv5PropertyType<
123
- typeof propertyToKind[typeof propertyToId[K]]
124
- >;
123
+ [K in PropertyNames]?:
124
+ | Mqttv5PropertyType<
125
+ typeof propertyToKind[typeof propertyToId[K]]
126
+ >
127
+ | undefined;
125
128
  };
126
129
 
127
130
  type PropertyByNumberType = InvertRecord<typeof propertyToId>;
@@ -242,7 +245,7 @@ type GeneratePacketTypeProperties<T extends readonly ValidPropertyNumber[]> =
242
245
  Pick<AllMqttv5Properties, PropertyIdsToKeys<T>>;
243
246
 
244
247
  export type PropsByPacketSetType = {
245
- [K in TPropertySetType]: GeneratePacketTypeProperties<
248
+ [K in PropertySetType]: GeneratePacketTypeProperties<
246
249
  typeof PropertyByPropertySetType[K]
247
250
  >;
248
251
  };