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