opcjs-client 0.1.26-alpha → 0.1.32-alpha

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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { StatusCodeToString, initLoggerProvider, getLogger, WebSocketFascade, WebSocketReadableStream, WebSocketWritableStream, SecureChannelContext, TcpMessageInjector, TcpConnectionHandler, TcpMessageDecoupler, SecureChannelMesssageEncoder, SecureChannelTypeDecoder, SecureChannelMessageDecoder, SecureChannelTypeEncoder, SecureChannelChunkWriter, SecureChannelChunkReader, SecureChannelFacade, CallMethodRequest, Variant, BrowseDescription, BrowseDirectionEnum, NodeId, BrowseResultMaskEnum, Configuration, LoggerFactory, Encoder, BinaryWriter, registerEncoders, Decoder, BinaryReader, registerTypeDecoders, registerBinaryDecoders, UserTokenTypeEnum, AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, TimestampsToReturnEnum, ReadValueId, QualifiedName, ReadRequest, StatusCode, CallRequest, ViewDescription, BrowseRequest, BrowseNextRequest, SubscriptionAcknowledgement, CreateSubscriptionRequest, PublishRequest, MonitoringParameters, ExtensionObject, MonitoredItemCreateRequest, MonitoringModeEnum, CreateMonitoredItemsRequest, StatusCodeToStringNumber, RequestHeader, ApplicationDescription, LocalizedText, ApplicationTypeEnum, CreateSessionRequest, CreateSessionResponse, SignatureData, ActivateSessionRequest } from 'opcjs-base';
1
+ import { NodeId, StatusCodeToString, initLoggerProvider, getLogger, WebSocketFascade, WebSocketReadableStream, WebSocketWritableStream, SecureChannelContext, TcpMessageInjector, TcpConnectionHandler, TcpMessageDecoupler, SecureChannelMessageEncoder, SecureChannelTypeDecoder, SecureChannelMessageDecoder, SecureChannelTypeEncoder, SecureChannelChunkWriter, SecureChannelChunkReader, SecureChannelFacade, CallMethodRequest, Variant, BrowseDescription, BrowseDirectionEnum, BrowseResultMaskEnum, Configuration, LoggerFactory, Encoder, BinaryWriter, registerEncoders, Decoder, BinaryReader, registerTypeDecoders, registerBinaryDecoders, UserTokenTypeEnum, AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, TimestampsToReturnEnum, ReadValueId, QualifiedName, ReadRequest, StatusCode, CallRequest, ViewDescription, BrowseRequest, BrowseNextRequest, SubscriptionAcknowledgement, ExpandedNodeId, CreateSubscriptionRequest, PublishRequest, MonitoringParameters, ExtensionObject, MonitoredItemCreateRequest, MonitoringModeEnum, CreateMonitoredItemsRequest, StatusCodeToStringNumber, RequestHeader, ApplicationDescription, LocalizedText, ApplicationTypeEnum, CreateSessionRequest, CreateSessionResponse, SignatureData, ActivateSessionRequest, CloseSessionRequest } from 'opcjs-base';
2
2
 
3
3
  // src/client.ts
4
4
  var SessionInvalidError = class extends Error {
@@ -90,17 +90,23 @@ var SessionService = class _SessionService extends ServiceBase {
90
90
  if (serviceResult !== void 0 && serviceResult !== StatusCode.Good) {
91
91
  throw new Error(`CreateSessionRequest failed: ${StatusCodeToString(serviceResult)}`);
92
92
  }
93
- const endpoint = "opc." + this.secureChannel.getEndpointUrl();
94
- const endpointUrl = new URL(endpoint);
93
+ const clientConnectionUrl = new URL("opc." + this.secureChannel.getEndpointUrl());
95
94
  const securityMode = this.secureChannel.getSecurityMode();
96
95
  const securityPolicyUri = this.secureChannel.getSecurityPolicy();
96
+ const normalizeEndpointUrl = (serverEndpointUrl) => {
97
+ const url = new URL(serverEndpointUrl);
98
+ url.hostname = clientConnectionUrl.hostname;
99
+ url.port = clientConnectionUrl.port;
100
+ return url;
101
+ };
97
102
  const serverEndpoint = castedResponse?.serverEndpoints?.find((currentEndpoint) => {
98
- const currentEndpointUrl = new URL(currentEndpoint.endpointUrl);
99
- return currentEndpointUrl.protocol === endpointUrl.protocol && currentEndpointUrl.pathname === endpointUrl.pathname && currentEndpointUrl.port === endpointUrl.port && currentEndpoint.securityMode === securityMode && currentEndpoint.securityPolicyUri === securityPolicyUri;
103
+ const normalized = normalizeEndpointUrl(currentEndpoint.endpointUrl);
104
+ return normalized.protocol === clientConnectionUrl.protocol && normalized.pathname === clientConnectionUrl.pathname && currentEndpoint.securityMode === securityMode && currentEndpoint.securityPolicyUri === securityPolicyUri;
100
105
  });
101
106
  if (!serverEndpoint) {
102
- throw new Error(`Server endpoint ${endpoint} not found in CreateSessionResponse`);
107
+ throw new Error(`Server endpoint ${clientConnectionUrl.toString()} not found in CreateSessionResponse`);
103
108
  }
109
+ serverEndpoint.endpointUrl = normalizeEndpointUrl(serverEndpoint.endpointUrl).toString();
104
110
  this.logger.debug("Session created with id:", castedResponse.sessionId.identifier);
105
111
  return {
106
112
  sessionId: castedResponse.sessionId.identifier,
@@ -131,6 +137,24 @@ var SessionService = class _SessionService extends ServiceBase {
131
137
  }
132
138
  this.logger.debug("Session activated.");
133
139
  }
140
+ /**
141
+ * Closes the current session on the server (OPC UA Part 4, Section 5.7.4).
142
+ * @param deleteSubscriptions - When true the server deletes all Subscriptions
143
+ * associated with this Session, freeing their resources immediately.
144
+ * Pass false to keep Subscriptions alive for transfer to another Session.
145
+ */
146
+ async closeSession(deleteSubscriptions) {
147
+ this.logger.debug("Sending CloseSessionRequest...");
148
+ const request = new CloseSessionRequest();
149
+ request.requestHeader = this.createRequestHeader();
150
+ request.deleteSubscriptions = deleteSubscriptions;
151
+ const response = await this.secureChannel.issueServiceRequest(request);
152
+ const result = response?.responseHeader?.serviceResult;
153
+ if (result !== void 0 && result !== StatusCode.Good) {
154
+ throw new Error(`CloseSession failed: ${StatusCodeToString(result)}`);
155
+ }
156
+ this.logger.debug("Session closed.");
157
+ }
134
158
  recreate(authToken) {
135
159
  return new _SessionService(authToken, this.secureChannel, this.configuration);
136
160
  }
@@ -192,23 +216,97 @@ var Session = class {
192
216
  getAuthToken() {
193
217
  return this.authToken;
194
218
  }
219
+ getSessionId() {
220
+ return this.sessionId;
221
+ }
222
+ getEndpoint() {
223
+ return this.endpoint;
224
+ }
225
+ /**
226
+ * Closes the session on the server (OPC UA Part 4, Section 5.7.4).
227
+ * @param deleteSubscriptions - When true the server deletes all Subscriptions
228
+ * tied to this Session. Defaults to true.
229
+ */
230
+ async close(deleteSubscriptions = true) {
231
+ await this.sessionServices.closeSession(deleteSubscriptions);
232
+ }
195
233
  };
196
234
 
197
235
  // src/sessions/sessionHandler.ts
198
236
  var SessionHandler = class {
237
+ constructor(secureChannel, configuration) {
238
+ this.configuration = configuration;
239
+ this.sessionServices = new SessionService(NodeId.newTwoByte(0), secureChannel, configuration);
240
+ }
199
241
  sessionServices;
242
+ logger = getLogger("sessions.SessionHandler");
200
243
  async createNewSession(identity) {
201
244
  const ret = await this.sessionServices.createSession();
202
245
  this.sessionServices = this.sessionServices.recreate(ret.authToken);
203
246
  const session = new Session(ret.sessionId, ret.authToken, ret.endpoint, this.sessionServices);
247
+ this.validateUserTokenPolicy(identity, ret.endpoint);
204
248
  await session.activateSession(identity);
205
249
  return session;
206
250
  }
207
- constructor(secureChannel, configuration) {
208
- this.sessionServices = new SessionService(NodeId.newTwoByte(0), secureChannel, configuration);
251
+ /**
252
+ * Attempts to reactivate an existing OPC UA session on the current (new) SecureChannel
253
+ * without calling CreateSession first (OPC UA Part 4, Section 5.7.3).
254
+ *
255
+ * This is the preferred recovery path when the SecureChannel drops but the server-side
256
+ * session has not yet timed out: only a new channel is needed, not a new session.
257
+ *
258
+ * @returns The reactivated Session if ActivateSession succeeded, or `null` if the server
259
+ * rejected the request (e.g. the session had already expired).
260
+ */
261
+ async tryActivateExistingSession(existingAuthToken, existingSessionId, existingEndpoint, identity) {
262
+ const serviceForExistingSession = this.sessionServices.recreate(existingAuthToken);
263
+ try {
264
+ const session = new Session(existingSessionId, existingAuthToken, existingEndpoint, serviceForExistingSession);
265
+ await session.activateSession(identity);
266
+ return session;
267
+ } catch (err) {
268
+ this.logger.debug("ActivateSession for existing session failed:", err);
269
+ return null;
270
+ }
271
+ }
272
+ /**
273
+ * Closes the active session on the server (OPC UA Part 4, Section 5.7.4).
274
+ * @param deleteSubscriptions - Forwarded to CloseSessionRequest. Defaults to true.
275
+ */
276
+ async closeSession(deleteSubscriptions = true) {
277
+ await this.sessionServices.closeSession(deleteSubscriptions);
278
+ }
279
+ /**
280
+ * Validates the requested user-identity token type against:
281
+ * 1. The `allowedUserTokenTypes` from the client security configuration — the
282
+ * client has explicitly restricted which token types it will use.
283
+ * 2. The token policies advertised by the server endpoint — verifies that the
284
+ * server actually supports at least one of the allowed types.
285
+ *
286
+ * Throws with a descriptive message if either check fails.
287
+ */
288
+ validateUserTokenPolicy(identity, endpoint) {
289
+ const allowedTypes = this.configuration.securityConfiguration?.allowedUserTokenTypes;
290
+ if (!allowedTypes) return;
291
+ const requestedType = identity.getTokenType();
292
+ if (!allowedTypes.includes(requestedType)) {
293
+ throw new Error(
294
+ `User token type '${UserTokenTypeEnum[requestedType]}' is not permitted by the client security configuration. Allowed types: ${allowedTypes.map((t) => UserTokenTypeEnum[t]).join(", ")}.`
295
+ );
296
+ }
297
+ const serverTypes = endpoint.userIdentityTokens?.map((p) => p.tokenType) ?? [];
298
+ const intersection = allowedTypes.filter((t) => serverTypes.includes(t));
299
+ if (intersection.length === 0) {
300
+ throw new Error(
301
+ `Server endpoint does not offer any user token type from the allowed list: ${allowedTypes.map((t) => UserTokenTypeEnum[t]).join(", ")}. Server offers: ${serverTypes.map((t) => UserTokenTypeEnum[t]).join(", ")}.`
302
+ );
303
+ }
209
304
  }
210
305
  };
211
306
 
307
+ // src/securityConfiguration.ts
308
+ var SECURITY_POLICY_NONE_URI = "http://opcfoundation.org/UA/SecurityPolicy#None";
309
+
212
310
  // src/services/attributeServiceAttributes.ts
213
311
  var AttrIdValue = 13;
214
312
 
@@ -283,6 +381,10 @@ var SubscriptionHandler = class {
283
381
  entries = new Array();
284
382
  nextHandle = 0;
285
383
  isRunning = false;
384
+ /** Returns true when at least one subscription is active and the publish loop is running. */
385
+ hasActiveSubscription() {
386
+ return this.isRunning && this.entries.length > 0;
387
+ }
286
388
  async subscribe(ids, callback) {
287
389
  if (this.entries.length > 0) {
288
390
  throw new Error("Subscribing more than once is not implemented");
@@ -325,7 +427,8 @@ var SubscriptionHandler = class {
325
427
  }
326
428
  for (const notificationData of notificationDatas) {
327
429
  const decodedData = notificationData.data;
328
- const typeNodeId = notificationData.typeId;
430
+ const rawTypeId = notificationData.typeId;
431
+ const typeNodeId = rawTypeId instanceof ExpandedNodeId ? rawTypeId.nodeId : rawTypeId;
329
432
  if (typeNodeId.namespace === 0 && typeNodeId.identifier === NODE_ID_DATA_CHANGE_NOTIFICATION) {
330
433
  const dataChangeNotification = decodedData;
331
434
  for (const item of dataChangeNotification.monitoredItems) {
@@ -538,6 +641,8 @@ var BrowseNodeResult = class {
538
641
  };
539
642
 
540
643
  // src/client.ts
644
+ var SERVER_STATUS_NODE_ID = NodeId.newNumeric(0, 2256);
645
+ var KEEP_ALIVE_INTERVAL_MS = 25e3;
541
646
  var Client = class {
542
647
  constructor(endpointUrl, configuration, identity) {
543
648
  this.configuration = configuration;
@@ -553,9 +658,12 @@ var Client = class {
553
658
  session;
554
659
  subscriptionHandler;
555
660
  logger;
556
- // Stored after connect() so that refreshSession() can recreate services.
661
+ // Stored after connect() so that refreshSession() and disconnect() can use them.
557
662
  secureChannel;
663
+ secureChannelFacade;
664
+ ws;
558
665
  sessionHandler;
666
+ keepAliveTimer;
559
667
  getSession() {
560
668
  if (!this.session) {
561
669
  throw new Error("No session available");
@@ -584,20 +692,77 @@ var Client = class {
584
692
  * This covers the reactive case: a service call reveals that the server has
585
693
  * already dropped the session (e.g. due to timeout). The new session is
586
694
  * established transparently before re-running the original operation.
695
+ *
696
+ * For any other error (e.g. transport-level failures when the SecureChannel
697
+ * drops), this method attempts to reconnect the channel and reactivate the
698
+ * existing session first — falling back to a brand-new session only when
699
+ * reactivation fails — before retrying the operation once.
587
700
  */
588
701
  async withSessionRefresh(fn) {
589
702
  try {
590
703
  return await fn();
591
704
  } catch (err) {
592
- if (!(err instanceof SessionInvalidError)) throw err;
593
- this.logger.info(`Session invalid (${err.statusCode.toString(16)}), refreshing session...`);
594
- this.session = await this.sessionHandler.createNewSession(this.identity);
595
- this.initServices();
596
- this.logger.info("Session refreshed, retrying operation.");
705
+ if (err instanceof SessionInvalidError) {
706
+ this.logger.info(`Session invalid (${err.statusCode.toString(16)}), refreshing session...`);
707
+ this.session = await this.sessionHandler.createNewSession(this.identity);
708
+ this.initServices();
709
+ this.logger.info("Session refreshed, retrying operation.");
710
+ return await fn();
711
+ }
712
+ this.logger.info("Service call failed, attempting channel reconnect and session reactivation...");
713
+ try {
714
+ await this.reconnectAndReactivate();
715
+ this.initServices();
716
+ this.logger.info("Reconnected successfully, retrying operation.");
717
+ } catch (reconnectErr) {
718
+ this.logger.warn("Channel reconnect failed:", reconnectErr);
719
+ throw err;
720
+ }
597
721
  return await fn();
598
722
  }
599
723
  }
724
+ /**
725
+ * Starts a periodic keep-alive timer that reads Server_ServerStatus when no subscription is
726
+ * active. OPC UA Part 4, Section 5.7.1 requires clients to keep the session alive; when no
727
+ * subscription Publish loop is running this is the only mechanism that does so.
728
+ */
729
+ startKeepAlive() {
730
+ this.keepAliveTimer = setInterval(() => {
731
+ if (this.subscriptionHandler?.hasActiveSubscription()) {
732
+ return;
733
+ }
734
+ if (this.attributeService) {
735
+ void this.attributeService.ReadValue([SERVER_STATUS_NODE_ID]).catch((err) => {
736
+ this.logger.warn("Keep-alive read failed:", err);
737
+ });
738
+ }
739
+ }, KEEP_ALIVE_INTERVAL_MS);
740
+ }
741
+ stopKeepAlive() {
742
+ clearInterval(this.keepAliveTimer);
743
+ this.keepAliveTimer = void 0;
744
+ }
600
745
  async connect() {
746
+ const { ws, sc } = await this.openTransportAndChannel();
747
+ this.secureChannel = sc;
748
+ this.secureChannelFacade = sc;
749
+ this.ws = ws;
750
+ this.logger.debug("Creating session...");
751
+ this.sessionHandler = new SessionHandler(sc, this.configuration);
752
+ this.session = await this.sessionHandler.createNewSession(this.identity);
753
+ this.logger.debug("Session created.");
754
+ this.logger.debug("Initializing services...");
755
+ this.initServices();
756
+ this.startKeepAlive();
757
+ }
758
+ /**
759
+ * Builds the full WebSocket → TCP → SecureChannel pipeline and returns the
760
+ * two objects needed to drive it: the raw WebSocket facade (for teardown)
761
+ * and the SecureChannelFacade (for service requests/session management).
762
+ *
763
+ * Extracted from `connect()` so it can be reused by `reconnectAndReactivate()`.
764
+ */
765
+ async openTransportAndChannel() {
601
766
  const wsOptions = { endpoint: this.endpointUrl };
602
767
  const ws = new WebSocketFascade(wsOptions);
603
768
  const webSocketReadableStream = new WebSocketReadableStream(ws, 1e3);
@@ -606,7 +771,7 @@ var Client = class {
606
771
  const tcpMessageInjector = new TcpMessageInjector();
607
772
  const tcpConnectionHandler = new TcpConnectionHandler(tcpMessageInjector, scContext);
608
773
  const tcpMessageDecoupler = new TcpMessageDecoupler(tcpConnectionHandler.onTcpMessage.bind(tcpConnectionHandler));
609
- const scMessageEncoder = new SecureChannelMesssageEncoder(scContext);
774
+ const scMessageEncoder = new SecureChannelMessageEncoder(scContext);
610
775
  const scTypeDecoder = new SecureChannelTypeDecoder(
611
776
  this.configuration.decoder
612
777
  );
@@ -640,16 +805,106 @@ var Client = class {
640
805
  this.logger.debug("Opening secure channel...");
641
806
  await sc.openSecureChannel();
642
807
  this.logger.debug("Secure channel established.");
643
- this.logger.debug("Creating session...");
644
- this.sessionHandler = new SessionHandler(sc, this.configuration);
808
+ this.enforceChannelSecurityConfig(sc);
809
+ return { ws, sc };
810
+ }
811
+ /**
812
+ * Validates the negotiated channel's security policy and mode against the
813
+ * client's `SecurityConfiguration` (OPC UA Part 2, Security Administration).
814
+ *
815
+ * Throws if:
816
+ * - `allowSecurityPolicyNone` is `false` and the channel uses SecurityPolicy None.
817
+ * - `messageSecurityMode` is set and does not match the channel's actual mode.
818
+ */
819
+ enforceChannelSecurityConfig(sc) {
820
+ const config = this.configuration.securityConfiguration;
821
+ if (!config) return;
822
+ const negotiatedPolicy = sc.getSecurityPolicy();
823
+ const negotiatedMode = sc.getSecurityMode();
824
+ if (config.allowSecurityPolicyNone === false && negotiatedPolicy === SECURITY_POLICY_NONE_URI) {
825
+ throw new Error(
826
+ "Connection refused: SecurityPolicy None is disabled by the client security configuration. Only SecurityPolicy None is currently supported by this client implementation."
827
+ );
828
+ }
829
+ if (config.messageSecurityMode !== void 0 && config.messageSecurityMode !== negotiatedMode) {
830
+ throw new Error(
831
+ `Connection refused: negotiated MessageSecurityMode ${negotiatedMode} does not match the required mode ${config.messageSecurityMode} from the security configuration.`
832
+ );
833
+ }
834
+ }
835
+ /**
836
+ * Tears down the current (dead) channel and establishes a fresh one, then
837
+ * attempts to recover the existing OPC UA session via ActivateSession before
838
+ * falling back to a full CreateSession + ActivateSession.
839
+ *
840
+ * OPC UA Part 4, Section 5.7.1 / Session Client Auto Reconnect conformance unit:
841
+ * When the SecureChannel drops but the server-side session has not yet timed
842
+ * out, the client SHOULD reuse the existing session by calling ActivateSession
843
+ * on the new channel. Only if that fails should the client create a new session.
844
+ */
845
+ async reconnectAndReactivate() {
846
+ this.logger.info("Tearing down dead channel before reconnect...");
847
+ try {
848
+ this.secureChannelFacade?.close();
849
+ } catch {
850
+ }
851
+ try {
852
+ this.ws?.close();
853
+ } catch {
854
+ }
855
+ this.secureChannelFacade = void 0;
856
+ this.secureChannel = void 0;
857
+ this.ws = void 0;
858
+ const { ws, sc } = await this.openTransportAndChannel();
645
859
  this.secureChannel = sc;
860
+ this.secureChannelFacade = sc;
861
+ this.ws = ws;
862
+ this.sessionHandler = new SessionHandler(sc, this.configuration);
863
+ if (this.session) {
864
+ const reactivated = await this.sessionHandler.tryActivateExistingSession(
865
+ this.session.getAuthToken(),
866
+ this.session.getSessionId(),
867
+ this.session.getEndpoint(),
868
+ this.identity
869
+ );
870
+ if (reactivated !== null) {
871
+ this.session = reactivated;
872
+ this.logger.info("Existing session successfully reactivated on new channel.");
873
+ return;
874
+ }
875
+ this.logger.info("ActivateSession for existing session failed; creating a fresh session...");
876
+ }
646
877
  this.session = await this.sessionHandler.createNewSession(this.identity);
647
- this.logger.debug("Session created.");
648
- this.logger.debug("Initializing services...");
649
- this.initServices();
878
+ this.logger.info("Fresh session established on new channel.");
650
879
  }
880
+ /**
881
+ * Gracefully disconnects from the OPC UA server.
882
+ *
883
+ * Sequence per OPC UA Part 4, Section 5.7.4:
884
+ * 1. CloseSession (deleteSubscriptions=true) so the server frees all resources.
885
+ * 2. Close the SecureChannel, which cancels the pending token-renewal timer.
886
+ * 3. Close the WebSocket transport.
887
+ *
888
+ * CloseSession errors are swallowed so transport teardown always completes even
889
+ * when the session has already expired on the server side.
890
+ */
651
891
  async disconnect() {
652
892
  this.logger.info("Disconnecting from OPC UA server...");
893
+ this.stopKeepAlive();
894
+ if (this.session && this.sessionHandler) {
895
+ try {
896
+ await this.sessionHandler.closeSession(true);
897
+ } catch (err) {
898
+ this.logger.warn("CloseSession failed (continuing teardown):", err);
899
+ }
900
+ this.session = void 0;
901
+ }
902
+ this.secureChannelFacade?.close();
903
+ this.secureChannelFacade = void 0;
904
+ this.secureChannel = void 0;
905
+ this.ws?.close();
906
+ this.ws = void 0;
907
+ this.logger.info("Disconnected.");
653
908
  }
654
909
  async read(ids) {
655
910
  return this.withSessionRefresh(async () => {
@@ -718,8 +973,8 @@ var Client = class {
718
973
  if (recursive) {
719
974
  for (const ref of allReferences) {
720
975
  const childNodeId = NodeId.newNumeric(
721
- ref.nodeId.namespace,
722
- ref.nodeId.identifier
976
+ ref.nodeId.nodeId.namespace,
977
+ ref.nodeId.nodeId.identifier
723
978
  );
724
979
  const childResults = await this.browseRecursive(
725
980
  childNodeId,
@@ -736,6 +991,14 @@ var Client = class {
736
991
  }
737
992
  };
738
993
  var ConfigurationClient = class _ConfigurationClient extends Configuration {
994
+ /**
995
+ * Optional security restrictions applied during `Client.connect()`.
996
+ * When not set, permissive defaults are used (SecurityPolicy None allowed,
997
+ * all user-token types accepted).
998
+ *
999
+ * @see SecurityConfiguration
1000
+ */
1001
+ securityConfiguration;
739
1002
  static getSimple(name, company, loggerFactory) {
740
1003
  if (!loggerFactory) {
741
1004
  loggerFactory = new LoggerFactory({
@@ -825,6 +1088,6 @@ var UserIdentity = class _UserIdentity {
825
1088
  }
826
1089
  };
827
1090
 
828
- export { BrowseNodeResult, Client, ConfigurationClient, SessionInvalidError, UserIdentity };
1091
+ export { BrowseNodeResult, Client, ConfigurationClient, SECURITY_POLICY_NONE_URI, SessionInvalidError, UserIdentity };
829
1092
  //# sourceMappingURL=index.js.map
830
1093
  //# sourceMappingURL=index.js.map