u8-mqtt 0.4.0 → 0.5.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 (82) hide show
  1. package/README.md +3 -3
  2. package/cjs/basic-v4.cjs +107 -146
  3. package/cjs/basic-v4.cjs.map +1 -1
  4. package/cjs/basic-v5.cjs +106 -145
  5. package/cjs/basic-v5.cjs.map +1 -1
  6. package/cjs/index.cjs +163 -206
  7. package/cjs/index.cjs.map +1 -1
  8. package/cjs/v4.cjs +164 -207
  9. package/cjs/v4.cjs.map +1 -1
  10. package/cjs/v5.cjs +163 -206
  11. package/cjs/v5.cjs.map +1 -1
  12. package/code/_dispatch.jsy +16 -0
  13. package/code/base.jsy +72 -133
  14. package/code/core.jsy +15 -9
  15. package/code/router_path.jsy +38 -51
  16. package/code/with_topic_router.jsy +20 -11
  17. package/esm/basic-v4.js +1154 -0
  18. package/esm/basic-v4.js.map +1 -0
  19. package/esm/basic-v5.js +1416 -0
  20. package/esm/basic-v5.js.map +1 -0
  21. package/esm/deno/basic-v4.js +107 -146
  22. package/esm/deno/basic-v4.js.map +1 -1
  23. package/esm/deno/basic-v5.js +106 -145
  24. package/esm/deno/basic-v5.js.map +1 -1
  25. package/esm/deno/index.js +163 -206
  26. package/esm/deno/index.js.map +1 -1
  27. package/esm/deno/v4.js +164 -207
  28. package/esm/deno/v4.js.map +1 -1
  29. package/esm/deno/v5.js +163 -206
  30. package/esm/deno/v5.js.map +1 -1
  31. package/esm/index.js +1599 -0
  32. package/esm/index.js.map +1 -0
  33. package/esm/node/basic-v4.js +107 -146
  34. package/esm/node/basic-v4.js.map +1 -1
  35. package/esm/node/basic-v4.mjs +107 -146
  36. package/esm/node/basic-v4.mjs.map +1 -1
  37. package/esm/node/basic-v5.js +106 -145
  38. package/esm/node/basic-v5.js.map +1 -1
  39. package/esm/node/basic-v5.mjs +106 -145
  40. package/esm/node/basic-v5.mjs.map +1 -1
  41. package/esm/node/index.js +163 -206
  42. package/esm/node/index.js.map +1 -1
  43. package/esm/node/index.mjs +163 -206
  44. package/esm/node/index.mjs.map +1 -1
  45. package/esm/node/v4.js +164 -207
  46. package/esm/node/v4.js.map +1 -1
  47. package/esm/node/v4.mjs +164 -207
  48. package/esm/node/v4.mjs.map +1 -1
  49. package/esm/node/v5.js +163 -206
  50. package/esm/node/v5.js.map +1 -1
  51. package/esm/node/v5.mjs +163 -206
  52. package/esm/node/v5.mjs.map +1 -1
  53. package/esm/v4.js +1336 -0
  54. package/esm/v4.js.map +1 -0
  55. package/esm/v5.js +1599 -0
  56. package/esm/v5.js.map +1 -0
  57. package/esm/web/basic-v4.js +107 -146
  58. package/esm/web/basic-v4.js.map +1 -1
  59. package/esm/web/basic-v4.min.js +1 -1
  60. package/esm/web/basic-v4.min.js.br +0 -0
  61. package/esm/web/basic-v4.min.js.gz +0 -0
  62. package/esm/web/basic-v5.js +106 -145
  63. package/esm/web/basic-v5.js.map +1 -1
  64. package/esm/web/basic-v5.min.js +1 -1
  65. package/esm/web/basic-v5.min.js.br +0 -0
  66. package/esm/web/basic-v5.min.js.gz +0 -0
  67. package/esm/web/index.js +163 -206
  68. package/esm/web/index.js.map +1 -1
  69. package/esm/web/index.min.js +1 -1
  70. package/esm/web/index.min.js.br +0 -0
  71. package/esm/web/index.min.js.gz +0 -0
  72. package/esm/web/v4.js +164 -207
  73. package/esm/web/v4.js.map +1 -1
  74. package/esm/web/v4.min.js +1 -1
  75. package/esm/web/v4.min.js.br +0 -0
  76. package/esm/web/v4.min.js.gz +0 -0
  77. package/esm/web/v5.js +163 -206
  78. package/esm/web/v5.js.map +1 -1
  79. package/esm/web/v5.min.js +1 -1
  80. package/esm/web/v5.min.js.br +0 -0
  81. package/esm/web/v5.min.js.gz +0 -0
  82. package/package.json +7 -8
package/esm/web/index.js CHANGED
@@ -147,7 +147,7 @@ class mqtt_reader_v4 {
147
147
 
148
148
  }
149
149
 
150
- class mqtt_reader_v5$1 extends mqtt_reader_v4 {
150
+ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
151
151
  props() {
152
152
  let {buf, step} = this;
153
153
  let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
@@ -182,7 +182,7 @@ class mqtt_reader_v5$1 extends mqtt_reader_v4 {
182
182
  : buf.subarray(vi, step.k|0)
183
183
  }
184
184
  */
185
- }
185
+ };
186
186
 
187
187
  function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
188
188
  mqtt_reader = class extends mqtt_reader {
@@ -812,30 +812,39 @@ const with_topic_router = mqtt_topic_router =>
812
812
  return super._aliases() +
813
813
  ' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'}
814
814
 
815
- _init_router(opt) {
816
- return mqtt_topic_router(opt, this)}
817
-
818
- get on_topic() {return this.router.add}
815
+ _init_router(opt, self, target) {
816
+ this._subs = [];
817
+ let router = this.router = target.router =
818
+ mqtt_topic_router(opt, this, target);
819
+ return router?.invoke}
819
820
 
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
821
+ on_sub(suback, pkt) {
822
+ suback.pkt = pkt;
823
+ this._subs.push(suback);
824
+ return suback}
825
+ subs_settled() {
826
+ return Promise.allSettled(
827
+ this._subs.splice(0,Infinity)) }
825
828
 
826
829
  // alias: sub_topic
827
830
  subscribe_topic(topic_route, ...args) {
828
831
  let router = this.router;
829
832
  router.add(topic_route, true, args.pop() );// handler
830
833
  let topic = router.mqtt_topic(topic_route);
831
- return this._sub_chain(topic, ...args ) }// ex, topic_prefix
834
+ this.subscribe(topic, ...args );// ex, topic_prefix
835
+ return this }// fluent api -- return this and track side effects
832
836
 
833
837
  // alias: unsub_topic
834
838
  unsubscribe_topic(topic_route, ...args) {
835
839
  let router = this.router;
836
840
  router.remove(topic_route, true);
837
841
  let topic = router.mqtt_topic(topic_route);
838
- return this.unsubscribe([[ topic ]], ...args ) } };// topic_prefix
842
+ return this.unsubscribe(topic, ...args ) }// topic_prefix
843
+
844
+ // add topic handlers without corresponding subscribe packet
845
+ on_topic(...args) {
846
+ this.router.add(...args);
847
+ return this} };
839
848
 
840
849
  // Use [regexparam][] for url-like topic parsing
841
850
  // [regexparam]: https://github.com/lukeed/regexparam
@@ -848,16 +857,22 @@ const with_topic_path_router = /* #__PURE__ */
848
857
  const mqtt_topic = topic_route =>
849
858
  topic_route
850
859
  .replace(/[*].*$/, '#')
851
- .replace(/:\w+\??/g, '+');
860
+ .replace(/:\w[^\/]*/g, '+');
852
861
 
853
- const as_topic_path = topic_route =>(
862
+ /* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
863
+ 4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
864
+ ... MUST be specified either on its own or following a topic level separator.
865
+ In either case it MUST be the last character specified in the Topic Filter
866
+
867
+ 4.7.1.3 Single-level wildcard -- (‘+’ U+002B)
868
+ ...it MUST occupy an entire level of the filter.
869
+ */
870
+
871
+ const as_topic_path = (topic_route, id) =>(
872
+ id=1,
854
873
  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
874
+ .replace(/#$/, '*' )// replace MQTT '#' multi-level wildcard at end
875
+ .replace(/\+/g, () => `:$${id++}` ) );// replace MQTT '+' single-level wildcards
861
876
 
862
877
  function _ignore(pkt, params, ctx) {ctx.done = true;}
863
878
 
@@ -872,9 +887,8 @@ function mqtt_topic_path_router() {
872
887
  let priority = args.pop();
873
888
 
874
889
  if ('function' !== typeof fn) {
875
- if (false === fn) {
876
- fn = _ignore;}
877
- else throw new TypeError()}
890
+ if (fn) {throw new TypeError()}
891
+ fn = _ignore;}
878
892
 
879
893
  let rte = parse(as_topic_path(topic_route));
880
894
 
@@ -890,7 +904,7 @@ function mqtt_topic_path_router() {
890
904
  , clear(priority) {
891
905
  pri_lsts[priority ? 0 : 1] = [];
892
906
  if (null == priority) {
893
- pri_lsts[1] = [];} }
907
+ pri_lsts[1] = []; } }// null clears both lists
894
908
 
895
909
  , async invoke(pkt, ctx) {
896
910
  ctx.idx = 0;
@@ -906,52 +920,34 @@ function mqtt_topic_path_router() {
906
920
  break}
907
921
  else ctx.idx++;}
908
922
 
909
- let {pkt_id, qos} = pkt;
910
- if (1 === qos) {
911
- await ctx.mqtt._send('puback', {pkt_id});} } } }
923
+ if (1 === pkt.qos) {
924
+ await ctx.mqtt.puback(pkt);} } } }
912
925
 
913
926
 
914
927
  function * _routes_iter(all_route_lists, topic) {
928
+ topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
915
929
  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]}
930
+ for (let {keys, pattern, tgt} of route_list) {
931
+ let match = pattern.exec(topic);
932
+ if (match) {
933
+ let params = keys
934
+ ? keys.reduce(
935
+ (o, k, i) => (o[k] = match[1+i], o)
936
+ , {})
937
+ : match.groups ?? match;
938
+ yield [tgt, params];} } } }
948
939
 
949
940
 
950
941
  function _route_remove(all_route_lists, query) {
951
- let match = route => route===query || route.tgt===query || route.key===query;
942
+ let fn_match = route =>(
943
+ route===query
944
+ || route.tgt===query
945
+ || route.key===query);
952
946
  for (let lst of all_route_lists) {
953
- let i = lst.findIndex(match);
954
- if (0 <= i) {return !! lst.splice(i,1)} }
947
+ let i = lst.findIndex(fn_match);
948
+ if (0 <= i) {
949
+ lst.splice(i,1);
950
+ return true} }
955
951
  return false}
956
952
 
957
953
  /*
@@ -1212,6 +1208,22 @@ const _mqtt_cmdid_dispatch ={
1212
1208
 
1213
1209
  await fn?.call(target, pkt, ctx);} })()) };
1214
1210
 
1211
+ /*
1212
+ on_mqtt_type = {
1213
+ mqtt_auth(pkt, ctx) ::
1214
+ mqtt_connect(pkt, ctx) ::
1215
+ mqtt_connack(pkt, ctx) ::
1216
+ mqtt_disconnect(pkt, ctx) ::
1217
+
1218
+ mqtt_publish(pkt, ctx)
1219
+ mqtt_subscribe(pkt, ctx) ::
1220
+ mqtt_unsubscribe(pkt, ctx) ::
1221
+
1222
+ mqtt_pingreq(pkt, ctx) ::
1223
+ mqtt_pingresp(pkt, ctx) ::
1224
+ }
1225
+ */
1226
+
1215
1227
  function _mqtt_dispatch(opt, target) {
1216
1228
  let _disp_ = _mqtt_cmdid_dispatch.create(target);
1217
1229
  let { cmdids } = _disp_;
@@ -1241,28 +1253,34 @@ class MQTTError extends Error {
1241
1253
 
1242
1254
  class MQTTBase {
1243
1255
  constructor(opt={}) {
1256
+ this.with(opt);
1244
1257
  this._conn_ = _mqtt_conn(this,
1245
1258
  this._init_dispatch(opt, this)); }
1246
1259
 
1260
+ with(fns_ns) {
1261
+ for (let [k,v] of Object.entries(fns_ns)) {
1262
+ if ('function' === typeof v) {this[k] = v;} }
1263
+ return this}
1264
+
1247
1265
  async conn_emit(evt, arg, err_arg) {
1248
1266
  this.log_conn?.(evt, arg, err_arg);
1249
1267
  try {
1250
- let fn_evt = this[await evt]; // microtask break
1268
+ let fn_evt = this[await evt]; // microtask break using `await evt`
1251
1269
  if (fn_evt) {
1252
1270
  await fn_evt.call(this, this, arg, err_arg);}
1253
- else if (err_arg) {
1254
- await this.on_error(err_arg, evt);} }
1271
+ else if (err_arg) {throw err_arg} }
1255
1272
  catch (err) {
1256
1273
  this.on_error(err, evt);} }
1257
1274
 
1258
- on_error(err, err_path) {
1259
- console.warn('[[u8-mqtt error: %s]]', err_path, err); }
1275
+ on_error(err, evt) {
1276
+ console.warn('[[u8-mqtt error: %s]]', evt, err); }
1260
1277
 
1261
1278
  // Handshaking Packets
1262
1279
 
1263
1280
  async connect(pkt={}) {
1264
- let cid = pkt.client_id || ['u8-mqtt--', ''];
1265
- if (Array.isArray(cid)) {
1281
+ let cid = pkt.client_id || this.client_id;
1282
+ if ('string' !== typeof cid) {
1283
+ // see init_client_id implementation in core.jsy
1266
1284
  pkt.client_id = cid = this.init_client_id(cid);}
1267
1285
  this.client_id = cid;
1268
1286
 
@@ -1288,12 +1306,13 @@ class MQTTBase {
1288
1306
  return this._send('auth', pkt, 'auth')}
1289
1307
 
1290
1308
  ping() {return this._send('pingreq', null, 'pingresp')}
1291
-
1309
+ puback({pkt_id}) {return this._send('puback', {pkt_id})}
1292
1310
 
1293
1311
  // alias: sub
1294
1312
  subscribe(pkt, ex, topic_prefix) {
1295
1313
  pkt = _as_topics(pkt, ex, topic_prefix);
1296
- return this._send('subscribe', pkt, pkt)}
1314
+ let suback = this._send('subscribe', pkt, pkt);
1315
+ return this.on_sub?.(suback, pkt) ?? suback}
1297
1316
 
1298
1317
  // alias: unsub
1299
1318
  unsubscribe(pkt, ex, topic_prefix) {
@@ -1301,48 +1320,52 @@ class MQTTBase {
1301
1320
  return this._send('unsubscribe', pkt, pkt)}
1302
1321
 
1303
1322
 
1304
- // alias: pub
1305
- publish(pkt, pub_opt) {return _pub(this, pkt, pub_opt)}
1306
- post(topic, payload, pub_opt) {return _pub.m(this, topic, payload, pub_opt)}
1307
- send(topic, payload, pub_opt) {return _pub.mq(this, topic, payload, pub_opt)}
1308
- store(topic, payload, pub_opt) {return _pub.mqr(this, topic, payload, pub_opt)}
1309
-
1310
- json_post(topic, msg, pub_opt) {return _pub.o(this, topic, msg, pub_opt)}
1311
- json_send(topic, msg, pub_opt) {return _pub.oq(this, topic, msg, pub_opt)}
1312
- json_store(topic, msg, pub_opt) {return _pub.oqr(this, topic, msg, pub_opt)}
1313
-
1314
- obj_post(topic, msg, pub_opt) {return _pub.o(this, topic, msg, pub_opt)}
1315
- obj_send(topic, msg, pub_opt) {return _pub.oq(this, topic, msg, pub_opt)}
1316
- obj_store(topic, msg, pub_opt) {return _pub.oqr(this, topic, msg, pub_opt)}
1317
-
1318
-
1319
-
1320
- // Utility Methods
1321
-
1322
- init_client_id(parts) {
1323
- let cid = this.client_id;
1324
-
1325
- if (undefined === cid) {
1326
- this.client_id = cid = (
1327
-
1328
- this.sess_client_id(parts)
1329
-
1330
-
1331
- );}
1332
-
1333
- return cid}
1334
-
1335
- new_client_id(parts) {
1336
- return [parts[0], Math.random().toString(36).slice(2), parts[1]].join('')}
1337
-
1338
-
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}
1323
+ post(topic, payload, pub_opt) {// qos:0
1324
+ return this.pub({topic, payload, qos:0}, pub_opt)}
1325
+ send(topic, payload, pub_opt) {// qos:1
1326
+ return this.pub({topic, payload, qos:1}, pub_opt)}
1327
+ store(topic, payload, pub_opt) {// qos:1, retain: 1
1328
+ return this.pub({topic, payload, qos:1, retain: 1}, pub_opt)}
1329
+
1330
+ // alias: json_post
1331
+ obj_post(topic, msg, pub_opt) {// qos:0
1332
+ return this.pub({topic, msg, arg: 'msg', qos:0}, pub_opt)}
1333
+ // alias: json_send
1334
+ obj_send(topic, msg, pub_opt) {// qos:1
1335
+ return this.pub({topic, msg, arg: 'msg', qos:1}, pub_opt)}
1336
+ // alias: json_store
1337
+ obj_store(topic, msg, pub_opt) {// qos:1, retain: 1
1338
+ return this.pub({topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)}
1339
+
1340
+ // alias: publish -- because 'pub' is shorter for semantic aliases above
1341
+ async pub(pkt, pub_opt) {
1342
+ if (undefined === pkt.payload) {
1343
+ if ('function' === typeof pub_opt) {
1344
+ pub_opt = {fn_encode: pub_opt};}
1345
+
1346
+ let {msg} = pkt;
1347
+ switch (typeof msg) {
1348
+ case 'function':
1349
+ pub_opt = {...pub_opt, fn_encode: msg};
1350
+ // flow into 'undefined' case
1351
+ case 'undefined':
1352
+ // return a single-value closure to publish packets
1353
+ return v => this.pub({...pkt, [pkt.arg || 'payload']: v}, pub_opt)}
1354
+
1355
+ // Encode payload from msg; fn_encode allows alternative to JSON.stringify
1356
+ let {fn_encode} = pub_opt || {};
1357
+ pkt.payload = fn_encode
1358
+ ? await fn_encode(msg)
1359
+ : JSON.stringify(msg);}
1360
+
1361
+ if (pub_opt) {
1362
+ if (pub_opt.props) {
1363
+ pkt.props = pub_opt.props;}
1364
+ if (pub_opt.xform) {
1365
+ pkt = pub_opt.xform(pkt) || pkt;} }
1366
+
1367
+ return this._send('publish', pkt,
1368
+ pkt.qos ? pkt : void 0 ) }// key
1346
1369
 
1347
1370
 
1348
1371
  // Internal API
@@ -1351,52 +1374,24 @@ class MQTTBase {
1351
1374
 
1352
1375
  _init_dispatch(opt) {
1353
1376
  this.constructor?._once_();
1354
- let router = this.router =
1355
- this._init_router?.(opt, this);
1356
-
1357
- let tgt ={
1358
- __proto__: opt.on_mqtt_type || {}
1359
- , router};
1360
-
1361
- tgt.mqtt_publish ||= router?.invoke;
1362
- return _mqtt_dispatch(this, tgt)}
1377
+ let target ={__proto__: opt.on_mqtt_type};
1378
+ target.mqtt_publish ||=
1379
+ this._init_router?.(opt, this, target);
1380
+ return _mqtt_dispatch(this, target)}
1363
1381
 
1364
1382
  static _aliases() {
1365
- return ' pub:publish sub:subscribe unsub:unsubscribe '}
1383
+ return ' publish:pub sub:subscribe unsub:unsubscribe json_post:obj_post json_send:obj_send json_store:obj_store'}
1366
1384
 
1367
1385
  static _once_(self=this) {
1368
1386
  self._once_ = _=>0;
1369
- self.MQTTError = MQTTError;
1370
1387
  let p = self.prototype;
1388
+ p.MQTTError = MQTTError;
1371
1389
  for (let alias of self._aliases().split(/\s+/)) {
1372
1390
  alias = alias.split(':');
1373
1391
  let fn = alias[1] && p[alias[1]];
1374
1392
  if (fn) {p[alias[0]] = fn;} } } }
1375
1393
 
1376
1394
 
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
- */
1392
-
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
1395
  function _as_topics(pkt, ex, topic_prefix) {
1401
1396
  if (ex?.trim) {// string
1402
1397
  topic_prefix = ex;
@@ -1413,55 +1408,11 @@ function _as_topics(pkt, ex, topic_prefix) {
1413
1408
  if (topic_prefix) {
1414
1409
  // particularly useful with shared queues, e.g.
1415
1410
  // topic_prefix = '$share/some-queue-name/'
1416
- pkt.topics = _prefix_topics(topic_prefix, pkt.topics);}
1417
- return pkt}
1418
-
1411
+ let _prefix_topics = v =>
1412
+ v.trim ? topic_prefix+v : v.map(_prefix_topics);
1419
1413
 
1420
- async function _pub(self, pkt, pub_opt) {
1421
- if (undefined === pkt.payload) {
1422
- if ('function' === typeof pub_opt) {
1423
- pub_opt = {fn_encode: pub_opt};}
1424
-
1425
- let {msg} = pkt;
1426
- switch (typeof msg) {
1427
- case 'function':
1428
- pub_opt = {...pub_opt, fn_encode: msg};
1429
- // flow into 'undefined' case
1430
- case 'undefined':
1431
- // return a single-value closure to publish packets
1432
- return v => _pub(self, {...pkt, [pkt.arg || 'payload']: v}, pub_opt)
1433
-
1434
- default:
1435
- // Encode payload from msg; fn_encode allows alternative to JSON.stringify
1436
- let {fn_encode} = pub_opt || {};
1437
- pkt.payload = fn_encode
1438
- ? await fn_encode(msg)
1439
- : JSON.stringify(msg);} }
1440
-
1441
- if (pub_opt) {
1442
- if (pub_opt.props) {
1443
- pkt.props = pub_opt.props;}
1444
- if (pub_opt.xform) {
1445
- pkt = pub_opt.xform(pkt) || pkt;} }
1446
-
1447
- return self._send('publish', pkt,
1448
- pkt.qos ? pkt : void 0 ) }// key
1449
-
1450
- {
1451
- Object.assign(_pub,{
1452
- m: (self, topic, payload, pub_opt) =>
1453
- _pub(self, {topic, payload, qos:0}, pub_opt)
1454
- , mq: (self, topic, payload, pub_opt) =>
1455
- _pub(self, {topic, payload, qos:1}, pub_opt)
1456
- , mqr: (self, topic, payload, pub_opt) =>
1457
- _pub(self, {topic, payload, qos:1, retain: 1}, pub_opt)
1458
-
1459
- , o: (self, topic, msg, pub_opt) =>
1460
- _pub(self, {topic, msg, arg: 'msg', qos:0}, pub_opt)
1461
- , oq: (self, topic, msg, pub_opt) =>
1462
- _pub(self, {topic, msg, arg: 'msg', qos:1}, pub_opt)
1463
- , oqr: (self, topic, msg, pub_opt) =>
1464
- _pub(self, {topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)} ); }
1414
+ pkt.topics = pkt.topics.map(_prefix_topics);}
1415
+ return pkt}
1465
1416
 
1466
1417
  const pkt_api = {
1467
1418
  utf8(u8) { return new TextDecoder('utf-8').decode(u8 || this.payload ) },
@@ -1470,20 +1421,27 @@ const pkt_api = {
1470
1421
  };
1471
1422
 
1472
1423
  class MQTTCore extends MQTTBase {
1473
- constructor(opt={}) {
1474
- super(opt);
1475
- this.with(opt);}
1476
-
1477
1424
  static mqtt_ctx(mqtt_level, mqtt_opts, pkt_ctx=pkt_api) {
1478
1425
  let self = class extends this {};
1479
1426
  self.prototype.mqtt_ctx =
1480
1427
  mqtt_pkt_ctx(mqtt_level, mqtt_opts, pkt_ctx);
1481
1428
  return self}
1482
1429
 
1483
- with(fns_ns) {
1484
- for (let [k,v] of Object.entries(fns_ns)) {
1485
- if ('function' === typeof v) {this[k] = v;} }
1486
- return this}
1430
+
1431
+ // automatic Client Id for connect()
1432
+ init_client_id(parts=['u8-mqtt--','']) {
1433
+ let sess_stg=this.sess_stg;
1434
+ let key, cid = sess_stg?.getItem(key=parts.join(' '));
1435
+ if (! cid) {
1436
+ cid = parts.join(Math.random().toString(36).slice(2));
1437
+ sess_stg?.setItem(key, cid);}
1438
+ return cid}
1439
+
1440
+ get sess_stg() {return globalThis.sessionStorage}
1441
+
1442
+
1443
+ //on_error(err, evt) ::
1444
+ // console.warn @ '[[u8-mqtt error: %s]]', evt, err
1487
1445
 
1488
1446
  //log_conn(evt, arg, err_arg) ::
1489
1447
  // console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
@@ -1559,7 +1517,6 @@ class MQTTCore extends MQTTBase {
1559
1517
 
1560
1518
 
1561
1519
 
1562
-
1563
1520
 
1564
1521
 
1565
1522
 
@@ -1622,7 +1579,7 @@ class MQTTCore extends MQTTBase {
1622
1579
 
1623
1580
  return this} }
1624
1581
 
1625
- const version = '0.4.0';
1582
+ const version = '0.5.0';
1626
1583
 
1627
1584
  const MQTTClient_v4 = /* #__PURE__ */
1628
1585
  with_topic_path_router(