@seriousme/opifex 1.9.4 → 1.11.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 (331) hide show
  1. package/README.md +37 -26
  2. package/bin/conformanceServer.ts +3 -2
  3. package/bin/demoServer.ts +3 -2
  4. package/bin/mqtt.ts +127 -118
  5. package/client/client.ts +61 -21
  6. package/client/context.ts +71 -30
  7. package/client/deps.ts +5 -0
  8. package/client/handlers/handleConnack.ts +17 -5
  9. package/client/handlers/handlePublish.ts +4 -1
  10. package/client/handlers/handlePubrec.ts +3 -1
  11. package/client/handlers/handlePubrel.ts +3 -1
  12. package/client/handlers/handleSuback.ts +3 -1
  13. package/client/mod.ts +8 -1
  14. package/client/store/memoryStore.ts +2 -1
  15. package/deno/tcpClient.ts +1 -1
  16. package/dev_utils/dummyConn.ts +17 -2
  17. package/dist/bin/conformanceServer.js +3 -2
  18. package/dist/bin/conformanceServer.js.map +1 -1
  19. package/dist/bin/demoServer.js +3 -2
  20. package/dist/bin/demoServer.js.map +1 -1
  21. package/dist/bin/mqtt.d.ts +29 -0
  22. package/dist/bin/mqtt.d.ts.map +1 -1
  23. package/dist/bin/mqtt.js +102 -97
  24. package/dist/bin/mqtt.js.map +1 -1
  25. package/dist/client/client.d.ts +16 -5
  26. package/dist/client/client.d.ts.map +1 -1
  27. package/dist/client/client.js +36 -15
  28. package/dist/client/client.js.map +1 -1
  29. package/dist/client/context.d.ts +8 -3
  30. package/dist/client/context.d.ts.map +1 -1
  31. package/dist/client/context.js +51 -21
  32. package/dist/client/context.js.map +1 -1
  33. package/dist/client/deps.d.ts +3 -2
  34. package/dist/client/deps.d.ts.map +1 -1
  35. package/dist/client/deps.js +2 -1
  36. package/dist/client/deps.js.map +1 -1
  37. package/dist/client/handlers/handleConnack.d.ts +1 -1
  38. package/dist/client/handlers/handleConnack.d.ts.map +1 -1
  39. package/dist/client/handlers/handleConnack.js +14 -5
  40. package/dist/client/handlers/handleConnack.js.map +1 -1
  41. package/dist/client/handlers/handlePublish.d.ts +1 -1
  42. package/dist/client/handlers/handlePublish.d.ts.map +1 -1
  43. package/dist/client/handlers/handlePublish.js +2 -0
  44. package/dist/client/handlers/handlePublish.js.map +1 -1
  45. package/dist/client/handlers/handlePubrec.d.ts +1 -1
  46. package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
  47. package/dist/client/handlers/handlePubrec.js +1 -0
  48. package/dist/client/handlers/handlePubrec.js.map +1 -1
  49. package/dist/client/handlers/handlePubrel.d.ts +1 -1
  50. package/dist/client/handlers/handlePubrel.d.ts.map +1 -1
  51. package/dist/client/handlers/handlePubrel.js +1 -0
  52. package/dist/client/handlers/handlePubrel.js.map +1 -1
  53. package/dist/client/handlers/handleSuback.d.ts.map +1 -1
  54. package/dist/client/handlers/handleSuback.js +3 -1
  55. package/dist/client/handlers/handleSuback.js.map +1 -1
  56. package/dist/client/mod.d.ts +3 -1
  57. package/dist/client/mod.d.ts.map +1 -1
  58. package/dist/client/mod.js +2 -1
  59. package/dist/client/mod.js.map +1 -1
  60. package/dist/client/store/memoryStore.d.ts +1 -1
  61. package/dist/client/store/memoryStore.d.ts.map +1 -1
  62. package/dist/client/store/memoryStore.js.map +1 -1
  63. package/dist/mqttConn/mqttConn.d.ts +13 -8
  64. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  65. package/dist/mqttConn/mqttConn.js +27 -12
  66. package/dist/mqttConn/mqttConn.js.map +1 -1
  67. package/dist/mqttPacket/PacketType.d.ts +1 -0
  68. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  69. package/dist/mqttPacket/PacketType.js +1 -0
  70. package/dist/mqttPacket/PacketType.js.map +1 -1
  71. package/dist/mqttPacket/Properties.d.ts +157 -0
  72. package/dist/mqttPacket/Properties.d.ts.map +1 -0
  73. package/dist/mqttPacket/Properties.js +177 -0
  74. package/dist/mqttPacket/Properties.js.map +1 -0
  75. package/dist/mqttPacket/ReasonCode.d.ts +74 -0
  76. package/dist/mqttPacket/ReasonCode.d.ts.map +1 -0
  77. package/dist/mqttPacket/ReasonCode.js +230 -0
  78. package/dist/mqttPacket/ReasonCode.js.map +1 -0
  79. package/dist/mqttPacket/RetainHandling.d.ts +12 -0
  80. package/dist/mqttPacket/RetainHandling.d.ts.map +1 -0
  81. package/dist/mqttPacket/RetainHandling.js +12 -0
  82. package/dist/mqttPacket/RetainHandling.js.map +1 -0
  83. package/dist/mqttPacket/auth.d.ts +21 -0
  84. package/dist/mqttPacket/auth.d.ts.map +1 -0
  85. package/dist/mqttPacket/auth.js +34 -0
  86. package/dist/mqttPacket/auth.js.map +1 -0
  87. package/dist/mqttPacket/connack.d.ts +19 -11
  88. package/dist/mqttPacket/connack.d.ts.map +1 -1
  89. package/dist/mqttPacket/connack.js +43 -15
  90. package/dist/mqttPacket/connack.js.map +1 -1
  91. package/dist/mqttPacket/connect.d.ts +30 -11
  92. package/dist/mqttPacket/connect.d.ts.map +1 -1
  93. package/dist/mqttPacket/connect.js +106 -30
  94. package/dist/mqttPacket/connect.js.map +1 -1
  95. package/dist/mqttPacket/decoder.d.ts +42 -3
  96. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  97. package/dist/mqttPacket/decoder.js +135 -4
  98. package/dist/mqttPacket/decoder.js.map +1 -1
  99. package/dist/mqttPacket/disconnect.d.ts +15 -9
  100. package/dist/mqttPacket/disconnect.d.ts.map +1 -1
  101. package/dist/mqttPacket/disconnect.js +45 -6
  102. package/dist/mqttPacket/disconnect.js.map +1 -1
  103. package/dist/mqttPacket/encoder.d.ts +57 -8
  104. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  105. package/dist/mqttPacket/encoder.js +185 -13
  106. package/dist/mqttPacket/encoder.js.map +1 -1
  107. package/dist/mqttPacket/length.d.ts.map +1 -1
  108. package/dist/mqttPacket/length.js +3 -2
  109. package/dist/mqttPacket/length.js.map +1 -1
  110. package/dist/mqttPacket/mod.d.ts +57 -91
  111. package/dist/mqttPacket/mod.d.ts.map +1 -1
  112. package/dist/mqttPacket/mod.js +23 -29
  113. package/dist/mqttPacket/mod.js.map +1 -1
  114. package/dist/mqttPacket/pingreq.d.ts +4 -6
  115. package/dist/mqttPacket/pingreq.d.ts.map +1 -1
  116. package/dist/mqttPacket/pingreq.js +5 -4
  117. package/dist/mqttPacket/pingreq.js.map +1 -1
  118. package/dist/mqttPacket/pingres.d.ts +4 -6
  119. package/dist/mqttPacket/pingres.d.ts.map +1 -1
  120. package/dist/mqttPacket/pingres.js +7 -5
  121. package/dist/mqttPacket/pingres.js.map +1 -1
  122. package/dist/mqttPacket/protocolLevels.d.ts +12 -0
  123. package/dist/mqttPacket/protocolLevels.d.ts.map +1 -0
  124. package/dist/mqttPacket/protocolLevels.js +11 -0
  125. package/dist/mqttPacket/protocolLevels.js.map +1 -0
  126. package/dist/mqttPacket/pubblishAcks.d.ts +42 -0
  127. package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -0
  128. package/dist/mqttPacket/pubblishAcks.js +56 -0
  129. package/dist/mqttPacket/pubblishAcks.js.map +1 -0
  130. package/dist/mqttPacket/publish.d.ts +19 -8
  131. package/dist/mqttPacket/publish.d.ts.map +1 -1
  132. package/dist/mqttPacket/publish.js +26 -7
  133. package/dist/mqttPacket/publish.js.map +1 -1
  134. package/dist/mqttPacket/suback.d.ts +18 -11
  135. package/dist/mqttPacket/suback.d.ts.map +1 -1
  136. package/dist/mqttPacket/suback.js +41 -20
  137. package/dist/mqttPacket/suback.js.map +1 -1
  138. package/dist/mqttPacket/subscribe.d.ts +27 -12
  139. package/dist/mqttPacket/subscribe.d.ts.map +1 -1
  140. package/dist/mqttPacket/subscribe.js +71 -15
  141. package/dist/mqttPacket/subscribe.js.map +1 -1
  142. package/dist/mqttPacket/types.d.ts +36 -0
  143. package/dist/mqttPacket/types.d.ts.map +1 -1
  144. package/dist/mqttPacket/unsuback.d.ts +17 -10
  145. package/dist/mqttPacket/unsuback.d.ts.map +1 -1
  146. package/dist/mqttPacket/unsuback.js +29 -6
  147. package/dist/mqttPacket/unsuback.js.map +1 -1
  148. package/dist/mqttPacket/unsubscribe.d.ts +17 -10
  149. package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
  150. package/dist/mqttPacket/unsubscribe.js +24 -8
  151. package/dist/mqttPacket/unsubscribe.js.map +1 -1
  152. package/dist/mqttPacket/validators.d.ts +15 -0
  153. package/dist/mqttPacket/validators.d.ts.map +1 -1
  154. package/dist/mqttPacket/validators.js +15 -0
  155. package/dist/mqttPacket/validators.js.map +1 -1
  156. package/dist/node/tcpClient.js +1 -1
  157. package/dist/node/tcpClient.js.map +1 -1
  158. package/dist/node/wrapNodeSocket.d.ts.map +1 -1
  159. package/dist/node/wrapNodeSocket.js.map +1 -1
  160. package/dist/persistence/deps.d.ts +1 -1
  161. package/dist/persistence/deps.d.ts.map +1 -1
  162. package/dist/persistence/deps.js +1 -1
  163. package/dist/persistence/deps.js.map +1 -1
  164. package/dist/persistence/memory/memoryPersistence.js +1 -1
  165. package/dist/persistence/memory/memoryPersistence.js.map +1 -1
  166. package/dist/server/context.d.ts +3 -1
  167. package/dist/server/context.d.ts.map +1 -1
  168. package/dist/server/context.js +8 -2
  169. package/dist/server/context.js.map +1 -1
  170. package/dist/server/deps.d.ts +2 -2
  171. package/dist/server/deps.d.ts.map +1 -1
  172. package/dist/server/deps.js +1 -1
  173. package/dist/server/deps.js.map +1 -1
  174. package/dist/server/handlers/handleConnect.d.ts +1 -1
  175. package/dist/server/handlers/handleConnect.d.ts.map +1 -1
  176. package/dist/server/handlers/handleConnect.js +9 -1
  177. package/dist/server/handlers/handleConnect.js.map +1 -1
  178. package/dist/server/handlers/handlePacket.d.ts +1 -1
  179. package/dist/server/handlers/handlePacket.d.ts.map +1 -1
  180. package/dist/server/handlers/handlePacket.js +1 -1
  181. package/dist/server/handlers/handlePacket.js.map +1 -1
  182. package/dist/server/handlers/handlePingreq.d.ts.map +1 -1
  183. package/dist/server/handlers/handlePingreq.js +1 -0
  184. package/dist/server/handlers/handlePingreq.js.map +1 -1
  185. package/dist/server/handlers/handlePublish.d.ts +2 -2
  186. package/dist/server/handlers/handlePublish.d.ts.map +1 -1
  187. package/dist/server/handlers/handlePublish.js +2 -0
  188. package/dist/server/handlers/handlePublish.js.map +1 -1
  189. package/dist/server/handlers/handlePubrec.d.ts +1 -1
  190. package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
  191. package/dist/server/handlers/handlePubrec.js +1 -0
  192. package/dist/server/handlers/handlePubrec.js.map +1 -1
  193. package/dist/server/handlers/handlePubrel.d.ts +1 -1
  194. package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
  195. package/dist/server/handlers/handlePubrel.js +1 -0
  196. package/dist/server/handlers/handlePubrel.js.map +1 -1
  197. package/dist/server/handlers/handleSubscribe.d.ts +1 -1
  198. package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
  199. package/dist/server/handlers/handleSubscribe.js +2 -1
  200. package/dist/server/handlers/handleSubscribe.js.map +1 -1
  201. package/dist/server/handlers/handleUnsubscribe.d.ts +1 -1
  202. package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
  203. package/dist/server/handlers/handleUnsubscribe.js +1 -0
  204. package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
  205. package/dist/server/server.d.ts +2 -2
  206. package/dist/server/server.d.ts.map +1 -1
  207. package/dist/server/server.js +5 -3
  208. package/dist/server/server.js.map +1 -1
  209. package/dist/socket/socket.d.ts.map +1 -1
  210. package/dist/socket/socket.js +6 -1
  211. package/dist/socket/socket.js.map +1 -1
  212. package/dist/utils/assert.d.ts +0 -3
  213. package/dist/utils/assert.d.ts.map +1 -1
  214. package/dist/utils/assert.js +0 -7
  215. package/dist/utils/assert.js.map +1 -1
  216. package/dist/utils/asyncQueue.d.ts +1 -3
  217. package/dist/utils/asyncQueue.d.ts.map +1 -1
  218. package/dist/utils/asyncQueue.js +16 -21
  219. package/dist/utils/asyncQueue.js.map +1 -1
  220. package/dist/utils/logger.d.ts +5 -15
  221. package/dist/utils/logger.d.ts.map +1 -1
  222. package/dist/utils/logger.js +7 -8
  223. package/dist/utils/logger.js.map +1 -1
  224. package/dist/utils/mod.d.ts +0 -3
  225. package/dist/utils/mod.d.ts.map +1 -1
  226. package/dist/utils/mod.js +0 -2
  227. package/dist/utils/mod.js.map +1 -1
  228. package/dist/utils/utils.d.ts +2 -0
  229. package/dist/utils/utils.d.ts.map +1 -0
  230. package/dist/utils/utils.js +6 -0
  231. package/dist/utils/utils.js.map +1 -0
  232. package/mqttConn/mqttConn.test.ts +27 -12
  233. package/mqttConn/mqttConn.ts +45 -14
  234. package/mqttPacket/PacketType.ts +1 -0
  235. package/mqttPacket/Properties.ts +276 -0
  236. package/mqttPacket/ReasonCode.test.ts +22 -0
  237. package/mqttPacket/ReasonCode.ts +256 -0
  238. package/mqttPacket/RetainHandling.ts +11 -0
  239. package/mqttPacket/auth.test.ts +112 -0
  240. package/mqttPacket/auth.ts +71 -0
  241. package/mqttPacket/connack.test.ts +84 -64
  242. package/mqttPacket/connack.ts +88 -24
  243. package/mqttPacket/connect.test.ts +497 -18
  244. package/mqttPacket/connect.ts +170 -39
  245. package/mqttPacket/decoder.test.ts +33 -16
  246. package/mqttPacket/decoder.ts +173 -5
  247. package/mqttPacket/disconnect.test.ts +97 -18
  248. package/mqttPacket/disconnect.ts +84 -12
  249. package/mqttPacket/encoder.test.ts +32 -8
  250. package/mqttPacket/encoder.ts +236 -11
  251. package/mqttPacket/length.ts +3 -2
  252. package/mqttPacket/mod.ts +76 -39
  253. package/mqttPacket/pingreq.test.ts +52 -4
  254. package/mqttPacket/pingreq.ts +20 -7
  255. package/mqttPacket/pingres.test.ts +52 -4
  256. package/mqttPacket/pingres.ts +22 -8
  257. package/mqttPacket/properties.test.ts +193 -0
  258. package/mqttPacket/protocolLevels.ts +13 -0
  259. package/mqttPacket/pubblishAcks.ts +123 -0
  260. package/mqttPacket/publish.test.ts +212 -133
  261. package/mqttPacket/publish.ts +69 -14
  262. package/mqttPacket/publishAcks.test.ts +128 -0
  263. package/mqttPacket/suback.test.ts +71 -27
  264. package/mqttPacket/suback.ts +82 -30
  265. package/mqttPacket/subscribe.test.ts +132 -43
  266. package/mqttPacket/subscribe.ts +128 -25
  267. package/mqttPacket/types.ts +43 -0
  268. package/mqttPacket/unsuback.test.ts +80 -30
  269. package/mqttPacket/unsuback.ts +68 -13
  270. package/mqttPacket/unsubscribe.test.ts +59 -34
  271. package/mqttPacket/unsubscribe.ts +64 -17
  272. package/mqttPacket/validators.ts +15 -0
  273. package/node/tcpClient.ts +1 -1
  274. package/node/wrapNodeSocket.ts +2 -1
  275. package/package.json +2 -2
  276. package/persistence/deps.ts +1 -1
  277. package/persistence/memory/memoryPersistence.test.ts +5 -1
  278. package/persistence/memory/memoryPersistence.ts +1 -1
  279. package/server/context.ts +23 -10
  280. package/server/deps.ts +2 -0
  281. package/server/handlers/handleConnect.ts +12 -9
  282. package/server/handlers/handlePacket.ts +10 -11
  283. package/server/handlers/handlePingreq.ts +1 -0
  284. package/server/handlers/handlePublish.ts +6 -2
  285. package/server/handlers/handlePubrec.ts +3 -1
  286. package/server/handlers/handlePubrel.ts +3 -1
  287. package/server/handlers/handleSubscribe.ts +3 -6
  288. package/server/handlers/handleUnsubscribe.ts +3 -1
  289. package/server/server.ts +8 -12
  290. package/server/test/handleConnect.test.ts +2 -1
  291. package/server/test/test-handlers.ts +2 -1
  292. package/socket/socket.ts +5 -1
  293. package/utils/assert.ts +0 -18
  294. package/utils/asyncQueue.ts +17 -21
  295. package/utils/logger.ts +12 -11
  296. package/utils/mod.ts +0 -3
  297. package/utils/utils.ts +6 -0
  298. package/dist/mqttPacket/puback.d.ts +0 -16
  299. package/dist/mqttPacket/puback.d.ts.map +0 -1
  300. package/dist/mqttPacket/puback.js +0 -21
  301. package/dist/mqttPacket/puback.js.map +0 -1
  302. package/dist/mqttPacket/pubcomp.d.ts +0 -17
  303. package/dist/mqttPacket/pubcomp.d.ts.map +0 -1
  304. package/dist/mqttPacket/pubcomp.js +0 -21
  305. package/dist/mqttPacket/pubcomp.js.map +0 -1
  306. package/dist/mqttPacket/pubrec.d.ts +0 -17
  307. package/dist/mqttPacket/pubrec.d.ts.map +0 -1
  308. package/dist/mqttPacket/pubrec.js +0 -21
  309. package/dist/mqttPacket/pubrec.js.map +0 -1
  310. package/dist/mqttPacket/pubrel.d.ts +0 -17
  311. package/dist/mqttPacket/pubrel.d.ts.map +0 -1
  312. package/dist/mqttPacket/pubrel.js +0 -21
  313. package/dist/mqttPacket/pubrel.js.map +0 -1
  314. package/dist/utils/args.d.ts +0 -28
  315. package/dist/utils/args.d.ts.map +0 -1
  316. package/dist/utils/args.js +0 -76
  317. package/dist/utils/args.js.map +0 -1
  318. package/dist/utils/platform.d.ts +0 -5
  319. package/dist/utils/platform.d.ts.map +0 -1
  320. package/dist/utils/platform.js +0 -8
  321. package/dist/utils/platform.js.map +0 -1
  322. package/mqttPacket/puback.test.ts +0 -55
  323. package/mqttPacket/puback.ts +0 -34
  324. package/mqttPacket/pubcomp.test.ts +0 -55
  325. package/mqttPacket/pubcomp.ts +0 -35
  326. package/mqttPacket/pubrec.test.ts +0 -55
  327. package/mqttPacket/pubrec.ts +0 -35
  328. package/mqttPacket/pubrel.test.ts +0 -55
  329. package/mqttPacket/pubrel.ts +0 -35
  330. package/utils/args.ts +0 -103
  331. package/utils/platform.ts +0 -8
@@ -0,0 +1,276 @@
1
+ import { PacketType } from "./PacketType.ts";
2
+ import type { InvertRecord, UTF8StringPair } from "./types.ts";
3
+
4
+ export const PropertySetType = {
5
+ ...PacketType,
6
+ will: 100,
7
+ } as const;
8
+
9
+ export type TPropertySetType =
10
+ typeof PropertySetType[keyof typeof PropertySetType];
11
+
12
+ export const propertyKind = {
13
+ boolean: 0, // its a byte in the MQTT standard, but for convenience we convert to boolean
14
+ byte: 1,
15
+ int16: 2,
16
+ int32: 3,
17
+ varInt: 4,
18
+ byteArray: 5,
19
+ utf8string: 6,
20
+ utf8StringPairs: 7,
21
+ varIntArray: 8,
22
+ } as const;
23
+
24
+ export const propertyToId = {
25
+ payloadFormatIndicator: 0x01,
26
+ messageExpiryInterval: 0x02,
27
+ contentType: 0x03,
28
+ responseTopic: 0x08,
29
+ correlationData: 0x09,
30
+ subscriptionIdentifier: 0x0b,
31
+ // special case,placeholder to encode decode multiple subscription identifiers
32
+ subscriptionIdentifiers: 0xff,
33
+ sessionExpiryInterval: 0x11,
34
+ assignedClientIdentifier: 0x12,
35
+ serverKeepAlive: 0x13,
36
+ authenticationMethod: 0x15,
37
+ authenticationData: 0x16,
38
+ requestProblemInformation: 0x17,
39
+ willDelayInterval: 0x18,
40
+ requestResponseInformation: 0x19,
41
+ responseInformation: 0x1a,
42
+ serverReference: 0x1c,
43
+ reasonString: 0x1f,
44
+ receiveMaximum: 0x21,
45
+ topicAliasMaximum: 0x22,
46
+ topicAlias: 0x23,
47
+ maximumQos: 0x24,
48
+ retainAvailable: 0x25,
49
+ userProperty: 0x26,
50
+ maximumPacketSize: 0x27,
51
+ wildcardSubscriptionAvailable: 0x28,
52
+ subscriptionIdentifierAvailable: 0x29,
53
+ sharedSubscriptionAvailable: 0x2a,
54
+ } as const;
55
+
56
+ type PropertyNames = keyof typeof propertyToId;
57
+ // A helper type to convert a tuple of numbers to a union of strings
58
+
59
+ export const propertyToKind = {
60
+ [propertyToId.payloadFormatIndicator]: propertyKind.boolean,
61
+ [propertyToId.messageExpiryInterval]: propertyKind.int32,
62
+ [propertyToId.contentType]: propertyKind.utf8string,
63
+ [propertyToId.responseTopic]: propertyKind.utf8string,
64
+ [propertyToId.correlationData]: propertyKind.byteArray,
65
+ [propertyToId.subscriptionIdentifier]: propertyKind.varInt,
66
+ [propertyToId.subscriptionIdentifiers]: propertyKind.varIntArray,
67
+ [propertyToId.sessionExpiryInterval]: propertyKind.int32,
68
+ [propertyToId.assignedClientIdentifier]: propertyKind.utf8string,
69
+ [propertyToId.serverKeepAlive]: propertyKind.int16,
70
+ [propertyToId.authenticationMethod]: propertyKind.utf8string,
71
+ [propertyToId.authenticationData]: propertyKind.byteArray,
72
+ [propertyToId.requestProblemInformation]: propertyKind.boolean,
73
+ [propertyToId.willDelayInterval]: propertyKind.int32,
74
+ [propertyToId.requestResponseInformation]: propertyKind.boolean,
75
+ [propertyToId.responseInformation]: propertyKind.utf8string,
76
+ [propertyToId.serverReference]: propertyKind.utf8string,
77
+ [propertyToId.reasonString]: propertyKind.utf8string,
78
+ [propertyToId.receiveMaximum]: propertyKind.int16,
79
+ [propertyToId.topicAliasMaximum]: propertyKind.int16,
80
+ [propertyToId.topicAlias]: propertyKind.int16,
81
+ [propertyToId.maximumQos]: propertyKind.byte,
82
+ [propertyToId.retainAvailable]: propertyKind.boolean,
83
+ [propertyToId.userProperty]: propertyKind.utf8StringPairs,
84
+ [propertyToId.maximumPacketSize]: propertyKind.int32,
85
+ [propertyToId.wildcardSubscriptionAvailable]: propertyKind.boolean,
86
+ [propertyToId.subscriptionIdentifierAvailable]: propertyKind.boolean,
87
+ [propertyToId.sharedSubscriptionAvailable]: propertyKind.boolean,
88
+ } as const;
89
+
90
+ export type UserPropertyType = Array<UTF8StringPair>;
91
+ export type SubscriptionIdentifiersType = Array<number>;
92
+
93
+ type PropertyKindMap = {
94
+ [propertyKind.boolean]: boolean;
95
+ [propertyKind.byte]: number;
96
+ [propertyKind.int16]: number;
97
+ [propertyKind.int32]: number;
98
+ [propertyKind.varInt]: number;
99
+ [propertyKind.byteArray]: Uint8Array;
100
+ [propertyKind.utf8string]: string;
101
+ [propertyKind.utf8StringPairs]: UserPropertyType;
102
+ [propertyKind.varIntArray]: SubscriptionIdentifiersType;
103
+ };
104
+
105
+ type Mqttv5PropertyType<K extends number> = K extends keyof PropertyKindMap
106
+ ? PropertyKindMap[K]
107
+ : never;
108
+
109
+ export type Mqttv5PropertyTypes = PropertyKindMap[keyof PropertyKindMap];
110
+ export type Mqttv5PropertyTypesNoUser = Exclude<
111
+ Mqttv5PropertyTypes,
112
+ UserPropertyType
113
+ >;
114
+
115
+ // First, create a type for all valid property numbers
116
+ export type ValidPropertyNumber =
117
+ (typeof propertyToId)[keyof typeof propertyToId];
118
+ // Then, create a mapped type that iterates over the property names
119
+ // and uses propertyToKind to look up the correct TypeScript type.
120
+
121
+ type AllMqttv5Properties = {
122
+ [K in PropertyNames]?: Mqttv5PropertyType<
123
+ typeof propertyToKind[typeof propertyToId[K]]
124
+ >;
125
+ };
126
+
127
+ type PropertyByNumberType = InvertRecord<typeof propertyToId>;
128
+
129
+ export const propertyByNumber = Object.fromEntries(
130
+ Object.entries(propertyToId).map(
131
+ ([k, v]) => [v, k],
132
+ ),
133
+ ) as PropertyByNumberType;
134
+
135
+ export const PropertyByPropertySetType = {
136
+ [PropertySetType.reserved]: [],
137
+ [PropertySetType.connect]: [
138
+ propertyToId.sessionExpiryInterval,
139
+ propertyToId.authenticationMethod,
140
+ propertyToId.authenticationData,
141
+ propertyToId.requestProblemInformation,
142
+ propertyToId.requestResponseInformation,
143
+ propertyToId.receiveMaximum,
144
+ propertyToId.topicAliasMaximum,
145
+ propertyToId.userProperty,
146
+ propertyToId.maximumPacketSize,
147
+ ],
148
+ [PropertySetType.connack]: [
149
+ propertyToId.sessionExpiryInterval,
150
+ propertyToId.assignedClientIdentifier,
151
+ propertyToId.serverKeepAlive,
152
+ propertyToId.authenticationMethod,
153
+ propertyToId.authenticationData,
154
+ propertyToId.responseInformation,
155
+ propertyToId.serverReference,
156
+ propertyToId.reasonString,
157
+ propertyToId.receiveMaximum,
158
+ propertyToId.topicAliasMaximum,
159
+ propertyToId.maximumQos,
160
+ propertyToId.retainAvailable,
161
+ propertyToId.userProperty,
162
+ propertyToId.maximumPacketSize,
163
+ propertyToId.wildcardSubscriptionAvailable,
164
+ propertyToId.subscriptionIdentifierAvailable,
165
+ propertyToId.sharedSubscriptionAvailable,
166
+ ],
167
+ [PropertySetType.publish]: [
168
+ propertyToId.payloadFormatIndicator,
169
+ propertyToId.messageExpiryInterval,
170
+ propertyToId.contentType,
171
+ propertyToId.responseTopic,
172
+ propertyToId.correlationData,
173
+ propertyToId.subscriptionIdentifiers,
174
+ propertyToId.topicAlias,
175
+ propertyToId.userProperty,
176
+ ],
177
+ [PropertySetType.subscribe]: [
178
+ propertyToId.subscriptionIdentifier,
179
+ propertyToId.userProperty,
180
+ ],
181
+ [PropertySetType.unsubscribe]: [
182
+ propertyToId.userProperty,
183
+ ],
184
+
185
+ [PropertySetType.disconnect]: [
186
+ propertyToId.sessionExpiryInterval,
187
+ propertyToId.serverReference,
188
+ propertyToId.reasonString,
189
+ propertyToId.userProperty,
190
+ ],
191
+ [PropertySetType.auth]: [
192
+ propertyToId.authenticationMethod,
193
+ propertyToId.authenticationData,
194
+ propertyToId.reasonString,
195
+ propertyToId.userProperty,
196
+ ],
197
+ [PropertySetType.puback]: [
198
+ propertyToId.reasonString,
199
+ propertyToId.userProperty,
200
+ ],
201
+ [PropertySetType.pubrec]: [
202
+ propertyToId.reasonString,
203
+ propertyToId.userProperty,
204
+ ],
205
+ [PropertySetType.pubrel]: [
206
+ propertyToId.reasonString,
207
+ propertyToId.userProperty,
208
+ ],
209
+ [PropertySetType.pubcomp]: [
210
+ propertyToId.reasonString,
211
+ propertyToId.userProperty,
212
+ ],
213
+ [PropertySetType.suback]: [
214
+ propertyToId.reasonString,
215
+ propertyToId.userProperty,
216
+ ],
217
+ [PropertySetType.unsuback]: [
218
+ propertyToId.reasonString,
219
+ propertyToId.userProperty,
220
+ ],
221
+ [PropertySetType.pingreq]: [],
222
+ [PropertySetType.pingres]: [],
223
+
224
+ [PropertySetType.will]: [
225
+ propertyToId.payloadFormatIndicator,
226
+ propertyToId.messageExpiryInterval,
227
+ propertyToId.contentType,
228
+ propertyToId.responseTopic,
229
+ propertyToId.correlationData,
230
+ propertyToId.willDelayInterval,
231
+ propertyToId.userProperty,
232
+ ],
233
+ } as const;
234
+
235
+ // helper types
236
+ type PropertyIdsToKeys<T extends readonly ValidPropertyNumber[]> = {
237
+ [K in T[number]]: (typeof propertyByNumber)[K];
238
+ }[T[number]];
239
+
240
+ // from AllMqttv5Properties pick the ones returned by PropertyIdsToKeys for this type
241
+ type GeneratePacketTypeProperties<T extends readonly ValidPropertyNumber[]> =
242
+ Pick<AllMqttv5Properties, PropertyIdsToKeys<T>>;
243
+
244
+ export type PropsByPacketSetType = {
245
+ [K in TPropertySetType]: GeneratePacketTypeProperties<
246
+ typeof PropertyByPropertySetType[K]
247
+ >;
248
+ };
249
+
250
+ // props per PacketType
251
+ export type ConnectProperties =
252
+ PropsByPacketSetType[typeof PropertySetType.connect];
253
+ export type ConnackProperties =
254
+ PropsByPacketSetType[typeof PropertySetType.connack];
255
+ export type PublishProperties =
256
+ PropsByPacketSetType[typeof PropertySetType.publish];
257
+ export type PubackProperties =
258
+ PropsByPacketSetType[typeof PropertySetType.puback];
259
+ export type PubrecProperties =
260
+ PropsByPacketSetType[typeof PropertySetType.pubrec];
261
+ export type PubrelProperties =
262
+ PropsByPacketSetType[typeof PropertySetType.pubrel];
263
+ export type PubcompProperties =
264
+ PropsByPacketSetType[typeof PropertySetType.pubcomp];
265
+ export type SubscribeProperties =
266
+ PropsByPacketSetType[typeof PropertySetType.subscribe];
267
+ export type SubackProperties =
268
+ PropsByPacketSetType[typeof PropertySetType.suback];
269
+ export type UnsubscribeProperties =
270
+ PropsByPacketSetType[typeof PropertySetType.unsubscribe];
271
+ export type UnsubackProperties =
272
+ PropsByPacketSetType[typeof PropertySetType.unsuback];
273
+ export type DisconnectProperties =
274
+ PropsByPacketSetType[typeof PropertySetType.disconnect];
275
+ export type AuthProperties = PropsByPacketSetType[typeof PropertySetType.auth];
276
+ export type WillProperties = PropsByPacketSetType[typeof PropertySetType.will];
@@ -0,0 +1,22 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { ReasonCode, reasonCodeToString } from "./ReasonCode.ts";
4
+ import { PacketType } from "./mod.ts";
5
+
6
+ test("lookup of reason codes works", () => {
7
+ assert.equal(
8
+ reasonCodeToString(PacketType.connect, ReasonCode.success),
9
+ "Success",
10
+ "Succes on Connect works",
11
+ );
12
+ assert.equal(
13
+ reasonCodeToString(PacketType.suback, ReasonCode.success),
14
+ "Granted QoS 0",
15
+ "Granted QoS 0 on Suback works",
16
+ );
17
+ assert.equal(
18
+ reasonCodeToString(PacketType.disconnect, ReasonCode.success),
19
+ "Normal disconnection",
20
+ "Normal disconnection on Disconnect works",
21
+ );
22
+ });
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Possible MQTT V5 reason codes
3
+ */
4
+
5
+ import { PacketType } from "./PacketType.ts";
6
+ import type { InvertRecord } from "./types.ts";
7
+
8
+ export const ReasonCode = {
9
+ success: 0x00,
10
+ normalDisconnection: 0x00,
11
+ grantedQos0: 0x00,
12
+ grantedQos1: 0x01,
13
+ grantedQos2: 0x02,
14
+ disconnectWithWillMessage: 0x04,
15
+ noMatchingSubscribers: 0x10,
16
+ noSubscriptionExisted: 0x11,
17
+ continueAuthentication: 0x18,
18
+ reAuthenticate: 0x19,
19
+ unspecifiedError: 0x80,
20
+ malformedPacket: 0x81,
21
+ protocolError: 0x82,
22
+ implementationSpecificError: 0x83,
23
+ unsupportedProtocolVersion: 0x84,
24
+ clientIdentifierNotValid: 0x85,
25
+ badUserNameOrPassword: 0x86,
26
+ notAuthorized: 0x87,
27
+ serverUnavailable: 0x88,
28
+ serverBusy: 0x89,
29
+ banned: 0x8a,
30
+ serverShuttingDown: 0x8b,
31
+ badAuthenticationMethod: 0x8c,
32
+ keepAliveTimeout: 0x8d,
33
+ sessionTakenOver: 0x8e,
34
+ topicFilterInvalid: 0x8f,
35
+ topicNameInvalid: 0x90,
36
+ packetIdentifierInUse: 0x91,
37
+ packetIdentifierNotFound: 0x92,
38
+ receiveMaximumExceeded: 0x93,
39
+ topicAliasInvalid: 0x94,
40
+ packetTooLarge: 0x95,
41
+ messageRateTooHigh: 0x96,
42
+ quotaExceeded: 0x97,
43
+ administrativeAction: 0x98,
44
+ payloadFormatInvalid: 0x99,
45
+ retainNotSupported: 0x9a,
46
+ qosNotSupported: 0x9b,
47
+ useAnotherServer: 0x9c,
48
+ serverMoved: 0x9d,
49
+ sharedSubscriptionsNotSupported: 0x9e,
50
+ connectionRateExceeded: 0x9f,
51
+ maximumConnectTime: 0xa0,
52
+ subscriptionIdentifiersNotSupported: 0xa1,
53
+ wildcardSubscriptionsNotSupported: 0xa2,
54
+ } as const;
55
+
56
+ /**
57
+ * Reverse lookup for ReasonCode
58
+ */
59
+
60
+ export type ReasonCodeByNumberType = InvertRecord<typeof ReasonCode>;
61
+ export const ReasonCodeByNumber = Object
62
+ .fromEntries(
63
+ Object.entries(ReasonCode).map(([k, v]) => [v, k]),
64
+ ) as ReasonCodeByNumberType;
65
+
66
+ export const ReasonCodebyPacket = {
67
+ [PacketType.connack]: [
68
+ ReasonCode.success,
69
+ ReasonCode.unspecifiedError,
70
+ ReasonCode.malformedPacket,
71
+ ReasonCode.protocolError,
72
+ ReasonCode.implementationSpecificError,
73
+ ReasonCode.unsupportedProtocolVersion,
74
+ ReasonCode.clientIdentifierNotValid,
75
+ ReasonCode.badUserNameOrPassword,
76
+ ReasonCode.notAuthorized,
77
+ ReasonCode.serverUnavailable,
78
+ ReasonCode.serverBusy,
79
+ ReasonCode.banned,
80
+ ReasonCode.badAuthenticationMethod,
81
+ ReasonCode.topicNameInvalid,
82
+ ReasonCode.packetTooLarge,
83
+ ReasonCode.quotaExceeded,
84
+ ReasonCode.payloadFormatInvalid,
85
+ ReasonCode.retainNotSupported,
86
+ ReasonCode.qosNotSupported,
87
+ ReasonCode.useAnotherServer,
88
+ ReasonCode.serverMoved,
89
+ ReasonCode.connectionRateExceeded,
90
+ ],
91
+ [PacketType.puback]: [
92
+ ReasonCode.success,
93
+ ReasonCode.noMatchingSubscribers,
94
+ ReasonCode.unspecifiedError,
95
+ ReasonCode.implementationSpecificError,
96
+ ReasonCode.notAuthorized,
97
+ ReasonCode.topicNameInvalid,
98
+ ReasonCode.packetIdentifierInUse,
99
+ ReasonCode.quotaExceeded,
100
+ ReasonCode.payloadFormatInvalid,
101
+ ],
102
+ [PacketType.pubrec]: [
103
+ ReasonCode.success,
104
+ ReasonCode.noMatchingSubscribers,
105
+ ReasonCode.unspecifiedError,
106
+ ReasonCode.implementationSpecificError,
107
+ ReasonCode.notAuthorized,
108
+ ReasonCode.topicNameInvalid,
109
+ ReasonCode.packetIdentifierInUse,
110
+ ReasonCode.quotaExceeded,
111
+ ReasonCode.payloadFormatInvalid,
112
+ ],
113
+ [PacketType.pubrel]: [
114
+ ReasonCode.success,
115
+ ReasonCode.packetIdentifierNotFound,
116
+ ],
117
+ [PacketType.pubcomp]: [
118
+ ReasonCode.success,
119
+ ReasonCode.packetIdentifierNotFound,
120
+ ],
121
+ [PacketType.unsuback]: [
122
+ ReasonCode.success,
123
+ ReasonCode.noSubscriptionExisted,
124
+ ReasonCode.unspecifiedError,
125
+ ReasonCode.implementationSpecificError,
126
+ ReasonCode.notAuthorized,
127
+ ReasonCode.topicFilterInvalid,
128
+ ReasonCode.packetIdentifierInUse,
129
+ ],
130
+ [PacketType.auth]: [
131
+ ReasonCode.success,
132
+ ReasonCode.continueAuthentication,
133
+ ReasonCode.reAuthenticate,
134
+ ],
135
+ [PacketType.disconnect]: [
136
+ ReasonCode.normalDisconnection,
137
+ ReasonCode.disconnectWithWillMessage,
138
+ ReasonCode.unspecifiedError,
139
+ ReasonCode.malformedPacket,
140
+ ReasonCode.protocolError,
141
+ ReasonCode.implementationSpecificError,
142
+ ReasonCode.notAuthorized,
143
+ ReasonCode.serverBusy,
144
+ ReasonCode.serverShuttingDown,
145
+ ReasonCode.badAuthenticationMethod,
146
+ ReasonCode.keepAliveTimeout,
147
+ ReasonCode.sessionTakenOver,
148
+ ReasonCode.topicFilterInvalid,
149
+ ReasonCode.topicNameInvalid,
150
+ ReasonCode.receiveMaximumExceeded,
151
+ ReasonCode.topicAliasInvalid,
152
+ ReasonCode.packetTooLarge,
153
+ ReasonCode.messageRateTooHigh,
154
+ ReasonCode.quotaExceeded,
155
+ ReasonCode.administrativeAction,
156
+ ReasonCode.payloadFormatInvalid,
157
+ ReasonCode.retainNotSupported,
158
+ ReasonCode.qosNotSupported,
159
+ ReasonCode.useAnotherServer,
160
+ ReasonCode.serverMoved,
161
+ ReasonCode.sharedSubscriptionsNotSupported,
162
+ ReasonCode.connectionRateExceeded,
163
+ ReasonCode.maximumConnectTime,
164
+ ReasonCode.subscriptionIdentifiersNotSupported,
165
+ ReasonCode.wildcardSubscriptionsNotSupported,
166
+ ],
167
+ [PacketType.suback]: [
168
+ ReasonCode.grantedQos0,
169
+ ReasonCode.grantedQos1,
170
+ ReasonCode.grantedQos2,
171
+ ReasonCode.unspecifiedError,
172
+ ReasonCode.implementationSpecificError,
173
+ ReasonCode.notAuthorized,
174
+ ReasonCode.topicFilterInvalid,
175
+ ReasonCode.packetIdentifierInUse,
176
+ ReasonCode.quotaExceeded,
177
+ ReasonCode.sharedSubscriptionsNotSupported,
178
+ ReasonCode.subscriptionIdentifiersNotSupported,
179
+ ReasonCode.wildcardSubscriptionsNotSupported,
180
+ ],
181
+ } as const;
182
+
183
+ const reasonCodesToString = {
184
+ [0x00]: "Success",
185
+ [0x01]: "Granted QoS 1",
186
+ [0x02]: "Granted QoS 2",
187
+ [0x04]: "Disconnect with Will Message",
188
+ [0x10]: "No matching subscribers",
189
+ [0x11]: "No subscription existed",
190
+ [0x18]: "Continue authentication",
191
+ [0x19]: "Re-authenticate",
192
+ [0x80]: "Unspecified error",
193
+ [0x81]: "Malformed Packet",
194
+ [0x82]: "Protocol Error",
195
+ [0x83]: "Implementation specific error",
196
+ [0x84]: "Unsupported Protocol Version",
197
+ [0x85]: "Client Identifier not valid",
198
+ [0x86]: "Bad User Name or Password",
199
+ [0x87]: "Not authorized",
200
+ [0x88]: "Server unavailable",
201
+ [0x89]: "Server busy",
202
+ [0x8a]: "Banned",
203
+ [0x8b]: "Server shutting down",
204
+ [0x8c]: "Bad authentication method",
205
+ [0x8d]: "Keep Alive timeout",
206
+ [0x8e]: "Session taken over",
207
+ [0x8f]: "Topic Filter invalid",
208
+ [0x90]: "Topic Name invalid",
209
+ [0x91]: "Packet Identifier in use",
210
+ [0x92]: "Packet Identifier not found",
211
+ [0x93]: "Receive Maximum exceeded",
212
+ [0x94]: "Topic Alias invalid",
213
+ [0x95]: "Packet too large",
214
+ [0x96]: "Message rate too high",
215
+ [0x97]: "Quota exceeded",
216
+ [0x98]: "Administrative action",
217
+ [0x99]: "Payload format invalid",
218
+ [0x9a]: "Retain not supported",
219
+ [0x9b]: "QoS not supported",
220
+ [0x9c]: "Use another server",
221
+ [0x9d]: "Server moved",
222
+ [0x9e]: "Shared Subscriptions not supported",
223
+ [0x9f]: "Connection rate exceeded",
224
+ [0xa0]: "Maximum connect time",
225
+ [0xa1]: "Subscription Identifiers not supported",
226
+ [0xa2]: "Wildcard Subscriptions not supported",
227
+ } as const;
228
+
229
+ // Can't import this from types as this would create an import loop
230
+ type TPacketType = typeof PacketType[keyof typeof PacketType];
231
+ export type TReasonCode = typeof ReasonCode[keyof typeof ReasonCode];
232
+ type TReasonCodeByPacket = keyof typeof ReasonCodebyPacket;
233
+
234
+ export function reasonCodeToString(
235
+ packetType: TPacketType,
236
+ code: TReasonCode,
237
+ ): string {
238
+ if (code === 0) {
239
+ if (packetType === PacketType.disconnect) {
240
+ return "Normal disconnection";
241
+ }
242
+ if (packetType === PacketType.suback) {
243
+ return "Granted QoS 0";
244
+ }
245
+ }
246
+ return reasonCodesToString[code];
247
+ }
248
+
249
+ export function isValidReasonCode(
250
+ packetType: TPacketType,
251
+ code: number,
252
+ ): boolean {
253
+ const validReasonCodes =
254
+ ReasonCodebyPacket[packetType as TReasonCodeByPacket] as readonly number[];
255
+ return validReasonCodes.includes(code);
256
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ *RetainHandling
3
+ 0 = Send retained messages at the time of the subscribe
4
+ 1 = Send retained messages at subscribe only if the subscription does not currently exist
5
+ 2 = Do not send retained messages at the time of the subscribe
6
+ */
7
+ export const RetainHandling = {
8
+ sendRetained: 0,
9
+ ifSubscriptionNotExists: 1,
10
+ noRetain: 2,
11
+ } as const;
@@ -0,0 +1,112 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { decode, encode, MQTTLevel, PacketType, ReasonCode } from "./mod.ts";
4
+ import type { AuthPacket, CodecOpts } from "./mod.ts";
5
+
6
+ const codecOptsV5: CodecOpts = {
7
+ protocolLevel: MQTTLevel.v5,
8
+ maxIncomingPacketSize: 0xffff,
9
+ maxOutgoingPacketSize: 0xffff,
10
+ };
11
+
12
+ const codecOptsV4: CodecOpts = {
13
+ protocolLevel: MQTTLevel.v4,
14
+ maxIncomingPacketSize: 0xffff,
15
+ maxOutgoingPacketSize: 0xffff,
16
+ };
17
+
18
+ test("decode Auth V5 with invalid reasonCode", () => {
19
+ assert.throws(
20
+ () =>
21
+ decode(
22
+ Uint8Array.from([
23
+ // fixedHeader
24
+ 0x20, // packetType + flags
25
+ 2, // remainingLength
26
+ // variableHeader
27
+ 0, // reason code
28
+ 64, // (reserved)
29
+ ]),
30
+ codecOptsV5,
31
+ ),
32
+ /Invalid reason code/,
33
+ );
34
+ });
35
+
36
+ test("decode Auth V5 as V4", () => {
37
+ assert.throws(
38
+ () =>
39
+ decode(
40
+ Uint8Array.from([
41
+ // fixedHeader
42
+ 0xf0, // packetType + flags
43
+ 2, // remainingLength
44
+ // variableHeader
45
+ 0, // reason code
46
+ 0, // properties length
47
+ ]),
48
+ codecOptsV4,
49
+ ),
50
+ /Invalid protocol level/,
51
+ );
52
+ });
53
+
54
+ test("encode/decode minimal auth V5", () => {
55
+ const packet = {
56
+ protocolLevel: MQTTLevel.v5,
57
+ type: PacketType.auth,
58
+ reasonCode: ReasonCode.success,
59
+ };
60
+ const encoded = encode(packet, codecOptsV5);
61
+ assert.deepStrictEqual(
62
+ encoded,
63
+ Uint8Array.from([
64
+ // fixedHeader
65
+
66
+ 0xf0, // auth packet + flags
67
+ 2, // remaining length
68
+ 0, // reason code
69
+ 0, // property length
70
+ ]),
71
+ );
72
+ const decoded = decode(encoded, codecOptsV5);
73
+ assert.deepStrictEqual(decoded, { ...packet, properties: {} });
74
+ });
75
+
76
+ test("encode/decode auth V5", () => {
77
+ const packet: AuthPacket = {
78
+ protocolLevel: 5,
79
+ type: PacketType.auth,
80
+ reasonCode: ReasonCode.continueAuthentication,
81
+ properties: {
82
+ userProperty: [["key", "value"]],
83
+ },
84
+ };
85
+ const encoded = encode(packet, codecOptsV5);
86
+ assert.deepStrictEqual(
87
+ encoded,
88
+ Uint8Array.from([
89
+ // fixedHeader
90
+
91
+ 0xf0, // auth packet + flags
92
+ 15, // remaining length
93
+ 24, // reason code
94
+ 13, // property length
95
+ 38, // user property
96
+ 0, // string MSB
97
+ 3, // string LSB
98
+ 107, // k
99
+ 101, // e
100
+ 121, // y
101
+ 0, // string MSB
102
+ 5, // string LSB
103
+ 118, // v
104
+ 97, // a
105
+ 108, // l
106
+ 117, // u
107
+ 101, // e
108
+ ]),
109
+ );
110
+ const decoded = decode(encoded, codecOptsV5);
111
+ assert.deepStrictEqual(decoded, packet);
112
+ });