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