mqtt-plus 1.4.25 → 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.
Files changed (67) hide show
  1. package/.ase/config.yaml +1 -0
  2. package/.ase/service.log +34 -0
  3. package/.ase/service.yaml +1 -1
  4. package/.ase/task/TASK-P18.md +1 -1
  5. package/.ase/task/TASK-P21.md +1 -1
  6. package/.claude/settings.local.json +4 -1
  7. package/AGENTS.md +1 -1
  8. package/CHANGELOG.md +24 -5
  9. package/README.md +2 -2
  10. package/doc/mqtt-plus-broker-setup.md +1 -1
  11. package/doc/mqtt-plus-comm.md +3 -3
  12. package/doc/mqtt-plus-internals.md +6 -0
  13. package/dst-stage1/mqtt-plus-base.d.ts +2 -2
  14. package/dst-stage1/mqtt-plus-base.js +13 -10
  15. package/dst-stage1/mqtt-plus-error.js +54 -28
  16. package/dst-stage1/mqtt-plus-event.js +3 -1
  17. package/dst-stage1/mqtt-plus-options.js +7 -0
  18. package/dst-stage1/mqtt-plus-service.js +9 -6
  19. package/dst-stage1/mqtt-plus-sink.js +27 -54
  20. package/dst-stage1/mqtt-plus-source.js +13 -9
  21. package/dst-stage1/mqtt-plus-util.d.ts +1 -0
  22. package/dst-stage1/mqtt-plus-util.js +25 -4
  23. package/dst-stage1/mqtt-plus.d.ts +1 -1
  24. package/dst-stage1/mqtt-plus.js +2 -0
  25. package/dst-stage2/mqtt-plus.cjs.cjs +164 -123
  26. package/dst-stage2/mqtt-plus.esm.js +154 -122
  27. package/dst-stage2/mqtt-plus.umd.js +11 -11
  28. package/etc/stx.conf +3 -2
  29. package/package.d/@typescript-eslint+typescript-estree+8.66.0.patch +12 -0
  30. package/package.d/{vite+8.1.4.patch → vite+8.2.1.patch} +2 -2
  31. package/package.json +16 -15
  32. package/src/mqtt-plus-base.ts +15 -12
  33. package/src/mqtt-plus-error.ts +65 -33
  34. package/src/mqtt-plus-event.ts +2 -1
  35. package/src/mqtt-plus-options.ts +8 -0
  36. package/src/mqtt-plus-service.ts +9 -6
  37. package/src/mqtt-plus-sink.ts +28 -54
  38. package/src/mqtt-plus-source.ts +13 -9
  39. package/src/mqtt-plus-util.ts +27 -4
  40. package/src/mqtt-plus.ts +3 -1
  41. package/tst/mqtt-plus-0-fixture.ts +1 -0
  42. package/tst/mqtt-plus-2-event.spec.ts +25 -0
  43. package/tst/mqtt-plus-4-sink.spec.ts +23 -0
  44. package/tst/mqtt-plus-5-source.spec.ts +26 -0
  45. package/tst/mqtt-plus-6-misc.spec.ts +58 -0
  46. package/tst/mqtt-plus-8-run.spec.ts +60 -0
  47. package/dst-stage1/mqtt-plus-api.js.map +0 -1
  48. package/dst-stage1/mqtt-plus-auth.js.map +0 -1
  49. package/dst-stage1/mqtt-plus-base.js.map +0 -1
  50. package/dst-stage1/mqtt-plus-codec.js.map +0 -1
  51. package/dst-stage1/mqtt-plus-encode.js.map +0 -1
  52. package/dst-stage1/mqtt-plus-error.js.map +0 -1
  53. package/dst-stage1/mqtt-plus-event.js.map +0 -1
  54. package/dst-stage1/mqtt-plus-info.js.map +0 -1
  55. package/dst-stage1/mqtt-plus-meta.js.map +0 -1
  56. package/dst-stage1/mqtt-plus-msg.js.map +0 -1
  57. package/dst-stage1/mqtt-plus-options.js.map +0 -1
  58. package/dst-stage1/mqtt-plus-service.js.map +0 -1
  59. package/dst-stage1/mqtt-plus-sink.js.map +0 -1
  60. package/dst-stage1/mqtt-plus-source.js.map +0 -1
  61. package/dst-stage1/mqtt-plus-subscription.js.map +0 -1
  62. package/dst-stage1/mqtt-plus-timer.js.map +0 -1
  63. package/dst-stage1/mqtt-plus-trace.js.map +0 -1
  64. package/dst-stage1/mqtt-plus-util.js.map +0 -1
  65. package/dst-stage1/mqtt-plus-version.js.map +0 -1
  66. package/dst-stage1/mqtt-plus.js.map +0 -1
  67. package/package.d/@typescript-eslint+typescript-estree+8.63.0.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
- const f1Value = obj[f1Name];
186
- const f2Value = obj[f2Name];
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
- enumerable: true,
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
- enumerable: true,
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) if (isAsync) return Promise.resolve();
289
- else return;
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) if (isAsync) return Promise.resolve();
306
- else return;
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 (!pending && failure !== void 0) throw failure;
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 (!pending && failure !== void 0) throw failure;
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
- let error = ensureError(arg, description);
383
- if (oncatch) {
384
- try {
385
- result = oncatch(error);
386
- } catch (arg) {
387
- error = ensureError(arg, description);
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
- runSettle(false, true, spool, onfinally, description);
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, false, spool, onfinally, description);
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, true, spool, onfinally, description);
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, false, spool, onfinally, description);
454
+ await runSettle(true, void 0, spool, onfinally, description);
415
455
  return result;
416
456
  }
417
- await runSettle(true, true, spool, onfinally, description);
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, false, spool, onfinally, description);
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: 10 * 1e3,
473
+ timeout: 1e4,
434
474
  share: "",
435
- chunkSize: 16 * 1024,
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.mqtt = mqtt;
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.messageHandler = (topic, message, packet) => {
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.mqtt.on("message", this.messageHandler);
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.mqtt.off("message", this.messageHandler);
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.mqtt.subscribe(topic, {
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.mqtt.unsubscribe(topic, (err, _packet) => {
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.mqtt.publish(topic, messageData, options, (err) => {
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) this.log("warning", `receiver mismatch on direct topic "${topic}" (expected "${topicMatch.peerId}", got "${message.receiver}")`);
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 = 30 * 1e3) {
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) if (count <= 1) {
1120
- this.counts.delete(topic);
1121
- return 0;
1122
- } else {
1123
- this.counts.set(topic, count - 1);
1124
- return count - 1;
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,21 +1210,23 @@ var RefCountedSubscription = class {
1160
1210
  }
1161
1211
  }
1162
1212
  async unsubscribe(topic) {
1163
- if (this.decrementCount(topic) === 0) if (this.lingerMs > 0 && !topic.startsWith("$share/")) {
1164
- const timer = setTimeout(() => {
1165
- this.lingers.delete(topic);
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
- }, this.lingerMs);
1171
- this.lingers.set(topic, timer);
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() {
@@ -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
- abortSignal.addEventListener("abort", () => {
1835
- if (info.stream instanceof node_stream.Readable && !info.stream.destroyed) info.stream.destroy(ensureError(abortSignal.reason));
1836
- }, { once: true });
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 && info.stream instanceof node_stream.Readable && !info.stream.destroyed) info.stream.destroy(ensureError(abortSignal.reason));
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 : 16 * 1024;
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 : 16 * 1024;
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) stream.destroy(ensureError(abortSignal.reason));
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
- abortController.abort(error);
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
- abortController.abort(error);
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
- abortController.abort(error);
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) if (pushDataComplete) {
2606
- pushFinalized = true;
2607
- pushFinalizeResolve();
2608
- } else pushTerminalReceived = true;
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
- abortController.abort(error);
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
- abortController.abort(error);
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
- abortController.abort(error);
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
- setImmediate(resolve);
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
- module.exports = MQTTp;
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;