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