mqtt-plus 1.4.24 → 1.4.26
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/.ase/config.yaml +1 -0
- package/.ase/service.log +39 -0
- package/.ase/service.yaml +1 -0
- package/.ase/task/TASK-P18.md +1 -1
- package/.ase/task/TASK-P21.md +1 -1
- package/.claude/settings.local.json +4 -1
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +29 -5
- package/README.md +2 -2
- package/doc/mqtt-plus-broker-setup.md +1 -1
- package/doc/mqtt-plus-comm.md +3 -3
- package/doc/mqtt-plus-internals.md +6 -0
- package/dst-stage1/mqtt-plus-base.d.ts +2 -2
- package/dst-stage1/mqtt-plus-base.js +13 -10
- package/dst-stage1/mqtt-plus-error.js +54 -28
- package/dst-stage1/mqtt-plus-event.js +3 -1
- package/dst-stage1/mqtt-plus-options.js +7 -0
- package/dst-stage1/mqtt-plus-service.js +9 -6
- package/dst-stage1/mqtt-plus-sink.js +27 -54
- package/dst-stage1/mqtt-plus-source.js +13 -9
- package/dst-stage1/mqtt-plus-util.d.ts +1 -0
- package/dst-stage1/mqtt-plus-util.js +25 -4
- package/dst-stage1/mqtt-plus.d.ts +1 -1
- package/dst-stage1/mqtt-plus.js +2 -0
- package/dst-stage2/mqtt-plus.cjs.cjs +165 -124
- package/dst-stage2/mqtt-plus.esm.js +155 -123
- package/dst-stage2/mqtt-plus.umd.js +11 -11
- package/etc/stx.conf +3 -2
- package/package.d/@typescript-eslint+typescript-estree+8.66.0.patch +12 -0
- package/package.d/{vite+8.0.13.patch → vite+8.2.1.patch} +2 -2
- package/package.json +27 -28
- package/src/mqtt-plus-base.ts +15 -12
- package/src/mqtt-plus-error.ts +65 -33
- package/src/mqtt-plus-event.ts +2 -1
- package/src/mqtt-plus-options.ts +8 -0
- package/src/mqtt-plus-service.ts +9 -6
- package/src/mqtt-plus-sink.ts +28 -54
- package/src/mqtt-plus-source.ts +13 -9
- package/src/mqtt-plus-util.ts +27 -4
- package/src/mqtt-plus.ts +3 -1
- package/tst/mqtt-plus-0-fixture.ts +1 -0
- package/tst/mqtt-plus-2-event.spec.ts +25 -0
- package/tst/mqtt-plus-4-sink.spec.ts +23 -0
- package/tst/mqtt-plus-5-source.spec.ts +26 -0
- package/tst/mqtt-plus-6-misc.spec.ts +58 -0
- package/tst/mqtt-plus-8-run.spec.ts +60 -0
- package/dst-stage1/mqtt-plus-api.js.map +0 -1
- package/dst-stage1/mqtt-plus-auth.js.map +0 -1
- package/dst-stage1/mqtt-plus-base.js.map +0 -1
- package/dst-stage1/mqtt-plus-codec.js.map +0 -1
- package/dst-stage1/mqtt-plus-encode.js.map +0 -1
- package/dst-stage1/mqtt-plus-error.js.map +0 -1
- package/dst-stage1/mqtt-plus-event.js.map +0 -1
- package/dst-stage1/mqtt-plus-info.js.map +0 -1
- package/dst-stage1/mqtt-plus-meta.js.map +0 -1
- package/dst-stage1/mqtt-plus-msg.js.map +0 -1
- package/dst-stage1/mqtt-plus-options.js.map +0 -1
- package/dst-stage1/mqtt-plus-service.js.map +0 -1
- package/dst-stage1/mqtt-plus-sink.js.map +0 -1
- package/dst-stage1/mqtt-plus-source.js.map +0 -1
- package/dst-stage1/mqtt-plus-subscription.js.map +0 -1
- package/dst-stage1/mqtt-plus-timer.js.map +0 -1
- package/dst-stage1/mqtt-plus-trace.js.map +0 -1
- package/dst-stage1/mqtt-plus-util.js.map +0 -1
- package/dst-stage1/mqtt-plus-version.js.map +0 -1
- package/dst-stage1/mqtt-plus.js.map +0 -1
- package/package.d/@typescript-eslint+typescript-estree+8.59.3.patch +0 -12
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
1
5
|
//#region \0rolldown/runtime.js
|
|
2
6
|
var __create = Object.create;
|
|
3
7
|
var __defProp = Object.defineProperty;
|
|
@@ -15,7 +19,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
19
|
}
|
|
16
20
|
return to;
|
|
17
21
|
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
19
23
|
value: mod,
|
|
20
24
|
enumerable: true
|
|
21
25
|
}) : target, mod));
|
|
@@ -146,6 +150,7 @@ var ReadableTee = class extends node_stream.Readable {
|
|
|
146
150
|
}
|
|
147
151
|
};
|
|
148
152
|
async function sendBufferAsChunks(buffer, chunkSize, sendChunk, creditGate, abortSignal) {
|
|
153
|
+
if (!(Number.isFinite(chunkSize) && chunkSize > 0)) throw new Error("invalid chunk size");
|
|
149
154
|
if (buffer.byteLength === 0) await sendChunk(void 0, void 0, true);
|
|
150
155
|
else for (let i = 0; i < buffer.byteLength; i += chunkSize) {
|
|
151
156
|
if (abortSignal?.aborted) throw abortSignal.reason ?? /* @__PURE__ */ new Error("aborted");
|
|
@@ -157,6 +162,7 @@ async function sendBufferAsChunks(buffer, chunkSize, sendChunk, creditGate, abor
|
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
async function sendStreamAsChunks(readable, chunkSize, sendChunk, creditGate, abortSignal) {
|
|
165
|
+
if (!(Number.isFinite(chunkSize) && chunkSize > 0)) throw new Error("invalid chunk size");
|
|
160
166
|
let pending;
|
|
161
167
|
for await (const raw of readable) {
|
|
162
168
|
if (abortSignal?.aborted) throw abortSignal.reason ?? /* @__PURE__ */ new Error("aborted");
|
|
@@ -179,11 +185,17 @@ async function sendStreamAsChunks(readable, chunkSize, sendChunk, creditGate, ab
|
|
|
179
185
|
await sendChunk(pending, void 0, true);
|
|
180
186
|
} else await sendChunk(void 0, void 0, true);
|
|
181
187
|
}
|
|
188
|
+
function alignHandlerParams(params, handler) {
|
|
189
|
+
if (typeof handler !== "function") return params;
|
|
190
|
+
const arity = handler.length - 1;
|
|
191
|
+
if (params.length >= arity) return params;
|
|
192
|
+
return [...params, ...Array(arity - params.length).fill(void 0)];
|
|
193
|
+
}
|
|
182
194
|
function makeMutuallyExclusiveFields(obj, f1Name, f2Name, onConsumed) {
|
|
183
195
|
if (!(typeof obj === "object" && obj !== null)) throw new Error("invalid object");
|
|
184
196
|
let consumed;
|
|
185
|
-
|
|
186
|
-
|
|
197
|
+
let f1Value = obj[f1Name];
|
|
198
|
+
let f2Value = obj[f2Name];
|
|
187
199
|
Object.defineProperty(obj, f1Name, {
|
|
188
200
|
get: () => {
|
|
189
201
|
if (consumed === "f2") throw new Error(`field "${f1Name}" is mutually exclusive with field "${f2Name}" and "${f2Name}" was already consumed`);
|
|
@@ -191,7 +203,10 @@ function makeMutuallyExclusiveFields(obj, f1Name, f2Name, onConsumed) {
|
|
|
191
203
|
consumed = "f1";
|
|
192
204
|
return f1Value;
|
|
193
205
|
},
|
|
194
|
-
|
|
206
|
+
set: (value) => {
|
|
207
|
+
f1Value = value;
|
|
208
|
+
},
|
|
209
|
+
enumerable: false,
|
|
195
210
|
configurable: true
|
|
196
211
|
});
|
|
197
212
|
Object.defineProperty(obj, f2Name, {
|
|
@@ -201,7 +216,10 @@ function makeMutuallyExclusiveFields(obj, f1Name, f2Name, onConsumed) {
|
|
|
201
216
|
consumed = "f2";
|
|
202
217
|
return f2Value;
|
|
203
218
|
},
|
|
204
|
-
|
|
219
|
+
set: (value) => {
|
|
220
|
+
f2Value = value;
|
|
221
|
+
},
|
|
222
|
+
enumerable: false,
|
|
205
223
|
configurable: true
|
|
206
224
|
});
|
|
207
225
|
}
|
|
@@ -285,8 +303,10 @@ function ensureError(error, prefix, debug = false) {
|
|
|
285
303
|
} else return new Error(msg);
|
|
286
304
|
}
|
|
287
305
|
function runFinally(isAsync, onfinally, description) {
|
|
288
|
-
if (!onfinally)
|
|
289
|
-
|
|
306
|
+
if (!onfinally) {
|
|
307
|
+
if (isAsync) return Promise.resolve();
|
|
308
|
+
else return;
|
|
309
|
+
}
|
|
290
310
|
let result;
|
|
291
311
|
try {
|
|
292
312
|
result = onfinally();
|
|
@@ -302,8 +322,10 @@ function runFinally(isAsync, onfinally, description) {
|
|
|
302
322
|
return result;
|
|
303
323
|
}
|
|
304
324
|
function runUnroll(isAsync, spool) {
|
|
305
|
-
if (!spool)
|
|
306
|
-
|
|
325
|
+
if (!spool) {
|
|
326
|
+
if (isAsync) return Promise.resolve();
|
|
327
|
+
else return;
|
|
328
|
+
}
|
|
307
329
|
let result = spool.unroll();
|
|
308
330
|
if (!isAsync && result instanceof Promise) throw new Error("spool unroll returned Promise in non-async context");
|
|
309
331
|
if (isAsync && !(result instanceof Promise)) result = Promise.resolve(result);
|
|
@@ -317,9 +339,12 @@ function runSettle(isAsync, pending, spool, onfinally, description) {
|
|
|
317
339
|
} catch (arg) {
|
|
318
340
|
failure = ensureError(arg, description);
|
|
319
341
|
}
|
|
320
|
-
if (pending || failure !== void 0) {
|
|
342
|
+
if (pending !== void 0 || failure !== void 0) {
|
|
321
343
|
runUnroll(false, spool);
|
|
322
|
-
if (
|
|
344
|
+
if (failure !== void 0) {
|
|
345
|
+
if (pending !== void 0) pending.suppressed = failure;
|
|
346
|
+
else throw failure;
|
|
347
|
+
}
|
|
323
348
|
}
|
|
324
349
|
} else return (async () => {
|
|
325
350
|
let failure;
|
|
@@ -328,12 +353,34 @@ function runSettle(isAsync, pending, spool, onfinally, description) {
|
|
|
328
353
|
} catch (arg) {
|
|
329
354
|
failure = ensureError(arg, description);
|
|
330
355
|
}
|
|
331
|
-
if (pending || failure !== void 0) {
|
|
356
|
+
if (pending !== void 0 || failure !== void 0) {
|
|
332
357
|
await runUnroll(true, spool);
|
|
333
|
-
if (
|
|
358
|
+
if (failure !== void 0) {
|
|
359
|
+
if (pending !== void 0) pending.suppressed = failure;
|
|
360
|
+
else throw failure;
|
|
361
|
+
}
|
|
334
362
|
}
|
|
335
363
|
})();
|
|
336
364
|
}
|
|
365
|
+
function runFail(error, spool, onfinally, description) {
|
|
366
|
+
const attach = (arg) => {
|
|
367
|
+
error.suppressed = ensureError(arg, description);
|
|
368
|
+
};
|
|
369
|
+
let result = void 0;
|
|
370
|
+
try {
|
|
371
|
+
result = onfinally?.();
|
|
372
|
+
} catch (arg) {
|
|
373
|
+
attach(arg);
|
|
374
|
+
}
|
|
375
|
+
if (result instanceof Promise) return result.catch(attach).then(() => spool?.unroll()).then(() => {
|
|
376
|
+
throw error;
|
|
377
|
+
});
|
|
378
|
+
const unrolled = spool?.unroll();
|
|
379
|
+
if (unrolled instanceof Promise) return unrolled.then(() => {
|
|
380
|
+
throw error;
|
|
381
|
+
});
|
|
382
|
+
throw error;
|
|
383
|
+
}
|
|
337
384
|
function run(...args) {
|
|
338
385
|
let description;
|
|
339
386
|
let spool;
|
|
@@ -379,25 +426,18 @@ function run(...args) {
|
|
|
379
426
|
try {
|
|
380
427
|
result = action();
|
|
381
428
|
} catch (arg) {
|
|
382
|
-
|
|
383
|
-
if (oncatch)
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
runSettle(false, true, spool, onfinally, description);
|
|
389
|
-
throw error;
|
|
390
|
-
}
|
|
391
|
-
if (spool && oncleanup) spool.roll(result, oncleanup);
|
|
392
|
-
runSettle(false, false, spool, onfinally, description);
|
|
393
|
-
return result;
|
|
429
|
+
const error = ensureError(arg, description);
|
|
430
|
+
if (!oncatch) return runFail(error, spool, onfinally, description);
|
|
431
|
+
try {
|
|
432
|
+
result = oncatch(error);
|
|
433
|
+
} catch (arg) {
|
|
434
|
+
return runFail(ensureError(arg, description), spool, onfinally, description);
|
|
394
435
|
}
|
|
395
|
-
|
|
396
|
-
throw error;
|
|
436
|
+
oncatch = void 0;
|
|
397
437
|
}
|
|
398
438
|
if (result instanceof Promise) return result.then(async (result) => {
|
|
399
439
|
if (spool && oncleanup) spool.roll(result, oncleanup);
|
|
400
|
-
await runSettle(true,
|
|
440
|
+
await runSettle(true, void 0, spool, onfinally, description);
|
|
401
441
|
return result;
|
|
402
442
|
}, async (arg) => {
|
|
403
443
|
let error = ensureError(arg, description);
|
|
@@ -407,19 +447,19 @@ function run(...args) {
|
|
|
407
447
|
result = await oncatch(error);
|
|
408
448
|
} catch (arg) {
|
|
409
449
|
error = ensureError(arg, description);
|
|
410
|
-
await runSettle(true,
|
|
450
|
+
await runSettle(true, error, spool, onfinally, description);
|
|
411
451
|
throw error;
|
|
412
452
|
}
|
|
413
453
|
if (spool && oncleanup) spool.roll(result, oncleanup);
|
|
414
|
-
await runSettle(true,
|
|
454
|
+
await runSettle(true, void 0, spool, onfinally, description);
|
|
415
455
|
return result;
|
|
416
456
|
}
|
|
417
|
-
await runSettle(true,
|
|
457
|
+
await runSettle(true, error, spool, onfinally, description);
|
|
418
458
|
throw error;
|
|
419
459
|
});
|
|
420
460
|
else {
|
|
421
461
|
if (spool && oncleanup) spool.roll(result, oncleanup);
|
|
422
|
-
runSettle(false,
|
|
462
|
+
runSettle(false, void 0, spool, onfinally, description);
|
|
423
463
|
return result;
|
|
424
464
|
}
|
|
425
465
|
}
|
|
@@ -430,9 +470,9 @@ var OptionsTrait = class {
|
|
|
430
470
|
this.options = {
|
|
431
471
|
id: "",
|
|
432
472
|
codec: "cbor",
|
|
433
|
-
timeout:
|
|
473
|
+
timeout: 1e4,
|
|
434
474
|
share: "",
|
|
435
|
-
chunkSize:
|
|
475
|
+
chunkSize: 16384,
|
|
436
476
|
chunkCredit: 4,
|
|
437
477
|
topicMake: (name, operation, peerId) => {
|
|
438
478
|
return `${name}/${operation}/${peerId ?? "any"}`;
|
|
@@ -447,6 +487,9 @@ var OptionsTrait = class {
|
|
|
447
487
|
},
|
|
448
488
|
...options
|
|
449
489
|
};
|
|
490
|
+
if (!(Number.isFinite(this.options.timeout) && this.options.timeout > 0)) throw new Error("options: \"timeout\" must be a positive number");
|
|
491
|
+
if (!(Number.isInteger(this.options.chunkSize) && this.options.chunkSize > 0)) throw new Error("options: \"chunkSize\" must be a positive integer");
|
|
492
|
+
if (!(Number.isInteger(this.options.chunkCredit) && this.options.chunkCredit >= 0)) throw new Error("options: \"chunkCredit\" must be a non-negative integer");
|
|
450
493
|
}
|
|
451
494
|
};
|
|
452
495
|
//#endregion
|
|
@@ -564,6 +607,8 @@ var versionToNum = (str) => {
|
|
|
564
607
|
if (minor > 99) throw new Error("invalid version string: minor version exceeds 99");
|
|
565
608
|
return parseInt(m[1], 10) * 100 + minor;
|
|
566
609
|
};
|
|
610
|
+
var VERSION = "1.4";
|
|
611
|
+
var MIN_VERSION = "1.4";
|
|
567
612
|
var version = versionToNum("1.4");
|
|
568
613
|
var minVersion = versionToNum("1.4");
|
|
569
614
|
//#endregion
|
|
@@ -959,13 +1004,13 @@ var BaseTrait = class extends TraceTrait {
|
|
|
959
1004
|
};
|
|
960
1005
|
} });
|
|
961
1006
|
}
|
|
962
|
-
this.
|
|
1007
|
+
this._mqtt = mqtt;
|
|
963
1008
|
if (this.options.id === "") {
|
|
964
1009
|
const clientId = mqtt.isFakeProxy ? void 0 : mqtt.options?.clientId;
|
|
965
1010
|
this.options.id = typeof clientId === "string" && clientId !== "" ? clientId : (0, nanoid.nanoid)();
|
|
966
1011
|
}
|
|
967
1012
|
this.log("info", "hooking into MQTT client");
|
|
968
|
-
this.
|
|
1013
|
+
this._messageHandler = (topic, message, packet) => {
|
|
969
1014
|
if (this.destroyed) return;
|
|
970
1015
|
let input;
|
|
971
1016
|
if (this.options.codec === "json") input = message.toString();
|
|
@@ -976,12 +1021,12 @@ var BaseTrait = class extends TraceTrait {
|
|
|
976
1021
|
}
|
|
977
1022
|
this._onMessage(topic, input, packet);
|
|
978
1023
|
};
|
|
979
|
-
this.
|
|
1024
|
+
this._mqtt.on("message", this._messageHandler);
|
|
980
1025
|
}
|
|
981
1026
|
async destroy() {
|
|
982
1027
|
this.destroyed = true;
|
|
983
1028
|
this.log("info", "un-hooking from MQTT client");
|
|
984
|
-
this.
|
|
1029
|
+
this._mqtt.off("message", this._messageHandler);
|
|
985
1030
|
this.onRequest.clear();
|
|
986
1031
|
this.onResponse.clear();
|
|
987
1032
|
}
|
|
@@ -1000,7 +1045,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1000
1045
|
async subscribeTopic(topic, options = {}) {
|
|
1001
1046
|
this.log("info", `subscribing to MQTT topic "${topic}"`);
|
|
1002
1047
|
return new Promise((resolve, reject) => {
|
|
1003
|
-
this.
|
|
1048
|
+
this._mqtt.subscribe(topic, {
|
|
1004
1049
|
qos: 2,
|
|
1005
1050
|
...options
|
|
1006
1051
|
}, (err, granted) => {
|
|
@@ -1018,7 +1063,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1018
1063
|
async unsubscribeTopic(topic) {
|
|
1019
1064
|
this.log("info", `unsubscribing from MQTT topic "${topic}"`);
|
|
1020
1065
|
return new Promise((resolve, reject) => {
|
|
1021
|
-
this.
|
|
1066
|
+
this._mqtt.unsubscribe(topic, (err, _packet) => {
|
|
1022
1067
|
if (err) {
|
|
1023
1068
|
this.error(err, `unsubscribing from MQTT topic "${topic}" failed`);
|
|
1024
1069
|
reject(err);
|
|
@@ -1042,7 +1087,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1042
1087
|
this.log("debug", `publishing to MQTT topic "${topic}"`, { message: messageOnDemand });
|
|
1043
1088
|
return new Promise((resolve, reject) => {
|
|
1044
1089
|
const messageData = typeof message === "string" ? message : Buffer.from(message.buffer, message.byteOffset, message.byteLength);
|
|
1045
|
-
this.
|
|
1090
|
+
this._mqtt.publish(topic, messageData, options, (err) => {
|
|
1046
1091
|
if (err) {
|
|
1047
1092
|
this.error(err, `publishing to MQTT topic "${topic}" failed`);
|
|
1048
1093
|
reject(err);
|
|
@@ -1077,7 +1122,10 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1077
1122
|
return;
|
|
1078
1123
|
}
|
|
1079
1124
|
this.log("debug", `received from MQTT topic "${topic}"`, { message });
|
|
1080
|
-
if (topicMatch.peerId !== void 0 && message.receiver !== void 0 && message.receiver !== topicMatch.peerId)
|
|
1125
|
+
if (topicMatch.peerId !== void 0 && message.receiver !== void 0 && message.receiver !== topicMatch.peerId) {
|
|
1126
|
+
this.log("warning", `receiver mismatch -- dropped message from direct topic "${topic}" (expected "${topicMatch.peerId}", got "${message.receiver}")`);
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1081
1129
|
if (this.msg.isRequest(message)) {
|
|
1082
1130
|
const handler = this.onRequest.get(`${message.type}:${message.name}`);
|
|
1083
1131
|
if (handler !== void 0) Promise.resolve().then(() => {
|
|
@@ -1100,7 +1148,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1100
1148
|
//#endregion
|
|
1101
1149
|
//#region dst-stage1/mqtt-plus-subscription.js
|
|
1102
1150
|
var RefCountedSubscription = class {
|
|
1103
|
-
constructor(subscribeFn, unsubscribeFn, lingerMs =
|
|
1151
|
+
constructor(subscribeFn, unsubscribeFn, lingerMs = 3e4) {
|
|
1104
1152
|
this.subscribeFn = subscribeFn;
|
|
1105
1153
|
this.unsubscribeFn = unsubscribeFn;
|
|
1106
1154
|
this.lingerMs = lingerMs;
|
|
@@ -1116,12 +1164,14 @@ var RefCountedSubscription = class {
|
|
|
1116
1164
|
}
|
|
1117
1165
|
decrementCount(topic) {
|
|
1118
1166
|
const count = this.counts.get(topic);
|
|
1119
|
-
if (count !== void 0)
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1167
|
+
if (count !== void 0) {
|
|
1168
|
+
if (count <= 1) {
|
|
1169
|
+
this.counts.delete(topic);
|
|
1170
|
+
return 0;
|
|
1171
|
+
} else {
|
|
1172
|
+
this.counts.set(topic, count - 1);
|
|
1173
|
+
return count - 1;
|
|
1174
|
+
}
|
|
1125
1175
|
}
|
|
1126
1176
|
}
|
|
1127
1177
|
clearCount(topic) {
|
|
@@ -1160,25 +1210,27 @@ var RefCountedSubscription = class {
|
|
|
1160
1210
|
}
|
|
1161
1211
|
}
|
|
1162
1212
|
async unsubscribe(topic) {
|
|
1163
|
-
if (this.decrementCount(topic) === 0)
|
|
1164
|
-
|
|
1165
|
-
|
|
1213
|
+
if (this.decrementCount(topic) === 0) {
|
|
1214
|
+
if (this.lingerMs > 0 && !topic.startsWith("$share/")) {
|
|
1215
|
+
const timer = setTimeout(() => {
|
|
1216
|
+
this.lingers.delete(topic);
|
|
1217
|
+
const promise = this.unsubscribeFn(topic).catch(() => {}).finally(() => {
|
|
1218
|
+
this.unsubbing.delete(topic);
|
|
1219
|
+
});
|
|
1220
|
+
this.unsubbing.set(topic, promise);
|
|
1221
|
+
}, this.lingerMs);
|
|
1222
|
+
this.lingers.set(topic, timer);
|
|
1223
|
+
} else {
|
|
1166
1224
|
const promise = this.unsubscribeFn(topic).catch(() => {}).finally(() => {
|
|
1167
1225
|
this.unsubbing.delete(topic);
|
|
1168
1226
|
});
|
|
1169
1227
|
this.unsubbing.set(topic, promise);
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
} else {
|
|
1173
|
-
const promise = this.unsubscribeFn(topic).catch(() => {}).finally(() => {
|
|
1174
|
-
this.unsubbing.delete(topic);
|
|
1175
|
-
});
|
|
1176
|
-
this.unsubbing.set(topic, promise);
|
|
1177
|
-
await promise;
|
|
1228
|
+
await promise;
|
|
1229
|
+
}
|
|
1178
1230
|
}
|
|
1179
1231
|
}
|
|
1180
1232
|
async flush() {
|
|
1181
|
-
const topics = new Set([
|
|
1233
|
+
const topics = /* @__PURE__ */ new Set([
|
|
1182
1234
|
...this.counts.keys(),
|
|
1183
1235
|
...this.lingers.keys(),
|
|
1184
1236
|
...this.pending.keys(),
|
|
@@ -1443,7 +1495,7 @@ var EventTrait = class extends AuthTrait {
|
|
|
1443
1495
|
this.log("warning", `event name mismatch -- dropped request for "${name}" (topic: "${topicName}", payload: "${request.name}")`, { requestId });
|
|
1444
1496
|
return;
|
|
1445
1497
|
}
|
|
1446
|
-
const params = request.params ?? [];
|
|
1498
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
1447
1499
|
if (this.eventControllers.has(requestId)) {
|
|
1448
1500
|
this.log("warning", `duplicate event request id -- dropped request for event "${name}"`, { requestId });
|
|
1449
1501
|
return;
|
|
@@ -1567,7 +1619,7 @@ var ServiceTrait = class extends EventTrait {
|
|
|
1567
1619
|
if (request.receiver && request.receiver !== this.options.id) return;
|
|
1568
1620
|
const requestId = request.id;
|
|
1569
1621
|
const senderId = request.sender;
|
|
1570
|
-
const params = request.params ?? [];
|
|
1622
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
1571
1623
|
if (senderId === void 0 || senderId === "") {
|
|
1572
1624
|
this.error(/* @__PURE__ */ new Error("invalid request: missing sender"));
|
|
1573
1625
|
return;
|
|
@@ -1671,7 +1723,9 @@ var ServiceTrait = class extends EventTrait {
|
|
|
1671
1723
|
const settle = () => {
|
|
1672
1724
|
if (settled) return false;
|
|
1673
1725
|
settled = true;
|
|
1674
|
-
spool.unroll()
|
|
1726
|
+
spool.unroll(false)?.catch((err) => {
|
|
1727
|
+
this.error(ensureError(err, `cleanup after call of service "${name}" failed`));
|
|
1728
|
+
});
|
|
1675
1729
|
return true;
|
|
1676
1730
|
};
|
|
1677
1731
|
const promise = new Promise((resolve, reject) => {
|
|
@@ -1778,7 +1832,7 @@ var SourceTrait = class extends ServiceTrait {
|
|
|
1778
1832
|
this.onRequest.set(`source-fetch-request:${name}`, async (request, topicName) => {
|
|
1779
1833
|
if (request.receiver && request.receiver !== this.options.id) return;
|
|
1780
1834
|
const requestId = request.id;
|
|
1781
|
-
const params = request.params ?? [];
|
|
1835
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
1782
1836
|
const sender = request.sender;
|
|
1783
1837
|
const receiver = request.receiver;
|
|
1784
1838
|
const reqSpool = new Spool();
|
|
@@ -1831,11 +1885,16 @@ var SourceTrait = class extends ServiceTrait {
|
|
|
1831
1885
|
if (current.size === 0) this.sourceRequests.delete(name);
|
|
1832
1886
|
}
|
|
1833
1887
|
});
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1888
|
+
const noopError = () => {};
|
|
1889
|
+
const destroyStream = () => {
|
|
1890
|
+
if (info.stream instanceof node_stream.Readable && !info.stream.destroyed) {
|
|
1891
|
+
info.stream.on("error", noopError);
|
|
1892
|
+
info.stream.destroy(ensureError(abortSignal.reason));
|
|
1893
|
+
}
|
|
1894
|
+
};
|
|
1895
|
+
abortSignal.addEventListener("abort", destroyStream, { once: true });
|
|
1837
1896
|
reqSpool.roll(() => {
|
|
1838
|
-
if (abortSignal.aborted
|
|
1897
|
+
if (abortSignal.aborted) destroyStream();
|
|
1839
1898
|
});
|
|
1840
1899
|
let abortReject;
|
|
1841
1900
|
const abortPromise = new Promise((_resolve, reject) => {
|
|
@@ -1982,7 +2041,7 @@ var SourceTrait = class extends ServiceTrait {
|
|
|
1982
2041
|
const sourceNameMismatchError = (kind, actualName) => /* @__PURE__ */ new Error(`${kind} name mismatch (expected "${name}", got "${actualName}")`);
|
|
1983
2042
|
await this.subscribeTopicAndSpool(spool, responseTopic, { qos: options.qos ?? 2 });
|
|
1984
2043
|
const chunkCredit = this.options.chunkCredit;
|
|
1985
|
-
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize :
|
|
2044
|
+
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize : 16384;
|
|
1986
2045
|
let chunksReceived = 0;
|
|
1987
2046
|
let creditGranted = chunkCredit;
|
|
1988
2047
|
let responderId = receiver;
|
|
@@ -2220,7 +2279,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2220
2279
|
this.onRequest.set(`sink-push-request:${name}`, async (request, topicName) => {
|
|
2221
2280
|
if (request.receiver && request.receiver !== this.options.id) return;
|
|
2222
2281
|
const requestId = request.id;
|
|
2223
|
-
const params = request.params ?? [];
|
|
2282
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
2224
2283
|
const sender = request.sender;
|
|
2225
2284
|
const receiver = request.receiver;
|
|
2226
2285
|
const reqSpool = new Spool();
|
|
@@ -2281,7 +2340,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2281
2340
|
chunksReceived: 0,
|
|
2282
2341
|
creditGranted: chunkCredit
|
|
2283
2342
|
} : void 0;
|
|
2284
|
-
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize :
|
|
2343
|
+
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize : 16384;
|
|
2285
2344
|
let streamEnded = false;
|
|
2286
2345
|
const pushTimerId = `sink-push-recv:${requestId}`;
|
|
2287
2346
|
const refreshPushTimeout = () => this.timerRefresh(pushTimerId, () => {
|
|
@@ -2511,8 +2570,12 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2511
2570
|
});
|
|
2512
2571
|
if (data instanceof node_stream.Readable) {
|
|
2513
2572
|
const stream = data;
|
|
2573
|
+
const noopError = () => {};
|
|
2514
2574
|
abortSignal.addEventListener("abort", () => {
|
|
2515
|
-
if (!stream.destroyed)
|
|
2575
|
+
if (!stream.destroyed) {
|
|
2576
|
+
stream.on("error", noopError);
|
|
2577
|
+
stream.destroy(ensureError(abortSignal.reason));
|
|
2578
|
+
}
|
|
2516
2579
|
}, { once: true });
|
|
2517
2580
|
}
|
|
2518
2581
|
const pushTimerId = `sink-push-send:${requestId}`;
|
|
@@ -2546,18 +2609,21 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2546
2609
|
pushFinalizeReject = reject;
|
|
2547
2610
|
});
|
|
2548
2611
|
pushFinalize.catch(() => {});
|
|
2612
|
+
const failPush = (error) => {
|
|
2613
|
+
abortController.abort(error);
|
|
2614
|
+
if (!pushAcked) {
|
|
2615
|
+
pushInitialSettled = true;
|
|
2616
|
+
pushInitialReject(error);
|
|
2617
|
+
} else if (!pushFinalized) {
|
|
2618
|
+
pushFinalized = true;
|
|
2619
|
+
pushFinalizeReject(error);
|
|
2620
|
+
}
|
|
2621
|
+
};
|
|
2549
2622
|
const lockResponder = (kind, sender) => {
|
|
2550
2623
|
if (sender === void 0 || sender === "") {
|
|
2551
2624
|
const error = /* @__PURE__ */ new Error(`received ${kind} without sender`);
|
|
2552
2625
|
remoteErrorObject = error;
|
|
2553
|
-
|
|
2554
|
-
if (!pushAcked) {
|
|
2555
|
-
pushInitialSettled = true;
|
|
2556
|
-
pushInitialReject(error);
|
|
2557
|
-
} else if (!pushFinalized) {
|
|
2558
|
-
pushFinalized = true;
|
|
2559
|
-
pushFinalizeReject(error);
|
|
2560
|
-
}
|
|
2626
|
+
failPush(error);
|
|
2561
2627
|
return false;
|
|
2562
2628
|
}
|
|
2563
2629
|
if (responderId === void 0) responderId = sender;
|
|
@@ -2575,37 +2641,25 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2575
2641
|
if (response.name !== name) {
|
|
2576
2642
|
const error = /* @__PURE__ */ new Error(`sink response name mismatch (expected "${name}", got "${response.name}")`);
|
|
2577
2643
|
remoteErrorObject = error;
|
|
2578
|
-
|
|
2579
|
-
if (!pushAcked) {
|
|
2580
|
-
pushInitialSettled = true;
|
|
2581
|
-
pushInitialReject(error);
|
|
2582
|
-
} else if (!pushFinalized) {
|
|
2583
|
-
pushFinalized = true;
|
|
2584
|
-
pushFinalizeReject(error);
|
|
2585
|
-
}
|
|
2644
|
+
failPush(error);
|
|
2586
2645
|
return;
|
|
2587
2646
|
}
|
|
2588
2647
|
if (!lockResponder("sink response", response.sender)) return;
|
|
2589
2648
|
if (response.error) {
|
|
2590
2649
|
const error = new Error(response.error);
|
|
2591
2650
|
remoteErrorObject = error;
|
|
2592
|
-
|
|
2593
|
-
if (!pushAcked) {
|
|
2594
|
-
pushInitialSettled = true;
|
|
2595
|
-
pushInitialReject(error);
|
|
2596
|
-
} else if (!pushFinalized) {
|
|
2597
|
-
pushFinalized = true;
|
|
2598
|
-
pushFinalizeReject(error);
|
|
2599
|
-
}
|
|
2651
|
+
failPush(error);
|
|
2600
2652
|
} else if (!pushAcked) {
|
|
2601
2653
|
initialCredit = response.credit;
|
|
2602
2654
|
pushAcked = true;
|
|
2603
2655
|
pushInitialSettled = true;
|
|
2604
2656
|
pushInitialResolve();
|
|
2605
|
-
} else if (!pushFinalized)
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2657
|
+
} else if (!pushFinalized) {
|
|
2658
|
+
if (pushDataComplete) {
|
|
2659
|
+
pushFinalized = true;
|
|
2660
|
+
pushFinalizeResolve();
|
|
2661
|
+
} else pushTerminalReceived = true;
|
|
2662
|
+
}
|
|
2609
2663
|
});
|
|
2610
2664
|
spool.roll(() => {
|
|
2611
2665
|
this.onResponse.delete(`sink-push-response:${requestId}`);
|
|
@@ -2614,28 +2668,14 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2614
2668
|
if (response.name !== name) {
|
|
2615
2669
|
const error = /* @__PURE__ */ new Error(`sink credit name mismatch (expected "${name}", got "${response.name}")`);
|
|
2616
2670
|
remoteErrorObject = error;
|
|
2617
|
-
|
|
2618
|
-
if (!pushAcked) {
|
|
2619
|
-
pushInitialSettled = true;
|
|
2620
|
-
pushInitialReject(error);
|
|
2621
|
-
} else if (!pushFinalized) {
|
|
2622
|
-
pushFinalized = true;
|
|
2623
|
-
pushFinalizeReject(error);
|
|
2624
|
-
}
|
|
2671
|
+
failPush(error);
|
|
2625
2672
|
return;
|
|
2626
2673
|
}
|
|
2627
2674
|
if (!lockResponder("sink credit", response.sender)) return;
|
|
2628
2675
|
if (response.credit === 0) {
|
|
2629
2676
|
cancelledByReceiver = true;
|
|
2630
2677
|
const error = /* @__PURE__ */ new Error(`push to sink "${name}" cancelled by receiver`);
|
|
2631
|
-
|
|
2632
|
-
if (!pushAcked) {
|
|
2633
|
-
pushInitialSettled = true;
|
|
2634
|
-
pushInitialReject(error);
|
|
2635
|
-
} else if (!pushFinalized) {
|
|
2636
|
-
pushFinalized = true;
|
|
2637
|
-
pushFinalizeReject(error);
|
|
2638
|
-
}
|
|
2678
|
+
failPush(error);
|
|
2639
2679
|
return;
|
|
2640
2680
|
}
|
|
2641
2681
|
if (creditGate !== void 0) {
|
|
@@ -2644,11 +2684,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2644
2684
|
} else if (pushAcked && initialCredit === void 0) {
|
|
2645
2685
|
const error = /* @__PURE__ */ new Error(`push to sink "${name}" received unsolicited credit (credit-flow disabled)`);
|
|
2646
2686
|
remoteErrorObject = error;
|
|
2647
|
-
|
|
2648
|
-
if (!pushFinalized) {
|
|
2649
|
-
pushFinalized = true;
|
|
2650
|
-
pushFinalizeReject(error);
|
|
2651
|
-
}
|
|
2687
|
+
failPush(error);
|
|
2652
2688
|
} else pendingCredit += response.credit;
|
|
2653
2689
|
});
|
|
2654
2690
|
spool.roll(() => {
|
|
@@ -2735,7 +2771,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2735
2771
|
}
|
|
2736
2772
|
} catch {}
|
|
2737
2773
|
if (pushAcked && !remoteErrorObject) await new Promise((resolve) => {
|
|
2738
|
-
|
|
2774
|
+
setTimeout(resolve, 0);
|
|
2739
2775
|
});
|
|
2740
2776
|
if (remoteErrorObject) throw remoteErrorObject;
|
|
2741
2777
|
throw err;
|
|
@@ -2748,4 +2784,9 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2748
2784
|
//#region dst-stage1/mqtt-plus.js
|
|
2749
2785
|
var MQTTp = class extends SinkTrait {};
|
|
2750
2786
|
//#endregion
|
|
2751
|
-
|
|
2787
|
+
exports.MIN_VERSION = MIN_VERSION;
|
|
2788
|
+
exports.VERSION = VERSION;
|
|
2789
|
+
exports.default = MQTTp;
|
|
2790
|
+
exports.minVersion = minVersion;
|
|
2791
|
+
exports.version = version;
|
|
2792
|
+
exports.versionToNum = versionToNum;
|