node-opcua-client 2.166.0 → 2.168.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 (102) hide show
  1. package/dist/alarms_and_conditions/client_alarm_tools.d.ts +1 -1
  2. package/dist/alarms_and_conditions/client_alarm_tools.js +2 -2
  3. package/dist/alarms_and_conditions/client_alarm_tools.js.map +1 -1
  4. package/dist/alarms_and_conditions/client_tools.d.ts +3 -0
  5. package/dist/alarms_and_conditions/client_tools.js +2 -2
  6. package/dist/alarms_and_conditions/client_tools.js.map +1 -1
  7. package/dist/client_base.d.ts +47 -40
  8. package/dist/client_base.js +5 -6
  9. package/dist/client_base.js.map +1 -1
  10. package/dist/client_monitored_item.d.ts +7 -7
  11. package/dist/client_monitored_item.js.map +1 -1
  12. package/dist/client_monitored_item_base.d.ts +12 -13
  13. package/dist/client_monitored_item_group.d.ts +5 -5
  14. package/dist/client_monitored_item_toolbox.d.ts +6 -7
  15. package/dist/client_monitored_item_toolbox.js.map +1 -1
  16. package/dist/client_session.d.ts +19 -23
  17. package/dist/client_session.js.map +1 -1
  18. package/dist/client_session_keepalive_manager.d.ts +1 -1
  19. package/dist/client_session_keepalive_manager.js +6 -6
  20. package/dist/client_session_keepalive_manager.js.map +1 -1
  21. package/dist/client_subscription.d.ts +11 -12
  22. package/dist/client_subscription.js.map +1 -1
  23. package/dist/client_utils.d.ts +3 -3
  24. package/dist/client_utils.js.map +1 -1
  25. package/dist/common.d.ts +12 -12
  26. package/dist/index.d.ts +26 -27
  27. package/dist/index.js +65 -66
  28. package/dist/index.js.map +1 -1
  29. package/dist/opcua_client.d.ts +17 -19
  30. package/dist/opcua_client.js.map +1 -1
  31. package/dist/private/client_base_impl.d.ts +19 -18
  32. package/dist/private/client_base_impl.js +220 -192
  33. package/dist/private/client_base_impl.js.map +1 -1
  34. package/dist/private/client_monitored_item_group_impl.d.ts +4 -5
  35. package/dist/private/client_monitored_item_group_impl.js +1 -1
  36. package/dist/private/client_monitored_item_group_impl.js.map +1 -1
  37. package/dist/private/client_monitored_item_impl.d.ts +9 -10
  38. package/dist/private/client_monitored_item_impl.js.map +1 -1
  39. package/dist/private/client_publish_engine.d.ts +3 -3
  40. package/dist/private/client_publish_engine.js +6 -7
  41. package/dist/private/client_publish_engine.js.map +1 -1
  42. package/dist/private/client_session_impl.d.ts +24 -25
  43. package/dist/private/client_session_impl.js +14 -10
  44. package/dist/private/client_session_impl.js.map +1 -1
  45. package/dist/private/client_subscription_impl.d.ts +10 -11
  46. package/dist/private/client_subscription_impl.js +12 -11
  47. package/dist/private/client_subscription_impl.js.map +1 -1
  48. package/dist/private/i_private_client.d.ts +7 -7
  49. package/dist/private/opcua_client_impl.d.ts +12 -9
  50. package/dist/private/opcua_client_impl.js +58 -48
  51. package/dist/private/opcua_client_impl.js.map +1 -1
  52. package/dist/private/performance.js.map +1 -1
  53. package/dist/private/reconnection/client_publish_engine_reconnection.d.ts +1 -1
  54. package/dist/private/reconnection/client_publish_engine_reconnection.js +54 -43
  55. package/dist/private/reconnection/client_publish_engine_reconnection.js.map +1 -1
  56. package/dist/private/reconnection/client_reconnection.d.ts +1 -1
  57. package/dist/private/reconnection/client_subscription_reconnection.d.ts +1 -1
  58. package/dist/private/reconnection/client_subscription_reconnection.js +2 -2
  59. package/dist/private/reconnection/client_subscription_reconnection.js.map +1 -1
  60. package/dist/private/reconnection/reconnection.d.ts +4 -4
  61. package/dist/private/reconnection/reconnection.js +200 -281
  62. package/dist/private/reconnection/reconnection.js.map +1 -1
  63. package/dist/tools/findservers.d.ts +7 -2
  64. package/dist/tools/findservers.js +41 -53
  65. package/dist/tools/findservers.js.map +1 -1
  66. package/dist/tools/read_history_server_capabilities.d.ts +1 -1
  67. package/dist/tools/read_history_server_capabilities.js +9 -8
  68. package/dist/tools/read_history_server_capabilities.js.map +1 -1
  69. package/dist/user_identity_info.d.ts +1 -1
  70. package/dist/verify.js.map +1 -1
  71. package/package.json +45 -45
  72. package/source/alarms_and_conditions/client_alarm_tools.ts +14 -8
  73. package/source/alarms_and_conditions/client_tools.ts +7 -6
  74. package/source/client_base.ts +93 -79
  75. package/source/client_monitored_item.ts +7 -8
  76. package/source/client_monitored_item_base.ts +12 -14
  77. package/source/client_monitored_item_group.ts +5 -5
  78. package/source/client_monitored_item_toolbox.ts +13 -14
  79. package/source/client_session.ts +37 -40
  80. package/source/client_session_keepalive_manager.ts +7 -10
  81. package/source/client_subscription.ts +11 -12
  82. package/source/client_utils.ts +6 -6
  83. package/source/common.ts +12 -12
  84. package/source/index.ts +44 -40
  85. package/source/opcua_client.ts +24 -23
  86. package/source/private/client_base_impl.ts +329 -290
  87. package/source/private/client_monitored_item_group_impl.ts +10 -14
  88. package/source/private/client_monitored_item_impl.ts +17 -17
  89. package/source/private/client_publish_engine.ts +11 -12
  90. package/source/private/client_session_impl.ts +85 -82
  91. package/source/private/client_subscription_impl.ts +42 -41
  92. package/source/private/i_private_client.ts +8 -8
  93. package/source/private/opcua_client_impl.ts +118 -97
  94. package/source/private/performance.ts +2 -3
  95. package/source/private/reconnection/client_publish_engine_reconnection.ts +76 -68
  96. package/source/private/reconnection/client_reconnection.ts +1 -1
  97. package/source/private/reconnection/client_subscription_reconnection.ts +16 -13
  98. package/source/private/reconnection/reconnection.ts +307 -301
  99. package/source/tools/findservers.ts +43 -62
  100. package/source/tools/read_history_server_capabilities.ts +20 -22
  101. package/source/user_identity_info.ts +5 -5
  102. package/source/verify.ts +25 -25
@@ -2,75 +2,78 @@
2
2
  * @module node-opcua-client-private
3
3
  */
4
4
  // tslint:disable:no-unused-expression
5
- import fs from "fs";
6
- import path from "path";
7
- import async from "async";
8
- import chalk from "chalk";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+
9
8
  import { withLock } from "@ster5/global-mutex";
9
+
10
+ import chalk from "chalk";
10
11
  import { assert } from "node-opcua-assert";
11
- import { IOPCUASecureObjectOptions, OPCUASecureObject } from "node-opcua-common";
12
- import { Certificate, makeSHA1Thumbprint, Nonce, split_der } from "node-opcua-crypto/web";
12
+ import { getDefaultCertificateManager, makeSubject, type OPCUACertificateManager } from "node-opcua-certificate-manager";
13
+ import { type IOPCUASecureObjectOptions, makeApplicationUrn, OPCUASecureObject } from "node-opcua-common";
14
+ import { type Certificate, makeSHA1Thumbprint, split_der } from "node-opcua-crypto/web";
13
15
  import { installPeriodicClockAdjustment, periodicClockAdjustment, uninstallPeriodicClockAdjustment } from "node-opcua-date-time";
14
16
  import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
15
-
16
- import { makeApplicationUrn } from "node-opcua-common";
17
17
  import { getHostname } from "node-opcua-hostname";
18
- import { IBasicTransportSettings, ResponseCallback } from "node-opcua-pseudo-session";
18
+ import type { IBasicTransportSettings, ResponseCallback } from "node-opcua-pseudo-session";
19
19
  import {
20
20
  ClientSecureChannelLayer,
21
+ type ConnectionStrategy,
22
+ type ConnectionStrategyOptions,
21
23
  coerceConnectionStrategy,
22
24
  coerceSecurityPolicy,
23
- ConnectionStrategy,
24
- ConnectionStrategyOptions,
25
- Request as Request1,
26
- Response as Response1,
27
- SecurityPolicy
25
+ type PerformTransactionCallback,
26
+ type Request as Request1,
27
+ type Response as Response1,
28
+ type SecurityPolicy
28
29
  } from "node-opcua-secure-channel";
29
30
  import {
30
31
  FindServersOnNetworkRequest,
31
- FindServersOnNetworkRequestOptions,
32
+ type FindServersOnNetworkRequestOptions,
32
33
  FindServersOnNetworkResponse,
33
34
  FindServersRequest,
34
35
  FindServersResponse,
35
- ServerOnNetwork
36
+ type ServerOnNetwork
36
37
  } from "node-opcua-service-discovery";
37
38
  import {
38
- ApplicationDescription,
39
- EndpointDescription,
39
+ type ApplicationDescription,
40
+ type EndpointDescription,
40
41
  GetEndpointsRequest,
41
42
  GetEndpointsResponse
42
43
  } from "node-opcua-service-endpoints";
43
- import { ChannelSecurityToken, coerceMessageSecurityMode, MessageSecurityMode } from "node-opcua-service-secure-channel";
44
- import { ErrorCallback, StatusCode, StatusCodes } from "node-opcua-status-code";
45
- import { matchUri, checkFileExistsAndIsNotEmpty } from "node-opcua-utils";
46
-
47
- import { getDefaultCertificateManager, makeSubject, OPCUACertificateManager } from "node-opcua-certificate-manager";
48
- import { VerificationStatus } from "node-opcua-pki";
49
- import { CloseSessionRequest, CloseSessionResponse } from "node-opcua-service-session";
50
- import { Request, Response } from "../common";
51
-
44
+ import { type ChannelSecurityToken, coerceMessageSecurityMode, MessageSecurityMode } from "node-opcua-service-secure-channel";
45
+ import { CloseSessionRequest, type CloseSessionResponse } from "node-opcua-service-session";
46
+ import { type ErrorCallback, StatusCodes } from "node-opcua-status-code";
47
+ import { checkFileExistsAndIsNotEmpty, matchUri } from "node-opcua-utils";
52
48
  import {
53
- CreateSecureChannelCallbackFunc,
54
- FindEndpointCallback,
55
- FindEndpointOptions,
56
- FindEndpointResult,
57
- FindServersOnNetworkRequestLike,
58
- FindServersRequestLike,
59
- GetEndpointsOptions,
49
+ type CreateSecureChannelCallbackFunc,
50
+ type FindEndpointCallback,
51
+ type FindEndpointOptions,
52
+ type FindEndpointResult,
53
+ type FindServersOnNetworkRequestLike,
54
+ type FindServersRequestLike,
55
+ type GetEndpointsOptions,
60
56
  OPCUAClientBase,
61
- OPCUAClientBaseOptions,
62
- TransportSettings
57
+ type OPCUAClientBaseEvents,
58
+ type OPCUAClientBaseOptions,
59
+ type TransportSettings
63
60
  } from "../client_base";
64
- import { UserIdentityInfo } from "../user_identity_info";
61
+ import type { Request, Response } from "../common";
62
+ import type { UserIdentityInfo } from "../user_identity_info";
65
63
  import { performCertificateSanityCheck } from "../verify";
66
- import { ClientSessionImpl } from "./client_session_impl";
67
- import { IClientBase } from "./i_private_client";
68
- import { waitUntilReconnectionIsCanceled } from "./reconnection/client_reconnection";
64
+ import type { ClientSessionImpl } from "./client_session_impl";
65
+ import type { IClientBase } from "./i_private_client";
69
66
 
70
67
  const debugLog = make_debugLog(__filename);
71
68
  const doDebug = checkDebugFlag(__filename);
72
69
  const errorLog = make_errorLog(__filename);
73
70
  const warningLog = make_warningLog(__filename);
71
+
72
+ function makeCertificateThumbPrint(certificate: Certificate | Certificate[] | null | undefined): Buffer | null {
73
+ if (!certificate) return null;
74
+ return makeSHA1Thumbprint(Array.isArray(certificate) ? certificate[0] : certificate);
75
+ }
76
+
74
77
  const traceInternalState = false;
75
78
 
76
79
  const defaultConnectionStrategy: ConnectionStrategyOptions = {
@@ -96,7 +99,7 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
96
99
 
97
100
  const securityMode = params.securityMode;
98
101
  const securityPolicy = params.securityPolicy;
99
- const connectionStrategy = params.connectionStrategy;
102
+ const _connectionStrategy = params.connectionStrategy;
100
103
  const options: OPCUAClientBaseOptions = {
101
104
  applicationName: params.applicationName,
102
105
  applicationUri: params.applicationUri,
@@ -119,10 +122,12 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
119
122
 
120
123
  let selectedEndpoint: EndpointDescription | undefined;
121
124
  const allEndpoints: EndpointDescription[] = [];
122
- const tasks = [
123
- (innerCallback: ErrorCallback) => {
125
+ const step1_connect = (): Promise<void> => {
126
+ return new Promise<void>((resolve, reject) => {
124
127
  // rebind backoff handler
125
- masterClient.listeners("backoff").forEach((handler: any) => client.on("backoff", handler));
128
+ masterClient.listeners("backoff").forEach((handler) => {
129
+ client.on("backoff", handler as unknown as (retryCount: number, delay: number) => void);
130
+ });
126
131
 
127
132
  // c8 ignore next
128
133
  if (doDebug) {
@@ -140,7 +145,6 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
140
145
 
141
146
  client.connect(endpointUrl, (err?: Error) => {
142
147
  if (err) {
143
- // let's improve the error message with meaningful info
144
148
  err.message =
145
149
  "Fail to connect to server at " +
146
150
  endpointUrl +
@@ -149,20 +153,23 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
149
153
  err.message +
150
154
  ")";
151
155
  warningLog(err.message);
156
+ return reject(err);
152
157
  }
153
- return innerCallback(err);
158
+ resolve();
154
159
  });
155
- },
160
+ });
161
+ };
156
162
 
157
- (innerCallback: ErrorCallback) => {
163
+ const step2_getEndpoints = (): Promise<void> => {
164
+ return new Promise<void>((resolve, reject) => {
158
165
  client.getEndpoints((err: Error | null, endpoints?: EndpointDescription[]) => {
159
166
  if (err) {
160
- err.message = "error in getEndpoints \n" + err.message;
161
- return innerCallback(err);
167
+ err.message = `error in getEndpoints \n${err.message}`;
168
+ return reject(err);
162
169
  }
163
170
  // c8 ignore next
164
171
  if (!endpoints) {
165
- return innerCallback(new Error("Internal Error"));
172
+ return reject(new Error("Internal Error"));
166
173
  }
167
174
 
168
175
  for (const endpoint of endpoints) {
@@ -177,55 +184,51 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
177
184
  selectedEndpoint = endpoint; // found it
178
185
  }
179
186
  }
180
- innerCallback();
187
+ resolve();
181
188
  });
182
- },
189
+ });
190
+ };
183
191
 
184
- (innerCallback: ErrorCallback) => {
185
- client.disconnect(innerCallback);
186
- }
187
- ];
192
+ const step3_disconnect = (): Promise<void> => {
193
+ return new Promise<void>((resolve) => {
194
+ client.disconnect(() => resolve());
195
+ });
196
+ };
188
197
 
189
- async.series(tasks, (err) => {
190
- if (err) {
198
+ step1_connect()
199
+ .then(() => step2_getEndpoints())
200
+ .then(() => step3_disconnect())
201
+ .then(() => {
202
+ if (!selectedEndpoint) {
203
+ return callback(
204
+ new Error(
205
+ "Cannot find an Endpoint matching " +
206
+ " security mode: " +
207
+ securityMode.toString() +
208
+ " policy: " +
209
+ securityPolicy.toString()
210
+ )
211
+ );
212
+ }
213
+
214
+ // c8 ignore next
215
+ if (doDebug) {
216
+ debugLog(chalk.bgWhite.red("xxxxxxxxxxxxxxxxxxxxx => selected EndPoint = "), selectedEndpoint.toString());
217
+ }
218
+
219
+ callback(null, { endpoints: allEndpoints, selectedEndpoint });
220
+ })
221
+ .catch((err) => {
191
222
  client.disconnect(() => {
192
223
  callback(err);
193
224
  });
194
- return;
195
- }
196
-
197
- if (!selectedEndpoint) {
198
- return callback(
199
- new Error(
200
- "Cannot find an Endpoint matching " +
201
- " security mode: " +
202
- securityMode.toString() +
203
- " policy: " +
204
- securityPolicy.toString()
205
- )
206
- );
207
- }
208
-
209
- // c8 ignore next
210
- if (doDebug) {
211
- debugLog(chalk.bgWhite.red("xxxxxxxxxxxxxxxxxxxxx => selected EndPoint = "), selectedEndpoint.toString());
212
- }
213
-
214
- const result = {
215
- endpoints: allEndpoints,
216
- selectedEndpoint
217
- };
218
-
219
- callback(null, result);
220
- });
225
+ });
221
226
  }
222
227
 
223
228
  /**
224
229
  * check if certificate is trusted or untrusted
225
230
  */
226
- async function _verify_serverCertificate(
227
- certificateManager: OPCUACertificateManager,
228
- serverCertificate: Certificate) {
231
+ async function _verify_serverCertificate(certificateManager: OPCUACertificateManager, serverCertificate: Certificate) {
229
232
  const status = await certificateManager.checkCertificate(serverCertificate);
230
233
  if (status !== StatusCodes.Good) {
231
234
  // c8 ignore next
@@ -234,9 +237,9 @@ async function _verify_serverCertificate(
234
237
  const status1 = await certificateManager.verifyCertificate(serverCertificate);
235
238
  debugLog(status1);
236
239
  }
237
- warningLog("serverCertificate = ", makeSHA1Thumbprint(serverCertificate).toString("hex"));
240
+ warningLog("serverCertificate = ", makeCertificateThumbPrint(serverCertificate)?.toString("hex") || "none");
238
241
  warningLog("serverCertificate = ", serverCertificate.toString("base64"));
239
- throw new Error("server Certificate verification failed with err " + status?.toString());
242
+ throw new Error(`server Certificate verification failed with err ${status?.toString()}`);
240
243
  }
241
244
  }
242
245
 
@@ -290,7 +293,9 @@ let g_ClientCounter = 0;
290
293
  * @internal
291
294
  */
292
295
  // tslint:disable-next-line: max-classes-per-file
293
- export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase, IClientBase {
296
+ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBaseEvents>
297
+ extends OPCUASecureObject<Events>
298
+ implements OPCUAClientBase<Events>, IClientBase {
294
299
  /**
295
300
  * total number of requests that been canceled due to timeout
296
301
  */
@@ -317,7 +322,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
317
322
  */
318
323
  get isReconnecting(): boolean {
319
324
  return (
320
- !!(this._secureChannel && this._secureChannel.isConnecting) ||
325
+ !!this._secureChannel?.isConnecting ||
321
326
  this._internalState === "reconnecting_newchannel_connected" ||
322
327
  this._internalState === "reconnecting"
323
328
  );
@@ -346,7 +351,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
346
351
 
347
352
  public securityMode: MessageSecurityMode;
348
353
  public securityPolicy: SecurityPolicy;
349
- public serverCertificate?: Certificate;
354
+ public serverCertificate?: Certificate | Certificate[];
350
355
  public clientName: string;
351
356
  public protocolVersion: 0;
352
357
  public defaultSecureTokenLifetime: number;
@@ -412,11 +417,15 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
412
417
 
413
418
  this._internalState = internalState;
414
419
  }
415
- public emit(eventName: string | symbol, ...others: any[]): boolean {
420
+ public emit<K>(eventName: K, ...others: unknown[]): boolean {
416
421
  // c8 ignore next
417
422
  if (doDebug) {
418
- debugLog(chalk.cyan(` Client ${this._instanceNumber} ${this.clientName} emitting `), chalk.magentaBright(eventName));
423
+ debugLog(
424
+ chalk.cyan(` Client ${this._instanceNumber} ${this.clientName} emitting `),
425
+ chalk.magentaBright(eventName as string)
426
+ );
419
427
  }
428
+ // @ts-expect-error
420
429
  return super.emit(eventName, ...others);
421
430
  }
422
431
  constructor(options?: OPCUAClientBaseOptions) {
@@ -464,9 +473,10 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
464
473
  this.defaultTransactionTimeout = options.defaultTransactionTimeout;
465
474
 
466
475
  this.tokenRenewalInterval = options.tokenRenewalInterval || 0;
467
- assert(isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
476
+ assert(Number.isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
468
477
  this.securityMode = coerceMessageSecurityMode(options.securityMode);
469
478
  this.securityPolicy = coerceSecurityPolicy(options.securityPolicy);
479
+
470
480
  this.serverCertificate = options.serverCertificate;
471
481
 
472
482
  this.keepSessionAlive = typeof options.keepSessionAlive === "boolean" ? options.keepSessionAlive : false;
@@ -517,9 +527,6 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
517
527
  this._secureChannel = null;
518
528
  callback();
519
529
  });
520
- this.once("reconnection_canceled", () => {
521
- /* empty */
522
- });
523
530
  }
524
531
 
525
532
  public _recreate_secure_channel(callback: ErrorCallback): void {
@@ -527,7 +534,8 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
527
534
 
528
535
  if (!this.knowsServerEndpoint) {
529
536
  debugLog("Cannot reconnect , server endpoint is unknown");
530
- return callback(new Error("Cannot reconnect, server endpoint is unknown - this.knowsServerEndpoint = false"));
537
+ callback(new Error("Cannot reconnect, server endpoint is unknown - this.knowsServerEndpoint = false"));
538
+ return;
531
539
  }
532
540
  assert(this.knowsServerEndpoint);
533
541
 
@@ -548,7 +556,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
548
556
  const _when_reconnectionIsCanceled = (callback: ErrorCallback) => {
549
557
  doDebug && debugLog("attempt to recreate a new secure channel : suspended because reconnection is canceled !");
550
558
  this.emit("reconnection_canceled");
551
- return callback(new Error("Reconnection has been canceled - " + this.clientName));
559
+ return callback(new Error(`Reconnection has been canceled - ${this.clientName}`));
552
560
  };
553
561
 
554
562
  const _failAndRetry = (err: Error, message: string, callback: ErrorCallback) => {
@@ -597,20 +605,21 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
597
605
  if (err.message.match(/ECONNREFUSED|ECONNABORTED|ETIMEDOUT/)) {
598
606
  return _failAndRetry(
599
607
  err,
600
- "create secure channel failed with ECONNREFUSED|ECONNABORTED|ETIMEDOUT\n" + err.message,
608
+ `create secure channel failed with ECONNREFUSED|ECONNABORTED|ETIMEDOUT\n${err.message}`,
601
609
  callback
602
610
  );
603
611
  }
604
612
 
605
613
  if (err.message.match("Backoff aborted.")) {
606
- return _failAndRetry(err!, "cannot create secure channel (backoff aborted)", callback);
614
+ _failAndRetry(err, "cannot create secure channel (backoff aborted)", callback);
615
+ return;
607
616
  }
608
617
 
609
618
  if (
610
- err!.message.match("BadCertificateInvalid") ||
611
- err!.message.match(/socket has been disconnected by third party/)
619
+ err?.message.match("BadCertificateInvalid") ||
620
+ err?.message.match(/socket has been disconnected by third party/)
612
621
  ) {
613
- // it is possible also that hte server has shutdown innapropriately the connection
622
+ // it is possible also that hte server has shutdown innapropriately the connection
614
623
  warningLog(
615
624
  "the server certificate has changed, we need to retrieve server certificate again: ",
616
625
  err.message
@@ -618,7 +627,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
618
627
  const oldServerCertificate = this.serverCertificate;
619
628
  warningLog(
620
629
  "old server certificate ",
621
- oldServerCertificate ? makeSHA1Thumbprint(oldServerCertificate!).toString("hex") : "undefined"
630
+ makeCertificateThumbPrint(oldServerCertificate)?.toString("hex") || "undefined"
622
631
  );
623
632
  // the server may have shut down the channel because its certificate
624
633
  // has changed ....
@@ -627,11 +636,14 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
627
636
  if (err1) {
628
637
  return _failAndRetry(err1, "Failing to fetch new server certificate", callback);
629
638
  }
630
- const newServerCertificate = this.serverCertificate!;
631
- warningLog("new server certificate ", makeSHA1Thumbprint(newServerCertificate).toString("hex"));
639
+ const newServerCertificate = this.serverCertificate;
640
+ warningLog(
641
+ "new server certificate ",
642
+ makeCertificateThumbPrint(newServerCertificate)?.toString("hex") || "none"
643
+ );
632
644
 
633
- const sha1Old = oldServerCertificate ? makeSHA1Thumbprint(oldServerCertificate!) : null;
634
- const sha1New = newServerCertificate ? makeSHA1Thumbprint(newServerCertificate) : null;
645
+ const sha1Old = makeCertificateThumbPrint(oldServerCertificate)?.toString("hex") || null;
646
+ const sha1New = makeCertificateThumbPrint(newServerCertificate)?.toString("hex") || null;
635
647
  if (sha1Old === sha1New) {
636
648
  warningLog("server certificate has not changed, but was expected to have changed");
637
649
  return _failAndRetry(
@@ -699,60 +711,65 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
699
711
 
700
712
  this.emit("secure_channel_created", secureChannel);
701
713
 
702
- async.series(
703
- [
704
- // ------------------------------------------------- STEP 2 : OpenSecureChannel
705
- (innerCallback: ErrorCallback) => {
706
- debugLog("_internal_create_secure_channel before secureChannel.create");
714
+ const step2_openSecureChannel = (): Promise<void> => {
715
+ return new Promise<void>((resolve, reject) => {
716
+ debugLog("_internal_create_secure_channel before secureChannel.create");
707
717
 
708
- secureChannel.create(this.endpointUrl, (err?: Error) => {
709
- debugLog("_internal_create_secure_channel after secureChannel.create");
718
+ secureChannel.create(this.endpointUrl, (err?: Error) => {
719
+ debugLog("_internal_create_secure_channel after secureChannel.create");
720
+ if (!this._secureChannel) {
721
+ debugLog("_secureChannel has been closed during the transaction !");
722
+ return reject(new Error("Secure Channel Closed"));
723
+ }
724
+ if (err) {
725
+ return reject(err);
726
+ }
727
+ this._install_secure_channel_event_handlers(secureChannel);
728
+ resolve();
729
+ });
730
+ });
731
+ };
732
+
733
+ const step3_getEndpoints = (): Promise<void> => {
734
+ return new Promise<void>((resolve, reject) => {
735
+ assert(this._secureChannel !== null);
736
+ if (!this.knowsServerEndpoint) {
737
+ this._setInternalState("connecting");
738
+
739
+ this.getEndpoints((err: Error | null /*, endpoints?: EndpointDescription[]*/) => {
710
740
  if (!this._secureChannel) {
711
- debugLog("_secureChannel has been closed during the transaction !");
712
- return innerCallback(new Error("Secure Channel Closed"));
741
+ debugLog("_secureChannel has been closed during the transaction ! (while getEndpoints)");
742
+ return reject(new Error("Secure Channel Closed"));
713
743
  }
714
- if (!err) {
715
- this._install_secure_channel_event_handlers(secureChannel);
744
+ if (err) {
745
+ return reject(err);
716
746
  }
717
- innerCallback(err);
747
+ resolve();
718
748
  });
719
- },
720
- // ------------------------------------------------- STEP 3 : GetEndpointsRequest
721
- (innerCallback: ErrorCallback) => {
722
- assert(this._secureChannel !== null);
723
- if (!this.knowsServerEndpoint) {
724
- this._setInternalState("connecting");
725
-
726
- this.getEndpoints((err: Error | null /*, endpoints?: EndpointDescription[]*/) => {
727
- if (!this._secureChannel) {
728
- debugLog("_secureChannel has been closed during the transaction ! (while getEndpoints)");
729
- return innerCallback(new Error("Secure Channel Closed"));
730
- }
731
- innerCallback(err ? err : undefined);
732
- });
733
- } else {
734
- // end points are already known
735
- innerCallback();
736
- }
749
+ } else {
750
+ // end points are already known
751
+ resolve();
737
752
  }
738
- ],
739
- (err) => {
740
- if (err) {
741
- doDebug && debugLog(this.clientName, " : Inner create secure channel has failed", err.message);
742
- if (this._secureChannel) {
743
- this._secureChannel!.abortConnection(() => {
744
- this._destroy_secure_channel();
745
- callback(err);
746
- });
747
- } else {
753
+ });
754
+ };
755
+
756
+ step2_openSecureChannel()
757
+ .then(() => step3_getEndpoints())
758
+ .then(() => {
759
+ assert(this._secureChannel !== null);
760
+ callback(null, secureChannel);
761
+ })
762
+ .catch((err) => {
763
+ doDebug && debugLog(this.clientName, " : Inner create secure channel has failed", err.message);
764
+ if (this._secureChannel) {
765
+ this._secureChannel.abortConnection(() => {
766
+ this._destroy_secure_channel();
748
767
  callback(err);
749
- }
768
+ });
750
769
  } else {
751
- assert(this._secureChannel !== null);
752
- callback(null, secureChannel);
770
+ callback(err);
753
771
  }
754
- }
755
- );
772
+ });
756
773
  }
757
774
 
758
775
  static async createCertificate(
@@ -776,19 +793,19 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
776
793
  }
777
794
  // c8 ignore next
778
795
  if (!fs.existsSync(certificateFile)) {
779
- throw new Error(" cannot locate certificate file " + certificateFile);
796
+ throw new Error(` cannot locate certificate file ${certificateFile}`);
780
797
  }
781
798
  }
782
799
 
783
800
  public async createDefaultCertificate(): Promise<void> {
784
801
  // c8 ignore next
785
- if ((this as any)._inCreateDefaultCertificate) {
802
+ if ((this as unknown as { _inCreateDefaultCertificate: boolean })._inCreateDefaultCertificate) {
786
803
  errorLog("Internal error : re-entrancy in createDefaultCertificate!");
787
804
  }
788
- (this as any)._inCreateDefaultCertificate = true;
805
+ (this as unknown as { _inCreateDefaultCertificate: boolean })._inCreateDefaultCertificate = true;
789
806
 
790
807
  if (!checkFileExistsAndIsNotEmpty(this.certificateFile)) {
791
- await withLock({ fileToLock: this.certificateFile + ".mutex" }, async () => {
808
+ await withLock({ fileToLock: `${this.certificateFile}.mutex` }, async () => {
792
809
  if (checkFileExistsAndIsNotEmpty(this.certificateFile)) {
793
810
  // the file may have been created in between
794
811
  return;
@@ -804,11 +821,11 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
804
821
  debugLog("privateKey = ", this.privateKeyFile);
805
822
  debugLog(" = ", this.clientCertificateManager.privateKey);
806
823
  debugLog("certificateFile = ", this.certificateFile);
807
- const certificate = this.getCertificate();
808
- const privateKey = this.getPrivateKey();
824
+ const _certificate = this.getCertificate();
825
+ const _privateKey = this.getPrivateKey();
809
826
  });
810
827
  }
811
- (this as any)._inCreateDefaultCertificate = false;
828
+ (this as unknown as { _inCreateDefaultCertificate: boolean })._inCreateDefaultCertificate = false;
812
829
  }
813
830
 
814
831
  protected _getBuiltApplicationUri(): string {
@@ -833,7 +850,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
833
850
  await this.createDefaultCertificate();
834
851
  // c8 ignore next
835
852
  if (!fs.existsSync(this.privateKeyFile)) {
836
- throw new Error(" cannot locate private key file " + this.privateKeyFile);
853
+ throw new Error(` cannot locate private key file ${this.privateKeyFile}`);
837
854
  }
838
855
  if (this.isUnusable()) return;
839
856
 
@@ -850,13 +867,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
850
867
  debugLog(err.message);
851
868
  this.emit("connection_failed", err);
852
869
  this._setInternalState("disconnected");
853
- return callback(err);
870
+ callback(err);
854
871
  }
855
872
  private _handleDisconnectionWhileConnecting(err: Error, callback: ErrorCallback) {
856
873
  debugLog(err.message);
857
874
  this.emit("connection_failed", err);
858
875
  this._setInternalState("disconnected");
859
- return callback(err);
876
+ callback(err);
860
877
  }
861
878
  private _handleSuccessfulConnection(callback: ErrorCallback) {
862
879
  debugLog(" Connected successfully to ", this.endpointUrl);
@@ -870,12 +887,12 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
870
887
  */
871
888
  public connect(endpointUrl: string): Promise<void>;
872
889
  public connect(endpointUrl: string, callback: ErrorCallback): void;
873
- public connect(...args: any[]): any {
890
+ public connect(...args: unknown[]): Promise<void> | void {
874
891
  const endpointUrl = args[0];
875
- const callback = args[1];
892
+ const callback = args[1] as ErrorCallback;
876
893
  assert(typeof callback === "function", "expecting a callback");
877
894
  if (typeof endpointUrl !== "string" || endpointUrl.length <= 0) {
878
- errorLog("[NODE-OPCUA-E03] OPCUAClient#connect expects a valid endpoint : " + endpointUrl);
895
+ errorLog(`[NODE-OPCUA-E03] OPCUAClient#connect expects a valid endpoint : ${endpointUrl}`);
879
896
  callback(new Error("Invalid endpoint"));
880
897
  return;
881
898
  }
@@ -916,7 +933,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
916
933
  }
917
934
  if (forceEndpointDiscoveryOnConnect) {
918
935
  debugLog("connecting with adjusted endpoint : ", adjustedEndpointUrl, " was =", endpointUrl);
919
- this._connectStep2(adjustedEndpointUrl!, callback);
936
+ this._connectStep2(adjustedEndpointUrl || "", callback);
920
937
  } else {
921
938
  debugLog("connecting with endpoint : ", endpointUrl);
922
939
  this._connectStep2(endpointUrl, callback);
@@ -955,15 +972,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
955
972
  }
956
973
  debugLog(chalk.red("SecureChannel creation has failed with error :", err.message));
957
974
  if (err.message.match(/ECONNABORTED/)) {
958
- debugLog(chalk.yellow("- The client cannot to :" + endpointUrl + ". Connection has been aborted."));
975
+ debugLog(chalk.yellow(`- The client cannot to :${endpointUrl}. Connection has been aborted.`));
959
976
  err = new Error("The connection has been aborted");
960
977
  this._handleUnrecoverableConnectionFailure(err, callback);
961
978
  } else if (err.message.match(/ECONNREF/)) {
962
- debugLog(chalk.yellow("- The client cannot to :" + endpointUrl + ". Server is not reachable."));
979
+ debugLog(chalk.yellow(`- The client cannot to :${endpointUrl}. Server is not reachable.`));
963
980
  err = new Error(
964
- "The connection cannot be established with server " +
965
- endpointUrl +
966
- " .\n" +
981
+ `The connection cannot be established with server ${endpointUrl} .\n` +
967
982
  "Please check that the server is up and running or your network configuration.\n" +
968
983
  "Err = (" +
969
984
  err.message +
@@ -974,7 +989,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
974
989
  /* */
975
990
  this._handleDisconnectionWhileConnecting(err, callback);
976
991
  } else {
977
- err = new Error("The connection may have been rejected by server,\n" + "Err = (" + err.message + ")");
992
+ err = new Error(`The connection may have been rejected by server,\n Err = (${err.message})`);
978
993
  this._handleUnrecoverableConnectionFailure(err, callback);
979
994
  }
980
995
  }
@@ -985,9 +1000,10 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
985
1000
  if (!this._secureChannel) {
986
1001
  // this may happen if the Server has closed the connection abruptly for some unknown reason
987
1002
  // or if the tcp connection has been broken.
988
- return callback(
1003
+ callback(
989
1004
  new Error("performMessageTransaction: No SecureChannel , connection may have been canceled abruptly by server")
990
1005
  );
1006
+ return;
991
1007
  }
992
1008
  if (
993
1009
  this._internalState !== "connected" &&
@@ -995,7 +1011,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
995
1011
  this._internalState !== "connecting" &&
996
1012
  this._internalState !== "reconnecting"
997
1013
  ) {
998
- return callback(
1014
+ callback(
999
1015
  new Error(
1000
1016
  "performMessageTransaction: Invalid client state = " +
1001
1017
  this._internalState +
@@ -1003,12 +1019,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1003
1019
  request.schema.name
1004
1020
  )
1005
1021
  );
1022
+ return;
1006
1023
  }
1007
1024
  assert(this._secureChannel);
1008
1025
  assert(request);
1009
1026
  assert(request.requestHeader);
1010
1027
  assert(typeof callback === "function");
1011
- this._secureChannel.performMessageTransaction(request, callback as any);
1028
+ this._secureChannel.performMessageTransaction(request, callback as unknown as PerformTransactionCallback);
1012
1029
  }
1013
1030
 
1014
1031
  /**
@@ -1054,9 +1071,10 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1054
1071
  public async getEndpoints(options?: GetEndpointsOptions): Promise<EndpointDescription[]>;
1055
1072
  public getEndpoints(options: GetEndpointsOptions, callback: ResponseCallback<EndpointDescription[]>): void;
1056
1073
  public getEndpoints(callback: ResponseCallback<EndpointDescription[]>): void;
1057
- public getEndpoints(...args: any[]): any {
1074
+ public getEndpoints(...args: unknown[]): Promise<EndpointDescription[]> | undefined {
1058
1075
  if (args.length === 1) {
1059
- return this.getEndpoints({}, args[0]);
1076
+ this.getEndpoints({} as GetEndpointsOptions, args[0] as unknown as ResponseCallback<EndpointDescription[]>);
1077
+ return;
1060
1078
  }
1061
1079
  const options = args[0] as GetEndpointsOptions;
1062
1080
  const callback = args[1] as ResponseCallback<EndpointDescription[]>;
@@ -1076,18 +1094,21 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1076
1094
 
1077
1095
  this.performMessageTransaction(request, (err: Error | null, response?: Response) => {
1078
1096
  if (err) {
1079
- return callback(err);
1097
+ callback(err);
1098
+ return;
1080
1099
  }
1081
1100
  this._serverEndpoints = [];
1082
1101
  // c8 ignore next
1083
1102
  if (!response || !(response instanceof GetEndpointsResponse)) {
1084
- return callback(new Error("Internal Error"));
1103
+ callback(new Error("Internal Error"));
1104
+ return;
1085
1105
  }
1086
- if (response && response.endpoints) {
1106
+ if (response?.endpoints) {
1087
1107
  this._serverEndpoints = response.endpoints;
1088
1108
  }
1089
1109
  callback(null, this._serverEndpoints);
1090
1110
  });
1111
+ return;
1091
1112
  }
1092
1113
 
1093
1114
  /**
@@ -1095,7 +1116,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1095
1116
  */
1096
1117
  public getEndpointsRequest(options: GetEndpointsOptions, callback: ResponseCallback<EndpointDescription[]>): void {
1097
1118
  warningLog("note: ClientBaseImpl#getEndpointsRequest is deprecated, use ClientBaseImpl#getEndpoints instead");
1098
- return this.getEndpoints(options, callback);
1119
+ this.getEndpoints(options, callback);
1099
1120
  }
1100
1121
 
1101
1122
  /**
@@ -1104,9 +1125,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1104
1125
  public findServers(options?: FindServersRequestLike): Promise<ApplicationDescription[]>;
1105
1126
  public findServers(options: FindServersRequestLike, callback: ResponseCallback<ApplicationDescription[]>): void;
1106
1127
  public findServers(callback: ResponseCallback<ApplicationDescription[]>): void;
1107
- public findServers(...args: any[]): any {
1128
+ public findServers(...args: unknown[]): Promise<ApplicationDescription[]> | undefined {
1108
1129
  if (args.length === 1) {
1109
- return this.findServers({}, args[0]);
1130
+ if (typeof args[0] === "function") {
1131
+ this.findServers({} as FindServersRequestLike, args[0] as ResponseCallback<ApplicationDescription[]>);
1132
+ return;
1133
+ }
1134
+ throw new Error("Invalid arguments");
1110
1135
  }
1111
1136
  const options = args[0] as FindServersRequestLike;
1112
1137
  const callback = args[1] as ResponseCallback<ApplicationDescription[]>;
@@ -1119,24 +1144,28 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1119
1144
 
1120
1145
  this.performMessageTransaction(request, (err: Error | null, response?: Response) => {
1121
1146
  if (err) {
1122
- return callback(err);
1147
+ callback(err);
1148
+ return;
1123
1149
  }
1124
1150
  /* c8 ignore next */
1125
1151
  if (!response || !(response instanceof FindServersResponse)) {
1126
- return callback(new Error("Internal Error"));
1152
+ callback(new Error("Internal Error"));
1153
+ return;
1127
1154
  }
1128
1155
  response.servers = response.servers || [];
1129
1156
 
1130
1157
  callback(null, response.servers);
1131
1158
  });
1159
+ return undefined;
1132
1160
  }
1133
1161
 
1134
1162
  public findServersOnNetwork(options?: FindServersOnNetworkRequestLike): Promise<ServerOnNetwork[]>;
1135
1163
  public findServersOnNetwork(callback: ResponseCallback<ServerOnNetwork[]>): void;
1136
1164
  public findServersOnNetwork(options: FindServersOnNetworkRequestLike, callback: ResponseCallback<ServerOnNetwork[]>): void;
1137
- public findServersOnNetwork(...args: any[]): any {
1165
+ public findServersOnNetwork(...args: unknown[]): Promise<ServerOnNetwork[]> | undefined {
1138
1166
  if (args.length === 1) {
1139
- return this.findServersOnNetwork({}, args[0]);
1167
+ this.findServersOnNetwork({} as FindServersOnNetworkRequestOptions, args[0] as ResponseCallback<ServerOnNetwork[]>);
1168
+ return undefined;
1140
1169
  }
1141
1170
  const options = args[0] as FindServersOnNetworkRequestOptions;
1142
1171
  const callback = args[1] as ResponseCallback<ServerOnNetwork[]>;
@@ -1144,21 +1173,24 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1144
1173
 
1145
1174
  this.performMessageTransaction(request, (err: Error | null, response?: Response) => {
1146
1175
  if (err) {
1147
- return callback(err);
1176
+ callback(err);
1177
+ return;
1148
1178
  }
1149
1179
  /* c8 ignore next */
1150
1180
  if (!response || !(response instanceof FindServersOnNetworkResponse)) {
1151
- return new Error("Internal Error");
1181
+ callback(new Error("Internal Error"));
1182
+ return;
1152
1183
  }
1153
1184
  response.servers = response.servers || [];
1154
1185
  callback(null, response.servers);
1155
1186
  });
1187
+ return undefined;
1156
1188
  }
1157
1189
 
1158
1190
  public _removeSession(session: ClientSessionImpl): void {
1159
1191
  const index = this._sessions.indexOf(session);
1160
1192
  if (index >= 0) {
1161
- const s = this._sessions.splice(index, 1)[0];
1193
+ const _s = this._sessions.splice(index, 1)[0];
1162
1194
  // assert(s === session);
1163
1195
  // assert(session._client === this);
1164
1196
  session._client = null;
@@ -1183,7 +1215,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1183
1215
  return callback(null);
1184
1216
  }
1185
1217
 
1186
- debugLog(chalk.bgWhite.green("_closeSession ") + this._secureChannel!.channelId);
1218
+ debugLog(chalk.bgWhite.green("_closeSession ") + this._secureChannel.channelId);
1187
1219
 
1188
1220
  const request = new CloseSessionRequest({
1189
1221
  deleteSubscriptions
@@ -1198,19 +1230,16 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1198
1230
  });
1199
1231
  }
1200
1232
 
1201
- public closeSession(...args: any[]): any {
1202
- const session = args[0] as ClientSessionImpl;
1203
- const deleteSubscriptions = args[1];
1204
- const callback = args[2];
1205
-
1233
+ public closeSession(session: ClientSessionImpl, deleteSubscriptions: boolean): Promise<void>;
1234
+ public closeSession(session: ClientSessionImpl, deleteSubscriptions: boolean, callback: ErrorCallback): void;
1235
+ public closeSession(session: ClientSessionImpl, deleteSubscriptions: boolean, callback?: ErrorCallback): Promise<void> | void {
1206
1236
  assert(typeof deleteSubscriptions === "boolean");
1207
- assert(typeof callback === "function");
1208
1237
  assert(session);
1209
1238
  assert(session._client === this, "session must be attached to this");
1210
1239
  session._closed = true;
1211
1240
 
1212
1241
  // todo : send close session on secure channel
1213
- this._closeSession(session, deleteSubscriptions, (err?: Error | null, response?: CloseSessionResponse) => {
1242
+ this._closeSession(session, deleteSubscriptions, (err?: Error | null, _response?: CloseSessionResponse) => {
1214
1243
  session.emitCloseEvent(StatusCodes.Good);
1215
1244
 
1216
1245
  this._removeSession(session);
@@ -1219,34 +1248,38 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1219
1248
  assert(this._sessions.indexOf(session) === -1);
1220
1249
  assert(session._closed, "session must indicate it is closed");
1221
1250
 
1222
- callback(err ? err : undefined);
1251
+ callback?.(err ? err : undefined);
1223
1252
  });
1224
1253
  }
1225
1254
 
1226
1255
  public disconnect(): Promise<void>;
1227
1256
  public disconnect(callback: ErrorCallback): void;
1228
1257
  // eslint-disable-next-line max-statements
1229
- public disconnect(...args: any[]): any {
1230
- const callback = args[0];
1258
+ public disconnect(...args: unknown[]): undefined | Promise<void> {
1259
+ const callback = args[0] as ErrorCallback;
1231
1260
  assert(typeof callback === "function", "expecting a callback function here");
1232
1261
  this._reconnectionIsCanceled = true;
1233
1262
  if (this._tmpClient) {
1234
1263
  warningLog("disconnecting client while tmpClient exists", this._tmpClient.clientName);
1235
- this._tmpClient.disconnect((err) => {
1264
+ this._tmpClient.disconnect((_err) => {
1236
1265
  this._tmpClient = undefined;
1237
1266
  // retry disconnect on main client
1238
1267
  this.disconnect(callback);
1239
1268
  });
1240
- return;
1269
+ return undefined;
1241
1270
  }
1242
1271
  if (this._internalState === "disconnected" || this._internalState === "disconnecting") {
1243
1272
  if (this._internalState === "disconnecting") {
1244
- warningLog("[NODE-OPCUA-W26] OPCUAClient#disconnect called while already disconnecting. clientName=", this.clientName);
1273
+ warningLog(
1274
+ "[NODE-OPCUA-W26] OPCUAClient#disconnect called while already disconnecting. clientName=",
1275
+ this.clientName
1276
+ );
1245
1277
  }
1246
1278
  if (!this._reconnectionIsCanceled && this.isReconnecting) {
1247
1279
  errorLog("Internal Error : _reconnectionIsCanceled should be true if isReconnecting is true");
1248
1280
  }
1249
- return callback();
1281
+ callback();
1282
+ return undefined;
1250
1283
  }
1251
1284
  debugLog("disconnecting client! (will set reconnectionIsCanceled to true");
1252
1285
  this._reconnectionIsCanceled = true;
@@ -1262,7 +1295,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1262
1295
  // sessions cannot be cancelled properly and must be discarded.
1263
1296
  this.disconnect(callback);
1264
1297
  });
1265
- return;
1298
+ return undefined;
1266
1299
  }
1267
1300
 
1268
1301
  if (this._sessions.length && !this.keepPendingSessionsOnDisconnect) {
@@ -1272,7 +1305,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1272
1305
  this._close_pending_sessions((/*err*/) => {
1273
1306
  this.disconnect(callback);
1274
1307
  });
1275
- return;
1308
+ return undefined;
1276
1309
  }
1277
1310
 
1278
1311
  debugLog("Disconnecting !");
@@ -1302,7 +1335,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1302
1335
  }
1303
1336
 
1304
1337
  if (this._secureChannel) {
1305
- let tmpChannel: any = this._secureChannel;
1338
+ let tmpChannel: ClientSecureChannelLayer | null = this._secureChannel;
1306
1339
  this._secureChannel = null;
1307
1340
  debugLog("Closing channel");
1308
1341
  tmpChannel.close(() => {
@@ -1317,6 +1350,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1317
1350
  // this.emit("close", null);
1318
1351
  callback();
1319
1352
  }
1353
+ return undefined;
1320
1354
  }
1321
1355
 
1322
1356
  // override me !
@@ -1326,36 +1360,34 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1326
1360
 
1327
1361
  public toString(): string {
1328
1362
  let str = "\n";
1329
- str += " defaultSecureTokenLifetime.... " + this.defaultSecureTokenLifetime + "\n";
1330
- str += " securityMode.................. " + MessageSecurityMode[this.securityMode] + "\n";
1331
- str += " securityPolicy................ " + this.securityPolicy.toString() + "\n";
1332
- str += " certificate fingerprint....... " + makeSHA1Thumbprint(this.getCertificate()).toString("hex") + "\n";
1333
- str +=
1334
- " server certificate fingerprint " +
1335
- (this.serverCertificate ? makeSHA1Thumbprint(this.serverCertificate).toString("hex") : "") +
1336
- "\n";
1363
+ str += ` defaultSecureTokenLifetime.... ${this.defaultSecureTokenLifetime}\n`;
1364
+ str += ` securityMode.................. ${MessageSecurityMode[this.securityMode]}\n`;
1365
+ str += ` securityPolicy................ ${this.securityPolicy.toString()}\n`;
1366
+ str += ` certificate fingerprint....... ${makeCertificateThumbPrint(this.getCertificate())?.toString("hex") || "none"}\n`;
1367
+
1368
+ str += ` server certificate fingerprint ${makeCertificateThumbPrint(this.serverCertificate)?.toString("hex") || "none"}\n`;
1337
1369
  // this.serverCertificate = options.serverCertificate || null + "\n";
1338
- str += " keepSessionAlive.............. " + this.keepSessionAlive + "\n";
1339
- str += " bytesRead..................... " + this.bytesRead + "\n";
1340
- str += " bytesWritten.................. " + this.bytesWritten + "\n";
1341
- str += " transactionsPerformed......... " + this.transactionsPerformed + "\n";
1342
- str += " timedOutRequestCount.......... " + this.timedOutRequestCount + "\n";
1370
+ str += ` keepSessionAlive.............. ${this.keepSessionAlive}\n`;
1371
+ str += ` bytesRead..................... ${this.bytesRead}\n`;
1372
+ str += ` bytesWritten.................. ${this.bytesWritten}\n`;
1373
+ str += ` transactionsPerformed......... ${this.transactionsPerformed}\n`;
1374
+ str += ` timedOutRequestCount.......... ${this.timedOutRequestCount}\n`;
1343
1375
  str += " connectionStrategy." + "\n";
1344
- str += " .maxRetry............... " + this.connectionStrategy.maxRetry + "\n";
1345
- str += " .initialDelay........... " + this.connectionStrategy.initialDelay + "\n";
1346
- str += " .maxDelay............... " + this.connectionStrategy.maxDelay + "\n";
1347
- str += " .randomisationFactor.... " + this.connectionStrategy.randomisationFactor + "\n";
1348
- str += " keepSessionAlive.............. " + this.keepSessionAlive + "\n";
1349
- str += " applicationName............... " + this.applicationName + "\n";
1350
- str += " applicationUri................ " + this._getBuiltApplicationUri() + "\n";
1351
- str += " clientName.................... " + this.clientName + "\n";
1352
- str += " reconnectOnFailure............ " + this.reconnectOnFailure + "\n";
1353
- str += " isReconnecting................ " + this.isReconnecting + "\n";
1354
- str += " (internal state).............. " + this._internalState + "\n";
1355
- str += " sessions count................ " + this.getSessions().length + "\n";
1376
+ str += ` .maxRetry............... ${this.connectionStrategy.maxRetry}\n`;
1377
+ str += ` .initialDelay........... ${this.connectionStrategy.initialDelay}\n`;
1378
+ str += ` .maxDelay............... ${this.connectionStrategy.maxDelay}\n`;
1379
+ str += ` .randomisationFactor.... ${this.connectionStrategy.randomisationFactor}\n`;
1380
+ str += ` keepSessionAlive.............. ${this.keepSessionAlive}\n`;
1381
+ str += ` applicationName............... ${this.applicationName}\n`;
1382
+ str += ` applicationUri................ ${this._getBuiltApplicationUri()}\n`;
1383
+ str += ` clientName.................... ${this.clientName}\n`;
1384
+ str += ` reconnectOnFailure............ ${this.reconnectOnFailure}\n`;
1385
+ str += ` isReconnecting................ ${this.isReconnecting}\n`;
1386
+ str += ` (internal state).............. ${this._internalState}\n`;
1387
+ str += ` sessions count................ ${this.getSessions().length}\n`;
1356
1388
 
1357
1389
  if (this._secureChannel) {
1358
- str += "secureChannel:\n" + this._secureChannel.toString();
1390
+ str += `secureChannel:\n${this._secureChannel.toString()}`;
1359
1391
  }
1360
1392
  return str;
1361
1393
  }
@@ -1365,7 +1397,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1365
1397
  }
1366
1398
 
1367
1399
  public getTransportSettings(): IBasicTransportSettings {
1368
- return this._secureChannel!.getTransportSettings();
1400
+ return this._secureChannel?.getTransportSettings() || ({} as IBasicTransportSettings);
1369
1401
  }
1370
1402
 
1371
1403
  protected _addSession(session: ClientSessionImpl): void {
@@ -1412,15 +1444,17 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1412
1444
 
1413
1445
  clientCertificateManager: this.clientCertificateManager
1414
1446
  };
1415
- return __findEndpoint.call(this, discoveryUrl, params, (err: Error | null, result?: FindEndpointResult) => {
1447
+ __findEndpoint.call(this, discoveryUrl, params, (err: Error | null, result?: FindEndpointResult) => {
1416
1448
  if (err) {
1417
- return callback(err);
1449
+ callback(err);
1450
+ return;
1418
1451
  }
1419
1452
 
1420
1453
  // c8 ignore next
1421
1454
  if (!result) {
1422
1455
  const err1 = new Error("internal error");
1423
- return callback(err1);
1456
+ callback(err1);
1457
+ return;
1424
1458
  }
1425
1459
 
1426
1460
  const endpoint = result.selectedEndpoint;
@@ -1432,7 +1466,8 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1432
1466
  " policy = " +
1433
1467
  this.securityPolicy
1434
1468
  );
1435
- return callback(err1);
1469
+ callback(err1);
1470
+ return;
1436
1471
  }
1437
1472
 
1438
1473
  assert(endpoint);
@@ -1440,20 +1475,20 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1440
1475
  _verify_serverCertificate(this.clientCertificateManager, endpoint.serverCertificate)
1441
1476
  .then(() => {
1442
1477
  this.serverCertificate = endpoint.serverCertificate;
1443
- callback(null, endpoint.endpointUrl!);
1478
+ callback(null, endpoint.endpointUrl || "");
1444
1479
  })
1445
1480
  .catch((err1: Error) => {
1446
1481
  warningLog("[NODE-OPCUA-W25] client's server certificate verification has failed ", err1.message);
1447
1482
  warningLog(" clientCertificateManager.rootDir = ", this.clientCertificateManager.rootDir);
1448
1483
 
1449
1484
  const f = (b: Buffer) =>
1450
- " " + b.toString("base64").replace(/(.{80})/g, "$1\n ");
1485
+ ` ${b.toString("base64").replace(/(.{80})/g, "$1\n ")}`;
1451
1486
 
1452
1487
  const chain = split_der(endpoint.serverCertificate);
1453
1488
  warningLog(` server certificate contains ${chain.length} elements`);
1454
1489
  for (let i = 0; i < chain.length; i++) {
1455
1490
  const c = chain[i];
1456
- warningLog("certificate", i, "\n" + f(c));
1491
+ warningLog("certificate", i, `\n${f(c)}`);
1457
1492
  }
1458
1493
  if (chain.length > 1) {
1459
1494
  warningLog(
@@ -1466,7 +1501,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1466
1501
  " verify that the server certificate is trusted or that server certificate issuer's certificate is present in the issuer folder"
1467
1502
  );
1468
1503
  }
1469
- return callback(err1);
1504
+ callback(err1);
1470
1505
  });
1471
1506
  });
1472
1507
  }
@@ -1507,30 +1542,27 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1507
1542
 
1508
1543
  private _close_pending_sessions(callback: ErrorCallback) {
1509
1544
  const sessions = [...this._sessions];
1510
- async.map(
1511
- sessions,
1512
- (session: ClientSessionImpl, next: () => void) => {
1513
- assert(session._client === this);
1514
-
1515
- // note: to prevent next to be call twice
1516
- let _next_already_call = false;
1517
- session.close((err?: Error) => {
1518
- if (_next_already_call) {
1519
- return;
1520
- }
1521
- _next_already_call = true;
1522
1545
 
1523
- // We should not bother if we have an error here
1524
- // Session may fail to close , if they haven't been activate and forcefully closed by server
1525
- // in a attempt to preserve resources in the case of a DDOS attack for instance.
1526
- if (err) {
1527
- const msg = session.authenticationToken ? session.authenticationToken.toString() : "";
1528
- debugLog(" failing to close session " + msg);
1529
- }
1530
- next();
1546
+ const closeAll = async (): Promise<void> => {
1547
+ for (const session of sessions) {
1548
+ assert(session._client === this);
1549
+ await new Promise<void>((resolve) => {
1550
+ let resolved = false;
1551
+ session.close((err?: Error) => {
1552
+ if (resolved) return;
1553
+ resolved = true;
1554
+ if (err) {
1555
+ const msg = session.authenticationToken ? session.authenticationToken.toString() : "";
1556
+ debugLog(` failing to close session ${msg}`);
1557
+ }
1558
+ resolve();
1559
+ });
1531
1560
  });
1532
- },
1533
- (err) => {
1561
+ }
1562
+ };
1563
+
1564
+ closeAll()
1565
+ .then(() => {
1534
1566
  // c8 ignore next
1535
1567
  if (this._sessions.length > 0) {
1536
1568
  debugLog(
@@ -1540,9 +1572,9 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1540
1572
  );
1541
1573
  }
1542
1574
  assert(this._sessions.length === 0, " failed to disconnect exiting sessions ");
1543
- callback(err!);
1544
- }
1545
- );
1575
+ callback();
1576
+ })
1577
+ .catch((err) => callback(err));
1546
1578
  }
1547
1579
 
1548
1580
  private _install_secure_channel_event_handlers(secureChannel: ClientSecureChannelLayer) {
@@ -1572,7 +1604,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1572
1604
  * @event send_request
1573
1605
  * @param message
1574
1606
  */
1575
- this.emit("send_request", message);
1607
+ this.emit("send_request", message as unknown as Request);
1576
1608
  });
1577
1609
 
1578
1610
  secureChannel.on("receive_response", (message: Response1) => {
@@ -1581,7 +1613,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1581
1613
  * @event receive_response
1582
1614
  * @param message
1583
1615
  */
1584
- this.emit("receive_response", message);
1616
+ this.emit("receive_response", message as unknown as Response);
1585
1617
  });
1586
1618
 
1587
1619
  secureChannel.on("lifetime_75", (token: ChannelSecurityToken) => {
@@ -1594,7 +1626,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1594
1626
  " is about to expired , it's time to request a new token"
1595
1627
  );
1596
1628
  // forward message to upper level
1597
- this.emit("lifetime_75", token, secureChannel);
1629
+ this.emit("lifetime_75", token);
1598
1630
  });
1599
1631
 
1600
1632
  secureChannel.on("security_token_renewed", (token: ChannelSecurityToken) => {
@@ -1613,7 +1645,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1613
1645
  /**
1614
1646
  * @event connection_lost
1615
1647
  */
1616
- this.emit("connection_lost", err?.message); // instead of "close"
1648
+ this.emit("connection_lost"); // instead of "close"
1617
1649
  }
1618
1650
  // this is a normal close operation initiated by us
1619
1651
  this.emit("close", err); // instead of "close"
@@ -1628,7 +1660,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1628
1660
  /**
1629
1661
  * @event connection_lost
1630
1662
  */
1631
- this.emit("connection_lost", err?.message); // instead of "close"
1663
+ this.emit("connection_lost"); // instead of "close"
1632
1664
  this._repairConnection();
1633
1665
  }
1634
1666
  }
@@ -1640,7 +1672,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1640
1672
  * @event timed_out_request
1641
1673
  * @param request
1642
1674
  */
1643
- this.emit("timed_out_request", request);
1675
+ this.emit("timed_out_request", request as unknown as Request);
1644
1676
  });
1645
1677
  }
1646
1678
 
@@ -1676,7 +1708,12 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1676
1708
 
1677
1709
  debugLog("Entering _repairConnection ", this._internalState);
1678
1710
  if (this.#insideRepairConnection) {
1679
- errorLog("_repairConnection already in progress internal state = ", this._internalState, "clientName =", this.clientName);
1711
+ errorLog(
1712
+ "_repairConnection already in progress internal state = ",
1713
+ this._internalState,
1714
+ "clientName =",
1715
+ this.clientName
1716
+ );
1680
1717
  this.#shouldRepairAgain = true;
1681
1718
  return;
1682
1719
  }
@@ -1748,15 +1785,15 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1748
1785
  * @private
1749
1786
  */
1750
1787
  public __createSession_step2(
1751
- session: ClientSessionImpl,
1752
- callback: (err: Error | null, session?: ClientSessionImpl) => void
1788
+ _session: ClientSessionImpl,
1789
+ _callback: (err: Error | null, session?: ClientSessionImpl) => void
1753
1790
  ): void {
1754
1791
  throw new Error("Please override");
1755
1792
  }
1756
1793
  public _activateSession(
1757
- session: ClientSessionImpl,
1758
- userIdentity: UserIdentityInfo,
1759
- callback: (err: Error | null, session?: ClientSessionImpl) => void
1794
+ _session: ClientSessionImpl,
1795
+ _userIdentity: UserIdentityInfo,
1796
+ _callback: (err: Error | null, session?: ClientSessionImpl) => void
1760
1797
  ): void {
1761
1798
  throw new Error("Please override");
1762
1799
  }
@@ -1765,27 +1802,28 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
1765
1802
  // tslint:disable-next-line: max-classes-per-file
1766
1803
  class TmpClient extends ClientBaseImpl {
1767
1804
  constructor(options: OPCUAClientBaseOptions) {
1768
- options.clientName = (options.clientName || "") + "_TmpClient";
1805
+ options.clientName = `${options.clientName || ""}_TmpClient`;
1769
1806
  super(options);
1770
1807
  }
1771
1808
 
1772
1809
  async connect(endpoint: string): Promise<void>;
1773
1810
  connect(endpoint: string, callback: ErrorCallback): void;
1774
- connect(endpoint: string, callback?: ErrorCallback): any {
1811
+ connect(endpoint: string, callback?: ErrorCallback): Promise<void> | void {
1775
1812
  debugLog("connecting to TmpClient");
1776
1813
 
1777
1814
  // c8 ignore next
1778
1815
  if (this._internalState !== "disconnected") {
1779
- callback!(new Error("TmpClient#connect: invalid internal state = " + this._internalState));
1816
+ callback?.(new Error(`TmpClient#connect: invalid internal state = ${this._internalState}`));
1780
1817
  return;
1781
1818
  }
1782
1819
 
1783
1820
  this._setInternalState("connecting");
1784
1821
  this._connectStep2(endpoint, (err?: Error) => {
1785
1822
  if (this.isUnusable()) {
1786
- return this._handleUnrecoverableConnectionFailure(new Error("premature disconnection 4"), callback!);
1823
+ this._handleUnrecoverableConnectionFailure(new Error("premature disconnection 4"), callback || (() => { }));
1824
+ return;
1787
1825
  }
1788
- callback!(err);
1826
+ callback?.(err);
1789
1827
  });
1790
1828
  }
1791
1829
  }
@@ -1793,6 +1831,7 @@ class TmpClient extends ClientBaseImpl {
1793
1831
  // tslint:disable:no-var-requires
1794
1832
  // tslint:disable:max-line-length
1795
1833
  import { withCallback } from "thenify-ex";
1834
+
1796
1835
  ClientBaseImpl.prototype.connect = withCallback(ClientBaseImpl.prototype.connect);
1797
1836
  ClientBaseImpl.prototype.disconnect = withCallback(ClientBaseImpl.prototype.disconnect);
1798
1837
  ClientBaseImpl.prototype.getEndpoints = withCallback(ClientBaseImpl.prototype.getEndpoints);