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