u8-mqtt 0.6.2 → 0.6.4

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 (108) hide show
  1. package/cjs/basic-v4.cjs +194 -243
  2. package/cjs/basic-v4.cjs.map +1 -1
  3. package/cjs/basic-v5.cjs +247 -368
  4. package/cjs/basic-v5.cjs.map +1 -1
  5. package/cjs/full-v4.cjs +342 -384
  6. package/cjs/full-v4.cjs.map +1 -1
  7. package/cjs/full-v5.cjs +395 -507
  8. package/cjs/full-v5.cjs.map +1 -1
  9. package/cjs/index.cjs +292 -399
  10. package/cjs/index.cjs.map +1 -1
  11. package/cjs/v4.cjs +239 -274
  12. package/cjs/v4.cjs.map +1 -1
  13. package/cjs/v5.cjs +292 -399
  14. package/cjs/v5.cjs.map +1 -1
  15. package/code/router_path.jsy +39 -28
  16. package/code/with_topic_router.jsy +4 -1
  17. package/esm/basic-v4.js +194 -243
  18. package/esm/basic-v4.js.map +1 -1
  19. package/esm/basic-v5.js +247 -368
  20. package/esm/basic-v5.js.map +1 -1
  21. package/esm/deno/basic-v4.js +194 -243
  22. package/esm/deno/basic-v4.js.map +1 -1
  23. package/esm/deno/basic-v5.js +247 -368
  24. package/esm/deno/basic-v5.js.map +1 -1
  25. package/esm/deno/full-v4.js +342 -384
  26. package/esm/deno/full-v4.js.map +1 -1
  27. package/esm/deno/full-v5.js +395 -507
  28. package/esm/deno/full-v5.js.map +1 -1
  29. package/esm/deno/index.js +292 -399
  30. package/esm/deno/index.js.map +1 -1
  31. package/esm/deno/v4.js +239 -274
  32. package/esm/deno/v4.js.map +1 -1
  33. package/esm/deno/v5.js +292 -399
  34. package/esm/deno/v5.js.map +1 -1
  35. package/esm/full-v4.js +342 -384
  36. package/esm/full-v4.js.map +1 -1
  37. package/esm/full-v5.js +395 -507
  38. package/esm/full-v5.js.map +1 -1
  39. package/esm/index.js +292 -399
  40. package/esm/index.js.map +1 -1
  41. package/esm/node/basic-v4.js +194 -243
  42. package/esm/node/basic-v4.js.map +1 -1
  43. package/esm/node/basic-v4.mjs +194 -243
  44. package/esm/node/basic-v4.mjs.map +1 -1
  45. package/esm/node/basic-v5.js +247 -368
  46. package/esm/node/basic-v5.js.map +1 -1
  47. package/esm/node/basic-v5.mjs +247 -368
  48. package/esm/node/basic-v5.mjs.map +1 -1
  49. package/esm/node/full-v4.js +342 -384
  50. package/esm/node/full-v4.js.map +1 -1
  51. package/esm/node/full-v4.mjs +342 -384
  52. package/esm/node/full-v4.mjs.map +1 -1
  53. package/esm/node/full-v5.js +395 -507
  54. package/esm/node/full-v5.js.map +1 -1
  55. package/esm/node/full-v5.mjs +395 -507
  56. package/esm/node/full-v5.mjs.map +1 -1
  57. package/esm/node/index.js +292 -399
  58. package/esm/node/index.js.map +1 -1
  59. package/esm/node/index.mjs +292 -399
  60. package/esm/node/index.mjs.map +1 -1
  61. package/esm/node/v4.js +239 -274
  62. package/esm/node/v4.js.map +1 -1
  63. package/esm/node/v4.mjs +239 -274
  64. package/esm/node/v4.mjs.map +1 -1
  65. package/esm/node/v5.js +292 -399
  66. package/esm/node/v5.js.map +1 -1
  67. package/esm/node/v5.mjs +292 -399
  68. package/esm/node/v5.mjs.map +1 -1
  69. package/esm/v4.js +239 -274
  70. package/esm/v4.js.map +1 -1
  71. package/esm/v5.js +292 -399
  72. package/esm/v5.js.map +1 -1
  73. package/esm/web/basic-v4.js +194 -243
  74. package/esm/web/basic-v4.js.map +1 -1
  75. package/esm/web/basic-v4.min.js +1 -1
  76. package/esm/web/basic-v4.min.js.br +0 -0
  77. package/esm/web/basic-v4.min.js.gz +0 -0
  78. package/esm/web/basic-v5.js +247 -368
  79. package/esm/web/basic-v5.js.map +1 -1
  80. package/esm/web/basic-v5.min.js +1 -1
  81. package/esm/web/basic-v5.min.js.br +0 -0
  82. package/esm/web/basic-v5.min.js.gz +0 -0
  83. package/esm/web/full-v4.js +342 -384
  84. package/esm/web/full-v4.js.map +1 -1
  85. package/esm/web/full-v4.min.js +1 -1
  86. package/esm/web/full-v4.min.js.br +0 -0
  87. package/esm/web/full-v4.min.js.gz +0 -0
  88. package/esm/web/full-v5.js +395 -507
  89. package/esm/web/full-v5.js.map +1 -1
  90. package/esm/web/full-v5.min.js +1 -1
  91. package/esm/web/full-v5.min.js.br +0 -0
  92. package/esm/web/full-v5.min.js.gz +0 -0
  93. package/esm/web/index.js +292 -399
  94. package/esm/web/index.js.map +1 -1
  95. package/esm/web/index.min.js +1 -1
  96. package/esm/web/index.min.js.br +0 -0
  97. package/esm/web/index.min.js.gz +0 -0
  98. package/esm/web/v4.js +239 -274
  99. package/esm/web/v4.js.map +1 -1
  100. package/esm/web/v4.min.js +1 -1
  101. package/esm/web/v4.min.js.br +0 -0
  102. package/esm/web/v4.min.js.gz +0 -0
  103. package/esm/web/v5.js +292 -399
  104. package/esm/web/v5.js.map +1 -1
  105. package/esm/web/v5.min.js +1 -1
  106. package/esm/web/v5.min.js.br +0 -0
  107. package/esm/web/v5.min.js.gz +0 -0
  108. package/package.json +5 -5
package/cjs/full-v4.cjs CHANGED
@@ -6,56 +6,34 @@ var node_net = require('node:net');
6
6
  var node_tls = require('node:tls');
7
7
 
8
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)
9
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
10
+ for(; ( n>>>=7 ) > 0 ;)
11
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
14
12
  return a
15
13
  }
16
14
 
15
+ function decode_varint$1(u8, i0=0, invalid) {
16
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
17
+ for(; b & 0x80;)
18
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
17
19
 
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]
20
+ return (u8.length < i)
21
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
22
+ : [n, i, i0] // successful value
44
23
  }
45
24
 
46
- class U8_Reason extends Number {
47
- static of(v, pkt_kind, by_kind) {
48
- let self = new this(v);
49
- self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
50
- return self
25
+ class mqtt_reason extends Number {
26
+ constructor(v, reason) {
27
+ super(v);
28
+ this.reason = `:${(this.ok = v<0x80) ? 'ok' : 'fail'}:${reason}`;
51
29
  }
52
30
  }
53
31
 
54
32
  let mqtt_reader_v4$1 = class mqtt_reader_v4 {
55
- static of(buf) { return this.prototype.of(buf) }
56
- of(buf) {
33
+ static for(pkt, u8_body) { return new this().of(u8_body, {pkt}) }
34
+ of(buf, opt) {
57
35
  let step = (width, k) => (k=0|step.k, step.k=k+width, k);
58
- return {__proto__: this, buf, step}
36
+ return {__proto__: this, buf, step, ...opt}
59
37
  }
60
38
 
61
39
  has_more() {
@@ -98,7 +76,7 @@ let mqtt_reader_v4$1 = class mqtt_reader_v4 {
98
76
  reason(pkt_kind) {
99
77
  let v = this.buf[this.step(1)];
100
78
  if (null != v)
101
- return U8_Reason.of(v, pkt_kind, this._reasons_by)
79
+ return new mqtt_reason(v, this._reason_for?.(v, pkt_kind))
102
80
  }
103
81
 
104
82
  flush() {
@@ -109,28 +87,57 @@ let mqtt_reader_v4$1 = class mqtt_reader_v4 {
109
87
 
110
88
  };
111
89
 
112
- function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
113
- mqtt_reader = class extends mqtt_reader {
114
- static reasons(pkt_type, ...reason_entries) {
115
- let proto = this.prototype;
116
- proto._reasons_by = {... proto._reasons_by};
90
+ function with_reasons(mqtt_reader, by_kind) {
91
+ for (let [k,lut] of Object.entries(by_kind))
92
+ by_kind[k] = new Map(lut);
117
93
 
118
- let lut = (proto._reasons_by[pkt_type] ||= new Map());
119
- for (let [u8, reason] of reason_entries)
120
- lut.set( u8, reason );
121
-
122
- return this
94
+ return class extends mqtt_reader {
95
+ _reason_for(v, pkt_kind) {
96
+ return by_kind[pkt_kind]?.get(v) || by_kind.all.get(v)
97
+ }
98
+ warn(msg) {
99
+ let pkt = this.pkt;
100
+ pkt.warn ? pkt.warn(msg, pkt)
101
+ : console.warn('[u8-mqtt-packet] '+msg);
123
102
  }
124
- };
103
+ }
104
+ }
125
105
 
126
- for (let fn_info of info_fn_list)
127
- fn_info(mqtt_reader);
128
106
 
129
- return mqtt_reader
130
- }
107
+ const reasons_v4 = {
108
+ connack: [
109
+ [ 0x01, 'conn refused: unacceptable protocol version'],
110
+ [ 0x02, 'conn refused: identifier rejected'],
111
+ [ 0x03, 'conn refused: server unavailable'],
112
+ [ 0x04, 'conn refused: bad user name or password'],
113
+ [ 0x05, 'conn refused: not authorized'],
114
+ ],
115
+ suback: [
116
+ [ 0x00, 'qos=0'],
117
+ [ 0x01, 'qos=1'],
118
+ [ 0x02, 'qos=2'],
119
+ ],
120
+ unsuback: [
121
+ [ 0x11, 'no subscription existed'],
122
+ ],
123
+ puback: [
124
+ [ 0x10, 'no matching subscribers'],
125
+ ],
126
+ all: [
127
+ [ 0, ''], // Success
128
+ [ 0x80, 'unspecified error'], // disconnect puback suback unsuback
129
+ [ 0x83, 'implementation specific error'], // connack disconnect puback suback unsuback
130
+ [ 0x87, 'not authorized'], // connack disconnect puback suback unsuback
131
+ [ 0x8F, 'topic filter invalid'], // disconnect suback unsuback
132
+ [ 0x91, 'packet identifier in use'], // puback suback unsuback
133
+ [ 0x92, 'packet identifier not found' ], // pubxxx
134
+ ]};
135
+
136
+ const mqtt_reader_v4 = /* #__PURE__ */
137
+ with_reasons(mqtt_reader_v4$1, reasons_v4);
131
138
 
132
139
  class mqtt_writer_v4 {
133
- static of() { return this.prototype.of() }
140
+ static for(pkt) { return new this().of() }
134
141
  of() { return {__proto__: this, $:[]} }
135
142
 
136
143
  static init() { return this }
@@ -201,234 +208,6 @@ class mqtt_writer_v4 {
201
208
  }
202
209
  }
203
210
 
204
- function mqtt_decode_connect(ns, mqtt_reader) {
205
- class _connect_flags_ extends Number {
206
- get reserved() { return this & 0x01 !== 0 }
207
- get clean_start() { return this & 0x02 !== 0 }
208
- get will_flag() { return this & 0x04 !== 0 }
209
- get will_qos() { return (this >>> 3) & 0x3 }
210
- get will_retain() { return this & 0x20 !== 0 }
211
- get password() { return this & 0x40 !== 0 }
212
- get username() { return this & 0x80 !== 0 }
213
- }
214
-
215
- return ns[0x1] = (pkt, u8_body) => {
216
- let rdr = mqtt_reader.of(u8_body);
217
- if ('MQTT' !== rdr.utf8())
218
- throw new Error('Invalid mqtt_connect packet')
219
-
220
- pkt._base_.mqtt_level = pkt.mqtt_level = rdr.u8();
221
-
222
- let flags = pkt.flags =
223
- rdr.flags(_connect_flags_);
224
-
225
- pkt.keep_alive = rdr.u16();
226
-
227
- if (5 <= pkt.mqtt_level)
228
- pkt.props = rdr.props();
229
-
230
-
231
-
232
- pkt.client_id = rdr.utf8();
233
- if (flags.will_flag) {
234
- let will = pkt.will = {};
235
- if (5 <= pkt.mqtt_level)
236
- will.props = rdr.props();
237
-
238
- will.topic = rdr.utf8();
239
- will.payload = rdr.bin();
240
- will.qos = flags.will_qos;
241
- will.retain = flags.will_retain;
242
- }
243
-
244
- if (flags.username)
245
- pkt.username = rdr.utf8();
246
-
247
- if (flags.password)
248
- pkt.password = rdr.bin();
249
- return pkt }
250
- }
251
-
252
- function mqtt_decode_connack(ns, mqtt_reader) {
253
- class _connack_flags_ extends Number {
254
- get session_present() { return this & 0x01 !== 0 }
255
- }
256
-
257
- return ns[0x2] = (pkt, u8_body) => {
258
- let rdr = mqtt_reader.of(u8_body);
259
-
260
- pkt.flags =
261
- rdr.flags(_connack_flags_);
262
-
263
- pkt.reason = rdr.reason(pkt.type);
264
- if (5 <= pkt.mqtt_level)
265
- pkt.props = rdr.props();
266
- return pkt }
267
- }
268
-
269
-
270
- function _connack_v4(mqtt_reader) {
271
- mqtt_reader.reasons('connack',
272
- // MQTT 3.1.1
273
- [ 0x00, 'Success'],
274
- [ 0x01, 'Connection refused, unacceptable protocol version'],
275
- [ 0x02, 'Connection refused, identifier rejected'],
276
- [ 0x03, 'Connection refused, server unavailable'],
277
- [ 0x04, 'Connection refused, bad user name or password'],
278
- [ 0x05, 'Connection refused, not authorized'],
279
- );
280
- }
281
-
282
- function mqtt_decode_publish(ns, mqtt_reader) {
283
- return ns[0x3] = (pkt, u8_body) => {
284
- let {hdr} = pkt;
285
- pkt.dup = Boolean(hdr & 0x8);
286
- pkt.retain = Boolean(hdr & 0x1);
287
- let qos = pkt.qos = (hdr>>1) & 0x3;
288
-
289
- let rdr = mqtt_reader.of(u8_body);
290
- pkt.topic = rdr.utf8();
291
- if (0 !== qos)
292
- pkt.pkt_id = rdr.u16();
293
-
294
- if (5 <= pkt.mqtt_level)
295
- pkt.props = rdr.props();
296
-
297
- pkt.payload = rdr.flush();
298
- return pkt }
299
- }
300
-
301
- function mqtt_decode_puback(ns, mqtt_reader) {
302
- return ns[0x4] = (pkt, u8_body) => {
303
- let rdr = mqtt_reader.of(u8_body);
304
-
305
- pkt.pkt_id = rdr.u16();
306
- if (5 <= pkt.mqtt_level) {
307
- pkt.reason = rdr.reason(pkt.type);
308
- pkt.props = rdr.props();
309
- }
310
-
311
- return pkt }
312
- }
313
-
314
- function mqtt_decode_pubxxx(ns, mqtt_reader) {
315
- return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
316
- let rdr = mqtt_reader.of(u8_body);
317
-
318
- pkt.pkt_id = rdr.u16();
319
- pkt.reason = rdr.reason('pubxxx', mqtt_reader);
320
- if (5 <= pkt.mqtt_level)
321
- pkt.props = rdr.props();
322
- return pkt }
323
- }
324
-
325
- function _pubxxx_v4(mqtt_reader) {
326
- mqtt_reader.reasons('pubxxx',
327
- // MQTT 3.1.1
328
- [ 0x00, 'Success' ],
329
- [ 0x92, 'Packet Identifier not found' ],
330
- );
331
- }
332
-
333
- function mqtt_decode_subscribe(ns, mqtt_reader) {
334
- class _subscription_options_ extends Number {
335
- get qos() { return this & 0x3 }
336
- get retain() { return this & 0x4 !== 0 }
337
- get retain_handling() { return (this >> 2) & 0x3 }
338
- }
339
-
340
- return ns[0x8] = (pkt, u8_body) => {
341
- let rdr = mqtt_reader.of(u8_body);
342
-
343
- pkt.pkt_id = rdr.u16();
344
- if (5 <= pkt.mqtt_level)
345
- pkt.props = rdr.props();
346
-
347
- let topic, opts, topic_list = pkt.topics = [];
348
- while (rdr.has_more()) {
349
- topic = rdr.utf8();
350
- opts = rdr.flags(_subscription_options_);
351
- topic_list.push({topic, opts});
352
- }
353
-
354
- return pkt }
355
- }
356
-
357
- function _mqtt_decode_suback(mqtt_reader) {
358
- return (pkt, u8_body) => {
359
- let rdr = mqtt_reader.of(u8_body);
360
-
361
- pkt.pkt_id = rdr.u16();
362
- if (5 <= pkt.mqtt_level)
363
- pkt.props = rdr.props();
364
-
365
- let answers = pkt.answers = [];
366
- while (rdr.has_more())
367
- answers.push(
368
- rdr.reason(pkt.type) );
369
-
370
- return pkt }
371
- }
372
-
373
- function mqtt_decode_suback(ns, mqtt_reader) {
374
- return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
375
- }
376
-
377
- function _suback_v4(mqtt_reader) {
378
- mqtt_reader.reasons('suback',
379
- // MQTT 3.1.1
380
- [ 0x00, 'Granted QoS 0'],
381
- [ 0x01, 'Granted QoS 1'],
382
- [ 0x02, 'Granted QoS 2'],
383
- );
384
- }
385
-
386
- function mqtt_decode_unsubscribe(ns, mqtt_reader) {
387
- return ns[0xa] = (pkt, u8_body) => {
388
- let rdr = mqtt_reader.of(u8_body);
389
-
390
- pkt.pkt_id = rdr.u16();
391
- if (5 <= pkt.mqtt_level)
392
- pkt.props = rdr.props();
393
-
394
- let topic_list = pkt.topics = [];
395
- while (rdr.has_more())
396
- topic_list.push(rdr.utf8());
397
-
398
- return pkt }
399
- }
400
-
401
- function mqtt_decode_unsuback(ns, mqtt_reader) {
402
- return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
403
- }
404
-
405
- function _unsuback_v4(mqtt_reader) {
406
- mqtt_reader.reasons('unsuback',
407
- // MQTT 3.1.1
408
- [ 0x00, 'Success'],
409
- [ 0x11, 'No subscription existed'],
410
- [ 0x80, 'Unspecified error'],
411
- [ 0x83, 'Implementation specific error'],
412
- [ 0x87, 'Not authorized'],
413
- [ 0x8F, 'Topic Filter invalid'],
414
- [ 0x91, 'Packet Identifier in use'],
415
- );
416
- }
417
-
418
- function mqtt_decode_pingxxx(ns) {
419
- return ns[0xc] = ns[0xd] = pkt => pkt
420
- }
421
-
422
- function mqtt_decode_disconnect(ns, mqtt_reader) {
423
- return ns[0xe] = (pkt, u8_body) => {
424
- if (u8_body && 5 <= pkt.mqtt_level) {
425
- let rdr = mqtt_reader.of(u8_body);
426
- pkt.reason = rdr.reason(pkt.type);
427
- pkt.props = rdr.props();
428
- }
429
- return pkt }
430
- }
431
-
432
211
  function mqtt_encode_connect(ns, mqtt_writer) {
433
212
  const _c_mqtt_proto = new Uint8Array([
434
213
  0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
@@ -447,7 +226,7 @@ function mqtt_encode_connect(ns, mqtt_writer) {
447
226
  | ( will.retain ? 0x20 : 0 );
448
227
 
449
228
  return ns.connect = ( mqtt_level, pkt ) => {
450
- let wrt = mqtt_writer.of(pkt);
229
+ let wrt = mqtt_writer.for(pkt);
451
230
 
452
231
  wrt.push(_c_mqtt_proto);
453
232
  wrt.u8( mqtt_level );
@@ -485,12 +264,61 @@ function mqtt_encode_connect(ns, mqtt_writer) {
485
264
  }
486
265
  }
487
266
 
267
+ function mqtt_decode_connect(ns, mqtt_reader) {
268
+ class _connect_flags_ extends Number {
269
+ get reserved() { return this & 0x01 !== 0 }
270
+ get clean_start() { return this & 0x02 !== 0 }
271
+ get will_flag() { return this & 0x04 !== 0 }
272
+ get will_qos() { return (this >>> 3) & 0x3 }
273
+ get will_retain() { return this & 0x20 !== 0 }
274
+ get password() { return this & 0x40 !== 0 }
275
+ get username() { return this & 0x80 !== 0 }
276
+ }
277
+
278
+ return ns[0x1] = (pkt, u8_body) => {
279
+ let rdr = mqtt_reader.for(pkt, u8_body);
280
+ if ('MQTT' !== rdr.utf8())
281
+ throw new Error('Invalid mqtt_connect packet')
282
+
283
+ pkt.__proto__.mqtt_level =
284
+ pkt.mqtt_level = rdr.u8();
285
+
286
+ let flags = pkt.flags =
287
+ rdr.flags(_connect_flags_);
288
+
289
+ pkt.keep_alive = rdr.u16();
290
+
291
+ if (5 <= pkt.mqtt_level)
292
+ pkt.props = rdr.props();
293
+
294
+
295
+
296
+ pkt.client_id = rdr.utf8();
297
+ if (flags.will_flag) {
298
+ let will = pkt.will = {};
299
+ if (5 <= pkt.mqtt_level)
300
+ will.props = rdr.props();
301
+
302
+ will.topic = rdr.utf8();
303
+ will.payload = rdr.bin();
304
+ will.qos = flags.will_qos;
305
+ will.retain = flags.will_retain;
306
+ }
307
+
308
+ if (flags.username)
309
+ pkt.username = rdr.utf8();
310
+
311
+ if (flags.password)
312
+ pkt.password = rdr.bin();
313
+ return pkt }
314
+ }
315
+
488
316
  function mqtt_encode_connack(ns, mqtt_writer) {
489
317
  const _enc_flags_connack = flags =>
490
318
  flags.session_present ? 1 : 0;
491
319
 
492
320
  return ns.connack = (mqtt_level, pkt) => {
493
- let wrt = mqtt_writer.of(pkt);
321
+ let wrt = mqtt_writer.for(pkt);
494
322
 
495
323
  wrt.flags( pkt.flags, _enc_flags_connack );
496
324
 
@@ -506,10 +334,28 @@ function mqtt_encode_connack(ns, mqtt_writer) {
506
334
  }
507
335
  }
508
336
 
337
+
338
+ function mqtt_decode_connack(ns, mqtt_reader) {
339
+ class _connack_flags_ extends Number {
340
+ get session_present() { return this & 0x01 !== 0 }
341
+ }
342
+
343
+ return ns[0x2] = (pkt, u8_body) => {
344
+ let rdr = mqtt_reader.for(pkt, u8_body);
345
+
346
+ pkt.flags =
347
+ rdr.flags(_connack_flags_);
348
+
349
+ pkt.reason = rdr.reason(pkt.type);
350
+ if (5 <= pkt.mqtt_level)
351
+ pkt.props = rdr.props();
352
+ return pkt }
353
+ }
354
+
509
355
  function mqtt_encode_publish(ns, mqtt_writer) {
510
356
  return ns.publish = ( mqtt_level, pkt ) => {
511
357
  let qos = (pkt.qos & 0x3) << 1;
512
- let wrt = mqtt_writer.of(pkt);
358
+ let wrt = mqtt_writer.for(pkt);
513
359
 
514
360
  wrt.utf8(pkt.topic);
515
361
  if (0 !== qos)
@@ -527,9 +373,28 @@ function mqtt_encode_publish(ns, mqtt_writer) {
527
373
  }
528
374
  }
529
375
 
376
+ function mqtt_decode_publish(ns, mqtt_reader) {
377
+ return ns[0x3] = (pkt, u8_body) => {
378
+ let {hdr} = pkt;
379
+ pkt.dup = Boolean(hdr & 0x8);
380
+ pkt.retain = Boolean(hdr & 0x1);
381
+ let qos = pkt.qos = (hdr>>1) & 0x3;
382
+
383
+ let rdr = mqtt_reader.for(pkt, u8_body);
384
+ pkt.topic = rdr.utf8();
385
+ if (0 !== qos)
386
+ pkt.pkt_id = rdr.u16();
387
+
388
+ if (5 <= pkt.mqtt_level)
389
+ pkt.props = rdr.props();
390
+
391
+ pkt.payload = rdr.flush();
392
+ return pkt }
393
+ }
394
+
530
395
  function mqtt_encode_puback(ns, mqtt_writer) {
531
396
  return ns.puback = ( mqtt_level, pkt ) => {
532
- let wrt = mqtt_writer.of(pkt);
397
+ let wrt = mqtt_writer.for(pkt);
533
398
 
534
399
  wrt.u16(pkt.pkt_id);
535
400
  if (5 <= mqtt_level) {
@@ -541,6 +406,20 @@ function mqtt_encode_puback(ns, mqtt_writer) {
541
406
  }
542
407
  }
543
408
 
409
+
410
+ function mqtt_decode_puback(ns, mqtt_reader) {
411
+ return ns[0x4] = (pkt, u8_body) => {
412
+ let rdr = mqtt_reader.for(pkt, u8_body);
413
+
414
+ pkt.pkt_id = rdr.u16();
415
+ if (5 <= pkt.mqtt_level) {
416
+ pkt.reason = rdr.reason(pkt.type);
417
+ pkt.props = rdr.props();
418
+ }
419
+
420
+ return pkt }
421
+ }
422
+
544
423
  function mqtt_encode_pubxxx(ns, mqtt_writer) {
545
424
  ns.pubrec = _enc_pubxxx(0x50);
546
425
  ns.pubrel = _enc_pubxxx(0x62);
@@ -549,7 +428,7 @@ function mqtt_encode_pubxxx(ns, mqtt_writer) {
549
428
 
550
429
  function _enc_pubxxx(hdr) {
551
430
  return ( mqtt_level, pkt ) => {
552
- let wrt = mqtt_writer.of(pkt);
431
+ let wrt = mqtt_writer.for(pkt);
553
432
 
554
433
  wrt.u16(pkt.pkt_id);
555
434
  if (5 <= mqtt_level) {
@@ -565,6 +444,17 @@ function mqtt_encode_pubxxx(ns, mqtt_writer) {
565
444
  }
566
445
  }
567
446
 
447
+ function mqtt_decode_pubxxx(ns, mqtt_reader) {
448
+ return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
449
+ let rdr = mqtt_reader.for(pkt, u8_body);
450
+
451
+ pkt.pkt_id = rdr.u16();
452
+ pkt.reason = rdr.reason('pubxxx', mqtt_reader);
453
+ if (5 <= pkt.mqtt_level)
454
+ pkt.props = rdr.props();
455
+ return pkt }
456
+ }
457
+
568
458
  function mqtt_encode_subscribe(ns, mqtt_writer) {
569
459
  const _enc_subscribe_flags = opts => 0
570
460
  | ( opts.qos & 0x3 )
@@ -572,7 +462,7 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
572
462
  | ( (opts.retain_handling & 0x3) << 2 );
573
463
 
574
464
  return ns.subscribe = ( mqtt_level, pkt ) => {
575
- let wrt = mqtt_writer.of(pkt);
465
+ let wrt = mqtt_writer.for(pkt);
576
466
 
577
467
  wrt.u16(pkt.pkt_id);
578
468
  if (5 <= mqtt_level)
@@ -598,6 +488,30 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
598
488
  }
599
489
  }
600
490
 
491
+ function mqtt_decode_subscribe(ns, mqtt_reader) {
492
+ class _subscription_options_ extends Number {
493
+ get qos() { return this & 0x3 }
494
+ get retain() { return this & 0x4 !== 0 }
495
+ get retain_handling() { return (this >> 2) & 0x3 }
496
+ }
497
+
498
+ return ns[0x8] = (pkt, u8_body) => {
499
+ let rdr = mqtt_reader.for(pkt, u8_body);
500
+
501
+ pkt.pkt_id = rdr.u16();
502
+ if (5 <= pkt.mqtt_level)
503
+ pkt.props = rdr.props();
504
+
505
+ let topic, opts, topic_list = pkt.topics = [];
506
+ while (rdr.has_more()) {
507
+ topic = rdr.utf8();
508
+ opts = rdr.flags(_subscription_options_);
509
+ topic_list.push({topic, opts});
510
+ }
511
+
512
+ return pkt }
513
+ }
514
+
601
515
  function mqtt_encode_xxsuback(ns, mqtt_writer) {
602
516
  ns.suback = _enc_xxsuback(0x90);
603
517
  ns.unsuback = _enc_xxsuback(0xb0);
@@ -605,7 +519,7 @@ function mqtt_encode_xxsuback(ns, mqtt_writer) {
605
519
 
606
520
  function _enc_xxsuback(hdr) {
607
521
  return ( mqtt_level, pkt ) => {
608
- let wrt = mqtt_writer.of(pkt);
522
+ let wrt = mqtt_writer.for(pkt);
609
523
 
610
524
  wrt.u16(pkt.pkt_id);
611
525
  if (5 <= mqtt_level)
@@ -619,9 +533,26 @@ function mqtt_encode_xxsuback(ns, mqtt_writer) {
619
533
  }
620
534
  }
621
535
 
536
+
537
+ function mqtt_decode_xxsuback(ns, mqtt_reader) {
538
+ return ns[0x9] = ns[0xb] = (pkt, u8_body) => {
539
+ let rdr = mqtt_reader.for(pkt, u8_body);
540
+
541
+ pkt.pkt_id = rdr.u16();
542
+ if (5 <= pkt.mqtt_level)
543
+ pkt.props = rdr.props();
544
+
545
+ let answers = pkt.answers = [];
546
+ while (rdr.has_more())
547
+ answers.push(
548
+ rdr.reason(pkt.type) );
549
+
550
+ return pkt }
551
+ }
552
+
622
553
  function mqtt_encode_unsubscribe(ns, mqtt_writer) {
623
554
  return ns.unsubscribe = ( mqtt_level, pkt ) => {
624
- let wrt = mqtt_writer.of(pkt);
555
+ let wrt = mqtt_writer.for(pkt);
625
556
 
626
557
  wrt.u16(pkt.pkt_id);
627
558
  if (5 <= mqtt_level)
@@ -634,14 +565,34 @@ function mqtt_encode_unsubscribe(ns, mqtt_writer) {
634
565
  }
635
566
  }
636
567
 
568
+ function mqtt_decode_unsubscribe(ns, mqtt_reader) {
569
+ return ns[0xa] = (pkt, u8_body) => {
570
+ let rdr = mqtt_reader.for(pkt, u8_body);
571
+
572
+ pkt.pkt_id = rdr.u16();
573
+ if (5 <= pkt.mqtt_level)
574
+ pkt.props = rdr.props();
575
+
576
+ let topic_list = pkt.topics = [];
577
+ while (rdr.has_more())
578
+ topic_list.push(rdr.utf8());
579
+
580
+ return pkt }
581
+ }
582
+
637
583
  function mqtt_encode_pingxxx(ns) {
638
584
  ns.pingreq = () => new Uint8Array([ 0xc0, 0 ]);
639
585
  ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
640
586
  }
641
587
 
588
+
589
+ function mqtt_decode_pingxxx(ns) {
590
+ return ns[0xc] = ns[0xd] = pkt => pkt
591
+ }
592
+
642
593
  function mqtt_encode_disconnect(ns, mqtt_writer) {
643
594
  return ns.disconnect = ( mqtt_level, pkt ) => {
644
- let wrt = mqtt_writer.of(pkt);
595
+ let wrt = mqtt_writer.for(pkt);
645
596
 
646
597
  if (pkt && 5 <= mqtt_level) {
647
598
  if (pkt.reason || pkt.props) {
@@ -654,17 +605,19 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
654
605
  }
655
606
  }
656
607
 
657
- // not a v4 packet: import { mqtt_encode_auth } from './encode/auth.js'
658
608
 
609
+ function mqtt_decode_disconnect(ns, mqtt_reader) {
610
+ return ns[0xe] = (pkt, u8_body) => {
611
+ if (u8_body && 5 <= pkt.mqtt_level) {
612
+ let rdr = mqtt_reader.for(pkt, u8_body);
613
+ pkt.reason = rdr.reason(pkt.type);
614
+ pkt.props = rdr.props();
615
+ }
616
+ return pkt }
617
+ }
618
+
619
+ // not a v4 packet: import { mqtt_encode_auth, mqtt_decode_auth } from './pkt/auth.js'
659
620
 
660
- const mqtt_reader_v4 = /* #__PURE__ */
661
- mqtt_reader_info(
662
- mqtt_reader_v4$1,
663
- _connack_v4,
664
- _pubxxx_v4,
665
- _suback_v4,
666
- _unsuback_v4,
667
- );
668
621
 
669
622
  const mqtt_decode_v4 = [
670
623
  mqtt_decode_connect,
@@ -673,9 +626,8 @@ const mqtt_decode_v4 = [
673
626
  mqtt_decode_puback,
674
627
  mqtt_decode_pubxxx,
675
628
  mqtt_decode_subscribe,
676
- mqtt_decode_suback,
629
+ mqtt_decode_xxsuback,
677
630
  mqtt_decode_unsubscribe,
678
- mqtt_decode_unsuback,
679
631
  mqtt_decode_pingxxx,
680
632
  mqtt_decode_disconnect,
681
633
  ];
@@ -786,7 +738,10 @@ const with_topic_router = mqtt_topic_router =>
786
738
  // alias: unsub_topic
787
739
  unsubscribe_topic(topic_route, ...args) {
788
740
  let router = this.router;
789
- router.remove(topic_route, true);
741
+
742
+ let fn = args.at(-1)?.call ? args.pop() : null;
743
+ router.remove(topic_route, true, fn);
744
+
790
745
  let topic = router.mqtt_topic(topic_route);
791
746
  return this.unsubscribe(topic, ...args ) }// topic_prefix
792
747
 
@@ -839,34 +794,38 @@ function mqtt_topic_path_router() {
839
794
  if (fn) {throw new TypeError()}
840
795
  fn = _ignore;}
841
796
 
842
- let rte = parse(as_topic_path(topic_route));
843
-
844
- rte.key = topic_route;
845
- rte.tgt = fn;
846
- pri_lsts[priority ? 0 : 1].push(rte);
797
+ let route = parse(as_topic_path(topic_route));
798
+ route.topic = topic_route;
799
+ route.tgt = fn;
800
+ pri_lsts[priority ? 0 : 1].push(route);
847
801
  return this}
848
802
 
849
- , remove(topic_route, priority) {
850
- let lst = pri_lsts[priority ? 0 : 1];
851
- return _route_remove([lst], topic_route)}
803
+ , remove(query, ...args) {
804
+ let lst = pri_lsts;
805
+ if ('boolean' === typeof args[0]) {
806
+ lst = [pri_lsts[args.shift() ? 0 : 1]];}
807
+
808
+ if ('string' === typeof query) {
809
+ query ={topic: query, tgt: args.pop()}; }
810
+ return _route_remove(lst, query)}
852
811
 
853
812
  , clear(priority) {
854
- pri_lsts[priority ? 0 : 1] = [];
855
813
  if (null == priority) {
856
- pri_lsts[1] = []; } }// null clears both lists
814
+ pri_lsts = [[],[]]; }// null clears both lists
815
+ else {
816
+ pri_lsts[priority ? 0 : 1] = [];} }
857
817
 
858
818
  , async invoke(pkt, ctx) {
859
819
  ctx.idx = 0;
860
820
  ctx.rm = rm;
861
821
 
862
- for (let [fn, params] of find(pkt.topic)) {
822
+ for (let [fn, params, route] of find(pkt.topic)) {
863
823
  let res = await fn(pkt, params, ctx);
864
824
 
865
825
  if (rm === res) {
866
- _route_remove(pri_lsts, fn);}
826
+ _route_remove(pri_lsts, route);}
867
827
 
868
- if (ctx.done) {
869
- break}
828
+ if (ctx.done) {break}
870
829
  else ctx.idx++;}
871
830
 
872
831
  if (1 === pkt.qos) {
@@ -876,70 +835,68 @@ function mqtt_topic_path_router() {
876
835
  function * _routes_iter(all_route_lists, topic) {
877
836
  topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
878
837
  for (let route_list of all_route_lists) {
879
- for (let {keys, pattern, tgt} of route_list) {
880
- let match = pattern.exec(topic);
838
+ for (let route of route_list) {
839
+ let match = route.pattern.exec(topic);
881
840
  if (match) {
882
- let params = keys
883
- ? keys.reduce(
841
+ let params = route.keys
842
+ ? route.keys.reduce(
884
843
  (o, k, i) => (o[k] = match[1+i], o)
885
844
  , {})
886
845
  : match.groups ?? match;
887
- yield [tgt, params];} } } }
846
+ yield [route.tgt, params, route];} } } }
888
847
 
889
848
 
890
849
  function _route_remove(all_route_lists, query) {
891
- let fn_match = route =>(
892
- route===query
893
- || route.tgt===query
894
- || route.key===query);
850
+ let ans = false;
895
851
  for (let lst of all_route_lists) {
896
- let i = lst.findIndex(fn_match);
897
- if (0 <= i) {
898
- lst.splice(i,1);
899
- return true} }
900
- return false}
901
-
902
- /*
903
- export function decode_varint_loop(u8, i=0) {
904
- let i0 = i
905
- let shift = 0, n = (u8[i] & 0x7f)
906
- while ( 0x80 & u8[i++] )
907
- n |= (u8[i] & 0x7f) << (shift += 7)
908
-
909
- return [n, i, i0]
910
- }
911
- */
912
-
913
-
914
- function decode_varint(u8, i=0) {
915
- let i0 = i;
916
- // unrolled for a max of 4 chains
917
- let n = (u8[i] & 0x7f) << 0;
918
- if ( 0x80 & u8[i++] ) {
919
- n |= (u8[i] & 0x7f) << 7;
920
- if ( 0x80 & u8[i++] ) {
921
- n |= (u8[i] & 0x7f) << 14;
922
- if ( 0x80 & u8[i++] ) {
923
- n |= (u8[i] & 0x7f) << 21;
924
- }
925
- }
926
- }
927
- return [n, i, i0]
852
+ let idx_tip = 0;
853
+ for (let route of lst) {
854
+ // skip matching routes to remove from compacted list
855
+ if (route === query) continue
856
+ if (route.topic === query.topic) {
857
+ if (null == query.tgt) continue
858
+ if (route.tgt === query.tgt) continue}
859
+
860
+ lst[idx_tip++] = route;}
861
+
862
+ // truncate remaining list
863
+ if (lst.splice(idx_tip).length)
864
+ ans = true;}
865
+
866
+ return ans}
867
+
868
+ function decode_varint(u8, i0=0, invalid) {
869
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
870
+ for(; b & 0x80;)
871
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
872
+
873
+ return (u8.length < i)
874
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
875
+ : [n, i, i0] // successful value
928
876
  }
929
877
 
930
878
  function mqtt_raw_dispatch(opt) {
931
- let u8 = new Uint8Array(0);
879
+ let u8 = new Uint8Array(0), len_tip=0;
932
880
  return u8_buf => {
933
881
  u8 = 0 === u8.byteLength
934
882
  ? u8_buf : _u8_join(u8, u8_buf);
935
883
 
936
884
  let res = [];
937
- while (1) {
938
- let [len_body, len_vh] = decode_varint(u8, 1);
939
- let len_pkt = len_body + len_vh;
940
885
 
941
- if ( u8.byteLength < len_pkt )
942
- return res
886
+ // wait for at least len_tip bytes for next (tip) message
887
+ while ( u8.byteLength >= len_tip ) {
888
+
889
+ // if varint is incomplete, return len_body=NaN
890
+ let [len_body, len_vh] = decode_varint(u8, 1, NaN);
891
+ let len_pkt = len_body + len_vh; // may be NaN
892
+
893
+ if (!( len_pkt <= u8.byteLength )) {
894
+ // incomplete packet cases:
895
+ // - len_pkt is less than available bytes
896
+ // - len_pkt is NaN from decode_varint() due to lack of data
897
+ len_tip = len_pkt || 0; // 0 when NaN
898
+ break
899
+ }
943
900
 
944
901
  let b0 = u8[0];
945
902
  let u8_body = 0 === len_body ? null
@@ -951,6 +908,8 @@ function mqtt_raw_dispatch(opt) {
951
908
  if (null != pkt)
952
909
  res.push( pkt );
953
910
  }
911
+
912
+ return res
954
913
  }
955
914
  }
956
915
 
@@ -961,16 +920,17 @@ function _u8_join(a, b) {
961
920
  return r
962
921
  }
963
922
 
964
- const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
923
+ const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
924
+
925
+
926
+ function mqtt_pkt_ctx(mqtt_level, opts, pkt_api=opts.pkt_ctx) {
927
+ let _as_pkt_ctx = pkt_api => ({
928
+ __proto__: pkt_api,
929
+ get hdr() { return this.b0 & 0xf },
930
+ get id() { return this.b0 >>> 4 },
931
+ get type() { return _pkt_types[this.b0 >>> 4] },
932
+ mqtt_level });
965
933
 
966
- function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
967
- pkt_ctx = {
968
- __proto__: pkt_ctx || opts.pkt_ctx,
969
- mqtt_level,
970
- get hdr() { return this.b0 & 0xf },
971
- get id() { return this.b0 >>> 4 },
972
- get type() { return _pkt_types[this.b0 >>> 4] },
973
- };
974
934
 
975
935
  let op, _decode_by_id=[], _encode_by_type={};
976
936
  for (op of opts.encode_fns)
@@ -979,10 +939,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
979
939
  op(_decode_by_id, opts.mqtt_reader);
980
940
 
981
941
  return {
982
- pkt_ctx,
942
+ pkt_api, pkt_ctx: _as_pkt_ctx(pkt_api),
983
943
 
984
- encode_pkt(type, pkt) {
985
- return _encode_by_type[type]( mqtt_level, pkt ) },
944
+ encode_pkt: (type, pkt) =>
945
+ _encode_by_type[type]( mqtt_level, pkt ),
986
946
 
987
947
  decode_pkt(b0, u8_body) {
988
948
  if (b0.map) // Uint8Array in first arg
@@ -991,12 +951,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
991
951
  let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
992
952
  return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
993
953
 
994
- mqtt_stream() {
995
- let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
996
- self.pkt_ctx._base_ = self.pkt_ctx;
954
+ mqtt_stream(pkt_api=this.pkt_api) {
955
+ let self = { __proto__: this, pkt_ctx: _as_pkt_ctx(pkt_api) };
997
956
  self.decode = mqtt_raw_dispatch(self);
998
- return self
999
- },
957
+ return self },
1000
958
  }
1001
959
  }
1002
960
 
@@ -1520,7 +1478,7 @@ class MQTTCore extends MQTTBase {
1520
1478
 
1521
1479
  return this} }
1522
1480
 
1523
- const version = '0.6.2-node';
1481
+ const version = '0.6.4-node';
1524
1482
 
1525
1483
  const MQTTClient_v4 = /* #__PURE__ */
1526
1484
  with_topic_path_router(