u8-mqtt 0.3.1 → 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 +312 -247
- package/cjs/index.cjs.map +1 -1
- package/cjs/v4.cjs +307 -242
- package/cjs/v4.cjs.map +1 -1
- package/cjs/v5.cjs +309 -243
- package/cjs/v5.cjs.map +1 -1
- package/code/_cmdid_dispatch.jsy +1 -3
- package/code/base.jsy +64 -84
- package/code/{v4.mjs → basic-v4.js} +1 -1
- package/code/{v5.mjs → basic-v5.js} +1 -1
- package/code/core.jsy +41 -15
- package/code/{index.mjs → index.js} +3 -2
- package/code/{_router.jsy → router_path.jsy} +30 -12
- package/code/v4.js +20 -0
- package/code/v5.js +29 -0
- package/code/version.js +1 -0
- 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 +307 -242
- package/esm/deno/index.js.map +1 -1
- package/esm/deno/v4.js +304 -240
- package/esm/deno/v4.js.map +1 -1
- package/esm/deno/v5.js +306 -241
- 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 +309 -243
- package/esm/node/index.js.map +1 -1
- package/esm/node/index.mjs +309 -243
- package/esm/node/index.mjs.map +1 -1
- package/esm/node/v4.js +306 -241
- package/esm/node/v4.js.map +1 -1
- package/esm/node/v4.mjs +306 -241
- package/esm/node/v4.mjs.map +1 -1
- package/esm/node/v5.js +308 -242
- package/esm/node/v5.js.map +1 -1
- package/esm/node/v5.mjs +308 -242
- 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 +307 -242
- 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 +305 -241
- 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 +306 -241
- 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 +7 -7
package/esm/node/v4.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { connect } from 'node:net';
|
|
2
|
+
import { connect as connect$1 } from 'node:tls';
|
|
2
3
|
|
|
3
4
|
function encode_varint(n, a=[]) {
|
|
4
5
|
do {
|
|
@@ -515,6 +516,191 @@ const mqtt_opts_v4 =
|
|
|
515
516
|
encode_fns: mqtt_encode_v4,
|
|
516
517
|
mqtt_writer: mqtt_writer_v4, };
|
|
517
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) {
|
|
563
|
+
return mqtt_topic_router(opt, this)}
|
|
564
|
+
|
|
565
|
+
get on_topic() {return this.router.add}
|
|
566
|
+
|
|
567
|
+
_sub_chain(topic, ex, topic_prefix) {
|
|
568
|
+
let res = this.subscribe([[ topic ]], ex, topic_prefix);
|
|
569
|
+
let subs = this.subs ||(this.subs = new Map());
|
|
570
|
+
subs.set((res.topic = topic), (subs.last = res));
|
|
571
|
+
return this }// fluent api -- return this and track side effects
|
|
572
|
+
|
|
573
|
+
// alias: sub_topic
|
|
574
|
+
subscribe_topic(topic_route, ...args) {
|
|
575
|
+
let router = this.router;
|
|
576
|
+
router.add(topic_route, true, args.pop() );// handler
|
|
577
|
+
let topic = router.mqtt_topic(topic_route);
|
|
578
|
+
return this._sub_chain(topic, ...args ) }// ex, topic_prefix
|
|
579
|
+
|
|
580
|
+
// alias: unsub_topic
|
|
581
|
+
unsubscribe_topic(topic_route, ...args) {
|
|
582
|
+
let router = this.router;
|
|
583
|
+
router.remove(topic_route, true);
|
|
584
|
+
let topic = router.mqtt_topic(topic_route);
|
|
585
|
+
return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
|
|
586
|
+
|
|
587
|
+
// Use [regexparam][] for url-like topic parsing
|
|
588
|
+
// [regexparam]: https://github.com/lukeed/regexparam
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
const with_topic_path_router = /* #__PURE__ */
|
|
592
|
+
with_topic_router(mqtt_topic_path_router);
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
const mqtt_topic = topic_route =>
|
|
596
|
+
topic_route
|
|
597
|
+
.replace(/[*].*$/, '#')
|
|
598
|
+
.replace(/:\w+\??/g, '+');
|
|
599
|
+
|
|
600
|
+
const as_topic_path = topic_route =>(
|
|
601
|
+
topic_route
|
|
602
|
+
.replace(/#$/, '*') // replace MQTT # wildcard at end
|
|
603
|
+
.split(/([^\/]*[+][^\/]*)/) // split on MQTT + match tokens
|
|
604
|
+
.reduce (( sz, v, idx ) => sz +(
|
|
605
|
+
idx & 1 // even entires are body, odd are MQTT + tokens
|
|
606
|
+
? `:$${1 + idx>>1}` // replace with `:$#` sequential ids, using ? for partial entries
|
|
607
|
+
: v ) ) );// pass through body
|
|
608
|
+
|
|
609
|
+
function _ignore(pkt, params, ctx) {ctx.done = true;}
|
|
610
|
+
|
|
611
|
+
function mqtt_topic_path_router() {
|
|
612
|
+
let pri_lsts = [[],[]], rm = Symbol();
|
|
613
|
+
let find = topic => _routes_iter(pri_lsts, topic);
|
|
614
|
+
|
|
615
|
+
// return duck-type compatible with AbstractTopicRouter in ./with_topic_router
|
|
616
|
+
return {find, mqtt_topic,
|
|
617
|
+
add(topic_route, ...args) {
|
|
618
|
+
let fn = args.pop();
|
|
619
|
+
let priority = args.pop();
|
|
620
|
+
|
|
621
|
+
if ('function' !== typeof fn) {
|
|
622
|
+
if (false === fn) {
|
|
623
|
+
fn = _ignore;}
|
|
624
|
+
else throw new TypeError()}
|
|
625
|
+
|
|
626
|
+
let rte = parse(as_topic_path(topic_route));
|
|
627
|
+
|
|
628
|
+
rte.key = topic_route;
|
|
629
|
+
rte.tgt = fn;
|
|
630
|
+
pri_lsts[priority ? 0 : 1].push(rte);
|
|
631
|
+
return this}
|
|
632
|
+
|
|
633
|
+
, remove(topic_route, priority) {
|
|
634
|
+
let lst = pri_lsts[priority ? 0 : 1];
|
|
635
|
+
return _route_remove([lst], topic_route)}
|
|
636
|
+
|
|
637
|
+
, clear(priority) {
|
|
638
|
+
pri_lsts[priority ? 0 : 1] = [];
|
|
639
|
+
if (null == priority) {
|
|
640
|
+
pri_lsts[1] = [];} }
|
|
641
|
+
|
|
642
|
+
, async invoke(pkt, ctx) {
|
|
643
|
+
ctx.idx = 0;
|
|
644
|
+
ctx.rm = rm;
|
|
645
|
+
|
|
646
|
+
for (let [fn, params] of find(pkt.topic)) {
|
|
647
|
+
let res = await fn(pkt, params, ctx);
|
|
648
|
+
|
|
649
|
+
if (rm === res) {
|
|
650
|
+
_route_remove(pri_lsts, fn);}
|
|
651
|
+
|
|
652
|
+
if (ctx.done) {
|
|
653
|
+
break}
|
|
654
|
+
else ctx.idx++;}
|
|
655
|
+
|
|
656
|
+
let {pkt_id, qos} = pkt;
|
|
657
|
+
if (1 === qos) {
|
|
658
|
+
await ctx.mqtt._send('puback', {pkt_id});} } } }
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
function * _routes_iter(all_route_lists, topic) {
|
|
662
|
+
for (let route_list of all_route_lists) {
|
|
663
|
+
for (let route of route_list) {
|
|
664
|
+
let res = _route_match_one(topic, route);
|
|
665
|
+
if (undefined !== res) {
|
|
666
|
+
yield res;} } } }
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
function _route_match_one(topic, {keys, pattern, tgt}) {
|
|
670
|
+
let match = '/' !== topic[0]
|
|
671
|
+
? pattern.exec('/'+topic)
|
|
672
|
+
: pattern.exec(topic);
|
|
673
|
+
|
|
674
|
+
if (null === match) {
|
|
675
|
+
return}
|
|
676
|
+
|
|
677
|
+
if (false === keys) {
|
|
678
|
+
let {groups} = match;
|
|
679
|
+
if (! groups) {
|
|
680
|
+
return [tgt]}
|
|
681
|
+
|
|
682
|
+
let params = {};
|
|
683
|
+
for (let k in groups) {
|
|
684
|
+
params[k] = groups[k];}
|
|
685
|
+
|
|
686
|
+
return [tgt, params]}
|
|
687
|
+
|
|
688
|
+
if (0 === keys.length) {
|
|
689
|
+
return [tgt]}
|
|
690
|
+
|
|
691
|
+
let params = {};
|
|
692
|
+
for (let i=0; i<keys.length; i++) {
|
|
693
|
+
params[ keys[i] ] = match[1+i];}
|
|
694
|
+
return [tgt, params]}
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
function _route_remove(all_route_lists, query) {
|
|
698
|
+
let match = route => route===query || route.tgt===query || route.key===query;
|
|
699
|
+
for (let lst of all_route_lists) {
|
|
700
|
+
let i = lst.findIndex(match);
|
|
701
|
+
if (0 <= i) {return !! lst.splice(i,1)} }
|
|
702
|
+
return false}
|
|
703
|
+
|
|
518
704
|
/*
|
|
519
705
|
export function decode_varint_loop(u8, i=0) {
|
|
520
706
|
let i0 = i
|
|
@@ -613,8 +799,6 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
|
|
|
613
799
|
}
|
|
614
800
|
}
|
|
615
801
|
|
|
616
|
-
Object.freeze({ao_done: true});
|
|
617
|
-
|
|
618
802
|
function ao_defer_ctx(as_res = (...args) => args) {
|
|
619
803
|
let y,n,_pset = (a,b) => { y=a, n=b; };
|
|
620
804
|
return p =>(
|
|
@@ -698,138 +882,13 @@ function _ping_interval(send_ping) {
|
|
|
698
882
|
if (td) {
|
|
699
883
|
tid = setInterval(send_ping, 1000 * td);
|
|
700
884
|
|
|
701
|
-
|
|
702
|
-
|
|
885
|
+
|
|
886
|
+
|
|
703
887
|
|
|
704
|
-
|
|
705
|
-
|
|
888
|
+
// ensure the interval allows the NodeJS event loop to exit
|
|
889
|
+
tid.unref?.();
|
|
706
890
|
return true} }) }
|
|
707
891
|
|
|
708
|
-
function parse(str, loose) {
|
|
709
|
-
if (str instanceof RegExp) return { keys:false, pattern:str };
|
|
710
|
-
var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
|
|
711
|
-
arr[0] || arr.shift();
|
|
712
|
-
|
|
713
|
-
while (tmp = arr.shift()) {
|
|
714
|
-
c = tmp[0];
|
|
715
|
-
if (c === '*') {
|
|
716
|
-
keys.push('wild');
|
|
717
|
-
pattern += '/(.*)';
|
|
718
|
-
} else if (c === ':') {
|
|
719
|
-
o = tmp.indexOf('?', 1);
|
|
720
|
-
ext = tmp.indexOf('.', 1);
|
|
721
|
-
keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
|
|
722
|
-
pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
|
|
723
|
-
if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
|
|
724
|
-
} else {
|
|
725
|
-
pattern += '/' + tmp;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
return {
|
|
730
|
-
keys: keys,
|
|
731
|
-
pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// Use [regexparam][] for url-like topic parsing
|
|
736
|
-
|
|
737
|
-
function _ignore(pkt, params, ctx) {ctx.done = true;}
|
|
738
|
-
|
|
739
|
-
function _mqtt_topic_router() {
|
|
740
|
-
let pri_lsts = [[],[]], rm = Symbol();
|
|
741
|
-
let find = topic => _mqtt_routes_iter(pri_lsts, topic);
|
|
742
|
-
|
|
743
|
-
return {find,
|
|
744
|
-
|
|
745
|
-
add(topic_route, ...args) {
|
|
746
|
-
let fn = args.pop();
|
|
747
|
-
let priority = args.pop();
|
|
748
|
-
|
|
749
|
-
if ('function' !== typeof fn) {
|
|
750
|
-
if (false === fn) {
|
|
751
|
-
fn = _ignore;}
|
|
752
|
-
else throw new TypeError()}
|
|
753
|
-
|
|
754
|
-
let rte = parse(
|
|
755
|
-
topic_route.replace(/[+#]$/, '*'));
|
|
756
|
-
|
|
757
|
-
rte.key = topic_route;
|
|
758
|
-
rte.tgt = fn;
|
|
759
|
-
pri_lsts[priority ? 0 : 1].push(rte);
|
|
760
|
-
return this}
|
|
761
|
-
|
|
762
|
-
, remove(topic_route, priority) {
|
|
763
|
-
let lst = pri_lsts[priority ? 0 : 1];
|
|
764
|
-
return _mqtt_route_remove([lst], topic_route)}
|
|
765
|
-
|
|
766
|
-
, clear(priority) {
|
|
767
|
-
pri_lsts[priority ? 0 : 1] = [];
|
|
768
|
-
if (null == priority) {
|
|
769
|
-
pri_lsts[1] = [];} }
|
|
770
|
-
|
|
771
|
-
, async invoke(pkt, ctx) {
|
|
772
|
-
ctx.idx = 0;
|
|
773
|
-
ctx.rm = rm;
|
|
774
|
-
|
|
775
|
-
for (let [fn, params] of find(pkt.topic)) {
|
|
776
|
-
let res = await fn(pkt, params, ctx);
|
|
777
|
-
|
|
778
|
-
if (rm === res) {
|
|
779
|
-
_mqtt_route_remove(pri_lsts, fn);}
|
|
780
|
-
|
|
781
|
-
if (ctx.done) {
|
|
782
|
-
break}
|
|
783
|
-
else ctx.idx++;}
|
|
784
|
-
|
|
785
|
-
let {pkt_id, qos} = pkt;
|
|
786
|
-
if (1 === qos) {
|
|
787
|
-
await ctx.mqtt._send('puback', {pkt_id});} } } }
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
function * _mqtt_routes_iter(all_route_lists, topic) {
|
|
791
|
-
for (let route_list of all_route_lists) {
|
|
792
|
-
for (let route of route_list) {
|
|
793
|
-
let res = _mqtt_route_match_one(topic, route);
|
|
794
|
-
if (undefined !== res) {
|
|
795
|
-
yield res;} } } }
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
function _mqtt_route_match_one(topic, {keys, pattern, tgt}) {
|
|
799
|
-
let match = '/' !== topic[0]
|
|
800
|
-
? pattern.exec('/'+topic)
|
|
801
|
-
: pattern.exec(topic);
|
|
802
|
-
|
|
803
|
-
if (null === match) {
|
|
804
|
-
return}
|
|
805
|
-
|
|
806
|
-
if (false === keys) {
|
|
807
|
-
let {groups} = match;
|
|
808
|
-
if (! groups) {
|
|
809
|
-
return [tgt]}
|
|
810
|
-
|
|
811
|
-
let params = {};
|
|
812
|
-
for (let k in groups) {
|
|
813
|
-
params[k] = groups[k];}
|
|
814
|
-
|
|
815
|
-
return [tgt, params]}
|
|
816
|
-
|
|
817
|
-
if (0 === keys.length) {
|
|
818
|
-
return [tgt]}
|
|
819
|
-
|
|
820
|
-
let params = {};
|
|
821
|
-
for (let i=0; i<keys.length; i++) {
|
|
822
|
-
params[ keys[i] ] = match[1+i];}
|
|
823
|
-
return [tgt, params]}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
function _mqtt_route_remove(all_route_lists, query) {
|
|
827
|
-
let match = route => route===query || route.tgt===query || route.key===query;
|
|
828
|
-
for (let lst of all_route_lists) {
|
|
829
|
-
let i = lst.findIndex(match);
|
|
830
|
-
if (0 <= i) {return !! lst.splice(i,1)} }
|
|
831
|
-
return false}
|
|
832
|
-
|
|
833
892
|
const _mqtt_cmdid_dispatch ={
|
|
834
893
|
create(target) {
|
|
835
894
|
return {__proto__: this, target, hashbelt: [new Map()]} }
|
|
@@ -898,8 +957,7 @@ const _mqtt_cmdid_dispatch ={
|
|
|
898
957
|
let fn = target[`mqtt_${pkt.type}`]
|
|
899
958
|
|| target.mqtt_pkt;
|
|
900
959
|
|
|
901
|
-
|
|
902
|
-
await fn.call(target, pkt, ctx);} } })()) };
|
|
960
|
+
await fn?.call(target, pkt, ctx);} })()) };
|
|
903
961
|
|
|
904
962
|
function _mqtt_dispatch(opt, target) {
|
|
905
963
|
let _disp_ = _mqtt_cmdid_dispatch.create(target);
|
|
@@ -980,53 +1038,15 @@ class MQTTBase {
|
|
|
980
1038
|
|
|
981
1039
|
|
|
982
1040
|
// alias: sub
|
|
983
|
-
subscribe(pkt, ex) {
|
|
984
|
-
pkt = _as_topics(pkt, ex);
|
|
1041
|
+
subscribe(pkt, ex, topic_prefix) {
|
|
1042
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
985
1043
|
return this._send('subscribe', pkt, pkt)}
|
|
986
|
-
_sub_chain(topic, ex) {
|
|
987
|
-
let res = this.subscribe([[ topic ]], ex);
|
|
988
|
-
let subs = this.subs ||(this.subs = new Map());
|
|
989
|
-
subs.set((res.topic = topic), (subs.last = res));
|
|
990
|
-
return this }// fluent api -- return this and track side effects
|
|
991
1044
|
|
|
992
1045
|
// alias: unsub
|
|
993
|
-
unsubscribe(pkt, ex) {
|
|
994
|
-
pkt = _as_topics(pkt, ex);
|
|
1046
|
+
unsubscribe(pkt, ex, topic_prefix) {
|
|
1047
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
995
1048
|
return this._send('unsubscribe', pkt, pkt)}
|
|
996
1049
|
|
|
997
|
-
get on_topic() {return this.router.add}
|
|
998
|
-
|
|
999
|
-
// alias: sub_topic
|
|
1000
|
-
subscribe_topic(topic_route, ...args) {
|
|
1001
|
-
this.router.add(topic_route, true, args.pop() );// handler
|
|
1002
|
-
let topic = this.topic_for(topic_route);
|
|
1003
|
-
return this._sub_chain(topic, args.pop() ) }// ex
|
|
1004
|
-
|
|
1005
|
-
// alias: unsub_topic
|
|
1006
|
-
unsubscribe_topic(topic_route) {
|
|
1007
|
-
this.router.remove(topic_route, true);
|
|
1008
|
-
let topic = this.topic_for(topic_route);
|
|
1009
|
-
return this.unsubscribe([[ topic ]]) }
|
|
1010
|
-
|
|
1011
|
-
// alias: shared_sub
|
|
1012
|
-
shared_subscribe(group, topic_route, ...args) {
|
|
1013
|
-
this.router.add(topic_route, true, args.pop() );// handler
|
|
1014
|
-
let topic = this.topic_for(topic_route);
|
|
1015
|
-
if (null != group) {
|
|
1016
|
-
topic = `$share/${group}/${topic}`;}
|
|
1017
|
-
return this._sub_chain(topic, args.pop() ) }// ex
|
|
1018
|
-
|
|
1019
|
-
// alias: shared_unsub
|
|
1020
|
-
shared_unsubscribe(group, topic_route) {
|
|
1021
|
-
this.router.remove(topic_route, true);
|
|
1022
|
-
let topic = this.topic_for(topic_route);
|
|
1023
|
-
if (null != group) {
|
|
1024
|
-
topic = `$share/${group}/${topic}`;}
|
|
1025
|
-
return this.unsubscribe([[ topic ]]) }
|
|
1026
|
-
|
|
1027
|
-
topic_for(topic_route) {
|
|
1028
|
-
return topic_route.replace(/[:*].*$/, '#')}
|
|
1029
|
-
|
|
1030
1050
|
|
|
1031
1051
|
// alias: pub
|
|
1032
1052
|
publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
|
|
@@ -1052,9 +1072,9 @@ class MQTTBase {
|
|
|
1052
1072
|
if (undefined === cid) {
|
|
1053
1073
|
this.client_id = cid = (
|
|
1054
1074
|
|
|
1055
|
-
|
|
1075
|
+
|
|
1056
1076
|
|
|
1057
|
-
|
|
1077
|
+
this.new_client_id(parts)
|
|
1058
1078
|
);}
|
|
1059
1079
|
|
|
1060
1080
|
return cid}
|
|
@@ -1063,66 +1083,85 @@ class MQTTBase {
|
|
|
1063
1083
|
return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
|
|
1064
1084
|
|
|
1065
1085
|
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1066
1093
|
|
|
1067
1094
|
|
|
1095
|
+
// Internal API
|
|
1068
1096
|
|
|
1097
|
+
/* async _send(type, pkt) -- provided by _conn_ and transport */
|
|
1069
1098
|
|
|
1099
|
+
_init_dispatch(opt) {
|
|
1100
|
+
this.constructor?._once_();
|
|
1101
|
+
let router = this.router =
|
|
1102
|
+
this._init_router?.(opt, this);
|
|
1070
1103
|
|
|
1104
|
+
let tgt ={
|
|
1105
|
+
__proto__: opt.on_mqtt_type || {}
|
|
1106
|
+
, router};
|
|
1071
1107
|
|
|
1108
|
+
tgt.mqtt_publish ||= router?.invoke;
|
|
1109
|
+
return _mqtt_dispatch(this, tgt)}
|
|
1072
1110
|
|
|
1111
|
+
static _aliases() {
|
|
1112
|
+
return ' pub:publish sub:subscribe unsub:unsubscribe '}
|
|
1073
1113
|
|
|
1114
|
+
static _once_(self=this) {
|
|
1115
|
+
self._once_ = _=>0;
|
|
1116
|
+
self.MQTTError = MQTTError;
|
|
1117
|
+
let p = self.prototype;
|
|
1118
|
+
for (let alias of self._aliases().split(/\s+/)) {
|
|
1119
|
+
alias = alias.split(':');
|
|
1120
|
+
let fn = alias[1] && p[alias[1]];
|
|
1121
|
+
if (fn) {p[alias[0]] = fn;} } } }
|
|
1074
1122
|
|
|
1075
|
-
// Internal API
|
|
1076
|
-
|
|
1077
|
-
/* async _send(type, pkt) -- provided by _conn_ and transport */
|
|
1078
|
-
|
|
1079
|
-
_init_router(opt) {
|
|
1080
|
-
return this.router = _mqtt_topic_router()}
|
|
1081
1123
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1124
|
+
/*
|
|
1125
|
+
on_mqtt_type = {
|
|
1126
|
+
mqtt_auth(pkt, ctx) ::
|
|
1127
|
+
mqtt_connect(pkt, ctx) ::
|
|
1128
|
+
mqtt_connack(pkt, ctx) ::
|
|
1129
|
+
mqtt_disconnect(pkt, ctx) ::
|
|
1130
|
+
|
|
1131
|
+
mqtt_publish(pkt, ctx)
|
|
1132
|
+
mqtt_subscribe(pkt, ctx) ::
|
|
1133
|
+
mqtt_unsubscribe(pkt, ctx) ::
|
|
1134
|
+
|
|
1135
|
+
mqtt_pingreq(pkt, ctx) ::
|
|
1136
|
+
mqtt_pingresp(pkt, ctx) ::
|
|
1137
|
+
}
|
|
1138
|
+
*/
|
|
1086
1139
|
|
|
1087
|
-
tgt.mqtt_publish ||= tgt.router.invoke;
|
|
1088
|
-
return _mqtt_dispatch(this, tgt)} }
|
|
1089
1140
|
|
|
1141
|
+
const _prefix_topics = (topic_prefix, iterable) =>
|
|
1142
|
+
Array.from(iterable, value =>(
|
|
1143
|
+
value.trim // string
|
|
1144
|
+
? _prefix_topics(topic_prefix, value)
|
|
1145
|
+
: topic_prefix + value) );
|
|
1090
1146
|
|
|
1091
|
-
{
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
, pub: p.publish
|
|
1096
|
-
, sub: p.subscribe
|
|
1097
|
-
, unsub: p.unsubscribe
|
|
1098
|
-
, sub_topic: p.subscribe_topic
|
|
1099
|
-
, unsub_topic: p.unsubscribe_topic
|
|
1100
|
-
, shared_sub: p.shared_subscribe
|
|
1101
|
-
, shared_unsub: p.shared_unsubscribe} );
|
|
1102
|
-
|
|
1103
|
-
/*
|
|
1104
|
-
p.on_mqtt_type = {
|
|
1105
|
-
mqtt_auth(pkt, ctx) ::
|
|
1106
|
-
mqtt_connect(pkt, ctx) ::
|
|
1107
|
-
mqtt_connack(pkt, ctx) ::
|
|
1108
|
-
mqtt_disconnect(pkt, ctx) ::
|
|
1109
|
-
|
|
1110
|
-
mqtt_publish(pkt, ctx)
|
|
1111
|
-
mqtt_subscribe(pkt, ctx) ::
|
|
1112
|
-
mqtt_unsubscribe(pkt, ctx) ::
|
|
1113
|
-
|
|
1114
|
-
mqtt_pingreq(pkt, ctx) ::
|
|
1115
|
-
mqtt_pingresp(pkt, ctx) ::
|
|
1116
|
-
}
|
|
1117
|
-
*/}
|
|
1147
|
+
function _as_topics(pkt, ex, topic_prefix) {
|
|
1148
|
+
if (ex?.trim) {// string
|
|
1149
|
+
topic_prefix = ex;
|
|
1150
|
+
ex = null;}
|
|
1118
1151
|
|
|
1152
|
+
pkt =(
|
|
1153
|
+
pkt.trim // string
|
|
1154
|
+
? {topics:[pkt], ... ex}
|
|
1155
|
+
: pkt[Symbol.iterator]
|
|
1156
|
+
? {topics:[... pkt], ... ex}
|
|
1157
|
+
: ex ? {...pkt, ...ex}
|
|
1158
|
+
: pkt);
|
|
1119
1159
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
return ex ? {...pkt, ...ex} : pkt}
|
|
1160
|
+
if (topic_prefix) {
|
|
1161
|
+
// particularly useful with shared queues, e.g.
|
|
1162
|
+
// topic_prefix = '$share/some-queue-name/'
|
|
1163
|
+
pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
|
|
1164
|
+
return pkt}
|
|
1126
1165
|
|
|
1127
1166
|
|
|
1128
1167
|
async function _pub(self, pkt, pub_opt) {
|
|
@@ -1194,7 +1233,7 @@ class MQTTCore extends MQTTBase {
|
|
|
1194
1233
|
return this}
|
|
1195
1234
|
|
|
1196
1235
|
//log_conn(evt, arg, err_arg) ::
|
|
1197
|
-
//console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
|
|
1236
|
+
// console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
|
|
1198
1237
|
|
|
1199
1238
|
on_live(client, is_reconnect) {
|
|
1200
1239
|
if (is_reconnect) {
|
|
@@ -1236,30 +1275,55 @@ class MQTTCore extends MQTTBase {
|
|
|
1236
1275
|
return this}
|
|
1237
1276
|
|
|
1238
1277
|
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
1278
|
|
|
1279
|
+
|
|
1280
|
+
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
|
|
1250
1286
|
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
|
|
1251
1292
|
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
|
|
1297
|
+
|
|
1252
1298
|
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
|
|
1253
1303
|
|
|
1304
|
+
|
|
1305
|
+
|
|
1254
1306
|
|
|
1255
1307
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
({
|
|
1308
|
+
with_tcp(...opt) {
|
|
1309
|
+
opt = this._conn_opt(opt);
|
|
1310
|
+
console.log({opt});
|
|
1311
|
+
return this._use_conn (() =>
|
|
1312
|
+
this.with_stream(
|
|
1313
|
+
connect(opt)) ) }
|
|
1314
|
+
|
|
1315
|
+
with_tls(...opt) {
|
|
1316
|
+
opt = this._conn_opt(opt);
|
|
1317
|
+
return this._use_conn (() =>
|
|
1318
|
+
this.with_stream(
|
|
1319
|
+
connect$1(opt)) ) }
|
|
1259
1320
|
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1321
|
+
_conn_opt([a0, a1, a2]) {
|
|
1322
|
+
// (port, hostname, options) or (url, options)
|
|
1323
|
+
if (Number.isFinite(a0)) {
|
|
1324
|
+
return {...a2, port: a0, host: a1}}
|
|
1325
|
+
a0 = new URL(a0);
|
|
1326
|
+
return {...a1, port: a0.port, host: a0.hostname}}
|
|
1263
1327
|
|
|
1264
1328
|
|
|
1265
1329
|
with_stream(read_stream, write_stream) {
|
|
@@ -1305,10 +1369,11 @@ class MQTTCore extends MQTTBase {
|
|
|
1305
1369
|
|
|
1306
1370
|
return this} }
|
|
1307
1371
|
|
|
1308
|
-
|
|
1372
|
+
const version = '0.4.0';
|
|
1309
1373
|
|
|
1310
1374
|
const MQTTClient_v4 = /* #__PURE__ */
|
|
1311
|
-
|
|
1375
|
+
with_topic_path_router(
|
|
1376
|
+
MQTTCore.mqtt_ctx(4, mqtt_opts_v4) );
|
|
1312
1377
|
|
|
1313
1378
|
const mqtt_v4 = opt =>
|
|
1314
1379
|
new MQTTClient_v4(opt);
|