mqtt-plus 1.4.25 → 1.4.27
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 +34 -0
- package/.ase/service.yaml +1 -1
- 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 +5 -1
- package/dst-stage1/mqtt-plus.js +10 -1
- package/dst-stage2/mqtt-plus.cjs.cjs +169 -123
- package/dst-stage2/mqtt-plus.esm.js +168 -122
- package/dst-stage2/mqtt-plus.umd.js +11 -11
- package/etc/stx.conf +3 -2
- package/etc/vite.mts +1 -1
- package/package.d/@typescript-eslint+typescript-estree+8.66.0.patch +12 -0
- package/package.d/{vite+8.1.4.patch → vite+8.2.1.patch} +2 -2
- package/package.json +16 -15
- 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 +14 -3
- 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.63.0.patch +0 -12
|
@@ -15,7 +15,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
}
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
19
19
|
value: mod,
|
|
20
20
|
enumerable: true
|
|
21
21
|
}) : target, mod));
|
|
@@ -146,6 +146,7 @@ var ReadableTee = class extends node_stream.Readable {
|
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
148
|
async function sendBufferAsChunks(buffer, chunkSize, sendChunk, creditGate, abortSignal) {
|
|
149
|
+
if (!(Number.isFinite(chunkSize) && chunkSize > 0)) throw new Error("invalid chunk size");
|
|
149
150
|
if (buffer.byteLength === 0) await sendChunk(void 0, void 0, true);
|
|
150
151
|
else for (let i = 0; i < buffer.byteLength; i += chunkSize) {
|
|
151
152
|
if (abortSignal?.aborted) throw abortSignal.reason ?? /* @__PURE__ */ new Error("aborted");
|
|
@@ -157,6 +158,7 @@ async function sendBufferAsChunks(buffer, chunkSize, sendChunk, creditGate, abor
|
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
160
|
async function sendStreamAsChunks(readable, chunkSize, sendChunk, creditGate, abortSignal) {
|
|
161
|
+
if (!(Number.isFinite(chunkSize) && chunkSize > 0)) throw new Error("invalid chunk size");
|
|
160
162
|
let pending;
|
|
161
163
|
for await (const raw of readable) {
|
|
162
164
|
if (abortSignal?.aborted) throw abortSignal.reason ?? /* @__PURE__ */ new Error("aborted");
|
|
@@ -179,11 +181,17 @@ async function sendStreamAsChunks(readable, chunkSize, sendChunk, creditGate, ab
|
|
|
179
181
|
await sendChunk(pending, void 0, true);
|
|
180
182
|
} else await sendChunk(void 0, void 0, true);
|
|
181
183
|
}
|
|
184
|
+
function alignHandlerParams(params, handler) {
|
|
185
|
+
if (typeof handler !== "function") return params;
|
|
186
|
+
const arity = handler.length - 1;
|
|
187
|
+
if (params.length >= arity) return params;
|
|
188
|
+
return [...params, ...Array(arity - params.length).fill(void 0)];
|
|
189
|
+
}
|
|
182
190
|
function makeMutuallyExclusiveFields(obj, f1Name, f2Name, onConsumed) {
|
|
183
191
|
if (!(typeof obj === "object" && obj !== null)) throw new Error("invalid object");
|
|
184
192
|
let consumed;
|
|
185
|
-
|
|
186
|
-
|
|
193
|
+
let f1Value = obj[f1Name];
|
|
194
|
+
let f2Value = obj[f2Name];
|
|
187
195
|
Object.defineProperty(obj, f1Name, {
|
|
188
196
|
get: () => {
|
|
189
197
|
if (consumed === "f2") throw new Error(`field "${f1Name}" is mutually exclusive with field "${f2Name}" and "${f2Name}" was already consumed`);
|
|
@@ -191,7 +199,10 @@ function makeMutuallyExclusiveFields(obj, f1Name, f2Name, onConsumed) {
|
|
|
191
199
|
consumed = "f1";
|
|
192
200
|
return f1Value;
|
|
193
201
|
},
|
|
194
|
-
|
|
202
|
+
set: (value) => {
|
|
203
|
+
f1Value = value;
|
|
204
|
+
},
|
|
205
|
+
enumerable: false,
|
|
195
206
|
configurable: true
|
|
196
207
|
});
|
|
197
208
|
Object.defineProperty(obj, f2Name, {
|
|
@@ -201,7 +212,10 @@ function makeMutuallyExclusiveFields(obj, f1Name, f2Name, onConsumed) {
|
|
|
201
212
|
consumed = "f2";
|
|
202
213
|
return f2Value;
|
|
203
214
|
},
|
|
204
|
-
|
|
215
|
+
set: (value) => {
|
|
216
|
+
f2Value = value;
|
|
217
|
+
},
|
|
218
|
+
enumerable: false,
|
|
205
219
|
configurable: true
|
|
206
220
|
});
|
|
207
221
|
}
|
|
@@ -285,8 +299,10 @@ function ensureError(error, prefix, debug = false) {
|
|
|
285
299
|
} else return new Error(msg);
|
|
286
300
|
}
|
|
287
301
|
function runFinally(isAsync, onfinally, description) {
|
|
288
|
-
if (!onfinally)
|
|
289
|
-
|
|
302
|
+
if (!onfinally) {
|
|
303
|
+
if (isAsync) return Promise.resolve();
|
|
304
|
+
else return;
|
|
305
|
+
}
|
|
290
306
|
let result;
|
|
291
307
|
try {
|
|
292
308
|
result = onfinally();
|
|
@@ -302,8 +318,10 @@ function runFinally(isAsync, onfinally, description) {
|
|
|
302
318
|
return result;
|
|
303
319
|
}
|
|
304
320
|
function runUnroll(isAsync, spool) {
|
|
305
|
-
if (!spool)
|
|
306
|
-
|
|
321
|
+
if (!spool) {
|
|
322
|
+
if (isAsync) return Promise.resolve();
|
|
323
|
+
else return;
|
|
324
|
+
}
|
|
307
325
|
let result = spool.unroll();
|
|
308
326
|
if (!isAsync && result instanceof Promise) throw new Error("spool unroll returned Promise in non-async context");
|
|
309
327
|
if (isAsync && !(result instanceof Promise)) result = Promise.resolve(result);
|
|
@@ -317,9 +335,12 @@ function runSettle(isAsync, pending, spool, onfinally, description) {
|
|
|
317
335
|
} catch (arg) {
|
|
318
336
|
failure = ensureError(arg, description);
|
|
319
337
|
}
|
|
320
|
-
if (pending || failure !== void 0) {
|
|
338
|
+
if (pending !== void 0 || failure !== void 0) {
|
|
321
339
|
runUnroll(false, spool);
|
|
322
|
-
if (
|
|
340
|
+
if (failure !== void 0) {
|
|
341
|
+
if (pending !== void 0) pending.suppressed = failure;
|
|
342
|
+
else throw failure;
|
|
343
|
+
}
|
|
323
344
|
}
|
|
324
345
|
} else return (async () => {
|
|
325
346
|
let failure;
|
|
@@ -328,12 +349,34 @@ function runSettle(isAsync, pending, spool, onfinally, description) {
|
|
|
328
349
|
} catch (arg) {
|
|
329
350
|
failure = ensureError(arg, description);
|
|
330
351
|
}
|
|
331
|
-
if (pending || failure !== void 0) {
|
|
352
|
+
if (pending !== void 0 || failure !== void 0) {
|
|
332
353
|
await runUnroll(true, spool);
|
|
333
|
-
if (
|
|
354
|
+
if (failure !== void 0) {
|
|
355
|
+
if (pending !== void 0) pending.suppressed = failure;
|
|
356
|
+
else throw failure;
|
|
357
|
+
}
|
|
334
358
|
}
|
|
335
359
|
})();
|
|
336
360
|
}
|
|
361
|
+
function runFail(error, spool, onfinally, description) {
|
|
362
|
+
const attach = (arg) => {
|
|
363
|
+
error.suppressed = ensureError(arg, description);
|
|
364
|
+
};
|
|
365
|
+
let result = void 0;
|
|
366
|
+
try {
|
|
367
|
+
result = onfinally?.();
|
|
368
|
+
} catch (arg) {
|
|
369
|
+
attach(arg);
|
|
370
|
+
}
|
|
371
|
+
if (result instanceof Promise) return result.catch(attach).then(() => spool?.unroll()).then(() => {
|
|
372
|
+
throw error;
|
|
373
|
+
});
|
|
374
|
+
const unrolled = spool?.unroll();
|
|
375
|
+
if (unrolled instanceof Promise) return unrolled.then(() => {
|
|
376
|
+
throw error;
|
|
377
|
+
});
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
337
380
|
function run(...args) {
|
|
338
381
|
let description;
|
|
339
382
|
let spool;
|
|
@@ -379,25 +422,18 @@ function run(...args) {
|
|
|
379
422
|
try {
|
|
380
423
|
result = action();
|
|
381
424
|
} 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;
|
|
425
|
+
const error = ensureError(arg, description);
|
|
426
|
+
if (!oncatch) return runFail(error, spool, onfinally, description);
|
|
427
|
+
try {
|
|
428
|
+
result = oncatch(error);
|
|
429
|
+
} catch (arg) {
|
|
430
|
+
return runFail(ensureError(arg, description), spool, onfinally, description);
|
|
394
431
|
}
|
|
395
|
-
|
|
396
|
-
throw error;
|
|
432
|
+
oncatch = void 0;
|
|
397
433
|
}
|
|
398
434
|
if (result instanceof Promise) return result.then(async (result) => {
|
|
399
435
|
if (spool && oncleanup) spool.roll(result, oncleanup);
|
|
400
|
-
await runSettle(true,
|
|
436
|
+
await runSettle(true, void 0, spool, onfinally, description);
|
|
401
437
|
return result;
|
|
402
438
|
}, async (arg) => {
|
|
403
439
|
let error = ensureError(arg, description);
|
|
@@ -407,19 +443,19 @@ function run(...args) {
|
|
|
407
443
|
result = await oncatch(error);
|
|
408
444
|
} catch (arg) {
|
|
409
445
|
error = ensureError(arg, description);
|
|
410
|
-
await runSettle(true,
|
|
446
|
+
await runSettle(true, error, spool, onfinally, description);
|
|
411
447
|
throw error;
|
|
412
448
|
}
|
|
413
449
|
if (spool && oncleanup) spool.roll(result, oncleanup);
|
|
414
|
-
await runSettle(true,
|
|
450
|
+
await runSettle(true, void 0, spool, onfinally, description);
|
|
415
451
|
return result;
|
|
416
452
|
}
|
|
417
|
-
await runSettle(true,
|
|
453
|
+
await runSettle(true, error, spool, onfinally, description);
|
|
418
454
|
throw error;
|
|
419
455
|
});
|
|
420
456
|
else {
|
|
421
457
|
if (spool && oncleanup) spool.roll(result, oncleanup);
|
|
422
|
-
runSettle(false,
|
|
458
|
+
runSettle(false, void 0, spool, onfinally, description);
|
|
423
459
|
return result;
|
|
424
460
|
}
|
|
425
461
|
}
|
|
@@ -430,9 +466,9 @@ var OptionsTrait = class {
|
|
|
430
466
|
this.options = {
|
|
431
467
|
id: "",
|
|
432
468
|
codec: "cbor",
|
|
433
|
-
timeout:
|
|
469
|
+
timeout: 1e4,
|
|
434
470
|
share: "",
|
|
435
|
-
chunkSize:
|
|
471
|
+
chunkSize: 16384,
|
|
436
472
|
chunkCredit: 4,
|
|
437
473
|
topicMake: (name, operation, peerId) => {
|
|
438
474
|
return `${name}/${operation}/${peerId ?? "any"}`;
|
|
@@ -447,6 +483,9 @@ var OptionsTrait = class {
|
|
|
447
483
|
},
|
|
448
484
|
...options
|
|
449
485
|
};
|
|
486
|
+
if (!(Number.isFinite(this.options.timeout) && this.options.timeout > 0)) throw new Error("options: \"timeout\" must be a positive number");
|
|
487
|
+
if (!(Number.isInteger(this.options.chunkSize) && this.options.chunkSize > 0)) throw new Error("options: \"chunkSize\" must be a positive integer");
|
|
488
|
+
if (!(Number.isInteger(this.options.chunkCredit) && this.options.chunkCredit >= 0)) throw new Error("options: \"chunkCredit\" must be a non-negative integer");
|
|
450
489
|
}
|
|
451
490
|
};
|
|
452
491
|
//#endregion
|
|
@@ -959,13 +998,13 @@ var BaseTrait = class extends TraceTrait {
|
|
|
959
998
|
};
|
|
960
999
|
} });
|
|
961
1000
|
}
|
|
962
|
-
this.
|
|
1001
|
+
this._mqtt = mqtt;
|
|
963
1002
|
if (this.options.id === "") {
|
|
964
1003
|
const clientId = mqtt.isFakeProxy ? void 0 : mqtt.options?.clientId;
|
|
965
1004
|
this.options.id = typeof clientId === "string" && clientId !== "" ? clientId : (0, nanoid.nanoid)();
|
|
966
1005
|
}
|
|
967
1006
|
this.log("info", "hooking into MQTT client");
|
|
968
|
-
this.
|
|
1007
|
+
this._messageHandler = (topic, message, packet) => {
|
|
969
1008
|
if (this.destroyed) return;
|
|
970
1009
|
let input;
|
|
971
1010
|
if (this.options.codec === "json") input = message.toString();
|
|
@@ -976,12 +1015,12 @@ var BaseTrait = class extends TraceTrait {
|
|
|
976
1015
|
}
|
|
977
1016
|
this._onMessage(topic, input, packet);
|
|
978
1017
|
};
|
|
979
|
-
this.
|
|
1018
|
+
this._mqtt.on("message", this._messageHandler);
|
|
980
1019
|
}
|
|
981
1020
|
async destroy() {
|
|
982
1021
|
this.destroyed = true;
|
|
983
1022
|
this.log("info", "un-hooking from MQTT client");
|
|
984
|
-
this.
|
|
1023
|
+
this._mqtt.off("message", this._messageHandler);
|
|
985
1024
|
this.onRequest.clear();
|
|
986
1025
|
this.onResponse.clear();
|
|
987
1026
|
}
|
|
@@ -1000,7 +1039,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1000
1039
|
async subscribeTopic(topic, options = {}) {
|
|
1001
1040
|
this.log("info", `subscribing to MQTT topic "${topic}"`);
|
|
1002
1041
|
return new Promise((resolve, reject) => {
|
|
1003
|
-
this.
|
|
1042
|
+
this._mqtt.subscribe(topic, {
|
|
1004
1043
|
qos: 2,
|
|
1005
1044
|
...options
|
|
1006
1045
|
}, (err, granted) => {
|
|
@@ -1018,7 +1057,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1018
1057
|
async unsubscribeTopic(topic) {
|
|
1019
1058
|
this.log("info", `unsubscribing from MQTT topic "${topic}"`);
|
|
1020
1059
|
return new Promise((resolve, reject) => {
|
|
1021
|
-
this.
|
|
1060
|
+
this._mqtt.unsubscribe(topic, (err, _packet) => {
|
|
1022
1061
|
if (err) {
|
|
1023
1062
|
this.error(err, `unsubscribing from MQTT topic "${topic}" failed`);
|
|
1024
1063
|
reject(err);
|
|
@@ -1042,7 +1081,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1042
1081
|
this.log("debug", `publishing to MQTT topic "${topic}"`, { message: messageOnDemand });
|
|
1043
1082
|
return new Promise((resolve, reject) => {
|
|
1044
1083
|
const messageData = typeof message === "string" ? message : Buffer.from(message.buffer, message.byteOffset, message.byteLength);
|
|
1045
|
-
this.
|
|
1084
|
+
this._mqtt.publish(topic, messageData, options, (err) => {
|
|
1046
1085
|
if (err) {
|
|
1047
1086
|
this.error(err, `publishing to MQTT topic "${topic}" failed`);
|
|
1048
1087
|
reject(err);
|
|
@@ -1077,7 +1116,10 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1077
1116
|
return;
|
|
1078
1117
|
}
|
|
1079
1118
|
this.log("debug", `received from MQTT topic "${topic}"`, { message });
|
|
1080
|
-
if (topicMatch.peerId !== void 0 && message.receiver !== void 0 && message.receiver !== topicMatch.peerId)
|
|
1119
|
+
if (topicMatch.peerId !== void 0 && message.receiver !== void 0 && message.receiver !== topicMatch.peerId) {
|
|
1120
|
+
this.log("warning", `receiver mismatch -- dropped message from direct topic "${topic}" (expected "${topicMatch.peerId}", got "${message.receiver}")`);
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1081
1123
|
if (this.msg.isRequest(message)) {
|
|
1082
1124
|
const handler = this.onRequest.get(`${message.type}:${message.name}`);
|
|
1083
1125
|
if (handler !== void 0) Promise.resolve().then(() => {
|
|
@@ -1100,7 +1142,7 @@ var BaseTrait = class extends TraceTrait {
|
|
|
1100
1142
|
//#endregion
|
|
1101
1143
|
//#region dst-stage1/mqtt-plus-subscription.js
|
|
1102
1144
|
var RefCountedSubscription = class {
|
|
1103
|
-
constructor(subscribeFn, unsubscribeFn, lingerMs =
|
|
1145
|
+
constructor(subscribeFn, unsubscribeFn, lingerMs = 3e4) {
|
|
1104
1146
|
this.subscribeFn = subscribeFn;
|
|
1105
1147
|
this.unsubscribeFn = unsubscribeFn;
|
|
1106
1148
|
this.lingerMs = lingerMs;
|
|
@@ -1116,12 +1158,14 @@ var RefCountedSubscription = class {
|
|
|
1116
1158
|
}
|
|
1117
1159
|
decrementCount(topic) {
|
|
1118
1160
|
const count = this.counts.get(topic);
|
|
1119
|
-
if (count !== void 0)
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1161
|
+
if (count !== void 0) {
|
|
1162
|
+
if (count <= 1) {
|
|
1163
|
+
this.counts.delete(topic);
|
|
1164
|
+
return 0;
|
|
1165
|
+
} else {
|
|
1166
|
+
this.counts.set(topic, count - 1);
|
|
1167
|
+
return count - 1;
|
|
1168
|
+
}
|
|
1125
1169
|
}
|
|
1126
1170
|
}
|
|
1127
1171
|
clearCount(topic) {
|
|
@@ -1160,21 +1204,23 @@ var RefCountedSubscription = class {
|
|
|
1160
1204
|
}
|
|
1161
1205
|
}
|
|
1162
1206
|
async unsubscribe(topic) {
|
|
1163
|
-
if (this.decrementCount(topic) === 0)
|
|
1164
|
-
|
|
1165
|
-
|
|
1207
|
+
if (this.decrementCount(topic) === 0) {
|
|
1208
|
+
if (this.lingerMs > 0 && !topic.startsWith("$share/")) {
|
|
1209
|
+
const timer = setTimeout(() => {
|
|
1210
|
+
this.lingers.delete(topic);
|
|
1211
|
+
const promise = this.unsubscribeFn(topic).catch(() => {}).finally(() => {
|
|
1212
|
+
this.unsubbing.delete(topic);
|
|
1213
|
+
});
|
|
1214
|
+
this.unsubbing.set(topic, promise);
|
|
1215
|
+
}, this.lingerMs);
|
|
1216
|
+
this.lingers.set(topic, timer);
|
|
1217
|
+
} else {
|
|
1166
1218
|
const promise = this.unsubscribeFn(topic).catch(() => {}).finally(() => {
|
|
1167
1219
|
this.unsubbing.delete(topic);
|
|
1168
1220
|
});
|
|
1169
1221
|
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;
|
|
1222
|
+
await promise;
|
|
1223
|
+
}
|
|
1178
1224
|
}
|
|
1179
1225
|
}
|
|
1180
1226
|
async flush() {
|
|
@@ -1443,7 +1489,7 @@ var EventTrait = class extends AuthTrait {
|
|
|
1443
1489
|
this.log("warning", `event name mismatch -- dropped request for "${name}" (topic: "${topicName}", payload: "${request.name}")`, { requestId });
|
|
1444
1490
|
return;
|
|
1445
1491
|
}
|
|
1446
|
-
const params = request.params ?? [];
|
|
1492
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
1447
1493
|
if (this.eventControllers.has(requestId)) {
|
|
1448
1494
|
this.log("warning", `duplicate event request id -- dropped request for event "${name}"`, { requestId });
|
|
1449
1495
|
return;
|
|
@@ -1567,7 +1613,7 @@ var ServiceTrait = class extends EventTrait {
|
|
|
1567
1613
|
if (request.receiver && request.receiver !== this.options.id) return;
|
|
1568
1614
|
const requestId = request.id;
|
|
1569
1615
|
const senderId = request.sender;
|
|
1570
|
-
const params = request.params ?? [];
|
|
1616
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
1571
1617
|
if (senderId === void 0 || senderId === "") {
|
|
1572
1618
|
this.error(/* @__PURE__ */ new Error("invalid request: missing sender"));
|
|
1573
1619
|
return;
|
|
@@ -1671,7 +1717,9 @@ var ServiceTrait = class extends EventTrait {
|
|
|
1671
1717
|
const settle = () => {
|
|
1672
1718
|
if (settled) return false;
|
|
1673
1719
|
settled = true;
|
|
1674
|
-
spool.unroll()
|
|
1720
|
+
spool.unroll(false)?.catch((err) => {
|
|
1721
|
+
this.error(ensureError(err, `cleanup after call of service "${name}" failed`));
|
|
1722
|
+
});
|
|
1675
1723
|
return true;
|
|
1676
1724
|
};
|
|
1677
1725
|
const promise = new Promise((resolve, reject) => {
|
|
@@ -1778,7 +1826,7 @@ var SourceTrait = class extends ServiceTrait {
|
|
|
1778
1826
|
this.onRequest.set(`source-fetch-request:${name}`, async (request, topicName) => {
|
|
1779
1827
|
if (request.receiver && request.receiver !== this.options.id) return;
|
|
1780
1828
|
const requestId = request.id;
|
|
1781
|
-
const params = request.params ?? [];
|
|
1829
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
1782
1830
|
const sender = request.sender;
|
|
1783
1831
|
const receiver = request.receiver;
|
|
1784
1832
|
const reqSpool = new Spool();
|
|
@@ -1831,11 +1879,16 @@ var SourceTrait = class extends ServiceTrait {
|
|
|
1831
1879
|
if (current.size === 0) this.sourceRequests.delete(name);
|
|
1832
1880
|
}
|
|
1833
1881
|
});
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1882
|
+
const noopError = () => {};
|
|
1883
|
+
const destroyStream = () => {
|
|
1884
|
+
if (info.stream instanceof node_stream.Readable && !info.stream.destroyed) {
|
|
1885
|
+
info.stream.on("error", noopError);
|
|
1886
|
+
info.stream.destroy(ensureError(abortSignal.reason));
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
abortSignal.addEventListener("abort", destroyStream, { once: true });
|
|
1837
1890
|
reqSpool.roll(() => {
|
|
1838
|
-
if (abortSignal.aborted
|
|
1891
|
+
if (abortSignal.aborted) destroyStream();
|
|
1839
1892
|
});
|
|
1840
1893
|
let abortReject;
|
|
1841
1894
|
const abortPromise = new Promise((_resolve, reject) => {
|
|
@@ -1982,7 +2035,7 @@ var SourceTrait = class extends ServiceTrait {
|
|
|
1982
2035
|
const sourceNameMismatchError = (kind, actualName) => /* @__PURE__ */ new Error(`${kind} name mismatch (expected "${name}", got "${actualName}")`);
|
|
1983
2036
|
await this.subscribeTopicAndSpool(spool, responseTopic, { qos: options.qos ?? 2 });
|
|
1984
2037
|
const chunkCredit = this.options.chunkCredit;
|
|
1985
|
-
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize :
|
|
2038
|
+
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize : 16384;
|
|
1986
2039
|
let chunksReceived = 0;
|
|
1987
2040
|
let creditGranted = chunkCredit;
|
|
1988
2041
|
let responderId = receiver;
|
|
@@ -2220,7 +2273,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2220
2273
|
this.onRequest.set(`sink-push-request:${name}`, async (request, topicName) => {
|
|
2221
2274
|
if (request.receiver && request.receiver !== this.options.id) return;
|
|
2222
2275
|
const requestId = request.id;
|
|
2223
|
-
const params = request.params ?? [];
|
|
2276
|
+
const params = alignHandlerParams(request.params ?? [], callback);
|
|
2224
2277
|
const sender = request.sender;
|
|
2225
2278
|
const receiver = request.receiver;
|
|
2226
2279
|
const reqSpool = new Spool();
|
|
@@ -2281,7 +2334,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2281
2334
|
chunksReceived: 0,
|
|
2282
2335
|
creditGranted: chunkCredit
|
|
2283
2336
|
} : void 0;
|
|
2284
|
-
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize :
|
|
2337
|
+
const maxBufferedBytes = chunkCredit > 0 ? chunkCredit * this.options.chunkSize : 16384;
|
|
2285
2338
|
let streamEnded = false;
|
|
2286
2339
|
const pushTimerId = `sink-push-recv:${requestId}`;
|
|
2287
2340
|
const refreshPushTimeout = () => this.timerRefresh(pushTimerId, () => {
|
|
@@ -2511,8 +2564,12 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2511
2564
|
});
|
|
2512
2565
|
if (data instanceof node_stream.Readable) {
|
|
2513
2566
|
const stream = data;
|
|
2567
|
+
const noopError = () => {};
|
|
2514
2568
|
abortSignal.addEventListener("abort", () => {
|
|
2515
|
-
if (!stream.destroyed)
|
|
2569
|
+
if (!stream.destroyed) {
|
|
2570
|
+
stream.on("error", noopError);
|
|
2571
|
+
stream.destroy(ensureError(abortSignal.reason));
|
|
2572
|
+
}
|
|
2516
2573
|
}, { once: true });
|
|
2517
2574
|
}
|
|
2518
2575
|
const pushTimerId = `sink-push-send:${requestId}`;
|
|
@@ -2546,18 +2603,21 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2546
2603
|
pushFinalizeReject = reject;
|
|
2547
2604
|
});
|
|
2548
2605
|
pushFinalize.catch(() => {});
|
|
2606
|
+
const failPush = (error) => {
|
|
2607
|
+
abortController.abort(error);
|
|
2608
|
+
if (!pushAcked) {
|
|
2609
|
+
pushInitialSettled = true;
|
|
2610
|
+
pushInitialReject(error);
|
|
2611
|
+
} else if (!pushFinalized) {
|
|
2612
|
+
pushFinalized = true;
|
|
2613
|
+
pushFinalizeReject(error);
|
|
2614
|
+
}
|
|
2615
|
+
};
|
|
2549
2616
|
const lockResponder = (kind, sender) => {
|
|
2550
2617
|
if (sender === void 0 || sender === "") {
|
|
2551
2618
|
const error = /* @__PURE__ */ new Error(`received ${kind} without sender`);
|
|
2552
2619
|
remoteErrorObject = error;
|
|
2553
|
-
|
|
2554
|
-
if (!pushAcked) {
|
|
2555
|
-
pushInitialSettled = true;
|
|
2556
|
-
pushInitialReject(error);
|
|
2557
|
-
} else if (!pushFinalized) {
|
|
2558
|
-
pushFinalized = true;
|
|
2559
|
-
pushFinalizeReject(error);
|
|
2560
|
-
}
|
|
2620
|
+
failPush(error);
|
|
2561
2621
|
return false;
|
|
2562
2622
|
}
|
|
2563
2623
|
if (responderId === void 0) responderId = sender;
|
|
@@ -2575,37 +2635,25 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2575
2635
|
if (response.name !== name) {
|
|
2576
2636
|
const error = /* @__PURE__ */ new Error(`sink response name mismatch (expected "${name}", got "${response.name}")`);
|
|
2577
2637
|
remoteErrorObject = error;
|
|
2578
|
-
|
|
2579
|
-
if (!pushAcked) {
|
|
2580
|
-
pushInitialSettled = true;
|
|
2581
|
-
pushInitialReject(error);
|
|
2582
|
-
} else if (!pushFinalized) {
|
|
2583
|
-
pushFinalized = true;
|
|
2584
|
-
pushFinalizeReject(error);
|
|
2585
|
-
}
|
|
2638
|
+
failPush(error);
|
|
2586
2639
|
return;
|
|
2587
2640
|
}
|
|
2588
2641
|
if (!lockResponder("sink response", response.sender)) return;
|
|
2589
2642
|
if (response.error) {
|
|
2590
2643
|
const error = new Error(response.error);
|
|
2591
2644
|
remoteErrorObject = error;
|
|
2592
|
-
|
|
2593
|
-
if (!pushAcked) {
|
|
2594
|
-
pushInitialSettled = true;
|
|
2595
|
-
pushInitialReject(error);
|
|
2596
|
-
} else if (!pushFinalized) {
|
|
2597
|
-
pushFinalized = true;
|
|
2598
|
-
pushFinalizeReject(error);
|
|
2599
|
-
}
|
|
2645
|
+
failPush(error);
|
|
2600
2646
|
} else if (!pushAcked) {
|
|
2601
2647
|
initialCredit = response.credit;
|
|
2602
2648
|
pushAcked = true;
|
|
2603
2649
|
pushInitialSettled = true;
|
|
2604
2650
|
pushInitialResolve();
|
|
2605
|
-
} else if (!pushFinalized)
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2651
|
+
} else if (!pushFinalized) {
|
|
2652
|
+
if (pushDataComplete) {
|
|
2653
|
+
pushFinalized = true;
|
|
2654
|
+
pushFinalizeResolve();
|
|
2655
|
+
} else pushTerminalReceived = true;
|
|
2656
|
+
}
|
|
2609
2657
|
});
|
|
2610
2658
|
spool.roll(() => {
|
|
2611
2659
|
this.onResponse.delete(`sink-push-response:${requestId}`);
|
|
@@ -2614,28 +2662,14 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2614
2662
|
if (response.name !== name) {
|
|
2615
2663
|
const error = /* @__PURE__ */ new Error(`sink credit name mismatch (expected "${name}", got "${response.name}")`);
|
|
2616
2664
|
remoteErrorObject = error;
|
|
2617
|
-
|
|
2618
|
-
if (!pushAcked) {
|
|
2619
|
-
pushInitialSettled = true;
|
|
2620
|
-
pushInitialReject(error);
|
|
2621
|
-
} else if (!pushFinalized) {
|
|
2622
|
-
pushFinalized = true;
|
|
2623
|
-
pushFinalizeReject(error);
|
|
2624
|
-
}
|
|
2665
|
+
failPush(error);
|
|
2625
2666
|
return;
|
|
2626
2667
|
}
|
|
2627
2668
|
if (!lockResponder("sink credit", response.sender)) return;
|
|
2628
2669
|
if (response.credit === 0) {
|
|
2629
2670
|
cancelledByReceiver = true;
|
|
2630
2671
|
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
|
-
}
|
|
2672
|
+
failPush(error);
|
|
2639
2673
|
return;
|
|
2640
2674
|
}
|
|
2641
2675
|
if (creditGate !== void 0) {
|
|
@@ -2644,11 +2678,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2644
2678
|
} else if (pushAcked && initialCredit === void 0) {
|
|
2645
2679
|
const error = /* @__PURE__ */ new Error(`push to sink "${name}" received unsolicited credit (credit-flow disabled)`);
|
|
2646
2680
|
remoteErrorObject = error;
|
|
2647
|
-
|
|
2648
|
-
if (!pushFinalized) {
|
|
2649
|
-
pushFinalized = true;
|
|
2650
|
-
pushFinalizeReject(error);
|
|
2651
|
-
}
|
|
2681
|
+
failPush(error);
|
|
2652
2682
|
} else pendingCredit += response.credit;
|
|
2653
2683
|
});
|
|
2654
2684
|
spool.roll(() => {
|
|
@@ -2735,7 +2765,7 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2735
2765
|
}
|
|
2736
2766
|
} catch {}
|
|
2737
2767
|
if (pushAcked && !remoteErrorObject) await new Promise((resolve) => {
|
|
2738
|
-
|
|
2768
|
+
setTimeout(resolve, 0);
|
|
2739
2769
|
});
|
|
2740
2770
|
if (remoteErrorObject) throw remoteErrorObject;
|
|
2741
2771
|
throw err;
|
|
@@ -2746,6 +2776,22 @@ var SinkTrait = class extends SourceTrait {
|
|
|
2746
2776
|
};
|
|
2747
2777
|
//#endregion
|
|
2748
2778
|
//#region dst-stage1/mqtt-plus.js
|
|
2749
|
-
var MQTTp = class extends SinkTrait {
|
|
2779
|
+
var MQTTp = class extends SinkTrait {
|
|
2780
|
+
static {
|
|
2781
|
+
this.VERSION = "1.4";
|
|
2782
|
+
}
|
|
2783
|
+
static {
|
|
2784
|
+
this.MIN_VERSION = "1.4";
|
|
2785
|
+
}
|
|
2786
|
+
static {
|
|
2787
|
+
this.version = version;
|
|
2788
|
+
}
|
|
2789
|
+
static {
|
|
2790
|
+
this.minVersion = minVersion;
|
|
2791
|
+
}
|
|
2792
|
+
static {
|
|
2793
|
+
this.versionToNum = versionToNum;
|
|
2794
|
+
}
|
|
2795
|
+
};
|
|
2750
2796
|
//#endregion
|
|
2751
2797
|
module.exports = MQTTp;
|