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.
Files changed (78) hide show
  1. package/README.md +5 -5
  2. package/cjs/basic-v4.cjs +1205 -0
  3. package/cjs/basic-v4.cjs.map +1 -0
  4. package/cjs/basic-v5.cjs +1469 -0
  5. package/cjs/basic-v5.cjs.map +1 -0
  6. package/cjs/index.cjs +312 -247
  7. package/cjs/index.cjs.map +1 -1
  8. package/cjs/v4.cjs +307 -242
  9. package/cjs/v4.cjs.map +1 -1
  10. package/cjs/v5.cjs +309 -243
  11. package/cjs/v5.cjs.map +1 -1
  12. package/code/_cmdid_dispatch.jsy +1 -3
  13. package/code/base.jsy +64 -84
  14. package/code/{v4.mjs → basic-v4.js} +1 -1
  15. package/code/{v5.mjs → basic-v5.js} +1 -1
  16. package/code/core.jsy +41 -15
  17. package/code/{index.mjs → index.js} +3 -2
  18. package/code/{_router.jsy → router_path.jsy} +30 -12
  19. package/code/v4.js +20 -0
  20. package/code/v5.js +29 -0
  21. package/code/version.js +1 -0
  22. package/code/with_topic_router.jsy +41 -0
  23. package/esm/deno/basic-v4.js +1193 -0
  24. package/esm/deno/basic-v4.js.map +1 -0
  25. package/esm/deno/basic-v5.js +1455 -0
  26. package/esm/deno/basic-v5.js.map +1 -0
  27. package/esm/deno/index.js +307 -242
  28. package/esm/deno/index.js.map +1 -1
  29. package/esm/deno/v4.js +304 -240
  30. package/esm/deno/v4.js.map +1 -1
  31. package/esm/deno/v5.js +306 -241
  32. package/esm/deno/v5.js.map +1 -1
  33. package/esm/node/basic-v4.js +1196 -0
  34. package/esm/node/basic-v4.js.map +1 -0
  35. package/esm/node/basic-v4.mjs +1196 -0
  36. package/esm/node/basic-v4.mjs.map +1 -0
  37. package/esm/node/basic-v5.js +1458 -0
  38. package/esm/node/basic-v5.js.map +1 -0
  39. package/esm/node/basic-v5.mjs +1458 -0
  40. package/esm/node/basic-v5.mjs.map +1 -0
  41. package/esm/node/index.js +309 -243
  42. package/esm/node/index.js.map +1 -1
  43. package/esm/node/index.mjs +309 -243
  44. package/esm/node/index.mjs.map +1 -1
  45. package/esm/node/v4.js +306 -241
  46. package/esm/node/v4.js.map +1 -1
  47. package/esm/node/v4.mjs +306 -241
  48. package/esm/node/v4.mjs.map +1 -1
  49. package/esm/node/v5.js +308 -242
  50. package/esm/node/v5.js.map +1 -1
  51. package/esm/node/v5.mjs +308 -242
  52. package/esm/node/v5.mjs.map +1 -1
  53. package/esm/web/basic-v4.js +1193 -0
  54. package/esm/web/basic-v4.js.map +1 -0
  55. package/esm/web/basic-v4.min.js +1 -0
  56. package/esm/web/basic-v4.min.js.br +0 -0
  57. package/esm/web/basic-v4.min.js.gz +0 -0
  58. package/esm/web/basic-v5.js +1455 -0
  59. package/esm/web/basic-v5.js.map +1 -0
  60. package/esm/web/basic-v5.min.js +1 -0
  61. package/esm/web/basic-v5.min.js.br +0 -0
  62. package/esm/web/basic-v5.min.js.gz +0 -0
  63. package/esm/web/index.js +307 -242
  64. package/esm/web/index.js.map +1 -1
  65. package/esm/web/index.min.js +1 -1
  66. package/esm/web/index.min.js.br +0 -0
  67. package/esm/web/index.min.js.gz +0 -0
  68. package/esm/web/v4.js +305 -241
  69. package/esm/web/v4.js.map +1 -1
  70. package/esm/web/v4.min.js +1 -1
  71. package/esm/web/v4.min.js.br +0 -0
  72. package/esm/web/v4.min.js.gz +0 -0
  73. package/esm/web/v5.js +306 -241
  74. package/esm/web/v5.js.map +1 -1
  75. package/esm/web/v5.min.js +1 -1
  76. package/esm/web/v5.min.js.br +0 -0
  77. package/esm/web/v5.min.js.gz +0 -0
  78. package/package.json +7 -7
package/esm/web/index.js CHANGED
@@ -769,6 +769,191 @@ 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) {
816
+ return mqtt_topic_router(opt, this)}
817
+
818
+ get on_topic() {return this.router.add}
819
+
820
+ _sub_chain(topic, ex, topic_prefix) {
821
+ let res = this.subscribe([[ topic ]], ex, topic_prefix);
822
+ let subs = this.subs ||(this.subs = new Map());
823
+ subs.set((res.topic = topic), (subs.last = res));
824
+ return this }// fluent api -- return this and track side effects
825
+
826
+ // alias: sub_topic
827
+ subscribe_topic(topic_route, ...args) {
828
+ let router = this.router;
829
+ router.add(topic_route, true, args.pop() );// handler
830
+ let topic = router.mqtt_topic(topic_route);
831
+ return this._sub_chain(topic, ...args ) }// ex, topic_prefix
832
+
833
+ // alias: unsub_topic
834
+ unsubscribe_topic(topic_route, ...args) {
835
+ let router = this.router;
836
+ router.remove(topic_route, true);
837
+ let topic = router.mqtt_topic(topic_route);
838
+ return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
839
+
840
+ // Use [regexparam][] for url-like topic parsing
841
+ // [regexparam]: https://github.com/lukeed/regexparam
842
+
843
+
844
+ const with_topic_path_router = /* #__PURE__ */
845
+ with_topic_router(mqtt_topic_path_router);
846
+
847
+
848
+ const mqtt_topic = topic_route =>
849
+ topic_route
850
+ .replace(/[*].*$/, '#')
851
+ .replace(/:\w+\??/g, '+');
852
+
853
+ const as_topic_path = topic_route =>(
854
+ topic_route
855
+ .replace(/#$/, '*') // replace MQTT # wildcard at end
856
+ .split(/([^\/]*[+][^\/]*)/) // split on MQTT + match tokens
857
+ .reduce (( sz, v, idx ) => sz +(
858
+ idx & 1 // even entires are body, odd are MQTT + tokens
859
+ ? `:$${1 + idx>>1}` // replace with `:$#` sequential ids, using ? for partial entries
860
+ : v ) ) );// pass through body
861
+
862
+ function _ignore(pkt, params, ctx) {ctx.done = true;}
863
+
864
+ function mqtt_topic_path_router() {
865
+ let pri_lsts = [[],[]], rm = Symbol();
866
+ let find = topic => _routes_iter(pri_lsts, topic);
867
+
868
+ // return duck-type compatible with AbstractTopicRouter in ./with_topic_router
869
+ return {find, mqtt_topic,
870
+ add(topic_route, ...args) {
871
+ let fn = args.pop();
872
+ let priority = args.pop();
873
+
874
+ if ('function' !== typeof fn) {
875
+ if (false === fn) {
876
+ fn = _ignore;}
877
+ else throw new TypeError()}
878
+
879
+ let rte = parse(as_topic_path(topic_route));
880
+
881
+ rte.key = topic_route;
882
+ rte.tgt = fn;
883
+ pri_lsts[priority ? 0 : 1].push(rte);
884
+ return this}
885
+
886
+ , remove(topic_route, priority) {
887
+ let lst = pri_lsts[priority ? 0 : 1];
888
+ return _route_remove([lst], topic_route)}
889
+
890
+ , clear(priority) {
891
+ pri_lsts[priority ? 0 : 1] = [];
892
+ if (null == priority) {
893
+ pri_lsts[1] = [];} }
894
+
895
+ , async invoke(pkt, ctx) {
896
+ ctx.idx = 0;
897
+ ctx.rm = rm;
898
+
899
+ for (let [fn, params] of find(pkt.topic)) {
900
+ let res = await fn(pkt, params, ctx);
901
+
902
+ if (rm === res) {
903
+ _route_remove(pri_lsts, fn);}
904
+
905
+ if (ctx.done) {
906
+ break}
907
+ else ctx.idx++;}
908
+
909
+ let {pkt_id, qos} = pkt;
910
+ if (1 === qos) {
911
+ await ctx.mqtt._send('puback', {pkt_id});} } } }
912
+
913
+
914
+ function * _routes_iter(all_route_lists, topic) {
915
+ for (let route_list of all_route_lists) {
916
+ for (let route of route_list) {
917
+ let res = _route_match_one(topic, route);
918
+ if (undefined !== res) {
919
+ yield res;} } } }
920
+
921
+
922
+ function _route_match_one(topic, {keys, pattern, tgt}) {
923
+ let match = '/' !== topic[0]
924
+ ? pattern.exec('/'+topic)
925
+ : pattern.exec(topic);
926
+
927
+ if (null === match) {
928
+ return}
929
+
930
+ if (false === keys) {
931
+ let {groups} = match;
932
+ if (! groups) {
933
+ return [tgt]}
934
+
935
+ let params = {};
936
+ for (let k in groups) {
937
+ params[k] = groups[k];}
938
+
939
+ return [tgt, params]}
940
+
941
+ if (0 === keys.length) {
942
+ return [tgt]}
943
+
944
+ let params = {};
945
+ for (let i=0; i<keys.length; i++) {
946
+ params[ keys[i] ] = match[1+i];}
947
+ return [tgt, params]}
948
+
949
+
950
+ function _route_remove(all_route_lists, query) {
951
+ let match = route => route===query || route.tgt===query || route.key===query;
952
+ for (let lst of all_route_lists) {
953
+ let i = lst.findIndex(match);
954
+ if (0 <= i) {return !! lst.splice(i,1)} }
955
+ return false}
956
+
772
957
  /*
773
958
  export function decode_varint_loop(u8, i=0) {
774
959
  let i0 = i
@@ -867,8 +1052,6 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
867
1052
  }
868
1053
  }
869
1054
 
870
- Object.freeze({ao_done: true});
871
-
872
1055
  function ao_defer_ctx(as_res = (...args) => args) {
873
1056
  let y,n,_pset = (a,b) => { y=a, n=b; };
874
1057
  return p =>(
@@ -952,138 +1135,13 @@ function _ping_interval(send_ping) {
952
1135
  if (td) {
953
1136
  tid = setInterval(send_ping, 1000 * td);
954
1137
 
955
-
956
-
1138
+
1139
+
957
1140
 
958
- // ensure the interval allows the NodeJS event loop to exit
959
- tid.unref?.();
1141
+ // ensure the interval allows the NodeJS event loop to exit
1142
+ tid.unref?.();
960
1143
  return true} }) }
961
1144
 
962
- function parse(str, loose) {
963
- if (str instanceof RegExp) return { keys:false, pattern:str };
964
- var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
965
- arr[0] || arr.shift();
966
-
967
- while (tmp = arr.shift()) {
968
- c = tmp[0];
969
- if (c === '*') {
970
- keys.push('wild');
971
- pattern += '/(.*)';
972
- } else if (c === ':') {
973
- o = tmp.indexOf('?', 1);
974
- ext = tmp.indexOf('.', 1);
975
- keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
976
- pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
977
- if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
978
- } else {
979
- pattern += '/' + tmp;
980
- }
981
- }
982
-
983
- return {
984
- keys: keys,
985
- pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
986
- };
987
- }
988
-
989
- // Use [regexparam][] for url-like topic parsing
990
-
991
- function _ignore(pkt, params, ctx) {ctx.done = true;}
992
-
993
- function _mqtt_topic_router() {
994
- let pri_lsts = [[],[]], rm = Symbol();
995
- let find = topic => _mqtt_routes_iter(pri_lsts, topic);
996
-
997
- return {find,
998
-
999
- add(topic_route, ...args) {
1000
- let fn = args.pop();
1001
- let priority = args.pop();
1002
-
1003
- if ('function' !== typeof fn) {
1004
- if (false === fn) {
1005
- fn = _ignore;}
1006
- else throw new TypeError()}
1007
-
1008
- let rte = parse(
1009
- topic_route.replace(/[+#]$/, '*'));
1010
-
1011
- rte.key = topic_route;
1012
- rte.tgt = fn;
1013
- pri_lsts[priority ? 0 : 1].push(rte);
1014
- return this}
1015
-
1016
- , remove(topic_route, priority) {
1017
- let lst = pri_lsts[priority ? 0 : 1];
1018
- return _mqtt_route_remove([lst], topic_route)}
1019
-
1020
- , clear(priority) {
1021
- pri_lsts[priority ? 0 : 1] = [];
1022
- if (null == priority) {
1023
- pri_lsts[1] = [];} }
1024
-
1025
- , async invoke(pkt, ctx) {
1026
- ctx.idx = 0;
1027
- ctx.rm = rm;
1028
-
1029
- for (let [fn, params] of find(pkt.topic)) {
1030
- let res = await fn(pkt, params, ctx);
1031
-
1032
- if (rm === res) {
1033
- _mqtt_route_remove(pri_lsts, fn);}
1034
-
1035
- if (ctx.done) {
1036
- break}
1037
- else ctx.idx++;}
1038
-
1039
- let {pkt_id, qos} = pkt;
1040
- if (1 === qos) {
1041
- await ctx.mqtt._send('puback', {pkt_id});} } } }
1042
-
1043
-
1044
- function * _mqtt_routes_iter(all_route_lists, topic) {
1045
- for (let route_list of all_route_lists) {
1046
- for (let route of route_list) {
1047
- let res = _mqtt_route_match_one(topic, route);
1048
- if (undefined !== res) {
1049
- yield res;} } } }
1050
-
1051
-
1052
- function _mqtt_route_match_one(topic, {keys, pattern, tgt}) {
1053
- let match = '/' !== topic[0]
1054
- ? pattern.exec('/'+topic)
1055
- : pattern.exec(topic);
1056
-
1057
- if (null === match) {
1058
- return}
1059
-
1060
- if (false === keys) {
1061
- let {groups} = match;
1062
- if (! groups) {
1063
- return [tgt]}
1064
-
1065
- let params = {};
1066
- for (let k in groups) {
1067
- params[k] = groups[k];}
1068
-
1069
- return [tgt, params]}
1070
-
1071
- if (0 === keys.length) {
1072
- return [tgt]}
1073
-
1074
- let params = {};
1075
- for (let i=0; i<keys.length; i++) {
1076
- params[ keys[i] ] = match[1+i];}
1077
- return [tgt, params]}
1078
-
1079
-
1080
- function _mqtt_route_remove(all_route_lists, query) {
1081
- let match = route => route===query || route.tgt===query || route.key===query;
1082
- for (let lst of all_route_lists) {
1083
- let i = lst.findIndex(match);
1084
- if (0 <= i) {return !! lst.splice(i,1)} }
1085
- return false}
1086
-
1087
1145
  const _mqtt_cmdid_dispatch ={
1088
1146
  create(target) {
1089
1147
  return {__proto__: this, target, hashbelt: [new Map()]} }
@@ -1152,8 +1210,7 @@ const _mqtt_cmdid_dispatch ={
1152
1210
  let fn = target[`mqtt_${pkt.type}`]
1153
1211
  || target.mqtt_pkt;
1154
1212
 
1155
- if (undefined !== fn) {
1156
- await fn.call(target, pkt, ctx);} } })()) };
1213
+ await fn?.call(target, pkt, ctx);} })()) };
1157
1214
 
1158
1215
  function _mqtt_dispatch(opt, target) {
1159
1216
  let _disp_ = _mqtt_cmdid_dispatch.create(target);
@@ -1234,53 +1291,15 @@ class MQTTBase {
1234
1291
 
1235
1292
 
1236
1293
  // alias: sub
1237
- subscribe(pkt, ex) {
1238
- pkt = _as_topics(pkt, ex);
1294
+ subscribe(pkt, ex, topic_prefix) {
1295
+ pkt = _as_topics(pkt, ex, topic_prefix);
1239
1296
  return this._send('subscribe', pkt, pkt)}
1240
- _sub_chain(topic, ex) {
1241
- let res = this.subscribe([[ topic ]], ex);
1242
- let subs = this.subs ||(this.subs = new Map());
1243
- subs.set((res.topic = topic), (subs.last = res));
1244
- return this }// fluent api -- return this and track side effects
1245
1297
 
1246
1298
  // alias: unsub
1247
- unsubscribe(pkt, ex) {
1248
- pkt = _as_topics(pkt, ex);
1299
+ unsubscribe(pkt, ex, topic_prefix) {
1300
+ pkt = _as_topics(pkt, ex, topic_prefix);
1249
1301
  return this._send('unsubscribe', pkt, pkt)}
1250
1302
 
1251
- get on_topic() {return this.router.add}
1252
-
1253
- // alias: sub_topic
1254
- subscribe_topic(topic_route, ...args) {
1255
- this.router.add(topic_route, true, args.pop() );// handler
1256
- let topic = this.topic_for(topic_route);
1257
- return this._sub_chain(topic, args.pop() ) }// ex
1258
-
1259
- // alias: unsub_topic
1260
- unsubscribe_topic(topic_route) {
1261
- this.router.remove(topic_route, true);
1262
- let topic = this.topic_for(topic_route);
1263
- return this.unsubscribe([[ topic ]]) }
1264
-
1265
- // alias: shared_sub
1266
- shared_subscribe(group, topic_route, ...args) {
1267
- this.router.add(topic_route, true, args.pop() );// handler
1268
- let topic = this.topic_for(topic_route);
1269
- if (null != group) {
1270
- topic = `$share/${group}/${topic}`;}
1271
- return this._sub_chain(topic, args.pop() ) }// ex
1272
-
1273
- // alias: shared_unsub
1274
- shared_unsubscribe(group, topic_route) {
1275
- this.router.remove(topic_route, true);
1276
- let topic = this.topic_for(topic_route);
1277
- if (null != group) {
1278
- topic = `$share/${group}/${topic}`;}
1279
- return this.unsubscribe([[ topic ]]) }
1280
-
1281
- topic_for(topic_route) {
1282
- return topic_route.replace(/[:*].*$/, '#')}
1283
-
1284
1303
 
1285
1304
  // alias: pub
1286
1305
  publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
@@ -1306,9 +1325,9 @@ class MQTTBase {
1306
1325
  if (undefined === cid) {
1307
1326
  this.client_id = cid = (
1308
1327
 
1309
- this.sess_client_id(parts)
1328
+ this.sess_client_id(parts)
1310
1329
 
1311
-
1330
+
1312
1331
  );}
1313
1332
 
1314
1333
  return cid}
@@ -1317,66 +1336,85 @@ class MQTTBase {
1317
1336
  return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
1318
1337
 
1319
1338
 
1320
- sess_client_id(parts) {
1321
- let key = parts.join('\x20');
1322
- let cid = sessionStorage.getItem(key);
1323
- if (null == cid) {
1324
- cid = this.new_client_id(parts);
1325
- sessionStorage.setItem(key, cid);}
1326
- return cid}
1339
+ sess_client_id(parts) {
1340
+ let key = parts.join('\x20');
1341
+ let cid = sessionStorage.getItem(key);
1342
+ if (null == cid) {
1343
+ cid = this.new_client_id(parts);
1344
+ sessionStorage.setItem(key, cid);}
1345
+ return cid}
1327
1346
 
1328
1347
 
1329
1348
  // Internal API
1330
1349
 
1331
1350
  /* async _send(type, pkt) -- provided by _conn_ and transport */
1332
1351
 
1333
- _init_router(opt) {
1334
- return this.router = _mqtt_topic_router()}
1335
-
1336
1352
  _init_dispatch(opt) {
1353
+ this.constructor?._once_();
1354
+ let router = this.router =
1355
+ this._init_router?.(opt, this);
1356
+
1337
1357
  let tgt ={
1338
1358
  __proto__: opt.on_mqtt_type || {}
1339
- , router: this._init_router(opt, this)};
1359
+ , router};
1340
1360
 
1341
- tgt.mqtt_publish ||= tgt.router.invoke;
1342
- return _mqtt_dispatch(this, tgt)} }
1361
+ tgt.mqtt_publish ||= router?.invoke;
1362
+ return _mqtt_dispatch(this, tgt)}
1343
1363
 
1364
+ static _aliases() {
1365
+ return ' pub:publish sub:subscribe unsub:unsubscribe '}
1344
1366
 
1345
- {
1346
- let p = MQTTBase.prototype;
1347
- Object.assign(p,{
1348
- MQTTError
1349
- , pub: p.publish
1350
- , sub: p.subscribe
1351
- , unsub: p.unsubscribe
1352
- , sub_topic: p.subscribe_topic
1353
- , unsub_topic: p.unsubscribe_topic
1354
- , shared_sub: p.shared_subscribe
1355
- , shared_unsub: p.shared_unsubscribe} );
1367
+ static _once_(self=this) {
1368
+ self._once_ = _=>0;
1369
+ self.MQTTError = MQTTError;
1370
+ let p = self.prototype;
1371
+ for (let alias of self._aliases().split(/\s+/)) {
1372
+ alias = alias.split(':');
1373
+ let fn = alias[1] && p[alias[1]];
1374
+ if (fn) {p[alias[0]] = fn;} } } }
1356
1375
 
1357
- /*
1358
- p.on_mqtt_type = {
1359
- mqtt_auth(pkt, ctx) ::
1360
- mqtt_connect(pkt, ctx) ::
1361
- mqtt_connack(pkt, ctx) ::
1362
- mqtt_disconnect(pkt, ctx) ::
1363
-
1364
- mqtt_publish(pkt, ctx)
1365
- mqtt_subscribe(pkt, ctx) ::
1366
- mqtt_unsubscribe(pkt, ctx) ::
1367
-
1368
- mqtt_pingreq(pkt, ctx) ::
1369
- mqtt_pingresp(pkt, ctx) ::
1370
- }
1371
- */}
1372
1376
 
1377
+ /*
1378
+ on_mqtt_type = {
1379
+ mqtt_auth(pkt, ctx) ::
1380
+ mqtt_connect(pkt, ctx) ::
1381
+ mqtt_connack(pkt, ctx) ::
1382
+ mqtt_disconnect(pkt, ctx) ::
1383
+
1384
+ mqtt_publish(pkt, ctx)
1385
+ mqtt_subscribe(pkt, ctx) ::
1386
+ mqtt_unsubscribe(pkt, ctx) ::
1387
+
1388
+ mqtt_pingreq(pkt, ctx) ::
1389
+ mqtt_pingresp(pkt, ctx) ::
1390
+ }
1391
+ */
1373
1392
 
1374
- function _as_topics(pkt, ex) {
1375
- if ('string' === typeof pkt) {
1376
- return {topics:[pkt], ... ex}}
1377
- if (pkt[Symbol.iterator]) {
1378
- return {topics:[... pkt], ... ex}}
1379
- return ex ? {...pkt, ...ex} : pkt}
1393
+
1394
+ const _prefix_topics = (topic_prefix, iterable) =>
1395
+ Array.from(iterable, value =>(
1396
+ value.trim // string
1397
+ ? _prefix_topics(topic_prefix, value)
1398
+ : topic_prefix + value) );
1399
+
1400
+ function _as_topics(pkt, ex, topic_prefix) {
1401
+ if (ex?.trim) {// string
1402
+ topic_prefix = ex;
1403
+ ex = null;}
1404
+
1405
+ pkt =(
1406
+ pkt.trim // string
1407
+ ? {topics:[pkt], ... ex}
1408
+ : pkt[Symbol.iterator]
1409
+ ? {topics:[... pkt], ... ex}
1410
+ : ex ? {...pkt, ...ex}
1411
+ : pkt);
1412
+
1413
+ if (topic_prefix) {
1414
+ // particularly useful with shared queues, e.g.
1415
+ // topic_prefix = '$share/some-queue-name/'
1416
+ pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
1417
+ return pkt}
1380
1418
 
1381
1419
 
1382
1420
  async function _pub(self, pkt, pub_opt) {
@@ -1448,7 +1486,7 @@ class MQTTCore extends MQTTBase {
1448
1486
  return this}
1449
1487
 
1450
1488
  //log_conn(evt, arg, err_arg) ::
1451
- //console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
1489
+ // console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
1452
1490
 
1453
1491
  on_live(client, is_reconnect) {
1454
1492
  if (is_reconnect) {
@@ -1490,30 +1528,55 @@ class MQTTCore extends MQTTBase {
1490
1528
  return this}
1491
1529
 
1492
1530
 
1493
-
1494
-
1495
-
1496
-
1497
-
1498
-
1499
-
1500
-
1501
-
1502
-
1503
-
1504
-
1505
-
1506
-
1507
-
1508
1531
 
1509
1532
 
1533
+
1534
+
1535
+
1536
+
1537
+
1538
+
1510
1539
 
1540
+
1541
+
1542
+
1543
+
1544
+
1511
1545
 
1546
+
1547
+
1548
+
1549
+
1550
+
1512
1551
 
1552
+
1553
+
1554
+
1555
+
1513
1556
 
1557
+
1558
+
1514
1559
 
1560
+
1561
+
1562
+
1563
+
1564
+
1565
+
1566
+
1515
1567
 
1568
+
1569
+
1570
+
1571
+
1572
+
1516
1573
 
1574
+
1575
+
1576
+
1577
+
1578
+
1579
+
1517
1580
 
1518
1581
 
1519
1582
  with_stream(read_stream, write_stream) {
@@ -1559,13 +1622,15 @@ class MQTTCore extends MQTTBase {
1559
1622
 
1560
1623
  return this} }
1561
1624
 
1562
- var version = "0.3.1";
1625
+ const version = '0.4.0';
1563
1626
 
1564
1627
  const MQTTClient_v4 = /* #__PURE__ */
1565
- MQTTCore.mqtt_ctx(4, mqtt_opts_v5);
1628
+ with_topic_path_router(
1629
+ MQTTCore.mqtt_ctx(4, mqtt_opts_v5) );
1566
1630
 
1567
1631
  const MQTTClient_v5 = /* #__PURE__ */
1568
- MQTTCore.mqtt_ctx(5, mqtt_opts_v5);
1632
+ with_topic_path_router(
1633
+ MQTTCore.mqtt_ctx(5, mqtt_opts_v5) );
1569
1634
 
1570
1635
  const mqtt_v4 = opt =>
1571
1636
  new MQTTClient_v4(opt);
@@ -1573,5 +1638,5 @@ const mqtt_v4 = opt =>
1573
1638
  const mqtt_v5 = opt =>
1574
1639
  new MQTTClient_v5(opt);
1575
1640
 
1576
- export { MQTTBase, MQTTClient_v4, MQTTClient_v5, MQTTCore, MQTTError, _mqtt_cmdid_dispatch, _mqtt_conn, _mqtt_dispatch, _mqtt_route_match_one, _mqtt_route_remove, _mqtt_routes_iter, _mqtt_topic_router, ao_defer_v, mqtt_v4 as default, mqtt_v4, mqtt_v5, version };
1641
+ export { MQTTBase, MQTTClient_v4, MQTTClient_v5, MQTTCore, MQTTError, _mqtt_cmdid_dispatch, _mqtt_conn, _mqtt_dispatch, ao_defer_v, as_topic_path, mqtt_v4 as default, mqtt_v4, mqtt_v5, version, with_topic_path_router, with_topic_router };
1577
1642
  //# sourceMappingURL=index.js.map