u8-mqtt 0.3.2-0 → 0.4.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 (76) hide show
  1. package/README.md +5 -5
  2. package/cjs/basic-v4.cjs +1205 -0
  3. package/cjs/basic-v4.cjs.map +1 -0
  4. package/cjs/basic-v5.cjs +1469 -0
  5. package/cjs/basic-v5.cjs.map +1 -0
  6. package/cjs/index.cjs +308 -267
  7. package/cjs/index.cjs.map +1 -1
  8. package/cjs/v4.cjs +303 -262
  9. package/cjs/v4.cjs.map +1 -1
  10. package/cjs/v5.cjs +305 -263
  11. package/cjs/v5.cjs.map +1 -1
  12. package/code/_cmdid_dispatch.jsy +1 -3
  13. package/code/base.jsy +64 -84
  14. package/code/basic-v4.js +18 -0
  15. package/code/basic-v5.js +26 -0
  16. package/code/index.js +2 -1
  17. package/code/{_router.jsy → router_path.jsy} +30 -12
  18. package/code/v4.js +3 -1
  19. package/code/v5.js +5 -2
  20. package/code/with_topic_router.jsy +41 -0
  21. package/esm/deno/basic-v4.js +1193 -0
  22. package/esm/deno/basic-v4.js.map +1 -0
  23. package/esm/deno/basic-v5.js +1455 -0
  24. package/esm/deno/basic-v5.js.map +1 -0
  25. package/esm/deno/index.js +306 -264
  26. package/esm/deno/index.js.map +1 -1
  27. package/esm/deno/v4.js +303 -262
  28. package/esm/deno/v4.js.map +1 -1
  29. package/esm/deno/v5.js +305 -263
  30. package/esm/deno/v5.js.map +1 -1
  31. package/esm/node/basic-v4.js +1196 -0
  32. package/esm/node/basic-v4.js.map +1 -0
  33. package/esm/node/basic-v4.mjs +1196 -0
  34. package/esm/node/basic-v4.mjs.map +1 -0
  35. package/esm/node/basic-v5.js +1458 -0
  36. package/esm/node/basic-v5.js.map +1 -0
  37. package/esm/node/basic-v5.mjs +1458 -0
  38. package/esm/node/basic-v5.mjs.map +1 -0
  39. package/esm/node/index.js +306 -264
  40. package/esm/node/index.js.map +1 -1
  41. package/esm/node/index.mjs +306 -264
  42. package/esm/node/index.mjs.map +1 -1
  43. package/esm/node/v4.js +303 -262
  44. package/esm/node/v4.js.map +1 -1
  45. package/esm/node/v4.mjs +303 -262
  46. package/esm/node/v4.mjs.map +1 -1
  47. package/esm/node/v5.js +305 -263
  48. package/esm/node/v5.js.map +1 -1
  49. package/esm/node/v5.mjs +305 -263
  50. package/esm/node/v5.mjs.map +1 -1
  51. package/esm/web/basic-v4.js +1193 -0
  52. package/esm/web/basic-v4.js.map +1 -0
  53. package/esm/web/basic-v4.min.js +1 -0
  54. package/esm/web/basic-v4.min.js.br +0 -0
  55. package/esm/web/basic-v4.min.js.gz +0 -0
  56. package/esm/web/basic-v5.js +1455 -0
  57. package/esm/web/basic-v5.js.map +1 -0
  58. package/esm/web/basic-v5.min.js +1 -0
  59. package/esm/web/basic-v5.min.js.br +0 -0
  60. package/esm/web/basic-v5.min.js.gz +0 -0
  61. package/esm/web/index.js +305 -263
  62. package/esm/web/index.js.map +1 -1
  63. package/esm/web/index.min.js +1 -1
  64. package/esm/web/index.min.js.br +0 -0
  65. package/esm/web/index.min.js.gz +0 -0
  66. package/esm/web/v4.js +303 -262
  67. package/esm/web/v4.js.map +1 -1
  68. package/esm/web/v4.min.js +1 -1
  69. package/esm/web/v4.min.js.br +0 -0
  70. package/esm/web/v4.min.js.gz +0 -0
  71. package/esm/web/v5.js +304 -262
  72. package/esm/web/v5.js.map +1 -1
  73. package/esm/web/v5.min.js +1 -1
  74. package/esm/web/v5.min.js.br +0 -0
  75. package/esm/web/v5.min.js.gz +0 -0
  76. package/package.json +5 -5
package/cjs/v4.cjs CHANGED
@@ -520,6 +520,191 @@ const mqtt_opts_v4 =
520
520
  encode_fns: mqtt_encode_v4,
521
521
  mqtt_writer: mqtt_writer_v4, };
522
522
 
523
+ function parse(str, loose) {
524
+ if (str instanceof RegExp) return { keys:false, pattern:str };
525
+ var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
526
+ arr[0] || arr.shift();
527
+
528
+ while (tmp = arr.shift()) {
529
+ c = tmp[0];
530
+ if (c === '*') {
531
+ keys.push('wild');
532
+ pattern += '/(.*)';
533
+ } else if (c === ':') {
534
+ o = tmp.indexOf('?', 1);
535
+ ext = tmp.indexOf('.', 1);
536
+ keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
537
+ pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
538
+ if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
539
+ } else {
540
+ pattern += '/' + tmp;
541
+ }
542
+ }
543
+
544
+ return {
545
+ keys: keys,
546
+ pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
547
+ };
548
+ }
549
+
550
+ /*
551
+ class AbstractTopicRouter ::
552
+ async invoke(pkt, ctx) ::
553
+ add(topic_route, ...args) ::
554
+ remove(topic_route, priority) ::
555
+ clear(priority) ::
556
+ find(topic) :: // optional
557
+ mqtt_topic(topic_route)
558
+ */
559
+
560
+ const with_topic_router = mqtt_topic_router =>
561
+ MQTTKlass => class extends MQTTKlass {
562
+ static _aliases() {
563
+ return super._aliases() +
564
+ ' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'}
565
+
566
+ _init_router(opt) {
567
+ return mqtt_topic_router(opt, this)}
568
+
569
+ get on_topic() {return this.router.add}
570
+
571
+ _sub_chain(topic, ex, topic_prefix) {
572
+ let res = this.subscribe([[ topic ]], ex, topic_prefix);
573
+ let subs = this.subs ||(this.subs = new Map());
574
+ subs.set((res.topic = topic), (subs.last = res));
575
+ return this }// fluent api -- return this and track side effects
576
+
577
+ // alias: sub_topic
578
+ subscribe_topic(topic_route, ...args) {
579
+ let router = this.router;
580
+ router.add(topic_route, true, args.pop() );// handler
581
+ let topic = router.mqtt_topic(topic_route);
582
+ return this._sub_chain(topic, ...args ) }// ex, topic_prefix
583
+
584
+ // alias: unsub_topic
585
+ unsubscribe_topic(topic_route, ...args) {
586
+ let router = this.router;
587
+ router.remove(topic_route, true);
588
+ let topic = router.mqtt_topic(topic_route);
589
+ return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
590
+
591
+ // Use [regexparam][] for url-like topic parsing
592
+ // [regexparam]: https://github.com/lukeed/regexparam
593
+
594
+
595
+ const with_topic_path_router = /* #__PURE__ */
596
+ with_topic_router(mqtt_topic_path_router);
597
+
598
+
599
+ const mqtt_topic = topic_route =>
600
+ topic_route
601
+ .replace(/[*].*$/, '#')
602
+ .replace(/:\w+\??/g, '+');
603
+
604
+ const as_topic_path = topic_route =>(
605
+ topic_route
606
+ .replace(/#$/, '*') // replace MQTT # wildcard at end
607
+ .split(/([^\/]*[+][^\/]*)/) // split on MQTT + match tokens
608
+ .reduce (( sz, v, idx ) => sz +(
609
+ idx & 1 // even entires are body, odd are MQTT + tokens
610
+ ? `:$${1 + idx>>1}` // replace with `:$#` sequential ids, using ? for partial entries
611
+ : v ) ) );// pass through body
612
+
613
+ function _ignore(pkt, params, ctx) {ctx.done = true;}
614
+
615
+ function mqtt_topic_path_router() {
616
+ let pri_lsts = [[],[]], rm = Symbol();
617
+ let find = topic => _routes_iter(pri_lsts, topic);
618
+
619
+ // return duck-type compatible with AbstractTopicRouter in ./with_topic_router
620
+ return {find, mqtt_topic,
621
+ add(topic_route, ...args) {
622
+ let fn = args.pop();
623
+ let priority = args.pop();
624
+
625
+ if ('function' !== typeof fn) {
626
+ if (false === fn) {
627
+ fn = _ignore;}
628
+ else throw new TypeError()}
629
+
630
+ let rte = parse(as_topic_path(topic_route));
631
+
632
+ rte.key = topic_route;
633
+ rte.tgt = fn;
634
+ pri_lsts[priority ? 0 : 1].push(rte);
635
+ return this}
636
+
637
+ , remove(topic_route, priority) {
638
+ let lst = pri_lsts[priority ? 0 : 1];
639
+ return _route_remove([lst], topic_route)}
640
+
641
+ , clear(priority) {
642
+ pri_lsts[priority ? 0 : 1] = [];
643
+ if (null == priority) {
644
+ pri_lsts[1] = [];} }
645
+
646
+ , async invoke(pkt, ctx) {
647
+ ctx.idx = 0;
648
+ ctx.rm = rm;
649
+
650
+ for (let [fn, params] of find(pkt.topic)) {
651
+ let res = await fn(pkt, params, ctx);
652
+
653
+ if (rm === res) {
654
+ _route_remove(pri_lsts, fn);}
655
+
656
+ if (ctx.done) {
657
+ break}
658
+ else ctx.idx++;}
659
+
660
+ let {pkt_id, qos} = pkt;
661
+ if (1 === qos) {
662
+ await ctx.mqtt._send('puback', {pkt_id});} } } }
663
+
664
+
665
+ function * _routes_iter(all_route_lists, topic) {
666
+ for (let route_list of all_route_lists) {
667
+ for (let route of route_list) {
668
+ let res = _route_match_one(topic, route);
669
+ if (undefined !== res) {
670
+ yield res;} } } }
671
+
672
+
673
+ function _route_match_one(topic, {keys, pattern, tgt}) {
674
+ let match = '/' !== topic[0]
675
+ ? pattern.exec('/'+topic)
676
+ : pattern.exec(topic);
677
+
678
+ if (null === match) {
679
+ return}
680
+
681
+ if (false === keys) {
682
+ let {groups} = match;
683
+ if (! groups) {
684
+ return [tgt]}
685
+
686
+ let params = {};
687
+ for (let k in groups) {
688
+ params[k] = groups[k];}
689
+
690
+ return [tgt, params]}
691
+
692
+ if (0 === keys.length) {
693
+ return [tgt]}
694
+
695
+ let params = {};
696
+ for (let i=0; i<keys.length; i++) {
697
+ params[ keys[i] ] = match[1+i];}
698
+ return [tgt, params]}
699
+
700
+
701
+ function _route_remove(all_route_lists, query) {
702
+ let match = route => route===query || route.tgt===query || route.key===query;
703
+ for (let lst of all_route_lists) {
704
+ let i = lst.findIndex(match);
705
+ if (0 <= i) {return !! lst.splice(i,1)} }
706
+ return false}
707
+
523
708
  /*
524
709
  export function decode_varint_loop(u8, i=0) {
525
710
  let i0 = i
@@ -701,138 +886,13 @@ function _ping_interval(send_ping) {
701
886
  if (td) {
702
887
  tid = setInterval(send_ping, 1000 * td);
703
888
 
704
-
705
-
889
+
890
+
706
891
 
707
- // ensure the interval allows the NodeJS event loop to exit
708
- tid.unref?.();
892
+ // ensure the interval allows the NodeJS event loop to exit
893
+ tid.unref?.();
709
894
  return true} }) }
710
895
 
711
- function parse(str, loose) {
712
- if (str instanceof RegExp) return { keys:false, pattern:str };
713
- var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
714
- arr[0] || arr.shift();
715
-
716
- while (tmp = arr.shift()) {
717
- c = tmp[0];
718
- if (c === '*') {
719
- keys.push('wild');
720
- pattern += '/(.*)';
721
- } else if (c === ':') {
722
- o = tmp.indexOf('?', 1);
723
- ext = tmp.indexOf('.', 1);
724
- keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
725
- pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
726
- if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
727
- } else {
728
- pattern += '/' + tmp;
729
- }
730
- }
731
-
732
- return {
733
- keys: keys,
734
- pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
735
- };
736
- }
737
-
738
- // Use [regexparam][] for url-like topic parsing
739
-
740
- function _ignore(pkt, params, ctx) {ctx.done = true;}
741
-
742
- function _mqtt_topic_router() {
743
- let pri_lsts = [[],[]], rm = Symbol();
744
- let find = topic => _mqtt_routes_iter(pri_lsts, topic);
745
-
746
- return {find,
747
-
748
- add(topic_route, ...args) {
749
- let fn = args.pop();
750
- let priority = args.pop();
751
-
752
- if ('function' !== typeof fn) {
753
- if (false === fn) {
754
- fn = _ignore;}
755
- else throw new TypeError()}
756
-
757
- let rte = parse(
758
- topic_route.replace(/[+#]$/, '*'));
759
-
760
- rte.key = topic_route;
761
- rte.tgt = fn;
762
- pri_lsts[priority ? 0 : 1].push(rte);
763
- return this}
764
-
765
- , remove(topic_route, priority) {
766
- let lst = pri_lsts[priority ? 0 : 1];
767
- return _mqtt_route_remove([lst], topic_route)}
768
-
769
- , clear(priority) {
770
- pri_lsts[priority ? 0 : 1] = [];
771
- if (null == priority) {
772
- pri_lsts[1] = [];} }
773
-
774
- , async invoke(pkt, ctx) {
775
- ctx.idx = 0;
776
- ctx.rm = rm;
777
-
778
- for (let [fn, params] of find(pkt.topic)) {
779
- let res = await fn(pkt, params, ctx);
780
-
781
- if (rm === res) {
782
- _mqtt_route_remove(pri_lsts, fn);}
783
-
784
- if (ctx.done) {
785
- break}
786
- else ctx.idx++;}
787
-
788
- let {pkt_id, qos} = pkt;
789
- if (1 === qos) {
790
- await ctx.mqtt._send('puback', {pkt_id});} } } }
791
-
792
-
793
- function * _mqtt_routes_iter(all_route_lists, topic) {
794
- for (let route_list of all_route_lists) {
795
- for (let route of route_list) {
796
- let res = _mqtt_route_match_one(topic, route);
797
- if (undefined !== res) {
798
- yield res;} } } }
799
-
800
-
801
- function _mqtt_route_match_one(topic, {keys, pattern, tgt}) {
802
- let match = '/' !== topic[0]
803
- ? pattern.exec('/'+topic)
804
- : pattern.exec(topic);
805
-
806
- if (null === match) {
807
- return}
808
-
809
- if (false === keys) {
810
- let {groups} = match;
811
- if (! groups) {
812
- return [tgt]}
813
-
814
- let params = {};
815
- for (let k in groups) {
816
- params[k] = groups[k];}
817
-
818
- return [tgt, params]}
819
-
820
- if (0 === keys.length) {
821
- return [tgt]}
822
-
823
- let params = {};
824
- for (let i=0; i<keys.length; i++) {
825
- params[ keys[i] ] = match[1+i];}
826
- return [tgt, params]}
827
-
828
-
829
- function _mqtt_route_remove(all_route_lists, query) {
830
- let match = route => route===query || route.tgt===query || route.key===query;
831
- for (let lst of all_route_lists) {
832
- let i = lst.findIndex(match);
833
- if (0 <= i) {return !! lst.splice(i,1)} }
834
- return false}
835
-
836
896
  const _mqtt_cmdid_dispatch ={
837
897
  create(target) {
838
898
  return {__proto__: this, target, hashbelt: [new Map()]} }
@@ -901,8 +961,7 @@ const _mqtt_cmdid_dispatch ={
901
961
  let fn = target[`mqtt_${pkt.type}`]
902
962
  || target.mqtt_pkt;
903
963
 
904
- if (undefined !== fn) {
905
- await fn.call(target, pkt, ctx);} } })()) };
964
+ await fn?.call(target, pkt, ctx);} })()) };
906
965
 
907
966
  function _mqtt_dispatch(opt, target) {
908
967
  let _disp_ = _mqtt_cmdid_dispatch.create(target);
@@ -983,53 +1042,15 @@ class MQTTBase {
983
1042
 
984
1043
 
985
1044
  // alias: sub
986
- subscribe(pkt, ex) {
987
- pkt = _as_topics(pkt, ex);
1045
+ subscribe(pkt, ex, topic_prefix) {
1046
+ pkt = _as_topics(pkt, ex, topic_prefix);
988
1047
  return this._send('subscribe', pkt, pkt)}
989
- _sub_chain(topic, ex) {
990
- let res = this.subscribe([[ topic ]], ex);
991
- let subs = this.subs ||(this.subs = new Map());
992
- subs.set((res.topic = topic), (subs.last = res));
993
- return this }// fluent api -- return this and track side effects
994
1048
 
995
1049
  // alias: unsub
996
- unsubscribe(pkt, ex) {
997
- pkt = _as_topics(pkt, ex);
1050
+ unsubscribe(pkt, ex, topic_prefix) {
1051
+ pkt = _as_topics(pkt, ex, topic_prefix);
998
1052
  return this._send('unsubscribe', pkt, pkt)}
999
1053
 
1000
- get on_topic() {return this.router.add}
1001
-
1002
- // alias: sub_topic
1003
- subscribe_topic(topic_route, ...args) {
1004
- this.router.add(topic_route, true, args.pop() );// handler
1005
- let topic = this.topic_for(topic_route);
1006
- return this._sub_chain(topic, args.pop() ) }// ex
1007
-
1008
- // alias: unsub_topic
1009
- unsubscribe_topic(topic_route) {
1010
- this.router.remove(topic_route, true);
1011
- let topic = this.topic_for(topic_route);
1012
- return this.unsubscribe([[ topic ]]) }
1013
-
1014
- // alias: shared_sub
1015
- shared_subscribe(group, topic_route, ...args) {
1016
- this.router.add(topic_route, true, args.pop() );// handler
1017
- let topic = this.topic_for(topic_route);
1018
- if (null != group) {
1019
- topic = `$share/${group}/${topic}`;}
1020
- return this._sub_chain(topic, args.pop() ) }// ex
1021
-
1022
- // alias: shared_unsub
1023
- shared_unsubscribe(group, topic_route) {
1024
- this.router.remove(topic_route, true);
1025
- let topic = this.topic_for(topic_route);
1026
- if (null != group) {
1027
- topic = `$share/${group}/${topic}`;}
1028
- return this.unsubscribe([[ topic ]]) }
1029
-
1030
- topic_for(topic_route) {
1031
- return topic_route.replace(/[:*].*$/, '#')}
1032
-
1033
1054
 
1034
1055
  // alias: pub
1035
1056
  publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
@@ -1055,9 +1076,9 @@ class MQTTBase {
1055
1076
  if (undefined === cid) {
1056
1077
  this.client_id = cid = (
1057
1078
 
1058
-
1079
+
1059
1080
 
1060
- this.new_client_id(parts)
1081
+ this.new_client_id(parts)
1061
1082
  );}
1062
1083
 
1063
1084
  return cid}
@@ -1066,66 +1087,85 @@ class MQTTBase {
1066
1087
  return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
1067
1088
 
1068
1089
 
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+
1096
+
1069
1097
 
1070
1098
 
1099
+ // Internal API
1071
1100
 
1101
+ /* async _send(type, pkt) -- provided by _conn_ and transport */
1072
1102
 
1103
+ _init_dispatch(opt) {
1104
+ this.constructor?._once_();
1105
+ let router = this.router =
1106
+ this._init_router?.(opt, this);
1073
1107
 
1108
+ let tgt ={
1109
+ __proto__: opt.on_mqtt_type || {}
1110
+ , router};
1074
1111
 
1112
+ tgt.mqtt_publish ||= router?.invoke;
1113
+ return _mqtt_dispatch(this, tgt)}
1075
1114
 
1115
+ static _aliases() {
1116
+ return ' pub:publish sub:subscribe unsub:unsubscribe '}
1076
1117
 
1118
+ static _once_(self=this) {
1119
+ self._once_ = _=>0;
1120
+ self.MQTTError = MQTTError;
1121
+ let p = self.prototype;
1122
+ for (let alias of self._aliases().split(/\s+/)) {
1123
+ alias = alias.split(':');
1124
+ let fn = alias[1] && p[alias[1]];
1125
+ if (fn) {p[alias[0]] = fn;} } } }
1077
1126
 
1078
- // Internal API
1079
-
1080
- /* async _send(type, pkt) -- provided by _conn_ and transport */
1081
-
1082
- _init_router(opt) {
1083
- return this.router = _mqtt_topic_router()}
1084
1127
 
1085
- _init_dispatch(opt) {
1086
- let tgt ={
1087
- __proto__: opt.on_mqtt_type || {}
1088
- , router: this._init_router(opt, this)};
1128
+ /*
1129
+ on_mqtt_type = {
1130
+ mqtt_auth(pkt, ctx) ::
1131
+ mqtt_connect(pkt, ctx) ::
1132
+ mqtt_connack(pkt, ctx) ::
1133
+ mqtt_disconnect(pkt, ctx) ::
1134
+
1135
+ mqtt_publish(pkt, ctx)
1136
+ mqtt_subscribe(pkt, ctx) ::
1137
+ mqtt_unsubscribe(pkt, ctx) ::
1138
+
1139
+ mqtt_pingreq(pkt, ctx) ::
1140
+ mqtt_pingresp(pkt, ctx) ::
1141
+ }
1142
+ */
1089
1143
 
1090
- tgt.mqtt_publish ||= tgt.router.invoke;
1091
- return _mqtt_dispatch(this, tgt)} }
1092
1144
 
1145
+ const _prefix_topics = (topic_prefix, iterable) =>
1146
+ Array.from(iterable, value =>(
1147
+ value.trim // string
1148
+ ? _prefix_topics(topic_prefix, value)
1149
+ : topic_prefix + value) );
1093
1150
 
1094
- {
1095
- let p = MQTTBase.prototype;
1096
- Object.assign(p,{
1097
- MQTTError
1098
- , pub: p.publish
1099
- , sub: p.subscribe
1100
- , unsub: p.unsubscribe
1101
- , sub_topic: p.subscribe_topic
1102
- , unsub_topic: p.unsubscribe_topic
1103
- , shared_sub: p.shared_subscribe
1104
- , shared_unsub: p.shared_unsubscribe} );
1105
-
1106
- /*
1107
- p.on_mqtt_type = {
1108
- mqtt_auth(pkt, ctx) ::
1109
- mqtt_connect(pkt, ctx) ::
1110
- mqtt_connack(pkt, ctx) ::
1111
- mqtt_disconnect(pkt, ctx) ::
1112
-
1113
- mqtt_publish(pkt, ctx)
1114
- mqtt_subscribe(pkt, ctx) ::
1115
- mqtt_unsubscribe(pkt, ctx) ::
1116
-
1117
- mqtt_pingreq(pkt, ctx) ::
1118
- mqtt_pingresp(pkt, ctx) ::
1119
- }
1120
- */}
1151
+ function _as_topics(pkt, ex, topic_prefix) {
1152
+ if (ex?.trim) {// string
1153
+ topic_prefix = ex;
1154
+ ex = null;}
1121
1155
 
1156
+ pkt =(
1157
+ pkt.trim // string
1158
+ ? {topics:[pkt], ... ex}
1159
+ : pkt[Symbol.iterator]
1160
+ ? {topics:[... pkt], ... ex}
1161
+ : ex ? {...pkt, ...ex}
1162
+ : pkt);
1122
1163
 
1123
- function _as_topics(pkt, ex) {
1124
- if ('string' === typeof pkt) {
1125
- return {topics:[pkt], ... ex}}
1126
- if (pkt[Symbol.iterator]) {
1127
- return {topics:[... pkt], ... ex}}
1128
- return ex ? {...pkt, ...ex} : pkt}
1164
+ if (topic_prefix) {
1165
+ // particularly useful with shared queues, e.g.
1166
+ // topic_prefix = '$share/some-queue-name/'
1167
+ pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
1168
+ return pkt}
1129
1169
 
1130
1170
 
1131
1171
  async function _pub(self, pkt, pub_opt) {
@@ -1241,53 +1281,53 @@ class MQTTCore extends MQTTBase {
1241
1281
 
1242
1282
 
1243
1283
 
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1244
1290
 
1291
+
1292
+
1293
+
1294
+
1295
+
1245
1296
 
1297
+
1298
+
1299
+
1300
+
1301
+
1246
1302
 
1303
+
1304
+
1305
+
1306
+
1247
1307
 
1308
+
1309
+
1248
1310
 
1311
+
1312
+ with_tcp(...opt) {
1313
+ opt = this._conn_opt(opt);
1314
+ console.log({opt});
1315
+ return this._use_conn (() =>
1316
+ this.with_stream(
1317
+ node_net.connect(opt)) ) }
1249
1318
 
1319
+ with_tls(...opt) {
1320
+ opt = this._conn_opt(opt);
1321
+ return this._use_conn (() =>
1322
+ this.with_stream(
1323
+ node_tls.connect(opt)) ) }
1250
1324
 
1251
-
1252
-
1253
-
1254
-
1255
-
1256
-
1257
-
1258
-
1259
-
1260
-
1261
-
1262
-
1263
-
1264
-
1265
-
1266
-
1267
-
1268
-
1269
-
1270
-
1271
-
1272
- with_tcp(...opt) {
1273
- opt = this._conn_opt(opt);
1274
- console.log({opt});
1275
- return this._use_conn (() =>
1276
- this.with_stream(
1277
- node_net.connect(opt)) ) }
1278
-
1279
- with_tls(...opt) {
1280
- opt = this._conn_opt(opt);
1281
- return this._use_conn (() =>
1282
- this.with_stream(
1283
- node_tls.connect(opt)) ) }
1284
-
1285
- _conn_opt([a0, a1, a2]) {
1286
- // (port, hostname, options) or (url, options)
1287
- if (Number.isFinite(a0)) {
1288
- return {...a2, port: a0, host: a1}}
1289
- a0 = new URL(a0);
1290
- return {...a1, port: a0.port, host: a0.hostname}}
1325
+ _conn_opt([a0, a1, a2]) {
1326
+ // (port, hostname, options) or (url, options)
1327
+ if (Number.isFinite(a0)) {
1328
+ return {...a2, port: a0, host: a1}}
1329
+ a0 = new URL(a0);
1330
+ return {...a1, port: a0.port, host: a0.hostname}}
1291
1331
 
1292
1332
 
1293
1333
  with_stream(read_stream, write_stream) {
@@ -1333,10 +1373,11 @@ class MQTTCore extends MQTTBase {
1333
1373
 
1334
1374
  return this} }
1335
1375
 
1336
- const version = '0.3.2-0';
1376
+ const version = '0.4.0';
1337
1377
 
1338
1378
  const MQTTClient_v4 = /* #__PURE__ */
1339
- MQTTCore.mqtt_ctx(4, mqtt_opts_v4);
1379
+ with_topic_path_router(
1380
+ MQTTCore.mqtt_ctx(4, mqtt_opts_v4) );
1340
1381
 
1341
1382
  const mqtt_v4 = opt =>
1342
1383
  new MQTTClient_v4(opt);