u8-mqtt 0.4.0 → 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 (82) hide show
  1. package/README.md +3 -3
  2. package/cjs/basic-v4.cjs +107 -146
  3. package/cjs/basic-v4.cjs.map +1 -1
  4. package/cjs/basic-v5.cjs +106 -145
  5. package/cjs/basic-v5.cjs.map +1 -1
  6. package/cjs/index.cjs +163 -206
  7. package/cjs/index.cjs.map +1 -1
  8. package/cjs/v4.cjs +164 -207
  9. package/cjs/v4.cjs.map +1 -1
  10. package/cjs/v5.cjs +163 -206
  11. package/cjs/v5.cjs.map +1 -1
  12. package/code/_dispatch.jsy +16 -0
  13. package/code/base.jsy +72 -133
  14. package/code/core.jsy +15 -9
  15. package/code/router_path.jsy +38 -51
  16. package/code/with_topic_router.jsy +20 -11
  17. package/esm/basic-v4.js +1154 -0
  18. package/esm/basic-v4.js.map +1 -0
  19. package/esm/basic-v5.js +1416 -0
  20. package/esm/basic-v5.js.map +1 -0
  21. package/esm/deno/basic-v4.js +107 -146
  22. package/esm/deno/basic-v4.js.map +1 -1
  23. package/esm/deno/basic-v5.js +106 -145
  24. package/esm/deno/basic-v5.js.map +1 -1
  25. package/esm/deno/index.js +163 -206
  26. package/esm/deno/index.js.map +1 -1
  27. package/esm/deno/v4.js +164 -207
  28. package/esm/deno/v4.js.map +1 -1
  29. package/esm/deno/v5.js +163 -206
  30. package/esm/deno/v5.js.map +1 -1
  31. package/esm/index.js +1599 -0
  32. package/esm/index.js.map +1 -0
  33. package/esm/node/basic-v4.js +107 -146
  34. package/esm/node/basic-v4.js.map +1 -1
  35. package/esm/node/basic-v4.mjs +107 -146
  36. package/esm/node/basic-v4.mjs.map +1 -1
  37. package/esm/node/basic-v5.js +106 -145
  38. package/esm/node/basic-v5.js.map +1 -1
  39. package/esm/node/basic-v5.mjs +106 -145
  40. package/esm/node/basic-v5.mjs.map +1 -1
  41. package/esm/node/index.js +163 -206
  42. package/esm/node/index.js.map +1 -1
  43. package/esm/node/index.mjs +163 -206
  44. package/esm/node/index.mjs.map +1 -1
  45. package/esm/node/v4.js +164 -207
  46. package/esm/node/v4.js.map +1 -1
  47. package/esm/node/v4.mjs +164 -207
  48. package/esm/node/v4.mjs.map +1 -1
  49. package/esm/node/v5.js +163 -206
  50. package/esm/node/v5.js.map +1 -1
  51. package/esm/node/v5.mjs +163 -206
  52. package/esm/node/v5.mjs.map +1 -1
  53. package/esm/v4.js +1336 -0
  54. package/esm/v4.js.map +1 -0
  55. package/esm/v5.js +1599 -0
  56. package/esm/v5.js.map +1 -0
  57. package/esm/web/basic-v4.js +107 -146
  58. package/esm/web/basic-v4.js.map +1 -1
  59. package/esm/web/basic-v4.min.js +1 -1
  60. package/esm/web/basic-v4.min.js.br +0 -0
  61. package/esm/web/basic-v4.min.js.gz +0 -0
  62. package/esm/web/basic-v5.js +106 -145
  63. package/esm/web/basic-v5.js.map +1 -1
  64. package/esm/web/basic-v5.min.js +1 -1
  65. package/esm/web/basic-v5.min.js.br +0 -0
  66. package/esm/web/basic-v5.min.js.gz +0 -0
  67. package/esm/web/index.js +163 -206
  68. package/esm/web/index.js.map +1 -1
  69. package/esm/web/index.min.js +1 -1
  70. package/esm/web/index.min.js.br +0 -0
  71. package/esm/web/index.min.js.gz +0 -0
  72. package/esm/web/v4.js +164 -207
  73. package/esm/web/v4.js.map +1 -1
  74. package/esm/web/v4.min.js +1 -1
  75. package/esm/web/v4.min.js.br +0 -0
  76. package/esm/web/v4.min.js.gz +0 -0
  77. package/esm/web/v5.js +163 -206
  78. package/esm/web/v5.js.map +1 -1
  79. package/esm/web/v5.min.js +1 -1
  80. package/esm/web/v5.min.js.br +0 -0
  81. package/esm/web/v5.min.js.gz +0 -0
  82. package/package.json +7 -8
package/esm/deno/v4.js CHANGED
@@ -44,7 +44,7 @@ class U8_Reason extends Number {
44
44
  }
45
45
  }
46
46
 
47
- class mqtt_reader_v4$1 {
47
+ let mqtt_reader_v4$1 = class mqtt_reader_v4 {
48
48
  static of(buf) { return this.prototype.of(buf) }
49
49
  of(buf) {
50
50
  let step = (width, k) => (k=0|step.k, step.k=k+width, k);
@@ -100,7 +100,7 @@ class mqtt_reader_v4$1 {
100
100
  return buf.subarray(step.k|0)
101
101
  }
102
102
 
103
- }
103
+ };
104
104
 
105
105
  function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
106
106
  mqtt_reader = class extends mqtt_reader {
@@ -475,7 +475,7 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
475
475
  }
476
476
  }
477
477
 
478
- // not a v4 packet: import { mqtt_encode_auth } from './encode/auth.mjs'
478
+ // not a v4 packet: import { mqtt_encode_auth } from './encode/auth.js'
479
479
 
480
480
 
481
481
  const mqtt_decode_v4 = [
@@ -556,30 +556,39 @@ const with_topic_router = mqtt_topic_router =>
556
556
  return super._aliases() +
557
557
  ' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'}
558
558
 
559
- _init_router(opt) {
560
- return mqtt_topic_router(opt, this)}
561
-
562
- get on_topic() {return this.router.add}
559
+ _init_router(opt, self, target) {
560
+ this._subs = [];
561
+ let router = this.router = target.router =
562
+ mqtt_topic_router(opt, this, target);
563
+ return router?.invoke}
563
564
 
564
- _sub_chain(topic, ex, topic_prefix) {
565
- let res = this.subscribe([[ topic ]], ex, topic_prefix);
566
- let subs = this.subs ||(this.subs = new Map());
567
- subs.set((res.topic = topic), (subs.last = res));
568
- return this }// fluent api -- return this and track side effects
565
+ on_sub(suback, pkt) {
566
+ suback.pkt = pkt;
567
+ this._subs.push(suback);
568
+ return suback}
569
+ subs_settled() {
570
+ return Promise.allSettled(
571
+ this._subs.splice(0,Infinity)) }
569
572
 
570
573
  // alias: sub_topic
571
574
  subscribe_topic(topic_route, ...args) {
572
575
  let router = this.router;
573
576
  router.add(topic_route, true, args.pop() );// handler
574
577
  let topic = router.mqtt_topic(topic_route);
575
- return this._sub_chain(topic, ...args ) }// ex, topic_prefix
578
+ this.subscribe(topic, ...args );// ex, topic_prefix
579
+ return this }// fluent api -- return this and track side effects
576
580
 
577
581
  // alias: unsub_topic
578
582
  unsubscribe_topic(topic_route, ...args) {
579
583
  let router = this.router;
580
584
  router.remove(topic_route, true);
581
585
  let topic = router.mqtt_topic(topic_route);
582
- return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
586
+ return this.unsubscribe(topic, ...args ) }// topic_prefix
587
+
588
+ // add topic handlers without corresponding subscribe packet
589
+ on_topic(...args) {
590
+ this.router.add(...args);
591
+ return this} };
583
592
 
584
593
  // Use [regexparam][] for url-like topic parsing
585
594
  // [regexparam]: https://github.com/lukeed/regexparam
@@ -592,16 +601,22 @@ const with_topic_path_router = /* #__PURE__ */
592
601
  const mqtt_topic = topic_route =>
593
602
  topic_route
594
603
  .replace(/[*].*$/, '#')
595
- .replace(/:\w+\??/g, '+');
604
+ .replace(/:\w[^\/]*/g, '+');
596
605
 
597
- const as_topic_path = topic_route =>(
606
+ /* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
607
+ 4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
608
+ ... MUST be specified either on its own or following a topic level separator.
609
+ In either case it MUST be the last character specified in the Topic Filter
610
+
611
+ 4.7.1.3 Single-level wildcard -- (‘+’ U+002B)
612
+ ...it MUST occupy an entire level of the filter.
613
+ */
614
+
615
+ const as_topic_path = (topic_route, id) =>(
616
+ id=1,
598
617
  topic_route
599
- .replace(/#$/, '*') // replace MQTT # wildcard at end
600
- .split(/([^\/]*[+][^\/]*)/) // split on MQTT + match tokens
601
- .reduce (( sz, v, idx ) => sz +(
602
- idx & 1 // even entires are body, odd are MQTT + tokens
603
- ? `:$${1 + idx>>1}` // replace with `:$#` sequential ids, using ? for partial entries
604
- : v ) ) );// pass through body
618
+ .replace(/#$/, '*' )// replace MQTT '#' multi-level wildcard at end
619
+ .replace(/\+/g, () => `:$${id++}` ) );// replace MQTT '+' single-level wildcards
605
620
 
606
621
  function _ignore(pkt, params, ctx) {ctx.done = true;}
607
622
 
@@ -616,9 +631,8 @@ function mqtt_topic_path_router() {
616
631
  let priority = args.pop();
617
632
 
618
633
  if ('function' !== typeof fn) {
619
- if (false === fn) {
620
- fn = _ignore;}
621
- else throw new TypeError()}
634
+ if (fn) {throw new TypeError()}
635
+ fn = _ignore;}
622
636
 
623
637
  let rte = parse(as_topic_path(topic_route));
624
638
 
@@ -634,7 +648,7 @@ function mqtt_topic_path_router() {
634
648
  , clear(priority) {
635
649
  pri_lsts[priority ? 0 : 1] = [];
636
650
  if (null == priority) {
637
- pri_lsts[1] = [];} }
651
+ pri_lsts[1] = []; } }// null clears both lists
638
652
 
639
653
  , async invoke(pkt, ctx) {
640
654
  ctx.idx = 0;
@@ -650,52 +664,34 @@ function mqtt_topic_path_router() {
650
664
  break}
651
665
  else ctx.idx++;}
652
666
 
653
- let {pkt_id, qos} = pkt;
654
- if (1 === qos) {
655
- await ctx.mqtt._send('puback', {pkt_id});} } } }
667
+ if (1 === pkt.qos) {
668
+ await ctx.mqtt.puback(pkt);} } } }
656
669
 
657
670
 
658
671
  function * _routes_iter(all_route_lists, topic) {
672
+ topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
659
673
  for (let route_list of all_route_lists) {
660
- for (let route of route_list) {
661
- let res = _route_match_one(topic, route);
662
- if (undefined !== res) {
663
- yield res;} } } }
664
-
665
-
666
- function _route_match_one(topic, {keys, pattern, tgt}) {
667
- let match = '/' !== topic[0]
668
- ? pattern.exec('/'+topic)
669
- : pattern.exec(topic);
670
-
671
- if (null === match) {
672
- return}
673
-
674
- if (false === keys) {
675
- let {groups} = match;
676
- if (! groups) {
677
- return [tgt]}
678
-
679
- let params = {};
680
- for (let k in groups) {
681
- params[k] = groups[k];}
682
-
683
- return [tgt, params]}
684
-
685
- if (0 === keys.length) {
686
- return [tgt]}
687
-
688
- let params = {};
689
- for (let i=0; i<keys.length; i++) {
690
- params[ keys[i] ] = match[1+i];}
691
- return [tgt, params]}
674
+ for (let {keys, pattern, tgt} of route_list) {
675
+ let match = pattern.exec(topic);
676
+ if (match) {
677
+ let params = keys
678
+ ? keys.reduce(
679
+ (o, k, i) => (o[k] = match[1+i], o)
680
+ , {})
681
+ : match.groups ?? match;
682
+ yield [tgt, params];} } } }
692
683
 
693
684
 
694
685
  function _route_remove(all_route_lists, query) {
695
- let match = route => route===query || route.tgt===query || route.key===query;
686
+ let fn_match = route =>(
687
+ route===query
688
+ || route.tgt===query
689
+ || route.key===query);
696
690
  for (let lst of all_route_lists) {
697
- let i = lst.findIndex(match);
698
- if (0 <= i) {return !! lst.splice(i,1)} }
691
+ let i = lst.findIndex(fn_match);
692
+ if (0 <= i) {
693
+ lst.splice(i,1);
694
+ return true} }
699
695
  return false}
700
696
 
701
697
  /*
@@ -956,6 +952,22 @@ const _mqtt_cmdid_dispatch ={
956
952
 
957
953
  await fn?.call(target, pkt, ctx);} })()) };
958
954
 
955
+ /*
956
+ on_mqtt_type = {
957
+ mqtt_auth(pkt, ctx) ::
958
+ mqtt_connect(pkt, ctx) ::
959
+ mqtt_connack(pkt, ctx) ::
960
+ mqtt_disconnect(pkt, ctx) ::
961
+
962
+ mqtt_publish(pkt, ctx)
963
+ mqtt_subscribe(pkt, ctx) ::
964
+ mqtt_unsubscribe(pkt, ctx) ::
965
+
966
+ mqtt_pingreq(pkt, ctx) ::
967
+ mqtt_pingresp(pkt, ctx) ::
968
+ }
969
+ */
970
+
959
971
  function _mqtt_dispatch(opt, target) {
960
972
  let _disp_ = _mqtt_cmdid_dispatch.create(target);
961
973
  let { cmdids } = _disp_;
@@ -985,28 +997,34 @@ class MQTTError extends Error {
985
997
 
986
998
  class MQTTBase {
987
999
  constructor(opt={}) {
1000
+ this.with(opt);
988
1001
  this._conn_ = _mqtt_conn(this,
989
1002
  this._init_dispatch(opt, this)); }
990
1003
 
1004
+ with(fns_ns) {
1005
+ for (let [k,v] of Object.entries(fns_ns)) {
1006
+ if ('function' === typeof v) {this[k] = v;} }
1007
+ return this}
1008
+
991
1009
  async conn_emit(evt, arg, err_arg) {
992
1010
  this.log_conn?.(evt, arg, err_arg);
993
1011
  try {
994
- let fn_evt = this[await evt]; // microtask break
1012
+ let fn_evt = this[await evt]; // microtask break using `await evt`
995
1013
  if (fn_evt) {
996
1014
  await fn_evt.call(this, this, arg, err_arg);}
997
- else if (err_arg) {
998
- await this.on_error(err_arg, evt);} }
1015
+ else if (err_arg) {throw err_arg} }
999
1016
  catch (err) {
1000
1017
  this.on_error(err, evt);} }
1001
1018
 
1002
- on_error(err, err_path) {
1003
- console.warn('[[u8-mqtt error: %s]]', err_path, err); }
1019
+ on_error(err, evt) {
1020
+ console.warn('[[u8-mqtt error: %s]]', evt, err); }
1004
1021
 
1005
1022
  // Handshaking Packets
1006
1023
 
1007
1024
  async connect(pkt={}) {
1008
- let cid = pkt.client_id || ['u8-mqtt--', ''];
1009
- if (Array.isArray(cid)) {
1025
+ let cid = pkt.client_id || this.client_id;
1026
+ if ('string' !== typeof cid) {
1027
+ // see init_client_id implementation in core.jsy
1010
1028
  pkt.client_id = cid = this.init_client_id(cid);}
1011
1029
  this.client_id = cid;
1012
1030
 
@@ -1032,12 +1050,13 @@ class MQTTBase {
1032
1050
  return this._send('auth', pkt, 'auth')}
1033
1051
 
1034
1052
  ping() {return this._send('pingreq', null, 'pingresp')}
1035
-
1053
+ puback({pkt_id}) {return this._send('puback', {pkt_id})}
1036
1054
 
1037
1055
  // alias: sub
1038
1056
  subscribe(pkt, ex, topic_prefix) {
1039
1057
  pkt = _as_topics(pkt, ex, topic_prefix);
1040
- return this._send('subscribe', pkt, pkt)}
1058
+ let suback = this._send('subscribe', pkt, pkt);
1059
+ return this.on_sub?.(suback, pkt) ?? suback}
1041
1060
 
1042
1061
  // alias: unsub
1043
1062
  unsubscribe(pkt, ex, topic_prefix) {
@@ -1045,48 +1064,52 @@ class MQTTBase {
1045
1064
  return this._send('unsubscribe', pkt, pkt)}
1046
1065
 
1047
1066
 
1048
- // alias: pub
1049
- publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
1050
- post(topic, payload, pub_opt) {return _pub.m(this, topic, payload, pub_opt)}
1051
- send(topic, payload, pub_opt) {return _pub.mq(this, topic, payload, pub_opt)}
1052
- store(topic, payload, pub_opt) {return _pub.mqr(this, topic, payload, pub_opt)}
1053
-
1054
- json_post(topic, msg, pub_opt) {return _pub.o(this, topic, msg, pub_opt)}
1055
- json_send(topic, msg, pub_opt) {return _pub.oq(this, topic, msg, pub_opt)}
1056
- json_store(topic, msg, pub_opt) {return _pub.oqr(this, topic, msg, pub_opt)}
1057
-
1058
- obj_post(topic, msg, pub_opt) {return _pub.o(this, topic, msg, pub_opt)}
1059
- obj_send(topic, msg, pub_opt) {return _pub.oq(this, topic, msg, pub_opt)}
1060
- obj_store(topic, msg, pub_opt) {return _pub.oqr(this, topic, msg, pub_opt)}
1061
-
1062
-
1063
-
1064
- // Utility Methods
1065
-
1066
- init_client_id(parts) {
1067
- let cid = this.client_id;
1068
-
1069
- if (undefined === cid) {
1070
- this.client_id = cid = (
1071
-
1072
-
1073
-
1074
- this.new_client_id(parts)
1075
- );}
1076
-
1077
- return cid}
1078
-
1079
- new_client_id(parts) {
1080
- return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
1081
-
1082
-
1083
-
1084
-
1085
-
1086
-
1087
-
1088
-
1089
-
1067
+ post(topic, payload, pub_opt) {// qos:0
1068
+ return this.pub({topic, payload, qos:0}, pub_opt)}
1069
+ send(topic, payload, pub_opt) {// qos:1
1070
+ return this.pub({topic, payload, qos:1}, pub_opt)}
1071
+ store(topic, payload, pub_opt) {// qos:1, retain: 1
1072
+ return this.pub({topic, payload, qos:1, retain: 1}, pub_opt)}
1073
+
1074
+ // alias: json_post
1075
+ obj_post(topic, msg, pub_opt) {// qos:0
1076
+ return this.pub({topic, msg, arg: 'msg', qos:0}, pub_opt)}
1077
+ // alias: json_send
1078
+ obj_send(topic, msg, pub_opt) {// qos:1
1079
+ return this.pub({topic, msg, arg: 'msg', qos:1}, pub_opt)}
1080
+ // alias: json_store
1081
+ obj_store(topic, msg, pub_opt) {// qos:1, retain: 1
1082
+ return this.pub({topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)}
1083
+
1084
+ // alias: publish -- because 'pub' is shorter for semantic aliases above
1085
+ async pub(pkt, pub_opt) {
1086
+ if (undefined === pkt.payload) {
1087
+ if ('function' === typeof pub_opt) {
1088
+ pub_opt = {fn_encode: pub_opt};}
1089
+
1090
+ let {msg} = pkt;
1091
+ switch (typeof msg) {
1092
+ case 'function':
1093
+ pub_opt = {...pub_opt, fn_encode: msg};
1094
+ // flow into 'undefined' case
1095
+ case 'undefined':
1096
+ // return a single-value closure to publish packets
1097
+ return v => this.pub({...pkt, [pkt.arg || 'payload']: v}, pub_opt)}
1098
+
1099
+ // Encode payload from msg; fn_encode allows alternative to JSON.stringify
1100
+ let {fn_encode} = pub_opt || {};
1101
+ pkt.payload = fn_encode
1102
+ ? await fn_encode(msg)
1103
+ : JSON.stringify(msg);}
1104
+
1105
+ if (pub_opt) {
1106
+ if (pub_opt.props) {
1107
+ pkt.props = pub_opt.props;}
1108
+ if (pub_opt.xform) {
1109
+ pkt = pub_opt.xform(pkt) || pkt;} }
1110
+
1111
+ return this._send('publish', pkt,
1112
+ pkt.qos ? pkt : void 0 ) }// key
1090
1113
 
1091
1114
 
1092
1115
  // Internal API
@@ -1095,52 +1118,24 @@ class MQTTBase {
1095
1118
 
1096
1119
  _init_dispatch(opt) {
1097
1120
  this.constructor?._once_();
1098
- let router = this.router =
1099
- this._init_router?.(opt, this);
1100
-
1101
- let tgt ={
1102
- __proto__: opt.on_mqtt_type || {}
1103
- , router};
1104
-
1105
- tgt.mqtt_publish ||= router?.invoke;
1106
- return _mqtt_dispatch(this, tgt)}
1121
+ let target ={__proto__: opt.on_mqtt_type};
1122
+ target.mqtt_publish ||=
1123
+ this._init_router?.(opt, this, target);
1124
+ return _mqtt_dispatch(this, target)}
1107
1125
 
1108
1126
  static _aliases() {
1109
- return ' pub:publish sub:subscribe unsub:unsubscribe '}
1127
+ return ' publish:pub sub:subscribe unsub:unsubscribe json_post:obj_post json_send:obj_send json_store:obj_store'}
1110
1128
 
1111
1129
  static _once_(self=this) {
1112
1130
  self._once_ = _=>0;
1113
- self.MQTTError = MQTTError;
1114
1131
  let p = self.prototype;
1132
+ p.MQTTError = MQTTError;
1115
1133
  for (let alias of self._aliases().split(/\s+/)) {
1116
1134
  alias = alias.split(':');
1117
1135
  let fn = alias[1] && p[alias[1]];
1118
1136
  if (fn) {p[alias[0]] = fn;} } } }
1119
1137
 
1120
1138
 
1121
- /*
1122
- on_mqtt_type = {
1123
- mqtt_auth(pkt, ctx) ::
1124
- mqtt_connect(pkt, ctx) ::
1125
- mqtt_connack(pkt, ctx) ::
1126
- mqtt_disconnect(pkt, ctx) ::
1127
-
1128
- mqtt_publish(pkt, ctx)
1129
- mqtt_subscribe(pkt, ctx) ::
1130
- mqtt_unsubscribe(pkt, ctx) ::
1131
-
1132
- mqtt_pingreq(pkt, ctx) ::
1133
- mqtt_pingresp(pkt, ctx) ::
1134
- }
1135
- */
1136
-
1137
-
1138
- const _prefix_topics = (topic_prefix, iterable) =>
1139
- Array.from(iterable, value =>(
1140
- value.trim // string
1141
- ? _prefix_topics(topic_prefix, value)
1142
- : topic_prefix + value) );
1143
-
1144
1139
  function _as_topics(pkt, ex, topic_prefix) {
1145
1140
  if (ex?.trim) {// string
1146
1141
  topic_prefix = ex;
@@ -1157,55 +1152,11 @@ function _as_topics(pkt, ex, topic_prefix) {
1157
1152
  if (topic_prefix) {
1158
1153
  // particularly useful with shared queues, e.g.
1159
1154
  // topic_prefix = '$share/some-queue-name/'
1160
- pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
1161
- return pkt}
1162
-
1155
+ let _prefix_topics = v =>
1156
+ v.trim ? topic_prefix+v : v.map(_prefix_topics);
1163
1157
 
1164
- async function _pub(self, pkt, pub_opt) {
1165
- if (undefined === pkt.payload) {
1166
- if ('function' === typeof pub_opt) {
1167
- pub_opt = {fn_encode: pub_opt};}
1168
-
1169
- let {msg} = pkt;
1170
- switch (typeof msg) {
1171
- case 'function':
1172
- pub_opt = {...pub_opt, fn_encode: msg};
1173
- // flow into 'undefined' case
1174
- case 'undefined':
1175
- // return a single-value closure to publish packets
1176
- return v => _pub(self, {...pkt, [pkt.arg || 'payload']: v}, pub_opt)
1177
-
1178
- default:
1179
- // Encode payload from msg; fn_encode allows alternative to JSON.stringify
1180
- let {fn_encode} = pub_opt || {};
1181
- pkt.payload = fn_encode
1182
- ? await fn_encode(msg)
1183
- : JSON.stringify(msg);} }
1184
-
1185
- if (pub_opt) {
1186
- if (pub_opt.props) {
1187
- pkt.props = pub_opt.props;}
1188
- if (pub_opt.xform) {
1189
- pkt = pub_opt.xform(pkt) || pkt;} }
1190
-
1191
- return self._send('publish', pkt,
1192
- pkt.qos ? pkt : void 0 ) }// key
1193
-
1194
- {
1195
- Object.assign(_pub,{
1196
- m: (self, topic, payload, pub_opt) =>
1197
- _pub(self, {topic, payload, qos:0}, pub_opt)
1198
- , mq: (self, topic, payload, pub_opt) =>
1199
- _pub(self, {topic, payload, qos:1}, pub_opt)
1200
- , mqr: (self, topic, payload, pub_opt) =>
1201
- _pub(self, {topic, payload, qos:1, retain: 1}, pub_opt)
1202
-
1203
- , o: (self, topic, msg, pub_opt) =>
1204
- _pub(self, {topic, msg, arg: 'msg', qos:0}, pub_opt)
1205
- , oq: (self, topic, msg, pub_opt) =>
1206
- _pub(self, {topic, msg, arg: 'msg', qos:1}, pub_opt)
1207
- , oqr: (self, topic, msg, pub_opt) =>
1208
- _pub(self, {topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)} ); }
1158
+ pkt.topics = pkt.topics.map(_prefix_topics);}
1159
+ return pkt}
1209
1160
 
1210
1161
  const pkt_api = {
1211
1162
  utf8(u8) { return new TextDecoder('utf-8').decode(u8 || this.payload ) },
@@ -1214,20 +1165,27 @@ const pkt_api = {
1214
1165
  };
1215
1166
 
1216
1167
  class MQTTCore extends MQTTBase {
1217
- constructor(opt={}) {
1218
- super(opt);
1219
- this.with(opt);}
1220
-
1221
1168
  static mqtt_ctx(mqtt_level, mqtt_opts, pkt_ctx=pkt_api) {
1222
1169
  let self = class extends this {};
1223
1170
  self.prototype.mqtt_ctx =
1224
1171
  mqtt_pkt_ctx(mqtt_level, mqtt_opts, pkt_ctx);
1225
1172
  return self}
1226
1173
 
1227
- with(fns_ns) {
1228
- for (let [k,v] of Object.entries(fns_ns)) {
1229
- if ('function' === typeof v) {this[k] = v;} }
1230
- return this}
1174
+
1175
+ // automatic Client Id for connect()
1176
+ init_client_id(parts=['u8-mqtt--','']) {
1177
+ let sess_stg=this.sess_stg;
1178
+ let key, cid = sess_stg?.getItem(key=parts.join(' '));
1179
+ if (! cid) {
1180
+ cid = parts.join(Math.random().toString(36).slice(2));
1181
+ sess_stg?.setItem(key, cid);}
1182
+ return cid}
1183
+
1184
+ get sess_stg() {return globalThis.sessionStorage}
1185
+
1186
+
1187
+ //on_error(err, evt) ::
1188
+ // console.warn @ '[[u8-mqtt error: %s]]', evt, err
1231
1189
 
1232
1190
  //log_conn(evt, arg, err_arg) ::
1233
1191
  // console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
@@ -1305,7 +1263,6 @@ class MQTTCore extends MQTTBase {
1305
1263
 
1306
1264
 
1307
1265
 
1308
-
1309
1266
 
1310
1267
 
1311
1268
 
@@ -1366,7 +1323,7 @@ class MQTTCore extends MQTTBase {
1366
1323
 
1367
1324
  return this} }
1368
1325
 
1369
- const version = '0.4.0';
1326
+ const version = '0.5.0';
1370
1327
 
1371
1328
  const MQTTClient_v4 = /* #__PURE__ */
1372
1329
  with_topic_path_router(