node-opcua-client 2.167.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-opcua-client",
3
- "version": "2.167.0",
3
+ "version": "2.168.0",
4
4
  "description": "pure nodejs OPCUA SDK - module client",
5
5
  "scripts": {
6
6
  "clean": "npx rimraf -g node_modules dist *.tsbuildinfo certificates",
@@ -15,56 +15,55 @@
15
15
  "types": "./dist/index.d.ts",
16
16
  "dependencies": {
17
17
  "@ster5/global-mutex": "^3.3.0",
18
- "async": "^3.2.6",
19
18
  "chalk": "4.1.2",
20
- "node-opcua-alarm-condition": "2.167.0",
19
+ "node-opcua-alarm-condition": "2.168.0",
21
20
  "node-opcua-assert": "2.164.0",
22
- "node-opcua-basic-types": "2.167.0",
23
- "node-opcua-buffer-utils": "2.167.0",
24
- "node-opcua-certificate-manager": "2.167.0",
25
- "node-opcua-client-dynamic-extension-object": "2.167.0",
26
- "node-opcua-common": "2.167.0",
21
+ "node-opcua-basic-types": "2.168.0",
22
+ "node-opcua-buffer-utils": "2.168.0",
23
+ "node-opcua-certificate-manager": "2.168.0",
24
+ "node-opcua-client-dynamic-extension-object": "2.168.0",
25
+ "node-opcua-common": "2.168.0",
27
26
  "node-opcua-constants": "2.157.0",
28
27
  "node-opcua-crypto": "5.3.3",
29
- "node-opcua-data-model": "2.167.0",
30
- "node-opcua-data-value": "2.167.0",
31
- "node-opcua-date-time": "2.167.0",
32
- "node-opcua-debug": "2.165.0",
33
- "node-opcua-extension-object": "2.167.0",
28
+ "node-opcua-data-model": "2.168.0",
29
+ "node-opcua-data-value": "2.168.0",
30
+ "node-opcua-date-time": "2.168.0",
31
+ "node-opcua-debug": "2.168.0",
32
+ "node-opcua-extension-object": "2.168.0",
34
33
  "node-opcua-hostname": "2.167.0",
35
- "node-opcua-nodeid": "2.167.0",
36
- "node-opcua-numeric-range": "2.167.0",
37
- "node-opcua-object-registry": "2.165.0",
34
+ "node-opcua-nodeid": "2.168.0",
35
+ "node-opcua-numeric-range": "2.168.0",
36
+ "node-opcua-object-registry": "2.168.0",
38
37
  "node-opcua-pki": "6.12.0",
39
- "node-opcua-pseudo-session": "2.167.0",
40
- "node-opcua-schemas": "2.167.0",
41
- "node-opcua-secure-channel": "2.167.0",
42
- "node-opcua-service-browse": "2.167.0",
43
- "node-opcua-service-call": "2.167.0",
44
- "node-opcua-service-discovery": "2.167.0",
45
- "node-opcua-service-endpoints": "2.167.0",
46
- "node-opcua-service-filter": "2.167.0",
47
- "node-opcua-service-history": "2.167.0",
48
- "node-opcua-service-query": "2.167.0",
49
- "node-opcua-service-read": "2.167.0",
50
- "node-opcua-service-register-node": "2.167.0",
51
- "node-opcua-service-secure-channel": "2.167.0",
52
- "node-opcua-service-session": "2.167.0",
53
- "node-opcua-service-subscription": "2.167.0",
54
- "node-opcua-service-translate-browse-path": "2.167.0",
55
- "node-opcua-service-write": "2.167.0",
56
- "node-opcua-status-code": "2.167.0",
57
- "node-opcua-types": "2.167.0",
58
- "node-opcua-utils": "2.165.0",
59
- "node-opcua-variant": "2.167.0",
38
+ "node-opcua-pseudo-session": "2.168.0",
39
+ "node-opcua-schemas": "2.168.0",
40
+ "node-opcua-secure-channel": "2.168.0",
41
+ "node-opcua-service-browse": "2.168.0",
42
+ "node-opcua-service-call": "2.168.0",
43
+ "node-opcua-service-discovery": "2.168.0",
44
+ "node-opcua-service-endpoints": "2.168.0",
45
+ "node-opcua-service-filter": "2.168.0",
46
+ "node-opcua-service-history": "2.168.0",
47
+ "node-opcua-service-query": "2.168.0",
48
+ "node-opcua-service-read": "2.168.0",
49
+ "node-opcua-service-register-node": "2.168.0",
50
+ "node-opcua-service-secure-channel": "2.168.0",
51
+ "node-opcua-service-session": "2.168.0",
52
+ "node-opcua-service-subscription": "2.168.0",
53
+ "node-opcua-service-translate-browse-path": "2.168.0",
54
+ "node-opcua-service-write": "2.168.0",
55
+ "node-opcua-status-code": "2.168.0",
56
+ "node-opcua-types": "2.168.0",
57
+ "node-opcua-utils": "2.168.0",
58
+ "node-opcua-variant": "2.168.0",
60
59
  "thenify-ex": "4.4.0"
61
60
  },
62
61
  "devDependencies": {
63
62
  "dequeue": "^1.0.5",
64
- "node-opcua-address-space": "2.167.0",
65
- "node-opcua-binary-stream": "2.167.0",
66
- "node-opcua-factory": "2.167.0",
67
- "node-opcua-leak-detector": "2.165.0",
63
+ "node-opcua-address-space": "2.168.0",
64
+ "node-opcua-binary-stream": "2.168.0",
65
+ "node-opcua-factory": "2.168.0",
66
+ "node-opcua-leak-detector": "2.168.0",
68
67
  "node-opcua-nodesets": "2.163.1"
69
68
  },
70
69
  "eslintConfig": {
@@ -87,7 +86,7 @@
87
86
  "internet of things"
88
87
  ],
89
88
  "homepage": "http://node-opcua.github.io/",
90
- "gitHead": "5decfa86ee53a36ecd3bb454e7bf6e3dd27c7a4e",
89
+ "gitHead": "653b6d6df801ca17298308089dee32e5b12102b6",
91
90
  "files": [
92
91
  "dist",
93
92
  "source"
@@ -6,52 +6,26 @@ import fs from "node:fs";
6
6
  import path from "node:path";
7
7
 
8
8
  import { withLock } from "@ster5/global-mutex";
9
- import async from "async";
9
+
10
10
  import chalk from "chalk";
11
11
  import { assert } from "node-opcua-assert";
12
- import {
13
- getDefaultCertificateManager,
14
- makeSubject,
15
- type OPCUACertificateManager
16
- } from "node-opcua-certificate-manager";
17
- import {
18
- type IOPCUASecureObjectOptions,
19
- makeApplicationUrn,
20
- OPCUASecureObject
21
- } from "node-opcua-common";
22
- import {
23
- type Certificate,
24
- makeSHA1Thumbprint,
25
- split_der
26
- } from "node-opcua-crypto/web";
27
- import {
28
- installPeriodicClockAdjustment,
29
- periodicClockAdjustment,
30
- uninstallPeriodicClockAdjustment
31
- } from "node-opcua-date-time";
32
- import {
33
- checkDebugFlag,
34
- make_debugLog,
35
- make_errorLog,
36
- make_warningLog
37
- } from "node-opcua-debug";
38
- import {
39
- getHostname
40
- } from "node-opcua-hostname";
41
- import type {
42
- IBasicTransportSettings,
43
- ResponseCallback
44
- } from "node-opcua-pseudo-session";
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";
15
+ import { installPeriodicClockAdjustment, periodicClockAdjustment, uninstallPeriodicClockAdjustment } from "node-opcua-date-time";
16
+ import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
17
+ import { getHostname } from "node-opcua-hostname";
18
+ import type { IBasicTransportSettings, ResponseCallback } from "node-opcua-pseudo-session";
45
19
  import {
46
20
  ClientSecureChannelLayer,
47
21
  type ConnectionStrategy,
48
22
  type ConnectionStrategyOptions,
49
23
  coerceConnectionStrategy,
50
24
  coerceSecurityPolicy,
25
+ type PerformTransactionCallback,
51
26
  type Request as Request1,
52
27
  type Response as Response1,
53
- type SecurityPolicy,
54
- type PerformTransactionCallback
28
+ type SecurityPolicy
55
29
  } from "node-opcua-secure-channel";
56
30
  import {
57
31
  FindServersOnNetworkRequest,
@@ -67,10 +41,7 @@ import {
67
41
  GetEndpointsRequest,
68
42
  GetEndpointsResponse
69
43
  } from "node-opcua-service-endpoints";
70
- import {
71
- type ChannelSecurityToken,
72
- coerceMessageSecurityMode, MessageSecurityMode
73
- } from "node-opcua-service-secure-channel";
44
+ import { type ChannelSecurityToken, coerceMessageSecurityMode, MessageSecurityMode } from "node-opcua-service-secure-channel";
74
45
  import { CloseSessionRequest, type CloseSessionResponse } from "node-opcua-service-session";
75
46
  import { type ErrorCallback, StatusCodes } from "node-opcua-status-code";
76
47
  import { checkFileExistsAndIsNotEmpty, matchUri } from "node-opcua-utils";
@@ -151,8 +122,8 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
151
122
 
152
123
  let selectedEndpoint: EndpointDescription | undefined;
153
124
  const allEndpoints: EndpointDescription[] = [];
154
- const tasks = [
155
- (innerCallback: ErrorCallback) => {
125
+ const step1_connect = (): Promise<void> => {
126
+ return new Promise<void>((resolve, reject) => {
156
127
  // rebind backoff handler
157
128
  masterClient.listeners("backoff").forEach((handler) => {
158
129
  client.on("backoff", handler as unknown as (retryCount: number, delay: number) => void);
@@ -174,7 +145,6 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
174
145
 
175
146
  client.connect(endpointUrl, (err?: Error) => {
176
147
  if (err) {
177
- // let's improve the error message with meaningful info
178
148
  err.message =
179
149
  "Fail to connect to server at " +
180
150
  endpointUrl +
@@ -183,20 +153,23 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
183
153
  err.message +
184
154
  ")";
185
155
  warningLog(err.message);
156
+ return reject(err);
186
157
  }
187
- return innerCallback(err);
158
+ resolve();
188
159
  });
189
- },
160
+ });
161
+ };
190
162
 
191
- (innerCallback: ErrorCallback) => {
163
+ const step2_getEndpoints = (): Promise<void> => {
164
+ return new Promise<void>((resolve, reject) => {
192
165
  client.getEndpoints((err: Error | null, endpoints?: EndpointDescription[]) => {
193
166
  if (err) {
194
167
  err.message = `error in getEndpoints \n${err.message}`;
195
- return innerCallback(err);
168
+ return reject(err);
196
169
  }
197
170
  // c8 ignore next
198
171
  if (!endpoints) {
199
- return innerCallback(new Error("Internal Error"));
172
+ return reject(new Error("Internal Error"));
200
173
  }
201
174
 
202
175
  for (const endpoint of endpoints) {
@@ -211,47 +184,45 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
211
184
  selectedEndpoint = endpoint; // found it
212
185
  }
213
186
  }
214
- innerCallback();
187
+ resolve();
215
188
  });
216
- },
189
+ });
190
+ };
217
191
 
218
- (innerCallback: ErrorCallback) => {
219
- client.disconnect(innerCallback);
220
- }
221
- ];
192
+ const step3_disconnect = (): Promise<void> => {
193
+ return new Promise<void>((resolve) => {
194
+ client.disconnect(() => resolve());
195
+ });
196
+ };
197
+
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
+ }
222
218
 
223
- async.series(tasks, (err) => {
224
- if (err) {
219
+ callback(null, { endpoints: allEndpoints, selectedEndpoint });
220
+ })
221
+ .catch((err) => {
225
222
  client.disconnect(() => {
226
223
  callback(err);
227
224
  });
228
- return;
229
- }
230
-
231
- if (!selectedEndpoint) {
232
- return callback(
233
- new Error(
234
- "Cannot find an Endpoint matching " +
235
- " security mode: " +
236
- securityMode.toString() +
237
- " policy: " +
238
- securityPolicy.toString()
239
- )
240
- );
241
- }
242
-
243
- // c8 ignore next
244
- if (doDebug) {
245
- debugLog(chalk.bgWhite.red("xxxxxxxxxxxxxxxxxxxxx => selected EndPoint = "), selectedEndpoint.toString());
246
- }
247
-
248
- const result = {
249
- endpoints: allEndpoints,
250
- selectedEndpoint
251
- };
252
-
253
- callback(null, result);
254
- });
225
+ });
255
226
  }
256
227
 
257
228
  /**
@@ -556,7 +527,6 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
556
527
  this._secureChannel = null;
557
528
  callback();
558
529
  });
559
-
560
530
  }
561
531
 
562
532
  public _recreate_secure_channel(callback: ErrorCallback): void {
@@ -741,60 +711,65 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
741
711
 
742
712
  this.emit("secure_channel_created", secureChannel);
743
713
 
744
- async.series(
745
- [
746
- // ------------------------------------------------- STEP 2 : OpenSecureChannel
747
- (innerCallback: ErrorCallback) => {
748
- 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");
717
+
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");
749
738
 
750
- secureChannel.create(this.endpointUrl, (err?: Error) => {
751
- debugLog("_internal_create_secure_channel after secureChannel.create");
739
+ this.getEndpoints((err: Error | null /*, endpoints?: EndpointDescription[]*/) => {
752
740
  if (!this._secureChannel) {
753
- debugLog("_secureChannel has been closed during the transaction !");
754
- 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"));
755
743
  }
756
- if (!err) {
757
- this._install_secure_channel_event_handlers(secureChannel);
744
+ if (err) {
745
+ return reject(err);
758
746
  }
759
- innerCallback(err);
747
+ resolve();
760
748
  });
761
- },
762
- // ------------------------------------------------- STEP 3 : GetEndpointsRequest
763
- (innerCallback: ErrorCallback) => {
764
- assert(this._secureChannel !== null);
765
- if (!this.knowsServerEndpoint) {
766
- this._setInternalState("connecting");
767
-
768
- this.getEndpoints((err: Error | null /*, endpoints?: EndpointDescription[]*/) => {
769
- if (!this._secureChannel) {
770
- debugLog("_secureChannel has been closed during the transaction ! (while getEndpoints)");
771
- return innerCallback(new Error("Secure Channel Closed"));
772
- }
773
- innerCallback(err ? err : undefined);
774
- });
775
- } else {
776
- // end points are already known
777
- innerCallback();
778
- }
749
+ } else {
750
+ // end points are already known
751
+ resolve();
779
752
  }
780
- ],
781
- (err) => {
782
- if (err) {
783
- doDebug && debugLog(this.clientName, " : Inner create secure channel has failed", err.message);
784
- if (this._secureChannel) {
785
- this._secureChannel.abortConnection(() => {
786
- this._destroy_secure_channel();
787
- callback(err);
788
- });
789
- } 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();
790
767
  callback(err);
791
- }
768
+ });
792
769
  } else {
793
- assert(this._secureChannel !== null);
794
- callback(null, secureChannel);
770
+ callback(err);
795
771
  }
796
- }
797
- );
772
+ });
798
773
  }
799
774
 
800
775
  static async createCertificate(
@@ -1021,10 +996,7 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1021
996
  });
1022
997
  }
1023
998
 
1024
- public performMessageTransaction(
1025
- request: Request,
1026
- callback: ResponseCallback<Response>
1027
- ): void {
999
+ public performMessageTransaction(request: Request, callback: ResponseCallback<Response>): void {
1028
1000
  if (!this._secureChannel) {
1029
1001
  // this may happen if the Server has closed the connection abruptly for some unknown reason
1030
1002
  // or if the tcp connection has been broken.
@@ -1053,10 +1025,7 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1053
1025
  assert(request);
1054
1026
  assert(request.requestHeader);
1055
1027
  assert(typeof callback === "function");
1056
- this._secureChannel.performMessageTransaction(
1057
- request,
1058
- callback as unknown as PerformTransactionCallback
1059
- );
1028
+ this._secureChannel.performMessageTransaction(request, callback as unknown as PerformTransactionCallback);
1060
1029
  }
1061
1030
 
1062
1031
  /**
@@ -1104,10 +1073,7 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1104
1073
  public getEndpoints(callback: ResponseCallback<EndpointDescription[]>): void;
1105
1074
  public getEndpoints(...args: unknown[]): Promise<EndpointDescription[]> | undefined {
1106
1075
  if (args.length === 1) {
1107
- this.getEndpoints(
1108
- {} as GetEndpointsOptions,
1109
- args[0] as unknown as ResponseCallback<EndpointDescription[]>
1110
- );
1076
+ this.getEndpoints({} as GetEndpointsOptions, args[0] as unknown as ResponseCallback<EndpointDescription[]>);
1111
1077
  return;
1112
1078
  }
1113
1079
  const options = args[0] as GetEndpointsOptions;
@@ -1156,27 +1122,16 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1156
1122
  /**
1157
1123
 
1158
1124
  */
1159
- public findServers(
1160
- options?: FindServersRequestLike
1161
- ): Promise<ApplicationDescription[]>;
1162
- public findServers(
1163
- options: FindServersRequestLike,
1164
- callback: ResponseCallback<ApplicationDescription[]>
1165
- ): void;
1166
- public findServers(
1167
- callback: ResponseCallback<ApplicationDescription[]>
1168
- ): void;
1169
- public findServers(
1170
- ...args: unknown[]
1171
- ): Promise<ApplicationDescription[]> | void {
1125
+ public findServers(options?: FindServersRequestLike): Promise<ApplicationDescription[]>;
1126
+ public findServers(options: FindServersRequestLike, callback: ResponseCallback<ApplicationDescription[]>): void;
1127
+ public findServers(callback: ResponseCallback<ApplicationDescription[]>): void;
1128
+ public findServers(...args: unknown[]): Promise<ApplicationDescription[]> | undefined {
1172
1129
  if (args.length === 1) {
1173
1130
  if (typeof args[0] === "function") {
1174
- this.findServers(
1175
- {} as FindServersRequestLike, args[0] as ResponseCallback<ApplicationDescription[]>);
1176
- return void 0;
1177
- } else {
1178
- throw new Error("Invalid arguments");
1131
+ this.findServers({} as FindServersRequestLike, args[0] as ResponseCallback<ApplicationDescription[]>);
1132
+ return;
1179
1133
  }
1134
+ throw new Error("Invalid arguments");
1180
1135
  }
1181
1136
  const options = args[0] as FindServersRequestLike;
1182
1137
  const callback = args[1] as ResponseCallback<ApplicationDescription[]>;
@@ -1201,18 +1156,16 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1201
1156
 
1202
1157
  callback(null, response.servers);
1203
1158
  });
1159
+ return undefined;
1204
1160
  }
1205
1161
 
1206
1162
  public findServersOnNetwork(options?: FindServersOnNetworkRequestLike): Promise<ServerOnNetwork[]>;
1207
1163
  public findServersOnNetwork(callback: ResponseCallback<ServerOnNetwork[]>): void;
1208
1164
  public findServersOnNetwork(options: FindServersOnNetworkRequestLike, callback: ResponseCallback<ServerOnNetwork[]>): void;
1209
- public findServersOnNetwork(...args: unknown[]): Promise<ServerOnNetwork[]> | unknown {
1165
+ public findServersOnNetwork(...args: unknown[]): Promise<ServerOnNetwork[]> | undefined {
1210
1166
  if (args.length === 1) {
1211
- this.findServersOnNetwork(
1212
- {} as FindServersOnNetworkRequestOptions,
1213
- args[0] as ResponseCallback<ServerOnNetwork[]>
1214
- );
1215
- return;
1167
+ this.findServersOnNetwork({} as FindServersOnNetworkRequestOptions, args[0] as ResponseCallback<ServerOnNetwork[]>);
1168
+ return undefined;
1216
1169
  }
1217
1170
  const options = args[0] as FindServersOnNetworkRequestOptions;
1218
1171
  const callback = args[1] as ResponseCallback<ServerOnNetwork[]>;
@@ -1231,7 +1184,7 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1231
1184
  response.servers = response.servers || [];
1232
1185
  callback(null, response.servers);
1233
1186
  });
1234
- return;
1187
+ return undefined;
1235
1188
  }
1236
1189
 
1237
1190
  public _removeSession(session: ClientSessionImpl): void {
@@ -1589,30 +1542,27 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1589
1542
 
1590
1543
  private _close_pending_sessions(callback: ErrorCallback) {
1591
1544
  const sessions = [...this._sessions];
1592
- async.map(
1593
- sessions,
1594
- (session: ClientSessionImpl, next: () => void) => {
1595
- assert(session._client === this);
1596
-
1597
- // note: to prevent next to be call twice
1598
- let _next_already_call = false;
1599
- session.close((err?: Error) => {
1600
- if (_next_already_call) {
1601
- return;
1602
- }
1603
- _next_already_call = true;
1604
1545
 
1605
- // We should not bother if we have an error here
1606
- // Session may fail to close , if they haven't been activate and forcefully closed by server
1607
- // in a attempt to preserve resources in the case of a DDOS attack for instance.
1608
- if (err) {
1609
- const msg = session.authenticationToken ? session.authenticationToken.toString() : "";
1610
- debugLog(` failing to close session ${msg}`);
1611
- }
1612
- 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
+ });
1613
1560
  });
1614
- },
1615
- (err) => {
1561
+ }
1562
+ };
1563
+
1564
+ closeAll()
1565
+ .then(() => {
1616
1566
  // c8 ignore next
1617
1567
  if (this._sessions.length > 0) {
1618
1568
  debugLog(
@@ -1622,9 +1572,9 @@ export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBa
1622
1572
  );
1623
1573
  }
1624
1574
  assert(this._sessions.length === 0, " failed to disconnect exiting sessions ");
1625
- callback(err || undefined);
1626
- }
1627
- );
1575
+ callback();
1576
+ })
1577
+ .catch((err) => callback(err));
1628
1578
  }
1629
1579
 
1630
1580
  private _install_secure_channel_event_handlers(secureChannel: ClientSecureChannelLayer) {
@@ -1863,8 +1813,7 @@ class TmpClient extends ClientBaseImpl {
1863
1813
 
1864
1814
  // c8 ignore next
1865
1815
  if (this._internalState !== "disconnected") {
1866
- callback?.(
1867
- new Error(`TmpClient#connect: invalid internal state = ${this._internalState}`));
1816
+ callback?.(new Error(`TmpClient#connect: invalid internal state = ${this._internalState}`));
1868
1817
  return;
1869
1818
  }
1870
1819