node-opcua-client 2.173.0 → 2.174.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.173.0",
3
+ "version": "2.174.0",
4
4
  "description": "pure nodejs OPCUA SDK - module client",
5
5
  "scripts": {
6
6
  "clean": "npx rimraf -g node_modules dist *.tsbuildinfo certificates",
@@ -16,56 +16,56 @@
16
16
  "dependencies": {
17
17
  "@ster5/global-mutex": "^3.3.0",
18
18
  "chalk": "4.1.2",
19
- "node-opcua-alarm-condition": "2.173.0",
19
+ "node-opcua-alarm-condition": "2.174.0",
20
20
  "node-opcua-assert": "2.164.0",
21
- "node-opcua-basic-types": "2.173.0",
21
+ "node-opcua-basic-types": "2.174.0",
22
22
  "node-opcua-buffer-utils": "2.173.0",
23
- "node-opcua-certificate-manager": "2.173.0",
24
- "node-opcua-client-dynamic-extension-object": "2.173.0",
25
- "node-opcua-common": "2.173.0",
26
- "node-opcua-constants": "2.157.0",
23
+ "node-opcua-certificate-manager": "2.174.0",
24
+ "node-opcua-client-dynamic-extension-object": "2.174.0",
25
+ "node-opcua-common": "2.174.0",
26
+ "node-opcua-constants": "2.174.0",
27
27
  "node-opcua-crypto": "5.3.6",
28
- "node-opcua-data-model": "2.173.0",
29
- "node-opcua-data-value": "2.173.0",
30
- "node-opcua-date-time": "2.173.0",
28
+ "node-opcua-data-model": "2.174.0",
29
+ "node-opcua-data-value": "2.174.0",
30
+ "node-opcua-date-time": "2.174.0",
31
31
  "node-opcua-debug": "2.172.0",
32
- "node-opcua-extension-object": "2.173.0",
32
+ "node-opcua-extension-object": "2.174.0",
33
33
  "node-opcua-hostname": "2.167.0",
34
- "node-opcua-nodeid": "2.173.0",
35
- "node-opcua-numeric-range": "2.173.0",
34
+ "node-opcua-nodeid": "2.174.0",
35
+ "node-opcua-numeric-range": "2.174.0",
36
36
  "node-opcua-object-registry": "2.172.0",
37
- "node-opcua-pki": "6.17.0",
38
- "node-opcua-pseudo-session": "2.173.0",
39
- "node-opcua-schemas": "2.173.0",
40
- "node-opcua-secure-channel": "2.173.0",
41
- "node-opcua-service-browse": "2.173.0",
42
- "node-opcua-service-call": "2.173.0",
43
- "node-opcua-service-discovery": "2.173.0",
44
- "node-opcua-service-endpoints": "2.173.0",
45
- "node-opcua-service-filter": "2.173.0",
46
- "node-opcua-service-history": "2.173.0",
47
- "node-opcua-service-query": "2.173.0",
48
- "node-opcua-service-read": "2.173.0",
49
- "node-opcua-service-register-node": "2.173.0",
50
- "node-opcua-service-secure-channel": "2.173.0",
51
- "node-opcua-service-session": "2.173.0",
52
- "node-opcua-service-subscription": "2.173.0",
53
- "node-opcua-service-translate-browse-path": "2.173.0",
54
- "node-opcua-service-write": "2.173.0",
37
+ "node-opcua-pki": "6.18.0",
38
+ "node-opcua-pseudo-session": "2.174.0",
39
+ "node-opcua-schemas": "2.174.0",
40
+ "node-opcua-secure-channel": "2.174.0",
41
+ "node-opcua-service-browse": "2.174.0",
42
+ "node-opcua-service-call": "2.174.0",
43
+ "node-opcua-service-discovery": "2.174.0",
44
+ "node-opcua-service-endpoints": "2.174.0",
45
+ "node-opcua-service-filter": "2.174.0",
46
+ "node-opcua-service-history": "2.174.0",
47
+ "node-opcua-service-query": "2.174.0",
48
+ "node-opcua-service-read": "2.174.0",
49
+ "node-opcua-service-register-node": "2.174.0",
50
+ "node-opcua-service-secure-channel": "2.174.0",
51
+ "node-opcua-service-session": "2.174.0",
52
+ "node-opcua-service-subscription": "2.174.0",
53
+ "node-opcua-service-translate-browse-path": "2.174.0",
54
+ "node-opcua-service-write": "2.174.0",
55
55
  "node-opcua-status-code": "2.173.0",
56
- "node-opcua-transport": "2.173.0",
57
- "node-opcua-types": "2.173.0",
56
+ "node-opcua-transport": "2.174.0",
57
+ "node-opcua-types": "2.174.0",
58
58
  "node-opcua-utils": "2.173.0",
59
- "node-opcua-variant": "2.173.0",
59
+ "node-opcua-variant": "2.174.0",
60
60
  "thenify-ex": "4.4.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "dequeue": "^1.0.5",
64
- "node-opcua-address-space": "2.173.0",
64
+ "node-opcua-address-space": "2.174.0",
65
65
  "node-opcua-binary-stream": "2.173.0",
66
- "node-opcua-factory": "2.173.0",
66
+ "node-opcua-factory": "2.174.0",
67
67
  "node-opcua-leak-detector": "2.172.0",
68
- "node-opcua-nodesets": "2.163.1"
68
+ "node-opcua-nodesets": "2.174.0"
69
69
  },
70
70
  "eslintConfig": {
71
71
  "env": {
@@ -87,7 +87,7 @@
87
87
  "internet of things"
88
88
  ],
89
89
  "homepage": "http://node-opcua.github.io/",
90
- "gitHead": "4aa6634e2e1e14e223fa46a632438295be12744c",
90
+ "gitHead": "011657a3a4805ad106df7381c24ed84e2a18d8f1",
91
91
  "files": [
92
92
  "dist",
93
93
  "source"
@@ -121,7 +121,21 @@ export interface ClientSessionBase {
121
121
  * the session name
122
122
  */
123
123
  name: string;
124
+ /**
125
+ * the StatusCode returned by the last ActivateSession — usually `Good`, but
126
+ * e.g. `Good_PasswordChangeRequired` when the user must change the password
127
+ * (OPC 10000-18 §5.2.8). Lets a Client react without server-side access.
128
+ */
129
+ lastActivateSessionStatusCode: StatusCode;
124
130
 
131
+ /**
132
+ * Close the session.
133
+ *
134
+ * @param deleteSubscription - if `true` (the default), all
135
+ * subscriptions created on this session are deleted on
136
+ * the server. Set to `false` to preserve subscriptions
137
+ * for later transfer to a new session.
138
+ */
125
139
  close(callback: ErrorCallback): void;
126
140
 
127
141
  close(deleteSubscription: boolean, callback: ErrorCallback): void;
@@ -129,6 +143,40 @@ export interface ClientSessionBase {
129
143
  close(deleteSubscription?: boolean): Promise<void>;
130
144
  }
131
145
 
146
+ /**
147
+ * An active session to an OPC UA server.
148
+ *
149
+ * `ClientSession` provides access to all OPC UA services:
150
+ * reading and writing node values, browsing the address space,
151
+ * calling methods, and creating subscriptions for data change
152
+ * or event notifications.
153
+ *
154
+ * Sessions are created via {@link OPCUAClient.createSession} or
155
+ * {@link OPCUAClient.create} followed by `client.createSession()`.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const session = await client.createSession();
160
+ *
161
+ * // Read a value
162
+ * const dataValue = await session.read({
163
+ * nodeId: "ns=0;i=2258",
164
+ * attributeId: AttributeIds.Value,
165
+ * });
166
+ *
167
+ * // Browse the root folder
168
+ * const browseResult = await session.browse("RootFolder");
169
+ *
170
+ * // Write a value
171
+ * await session.write({
172
+ * nodeId: "ns=1;s=MyVariable",
173
+ * attributeId: AttributeIds.Value,
174
+ * value: { value: { dataType: DataType.Double, value: 42.0 } },
175
+ * });
176
+ *
177
+ * await session.close();
178
+ * ```
179
+ */
132
180
  export interface ClientSession extends ClientSessionBase {
133
181
  /* */
134
182
  serverEndpoints: EndpointDescription[];
@@ -152,11 +200,17 @@ export interface ClientSession extends EventEmitter {
152
200
  }
153
201
 
154
202
  // browse services
203
+ /**
204
+ * Browse service — navigate the OPC UA address space.
205
+ *
206
+ * The `browse()` and `browseNext()` methods are inherited from
207
+ * {@link node-opcua-pseudo-session!IBasicSessionBrowse}.
208
+ */
155
209
  export interface ClientSessionBrowseService extends IBasicSessionBrowse, IBasicSessionBrowseNext {
156
210
  /**
157
- * the maximum number of reference that the server should return per browseResult
158
- * Continuous points will be return by server to allow retrieving remaining references
159
- * with browseNext
211
+ * The maximum number of references the server should return
212
+ * per browse result. If the server has more, it returns a
213
+ * continuation point to retrieve the rest with `browseNext()`.
160
214
  */
161
215
  requestedMaxReferencesPerNode: number;
162
216
  }
@@ -172,7 +226,19 @@ export interface ClientSessionQueryService {
172
226
  }
173
227
 
174
228
  // call services
229
+ /**
230
+ * Call service — invoke methods on server objects.
231
+ *
232
+ * The `call()` method is inherited from
233
+ * {@link node-opcua-pseudo-session!IBasicSessionCall}.
234
+ */
175
235
  export interface ClientSessionCallService extends IBasicSessionCall {
236
+ /**
237
+ * Retrieve the input and output argument definitions of a method.
238
+ *
239
+ * @param methodId - the NodeId of the method
240
+ * @returns the argument definitions (input and output)
241
+ */
176
242
  getArgumentDefinition(methodId: MethodId): Promise<ArgumentDefinition>;
177
243
  getArgumentDefinition(methodId: MethodId, callback: (err: Error | null, args?: ArgumentDefinition) => void): void;
178
244
  }
@@ -222,6 +288,12 @@ export interface ClientSessionWriteService extends IBasicSessionWrite {
222
288
  }
223
289
 
224
290
  // raw subscription services
291
+ /**
292
+ * Raw subscription service — low-level OPC UA subscription management.
293
+ *
294
+ * For a higher-level API, use {@link ClientSubscription} via
295
+ * `ClientSession.createSubscription2()`.
296
+ */
225
297
  export interface ClientSessionRawSubscriptionService {
226
298
  /**
227
299
  *
@@ -61,31 +61,90 @@ export type WithSessionFuncP<T> = (session: ClientSession) => Promise<T>;
61
61
  export type WithSubscriptionFunc = (session: ClientSession, subscription: ClientSubscription) => Promise<void>;
62
62
  export type WithSubscriptionFuncP<T> = (session: ClientSession, subscription: ClientSubscription) => Promise<T>;
63
63
 
64
+ /**
65
+ * The OPC UA client interface.
66
+ *
67
+ * `OPCUAClient` provides methods to connect to an OPC UA server,
68
+ * create sessions, and manage the client lifecycle.
69
+ *
70
+ * Use {@link OPCUAClient.create} to instantiate a client.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const client = OPCUAClient.create({ endpointMustExist: false });
75
+ * await client.connect("opc.tcp://localhost:26543");
76
+ * const session = await client.createSession();
77
+ * // ... use the session ...
78
+ * await session.close();
79
+ * await client.disconnect();
80
+ * ```
81
+ */
64
82
  export interface OPCUAClient<Events extends OPCUAClientBaseEvents = OPCUAClientBaseEvents> extends OPCUAClientBase<Events> {
83
+ /**
84
+ * Connect the client to the specified OPC UA server endpoint.
85
+ *
86
+ * The client will establish a secure channel, negotiate security
87
+ * parameters, and verify the server certificate.
88
+ *
89
+ * @param endpointUrl - the OPC UA endpoint URL (e.g. `"opc.tcp://host:4840"`)
90
+ */
65
91
  connect(endpointUrl: string): Promise<void>;
66
92
  connect(endpointUrl: string, callback: ErrorCallback): void;
67
93
 
94
+ /**
95
+ * Disconnect the client from the server.
96
+ *
97
+ * This closes all active sessions, subscriptions, and the
98
+ * underlying secure channel.
99
+ */
68
100
  disconnect(): Promise<void>;
69
101
  disconnect(callback: ErrorCallback): void;
70
102
 
103
+ /**
104
+ * Retrieve the list of endpoints exposed by the server.
105
+ *
106
+ * @param options - optional filter criteria for the endpoint query
107
+ * @returns the array of endpoint descriptions advertised by the server
108
+ */
71
109
  getEndpoints(options?: GetEndpointsOptions): Promise<EndpointDescription[]>;
72
110
 
73
111
  getEndpoints(options: GetEndpointsOptions, callback: ResponseCallback<EndpointDescription[]>): void;
74
112
 
75
113
  getEndpoints(callback: ResponseCallback<EndpointDescription[]>): void;
76
114
 
115
+ /**
116
+ * Discover OPC UA servers registered on the network.
117
+ *
118
+ * @param options - optional filter criteria for the discovery query
119
+ * @returns the array of discovered server application descriptions
120
+ */
77
121
  findServers(options?: FindServersRequestLike): Promise<ApplicationDescription[]>;
78
122
 
79
123
  findServers(options: FindServersRequestLike, callback: ResponseCallback<ApplicationDescription[]>): void;
80
124
 
81
125
  findServers(callback: ResponseCallback<ApplicationDescription[]>): void;
82
126
 
127
+ /**
128
+ * Create a new session on the connected server.
129
+ *
130
+ * If `userIdentityInfo` is not provided, an anonymous session
131
+ * is created.
132
+ *
133
+ * @param userIdentityInfo - optional credentials for user authentication
134
+ * @returns the newly created client session
135
+ */
83
136
  createSession(userIdentityInfo?: UserIdentityInfo): Promise<ClientSession>;
84
137
 
85
138
  createSession(userIdentityInfo: UserIdentityInfo, callback: (err: Error | null, session?: ClientSession) => void): void;
86
139
 
87
140
  createSession(callback: (err: Error | null, session?: ClientSession) => void): void;
88
141
 
142
+ /**
143
+ * Create a new session, using createSession2 service (OPC UA 1.04+).
144
+ *
145
+ * @param userIdentityInfo - optional credentials for user authentication
146
+ * @returns the newly created client session
147
+ */
89
148
  createSession2(userIdentityInfo?: UserIdentityInfo): Promise<ClientSession>;
90
149
 
91
150
  createSession2(userIdentityInfo: UserIdentityInfo, callback: (err: Error | null, session?: ClientSession) => void): void;
@@ -96,29 +155,63 @@ export interface OPCUAClient<Events extends OPCUAClientBaseEvents = OPCUAClientB
96
155
  changeSessionIdentity(session: ClientSession, userIdentityInfo: UserIdentityInfo): Promise<StatusCode>;
97
156
  changeSessionIdentity(session: ClientSession, userIdentityInfo: UserIdentityInfo, callback: CallbackT<StatusCode>): void;
98
157
 
158
+ /**
159
+ * Close a previously created session.
160
+ *
161
+ * @param session - the session to close
162
+ * @param deleteSubscriptions - if `true`, all subscriptions
163
+ * associated with the session are deleted on the server
164
+ */
99
165
  closeSession(session: ClientSession, deleteSubscriptions: boolean): Promise<void>;
100
166
 
101
167
  closeSession(session: ClientSession, deleteSubscriptions: boolean, callback: (err?: Error) => void): void;
102
168
 
169
+ /**
170
+ * Reactivate a session that was previously transferred or
171
+ * disconnected.
172
+ *
173
+ * @param session - the session to reactivate
174
+ */
103
175
  reactivateSession(session: ClientSession): Promise<void>;
104
176
 
105
177
  reactivateSession(session: ClientSession, callback: (err?: Error) => void): void;
106
178
 
107
- // @private
179
+ /** @internal */
108
180
  createDefaultCertificate(): Promise<void>;
109
181
 
110
182
  /**
183
+ * Connect to a server, execute an async function within a session,
184
+ * then automatically close the session and disconnect.
185
+ *
186
+ * This is a convenience method for simple one-shot operations.
187
+ *
188
+ * @param endpointUrl - the server endpoint URL or endpoint with credentials
189
+ * @param inner_func - the async function to execute with the session
190
+ * @returns the value returned by `inner_func`
111
191
  *
112
- * @param endpointUrl
113
- * @param inner_func
192
+ * @example
193
+ * ```typescript
194
+ * const result = await client.withSessionAsync(
195
+ * "opc.tcp://localhost:26543",
196
+ * async (session) => {
197
+ * return await session.read({ nodeId: "ns=0;i=2258",
198
+ * attributeId: AttributeIds.Value });
199
+ * }
200
+ * );
201
+ * ```
114
202
  */
115
203
  withSessionAsync<T>(endpointUrl: string | EndpointWithUserIdentity, inner_func: WithSessionFuncP<T>): Promise<T>;
116
204
 
117
205
  /**
206
+ * Connect to a server, create a session and a subscription,
207
+ * execute an async function, then clean up everything.
118
208
  *
119
- * @param endpointUrl
120
- * @param parameters
121
- * @param inner_func
209
+ * This is a convenience method for subscription-based operations.
210
+ *
211
+ * @param endpointUrl - the server endpoint URL or endpoint with credentials
212
+ * @param parameters - subscription creation parameters
213
+ * @param inner_func - the async function to execute with the session and subscription
214
+ * @returns the value returned by `inner_func`
122
215
  */
123
216
  withSubscriptionAsync<T>(
124
217
  endpointUrl: string | EndpointWithUserIdentity,
@@ -127,10 +220,50 @@ export interface OPCUAClient<Events extends OPCUAClientBaseEvents = OPCUAClientB
127
220
  ): Promise<T>;
128
221
  }
129
222
 
223
+ /**
224
+ * Factory class for creating OPC UA client instances.
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * import { OPCUAClient } from "node-opcua-client";
229
+ *
230
+ * const client = OPCUAClient.create({
231
+ * endpointMustExist: false,
232
+ * requestedSessionTimeout: 60000,
233
+ * });
234
+ * ```
235
+ */
130
236
  export class OPCUAClient {
237
+ /**
238
+ * Create a new OPC UA client instance.
239
+ *
240
+ * @param options - client configuration options
241
+ * @returns a configured OPC UA client ready to connect
242
+ */
131
243
  public static create(options: OPCUAClientOptions): OPCUAClient {
132
244
  return new OPCUAClientImpl(options) as unknown as OPCUAClient;
133
245
  }
246
+ /**
247
+ * Convenience method to create a client, connect, and establish
248
+ * a session in one call.
249
+ *
250
+ * @param endpointUrl - the OPC UA endpoint URL
251
+ * @param userIdentity - optional user credentials
252
+ * @param clientOptions - optional client configuration
253
+ * @returns a connected client session
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * const session = await OPCUAClient.createSession(
258
+ * "opc.tcp://localhost:26543"
259
+ * );
260
+ * const dataValue = await session.read({
261
+ * nodeId: "ns=0;i=2258",
262
+ * attributeId: AttributeIds.Value,
263
+ * });
264
+ * await session.close(true); // deleteSubscriptions = true
265
+ * ```
266
+ */
134
267
  public static async createSession(
135
268
  endpointUrl: string,
136
269
  userIdentity?: UserIdentityInfo,
@@ -205,6 +205,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
205
205
  public serverNonce?: Nonce;
206
206
  public serverSignature?: SignatureData; // todo : remove ?
207
207
  public serverEndpoints: EndpointDescription[] = [];
208
+ public lastActivateSessionStatusCode: StatusCode = StatusCodes.Good;
208
209
  public _client: IClientBase | null;
209
210
  public _closed: boolean;
210
211
 
@@ -278,7 +279,6 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
278
279
  };
279
280
  }
280
281
 
281
-
282
282
  public [Symbol.for("nodejs.util.inspect.custom")](): string {
283
283
  return this.toString();
284
284
  }
@@ -420,8 +420,8 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
420
420
  if (r.references && r.references.length > this.requestedMaxReferencesPerNode) {
421
421
  warningLog(
422
422
  chalk.yellow("warning") +
423
- " BrowseResponse : the server didn't take into" +
424
- " account our requestedMaxReferencesPerNode "
423
+ " BrowseResponse : the server didn't take into" +
424
+ " account our requestedMaxReferencesPerNode "
425
425
  );
426
426
  warningLog(" this.requestedMaxReferencesPerNode= " + this.requestedMaxReferencesPerNode);
427
427
  warningLog(" got " + r.references.length + "for " + nodesToBrowse[i].nodeId.toString());
@@ -430,7 +430,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
430
430
  }
431
431
  }
432
432
  for (const r of results) {
433
- r.references = r.references || /* c8 ignore next */[];
433
+ r.references = r.references || /* c8 ignore next */ [];
434
434
  }
435
435
  assert(results[0] instanceof BrowseResult);
436
436
  return callback(null, isArray ? results : results[0]);
@@ -725,7 +725,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
725
725
  return callback(new Error(response.responseHeader.serviceResult.toString()));
726
726
  }
727
727
 
728
- response.results = response.results || /* c8 ignore next */[];
728
+ response.results = response.results || /* c8 ignore next */ [];
729
729
 
730
730
  // perform ExtensionObject resolution
731
731
  const promises = response.results.map(async (result) => {
@@ -870,7 +870,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
870
870
  return callback(new Error(response.responseHeader.serviceResult.toString()));
871
871
  }
872
872
 
873
- response.results = response.results || /* c8 ignore next */[];
873
+ response.results = response.results || /* c8 ignore next */ [];
874
874
 
875
875
  assert(nodesToRead.length === response.results.length);
876
876
 
@@ -1009,7 +1009,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
1009
1009
  if (response.responseHeader.serviceResult.isNot(StatusCodes.Good)) {
1010
1010
  return callback(new Error(response.responseHeader.serviceResult.toString()));
1011
1011
  }
1012
- response.results = response.results || /* c8 ignore next */[];
1012
+ response.results = response.results || /* c8 ignore next */ [];
1013
1013
  assert(nodesToWrite.length === response.results.length);
1014
1014
  callback(null, isArray ? response.results : response.results[0]);
1015
1015
  });
@@ -1204,7 +1204,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
1204
1204
  warningLog(
1205
1205
  chalk.yellow(
1206
1206
  "please make sure to refactor your code and check that " +
1207
- "the second argument of your callback function is named"
1207
+ "the second argument of your callback function is named"
1208
1208
  ),
1209
1209
  chalk.cyan("dataValue" + (isArray ? "s" : ""))
1210
1210
  );
@@ -1238,7 +1238,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
1238
1238
  // perform ExtensionObject resolution
1239
1239
  promoteOpaqueStructure(this, response.results!)
1240
1240
  .then(() => {
1241
- response.results = response.results || /* c8 ignore next */[];
1241
+ response.results = response.results || /* c8 ignore next */ [];
1242
1242
  callback(null, isArray ? response.results : response.results[0]);
1243
1243
  })
1244
1244
  .catch((err) => {
@@ -1416,7 +1416,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
1416
1416
  if (!response) {
1417
1417
  return callback(new Error("Internal Error"));
1418
1418
  }
1419
- response.results = response.results || /* c8 ignore next */[];
1419
+ response.results = response.results || /* c8 ignore next */ [];
1420
1420
  callback(err, isArray ? response.results : response.results[0]);
1421
1421
  }
1422
1422
  );
@@ -1452,7 +1452,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
1452
1452
  if (!response || !(response instanceof TranslateBrowsePathsToNodeIdsResponse)) {
1453
1453
  return callback(new Error("Internal Error"));
1454
1454
  }
1455
- response.results = response.results || /* c8 ignore next */[];
1455
+ response.results = response.results || /* c8 ignore next */ [];
1456
1456
 
1457
1457
  callback(null, isArray ? response.results : response.results[0]);
1458
1458
  });
@@ -1601,9 +1601,9 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
1601
1601
  if (response.responseHeader.serviceResult.isNot(StatusCodes.Good)) {
1602
1602
  err = new Error(
1603
1603
  " ServiceResult is " +
1604
- response.responseHeader.serviceResult.toString() +
1605
- " request was " +
1606
- request.constructor.name
1604
+ response.responseHeader.serviceResult.toString() +
1605
+ " request was " +
1606
+ request.constructor.name
1607
1607
  );
1608
1608
 
1609
1609
  if (response && response.responseHeader.serviceDiagnostics) {
@@ -1852,7 +1852,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession, Re
1852
1852
  return callback(new Error("Internal Error"));
1853
1853
  }
1854
1854
 
1855
- response.registeredNodeIds = response.registeredNodeIds || /* c8 ignore next */[];
1855
+ response.registeredNodeIds = response.registeredNodeIds || /* c8 ignore next */ [];
1856
1856
 
1857
1857
  callback(null, response.registeredNodeIds);
1858
1858
  });
@@ -21,6 +21,7 @@ import {
21
21
  import { LocalizedText } from "node-opcua-data-model";
22
22
  import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
23
23
  import { extractFullyQualifiedDomainName } from "node-opcua-hostname";
24
+ import type { NodeId } from "node-opcua-nodeid";
24
25
  import { readNamespaceArray } from "node-opcua-pseudo-session";
25
26
  import {
26
27
  type ClientSecureChannelLayer,
@@ -48,7 +49,6 @@ import {
48
49
  import { type Callback, type CallbackT, type StatusCode, StatusCodes } from "node-opcua-status-code";
49
50
  import type { SignatureDataOptions, UserIdentityToken } from "node-opcua-types";
50
51
  import { isNullOrUndefined, matchUri, randomBytes } from "node-opcua-utils";
51
- import type { NodeId } from "node-opcua-nodeid";
52
52
  import type { OPCUAClientBaseEvents } from "../client_base";
53
53
  import type { ClientSession } from "../client_session";
54
54
  import type { ClientSubscriptionOptions } from "../client_subscription";
@@ -563,11 +563,7 @@ export class OPCUAClientImpl extends ClientBaseImpl<OPCUAClientBaseEvents> {
563
563
  clearTimeout(this._retryCreateSessionTimer);
564
564
  this._retryCreateSessionTimer = undefined;
565
565
  }
566
- super.closeSession(
567
- session as unknown as ClientSessionImpl,
568
- deleteSubscriptions,
569
- callback as (err?: Error) => void
570
- );
566
+ super.closeSession(session as unknown as ClientSessionImpl, deleteSubscriptions, callback as (err?: Error) => void);
571
567
  }
572
568
 
573
569
  public toJSON(): Record<string, string | number | boolean | undefined> {
@@ -733,11 +729,11 @@ export class OPCUAClientImpl extends ClientBaseImpl<OPCUAClientBaseEvents> {
733
729
  return callback?.(
734
730
  new Error(
735
731
  " End point must exist " +
736
- this._secureChannel?.endpointUrl +
737
- " securityMode = " +
738
- MessageSecurityMode[this.securityMode] +
739
- " securityPolicy = " +
740
- this.securityPolicy
732
+ this._secureChannel?.endpointUrl +
733
+ " securityMode = " +
734
+ MessageSecurityMode[this.securityMode] +
735
+ " securityPolicy = " +
736
+ this.securityPolicy
741
737
  )
742
738
  );
743
739
  }
@@ -968,7 +964,9 @@ export class OPCUAClientImpl extends ClientBaseImpl<OPCUAClientBaseEvents> {
968
964
  // clientCertificate. The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm
969
965
  // specified in the SecurityPolicy for the Endpoint. The SignatureData type is defined in 7.30.
970
966
 
971
- clientSignature: this.computeClientSignature(this._secureChannel as ClientSecureChannelLayer, serverCertificate, serverNonce) || undefined,
967
+ clientSignature:
968
+ this.computeClientSignature(this._secureChannel as ClientSecureChannelLayer, serverCertificate, serverNonce) ||
969
+ undefined,
972
970
 
973
971
  // These are the SoftwareCertificates which have been issued to the Client application.
974
972
  // The productUri contained in the SoftwareCertificates shall match the productUri in the
@@ -1013,7 +1011,7 @@ export class OPCUAClientImpl extends ClientBaseImpl<OPCUAClientBaseEvents> {
1013
1011
  session.lastRequestSentTime = new Date();
1014
1012
 
1015
1013
  this.performMessageTransaction(request, (err1: Error | null, response?: Response) => {
1016
- if (!err1 && response && response.responseHeader.serviceResult === StatusCodes.Good) {
1014
+ if (!err1 && response && response.responseHeader.serviceResult.isGoodish()) {
1017
1015
  /* c8 ignore next */
1018
1016
  if (!(response instanceof ActivateSessionResponse)) {
1019
1017
  return callback(new Error("Internal Error"));
@@ -1023,6 +1021,9 @@ export class OPCUAClientImpl extends ClientBaseImpl<OPCUAClientBaseEvents> {
1023
1021
  return callback(new Error("Invalid server Nonce"));
1024
1022
  }
1025
1023
  session._client = this;
1024
+ // capture the activation outcome (e.g. Good_PasswordChangeRequired,
1025
+ // OPC 10000-18 §5.2.8) so a Client can react without server access.
1026
+ session.lastActivateSessionStatusCode = response.responseHeader.serviceResult;
1026
1027
  session.serverNonce = response.serverNonce;
1027
1028
  session.lastResponseReceivedTime = new Date();
1028
1029
  if (this.keepSessionAlive) {
@@ -1152,11 +1153,11 @@ export class OPCUAClientImpl extends ClientBaseImpl<OPCUAClientBaseEvents> {
1152
1153
  return callback(
1153
1154
  new Error(
1154
1155
  " End point must exist " +
1155
- this._secureChannel?.endpointUrl +
1156
- " securityMode = " +
1157
- MessageSecurityMode[this.securityMode] +
1158
- " securityPolicy = " +
1159
- this.securityPolicy
1156
+ this._secureChannel?.endpointUrl +
1157
+ " securityMode = " +
1158
+ MessageSecurityMode[this.securityMode] +
1159
+ " securityPolicy = " +
1160
+ this.securityPolicy
1160
1161
  )
1161
1162
  );
1162
1163
  }