node-opcua-client 2.178.0 → 2.180.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/alarms_and_conditions/client_alarm_tools.js +7 -5
  2. package/dist/alarms_and_conditions/client_alarm_tools.js.map +1 -1
  3. package/dist/alarms_and_conditions/client_tools.js +38 -28
  4. package/dist/alarms_and_conditions/client_tools.js.map +1 -1
  5. package/dist/client_base.js.map +1 -1
  6. package/dist/client_monitored_item.d.ts +1 -1
  7. package/dist/client_monitored_item.js +4 -2
  8. package/dist/client_monitored_item.js.map +1 -1
  9. package/dist/client_monitored_item_group.d.ts +4 -3
  10. package/dist/client_monitored_item_group.js +8 -5
  11. package/dist/client_monitored_item_group.js.map +1 -1
  12. package/dist/client_monitored_item_toolbox.js +4 -2
  13. package/dist/client_monitored_item_toolbox.js.map +1 -1
  14. package/dist/client_session.d.ts +9 -2
  15. package/dist/client_session_keepalive_manager.d.ts +1 -1
  16. package/dist/client_session_keepalive_manager.js +50 -29
  17. package/dist/client_session_keepalive_manager.js.map +1 -1
  18. package/dist/client_subscription.d.ts +2 -2
  19. package/dist/client_subscription.js +3 -1
  20. package/dist/client_subscription.js.map +1 -1
  21. package/dist/common.d.ts +3 -3
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/opcua_client.js +1 -0
  26. package/dist/opcua_client.js.map +1 -1
  27. package/dist/private/client_base_impl.js +125 -65
  28. package/dist/private/client_base_impl.js.map +1 -1
  29. package/dist/private/client_monitored_item_group_impl.d.ts +1 -0
  30. package/dist/private/client_monitored_item_group_impl.js +6 -8
  31. package/dist/private/client_monitored_item_group_impl.js.map +1 -1
  32. package/dist/private/client_monitored_item_impl.js +0 -4
  33. package/dist/private/client_monitored_item_impl.js.map +1 -1
  34. package/dist/private/client_publish_engine.js +62 -28
  35. package/dist/private/client_publish_engine.js.map +1 -1
  36. package/dist/private/client_session_impl.d.ts +49 -17
  37. package/dist/private/client_session_impl.js +240 -143
  38. package/dist/private/client_session_impl.js.map +1 -1
  39. package/dist/private/client_subscription_impl.js +15 -12
  40. package/dist/private/client_subscription_impl.js.map +1 -1
  41. package/dist/private/i_private_client.d.ts +1 -1
  42. package/dist/private/opcua_client_impl.js +12 -10
  43. package/dist/private/opcua_client_impl.js.map +1 -1
  44. package/dist/private/reconnection/client_publish_engine_reconnection.js +17 -7
  45. package/dist/private/reconnection/client_publish_engine_reconnection.js.map +1 -1
  46. package/dist/private/reconnection/client_subscription_reconnection.js +11 -7
  47. package/dist/private/reconnection/client_subscription_reconnection.js.map +1 -1
  48. package/dist/private/reconnection/reconnection.js +31 -14
  49. package/dist/private/reconnection/reconnection.js.map +1 -1
  50. package/dist/reverse/client_reverse_connect.js.map +1 -1
  51. package/dist/tools/findservers.js.map +1 -1
  52. package/dist/tools/read_history_server_capabilities.d.ts +2 -1
  53. package/dist/tools/read_history_server_capabilities.js +6 -3
  54. package/dist/tools/read_history_server_capabilities.js.map +1 -1
  55. package/package.json +50 -50
  56. package/source/alarms_and_conditions/client_alarm_tools.ts +10 -8
  57. package/source/alarms_and_conditions/client_tools.ts +71 -30
  58. package/source/client_base.ts +0 -1
  59. package/source/client_monitored_item.ts +10 -9
  60. package/source/client_monitored_item_base.ts +2 -8
  61. package/source/client_monitored_item_group.ts +13 -10
  62. package/source/client_monitored_item_toolbox.ts +4 -2
  63. package/source/client_session.ts +10 -3
  64. package/source/client_session_keepalive_manager.ts +72 -55
  65. package/source/client_subscription.ts +6 -3
  66. package/source/common.ts +4 -0
  67. package/source/index.ts +1 -1
  68. package/source/opcua_client.ts +1 -0
  69. package/source/private/client_base_impl.ts +179 -102
  70. package/source/private/client_monitored_item_group_impl.ts +17 -18
  71. package/source/private/client_monitored_item_impl.ts +0 -4
  72. package/source/private/client_publish_engine.ts +78 -40
  73. package/source/private/client_session_impl.ts +393 -236
  74. package/source/private/client_subscription_impl.ts +20 -25
  75. package/source/private/i_private_client.ts +1 -1
  76. package/source/private/opcua_client_impl.ts +13 -10
  77. package/source/private/reconnection/client_publish_engine_reconnection.ts +22 -21
  78. package/source/private/reconnection/client_subscription_reconnection.ts +12 -8
  79. package/source/private/reconnection/reconnection.ts +35 -18
  80. package/source/reverse/client_reverse_connect.ts +11 -3
  81. package/source/tools/findservers.ts +0 -1
  82. package/source/tools/read_history_server_capabilities.ts +9 -7
@@ -7,8 +7,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  };
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.ClientSessionImpl = void 0;
10
+ const node_events_1 = require("node:events");
10
11
  const chalk_1 = __importDefault(require("chalk"));
11
- const events_1 = require("events");
12
12
  const node_opcua_assert_1 = require("node-opcua-assert");
13
13
  const node_opcua_client_dynamic_extension_object_1 = require("node-opcua-client-dynamic-extension-object");
14
14
  const node_opcua_data_model_1 = require("node-opcua-data-model");
@@ -34,11 +34,11 @@ const client_session_keepalive_manager_1 = require("../client_session_keepalive_
34
34
  const client_publish_engine_1 = require("./client_publish_engine");
35
35
  const client_subscription_impl_1 = require("./client_subscription_impl");
36
36
  const reconnection_1 = require("./reconnection/reconnection");
37
- const helpAPIChange = process.env.DEBUG && process.env.DEBUG.match(/API/);
37
+ const helpAPIChange = process.env.DEBUG?.match(/API/);
38
38
  const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
39
39
  const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
40
40
  const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
41
- const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
41
+ const _errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
42
42
  let pendingTransactionMessageDisplayed = false;
43
43
  function coerceBrowseDescription(data) {
44
44
  if (typeof data === "string" || data instanceof node_opcua_nodeid_1.NodeId) {
@@ -52,9 +52,10 @@ function coerceBrowseDescription(data) {
52
52
  });
53
53
  }
54
54
  else {
55
- data.nodeId = (0, node_opcua_nodeid_1.resolveNodeId)(data.nodeId);
56
- data.referenceTypeId = data.referenceTypeId ? (0, node_opcua_nodeid_1.resolveNodeId)(data.referenceTypeId) : null;
57
- return new node_opcua_service_browse_1.BrowseDescription(data);
55
+ const options = data;
56
+ options.nodeId = (0, node_opcua_nodeid_1.resolveNodeId)(options.nodeId);
57
+ options.referenceTypeId = options.referenceTypeId ? (0, node_opcua_nodeid_1.resolveNodeId)(options.referenceTypeId) : null;
58
+ return new node_opcua_service_browse_1.BrowseDescription(options);
58
59
  }
59
60
  }
60
61
  function coerceReadValueId(node) {
@@ -72,10 +73,30 @@ function coerceReadValueId(node) {
72
73
  }
73
74
  }
74
75
  const emptyUint32Array = new Uint32Array(0);
76
+ /**
77
+ * attach the server side diagnostics to an error, so that a caller can inspect them without
78
+ * having to know how the channel delivered the failure.
79
+ *
80
+ * For a ServiceFault there is no `response` argument at all - the channel moved the decoded
81
+ * fault onto `err.response` - so fall back to it, otherwise the diagnostics of the most
82
+ * interesting case would always be dropped.
83
+ */
84
+ function annotateWithDiagnostics(err, response) {
85
+ const annotatedError = err;
86
+ const source = response ?? annotatedError.response;
87
+ if (source?.responseHeader.serviceDiagnostics) {
88
+ annotatedError.serviceDiagnostics = source.responseHeader.serviceDiagnostics;
89
+ }
90
+ const responseWithDiagnosticInfos = source;
91
+ if (responseWithDiagnosticInfos?.diagnosticInfos) {
92
+ annotatedError.diagnosticsInfo = responseWithDiagnosticInfos.diagnosticInfos;
93
+ }
94
+ return annotatedError;
95
+ }
75
96
  /**
76
97
  * @class ClientSession
77
98
  */
78
- class ClientSessionImpl extends events_1.EventEmitter {
99
+ class ClientSessionImpl extends node_events_1.EventEmitter {
79
100
  static reconnectingElement = new WeakMap();
80
101
  timeout;
81
102
  authenticationToken;
@@ -120,6 +141,9 @@ class ClientSessionImpl extends events_1.EventEmitter {
120
141
  this.timeout = 0;
121
142
  }
122
143
  getTransportSettings() {
144
+ if (!this._client) {
145
+ throw new Error("session has been closed - no transport settings available");
146
+ }
123
147
  return this._client.getTransportSettings();
124
148
  }
125
149
  /**
@@ -128,6 +152,9 @@ class ClientSessionImpl extends events_1.EventEmitter {
128
152
  * @type {EndpointDescription}
129
153
  */
130
154
  get endpoint() {
155
+ if (!this._client?.endpoint) {
156
+ throw new Error("session has been closed - no endpoint available");
157
+ }
131
158
  return this._client.endpoint;
132
159
  }
133
160
  get subscriptionCount() {
@@ -163,18 +190,19 @@ class ClientSessionImpl extends events_1.EventEmitter {
163
190
  };
164
191
  if (!this._client || !this.userIdentityInfo) {
165
192
  warningLog("changeUser: invalid session");
166
- return callback(null, node_opcua_status_code_1.StatusCodes.BadInternalError);
193
+ return callback?.(null, node_opcua_status_code_1.StatusCodes.BadInternalError);
167
194
  }
168
195
  const old_userIdentity = this.userIdentityInfo;
169
- this._client._activateSession(this, userIdentityInfo, (err1, session2) => {
196
+ this._client._activateSession(this, userIdentityInfo, (err1, _session2) => {
170
197
  if (err1) {
171
198
  this.userIdentityInfo = old_userIdentity;
172
199
  warningLog("activate session error = ", err1.message);
173
- return callback(null, node_opcua_status_code_1.StatusCodes.BadUserAccessDenied);
200
+ return callback?.(null, node_opcua_status_code_1.StatusCodes.BadUserAccessDenied);
174
201
  }
175
202
  this.userIdentityInfo = userIdentityInfo;
176
- callback(null, node_opcua_status_code_1.StatusCodes.Good);
203
+ callback?.(null, node_opcua_status_code_1.StatusCodes.Good);
177
204
  });
205
+ return undefined;
178
206
  }
179
207
  /**
180
208
  * @internal
@@ -185,13 +213,13 @@ class ClientSessionImpl extends events_1.EventEmitter {
185
213
  const isArray = Array.isArray(arg0);
186
214
  const callback = args[1];
187
215
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
188
- (0, node_opcua_assert_1.assert)(isFinite(this.requestedMaxReferencesPerNode));
216
+ (0, node_opcua_assert_1.assert)(Number.isFinite(this.requestedMaxReferencesPerNode));
189
217
  const nodesToBrowse = (isArray ? arg0 : [arg0]).map(coerceBrowseDescription);
190
218
  const request = new node_opcua_service_browse_1.BrowseRequest({
191
219
  nodesToBrowse,
192
220
  requestedMaxReferencesPerNode: this.requestedMaxReferencesPerNode
193
221
  });
194
- this.performMessageTransaction(request, (err, response) => {
222
+ return this.performMessageTransaction(request, (err, response) => {
195
223
  if (err) {
196
224
  return callback(err);
197
225
  }
@@ -208,8 +236,8 @@ class ClientSessionImpl extends events_1.EventEmitter {
208
236
  warningLog(chalk_1.default.yellow("warning") +
209
237
  " BrowseResponse : the server didn't take into" +
210
238
  " account our requestedMaxReferencesPerNode ");
211
- warningLog(" this.requestedMaxReferencesPerNode= " + this.requestedMaxReferencesPerNode);
212
- warningLog(" got " + r.references.length + "for " + nodesToBrowse[i].nodeId.toString());
239
+ warningLog(` this.requestedMaxReferencesPerNode= ${this.requestedMaxReferencesPerNode}`);
240
+ warningLog(` got ${r.references.length}for ${nodesToBrowse[i].nodeId.toString()}`);
213
241
  warningLog(" continuationPoint ", r.continuationPoint);
214
242
  }
215
243
  }
@@ -232,7 +260,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
232
260
  continuationPoints,
233
261
  releaseContinuationPoints
234
262
  });
235
- this.performMessageTransaction(request, (err, response) => {
263
+ return this.performMessageTransaction(request, (err, response) => {
236
264
  /* c8 ignore next */
237
265
  if (err) {
238
266
  return callback(err);
@@ -263,7 +291,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
263
291
  nodesToRead,
264
292
  timestampsToReturn: node_opcua_service_read_1.TimestampsToReturn.Neither
265
293
  });
266
- this.performMessageTransaction(request, (err, response) => {
294
+ return this.performMessageTransaction(request, (err, response) => {
267
295
  /* c8 ignore next */
268
296
  if (err) {
269
297
  return callback(err);
@@ -294,9 +322,10 @@ class ClientSessionImpl extends events_1.EventEmitter {
294
322
  callback = args[4];
295
323
  }
296
324
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
325
+ const cb = callback;
297
326
  // adjust parameters
298
327
  options.numValuesPerNode = options.numValuesPerNode || 0;
299
- options.returnBounds = options.returnBounds || options.returnBounds === undefined ? true : false;
328
+ options.returnBounds = !!(options.returnBounds || options.returnBounds === undefined);
300
329
  options.isReadModified = options.isReadModified || false;
301
330
  options.timestampsToReturn = options.timestampsToReturn ?? node_opcua_service_read_1.TimestampsToReturn.Both;
302
331
  const arg0 = args[0];
@@ -331,18 +360,18 @@ class ClientSessionImpl extends events_1.EventEmitter {
331
360
  });
332
361
  request.nodesToRead = request.nodesToRead || [];
333
362
  (0, node_opcua_assert_1.assert)(nodes.length === request.nodesToRead.length);
334
- this.historyRead(request, (err, response) => {
363
+ return this.historyRead(request, (err, response) => {
335
364
  /* c8 ignore next */
336
365
  if (err) {
337
- return callback(err);
366
+ return cb(err);
338
367
  }
339
368
  /* c8 ignore next */
340
369
  if (!response || !(response instanceof node_opcua_service_history_1.HistoryReadResponse)) {
341
- return callback(new Error("Internal Error"));
370
+ return cb(new Error("Internal Error"));
342
371
  }
343
372
  response.results = response.results || [];
344
373
  (0, node_opcua_assert_1.assert)(nodes.length === response.results.length);
345
- callback(null, isArray ? response.results : response.results[0]);
374
+ cb(null, isArray ? response.results : response.results[0]);
346
375
  });
347
376
  }
348
377
  historyRead(request, callback) {
@@ -350,7 +379,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
350
379
  if (!callback) {
351
380
  throw new Error("expecting a callback");
352
381
  }
353
- this.performMessageTransaction(request, (err, response) => {
382
+ return this.performMessageTransaction(request, (err, response) => {
354
383
  /* c8 ignore next */
355
384
  if (err) {
356
385
  return callback(err);
@@ -379,7 +408,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
379
408
  });
380
409
  }
381
410
  readAggregateValue(arg0, startTime, endTime, aggregateFn, processingInterval, ...args) {
382
- const callback = typeof args[0] === "function" ? args[0] : args[1];
411
+ const callback = (typeof args[0] === "function" ? args[0] : args[1]);
383
412
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
384
413
  const defaultAggregateFunction = {
385
414
  percentDataBad: 100,
@@ -388,7 +417,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
388
417
  useServerCapabilitiesDefaults: true,
389
418
  useSlopedExtrapolation: false
390
419
  };
391
- const aggregateConfiguration = typeof args[0] === "function" ? defaultAggregateFunction : args[0];
420
+ const aggregateConfiguration = (typeof args[0] === "function" ? defaultAggregateFunction : args[0]);
392
421
  const isArray = Array.isArray(arg0);
393
422
  const nodesToRead = isArray
394
423
  ? arg0
@@ -410,8 +439,8 @@ class ClientSessionImpl extends events_1.EventEmitter {
410
439
  releaseContinuationPoints: false,
411
440
  timestampsToReturn: node_opcua_service_read_1.TimestampsToReturn.Both
412
441
  });
413
- (0, node_opcua_assert_1.assert)(nodesToRead.length === request.nodesToRead.length);
414
- this.performMessageTransaction(request, (err, response) => {
442
+ (0, node_opcua_assert_1.assert)(nodesToRead.length === request.nodesToRead?.length);
443
+ return this.performMessageTransaction(request, (err, response) => {
415
444
  /* c8 ignore next */
416
445
  if (err) {
417
446
  return callback(err);
@@ -439,7 +468,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
439
468
  const callback = args[1];
440
469
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
441
470
  const request = new node_opcua_service_write_1.WriteRequest({ nodesToWrite });
442
- this.performMessageTransaction(request, (err, response) => {
471
+ return this.performMessageTransaction(request, (err, response) => {
443
472
  /* c8 ignore next */
444
473
  if (err) {
445
474
  return callback(err, response);
@@ -468,7 +497,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
468
497
  nodeId: this.resolveNodeId(nodeId),
469
498
  value: new node_opcua_data_value_1.DataValue({ value })
470
499
  });
471
- this.write(nodeToWrite, (err, statusCode) => {
500
+ return this.write(nodeToWrite, (err, statusCode) => {
472
501
  /* c8 ignore next */
473
502
  if (err) {
474
503
  return callback(err);
@@ -502,7 +531,8 @@ class ClientSessionImpl extends events_1.EventEmitter {
502
531
  /* c8 ignore next */
503
532
  if (helpAPIChange) {
504
533
  // the read method deprecation detection and warning
505
- if (!((0, node_opcua_utils_1.getFunctionParameterNames)(callback)[1] === "dataValues" || (0, node_opcua_utils_1.getFunctionParameterNames)(callback)[1] === "dataValue")) {
534
+ if (!((0, node_opcua_utils_1.getFunctionParameterNames)(callback)[1] === "dataValues" ||
535
+ (0, node_opcua_utils_1.getFunctionParameterNames)(callback)[1] === "dataValue")) {
506
536
  warningLog(chalk_1.default.red("[NODE-OPCUA-E04] the ClientSession#read API has changed !!, please fix the client code"));
507
537
  warningLog(chalk_1.default.red(" replace ..:"));
508
538
  warningLog(chalk_1.default.cyan(" session.read(nodesToRead,function(err,nodesToRead,results) {}"));
@@ -510,21 +540,23 @@ class ClientSessionImpl extends events_1.EventEmitter {
510
540
  warningLog(chalk_1.default.cyan(" session.read(nodesToRead,function(err,dataValues) {}"));
511
541
  warningLog("");
512
542
  warningLog(chalk_1.default.yellow("please make sure to refactor your code and check that " +
513
- "the second argument of your callback function is named"), chalk_1.default.cyan("dataValue" + (isArray ? "s" : "")));
543
+ "the second argument of your callback function is named"), chalk_1.default.cyan(`dataValue${isArray ? "s" : ""}`));
514
544
  warningLog(chalk_1.default.cyan("to make this exception disappear"));
515
545
  throw new Error("ERROR ClientSession#read API has changed !!, please fix the client code");
516
546
  }
517
547
  }
518
548
  // coerce nodeIds
519
549
  for (const node of nodesToRead) {
520
- node.nodeId = this.resolveNodeId(node.nodeId);
550
+ if (node.nodeId) {
551
+ node.nodeId = this.resolveNodeId(node.nodeId);
552
+ }
521
553
  }
522
554
  const request = new node_opcua_service_read_1.ReadRequest({
523
555
  maxAge,
524
556
  nodesToRead,
525
557
  timestampsToReturn: node_opcua_service_read_1.TimestampsToReturn.Both
526
558
  });
527
- this.performMessageTransaction(request, (err, response) => {
559
+ return this.performMessageTransaction(request, (err, response) => {
528
560
  /* c8 ignore next */
529
561
  if (err) {
530
562
  return callback(err, response);
@@ -534,7 +566,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
534
566
  return callback(new Error("Internal Error"));
535
567
  }
536
568
  // perform ExtensionObject resolution
537
- (0, node_opcua_client_dynamic_extension_object_1.promoteOpaqueStructure)(this, response.results)
569
+ (0, node_opcua_client_dynamic_extension_object_1.promoteOpaqueStructure)(this, response.results || [])
538
570
  .then(() => {
539
571
  response.results = response.results || /* c8 ignore next */ [];
540
572
  callback(null, isArray ? response.results : response.results[0]);
@@ -546,19 +578,19 @@ class ClientSessionImpl extends events_1.EventEmitter {
546
578
  }
547
579
  emitCloseEvent(statusCode) {
548
580
  if (!this._closeEventHasBeenEmitted) {
549
- debugLog("ClientSession#emitCloseEvent");
581
+ // c8 ignore next
582
+ doDebug && debugLog("ClientSession#emitCloseEvent");
550
583
  this._closeEventHasBeenEmitted = true;
551
584
  this.emit("session_closed", statusCode);
552
585
  }
553
586
  }
554
587
  createSubscription(options, callback) {
555
- this._defaultRequest(node_opcua_service_subscription_1.CreateSubscriptionRequest, node_opcua_service_subscription_1.CreateSubscriptionResponse, options, callback);
588
+ return this._defaultRequest(node_opcua_service_subscription_1.CreateSubscriptionRequest, node_opcua_service_subscription_1.CreateSubscriptionResponse, options, callback);
556
589
  }
557
590
  createSubscription2(...args) {
558
591
  const createSubscriptionRequest = args[0];
559
592
  let callback = args[1];
560
593
  const subscription = new client_subscription_impl_1.ClientSubscriptionImpl(this, createSubscriptionRequest);
561
- // tslint:disable-next-line:no-empty
562
594
  subscription.on("error", (err) => {
563
595
  if (callback) {
564
596
  callback(err);
@@ -572,32 +604,33 @@ class ClientSessionImpl extends events_1.EventEmitter {
572
604
  callback = null;
573
605
  }
574
606
  });
607
+ return undefined;
575
608
  }
576
609
  deleteSubscriptions(options, callback) {
577
- this._defaultRequest(node_opcua_service_subscription_1.DeleteSubscriptionsRequest, node_opcua_service_subscription_1.DeleteSubscriptionsResponse, options, callback);
610
+ return this._defaultRequest(node_opcua_service_subscription_1.DeleteSubscriptionsRequest, node_opcua_service_subscription_1.DeleteSubscriptionsResponse, options, callback);
578
611
  }
579
612
  setTriggering(request, callback) {
580
- this._defaultRequest(node_opcua_service_subscription_1.SetTriggeringRequest, node_opcua_service_subscription_1.SetTriggeringResponse, request, callback);
613
+ return this._defaultRequest(node_opcua_service_subscription_1.SetTriggeringRequest, node_opcua_service_subscription_1.SetTriggeringResponse, request, callback);
581
614
  }
582
615
  /**
583
616
  */
584
617
  transferSubscriptions(options, callback) {
585
- this._defaultRequest(node_opcua_service_subscription_1.TransferSubscriptionsRequest, node_opcua_service_subscription_1.TransferSubscriptionsResponse, options, callback);
618
+ return this._defaultRequest(node_opcua_service_subscription_1.TransferSubscriptionsRequest, node_opcua_service_subscription_1.TransferSubscriptionsResponse, options, callback);
586
619
  }
587
620
  createMonitoredItems(options, callback) {
588
- this._defaultRequest(node_opcua_service_subscription_1.CreateMonitoredItemsRequest, node_opcua_service_subscription_1.CreateMonitoredItemsResponse, options, callback);
621
+ return this._defaultRequest(node_opcua_service_subscription_1.CreateMonitoredItemsRequest, node_opcua_service_subscription_1.CreateMonitoredItemsResponse, options, callback);
589
622
  }
590
623
  modifyMonitoredItems(options, callback) {
591
- this._defaultRequest(node_opcua_service_subscription_1.ModifyMonitoredItemsRequest, node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, options, callback);
624
+ return this._defaultRequest(node_opcua_service_subscription_1.ModifyMonitoredItemsRequest, node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, options, callback);
592
625
  }
593
626
  /**
594
627
  *
595
628
  */
596
629
  modifySubscription(options, callback) {
597
- this._defaultRequest(node_opcua_service_subscription_1.ModifySubscriptionRequest, node_opcua_service_subscription_1.ModifySubscriptionResponse, options, callback);
630
+ return this._defaultRequest(node_opcua_service_subscription_1.ModifySubscriptionRequest, node_opcua_service_subscription_1.ModifySubscriptionResponse, options, callback);
598
631
  }
599
632
  setMonitoringMode(options, callback) {
600
- this._defaultRequest(node_opcua_service_subscription_1.SetMonitoringModeRequest, node_opcua_service_subscription_1.SetMonitoringModeResponse, options, callback);
633
+ return this._defaultRequest(node_opcua_service_subscription_1.SetMonitoringModeRequest, node_opcua_service_subscription_1.SetMonitoringModeResponse, options, callback);
601
634
  }
602
635
  /**
603
636
  */
@@ -630,7 +663,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
630
663
  publishingEnabled,
631
664
  subscriptionIds
632
665
  });
633
- this._defaultRequest(node_opcua_service_subscription_1.SetPublishingModeRequest, node_opcua_service_subscription_1.SetPublishingModeResponse, options, (err, response) => {
666
+ return this._defaultRequest(node_opcua_service_subscription_1.SetPublishingModeRequest, node_opcua_service_subscription_1.SetPublishingModeResponse, options, (err, response) => {
634
667
  /* c8 ignore next */
635
668
  if (err) {
636
669
  return callback(err);
@@ -653,7 +686,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
653
686
  const callback = args[1];
654
687
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
655
688
  const request = new node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsRequest({ browsePaths });
656
- this.performMessageTransaction(request, (err, response) => {
689
+ return this.performMessageTransaction(request, (err, response) => {
657
690
  /* c8 ignore next */
658
691
  if (err) {
659
692
  return callback(err, response);
@@ -667,28 +700,36 @@ class ClientSessionImpl extends events_1.EventEmitter {
667
700
  });
668
701
  }
669
702
  channelId() {
670
- return this._client !== null && this._client._secureChannel !== null && this._client._secureChannel.isOpened()
671
- ? this._client._secureChannel.channelId
672
- : -1;
703
+ const secureChannel = this._client?._secureChannel;
704
+ return secureChannel?.isOpened() ? secureChannel.channelId : -1;
673
705
  }
674
706
  isChannelValid() {
675
707
  /* c8 ignore next */
676
708
  if (!this._client) {
677
- debugLog(chalk_1.default.red("Warning SessionClient is null ?"));
709
+ // c8 ignore next
710
+ doDebug && debugLog(chalk_1.default.red("Warning SessionClient is null ?"));
678
711
  }
679
- return this._client !== null && this._client._secureChannel !== null && this._client._secureChannel.isOpened();
712
+ return !!this._client?._secureChannel?.isOpened();
680
713
  }
681
714
  performMessageTransaction(request, callback) {
682
715
  if (!this._client) {
683
716
  // session may have been closed by user ... but is still in used !!
684
- return callback(new Error("Session has been closed and should not be used to perform a transaction anymore"));
717
+ callback(new Error("Session has been closed and should not be used to perform a transaction anymore"));
718
+ return;
685
719
  }
686
720
  if (request instanceof node_opcua_service_subscription_1.PublishRequest ||
687
721
  request instanceof node_opcua_types_1.ActivateSessionRequest ||
688
722
  request instanceof node_opcua_types_1.CloseSessionRequest) {
689
- return this._performMessageTransaction(request, callback);
723
+ this._performMessageTransaction(request, callback);
724
+ return;
690
725
  }
691
- if (this._reconnecting.pendingTransactions.length > 0) {
726
+ // Hold the transaction only while the channel is genuinely down and a repair is under
727
+ // way. The repair restores the session *after* the secure channel is back up
728
+ // (_repairConnection: _recreate_secure_channel, then _finalReconnectionStep), so its own
729
+ // traffic - including the plain Read that readOperationLimits issues - always sees a
730
+ // valid channel and passes straight through. Queueing on "reconnecting" alone would
731
+ // park the repair's requests behind the repair that is waiting for them.
732
+ if (!this.isChannelValid() && (this._reconnecting.reconnecting || this._client.isReconnecting)) {
692
733
  /* c8 ignore next */
693
734
  if (this._reconnecting.pendingTransactions.length > 10) {
694
735
  if (!pendingTransactionMessageDisplayed) {
@@ -698,7 +739,9 @@ class ClientSessionImpl extends events_1.EventEmitter {
698
739
  }
699
740
  }
700
741
  else if (this._reconnecting.pendingTransactions.length > 3) {
701
- debugLog(chalk_1.default.yellow("Warning : your client is sending multiple requests simultaneously to the server", request.constructor.name));
742
+ // c8 ignore next
743
+ doDebug &&
744
+ debugLog(chalk_1.default.yellow("Warning : your client is sending multiple requests simultaneously to the server", request.constructor.name));
702
745
  }
703
746
  this._reconnecting.pendingTransactions.push({ request, callback });
704
747
  return;
@@ -709,78 +752,113 @@ class ClientSessionImpl extends events_1.EventEmitter {
709
752
  attemptCount > 0 &&
710
753
  warningLog("reprocessRequest => ", request.constructor.name, this._reconnecting.pendingTransactions.length);
711
754
  this._performMessageTransaction(request, (err, response) => {
712
- if (err && err.message.match(/BadSessionIdInvalid/) && request.constructor.name !== "ActivateSessionRequest") {
755
+ if (err?.message.match(/BadSessionIdInvalid/) && request.constructor.name !== "ActivateSessionRequest") {
713
756
  warningLog("Transaction on Invalid Session ", request.constructor.name, err.message, "isReconnecting?=", this.isReconnecting, "q=", this._reconnecting.pendingTransactions.length);
714
757
  request.requestHeader.requestHandle = node_opcua_secure_channel_1.requestHandleNotSetValue;
715
758
  if (this.isReconnecting) {
716
- this.once("session_restored", () => {
717
- warningLog("redoing", request.constructor.name, this.isReconnecting);
718
- this.#reprocessRequest(attemptCount + 1, request, callback);
719
- });
759
+ // Hand it back to the queue rather than parking it on a one-shot
760
+ // session_restored listener: that event is emitted only when a repair
761
+ // succeeds, so a repair that gave up - or a dispose, which drops every
762
+ // listener - left the caller waiting for an answer that could never come.
763
+ // flushPendingTransactions is called on every exit from a repair, so the
764
+ // transaction is always resolved one way or the other.
765
+ // c8 ignore next
766
+ doDebug && debugLog("holding for replay after repair:", request.constructor.name, "attempt", attemptCount);
767
+ this._reconnecting.pendingTransactions.push({ request, callback });
720
768
  }
721
769
  else {
722
770
  this.#_recreate_session_and_reperform_transaction(request, callback);
723
771
  }
724
772
  return;
725
773
  }
774
+ // the queue is owned by flushPendingTransactions, which the repair calls on every
775
+ // exit: draining one entry from here would send it before the session is restored,
776
+ // and would race with that flush.
726
777
  callback(err, response);
727
- const length = this._reconnecting.pendingTransactions.length; // record length before callback is called !
728
- if (length > 0) {
729
- debugLog("reprocessRequest => ", this._reconnecting.pendingTransactions.length, " transaction(s) left in queue");
730
- // tslint:disable-next-line: no-shadowed-variable
731
- const { request, callback } = this._reconnecting.pendingTransactions.shift();
732
- this.#reprocessRequest(0, request, callback);
733
- }
734
778
  });
735
779
  }
780
+ /**
781
+ * record that the server has answered.
782
+ *
783
+ * A transaction that failed on a timeout or on a broken channel comes back with no response
784
+ * at all and must not refresh lastResponseReceivedTime, or the keep-alive manager would never
785
+ * notice that the server is gone (see #1569). A ServiceFault does count - the round trip
786
+ * completed - but the channel reports it as an Error carrying the decoded fault on
787
+ * err.response, so the response argument alone does not tell the two cases apart.
788
+ *
789
+ * @internal
790
+ */
791
+ /**
792
+ * resolve every transaction that was held while the connection was down: replay them when the
793
+ * session is usable again, fail them when the repair gave up.
794
+ *
795
+ * Every exit from a repair must call this, otherwise a held caller waits for an answer that
796
+ * can never come - and the session is disposed with a queue that nobody drained.
797
+ *
798
+ * @internal
799
+ */
800
+ flushPendingTransactions(err) {
801
+ const heldTransactions = this._reconnecting.pendingTransactions.splice(0);
802
+ if (heldTransactions.length === 0) {
803
+ return;
804
+ }
805
+ // c8 ignore next
806
+ doDebug && debugLog("flushPendingTransactions", heldTransactions.length, err ? `failing: ${err.message}` : "replaying");
807
+ pendingTransactionMessageDisplayed = false;
808
+ for (const pending of heldTransactions) {
809
+ if (err) {
810
+ pending.callback(err);
811
+ }
812
+ else {
813
+ this.#reprocessRequest(0, pending.request, pending.callback);
814
+ }
815
+ }
816
+ }
817
+ noteServerAnswer(err, response) {
818
+ if (response || err?.response) {
819
+ this.lastResponseReceivedTime = new Date();
820
+ }
821
+ }
736
822
  _performMessageTransaction(request, callback) {
737
823
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
738
824
  /* c8 ignore next */
739
825
  if (!this._client) {
740
826
  // session may have been closed by user ... but is still in used !!
741
- return callback(new Error("Session has been closed and should not be used to perform a transaction anymore"));
827
+ callback(new Error("Session has been closed and should not be used to perform a transaction anymore"));
828
+ return;
742
829
  }
743
830
  if (!this.isChannelValid()) {
744
831
  // the secure channel is broken, may be the server has crashed or the network cable has been disconnected
745
832
  // for a long time
746
833
  // we may need to queue this transaction, as a secure token may be being reprocessed
747
- debugLog(chalk_1.default.bgWhite.red("!!! Performing transaction on invalid channel !!! ", request.constructor.name));
748
- return callback(new Error("Invalid Channel BadConnectionClosed"));
834
+ // c8 ignore next
835
+ doDebug && debugLog(chalk_1.default.bgWhite.red("!!! Performing transaction on invalid channel !!! ", request.constructor.name));
836
+ callback(new Error("Invalid Channel BadConnectionClosed"));
837
+ return;
749
838
  }
750
839
  // is this stuff useful?
751
840
  if (request.requestHeader) {
841
+ if (!this.authenticationToken) {
842
+ throw new Error("internal error: authenticationToken should be set on an active session");
843
+ }
752
844
  request.requestHeader.authenticationToken = this.authenticationToken;
753
845
  }
754
846
  this.lastRequestSentTime = new Date();
755
847
  this._client.performMessageTransaction(request, (err, response) => {
756
- this.lastResponseReceivedTime = new Date();
757
- /* c8 ignore next */
848
+ this.noteServerAnswer(err, response);
758
849
  if (err) {
759
- if (response && response.responseHeader.serviceDiagnostics) {
760
- err.serviceDiagnostics = response.responseHeader.serviceDiagnostics;
761
- }
762
- if (response && response.diagnosticInfos) {
763
- err.diagnosticsInfo = response.diagnosticInfos;
764
- }
765
- return callback(err);
850
+ return callback(annotateWithDiagnostics(err, response));
766
851
  }
767
852
  /* c8 ignore next */
768
853
  if (!response) {
769
854
  return callback(new Error("internal Error"));
770
855
  }
771
- /* c8 ignore next */
772
856
  if (response.responseHeader.serviceResult.isNot(node_opcua_status_code_1.StatusCodes.Good)) {
773
- err = new Error(" ServiceResult is " +
857
+ const serviceResultError = new Error(" ServiceResult is " +
774
858
  response.responseHeader.serviceResult.toString() +
775
859
  " request was " +
776
860
  request.constructor.name);
777
- if (response && response.responseHeader.serviceDiagnostics) {
778
- err.serviceDiagnostics = response.responseHeader.serviceDiagnostics;
779
- }
780
- if (response && response.diagnosticInfos) {
781
- err.diagnosticsInfo = response.diagnosticInfos;
782
- }
783
- return callback(err, response);
861
+ return callback(annotateWithDiagnostics(serviceResultError, response), response);
784
862
  }
785
863
  return callback(null, response);
786
864
  });
@@ -811,7 +889,12 @@ class ClientSessionImpl extends events_1.EventEmitter {
811
889
  */
812
890
  evaluateRemainingLifetime() {
813
891
  const now = Date.now();
814
- const expiryTime = this.lastRequestSentTime.getTime() + this.timeout;
892
+ // anchored on the last answer, not the last send: the server restarts its session
893
+ // watchdog when it *receives* a request, and the only proof the client has that a
894
+ // request arrived is an answer coming back. Anchoring on the send made this return a
895
+ // full lifetime throughout an outage - a client that keeps trying keeps refreshing the
896
+ // send timestamp - which is precisely when the caller needs the truth (see #1569).
897
+ const expiryTime = this.lastResponseReceivedTime.getTime() + this.timeout;
815
898
  return Math.max(0, expiryTime - now);
816
899
  }
817
900
  _terminatePublishEngine() {
@@ -825,7 +908,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
825
908
  * @param args
826
909
  */
827
910
  close(...args) {
828
- if (arguments.length === 1) {
911
+ if (args.length === 1) {
829
912
  return this.close(true, args[0]);
830
913
  }
831
914
  const deleteSubscription = args[0];
@@ -834,15 +917,18 @@ class ClientSessionImpl extends events_1.EventEmitter {
834
917
  (0, node_opcua_assert_1.assert)(typeof deleteSubscription === "boolean");
835
918
  /* c8 ignore next */
836
919
  if (!this._client) {
837
- debugLog("ClientSession#close : warning, client is already closed");
920
+ // c8 ignore next
921
+ doDebug && debugLog("ClientSession#close : warning, client is already closed");
838
922
  return callback(); // already close ?
839
923
  }
840
924
  (0, node_opcua_assert_1.assert)(this._client);
841
925
  this._terminatePublishEngine();
842
926
  this._client.closeSession(this, deleteSubscription, (err) => {
843
- debugLog("session Close err ", err ? err.message : "null");
927
+ // c8 ignore next
928
+ doDebug && debugLog("session Close err ", err ? err.message : "null");
844
929
  callback();
845
930
  });
931
+ return undefined;
846
932
  }
847
933
  /**
848
934
 
@@ -857,7 +943,9 @@ class ClientSessionImpl extends events_1.EventEmitter {
857
943
  */
858
944
  call(...args) {
859
945
  const isArray = Array.isArray(args[0]);
860
- const methodsToCall = isArray ? args[0] : [args[0]];
946
+ const methodsToCall = isArray
947
+ ? args[0]
948
+ : [args[0]];
861
949
  (0, node_opcua_assert_1.assert)(Array.isArray(methodsToCall));
862
950
  const callback = args[1];
863
951
  // Note : The client has no explicit address space and therefore will struggle to
@@ -867,7 +955,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
867
955
  // - load a fake address space to have some thing to query on our end
868
956
  // const request = this._client.factory.constructObjectId("CallRequest",{ methodsToCall: methodsToCall});
869
957
  const request = new node_opcua_service_call_1.CallRequest({ methodsToCall });
870
- this.performMessageTransaction(request, (err, response) => {
958
+ return this.performMessageTransaction(request, (err, response) => {
871
959
  /* c8 ignore next */
872
960
  if (err) {
873
961
  return callback(err);
@@ -876,10 +964,11 @@ class ClientSessionImpl extends events_1.EventEmitter {
876
964
  if (!response || !(response instanceof node_opcua_service_call_1.CallResponse)) {
877
965
  return callback(new Error("internal error"));
878
966
  }
879
- response.results = response.results || [];
880
- promoteOpaqueStructureForCall(this, response.results)
967
+ const results = response.results || [];
968
+ response.results = results;
969
+ promoteOpaqueStructureForCall(this, results)
881
970
  .then(() => {
882
- callback(null, isArray ? response.results : response.results[0]);
971
+ callback(null, isArray ? results : results[0]);
883
972
  })
884
973
  .catch((err) => {
885
974
  callback(err);
@@ -901,7 +990,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
901
990
  methodId: (0, node_opcua_nodeid_1.coerceNodeId)("ns=0;i=11492"), // MethodIds.Server_GetMonitoredItems;
902
991
  objectId: (0, node_opcua_nodeid_1.coerceNodeId)("ns=0;i=2253") // ObjectId.Server
903
992
  });
904
- this.call(methodsToCall, (err, result) => {
993
+ return this.call(methodsToCall, (err, result) => {
905
994
  /* c8 ignore next */
906
995
  if (err) {
907
996
  return callback(err);
@@ -940,7 +1029,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
940
1029
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
941
1030
  return (0, node_opcua_pseudo_session_1.getArgumentDefinitionHelper)(this, methodId)
942
1031
  .then((result) => {
943
- callback(null, result);
1032
+ callback?.(null, result);
944
1033
  })
945
1034
  .catch((err) => {
946
1035
  callback(err);
@@ -954,7 +1043,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
954
1043
  const request = new node_opcua_service_register_node_1.RegisterNodesRequest({
955
1044
  nodesToRegister: nodesToRegister.map((n) => this.resolveNodeId(n))
956
1045
  });
957
- this.performMessageTransaction(request, (err, response) => {
1046
+ return this.performMessageTransaction(request, (err, response) => {
958
1047
  /* c8 ignore next */
959
1048
  if (err) {
960
1049
  return callback(err);
@@ -975,7 +1064,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
975
1064
  const request = new node_opcua_service_register_node_1.UnregisterNodesRequest({
976
1065
  nodesToUnregister: nodesToUnregister.map((n) => this.resolveNodeId(n))
977
1066
  });
978
- this.performMessageTransaction(request, (err, response) => {
1067
+ return this.performMessageTransaction(request, (err, response) => {
979
1068
  /* c8 ignore next */
980
1069
  if (err) {
981
1070
  return callback(err);
@@ -992,7 +1081,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
992
1081
  const callback = args[1];
993
1082
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
994
1083
  const request = new node_opcua_service_query_1.QueryFirstRequest(queryFirstRequest);
995
- this.performMessageTransaction(request, (err, response) => {
1084
+ return this.performMessageTransaction(request, (err, response) => {
996
1085
  /* c8 ignore next */
997
1086
  if (err) {
998
1087
  return callback(err);
@@ -1038,11 +1127,8 @@ class ClientSessionImpl extends events_1.EventEmitter {
1038
1127
  this.stopKeepAliveManager();
1039
1128
  this.removeAllListeners();
1040
1129
  //
1041
- const privateThis = this;
1042
- if (!(!privateThis.pendingTransactions || privateThis.pendingTransactions.length === 0)) {
1043
- // tslint:disable-next-line: no-console
1044
- warningLog("dispose when pendingTransactions is not empty ");
1045
- }
1130
+ // never strand a held caller: the session is going away, so nothing will ever replay them
1131
+ this.flushPendingTransactions(new Error("Session has been disposed while the transaction was waiting for reconnection"));
1046
1132
  }
1047
1133
  toString() {
1048
1134
  const now = Date.now();
@@ -1050,33 +1136,33 @@ class ClientSessionImpl extends events_1.EventEmitter {
1050
1136
  const lap2 = now - this.lastResponseReceivedTime.getTime();
1051
1137
  const timeoutDelay = this.timeout - lap1;
1052
1138
  const timeoutInfo = timeoutDelay < 0
1053
- ? chalk_1.default.red(" expired since " + -timeoutDelay / 1000 + " seconds")
1054
- : chalk_1.default.green(" timeout in " + timeoutDelay / 1000 + " seconds");
1139
+ ? chalk_1.default.red(` expired since ${-timeoutDelay / 1000} seconds`)
1140
+ : chalk_1.default.green(` timeout in ${timeoutDelay / 1000} seconds`);
1055
1141
  let str = "";
1056
- str += " name..................... " + this.name;
1057
- str += "\n sessionId................ " + this.sessionId.toString();
1058
- str += "\n authenticationToken...... " + (this.authenticationToken ? this.authenticationToken.toString() : "");
1059
- str += "\n timeout.................. " + this.timeout + "ms" + timeoutInfo;
1060
- str += "\n serverNonce.............. " + (this.serverNonce ? this.serverNonce.toString("hex") : "");
1061
- str += "\n serverCertificate........ " + (0, node_opcua_utils_1.buffer_ellipsis)(this.serverCertificate);
1062
- str += "\n serverSignature.......... " + this.serverSignature;
1063
- str += "\n lastRequestSentTime...... " + new Date(this.lastRequestSentTime).toISOString() + " (" + lap1 + ")";
1064
- str += "\n lastResponseReceivedTime. " + new Date(this.lastResponseReceivedTime).toISOString() + " (" + lap2 + ")";
1065
- str += "\n isReconnecting........... " + this.isReconnecting;
1066
- str += "\n isValidChannel........... " + this.isChannelValid() + " has been closed " + this.hasBeenClosed();
1067
- str += "\n channelId................ " + this.channelId();
1068
- str += "\n remaining life time...... " + this.evaluateRemainingLifetime();
1069
- str += "\n subscription count....... " + this.subscriptionCount;
1070
- if (this._client && this._client._secureChannel) {
1142
+ str += ` name..................... ${this.name}`;
1143
+ str += `\n sessionId................ ${this.sessionId.toString()}`;
1144
+ str += `\n authenticationToken...... ${this.authenticationToken ? this.authenticationToken?.toString() : ""}`;
1145
+ str += `\n timeout.................. ${this.timeout}ms${timeoutInfo}`;
1146
+ str += `\n serverNonce.............. ${this.serverNonce ? this.serverNonce?.toString("hex") : ""}`;
1147
+ str += `\n serverCertificate........ ${(0, node_opcua_utils_1.buffer_ellipsis)(this.serverCertificate)}`;
1148
+ str += `\n serverSignature.......... ${this.serverSignature}`;
1149
+ str += `\n lastRequestSentTime...... ${new Date(this.lastRequestSentTime).toISOString()} (${lap1})`;
1150
+ str += `\n lastResponseReceivedTime. ${new Date(this.lastResponseReceivedTime).toISOString()} (${lap2})`;
1151
+ str += `\n isReconnecting........... ${this.isReconnecting}`;
1152
+ str += `\n isValidChannel........... ${this.isChannelValid()} has been closed ${this.hasBeenClosed()}`;
1153
+ str += `\n channelId................ ${this.channelId()}`;
1154
+ str += `\n remaining life time...... ${this.evaluateRemainingLifetime()}`;
1155
+ str += `\n subscription count....... ${this.subscriptionCount}`;
1156
+ if (this._client?._secureChannel) {
1071
1157
  if (this._client._secureChannel.activeSecurityToken) {
1072
- str += "\n reviseTokenLifetime...... " + this._client._secureChannel.activeSecurityToken.revisedLifetime;
1158
+ str += `\n reviseTokenLifetime...... ${this._client._secureChannel.activeSecurityToken.revisedLifetime}`;
1073
1159
  }
1074
1160
  }
1075
- str += "\n keepAlive ................ " + this._keepAliveManager ? true : false;
1076
1161
  if (this._keepAliveManager) {
1077
- str += "\n keepAlive checkInterval.. " + this._keepAliveManager.checkInterval + " ms";
1078
- str += "\n (defaultTransportTimeout)." + node_opcua_secure_channel_1.ClientSecureChannelLayer.defaultTransportTimeout + " ms";
1079
- str += "\n session timeout " + this.timeout + " ms";
1162
+ str += `\n keepAlive ................ ${this._keepAliveManager}`;
1163
+ str += `\n keepAlive checkInterval.. ${this._keepAliveManager.checkInterval} ms`;
1164
+ str += `\n (defaultTransportTimeout).${node_opcua_secure_channel_1.ClientSecureChannelLayer.defaultTransportTimeout} ms`;
1165
+ str += `\n session timeout ${this.timeout} ms`;
1080
1166
  }
1081
1167
  return str;
1082
1168
  }
@@ -1094,12 +1180,15 @@ class ClientSessionImpl extends events_1.EventEmitter {
1094
1180
  .catch((err) => {
1095
1181
  callback(err);
1096
1182
  });
1183
+ return undefined;
1097
1184
  }
1098
1185
  getNamespaceIndex(namespaceUri) {
1099
1186
  (0, node_opcua_assert_1.assert)(this.$$namespaceArray, "please make sure that readNamespaceArray has been called");
1187
+ if (!this.$$namespaceArray) {
1188
+ throw new Error("please make sure that readNamespaceArray has been called");
1189
+ }
1100
1190
  return this.$$namespaceArray.indexOf(namespaceUri);
1101
1191
  }
1102
- // tslint:disable:no-empty
1103
1192
  // ---------------------------------------- Alarm & condition stub
1104
1193
  disableCondition() {
1105
1194
  /** empty */
@@ -1109,19 +1198,19 @@ class ClientSessionImpl extends events_1.EventEmitter {
1109
1198
  }
1110
1199
  addCommentCondition(_conditionId, _eventId, _comment, _callback) {
1111
1200
  /** empty */
1201
+ return undefined;
1112
1202
  }
1113
1203
  confirmCondition(_conditionId, _eventId, _comment, _callback) {
1114
1204
  /** empty */
1205
+ return undefined;
1115
1206
  }
1116
1207
  acknowledgeCondition(_conditionId, _eventId, _comment, _callback) {
1117
1208
  /** empty */
1209
+ return undefined;
1118
1210
  }
1119
- /**
1120
- * @deprecated
1121
- * @private
1122
- */
1123
1211
  findMethodId(_nodeId, _methodName, _callback) {
1124
1212
  /** empty */
1213
+ return undefined;
1125
1214
  }
1126
1215
  _callMethodCondition(_methodName, _conditionId, _eventId, _comment, _callback) {
1127
1216
  /** empty */
@@ -1143,6 +1232,9 @@ class ClientSessionImpl extends events_1.EventEmitter {
1143
1232
  }
1144
1233
  _defaultRequest(requestClass, _responseClass, options, callback) {
1145
1234
  (0, node_opcua_assert_1.assert)(typeof callback === "function");
1235
+ if (!callback) {
1236
+ throw new Error("_defaultRequest: expecting a callback function here");
1237
+ }
1146
1238
  const request = options instanceof requestClass ? options : new requestClass(options);
1147
1239
  /* c8 ignore next */
1148
1240
  if (doDebug) {
@@ -1150,19 +1242,23 @@ class ClientSessionImpl extends events_1.EventEmitter {
1150
1242
  }
1151
1243
  /* c8 ignore next */
1152
1244
  if (this._closeEventHasBeenEmitted) {
1153
- debugLog("ClientSession#_defaultRequest => session has been closed !!", request.toString());
1245
+ // c8 ignore next
1246
+ doDebug && debugLog("ClientSession#_defaultRequest => session has been closed !!", request.toString());
1154
1247
  setImmediate(() => {
1155
1248
  callback(new Error("ClientSession is closed !"));
1156
1249
  });
1157
- return;
1250
+ return undefined;
1158
1251
  }
1159
- this.performMessageTransaction(request, (err, response) => {
1252
+ return this.performMessageTransaction(request, (err, response) => {
1160
1253
  if (this._closeEventHasBeenEmitted) {
1161
- debugLog("ClientSession#_defaultRequest ... err =", err ? err.message : "null", response ? response.toString() : " null");
1254
+ // c8 ignore next
1255
+ doDebug &&
1256
+ debugLog("ClientSession#_defaultRequest ... err =", err ? err.message : "null", response ? response.toString() : " null");
1162
1257
  }
1163
1258
  /* c8 ignore next */
1164
1259
  if (err) {
1165
- debugLog("Client session : performMessageTransaction error = ", err.message);
1260
+ // c8 ignore next
1261
+ doDebug && debugLog("Client session : performMessageTransaction error = ", err.message);
1166
1262
  // let intercept interesting error message
1167
1263
  if (err.message.match(/BadSessionClosed/)) {
1168
1264
  // the session has been closed by Server
@@ -1179,6 +1275,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
1179
1275
  }
1180
1276
  // DO NOT TERMINATE SESSION, as we will need a publishEngine when we
1181
1277
  // reconnect this._terminatePublishEngine();
1278
+ // biome-ignore lint/correctness/noConstantCondition: deliberate debug on/off toggle, not dead code
1182
1279
  if (false) {
1183
1280
  // ER 10.2019
1184
1281
  /**
@@ -1196,10 +1293,12 @@ class ClientSessionImpl extends events_1.EventEmitter {
1196
1293
  #_recreate_session_and_reperform_transaction(request, callback) {
1197
1294
  warningLog("attempt to recreate session to reperform a transaction ", request.constructor.name);
1198
1295
  if (this.recursive_repair_detector >= 1) {
1199
- // tslint:disable-next-line: no-console
1200
1296
  warningLog("recreate_session_and_reperform_transaction => Already in Progress");
1201
1297
  return callback(new Error("Cannot recreate session"));
1202
1298
  }
1299
+ if (!this._client) {
1300
+ return callback(new Error("Cannot recreate session: session has no client"));
1301
+ }
1203
1302
  this.recursive_repair_detector += 1;
1204
1303
  warningLog(chalk_1.default.red("----------------> Repairing Client Session as Server believes it is invalid now "));
1205
1304
  (0, reconnection_1.repair_client_session)(this._client, this, (err) => {
@@ -1215,7 +1314,7 @@ class ClientSessionImpl extends events_1.EventEmitter {
1215
1314
  }
1216
1315
  exports.ClientSessionImpl = ClientSessionImpl;
1217
1316
  async function promoteOpaqueStructureForCallMethodResult(session, callMethodResult) {
1218
- if (!callMethodResult || !callMethodResult.outputArguments || callMethodResult.outputArguments.length === 0) {
1317
+ if (!callMethodResult?.outputArguments || callMethodResult.outputArguments.length === 0) {
1219
1318
  return;
1220
1319
  }
1221
1320
  await (0, node_opcua_client_dynamic_extension_object_1.promoteOpaqueStructure)(session, callMethodResult.outputArguments.map((a) => ({ value: a })));
@@ -1242,8 +1341,6 @@ async function promoteOpaqueStructureForCall(session, callMethodResults) {
1242
1341
  const promises = callMethodResults.map(async (x) => promoteOpaqueStructureForCallMethodResult(session, x));
1243
1342
  await Promise.all(promises);
1244
1343
  }
1245
- // tslint:disable:no-var-requires
1246
- // tslint:disable:max-line-length
1247
1344
  const thenify_ex_1 = require("thenify-ex");
1248
1345
  const opts = { multiArgs: false };
1249
1346
  ClientSessionImpl.prototype.browse = (0, thenify_ex_1.withCallback)(ClientSessionImpl.prototype.browse, opts);