node-opcua-server 2.164.2 → 2.165.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.
@@ -1,86 +1,91 @@
1
1
  /**
2
2
  * @module node-opcua-server
3
3
  */
4
- import { EventEmitter } from "events";
5
- import { types } from "util";
4
+ import { EventEmitter } from "node:events";
5
+ import { types } from "node:util";
6
+
6
7
  import async from "async";
7
8
  import chalk from "chalk";
8
- import { assert } from "node-opcua-assert";
9
- import { BinaryStream } from "node-opcua-binary-stream";
10
9
  import {
11
- addElement,
12
10
  AddressSpace,
11
+ addElement,
12
+ type BindVariableOptions,
13
13
  bindExtObjArrayNode,
14
+ type DTServerStatus,
14
15
  ensureObjectIsSecure,
15
- MethodFunctor,
16
+ type IServerBase,
17
+ type ISessionContext,
18
+ type MethodFunctor,
16
19
  removeElement,
17
- SessionContext,
18
- UADynamicVariableArray,
19
- UAMethod,
20
- UAObject,
21
- UAServerDiagnosticsSummary,
22
- UAServerStatus,
23
- UAVariable,
24
- UAServerDiagnostics,
25
- BindVariableOptions,
26
- ISessionContext,
27
- DTServerStatus,
28
- IServerBase
20
+ type SessionContext,
21
+ type UADynamicVariableArray,
22
+ type UAMethod,
23
+ type UAObject,
24
+ type UAServerDiagnostics,
25
+ type UAServerDiagnosticsSummary,
26
+ type UAServerStatus,
27
+ type UAVariable
29
28
  } from "node-opcua-address-space";
30
29
  import { generateAddressSpace } from "node-opcua-address-space/nodeJS";
31
- import { DataValue } from "node-opcua-data-value";
30
+ import { assert } from "node-opcua-assert";
31
+ import type { UInt32 } from "node-opcua-basic-types";
32
+ import { BinaryStream } from "node-opcua-binary-stream";
33
+ import type { CreateSubscriptionRequestLike } from "node-opcua-client";
32
34
  import {
33
35
  ServerDiagnosticsSummaryDataType,
34
36
  ServerState,
35
37
  ServerStatusDataType,
36
38
  SubscriptionDiagnosticsDataType
37
39
  } from "node-opcua-common";
38
- import { AttributeIds, coerceLocalizedText, LocalizedTextLike, makeAccessLevelFlag, NodeClass } from "node-opcua-data-model";
39
- import { coerceNodeId, makeNodeId, NodeId, NodeIdLike, NodeIdType, resolveNodeId } from "node-opcua-nodeid";
40
- import { BrowseResult } from "node-opcua-service-browse";
41
- import { UInt32 } from "node-opcua-basic-types";
42
- import { CreateSubscriptionRequestLike } from "node-opcua-client";
43
40
  import { DataTypeIds, MethodIds, ObjectIds, VariableIds } from "node-opcua-constants";
41
+ import { AttributeIds, coerceLocalizedText, type LocalizedTextLike, makeAccessLevelFlag, NodeClass } from "node-opcua-data-model";
42
+ import type { DataValue } from "node-opcua-data-value";
44
43
  import { getCurrentClock, getMinOPCUADate } from "node-opcua-date-time";
45
44
  import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog, traceFromThisProjectOnly } from "node-opcua-debug";
45
+ import { coerceNodeId, makeNodeId, NodeId, type NodeIdLike, NodeIdType, resolveNodeId } from "node-opcua-nodeid";
46
46
  import { nodesets } from "node-opcua-nodesets";
47
47
  import { ObjectRegistry } from "node-opcua-object-registry";
48
+ import type { BrowseResult } from "node-opcua-service-browse";
48
49
  import { CallMethodResult } from "node-opcua-service-call";
49
- import { TransferResult } from "node-opcua-service-subscription";
50
50
  import { ApplicationDescription } from "node-opcua-service-endpoints";
51
- import { HistoryReadRequest, HistoryReadResult, HistoryReadValueId } from "node-opcua-service-history";
52
- import { StatusCode, StatusCodes, CallbackT } from "node-opcua-status-code";
51
+ import type { HistoryReadRequest, HistoryReadResult, HistoryReadValueId } from "node-opcua-service-history";
52
+ import { TransferResult } from "node-opcua-service-subscription";
53
+ import { type CallbackT, type StatusCode, StatusCodes } from "node-opcua-status-code";
53
54
  import {
54
- BrowseDescription,
55
- BrowsePath,
56
- BrowsePathResult,
57
- BuildInfo,
58
- BuildInfoOptions,
59
- SessionDiagnosticsDataType,
60
- SessionSecurityDiagnosticsDataType,
61
- WriteValue,
55
+ ApplicationType,
56
+ type BrowseDescription,
57
+ type BrowseDescriptionOptions,
58
+ type BrowsePath,
59
+ type BrowsePathResult,
60
+ type BuildInfo,
61
+ type BuildInfoOptions,
62
+ type CallMethodRequest,
63
+ type CallMethodResultOptions,
64
+ ProgramDiagnosticDataType,
65
+ type ReadRequestOptions,
62
66
  ReadValueId,
67
+ type SessionDiagnosticsDataType,
68
+ type SessionSecurityDiagnosticsDataType,
63
69
  TimeZoneDataType,
64
- ProgramDiagnosticDataType,
65
- CallMethodResultOptions,
66
- ReadRequestOptions,
67
- BrowseDescriptionOptions,
68
- CallMethodRequest,
69
- ApplicationType
70
+ type WriteValue
70
71
  } from "node-opcua-types";
71
72
  import { DataType, isValidVariant, Variant, VariantArrayType } from "node-opcua-variant";
72
-
73
- import { HistoryServerCapabilities, HistoryServerCapabilitiesOptions } from "./history_server_capabilities";
73
+ import { AddressSpaceAccessor } from "./addressSpace_accessor";
74
+ import { HistoryServerCapabilities, type HistoryServerCapabilitiesOptions } from "./history_server_capabilities";
75
+ import type { IAddressSpaceAccessor } from "./i_address_space_accessor";
74
76
  import { MonitoredItem } from "./monitored_item";
75
- import { ServerCapabilities, ServerCapabilitiesOptions, ServerOperationLimits, defaultServerCapabilities } from "./server_capabilities";
77
+ import type { OPCUAServerOptions } from "./opcua_server";
78
+ import {
79
+ defaultServerCapabilities,
80
+ ServerCapabilities,
81
+ type ServerCapabilitiesOptions,
82
+ type ServerOperationLimits
83
+ } from "./server_capabilities";
76
84
  import { ServerSidePublishEngine } from "./server_publish_engine";
77
85
  import { ServerSidePublishEngineForOrphanSubscription } from "./server_publish_engine_for_orphan_subscriptions";
78
86
  import { ServerSession } from "./server_session";
79
87
  import { Subscription } from "./server_subscription";
80
88
  import { sessionsCompatibleForTransfer } from "./sessions_compatible_for_transfer";
81
- import { OPCUAServerOptions } from "./opcua_server";
82
- import { IAddressSpaceAccessor } from "./i_address_space_accessor";
83
- import { AddressSpaceAccessor } from "./addressSpace_accessor";
84
89
 
85
90
  const debugLog = make_debugLog(__filename);
86
91
  const errorLog = make_errorLog(__filename);
@@ -95,7 +100,7 @@ async function shutdownAndDisposeAddressSpace(this: ServerEngine) {
95
100
  if (this.addressSpace) {
96
101
  await this.addressSpace.shutdown();
97
102
  this.addressSpace.dispose();
98
- delete (this as any).addressSpace;
103
+ this.addressSpace = null;
99
104
  }
100
105
  }
101
106
 
@@ -220,7 +225,10 @@ function resendData(
220
225
  assert(typeof callback === "function");
221
226
 
222
227
  const data = _getSubscription.call(this, inputArguments, context);
223
- if (data.statusCode) return callback(null, { statusCode: data.statusCode });
228
+ if (data.statusCode) {
229
+ callback(null, { statusCode: data.statusCode });
230
+ return;
231
+ }
224
232
  const { subscription } = data;
225
233
 
226
234
  subscription
@@ -260,11 +268,14 @@ function getMonitoredItemsId(
260
268
  function __bindVariable(self: ServerEngine, nodeId: NodeIdLike, options?: BindVariableOptions) {
261
269
  options = options || {};
262
270
 
263
- const variable = self.addressSpace!.findNode(nodeId) as UAVariable;
264
- if (variable && variable.bindVariable) {
271
+ if (!self.addressSpace) {
272
+ return;
273
+ }
274
+ const variable = self.addressSpace.findNode(nodeId) as UAVariable;
275
+ if (variable?.bindVariable) {
265
276
  variable.bindVariable(options, true);
266
277
  assert(typeof variable.asyncRefresh === "function");
267
- assert(typeof (variable as any).refreshFunc === "function");
278
+ assert(typeof (variable as unknown as Record<string, unknown>).refreshFunc === "function");
268
279
  } else {
269
280
  warningLog(
270
281
  "Warning: cannot bind object with id ",
@@ -419,8 +430,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
419
430
  "http://opcfoundation.org/UA-Profile/Server/StandardEventSubscription",
420
431
  "http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary",
421
432
  "http://opcfoundation.org/UA-Profile/Server/FileAccess",
422
- "http://opcfoundation.org/UA-Profile/Server/StateMachine",
423
-
433
+ "http://opcfoundation.org/UA-Profile/Server/StateMachine"
424
434
 
425
435
  // "http://opcfoundation.org/UA-Profile/Transport/wss-uajson",
426
436
  // "http://opcfoundation.org/UA-Profile/Transport/wss-uasc-uabinary"
@@ -445,8 +455,9 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
445
455
  ];
446
456
 
447
457
  // make sure minSupportedSampleRate matches MonitoredItem.minimumSamplingInterval
448
- (this.serverCapabilities as any).__defineGetter__("minSupportedSampleRate", () => {
449
- return options!.serverCapabilities?.minSupportedSampleRate || MonitoredItem.minimumSamplingInterval;
458
+ Object.defineProperty(this.serverCapabilities, "minSupportedSampleRate", {
459
+ get: () => options.serverCapabilities?.minSupportedSampleRate || MonitoredItem.minimumSamplingInterval,
460
+ configurable: true
450
461
  });
451
462
 
452
463
  this.serverConfiguration = options.serverConfiguration;
@@ -461,16 +472,19 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
461
472
  // and sessionDiagnostics.currentSubscriptionsCount ( with an s)
462
473
  assert(Object.prototype.hasOwnProperty.call(this.serverDiagnosticsSummary, "currentSubscriptionCount"));
463
474
 
464
- (this.serverDiagnosticsSummary as any).__defineGetter__("currentSubscriptionCount", () => {
465
- // currentSubscriptionCount returns the total number of subscriptions
466
- // that are currently active on all sessions
467
- let counter = 0;
468
- Object.values(this._sessions).forEach((session: ServerSession) => {
469
- counter += session.currentSubscriptionCount;
470
- });
471
- // we also need to add the orphan subscriptions
472
- counter += this._orphanPublishEngine ? this._orphanPublishEngine.subscriptions.length : 0;
473
- return counter;
475
+ Object.defineProperty(this.serverDiagnosticsSummary, "currentSubscriptionCount", {
476
+ get: () => {
477
+ // currentSubscriptionCount returns the total number of subscriptions
478
+ // that are currently active on all sessions
479
+ let counter = 0;
480
+ Object.values(this._sessions).forEach((session: ServerSession) => {
481
+ counter += session.currentSubscriptionCount;
482
+ });
483
+ // we also need to add the orphan subscriptions
484
+ counter += this._orphanPublishEngine ? this._orphanPublishEngine.subscriptions.length : 0;
485
+ return counter;
486
+ },
487
+ configurable: true
474
488
  });
475
489
 
476
490
  this._internalState = "creating";
@@ -483,7 +497,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
483
497
 
484
498
  this._applicationUri = "";
485
499
  if (typeof options.applicationUri === "function") {
486
- (this as any).__defineGetter__("_applicationUri", options.applicationUri);
500
+ Object.defineProperty(this, "_applicationUri", {
501
+ get: options.applicationUri,
502
+ configurable: true
503
+ });
487
504
  } else {
488
505
  this._applicationUri = options.applicationUri || "<unset _applicationUri>";
489
506
  }
@@ -492,10 +509,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
492
509
  ? options.serverDiagnosticsEnabled
493
510
  : true;
494
511
 
495
- this.serverDiagnosticsEnabled = options.serverDiagnosticsEnabled!;
512
+ this.serverDiagnosticsEnabled = options.serverDiagnosticsEnabled || false;
496
513
  }
497
514
  public isStarted(): boolean {
498
- return !!this._serverStatus!;
515
+ return !!this._serverStatus;
499
516
  }
500
517
 
501
518
  public dispose(): void {
@@ -515,7 +532,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
515
532
  }
516
533
 
517
534
  this._shutdownTasks = [];
518
- this._serverStatus = null as any as ServerStatusDataType;
535
+ this._serverStatus = null as unknown as ServerStatusDataType;
519
536
  this._internalState = "disposed";
520
537
  this.removeAllListeners();
521
538
 
@@ -523,11 +540,11 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
523
540
  }
524
541
 
525
542
  public get startTime(): Date {
526
- return this._serverStatus.startTime!;
543
+ return this._serverStatus.startTime || new Date();
527
544
  }
528
545
 
529
546
  public get currentTime(): Date {
530
- return this._serverStatus.currentTime!;
547
+ return this._serverStatus.currentTime || new Date();
531
548
  }
532
549
 
533
550
  public get buildInfo(): BuildInfo {
@@ -683,9 +700,11 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
683
700
  this._expectedShutdownTime = date;
684
701
  }
685
702
  public setShutdownReason(reason: LocalizedTextLike): void {
703
+ const localizedReason = coerceLocalizedText(reason);
704
+ if (!localizedReason) return;
686
705
  this.addressSpace?.rootFolder.objects.server.serverStatus.shutdownReason.setValueFromSource({
687
706
  dataType: DataType.LocalizedText,
688
- value: coerceLocalizedText(reason)!
707
+ value: localizedReason
689
708
  });
690
709
  }
691
710
  /**
@@ -705,7 +724,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
705
724
  * the name of the server
706
725
  */
707
726
  public get serverName(): string {
708
- return this._serverStatus.buildInfo!.productName!;
727
+ return this._serverStatus.buildInfo?.productName || "";
709
728
  }
710
729
 
711
730
  /**
@@ -733,8 +752,77 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
733
752
  });
734
753
  }
735
754
 
755
+ public getServerState(): ServerState {
756
+ return this._serverStatus.state;
757
+ }
758
+
759
+ /**
760
+ * Set the `ServerConfiguration.InApplicationSetup` property
761
+ * in the address space.
762
+ *
763
+ * This flag indicates whether the server is currently in
764
+ * its initial application setup phase (e.g. waiting for
765
+ * GDS provisioning).
766
+ */
767
+ public setInApplicationSetup(value: boolean): void {
768
+ const addressSpace = this.addressSpace;
769
+ if (!addressSpace) {
770
+ return;
771
+ }
772
+ const serverConfiguration = addressSpace.rootFolder?.objects?.server?.getChildByName(
773
+ "ServerConfiguration"
774
+ ) as UAObject | null;
775
+ if (!serverConfiguration) {
776
+ return;
777
+ }
778
+ let prop = serverConfiguration.getPropertyByName("InApplicationSetup") as UAVariable | null;
779
+ if (!prop) {
780
+ // InApplicationSetup is ModellingRule_Optional on
781
+ // ServerConfigurationType (i=19308) — instantiate
782
+ // it on the instance on first use.
783
+ const ns = addressSpace.getOwnNamespace();
784
+ prop = ns.addVariable({
785
+ browseName: { name: "InApplicationSetup", namespaceIndex: 0 },
786
+ propertyOf: serverConfiguration,
787
+ typeDefinition: "PropertyType",
788
+ dataType: DataType.Boolean,
789
+ minimumSamplingInterval: -1,
790
+ value: { dataType: DataType.Boolean, value }
791
+ });
792
+ return;
793
+ }
794
+ prop.setValueFromSource({
795
+ dataType: DataType.Boolean,
796
+ value
797
+ });
798
+ }
799
+
800
+ /**
801
+ * Read the current value of
802
+ * `ServerConfiguration.InApplicationSetup`.
803
+ *
804
+ * Returns `false` if the property does not exist in
805
+ * the address space.
806
+ */
807
+ public getInApplicationSetup(): boolean {
808
+ const serverConfiguration = this.addressSpace?.rootFolder?.objects?.server?.getChildByName(
809
+ "ServerConfiguration"
810
+ ) as UAObject | null;
811
+ if (!serverConfiguration) {
812
+ return false;
813
+ }
814
+ const prop = serverConfiguration.getPropertyByName("InApplicationSetup") as UAVariable | null;
815
+ if (!prop) {
816
+ return false;
817
+ }
818
+ return prop.readValue().value.value ?? false;
819
+ }
820
+
736
821
  public getServerDiagnosticsEnabledFlag(): boolean {
737
- const server = this.addressSpace!.rootFolder.objects.server;
822
+ if (!this.addressSpace) {
823
+ return false;
824
+ }
825
+ const server = this.addressSpace.rootFolder.objects.server;
738
826
  const serverDiagnostics = server.getComponentByName("ServerDiagnostics") as UAVariable;
739
827
  if (!serverDiagnostics) {
740
828
  return false;
@@ -784,7 +872,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
784
872
  const endTime = new Date();
785
873
  debugLog("Loading ", options.nodeset_filename, " done : ", endTime.getTime() - startTime.getTime(), " ms");
786
874
 
787
- const bindVariableIfPresent = (nodeId: NodeId, opts: any) => {
875
+ const bindVariableIfPresent = (nodeId: NodeId, opts?: BindVariableOptions) => {
788
876
  assert(!nodeId.isEmpty());
789
877
  const obj = addressSpace.findNode(nodeId);
790
878
  if (obj) {
@@ -842,8 +930,8 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
842
930
  const bindStandardScalar = (
843
931
  id: number,
844
932
  dataType: DataType,
845
- func: () => any,
846
- setter_func?: (value: any) => void
933
+ func: () => unknown,
934
+ setter_func?: (value: boolean) => void
847
935
  ) => {
848
936
  assert(typeof id === "number", "expecting id to be a number");
849
937
  assert(typeof func === "function");
@@ -867,7 +955,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
867
955
  /* c8 ignore next */
868
956
  if (!isValidVariant(VariantArrayType.Scalar, dataType, func())) {
869
957
  errorLog("func", func());
870
- throw new Error("bindStandardScalar : func doesn't provide an value of type " + DataType[dataType]);
958
+ throw new Error(`bindStandardScalar : func doesn't provide an value of type ${DataType[dataType]}`);
871
959
  }
872
960
 
873
961
  return bindVariableIfPresent(nodeId, {
@@ -882,7 +970,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
882
970
  });
883
971
  };
884
972
 
885
- const bindStandardArray = (id: number, variantDataType: DataType, dataType: any, func: () => any[]) => {
973
+ const bindStandardArray = (id: number, variantDataType: DataType, _dataType: unknown, func: () => unknown[]) => {
886
974
  assert(typeof func === "function");
887
975
  assert(variantDataType !== null); // check invalid dataType
888
976
 
@@ -909,7 +997,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
909
997
  bindStandardScalar(VariableIds.Server_EstimatedReturnTime, DataType.DateTime, () => getMinOPCUADate());
910
998
 
911
999
  // TimeZoneDataType
912
- const timeZoneDataType = addressSpace.findDataType(resolveNodeId(DataTypeIds.TimeZoneDataType))!;
1000
+ addressSpace.findDataType(resolveNodeId(DataTypeIds.TimeZoneDataType));
913
1001
 
914
1002
  const timeZone = new TimeZoneDataType({
915
1003
  daylightSavingInOffset: /* boolean*/ false,
@@ -1005,7 +1093,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1005
1093
  serverStatusNode.secondsTillShutdown.touchValue();
1006
1094
  return engine.secondsTillShutdown();
1007
1095
  }
1008
- return (target as any)[prop];
1096
+ return (target as unknown as Record<string | symbol, unknown>)[prop];
1009
1097
  }
1010
1098
  });
1011
1099
  this._serverStatus = serverStatusNode.$extensionObject;
@@ -1111,12 +1199,12 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1111
1199
  const keys = Object.keys(operationLimits);
1112
1200
 
1113
1201
  keys.forEach((key: string) => {
1114
- const uid = "Server_ServerCapabilities_OperationLimits_" + upperCaseFirst(key);
1115
- const nodeId = makeNodeId((VariableIds as any)[uid]);
1202
+ const uid = `Server_ServerCapabilities_OperationLimits_${upperCaseFirst(key)}`;
1203
+ const nodeId = makeNodeId((VariableIds as unknown as Record<string, number>)[uid]);
1116
1204
  assert(!nodeId.isEmpty());
1117
1205
 
1118
- bindStandardScalar((VariableIds as any)[uid], DataType.UInt32, () => {
1119
- return (operationLimits as any)[key];
1206
+ bindStandardScalar((VariableIds as unknown as Record<string, number>)[uid], DataType.UInt32, () => {
1207
+ return (operationLimits as unknown as Record<string, unknown>)[key];
1120
1208
  });
1121
1209
  });
1122
1210
  };
@@ -1128,7 +1216,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1128
1216
  const nodeId = coerceNodeId("i=2399"); // ProgramStateMachineType_ProgramDiagnostics
1129
1217
  const variable = addressSpace.findNode(nodeId) as UAVariable;
1130
1218
  if (variable) {
1131
- (variable as any).$extensionObject = new ProgramDiagnosticDataType({});
1219
+ (variable as unknown as Record<string, unknown>).$extensionObject = new ProgramDiagnosticDataType({});
1132
1220
  // variable.setValueFromSource({
1133
1221
  // dataType: DataType.ExtensionObject,
1134
1222
  // // value: new ProgramDiagnostic2DataType()
@@ -1201,7 +1289,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1201
1289
  function r<T>(a: undefined | T | Getter<T>, defaultValue: T): T {
1202
1290
  if (a === undefined) return defaultValue;
1203
1291
  if (typeof a === "function") {
1204
- return (a as any)();
1292
+ return (a as unknown as () => T)();
1205
1293
  }
1206
1294
  return a;
1207
1295
  }
@@ -1294,15 +1382,18 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1294
1382
 
1295
1383
  // fix getMonitoredItems.outputArguments arrayDimensions
1296
1384
  const fixGetMonitoredItemArgs = () => {
1297
- const objects = this.addressSpace!.rootFolder?.objects;
1385
+ const objects = this.addressSpace?.rootFolder?.objects;
1298
1386
  if (!objects || !objects.server) {
1299
1387
  return;
1300
1388
  }
1301
- const getMonitoredItemsMethod = objects.server.getMethodByName("GetMonitoredItems")!;
1389
+ const getMonitoredItemsMethod = objects.server.getMethodByName("GetMonitoredItems");
1302
1390
  if (!getMonitoredItemsMethod) {
1303
1391
  return;
1304
1392
  }
1305
- const outputArguments = getMonitoredItemsMethod.outputArguments!;
1393
+ const outputArguments = getMonitoredItemsMethod.outputArguments;
1394
+ if (!outputArguments) {
1395
+ return;
1396
+ }
1306
1397
  const dataValue = outputArguments.readValue();
1307
1398
  if (!dataValue.value?.value) {
1308
1399
  // value is null or undefined , meaning no arguments necessary
@@ -1318,7 +1409,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1318
1409
  fixGetMonitoredItemArgs();
1319
1410
 
1320
1411
  const prepareServerDiagnostics = () => {
1321
- const addressSpace1 = this.addressSpace!;
1412
+ const addressSpace1 = this.addressSpace;
1413
+ if (!addressSpace1) {
1414
+ return;
1415
+ }
1322
1416
 
1323
1417
  if (!addressSpace1.rootFolder.objects) {
1324
1418
  return;
@@ -1349,22 +1443,24 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1349
1443
  );
1350
1444
  if (samplingIntervalDiagnosticsArray) {
1351
1445
  addressSpace.deleteNode(samplingIntervalDiagnosticsArray);
1352
- const s = serverDiagnosticsNode.getComponents();
1353
1446
  }
1354
1447
 
1355
1448
  const subscriptionDiagnosticsArrayNode = serverDiagnosticsNode.getComponentByName(
1356
1449
  "SubscriptionDiagnosticsArray"
1357
- )! as UADynamicVariableArray<SessionDiagnosticsDataType>;
1450
+ ) as UADynamicVariableArray<SessionDiagnosticsDataType>;
1358
1451
  assert(subscriptionDiagnosticsArrayNode.nodeClass === NodeClass.Variable);
1359
1452
  bindExtObjArrayNode(subscriptionDiagnosticsArrayNode, "SubscriptionDiagnosticsType", "subscriptionId");
1360
1453
 
1361
1454
  makeNotReadableIfEnabledFlagIsFalse(subscriptionDiagnosticsArrayNode);
1362
1455
 
1363
- const sessionsDiagnosticsSummary = serverDiagnosticsNode.getComponentByName("SessionsDiagnosticsSummary")!;
1456
+ const sessionsDiagnosticsSummary = serverDiagnosticsNode.getComponentByName("SessionsDiagnosticsSummary");
1364
1457
 
1458
+ if (!sessionsDiagnosticsSummary) {
1459
+ return;
1460
+ }
1365
1461
  const sessionDiagnosticsArray = sessionsDiagnosticsSummary.getComponentByName(
1366
1462
  "SessionDiagnosticsArray"
1367
- )! as UADynamicVariableArray<SessionDiagnosticsDataType>;
1463
+ ) as UADynamicVariableArray<SessionDiagnosticsDataType>;
1368
1464
  assert(sessionDiagnosticsArray.nodeClass === NodeClass.Variable);
1369
1465
 
1370
1466
  bindExtObjArrayNode(sessionDiagnosticsArray, "SessionDiagnosticsVariableType", "sessionId");
@@ -1375,7 +1471,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1375
1471
  } else {
1376
1472
  const sessionSecurityDiagnosticsArray = sessionsDiagnosticsSummary.getComponentByName(
1377
1473
  "SessionSecurityDiagnosticsArray"
1378
- )! as UADynamicVariableArray<SessionSecurityDiagnosticsDataType>;
1474
+ ) as UADynamicVariableArray<SessionSecurityDiagnosticsDataType>;
1379
1475
  assert(sessionSecurityDiagnosticsArray.nodeClass === NodeClass.Variable);
1380
1476
  bindExtObjArrayNode(sessionSecurityDiagnosticsArray, "SessionSecurityDiagnosticsType", "sessionId");
1381
1477
  ensureObjectIsSecure(sessionSecurityDiagnosticsArray);
@@ -1397,7 +1493,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1397
1493
  // do expansion first
1398
1494
  for (const browseDescription of nodesToBrowse) {
1399
1495
  const nodeId = resolveNodeId(browseDescription.nodeId);
1400
- const node = this.addressSpace!.findNode(nodeId);
1496
+ const node = this.addressSpace?.findNode(nodeId);
1401
1497
  if (node) {
1402
1498
  if (node.onFirstBrowseAction) {
1403
1499
  try {
@@ -1416,19 +1512,34 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1416
1512
  return await this.browse(context, nodesToBrowse);
1417
1513
  }
1418
1514
  public async browse(context: ISessionContext, nodesToBrowse: BrowseDescriptionOptions[]): Promise<BrowseResult[]> {
1419
- return this.addressSpaceAccessor!.browse(context, nodesToBrowse);
1515
+ if (!this.addressSpaceAccessor) {
1516
+ throw new Error("addressSpaceAccessor is not available");
1517
+ }
1518
+ return this.addressSpaceAccessor.browse(context, nodesToBrowse);
1420
1519
  }
1421
1520
  public async read(context: ISessionContext, readRequest: ReadRequestOptions): Promise<DataValue[]> {
1422
- return this.addressSpaceAccessor!.read(context, readRequest);
1521
+ if (!this.addressSpaceAccessor) {
1522
+ throw new Error("addressSpaceAccessor is not available");
1523
+ }
1524
+ return this.addressSpaceAccessor.read(context, readRequest);
1423
1525
  }
1424
1526
  public async write(context: ISessionContext, nodesToWrite: WriteValue[]): Promise<StatusCode[]> {
1425
- return await this.addressSpaceAccessor!.write(context, nodesToWrite);
1527
+ if (!this.addressSpaceAccessor) {
1528
+ throw new Error("addressSpaceAccessor is not available");
1529
+ }
1530
+ return await this.addressSpaceAccessor.write(context, nodesToWrite);
1426
1531
  }
1427
1532
  public async call(context: ISessionContext, methodsToCall: CallMethodRequest[]): Promise<CallMethodResultOptions[]> {
1428
- return await this.addressSpaceAccessor!.call(context, methodsToCall);
1533
+ if (!this.addressSpaceAccessor) {
1534
+ throw new Error("addressSpaceAccessor is not available");
1535
+ }
1536
+ return await this.addressSpaceAccessor.call(context, methodsToCall);
1429
1537
  }
1430
1538
  public async historyRead(context: ISessionContext, historyReadRequest: HistoryReadRequest): Promise<HistoryReadResult[]> {
1431
- return this.addressSpaceAccessor!.historyRead(context, historyReadRequest);
1539
+ if (!this.addressSpaceAccessor) {
1540
+ throw new Error("addressSpaceAccessor is not available");
1541
+ }
1542
+ return this.addressSpaceAccessor.historyRead(context, historyReadRequest);
1432
1543
  }
1433
1544
 
1434
1545
  public getOldestInactiveSession(): ServerSession | null {
@@ -1467,7 +1578,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1467
1578
  const sessionTimeout = options.sessionTimeout || 1000;
1468
1579
  assert(typeof sessionTimeout === "number");
1469
1580
 
1470
- const session = new ServerSession(this, options.server.userManager!, sessionTimeout);
1581
+ const session = new ServerSession(this, options.server.userManager || {}, sessionTimeout);
1471
1582
 
1472
1583
  debugLog("createSession :sessionTimeout = ", session.sessionTimeout);
1473
1584
 
@@ -1479,13 +1590,13 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1479
1590
  // TODO : When a Session is created, the Server adds an entry for the Client
1480
1591
  // in its SessionDiagnosticsArray Variable
1481
1592
 
1482
- session.on("new_subscription", (subscription: Subscription) => {
1593
+ session.on("new_subscription", (_subscription: Subscription) => {
1483
1594
  this.serverDiagnosticsSummary.cumulatedSubscriptionCount += 1;
1484
1595
  // add the subscription diagnostics in our subscriptions diagnostics array
1485
1596
  // note currentSubscriptionCount is handled directly with a special getter
1486
1597
  });
1487
1598
 
1488
- session.on("subscription_terminated", (subscription: Subscription) => {
1599
+ session.on("subscription_terminated", (_subscription: Subscription) => {
1489
1600
  // remove the subscription diagnostics in our subscriptions diagnostics array
1490
1601
  // note currentSubscriptionCount is handled directly with a special getter
1491
1602
  });
@@ -1555,7 +1666,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1555
1666
 
1556
1667
  // c8 ignore next
1557
1668
  if (!session) {
1558
- throw new Error("cannot find session with this authenticationToken " + authenticationToken.toString());
1669
+ throw new Error(`cannot find session with this authenticationToken ${authenticationToken.toString()}`);
1559
1670
  }
1560
1671
 
1561
1672
  if (!deleteSubscriptions) {
@@ -1586,7 +1697,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1586
1697
 
1587
1698
  public findSubscription(subscriptionId: number): Subscription | null {
1588
1699
  const subscriptions: Subscription[] = [];
1589
- Object.values(this._sessions).map((session) => {
1700
+ Object.values(this._sessions).forEach((session) => {
1590
1701
  if (subscriptions.length) {
1591
1702
  return;
1592
1703
  }
@@ -1655,7 +1766,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1655
1766
  // warningLog("ServerEngine#transferSubscription => BadUserAccessDenied");
1656
1767
  // return new TransferResult({ statusCode: StatusCodes.BadUserAccessDenied });
1657
1768
  // }
1658
- if ((session.publishEngine as any) === subscription.publishEngine) {
1769
+ if (session.publishEngine === (subscription.publishEngine as unknown)) {
1659
1770
  // subscription is already in this session !!
1660
1771
  return new TransferResult({ statusCode: StatusCodes.BadNothingToDo });
1661
1772
  }
@@ -1669,8 +1780,6 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1669
1780
  // The number of times the subscription has been transferred to an alternate session for the same client.
1670
1781
  subscription.subscriptionDiagnostics.transferredToSameClientCount++;
1671
1782
 
1672
- const nbSubscriptionBefore = session.publishEngine.subscriptionCount;
1673
-
1674
1783
  if (subscription.$session) {
1675
1784
  subscription.$session._unexposeSubscriptionDiagnostics(subscription);
1676
1785
  }
@@ -1681,7 +1790,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1681
1790
 
1682
1791
  session._exposeSubscriptionDiagnostics(subscription);
1683
1792
 
1684
- assert((subscription.publishEngine as any) === session.publishEngine);
1793
+ assert(subscription.publishEngine === session.publishEngine);
1685
1794
  // assert(session.publishEngine.subscriptionCount === nbSubscriptionBefore + 1);
1686
1795
 
1687
1796
  const result = new TransferResult({
@@ -1728,7 +1837,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1728
1837
  return browsePathResults;
1729
1838
  }
1730
1839
  public async translateBrowsePath(browsePath: BrowsePath): Promise<BrowsePathResult> {
1731
- return this.addressSpace!.browsePath(browsePath);
1840
+ if (!this.addressSpace) {
1841
+ throw new Error("addressSpace is not available");
1842
+ }
1843
+ return this.addressSpace.browsePath(browsePath);
1732
1844
  }
1733
1845
 
1734
1846
  /**
@@ -1765,12 +1877,12 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1765
1877
  continue;
1766
1878
  }
1767
1879
  // ... and that are valid object and instances of Variables ...
1768
- const uaNode = this.addressSpace!.findNode(nodeToRefresh.nodeId);
1880
+ const uaNode = this.addressSpace?.findNode(nodeToRefresh.nodeId);
1769
1881
  if (!uaNode || !(uaNode.nodeClass === NodeClass.Variable)) {
1770
1882
  continue;
1771
1883
  }
1772
1884
  // ... and that have been declared as asynchronously updating
1773
- if (typeof (uaNode as any).refreshFunc !== "function") {
1885
+ if (typeof (uaNode as unknown as Record<string, unknown>).refreshFunc !== "function") {
1774
1886
  continue;
1775
1887
  }
1776
1888
  const key = uaNode.nodeId.toString();
@@ -1783,7 +1895,8 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1783
1895
  const uaVariableArray = Object.values(nodeMap);
1784
1896
  if (uaVariableArray.length === 0) {
1785
1897
  // nothing to do
1786
- return callback(null, []);
1898
+ callback(null, []);
1899
+ return;
1787
1900
  }
1788
1901
  // perform all asyncRefresh in parallel
1789
1902
  async.map(
@@ -1810,7 +1923,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1810
1923
  debugLog("ServerEngine#_exposeSubscriptionDiagnostics", subscription.subscriptionId);
1811
1924
  const subscriptionDiagnosticsArray = this._getServerSubscriptionDiagnosticsArrayNode();
1812
1925
  const subscriptionDiagnostics = subscription.subscriptionDiagnostics;
1813
- assert((subscriptionDiagnostics as any).$subscription === subscription);
1926
+ assert((subscriptionDiagnostics as unknown as Record<string, unknown>).$subscription === subscription);
1814
1927
  assert(subscriptionDiagnostics instanceof SubscriptionDiagnosticsDataType);
1815
1928
 
1816
1929
  if (subscriptionDiagnostics && subscriptionDiagnosticsArray) {
@@ -1826,7 +1939,6 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1826
1939
  const subscriptionDiagnostics = subscription.subscriptionDiagnostics;
1827
1940
  assert(subscriptionDiagnostics instanceof SubscriptionDiagnosticsDataType);
1828
1941
  if (subscriptionDiagnostics && serverSubscriptionDiagnosticsArray) {
1829
- const node = (serverSubscriptionDiagnosticsArray as any)[subscription.id];
1830
1942
  removeElement(serverSubscriptionDiagnosticsArray, (a) => a.subscriptionId === subscription.id);
1831
1943
  /*assert(
1832
1944
  !(subscriptionDiagnosticsArray as any)[subscription.id],
@@ -1860,7 +1972,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1860
1972
  maxKeepAliveCount,
1861
1973
  maxNotificationsPerPublish: request.maxNotificationsPerPublish,
1862
1974
  priority: request.priority || 0,
1863
- publishEngine: session.publishEngine as any, //
1975
+ publishEngine: session.publishEngine as unknown as ServerSidePublishEngine, //
1864
1976
  publishingEnabled: request.publishingEnabled,
1865
1977
  publishingInterval,
1866
1978
  // -------------------
@@ -1872,7 +1984,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1872
1984
  // add subscriptionDiagnostics
1873
1985
  this._exposeSubscriptionDiagnostics(subscription);
1874
1986
 
1875
- assert((subscription.publishEngine as any) === session.publishEngine);
1987
+ assert(subscription.publishEngine === session.publishEngine);
1876
1988
  session.publishEngine.add_subscription(subscription);
1877
1989
 
1878
1990
  // eslint-disable-next-line @typescript-eslint/no-this-alias
@@ -1890,19 +2002,18 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1890
2002
  assert(typeof func === "function");
1891
2003
  assert(nodeId instanceof NodeId);
1892
2004
 
1893
- const methodNode = this.addressSpace!.findNode(nodeId)! as UAMethod;
2005
+ const methodNode = this.addressSpace?.findNode(nodeId) as UAMethod | undefined;
1894
2006
  if (!methodNode) {
1895
2007
  return;
1896
2008
  }
1897
- if (methodNode && methodNode.bindMethod) {
2009
+ if (methodNode?.bindMethod) {
1898
2010
  methodNode.bindMethod(func);
1899
- }
1900
- /* c8 ignore next */
1901
- else {
2011
+ } else {
2012
+ /* c8 ignore next */
1902
2013
  warningLog(
1903
2014
  chalk.yellow("WARNING: cannot bind a method with id ") +
1904
- chalk.cyan(nodeId.toString()) +
1905
- chalk.yellow(". please check your nodeset.xml file or add this node programmatically")
2015
+ chalk.cyan(nodeId.toString()) +
2016
+ chalk.yellow(". please check your nodeset.xml file or add this node programmatically")
1906
2017
  );
1907
2018
  warningLog(traceFromThisProjectOnly());
1908
2019
  }
@@ -1917,14 +2028,13 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
1917
2028
  }
1918
2029
  const subscriptionDiagnosticsType = this.addressSpace.findVariableType("SubscriptionDiagnosticsType");
1919
2030
  if (!subscriptionDiagnosticsType) {
1920
- doDebug &&
1921
- debugLog("ServerEngine#_getServerSubscriptionDiagnosticsArray " + ": cannot find SubscriptionDiagnosticsType");
2031
+ doDebug && debugLog(`ServerEngine#_getServerSubscriptionDiagnosticsArray : cannot find SubscriptionDiagnosticsType`);
1922
2032
  }
1923
2033
 
1924
2034
  // SubscriptionDiagnosticsArray = i=2290
1925
2035
  const subscriptionDiagnosticsArrayNode = this.addressSpace.findNode(
1926
2036
  makeNodeId(VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray)
1927
- )!;
2037
+ );
1928
2038
 
1929
2039
  return subscriptionDiagnosticsArrayNode as UADynamicVariableArray<SubscriptionDiagnosticsDataType>;
1930
2040
  }