u8-mqtt 0.4.1 → 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.
- package/cjs/basic-v4.cjs +103 -137
- package/cjs/basic-v4.cjs.map +1 -1
- package/cjs/basic-v5.cjs +102 -136
- package/cjs/basic-v5.cjs.map +1 -1
- package/cjs/index.cjs +144 -189
- package/cjs/index.cjs.map +1 -1
- package/cjs/v4.cjs +145 -190
- package/cjs/v4.cjs.map +1 -1
- package/cjs/v5.cjs +144 -189
- package/cjs/v5.cjs.map +1 -1
- package/code/_dispatch.jsy +16 -0
- package/code/base.jsy +68 -124
- package/code/core.jsy +15 -9
- package/code/router_path.jsy +24 -43
- package/code/with_topic_router.jsy +18 -10
- package/esm/basic-v4.js +1154 -0
- package/esm/basic-v4.js.map +1 -0
- package/esm/basic-v5.js +1416 -0
- package/esm/basic-v5.js.map +1 -0
- package/esm/deno/basic-v4.js +103 -137
- package/esm/deno/basic-v4.js.map +1 -1
- package/esm/deno/basic-v5.js +102 -136
- package/esm/deno/basic-v5.js.map +1 -1
- package/esm/deno/index.js +144 -189
- package/esm/deno/index.js.map +1 -1
- package/esm/deno/v4.js +145 -190
- package/esm/deno/v4.js.map +1 -1
- package/esm/deno/v5.js +144 -189
- package/esm/deno/v5.js.map +1 -1
- package/esm/index.js +1599 -0
- package/esm/index.js.map +1 -0
- package/esm/node/basic-v4.js +103 -137
- package/esm/node/basic-v4.js.map +1 -1
- package/esm/node/basic-v4.mjs +103 -137
- package/esm/node/basic-v4.mjs.map +1 -1
- package/esm/node/basic-v5.js +102 -136
- package/esm/node/basic-v5.js.map +1 -1
- package/esm/node/basic-v5.mjs +102 -136
- package/esm/node/basic-v5.mjs.map +1 -1
- package/esm/node/index.js +144 -189
- package/esm/node/index.js.map +1 -1
- package/esm/node/index.mjs +144 -189
- package/esm/node/index.mjs.map +1 -1
- package/esm/node/v4.js +145 -190
- package/esm/node/v4.js.map +1 -1
- package/esm/node/v4.mjs +145 -190
- package/esm/node/v4.mjs.map +1 -1
- package/esm/node/v5.js +144 -189
- package/esm/node/v5.js.map +1 -1
- package/esm/node/v5.mjs +144 -189
- package/esm/node/v5.mjs.map +1 -1
- package/esm/v4.js +1336 -0
- package/esm/v4.js.map +1 -0
- package/esm/v5.js +1599 -0
- package/esm/v5.js.map +1 -0
- package/esm/web/basic-v4.js +103 -137
- 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 +102 -136
- 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/index.js +144 -189
- 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 +145 -190
- 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 +144 -189
- 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/code/base.jsy
CHANGED
|
@@ -9,28 +9,34 @@ export class MQTTError extends Error ::
|
|
|
9
9
|
|
|
10
10
|
export class MQTTBase ::
|
|
11
11
|
constructor(opt={}) ::
|
|
12
|
+
this.with(opt)
|
|
12
13
|
this._conn_ = _mqtt_conn @ this,
|
|
13
14
|
this._init_dispatch(opt, this)
|
|
14
15
|
|
|
16
|
+
with(fns_ns) ::
|
|
17
|
+
for let [k,v] of Object.entries(fns_ns) ::
|
|
18
|
+
if 'function' === typeof v :: this[k] = v
|
|
19
|
+
return this
|
|
20
|
+
|
|
15
21
|
async conn_emit(evt, arg, err_arg) ::
|
|
16
22
|
this.log_conn?.(evt, arg, err_arg)
|
|
17
23
|
try ::
|
|
18
|
-
let fn_evt = this[await evt] // microtask break
|
|
24
|
+
let fn_evt = this[await evt] // microtask break using `await evt`
|
|
19
25
|
if fn_evt ::
|
|
20
26
|
await fn_evt.call(this, this, arg, err_arg)
|
|
21
|
-
else if err_arg ::
|
|
22
|
-
await this.on_error(err_arg, evt)
|
|
27
|
+
else if err_arg :: throw err_arg
|
|
23
28
|
catch err ::
|
|
24
29
|
this.on_error(err, evt)
|
|
25
30
|
|
|
26
|
-
on_error(err,
|
|
27
|
-
console.warn @ '[[u8-mqtt error: %s]]',
|
|
31
|
+
on_error(err, evt) ::
|
|
32
|
+
console.warn @ '[[u8-mqtt error: %s]]', evt, err
|
|
28
33
|
|
|
29
34
|
// Handshaking Packets
|
|
30
35
|
|
|
31
36
|
async connect(pkt={}) ::
|
|
32
|
-
let cid = pkt.client_id ||
|
|
33
|
-
if
|
|
37
|
+
let cid = pkt.client_id || this.client_id
|
|
38
|
+
if 'string' !== typeof cid ::
|
|
39
|
+
// see init_client_id implementation in core.jsy
|
|
34
40
|
pkt.client_id = cid = this.init_client_id(cid)
|
|
35
41
|
this.client_id = cid
|
|
36
42
|
|
|
@@ -56,12 +62,13 @@ export class MQTTBase ::
|
|
|
56
62
|
return this._send('auth', pkt, 'auth')
|
|
57
63
|
|
|
58
64
|
ping() :: return this._send('pingreq', null, 'pingresp')
|
|
59
|
-
|
|
65
|
+
puback({pkt_id}) :: return this._send('puback', {pkt_id})
|
|
60
66
|
|
|
61
67
|
// alias: sub
|
|
62
68
|
subscribe(pkt, ex, topic_prefix) ::
|
|
63
69
|
pkt = _as_topics(pkt, ex, topic_prefix)
|
|
64
|
-
|
|
70
|
+
let suback = this._send('subscribe', pkt, pkt)
|
|
71
|
+
return this.on_sub?.(suback, pkt) ?? suback
|
|
65
72
|
|
|
66
73
|
// alias: unsub
|
|
67
74
|
unsubscribe(pkt, ex, topic_prefix) ::
|
|
@@ -69,48 +76,52 @@ export class MQTTBase ::
|
|
|
69
76
|
return this._send('unsubscribe', pkt, pkt)
|
|
70
77
|
|
|
71
78
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
store(topic, payload, pub_opt) ::
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
obj_send(topic, msg, pub_opt) ::
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
79
|
+
post(topic, payload, pub_opt) :: // qos:0
|
|
80
|
+
return this.pub({topic, payload, qos:0}, pub_opt)
|
|
81
|
+
send(topic, payload, pub_opt) :: // qos:1
|
|
82
|
+
return this.pub({topic, payload, qos:1}, pub_opt)
|
|
83
|
+
store(topic, payload, pub_opt) :: // qos:1, retain: 1
|
|
84
|
+
return this.pub({topic, payload, qos:1, retain: 1}, pub_opt)
|
|
85
|
+
|
|
86
|
+
// alias: json_post
|
|
87
|
+
obj_post(topic, msg, pub_opt) :: // qos:0
|
|
88
|
+
return this.pub({topic, msg, arg: 'msg', qos:0}, pub_opt)
|
|
89
|
+
// alias: json_send
|
|
90
|
+
obj_send(topic, msg, pub_opt) :: // qos:1
|
|
91
|
+
return this.pub({topic, msg, arg: 'msg', qos:1}, pub_opt)
|
|
92
|
+
// alias: json_store
|
|
93
|
+
obj_store(topic, msg, pub_opt) :: // qos:1, retain: 1
|
|
94
|
+
return this.pub({topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)
|
|
95
|
+
|
|
96
|
+
// alias: publish -- because 'pub' is shorter for semantic aliases above
|
|
97
|
+
async pub(pkt, pub_opt) ::
|
|
98
|
+
if undefined === pkt.payload ::
|
|
99
|
+
if 'function' === typeof pub_opt ::
|
|
100
|
+
pub_opt = {fn_encode: pub_opt}
|
|
101
|
+
|
|
102
|
+
let {msg} = pkt
|
|
103
|
+
switch typeof msg ::
|
|
104
|
+
case 'function':
|
|
105
|
+
pub_opt = {...pub_opt, fn_encode: msg}
|
|
106
|
+
// flow into 'undefined' case
|
|
107
|
+
case 'undefined':
|
|
108
|
+
// return a single-value closure to publish packets
|
|
109
|
+
return v => this.pub({...pkt, [pkt.arg || 'payload']: v}, pub_opt)
|
|
110
|
+
|
|
111
|
+
// Encode payload from msg; fn_encode allows alternative to JSON.stringify
|
|
112
|
+
let {fn_encode} = pub_opt || {}
|
|
113
|
+
pkt.payload = fn_encode
|
|
114
|
+
? await fn_encode(msg)
|
|
115
|
+
: JSON.stringify(msg)
|
|
116
|
+
|
|
117
|
+
if pub_opt ::
|
|
118
|
+
if pub_opt.props ::
|
|
119
|
+
pkt.props = pub_opt.props
|
|
120
|
+
if pub_opt.xform ::
|
|
121
|
+
pkt = pub_opt.xform(pkt) || pkt
|
|
122
|
+
|
|
123
|
+
return this._send @ 'publish', pkt,
|
|
124
|
+
pkt.qos ? pkt : void 0 // key
|
|
114
125
|
|
|
115
126
|
|
|
116
127
|
// Internal API
|
|
@@ -125,41 +136,18 @@ export class MQTTBase ::
|
|
|
125
136
|
return _mqtt_dispatch(this, target)
|
|
126
137
|
|
|
127
138
|
static _aliases() ::
|
|
128
|
-
return ' pub
|
|
139
|
+
return ' publish:pub sub:subscribe unsub:unsubscribe json_post:obj_post json_send:obj_send json_store:obj_store'
|
|
129
140
|
|
|
130
141
|
static _once_(self=this) ::
|
|
131
142
|
self._once_ = _=>0
|
|
132
|
-
self.MQTTError = MQTTError
|
|
133
143
|
let p = self.prototype
|
|
144
|
+
p.MQTTError = MQTTError
|
|
134
145
|
for let alias of self._aliases().split(/\s+/) ::
|
|
135
146
|
alias = alias.split(':')
|
|
136
147
|
let fn = alias[1] && p[alias[1]]
|
|
137
148
|
if fn :: p[alias[0]] = fn
|
|
138
149
|
|
|
139
150
|
|
|
140
|
-
/*
|
|
141
|
-
on_mqtt_type = {
|
|
142
|
-
mqtt_auth(pkt, ctx) ::
|
|
143
|
-
mqtt_connect(pkt, ctx) ::
|
|
144
|
-
mqtt_connack(pkt, ctx) ::
|
|
145
|
-
mqtt_disconnect(pkt, ctx) ::
|
|
146
|
-
|
|
147
|
-
mqtt_publish(pkt, ctx)
|
|
148
|
-
mqtt_subscribe(pkt, ctx) ::
|
|
149
|
-
mqtt_unsubscribe(pkt, ctx) ::
|
|
150
|
-
|
|
151
|
-
mqtt_pingreq(pkt, ctx) ::
|
|
152
|
-
mqtt_pingresp(pkt, ctx) ::
|
|
153
|
-
}
|
|
154
|
-
*/
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const _prefix_topics = (topic_prefix, iterable) =>
|
|
158
|
-
Array.from @ iterable, value => @
|
|
159
|
-
value.trim // string
|
|
160
|
-
? _prefix_topics(topic_prefix, value)
|
|
161
|
-
: topic_prefix + value
|
|
162
|
-
|
|
163
151
|
function _as_topics(pkt, ex, topic_prefix) ::
|
|
164
152
|
if ex?.trim :: // string
|
|
165
153
|
topic_prefix = ex
|
|
@@ -176,53 +164,9 @@ function _as_topics(pkt, ex, topic_prefix) ::
|
|
|
176
164
|
if topic_prefix ::
|
|
177
165
|
// particularly useful with shared queues, e.g.
|
|
178
166
|
// topic_prefix = '$share/some-queue-name/'
|
|
179
|
-
|
|
180
|
-
|
|
167
|
+
let _prefix_topics = v =>
|
|
168
|
+
v.trim ? topic_prefix+v : v.map(_prefix_topics)
|
|
181
169
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if undefined === pkt.payload ::
|
|
185
|
-
if 'function' === typeof pub_opt ::
|
|
186
|
-
pub_opt = {fn_encode: pub_opt}
|
|
187
|
-
|
|
188
|
-
let {msg} = pkt
|
|
189
|
-
switch typeof msg ::
|
|
190
|
-
case 'function':
|
|
191
|
-
pub_opt = {...pub_opt, fn_encode: msg}
|
|
192
|
-
// flow into 'undefined' case
|
|
193
|
-
case 'undefined':
|
|
194
|
-
// return a single-value closure to publish packets
|
|
195
|
-
return v => _pub(self, {...pkt, [pkt.arg || 'payload']: v}, pub_opt)
|
|
196
|
-
|
|
197
|
-
default:
|
|
198
|
-
// Encode payload from msg; fn_encode allows alternative to JSON.stringify
|
|
199
|
-
let {fn_encode} = pub_opt || {}
|
|
200
|
-
pkt.payload = fn_encode
|
|
201
|
-
? await fn_encode(msg)
|
|
202
|
-
: JSON.stringify(msg)
|
|
203
|
-
|
|
204
|
-
if pub_opt ::
|
|
205
|
-
if pub_opt.props ::
|
|
206
|
-
pkt.props = pub_opt.props
|
|
207
|
-
if pub_opt.xform ::
|
|
208
|
-
pkt = pub_opt.xform(pkt) || pkt
|
|
209
|
-
|
|
210
|
-
return self._send @ 'publish', pkt,
|
|
211
|
-
pkt.qos ? pkt : void 0 // key
|
|
212
|
-
|
|
213
|
-
::
|
|
214
|
-
Object.assign @ _pub, @{}
|
|
215
|
-
m: (self, topic, payload, pub_opt) =>
|
|
216
|
-
_pub(self, {topic, payload, qos:0}, pub_opt)
|
|
217
|
-
mq: (self, topic, payload, pub_opt) =>
|
|
218
|
-
_pub(self, {topic, payload, qos:1}, pub_opt)
|
|
219
|
-
mqr: (self, topic, payload, pub_opt) =>
|
|
220
|
-
_pub(self, {topic, payload, qos:1, retain: 1}, pub_opt)
|
|
221
|
-
|
|
222
|
-
o: (self, topic, msg, pub_opt) =>
|
|
223
|
-
_pub(self, {topic, msg, arg: 'msg', qos:0}, pub_opt)
|
|
224
|
-
oq: (self, topic, msg, pub_opt) =>
|
|
225
|
-
_pub(self, {topic, msg, arg: 'msg', qos:1}, pub_opt)
|
|
226
|
-
oqr: (self, topic, msg, pub_opt) =>
|
|
227
|
-
_pub(self, {topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)
|
|
170
|
+
pkt.topics = pkt.topics.map(_prefix_topics)
|
|
171
|
+
return pkt
|
|
228
172
|
|
package/code/core.jsy
CHANGED
|
@@ -12,20 +12,27 @@ const pkt_api = {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export class MQTTCore extends MQTTBase ::
|
|
15
|
-
constructor(opt={}) ::
|
|
16
|
-
super(opt)
|
|
17
|
-
this.with(opt)
|
|
18
|
-
|
|
19
15
|
static mqtt_ctx(mqtt_level, mqtt_opts, pkt_ctx=pkt_api) ::
|
|
20
16
|
let self = class extends this {}
|
|
21
17
|
self.prototype.mqtt_ctx =
|
|
22
18
|
mqtt_pkt_ctx(mqtt_level, mqtt_opts, pkt_ctx)
|
|
23
19
|
return self
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
|
|
22
|
+
// automatic Client Id for connect()
|
|
23
|
+
init_client_id(parts=['u8-mqtt--','']) ::
|
|
24
|
+
let sess_stg=this.sess_stg
|
|
25
|
+
let key, cid = sess_stg?.getItem(key=parts.join(' '))
|
|
26
|
+
if ! cid ::
|
|
27
|
+
cid = parts.join @ Math.random().toString(36).slice(2)
|
|
28
|
+
sess_stg?.setItem(key, cid)
|
|
29
|
+
return cid
|
|
30
|
+
|
|
31
|
+
get sess_stg() :: return globalThis.sessionStorage
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
//on_error(err, evt) ::
|
|
35
|
+
// console.warn @ '[[u8-mqtt error: %s]]', evt, err
|
|
29
36
|
|
|
30
37
|
//log_conn(evt, arg, err_arg) ::
|
|
31
38
|
// console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
|
|
@@ -102,7 +109,6 @@ export class MQTTCore extends MQTTBase ::
|
|
|
102
109
|
#IF PLAT_NODEJS
|
|
103
110
|
with_tcp(...opt) ::
|
|
104
111
|
opt = this._conn_opt(opt)
|
|
105
|
-
console.log @: opt
|
|
106
112
|
return this._use_conn @=>
|
|
107
113
|
this.with_stream @
|
|
108
114
|
tcp_connect(opt)
|
package/code/router_path.jsy
CHANGED
|
@@ -11,7 +11,7 @@ export const with_topic_path_router = /* #__PURE__ */
|
|
|
11
11
|
const mqtt_topic = topic_route =>
|
|
12
12
|
topic_route
|
|
13
13
|
.replace @ /[*].*$/, '#'
|
|
14
|
-
.replace @ /:\w
|
|
14
|
+
.replace @ /:\w[^\/]*/g, '+'
|
|
15
15
|
|
|
16
16
|
/* From the [MQTT v5 Spec](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Topic_Names_and)
|
|
17
17
|
4.7.1.2 Multi-level wildcard -- (‘#’ U+0023)
|
|
@@ -41,9 +41,8 @@ function mqtt_topic_path_router() ::
|
|
|
41
41
|
let priority = args.pop()
|
|
42
42
|
|
|
43
43
|
if 'function' !== typeof fn ::
|
|
44
|
-
if
|
|
45
|
-
|
|
46
|
-
else throw new TypeError()
|
|
44
|
+
if fn :: throw new TypeError()
|
|
45
|
+
fn = _ignore
|
|
47
46
|
|
|
48
47
|
let rte = _rxp_parse @ as_topic_path @ topic_route
|
|
49
48
|
|
|
@@ -59,7 +58,7 @@ function mqtt_topic_path_router() ::
|
|
|
59
58
|
clear(priority) ::
|
|
60
59
|
pri_lsts[priority ? 0 : 1] = []
|
|
61
60
|
if null == priority ::
|
|
62
|
-
pri_lsts[1] = []
|
|
61
|
+
pri_lsts[1] = [] // null clears both lists
|
|
63
62
|
|
|
64
63
|
async invoke(pkt, ctx) ::
|
|
65
64
|
ctx.idx = 0
|
|
@@ -75,51 +74,33 @@ function mqtt_topic_path_router() ::
|
|
|
75
74
|
break
|
|
76
75
|
else ctx.idx++
|
|
77
76
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
await ctx.mqtt._send('puback', {pkt_id})
|
|
77
|
+
if 1 === pkt.qos ::
|
|
78
|
+
await ctx.mqtt.puback(pkt)
|
|
81
79
|
|
|
82
80
|
|
|
83
81
|
function * _routes_iter(all_route_lists, topic) ::
|
|
82
|
+
topic = topic.replace(/^[\/]*/, '/') // ensure '/' prefix for regexparam library
|
|
84
83
|
for let route_list of all_route_lists ::
|
|
85
|
-
for let
|
|
86
|
-
let
|
|
87
|
-
if
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
: pattern.exec(topic)
|
|
95
|
-
|
|
96
|
-
if null === match ::
|
|
97
|
-
return
|
|
98
|
-
|
|
99
|
-
if false === keys ::
|
|
100
|
-
let {groups} = match
|
|
101
|
-
if ! groups ::
|
|
102
|
-
return [tgt]
|
|
103
|
-
|
|
104
|
-
let params = {}
|
|
105
|
-
for let k in groups ::
|
|
106
|
-
params[k] = groups[k]
|
|
107
|
-
|
|
108
|
-
return [tgt, params]
|
|
109
|
-
|
|
110
|
-
if 0 === keys.length ::
|
|
111
|
-
return [tgt]
|
|
112
|
-
|
|
113
|
-
let params = {}
|
|
114
|
-
for let i=0; i<keys.length; i++ ::
|
|
115
|
-
params[ keys[i] ] = match[1+i]
|
|
116
|
-
return [tgt, params]
|
|
84
|
+
for let {keys, pattern, tgt} of route_list ::
|
|
85
|
+
let match = pattern.exec(topic)
|
|
86
|
+
if match ::
|
|
87
|
+
let params = keys
|
|
88
|
+
? keys.reduce @
|
|
89
|
+
(o, k, i) => (o[k] = match[1+i], o)
|
|
90
|
+
{}
|
|
91
|
+
: match.groups ?? match
|
|
92
|
+
yield [tgt, params]
|
|
117
93
|
|
|
118
94
|
|
|
119
95
|
function _route_remove(all_route_lists, query) ::
|
|
120
|
-
let
|
|
96
|
+
let fn_match = route => @
|
|
97
|
+
route===query
|
|
98
|
+
|| route.tgt===query
|
|
99
|
+
|| route.key===query
|
|
121
100
|
for let lst of all_route_lists ::
|
|
122
|
-
let i = lst.findIndex(
|
|
123
|
-
if 0 <= i ::
|
|
101
|
+
let i = lst.findIndex(fn_match)
|
|
102
|
+
if 0 <= i ::
|
|
103
|
+
lst.splice(i,1)
|
|
104
|
+
return true
|
|
124
105
|
return false
|
|
125
106
|
|
|
@@ -14,29 +14,37 @@ export const with_topic_router = mqtt_topic_router =>
|
|
|
14
14
|
return super._aliases() +
|
|
15
15
|
' sub_topic:subscribe_topic unsub_topic:unsubscribe_topic'
|
|
16
16
|
|
|
17
|
-
_init_router(opt,
|
|
17
|
+
_init_router(opt, self, target) ::
|
|
18
|
+
this._subs = []
|
|
18
19
|
let router = this.router = target.router =
|
|
19
|
-
mqtt_topic_router(opt, this)
|
|
20
|
+
mqtt_topic_router(opt, this, target)
|
|
20
21
|
return router?.invoke
|
|
21
|
-
get on_topic() :: return this.router.add
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
on_sub(suback, pkt) ::
|
|
24
|
+
suback.pkt = pkt
|
|
25
|
+
this._subs.push(suback)
|
|
26
|
+
return suback
|
|
27
|
+
subs_settled() ::
|
|
28
|
+
return Promise.allSettled @
|
|
29
|
+
this._subs.splice(0,Infinity)
|
|
28
30
|
|
|
29
31
|
// alias: sub_topic
|
|
30
32
|
subscribe_topic(topic_route, ...args) ::
|
|
31
33
|
let router = this.router
|
|
32
34
|
router.add @ topic_route, true, args.pop() // handler
|
|
33
35
|
let topic = router.mqtt_topic(topic_route)
|
|
34
|
-
|
|
36
|
+
this.subscribe @ topic, ...args // ex, topic_prefix
|
|
37
|
+
return this // fluent api -- return this and track side effects
|
|
35
38
|
|
|
36
39
|
// alias: unsub_topic
|
|
37
40
|
unsubscribe_topic(topic_route, ...args) ::
|
|
38
41
|
let router = this.router
|
|
39
42
|
router.remove @ topic_route, true
|
|
40
43
|
let topic = router.mqtt_topic(topic_route)
|
|
41
|
-
return this.unsubscribe @
|
|
44
|
+
return this.unsubscribe @ topic, ...args // topic_prefix
|
|
45
|
+
|
|
46
|
+
// add topic handlers without corresponding subscribe packet
|
|
47
|
+
on_topic(...args) ::
|
|
48
|
+
this.router.add(...args)
|
|
49
|
+
return this
|
|
42
50
|
|