u8-mqtt 0.3.2-0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/cjs/basic-v4.cjs +1200 -0
- package/cjs/basic-v4.cjs.map +1 -0
- package/cjs/basic-v5.cjs +1464 -0
- package/cjs/basic-v5.cjs.map +1 -0
- package/cjs/index.cjs +312 -269
- package/cjs/index.cjs.map +1 -1
- package/cjs/v4.cjs +307 -264
- package/cjs/v4.cjs.map +1 -1
- package/cjs/v5.cjs +309 -265
- package/cjs/v5.cjs.map +1 -1
- package/code/_cmdid_dispatch.jsy +1 -3
- package/code/base.jsy +64 -89
- package/code/basic-v4.js +18 -0
- package/code/basic-v5.js +26 -0
- package/code/index.js +2 -1
- package/code/{_router.jsy → router_path.jsy} +36 -12
- package/code/v4.js +3 -1
- package/code/v5.js +5 -2
- package/code/with_topic_router.jsy +42 -0
- package/esm/deno/basic-v4.js +1188 -0
- package/esm/deno/basic-v4.js.map +1 -0
- package/esm/deno/basic-v5.js +1450 -0
- package/esm/deno/basic-v5.js.map +1 -0
- package/esm/deno/index.js +310 -266
- package/esm/deno/index.js.map +1 -1
- package/esm/deno/v4.js +307 -264
- package/esm/deno/v4.js.map +1 -1
- package/esm/deno/v5.js +309 -265
- package/esm/deno/v5.js.map +1 -1
- package/esm/node/basic-v4.js +1191 -0
- package/esm/node/basic-v4.js.map +1 -0
- package/esm/node/basic-v4.mjs +1191 -0
- package/esm/node/basic-v4.mjs.map +1 -0
- package/esm/node/basic-v5.js +1453 -0
- package/esm/node/basic-v5.js.map +1 -0
- package/esm/node/basic-v5.mjs +1453 -0
- package/esm/node/basic-v5.mjs.map +1 -0
- package/esm/node/index.js +310 -266
- package/esm/node/index.js.map +1 -1
- package/esm/node/index.mjs +310 -266
- package/esm/node/index.mjs.map +1 -1
- package/esm/node/v4.js +307 -264
- package/esm/node/v4.js.map +1 -1
- package/esm/node/v4.mjs +307 -264
- package/esm/node/v4.mjs.map +1 -1
- package/esm/node/v5.js +309 -265
- package/esm/node/v5.js.map +1 -1
- package/esm/node/v5.mjs +309 -265
- package/esm/node/v5.mjs.map +1 -1
- package/esm/web/basic-v4.js +1188 -0
- package/esm/web/basic-v4.js.map +1 -0
- package/esm/web/basic-v4.min.js +1 -0
- package/esm/web/basic-v4.min.js.br +0 -0
- package/esm/web/basic-v4.min.js.gz +0 -0
- package/esm/web/basic-v5.js +1450 -0
- package/esm/web/basic-v5.js.map +1 -0
- package/esm/web/basic-v5.min.js +1 -0
- package/esm/web/basic-v5.min.js.br +0 -0
- package/esm/web/basic-v5.min.js.gz +0 -0
- package/esm/web/index.js +309 -265
- package/esm/web/index.js.map +1 -1
- package/esm/web/index.min.js +1 -1
- package/esm/web/index.min.js.br +0 -0
- package/esm/web/index.min.js.gz +0 -0
- package/esm/web/v4.js +307 -264
- package/esm/web/v4.js.map +1 -1
- package/esm/web/v4.min.js +1 -1
- package/esm/web/v4.min.js.br +0 -0
- package/esm/web/v4.min.js.gz +0 -0
- package/esm/web/v5.js +308 -264
- package/esm/web/v5.js.map +1 -1
- package/esm/web/v5.min.js +1 -1
- package/esm/web/v5.min.js.br +0 -0
- package/esm/web/v5.min.js.gz +0 -0
- package/package.json +5 -5
package/esm/node/v5.js
CHANGED
|
@@ -772,6 +772,198 @@ const mqtt_opts_v5 =
|
|
|
772
772
|
encode_fns: mqtt_encode_v5,
|
|
773
773
|
mqtt_writer: mqtt_writer_v5, };
|
|
774
774
|
|
|
775
|
+
function parse(str, loose) {
|
|
776
|
+
if (str instanceof RegExp) return { keys:false, pattern:str };
|
|
777
|
+
var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
|
|
778
|
+
arr[0] || arr.shift();
|
|
779
|
+
|
|
780
|
+
while (tmp = arr.shift()) {
|
|
781
|
+
c = tmp[0];
|
|
782
|
+
if (c === '*') {
|
|
783
|
+
keys.push('wild');
|
|
784
|
+
pattern += '/(.*)';
|
|
785
|
+
} else if (c === ':') {
|
|
786
|
+
o = tmp.indexOf('?', 1);
|
|
787
|
+
ext = tmp.indexOf('.', 1);
|
|
788
|
+
keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
|
|
789
|
+
pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
|
|
790
|
+
if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
|
|
791
|
+
} else {
|
|
792
|
+
pattern += '/' + tmp;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
return {
|
|
797
|
+
keys: keys,
|
|
798
|
+
pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/*
|
|
803
|
+
class AbstractTopicRouter ::
|
|
804
|
+
async invoke(pkt, ctx) ::
|
|
805
|
+
add(topic_route, ...args) ::
|
|
806
|
+
remove(topic_route, priority) ::
|
|
807
|
+
clear(priority) ::
|
|
808
|
+
find(topic) :: // optional
|
|
809
|
+
mqtt_topic(topic_route)
|
|
810
|
+
*/
|
|
811
|
+
|
|
812
|
+
const with_topic_router = mqtt_topic_router =>
|
|
813
|
+
MQTTKlass => class extends MQTTKlass {
|
|
814
|
+
static _aliases() {
|
|
815
|
+
return super._aliases() +
|
|
816
|
+
' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'}
|
|
817
|
+
|
|
818
|
+
_init_router(opt, client, target) {
|
|
819
|
+
let router = this.router = target.router =
|
|
820
|
+
mqtt_topic_router(opt, this);
|
|
821
|
+
return router?.invoke}
|
|
822
|
+
get on_topic() {return this.router.add}
|
|
823
|
+
|
|
824
|
+
_sub_chain(topic, ex, topic_prefix) {
|
|
825
|
+
let res = this.subscribe([[ topic ]], ex, topic_prefix);
|
|
826
|
+
let subs = this.subs ||(this.subs = new Map());
|
|
827
|
+
subs.set((res.topic = topic), (subs.last = res));
|
|
828
|
+
return this }// fluent api -- return this and track side effects
|
|
829
|
+
|
|
830
|
+
// alias: sub_topic
|
|
831
|
+
subscribe_topic(topic_route, ...args) {
|
|
832
|
+
let router = this.router;
|
|
833
|
+
router.add(topic_route, true, args.pop() );// handler
|
|
834
|
+
let topic = router.mqtt_topic(topic_route);
|
|
835
|
+
return this._sub_chain(topic, ...args ) }// ex, topic_prefix
|
|
836
|
+
|
|
837
|
+
// alias: unsub_topic
|
|
838
|
+
unsubscribe_topic(topic_route, ...args) {
|
|
839
|
+
let router = this.router;
|
|
840
|
+
router.remove(topic_route, true);
|
|
841
|
+
let topic = router.mqtt_topic(topic_route);
|
|
842
|
+
return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
|
|
843
|
+
|
|
844
|
+
// Use [regexparam][] for url-like topic parsing
|
|
845
|
+
// [regexparam]: https://github.com/lukeed/regexparam
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
const with_topic_path_router = /* #__PURE__ */
|
|
849
|
+
with_topic_router(mqtt_topic_path_router);
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
const mqtt_topic = topic_route =>
|
|
853
|
+
topic_route
|
|
854
|
+
.replace(/[*].*$/, '#')
|
|
855
|
+
.replace(/:\w+\??/g, '+');
|
|
856
|
+
|
|
857
|
+
/* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
|
|
858
|
+
4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
|
|
859
|
+
... MUST be specified either on its own or following a topic level separator.
|
|
860
|
+
In either case it MUST be the last character specified in the Topic Filter
|
|
861
|
+
|
|
862
|
+
4.7.1.3 Single-level wildcard -- (‘+’ U+002B)
|
|
863
|
+
...it MUST occupy an entire level of the filter.
|
|
864
|
+
*/
|
|
865
|
+
|
|
866
|
+
const as_topic_path = (topic_route, id) =>(
|
|
867
|
+
id=1,
|
|
868
|
+
topic_route
|
|
869
|
+
.replace(/#$/, '*' )// replace MQTT '#' multi-level wildcard at end
|
|
870
|
+
.replace(/\+/g, () => `:$${id++}` ) );// replace MQTT '+' single-level wildcards
|
|
871
|
+
|
|
872
|
+
function _ignore(pkt, params, ctx) {ctx.done = true;}
|
|
873
|
+
|
|
874
|
+
function mqtt_topic_path_router() {
|
|
875
|
+
let pri_lsts = [[],[]], rm = Symbol();
|
|
876
|
+
let find = topic => _routes_iter(pri_lsts, topic);
|
|
877
|
+
|
|
878
|
+
// return duck-type compatible with AbstractTopicRouter in ./with_topic_router
|
|
879
|
+
return {find, mqtt_topic,
|
|
880
|
+
add(topic_route, ...args) {
|
|
881
|
+
let fn = args.pop();
|
|
882
|
+
let priority = args.pop();
|
|
883
|
+
|
|
884
|
+
if ('function' !== typeof fn) {
|
|
885
|
+
if (false === fn) {
|
|
886
|
+
fn = _ignore;}
|
|
887
|
+
else throw new TypeError()}
|
|
888
|
+
|
|
889
|
+
let rte = parse(as_topic_path(topic_route));
|
|
890
|
+
|
|
891
|
+
rte.key = topic_route;
|
|
892
|
+
rte.tgt = fn;
|
|
893
|
+
pri_lsts[priority ? 0 : 1].push(rte);
|
|
894
|
+
return this}
|
|
895
|
+
|
|
896
|
+
, remove(topic_route, priority) {
|
|
897
|
+
let lst = pri_lsts[priority ? 0 : 1];
|
|
898
|
+
return _route_remove([lst], topic_route)}
|
|
899
|
+
|
|
900
|
+
, clear(priority) {
|
|
901
|
+
pri_lsts[priority ? 0 : 1] = [];
|
|
902
|
+
if (null == priority) {
|
|
903
|
+
pri_lsts[1] = [];} }
|
|
904
|
+
|
|
905
|
+
, async invoke(pkt, ctx) {
|
|
906
|
+
ctx.idx = 0;
|
|
907
|
+
ctx.rm = rm;
|
|
908
|
+
|
|
909
|
+
for (let [fn, params] of find(pkt.topic)) {
|
|
910
|
+
let res = await fn(pkt, params, ctx);
|
|
911
|
+
|
|
912
|
+
if (rm === res) {
|
|
913
|
+
_route_remove(pri_lsts, fn);}
|
|
914
|
+
|
|
915
|
+
if (ctx.done) {
|
|
916
|
+
break}
|
|
917
|
+
else ctx.idx++;}
|
|
918
|
+
|
|
919
|
+
let {pkt_id, qos} = pkt;
|
|
920
|
+
if (1 === qos) {
|
|
921
|
+
await ctx.mqtt._send('puback', {pkt_id});} } } }
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
function * _routes_iter(all_route_lists, topic) {
|
|
925
|
+
for (let route_list of all_route_lists) {
|
|
926
|
+
for (let route of route_list) {
|
|
927
|
+
let res = _route_match_one(topic, route);
|
|
928
|
+
if (undefined !== res) {
|
|
929
|
+
yield res;} } } }
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
function _route_match_one(topic, {keys, pattern, tgt}) {
|
|
933
|
+
let match = '/' !== topic[0]
|
|
934
|
+
? pattern.exec('/'+topic)
|
|
935
|
+
: pattern.exec(topic);
|
|
936
|
+
|
|
937
|
+
if (null === match) {
|
|
938
|
+
return}
|
|
939
|
+
|
|
940
|
+
if (false === keys) {
|
|
941
|
+
let {groups} = match;
|
|
942
|
+
if (! groups) {
|
|
943
|
+
return [tgt]}
|
|
944
|
+
|
|
945
|
+
let params = {};
|
|
946
|
+
for (let k in groups) {
|
|
947
|
+
params[k] = groups[k];}
|
|
948
|
+
|
|
949
|
+
return [tgt, params]}
|
|
950
|
+
|
|
951
|
+
if (0 === keys.length) {
|
|
952
|
+
return [tgt]}
|
|
953
|
+
|
|
954
|
+
let params = {};
|
|
955
|
+
for (let i=0; i<keys.length; i++) {
|
|
956
|
+
params[ keys[i] ] = match[1+i];}
|
|
957
|
+
return [tgt, params]}
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
function _route_remove(all_route_lists, query) {
|
|
961
|
+
let match = route => route===query || route.tgt===query || route.key===query;
|
|
962
|
+
for (let lst of all_route_lists) {
|
|
963
|
+
let i = lst.findIndex(match);
|
|
964
|
+
if (0 <= i) {return !! lst.splice(i,1)} }
|
|
965
|
+
return false}
|
|
966
|
+
|
|
775
967
|
/*
|
|
776
968
|
export function decode_varint_loop(u8, i=0) {
|
|
777
969
|
let i0 = i
|
|
@@ -953,138 +1145,13 @@ function _ping_interval(send_ping) {
|
|
|
953
1145
|
if (td) {
|
|
954
1146
|
tid = setInterval(send_ping, 1000 * td);
|
|
955
1147
|
|
|
956
|
-
|
|
957
|
-
|
|
1148
|
+
|
|
1149
|
+
|
|
958
1150
|
|
|
959
|
-
|
|
960
|
-
|
|
1151
|
+
// ensure the interval allows the NodeJS event loop to exit
|
|
1152
|
+
tid.unref?.();
|
|
961
1153
|
return true} }) }
|
|
962
1154
|
|
|
963
|
-
function parse(str, loose) {
|
|
964
|
-
if (str instanceof RegExp) return { keys:false, pattern:str };
|
|
965
|
-
var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
|
|
966
|
-
arr[0] || arr.shift();
|
|
967
|
-
|
|
968
|
-
while (tmp = arr.shift()) {
|
|
969
|
-
c = tmp[0];
|
|
970
|
-
if (c === '*') {
|
|
971
|
-
keys.push('wild');
|
|
972
|
-
pattern += '/(.*)';
|
|
973
|
-
} else if (c === ':') {
|
|
974
|
-
o = tmp.indexOf('?', 1);
|
|
975
|
-
ext = tmp.indexOf('.', 1);
|
|
976
|
-
keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
|
|
977
|
-
pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
|
|
978
|
-
if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
|
|
979
|
-
} else {
|
|
980
|
-
pattern += '/' + tmp;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
return {
|
|
985
|
-
keys: keys,
|
|
986
|
-
pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
|
|
987
|
-
};
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
// Use [regexparam][] for url-like topic parsing
|
|
991
|
-
|
|
992
|
-
function _ignore(pkt, params, ctx) {ctx.done = true;}
|
|
993
|
-
|
|
994
|
-
function _mqtt_topic_router() {
|
|
995
|
-
let pri_lsts = [[],[]], rm = Symbol();
|
|
996
|
-
let find = topic => _mqtt_routes_iter(pri_lsts, topic);
|
|
997
|
-
|
|
998
|
-
return {find,
|
|
999
|
-
|
|
1000
|
-
add(topic_route, ...args) {
|
|
1001
|
-
let fn = args.pop();
|
|
1002
|
-
let priority = args.pop();
|
|
1003
|
-
|
|
1004
|
-
if ('function' !== typeof fn) {
|
|
1005
|
-
if (false === fn) {
|
|
1006
|
-
fn = _ignore;}
|
|
1007
|
-
else throw new TypeError()}
|
|
1008
|
-
|
|
1009
|
-
let rte = parse(
|
|
1010
|
-
topic_route.replace(/[+#]$/, '*'));
|
|
1011
|
-
|
|
1012
|
-
rte.key = topic_route;
|
|
1013
|
-
rte.tgt = fn;
|
|
1014
|
-
pri_lsts[priority ? 0 : 1].push(rte);
|
|
1015
|
-
return this}
|
|
1016
|
-
|
|
1017
|
-
, remove(topic_route, priority) {
|
|
1018
|
-
let lst = pri_lsts[priority ? 0 : 1];
|
|
1019
|
-
return _mqtt_route_remove([lst], topic_route)}
|
|
1020
|
-
|
|
1021
|
-
, clear(priority) {
|
|
1022
|
-
pri_lsts[priority ? 0 : 1] = [];
|
|
1023
|
-
if (null == priority) {
|
|
1024
|
-
pri_lsts[1] = [];} }
|
|
1025
|
-
|
|
1026
|
-
, async invoke(pkt, ctx) {
|
|
1027
|
-
ctx.idx = 0;
|
|
1028
|
-
ctx.rm = rm;
|
|
1029
|
-
|
|
1030
|
-
for (let [fn, params] of find(pkt.topic)) {
|
|
1031
|
-
let res = await fn(pkt, params, ctx);
|
|
1032
|
-
|
|
1033
|
-
if (rm === res) {
|
|
1034
|
-
_mqtt_route_remove(pri_lsts, fn);}
|
|
1035
|
-
|
|
1036
|
-
if (ctx.done) {
|
|
1037
|
-
break}
|
|
1038
|
-
else ctx.idx++;}
|
|
1039
|
-
|
|
1040
|
-
let {pkt_id, qos} = pkt;
|
|
1041
|
-
if (1 === qos) {
|
|
1042
|
-
await ctx.mqtt._send('puback', {pkt_id});} } } }
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
function * _mqtt_routes_iter(all_route_lists, topic) {
|
|
1046
|
-
for (let route_list of all_route_lists) {
|
|
1047
|
-
for (let route of route_list) {
|
|
1048
|
-
let res = _mqtt_route_match_one(topic, route);
|
|
1049
|
-
if (undefined !== res) {
|
|
1050
|
-
yield res;} } } }
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
function _mqtt_route_match_one(topic, {keys, pattern, tgt}) {
|
|
1054
|
-
let match = '/' !== topic[0]
|
|
1055
|
-
? pattern.exec('/'+topic)
|
|
1056
|
-
: pattern.exec(topic);
|
|
1057
|
-
|
|
1058
|
-
if (null === match) {
|
|
1059
|
-
return}
|
|
1060
|
-
|
|
1061
|
-
if (false === keys) {
|
|
1062
|
-
let {groups} = match;
|
|
1063
|
-
if (! groups) {
|
|
1064
|
-
return [tgt]}
|
|
1065
|
-
|
|
1066
|
-
let params = {};
|
|
1067
|
-
for (let k in groups) {
|
|
1068
|
-
params[k] = groups[k];}
|
|
1069
|
-
|
|
1070
|
-
return [tgt, params]}
|
|
1071
|
-
|
|
1072
|
-
if (0 === keys.length) {
|
|
1073
|
-
return [tgt]}
|
|
1074
|
-
|
|
1075
|
-
let params = {};
|
|
1076
|
-
for (let i=0; i<keys.length; i++) {
|
|
1077
|
-
params[ keys[i] ] = match[1+i];}
|
|
1078
|
-
return [tgt, params]}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
function _mqtt_route_remove(all_route_lists, query) {
|
|
1082
|
-
let match = route => route===query || route.tgt===query || route.key===query;
|
|
1083
|
-
for (let lst of all_route_lists) {
|
|
1084
|
-
let i = lst.findIndex(match);
|
|
1085
|
-
if (0 <= i) {return !! lst.splice(i,1)} }
|
|
1086
|
-
return false}
|
|
1087
|
-
|
|
1088
1155
|
const _mqtt_cmdid_dispatch ={
|
|
1089
1156
|
create(target) {
|
|
1090
1157
|
return {__proto__: this, target, hashbelt: [new Map()]} }
|
|
@@ -1153,8 +1220,7 @@ const _mqtt_cmdid_dispatch ={
|
|
|
1153
1220
|
let fn = target[`mqtt_${pkt.type}`]
|
|
1154
1221
|
|| target.mqtt_pkt;
|
|
1155
1222
|
|
|
1156
|
-
|
|
1157
|
-
await fn.call(target, pkt, ctx);} } })()) };
|
|
1223
|
+
await fn?.call(target, pkt, ctx);} })()) };
|
|
1158
1224
|
|
|
1159
1225
|
function _mqtt_dispatch(opt, target) {
|
|
1160
1226
|
let _disp_ = _mqtt_cmdid_dispatch.create(target);
|
|
@@ -1235,53 +1301,15 @@ class MQTTBase {
|
|
|
1235
1301
|
|
|
1236
1302
|
|
|
1237
1303
|
// alias: sub
|
|
1238
|
-
subscribe(pkt, ex) {
|
|
1239
|
-
pkt = _as_topics(pkt, ex);
|
|
1304
|
+
subscribe(pkt, ex, topic_prefix) {
|
|
1305
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
1240
1306
|
return this._send('subscribe', pkt, pkt)}
|
|
1241
|
-
_sub_chain(topic, ex) {
|
|
1242
|
-
let res = this.subscribe([[ topic ]], ex);
|
|
1243
|
-
let subs = this.subs ||(this.subs = new Map());
|
|
1244
|
-
subs.set((res.topic = topic), (subs.last = res));
|
|
1245
|
-
return this }// fluent api -- return this and track side effects
|
|
1246
1307
|
|
|
1247
1308
|
// alias: unsub
|
|
1248
|
-
unsubscribe(pkt, ex) {
|
|
1249
|
-
pkt = _as_topics(pkt, ex);
|
|
1309
|
+
unsubscribe(pkt, ex, topic_prefix) {
|
|
1310
|
+
pkt = _as_topics(pkt, ex, topic_prefix);
|
|
1250
1311
|
return this._send('unsubscribe', pkt, pkt)}
|
|
1251
1312
|
|
|
1252
|
-
get on_topic() {return this.router.add}
|
|
1253
|
-
|
|
1254
|
-
// alias: sub_topic
|
|
1255
|
-
subscribe_topic(topic_route, ...args) {
|
|
1256
|
-
this.router.add(topic_route, true, args.pop() );// handler
|
|
1257
|
-
let topic = this.topic_for(topic_route);
|
|
1258
|
-
return this._sub_chain(topic, args.pop() ) }// ex
|
|
1259
|
-
|
|
1260
|
-
// alias: unsub_topic
|
|
1261
|
-
unsubscribe_topic(topic_route) {
|
|
1262
|
-
this.router.remove(topic_route, true);
|
|
1263
|
-
let topic = this.topic_for(topic_route);
|
|
1264
|
-
return this.unsubscribe([[ topic ]]) }
|
|
1265
|
-
|
|
1266
|
-
// alias: shared_sub
|
|
1267
|
-
shared_subscribe(group, topic_route, ...args) {
|
|
1268
|
-
this.router.add(topic_route, true, args.pop() );// handler
|
|
1269
|
-
let topic = this.topic_for(topic_route);
|
|
1270
|
-
if (null != group) {
|
|
1271
|
-
topic = `$share/${group}/${topic}`;}
|
|
1272
|
-
return this._sub_chain(topic, args.pop() ) }// ex
|
|
1273
|
-
|
|
1274
|
-
// alias: shared_unsub
|
|
1275
|
-
shared_unsubscribe(group, topic_route) {
|
|
1276
|
-
this.router.remove(topic_route, true);
|
|
1277
|
-
let topic = this.topic_for(topic_route);
|
|
1278
|
-
if (null != group) {
|
|
1279
|
-
topic = `$share/${group}/${topic}`;}
|
|
1280
|
-
return this.unsubscribe([[ topic ]]) }
|
|
1281
|
-
|
|
1282
|
-
topic_for(topic_route) {
|
|
1283
|
-
return topic_route.replace(/[:*].*$/, '#')}
|
|
1284
|
-
|
|
1285
1313
|
|
|
1286
1314
|
// alias: pub
|
|
1287
1315
|
publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
|
|
@@ -1307,9 +1335,9 @@ class MQTTBase {
|
|
|
1307
1335
|
if (undefined === cid) {
|
|
1308
1336
|
this.client_id = cid = (
|
|
1309
1337
|
|
|
1310
|
-
|
|
1338
|
+
|
|
1311
1339
|
|
|
1312
|
-
|
|
1340
|
+
this.new_client_id(parts)
|
|
1313
1341
|
);}
|
|
1314
1342
|
|
|
1315
1343
|
return cid}
|
|
@@ -1318,66 +1346,80 @@ class MQTTBase {
|
|
|
1318
1346
|
return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
|
|
1319
1347
|
|
|
1320
1348
|
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1349
|
+
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
|
|
1328
1356
|
|
|
1329
1357
|
|
|
1330
1358
|
// Internal API
|
|
1331
1359
|
|
|
1332
1360
|
/* async _send(type, pkt) -- provided by _conn_ and transport */
|
|
1333
1361
|
|
|
1334
|
-
_init_router(opt) {
|
|
1335
|
-
return this.router = _mqtt_topic_router()}
|
|
1336
|
-
|
|
1337
1362
|
_init_dispatch(opt) {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1363
|
+
this.constructor?._once_();
|
|
1364
|
+
let target ={__proto__: opt.on_mqtt_type};
|
|
1365
|
+
target.mqtt_publish ||=
|
|
1366
|
+
this._init_router?.(opt, this, target);
|
|
1367
|
+
return _mqtt_dispatch(this, target)}
|
|
1341
1368
|
|
|
1342
|
-
|
|
1343
|
-
return
|
|
1369
|
+
static _aliases() {
|
|
1370
|
+
return ' pub:publish sub:subscribe unsub:unsubscribe '}
|
|
1344
1371
|
|
|
1372
|
+
static _once_(self=this) {
|
|
1373
|
+
self._once_ = _=>0;
|
|
1374
|
+
self.MQTTError = MQTTError;
|
|
1375
|
+
let p = self.prototype;
|
|
1376
|
+
for (let alias of self._aliases().split(/\s+/)) {
|
|
1377
|
+
alias = alias.split(':');
|
|
1378
|
+
let fn = alias[1] && p[alias[1]];
|
|
1379
|
+
if (fn) {p[alias[0]] = fn;} } } }
|
|
1345
1380
|
|
|
1346
|
-
{
|
|
1347
|
-
let p = MQTTBase.prototype;
|
|
1348
|
-
Object.assign(p,{
|
|
1349
|
-
MQTTError
|
|
1350
|
-
, pub: p.publish
|
|
1351
|
-
, sub: p.subscribe
|
|
1352
|
-
, unsub: p.unsubscribe
|
|
1353
|
-
, sub_topic: p.subscribe_topic
|
|
1354
|
-
, unsub_topic: p.unsubscribe_topic
|
|
1355
|
-
, shared_sub: p.shared_subscribe
|
|
1356
|
-
, shared_unsub: p.shared_unsubscribe} );
|
|
1357
1381
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1382
|
+
/*
|
|
1383
|
+
on_mqtt_type = {
|
|
1384
|
+
mqtt_auth(pkt, ctx) ::
|
|
1385
|
+
mqtt_connect(pkt, ctx) ::
|
|
1386
|
+
mqtt_connack(pkt, ctx) ::
|
|
1387
|
+
mqtt_disconnect(pkt, ctx) ::
|
|
1388
|
+
|
|
1389
|
+
mqtt_publish(pkt, ctx)
|
|
1390
|
+
mqtt_subscribe(pkt, ctx) ::
|
|
1391
|
+
mqtt_unsubscribe(pkt, ctx) ::
|
|
1392
|
+
|
|
1393
|
+
mqtt_pingreq(pkt, ctx) ::
|
|
1394
|
+
mqtt_pingresp(pkt, ctx) ::
|
|
1395
|
+
}
|
|
1396
|
+
*/
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
const _prefix_topics = (topic_prefix, iterable) =>
|
|
1400
|
+
Array.from(iterable, value =>(
|
|
1401
|
+
value.trim // string
|
|
1402
|
+
? _prefix_topics(topic_prefix, value)
|
|
1403
|
+
: topic_prefix + value) );
|
|
1404
|
+
|
|
1405
|
+
function _as_topics(pkt, ex, topic_prefix) {
|
|
1406
|
+
if (ex?.trim) {// string
|
|
1407
|
+
topic_prefix = ex;
|
|
1408
|
+
ex = null;}
|
|
1373
1409
|
|
|
1410
|
+
pkt =(
|
|
1411
|
+
pkt.trim // string
|
|
1412
|
+
? {topics:[pkt], ... ex}
|
|
1413
|
+
: pkt[Symbol.iterator]
|
|
1414
|
+
? {topics:[... pkt], ... ex}
|
|
1415
|
+
: ex ? {...pkt, ...ex}
|
|
1416
|
+
: pkt);
|
|
1374
1417
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
return ex ? {...pkt, ...ex} : pkt}
|
|
1418
|
+
if (topic_prefix) {
|
|
1419
|
+
// particularly useful with shared queues, e.g.
|
|
1420
|
+
// topic_prefix = '$share/some-queue-name/'
|
|
1421
|
+
pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
|
|
1422
|
+
return pkt}
|
|
1381
1423
|
|
|
1382
1424
|
|
|
1383
1425
|
async function _pub(self, pkt, pub_opt) {
|
|
@@ -1493,53 +1535,53 @@ class MQTTCore extends MQTTBase {
|
|
|
1493
1535
|
|
|
1494
1536
|
|
|
1495
1537
|
|
|
1538
|
+
|
|
1539
|
+
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
|
|
1496
1544
|
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
|
|
1549
|
+
|
|
1497
1550
|
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
|
|
1498
1556
|
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
|
|
1499
1561
|
|
|
1562
|
+
|
|
1563
|
+
|
|
1500
1564
|
|
|
1565
|
+
|
|
1566
|
+
with_tcp(...opt) {
|
|
1567
|
+
opt = this._conn_opt(opt);
|
|
1568
|
+
console.log({opt});
|
|
1569
|
+
return this._use_conn (() =>
|
|
1570
|
+
this.with_stream(
|
|
1571
|
+
connect(opt)) ) }
|
|
1501
1572
|
|
|
1573
|
+
with_tls(...opt) {
|
|
1574
|
+
opt = this._conn_opt(opt);
|
|
1575
|
+
return this._use_conn (() =>
|
|
1576
|
+
this.with_stream(
|
|
1577
|
+
connect$1(opt)) ) }
|
|
1502
1578
|
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
with_tcp(...opt) {
|
|
1525
|
-
opt = this._conn_opt(opt);
|
|
1526
|
-
console.log({opt});
|
|
1527
|
-
return this._use_conn (() =>
|
|
1528
|
-
this.with_stream(
|
|
1529
|
-
connect(opt)) ) }
|
|
1530
|
-
|
|
1531
|
-
with_tls(...opt) {
|
|
1532
|
-
opt = this._conn_opt(opt);
|
|
1533
|
-
return this._use_conn (() =>
|
|
1534
|
-
this.with_stream(
|
|
1535
|
-
connect$1(opt)) ) }
|
|
1536
|
-
|
|
1537
|
-
_conn_opt([a0, a1, a2]) {
|
|
1538
|
-
// (port, hostname, options) or (url, options)
|
|
1539
|
-
if (Number.isFinite(a0)) {
|
|
1540
|
-
return {...a2, port: a0, host: a1}}
|
|
1541
|
-
a0 = new URL(a0);
|
|
1542
|
-
return {...a1, port: a0.port, host: a0.hostname}}
|
|
1579
|
+
_conn_opt([a0, a1, a2]) {
|
|
1580
|
+
// (port, hostname, options) or (url, options)
|
|
1581
|
+
if (Number.isFinite(a0)) {
|
|
1582
|
+
return {...a2, port: a0, host: a1}}
|
|
1583
|
+
a0 = new URL(a0);
|
|
1584
|
+
return {...a1, port: a0.port, host: a0.hostname}}
|
|
1543
1585
|
|
|
1544
1586
|
|
|
1545
1587
|
with_stream(read_stream, write_stream) {
|
|
@@ -1585,13 +1627,15 @@ class MQTTCore extends MQTTBase {
|
|
|
1585
1627
|
|
|
1586
1628
|
return this} }
|
|
1587
1629
|
|
|
1588
|
-
const version = '0.
|
|
1630
|
+
const version = '0.4.1';
|
|
1589
1631
|
|
|
1590
1632
|
const MQTTClient_v4 = /* #__PURE__ */
|
|
1591
|
-
|
|
1633
|
+
with_topic_path_router(
|
|
1634
|
+
MQTTCore.mqtt_ctx(4, mqtt_opts_v5) );
|
|
1592
1635
|
|
|
1593
1636
|
const MQTTClient_v5 = /* #__PURE__ */
|
|
1594
|
-
|
|
1637
|
+
with_topic_path_router(
|
|
1638
|
+
MQTTCore.mqtt_ctx(5, mqtt_opts_v5) );
|
|
1595
1639
|
|
|
1596
1640
|
const mqtt_v4 = opt =>
|
|
1597
1641
|
new MQTTClient_v4(opt);
|