u8-mqtt 0.3.2-0 → 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 (76) 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 +308 -267
  7. package/cjs/index.cjs.map +1 -1
  8. package/cjs/v4.cjs +303 -262
  9. package/cjs/v4.cjs.map +1 -1
  10. package/cjs/v5.cjs +305 -263
  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/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} +30 -12
  18. package/code/v4.js +3 -1
  19. package/code/v5.js +5 -2
  20. package/code/with_topic_router.jsy +41 -0
  21. package/esm/deno/basic-v4.js +1193 -0
  22. package/esm/deno/basic-v4.js.map +1 -0
  23. package/esm/deno/basic-v5.js +1455 -0
  24. package/esm/deno/basic-v5.js.map +1 -0
  25. package/esm/deno/index.js +306 -264
  26. package/esm/deno/index.js.map +1 -1
  27. package/esm/deno/v4.js +303 -262
  28. package/esm/deno/v4.js.map +1 -1
  29. package/esm/deno/v5.js +305 -263
  30. package/esm/deno/v5.js.map +1 -1
  31. package/esm/node/basic-v4.js +1196 -0
  32. package/esm/node/basic-v4.js.map +1 -0
  33. package/esm/node/basic-v4.mjs +1196 -0
  34. package/esm/node/basic-v4.mjs.map +1 -0
  35. package/esm/node/basic-v5.js +1458 -0
  36. package/esm/node/basic-v5.js.map +1 -0
  37. package/esm/node/basic-v5.mjs +1458 -0
  38. package/esm/node/basic-v5.mjs.map +1 -0
  39. package/esm/node/index.js +306 -264
  40. package/esm/node/index.js.map +1 -1
  41. package/esm/node/index.mjs +306 -264
  42. package/esm/node/index.mjs.map +1 -1
  43. package/esm/node/v4.js +303 -262
  44. package/esm/node/v4.js.map +1 -1
  45. package/esm/node/v4.mjs +303 -262
  46. package/esm/node/v4.mjs.map +1 -1
  47. package/esm/node/v5.js +305 -263
  48. package/esm/node/v5.js.map +1 -1
  49. package/esm/node/v5.mjs +305 -263
  50. package/esm/node/v5.mjs.map +1 -1
  51. package/esm/web/basic-v4.js +1193 -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 +1455 -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 +305 -263
  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 +303 -262
  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 +304 -262
  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
@@ -772,6 +772,191 @@ 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) {
819
+ return mqtt_topic_router(opt, this)}
820
+
821
+ get on_topic() {return this.router.add}
822
+
823
+ _sub_chain(topic, ex, topic_prefix) {
824
+ let res = this.subscribe([[ topic ]], ex, topic_prefix);
825
+ let subs = this.subs ||(this.subs = new Map());
826
+ subs.set((res.topic = topic), (subs.last = res));
827
+ return this }// fluent api -- return this and track side effects
828
+
829
+ // alias: sub_topic
830
+ subscribe_topic(topic_route, ...args) {
831
+ let router = this.router;
832
+ router.add(topic_route, true, args.pop() );// handler
833
+ let topic = router.mqtt_topic(topic_route);
834
+ return this._sub_chain(topic, ...args ) }// ex, topic_prefix
835
+
836
+ // alias: unsub_topic
837
+ unsubscribe_topic(topic_route, ...args) {
838
+ let router = this.router;
839
+ router.remove(topic_route, true);
840
+ let topic = router.mqtt_topic(topic_route);
841
+ return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
842
+
843
+ // Use [regexparam][] for url-like topic parsing
844
+ // [regexparam]: https://github.com/lukeed/regexparam
845
+
846
+
847
+ const with_topic_path_router = /* #__PURE__ */
848
+ with_topic_router(mqtt_topic_path_router);
849
+
850
+
851
+ const mqtt_topic = topic_route =>
852
+ topic_route
853
+ .replace(/[*].*$/, '#')
854
+ .replace(/:\w+\??/g, '+');
855
+
856
+ const as_topic_path = topic_route =>(
857
+ topic_route
858
+ .replace(/#$/, '*') // replace MQTT # wildcard at end
859
+ .split(/([^\/]*[+][^\/]*)/) // split on MQTT + match tokens
860
+ .reduce (( sz, v, idx ) => sz +(
861
+ idx & 1 // even entires are body, odd are MQTT + tokens
862
+ ? `:$${1 + idx>>1}` // replace with `:$#` sequential ids, using ? for partial entries
863
+ : v ) ) );// pass through body
864
+
865
+ function _ignore(pkt, params, ctx) {ctx.done = true;}
866
+
867
+ function mqtt_topic_path_router() {
868
+ let pri_lsts = [[],[]], rm = Symbol();
869
+ let find = topic => _routes_iter(pri_lsts, topic);
870
+
871
+ // return duck-type compatible with AbstractTopicRouter in ./with_topic_router
872
+ return {find, mqtt_topic,
873
+ add(topic_route, ...args) {
874
+ let fn = args.pop();
875
+ let priority = args.pop();
876
+
877
+ if ('function' !== typeof fn) {
878
+ if (false === fn) {
879
+ fn = _ignore;}
880
+ else throw new TypeError()}
881
+
882
+ let rte = parse(as_topic_path(topic_route));
883
+
884
+ rte.key = topic_route;
885
+ rte.tgt = fn;
886
+ pri_lsts[priority ? 0 : 1].push(rte);
887
+ return this}
888
+
889
+ , remove(topic_route, priority) {
890
+ let lst = pri_lsts[priority ? 0 : 1];
891
+ return _route_remove([lst], topic_route)}
892
+
893
+ , clear(priority) {
894
+ pri_lsts[priority ? 0 : 1] = [];
895
+ if (null == priority) {
896
+ pri_lsts[1] = [];} }
897
+
898
+ , async invoke(pkt, ctx) {
899
+ ctx.idx = 0;
900
+ ctx.rm = rm;
901
+
902
+ for (let [fn, params] of find(pkt.topic)) {
903
+ let res = await fn(pkt, params, ctx);
904
+
905
+ if (rm === res) {
906
+ _route_remove(pri_lsts, fn);}
907
+
908
+ if (ctx.done) {
909
+ break}
910
+ else ctx.idx++;}
911
+
912
+ let {pkt_id, qos} = pkt;
913
+ if (1 === qos) {
914
+ await ctx.mqtt._send('puback', {pkt_id});} } } }
915
+
916
+
917
+ function * _routes_iter(all_route_lists, topic) {
918
+ for (let route_list of all_route_lists) {
919
+ for (let route of route_list) {
920
+ let res = _route_match_one(topic, route);
921
+ if (undefined !== res) {
922
+ yield res;} } } }
923
+
924
+
925
+ function _route_match_one(topic, {keys, pattern, tgt}) {
926
+ let match = '/' !== topic[0]
927
+ ? pattern.exec('/'+topic)
928
+ : pattern.exec(topic);
929
+
930
+ if (null === match) {
931
+ return}
932
+
933
+ if (false === keys) {
934
+ let {groups} = match;
935
+ if (! groups) {
936
+ return [tgt]}
937
+
938
+ let params = {};
939
+ for (let k in groups) {
940
+ params[k] = groups[k];}
941
+
942
+ return [tgt, params]}
943
+
944
+ if (0 === keys.length) {
945
+ return [tgt]}
946
+
947
+ let params = {};
948
+ for (let i=0; i<keys.length; i++) {
949
+ params[ keys[i] ] = match[1+i];}
950
+ return [tgt, params]}
951
+
952
+
953
+ function _route_remove(all_route_lists, query) {
954
+ let match = route => route===query || route.tgt===query || route.key===query;
955
+ for (let lst of all_route_lists) {
956
+ let i = lst.findIndex(match);
957
+ if (0 <= i) {return !! lst.splice(i,1)} }
958
+ return false}
959
+
775
960
  /*
776
961
  export function decode_varint_loop(u8, i=0) {
777
962
  let i0 = i
@@ -953,138 +1138,13 @@ function _ping_interval(send_ping) {
953
1138
  if (td) {
954
1139
  tid = setInterval(send_ping, 1000 * td);
955
1140
 
956
-
957
-
1141
+
1142
+
958
1143
 
959
- // ensure the interval allows the NodeJS event loop to exit
960
- tid.unref?.();
1144
+ // ensure the interval allows the NodeJS event loop to exit
1145
+ tid.unref?.();
961
1146
  return true} }) }
962
1147
 
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
1148
  const _mqtt_cmdid_dispatch ={
1089
1149
  create(target) {
1090
1150
  return {__proto__: this, target, hashbelt: [new Map()]} }
@@ -1153,8 +1213,7 @@ const _mqtt_cmdid_dispatch ={
1153
1213
  let fn = target[`mqtt_${pkt.type}`]
1154
1214
  || target.mqtt_pkt;
1155
1215
 
1156
- if (undefined !== fn) {
1157
- await fn.call(target, pkt, ctx);} } })()) };
1216
+ await fn?.call(target, pkt, ctx);} })()) };
1158
1217
 
1159
1218
  function _mqtt_dispatch(opt, target) {
1160
1219
  let _disp_ = _mqtt_cmdid_dispatch.create(target);
@@ -1235,53 +1294,15 @@ class MQTTBase {
1235
1294
 
1236
1295
 
1237
1296
  // alias: sub
1238
- subscribe(pkt, ex) {
1239
- pkt = _as_topics(pkt, ex);
1297
+ subscribe(pkt, ex, topic_prefix) {
1298
+ pkt = _as_topics(pkt, ex, topic_prefix);
1240
1299
  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
1300
 
1247
1301
  // alias: unsub
1248
- unsubscribe(pkt, ex) {
1249
- pkt = _as_topics(pkt, ex);
1302
+ unsubscribe(pkt, ex, topic_prefix) {
1303
+ pkt = _as_topics(pkt, ex, topic_prefix);
1250
1304
  return this._send('unsubscribe', pkt, pkt)}
1251
1305
 
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
1306
 
1286
1307
  // alias: pub
1287
1308
  publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
@@ -1307,9 +1328,9 @@ class MQTTBase {
1307
1328
  if (undefined === cid) {
1308
1329
  this.client_id = cid = (
1309
1330
 
1310
-
1331
+
1311
1332
 
1312
- this.new_client_id(parts)
1333
+ this.new_client_id(parts)
1313
1334
  );}
1314
1335
 
1315
1336
  return cid}
@@ -1318,66 +1339,85 @@ class MQTTBase {
1318
1339
  return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
1319
1340
 
1320
1341
 
1321
-
1322
-
1323
-
1324
-
1325
-
1326
-
1327
-
1342
+
1343
+
1344
+
1345
+
1346
+
1347
+
1348
+
1328
1349
 
1329
1350
 
1330
1351
  // Internal API
1331
1352
 
1332
1353
  /* async _send(type, pkt) -- provided by _conn_ and transport */
1333
1354
 
1334
- _init_router(opt) {
1335
- return this.router = _mqtt_topic_router()}
1336
-
1337
1355
  _init_dispatch(opt) {
1356
+ this.constructor?._once_();
1357
+ let router = this.router =
1358
+ this._init_router?.(opt, this);
1359
+
1338
1360
  let tgt ={
1339
1361
  __proto__: opt.on_mqtt_type || {}
1340
- , router: this._init_router(opt, this)};
1362
+ , router};
1341
1363
 
1342
- tgt.mqtt_publish ||= tgt.router.invoke;
1343
- return _mqtt_dispatch(this, tgt)} }
1364
+ tgt.mqtt_publish ||= router?.invoke;
1365
+ return _mqtt_dispatch(this, tgt)}
1344
1366
 
1367
+ static _aliases() {
1368
+ return ' pub:publish sub:subscribe unsub:unsubscribe '}
1345
1369
 
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} );
1370
+ static _once_(self=this) {
1371
+ self._once_ = _=>0;
1372
+ self.MQTTError = MQTTError;
1373
+ let p = self.prototype;
1374
+ for (let alias of self._aliases().split(/\s+/)) {
1375
+ alias = alias.split(':');
1376
+ let fn = alias[1] && p[alias[1]];
1377
+ if (fn) {p[alias[0]] = fn;} } } }
1357
1378
 
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
- */}
1379
+
1380
+ /*
1381
+ on_mqtt_type = {
1382
+ mqtt_auth(pkt, ctx) ::
1383
+ mqtt_connect(pkt, ctx) ::
1384
+ mqtt_connack(pkt, ctx) ::
1385
+ mqtt_disconnect(pkt, ctx) ::
1386
+
1387
+ mqtt_publish(pkt, ctx)
1388
+ mqtt_subscribe(pkt, ctx) ::
1389
+ mqtt_unsubscribe(pkt, ctx) ::
1390
+
1391
+ mqtt_pingreq(pkt, ctx) ::
1392
+ mqtt_pingresp(pkt, ctx) ::
1393
+ }
1394
+ */
1373
1395
 
1374
1396
 
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}
1397
+ const _prefix_topics = (topic_prefix, iterable) =>
1398
+ Array.from(iterable, value =>(
1399
+ value.trim // string
1400
+ ? _prefix_topics(topic_prefix, value)
1401
+ : topic_prefix + value) );
1402
+
1403
+ function _as_topics(pkt, ex, topic_prefix) {
1404
+ if (ex?.trim) {// string
1405
+ topic_prefix = ex;
1406
+ ex = null;}
1407
+
1408
+ pkt =(
1409
+ pkt.trim // string
1410
+ ? {topics:[pkt], ... ex}
1411
+ : pkt[Symbol.iterator]
1412
+ ? {topics:[... pkt], ... ex}
1413
+ : ex ? {...pkt, ...ex}
1414
+ : pkt);
1415
+
1416
+ if (topic_prefix) {
1417
+ // particularly useful with shared queues, e.g.
1418
+ // topic_prefix = '$share/some-queue-name/'
1419
+ pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
1420
+ return pkt}
1381
1421
 
1382
1422
 
1383
1423
  async function _pub(self, pkt, pub_opt) {
@@ -1493,53 +1533,53 @@ class MQTTCore extends MQTTBase {
1493
1533
 
1494
1534
 
1495
1535
 
1536
+
1537
+
1538
+
1539
+
1540
+
1541
+
1496
1542
 
1543
+
1544
+
1545
+
1546
+
1547
+
1497
1548
 
1549
+
1550
+
1551
+
1552
+
1553
+
1498
1554
 
1555
+
1556
+
1557
+
1558
+
1499
1559
 
1560
+
1561
+
1500
1562
 
1563
+
1564
+ with_tcp(...opt) {
1565
+ opt = this._conn_opt(opt);
1566
+ console.log({opt});
1567
+ return this._use_conn (() =>
1568
+ this.with_stream(
1569
+ connect(opt)) ) }
1501
1570
 
1571
+ with_tls(...opt) {
1572
+ opt = this._conn_opt(opt);
1573
+ return this._use_conn (() =>
1574
+ this.with_stream(
1575
+ connect$1(opt)) ) }
1502
1576
 
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}}
1577
+ _conn_opt([a0, a1, a2]) {
1578
+ // (port, hostname, options) or (url, options)
1579
+ if (Number.isFinite(a0)) {
1580
+ return {...a2, port: a0, host: a1}}
1581
+ a0 = new URL(a0);
1582
+ return {...a1, port: a0.port, host: a0.hostname}}
1543
1583
 
1544
1584
 
1545
1585
  with_stream(read_stream, write_stream) {
@@ -1585,13 +1625,15 @@ class MQTTCore extends MQTTBase {
1585
1625
 
1586
1626
  return this} }
1587
1627
 
1588
- const version = '0.3.2-0';
1628
+ const version = '0.4.0';
1589
1629
 
1590
1630
  const MQTTClient_v4 = /* #__PURE__ */
1591
- MQTTCore.mqtt_ctx(4, mqtt_opts_v5);
1631
+ with_topic_path_router(
1632
+ MQTTCore.mqtt_ctx(4, mqtt_opts_v5) );
1592
1633
 
1593
1634
  const MQTTClient_v5 = /* #__PURE__ */
1594
- MQTTCore.mqtt_ctx(5, mqtt_opts_v5);
1635
+ with_topic_path_router(
1636
+ MQTTCore.mqtt_ctx(5, mqtt_opts_v5) );
1595
1637
 
1596
1638
  const mqtt_v4 = opt =>
1597
1639
  new MQTTClient_v4(opt);
@@ -1599,5 +1641,5 @@ const mqtt_v4 = opt =>
1599
1641
  const mqtt_v5 = opt =>
1600
1642
  new MQTTClient_v5(opt);
1601
1643
 
1602
- 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 };
1644
+ 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 };
1603
1645
  //# sourceMappingURL=index.mjs.map