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