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