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/cjs/v4.cjs
CHANGED
|
@@ -520,6 +520,198 @@ 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, client, target) {
|
|
567
|
+
let router = this.router = target.router =
|
|
568
|
+
mqtt_topic_router(opt, this);
|
|
569
|
+
return router?.invoke}
|
|
570
|
+
get on_topic() {return this.router.add}
|
|
571
|
+
|
|
572
|
+
_sub_chain(topic, ex, topic_prefix) {
|
|
573
|
+
let res = this.subscribe([[ topic ]], ex, topic_prefix);
|
|
574
|
+
let subs = this.subs ||(this.subs = new Map());
|
|
575
|
+
subs.set((res.topic = topic), (subs.last = res));
|
|
576
|
+
return this }// fluent api -- return this and track side effects
|
|
577
|
+
|
|
578
|
+
// alias: sub_topic
|
|
579
|
+
subscribe_topic(topic_route, ...args) {
|
|
580
|
+
let router = this.router;
|
|
581
|
+
router.add(topic_route, true, args.pop() );// handler
|
|
582
|
+
let topic = router.mqtt_topic(topic_route);
|
|
583
|
+
return this._sub_chain(topic, ...args ) }// ex, topic_prefix
|
|
584
|
+
|
|
585
|
+
// alias: unsub_topic
|
|
586
|
+
unsubscribe_topic(topic_route, ...args) {
|
|
587
|
+
let router = this.router;
|
|
588
|
+
router.remove(topic_route, true);
|
|
589
|
+
let topic = router.mqtt_topic(topic_route);
|
|
590
|
+
return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
|
|
591
|
+
|
|
592
|
+
// Use [regexparam][] for url-like topic parsing
|
|
593
|
+
// [regexparam]: https://github.com/lukeed/regexparam
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
const with_topic_path_router = /* #__PURE__ */
|
|
597
|
+
with_topic_router(mqtt_topic_path_router);
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
const mqtt_topic = topic_route =>
|
|
601
|
+
topic_route
|
|
602
|
+
.replace(/[*].*$/, '#')
|
|
603
|
+
.replace(/:\w+\??/g, '+');
|
|
604
|
+
|
|
605
|
+
/* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
|
|
606
|
+
4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
|
|
607
|
+
... MUST be specified either on its own or following a topic level separator.
|
|
608
|
+
In either case it MUST be the last character specified in the Topic Filter
|
|
609
|
+
|
|
610
|
+
4.7.1.3 Single-level wildcard -- (‘+’ U+002B)
|
|
611
|
+
...it MUST occupy an entire level of the filter.
|
|
612
|
+
*/
|
|
613
|
+
|
|
614
|
+
const as_topic_path = (topic_route, id) =>(
|
|
615
|
+
id=1,
|
|
616
|
+
topic_route
|
|
617
|
+
.replace(/#$/, '*' )// replace MQTT '#' multi-level wildcard at end
|
|
618
|
+
.replace(/\+/g, () => `:$${id++}` ) );// replace MQTT '+' single-level wildcards
|
|
619
|
+
|
|
620
|
+
function _ignore(pkt, params, ctx) {ctx.done = true;}
|
|
621
|
+
|
|
622
|
+
function mqtt_topic_path_router() {
|
|
623
|
+
let pri_lsts = [[],[]], rm = Symbol();
|
|
624
|
+
let find = topic => _routes_iter(pri_lsts, topic);
|
|
625
|
+
|
|
626
|
+
// return duck-type compatible with AbstractTopicRouter in ./with_topic_router
|
|
627
|
+
return {find, mqtt_topic,
|
|
628
|
+
add(topic_route, ...args) {
|
|
629
|
+
let fn = args.pop();
|
|
630
|
+
let priority = args.pop();
|
|
631
|
+
|
|
632
|
+
if ('function' !== typeof fn) {
|
|
633
|
+
if (false === fn) {
|
|
634
|
+
fn = _ignore;}
|
|
635
|
+
else throw new TypeError()}
|
|
636
|
+
|
|
637
|
+
let rte = parse(as_topic_path(topic_route));
|
|
638
|
+
|
|
639
|
+
rte.key = topic_route;
|
|
640
|
+
rte.tgt = fn;
|
|
641
|
+
pri_lsts[priority ? 0 : 1].push(rte);
|
|
642
|
+
return this}
|
|
643
|
+
|
|
644
|
+
, remove(topic_route, priority) {
|
|
645
|
+
let lst = pri_lsts[priority ? 0 : 1];
|
|
646
|
+
return _route_remove([lst], topic_route)}
|
|
647
|
+
|
|
648
|
+
, clear(priority) {
|
|
649
|
+
pri_lsts[priority ? 0 : 1] = [];
|
|
650
|
+
if (null == priority) {
|
|
651
|
+
pri_lsts[1] = [];} }
|
|
652
|
+
|
|
653
|
+
, async invoke(pkt, ctx) {
|
|
654
|
+
ctx.idx = 0;
|
|
655
|
+
ctx.rm = rm;
|
|
656
|
+
|
|
657
|
+
for (let [fn, params] of find(pkt.topic)) {
|
|
658
|
+
let res = await fn(pkt, params, ctx);
|
|
659
|
+
|
|
660
|
+
if (rm === res) {
|
|
661
|
+
_route_remove(pri_lsts, fn);}
|
|
662
|
+
|
|
663
|
+
if (ctx.done) {
|
|
664
|
+
break}
|
|
665
|
+
else ctx.idx++;}
|
|
666
|
+
|
|
667
|
+
let {pkt_id, qos} = pkt;
|
|
668
|
+
if (1 === qos) {
|
|
669
|
+
await ctx.mqtt._send('puback', {pkt_id});} } } }
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
function * _routes_iter(all_route_lists, topic) {
|
|
673
|
+
for (let route_list of all_route_lists) {
|
|
674
|
+
for (let route of route_list) {
|
|
675
|
+
let res = _route_match_one(topic, route);
|
|
676
|
+
if (undefined !== res) {
|
|
677
|
+
yield res;} } } }
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
function _route_match_one(topic, {keys, pattern, tgt}) {
|
|
681
|
+
let match = '/' !== topic[0]
|
|
682
|
+
? pattern.exec('/'+topic)
|
|
683
|
+
: pattern.exec(topic);
|
|
684
|
+
|
|
685
|
+
if (null === match) {
|
|
686
|
+
return}
|
|
687
|
+
|
|
688
|
+
if (false === keys) {
|
|
689
|
+
let {groups} = match;
|
|
690
|
+
if (! groups) {
|
|
691
|
+
return [tgt]}
|
|
692
|
+
|
|
693
|
+
let params = {};
|
|
694
|
+
for (let k in groups) {
|
|
695
|
+
params[k] = groups[k];}
|
|
696
|
+
|
|
697
|
+
return [tgt, params]}
|
|
698
|
+
|
|
699
|
+
if (0 === keys.length) {
|
|
700
|
+
return [tgt]}
|
|
701
|
+
|
|
702
|
+
let params = {};
|
|
703
|
+
for (let i=0; i<keys.length; i++) {
|
|
704
|
+
params[ keys[i] ] = match[1+i];}
|
|
705
|
+
return [tgt, params]}
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
function _route_remove(all_route_lists, query) {
|
|
709
|
+
let match = route => route===query || route.tgt===query || route.key===query;
|
|
710
|
+
for (let lst of all_route_lists) {
|
|
711
|
+
let i = lst.findIndex(match);
|
|
712
|
+
if (0 <= i) {return !! lst.splice(i,1)} }
|
|
713
|
+
return false}
|
|
714
|
+
|
|
523
715
|
/*
|
|
524
716
|
export function decode_varint_loop(u8, i=0) {
|
|
525
717
|
let i0 = i
|
|
@@ -701,138 +893,13 @@ function _ping_interval(send_ping) {
|
|
|
701
893
|
if (td) {
|
|
702
894
|
tid = setInterval(send_ping, 1000 * td);
|
|
703
895
|
|
|
704
|
-
|
|
705
|
-
|
|
896
|
+
|
|
897
|
+
|
|
706
898
|
|
|
707
|
-
|
|
708
|
-
|
|
899
|
+
// ensure the interval allows the NodeJS event loop to exit
|
|
900
|
+
tid.unref?.();
|
|
709
901
|
return true} }) }
|
|
710
902
|
|
|
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
903
|
const _mqtt_cmdid_dispatch ={
|
|
837
904
|
create(target) {
|
|
838
905
|
return {__proto__: this, target, hashbelt: [new Map()]} }
|
|
@@ -901,8 +968,7 @@ const _mqtt_cmdid_dispatch ={
|
|
|
901
968
|
let fn = target[`mqtt_${pkt.type}`]
|
|
902
969
|
|| target.mqtt_pkt;
|
|
903
970
|
|
|
904
|
-
|
|
905
|
-
await fn.call(target, pkt, ctx);} } })()) };
|
|
971
|
+
await fn?.call(target, pkt, ctx);} })()) };
|
|
906
972
|
|
|
907
973
|
function _mqtt_dispatch(opt, target) {
|
|
908
974
|
let _disp_ = _mqtt_cmdid_dispatch.create(target);
|
|
@@ -983,53 +1049,15 @@ class MQTTBase {
|
|
|
983
1049
|
|
|
984
1050
|
|
|
985
1051
|
// alias: sub
|
|
986
|
-
subscribe(pkt, ex) {
|
|
987
|
-
pkt = _as_topics(pkt, ex);
|
|
1052
|
+
subscribe(pkt, ex, topic_prefix) {
|
|
1053
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
988
1054
|
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
1055
|
|
|
995
1056
|
// alias: unsub
|
|
996
|
-
unsubscribe(pkt, ex) {
|
|
997
|
-
pkt = _as_topics(pkt, ex);
|
|
1057
|
+
unsubscribe(pkt, ex, topic_prefix) {
|
|
1058
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
998
1059
|
return this._send('unsubscribe', pkt, pkt)}
|
|
999
1060
|
|
|
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
1061
|
|
|
1034
1062
|
// alias: pub
|
|
1035
1063
|
publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
|
|
@@ -1055,9 +1083,9 @@ class MQTTBase {
|
|
|
1055
1083
|
if (undefined === cid) {
|
|
1056
1084
|
this.client_id = cid = (
|
|
1057
1085
|
|
|
1058
|
-
|
|
1086
|
+
|
|
1059
1087
|
|
|
1060
|
-
|
|
1088
|
+
this.new_client_id(parts)
|
|
1061
1089
|
);}
|
|
1062
1090
|
|
|
1063
1091
|
return cid}
|
|
@@ -1066,66 +1094,80 @@ class MQTTBase {
|
|
|
1066
1094
|
return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
|
|
1067
1095
|
|
|
1068
1096
|
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
|
|
1069
1104
|
|
|
1070
1105
|
|
|
1106
|
+
// Internal API
|
|
1071
1107
|
|
|
1108
|
+
/* async _send(type, pkt) -- provided by _conn_ and transport */
|
|
1072
1109
|
|
|
1110
|
+
_init_dispatch(opt) {
|
|
1111
|
+
this.constructor?._once_();
|
|
1112
|
+
let target ={__proto__: opt.on_mqtt_type};
|
|
1113
|
+
target.mqtt_publish ||=
|
|
1114
|
+
this._init_router?.(opt, this, target);
|
|
1115
|
+
return _mqtt_dispatch(this, target)}
|
|
1073
1116
|
|
|
1117
|
+
static _aliases() {
|
|
1118
|
+
return ' pub:publish sub:subscribe unsub:unsubscribe '}
|
|
1074
1119
|
|
|
1120
|
+
static _once_(self=this) {
|
|
1121
|
+
self._once_ = _=>0;
|
|
1122
|
+
self.MQTTError = MQTTError;
|
|
1123
|
+
let p = self.prototype;
|
|
1124
|
+
for (let alias of self._aliases().split(/\s+/)) {
|
|
1125
|
+
alias = alias.split(':');
|
|
1126
|
+
let fn = alias[1] && p[alias[1]];
|
|
1127
|
+
if (fn) {p[alias[0]] = fn;} } } }
|
|
1075
1128
|
|
|
1076
1129
|
|
|
1130
|
+
/*
|
|
1131
|
+
on_mqtt_type = {
|
|
1132
|
+
mqtt_auth(pkt, ctx) ::
|
|
1133
|
+
mqtt_connect(pkt, ctx) ::
|
|
1134
|
+
mqtt_connack(pkt, ctx) ::
|
|
1135
|
+
mqtt_disconnect(pkt, ctx) ::
|
|
1136
|
+
|
|
1137
|
+
mqtt_publish(pkt, ctx)
|
|
1138
|
+
mqtt_subscribe(pkt, ctx) ::
|
|
1139
|
+
mqtt_unsubscribe(pkt, ctx) ::
|
|
1140
|
+
|
|
1141
|
+
mqtt_pingreq(pkt, ctx) ::
|
|
1142
|
+
mqtt_pingresp(pkt, ctx) ::
|
|
1143
|
+
}
|
|
1144
|
+
*/
|
|
1077
1145
|
|
|
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
|
-
|
|
1085
|
-
_init_dispatch(opt) {
|
|
1086
|
-
let tgt ={
|
|
1087
|
-
__proto__: opt.on_mqtt_type || {}
|
|
1088
|
-
, router: this._init_router(opt, this)};
|
|
1089
|
-
|
|
1090
|
-
tgt.mqtt_publish ||= tgt.router.invoke;
|
|
1091
|
-
return _mqtt_dispatch(this, tgt)} }
|
|
1092
1146
|
|
|
1147
|
+
const _prefix_topics = (topic_prefix, iterable) =>
|
|
1148
|
+
Array.from(iterable, value =>(
|
|
1149
|
+
value.trim // string
|
|
1150
|
+
? _prefix_topics(topic_prefix, value)
|
|
1151
|
+
: topic_prefix + value) );
|
|
1093
1152
|
|
|
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
|
-
*/}
|
|
1153
|
+
function _as_topics(pkt, ex, topic_prefix) {
|
|
1154
|
+
if (ex?.trim) {// string
|
|
1155
|
+
topic_prefix = ex;
|
|
1156
|
+
ex = null;}
|
|
1121
1157
|
|
|
1158
|
+
pkt =(
|
|
1159
|
+
pkt.trim // string
|
|
1160
|
+
? {topics:[pkt], ... ex}
|
|
1161
|
+
: pkt[Symbol.iterator]
|
|
1162
|
+
? {topics:[... pkt], ... ex}
|
|
1163
|
+
: ex ? {...pkt, ...ex}
|
|
1164
|
+
: pkt);
|
|
1122
1165
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
return ex ? {...pkt, ...ex} : pkt}
|
|
1166
|
+
if (topic_prefix) {
|
|
1167
|
+
// particularly useful with shared queues, e.g.
|
|
1168
|
+
// topic_prefix = '$share/some-queue-name/'
|
|
1169
|
+
pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
|
|
1170
|
+
return pkt}
|
|
1129
1171
|
|
|
1130
1172
|
|
|
1131
1173
|
async function _pub(self, pkt, pub_opt) {
|
|
@@ -1241,53 +1283,53 @@ class MQTTCore extends MQTTBase {
|
|
|
1241
1283
|
|
|
1242
1284
|
|
|
1243
1285
|
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
|
|
1244
1292
|
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
|
|
1297
|
+
|
|
1245
1298
|
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
|
|
1303
|
+
|
|
1246
1304
|
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
|
|
1247
1309
|
|
|
1310
|
+
|
|
1311
|
+
|
|
1248
1312
|
|
|
1313
|
+
|
|
1314
|
+
with_tcp(...opt) {
|
|
1315
|
+
opt = this._conn_opt(opt);
|
|
1316
|
+
console.log({opt});
|
|
1317
|
+
return this._use_conn (() =>
|
|
1318
|
+
this.with_stream(
|
|
1319
|
+
node_net.connect(opt)) ) }
|
|
1249
1320
|
|
|
1321
|
+
with_tls(...opt) {
|
|
1322
|
+
opt = this._conn_opt(opt);
|
|
1323
|
+
return this._use_conn (() =>
|
|
1324
|
+
this.with_stream(
|
|
1325
|
+
node_tls.connect(opt)) ) }
|
|
1250
1326
|
|
|
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}}
|
|
1327
|
+
_conn_opt([a0, a1, a2]) {
|
|
1328
|
+
// (port, hostname, options) or (url, options)
|
|
1329
|
+
if (Number.isFinite(a0)) {
|
|
1330
|
+
return {...a2, port: a0, host: a1}}
|
|
1331
|
+
a0 = new URL(a0);
|
|
1332
|
+
return {...a1, port: a0.port, host: a0.hostname}}
|
|
1291
1333
|
|
|
1292
1334
|
|
|
1293
1335
|
with_stream(read_stream, write_stream) {
|
|
@@ -1333,10 +1375,11 @@ class MQTTCore extends MQTTBase {
|
|
|
1333
1375
|
|
|
1334
1376
|
return this} }
|
|
1335
1377
|
|
|
1336
|
-
const version = '0.
|
|
1378
|
+
const version = '0.4.1';
|
|
1337
1379
|
|
|
1338
1380
|
const MQTTClient_v4 = /* #__PURE__ */
|
|
1339
|
-
|
|
1381
|
+
with_topic_path_router(
|
|
1382
|
+
MQTTCore.mqtt_ctx(4, mqtt_opts_v4) );
|
|
1340
1383
|
|
|
1341
1384
|
const mqtt_v4 = opt =>
|
|
1342
1385
|
new MQTTClient_v4(opt);
|