u8-mqtt 0.5.3 → 0.6.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.
- package/README.md +1 -1
- package/cjs/basic-v4.cjs +283 -277
- package/cjs/basic-v4.cjs.map +1 -1
- package/cjs/basic-v5.cjs +297 -281
- package/cjs/basic-v5.cjs.map +1 -1
- package/cjs/full-v4.cjs +295 -289
- package/cjs/full-v4.cjs.map +1 -1
- package/cjs/full-v5.cjs +309 -293
- package/cjs/full-v5.cjs.map +1 -1
- package/cjs/index.cjs +310 -295
- package/cjs/index.cjs.map +1 -1
- package/cjs/v4.cjs +295 -289
- package/cjs/v4.cjs.map +1 -1
- package/cjs/v5.cjs +309 -293
- package/cjs/v5.cjs.map +1 -1
- package/code/_cmdid_dispatch.jsy +45 -69
- package/code/_conn.jsy +96 -72
- package/code/_dispatch.jsy +36 -28
- package/code/_utils.jsy +17 -0
- package/code/base.jsy +33 -61
- package/code/core.jsy +73 -51
- package/code/router_path.jsy +2 -1
- package/esm/basic-v4.js +283 -277
- package/esm/basic-v4.js.map +1 -1
- package/esm/basic-v5.js +297 -281
- package/esm/basic-v5.js.map +1 -1
- package/esm/deno/basic-v4.js +287 -281
- package/esm/deno/basic-v4.js.map +1 -1
- package/esm/deno/basic-v5.js +301 -285
- package/esm/deno/basic-v5.js.map +1 -1
- package/esm/deno/full-v4.js +299 -293
- package/esm/deno/full-v4.js.map +1 -1
- package/esm/deno/full-v5.js +313 -297
- package/esm/deno/full-v5.js.map +1 -1
- package/esm/deno/index.js +314 -298
- package/esm/deno/index.js.map +1 -1
- package/esm/deno/v4.js +299 -293
- package/esm/deno/v4.js.map +1 -1
- package/esm/deno/v5.js +313 -297
- package/esm/deno/v5.js.map +1 -1
- package/esm/full-v4.js +295 -289
- package/esm/full-v4.js.map +1 -1
- package/esm/full-v5.js +309 -293
- package/esm/full-v5.js.map +1 -1
- package/esm/index.js +310 -294
- package/esm/index.js.map +1 -1
- package/esm/node/basic-v4.js +283 -277
- package/esm/node/basic-v4.js.map +1 -1
- package/esm/node/basic-v4.mjs +283 -277
- package/esm/node/basic-v4.mjs.map +1 -1
- package/esm/node/basic-v5.js +297 -281
- package/esm/node/basic-v5.js.map +1 -1
- package/esm/node/basic-v5.mjs +297 -281
- package/esm/node/basic-v5.mjs.map +1 -1
- package/esm/node/full-v4.js +295 -289
- package/esm/node/full-v4.js.map +1 -1
- package/esm/node/full-v4.mjs +295 -289
- package/esm/node/full-v4.mjs.map +1 -1
- package/esm/node/full-v5.js +309 -293
- package/esm/node/full-v5.js.map +1 -1
- package/esm/node/full-v5.mjs +309 -293
- package/esm/node/full-v5.mjs.map +1 -1
- package/esm/node/index.js +310 -294
- package/esm/node/index.js.map +1 -1
- package/esm/node/index.mjs +310 -294
- package/esm/node/index.mjs.map +1 -1
- package/esm/node/v4.js +295 -289
- package/esm/node/v4.js.map +1 -1
- package/esm/node/v4.mjs +295 -289
- package/esm/node/v4.mjs.map +1 -1
- package/esm/node/v5.js +309 -293
- package/esm/node/v5.js.map +1 -1
- package/esm/node/v5.mjs +309 -293
- package/esm/node/v5.mjs.map +1 -1
- package/esm/v4.js +295 -289
- package/esm/v4.js.map +1 -1
- package/esm/v5.js +309 -293
- package/esm/v5.js.map +1 -1
- package/esm/web/basic-v4.js +283 -277
- package/esm/web/basic-v4.js.map +1 -1
- package/esm/web/basic-v4.min.js +1 -1
- package/esm/web/basic-v4.min.js.br +0 -0
- package/esm/web/basic-v4.min.js.gz +0 -0
- package/esm/web/basic-v5.js +297 -281
- package/esm/web/basic-v5.js.map +1 -1
- package/esm/web/basic-v5.min.js +1 -1
- package/esm/web/basic-v5.min.js.br +0 -0
- package/esm/web/basic-v5.min.js.gz +0 -0
- package/esm/web/full-v4.js +295 -289
- package/esm/web/full-v4.js.map +1 -1
- package/esm/web/full-v4.min.js +1 -1
- package/esm/web/full-v4.min.js.br +0 -0
- package/esm/web/full-v4.min.js.gz +0 -0
- package/esm/web/full-v5.js +309 -293
- package/esm/web/full-v5.js.map +1 -1
- package/esm/web/full-v5.min.js +1 -1
- package/esm/web/full-v5.min.js.br +0 -0
- package/esm/web/full-v5.min.js.gz +0 -0
- package/esm/web/index.js +310 -294
- package/esm/web/index.js.map +1 -1
- package/esm/web/index.min.js +1 -1
- package/esm/web/index.min.js.br +0 -0
- package/esm/web/index.min.js.gz +0 -0
- package/esm/web/v4.js +295 -289
- package/esm/web/v4.js.map +1 -1
- package/esm/web/v4.min.js +1 -1
- package/esm/web/v4.min.js.br +0 -0
- package/esm/web/v4.min.js.gz +0 -0
- package/esm/web/v5.js +309 -293
- package/esm/web/v5.js.map +1 -1
- package/esm/web/v5.min.js +1 -1
- package/esm/web/v5.min.js.br +0 -0
- package/esm/web/v5.min.js.gz +0 -0
- package/package.json +7 -8
package/esm/index.js
CHANGED
|
@@ -156,10 +156,18 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
|
|
|
156
156
|
|
|
157
157
|
let res={}, fork = this.of(buf.subarray(vi, step.k|0));
|
|
158
158
|
while (fork.has_more()) {
|
|
159
|
-
let pt = mqtt_props.get(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
let v, pk = fork.u8(), pt = mqtt_props.get( pk );
|
|
160
|
+
|
|
161
|
+
if (!pt) {
|
|
162
|
+
res.error = `Unknown mqtt_prop enum ${pk}`;
|
|
163
|
+
return res
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
v = fork[pt.type]();
|
|
167
|
+
if (pt.op) // accumulate operation
|
|
168
|
+
v = fork[pt.op](res[pt.name], v);
|
|
169
|
+
|
|
170
|
+
res[pt.name] = v;
|
|
163
171
|
}
|
|
164
172
|
return res
|
|
165
173
|
}
|
|
@@ -293,6 +301,8 @@ class mqtt_writer_v5 extends mqtt_writer_v4 {
|
|
|
293
301
|
let fork = this.of();
|
|
294
302
|
for (let [name, value] of props) {
|
|
295
303
|
let pt = mqtt_props.get(name);
|
|
304
|
+
if (!pt)
|
|
305
|
+
throw new Error(`Unknown mqtt_prop "${name}"`)
|
|
296
306
|
fork[pt.op || 'one'](value, pt);
|
|
297
307
|
}
|
|
298
308
|
this.push(fork.pack());
|
|
@@ -796,6 +806,23 @@ function parse(str, loose) {
|
|
|
796
806
|
};
|
|
797
807
|
}
|
|
798
808
|
|
|
809
|
+
const _isfn = v => typeof v === 'function';
|
|
810
|
+
const _isstr = v => typeof v === 'string';
|
|
811
|
+
|
|
812
|
+
function _interval(fn_callback) {
|
|
813
|
+
let tid;
|
|
814
|
+
return (( td ) => {
|
|
815
|
+
tid = clearInterval(tid);
|
|
816
|
+
if (td) {
|
|
817
|
+
tid = setInterval(fn_callback, 1000 * td);
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
// ensure the interval allows the NodeJS event loop to exit
|
|
823
|
+
tid.unref?.();
|
|
824
|
+
return true} }) }
|
|
825
|
+
|
|
799
826
|
/*
|
|
800
827
|
class AbstractTopicRouter ::
|
|
801
828
|
async invoke(pkt, ctx) ::
|
|
@@ -886,7 +913,7 @@ function mqtt_topic_path_router() {
|
|
|
886
913
|
let fn = args.pop();
|
|
887
914
|
let priority = args.pop();
|
|
888
915
|
|
|
889
|
-
if (
|
|
916
|
+
if (! _isfn(fn)) {
|
|
890
917
|
if (fn) {throw new TypeError()}
|
|
891
918
|
fn = _ignore;}
|
|
892
919
|
|
|
@@ -1051,238 +1078,108 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
|
|
|
1051
1078
|
}
|
|
1052
1079
|
}
|
|
1053
1080
|
|
|
1054
|
-
function
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
,
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
_q_ready = ao_defer_v();
|
|
1100
|
-
client.conn_emit('on_ready');}
|
|
1101
|
-
|
|
1102
|
-
return res}
|
|
1081
|
+
async function _mqtt_cmd_evt(target, answer, pkt, ctx) {
|
|
1082
|
+
/* target : on_mqtt_type = {
|
|
1083
|
+
mqtt_pkt(pkt, ctx) {}, // generic
|
|
1084
|
+
|
|
1085
|
+
mqtt_auth(pkt, ctx) {},
|
|
1086
|
+
mqtt_connect(pkt, ctx) {},
|
|
1087
|
+
mqtt_connack(pkt, ctx) {},
|
|
1088
|
+
mqtt_disconnect(pkt, ctx) {},
|
|
1089
|
+
|
|
1090
|
+
mqtt_publish(pkt, ctx) {},
|
|
1091
|
+
mqtt_subscribe(pkt, ctx) {},
|
|
1092
|
+
mqtt_unsubscribe(pkt, ctx) {},
|
|
1093
|
+
|
|
1094
|
+
mqtt_pingreq(pkt, ctx) {},
|
|
1095
|
+
mqtt_pingresp(pkt, ctx) {},
|
|
1096
|
+
} */
|
|
1097
|
+
|
|
1098
|
+
let pkt_fn = target[`mqtt_${pkt.type}`] || target.mqtt_pkt;
|
|
1099
|
+
await pkt_fn?.call(target, pkt, ctx);}
|
|
1100
|
+
|
|
1101
|
+
function _mqtt_cmd_type(target, answer, pkt, ctx) {
|
|
1102
|
+
answer(pkt.type, pkt);
|
|
1103
|
+
_mqtt_cmd_evt(target, answer, pkt, ctx);}
|
|
1104
|
+
|
|
1105
|
+
function _mqtt_cmd_id(target, answer, pkt) {
|
|
1106
|
+
answer(pkt.pkt_id, pkt);}
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
const _mqtt_cmdids =[
|
|
1110
|
+
_ => {} // 0x0 reserved
|
|
1111
|
+
, _mqtt_cmd_evt // 0x1 connect
|
|
1112
|
+
, _mqtt_cmd_type // 0x2 connack
|
|
1113
|
+
, _mqtt_cmd_evt // 0x3 publish
|
|
1114
|
+
, _mqtt_cmd_id // 0x4 puback
|
|
1115
|
+
, _mqtt_cmd_id // 0x5 pubrec
|
|
1116
|
+
, _mqtt_cmd_id // 0x6 pubrel
|
|
1117
|
+
, _mqtt_cmd_id // 0x7 pubcomp
|
|
1118
|
+
, _mqtt_cmd_evt // 0x8 subscribe
|
|
1119
|
+
, _mqtt_cmd_id // 0x9 suback
|
|
1120
|
+
, _mqtt_cmd_evt // 0xa unsubscribe
|
|
1121
|
+
, _mqtt_cmd_id // 0xb unsuback
|
|
1122
|
+
, _mqtt_cmd_type // 0xc pingreq
|
|
1123
|
+
, _mqtt_cmd_type // 0xd pingresp
|
|
1124
|
+
, _mqtt_cmd_evt // 0xe disconnect
|
|
1125
|
+
, _mqtt_cmd_type ];// 0xf auth
|
|
1103
1126
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
mqtt_ctx = mqtt_ctx.mqtt_stream();
|
|
1110
|
-
let sess_ctx = {mqtt: client};
|
|
1111
|
-
let on_mqtt_chunk = u8_buf =>
|
|
1112
|
-
on_mqtt(mqtt_ctx.decode(u8_buf), sess_ctx);
|
|
1113
|
-
|
|
1114
|
-
_send_mqtt_pkt = async (type, pkt, key) => {
|
|
1115
|
-
let res = undefined !== key
|
|
1116
|
-
? pkt_future(key) : true;
|
|
1117
|
-
|
|
1118
|
-
await send_u8_pkt(
|
|
1119
|
-
mqtt_ctx.encode_pkt(type, pkt));
|
|
1120
|
-
|
|
1121
|
-
return res};
|
|
1122
|
-
|
|
1123
|
-
_q_init[1](_send_mqtt_pkt); // resolve _q_init with _send_mqtt_pkt closure
|
|
1124
|
-
|
|
1125
|
-
// call client.on_live in next promise microtask
|
|
1126
|
-
client.conn_emit('on_live', _has_connected);
|
|
1127
|
-
return on_mqtt_chunk} } }
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
function _ping_interval(send_ping) {
|
|
1131
|
-
let tid;
|
|
1132
|
-
return (( td ) => {
|
|
1133
|
-
tid = clearInterval(tid);
|
|
1134
|
-
if (td) {
|
|
1135
|
-
tid = setInterval(send_ping, 1000 * td);
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
// ensure the interval allows the NodeJS event loop to exit
|
|
1141
|
-
tid.unref?.();
|
|
1142
|
-
return true} }) }
|
|
1127
|
+
function _mqtt_dispatch(opt, target) {
|
|
1128
|
+
let hashbelt=[], rotate_ts=0;
|
|
1129
|
+
// default rotate at 1s across 5 buckets
|
|
1130
|
+
let { td: rotate_td=1000, n: rotate_n=5 } = opt?.rotate || {};
|
|
1143
1131
|
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1132
|
+
// Promise / future scaffolding
|
|
1133
|
+
let _pkt_id=100, _ftr_key; // use _ftr_key to reuse _by_key closure
|
|
1134
|
+
let _ftr_by_key = fn_answer => hashbelt[0].set(_ftr_key, fn_answer);
|
|
1147
1135
|
|
|
1148
|
-
|
|
1149
|
-
|
|
1136
|
+
on_mqtt([]); // init hashbelt and rotate_ts
|
|
1137
|
+
return [on_mqtt, pkt_future]
|
|
1150
1138
|
|
|
1151
|
-
let _tmp_; // use _tmp_ to reuse _by_key closure
|
|
1152
|
-
let _by_key = answer_monad =>
|
|
1153
|
-
hashbelt[0].set(_tmp_, answer_monad);
|
|
1154
1139
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
_tmp_ = pkt_or_key.pkt_id = _pkt_id;}
|
|
1140
|
+
function pkt_future(pkt_or_key) {
|
|
1141
|
+
if (! _isstr(pkt_or_key)) {
|
|
1142
|
+
_pkt_id = (_pkt_id + 1) & 0xffff; // 16-bit unsigned short
|
|
1143
|
+
_ftr_key = pkt_or_key.pkt_id = _pkt_id;}
|
|
1144
|
+
else _ftr_key = pkt_or_key;
|
|
1161
1145
|
|
|
1162
|
-
|
|
1146
|
+
return new Promise(_ftr_by_key)}
|
|
1163
1147
|
|
|
1164
|
-
|
|
1165
|
-
for (let map of
|
|
1166
|
-
let
|
|
1167
|
-
if (
|
|
1148
|
+
function answer(key, pkt) {
|
|
1149
|
+
for (let map of hashbelt) {
|
|
1150
|
+
let fn_answer = map.get(key);
|
|
1151
|
+
if (fn_answer) {
|
|
1168
1152
|
map.delete(key);
|
|
1169
1153
|
|
|
1170
|
-
|
|
1154
|
+
fn_answer([pkt, /*err*/]); // option/maybe monad
|
|
1171
1155
|
return true} }
|
|
1172
1156
|
return false}
|
|
1173
1157
|
|
|
1174
|
-
, rotate_belt(n) {
|
|
1175
|
-
let {hashbelt} = this;
|
|
1176
|
-
hashbelt.unshift(new Map());
|
|
1177
|
-
for (let old of hashbelt.splice(n || 5)) {
|
|
1178
|
-
for (let answer_monad of old.values()) {
|
|
1179
|
-
answer_monad([/*pkt*/, 'expired']); } } }// option/maybe monad
|
|
1180
|
-
|
|
1181
|
-
, cmdids: ((() => {
|
|
1182
|
-
return [
|
|
1183
|
-
(() =>{} )// 0x0 reserved
|
|
1184
|
-
, by_evt // 0x1 connect
|
|
1185
|
-
, by_type // 0x2 connack
|
|
1186
|
-
, by_evt // 0x3 publish
|
|
1187
|
-
, by_id // 0x4 puback
|
|
1188
|
-
, by_id // 0x5 pubrec
|
|
1189
|
-
, by_id // 0x6 pubrel
|
|
1190
|
-
, by_id // 0x7 pubcomp
|
|
1191
|
-
, by_evt // 0x8 subscribe
|
|
1192
|
-
, by_id // 0x9 suback
|
|
1193
|
-
, by_evt // 0xa unsubscribe
|
|
1194
|
-
, by_id // 0xb unsuback
|
|
1195
|
-
, by_type // 0xc pingreq
|
|
1196
|
-
, by_type // 0xd pingresp
|
|
1197
|
-
, by_evt // 0xe disconnect
|
|
1198
|
-
, by_type ]// 0xf auth
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
function by_id(disp, pkt) {
|
|
1202
|
-
disp.answer(pkt.pkt_id, pkt); }
|
|
1203
|
-
|
|
1204
|
-
function by_type(disp, pkt, ctx) {
|
|
1205
|
-
disp.answer(pkt.type, pkt);
|
|
1206
|
-
by_evt(disp, pkt, ctx);}
|
|
1207
|
-
|
|
1208
|
-
async function by_evt({target}, pkt, ctx) {
|
|
1209
|
-
let fn = target[`mqtt_${pkt.type}`]
|
|
1210
|
-
|| target.mqtt_pkt;
|
|
1211
|
-
|
|
1212
|
-
await fn?.call(target, pkt, ctx);} })()) };
|
|
1213
|
-
|
|
1214
|
-
/*
|
|
1215
|
-
on_mqtt_type = {
|
|
1216
|
-
mqtt_auth(pkt, ctx) ::
|
|
1217
|
-
mqtt_connect(pkt, ctx) ::
|
|
1218
|
-
mqtt_connack(pkt, ctx) ::
|
|
1219
|
-
mqtt_disconnect(pkt, ctx) ::
|
|
1220
|
-
|
|
1221
|
-
mqtt_publish(pkt, ctx)
|
|
1222
|
-
mqtt_subscribe(pkt, ctx) ::
|
|
1223
|
-
mqtt_unsubscribe(pkt, ctx) ::
|
|
1224
|
-
|
|
1225
|
-
mqtt_pingreq(pkt, ctx) ::
|
|
1226
|
-
mqtt_pingresp(pkt, ctx) ::
|
|
1227
|
-
}
|
|
1228
|
-
*/
|
|
1229
|
-
|
|
1230
|
-
function _mqtt_dispatch(opt, target) {
|
|
1231
|
-
let _disp_ = _mqtt_cmdid_dispatch.create(target);
|
|
1232
|
-
let { cmdids } = _disp_;
|
|
1233
|
-
|
|
1234
|
-
// default rotate at 1s across 5 buckets
|
|
1235
|
-
let { td: rotate_td=1000, n: rotate_n=5 } =
|
|
1236
|
-
opt && opt.rotate || {};
|
|
1237
|
-
|
|
1238
|
-
let rotate_ts = rotate_td + Date.now();
|
|
1239
|
-
|
|
1240
|
-
return [on_mqtt,
|
|
1241
|
-
_disp_.bind_pkt_future()]
|
|
1242
|
-
|
|
1243
1158
|
function on_mqtt(pkt_list, ctx) {
|
|
1244
1159
|
for (let pkt of pkt_list) {
|
|
1245
|
-
|
|
1160
|
+
_mqtt_cmdids[pkt.id](target, answer, pkt, ctx);}
|
|
1246
1161
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1162
|
+
// rotate after rotate_ts
|
|
1163
|
+
let now = Date.now();
|
|
1164
|
+
if (now > rotate_ts) {
|
|
1165
|
+
rotate_ts = rotate_td + now;
|
|
1166
|
+
hashbelt.unshift(new Map());
|
|
1167
|
+
while (hashbelt.length > rotate_n) {
|
|
1168
|
+
for (let fn_answer of hashbelt.pop().values()) {
|
|
1169
|
+
fn_answer([/*pkt*/, 'expired']); } } } } }// option/maybe monad
|
|
1250
1170
|
|
|
1251
1171
|
class MQTTError extends Error {
|
|
1252
1172
|
constructor(mqtt_pkt, reason=mqtt_pkt.reason) {
|
|
1173
|
+
// use hex-encoded reasons to match MQTT spec documentation
|
|
1253
1174
|
super(`[0x${reason.toString(16)}] ${reason.reason}`);
|
|
1254
1175
|
this.mqtt_pkt = mqtt_pkt;
|
|
1255
1176
|
this.reason = reason;} }
|
|
1256
1177
|
|
|
1257
1178
|
class MQTTBase {
|
|
1258
|
-
constructor(opt={}) {
|
|
1259
|
-
this.with(opt);
|
|
1260
|
-
this._conn_ = _mqtt_conn(this,
|
|
1261
|
-
this._init_dispatch(opt, this)); }
|
|
1262
|
-
|
|
1263
|
-
with(fns_ns) {
|
|
1264
|
-
for (let [k,v] of Object.entries(fns_ns)) {
|
|
1265
|
-
if ('function' === typeof v) {this[k] = v;} }
|
|
1266
|
-
return this}
|
|
1267
|
-
|
|
1268
|
-
async conn_emit(evt, arg, err_arg) {
|
|
1269
|
-
this.log_conn?.(evt, arg, err_arg);
|
|
1270
|
-
try {
|
|
1271
|
-
let fn_evt = this[await evt]; // microtask break using `await evt`
|
|
1272
|
-
if (fn_evt) {
|
|
1273
|
-
await fn_evt.call(this, this, arg, err_arg);}
|
|
1274
|
-
else if (err_arg) {throw err_arg} }
|
|
1275
|
-
catch (err) {
|
|
1276
|
-
this.on_error(err, evt);} }
|
|
1277
|
-
|
|
1278
|
-
on_error(err, evt) {
|
|
1279
|
-
console.warn('[[u8-mqtt error: %s]]', evt, err); }
|
|
1280
|
-
|
|
1281
1179
|
// Handshaking Packets
|
|
1282
|
-
|
|
1283
1180
|
async connect(pkt={}) {
|
|
1284
1181
|
let cid = pkt.client_id;
|
|
1285
|
-
if (
|
|
1182
|
+
if (! _isstr(cid)) {
|
|
1286
1183
|
// see init_client_id implementation in core.jsy
|
|
1287
1184
|
pkt.client_id = cid = this.client_id || this.init_client_id(cid);}
|
|
1288
1185
|
this.client_id = cid;
|
|
@@ -1290,23 +1187,20 @@ class MQTTBase {
|
|
|
1290
1187
|
if (null == pkt.keep_alive) {
|
|
1291
1188
|
pkt.keep_alive = 60;}
|
|
1292
1189
|
|
|
1293
|
-
let
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
throw new this.MQTTError(res[0])}
|
|
1298
|
-
|
|
1299
|
-
// TODO: merge with server's keep_alive frequency
|
|
1300
|
-
this._conn_.ping(pkt.keep_alive);
|
|
1301
|
-
return res}
|
|
1190
|
+
let response = await this._send0('connect', pkt, 'connack');
|
|
1191
|
+
if (0 != response[0].reason) {// compare to 0 to coerce to number
|
|
1192
|
+
throw new this.MQTTError(response[0])}
|
|
1193
|
+
return this.conn.on_conn(pkt, response)}
|
|
1302
1194
|
|
|
1303
1195
|
async disconnect(pkt={}) {
|
|
1304
|
-
let
|
|
1305
|
-
this.
|
|
1306
|
-
return res}
|
|
1196
|
+
let response = await this._send0('disconnect', pkt);
|
|
1197
|
+
return this.conn.on_dis(pkt, response)}
|
|
1307
1198
|
|
|
1308
|
-
auth(pkt={}) {
|
|
1309
|
-
|
|
1199
|
+
async auth(pkt={}) {
|
|
1200
|
+
let response = await this._send0('auth', pkt, 'auth');
|
|
1201
|
+
if (response[0].reason) {
|
|
1202
|
+
throw new this.MQTTError(response[0])}
|
|
1203
|
+
return this.conn.on_auth(pkt, response)}
|
|
1310
1204
|
|
|
1311
1205
|
ping() {return this._send('pingreq', null, 'pingresp')}
|
|
1312
1206
|
puback({pkt_id}) {return this._send('puback', {pkt_id})}
|
|
@@ -1343,20 +1237,18 @@ class MQTTBase {
|
|
|
1343
1237
|
// alias: publish -- because 'pub' is shorter for semantic aliases above
|
|
1344
1238
|
async pub(pkt, pub_opt) {
|
|
1345
1239
|
if (undefined === pkt.payload) {
|
|
1346
|
-
if (
|
|
1240
|
+
if (_isfn(pub_opt)) {
|
|
1241
|
+
// pub_opt as a function is fn_encode value
|
|
1347
1242
|
pub_opt = {fn_encode: pub_opt};}
|
|
1348
1243
|
|
|
1349
|
-
let
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
// return a single-value closure to publish packets
|
|
1356
|
-
return v => this.pub({...pkt, [pkt.arg || 'payload']: v}, pub_opt)}
|
|
1244
|
+
let msg = pkt.msg, fn_encode = pub_opt?.fn_encode;
|
|
1245
|
+
if (null == msg || _isfn(msg)) {
|
|
1246
|
+
// when msg is a function, return closure using fn_encode
|
|
1247
|
+
if (msg) {pub_opt = {...pub_opt, fn_encode: msg};}
|
|
1248
|
+
// return a single-value closure to publish packets
|
|
1249
|
+
return v => this.pub({...pkt, [pkt.arg || 'payload']: v}, pub_opt)}
|
|
1357
1250
|
|
|
1358
1251
|
// Encode payload from msg; fn_encode allows alternative to JSON.stringify
|
|
1359
|
-
let {fn_encode} = pub_opt || {};
|
|
1360
1252
|
pkt.payload = fn_encode
|
|
1361
1253
|
? await fn_encode(msg)
|
|
1362
1254
|
: JSON.stringify(msg);}
|
|
@@ -1368,31 +1260,31 @@ class MQTTBase {
|
|
|
1368
1260
|
pkt = pub_opt.xform(pkt) || pkt;} }
|
|
1369
1261
|
|
|
1370
1262
|
return this._send('publish', pkt,
|
|
1371
|
-
pkt.qos ? pkt :
|
|
1263
|
+
pkt.qos ? pkt : null ) }// key
|
|
1372
1264
|
|
|
1373
1265
|
|
|
1374
1266
|
// Internal API
|
|
1375
1267
|
|
|
1376
|
-
/* async
|
|
1268
|
+
/* async _send0(type, pkt) -- provided by conn and transport */
|
|
1269
|
+
/* async _send(type, pkt) -- provided by conn and transport */
|
|
1377
1270
|
|
|
1378
1271
|
_init_dispatch(opt) {
|
|
1379
1272
|
this.constructor?._once_();
|
|
1380
1273
|
let target ={__proto__: opt.on_mqtt_type};
|
|
1381
1274
|
target.mqtt_publish ||=
|
|
1382
1275
|
this._init_router?.(opt, this, target);
|
|
1383
|
-
return _mqtt_dispatch(
|
|
1276
|
+
return _mqtt_dispatch(opt, target)}
|
|
1384
1277
|
|
|
1385
1278
|
static _aliases() {
|
|
1386
1279
|
return ' publish:pub sub:subscribe unsub:unsubscribe json_post:obj_post json_send:obj_send json_store:obj_store'}
|
|
1387
1280
|
|
|
1388
|
-
static _once_(
|
|
1389
|
-
|
|
1390
|
-
|
|
1281
|
+
static _once_(klass=this) {
|
|
1282
|
+
klass._once_ = _=>0;
|
|
1283
|
+
var alias, name, p = klass.prototype;
|
|
1391
1284
|
p.MQTTError = MQTTError;
|
|
1392
|
-
for (
|
|
1393
|
-
alias = alias.split(':');
|
|
1394
|
-
|
|
1395
|
-
if (fn) {p[alias[0]] = fn;} } } }
|
|
1285
|
+
for (alias of klass._aliases().split(/\s+/)) {
|
|
1286
|
+
[alias, name] = alias.split(':');
|
|
1287
|
+
p[alias] = p[name];} } }
|
|
1396
1288
|
|
|
1397
1289
|
|
|
1398
1290
|
function _as_topics(pkt, ex, topic_prefix) {
|
|
@@ -1417,37 +1309,167 @@ function _as_topics(pkt, ex, topic_prefix) {
|
|
|
1417
1309
|
pkt.topics = pkt.topics.map(_prefix_topics);}
|
|
1418
1310
|
return pkt}
|
|
1419
1311
|
|
|
1420
|
-
const
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1312
|
+
const _defer_obj = o =>(
|
|
1313
|
+
o.p = new Promise((a,e) => { o.a=a; o.e=e; })
|
|
1314
|
+
, o);
|
|
1315
|
+
|
|
1316
|
+
function _dfn_reset(client, attr, fn_after) {
|
|
1317
|
+
// a resetable deferred for a function
|
|
1318
|
+
let self = {set}, afn = async (...args) => (await self.p)(...args);
|
|
1319
|
+
return set()
|
|
1320
|
+
|
|
1321
|
+
function set() {
|
|
1322
|
+
if (afn !== client[attr]) {
|
|
1323
|
+
_defer_obj(self).p.then(fn_after, _=>0);
|
|
1324
|
+
client[attr] = afn;}
|
|
1325
|
+
return self} }
|
|
1326
|
+
|
|
1327
|
+
function _mqtt_conn(opt, client, [on_mqtt, pkt_future]) {
|
|
1328
|
+
let _abort;
|
|
1329
|
+
let _dfn_send0 = _dfn_reset(client, '_send0', // client._send0 getter/setter
|
|
1330
|
+
_=> client.conn_emit('on_live', conn.has_connected));
|
|
1331
|
+
let _dfn_ready = _dfn_reset(client, '_send', // client._send getter/setter
|
|
1332
|
+
_=> client.conn_emit('on_ready'));
|
|
1333
|
+
let _keep_alive_ival = _interval (() =>client._send0('pingreq') );// resettable interval for keep_alive ping
|
|
1334
|
+
|
|
1335
|
+
let conn = Object.create({
|
|
1336
|
+
ping: (td=conn.keep_alive) => _keep_alive_ival(td)
|
|
1337
|
+
|
|
1338
|
+
, on_conn(pkt, response) {
|
|
1339
|
+
conn.has_connected = true;
|
|
1340
|
+
conn.keep_alive = opt.keep_alive || response[0].props?.server_keep_alive || pkt.keep_alive;
|
|
1341
|
+
client.conn_emit('on_conn');
|
|
1342
|
+
return opt.use_auth
|
|
1343
|
+
? response // wait on enhanced authentication step
|
|
1344
|
+
: conn.on_auth(null, response) }// otherwise, connect is also auth
|
|
1345
|
+
|
|
1346
|
+
, on_auth(pkt, response) {
|
|
1347
|
+
_dfn_ready.a(_dfn_send0.p);
|
|
1348
|
+
if (0 != opt.keep_alive) {
|
|
1349
|
+
conn.ping();}
|
|
1350
|
+
client.conn_emit('on_auth', !pkt);
|
|
1351
|
+
return response}
|
|
1352
|
+
|
|
1353
|
+
, on_dis(pkt, response) {
|
|
1354
|
+
conn.reset(false);
|
|
1355
|
+
return response}
|
|
1356
|
+
|
|
1357
|
+
, reset(err) {
|
|
1358
|
+
if (err) {
|
|
1359
|
+
_dfn_send0.e(err); }// send error to uses of _send0 (connect, auth)
|
|
1360
|
+
_abort.e(err); // abort in-progress connections
|
|
1361
|
+
|
|
1362
|
+
delete conn.is_set;
|
|
1363
|
+
conn.ready = handshake();
|
|
1364
|
+
client.conn_emit('on_disconnect', false===err, err);}
|
|
1365
|
+
|
|
1366
|
+
, abort() {
|
|
1367
|
+
_dfn_ready.e(err); // abort all messages awaiting ready state
|
|
1368
|
+
return conn.reset(err)}
|
|
1369
|
+
|
|
1370
|
+
, async setup(gate, send_u8_pkt, init_msg_loop) {
|
|
1371
|
+
if (conn.is_set) {
|
|
1372
|
+
throw new Error() }// already in-progress
|
|
1373
|
+
|
|
1374
|
+
conn.is_set = true;
|
|
1375
|
+
await gate;
|
|
1376
|
+
|
|
1377
|
+
// setup send/recv MQTT parsing context
|
|
1378
|
+
let mqtt_ctx = client.mqtt_ctx.mqtt_stream();
|
|
1379
|
+
|
|
1380
|
+
{// setup inbound message loop
|
|
1381
|
+
let sess_ctx = {mqtt: client}; // mutable session context
|
|
1382
|
+
let on_mqtt_chunk = u8 => on_mqtt(mqtt_ctx.decode(u8), sess_ctx);
|
|
1383
|
+
init_msg_loop(on_mqtt_chunk, conn);}
|
|
1384
|
+
|
|
1385
|
+
// setup outbound message path and transport connection
|
|
1386
|
+
send_u8_pkt = await send_u8_pkt;
|
|
1387
|
+
_dfn_send0.a(
|
|
1388
|
+
async (type, pkt, key) => {
|
|
1389
|
+
let res = undefined !== key
|
|
1390
|
+
? pkt_future(key) : true;
|
|
1391
|
+
|
|
1392
|
+
await send_u8_pkt(
|
|
1393
|
+
mqtt_ctx.encode_pkt(type, pkt));
|
|
1394
|
+
return res} ); } });
|
|
1395
|
+
|
|
1396
|
+
conn.ready = handshake();
|
|
1397
|
+
return conn
|
|
1398
|
+
|
|
1399
|
+
async function handshake() {
|
|
1400
|
+
_abort = _defer_obj({});
|
|
1401
|
+
|
|
1402
|
+
_keep_alive_ival(0); // clearInterval on keep alive ping
|
|
1403
|
+
_dfn_send0.set(); // reset client._send0 if necessary
|
|
1404
|
+
_dfn_ready.set(); // reset client._send if necessary
|
|
1405
|
+
|
|
1406
|
+
try {
|
|
1407
|
+
// set client._send0 as passtrhough after transport connection
|
|
1408
|
+
client._send0 = await Promise.race([_dfn_send0.p, _abort.p]);
|
|
1409
|
+
|
|
1410
|
+
// set client._send as passtrhough after ready
|
|
1411
|
+
client._send = await Promise.race([_dfn_ready.p, _abort.p]);
|
|
1412
|
+
return true}
|
|
1413
|
+
catch (err) {
|
|
1414
|
+
return false} } }
|
|
1415
|
+
|
|
1416
|
+
const pkt_api ={
|
|
1417
|
+
utf8(u8) {return new TextDecoder('utf-8').decode(u8 || this.payload )}
|
|
1418
|
+
, json(u8) {return JSON.parse( this.utf8(u8) || null )}
|
|
1419
|
+
, text(u8) {return this.utf8(u8)} };
|
|
1420
|
+
|
|
1421
|
+
const opt_default ={
|
|
1422
|
+
sess_stg: globalThis.sessionStorage};
|
|
1425
1423
|
|
|
1426
1424
|
class MQTTCore extends MQTTBase {
|
|
1425
|
+
constructor(opt) {
|
|
1426
|
+
opt = {...opt_default, ...opt};
|
|
1427
|
+
super();
|
|
1428
|
+
this.with(opt);
|
|
1429
|
+
// settings for MQTTCore
|
|
1430
|
+
this.sess_stg = opt.sess_stg;
|
|
1431
|
+
// setup connection and dispatch
|
|
1432
|
+
this.conn = _mqtt_conn(opt, this,
|
|
1433
|
+
this._init_dispatch(opt)); }
|
|
1434
|
+
|
|
1435
|
+
with(fns_ns) {
|
|
1436
|
+
for (let [k,v] of Object.entries(fns_ns)) {
|
|
1437
|
+
if (_isfn(v)) {this[k] = v;} }
|
|
1438
|
+
return this}
|
|
1439
|
+
|
|
1440
|
+
|
|
1427
1441
|
static mqtt_ctx(mqtt_level, mqtt_opts, pkt_ctx=pkt_api) {
|
|
1428
|
-
let
|
|
1429
|
-
|
|
1442
|
+
let klass = class extends this {};
|
|
1443
|
+
klass.prototype.mqtt_ctx =
|
|
1430
1444
|
mqtt_pkt_ctx(mqtt_level, mqtt_opts, pkt_ctx);
|
|
1431
|
-
return
|
|
1445
|
+
return klass}
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
async conn_emit(evt, arg, err_arg) {
|
|
1449
|
+
this.log_conn?.(evt, arg, err_arg);
|
|
1450
|
+
try {
|
|
1451
|
+
let fn_evt = this[await evt]; // microtask break using `await evt`
|
|
1452
|
+
if (fn_evt) {
|
|
1453
|
+
await fn_evt.call(this, this, arg, err_arg);}
|
|
1454
|
+
else if (err_arg) {throw err_arg} }
|
|
1455
|
+
catch (err) {
|
|
1456
|
+
this.on_error(err, evt);} }
|
|
1457
|
+
|
|
1458
|
+
on_error(err, evt) {
|
|
1459
|
+
console.warn('[[u8-mqtt error: %s]]', evt, err); }
|
|
1460
|
+
log_conn(evt, arg, err_arg) {
|
|
1461
|
+
console.info('[[u8-mqtt conn: %s]]', evt, arg, err_arg); }
|
|
1432
1462
|
|
|
1433
1463
|
|
|
1434
1464
|
// automatic Client Id for connect()
|
|
1435
1465
|
init_client_id(parts=['u8-mqtt--','']) {
|
|
1436
|
-
let sess_stg=this.sess_stg;
|
|
1466
|
+
let sess_stg = this.sess_stg;
|
|
1437
1467
|
let key, cid = sess_stg?.getItem(key=parts.join(' '));
|
|
1438
1468
|
if (! cid) {
|
|
1439
1469
|
cid = parts.join(Math.random().toString(36).slice(2));
|
|
1440
1470
|
sess_stg?.setItem(key, cid);}
|
|
1441
1471
|
return cid}
|
|
1442
1472
|
|
|
1443
|
-
get sess_stg() {return globalThis.sessionStorage}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
//on_error(err, evt) ::
|
|
1447
|
-
// console.warn @ '[[u8-mqtt error: %s]]', evt, err
|
|
1448
|
-
|
|
1449
|
-
//log_conn(evt, arg, err_arg) ::
|
|
1450
|
-
// console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
|
|
1451
1473
|
|
|
1452
1474
|
on_live(client, is_reconnect) {
|
|
1453
1475
|
if (is_reconnect) {
|
|
@@ -1473,19 +1495,16 @@ class MQTTCore extends MQTTBase {
|
|
|
1473
1495
|
return new Promise(done => setTimeout(done, ms)) }
|
|
1474
1496
|
|
|
1475
1497
|
with_async_iter(async_iter, write_u8_pkt) {
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
catch (err) {
|
|
1487
|
-
this._conn_.reset(err);} })());
|
|
1488
|
-
|
|
1498
|
+
this.conn.setup(async_iter,
|
|
1499
|
+
write_u8_pkt,
|
|
1500
|
+
async (on_mqtt_chunk, conn) => {
|
|
1501
|
+
try {
|
|
1502
|
+
async_iter = await async_iter;
|
|
1503
|
+
for await (let chunk of async_iter)
|
|
1504
|
+
on_mqtt_chunk(chunk);
|
|
1505
|
+
conn.reset();}
|
|
1506
|
+
catch (err) {
|
|
1507
|
+
conn.reset(err);} } );
|
|
1489
1508
|
return this}
|
|
1490
1509
|
|
|
1491
1510
|
|
|
@@ -1556,33 +1575,30 @@ class MQTTCore extends MQTTBase {
|
|
|
1556
1575
|
|
|
1557
1576
|
websock.binaryType = 'arraybuffer';
|
|
1558
1577
|
|
|
1559
|
-
let
|
|
1578
|
+
let ws_ready, readyState = websock.readyState;
|
|
1560
1579
|
if (1 !== readyState) {
|
|
1561
1580
|
if (0 !== readyState) {
|
|
1562
|
-
throw new Error('
|
|
1563
|
-
|
|
1564
|
-
ready = new Promise(fn => websock.onopen = fn); }
|
|
1581
|
+
throw new Error('WS readyState') }
|
|
1565
1582
|
|
|
1583
|
+
ws_ready = new Promise(ready => websock.onopen = ready); }
|
|
1566
1584
|
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
, websock.send(u8_pkt)) );
|
|
1585
|
+
this.conn.setup(ws_ready,
|
|
1586
|
+
u8_pkt => websock.send(u8_pkt),
|
|
1587
|
+
(on_mqtt_chunk, conn) => {
|
|
1588
|
+
websock.onmessage = evt =>(
|
|
1589
|
+
on_mqtt_chunk(new Uint8Array(evt.data)) );
|
|
1573
1590
|
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
err.reason = evt.reason;}
|
|
1591
|
+
websock.onclose = evt => {
|
|
1592
|
+
if (! evt.wasClean) {
|
|
1593
|
+
var err = new Error('websocket close');
|
|
1594
|
+
err.code = evt.code;
|
|
1595
|
+
err.reason = evt.reason;}
|
|
1580
1596
|
|
|
1581
|
-
|
|
1597
|
+
conn.reset(err);}; } );
|
|
1582
1598
|
|
|
1583
1599
|
return this} }
|
|
1584
1600
|
|
|
1585
|
-
const version = '0.
|
|
1601
|
+
const version = '0.6.1';
|
|
1586
1602
|
|
|
1587
1603
|
const MQTTClient_v4 = /* #__PURE__ */
|
|
1588
1604
|
with_topic_path_router(
|
|
@@ -1598,5 +1614,5 @@ const mqtt_v4 = opt =>
|
|
|
1598
1614
|
const mqtt_v5 = opt =>
|
|
1599
1615
|
new MQTTClient_v5(opt);
|
|
1600
1616
|
|
|
1601
|
-
export { MQTTBase, MQTTClient_v4, MQTTClient_v5, MQTTCore, MQTTError,
|
|
1617
|
+
export { MQTTBase, MQTTClient_v4, MQTTClient_v5, MQTTCore, MQTTError, _mqtt_cmdids, _mqtt_conn, _mqtt_dispatch, as_topic_path, mqtt_v4 as default, mqtt_v4, mqtt_v5, version, with_topic_path_router, with_topic_router };
|
|
1602
1618
|
//# sourceMappingURL=index.js.map
|