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