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/esm/node/v4.js CHANGED
@@ -2,56 +2,34 @@ import { connect } from 'node:net';
2
2
  import { connect as connect$1 } from 'node:tls';
3
3
 
4
4
  function encode_varint(n, a=[]) {
5
- do {
6
- const ni = n & 0x7f;
7
- n >>>= 7;
8
- a.push( ni | (0===n ? 0 : 0x80) );
9
- } while (n > 0)
5
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
6
+ for(; ( n>>>=7 ) > 0 ;)
7
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
10
8
  return a
11
9
  }
12
10
 
11
+ function decode_varint$1(u8, i0=0, invalid) {
12
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
13
+ for(; b & 0x80;)
14
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
13
15
 
14
- /*
15
- export function decode_varint_loop(u8, i=0) {
16
- let i0 = i
17
- let shift = 0, n = (u8[i] & 0x7f)
18
- while ( 0x80 & u8[i++] )
19
- n |= (u8[i] & 0x7f) << (shift += 7)
20
-
21
- return [n, i, i0]
16
+ return (u8.length < i)
17
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
18
+ : [n, i, i0] // successful value
22
19
  }
23
- */
24
-
25
20
 
26
- function decode_varint$1(u8, i=0) {
27
- let i0 = i;
28
- // unrolled for a max of 4 chains
29
- let n = (u8[i] & 0x7f) << 0;
30
- if ( 0x80 & u8[i++] ) {
31
- n |= (u8[i] & 0x7f) << 7;
32
- if ( 0x80 & u8[i++] ) {
33
- n |= (u8[i] & 0x7f) << 14;
34
- if ( 0x80 & u8[i++] ) {
35
- n |= (u8[i] & 0x7f) << 21;
36
- }
37
- }
38
- }
39
- return [n, i, i0]
40
- }
41
-
42
- class U8_Reason extends Number {
43
- static of(v, pkt_kind, by_kind) {
44
- let self = new this(v);
45
- self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
46
- return self
21
+ class mqtt_reason extends Number {
22
+ constructor(v, reason) {
23
+ super(v);
24
+ this.reason = `:${(this.ok = v<0x80) ? 'ok' : 'fail'}:${reason}`;
47
25
  }
48
26
  }
49
27
 
50
28
  let mqtt_reader_v4$1 = class mqtt_reader_v4 {
51
- static of(buf) { return this.prototype.of(buf) }
52
- of(buf) {
29
+ static for(pkt, u8_body) { return new this().of(u8_body, {pkt}) }
30
+ of(buf, opt) {
53
31
  let step = (width, k) => (k=0|step.k, step.k=k+width, k);
54
- return {__proto__: this, buf, step}
32
+ return {__proto__: this, buf, step, ...opt}
55
33
  }
56
34
 
57
35
  has_more() {
@@ -94,7 +72,7 @@ let mqtt_reader_v4$1 = class mqtt_reader_v4 {
94
72
  reason(pkt_kind) {
95
73
  let v = this.buf[this.step(1)];
96
74
  if (null != v)
97
- return U8_Reason.of(v, pkt_kind, this._reasons_by)
75
+ return new mqtt_reason(v, this._reason_for?.(v, pkt_kind))
98
76
  }
99
77
 
100
78
  flush() {
@@ -105,28 +83,57 @@ let mqtt_reader_v4$1 = class mqtt_reader_v4 {
105
83
 
106
84
  };
107
85
 
108
- function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
109
- mqtt_reader = class extends mqtt_reader {
110
- static reasons(pkt_type, ...reason_entries) {
111
- let proto = this.prototype;
112
- proto._reasons_by = {... proto._reasons_by};
113
-
114
- let lut = (proto._reasons_by[pkt_type] ||= new Map());
115
- for (let [u8, reason] of reason_entries)
116
- lut.set( u8, reason );
86
+ function with_reasons(mqtt_reader, by_kind) {
87
+ for (let [k,lut] of Object.entries(by_kind))
88
+ by_kind[k] = new Map(lut);
117
89
 
118
- return this
90
+ return class extends mqtt_reader {
91
+ _reason_for(v, pkt_kind) {
92
+ return by_kind[pkt_kind]?.get(v) || by_kind.all.get(v)
119
93
  }
120
- };
94
+ warn(msg) {
95
+ let pkt = this.pkt;
96
+ pkt.warn ? pkt.warn(msg, pkt)
97
+ : console.warn('[u8-mqtt-packet] '+msg);
98
+ }
99
+ }
100
+ }
121
101
 
122
- for (let fn_info of info_fn_list)
123
- fn_info(mqtt_reader);
124
102
 
125
- return mqtt_reader
126
- }
103
+ const reasons_v4 = {
104
+ connack: [
105
+ [ 0x01, 'conn refused: unacceptable protocol version'],
106
+ [ 0x02, 'conn refused: identifier rejected'],
107
+ [ 0x03, 'conn refused: server unavailable'],
108
+ [ 0x04, 'conn refused: bad user name or password'],
109
+ [ 0x05, 'conn refused: not authorized'],
110
+ ],
111
+ suback: [
112
+ [ 0x00, 'qos=0'],
113
+ [ 0x01, 'qos=1'],
114
+ [ 0x02, 'qos=2'],
115
+ ],
116
+ unsuback: [
117
+ [ 0x11, 'no subscription existed'],
118
+ ],
119
+ puback: [
120
+ [ 0x10, 'no matching subscribers'],
121
+ ],
122
+ all: [
123
+ [ 0, ''], // Success
124
+ [ 0x80, 'unspecified error'], // disconnect puback suback unsuback
125
+ [ 0x83, 'implementation specific error'], // connack disconnect puback suback unsuback
126
+ [ 0x87, 'not authorized'], // connack disconnect puback suback unsuback
127
+ [ 0x8F, 'topic filter invalid'], // disconnect suback unsuback
128
+ [ 0x91, 'packet identifier in use'], // puback suback unsuback
129
+ [ 0x92, 'packet identifier not found' ], // pubxxx
130
+ ]};
131
+
132
+ const mqtt_reader_v4 = /* #__PURE__ */
133
+ with_reasons(mqtt_reader_v4$1, reasons_v4);
127
134
 
128
135
  class mqtt_writer_v4 {
129
- static of() { return this.prototype.of() }
136
+ static for(pkt) { return new this().of() }
130
137
  of() { return {__proto__: this, $:[]} }
131
138
 
132
139
  static init() { return this }
@@ -197,128 +204,6 @@ class mqtt_writer_v4 {
197
204
  }
198
205
  }
199
206
 
200
- function mqtt_decode_connack(ns, mqtt_reader) {
201
- class _connack_flags_ extends Number {
202
- get session_present() { return this & 0x01 !== 0 }
203
- }
204
-
205
- return ns[0x2] = (pkt, u8_body) => {
206
- let rdr = mqtt_reader.of(u8_body);
207
-
208
- pkt.flags =
209
- rdr.flags(_connack_flags_);
210
-
211
- pkt.reason = rdr.reason(pkt.type);
212
- if (5 <= pkt.mqtt_level)
213
- pkt.props = rdr.props();
214
- return pkt }
215
- }
216
-
217
-
218
- function _connack_v4(mqtt_reader) {
219
- mqtt_reader.reasons('connack',
220
- // MQTT 3.1.1
221
- [ 0x00, 'Success'],
222
- [ 0x01, 'Connection refused, unacceptable protocol version'],
223
- [ 0x02, 'Connection refused, identifier rejected'],
224
- [ 0x03, 'Connection refused, server unavailable'],
225
- [ 0x04, 'Connection refused, bad user name or password'],
226
- [ 0x05, 'Connection refused, not authorized'],
227
- );
228
- }
229
-
230
- function mqtt_decode_publish(ns, mqtt_reader) {
231
- return ns[0x3] = (pkt, u8_body) => {
232
- let {hdr} = pkt;
233
- pkt.dup = Boolean(hdr & 0x8);
234
- pkt.retain = Boolean(hdr & 0x1);
235
- let qos = pkt.qos = (hdr>>1) & 0x3;
236
-
237
- let rdr = mqtt_reader.of(u8_body);
238
- pkt.topic = rdr.utf8();
239
- if (0 !== qos)
240
- pkt.pkt_id = rdr.u16();
241
-
242
- if (5 <= pkt.mqtt_level)
243
- pkt.props = rdr.props();
244
-
245
- pkt.payload = rdr.flush();
246
- return pkt }
247
- }
248
-
249
- function mqtt_decode_puback(ns, mqtt_reader) {
250
- return ns[0x4] = (pkt, u8_body) => {
251
- let rdr = mqtt_reader.of(u8_body);
252
-
253
- pkt.pkt_id = rdr.u16();
254
- if (5 <= pkt.mqtt_level) {
255
- pkt.reason = rdr.reason(pkt.type);
256
- pkt.props = rdr.props();
257
- }
258
-
259
- return pkt }
260
- }
261
-
262
- function _mqtt_decode_suback(mqtt_reader) {
263
- return (pkt, u8_body) => {
264
- let rdr = mqtt_reader.of(u8_body);
265
-
266
- pkt.pkt_id = rdr.u16();
267
- if (5 <= pkt.mqtt_level)
268
- pkt.props = rdr.props();
269
-
270
- let answers = pkt.answers = [];
271
- while (rdr.has_more())
272
- answers.push(
273
- rdr.reason(pkt.type) );
274
-
275
- return pkt }
276
- }
277
-
278
- function mqtt_decode_suback(ns, mqtt_reader) {
279
- return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
280
- }
281
-
282
- function _suback_v4(mqtt_reader) {
283
- mqtt_reader.reasons('suback',
284
- // MQTT 3.1.1
285
- [ 0x00, 'Granted QoS 0'],
286
- [ 0x01, 'Granted QoS 1'],
287
- [ 0x02, 'Granted QoS 2'],
288
- );
289
- }
290
-
291
- function mqtt_decode_unsuback(ns, mqtt_reader) {
292
- return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
293
- }
294
-
295
- function _unsuback_v4(mqtt_reader) {
296
- mqtt_reader.reasons('unsuback',
297
- // MQTT 3.1.1
298
- [ 0x00, 'Success'],
299
- [ 0x11, 'No subscription existed'],
300
- [ 0x80, 'Unspecified error'],
301
- [ 0x83, 'Implementation specific error'],
302
- [ 0x87, 'Not authorized'],
303
- [ 0x8F, 'Topic Filter invalid'],
304
- [ 0x91, 'Packet Identifier in use'],
305
- );
306
- }
307
-
308
- function mqtt_decode_pingxxx(ns) {
309
- return ns[0xc] = ns[0xd] = pkt => pkt
310
- }
311
-
312
- function mqtt_decode_disconnect(ns, mqtt_reader) {
313
- return ns[0xe] = (pkt, u8_body) => {
314
- if (u8_body && 5 <= pkt.mqtt_level) {
315
- let rdr = mqtt_reader.of(u8_body);
316
- pkt.reason = rdr.reason(pkt.type);
317
- pkt.props = rdr.props();
318
- }
319
- return pkt }
320
- }
321
-
322
207
  function mqtt_encode_connect(ns, mqtt_writer) {
323
208
  const _c_mqtt_proto = new Uint8Array([
324
209
  0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
@@ -337,7 +222,7 @@ function mqtt_encode_connect(ns, mqtt_writer) {
337
222
  | ( will.retain ? 0x20 : 0 );
338
223
 
339
224
  return ns.connect = ( mqtt_level, pkt ) => {
340
- let wrt = mqtt_writer.of(pkt);
225
+ let wrt = mqtt_writer.for(pkt);
341
226
 
342
227
  wrt.push(_c_mqtt_proto);
343
228
  wrt.u8( mqtt_level );
@@ -375,10 +260,27 @@ function mqtt_encode_connect(ns, mqtt_writer) {
375
260
  }
376
261
  }
377
262
 
263
+ function mqtt_decode_connack(ns, mqtt_reader) {
264
+ class _connack_flags_ extends Number {
265
+ get session_present() { return this & 0x01 !== 0 }
266
+ }
267
+
268
+ return ns[0x2] = (pkt, u8_body) => {
269
+ let rdr = mqtt_reader.for(pkt, u8_body);
270
+
271
+ pkt.flags =
272
+ rdr.flags(_connack_flags_);
273
+
274
+ pkt.reason = rdr.reason(pkt.type);
275
+ if (5 <= pkt.mqtt_level)
276
+ pkt.props = rdr.props();
277
+ return pkt }
278
+ }
279
+
378
280
  function mqtt_encode_publish(ns, mqtt_writer) {
379
281
  return ns.publish = ( mqtt_level, pkt ) => {
380
282
  let qos = (pkt.qos & 0x3) << 1;
381
- let wrt = mqtt_writer.of(pkt);
283
+ let wrt = mqtt_writer.for(pkt);
382
284
 
383
285
  wrt.utf8(pkt.topic);
384
286
  if (0 !== qos)
@@ -396,9 +298,28 @@ function mqtt_encode_publish(ns, mqtt_writer) {
396
298
  }
397
299
  }
398
300
 
301
+ function mqtt_decode_publish(ns, mqtt_reader) {
302
+ return ns[0x3] = (pkt, u8_body) => {
303
+ let {hdr} = pkt;
304
+ pkt.dup = Boolean(hdr & 0x8);
305
+ pkt.retain = Boolean(hdr & 0x1);
306
+ let qos = pkt.qos = (hdr>>1) & 0x3;
307
+
308
+ let rdr = mqtt_reader.for(pkt, u8_body);
309
+ pkt.topic = rdr.utf8();
310
+ if (0 !== qos)
311
+ pkt.pkt_id = rdr.u16();
312
+
313
+ if (5 <= pkt.mqtt_level)
314
+ pkt.props = rdr.props();
315
+
316
+ pkt.payload = rdr.flush();
317
+ return pkt }
318
+ }
319
+
399
320
  function mqtt_encode_puback(ns, mqtt_writer) {
400
321
  return ns.puback = ( mqtt_level, pkt ) => {
401
- let wrt = mqtt_writer.of(pkt);
322
+ let wrt = mqtt_writer.for(pkt);
402
323
 
403
324
  wrt.u16(pkt.pkt_id);
404
325
  if (5 <= mqtt_level) {
@@ -410,6 +331,20 @@ function mqtt_encode_puback(ns, mqtt_writer) {
410
331
  }
411
332
  }
412
333
 
334
+
335
+ function mqtt_decode_puback(ns, mqtt_reader) {
336
+ return ns[0x4] = (pkt, u8_body) => {
337
+ let rdr = mqtt_reader.for(pkt, u8_body);
338
+
339
+ pkt.pkt_id = rdr.u16();
340
+ if (5 <= pkt.mqtt_level) {
341
+ pkt.reason = rdr.reason(pkt.type);
342
+ pkt.props = rdr.props();
343
+ }
344
+
345
+ return pkt }
346
+ }
347
+
413
348
  function mqtt_encode_subscribe(ns, mqtt_writer) {
414
349
  const _enc_subscribe_flags = opts => 0
415
350
  | ( opts.qos & 0x3 )
@@ -417,7 +352,7 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
417
352
  | ( (opts.retain_handling & 0x3) << 2 );
418
353
 
419
354
  return ns.subscribe = ( mqtt_level, pkt ) => {
420
- let wrt = mqtt_writer.of(pkt);
355
+ let wrt = mqtt_writer.for(pkt);
421
356
 
422
357
  wrt.u16(pkt.pkt_id);
423
358
  if (5 <= mqtt_level)
@@ -443,9 +378,25 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
443
378
  }
444
379
  }
445
380
 
381
+ function mqtt_decode_xxsuback(ns, mqtt_reader) {
382
+ return ns[0x9] = ns[0xb] = (pkt, u8_body) => {
383
+ let rdr = mqtt_reader.for(pkt, u8_body);
384
+
385
+ pkt.pkt_id = rdr.u16();
386
+ if (5 <= pkt.mqtt_level)
387
+ pkt.props = rdr.props();
388
+
389
+ let answers = pkt.answers = [];
390
+ while (rdr.has_more())
391
+ answers.push(
392
+ rdr.reason(pkt.type) );
393
+
394
+ return pkt }
395
+ }
396
+
446
397
  function mqtt_encode_unsubscribe(ns, mqtt_writer) {
447
398
  return ns.unsubscribe = ( mqtt_level, pkt ) => {
448
- let wrt = mqtt_writer.of(pkt);
399
+ let wrt = mqtt_writer.for(pkt);
449
400
 
450
401
  wrt.u16(pkt.pkt_id);
451
402
  if (5 <= mqtt_level)
@@ -463,9 +414,14 @@ function mqtt_encode_pingxxx(ns) {
463
414
  ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
464
415
  }
465
416
 
417
+
418
+ function mqtt_decode_pingxxx(ns) {
419
+ return ns[0xc] = ns[0xd] = pkt => pkt
420
+ }
421
+
466
422
  function mqtt_encode_disconnect(ns, mqtt_writer) {
467
423
  return ns.disconnect = ( mqtt_level, pkt ) => {
468
- let wrt = mqtt_writer.of(pkt);
424
+ let wrt = mqtt_writer.for(pkt);
469
425
 
470
426
  if (pkt && 5 <= mqtt_level) {
471
427
  if (pkt.reason || pkt.props) {
@@ -478,15 +434,25 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
478
434
  }
479
435
  }
480
436
 
481
- // not a v4 packet: import { mqtt_encode_auth } from './encode/auth.js'
437
+
438
+ function mqtt_decode_disconnect(ns, mqtt_reader) {
439
+ return ns[0xe] = (pkt, u8_body) => {
440
+ if (u8_body && 5 <= pkt.mqtt_level) {
441
+ let rdr = mqtt_reader.for(pkt, u8_body);
442
+ pkt.reason = rdr.reason(pkt.type);
443
+ pkt.props = rdr.props();
444
+ }
445
+ return pkt }
446
+ }
447
+
448
+ // not a v4 packet: import { mqtt_encode_auth, mqtt_decode_auth } from './pkt/auth.js'
482
449
 
483
450
 
484
451
  const mqtt_decode_v4 = [
485
452
  mqtt_decode_connack,
486
453
  mqtt_decode_publish,
487
454
  mqtt_decode_puback,
488
- mqtt_decode_suback,
489
- mqtt_decode_unsuback,
455
+ mqtt_decode_xxsuback,
490
456
  mqtt_decode_pingxxx,
491
457
  mqtt_decode_disconnect,
492
458
  ];
@@ -502,13 +468,6 @@ const mqtt_encode_v4 = [
502
468
  mqtt_encode_disconnect,
503
469
  ];
504
470
 
505
- const mqtt_reader_v4 = /* #__PURE__ */
506
- mqtt_reader_info(
507
- mqtt_reader_v4$1,
508
- _connack_v4,
509
- _suback_v4,
510
- _unsuback_v4,
511
- );
512
471
 
513
472
  const mqtt_opts_v4 =
514
473
  { decode_fns: mqtt_decode_v4,
@@ -601,7 +560,10 @@ const with_topic_router = mqtt_topic_router =>
601
560
  // alias: unsub_topic
602
561
  unsubscribe_topic(topic_route, ...args) {
603
562
  let router = this.router;
604
- router.remove(topic_route, true);
563
+
564
+ let fn = args.at(-1)?.call ? args.pop() : null;
565
+ router.remove(topic_route, true, fn);
566
+
605
567
  let topic = router.mqtt_topic(topic_route);
606
568
  return this.unsubscribe(topic, ...args ) }// topic_prefix
607
569
 
@@ -654,34 +616,38 @@ function mqtt_topic_path_router() {
654
616
  if (fn) {throw new TypeError()}
655
617
  fn = _ignore;}
656
618
 
657
- let rte = parse(as_topic_path(topic_route));
658
-
659
- rte.key = topic_route;
660
- rte.tgt = fn;
661
- pri_lsts[priority ? 0 : 1].push(rte);
619
+ let route = parse(as_topic_path(topic_route));
620
+ route.topic = topic_route;
621
+ route.tgt = fn;
622
+ pri_lsts[priority ? 0 : 1].push(route);
662
623
  return this}
663
624
 
664
- , remove(topic_route, priority) {
665
- let lst = pri_lsts[priority ? 0 : 1];
666
- return _route_remove([lst], topic_route)}
625
+ , remove(query, ...args) {
626
+ let lst = pri_lsts;
627
+ if ('boolean' === typeof args[0]) {
628
+ lst = [pri_lsts[args.shift() ? 0 : 1]];}
629
+
630
+ if ('string' === typeof query) {
631
+ query ={topic: query, tgt: args.pop()}; }
632
+ return _route_remove(lst, query)}
667
633
 
668
634
  , clear(priority) {
669
- pri_lsts[priority ? 0 : 1] = [];
670
635
  if (null == priority) {
671
- pri_lsts[1] = []; } }// null clears both lists
636
+ pri_lsts = [[],[]]; }// null clears both lists
637
+ else {
638
+ pri_lsts[priority ? 0 : 1] = [];} }
672
639
 
673
640
  , async invoke(pkt, ctx) {
674
641
  ctx.idx = 0;
675
642
  ctx.rm = rm;
676
643
 
677
- for (let [fn, params] of find(pkt.topic)) {
644
+ for (let [fn, params, route] of find(pkt.topic)) {
678
645
  let res = await fn(pkt, params, ctx);
679
646
 
680
647
  if (rm === res) {
681
- _route_remove(pri_lsts, fn);}
648
+ _route_remove(pri_lsts, route);}
682
649
 
683
- if (ctx.done) {
684
- break}
650
+ if (ctx.done) {break}
685
651
  else ctx.idx++;}
686
652
 
687
653
  if (1 === pkt.qos) {
@@ -691,70 +657,68 @@ function mqtt_topic_path_router() {
691
657
  function * _routes_iter(all_route_lists, topic) {
692
658
  topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
693
659
  for (let route_list of all_route_lists) {
694
- for (let {keys, pattern, tgt} of route_list) {
695
- let match = pattern.exec(topic);
660
+ for (let route of route_list) {
661
+ let match = route.pattern.exec(topic);
696
662
  if (match) {
697
- let params = keys
698
- ? keys.reduce(
663
+ let params = route.keys
664
+ ? route.keys.reduce(
699
665
  (o, k, i) => (o[k] = match[1+i], o)
700
666
  , {})
701
667
  : match.groups ?? match;
702
- yield [tgt, params];} } } }
668
+ yield [route.tgt, params, route];} } } }
703
669
 
704
670
 
705
671
  function _route_remove(all_route_lists, query) {
706
- let fn_match = route =>(
707
- route===query
708
- || route.tgt===query
709
- || route.key===query);
672
+ let ans = false;
710
673
  for (let lst of all_route_lists) {
711
- let i = lst.findIndex(fn_match);
712
- if (0 <= i) {
713
- lst.splice(i,1);
714
- return true} }
715
- return false}
716
-
717
- /*
718
- export function decode_varint_loop(u8, i=0) {
719
- let i0 = i
720
- let shift = 0, n = (u8[i] & 0x7f)
721
- while ( 0x80 & u8[i++] )
722
- n |= (u8[i] & 0x7f) << (shift += 7)
723
-
724
- return [n, i, i0]
725
- }
726
- */
727
-
728
-
729
- function decode_varint(u8, i=0) {
730
- let i0 = i;
731
- // unrolled for a max of 4 chains
732
- let n = (u8[i] & 0x7f) << 0;
733
- if ( 0x80 & u8[i++] ) {
734
- n |= (u8[i] & 0x7f) << 7;
735
- if ( 0x80 & u8[i++] ) {
736
- n |= (u8[i] & 0x7f) << 14;
737
- if ( 0x80 & u8[i++] ) {
738
- n |= (u8[i] & 0x7f) << 21;
739
- }
740
- }
741
- }
742
- return [n, i, i0]
674
+ let idx_tip = 0;
675
+ for (let route of lst) {
676
+ // skip matching routes to remove from compacted list
677
+ if (route === query) continue
678
+ if (route.topic === query.topic) {
679
+ if (null == query.tgt) continue
680
+ if (route.tgt === query.tgt) continue}
681
+
682
+ lst[idx_tip++] = route;}
683
+
684
+ // truncate remaining list
685
+ if (lst.splice(idx_tip).length)
686
+ ans = true;}
687
+
688
+ return ans}
689
+
690
+ function decode_varint(u8, i0=0, invalid) {
691
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
692
+ for(; b & 0x80;)
693
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
694
+
695
+ return (u8.length < i)
696
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
697
+ : [n, i, i0] // successful value
743
698
  }
744
699
 
745
700
  function mqtt_raw_dispatch(opt) {
746
- let u8 = new Uint8Array(0);
701
+ let u8 = new Uint8Array(0), len_tip=0;
747
702
  return u8_buf => {
748
703
  u8 = 0 === u8.byteLength
749
704
  ? u8_buf : _u8_join(u8, u8_buf);
750
705
 
751
706
  let res = [];
752
- while (1) {
753
- let [len_body, len_vh] = decode_varint(u8, 1);
754
- let len_pkt = len_body + len_vh;
755
707
 
756
- if ( u8.byteLength < len_pkt )
757
- return res
708
+ // wait for at least len_tip bytes for next (tip) message
709
+ while ( u8.byteLength >= len_tip ) {
710
+
711
+ // if varint is incomplete, return len_body=NaN
712
+ let [len_body, len_vh] = decode_varint(u8, 1, NaN);
713
+ let len_pkt = len_body + len_vh; // may be NaN
714
+
715
+ if (!( len_pkt <= u8.byteLength )) {
716
+ // incomplete packet cases:
717
+ // - len_pkt is less than available bytes
718
+ // - len_pkt is NaN from decode_varint() due to lack of data
719
+ len_tip = len_pkt || 0; // 0 when NaN
720
+ break
721
+ }
758
722
 
759
723
  let b0 = u8[0];
760
724
  let u8_body = 0 === len_body ? null
@@ -766,6 +730,8 @@ function mqtt_raw_dispatch(opt) {
766
730
  if (null != pkt)
767
731
  res.push( pkt );
768
732
  }
733
+
734
+ return res
769
735
  }
770
736
  }
771
737
 
@@ -776,16 +742,17 @@ function _u8_join(a, b) {
776
742
  return r
777
743
  }
778
744
 
779
- const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
745
+ const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
746
+
747
+
748
+ function mqtt_pkt_ctx(mqtt_level, opts, pkt_api=opts.pkt_ctx) {
749
+ let _as_pkt_ctx = pkt_api => ({
750
+ __proto__: pkt_api,
751
+ get hdr() { return this.b0 & 0xf },
752
+ get id() { return this.b0 >>> 4 },
753
+ get type() { return _pkt_types[this.b0 >>> 4] },
754
+ mqtt_level });
780
755
 
781
- function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
782
- pkt_ctx = {
783
- __proto__: pkt_ctx || opts.pkt_ctx,
784
- mqtt_level,
785
- get hdr() { return this.b0 & 0xf },
786
- get id() { return this.b0 >>> 4 },
787
- get type() { return _pkt_types[this.b0 >>> 4] },
788
- };
789
756
 
790
757
  let op, _decode_by_id=[], _encode_by_type={};
791
758
  for (op of opts.encode_fns)
@@ -794,10 +761,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
794
761
  op(_decode_by_id, opts.mqtt_reader);
795
762
 
796
763
  return {
797
- pkt_ctx,
764
+ pkt_api, pkt_ctx: _as_pkt_ctx(pkt_api),
798
765
 
799
- encode_pkt(type, pkt) {
800
- return _encode_by_type[type]( mqtt_level, pkt ) },
766
+ encode_pkt: (type, pkt) =>
767
+ _encode_by_type[type]( mqtt_level, pkt ),
801
768
 
802
769
  decode_pkt(b0, u8_body) {
803
770
  if (b0.map) // Uint8Array in first arg
@@ -806,12 +773,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
806
773
  let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
807
774
  return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
808
775
 
809
- mqtt_stream() {
810
- let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
811
- self.pkt_ctx._base_ = self.pkt_ctx;
776
+ mqtt_stream(pkt_api=this.pkt_api) {
777
+ let self = { __proto__: this, pkt_ctx: _as_pkt_ctx(pkt_api) };
812
778
  self.decode = mqtt_raw_dispatch(self);
813
- return self
814
- },
779
+ return self },
815
780
  }
816
781
  }
817
782
 
@@ -1335,7 +1300,7 @@ class MQTTCore extends MQTTBase {
1335
1300
 
1336
1301
  return this} }
1337
1302
 
1338
- const version = '0.6.2-node';
1303
+ const version = '0.6.4-node';
1339
1304
 
1340
1305
  const MQTTClient_v4 = /* #__PURE__ */
1341
1306
  with_topic_path_router(