u8-mqtt 0.3.2-0 → 0.4.1

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 +1200 -0
  3. package/cjs/basic-v4.cjs.map +1 -0
  4. package/cjs/basic-v5.cjs +1464 -0
  5. package/cjs/basic-v5.cjs.map +1 -0
  6. package/cjs/index.cjs +312 -269
  7. package/cjs/index.cjs.map +1 -1
  8. package/cjs/v4.cjs +307 -264
  9. package/cjs/v4.cjs.map +1 -1
  10. package/cjs/v5.cjs +309 -265
  11. package/cjs/v5.cjs.map +1 -1
  12. package/code/_cmdid_dispatch.jsy +1 -3
  13. package/code/base.jsy +64 -89
  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} +36 -12
  18. package/code/v4.js +3 -1
  19. package/code/v5.js +5 -2
  20. package/code/with_topic_router.jsy +42 -0
  21. package/esm/deno/basic-v4.js +1188 -0
  22. package/esm/deno/basic-v4.js.map +1 -0
  23. package/esm/deno/basic-v5.js +1450 -0
  24. package/esm/deno/basic-v5.js.map +1 -0
  25. package/esm/deno/index.js +310 -266
  26. package/esm/deno/index.js.map +1 -1
  27. package/esm/deno/v4.js +307 -264
  28. package/esm/deno/v4.js.map +1 -1
  29. package/esm/deno/v5.js +309 -265
  30. package/esm/deno/v5.js.map +1 -1
  31. package/esm/node/basic-v4.js +1191 -0
  32. package/esm/node/basic-v4.js.map +1 -0
  33. package/esm/node/basic-v4.mjs +1191 -0
  34. package/esm/node/basic-v4.mjs.map +1 -0
  35. package/esm/node/basic-v5.js +1453 -0
  36. package/esm/node/basic-v5.js.map +1 -0
  37. package/esm/node/basic-v5.mjs +1453 -0
  38. package/esm/node/basic-v5.mjs.map +1 -0
  39. package/esm/node/index.js +310 -266
  40. package/esm/node/index.js.map +1 -1
  41. package/esm/node/index.mjs +310 -266
  42. package/esm/node/index.mjs.map +1 -1
  43. package/esm/node/v4.js +307 -264
  44. package/esm/node/v4.js.map +1 -1
  45. package/esm/node/v4.mjs +307 -264
  46. package/esm/node/v4.mjs.map +1 -1
  47. package/esm/node/v5.js +309 -265
  48. package/esm/node/v5.js.map +1 -1
  49. package/esm/node/v5.mjs +309 -265
  50. package/esm/node/v5.mjs.map +1 -1
  51. package/esm/web/basic-v4.js +1188 -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 +1450 -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 +309 -265
  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 +307 -264
  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 +308 -264
  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/esm/deno/v4.js CHANGED
@@ -513,6 +513,198 @@ const mqtt_opts_v4 =
513
513
  encode_fns: mqtt_encode_v4,
514
514
  mqtt_writer: mqtt_writer_v4, };
515
515
 
516
+ function parse(str, loose) {
517
+ if (str instanceof RegExp) return { keys:false, pattern:str };
518
+ var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
519
+ arr[0] || arr.shift();
520
+
521
+ while (tmp = arr.shift()) {
522
+ c = tmp[0];
523
+ if (c === '*') {
524
+ keys.push('wild');
525
+ pattern += '/(.*)';
526
+ } else if (c === ':') {
527
+ o = tmp.indexOf('?', 1);
528
+ ext = tmp.indexOf('.', 1);
529
+ keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
530
+ pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
531
+ if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
532
+ } else {
533
+ pattern += '/' + tmp;
534
+ }
535
+ }
536
+
537
+ return {
538
+ keys: keys,
539
+ pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
540
+ };
541
+ }
542
+
543
+ /*
544
+ class AbstractTopicRouter ::
545
+ async invoke(pkt, ctx) ::
546
+ add(topic_route, ...args) ::
547
+ remove(topic_route, priority) ::
548
+ clear(priority) ::
549
+ find(topic) :: // optional
550
+ mqtt_topic(topic_route)
551
+ */
552
+
553
+ const with_topic_router = mqtt_topic_router =>
554
+ MQTTKlass => class extends MQTTKlass {
555
+ static _aliases() {
556
+ return super._aliases() +
557
+ ' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'}
558
+
559
+ _init_router(opt, client, target) {
560
+ let router = this.router = target.router =
561
+ mqtt_topic_router(opt, this);
562
+ return router?.invoke}
563
+ get on_topic() {return this.router.add}
564
+
565
+ _sub_chain(topic, ex, topic_prefix) {
566
+ let res = this.subscribe([[ topic ]], ex, topic_prefix);
567
+ let subs = this.subs ||(this.subs = new Map());
568
+ subs.set((res.topic = topic), (subs.last = res));
569
+ return this }// fluent api -- return this and track side effects
570
+
571
+ // alias: sub_topic
572
+ subscribe_topic(topic_route, ...args) {
573
+ let router = this.router;
574
+ router.add(topic_route, true, args.pop() );// handler
575
+ let topic = router.mqtt_topic(topic_route);
576
+ return this._sub_chain(topic, ...args ) }// ex, topic_prefix
577
+
578
+ // alias: unsub_topic
579
+ unsubscribe_topic(topic_route, ...args) {
580
+ let router = this.router;
581
+ router.remove(topic_route, true);
582
+ let topic = router.mqtt_topic(topic_route);
583
+ return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
584
+
585
+ // Use [regexparam][] for url-like topic parsing
586
+ // [regexparam]: https://github.com/lukeed/regexparam
587
+
588
+
589
+ const with_topic_path_router = /* #__PURE__ */
590
+ with_topic_router(mqtt_topic_path_router);
591
+
592
+
593
+ const mqtt_topic = topic_route =>
594
+ topic_route
595
+ .replace(/[*].*$/, '#')
596
+ .replace(/:\w+\??/g, '+');
597
+
598
+ /* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
599
+ 4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
600
+ ... MUST be specified either on its own or following a topic level separator.
601
+ In either case it MUST be the last character specified in the Topic Filter
602
+
603
+ 4.7.1.3 Single-level wildcard -- (‘+’ U+002B)
604
+ ...it MUST occupy an entire level of the filter.
605
+ */
606
+
607
+ const as_topic_path = (topic_route, id) =>(
608
+ id=1,
609
+ topic_route
610
+ .replace(/#$/, '*' )// replace MQTT '#' multi-level wildcard at end
611
+ .replace(/\+/g, () => `:$${id++}` ) );// replace MQTT '+' single-level wildcards
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
+
516
708
  /*
517
709
  export function decode_varint_loop(u8, i=0) {
518
710
  let i0 = i
@@ -694,138 +886,13 @@ function _ping_interval(send_ping) {
694
886
  if (td) {
695
887
  tid = setInterval(send_ping, 1000 * td);
696
888
 
697
- // ensure the interval allows the Deno event loop to exit
698
- Deno.unrefTimer(tid);
889
+ // ensure the interval allows the Deno event loop to exit
890
+ Deno.unrefTimer(tid);
699
891
 
700
-
701
-
892
+
893
+
702
894
  return true} }) }
703
895
 
704
- function parse(str, loose) {
705
- if (str instanceof RegExp) return { keys:false, pattern:str };
706
- var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
707
- arr[0] || arr.shift();
708
-
709
- while (tmp = arr.shift()) {
710
- c = tmp[0];
711
- if (c === '*') {
712
- keys.push('wild');
713
- pattern += '/(.*)';
714
- } else if (c === ':') {
715
- o = tmp.indexOf('?', 1);
716
- ext = tmp.indexOf('.', 1);
717
- keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
718
- pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
719
- if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
720
- } else {
721
- pattern += '/' + tmp;
722
- }
723
- }
724
-
725
- return {
726
- keys: keys,
727
- pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
728
- };
729
- }
730
-
731
- // Use [regexparam][] for url-like topic parsing
732
-
733
- function _ignore(pkt, params, ctx) {ctx.done = true;}
734
-
735
- function _mqtt_topic_router() {
736
- let pri_lsts = [[],[]], rm = Symbol();
737
- let find = topic => _mqtt_routes_iter(pri_lsts, topic);
738
-
739
- return {find,
740
-
741
- add(topic_route, ...args) {
742
- let fn = args.pop();
743
- let priority = args.pop();
744
-
745
- if ('function' !== typeof fn) {
746
- if (false === fn) {
747
- fn = _ignore;}
748
- else throw new TypeError()}
749
-
750
- let rte = parse(
751
- topic_route.replace(/[+#]$/, '*'));
752
-
753
- rte.key = topic_route;
754
- rte.tgt = fn;
755
- pri_lsts[priority ? 0 : 1].push(rte);
756
- return this}
757
-
758
- , remove(topic_route, priority) {
759
- let lst = pri_lsts[priority ? 0 : 1];
760
- return _mqtt_route_remove([lst], topic_route)}
761
-
762
- , clear(priority) {
763
- pri_lsts[priority ? 0 : 1] = [];
764
- if (null == priority) {
765
- pri_lsts[1] = [];} }
766
-
767
- , async invoke(pkt, ctx) {
768
- ctx.idx = 0;
769
- ctx.rm = rm;
770
-
771
- for (let [fn, params] of find(pkt.topic)) {
772
- let res = await fn(pkt, params, ctx);
773
-
774
- if (rm === res) {
775
- _mqtt_route_remove(pri_lsts, fn);}
776
-
777
- if (ctx.done) {
778
- break}
779
- else ctx.idx++;}
780
-
781
- let {pkt_id, qos} = pkt;
782
- if (1 === qos) {
783
- await ctx.mqtt._send('puback', {pkt_id});} } } }
784
-
785
-
786
- function * _mqtt_routes_iter(all_route_lists, topic) {
787
- for (let route_list of all_route_lists) {
788
- for (let route of route_list) {
789
- let res = _mqtt_route_match_one(topic, route);
790
- if (undefined !== res) {
791
- yield res;} } } }
792
-
793
-
794
- function _mqtt_route_match_one(topic, {keys, pattern, tgt}) {
795
- let match = '/' !== topic[0]
796
- ? pattern.exec('/'+topic)
797
- : pattern.exec(topic);
798
-
799
- if (null === match) {
800
- return}
801
-
802
- if (false === keys) {
803
- let {groups} = match;
804
- if (! groups) {
805
- return [tgt]}
806
-
807
- let params = {};
808
- for (let k in groups) {
809
- params[k] = groups[k];}
810
-
811
- return [tgt, params]}
812
-
813
- if (0 === keys.length) {
814
- return [tgt]}
815
-
816
- let params = {};
817
- for (let i=0; i<keys.length; i++) {
818
- params[ keys[i] ] = match[1+i];}
819
- return [tgt, params]}
820
-
821
-
822
- function _mqtt_route_remove(all_route_lists, query) {
823
- let match = route => route===query || route.tgt===query || route.key===query;
824
- for (let lst of all_route_lists) {
825
- let i = lst.findIndex(match);
826
- if (0 <= i) {return !! lst.splice(i,1)} }
827
- return false}
828
-
829
896
  const _mqtt_cmdid_dispatch ={
830
897
  create(target) {
831
898
  return {__proto__: this, target, hashbelt: [new Map()]} }
@@ -894,8 +961,7 @@ const _mqtt_cmdid_dispatch ={
894
961
  let fn = target[`mqtt_${pkt.type}`]
895
962
  || target.mqtt_pkt;
896
963
 
897
- if (undefined !== fn) {
898
- await fn.call(target, pkt, ctx);} } })()) };
964
+ await fn?.call(target, pkt, ctx);} })()) };
899
965
 
900
966
  function _mqtt_dispatch(opt, target) {
901
967
  let _disp_ = _mqtt_cmdid_dispatch.create(target);
@@ -976,53 +1042,15 @@ class MQTTBase {
976
1042
 
977
1043
 
978
1044
  // alias: sub
979
- subscribe(pkt, ex) {
980
- pkt = _as_topics(pkt, ex);
1045
+ subscribe(pkt, ex, topic_prefix) {
1046
+ pkt = _as_topics(pkt, ex, topic_prefix);
981
1047
  return this._send('subscribe', pkt, pkt)}
982
- _sub_chain(topic, ex) {
983
- let res = this.subscribe([[ topic ]], ex);
984
- let subs = this.subs ||(this.subs = new Map());
985
- subs.set((res.topic = topic), (subs.last = res));
986
- return this }// fluent api -- return this and track side effects
987
1048
 
988
1049
  // alias: unsub
989
- unsubscribe(pkt, ex) {
990
- pkt = _as_topics(pkt, ex);
1050
+ unsubscribe(pkt, ex, topic_prefix) {
1051
+ pkt = _as_topics(pkt, ex, topic_prefix);
991
1052
  return this._send('unsubscribe', pkt, pkt)}
992
1053
 
993
- get on_topic() {return this.router.add}
994
-
995
- // alias: sub_topic
996
- subscribe_topic(topic_route, ...args) {
997
- this.router.add(topic_route, true, args.pop() );// handler
998
- let topic = this.topic_for(topic_route);
999
- return this._sub_chain(topic, args.pop() ) }// ex
1000
-
1001
- // alias: unsub_topic
1002
- unsubscribe_topic(topic_route) {
1003
- this.router.remove(topic_route, true);
1004
- let topic = this.topic_for(topic_route);
1005
- return this.unsubscribe([[ topic ]]) }
1006
-
1007
- // alias: shared_sub
1008
- shared_subscribe(group, topic_route, ...args) {
1009
- this.router.add(topic_route, true, args.pop() );// handler
1010
- let topic = this.topic_for(topic_route);
1011
- if (null != group) {
1012
- topic = `$share/${group}/${topic}`;}
1013
- return this._sub_chain(topic, args.pop() ) }// ex
1014
-
1015
- // alias: shared_unsub
1016
- shared_unsubscribe(group, topic_route) {
1017
- this.router.remove(topic_route, true);
1018
- let topic = this.topic_for(topic_route);
1019
- if (null != group) {
1020
- topic = `$share/${group}/${topic}`;}
1021
- return this.unsubscribe([[ topic ]]) }
1022
-
1023
- topic_for(topic_route) {
1024
- return topic_route.replace(/[:*].*$/, '#')}
1025
-
1026
1054
 
1027
1055
  // alias: pub
1028
1056
  publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
@@ -1048,9 +1076,9 @@ class MQTTBase {
1048
1076
  if (undefined === cid) {
1049
1077
  this.client_id = cid = (
1050
1078
 
1051
-
1079
+
1052
1080
 
1053
- this.new_client_id(parts)
1081
+ this.new_client_id(parts)
1054
1082
  );}
1055
1083
 
1056
1084
  return cid}
@@ -1059,66 +1087,80 @@ class MQTTBase {
1059
1087
  return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
1060
1088
 
1061
1089
 
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+
1096
+
1062
1097
 
1063
1098
 
1099
+ // Internal API
1064
1100
 
1101
+ /* async _send(type, pkt) -- provided by _conn_ and transport */
1065
1102
 
1103
+ _init_dispatch(opt) {
1104
+ this.constructor?._once_();
1105
+ let target ={__proto__: opt.on_mqtt_type};
1106
+ target.mqtt_publish ||=
1107
+ this._init_router?.(opt, this, target);
1108
+ return _mqtt_dispatch(this, target)}
1066
1109
 
1110
+ static _aliases() {
1111
+ return ' pub:publish sub:subscribe unsub:unsubscribe '}
1067
1112
 
1113
+ static _once_(self=this) {
1114
+ self._once_ = _=>0;
1115
+ self.MQTTError = MQTTError;
1116
+ let p = self.prototype;
1117
+ for (let alias of self._aliases().split(/\s+/)) {
1118
+ alias = alias.split(':');
1119
+ let fn = alias[1] && p[alias[1]];
1120
+ if (fn) {p[alias[0]] = fn;} } } }
1068
1121
 
1069
1122
 
1123
+ /*
1124
+ on_mqtt_type = {
1125
+ mqtt_auth(pkt, ctx) ::
1126
+ mqtt_connect(pkt, ctx) ::
1127
+ mqtt_connack(pkt, ctx) ::
1128
+ mqtt_disconnect(pkt, ctx) ::
1129
+
1130
+ mqtt_publish(pkt, ctx)
1131
+ mqtt_subscribe(pkt, ctx) ::
1132
+ mqtt_unsubscribe(pkt, ctx) ::
1133
+
1134
+ mqtt_pingreq(pkt, ctx) ::
1135
+ mqtt_pingresp(pkt, ctx) ::
1136
+ }
1137
+ */
1070
1138
 
1071
- // Internal API
1072
-
1073
- /* async _send(type, pkt) -- provided by _conn_ and transport */
1074
-
1075
- _init_router(opt) {
1076
- return this.router = _mqtt_topic_router()}
1077
-
1078
- _init_dispatch(opt) {
1079
- let tgt ={
1080
- __proto__: opt.on_mqtt_type || {}
1081
- , router: this._init_router(opt, this)};
1082
-
1083
- tgt.mqtt_publish ||= tgt.router.invoke;
1084
- return _mqtt_dispatch(this, tgt)} }
1085
1139
 
1140
+ const _prefix_topics = (topic_prefix, iterable) =>
1141
+ Array.from(iterable, value =>(
1142
+ value.trim // string
1143
+ ? _prefix_topics(topic_prefix, value)
1144
+ : topic_prefix + value) );
1086
1145
 
1087
- {
1088
- let p = MQTTBase.prototype;
1089
- Object.assign(p,{
1090
- MQTTError
1091
- , pub: p.publish
1092
- , sub: p.subscribe
1093
- , unsub: p.unsubscribe
1094
- , sub_topic: p.subscribe_topic
1095
- , unsub_topic: p.unsubscribe_topic
1096
- , shared_sub: p.shared_subscribe
1097
- , shared_unsub: p.shared_unsubscribe} );
1098
-
1099
- /*
1100
- p.on_mqtt_type = {
1101
- mqtt_auth(pkt, ctx) ::
1102
- mqtt_connect(pkt, ctx) ::
1103
- mqtt_connack(pkt, ctx) ::
1104
- mqtt_disconnect(pkt, ctx) ::
1105
-
1106
- mqtt_publish(pkt, ctx)
1107
- mqtt_subscribe(pkt, ctx) ::
1108
- mqtt_unsubscribe(pkt, ctx) ::
1109
-
1110
- mqtt_pingreq(pkt, ctx) ::
1111
- mqtt_pingresp(pkt, ctx) ::
1112
- }
1113
- */}
1146
+ function _as_topics(pkt, ex, topic_prefix) {
1147
+ if (ex?.trim) {// string
1148
+ topic_prefix = ex;
1149
+ ex = null;}
1114
1150
 
1151
+ pkt =(
1152
+ pkt.trim // string
1153
+ ? {topics:[pkt], ... ex}
1154
+ : pkt[Symbol.iterator]
1155
+ ? {topics:[... pkt], ... ex}
1156
+ : ex ? {...pkt, ...ex}
1157
+ : pkt);
1115
1158
 
1116
- function _as_topics(pkt, ex) {
1117
- if ('string' === typeof pkt) {
1118
- return {topics:[pkt], ... ex}}
1119
- if (pkt[Symbol.iterator]) {
1120
- return {topics:[... pkt], ... ex}}
1121
- return ex ? {...pkt, ...ex} : pkt}
1159
+ if (topic_prefix) {
1160
+ // particularly useful with shared queues, e.g.
1161
+ // topic_prefix = '$share/some-queue-name/'
1162
+ pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
1163
+ return pkt}
1122
1164
 
1123
1165
 
1124
1166
  async function _pub(self, pkt, pub_opt) {
@@ -1234,53 +1276,53 @@ class MQTTCore extends MQTTBase {
1234
1276
 
1235
1277
 
1236
1278
 
1237
- with_tcp(...opt) {
1238
- opt = this._conn_opt(opt);
1239
- opt.transport = 'tcp';
1240
- return this._use_conn (() =>
1241
- this.with_deno_iter(
1242
- Deno.connect(opt)) ) }
1243
-
1244
- with_tls(...opt) {
1245
- opt = this._conn_opt(opt);
1246
- return this._use_conn (() =>
1247
- this.with_deno_iter(
1248
- Deno.connectTls(opt)) ) }
1249
-
1250
- with_deno_iter(conn) {
1251
- return this.with_async_iter(
1252
- conn.then(Deno.iter),
1253
- async u8_pkt =>
1254
- (await conn).write(u8_pkt)) }
1255
-
1256
- _conn_opt([a0, a1, a2]) {
1257
- // (port, hostname, options) or (url, options)
1258
- if (Number.isFinite(a0)) {
1259
- return {...a2, port: a0, hostname: a1}}
1260
-
1261
- a0 = new URL(a0);
1262
- return {...a1, port: a0.port, hostname: a0.hostname}}
1263
-
1264
-
1265
-
1266
-
1267
-
1268
-
1269
-
1270
-
1271
-
1272
-
1273
-
1274
-
1275
-
1276
-
1279
+ with_tcp(...opt) {
1280
+ opt = this._conn_opt(opt);
1281
+ opt.transport = 'tcp';
1282
+ return this._use_conn (() =>
1283
+ this.with_deno_iter(
1284
+ Deno.connect(opt)) ) }
1277
1285
 
1286
+ with_tls(...opt) {
1287
+ opt = this._conn_opt(opt);
1288
+ return this._use_conn (() =>
1289
+ this.with_deno_iter(
1290
+ Deno.connectTls(opt)) ) }
1278
1291
 
1292
+ with_deno_iter(conn) {
1293
+ return this.with_async_iter(
1294
+ conn.then(Deno.iter),
1295
+ async u8_pkt =>
1296
+ (await conn).write(u8_pkt)) }
1279
1297
 
1298
+ _conn_opt([a0, a1, a2]) {
1299
+ // (port, hostname, options) or (url, options)
1300
+ if (Number.isFinite(a0)) {
1301
+ return {...a2, port: a0, hostname: a1}}
1280
1302
 
1303
+ a0 = new URL(a0);
1304
+ return {...a1, port: a0.port, hostname: a0.hostname}}
1281
1305
 
1306
+
1307
+
1308
+
1309
+
1310
+
1311
+
1312
+
1282
1313
 
1314
+
1315
+
1316
+
1317
+
1318
+
1283
1319
 
1320
+
1321
+
1322
+
1323
+
1324
+
1325
+
1284
1326
 
1285
1327
 
1286
1328
  with_stream(read_stream, write_stream) {
@@ -1326,10 +1368,11 @@ class MQTTCore extends MQTTBase {
1326
1368
 
1327
1369
  return this} }
1328
1370
 
1329
- const version = '0.3.2-0';
1371
+ const version = '0.4.1';
1330
1372
 
1331
1373
  const MQTTClient_v4 = /* #__PURE__ */
1332
- MQTTCore.mqtt_ctx(4, mqtt_opts_v4);
1374
+ with_topic_path_router(
1375
+ MQTTCore.mqtt_ctx(4, mqtt_opts_v4) );
1333
1376
 
1334
1377
  const mqtt_v4 = opt =>
1335
1378
  new MQTTClient_v4(opt);