u8-mqtt 0.5.2 → 0.6.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 (116) hide show
  1. package/README.md +23 -6
  2. package/cjs/basic-v4.cjs +293 -284
  3. package/cjs/basic-v4.cjs.map +1 -1
  4. package/cjs/basic-v5.cjs +307 -288
  5. package/cjs/basic-v5.cjs.map +1 -1
  6. package/cjs/full-v4.cjs +1538 -0
  7. package/cjs/full-v4.cjs.map +1 -0
  8. package/cjs/full-v5.cjs +1812 -0
  9. package/cjs/full-v5.cjs.map +1 -0
  10. package/cjs/index.cjs +320 -302
  11. package/cjs/index.cjs.map +1 -1
  12. package/cjs/v4.cjs +305 -296
  13. package/cjs/v4.cjs.map +1 -1
  14. package/cjs/v5.cjs +319 -300
  15. package/cjs/v5.cjs.map +1 -1
  16. package/code/_cmdid_dispatch.jsy +45 -69
  17. package/code/_conn.jsy +96 -72
  18. package/code/_dispatch.jsy +36 -28
  19. package/code/_utils.jsy +17 -0
  20. package/code/base.jsy +35 -63
  21. package/code/core.jsy +78 -56
  22. package/code/full-v4.js +20 -0
  23. package/code/full-v5.js +29 -0
  24. package/code/router_path.jsy +2 -1
  25. package/esm/basic-v4.js +293 -284
  26. package/esm/basic-v4.js.map +1 -1
  27. package/esm/basic-v5.js +307 -288
  28. package/esm/basic-v5.js.map +1 -1
  29. package/esm/deno/basic-v4.js +297 -288
  30. package/esm/deno/basic-v4.js.map +1 -1
  31. package/esm/deno/basic-v5.js +311 -292
  32. package/esm/deno/basic-v5.js.map +1 -1
  33. package/esm/deno/full-v4.js +1526 -0
  34. package/esm/deno/full-v4.js.map +1 -0
  35. package/esm/deno/full-v5.js +1798 -0
  36. package/esm/deno/full-v5.js.map +1 -0
  37. package/esm/deno/index.js +324 -305
  38. package/esm/deno/index.js.map +1 -1
  39. package/esm/deno/v4.js +309 -300
  40. package/esm/deno/v4.js.map +1 -1
  41. package/esm/deno/v5.js +323 -304
  42. package/esm/deno/v5.js.map +1 -1
  43. package/esm/full-v4.js +1526 -0
  44. package/esm/full-v4.js.map +1 -0
  45. package/esm/full-v5.js +1798 -0
  46. package/esm/full-v5.js.map +1 -0
  47. package/esm/index.js +320 -301
  48. package/esm/index.js.map +1 -1
  49. package/esm/node/basic-v4.js +293 -284
  50. package/esm/node/basic-v4.js.map +1 -1
  51. package/esm/node/basic-v4.mjs +293 -284
  52. package/esm/node/basic-v4.mjs.map +1 -1
  53. package/esm/node/basic-v5.js +307 -288
  54. package/esm/node/basic-v5.js.map +1 -1
  55. package/esm/node/basic-v5.mjs +307 -288
  56. package/esm/node/basic-v5.mjs.map +1 -1
  57. package/esm/node/full-v4.js +1529 -0
  58. package/esm/node/full-v4.js.map +1 -0
  59. package/esm/node/full-v4.mjs +1529 -0
  60. package/esm/node/full-v4.mjs.map +1 -0
  61. package/esm/node/full-v5.js +1801 -0
  62. package/esm/node/full-v5.js.map +1 -0
  63. package/esm/node/full-v5.mjs +1801 -0
  64. package/esm/node/full-v5.mjs.map +1 -0
  65. package/esm/node/index.js +320 -301
  66. package/esm/node/index.js.map +1 -1
  67. package/esm/node/index.mjs +320 -301
  68. package/esm/node/index.mjs.map +1 -1
  69. package/esm/node/v4.js +305 -296
  70. package/esm/node/v4.js.map +1 -1
  71. package/esm/node/v4.mjs +305 -296
  72. package/esm/node/v4.mjs.map +1 -1
  73. package/esm/node/v5.js +319 -300
  74. package/esm/node/v5.js.map +1 -1
  75. package/esm/node/v5.mjs +319 -300
  76. package/esm/node/v5.mjs.map +1 -1
  77. package/esm/v4.js +305 -296
  78. package/esm/v4.js.map +1 -1
  79. package/esm/v5.js +319 -300
  80. package/esm/v5.js.map +1 -1
  81. package/esm/web/basic-v4.js +293 -284
  82. package/esm/web/basic-v4.js.map +1 -1
  83. package/esm/web/basic-v4.min.js +1 -1
  84. package/esm/web/basic-v4.min.js.br +0 -0
  85. package/esm/web/basic-v4.min.js.gz +0 -0
  86. package/esm/web/basic-v5.js +307 -288
  87. package/esm/web/basic-v5.js.map +1 -1
  88. package/esm/web/basic-v5.min.js +1 -1
  89. package/esm/web/basic-v5.min.js.br +0 -0
  90. package/esm/web/basic-v5.min.js.gz +0 -0
  91. package/esm/web/full-v4.js +1526 -0
  92. package/esm/web/full-v4.js.map +1 -0
  93. package/esm/web/full-v4.min.js +1 -0
  94. package/esm/web/full-v4.min.js.br +0 -0
  95. package/esm/web/full-v4.min.js.gz +0 -0
  96. package/esm/web/full-v5.js +1798 -0
  97. package/esm/web/full-v5.js.map +1 -0
  98. package/esm/web/full-v5.min.js +1 -0
  99. package/esm/web/full-v5.min.js.br +0 -0
  100. package/esm/web/full-v5.min.js.gz +0 -0
  101. package/esm/web/index.js +320 -301
  102. package/esm/web/index.js.map +1 -1
  103. package/esm/web/index.min.js +1 -1
  104. package/esm/web/index.min.js.br +0 -0
  105. package/esm/web/index.min.js.gz +0 -0
  106. package/esm/web/v4.js +305 -296
  107. package/esm/web/v4.js.map +1 -1
  108. package/esm/web/v4.min.js +1 -1
  109. package/esm/web/v4.min.js.br +0 -0
  110. package/esm/web/v4.min.js.gz +0 -0
  111. package/esm/web/v5.js +319 -300
  112. package/esm/web/v5.js.map +1 -1
  113. package/esm/web/v5.min.js +1 -1
  114. package/esm/web/v5.min.js.br +0 -0
  115. package/esm/web/v5.min.js.gz +0 -0
  116. package/package.json +7 -8
@@ -0,0 +1,1812 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var node_net = require('node:net');
6
+ var node_tls = require('node:tls');
7
+
8
+ function encode_varint(n, a=[]) {
9
+ do {
10
+ const ni = n & 0x7f;
11
+ n >>>= 7;
12
+ a.push( ni | (0===n ? 0 : 0x80) );
13
+ } while (n > 0)
14
+ return a
15
+ }
16
+
17
+
18
+ /*
19
+ export function decode_varint_loop(u8, i=0) {
20
+ let i0 = i
21
+ let shift = 0, n = (u8[i] & 0x7f)
22
+ while ( 0x80 & u8[i++] )
23
+ n |= (u8[i] & 0x7f) << (shift += 7)
24
+
25
+ return [n, i, i0]
26
+ }
27
+ */
28
+
29
+
30
+ function decode_varint$1(u8, i=0) {
31
+ let i0 = i;
32
+ // unrolled for a max of 4 chains
33
+ let n = (u8[i] & 0x7f) << 0;
34
+ if ( 0x80 & u8[i++] ) {
35
+ n |= (u8[i] & 0x7f) << 7;
36
+ if ( 0x80 & u8[i++] ) {
37
+ n |= (u8[i] & 0x7f) << 14;
38
+ if ( 0x80 & u8[i++] ) {
39
+ n |= (u8[i] & 0x7f) << 21;
40
+ }
41
+ }
42
+ }
43
+ return [n, i, i0]
44
+ }
45
+
46
+ const mqtt_props = /* #__PURE__ */
47
+ init_mqtt_props();
48
+
49
+ function init_mqtt_props() {
50
+ let mqtt_props = new Map();
51
+
52
+ let entries = [
53
+ [ 0x01, 'u8', 'payload_format_indicator'],
54
+ [ 0x02, 'u32', 'message_expiry_interval'],
55
+ [ 0x03, 'utf8', 'content_type'],
56
+ [ 0x08, 'utf8', 'response_topic'],
57
+ [ 0x09, 'bin', 'correlation_data'],
58
+ [ 0x0B, 'vint', 'subscription_identifier'],
59
+ [ 0x11, 'u32', 'session_expiry_interval'],
60
+ [ 0x12, 'utf8', 'assigned_client_identifier'],
61
+ [ 0x13, 'u16', 'server_keep_alive'],
62
+ [ 0x15, 'utf8', 'authentication_method'],
63
+ [ 0x16, 'bin', 'authentication_data'],
64
+ [ 0x17, 'u8', 'request_problem_information'],
65
+ [ 0x18, 'u32', 'will_delay_interval'],
66
+ [ 0x19, 'u8', 'request_response_information'],
67
+ [ 0x1A, 'utf8', 'response_information'],
68
+ [ 0x1C, 'utf8', 'server_reference'],
69
+ [ 0x1F, 'utf8', 'reason_string'],
70
+ [ 0x21, 'u16', 'receive_maximum'],
71
+ [ 0x22, 'u16', 'topic_alias_maximum'],
72
+ [ 0x23, 'u16', 'topic_alias'],
73
+ [ 0x24, 'u8', 'maximum_qos'],
74
+ [ 0x25, 'u8', 'retain_available'],
75
+ [ 0x26, 'pair', 'user_properties', {op: 'kv_obj'}],
76
+ [ 0x27, 'u32', 'maximum_packet_size'],
77
+ [ 0x28, 'u8', 'wildcard_subscription_available'],
78
+ [ 0x29, 'u8', 'subscription_identifiers_available', {op: 'u8_vec'}],
79
+ [ 0x2A, 'u8', 'shared_subscription_available'],
80
+ ];
81
+
82
+ for (let [id, type, name, extra] of entries) {
83
+ let prop_obj = {id, type, name, ...extra};
84
+ mqtt_props.set(prop_obj.id, prop_obj);
85
+ mqtt_props.set(prop_obj.name, prop_obj);
86
+ }
87
+
88
+ return mqtt_props
89
+ }
90
+
91
+ class U8_Reason extends Number {
92
+ static of(v, pkt_kind, by_kind) {
93
+ let self = new this(v);
94
+ self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
95
+ return self
96
+ }
97
+ }
98
+
99
+ class mqtt_reader_v4 {
100
+ static of(buf) { return this.prototype.of(buf) }
101
+ of(buf) {
102
+ let step = (width, k) => (k=0|step.k, step.k=k+width, k);
103
+ return {__proto__: this, buf, step}
104
+ }
105
+
106
+ has_more() {
107
+ return this.buf.byteLength > (this.step.k|0)
108
+ }
109
+
110
+ u8() {
111
+ return this.buf[this.step(1)]
112
+ }
113
+
114
+ u16() {
115
+ let {buf, step} = this, i = step(2);
116
+ return (buf[i]<<8) | buf[i+1]
117
+ }
118
+
119
+ u32() {
120
+ let {buf, step} = this, i = step(4);
121
+ return (buf[i]<<24) | (buf[i+1]<<16) | (buf[i+2]<<8) | buf[i+3]
122
+ }
123
+
124
+ vint() {
125
+ let {buf, step} = this;
126
+ let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
127
+ step(vi - vi0);
128
+ return n
129
+ }
130
+
131
+ bin() {
132
+ let {buf, step} = this, i = step(2);
133
+ let len = (buf[i]<<8) | buf[i+1];
134
+ i = step(len);
135
+ return buf.subarray(i, i+len)
136
+ }
137
+
138
+ utf8() { return new TextDecoder('utf-8').decode(this.bin()) }
139
+ pair() { return [ this.utf8(), this.utf8() ] }
140
+
141
+ flags(FlagsType) { return new FlagsType(this.buf[this.step(1)]) }
142
+
143
+ reason(pkt_kind) {
144
+ let v = this.buf[this.step(1)];
145
+ if (null != v)
146
+ return U8_Reason.of(v, pkt_kind, this._reasons_by)
147
+ }
148
+
149
+ flush() {
150
+ let {buf, step} = this;
151
+ this.step = this.buf = null;
152
+ return buf.subarray(step.k|0)
153
+ }
154
+
155
+ }
156
+
157
+ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
158
+ props() {
159
+ let {buf, step} = this;
160
+ let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
161
+ step(n + vi - vi0);
162
+ if (0 === n) return null
163
+
164
+ let res={}, fork = this.of(buf.subarray(vi, step.k|0));
165
+ while (fork.has_more()) {
166
+ let v, pk = fork.u8(), pt = mqtt_props.get( pk );
167
+
168
+ if (!pt) {
169
+ res.error = `Unknown mqtt_prop enum ${pk}`;
170
+ return res
171
+ }
172
+
173
+ v = fork[pt.type]();
174
+ if (pt.op) // accumulate operation
175
+ v = fork[pt.op](res[pt.name], v);
176
+
177
+ res[pt.name] = v;
178
+ }
179
+ return res
180
+ }
181
+
182
+ kv_obj(obj=Object.create(null), [k,v]) {
183
+ obj[k] = v;
184
+ return obj
185
+ }
186
+ u8_vec(vec=[], u8) {
187
+ vec.push(u8);
188
+ return vec
189
+ }
190
+
191
+ /*
192
+ vbuf() {
193
+ let {buf, step} = this
194
+ let [n, vi, vi0] = decode_varint(buf, step.k|0)
195
+ step(n + vi - vi0)
196
+ return 0 === n ? null
197
+ : buf.subarray(vi, step.k|0)
198
+ }
199
+ */
200
+ };
201
+
202
+ function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
203
+ mqtt_reader = class extends mqtt_reader {
204
+ static reasons(pkt_type, ...reason_entries) {
205
+ let proto = this.prototype;
206
+ proto._reasons_by = {... proto._reasons_by};
207
+
208
+ let lut = (proto._reasons_by[pkt_type] ||= new Map());
209
+ for (let [u8, reason] of reason_entries)
210
+ lut.set( u8, reason );
211
+
212
+ return this
213
+ }
214
+ };
215
+
216
+ for (let fn_info of info_fn_list)
217
+ fn_info(mqtt_reader);
218
+
219
+ return mqtt_reader
220
+ }
221
+
222
+ class mqtt_writer_v4 {
223
+ static of() { return this.prototype.of() }
224
+ of() { return {__proto__: this, $:[]} }
225
+
226
+ static init() { return this }
227
+
228
+ as_pkt(pkt_id) { return this.pack([pkt_id]) }
229
+
230
+ push(...z) { this.$.push(...z); }
231
+ pack(hdr) {
232
+ let z, i, n=0, parts = this.$;
233
+ this.$ = false;
234
+ for (z of parts) n += z.length;
235
+
236
+ hdr = encode_varint(n, hdr);
237
+ i = hdr.length;
238
+
239
+ let pkt = new Uint8Array(i + n);
240
+ pkt.set(hdr, 0);
241
+ for (z of parts) {
242
+ pkt.set(z, i);
243
+ i += z.length;
244
+ }
245
+ return pkt
246
+ }
247
+
248
+ u8(v) { this.push([ v & 0xff ]); }
249
+ u16(v) { this.push([ (v>>>8) & 0xff, v & 0xff ]); }
250
+ u32(v) { this.push([ (v>>>24) & 0xff, (v>>>16) & 0xff, (v>>>8) & 0xff, v & 0xff ]); }
251
+ vint(v) { this.push( encode_varint(v) );}
252
+
253
+ bin(u8_buf) {
254
+ if (! u8_buf) return this.u16(0)
255
+ if ('string' === typeof u8_buf)
256
+ return this.utf8(u8_buf)
257
+
258
+ if (u8_buf.length !== u8_buf.byteLength)
259
+ u8_buf = new Uint8Array(u8_buf);
260
+
261
+ this.u16(u8_buf.byteLength);
262
+ this.push(u8_buf);
263
+ }
264
+
265
+ utf8(v) {
266
+ let u8_buf = new TextEncoder('utf-8').encode(v);
267
+ this.u16(u8_buf.byteLength);
268
+ this.push(u8_buf);
269
+ }
270
+ pair(k,v) { this.utf8(k); this.utf8(v); }
271
+
272
+ flags(v, enc_flags, b0=0) {
273
+ if (undefined !== v && isNaN(+v))
274
+ v = enc_flags(v, 0);
275
+
276
+ v |= b0;
277
+ this.push([v]);
278
+ return v
279
+ }
280
+
281
+ reason(v) { this.push([v | 0]); }
282
+
283
+ flush(buf) {
284
+ if (null != buf)
285
+ this.push(
286
+ 'string' === typeof buf
287
+ ? new TextEncoder('utf-8').encode(buf)
288
+ : buf );
289
+
290
+ this.push = false;
291
+ }
292
+ }
293
+
294
+
295
+ class mqtt_writer_v5 extends mqtt_writer_v4 {
296
+ props(props) {
297
+ if (! props)
298
+ return this.u8(0)
299
+
300
+ if (! Array.isArray(props))
301
+ props = props.entries
302
+ ? Array.from(props.entries())
303
+ : Object.entries(props);
304
+
305
+ if (0 === props.length)
306
+ return this.u8(0)
307
+
308
+ let fork = this.of();
309
+ for (let [name, value] of props) {
310
+ let pt = mqtt_props.get(name);
311
+ if (!pt)
312
+ throw new Error(`Unknown mqtt_prop "${name}"`)
313
+ fork[pt.op || 'one'](value, pt);
314
+ }
315
+ this.push(fork.pack());
316
+ }
317
+
318
+ one(value, pt) {
319
+ this.u8(pt.id);
320
+ this[pt.type](value);
321
+ }
322
+ kv_obj(obj, pt) {
323
+ for (let kv of Object.entries(obj)) {
324
+ this.u8(pt.id);
325
+ this.pair(kv);
326
+ }
327
+ }
328
+ u8_vec(vec, pt) {
329
+ for (let v of vec) {
330
+ this.u8(pt.id);
331
+ this.u8(v);
332
+ }
333
+ }
334
+ }
335
+
336
+ function mqtt_decode_connect(ns, mqtt_reader) {
337
+ class _connect_flags_ extends Number {
338
+ get reserved() { return this & 0x01 !== 0 }
339
+ get clean_start() { return this & 0x02 !== 0 }
340
+ get will_flag() { return this & 0x04 !== 0 }
341
+ get will_qos() { return (this >>> 3) & 0x3 }
342
+ get will_retain() { return this & 0x20 !== 0 }
343
+ get password() { return this & 0x40 !== 0 }
344
+ get username() { return this & 0x80 !== 0 }
345
+ }
346
+
347
+ return ns[0x1] = (pkt, u8_body) => {
348
+ let rdr = mqtt_reader.of(u8_body);
349
+ if ('MQTT' !== rdr.utf8())
350
+ throw new Error('Invalid mqtt_connect packet')
351
+
352
+ pkt._base_.mqtt_level = pkt.mqtt_level = rdr.u8();
353
+
354
+ let flags = pkt.flags =
355
+ rdr.flags(_connect_flags_);
356
+
357
+ pkt.keep_alive = rdr.u16();
358
+
359
+ if (5 <= pkt.mqtt_level)
360
+ pkt.props = rdr.props();
361
+
362
+
363
+
364
+ pkt.client_id = rdr.utf8();
365
+ if (flags.will_flag) {
366
+ let will = pkt.will = {};
367
+ if (5 <= pkt.mqtt_level)
368
+ will.props = rdr.props();
369
+
370
+ will.topic = rdr.utf8();
371
+ will.payload = rdr.bin();
372
+ will.qos = flags.will_qos;
373
+ will.retain = flags.will_retain;
374
+ }
375
+
376
+ if (flags.username)
377
+ pkt.username = rdr.utf8();
378
+
379
+ if (flags.password)
380
+ pkt.password = rdr.bin();
381
+ return pkt }
382
+ }
383
+
384
+ function mqtt_decode_connack(ns, mqtt_reader) {
385
+ class _connack_flags_ extends Number {
386
+ get session_present() { return this & 0x01 !== 0 }
387
+ }
388
+
389
+ return ns[0x2] = (pkt, u8_body) => {
390
+ let rdr = mqtt_reader.of(u8_body);
391
+
392
+ pkt.flags =
393
+ rdr.flags(_connack_flags_);
394
+
395
+ pkt.reason = rdr.reason(pkt.type);
396
+ if (5 <= pkt.mqtt_level)
397
+ pkt.props = rdr.props();
398
+ return pkt }
399
+ }
400
+
401
+
402
+ function _connack_v4(mqtt_reader) {
403
+ mqtt_reader.reasons('connack',
404
+ // MQTT 3.1.1
405
+ [ 0x00, 'Success'],
406
+ [ 0x01, 'Connection refused, unacceptable protocol version'],
407
+ [ 0x02, 'Connection refused, identifier rejected'],
408
+ [ 0x03, 'Connection refused, server unavailable'],
409
+ [ 0x04, 'Connection refused, bad user name or password'],
410
+ [ 0x05, 'Connection refused, not authorized'],
411
+ );
412
+ }
413
+
414
+ function _connack_v5(mqtt_reader) {
415
+ _connack_v4(mqtt_reader);
416
+
417
+ mqtt_reader.reasons('connack',
418
+ // MQTT 5.0
419
+ [ 0x81, 'Malformed Packet'],
420
+ [ 0x82, 'Protocol Error'],
421
+ [ 0x83, 'Implementation specific error'],
422
+ [ 0x84, 'Unsupported Protocol Version'],
423
+ [ 0x85, 'Client Identifier not valid'],
424
+ [ 0x86, 'Bad User Name or Password'],
425
+ [ 0x87, 'Not authorized'],
426
+ [ 0x88, 'Server unavailable'],
427
+ [ 0x89, 'Server busy'],
428
+ [ 0x8A, 'Banned'],
429
+ [ 0x8C, 'Bad authentication method'],
430
+ [ 0x90, 'Topic Name invalid'],
431
+ [ 0x95, 'Packet too large'],
432
+ [ 0x97, 'Quota exceeded'],
433
+ [ 0x99, 'Payload format invalid'],
434
+ [ 0x9A, 'Retain not supported'],
435
+ [ 0x9B, 'QoS not supported'],
436
+ [ 0x9C, 'Use another server'],
437
+ [ 0x9D, 'Server moved'],
438
+ [ 0x9F, 'Connection rate exceeded'],
439
+ );
440
+ }
441
+
442
+ function mqtt_decode_publish(ns, mqtt_reader) {
443
+ return ns[0x3] = (pkt, u8_body) => {
444
+ let {hdr} = pkt;
445
+ pkt.dup = Boolean(hdr & 0x8);
446
+ pkt.retain = Boolean(hdr & 0x1);
447
+ let qos = pkt.qos = (hdr>>1) & 0x3;
448
+
449
+ let rdr = mqtt_reader.of(u8_body);
450
+ pkt.topic = rdr.utf8();
451
+ if (0 !== qos)
452
+ pkt.pkt_id = rdr.u16();
453
+
454
+ if (5 <= pkt.mqtt_level)
455
+ pkt.props = rdr.props();
456
+
457
+ pkt.payload = rdr.flush();
458
+ return pkt }
459
+ }
460
+
461
+ function mqtt_decode_puback(ns, mqtt_reader) {
462
+ return ns[0x4] = (pkt, u8_body) => {
463
+ let rdr = mqtt_reader.of(u8_body);
464
+
465
+ pkt.pkt_id = rdr.u16();
466
+ if (5 <= pkt.mqtt_level) {
467
+ pkt.reason = rdr.reason(pkt.type);
468
+ pkt.props = rdr.props();
469
+ }
470
+
471
+ return pkt }
472
+ }
473
+
474
+
475
+ function _puback_v5(mqtt_reader) {
476
+ mqtt_reader.reasons('puback',
477
+ // MQTT 5.0
478
+ [ 0x00, 'Success'],
479
+ [ 0x10, 'No matching subscribers'],
480
+ [ 0x80, 'Unspecified error'],
481
+ [ 0x83, 'Implementation specific error'],
482
+ [ 0x87, 'Not authorized'],
483
+ [ 0x90, 'Topic Name invalid'],
484
+ [ 0x91, 'Packet identifier in use'],
485
+ [ 0x97, 'Quota exceeded'],
486
+ [ 0x99, 'Payload format invalid'],
487
+ );
488
+ }
489
+
490
+ function mqtt_decode_pubxxx(ns, mqtt_reader) {
491
+ return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
492
+ let rdr = mqtt_reader.of(u8_body);
493
+
494
+ pkt.pkt_id = rdr.u16();
495
+ pkt.reason = rdr.reason('pubxxx', mqtt_reader);
496
+ if (5 <= pkt.mqtt_level)
497
+ pkt.props = rdr.props();
498
+ return pkt }
499
+ }
500
+
501
+ function _pubxxx_v4(mqtt_reader) {
502
+ mqtt_reader.reasons('pubxxx',
503
+ // MQTT 3.1.1
504
+ [ 0x00, 'Success' ],
505
+ [ 0x92, 'Packet Identifier not found' ],
506
+ );
507
+ }
508
+
509
+ function mqtt_decode_subscribe(ns, mqtt_reader) {
510
+ class _subscription_options_ extends Number {
511
+ get qos() { return this & 0x3 }
512
+ get retain() { return this & 0x4 !== 0 }
513
+ get retain_handling() { return (this >> 2) & 0x3 }
514
+ }
515
+
516
+ return ns[0x8] = (pkt, u8_body) => {
517
+ let rdr = mqtt_reader.of(u8_body);
518
+
519
+ pkt.pkt_id = rdr.u16();
520
+ if (5 <= pkt.mqtt_level)
521
+ pkt.props = rdr.props();
522
+
523
+ let topic, opts, topic_list = pkt.topics = [];
524
+ while (rdr.has_more()) {
525
+ topic = rdr.utf8();
526
+ opts = rdr.flags(_subscription_options_);
527
+ topic_list.push({topic, opts});
528
+ }
529
+
530
+ return pkt }
531
+ }
532
+
533
+ function _mqtt_decode_suback(mqtt_reader) {
534
+ return (pkt, u8_body) => {
535
+ let rdr = mqtt_reader.of(u8_body);
536
+
537
+ pkt.pkt_id = rdr.u16();
538
+ if (5 <= pkt.mqtt_level)
539
+ pkt.props = rdr.props();
540
+
541
+ let answers = pkt.answers = [];
542
+ while (rdr.has_more())
543
+ answers.push(
544
+ rdr.reason(pkt.type) );
545
+
546
+ return pkt }
547
+ }
548
+
549
+ function mqtt_decode_suback(ns, mqtt_reader) {
550
+ return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
551
+ }
552
+
553
+ function _suback_v4(mqtt_reader) {
554
+ mqtt_reader.reasons('suback',
555
+ // MQTT 3.1.1
556
+ [ 0x00, 'Granted QoS 0'],
557
+ [ 0x01, 'Granted QoS 1'],
558
+ [ 0x02, 'Granted QoS 2'],
559
+ );
560
+ }
561
+
562
+ function _suback_v5(mqtt_reader) {
563
+ _suback_v4(mqtt_reader);
564
+
565
+ mqtt_reader.reasons('suback',
566
+ // MQTT 5.0
567
+ [ 0x80, 'Unspecified error'],
568
+ [ 0x83, 'Implementation specific error'],
569
+ [ 0x87, 'Not authorized'],
570
+ [ 0x8F, 'Topic Filter invalid'],
571
+ [ 0x91, 'Packet Identifier in use'],
572
+ [ 0x97, 'Quota exceeded'],
573
+ [ 0x9E, 'Shared Subscriptions not supported'],
574
+ [ 0xA1, 'Subscription Identifiers not supported'],
575
+ [ 0xA2, 'Wildcard Subscriptions not supported'],
576
+ );
577
+ }
578
+
579
+ function mqtt_decode_unsubscribe(ns, mqtt_reader) {
580
+ return ns[0xa] = (pkt, u8_body) => {
581
+ let rdr = mqtt_reader.of(u8_body);
582
+
583
+ pkt.pkt_id = rdr.u16();
584
+ if (5 <= pkt.mqtt_level)
585
+ pkt.props = rdr.props();
586
+
587
+ let topic_list = pkt.topics = [];
588
+ while (rdr.has_more())
589
+ topic_list.push(rdr.utf8());
590
+
591
+ return pkt }
592
+ }
593
+
594
+ function mqtt_decode_unsuback(ns, mqtt_reader) {
595
+ return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
596
+ }
597
+
598
+ function _unsuback_v4(mqtt_reader) {
599
+ mqtt_reader.reasons('unsuback',
600
+ // MQTT 3.1.1
601
+ [ 0x00, 'Success'],
602
+ [ 0x11, 'No subscription existed'],
603
+ [ 0x80, 'Unspecified error'],
604
+ [ 0x83, 'Implementation specific error'],
605
+ [ 0x87, 'Not authorized'],
606
+ [ 0x8F, 'Topic Filter invalid'],
607
+ [ 0x91, 'Packet Identifier in use'],
608
+ );
609
+ }
610
+
611
+ function mqtt_decode_pingxxx(ns) {
612
+ return ns[0xc] = ns[0xd] = pkt => pkt
613
+ }
614
+
615
+ function mqtt_decode_disconnect(ns, mqtt_reader) {
616
+ return ns[0xe] = (pkt, u8_body) => {
617
+ if (u8_body && 5 <= pkt.mqtt_level) {
618
+ let rdr = mqtt_reader.of(u8_body);
619
+ pkt.reason = rdr.reason(pkt.type);
620
+ pkt.props = rdr.props();
621
+ }
622
+ return pkt }
623
+ }
624
+
625
+
626
+ function _disconnect_v5(mqtt_reader) {
627
+ mqtt_reader.reasons('disconnect',
628
+ // MQTT 5.0
629
+ [ 0x00, 'Normal disconnection'],
630
+ [ 0x04, 'Disconnect with Will Message'],
631
+ [ 0x80, 'Unspecified error'],
632
+ [ 0x81, 'Malformed Packet'],
633
+ [ 0x82, 'Protocol Error'],
634
+ [ 0x83, 'Implementation specific error'],
635
+ [ 0x87, 'Not authorized'],
636
+ [ 0x89, 'Server busy'],
637
+ [ 0x8B, 'Server shutting down'],
638
+ [ 0x8D, 'Keep Alive timeout'],
639
+ [ 0x8E, 'Session taken over'],
640
+ [ 0x8F, 'Topic Filter invalid'],
641
+ [ 0x90, 'Topic Name invalid'],
642
+ [ 0x93, 'Receive Maximum exceeded'],
643
+ [ 0x94, 'Topic Alias invalid'],
644
+ [ 0x95, 'Packet too large'],
645
+ [ 0x96, 'Message rate too high'],
646
+ [ 0x97, 'Quota exceeded'],
647
+ [ 0x98, 'Administrative action'],
648
+ [ 0x99, 'Payload format invalid'],
649
+ [ 0x9A, 'Retain not supported'],
650
+ [ 0x9B, 'QoS not supported'],
651
+ [ 0x9C, 'Use another server'],
652
+ [ 0x9D, 'Server moved'],
653
+ [ 0x9E, 'Shared Subscriptions not supported'],
654
+ [ 0x9F, 'Connection rate exceeded'],
655
+ [ 0xA0, 'Maximum connect time'],
656
+ [ 0xA1, 'Subscription Identifiers not supported'],
657
+ [ 0xA2, 'Wildcard Subscriptions not supported'],
658
+ );
659
+ }
660
+
661
+ function mqtt_decode_auth(ns, mqtt_reader) {
662
+ return ns[0xf] = (pkt, u8_body) => {
663
+ if ( 5 <= pkt.mqtt_level ) {
664
+ let rdr = mqtt_reader.of(u8_body);
665
+ pkt.reason = rdr.reason(pkt.type);
666
+ pkt.props = rdr.props();
667
+ }
668
+ return pkt }
669
+ }
670
+
671
+
672
+ function _auth_v5(mqtt_reader) {
673
+ mqtt_reader.reasons('auth',
674
+ // MQTT 5.0
675
+ [ 0x00, 'Success' ],
676
+ [ 0x18, 'Continue authentication' ],
677
+ [ 0x19, 'Re-authenticate' ],
678
+ );
679
+ }
680
+
681
+ function mqtt_encode_connect(ns, mqtt_writer) {
682
+ const _c_mqtt_proto = new Uint8Array([
683
+ 0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
684
+
685
+ const _enc_flags_connect = flags => 0
686
+ | ( flags.reserved ? 0x01 : 0 )
687
+ | ( (flags.will_qos & 0x3) << 3 )
688
+ | ( flags.clean_start ? 0x02 : 0 )
689
+ | ( flags.will_flag ? 0x04 : 0 )
690
+ | ( flags.will_retain ? 0x20 : 0 )
691
+ | ( flags.password ? 0x40 : 0 )
692
+ | ( flags.username ? 0x80 : 0 );
693
+
694
+ const _enc_flags_will = will => 0x4
695
+ | ( (will.qos & 0x3) << 3 )
696
+ | ( will.retain ? 0x20 : 0 );
697
+
698
+ return ns.connect = ( mqtt_level, pkt ) => {
699
+ let wrt = mqtt_writer.of(pkt);
700
+
701
+ wrt.push(_c_mqtt_proto);
702
+ wrt.u8( mqtt_level );
703
+
704
+ let {will, username, password} = pkt;
705
+ let flags = wrt.flags(
706
+ pkt.flags,
707
+ _enc_flags_connect,
708
+ 0 | (username ? 0x80 : 0)
709
+ | (password ? 0x40 : 0)
710
+ | (will ? _enc_flags_will(will) : 0) );
711
+
712
+ wrt.u16(pkt.keep_alive);
713
+
714
+ if (5 <= mqtt_level)
715
+ wrt.props(pkt.props);
716
+
717
+
718
+ wrt.utf8(pkt.client_id);
719
+ if (flags & 0x04) { // .will_flag
720
+ if (5 <= mqtt_level)
721
+ wrt.props(will.props);
722
+
723
+ wrt.utf8(will.topic);
724
+ wrt.bin(will.payload);
725
+ }
726
+
727
+ if (flags & 0x80) // .username
728
+ wrt.utf8(username);
729
+
730
+ if (flags & 0x40) // .password
731
+ wrt.bin(password);
732
+
733
+ return wrt.as_pkt(0x10)
734
+ }
735
+ }
736
+
737
+ function mqtt_encode_connack(ns, mqtt_writer) {
738
+ const _enc_flags_connack = flags =>
739
+ flags.session_present ? 1 : 0;
740
+
741
+ return ns.connack = (mqtt_level, pkt) => {
742
+ let wrt = mqtt_writer.of(pkt);
743
+
744
+ wrt.flags( pkt.flags, _enc_flags_connack );
745
+
746
+ if (5 <= mqtt_level) {
747
+ wrt.reason( pkt.reason );
748
+ wrt.props( pkt.props );
749
+
750
+ } else {
751
+ wrt.reason( pkt.return_code || pkt.reason );
752
+ }
753
+
754
+ return wrt.as_pkt(0x20)
755
+ }
756
+ }
757
+
758
+ function mqtt_encode_publish(ns, mqtt_writer) {
759
+ return ns.publish = ( mqtt_level, pkt ) => {
760
+ let qos = (pkt.qos & 0x3) << 1;
761
+ let wrt = mqtt_writer.of(pkt);
762
+
763
+ wrt.utf8(pkt.topic);
764
+ if (0 !== qos)
765
+ wrt.u16(pkt.pkt_id);
766
+
767
+ if ( 5 <= mqtt_level) {
768
+ wrt.props(pkt.props);
769
+ wrt.flush(pkt.payload);
770
+ } else {
771
+ wrt.flush(pkt.payload);
772
+ }
773
+
774
+ return wrt.as_pkt(
775
+ 0x30 | qos | (pkt.dup ? 0x8 : 0) | (pkt.retain ? 0x1 : 0) )
776
+ }
777
+ }
778
+
779
+ function mqtt_encode_puback(ns, mqtt_writer) {
780
+ return ns.puback = ( mqtt_level, pkt ) => {
781
+ let wrt = mqtt_writer.of(pkt);
782
+
783
+ wrt.u16(pkt.pkt_id);
784
+ if (5 <= mqtt_level) {
785
+ wrt.reason(pkt.reason);
786
+ wrt.props(pkt.props);
787
+ }
788
+
789
+ return wrt.as_pkt(0x40)
790
+ }
791
+ }
792
+
793
+ function mqtt_encode_pubxxx(ns, mqtt_writer) {
794
+ ns.pubrec = _enc_pubxxx(0x50);
795
+ ns.pubrel = _enc_pubxxx(0x62);
796
+ ns.pubcomp = _enc_pubxxx(0x70);
797
+
798
+
799
+ function _enc_pubxxx(hdr) {
800
+ return ( mqtt_level, pkt ) => {
801
+ let wrt = mqtt_writer.of(pkt);
802
+
803
+ wrt.u16(pkt.pkt_id);
804
+ if (5 <= mqtt_level) {
805
+ wrt.props(pkt.props);
806
+ wrt.reason(pkt.reason);
807
+
808
+ } else {
809
+ wrt.reason( pkt.return_code || pkt.reason );
810
+ }
811
+
812
+ return wrt.as_pkt(hdr)
813
+ }
814
+ }
815
+ }
816
+
817
+ function mqtt_encode_subscribe(ns, mqtt_writer) {
818
+ const _enc_subscribe_flags = opts => 0
819
+ | ( opts.qos & 0x3 )
820
+ | ( opts.retain ? 0x4 : 0 )
821
+ | ( (opts.retain_handling & 0x3) << 2 );
822
+
823
+ return ns.subscribe = ( mqtt_level, pkt ) => {
824
+ let wrt = mqtt_writer.of(pkt);
825
+
826
+ wrt.u16(pkt.pkt_id);
827
+ if (5 <= mqtt_level)
828
+ wrt.props(pkt.props);
829
+
830
+ let f0 = _enc_subscribe_flags(pkt);
831
+ for (let each of pkt.topics) {
832
+ if ('string' === typeof each) {
833
+ wrt.utf8(each);
834
+ wrt.u8(f0);
835
+ } else {
836
+ let [topic, opts] =
837
+ Array.isArray(each) ? each
838
+ : [each.topic, each.opts];
839
+
840
+ wrt.utf8(topic);
841
+ if (undefined === opts) wrt.u8(f0);
842
+ else wrt.flags(opts, _enc_subscribe_flags);
843
+ }
844
+ }
845
+
846
+ return wrt.as_pkt(0x82)
847
+ }
848
+ }
849
+
850
+ function mqtt_encode_xxsuback(ns, mqtt_writer) {
851
+ ns.suback = _enc_xxsuback(0x90);
852
+ ns.unsuback = _enc_xxsuback(0xb0);
853
+
854
+
855
+ function _enc_xxsuback(hdr) {
856
+ return ( mqtt_level, pkt ) => {
857
+ let wrt = mqtt_writer.of(pkt);
858
+
859
+ wrt.u16(pkt.pkt_id);
860
+ if (5 <= mqtt_level)
861
+ wrt.props(pkt.props);
862
+
863
+ for (let ans of pkt.answers)
864
+ wrt.reason(ans);
865
+
866
+ return wrt.as_pkt(hdr)
867
+ }
868
+ }
869
+ }
870
+
871
+ function mqtt_encode_unsubscribe(ns, mqtt_writer) {
872
+ return ns.unsubscribe = ( mqtt_level, pkt ) => {
873
+ let wrt = mqtt_writer.of(pkt);
874
+
875
+ wrt.u16(pkt.pkt_id);
876
+ if (5 <= mqtt_level)
877
+ wrt.props(pkt.props);
878
+
879
+ for (let topic of pkt.topics)
880
+ wrt.utf8(topic);
881
+
882
+ return wrt.as_pkt(0xa2)
883
+ }
884
+ }
885
+
886
+ function mqtt_encode_pingxxx(ns) {
887
+ ns.pingreq = () => new Uint8Array([ 0xc0, 0 ]);
888
+ ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
889
+ }
890
+
891
+ function mqtt_encode_disconnect(ns, mqtt_writer) {
892
+ return ns.disconnect = ( mqtt_level, pkt ) => {
893
+ let wrt = mqtt_writer.of(pkt);
894
+
895
+ if (pkt && 5 <= mqtt_level) {
896
+ if (pkt.reason || pkt.props) {
897
+ wrt.reason(pkt.reason);
898
+ wrt.props(pkt.props);
899
+ }
900
+ }
901
+
902
+ return wrt.as_pkt(0xe0)
903
+ }
904
+ }
905
+
906
+ function mqtt_encode_auth(ns, mqtt_writer) {
907
+ return ns.auth = ( mqtt_level, pkt ) => {
908
+ if (5 > mqtt_level)
909
+ throw new Error('Auth packets are only available after MQTT 5.x')
910
+
911
+ let wrt = mqtt_writer.of(pkt);
912
+
913
+ wrt.reason(pkt.reason);
914
+ wrt.props(pkt.props);
915
+
916
+ return wrt.as_pkt(0xf0)
917
+ }
918
+ }
919
+
920
+ const mqtt_reader_v5 = /* #__PURE__ */
921
+ mqtt_reader_info(
922
+ mqtt_reader_v5$1,
923
+ _connack_v5,
924
+ _puback_v5,
925
+ _pubxxx_v4,
926
+ _suback_v5,
927
+ _unsuback_v4,
928
+ _disconnect_v5,
929
+ _auth_v5,
930
+ );
931
+
932
+ const mqtt_decode_v5 = [
933
+ mqtt_decode_connect,
934
+ mqtt_decode_connack,
935
+ mqtt_decode_publish,
936
+ mqtt_decode_puback,
937
+ mqtt_decode_pubxxx,
938
+ mqtt_decode_subscribe,
939
+ mqtt_decode_suback,
940
+ mqtt_decode_unsubscribe,
941
+ mqtt_decode_unsuback,
942
+ mqtt_decode_pingxxx,
943
+ mqtt_decode_disconnect,
944
+ mqtt_decode_auth,
945
+ ];
946
+
947
+
948
+ const mqtt_encode_v5 = [
949
+ mqtt_encode_connect,
950
+ mqtt_encode_connack,
951
+ mqtt_encode_publish,
952
+ mqtt_encode_puback,
953
+ mqtt_encode_pubxxx,
954
+ mqtt_encode_subscribe,
955
+ mqtt_encode_xxsuback,
956
+ mqtt_encode_unsubscribe,
957
+ mqtt_encode_pingxxx,
958
+ mqtt_encode_disconnect,
959
+ mqtt_encode_auth,
960
+ ];
961
+
962
+
963
+ const mqtt_opts_v5 =
964
+ { decode_fns: mqtt_decode_v5,
965
+ mqtt_reader: mqtt_reader_v5,
966
+ encode_fns: mqtt_encode_v5,
967
+ mqtt_writer: mqtt_writer_v5, };
968
+
969
+ function parse(str, loose) {
970
+ if (str instanceof RegExp) return { keys:false, pattern:str };
971
+ var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
972
+ arr[0] || arr.shift();
973
+
974
+ while (tmp = arr.shift()) {
975
+ c = tmp[0];
976
+ if (c === '*') {
977
+ keys.push('wild');
978
+ pattern += '/(.*)';
979
+ } else if (c === ':') {
980
+ o = tmp.indexOf('?', 1);
981
+ ext = tmp.indexOf('.', 1);
982
+ keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
983
+ pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
984
+ if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
985
+ } else {
986
+ pattern += '/' + tmp;
987
+ }
988
+ }
989
+
990
+ return {
991
+ keys: keys,
992
+ pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
993
+ };
994
+ }
995
+
996
+ const _isfn = v => typeof v === 'function';
997
+ const _isstr = v => typeof v === 'string';
998
+
999
+ function _interval(fn_callback) {
1000
+ let tid;
1001
+ return (( td ) => {
1002
+ tid = clearInterval(tid);
1003
+ if (td) {
1004
+ tid = setInterval(fn_callback, 1000 * td);
1005
+
1006
+
1007
+
1008
+
1009
+ // ensure the interval allows the NodeJS event loop to exit
1010
+ tid.unref?.();
1011
+ return true} }) }
1012
+
1013
+ /*
1014
+ class AbstractTopicRouter ::
1015
+ async invoke(pkt, ctx) ::
1016
+ add(topic_route, ...args) ::
1017
+ remove(topic_route, priority) ::
1018
+ clear(priority) ::
1019
+ find(topic) :: // optional
1020
+ mqtt_topic(topic_route)
1021
+ */
1022
+
1023
+ const with_topic_router = mqtt_topic_router =>
1024
+ MQTTKlass => class extends MQTTKlass {
1025
+ static _aliases() {
1026
+ return super._aliases() +
1027
+ ' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'}
1028
+
1029
+ _init_router(opt, self, target) {
1030
+ this._subs = [];
1031
+ let router = this.router = target.router =
1032
+ mqtt_topic_router(opt, this, target);
1033
+ return router?.invoke}
1034
+
1035
+ on_sub(suback, pkt) {
1036
+ suback.pkt = pkt;
1037
+ this._subs.push(suback);
1038
+ return suback}
1039
+ subs_settled() {
1040
+ return Promise.allSettled(
1041
+ this._subs.splice(0,Infinity)) }
1042
+
1043
+ // alias: sub_topic
1044
+ subscribe_topic(topic_route, ...args) {
1045
+ let router = this.router;
1046
+ router.add(topic_route, true, args.pop() );// handler
1047
+ let topic = router.mqtt_topic(topic_route);
1048
+ this.subscribe(topic, ...args );// ex, topic_prefix
1049
+ return this }// fluent api -- return this and track side effects
1050
+
1051
+ // alias: unsub_topic
1052
+ unsubscribe_topic(topic_route, ...args) {
1053
+ let router = this.router;
1054
+ router.remove(topic_route, true);
1055
+ let topic = router.mqtt_topic(topic_route);
1056
+ return this.unsubscribe(topic, ...args ) }// topic_prefix
1057
+
1058
+ // add topic handlers without corresponding subscribe packet
1059
+ on_topic(...args) {
1060
+ this.router.add(...args);
1061
+ return this} };
1062
+
1063
+ // Use [regexparam][] for url-like topic parsing
1064
+ // [regexparam]: https://github.com/lukeed/regexparam
1065
+
1066
+
1067
+ const with_topic_path_router = /* #__PURE__ */
1068
+ with_topic_router(mqtt_topic_path_router);
1069
+
1070
+
1071
+ const mqtt_topic = topic_route =>
1072
+ topic_route
1073
+ .replace(/[*].*$/, '#')
1074
+ .replace(/:\w[^\/]*/g, '+');
1075
+
1076
+ /* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
1077
+ 4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
1078
+ ... MUST be specified either on its own or following a topic level separator.
1079
+ In either case it MUST be the last character specified in the Topic Filter
1080
+
1081
+ 4.7.1.3 Single-level wildcard -- (‘+’ U+002B)
1082
+ ...it MUST occupy an entire level of the filter.
1083
+ */
1084
+
1085
+ const as_topic_path = (topic_route, id) =>(
1086
+ id=1,
1087
+ topic_route
1088
+ .replace(/#$/, '*' )// replace MQTT '#' multi-level wildcard at end
1089
+ .replace(/\+/g, () => `:$${id++}` ) );// replace MQTT '+' single-level wildcards
1090
+
1091
+ function _ignore(pkt, params, ctx) {ctx.done = true;}
1092
+
1093
+ function mqtt_topic_path_router() {
1094
+ let pri_lsts = [[],[]], rm = Symbol();
1095
+ let find = topic => _routes_iter(pri_lsts, topic);
1096
+
1097
+ // return duck-type compatible with AbstractTopicRouter in ./with_topic_router
1098
+ return {find, mqtt_topic,
1099
+ add(topic_route, ...args) {
1100
+ let fn = args.pop();
1101
+ let priority = args.pop();
1102
+
1103
+ if (! _isfn(fn)) {
1104
+ if (fn) {throw new TypeError()}
1105
+ fn = _ignore;}
1106
+
1107
+ let rte = parse(as_topic_path(topic_route));
1108
+
1109
+ rte.key = topic_route;
1110
+ rte.tgt = fn;
1111
+ pri_lsts[priority ? 0 : 1].push(rte);
1112
+ return this}
1113
+
1114
+ , remove(topic_route, priority) {
1115
+ let lst = pri_lsts[priority ? 0 : 1];
1116
+ return _route_remove([lst], topic_route)}
1117
+
1118
+ , clear(priority) {
1119
+ pri_lsts[priority ? 0 : 1] = [];
1120
+ if (null == priority) {
1121
+ pri_lsts[1] = []; } }// null clears both lists
1122
+
1123
+ , async invoke(pkt, ctx) {
1124
+ ctx.idx = 0;
1125
+ ctx.rm = rm;
1126
+
1127
+ for (let [fn, params] of find(pkt.topic)) {
1128
+ let res = await fn(pkt, params, ctx);
1129
+
1130
+ if (rm === res) {
1131
+ _route_remove(pri_lsts, fn);}
1132
+
1133
+ if (ctx.done) {
1134
+ break}
1135
+ else ctx.idx++;}
1136
+
1137
+ if (1 === pkt.qos) {
1138
+ await ctx.mqtt.puback(pkt);} } } }
1139
+
1140
+
1141
+ function * _routes_iter(all_route_lists, topic) {
1142
+ topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
1143
+ for (let route_list of all_route_lists) {
1144
+ for (let {keys, pattern, tgt} of route_list) {
1145
+ let match = pattern.exec(topic);
1146
+ if (match) {
1147
+ let params = keys
1148
+ ? keys.reduce(
1149
+ (o, k, i) => (o[k] = match[1+i], o)
1150
+ , {})
1151
+ : match.groups ?? match;
1152
+ yield [tgt, params];} } } }
1153
+
1154
+
1155
+ function _route_remove(all_route_lists, query) {
1156
+ let fn_match = route =>(
1157
+ route===query
1158
+ || route.tgt===query
1159
+ || route.key===query);
1160
+ for (let lst of all_route_lists) {
1161
+ let i = lst.findIndex(fn_match);
1162
+ if (0 <= i) {
1163
+ lst.splice(i,1);
1164
+ return true} }
1165
+ return false}
1166
+
1167
+ /*
1168
+ export function decode_varint_loop(u8, i=0) {
1169
+ let i0 = i
1170
+ let shift = 0, n = (u8[i] & 0x7f)
1171
+ while ( 0x80 & u8[i++] )
1172
+ n |= (u8[i] & 0x7f) << (shift += 7)
1173
+
1174
+ return [n, i, i0]
1175
+ }
1176
+ */
1177
+
1178
+
1179
+ function decode_varint(u8, i=0) {
1180
+ let i0 = i;
1181
+ // unrolled for a max of 4 chains
1182
+ let n = (u8[i] & 0x7f) << 0;
1183
+ if ( 0x80 & u8[i++] ) {
1184
+ n |= (u8[i] & 0x7f) << 7;
1185
+ if ( 0x80 & u8[i++] ) {
1186
+ n |= (u8[i] & 0x7f) << 14;
1187
+ if ( 0x80 & u8[i++] ) {
1188
+ n |= (u8[i] & 0x7f) << 21;
1189
+ }
1190
+ }
1191
+ }
1192
+ return [n, i, i0]
1193
+ }
1194
+
1195
+ function mqtt_raw_dispatch(opt) {
1196
+ let u8 = new Uint8Array(0);
1197
+ return u8_buf => {
1198
+ u8 = 0 === u8.byteLength
1199
+ ? u8_buf : _u8_join(u8, u8_buf);
1200
+
1201
+ let res = [];
1202
+ while (1) {
1203
+ let [len_body, len_vh] = decode_varint(u8, 1);
1204
+ let len_pkt = len_body + len_vh;
1205
+
1206
+ if ( u8.byteLength < len_pkt )
1207
+ return res
1208
+
1209
+ let b0 = u8[0];
1210
+ let u8_body = 0 === len_body ? null
1211
+ : u8.subarray(len_vh, len_pkt);
1212
+
1213
+ u8 = u8.subarray(len_pkt);
1214
+
1215
+ let pkt = opt.decode_pkt(b0, u8_body, opt);
1216
+ if (null != pkt)
1217
+ res.push( pkt );
1218
+ }
1219
+ }
1220
+ }
1221
+
1222
+ function _u8_join(a, b) {
1223
+ let alen = a.byteLength, r = new Uint8Array(alen + b.byteLength);
1224
+ r.set(a, 0);
1225
+ r.set(b, alen);
1226
+ return r
1227
+ }
1228
+
1229
+ const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
1230
+
1231
+ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1232
+ pkt_ctx = {
1233
+ __proto__: pkt_ctx || opts.pkt_ctx,
1234
+ mqtt_level,
1235
+ get hdr() { return this.b0 & 0xf },
1236
+ get id() { return this.b0 >>> 4 },
1237
+ get type() { return _pkt_types[this.b0 >>> 4] },
1238
+ };
1239
+
1240
+ let op, _decode_by_id=[], _encode_by_type={};
1241
+ for (op of opts.encode_fns)
1242
+ op(_encode_by_type, opts.mqtt_writer);
1243
+ for (op of opts.decode_fns)
1244
+ op(_decode_by_id, opts.mqtt_reader);
1245
+
1246
+ return {
1247
+ pkt_ctx,
1248
+
1249
+ encode_pkt(type, pkt) {
1250
+ return _encode_by_type[type]( mqtt_level, pkt ) },
1251
+
1252
+ decode_pkt(b0, u8_body) {
1253
+ if (b0.map) // Uint8Array in first arg
1254
+ return mqtt_raw_dispatch(this)(b0)[0]
1255
+
1256
+ let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
1257
+ return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
1258
+
1259
+ mqtt_stream() {
1260
+ let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
1261
+ self.pkt_ctx._base_ = self.pkt_ctx;
1262
+ self.decode = mqtt_raw_dispatch(self);
1263
+ return self
1264
+ },
1265
+ }
1266
+ }
1267
+
1268
+ async function _mqtt_cmd_evt(target, answer, pkt, ctx) {
1269
+ /* target : on_mqtt_type = {
1270
+ mqtt_pkt(pkt, ctx) {}, // generic
1271
+
1272
+ mqtt_auth(pkt, ctx) {},
1273
+ mqtt_connect(pkt, ctx) {},
1274
+ mqtt_connack(pkt, ctx) {},
1275
+ mqtt_disconnect(pkt, ctx) {},
1276
+
1277
+ mqtt_publish(pkt, ctx) {},
1278
+ mqtt_subscribe(pkt, ctx) {},
1279
+ mqtt_unsubscribe(pkt, ctx) {},
1280
+
1281
+ mqtt_pingreq(pkt, ctx) {},
1282
+ mqtt_pingresp(pkt, ctx) {},
1283
+ } */
1284
+
1285
+ let pkt_fn = target[`mqtt_${pkt.type}`] || target.mqtt_pkt;
1286
+ await pkt_fn?.call(target, pkt, ctx);}
1287
+
1288
+ function _mqtt_cmd_type(target, answer, pkt, ctx) {
1289
+ answer(pkt.type, pkt);
1290
+ _mqtt_cmd_evt(target, answer, pkt, ctx);}
1291
+
1292
+ function _mqtt_cmd_id(target, answer, pkt) {
1293
+ answer(pkt.pkt_id, pkt);}
1294
+
1295
+
1296
+ const _mqtt_cmdids =[
1297
+ _ => {} // 0x0 reserved
1298
+ , _mqtt_cmd_evt // 0x1 connect
1299
+ , _mqtt_cmd_type // 0x2 connack
1300
+ , _mqtt_cmd_evt // 0x3 publish
1301
+ , _mqtt_cmd_id // 0x4 puback
1302
+ , _mqtt_cmd_id // 0x5 pubrec
1303
+ , _mqtt_cmd_id // 0x6 pubrel
1304
+ , _mqtt_cmd_id // 0x7 pubcomp
1305
+ , _mqtt_cmd_evt // 0x8 subscribe
1306
+ , _mqtt_cmd_id // 0x9 suback
1307
+ , _mqtt_cmd_evt // 0xa unsubscribe
1308
+ , _mqtt_cmd_id // 0xb unsuback
1309
+ , _mqtt_cmd_type // 0xc pingreq
1310
+ , _mqtt_cmd_type // 0xd pingresp
1311
+ , _mqtt_cmd_evt // 0xe disconnect
1312
+ , _mqtt_cmd_type ];// 0xf auth
1313
+
1314
+ function _mqtt_dispatch(opt, target) {
1315
+ let hashbelt=[], rotate_ts=0;
1316
+ // default rotate at 1s across 5 buckets
1317
+ let { td: rotate_td=1000, n: rotate_n=5 } = opt?.rotate || {};
1318
+
1319
+ // Promise / future scaffolding
1320
+ let _pkt_id=100, _ftr_key; // use _ftr_key to reuse _by_key closure
1321
+ let _ftr_by_key = fn_answer => hashbelt[0].set(_ftr_key, fn_answer);
1322
+
1323
+ on_mqtt([]); // init hashbelt and rotate_ts
1324
+ return [on_mqtt, pkt_future]
1325
+
1326
+
1327
+ function pkt_future(pkt_or_key) {
1328
+ if (! _isstr(pkt_or_key)) {
1329
+ _pkt_id = (_pkt_id + 1) & 0xffff; // 16-bit unsigned short
1330
+ _ftr_key = pkt_or_key.pkt_id = _pkt_id;}
1331
+ else _ftr_key = pkt_or_key;
1332
+
1333
+ return new Promise(_ftr_by_key)}
1334
+
1335
+ function answer(key, pkt) {
1336
+ for (let map of hashbelt) {
1337
+ let fn_answer = map.get(key);
1338
+ if (fn_answer) {
1339
+ map.delete(key);
1340
+
1341
+ fn_answer([pkt, /*err*/]); // option/maybe monad
1342
+ return true} }
1343
+ return false}
1344
+
1345
+ function on_mqtt(pkt_list, ctx) {
1346
+ for (let pkt of pkt_list) {
1347
+ _mqtt_cmdids[pkt.id](target, answer, pkt, ctx);}
1348
+
1349
+ // rotate after rotate_ts
1350
+ let now = Date.now();
1351
+ if (now > rotate_ts) {
1352
+ rotate_ts = rotate_td + now;
1353
+ hashbelt.unshift(new Map());
1354
+ while (hashbelt.length > rotate_n) {
1355
+ for (let fn_answer of hashbelt.pop().values()) {
1356
+ fn_answer([/*pkt*/, 'expired']); } } } } }// option/maybe monad
1357
+
1358
+ class MQTTError extends Error {
1359
+ constructor(mqtt_pkt, reason=mqtt_pkt.reason) {
1360
+ // use hex-encoded reasons to match MQTT spec documentation
1361
+ super(`[0x${reason.toString(16)}] ${reason.reason}`);
1362
+ this.mqtt_pkt = mqtt_pkt;
1363
+ this.reason = reason;} }
1364
+
1365
+ class MQTTBase {
1366
+ // Handshaking Packets
1367
+ async connect(pkt={}) {
1368
+ let cid = pkt.client_id;
1369
+ if (! _isstr(cid)) {
1370
+ // see init_client_id implementation in core.jsy
1371
+ pkt.client_id = cid = this.client_id || this.init_client_id(cid);}
1372
+ this.client_id = cid;
1373
+
1374
+ if (null == pkt.keep_alive) {
1375
+ pkt.keep_alive = 60;}
1376
+
1377
+ let response = await this._send0('connect', pkt, 'connack');
1378
+ if (0 != response[0].reason) {// compare to 0 to coerce to number
1379
+ throw new this.MQTTError(response[0])}
1380
+ return this.conn.on_conn(pkt, response)}
1381
+
1382
+ async disconnect(pkt={}) {
1383
+ let response = await this._send0('disconnect', pkt);
1384
+ return this.conn.on_dis(pkt, response)}
1385
+
1386
+ async auth(pkt={}) {
1387
+ let response = await this._send0('auth', pkt, 'auth');
1388
+ if (response[0].reason) {
1389
+ throw new this.MQTTError(response[0])}
1390
+ return this.conn.on_auth(pkt, response)}
1391
+
1392
+ ping() {return this._send('pingreq', null, 'pingresp')}
1393
+ puback({pkt_id}) {return this._send('puback', {pkt_id})}
1394
+
1395
+ // alias: sub
1396
+ subscribe(pkt, ex, topic_prefix) {
1397
+ pkt = _as_topics(pkt, ex, topic_prefix);
1398
+ let suback = this._send('subscribe', pkt, pkt);
1399
+ return this.on_sub?.(suback, pkt) ?? suback}
1400
+
1401
+ // alias: unsub
1402
+ unsubscribe(pkt, ex, topic_prefix) {
1403
+ pkt = _as_topics(pkt, ex, topic_prefix);
1404
+ return this._send('unsubscribe', pkt, pkt)}
1405
+
1406
+
1407
+ post(topic, payload, pub_opt) {// qos:0
1408
+ return this.pub({topic, payload, qos:0}, pub_opt)}
1409
+ send(topic, payload, pub_opt) {// qos:1
1410
+ return this.pub({topic, payload, qos:1}, pub_opt)}
1411
+ store(topic, payload, pub_opt) {// qos:1, retain: 1
1412
+ return this.pub({topic, payload, qos:1, retain: 1}, pub_opt)}
1413
+
1414
+ // alias: json_post
1415
+ obj_post(topic, msg, pub_opt) {// qos:0
1416
+ return this.pub({topic, msg, arg: 'msg', qos:0}, pub_opt)}
1417
+ // alias: json_send
1418
+ obj_send(topic, msg, pub_opt) {// qos:1
1419
+ return this.pub({topic, msg, arg: 'msg', qos:1}, pub_opt)}
1420
+ // alias: json_store
1421
+ obj_store(topic, msg, pub_opt) {// qos:1, retain: 1
1422
+ return this.pub({topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)}
1423
+
1424
+ // alias: publish -- because 'pub' is shorter for semantic aliases above
1425
+ async pub(pkt, pub_opt) {
1426
+ if (undefined === pkt.payload) {
1427
+ if (_isfn(pub_opt)) {
1428
+ // pub_opt as a function is fn_encode value
1429
+ pub_opt = {fn_encode: pub_opt};}
1430
+
1431
+ let msg = pkt.msg, fn_encode = pub_opt?.fn_encode;
1432
+ if (null == msg || _isfn(msg)) {
1433
+ // when msg is a function, return closure using fn_encode
1434
+ if (msg) {pub_opt = {...pub_opt, fn_encode: msg};}
1435
+ // return a single-value closure to publish packets
1436
+ return v => this.pub({...pkt, [pkt.arg || 'payload']: v}, pub_opt)}
1437
+
1438
+ // Encode payload from msg; fn_encode allows alternative to JSON.stringify
1439
+ pkt.payload = fn_encode
1440
+ ? await fn_encode(msg)
1441
+ : JSON.stringify(msg);}
1442
+
1443
+ if (pub_opt) {
1444
+ if (pub_opt.props) {
1445
+ pkt.props = pub_opt.props;}
1446
+ if (pub_opt.xform) {
1447
+ pkt = pub_opt.xform(pkt) || pkt;} }
1448
+
1449
+ return this._send('publish', pkt,
1450
+ pkt.qos ? pkt : null ) }// key
1451
+
1452
+
1453
+ // Internal API
1454
+
1455
+ /* async _send0(type, pkt) -- provided by conn and transport */
1456
+ /* async _send(type, pkt) -- provided by conn and transport */
1457
+
1458
+ _init_dispatch(opt) {
1459
+ this.constructor?._once_();
1460
+ let target ={__proto__: opt.on_mqtt_type};
1461
+ target.mqtt_publish ||=
1462
+ this._init_router?.(opt, this, target);
1463
+ return _mqtt_dispatch(opt, target)}
1464
+
1465
+ static _aliases() {
1466
+ return ' publish:pub sub:subscribe unsub:unsubscribe json_post:obj_post json_send:obj_send json_store:obj_store'}
1467
+
1468
+ static _once_(klass=this) {
1469
+ klass._once_ = _=>0;
1470
+ var alias, name, p = klass.prototype;
1471
+ p.MQTTError = MQTTError;
1472
+ for (alias of klass._aliases().split(/\s+/)) {
1473
+ [alias, name] = alias.split(':');
1474
+ p[alias] = p[name];} } }
1475
+
1476
+
1477
+ function _as_topics(pkt, ex, topic_prefix) {
1478
+ if (ex?.trim) {// string
1479
+ topic_prefix = ex;
1480
+ ex = null;}
1481
+
1482
+ pkt =(
1483
+ pkt.trim // string
1484
+ ? {topics:[pkt], ... ex}
1485
+ : pkt[Symbol.iterator]
1486
+ ? {topics:[... pkt], ... ex}
1487
+ : ex ? {...pkt, ...ex}
1488
+ : pkt);
1489
+
1490
+ if (topic_prefix) {
1491
+ // particularly useful with shared queues, e.g.
1492
+ // topic_prefix = '$share/some-queue-name/'
1493
+ let _prefix_topics = v =>
1494
+ v.trim ? topic_prefix+v : v.map(_prefix_topics);
1495
+
1496
+ pkt.topics = pkt.topics.map(_prefix_topics);}
1497
+ return pkt}
1498
+
1499
+ const _defer_obj = o =>(
1500
+ o.p = new Promise((a,e) => { o.a=a; o.e=e; })
1501
+ , o);
1502
+
1503
+ function _dfn_reset(client, attr, fn_after) {
1504
+ // a resetable deferred for a function
1505
+ let self = {set}, afn = async (...args) => (await self.p)(...args);
1506
+ return set()
1507
+
1508
+ function set() {
1509
+ if (afn !== client[attr]) {
1510
+ _defer_obj(self).p.then(fn_after, _=>0);
1511
+ client[attr] = afn;}
1512
+ return self} }
1513
+
1514
+ function _mqtt_conn(opt, client, [on_mqtt, pkt_future]) {
1515
+ let _abort;
1516
+ let _dfn_send0 = _dfn_reset(client, '_send0', // client._send0 getter/setter
1517
+ _=> client.conn_emit('on_live', conn.has_connected));
1518
+ let _dfn_ready = _dfn_reset(client, '_send', // client._send getter/setter
1519
+ _=> client.conn_emit('on_ready'));
1520
+ let _keep_alive_ival = _interval (() =>client._send0('pingreq') );// resettable interval for keep_alive ping
1521
+
1522
+ let conn = Object.create({
1523
+ ping: (td=conn.keep_alive) => _keep_alive_ival(td)
1524
+
1525
+ , on_conn(pkt, response) {
1526
+ conn.has_connected = true;
1527
+ conn.keep_alive = opt.keep_alive || response[0].props?.server_keep_alive || pkt.keep_alive;
1528
+ client.conn_emit('on_conn');
1529
+ return opt.use_auth
1530
+ ? response // wait on enhanced authentication step
1531
+ : conn.on_auth(null, response) }// otherwise, connect is also auth
1532
+
1533
+ , on_auth(pkt, response) {
1534
+ _dfn_ready.a(_dfn_send0.p);
1535
+ if (0 != opt.keep_alive) {
1536
+ conn.ping();}
1537
+ client.conn_emit('on_auth', !pkt);
1538
+ return response}
1539
+
1540
+ , on_dis(pkt, response) {
1541
+ conn.reset(false);
1542
+ return response}
1543
+
1544
+ , reset(err) {
1545
+ if (err) {
1546
+ _dfn_send0.e(err); }// send error to uses of _send0 (connect, auth)
1547
+ _abort.e(err); // abort in-progress connections
1548
+
1549
+ delete conn.is_set;
1550
+ conn.ready = handshake();
1551
+ client.conn_emit('on_disconnect', false===err, err);}
1552
+
1553
+ , abort() {
1554
+ _dfn_ready.e(err); // abort all messages awaiting ready state
1555
+ return conn.reset(err)}
1556
+
1557
+ , async setup(gate, send_u8_pkt, init_msg_loop) {
1558
+ if (conn.is_set) {
1559
+ throw new Error() }// already in-progress
1560
+
1561
+ conn.is_set = true;
1562
+ await gate;
1563
+
1564
+ // setup send/recv MQTT parsing context
1565
+ let mqtt_ctx = client.mqtt_ctx.mqtt_stream();
1566
+
1567
+ {// setup inbound message loop
1568
+ let sess_ctx = {mqtt: client}; // mutable session context
1569
+ let on_mqtt_chunk = u8 => on_mqtt(mqtt_ctx.decode(u8), sess_ctx);
1570
+ init_msg_loop(on_mqtt_chunk, conn);}
1571
+
1572
+ // setup outbound message path and transport connection
1573
+ send_u8_pkt = await send_u8_pkt;
1574
+ _dfn_send0.a(
1575
+ async (type, pkt, key) => {
1576
+ let res = undefined !== key
1577
+ ? pkt_future(key) : true;
1578
+
1579
+ await send_u8_pkt(
1580
+ mqtt_ctx.encode_pkt(type, pkt));
1581
+ return res} ); } });
1582
+
1583
+ conn.ready = handshake();
1584
+ return conn
1585
+
1586
+ async function handshake() {
1587
+ _abort = _defer_obj({});
1588
+
1589
+ _keep_alive_ival(0); // clearInterval on keep alive ping
1590
+ _dfn_send0.set(); // reset client._send0 if necessary
1591
+ _dfn_ready.set(); // reset client._send if necessary
1592
+
1593
+ try {
1594
+ // set client._send0 as passtrhough after transport connection
1595
+ client._send0 = await Promise.race([_dfn_send0.p, _abort.p]);
1596
+
1597
+ // set client._send as passtrhough after ready
1598
+ client._send = await Promise.race([_dfn_ready.p, _abort.p]);
1599
+ return true}
1600
+ catch (err) {
1601
+ return false} } }
1602
+
1603
+ const pkt_api ={
1604
+ utf8(u8) {return new TextDecoder('utf-8').decode(u8 || this.payload )}
1605
+ , json(u8) {return JSON.parse( this.utf8(u8) || null )}
1606
+ , text(u8) {return this.utf8(u8)} };
1607
+
1608
+ const opt_default ={
1609
+ sess_stg: globalThis.sessionStorage};
1610
+
1611
+ class MQTTCore extends MQTTBase {
1612
+ constructor(opt) {
1613
+ super();
1614
+ this.with(opt);
1615
+ opt ={...opt_default, ...opt};
1616
+ // settings for MQTTCore
1617
+ this.sess_stg = opt.sess_stg;
1618
+ // setup connection and dispatch
1619
+ this.conn = _mqtt_conn(opt, this,
1620
+ this._init_dispatch(opt)); }
1621
+
1622
+ with(fns_ns) {
1623
+ for (let [k,v] of Object.entries(fns_ns)) {
1624
+ if (_isfn(v)) {this[k] = v;} }
1625
+ return this}
1626
+
1627
+
1628
+ static mqtt_ctx(mqtt_level, mqtt_opts, pkt_ctx=pkt_api) {
1629
+ let klass = class extends this {};
1630
+ klass.prototype.mqtt_ctx =
1631
+ mqtt_pkt_ctx(mqtt_level, mqtt_opts, pkt_ctx);
1632
+ return klass}
1633
+
1634
+
1635
+ async conn_emit(evt, arg, err_arg) {
1636
+ this.log_conn?.(evt, arg, err_arg);
1637
+ try {
1638
+ let fn_evt = this[await evt]; // microtask break using `await evt`
1639
+ if (fn_evt) {
1640
+ await fn_evt.call(this, this, arg, err_arg);}
1641
+ else if (err_arg) {throw err_arg} }
1642
+ catch (err) {
1643
+ this.on_error(err, evt);} }
1644
+
1645
+ on_error(err, evt) {
1646
+ console.warn('[[u8-mqtt error: %s]]', evt, err); }
1647
+ log_conn(evt, arg, err_arg) {
1648
+ console.info('[[u8-mqtt conn: %s]]', evt, arg, err_arg); }
1649
+
1650
+
1651
+ // automatic Client Id for connect()
1652
+ init_client_id(parts=['u8-mqtt--','']) {
1653
+ let sess_stg = this.sess_stg;
1654
+ let key, cid = sess_stg?.getItem(key=parts.join(' '));
1655
+ if (! cid) {
1656
+ cid = parts.join(Math.random().toString(36).slice(2));
1657
+ sess_stg?.setItem(key, cid);}
1658
+ return cid}
1659
+
1660
+
1661
+ on_live(client, is_reconnect) {
1662
+ if (is_reconnect) {
1663
+ return client.connect()} }
1664
+
1665
+ // on_ready(client) ::
1666
+ // on_reconnect(client) ::
1667
+ on_disconnect(client, intentional) {
1668
+ if (! intentional) {
1669
+ return client.on_reconnect?.()} }
1670
+
1671
+ _use_conn(fn_reconnect) {
1672
+ return (this.reconnect = fn_reconnect)?.()}
1673
+ with_autoreconnect(opt=2000) {
1674
+ if (opt.toFixed) {opt ={delay: opt};}
1675
+ return this.with({
1676
+ on_reconnect() {
1677
+ this.delay(opt.delay || 2000)
1678
+ .then(this.reconnect)
1679
+ .then(opt.reconnect, opt.error);} }) }
1680
+
1681
+ delay(ms) {
1682
+ return new Promise(done => setTimeout(done, ms)) }
1683
+
1684
+ with_async_iter(async_iter, write_u8_pkt) {
1685
+ this.conn.setup(async_iter,
1686
+ write_u8_pkt,
1687
+ async (on_mqtt_chunk, conn) => {
1688
+ try {
1689
+ async_iter = await async_iter;
1690
+ for await (let chunk of async_iter)
1691
+ on_mqtt_chunk(chunk);
1692
+ conn.reset();}
1693
+ catch (err) {
1694
+ conn.reset(err);} } );
1695
+ return this}
1696
+
1697
+
1698
+
1699
+
1700
+
1701
+
1702
+
1703
+
1704
+
1705
+
1706
+
1707
+
1708
+
1709
+
1710
+
1711
+
1712
+
1713
+
1714
+
1715
+
1716
+
1717
+
1718
+
1719
+
1720
+
1721
+
1722
+
1723
+
1724
+
1725
+
1726
+
1727
+
1728
+ with_tcp(...opt) {
1729
+ opt = this._conn_opt(opt);
1730
+ return this._use_conn (() =>
1731
+ this.with_stream(
1732
+ node_net.connect(opt)) ) }
1733
+
1734
+ with_tls(...opt) {
1735
+ opt = this._conn_opt(opt);
1736
+ return this._use_conn (() =>
1737
+ this.with_stream(
1738
+ node_tls.connect(opt)) ) }
1739
+
1740
+ _conn_opt([a0, a1, a2]) {
1741
+ // (port, hostname, options) or (url, options)
1742
+ if (Number.isFinite(a0)) {
1743
+ return {...a2, port: a0, host: a1}}
1744
+ a0 = new URL(a0);
1745
+ return {...a1, port: a0.port, host: a0.hostname}}
1746
+
1747
+
1748
+ with_stream(read_stream, write_stream) {
1749
+ if (undefined === write_stream) {
1750
+ write_stream = read_stream;}
1751
+
1752
+ return this.with_async_iter(read_stream,
1753
+ u8_pkt => write_stream.write(u8_pkt)) }
1754
+
1755
+
1756
+ with_websock(websock) {
1757
+ if (! websock?.send) {
1758
+ websock = new URL(websock || 'ws://127.0.0.1:9001');
1759
+ return this._use_conn (() =>
1760
+ this.with_websock(
1761
+ new WebSocket(websock, ['mqtt'])) ) }
1762
+
1763
+ websock.binaryType = 'arraybuffer';
1764
+
1765
+ let ws_ready, readyState = websock.readyState;
1766
+ if (1 !== readyState) {
1767
+ if (0 !== readyState) {
1768
+ throw new Error('WS readyState') }
1769
+
1770
+ ws_ready = new Promise(ready => websock.onopen = ready); }
1771
+
1772
+ this.conn.setup(ws_ready,
1773
+ u8_pkt => websock.send(u8_pkt),
1774
+ (on_mqtt_chunk, conn) => {
1775
+ websock.onmessage = evt =>(
1776
+ on_mqtt_chunk(new Uint8Array(evt.data)) );
1777
+
1778
+ websock.onclose = evt => {
1779
+ if (! evt.wasClean) {
1780
+ var err = new Error('websocket close');
1781
+ err.code = evt.code;
1782
+ err.reason = evt.reason;}
1783
+
1784
+ conn.reset(err);}; } );
1785
+
1786
+ return this} }
1787
+
1788
+ const version = '0.6.0-node';
1789
+
1790
+ const MQTTClient_v4 = /* #__PURE__ */
1791
+ with_topic_path_router(
1792
+ MQTTCore.mqtt_ctx(4, mqtt_opts_v5) );
1793
+
1794
+ const MQTTClient_v5 = /* #__PURE__ */
1795
+ with_topic_path_router(
1796
+ MQTTCore.mqtt_ctx(5, mqtt_opts_v5) );
1797
+
1798
+ const mqtt_v4 = opt =>
1799
+ new MQTTClient_v4(opt);
1800
+
1801
+ const mqtt_v5 = opt =>
1802
+ new MQTTClient_v5(opt);
1803
+
1804
+ exports.MQTTClient = MQTTClient_v5;
1805
+ exports.MQTTClient_v4 = MQTTClient_v4;
1806
+ exports.MQTTClient_v5 = MQTTClient_v5;
1807
+ exports.default = mqtt_v5;
1808
+ exports.mqtt = mqtt_v5;
1809
+ exports.mqtt_v4 = mqtt_v4;
1810
+ exports.mqtt_v5 = mqtt_v5;
1811
+ exports.version = version;
1812
+ //# sourceMappingURL=full-v5.cjs.map