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/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
- // ensure the interval allows the NodeJS event loop to exit
960
- tid.unref?.();
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
- if (undefined !== fn) {
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
- this.new_client_id(parts)
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
- let tgt ={
1339
- __proto__: opt.on_mqtt_type || {}
1340
- , router: this._init_router(opt, this)};
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
- tgt.mqtt_publish ||= tgt.router.invoke;
1343
- return _mqtt_dispatch(this, tgt)} }
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
- p.on_mqtt_type = {
1360
- mqtt_auth(pkt, ctx) ::
1361
- mqtt_connect(pkt, ctx) ::
1362
- mqtt_connack(pkt, ctx) ::
1363
- mqtt_disconnect(pkt, ctx) ::
1364
-
1365
- mqtt_publish(pkt, ctx)
1366
- mqtt_subscribe(pkt, ctx) ::
1367
- mqtt_unsubscribe(pkt, ctx) ::
1368
-
1369
- mqtt_pingreq(pkt, ctx) ::
1370
- mqtt_pingresp(pkt, ctx) ::
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
- function _as_topics(pkt, ex) {
1376
- if ('string' === typeof pkt) {
1377
- return {topics:[pkt], ... ex}}
1378
- if (pkt[Symbol.iterator]) {
1379
- return {topics:[... pkt], ... ex}}
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.3.2-0';
1630
+ const version = '0.4.1';
1589
1631
 
1590
1632
  const MQTTClient_v4 = /* #__PURE__ */
1591
- MQTTCore.mqtt_ctx(4, mqtt_opts_v5);
1633
+ with_topic_path_router(
1634
+ MQTTCore.mqtt_ctx(4, mqtt_opts_v5) );
1592
1635
 
1593
1636
  const MQTTClient_v5 = /* #__PURE__ */
1594
- MQTTCore.mqtt_ctx(5, mqtt_opts_v5);
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);