u8-mqtt 0.4.1 → 0.5.0

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 (81) hide show
  1. package/cjs/basic-v4.cjs +103 -137
  2. package/cjs/basic-v4.cjs.map +1 -1
  3. package/cjs/basic-v5.cjs +102 -136
  4. package/cjs/basic-v5.cjs.map +1 -1
  5. package/cjs/index.cjs +144 -189
  6. package/cjs/index.cjs.map +1 -1
  7. package/cjs/v4.cjs +145 -190
  8. package/cjs/v4.cjs.map +1 -1
  9. package/cjs/v5.cjs +144 -189
  10. package/cjs/v5.cjs.map +1 -1
  11. package/code/_dispatch.jsy +16 -0
  12. package/code/base.jsy +68 -124
  13. package/code/core.jsy +15 -9
  14. package/code/router_path.jsy +24 -43
  15. package/code/with_topic_router.jsy +18 -10
  16. package/esm/basic-v4.js +1154 -0
  17. package/esm/basic-v4.js.map +1 -0
  18. package/esm/basic-v5.js +1416 -0
  19. package/esm/basic-v5.js.map +1 -0
  20. package/esm/deno/basic-v4.js +103 -137
  21. package/esm/deno/basic-v4.js.map +1 -1
  22. package/esm/deno/basic-v5.js +102 -136
  23. package/esm/deno/basic-v5.js.map +1 -1
  24. package/esm/deno/index.js +144 -189
  25. package/esm/deno/index.js.map +1 -1
  26. package/esm/deno/v4.js +145 -190
  27. package/esm/deno/v4.js.map +1 -1
  28. package/esm/deno/v5.js +144 -189
  29. package/esm/deno/v5.js.map +1 -1
  30. package/esm/index.js +1599 -0
  31. package/esm/index.js.map +1 -0
  32. package/esm/node/basic-v4.js +103 -137
  33. package/esm/node/basic-v4.js.map +1 -1
  34. package/esm/node/basic-v4.mjs +103 -137
  35. package/esm/node/basic-v4.mjs.map +1 -1
  36. package/esm/node/basic-v5.js +102 -136
  37. package/esm/node/basic-v5.js.map +1 -1
  38. package/esm/node/basic-v5.mjs +102 -136
  39. package/esm/node/basic-v5.mjs.map +1 -1
  40. package/esm/node/index.js +144 -189
  41. package/esm/node/index.js.map +1 -1
  42. package/esm/node/index.mjs +144 -189
  43. package/esm/node/index.mjs.map +1 -1
  44. package/esm/node/v4.js +145 -190
  45. package/esm/node/v4.js.map +1 -1
  46. package/esm/node/v4.mjs +145 -190
  47. package/esm/node/v4.mjs.map +1 -1
  48. package/esm/node/v5.js +144 -189
  49. package/esm/node/v5.js.map +1 -1
  50. package/esm/node/v5.mjs +144 -189
  51. package/esm/node/v5.mjs.map +1 -1
  52. package/esm/v4.js +1336 -0
  53. package/esm/v4.js.map +1 -0
  54. package/esm/v5.js +1599 -0
  55. package/esm/v5.js.map +1 -0
  56. package/esm/web/basic-v4.js +103 -137
  57. package/esm/web/basic-v4.js.map +1 -1
  58. package/esm/web/basic-v4.min.js +1 -1
  59. package/esm/web/basic-v4.min.js.br +0 -0
  60. package/esm/web/basic-v4.min.js.gz +0 -0
  61. package/esm/web/basic-v5.js +102 -136
  62. package/esm/web/basic-v5.js.map +1 -1
  63. package/esm/web/basic-v5.min.js +1 -1
  64. package/esm/web/basic-v5.min.js.br +0 -0
  65. package/esm/web/basic-v5.min.js.gz +0 -0
  66. package/esm/web/index.js +144 -189
  67. package/esm/web/index.js.map +1 -1
  68. package/esm/web/index.min.js +1 -1
  69. package/esm/web/index.min.js.br +0 -0
  70. package/esm/web/index.min.js.gz +0 -0
  71. package/esm/web/v4.js +145 -190
  72. package/esm/web/v4.js.map +1 -1
  73. package/esm/web/v4.min.js +1 -1
  74. package/esm/web/v4.min.js.br +0 -0
  75. package/esm/web/v4.min.js.gz +0 -0
  76. package/esm/web/v5.js +144 -189
  77. package/esm/web/v5.js.map +1 -1
  78. package/esm/web/v5.min.js +1 -1
  79. package/esm/web/v5.min.js.br +0 -0
  80. package/esm/web/v5.min.js.gz +0 -0
  81. package/package.json +7 -8
package/cjs/v4.cjs CHANGED
@@ -51,7 +51,7 @@ class U8_Reason extends Number {
51
51
  }
52
52
  }
53
53
 
54
- class mqtt_reader_v4$1 {
54
+ let mqtt_reader_v4$1 = class mqtt_reader_v4 {
55
55
  static of(buf) { return this.prototype.of(buf) }
56
56
  of(buf) {
57
57
  let step = (width, k) => (k=0|step.k, step.k=k+width, k);
@@ -107,7 +107,7 @@ class mqtt_reader_v4$1 {
107
107
  return buf.subarray(step.k|0)
108
108
  }
109
109
 
110
- }
110
+ };
111
111
 
112
112
  function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
113
113
  mqtt_reader = class extends mqtt_reader {
@@ -482,7 +482,7 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
482
482
  }
483
483
  }
484
484
 
485
- // not a v4 packet: import { mqtt_encode_auth } from './encode/auth.mjs'
485
+ // not a v4 packet: import { mqtt_encode_auth } from './encode/auth.js'
486
486
 
487
487
 
488
488
  const mqtt_decode_v4 = [
@@ -563,31 +563,39 @@ const with_topic_router = mqtt_topic_router =>
563
563
  return super._aliases() +
564
564
  ' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'}
565
565
 
566
- _init_router(opt, client, target) {
566
+ _init_router(opt, self, target) {
567
+ this._subs = [];
567
568
  let router = this.router = target.router =
568
- mqtt_topic_router(opt, this);
569
+ mqtt_topic_router(opt, this, target);
569
570
  return router?.invoke}
570
- get on_topic() {return this.router.add}
571
571
 
572
- _sub_chain(topic, ex, topic_prefix) {
573
- let res = this.subscribe([[ topic ]], ex, topic_prefix);
574
- let subs = this.subs ||(this.subs = new Map());
575
- subs.set((res.topic = topic), (subs.last = res));
576
- return this }// fluent api -- return this and track side effects
572
+ on_sub(suback, pkt) {
573
+ suback.pkt = pkt;
574
+ this._subs.push(suback);
575
+ return suback}
576
+ subs_settled() {
577
+ return Promise.allSettled(
578
+ this._subs.splice(0,Infinity)) }
577
579
 
578
580
  // alias: sub_topic
579
581
  subscribe_topic(topic_route, ...args) {
580
582
  let router = this.router;
581
583
  router.add(topic_route, true, args.pop() );// handler
582
584
  let topic = router.mqtt_topic(topic_route);
583
- return this._sub_chain(topic, ...args ) }// ex, topic_prefix
585
+ this.subscribe(topic, ...args );// ex, topic_prefix
586
+ return this }// fluent api -- return this and track side effects
584
587
 
585
588
  // alias: unsub_topic
586
589
  unsubscribe_topic(topic_route, ...args) {
587
590
  let router = this.router;
588
591
  router.remove(topic_route, true);
589
592
  let topic = router.mqtt_topic(topic_route);
590
- return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
593
+ return this.unsubscribe(topic, ...args ) }// topic_prefix
594
+
595
+ // add topic handlers without corresponding subscribe packet
596
+ on_topic(...args) {
597
+ this.router.add(...args);
598
+ return this} };
591
599
 
592
600
  // Use [regexparam][] for url-like topic parsing
593
601
  // [regexparam]: https://github.com/lukeed/regexparam
@@ -600,7 +608,7 @@ const with_topic_path_router = /* #__PURE__ */
600
608
  const mqtt_topic = topic_route =>
601
609
  topic_route
602
610
  .replace(/[*].*$/, '#')
603
- .replace(/:\w+\??/g, '+');
611
+ .replace(/:\w[^\/]*/g, '+');
604
612
 
605
613
  /* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
606
614
  4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
@@ -630,9 +638,8 @@ function mqtt_topic_path_router() {
630
638
  let priority = args.pop();
631
639
 
632
640
  if ('function' !== typeof fn) {
633
- if (false === fn) {
634
- fn = _ignore;}
635
- else throw new TypeError()}
641
+ if (fn) {throw new TypeError()}
642
+ fn = _ignore;}
636
643
 
637
644
  let rte = parse(as_topic_path(topic_route));
638
645
 
@@ -648,7 +655,7 @@ function mqtt_topic_path_router() {
648
655
  , clear(priority) {
649
656
  pri_lsts[priority ? 0 : 1] = [];
650
657
  if (null == priority) {
651
- pri_lsts[1] = [];} }
658
+ pri_lsts[1] = []; } }// null clears both lists
652
659
 
653
660
  , async invoke(pkt, ctx) {
654
661
  ctx.idx = 0;
@@ -664,52 +671,34 @@ function mqtt_topic_path_router() {
664
671
  break}
665
672
  else ctx.idx++;}
666
673
 
667
- let {pkt_id, qos} = pkt;
668
- if (1 === qos) {
669
- await ctx.mqtt._send('puback', {pkt_id});} } } }
674
+ if (1 === pkt.qos) {
675
+ await ctx.mqtt.puback(pkt);} } } }
670
676
 
671
677
 
672
678
  function * _routes_iter(all_route_lists, topic) {
679
+ topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
673
680
  for (let route_list of all_route_lists) {
674
- for (let route of route_list) {
675
- let res = _route_match_one(topic, route);
676
- if (undefined !== res) {
677
- yield res;} } } }
678
-
679
-
680
- function _route_match_one(topic, {keys, pattern, tgt}) {
681
- let match = '/' !== topic[0]
682
- ? pattern.exec('/'+topic)
683
- : pattern.exec(topic);
684
-
685
- if (null === match) {
686
- return}
687
-
688
- if (false === keys) {
689
- let {groups} = match;
690
- if (! groups) {
691
- return [tgt]}
692
-
693
- let params = {};
694
- for (let k in groups) {
695
- params[k] = groups[k];}
696
-
697
- return [tgt, params]}
698
-
699
- if (0 === keys.length) {
700
- return [tgt]}
701
-
702
- let params = {};
703
- for (let i=0; i<keys.length; i++) {
704
- params[ keys[i] ] = match[1+i];}
705
- return [tgt, params]}
681
+ for (let {keys, pattern, tgt} of route_list) {
682
+ let match = pattern.exec(topic);
683
+ if (match) {
684
+ let params = keys
685
+ ? keys.reduce(
686
+ (o, k, i) => (o[k] = match[1+i], o)
687
+ , {})
688
+ : match.groups ?? match;
689
+ yield [tgt, params];} } } }
706
690
 
707
691
 
708
692
  function _route_remove(all_route_lists, query) {
709
- let match = route => route===query || route.tgt===query || route.key===query;
693
+ let fn_match = route =>(
694
+ route===query
695
+ || route.tgt===query
696
+ || route.key===query);
710
697
  for (let lst of all_route_lists) {
711
- let i = lst.findIndex(match);
712
- if (0 <= i) {return !! lst.splice(i,1)} }
698
+ let i = lst.findIndex(fn_match);
699
+ if (0 <= i) {
700
+ lst.splice(i,1);
701
+ return true} }
713
702
  return false}
714
703
 
715
704
  /*
@@ -970,6 +959,22 @@ const _mqtt_cmdid_dispatch ={
970
959
 
971
960
  await fn?.call(target, pkt, ctx);} })()) };
972
961
 
962
+ /*
963
+ on_mqtt_type = {
964
+ mqtt_auth(pkt, ctx) ::
965
+ mqtt_connect(pkt, ctx) ::
966
+ mqtt_connack(pkt, ctx) ::
967
+ mqtt_disconnect(pkt, ctx) ::
968
+
969
+ mqtt_publish(pkt, ctx)
970
+ mqtt_subscribe(pkt, ctx) ::
971
+ mqtt_unsubscribe(pkt, ctx) ::
972
+
973
+ mqtt_pingreq(pkt, ctx) ::
974
+ mqtt_pingresp(pkt, ctx) ::
975
+ }
976
+ */
977
+
973
978
  function _mqtt_dispatch(opt, target) {
974
979
  let _disp_ = _mqtt_cmdid_dispatch.create(target);
975
980
  let { cmdids } = _disp_;
@@ -999,28 +1004,34 @@ class MQTTError extends Error {
999
1004
 
1000
1005
  class MQTTBase {
1001
1006
  constructor(opt={}) {
1007
+ this.with(opt);
1002
1008
  this._conn_ = _mqtt_conn(this,
1003
1009
  this._init_dispatch(opt, this)); }
1004
1010
 
1011
+ with(fns_ns) {
1012
+ for (let [k,v] of Object.entries(fns_ns)) {
1013
+ if ('function' === typeof v) {this[k] = v;} }
1014
+ return this}
1015
+
1005
1016
  async conn_emit(evt, arg, err_arg) {
1006
1017
  this.log_conn?.(evt, arg, err_arg);
1007
1018
  try {
1008
- let fn_evt = this[await evt]; // microtask break
1019
+ let fn_evt = this[await evt]; // microtask break using `await evt`
1009
1020
  if (fn_evt) {
1010
1021
  await fn_evt.call(this, this, arg, err_arg);}
1011
- else if (err_arg) {
1012
- await this.on_error(err_arg, evt);} }
1022
+ else if (err_arg) {throw err_arg} }
1013
1023
  catch (err) {
1014
1024
  this.on_error(err, evt);} }
1015
1025
 
1016
- on_error(err, err_path) {
1017
- console.warn('[[u8-mqtt error: %s]]', err_path, err); }
1026
+ on_error(err, evt) {
1027
+ console.warn('[[u8-mqtt error: %s]]', evt, err); }
1018
1028
 
1019
1029
  // Handshaking Packets
1020
1030
 
1021
1031
  async connect(pkt={}) {
1022
- let cid = pkt.client_id || ['u8-mqtt--', ''];
1023
- if (Array.isArray(cid)) {
1032
+ let cid = pkt.client_id || this.client_id;
1033
+ if ('string' !== typeof cid) {
1034
+ // see init_client_id implementation in core.jsy
1024
1035
  pkt.client_id = cid = this.init_client_id(cid);}
1025
1036
  this.client_id = cid;
1026
1037
 
@@ -1046,12 +1057,13 @@ class MQTTBase {
1046
1057
  return this._send('auth', pkt, 'auth')}
1047
1058
 
1048
1059
  ping() {return this._send('pingreq', null, 'pingresp')}
1049
-
1060
+ puback({pkt_id}) {return this._send('puback', {pkt_id})}
1050
1061
 
1051
1062
  // alias: sub
1052
1063
  subscribe(pkt, ex, topic_prefix) {
1053
1064
  pkt = _as_topics(pkt, ex, topic_prefix);
1054
- return this._send('subscribe', pkt, pkt)}
1065
+ let suback = this._send('subscribe', pkt, pkt);
1066
+ return this.on_sub?.(suback, pkt) ?? suback}
1055
1067
 
1056
1068
  // alias: unsub
1057
1069
  unsubscribe(pkt, ex, topic_prefix) {
@@ -1059,48 +1071,52 @@ class MQTTBase {
1059
1071
  return this._send('unsubscribe', pkt, pkt)}
1060
1072
 
1061
1073
 
1062
- // alias: pub
1063
- publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
1064
- post(topic, payload, pub_opt) {return _pub.m(this, topic, payload, pub_opt)}
1065
- send(topic, payload, pub_opt) {return _pub.mq(this, topic, payload, pub_opt)}
1066
- store(topic, payload, pub_opt) {return _pub.mqr(this, topic, payload, pub_opt)}
1067
-
1068
- json_post(topic, msg, pub_opt) {return _pub.o(this, topic, msg, pub_opt)}
1069
- json_send(topic, msg, pub_opt) {return _pub.oq(this, topic, msg, pub_opt)}
1070
- json_store(topic, msg, pub_opt) {return _pub.oqr(this, topic, msg, pub_opt)}
1071
-
1072
- obj_post(topic, msg, pub_opt) {return _pub.o(this, topic, msg, pub_opt)}
1073
- obj_send(topic, msg, pub_opt) {return _pub.oq(this, topic, msg, pub_opt)}
1074
- obj_store(topic, msg, pub_opt) {return _pub.oqr(this, topic, msg, pub_opt)}
1075
-
1076
-
1077
-
1078
- // Utility Methods
1079
-
1080
- init_client_id(parts) {
1081
- let cid = this.client_id;
1082
-
1083
- if (undefined === cid) {
1084
- this.client_id = cid = (
1085
-
1086
-
1087
-
1088
- this.new_client_id(parts)
1089
- );}
1090
-
1091
- return cid}
1092
-
1093
- new_client_id(parts) {
1094
- return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
1095
-
1096
-
1097
-
1098
-
1099
-
1100
-
1101
-
1102
-
1103
-
1074
+ post(topic, payload, pub_opt) {// qos:0
1075
+ return this.pub({topic, payload, qos:0}, pub_opt)}
1076
+ send(topic, payload, pub_opt) {// qos:1
1077
+ return this.pub({topic, payload, qos:1}, pub_opt)}
1078
+ store(topic, payload, pub_opt) {// qos:1, retain: 1
1079
+ return this.pub({topic, payload, qos:1, retain: 1}, pub_opt)}
1080
+
1081
+ // alias: json_post
1082
+ obj_post(topic, msg, pub_opt) {// qos:0
1083
+ return this.pub({topic, msg, arg: 'msg', qos:0}, pub_opt)}
1084
+ // alias: json_send
1085
+ obj_send(topic, msg, pub_opt) {// qos:1
1086
+ return this.pub({topic, msg, arg: 'msg', qos:1}, pub_opt)}
1087
+ // alias: json_store
1088
+ obj_store(topic, msg, pub_opt) {// qos:1, retain: 1
1089
+ return this.pub({topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)}
1090
+
1091
+ // alias: publish -- because 'pub' is shorter for semantic aliases above
1092
+ async pub(pkt, pub_opt) {
1093
+ if (undefined === pkt.payload) {
1094
+ if ('function' === typeof pub_opt) {
1095
+ pub_opt = {fn_encode: pub_opt};}
1096
+
1097
+ let {msg} = pkt;
1098
+ switch (typeof msg) {
1099
+ case 'function':
1100
+ pub_opt = {...pub_opt, fn_encode: msg};
1101
+ // flow into 'undefined' case
1102
+ case 'undefined':
1103
+ // return a single-value closure to publish packets
1104
+ return v => this.pub({...pkt, [pkt.arg || 'payload']: v}, pub_opt)}
1105
+
1106
+ // Encode payload from msg; fn_encode allows alternative to JSON.stringify
1107
+ let {fn_encode} = pub_opt || {};
1108
+ pkt.payload = fn_encode
1109
+ ? await fn_encode(msg)
1110
+ : JSON.stringify(msg);}
1111
+
1112
+ if (pub_opt) {
1113
+ if (pub_opt.props) {
1114
+ pkt.props = pub_opt.props;}
1115
+ if (pub_opt.xform) {
1116
+ pkt = pub_opt.xform(pkt) || pkt;} }
1117
+
1118
+ return this._send('publish', pkt,
1119
+ pkt.qos ? pkt : void 0 ) }// key
1104
1120
 
1105
1121
 
1106
1122
  // Internal API
@@ -1115,41 +1131,18 @@ class MQTTBase {
1115
1131
  return _mqtt_dispatch(this, target)}
1116
1132
 
1117
1133
  static _aliases() {
1118
- return ' pub:publish sub:subscribe unsub:unsubscribe '}
1134
+ return ' publish:pub sub:subscribe unsub:unsubscribe json_post:obj_post json_send:obj_send json_store:obj_store'}
1119
1135
 
1120
1136
  static _once_(self=this) {
1121
1137
  self._once_ = _=>0;
1122
- self.MQTTError = MQTTError;
1123
1138
  let p = self.prototype;
1139
+ p.MQTTError = MQTTError;
1124
1140
  for (let alias of self._aliases().split(/\s+/)) {
1125
1141
  alias = alias.split(':');
1126
1142
  let fn = alias[1] && p[alias[1]];
1127
1143
  if (fn) {p[alias[0]] = fn;} } } }
1128
1144
 
1129
1145
 
1130
- /*
1131
- on_mqtt_type = {
1132
- mqtt_auth(pkt, ctx) ::
1133
- mqtt_connect(pkt, ctx) ::
1134
- mqtt_connack(pkt, ctx) ::
1135
- mqtt_disconnect(pkt, ctx) ::
1136
-
1137
- mqtt_publish(pkt, ctx)
1138
- mqtt_subscribe(pkt, ctx) ::
1139
- mqtt_unsubscribe(pkt, ctx) ::
1140
-
1141
- mqtt_pingreq(pkt, ctx) ::
1142
- mqtt_pingresp(pkt, ctx) ::
1143
- }
1144
- */
1145
-
1146
-
1147
- const _prefix_topics = (topic_prefix, iterable) =>
1148
- Array.from(iterable, value =>(
1149
- value.trim // string
1150
- ? _prefix_topics(topic_prefix, value)
1151
- : topic_prefix + value) );
1152
-
1153
1146
  function _as_topics(pkt, ex, topic_prefix) {
1154
1147
  if (ex?.trim) {// string
1155
1148
  topic_prefix = ex;
@@ -1166,55 +1159,11 @@ function _as_topics(pkt, ex, topic_prefix) {
1166
1159
  if (topic_prefix) {
1167
1160
  // particularly useful with shared queues, e.g.
1168
1161
  // topic_prefix = '$share/some-queue-name/'
1169
- pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
1170
- return pkt}
1162
+ let _prefix_topics = v =>
1163
+ v.trim ? topic_prefix+v : v.map(_prefix_topics);
1171
1164
 
1172
-
1173
- async function _pub(self, pkt, pub_opt) {
1174
- if (undefined === pkt.payload) {
1175
- if ('function' === typeof pub_opt) {
1176
- pub_opt = {fn_encode: pub_opt};}
1177
-
1178
- let {msg} = pkt;
1179
- switch (typeof msg) {
1180
- case 'function':
1181
- pub_opt = {...pub_opt, fn_encode: msg};
1182
- // flow into 'undefined' case
1183
- case 'undefined':
1184
- // return a single-value closure to publish packets
1185
- return v => _pub(self, {...pkt, [pkt.arg || 'payload']: v}, pub_opt)
1186
-
1187
- default:
1188
- // Encode payload from msg; fn_encode allows alternative to JSON.stringify
1189
- let {fn_encode} = pub_opt || {};
1190
- pkt.payload = fn_encode
1191
- ? await fn_encode(msg)
1192
- : JSON.stringify(msg);} }
1193
-
1194
- if (pub_opt) {
1195
- if (pub_opt.props) {
1196
- pkt.props = pub_opt.props;}
1197
- if (pub_opt.xform) {
1198
- pkt = pub_opt.xform(pkt) || pkt;} }
1199
-
1200
- return self._send('publish', pkt,
1201
- pkt.qos ? pkt : void 0 ) }// key
1202
-
1203
- {
1204
- Object.assign(_pub,{
1205
- m: (self, topic, payload, pub_opt) =>
1206
- _pub(self, {topic, payload, qos:0}, pub_opt)
1207
- , mq: (self, topic, payload, pub_opt) =>
1208
- _pub(self, {topic, payload, qos:1}, pub_opt)
1209
- , mqr: (self, topic, payload, pub_opt) =>
1210
- _pub(self, {topic, payload, qos:1, retain: 1}, pub_opt)
1211
-
1212
- , o: (self, topic, msg, pub_opt) =>
1213
- _pub(self, {topic, msg, arg: 'msg', qos:0}, pub_opt)
1214
- , oq: (self, topic, msg, pub_opt) =>
1215
- _pub(self, {topic, msg, arg: 'msg', qos:1}, pub_opt)
1216
- , oqr: (self, topic, msg, pub_opt) =>
1217
- _pub(self, {topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)} ); }
1165
+ pkt.topics = pkt.topics.map(_prefix_topics);}
1166
+ return pkt}
1218
1167
 
1219
1168
  const pkt_api = {
1220
1169
  utf8(u8) { return new TextDecoder('utf-8').decode(u8 || this.payload ) },
@@ -1223,20 +1172,27 @@ const pkt_api = {
1223
1172
  };
1224
1173
 
1225
1174
  class MQTTCore extends MQTTBase {
1226
- constructor(opt={}) {
1227
- super(opt);
1228
- this.with(opt);}
1229
-
1230
1175
  static mqtt_ctx(mqtt_level, mqtt_opts, pkt_ctx=pkt_api) {
1231
1176
  let self = class extends this {};
1232
1177
  self.prototype.mqtt_ctx =
1233
1178
  mqtt_pkt_ctx(mqtt_level, mqtt_opts, pkt_ctx);
1234
1179
  return self}
1235
1180
 
1236
- with(fns_ns) {
1237
- for (let [k,v] of Object.entries(fns_ns)) {
1238
- if ('function' === typeof v) {this[k] = v;} }
1239
- return this}
1181
+
1182
+ // automatic Client Id for connect()
1183
+ init_client_id(parts=['u8-mqtt--','']) {
1184
+ let sess_stg=this.sess_stg;
1185
+ let key, cid = sess_stg?.getItem(key=parts.join(' '));
1186
+ if (! cid) {
1187
+ cid = parts.join(Math.random().toString(36).slice(2));
1188
+ sess_stg?.setItem(key, cid);}
1189
+ return cid}
1190
+
1191
+ get sess_stg() {return globalThis.sessionStorage}
1192
+
1193
+
1194
+ //on_error(err, evt) ::
1195
+ // console.warn @ '[[u8-mqtt error: %s]]', evt, err
1240
1196
 
1241
1197
  //log_conn(evt, arg, err_arg) ::
1242
1198
  // console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
@@ -1313,7 +1269,6 @@ class MQTTCore extends MQTTBase {
1313
1269
 
1314
1270
  with_tcp(...opt) {
1315
1271
  opt = this._conn_opt(opt);
1316
- console.log({opt});
1317
1272
  return this._use_conn (() =>
1318
1273
  this.with_stream(
1319
1274
  node_net.connect(opt)) ) }
@@ -1375,7 +1330,7 @@ class MQTTCore extends MQTTBase {
1375
1330
 
1376
1331
  return this} }
1377
1332
 
1378
- const version = '0.4.1';
1333
+ const version = '0.5.0';
1379
1334
 
1380
1335
  const MQTTClient_v4 = /* #__PURE__ */
1381
1336
  with_topic_path_router(