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/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]
20
+ return (u8.length < i)
21
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
22
+ : [n, i, i0] // successful value
26
23
  }
27
- */
28
-
29
24
 
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
- 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};
117
-
118
- let lut = (proto._reasons_by[pkt_type] ||= new Map());
119
- for (let [u8, reason] of reason_entries)
120
- lut.set( u8, reason );
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);
121
93
 
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)
123
97
  }
124
- };
98
+ warn(msg) {
99
+ let pkt = this.pkt;
100
+ pkt.warn ? pkt.warn(msg, pkt)
101
+ : console.warn('[u8-mqtt-packet] '+msg);
102
+ }
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,128 +208,6 @@ class mqtt_writer_v4 {
201
208
  }
202
209
  }
203
210
 
204
- function mqtt_decode_connack(ns, mqtt_reader) {
205
- class _connack_flags_ extends Number {
206
- get session_present() { return this & 0x01 !== 0 }
207
- }
208
-
209
- return ns[0x2] = (pkt, u8_body) => {
210
- let rdr = mqtt_reader.of(u8_body);
211
-
212
- pkt.flags =
213
- rdr.flags(_connack_flags_);
214
-
215
- pkt.reason = rdr.reason(pkt.type);
216
- if (5 <= pkt.mqtt_level)
217
- pkt.props = rdr.props();
218
- return pkt }
219
- }
220
-
221
-
222
- function _connack_v4(mqtt_reader) {
223
- mqtt_reader.reasons('connack',
224
- // MQTT 3.1.1
225
- [ 0x00, 'Success'],
226
- [ 0x01, 'Connection refused, unacceptable protocol version'],
227
- [ 0x02, 'Connection refused, identifier rejected'],
228
- [ 0x03, 'Connection refused, server unavailable'],
229
- [ 0x04, 'Connection refused, bad user name or password'],
230
- [ 0x05, 'Connection refused, not authorized'],
231
- );
232
- }
233
-
234
- function mqtt_decode_publish(ns, mqtt_reader) {
235
- return ns[0x3] = (pkt, u8_body) => {
236
- let {hdr} = pkt;
237
- pkt.dup = Boolean(hdr & 0x8);
238
- pkt.retain = Boolean(hdr & 0x1);
239
- let qos = pkt.qos = (hdr>>1) & 0x3;
240
-
241
- let rdr = mqtt_reader.of(u8_body);
242
- pkt.topic = rdr.utf8();
243
- if (0 !== qos)
244
- pkt.pkt_id = rdr.u16();
245
-
246
- if (5 <= pkt.mqtt_level)
247
- pkt.props = rdr.props();
248
-
249
- pkt.payload = rdr.flush();
250
- return pkt }
251
- }
252
-
253
- function mqtt_decode_puback(ns, mqtt_reader) {
254
- return ns[0x4] = (pkt, u8_body) => {
255
- let rdr = mqtt_reader.of(u8_body);
256
-
257
- pkt.pkt_id = rdr.u16();
258
- if (5 <= pkt.mqtt_level) {
259
- pkt.reason = rdr.reason(pkt.type);
260
- pkt.props = rdr.props();
261
- }
262
-
263
- return pkt }
264
- }
265
-
266
- function _mqtt_decode_suback(mqtt_reader) {
267
- return (pkt, u8_body) => {
268
- let rdr = mqtt_reader.of(u8_body);
269
-
270
- pkt.pkt_id = rdr.u16();
271
- if (5 <= pkt.mqtt_level)
272
- pkt.props = rdr.props();
273
-
274
- let answers = pkt.answers = [];
275
- while (rdr.has_more())
276
- answers.push(
277
- rdr.reason(pkt.type) );
278
-
279
- return pkt }
280
- }
281
-
282
- function mqtt_decode_suback(ns, mqtt_reader) {
283
- return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
284
- }
285
-
286
- function _suback_v4(mqtt_reader) {
287
- mqtt_reader.reasons('suback',
288
- // MQTT 3.1.1
289
- [ 0x00, 'Granted QoS 0'],
290
- [ 0x01, 'Granted QoS 1'],
291
- [ 0x02, 'Granted QoS 2'],
292
- );
293
- }
294
-
295
- function mqtt_decode_unsuback(ns, mqtt_reader) {
296
- return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
297
- }
298
-
299
- function _unsuback_v4(mqtt_reader) {
300
- mqtt_reader.reasons('unsuback',
301
- // MQTT 3.1.1
302
- [ 0x00, 'Success'],
303
- [ 0x11, 'No subscription existed'],
304
- [ 0x80, 'Unspecified error'],
305
- [ 0x83, 'Implementation specific error'],
306
- [ 0x87, 'Not authorized'],
307
- [ 0x8F, 'Topic Filter invalid'],
308
- [ 0x91, 'Packet Identifier in use'],
309
- );
310
- }
311
-
312
- function mqtt_decode_pingxxx(ns) {
313
- return ns[0xc] = ns[0xd] = pkt => pkt
314
- }
315
-
316
- function mqtt_decode_disconnect(ns, mqtt_reader) {
317
- return ns[0xe] = (pkt, u8_body) => {
318
- if (u8_body && 5 <= pkt.mqtt_level) {
319
- let rdr = mqtt_reader.of(u8_body);
320
- pkt.reason = rdr.reason(pkt.type);
321
- pkt.props = rdr.props();
322
- }
323
- return pkt }
324
- }
325
-
326
211
  function mqtt_encode_connect(ns, mqtt_writer) {
327
212
  const _c_mqtt_proto = new Uint8Array([
328
213
  0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
@@ -341,7 +226,7 @@ function mqtt_encode_connect(ns, mqtt_writer) {
341
226
  | ( will.retain ? 0x20 : 0 );
342
227
 
343
228
  return ns.connect = ( mqtt_level, pkt ) => {
344
- let wrt = mqtt_writer.of(pkt);
229
+ let wrt = mqtt_writer.for(pkt);
345
230
 
346
231
  wrt.push(_c_mqtt_proto);
347
232
  wrt.u8( mqtt_level );
@@ -379,10 +264,27 @@ function mqtt_encode_connect(ns, mqtt_writer) {
379
264
  }
380
265
  }
381
266
 
267
+ function mqtt_decode_connack(ns, mqtt_reader) {
268
+ class _connack_flags_ extends Number {
269
+ get session_present() { return this & 0x01 !== 0 }
270
+ }
271
+
272
+ return ns[0x2] = (pkt, u8_body) => {
273
+ let rdr = mqtt_reader.for(pkt, u8_body);
274
+
275
+ pkt.flags =
276
+ rdr.flags(_connack_flags_);
277
+
278
+ pkt.reason = rdr.reason(pkt.type);
279
+ if (5 <= pkt.mqtt_level)
280
+ pkt.props = rdr.props();
281
+ return pkt }
282
+ }
283
+
382
284
  function mqtt_encode_publish(ns, mqtt_writer) {
383
285
  return ns.publish = ( mqtt_level, pkt ) => {
384
286
  let qos = (pkt.qos & 0x3) << 1;
385
- let wrt = mqtt_writer.of(pkt);
287
+ let wrt = mqtt_writer.for(pkt);
386
288
 
387
289
  wrt.utf8(pkt.topic);
388
290
  if (0 !== qos)
@@ -400,9 +302,28 @@ function mqtt_encode_publish(ns, mqtt_writer) {
400
302
  }
401
303
  }
402
304
 
305
+ function mqtt_decode_publish(ns, mqtt_reader) {
306
+ return ns[0x3] = (pkt, u8_body) => {
307
+ let {hdr} = pkt;
308
+ pkt.dup = Boolean(hdr & 0x8);
309
+ pkt.retain = Boolean(hdr & 0x1);
310
+ let qos = pkt.qos = (hdr>>1) & 0x3;
311
+
312
+ let rdr = mqtt_reader.for(pkt, u8_body);
313
+ pkt.topic = rdr.utf8();
314
+ if (0 !== qos)
315
+ pkt.pkt_id = rdr.u16();
316
+
317
+ if (5 <= pkt.mqtt_level)
318
+ pkt.props = rdr.props();
319
+
320
+ pkt.payload = rdr.flush();
321
+ return pkt }
322
+ }
323
+
403
324
  function mqtt_encode_puback(ns, mqtt_writer) {
404
325
  return ns.puback = ( mqtt_level, pkt ) => {
405
- let wrt = mqtt_writer.of(pkt);
326
+ let wrt = mqtt_writer.for(pkt);
406
327
 
407
328
  wrt.u16(pkt.pkt_id);
408
329
  if (5 <= mqtt_level) {
@@ -414,6 +335,20 @@ function mqtt_encode_puback(ns, mqtt_writer) {
414
335
  }
415
336
  }
416
337
 
338
+
339
+ function mqtt_decode_puback(ns, mqtt_reader) {
340
+ return ns[0x4] = (pkt, u8_body) => {
341
+ let rdr = mqtt_reader.for(pkt, u8_body);
342
+
343
+ pkt.pkt_id = rdr.u16();
344
+ if (5 <= pkt.mqtt_level) {
345
+ pkt.reason = rdr.reason(pkt.type);
346
+ pkt.props = rdr.props();
347
+ }
348
+
349
+ return pkt }
350
+ }
351
+
417
352
  function mqtt_encode_subscribe(ns, mqtt_writer) {
418
353
  const _enc_subscribe_flags = opts => 0
419
354
  | ( opts.qos & 0x3 )
@@ -421,7 +356,7 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
421
356
  | ( (opts.retain_handling & 0x3) << 2 );
422
357
 
423
358
  return ns.subscribe = ( mqtt_level, pkt ) => {
424
- let wrt = mqtt_writer.of(pkt);
359
+ let wrt = mqtt_writer.for(pkt);
425
360
 
426
361
  wrt.u16(pkt.pkt_id);
427
362
  if (5 <= mqtt_level)
@@ -447,9 +382,25 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
447
382
  }
448
383
  }
449
384
 
385
+ function mqtt_decode_xxsuback(ns, mqtt_reader) {
386
+ return ns[0x9] = ns[0xb] = (pkt, u8_body) => {
387
+ let rdr = mqtt_reader.for(pkt, u8_body);
388
+
389
+ pkt.pkt_id = rdr.u16();
390
+ if (5 <= pkt.mqtt_level)
391
+ pkt.props = rdr.props();
392
+
393
+ let answers = pkt.answers = [];
394
+ while (rdr.has_more())
395
+ answers.push(
396
+ rdr.reason(pkt.type) );
397
+
398
+ return pkt }
399
+ }
400
+
450
401
  function mqtt_encode_unsubscribe(ns, mqtt_writer) {
451
402
  return ns.unsubscribe = ( mqtt_level, pkt ) => {
452
- let wrt = mqtt_writer.of(pkt);
403
+ let wrt = mqtt_writer.for(pkt);
453
404
 
454
405
  wrt.u16(pkt.pkt_id);
455
406
  if (5 <= mqtt_level)
@@ -467,9 +418,14 @@ function mqtt_encode_pingxxx(ns) {
467
418
  ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
468
419
  }
469
420
 
421
+
422
+ function mqtt_decode_pingxxx(ns) {
423
+ return ns[0xc] = ns[0xd] = pkt => pkt
424
+ }
425
+
470
426
  function mqtt_encode_disconnect(ns, mqtt_writer) {
471
427
  return ns.disconnect = ( mqtt_level, pkt ) => {
472
- let wrt = mqtt_writer.of(pkt);
428
+ let wrt = mqtt_writer.for(pkt);
473
429
 
474
430
  if (pkt && 5 <= mqtt_level) {
475
431
  if (pkt.reason || pkt.props) {
@@ -482,15 +438,25 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
482
438
  }
483
439
  }
484
440
 
485
- // not a v4 packet: import { mqtt_encode_auth } from './encode/auth.js'
441
+
442
+ function mqtt_decode_disconnect(ns, mqtt_reader) {
443
+ return ns[0xe] = (pkt, u8_body) => {
444
+ if (u8_body && 5 <= pkt.mqtt_level) {
445
+ let rdr = mqtt_reader.for(pkt, u8_body);
446
+ pkt.reason = rdr.reason(pkt.type);
447
+ pkt.props = rdr.props();
448
+ }
449
+ return pkt }
450
+ }
451
+
452
+ // not a v4 packet: import { mqtt_encode_auth, mqtt_decode_auth } from './pkt/auth.js'
486
453
 
487
454
 
488
455
  const mqtt_decode_v4 = [
489
456
  mqtt_decode_connack,
490
457
  mqtt_decode_publish,
491
458
  mqtt_decode_puback,
492
- mqtt_decode_suback,
493
- mqtt_decode_unsuback,
459
+ mqtt_decode_xxsuback,
494
460
  mqtt_decode_pingxxx,
495
461
  mqtt_decode_disconnect,
496
462
  ];
@@ -506,13 +472,6 @@ const mqtt_encode_v4 = [
506
472
  mqtt_encode_disconnect,
507
473
  ];
508
474
 
509
- const mqtt_reader_v4 = /* #__PURE__ */
510
- mqtt_reader_info(
511
- mqtt_reader_v4$1,
512
- _connack_v4,
513
- _suback_v4,
514
- _unsuback_v4,
515
- );
516
475
 
517
476
  const mqtt_opts_v4 =
518
477
  { decode_fns: mqtt_decode_v4,
@@ -605,7 +564,10 @@ const with_topic_router = mqtt_topic_router =>
605
564
  // alias: unsub_topic
606
565
  unsubscribe_topic(topic_route, ...args) {
607
566
  let router = this.router;
608
- router.remove(topic_route, true);
567
+
568
+ let fn = args.at(-1)?.call ? args.pop() : null;
569
+ router.remove(topic_route, true, fn);
570
+
609
571
  let topic = router.mqtt_topic(topic_route);
610
572
  return this.unsubscribe(topic, ...args ) }// topic_prefix
611
573
 
@@ -658,34 +620,38 @@ function mqtt_topic_path_router() {
658
620
  if (fn) {throw new TypeError()}
659
621
  fn = _ignore;}
660
622
 
661
- let rte = parse(as_topic_path(topic_route));
662
-
663
- rte.key = topic_route;
664
- rte.tgt = fn;
665
- pri_lsts[priority ? 0 : 1].push(rte);
623
+ let route = parse(as_topic_path(topic_route));
624
+ route.topic = topic_route;
625
+ route.tgt = fn;
626
+ pri_lsts[priority ? 0 : 1].push(route);
666
627
  return this}
667
628
 
668
- , remove(topic_route, priority) {
669
- let lst = pri_lsts[priority ? 0 : 1];
670
- return _route_remove([lst], topic_route)}
629
+ , remove(query, ...args) {
630
+ let lst = pri_lsts;
631
+ if ('boolean' === typeof args[0]) {
632
+ lst = [pri_lsts[args.shift() ? 0 : 1]];}
633
+
634
+ if ('string' === typeof query) {
635
+ query ={topic: query, tgt: args.pop()}; }
636
+ return _route_remove(lst, query)}
671
637
 
672
638
  , clear(priority) {
673
- pri_lsts[priority ? 0 : 1] = [];
674
639
  if (null == priority) {
675
- pri_lsts[1] = []; } }// null clears both lists
640
+ pri_lsts = [[],[]]; }// null clears both lists
641
+ else {
642
+ pri_lsts[priority ? 0 : 1] = [];} }
676
643
 
677
644
  , async invoke(pkt, ctx) {
678
645
  ctx.idx = 0;
679
646
  ctx.rm = rm;
680
647
 
681
- for (let [fn, params] of find(pkt.topic)) {
648
+ for (let [fn, params, route] of find(pkt.topic)) {
682
649
  let res = await fn(pkt, params, ctx);
683
650
 
684
651
  if (rm === res) {
685
- _route_remove(pri_lsts, fn);}
652
+ _route_remove(pri_lsts, route);}
686
653
 
687
- if (ctx.done) {
688
- break}
654
+ if (ctx.done) {break}
689
655
  else ctx.idx++;}
690
656
 
691
657
  if (1 === pkt.qos) {
@@ -695,70 +661,68 @@ function mqtt_topic_path_router() {
695
661
  function * _routes_iter(all_route_lists, topic) {
696
662
  topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
697
663
  for (let route_list of all_route_lists) {
698
- for (let {keys, pattern, tgt} of route_list) {
699
- let match = pattern.exec(topic);
664
+ for (let route of route_list) {
665
+ let match = route.pattern.exec(topic);
700
666
  if (match) {
701
- let params = keys
702
- ? keys.reduce(
667
+ let params = route.keys
668
+ ? route.keys.reduce(
703
669
  (o, k, i) => (o[k] = match[1+i], o)
704
670
  , {})
705
671
  : match.groups ?? match;
706
- yield [tgt, params];} } } }
672
+ yield [route.tgt, params, route];} } } }
707
673
 
708
674
 
709
675
  function _route_remove(all_route_lists, query) {
710
- let fn_match = route =>(
711
- route===query
712
- || route.tgt===query
713
- || route.key===query);
676
+ let ans = false;
714
677
  for (let lst of all_route_lists) {
715
- let i = lst.findIndex(fn_match);
716
- if (0 <= i) {
717
- lst.splice(i,1);
718
- return true} }
719
- return false}
720
-
721
- /*
722
- export function decode_varint_loop(u8, i=0) {
723
- let i0 = i
724
- let shift = 0, n = (u8[i] & 0x7f)
725
- while ( 0x80 & u8[i++] )
726
- n |= (u8[i] & 0x7f) << (shift += 7)
727
-
728
- return [n, i, i0]
729
- }
730
- */
731
-
732
-
733
- function decode_varint(u8, i=0) {
734
- let i0 = i;
735
- // unrolled for a max of 4 chains
736
- let n = (u8[i] & 0x7f) << 0;
737
- if ( 0x80 & u8[i++] ) {
738
- n |= (u8[i] & 0x7f) << 7;
739
- if ( 0x80 & u8[i++] ) {
740
- n |= (u8[i] & 0x7f) << 14;
741
- if ( 0x80 & u8[i++] ) {
742
- n |= (u8[i] & 0x7f) << 21;
743
- }
744
- }
745
- }
746
- return [n, i, i0]
678
+ let idx_tip = 0;
679
+ for (let route of lst) {
680
+ // skip matching routes to remove from compacted list
681
+ if (route === query) continue
682
+ if (route.topic === query.topic) {
683
+ if (null == query.tgt) continue
684
+ if (route.tgt === query.tgt) continue}
685
+
686
+ lst[idx_tip++] = route;}
687
+
688
+ // truncate remaining list
689
+ if (lst.splice(idx_tip).length)
690
+ ans = true;}
691
+
692
+ return ans}
693
+
694
+ function decode_varint(u8, i0=0, invalid) {
695
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
696
+ for(; b & 0x80;)
697
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
698
+
699
+ return (u8.length < i)
700
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
701
+ : [n, i, i0] // successful value
747
702
  }
748
703
 
749
704
  function mqtt_raw_dispatch(opt) {
750
- let u8 = new Uint8Array(0);
705
+ let u8 = new Uint8Array(0), len_tip=0;
751
706
  return u8_buf => {
752
707
  u8 = 0 === u8.byteLength
753
708
  ? u8_buf : _u8_join(u8, u8_buf);
754
709
 
755
710
  let res = [];
756
- while (1) {
757
- let [len_body, len_vh] = decode_varint(u8, 1);
758
- let len_pkt = len_body + len_vh;
759
711
 
760
- if ( u8.byteLength < len_pkt )
761
- return res
712
+ // wait for at least len_tip bytes for next (tip) message
713
+ while ( u8.byteLength >= len_tip ) {
714
+
715
+ // if varint is incomplete, return len_body=NaN
716
+ let [len_body, len_vh] = decode_varint(u8, 1, NaN);
717
+ let len_pkt = len_body + len_vh; // may be NaN
718
+
719
+ if (!( len_pkt <= u8.byteLength )) {
720
+ // incomplete packet cases:
721
+ // - len_pkt is less than available bytes
722
+ // - len_pkt is NaN from decode_varint() due to lack of data
723
+ len_tip = len_pkt || 0; // 0 when NaN
724
+ break
725
+ }
762
726
 
763
727
  let b0 = u8[0];
764
728
  let u8_body = 0 === len_body ? null
@@ -770,6 +734,8 @@ function mqtt_raw_dispatch(opt) {
770
734
  if (null != pkt)
771
735
  res.push( pkt );
772
736
  }
737
+
738
+ return res
773
739
  }
774
740
  }
775
741
 
@@ -780,16 +746,17 @@ function _u8_join(a, b) {
780
746
  return r
781
747
  }
782
748
 
783
- const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
749
+ const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
750
+
751
+
752
+ function mqtt_pkt_ctx(mqtt_level, opts, pkt_api=opts.pkt_ctx) {
753
+ let _as_pkt_ctx = pkt_api => ({
754
+ __proto__: pkt_api,
755
+ get hdr() { return this.b0 & 0xf },
756
+ get id() { return this.b0 >>> 4 },
757
+ get type() { return _pkt_types[this.b0 >>> 4] },
758
+ mqtt_level });
784
759
 
785
- function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
786
- pkt_ctx = {
787
- __proto__: pkt_ctx || opts.pkt_ctx,
788
- mqtt_level,
789
- get hdr() { return this.b0 & 0xf },
790
- get id() { return this.b0 >>> 4 },
791
- get type() { return _pkt_types[this.b0 >>> 4] },
792
- };
793
760
 
794
761
  let op, _decode_by_id=[], _encode_by_type={};
795
762
  for (op of opts.encode_fns)
@@ -798,10 +765,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
798
765
  op(_decode_by_id, opts.mqtt_reader);
799
766
 
800
767
  return {
801
- pkt_ctx,
768
+ pkt_api, pkt_ctx: _as_pkt_ctx(pkt_api),
802
769
 
803
- encode_pkt(type, pkt) {
804
- return _encode_by_type[type]( mqtt_level, pkt ) },
770
+ encode_pkt: (type, pkt) =>
771
+ _encode_by_type[type]( mqtt_level, pkt ),
805
772
 
806
773
  decode_pkt(b0, u8_body) {
807
774
  if (b0.map) // Uint8Array in first arg
@@ -810,12 +777,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
810
777
  let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
811
778
  return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
812
779
 
813
- mqtt_stream() {
814
- let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
815
- self.pkt_ctx._base_ = self.pkt_ctx;
780
+ mqtt_stream(pkt_api=this.pkt_api) {
781
+ let self = { __proto__: this, pkt_ctx: _as_pkt_ctx(pkt_api) };
816
782
  self.decode = mqtt_raw_dispatch(self);
817
- return self
818
- },
783
+ return self },
819
784
  }
820
785
  }
821
786
 
@@ -1339,7 +1304,7 @@ class MQTTCore extends MQTTBase {
1339
1304
 
1340
1305
  return this} }
1341
1306
 
1342
- const version = '0.6.2-node';
1307
+ const version = '0.6.4-node';
1343
1308
 
1344
1309
  const MQTTClient_v4 = /* #__PURE__ */
1345
1310
  with_topic_path_router(