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/cjs/v4.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var node_net = require('node:net');
|
|
6
|
+
var node_tls = require('node:tls');
|
|
6
7
|
|
|
7
8
|
function encode_varint(n, a=[]) {
|
|
8
9
|
do {
|
|
@@ -519,6 +520,191 @@ const mqtt_opts_v4 =
|
|
|
519
520
|
encode_fns: mqtt_encode_v4,
|
|
520
521
|
mqtt_writer: mqtt_writer_v4, };
|
|
521
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
|
+
|
|
522
708
|
/*
|
|
523
709
|
export function decode_varint_loop(u8, i=0) {
|
|
524
710
|
let i0 = i
|
|
@@ -617,8 +803,6 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
|
|
|
617
803
|
}
|
|
618
804
|
}
|
|
619
805
|
|
|
620
|
-
Object.freeze({ao_done: true});
|
|
621
|
-
|
|
622
806
|
function ao_defer_ctx(as_res = (...args) => args) {
|
|
623
807
|
let y,n,_pset = (a,b) => { y=a, n=b; };
|
|
624
808
|
return p =>(
|
|
@@ -702,138 +886,13 @@ function _ping_interval(send_ping) {
|
|
|
702
886
|
if (td) {
|
|
703
887
|
tid = setInterval(send_ping, 1000 * td);
|
|
704
888
|
|
|
705
|
-
|
|
706
|
-
|
|
889
|
+
|
|
890
|
+
|
|
707
891
|
|
|
708
|
-
|
|
709
|
-
|
|
892
|
+
// ensure the interval allows the NodeJS event loop to exit
|
|
893
|
+
tid.unref?.();
|
|
710
894
|
return true} }) }
|
|
711
895
|
|
|
712
|
-
function parse(str, loose) {
|
|
713
|
-
if (str instanceof RegExp) return { keys:false, pattern:str };
|
|
714
|
-
var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
|
|
715
|
-
arr[0] || arr.shift();
|
|
716
|
-
|
|
717
|
-
while (tmp = arr.shift()) {
|
|
718
|
-
c = tmp[0];
|
|
719
|
-
if (c === '*') {
|
|
720
|
-
keys.push('wild');
|
|
721
|
-
pattern += '/(.*)';
|
|
722
|
-
} else if (c === ':') {
|
|
723
|
-
o = tmp.indexOf('?', 1);
|
|
724
|
-
ext = tmp.indexOf('.', 1);
|
|
725
|
-
keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
|
|
726
|
-
pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
|
|
727
|
-
if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
|
|
728
|
-
} else {
|
|
729
|
-
pattern += '/' + tmp;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
return {
|
|
734
|
-
keys: keys,
|
|
735
|
-
pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
|
|
736
|
-
};
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// Use [regexparam][] for url-like topic parsing
|
|
740
|
-
|
|
741
|
-
function _ignore(pkt, params, ctx) {ctx.done = true;}
|
|
742
|
-
|
|
743
|
-
function _mqtt_topic_router() {
|
|
744
|
-
let pri_lsts = [[],[]], rm = Symbol();
|
|
745
|
-
let find = topic => _mqtt_routes_iter(pri_lsts, topic);
|
|
746
|
-
|
|
747
|
-
return {find,
|
|
748
|
-
|
|
749
|
-
add(topic_route, ...args) {
|
|
750
|
-
let fn = args.pop();
|
|
751
|
-
let priority = args.pop();
|
|
752
|
-
|
|
753
|
-
if ('function' !== typeof fn) {
|
|
754
|
-
if (false === fn) {
|
|
755
|
-
fn = _ignore;}
|
|
756
|
-
else throw new TypeError()}
|
|
757
|
-
|
|
758
|
-
let rte = parse(
|
|
759
|
-
topic_route.replace(/[+#]$/, '*'));
|
|
760
|
-
|
|
761
|
-
rte.key = topic_route;
|
|
762
|
-
rte.tgt = fn;
|
|
763
|
-
pri_lsts[priority ? 0 : 1].push(rte);
|
|
764
|
-
return this}
|
|
765
|
-
|
|
766
|
-
, remove(topic_route, priority) {
|
|
767
|
-
let lst = pri_lsts[priority ? 0 : 1];
|
|
768
|
-
return _mqtt_route_remove([lst], topic_route)}
|
|
769
|
-
|
|
770
|
-
, clear(priority) {
|
|
771
|
-
pri_lsts[priority ? 0 : 1] = [];
|
|
772
|
-
if (null == priority) {
|
|
773
|
-
pri_lsts[1] = [];} }
|
|
774
|
-
|
|
775
|
-
, async invoke(pkt, ctx) {
|
|
776
|
-
ctx.idx = 0;
|
|
777
|
-
ctx.rm = rm;
|
|
778
|
-
|
|
779
|
-
for (let [fn, params] of find(pkt.topic)) {
|
|
780
|
-
let res = await fn(pkt, params, ctx);
|
|
781
|
-
|
|
782
|
-
if (rm === res) {
|
|
783
|
-
_mqtt_route_remove(pri_lsts, fn);}
|
|
784
|
-
|
|
785
|
-
if (ctx.done) {
|
|
786
|
-
break}
|
|
787
|
-
else ctx.idx++;}
|
|
788
|
-
|
|
789
|
-
let {pkt_id, qos} = pkt;
|
|
790
|
-
if (1 === qos) {
|
|
791
|
-
await ctx.mqtt._send('puback', {pkt_id});} } } }
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
function * _mqtt_routes_iter(all_route_lists, topic) {
|
|
795
|
-
for (let route_list of all_route_lists) {
|
|
796
|
-
for (let route of route_list) {
|
|
797
|
-
let res = _mqtt_route_match_one(topic, route);
|
|
798
|
-
if (undefined !== res) {
|
|
799
|
-
yield res;} } } }
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
function _mqtt_route_match_one(topic, {keys, pattern, tgt}) {
|
|
803
|
-
let match = '/' !== topic[0]
|
|
804
|
-
? pattern.exec('/'+topic)
|
|
805
|
-
: pattern.exec(topic);
|
|
806
|
-
|
|
807
|
-
if (null === match) {
|
|
808
|
-
return}
|
|
809
|
-
|
|
810
|
-
if (false === keys) {
|
|
811
|
-
let {groups} = match;
|
|
812
|
-
if (! groups) {
|
|
813
|
-
return [tgt]}
|
|
814
|
-
|
|
815
|
-
let params = {};
|
|
816
|
-
for (let k in groups) {
|
|
817
|
-
params[k] = groups[k];}
|
|
818
|
-
|
|
819
|
-
return [tgt, params]}
|
|
820
|
-
|
|
821
|
-
if (0 === keys.length) {
|
|
822
|
-
return [tgt]}
|
|
823
|
-
|
|
824
|
-
let params = {};
|
|
825
|
-
for (let i=0; i<keys.length; i++) {
|
|
826
|
-
params[ keys[i] ] = match[1+i];}
|
|
827
|
-
return [tgt, params]}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
function _mqtt_route_remove(all_route_lists, query) {
|
|
831
|
-
let match = route => route===query || route.tgt===query || route.key===query;
|
|
832
|
-
for (let lst of all_route_lists) {
|
|
833
|
-
let i = lst.findIndex(match);
|
|
834
|
-
if (0 <= i) {return !! lst.splice(i,1)} }
|
|
835
|
-
return false}
|
|
836
|
-
|
|
837
896
|
const _mqtt_cmdid_dispatch ={
|
|
838
897
|
create(target) {
|
|
839
898
|
return {__proto__: this, target, hashbelt: [new Map()]} }
|
|
@@ -902,8 +961,7 @@ const _mqtt_cmdid_dispatch ={
|
|
|
902
961
|
let fn = target[`mqtt_${pkt.type}`]
|
|
903
962
|
|| target.mqtt_pkt;
|
|
904
963
|
|
|
905
|
-
|
|
906
|
-
await fn.call(target, pkt, ctx);} } })()) };
|
|
964
|
+
await fn?.call(target, pkt, ctx);} })()) };
|
|
907
965
|
|
|
908
966
|
function _mqtt_dispatch(opt, target) {
|
|
909
967
|
let _disp_ = _mqtt_cmdid_dispatch.create(target);
|
|
@@ -984,53 +1042,15 @@ class MQTTBase {
|
|
|
984
1042
|
|
|
985
1043
|
|
|
986
1044
|
// alias: sub
|
|
987
|
-
subscribe(pkt, ex) {
|
|
988
|
-
pkt = _as_topics(pkt, ex);
|
|
1045
|
+
subscribe(pkt, ex, topic_prefix) {
|
|
1046
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
989
1047
|
return this._send('subscribe', pkt, pkt)}
|
|
990
|
-
_sub_chain(topic, ex) {
|
|
991
|
-
let res = this.subscribe([[ topic ]], ex);
|
|
992
|
-
let subs = this.subs ||(this.subs = new Map());
|
|
993
|
-
subs.set((res.topic = topic), (subs.last = res));
|
|
994
|
-
return this }// fluent api -- return this and track side effects
|
|
995
1048
|
|
|
996
1049
|
// alias: unsub
|
|
997
|
-
unsubscribe(pkt, ex) {
|
|
998
|
-
pkt = _as_topics(pkt, ex);
|
|
1050
|
+
unsubscribe(pkt, ex, topic_prefix) {
|
|
1051
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
999
1052
|
return this._send('unsubscribe', pkt, pkt)}
|
|
1000
1053
|
|
|
1001
|
-
get on_topic() {return this.router.add}
|
|
1002
|
-
|
|
1003
|
-
// alias: sub_topic
|
|
1004
|
-
subscribe_topic(topic_route, ...args) {
|
|
1005
|
-
this.router.add(topic_route, true, args.pop() );// handler
|
|
1006
|
-
let topic = this.topic_for(topic_route);
|
|
1007
|
-
return this._sub_chain(topic, args.pop() ) }// ex
|
|
1008
|
-
|
|
1009
|
-
// alias: unsub_topic
|
|
1010
|
-
unsubscribe_topic(topic_route) {
|
|
1011
|
-
this.router.remove(topic_route, true);
|
|
1012
|
-
let topic = this.topic_for(topic_route);
|
|
1013
|
-
return this.unsubscribe([[ topic ]]) }
|
|
1014
|
-
|
|
1015
|
-
// alias: shared_sub
|
|
1016
|
-
shared_subscribe(group, topic_route, ...args) {
|
|
1017
|
-
this.router.add(topic_route, true, args.pop() );// handler
|
|
1018
|
-
let topic = this.topic_for(topic_route);
|
|
1019
|
-
if (null != group) {
|
|
1020
|
-
topic = `$share/${group}/${topic}`;}
|
|
1021
|
-
return this._sub_chain(topic, args.pop() ) }// ex
|
|
1022
|
-
|
|
1023
|
-
// alias: shared_unsub
|
|
1024
|
-
shared_unsubscribe(group, topic_route) {
|
|
1025
|
-
this.router.remove(topic_route, true);
|
|
1026
|
-
let topic = this.topic_for(topic_route);
|
|
1027
|
-
if (null != group) {
|
|
1028
|
-
topic = `$share/${group}/${topic}`;}
|
|
1029
|
-
return this.unsubscribe([[ topic ]]) }
|
|
1030
|
-
|
|
1031
|
-
topic_for(topic_route) {
|
|
1032
|
-
return topic_route.replace(/[:*].*$/, '#')}
|
|
1033
|
-
|
|
1034
1054
|
|
|
1035
1055
|
// alias: pub
|
|
1036
1056
|
publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
|
|
@@ -1056,9 +1076,9 @@ class MQTTBase {
|
|
|
1056
1076
|
if (undefined === cid) {
|
|
1057
1077
|
this.client_id = cid = (
|
|
1058
1078
|
|
|
1059
|
-
|
|
1079
|
+
|
|
1060
1080
|
|
|
1061
|
-
|
|
1081
|
+
this.new_client_id(parts)
|
|
1062
1082
|
);}
|
|
1063
1083
|
|
|
1064
1084
|
return cid}
|
|
@@ -1067,66 +1087,85 @@ class MQTTBase {
|
|
|
1067
1087
|
return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
|
|
1068
1088
|
|
|
1069
1089
|
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
|
|
1070
1097
|
|
|
1071
1098
|
|
|
1099
|
+
// Internal API
|
|
1072
1100
|
|
|
1101
|
+
/* async _send(type, pkt) -- provided by _conn_ and transport */
|
|
1073
1102
|
|
|
1103
|
+
_init_dispatch(opt) {
|
|
1104
|
+
this.constructor?._once_();
|
|
1105
|
+
let router = this.router =
|
|
1106
|
+
this._init_router?.(opt, this);
|
|
1074
1107
|
|
|
1108
|
+
let tgt ={
|
|
1109
|
+
__proto__: opt.on_mqtt_type || {}
|
|
1110
|
+
, router};
|
|
1075
1111
|
|
|
1112
|
+
tgt.mqtt_publish ||= router?.invoke;
|
|
1113
|
+
return _mqtt_dispatch(this, tgt)}
|
|
1076
1114
|
|
|
1115
|
+
static _aliases() {
|
|
1116
|
+
return ' pub:publish sub:subscribe unsub:unsubscribe '}
|
|
1077
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;} } } }
|
|
1078
1126
|
|
|
1079
|
-
// Internal API
|
|
1080
|
-
|
|
1081
|
-
/* async _send(type, pkt) -- provided by _conn_ and transport */
|
|
1082
|
-
|
|
1083
|
-
_init_router(opt) {
|
|
1084
|
-
return this.router = _mqtt_topic_router()}
|
|
1085
1127
|
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
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
|
+
*/
|
|
1090
1143
|
|
|
1091
|
-
tgt.mqtt_publish ||= tgt.router.invoke;
|
|
1092
|
-
return _mqtt_dispatch(this, tgt)} }
|
|
1093
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) );
|
|
1094
1150
|
|
|
1095
|
-
{
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
, pub: p.publish
|
|
1100
|
-
, sub: p.subscribe
|
|
1101
|
-
, unsub: p.unsubscribe
|
|
1102
|
-
, sub_topic: p.subscribe_topic
|
|
1103
|
-
, unsub_topic: p.unsubscribe_topic
|
|
1104
|
-
, shared_sub: p.shared_subscribe
|
|
1105
|
-
, shared_unsub: p.shared_unsubscribe} );
|
|
1106
|
-
|
|
1107
|
-
/*
|
|
1108
|
-
p.on_mqtt_type = {
|
|
1109
|
-
mqtt_auth(pkt, ctx) ::
|
|
1110
|
-
mqtt_connect(pkt, ctx) ::
|
|
1111
|
-
mqtt_connack(pkt, ctx) ::
|
|
1112
|
-
mqtt_disconnect(pkt, ctx) ::
|
|
1113
|
-
|
|
1114
|
-
mqtt_publish(pkt, ctx)
|
|
1115
|
-
mqtt_subscribe(pkt, ctx) ::
|
|
1116
|
-
mqtt_unsubscribe(pkt, ctx) ::
|
|
1117
|
-
|
|
1118
|
-
mqtt_pingreq(pkt, ctx) ::
|
|
1119
|
-
mqtt_pingresp(pkt, ctx) ::
|
|
1120
|
-
}
|
|
1121
|
-
*/}
|
|
1151
|
+
function _as_topics(pkt, ex, topic_prefix) {
|
|
1152
|
+
if (ex?.trim) {// string
|
|
1153
|
+
topic_prefix = ex;
|
|
1154
|
+
ex = null;}
|
|
1122
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);
|
|
1123
1163
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
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}
|
|
1130
1169
|
|
|
1131
1170
|
|
|
1132
1171
|
async function _pub(self, pkt, pub_opt) {
|
|
@@ -1198,7 +1237,7 @@ class MQTTCore extends MQTTBase {
|
|
|
1198
1237
|
return this}
|
|
1199
1238
|
|
|
1200
1239
|
//log_conn(evt, arg, err_arg) ::
|
|
1201
|
-
//console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
|
|
1240
|
+
// console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
|
|
1202
1241
|
|
|
1203
1242
|
on_live(client, is_reconnect) {
|
|
1204
1243
|
if (is_reconnect) {
|
|
@@ -1240,30 +1279,55 @@ class MQTTCore extends MQTTBase {
|
|
|
1240
1279
|
return this}
|
|
1241
1280
|
|
|
1242
1281
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
1282
|
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
|
|
1254
1290
|
|
|
1291
|
+
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
|
|
1255
1296
|
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
|
|
1256
1302
|
|
|
1303
|
+
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
|
|
1257
1307
|
|
|
1308
|
+
|
|
1309
|
+
|
|
1258
1310
|
|
|
1259
1311
|
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
({
|
|
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)) ) }
|
|
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)) ) }
|
|
1263
1324
|
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
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}}
|
|
1267
1331
|
|
|
1268
1332
|
|
|
1269
1333
|
with_stream(read_stream, write_stream) {
|
|
@@ -1309,17 +1373,18 @@ class MQTTCore extends MQTTBase {
|
|
|
1309
1373
|
|
|
1310
1374
|
return this} }
|
|
1311
1375
|
|
|
1312
|
-
|
|
1376
|
+
const version = '0.4.0';
|
|
1313
1377
|
|
|
1314
1378
|
const MQTTClient_v4 = /* #__PURE__ */
|
|
1315
|
-
|
|
1379
|
+
with_topic_path_router(
|
|
1380
|
+
MQTTCore.mqtt_ctx(4, mqtt_opts_v4) );
|
|
1316
1381
|
|
|
1317
1382
|
const mqtt_v4 = opt =>
|
|
1318
1383
|
new MQTTClient_v4(opt);
|
|
1319
1384
|
|
|
1320
1385
|
exports.MQTTClient = MQTTClient_v4;
|
|
1321
1386
|
exports.MQTTClient_v4 = MQTTClient_v4;
|
|
1322
|
-
exports
|
|
1387
|
+
exports.default = mqtt_v4;
|
|
1323
1388
|
exports.mqtt = mqtt_v4;
|
|
1324
1389
|
exports.mqtt_v4 = mqtt_v4;
|
|
1325
1390
|
exports.version = version;
|