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/v5.js CHANGED
@@ -2,41 +2,20 @@ 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]
22
- }
23
- */
24
-
25
-
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]
16
+ return (u8.length < i)
17
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
18
+ : [n, i, i0] // successful value
40
19
  }
41
20
 
42
21
  function add_mqtt_props(mqtt_props, entries) {
@@ -83,19 +62,18 @@ const init_mqtt_props = () =>
83
62
  const mqtt_props = /* #__PURE__ */
84
63
  init_mqtt_props();
85
64
 
86
- class U8_Reason extends Number {
87
- static of(v, pkt_kind, by_kind) {
88
- let self = new this(v);
89
- self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
90
- return self
65
+ class mqtt_reason extends Number {
66
+ constructor(v, reason) {
67
+ super(v);
68
+ this.reason = `:${(this.ok = v<0x80) ? 'ok' : 'fail'}:${reason}`;
91
69
  }
92
70
  }
93
71
 
94
72
  class mqtt_reader_v4 {
95
- static of(buf) { return this.prototype.of(buf) }
96
- of(buf) {
73
+ static for(pkt, u8_body) { return new this().of(u8_body, {pkt}) }
74
+ of(buf, opt) {
97
75
  let step = (width, k) => (k=0|step.k, step.k=k+width, k);
98
- return {__proto__: this, buf, step}
76
+ return {__proto__: this, buf, step, ...opt}
99
77
  }
100
78
 
101
79
  has_more() {
@@ -138,7 +116,7 @@ class mqtt_reader_v4 {
138
116
  reason(pkt_kind) {
139
117
  let v = this.buf[this.step(1)];
140
118
  if (null != v)
141
- return U8_Reason.of(v, pkt_kind, this._reasons_by)
119
+ return new mqtt_reason(v, this._reason_for?.(v, pkt_kind))
142
120
  }
143
121
 
144
122
  flush() {
@@ -152,7 +130,7 @@ class mqtt_reader_v4 {
152
130
  let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
153
131
  props() {
154
132
  let {buf, step} = this;
155
- let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
133
+ let [n, vi, vi0] = decode_varint$1(buf, step.k|0, 0);
156
134
  step(n + vi - vi0);
157
135
  if (0 === n) return null
158
136
 
@@ -161,7 +139,7 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
161
139
  let v, pk = fork.u8(), pt = mqtt_props.get( pk );
162
140
  if (!pt) {
163
141
  res._unknown_ = pk;
164
- this.warn(`unknown property: ${pk}`);
142
+ this.warn?.(`unknown property: ${pk}`);
165
143
  break
166
144
  }
167
145
 
@@ -181,8 +159,6 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
181
159
  return vec
182
160
  }
183
161
 
184
- warn(msg) { console.warn('[u8-mqtt-packet] '+msg); }
185
-
186
162
  /*
187
163
  vbuf() {
188
164
  let {buf, step} = this
@@ -194,28 +170,99 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
194
170
  */
195
171
  };
196
172
 
197
- function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
198
- mqtt_reader = class extends mqtt_reader {
199
- static reasons(pkt_type, ...reason_entries) {
200
- let proto = this.prototype;
201
- proto._reasons_by = {... proto._reasons_by};
202
-
203
- let lut = (proto._reasons_by[pkt_type] ||= new Map());
204
- for (let [u8, reason] of reason_entries)
205
- lut.set( u8, reason );
173
+ function with_reasons(mqtt_reader, by_kind) {
174
+ for (let [k,lut] of Object.entries(by_kind))
175
+ by_kind[k] = new Map(lut);
206
176
 
207
- return this
177
+ return class extends mqtt_reader {
178
+ _reason_for(v, pkt_kind) {
179
+ return by_kind[pkt_kind]?.get(v) || by_kind.all.get(v)
208
180
  }
209
- };
181
+ warn(msg) {
182
+ let pkt = this.pkt;
183
+ pkt.warn ? pkt.warn(msg, pkt)
184
+ : console.warn('[u8-mqtt-packet] '+msg);
185
+ }
186
+ }
187
+ }
210
188
 
211
- for (let fn_info of info_fn_list)
212
- fn_info(mqtt_reader);
213
189
 
214
- return mqtt_reader
215
- }
190
+ const reasons_v4 = {
191
+ connack: [
192
+ [ 0x01, 'conn refused: unacceptable protocol version'],
193
+ [ 0x02, 'conn refused: identifier rejected'],
194
+ [ 0x03, 'conn refused: server unavailable'],
195
+ [ 0x04, 'conn refused: bad user name or password'],
196
+ [ 0x05, 'conn refused: not authorized'],
197
+ ],
198
+ suback: [
199
+ [ 0x00, 'qos=0'],
200
+ [ 0x01, 'qos=1'],
201
+ [ 0x02, 'qos=2'],
202
+ ],
203
+ unsuback: [
204
+ [ 0x11, 'no subscription existed'],
205
+ ],
206
+ puback: [
207
+ [ 0x10, 'no matching subscribers'],
208
+ ],
209
+ all: [
210
+ [ 0, ''], // Success
211
+ [ 0x80, 'unspecified error'], // disconnect puback suback unsuback
212
+ [ 0x83, 'implementation specific error'], // connack disconnect puback suback unsuback
213
+ [ 0x87, 'not authorized'], // connack disconnect puback suback unsuback
214
+ [ 0x8F, 'topic filter invalid'], // disconnect suback unsuback
215
+ [ 0x91, 'packet identifier in use'], // puback suback unsuback
216
+ [ 0x92, 'packet identifier not found' ], // pubxxx
217
+ ]};
218
+
219
+ const reasons_v5 = {
220
+ ... reasons_v4,
221
+ auth: [
222
+ [ 0x18, 'continue authentication' ],
223
+ [ 0x19, 're-authenticate' ],
224
+ ],
225
+ disconnect: [
226
+ [ 0x04, 'disconnect with will message'],
227
+ ],
228
+ all: [
229
+ ... reasons_v4.all,
230
+ [ 0x81, 'malformed packet'], // connack disconnect
231
+ [ 0x82, 'protocol error'], // connack disconnect
232
+ [ 0x84, 'unsupported protocol version'], // connack
233
+ [ 0x85, 'client identifier not valid'], // connack
234
+ [ 0x86, 'bad user name or password'], // connack
235
+ [ 0x88, 'server unavailable'], // connack
236
+ [ 0x89, 'server busy'], // connack disconnect
237
+ [ 0x8A, 'banned'], // connack
238
+ [ 0x8B, 'server shutting down'], // disconnect
239
+ [ 0x8C, 'bad authentication method'], // connack
240
+ [ 0x8D, 'keep alive timeout'], // disconnect
241
+ [ 0x8E, 'session taken over'], // disconnect
242
+ [ 0x90, 'topic name invalid'], // connack disconnect puback
243
+ [ 0x93, 'receive maximum exceeded'], // disconnect
244
+ [ 0x94, 'topic alias invalid'], // disconnect
245
+ [ 0x95, 'packet too large'], // connack disconnect
246
+ [ 0x96, 'message rate too high'], // disconnect
247
+ [ 0x97, 'quota exceeded'], // connack disconnect puback suback
248
+ [ 0x98, 'administrative action'], // disconnect
249
+ [ 0x99, 'payload format invalid'], // connack disconnect puback
250
+ [ 0x9A, 'retain not supported'], // connack disconnect
251
+ [ 0x9B, 'qoS not supported'], // connack disconnect
252
+ [ 0x9C, 'use another server'], // connack disconnect
253
+ [ 0x9D, 'server moved'], // connack disconnect
254
+ [ 0x9E, 'shared subscriptions not supported'], // disconnect suback
255
+ [ 0x9F, 'connection rate exceeded'], // connack disconnect
256
+ [ 0xA0, 'maximum connect time'], // disconnect
257
+ [ 0xA1, 'subscription identifiers not supported'], // disconnect suback
258
+ [ 0xA2, 'wildcard subscriptions not supported'], // disconnect suback
259
+ ]};
260
+
261
+ const mqtt_reader_v5 = /* #__PURE__ */
262
+ with_reasons(mqtt_reader_v5$1, reasons_v5);
216
263
 
217
264
  class mqtt_writer_v4 {
218
- static of() { return this.prototype.of() }
265
+ static for(pkt) { return new this().of() }
219
266
  of() { return {__proto__: this, $:[]} }
220
267
 
221
268
  static init() { return this }
@@ -329,245 +376,6 @@ class mqtt_writer_v5 extends mqtt_writer_v4 {
329
376
  }
330
377
  }
331
378
 
332
- function mqtt_decode_connack(ns, mqtt_reader) {
333
- class _connack_flags_ extends Number {
334
- get session_present() { return this & 0x01 !== 0 }
335
- }
336
-
337
- return ns[0x2] = (pkt, u8_body) => {
338
- let rdr = mqtt_reader.of(u8_body);
339
-
340
- pkt.flags =
341
- rdr.flags(_connack_flags_);
342
-
343
- pkt.reason = rdr.reason(pkt.type);
344
- if (5 <= pkt.mqtt_level)
345
- pkt.props = rdr.props();
346
- return pkt }
347
- }
348
-
349
-
350
- function _connack_v4(mqtt_reader) {
351
- mqtt_reader.reasons('connack',
352
- // MQTT 3.1.1
353
- [ 0x00, 'Success'],
354
- [ 0x01, 'Connection refused, unacceptable protocol version'],
355
- [ 0x02, 'Connection refused, identifier rejected'],
356
- [ 0x03, 'Connection refused, server unavailable'],
357
- [ 0x04, 'Connection refused, bad user name or password'],
358
- [ 0x05, 'Connection refused, not authorized'],
359
- );
360
- }
361
-
362
- function _connack_v5(mqtt_reader) {
363
- _connack_v4(mqtt_reader);
364
-
365
- mqtt_reader.reasons('connack',
366
- // MQTT 5.0
367
- [ 0x81, 'Malformed Packet'],
368
- [ 0x82, 'Protocol Error'],
369
- [ 0x83, 'Implementation specific error'],
370
- [ 0x84, 'Unsupported Protocol Version'],
371
- [ 0x85, 'Client Identifier not valid'],
372
- [ 0x86, 'Bad User Name or Password'],
373
- [ 0x87, 'Not authorized'],
374
- [ 0x88, 'Server unavailable'],
375
- [ 0x89, 'Server busy'],
376
- [ 0x8A, 'Banned'],
377
- [ 0x8C, 'Bad authentication method'],
378
- [ 0x90, 'Topic Name invalid'],
379
- [ 0x95, 'Packet too large'],
380
- [ 0x97, 'Quota exceeded'],
381
- [ 0x99, 'Payload format invalid'],
382
- [ 0x9A, 'Retain not supported'],
383
- [ 0x9B, 'QoS not supported'],
384
- [ 0x9C, 'Use another server'],
385
- [ 0x9D, 'Server moved'],
386
- [ 0x9F, 'Connection rate exceeded'],
387
- );
388
- }
389
-
390
- function mqtt_decode_publish(ns, mqtt_reader) {
391
- return ns[0x3] = (pkt, u8_body) => {
392
- let {hdr} = pkt;
393
- pkt.dup = Boolean(hdr & 0x8);
394
- pkt.retain = Boolean(hdr & 0x1);
395
- let qos = pkt.qos = (hdr>>1) & 0x3;
396
-
397
- let rdr = mqtt_reader.of(u8_body);
398
- pkt.topic = rdr.utf8();
399
- if (0 !== qos)
400
- pkt.pkt_id = rdr.u16();
401
-
402
- if (5 <= pkt.mqtt_level)
403
- pkt.props = rdr.props();
404
-
405
- pkt.payload = rdr.flush();
406
- return pkt }
407
- }
408
-
409
- function mqtt_decode_puback(ns, mqtt_reader) {
410
- return ns[0x4] = (pkt, u8_body) => {
411
- let rdr = mqtt_reader.of(u8_body);
412
-
413
- pkt.pkt_id = rdr.u16();
414
- if (5 <= pkt.mqtt_level) {
415
- pkt.reason = rdr.reason(pkt.type);
416
- pkt.props = rdr.props();
417
- }
418
-
419
- return pkt }
420
- }
421
-
422
-
423
- function _puback_v5(mqtt_reader) {
424
- mqtt_reader.reasons('puback',
425
- // MQTT 5.0
426
- [ 0x00, 'Success'],
427
- [ 0x10, 'No matching subscribers'],
428
- [ 0x80, 'Unspecified error'],
429
- [ 0x83, 'Implementation specific error'],
430
- [ 0x87, 'Not authorized'],
431
- [ 0x90, 'Topic Name invalid'],
432
- [ 0x91, 'Packet identifier in use'],
433
- [ 0x97, 'Quota exceeded'],
434
- [ 0x99, 'Payload format invalid'],
435
- );
436
- }
437
-
438
- function _mqtt_decode_suback(mqtt_reader) {
439
- return (pkt, u8_body) => {
440
- let rdr = mqtt_reader.of(u8_body);
441
-
442
- pkt.pkt_id = rdr.u16();
443
- if (5 <= pkt.mqtt_level)
444
- pkt.props = rdr.props();
445
-
446
- let answers = pkt.answers = [];
447
- while (rdr.has_more())
448
- answers.push(
449
- rdr.reason(pkt.type) );
450
-
451
- return pkt }
452
- }
453
-
454
- function mqtt_decode_suback(ns, mqtt_reader) {
455
- return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
456
- }
457
-
458
- function _suback_v4(mqtt_reader) {
459
- mqtt_reader.reasons('suback',
460
- // MQTT 3.1.1
461
- [ 0x00, 'Granted QoS 0'],
462
- [ 0x01, 'Granted QoS 1'],
463
- [ 0x02, 'Granted QoS 2'],
464
- );
465
- }
466
-
467
- function _suback_v5(mqtt_reader) {
468
- _suback_v4(mqtt_reader);
469
-
470
- mqtt_reader.reasons('suback',
471
- // MQTT 5.0
472
- [ 0x80, 'Unspecified error'],
473
- [ 0x83, 'Implementation specific error'],
474
- [ 0x87, 'Not authorized'],
475
- [ 0x8F, 'Topic Filter invalid'],
476
- [ 0x91, 'Packet Identifier in use'],
477
- [ 0x97, 'Quota exceeded'],
478
- [ 0x9E, 'Shared Subscriptions not supported'],
479
- [ 0xA1, 'Subscription Identifiers not supported'],
480
- [ 0xA2, 'Wildcard Subscriptions not supported'],
481
- );
482
- }
483
-
484
- function mqtt_decode_unsuback(ns, mqtt_reader) {
485
- return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
486
- }
487
-
488
- function _unsuback_v4(mqtt_reader) {
489
- mqtt_reader.reasons('unsuback',
490
- // MQTT 3.1.1
491
- [ 0x00, 'Success'],
492
- [ 0x11, 'No subscription existed'],
493
- [ 0x80, 'Unspecified error'],
494
- [ 0x83, 'Implementation specific error'],
495
- [ 0x87, 'Not authorized'],
496
- [ 0x8F, 'Topic Filter invalid'],
497
- [ 0x91, 'Packet Identifier in use'],
498
- );
499
- }
500
-
501
- function mqtt_decode_pingxxx(ns) {
502
- return ns[0xc] = ns[0xd] = pkt => pkt
503
- }
504
-
505
- function mqtt_decode_disconnect(ns, mqtt_reader) {
506
- return ns[0xe] = (pkt, u8_body) => {
507
- if (u8_body && 5 <= pkt.mqtt_level) {
508
- let rdr = mqtt_reader.of(u8_body);
509
- pkt.reason = rdr.reason(pkt.type);
510
- pkt.props = rdr.props();
511
- }
512
- return pkt }
513
- }
514
-
515
-
516
- function _disconnect_v5(mqtt_reader) {
517
- mqtt_reader.reasons('disconnect',
518
- // MQTT 5.0
519
- [ 0x00, 'Normal disconnection'],
520
- [ 0x04, 'Disconnect with Will Message'],
521
- [ 0x80, 'Unspecified error'],
522
- [ 0x81, 'Malformed Packet'],
523
- [ 0x82, 'Protocol Error'],
524
- [ 0x83, 'Implementation specific error'],
525
- [ 0x87, 'Not authorized'],
526
- [ 0x89, 'Server busy'],
527
- [ 0x8B, 'Server shutting down'],
528
- [ 0x8D, 'Keep Alive timeout'],
529
- [ 0x8E, 'Session taken over'],
530
- [ 0x8F, 'Topic Filter invalid'],
531
- [ 0x90, 'Topic Name invalid'],
532
- [ 0x93, 'Receive Maximum exceeded'],
533
- [ 0x94, 'Topic Alias invalid'],
534
- [ 0x95, 'Packet too large'],
535
- [ 0x96, 'Message rate too high'],
536
- [ 0x97, 'Quota exceeded'],
537
- [ 0x98, 'Administrative action'],
538
- [ 0x99, 'Payload format invalid'],
539
- [ 0x9A, 'Retain not supported'],
540
- [ 0x9B, 'QoS not supported'],
541
- [ 0x9C, 'Use another server'],
542
- [ 0x9D, 'Server moved'],
543
- [ 0x9E, 'Shared Subscriptions not supported'],
544
- [ 0x9F, 'Connection rate exceeded'],
545
- [ 0xA0, 'Maximum connect time'],
546
- [ 0xA1, 'Subscription Identifiers not supported'],
547
- [ 0xA2, 'Wildcard Subscriptions not supported'],
548
- );
549
- }
550
-
551
- function mqtt_decode_auth(ns, mqtt_reader) {
552
- return ns[0xf] = (pkt, u8_body) => {
553
- if ( 5 <= pkt.mqtt_level ) {
554
- let rdr = mqtt_reader.of(u8_body);
555
- pkt.reason = rdr.reason(pkt.type);
556
- pkt.props = rdr.props();
557
- }
558
- return pkt }
559
- }
560
-
561
-
562
- function _auth_v5(mqtt_reader) {
563
- mqtt_reader.reasons('auth',
564
- // MQTT 5.0
565
- [ 0x00, 'Success' ],
566
- [ 0x18, 'Continue authentication' ],
567
- [ 0x19, 'Re-authenticate' ],
568
- );
569
- }
570
-
571
379
  function mqtt_encode_connect(ns, mqtt_writer) {
572
380
  const _c_mqtt_proto = new Uint8Array([
573
381
  0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
@@ -586,7 +394,7 @@ function mqtt_encode_connect(ns, mqtt_writer) {
586
394
  | ( will.retain ? 0x20 : 0 );
587
395
 
588
396
  return ns.connect = ( mqtt_level, pkt ) => {
589
- let wrt = mqtt_writer.of(pkt);
397
+ let wrt = mqtt_writer.for(pkt);
590
398
 
591
399
  wrt.push(_c_mqtt_proto);
592
400
  wrt.u8( mqtt_level );
@@ -624,10 +432,27 @@ function mqtt_encode_connect(ns, mqtt_writer) {
624
432
  }
625
433
  }
626
434
 
435
+ function mqtt_decode_connack(ns, mqtt_reader) {
436
+ class _connack_flags_ extends Number {
437
+ get session_present() { return this & 0x01 !== 0 }
438
+ }
439
+
440
+ return ns[0x2] = (pkt, u8_body) => {
441
+ let rdr = mqtt_reader.for(pkt, u8_body);
442
+
443
+ pkt.flags =
444
+ rdr.flags(_connack_flags_);
445
+
446
+ pkt.reason = rdr.reason(pkt.type);
447
+ if (5 <= pkt.mqtt_level)
448
+ pkt.props = rdr.props();
449
+ return pkt }
450
+ }
451
+
627
452
  function mqtt_encode_publish(ns, mqtt_writer) {
628
453
  return ns.publish = ( mqtt_level, pkt ) => {
629
454
  let qos = (pkt.qos & 0x3) << 1;
630
- let wrt = mqtt_writer.of(pkt);
455
+ let wrt = mqtt_writer.for(pkt);
631
456
 
632
457
  wrt.utf8(pkt.topic);
633
458
  if (0 !== qos)
@@ -645,9 +470,28 @@ function mqtt_encode_publish(ns, mqtt_writer) {
645
470
  }
646
471
  }
647
472
 
473
+ function mqtt_decode_publish(ns, mqtt_reader) {
474
+ return ns[0x3] = (pkt, u8_body) => {
475
+ let {hdr} = pkt;
476
+ pkt.dup = Boolean(hdr & 0x8);
477
+ pkt.retain = Boolean(hdr & 0x1);
478
+ let qos = pkt.qos = (hdr>>1) & 0x3;
479
+
480
+ let rdr = mqtt_reader.for(pkt, u8_body);
481
+ pkt.topic = rdr.utf8();
482
+ if (0 !== qos)
483
+ pkt.pkt_id = rdr.u16();
484
+
485
+ if (5 <= pkt.mqtt_level)
486
+ pkt.props = rdr.props();
487
+
488
+ pkt.payload = rdr.flush();
489
+ return pkt }
490
+ }
491
+
648
492
  function mqtt_encode_puback(ns, mqtt_writer) {
649
493
  return ns.puback = ( mqtt_level, pkt ) => {
650
- let wrt = mqtt_writer.of(pkt);
494
+ let wrt = mqtt_writer.for(pkt);
651
495
 
652
496
  wrt.u16(pkt.pkt_id);
653
497
  if (5 <= mqtt_level) {
@@ -659,6 +503,20 @@ function mqtt_encode_puback(ns, mqtt_writer) {
659
503
  }
660
504
  }
661
505
 
506
+
507
+ function mqtt_decode_puback(ns, mqtt_reader) {
508
+ return ns[0x4] = (pkt, u8_body) => {
509
+ let rdr = mqtt_reader.for(pkt, u8_body);
510
+
511
+ pkt.pkt_id = rdr.u16();
512
+ if (5 <= pkt.mqtt_level) {
513
+ pkt.reason = rdr.reason(pkt.type);
514
+ pkt.props = rdr.props();
515
+ }
516
+
517
+ return pkt }
518
+ }
519
+
662
520
  function mqtt_encode_subscribe(ns, mqtt_writer) {
663
521
  const _enc_subscribe_flags = opts => 0
664
522
  | ( opts.qos & 0x3 )
@@ -666,7 +524,7 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
666
524
  | ( (opts.retain_handling & 0x3) << 2 );
667
525
 
668
526
  return ns.subscribe = ( mqtt_level, pkt ) => {
669
- let wrt = mqtt_writer.of(pkt);
527
+ let wrt = mqtt_writer.for(pkt);
670
528
 
671
529
  wrt.u16(pkt.pkt_id);
672
530
  if (5 <= mqtt_level)
@@ -692,9 +550,25 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
692
550
  }
693
551
  }
694
552
 
553
+ function mqtt_decode_xxsuback(ns, mqtt_reader) {
554
+ return ns[0x9] = ns[0xb] = (pkt, u8_body) => {
555
+ let rdr = mqtt_reader.for(pkt, u8_body);
556
+
557
+ pkt.pkt_id = rdr.u16();
558
+ if (5 <= pkt.mqtt_level)
559
+ pkt.props = rdr.props();
560
+
561
+ let answers = pkt.answers = [];
562
+ while (rdr.has_more())
563
+ answers.push(
564
+ rdr.reason(pkt.type) );
565
+
566
+ return pkt }
567
+ }
568
+
695
569
  function mqtt_encode_unsubscribe(ns, mqtt_writer) {
696
570
  return ns.unsubscribe = ( mqtt_level, pkt ) => {
697
- let wrt = mqtt_writer.of(pkt);
571
+ let wrt = mqtt_writer.for(pkt);
698
572
 
699
573
  wrt.u16(pkt.pkt_id);
700
574
  if (5 <= mqtt_level)
@@ -712,9 +586,14 @@ function mqtt_encode_pingxxx(ns) {
712
586
  ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
713
587
  }
714
588
 
589
+
590
+ function mqtt_decode_pingxxx(ns) {
591
+ return ns[0xc] = ns[0xd] = pkt => pkt
592
+ }
593
+
715
594
  function mqtt_encode_disconnect(ns, mqtt_writer) {
716
595
  return ns.disconnect = ( mqtt_level, pkt ) => {
717
- let wrt = mqtt_writer.of(pkt);
596
+ let wrt = mqtt_writer.for(pkt);
718
597
 
719
598
  if (pkt && 5 <= mqtt_level) {
720
599
  if (pkt.reason || pkt.props) {
@@ -727,6 +606,17 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
727
606
  }
728
607
  }
729
608
 
609
+
610
+ function mqtt_decode_disconnect(ns, mqtt_reader) {
611
+ return ns[0xe] = (pkt, u8_body) => {
612
+ if (u8_body && 5 <= pkt.mqtt_level) {
613
+ let rdr = mqtt_reader.for(pkt, u8_body);
614
+ pkt.reason = rdr.reason(pkt.type);
615
+ pkt.props = rdr.props();
616
+ }
617
+ return pkt }
618
+ }
619
+
730
620
  function mqtt_encode_auth(ns, mqtt_writer) {
731
621
  return ns.auth = ( mqtt_level, pkt ) => {
732
622
  if (5 > mqtt_level)
@@ -741,12 +631,21 @@ function mqtt_encode_auth(ns, mqtt_writer) {
741
631
  }
742
632
  }
743
633
 
634
+ function mqtt_decode_auth(ns, mqtt_reader) {
635
+ return ns[0xf] = (pkt, u8_body) => {
636
+ if ( 5 <= pkt.mqtt_level ) {
637
+ let rdr = mqtt_reader.of(u8_body);
638
+ pkt.reason = rdr.reason(pkt.type);
639
+ pkt.props = rdr.props();
640
+ }
641
+ return pkt }
642
+ }
643
+
744
644
  const mqtt_decode_v5 = [
745
645
  mqtt_decode_connack,
746
646
  mqtt_decode_publish,
747
647
  mqtt_decode_puback,
748
- mqtt_decode_suback,
749
- mqtt_decode_unsuback,
648
+ mqtt_decode_xxsuback,
750
649
  mqtt_decode_pingxxx,
751
650
  mqtt_decode_disconnect,
752
651
  mqtt_decode_auth,
@@ -764,18 +663,6 @@ const mqtt_encode_v5 = [
764
663
  mqtt_encode_auth,
765
664
  ];
766
665
 
767
- const mqtt_reader_v5 = /* #__PURE__ */
768
- mqtt_reader_info(
769
- mqtt_reader_v5$1,
770
- _connack_v5,
771
- _puback_v5,
772
- _suback_v5,
773
- _unsuback_v4,
774
- _disconnect_v5,
775
- _auth_v5,
776
- );
777
-
778
-
779
666
  const mqtt_opts_v5 =
780
667
  { decode_fns: mqtt_decode_v5,
781
668
  mqtt_reader: mqtt_reader_v5,
@@ -867,7 +754,10 @@ const with_topic_router = mqtt_topic_router =>
867
754
  // alias: unsub_topic
868
755
  unsubscribe_topic(topic_route, ...args) {
869
756
  let router = this.router;
870
- router.remove(topic_route, true);
757
+
758
+ let fn = args.at(-1)?.call ? args.pop() : null;
759
+ router.remove(topic_route, true, fn);
760
+
871
761
  let topic = router.mqtt_topic(topic_route);
872
762
  return this.unsubscribe(topic, ...args ) }// topic_prefix
873
763
 
@@ -920,34 +810,38 @@ function mqtt_topic_path_router() {
920
810
  if (fn) {throw new TypeError()}
921
811
  fn = _ignore;}
922
812
 
923
- let rte = parse(as_topic_path(topic_route));
924
-
925
- rte.key = topic_route;
926
- rte.tgt = fn;
927
- pri_lsts[priority ? 0 : 1].push(rte);
813
+ let route = parse(as_topic_path(topic_route));
814
+ route.topic = topic_route;
815
+ route.tgt = fn;
816
+ pri_lsts[priority ? 0 : 1].push(route);
928
817
  return this}
929
818
 
930
- , remove(topic_route, priority) {
931
- let lst = pri_lsts[priority ? 0 : 1];
932
- return _route_remove([lst], topic_route)}
819
+ , remove(query, ...args) {
820
+ let lst = pri_lsts;
821
+ if ('boolean' === typeof args[0]) {
822
+ lst = [pri_lsts[args.shift() ? 0 : 1]];}
823
+
824
+ if ('string' === typeof query) {
825
+ query ={topic: query, tgt: args.pop()}; }
826
+ return _route_remove(lst, query)}
933
827
 
934
828
  , clear(priority) {
935
- pri_lsts[priority ? 0 : 1] = [];
936
829
  if (null == priority) {
937
- pri_lsts[1] = []; } }// null clears both lists
830
+ pri_lsts = [[],[]]; }// null clears both lists
831
+ else {
832
+ pri_lsts[priority ? 0 : 1] = [];} }
938
833
 
939
834
  , async invoke(pkt, ctx) {
940
835
  ctx.idx = 0;
941
836
  ctx.rm = rm;
942
837
 
943
- for (let [fn, params] of find(pkt.topic)) {
838
+ for (let [fn, params, route] of find(pkt.topic)) {
944
839
  let res = await fn(pkt, params, ctx);
945
840
 
946
841
  if (rm === res) {
947
- _route_remove(pri_lsts, fn);}
842
+ _route_remove(pri_lsts, route);}
948
843
 
949
- if (ctx.done) {
950
- break}
844
+ if (ctx.done) {break}
951
845
  else ctx.idx++;}
952
846
 
953
847
  if (1 === pkt.qos) {
@@ -957,70 +851,68 @@ function mqtt_topic_path_router() {
957
851
  function * _routes_iter(all_route_lists, topic) {
958
852
  topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
959
853
  for (let route_list of all_route_lists) {
960
- for (let {keys, pattern, tgt} of route_list) {
961
- let match = pattern.exec(topic);
854
+ for (let route of route_list) {
855
+ let match = route.pattern.exec(topic);
962
856
  if (match) {
963
- let params = keys
964
- ? keys.reduce(
857
+ let params = route.keys
858
+ ? route.keys.reduce(
965
859
  (o, k, i) => (o[k] = match[1+i], o)
966
860
  , {})
967
861
  : match.groups ?? match;
968
- yield [tgt, params];} } } }
862
+ yield [route.tgt, params, route];} } } }
969
863
 
970
864
 
971
865
  function _route_remove(all_route_lists, query) {
972
- let fn_match = route =>(
973
- route===query
974
- || route.tgt===query
975
- || route.key===query);
866
+ let ans = false;
976
867
  for (let lst of all_route_lists) {
977
- let i = lst.findIndex(fn_match);
978
- if (0 <= i) {
979
- lst.splice(i,1);
980
- return true} }
981
- return false}
982
-
983
- /*
984
- export function decode_varint_loop(u8, i=0) {
985
- let i0 = i
986
- let shift = 0, n = (u8[i] & 0x7f)
987
- while ( 0x80 & u8[i++] )
988
- n |= (u8[i] & 0x7f) << (shift += 7)
989
-
990
- return [n, i, i0]
991
- }
992
- */
993
-
994
-
995
- function decode_varint(u8, i=0) {
996
- let i0 = i;
997
- // unrolled for a max of 4 chains
998
- let n = (u8[i] & 0x7f) << 0;
999
- if ( 0x80 & u8[i++] ) {
1000
- n |= (u8[i] & 0x7f) << 7;
1001
- if ( 0x80 & u8[i++] ) {
1002
- n |= (u8[i] & 0x7f) << 14;
1003
- if ( 0x80 & u8[i++] ) {
1004
- n |= (u8[i] & 0x7f) << 21;
1005
- }
1006
- }
1007
- }
1008
- return [n, i, i0]
868
+ let idx_tip = 0;
869
+ for (let route of lst) {
870
+ // skip matching routes to remove from compacted list
871
+ if (route === query) continue
872
+ if (route.topic === query.topic) {
873
+ if (null == query.tgt) continue
874
+ if (route.tgt === query.tgt) continue}
875
+
876
+ lst[idx_tip++] = route;}
877
+
878
+ // truncate remaining list
879
+ if (lst.splice(idx_tip).length)
880
+ ans = true;}
881
+
882
+ return ans}
883
+
884
+ function decode_varint(u8, i0=0, invalid) {
885
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
886
+ for(; b & 0x80;)
887
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
888
+
889
+ return (u8.length < i)
890
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
891
+ : [n, i, i0] // successful value
1009
892
  }
1010
893
 
1011
894
  function mqtt_raw_dispatch(opt) {
1012
- let u8 = new Uint8Array(0);
895
+ let u8 = new Uint8Array(0), len_tip=0;
1013
896
  return u8_buf => {
1014
897
  u8 = 0 === u8.byteLength
1015
898
  ? u8_buf : _u8_join(u8, u8_buf);
1016
899
 
1017
900
  let res = [];
1018
- while (1) {
1019
- let [len_body, len_vh] = decode_varint(u8, 1);
1020
- let len_pkt = len_body + len_vh;
1021
901
 
1022
- if ( u8.byteLength < len_pkt )
1023
- return res
902
+ // wait for at least len_tip bytes for next (tip) message
903
+ while ( u8.byteLength >= len_tip ) {
904
+
905
+ // if varint is incomplete, return len_body=NaN
906
+ let [len_body, len_vh] = decode_varint(u8, 1, NaN);
907
+ let len_pkt = len_body + len_vh; // may be NaN
908
+
909
+ if (!( len_pkt <= u8.byteLength )) {
910
+ // incomplete packet cases:
911
+ // - len_pkt is less than available bytes
912
+ // - len_pkt is NaN from decode_varint() due to lack of data
913
+ len_tip = len_pkt || 0; // 0 when NaN
914
+ break
915
+ }
1024
916
 
1025
917
  let b0 = u8[0];
1026
918
  let u8_body = 0 === len_body ? null
@@ -1032,6 +924,8 @@ function mqtt_raw_dispatch(opt) {
1032
924
  if (null != pkt)
1033
925
  res.push( pkt );
1034
926
  }
927
+
928
+ return res
1035
929
  }
1036
930
  }
1037
931
 
@@ -1042,16 +936,17 @@ function _u8_join(a, b) {
1042
936
  return r
1043
937
  }
1044
938
 
1045
- const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
939
+ const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
940
+
941
+
942
+ function mqtt_pkt_ctx(mqtt_level, opts, pkt_api=opts.pkt_ctx) {
943
+ let _as_pkt_ctx = pkt_api => ({
944
+ __proto__: pkt_api,
945
+ get hdr() { return this.b0 & 0xf },
946
+ get id() { return this.b0 >>> 4 },
947
+ get type() { return _pkt_types[this.b0 >>> 4] },
948
+ mqtt_level });
1046
949
 
1047
- function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1048
- pkt_ctx = {
1049
- __proto__: pkt_ctx || opts.pkt_ctx,
1050
- mqtt_level,
1051
- get hdr() { return this.b0 & 0xf },
1052
- get id() { return this.b0 >>> 4 },
1053
- get type() { return _pkt_types[this.b0 >>> 4] },
1054
- };
1055
950
 
1056
951
  let op, _decode_by_id=[], _encode_by_type={};
1057
952
  for (op of opts.encode_fns)
@@ -1060,10 +955,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1060
955
  op(_decode_by_id, opts.mqtt_reader);
1061
956
 
1062
957
  return {
1063
- pkt_ctx,
958
+ pkt_api, pkt_ctx: _as_pkt_ctx(pkt_api),
1064
959
 
1065
- encode_pkt(type, pkt) {
1066
- return _encode_by_type[type]( mqtt_level, pkt ) },
960
+ encode_pkt: (type, pkt) =>
961
+ _encode_by_type[type]( mqtt_level, pkt ),
1067
962
 
1068
963
  decode_pkt(b0, u8_body) {
1069
964
  if (b0.map) // Uint8Array in first arg
@@ -1072,12 +967,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1072
967
  let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
1073
968
  return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
1074
969
 
1075
- mqtt_stream() {
1076
- let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
1077
- self.pkt_ctx._base_ = self.pkt_ctx;
970
+ mqtt_stream(pkt_api=this.pkt_api) {
971
+ let self = { __proto__: this, pkt_ctx: _as_pkt_ctx(pkt_api) };
1078
972
  self.decode = mqtt_raw_dispatch(self);
1079
- return self
1080
- },
973
+ return self },
1081
974
  }
1082
975
  }
1083
976
 
@@ -1601,7 +1494,7 @@ class MQTTCore extends MQTTBase {
1601
1494
 
1602
1495
  return this} }
1603
1496
 
1604
- const version = '0.6.2-node';
1497
+ const version = '0.6.4-node';
1605
1498
 
1606
1499
  const MQTTClient_v4 = /* #__PURE__ */
1607
1500
  with_topic_path_router(