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.
- package/README.md +5 -5
- package/cjs/basic-v4.cjs +1205 -0
- package/cjs/basic-v4.cjs.map +1 -0
- package/cjs/basic-v5.cjs +1469 -0
- package/cjs/basic-v5.cjs.map +1 -0
- package/cjs/index.cjs +308 -267
- package/cjs/index.cjs.map +1 -1
- package/cjs/v4.cjs +303 -262
- package/cjs/v4.cjs.map +1 -1
- package/cjs/v5.cjs +305 -263
- package/cjs/v5.cjs.map +1 -1
- package/code/_cmdid_dispatch.jsy +1 -3
- package/code/base.jsy +64 -84
- package/code/basic-v4.js +18 -0
- package/code/basic-v5.js +26 -0
- package/code/index.js +2 -1
- package/code/{_router.jsy → router_path.jsy} +30 -12
- package/code/v4.js +3 -1
- package/code/v5.js +5 -2
- package/code/with_topic_router.jsy +41 -0
- package/esm/deno/basic-v4.js +1193 -0
- package/esm/deno/basic-v4.js.map +1 -0
- package/esm/deno/basic-v5.js +1455 -0
- package/esm/deno/basic-v5.js.map +1 -0
- package/esm/deno/index.js +306 -264
- package/esm/deno/index.js.map +1 -1
- package/esm/deno/v4.js +303 -262
- package/esm/deno/v4.js.map +1 -1
- package/esm/deno/v5.js +305 -263
- package/esm/deno/v5.js.map +1 -1
- package/esm/node/basic-v4.js +1196 -0
- package/esm/node/basic-v4.js.map +1 -0
- package/esm/node/basic-v4.mjs +1196 -0
- package/esm/node/basic-v4.mjs.map +1 -0
- package/esm/node/basic-v5.js +1458 -0
- package/esm/node/basic-v5.js.map +1 -0
- package/esm/node/basic-v5.mjs +1458 -0
- package/esm/node/basic-v5.mjs.map +1 -0
- package/esm/node/index.js +306 -264
- package/esm/node/index.js.map +1 -1
- package/esm/node/index.mjs +306 -264
- package/esm/node/index.mjs.map +1 -1
- package/esm/node/v4.js +303 -262
- package/esm/node/v4.js.map +1 -1
- package/esm/node/v4.mjs +303 -262
- package/esm/node/v4.mjs.map +1 -1
- package/esm/node/v5.js +305 -263
- package/esm/node/v5.js.map +1 -1
- package/esm/node/v5.mjs +305 -263
- package/esm/node/v5.mjs.map +1 -1
- package/esm/web/basic-v4.js +1193 -0
- package/esm/web/basic-v4.js.map +1 -0
- package/esm/web/basic-v4.min.js +1 -0
- package/esm/web/basic-v4.min.js.br +0 -0
- package/esm/web/basic-v4.min.js.gz +0 -0
- package/esm/web/basic-v5.js +1455 -0
- package/esm/web/basic-v5.js.map +1 -0
- package/esm/web/basic-v5.min.js +1 -0
- package/esm/web/basic-v5.min.js.br +0 -0
- package/esm/web/basic-v5.min.js.gz +0 -0
- package/esm/web/index.js +305 -263
- package/esm/web/index.js.map +1 -1
- package/esm/web/index.min.js +1 -1
- package/esm/web/index.min.js.br +0 -0
- package/esm/web/index.min.js.gz +0 -0
- package/esm/web/v4.js +303 -262
- package/esm/web/v4.js.map +1 -1
- package/esm/web/v4.min.js +1 -1
- package/esm/web/v4.min.js.br +0 -0
- package/esm/web/v4.min.js.gz +0 -0
- package/esm/web/v5.js +304 -262
- package/esm/web/v5.js.map +1 -1
- package/esm/web/v5.min.js +1 -1
- package/esm/web/v5.min.js.br +0 -0
- package/esm/web/v5.min.js.gz +0 -0
- 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
|
-
|
|
708
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
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
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
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
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
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.
|
|
1376
|
+
const version = '0.4.0';
|
|
1337
1377
|
|
|
1338
1378
|
const MQTTClient_v4 = /* #__PURE__ */
|
|
1339
|
-
|
|
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);
|