mqtt-plus 1.4.13 → 1.4.15

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 (92) hide show
  1. package/AGENTS.md +0 -1
  2. package/CHANGELOG.md +18 -0
  3. package/dst-stage1/mqtt-plus-api.js +1 -0
  4. package/dst-stage1/mqtt-plus-api.js.map +1 -0
  5. package/dst-stage1/mqtt-plus-auth.js +1 -0
  6. package/dst-stage1/mqtt-plus-auth.js.map +1 -0
  7. package/dst-stage1/mqtt-plus-base.js +1 -0
  8. package/dst-stage1/mqtt-plus-base.js.map +1 -0
  9. package/dst-stage1/mqtt-plus-codec.js +1 -0
  10. package/dst-stage1/mqtt-plus-codec.js.map +1 -0
  11. package/dst-stage1/mqtt-plus-encode.js +1 -0
  12. package/dst-stage1/mqtt-plus-encode.js.map +1 -0
  13. package/dst-stage1/mqtt-plus-error.js +1 -0
  14. package/dst-stage1/mqtt-plus-error.js.map +1 -0
  15. package/dst-stage1/mqtt-plus-event.js +1 -0
  16. package/dst-stage1/mqtt-plus-event.js.map +1 -0
  17. package/dst-stage1/mqtt-plus-info.js +1 -0
  18. package/dst-stage1/mqtt-plus-info.js.map +1 -0
  19. package/dst-stage1/mqtt-plus-meta.js +1 -0
  20. package/dst-stage1/mqtt-plus-meta.js.map +1 -0
  21. package/dst-stage1/mqtt-plus-msg.js +1 -0
  22. package/dst-stage1/mqtt-plus-msg.js.map +1 -0
  23. package/dst-stage1/mqtt-plus-options.js +1 -0
  24. package/dst-stage1/mqtt-plus-options.js.map +1 -0
  25. package/dst-stage1/mqtt-plus-service.js +1 -0
  26. package/dst-stage1/mqtt-plus-service.js.map +1 -0
  27. package/dst-stage1/mqtt-plus-sink.js +14 -2
  28. package/dst-stage1/mqtt-plus-sink.js.map +1 -0
  29. package/dst-stage1/mqtt-plus-source.js +27 -16
  30. package/dst-stage1/mqtt-plus-source.js.map +1 -0
  31. package/dst-stage1/mqtt-plus-subscription.js +1 -0
  32. package/dst-stage1/mqtt-plus-subscription.js.map +1 -0
  33. package/dst-stage1/mqtt-plus-timer.js +1 -0
  34. package/dst-stage1/mqtt-plus-timer.js.map +1 -0
  35. package/dst-stage1/mqtt-plus-trace.js +1 -0
  36. package/dst-stage1/mqtt-plus-trace.js.map +1 -0
  37. package/dst-stage1/mqtt-plus-util.js +1 -0
  38. package/dst-stage1/mqtt-plus-util.js.map +1 -0
  39. package/dst-stage1/mqtt-plus-version.d.ts +1 -1
  40. package/dst-stage1/mqtt-plus-version.js +3 -1
  41. package/dst-stage1/mqtt-plus-version.js.map +1 -0
  42. package/dst-stage1/mqtt-plus.js +1 -0
  43. package/dst-stage1/mqtt-plus.js.map +1 -0
  44. package/dst-stage2/mqtt-plus.cjs.js +1972 -2161
  45. package/dst-stage2/mqtt-plus.esm.js +1934 -2131
  46. package/dst-stage2/mqtt-plus.umd.js +13 -14
  47. package/etc/c8.json +16 -0
  48. package/etc/knip.jsonc +7 -1
  49. package/etc/stx.conf +36 -4
  50. package/etc/tsc.json +1 -1
  51. package/etc/vite.mts +11 -5
  52. package/package.d/vite+8.0.0.patch +12 -0
  53. package/package.json +12 -3
  54. package/src/mqtt-plus-sink.ts +14 -2
  55. package/src/mqtt-plus-source.ts +27 -16
  56. package/src/mqtt-plus-version.ts +2 -3
  57. package/tst/.c8/base.css +224 -0
  58. package/tst/.c8/block-navigation.js +87 -0
  59. package/tst/.c8/favicon.png +0 -0
  60. package/tst/.c8/index.html +371 -0
  61. package/tst/.c8/mqtt-plus-auth.ts.html +538 -0
  62. package/tst/.c8/mqtt-plus-base.ts.html +826 -0
  63. package/tst/.c8/mqtt-plus-codec.ts.html +457 -0
  64. package/tst/.c8/mqtt-plus-encode.ts.html +310 -0
  65. package/tst/.c8/mqtt-plus-error.ts.html +1186 -0
  66. package/tst/.c8/mqtt-plus-event.ts.html +733 -0
  67. package/tst/.c8/mqtt-plus-meta.ts.html +271 -0
  68. package/tst/.c8/mqtt-plus-msg.ts.html +1693 -0
  69. package/tst/.c8/mqtt-plus-options.ts.html +319 -0
  70. package/tst/.c8/mqtt-plus-service.ts.html +865 -0
  71. package/tst/.c8/mqtt-plus-sink.ts.html +1645 -0
  72. package/tst/.c8/mqtt-plus-source.ts.html +1585 -0
  73. package/tst/.c8/mqtt-plus-subscription.ts.html +706 -0
  74. package/tst/.c8/mqtt-plus-timer.ts.html +286 -0
  75. package/tst/.c8/mqtt-plus-trace.ts.html +463 -0
  76. package/tst/.c8/mqtt-plus-util.ts.html +823 -0
  77. package/tst/.c8/mqtt-plus-version.ts.html +205 -0
  78. package/tst/.c8/mqtt-plus.ts.html +193 -0
  79. package/tst/.c8/prettify.css +1 -0
  80. package/tst/.c8/prettify.js +2 -0
  81. package/tst/.c8/sort-arrow-sprite.png +0 -0
  82. package/tst/.c8/sorter.js +210 -0
  83. package/tst/.c8/tmp/coverage-6577-1773528098323-2.json +1 -0
  84. package/tst/.c8/tmp/coverage-6577-1773528098331-1.json +1 -0
  85. package/tst/.c8/tmp/coverage-6577-1773528098353-0.json +1 -0
  86. package/tst/.c8/tmp/coverage-6578-1773528089194-0.json +1 -0
  87. package/tst/mqtt-plus-2-event.spec.ts +29 -0
  88. package/tst/mqtt-plus-6-misc.spec.ts +79 -2
  89. package/tst/mqtt-plus-7-spool.spec.ts +101 -0
  90. package/tst/mqtt-plus-8-run.spec.ts +115 -0
  91. package/tst/{tsc.json → tsc.cov.json} +4 -3
  92. package/tst/tsc.std.json +31 -0
@@ -0,0 +1,826 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for mqtt-plus-base.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="prettify.css" />
9
+ <link rel="stylesheet" href="base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="index.html">All files</a> mqtt-plus-base.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">88.66% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>219/247</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">79.31% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>46/58</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>17/17</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">88.66% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>219/247</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
314
+ <span class="cline-any cline-yes">1x</span>
315
+ <span class="cline-any cline-yes">1x</span>
316
+ <span class="cline-any cline-yes">1x</span>
317
+ <span class="cline-any cline-yes">1x</span>
318
+ <span class="cline-any cline-yes">1x</span>
319
+ <span class="cline-any cline-yes">1x</span>
320
+ <span class="cline-any cline-yes">1x</span>
321
+ <span class="cline-any cline-yes">1x</span>
322
+ <span class="cline-any cline-yes">1x</span>
323
+ <span class="cline-any cline-yes">1x</span>
324
+ <span class="cline-any cline-yes">1x</span>
325
+ <span class="cline-any cline-yes">1x</span>
326
+ <span class="cline-any cline-yes">1x</span>
327
+ <span class="cline-any cline-yes">1x</span>
328
+ <span class="cline-any cline-yes">1x</span>
329
+ <span class="cline-any cline-yes">1x</span>
330
+ <span class="cline-any cline-yes">1x</span>
331
+ <span class="cline-any cline-yes">1x</span>
332
+ <span class="cline-any cline-yes">1x</span>
333
+ <span class="cline-any cline-yes">1x</span>
334
+ <span class="cline-any cline-yes">1x</span>
335
+ <span class="cline-any cline-yes">1x</span>
336
+ <span class="cline-any cline-yes">1x</span>
337
+ <span class="cline-any cline-yes">1x</span>
338
+ <span class="cline-any cline-yes">1x</span>
339
+ <span class="cline-any cline-yes">1x</span>
340
+ <span class="cline-any cline-yes">1x</span>
341
+ <span class="cline-any cline-yes">1x</span>
342
+ <span class="cline-any cline-yes">1x</span>
343
+ <span class="cline-any cline-yes">1x</span>
344
+ <span class="cline-any cline-yes">1x</span>
345
+ <span class="cline-any cline-yes">1x</span>
346
+ <span class="cline-any cline-yes">1x</span>
347
+ <span class="cline-any cline-yes">1x</span>
348
+ <span class="cline-any cline-yes">1x</span>
349
+ <span class="cline-any cline-yes">1x</span>
350
+ <span class="cline-any cline-yes">1x</span>
351
+ <span class="cline-any cline-yes">1x</span>
352
+ <span class="cline-any cline-yes">1x</span>
353
+ <span class="cline-any cline-yes">1x</span>
354
+ <span class="cline-any cline-yes">9x</span>
355
+ <span class="cline-any cline-yes">9x</span>
356
+ <span class="cline-any cline-yes">9x</span>
357
+ <span class="cline-any cline-yes">9x</span>
358
+ <span class="cline-any cline-yes">9x</span>
359
+ <span class="cline-any cline-yes">1x</span>
360
+ <span class="cline-any cline-yes">1x</span>
361
+ <span class="cline-any cline-yes">1x</span>
362
+ <span class="cline-any cline-yes">9x</span>
363
+ <span class="cline-any cline-yes">9x</span>
364
+ <span class="cline-any cline-yes">9x</span>
365
+ <span class="cline-any cline-yes">9x</span>
366
+ <span class="cline-any cline-yes">9x</span>
367
+ <span class="cline-any cline-yes">9x</span>
368
+ <span class="cline-any cline-yes">9x</span>
369
+ <span class="cline-any cline-yes">9x</span>
370
+ <span class="cline-any cline-yes">2x</span>
371
+ <span class="cline-any cline-yes">2x</span>
372
+ <span class="cline-any cline-yes">2x</span>
373
+ <span class="cline-any cline-yes">4x</span>
374
+ <span class="cline-any cline-yes">4x</span>
375
+ <span class="cline-any cline-yes">4x</span>
376
+ <span class="cline-any cline-yes">4x</span>
377
+ <span class="cline-any cline-no">&nbsp;</span>
378
+ <span class="cline-any cline-no">&nbsp;</span>
379
+ <span class="cline-any cline-no">&nbsp;</span>
380
+ <span class="cline-any cline-no">&nbsp;</span>
381
+ <span class="cline-any cline-no">&nbsp;</span>
382
+ <span class="cline-any cline-no">&nbsp;</span>
383
+ <span class="cline-any cline-yes">4x</span>
384
+ <span class="cline-any cline-yes">2x</span>
385
+ <span class="cline-any cline-yes">2x</span>
386
+ <span class="cline-any cline-yes">9x</span>
387
+ <span class="cline-any cline-yes">9x</span>
388
+ <span class="cline-any cline-yes">9x</span>
389
+ <span class="cline-any cline-yes">9x</span>
390
+ <span class="cline-any cline-yes">9x</span>
391
+ <span class="cline-any cline-yes">9x</span>
392
+ <span class="cline-any cline-yes">9x</span>
393
+ <span class="cline-any cline-yes">1093x</span>
394
+ <span class="cline-any cline-yes">1093x</span>
395
+ <span class="cline-any cline-yes">1093x</span>
396
+ <span class="cline-any cline-yes">1093x</span>
397
+ <span class="cline-any cline-yes">1093x</span>
398
+ <span class="cline-any cline-yes">1093x</span>
399
+ <span class="cline-any cline-yes">1093x</span>
400
+ <span class="cline-any cline-yes">1092x</span>
401
+ <span class="cline-any cline-yes">1092x</span>
402
+ <span class="cline-any cline-yes">1092x</span>
403
+ <span class="cline-any cline-no">&nbsp;</span>
404
+ <span class="cline-any cline-no">&nbsp;</span>
405
+ <span class="cline-any cline-no">&nbsp;</span>
406
+ <span class="cline-any cline-yes">1093x</span>
407
+ <span class="cline-any cline-yes">1093x</span>
408
+ <span class="cline-any cline-yes">9x</span>
409
+ <span class="cline-any cline-yes">9x</span>
410
+ <span class="cline-any cline-yes">1x</span>
411
+ <span class="cline-any cline-yes">1x</span>
412
+ <span class="cline-any cline-yes">1x</span>
413
+ <span class="cline-any cline-yes">9x</span>
414
+ <span class="cline-any cline-yes">9x</span>
415
+ <span class="cline-any cline-yes">9x</span>
416
+ <span class="cline-any cline-yes">9x</span>
417
+ <span class="cline-any cline-yes">9x</span>
418
+ <span class="cline-any cline-yes">1x</span>
419
+ <span class="cline-any cline-yes">1x</span>
420
+ <span class="cline-any cline-yes">1x</span>
421
+ <span class="cline-any cline-yes">28x</span>
422
+ <span class="cline-any cline-yes">28x</span>
423
+ <span class="cline-any cline-yes">28x</span>
424
+ <span class="cline-any cline-yes">28x</span>
425
+ <span class="cline-any cline-yes">28x</span>
426
+ <span class="cline-any cline-no">&nbsp;</span>
427
+ <span class="cline-any cline-no">&nbsp;</span>
428
+ <span class="cline-any cline-no">&nbsp;</span>
429
+ <span class="cline-any cline-yes">28x</span>
430
+ <span class="cline-any cline-yes">28x</span>
431
+ <span class="cline-any cline-yes">28x</span>
432
+ <span class="cline-any cline-yes">28x</span>
433
+ <span class="cline-any cline-yes">1x</span>
434
+ <span class="cline-any cline-yes">1x</span>
435
+ <span class="cline-any cline-yes">1x</span>
436
+ <span class="cline-any cline-yes">19x</span>
437
+ <span class="cline-any cline-yes">19x</span>
438
+ <span class="cline-any cline-yes">19x</span>
439
+ <span class="cline-any cline-yes">19x</span>
440
+ <span class="cline-any cline-no">&nbsp;</span>
441
+ <span class="cline-any cline-no">&nbsp;</span>
442
+ <span class="cline-any cline-no">&nbsp;</span>
443
+ <span class="cline-any cline-yes">19x</span>
444
+ <span class="cline-any cline-yes">19x</span>
445
+ <span class="cline-any cline-yes">19x</span>
446
+ <span class="cline-any cline-yes">19x</span>
447
+ <span class="cline-any cline-yes">19x</span>
448
+ <span class="cline-any cline-yes">1x</span>
449
+ <span class="cline-any cline-yes">1x</span>
450
+ <span class="cline-any cline-yes">1x</span>
451
+ <span class="cline-any cline-yes">19x</span>
452
+ <span class="cline-any cline-yes">19x</span>
453
+ <span class="cline-any cline-yes">19x</span>
454
+ <span class="cline-any cline-yes">19x</span>
455
+ <span class="cline-any cline-yes">7x</span>
456
+ <span class="cline-any cline-yes">7x</span>
457
+ <span class="cline-any cline-yes">7x</span>
458
+ <span class="cline-any cline-yes">12x</span>
459
+ <span class="cline-any cline-yes">12x</span>
460
+ <span class="cline-any cline-yes">19x</span>
461
+ <span class="cline-any cline-yes">19x</span>
462
+ <span class="cline-any cline-yes">19x</span>
463
+ <span class="cline-any cline-yes">1x</span>
464
+ <span class="cline-any cline-yes">1x</span>
465
+ <span class="cline-any cline-yes">1x</span>
466
+ <span class="cline-any cline-yes">1093x</span>
467
+ <span class="cline-any cline-yes">1093x</span>
468
+ <span class="cline-any cline-yes">1093x</span>
469
+ <span class="cline-any cline-yes">1093x</span>
470
+ <span class="cline-any cline-yes">1093x</span>
471
+ <span class="cline-any cline-yes">1093x</span>
472
+ <span class="cline-any cline-yes">1093x</span>
473
+ <span class="cline-any cline-yes">1092x</span>
474
+ <span class="cline-any cline-yes">1092x</span>
475
+ <span class="cline-any cline-yes">1093x</span>
476
+ <span class="cline-any cline-yes">1093x</span>
477
+ <span class="cline-any cline-yes">1093x</span>
478
+ <span class="cline-any cline-yes">1090x</span>
479
+ <span class="cline-any cline-yes">1090x</span>
480
+ <span class="cline-any cline-yes">1090x</span>
481
+ <span class="cline-any cline-yes">1090x</span>
482
+ <span class="cline-any cline-yes">1090x</span>
483
+ <span class="cline-any cline-no">&nbsp;</span>
484
+ <span class="cline-any cline-no">&nbsp;</span>
485
+ <span class="cline-any cline-no">&nbsp;</span>
486
+ <span class="cline-any cline-yes">1090x</span>
487
+ <span class="cline-any cline-yes">1093x</span>
488
+ <span class="cline-any cline-yes">1093x</span>
489
+ <span class="cline-any cline-yes">1093x</span>
490
+ <span class="cline-any cline-yes">1093x</span>
491
+ <span class="cline-any cline-yes">1093x</span>
492
+ <span class="cline-any cline-yes">1093x</span>
493
+ <span class="cline-any cline-yes">1093x</span>
494
+ <span class="cline-any cline-yes">1x</span>
495
+ <span class="cline-any cline-yes">1092x</span>
496
+ <span class="cline-any cline-yes">1093x</span>
497
+ <span class="cline-any cline-yes">1093x</span>
498
+ <span class="cline-any cline-no">&nbsp;</span>
499
+ <span class="cline-any cline-no">&nbsp;</span>
500
+ <span class="cline-any cline-no">&nbsp;</span>
501
+ <span class="cline-any cline-yes">1093x</span>
502
+ <span class="cline-any cline-yes">1093x</span>
503
+ <span class="cline-any cline-yes">1093x</span>
504
+ <span class="cline-any cline-yes">1093x</span>
505
+ <span class="cline-any cline-yes">1093x</span>
506
+ <span class="cline-any cline-yes">1x</span>
507
+ <span class="cline-any cline-yes">1x</span>
508
+ <span class="cline-any cline-yes">1x</span>
509
+ <span class="cline-any cline-yes">1093x</span>
510
+ <span class="cline-any cline-yes">1093x</span>
511
+ <span class="cline-any cline-yes">1093x</span>
512
+ <span class="cline-any cline-yes">1093x</span>
513
+ <span class="cline-any cline-yes">1093x</span>
514
+ <span class="cline-any cline-yes">1093x</span>
515
+ <span class="cline-any cline-yes">1093x</span>
516
+ <span class="cline-any cline-yes">1093x</span>
517
+ <span class="cline-any cline-yes">1092x</span>
518
+ <span class="cline-any cline-yes">1092x</span>
519
+ <span class="cline-any cline-yes">1093x</span>
520
+ <span class="cline-any cline-yes">1093x</span>
521
+ <span class="cline-any cline-yes">1093x</span>
522
+ <span class="cline-any cline-yes">1093x</span>
523
+ <span class="cline-any cline-yes">1x</span>
524
+ <span class="cline-any cline-yes">1x</span>
525
+ <span class="cline-any cline-yes">1x</span>
526
+ <span class="cline-any cline-yes">1x</span>
527
+ <span class="cline-any cline-yes">1093x</span>
528
+ <span class="cline-any cline-yes">1093x</span>
529
+ <span class="cline-any cline-yes">1093x</span>
530
+ <span class="cline-any cline-yes">1092x</span>
531
+ <span class="cline-any cline-yes">1092x</span>
532
+ <span class="cline-any cline-yes">1092x</span>
533
+ <span class="cline-any cline-no">&nbsp;</span>
534
+ <span class="cline-any cline-no">&nbsp;</span>
535
+ <span class="cline-any cline-no">&nbsp;</span>
536
+ <span class="cline-any cline-no">&nbsp;</span>
537
+ <span class="cline-any cline-yes">1093x</span>
538
+ <span class="cline-any cline-yes">1092x</span>
539
+ <span class="cline-any cline-yes">1092x</span>
540
+ <span class="cline-any cline-yes">1093x</span>
541
+ <span class="cline-any cline-yes">33x</span>
542
+ <span class="cline-any cline-yes">33x</span>
543
+ <span class="cline-any cline-yes">33x</span>
544
+ <span class="cline-any cline-yes">32x</span>
545
+ <span class="cline-any cline-no">&nbsp;</span>
546
+ <span class="cline-any cline-yes">32x</span>
547
+ <span class="cline-any cline-yes">32x</span>
548
+ <span class="cline-any cline-yes">33x</span>
549
+ <span class="cline-any cline-yes">1059x</span>
550
+ <span class="cline-any cline-yes">1059x</span>
551
+ <span class="cline-any cline-yes">1059x</span>
552
+ <span class="cline-any cline-yes">1059x</span>
553
+ <span class="cline-any cline-yes">1056x</span>
554
+ <span class="cline-any cline-no">&nbsp;</span>
555
+ <span class="cline-any cline-yes">1056x</span>
556
+ <span class="cline-any cline-yes">1056x</span>
557
+ <span class="cline-any cline-yes">1059x</span>
558
+ <span class="cline-any cline-yes">1093x</span>
559
+ <span class="cline-any cline-no">&nbsp;</span>
560
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js"><span class="branch-0 cbranch-no" title="branch not covered" >/*</span>
561
+ ** MQTT+ -- MQTT Communication Patterns
562
+ ** Copyright (c) 2018-2026 Dr. Ralf S. Engelschall &lt;rse@engelschall.com&gt;
563
+ **
564
+ ** Permission is hereby granted, free of charge, to any person obtaining
565
+ ** a copy of this software and associated documentation files (the
566
+ ** "Software"), to deal in the Software without restriction, including
567
+ ** without limitation the rights to use, copy, modify, merge, publish,
568
+ ** distribute, sublicense, and/or sell copies of the Software, and to
569
+ ** permit persons to whom the Software is furnished to do so, subject to
570
+ ** the following conditions:
571
+ **
572
+ ** The above copyright notice and this permission notice shall be included
573
+ ** in all copies or substantial portions of the Software.
574
+ **
575
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
576
+ ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
577
+ ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
578
+ ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
579
+ ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
580
+ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
581
+ ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
582
+ */
583
+ &nbsp;
584
+ /* external requirements */
585
+ import { type MqttClient,
586
+ type OnMessageCallback,
587
+ type IClientSubscribeOptions,
588
+ type IClientPublishOptions,
589
+ type IPublishPacket } from "mqtt"
590
+ &nbsp;
591
+ /* internal requirements */
592
+ import type { APISchema, Registration } from "./mqtt-plus-api"
593
+ import type { APIOptions } from "./mqtt-plus-options"
594
+ import { TraceTrait } from "./mqtt-plus-trace"
595
+ import { Spool, ensureError } from "./mqtt-plus-error"
596
+ import { PLazy } from "./mqtt-plus-util"
597
+ &nbsp;
598
+ /* MQTTp Base class with shared infrastructure */
599
+ export class BaseTrait&lt;T extends APISchema = APISchema&gt; extends TraceTrait&lt;T&gt; {
600
+ private mqtt: MqttClient
601
+ private messageHandler: OnMessageCallback
602
+ &nbsp;
603
+ /* central message callback registries */
604
+ protected onRequest = new Map&lt;string, (message: any, topicName: string) =&gt; void | Promise&lt;void&gt;&gt;()
605
+ protected onResponse = new Map&lt;string, (message: any, topicName: string) =&gt; void | Promise&lt;void&gt;&gt;()
606
+ &nbsp;
607
+ /* construct API class */
608
+ constructor (
609
+ mqtt: MqttClient | null,
610
+ options: Partial&lt;APIOptions&gt; = {}
611
+ ) {
612
+ super(options)
613
+ &nbsp;
614
+ /* optionally provide a fake proxy for the MQTT client
615
+ (mainly for using emit({ ..., dry: true }) to just make MQTT "last will") */
616
+ if (mqtt === null) {
617
+ this.log("info", "establishing proxy MQTT client")
618
+ mqtt = new Proxy&lt;MqttClient&gt;({} as MqttClient, {
619
+ get (_target, prop, _receiver): any {
620
+ if (prop === "isFakeProxy")
621
+ <span class="branch-0 cbranch-no" title="branch not covered" > return true</span>
622
+ else if (typeof prop === "string" &amp;&amp; [ "on", "off", "once" ].includes(prop))
623
+ return () =&gt; {<span class="branch-0 cbranch-no" title="branch not covered" >}</span>
624
+ <span class="cstat-no" title="statement not covered" > else</span>
625
+ <span class="cstat-no" title="statement not covered" > return () =&gt; {</span>
626
+ <span class="cstat-no" title="statement not covered" > throw new Error(`Underlying MQTT operation "${String(prop)}" called ` +</span>
627
+ <span class="cstat-no" title="statement not covered" > "on a null MQTT client -- only MQTT+ \"emit({ ..., dry: true })\" " +</span>
628
+ <span class="cstat-no" title="statement not covered" > "is supported in this special operation mode")</span>
629
+ <span class="cstat-no" title="statement not covered" > }</span>
630
+ }
631
+ })
632
+ }
633
+ &nbsp;
634
+ /* store MQTT client */
635
+ this.mqtt = mqtt
636
+ &nbsp;
637
+ /* hook into the MQTT message processing */
638
+ this.log("info", "hooking into MQTT client")
639
+ this.messageHandler = (topic, message, packet) =&gt; {
640
+ /* convert message to codec-specific input format
641
+ (NOTICE: MQTT.js uses Buffer in its handler signature only,
642
+ but internally supports string or Buffer, while we are
643
+ dealing with string or Uint8Array only) */
644
+ let input: Uint8Array | string
645
+ if (this.options.codec === "json")
646
+ input = message.toString()
647
+ else if (this.options.codec === "cbor")
648
+ input = Buffer.isBuffer(message)
649
+ ? new Uint8Array(message.buffer, message.byteOffset, message.byteLength<span class="branch-0 cbranch-no" title="branch not covered" >)</span>
650
+ <span class="cstat-no" title="statement not covered" > : <span class="branch-0 cbranch-no" title="branch not covered" >message</span></span>
651
+ <span class="cstat-no" title="statement not covered" > else</span>
652
+ <span class="cstat-no" title="statement not covered" > throw new Error("invalid codec configured")</span>
653
+ this._onMessage(topic, input, packet)
654
+ }
655
+ this.mqtt.on("message", this.messageHandler)
656
+ }
657
+ &nbsp;
658
+ /* destroy API class */
659
+ async destroy () {
660
+ this.log("info", "un-hooking from MQTT client")
661
+ this.mqtt.off("message", this.messageHandler)
662
+ this.onRequest.clear()
663
+ this.onResponse.clear()
664
+ }
665
+ &nbsp;
666
+ /* create a registration for subsequent destruction */
667
+ protected makeRegistration (spool: Spool, kind: string, name: string, key: string): Registration {
668
+ return {
669
+ destroy: async (): Promise&lt;void&gt; =&gt; {
670
+ if (!this.onRequest.has(key))
671
+ <span class="branch-0 cbranch-no" title="branch not covered" > throw new Error(`destroy: ${kind} "${name}" not registered`)</span>
672
+ await spool.unroll(false)?.catch((err: unknown) =&gt; {
673
+ <span class="cstat-no" title="statement not covered" > const error = ensureError(err, `destroy: ${kind} "${name}" failed to cleanup`)</span>
674
+ <span class="cstat-no" title="statement not covered" > this.error(error)</span>
675
+ <span class="cstat-no" title="statement not covered" > throw error</span>
676
+ })
677
+ }
678
+ }
679
+ }
680
+ &nbsp;
681
+ /* subscribe to an MQTT topic (Promise-based) */
682
+ protected async subscribeTopic (topic: string, options: Partial&lt;IClientSubscribeOptions&gt; = {}) {
683
+ this.log("info", `subscribing to MQTT topic "${topic}"`)
684
+ return new Promise&lt;void&gt;((resolve, reject) =&gt; {
685
+ this.mqtt.subscribe(topic, { qos: 2, ...options }, (err: Error | null, _granted: any) =&gt; {
686
+ if (err) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
687
+ <span class="cstat-no" title="statement not covered" > this.error(err, `subscribing to MQTT topic "${topic}" failed`)</span>
688
+ <span class="cstat-no" title="statement not covered" > reject(err)</span>
689
+ <span class="cstat-no" title="statement not covered" > }</span>
690
+ else
691
+ resolve()
692
+ })
693
+ })
694
+ }
695
+ &nbsp;
696
+ /* unsubscribe from an MQTT topic (Promise-based) */
697
+ protected async unsubscribeTopic (topic: string) {
698
+ this.log("info", `unsubscribing from MQTT topic "${topic}"`)
699
+ return new Promise&lt;void&gt;((resolve, reject) =&gt; {
700
+ this.mqtt.unsubscribe(topic, (err?: Error, _packet?: any) =&gt; {
701
+ if (err) {
702
+ this.error(err, `unsubscribing from MQTT topic "${topic}" failed`)
703
+ reject(err)
704
+ }
705
+ else
706
+ resolve()
707
+ })
708
+ })
709
+ }
710
+ &nbsp;
711
+ /* publish to an MQTT topic (Promise-based) */
712
+ protected async publishToTopic (
713
+ topic: string,
714
+ message: string | Uint8Array,
715
+ options: IClientPublishOptions = {}
716
+ ) {
717
+ /* determine buffer */
718
+ if (typeof message === "string")
719
+ this.log("info", `publishing to MQTT topic "${topic}" (type: string, length: ${message.length} chars)`)
720
+ else
721
+ this.log("info", `publishing to MQTT topic "${topic}" (type: buffer, length: ${message.byteLength} bytes)`)
722
+ &nbsp;
723
+ /* provide decoded message on demand */
724
+ const messageOnDemand = new PLazy&lt;any&gt;((resolve, reject) =&gt; {
725
+ let parsed: any
726
+ try {
727
+ const payload = this.codec.decode(message)
728
+ parsed = this.msg.parse(payload)
729
+ <span class="branch-0 cbranch-no" title="branch not covered" > }</span>
730
+ <span class="cstat-no" title="statement not covered" > catch (err: unknown) {</span>
731
+ <span class="cstat-no" title="statement not covered" > return reject(err)</span>
732
+ <span class="cstat-no" title="statement not covered" > }</span>
733
+ resolve(parsed)
734
+ })
735
+ this.log("debug", `publishing to MQTT topic "${topic}"`, { message: messageOnDemand })
736
+ &nbsp;
737
+ /* forward operation to underlying MQTT facility */
738
+ return new Promise&lt;void&gt;((resolve, reject) =&gt; {
739
+ /* NOTICE: MQTT.js is dealing with string or Buffer only */
740
+ const messageData = typeof message === "string"
741
+ ? message
742
+ : Buffer.from(message.buffer, message.byteOffset, message.byteLength)
743
+ this.mqtt.publish(topic, messageData, options, (err?: Error) =&gt; {
744
+ if (err) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
745
+ <span class="cstat-no" title="statement not covered" > this.error(err, `publishing to MQTT topic "${topic}" failed`)</span>
746
+ <span class="cstat-no" title="statement not covered" > reject(err)</span>
747
+ <span class="cstat-no" title="statement not covered" > }</span>
748
+ else
749
+ resolve()
750
+ })
751
+ })
752
+ }
753
+ &nbsp;
754
+ /* handle incoming MQTT message */
755
+ private _onMessage (topic: string, data: string | Uint8Array, _packet: IPublishPacket): void {
756
+ /* parse MQTT topic */
757
+ const topicMatch = this.options.topicMatch(topic)
758
+ if (topicMatch === null)
759
+ <span class="branch-0 cbranch-no" title="branch not covered" > return</span>
760
+ &nbsp;
761
+ /* parse MQTT data into payload object */
762
+ if (typeof data === "string")
763
+ this.log("info", `received from MQTT topic "${topic}" (type: string, length: ${data.length} chars)`)
764
+ else
765
+ this.log("info", `received from MQTT topic "${topic}" (type: buffer, length: ${data.byteLength} bytes)`)
766
+ let payload: any
767
+ try {
768
+ payload = this.codec.decode(data)
769
+ }
770
+ catch (err: unknown) {
771
+ this.error(ensureError(err, "failed to parse message into object"))
772
+ return
773
+ }
774
+ &nbsp;
775
+ /* parse payload object into typed MQTT+ message */
776
+ let message: any
777
+ try {
778
+ message = this.msg.parse(payload)
779
+ <span class="branch-0 cbranch-no" title="branch not covered" > }</span>
780
+ <span class="cstat-no" title="statement not covered" > catch (err: unknown) {</span>
781
+ <span class="cstat-no" title="statement not covered" > this.error(ensureError(err, "failed to parse object into typed message object"))</span>
782
+ <span class="cstat-no" title="statement not covered" > return</span>
783
+ <span class="cstat-no" title="statement not covered" > }</span>
784
+ this.log("debug", `received from MQTT topic "${topic}"`, { message })
785
+ &nbsp;
786
+ /* dispatch MQTT+ message */
787
+ if (this.msg.isRequest(message)) {
788
+ /* dispatch request message */
789
+ const handler = this.onRequest.get(`${message.type}:${message.name}`)
790
+ if (handler !== undefined) {
791
+ Promise.resolve().then(() =&gt; handler(message, topicMatch.name)).catch((err: unknown) =&gt; {
792
+ <span class="cstat-no" title="statement not covered" > this.error(ensureError(err, `dispatching request message from MQTT topic "${topic}" failed`))</span>
793
+ })
794
+ }
795
+ }
796
+ else if (this.msg.isResponse(message)) {
797
+ /* dispatch response message */
798
+ const handler = this.onResponse.get(`${message.type}:${message.id}`)
799
+ if (handler !== undefined) {
800
+ Promise.resolve().then(() =&gt; handler(message, topicMatch.name)).catch((err: unknown) =&gt; {
801
+ <span class="cstat-no" title="statement not covered" > this.error(ensureError(err, `dispatching response message from MQTT topic "${topic}" failed`))</span>
802
+ })
803
+ }
804
+ }
805
+ }
806
+ <span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" >}</span></span>
807
+ &nbsp;</pre></td></tr></table></pre>
808
+
809
+ <div class='push'></div><!-- for sticky footer -->
810
+ </div><!-- /wrapper -->
811
+ <div class='footer quiet pad2 space-top1 center small'>
812
+ Code coverage generated by
813
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
814
+ at 2026-03-14T22:41:38.599Z
815
+ </div>
816
+ <script src="prettify.js"></script>
817
+ <script>
818
+ window.onload = function () {
819
+ prettyPrint();
820
+ };
821
+ </script>
822
+ <script src="sorter.js"></script>
823
+ <script src="block-navigation.js"></script>
824
+ </body>
825
+ </html>
826
+