node-opcua-address-space 2.168.0 → 2.170.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/source/loader/namespace_post_step.js +25 -17
  2. package/dist/source/loader/namespace_post_step.js.map +1 -1
  3. package/dist/source/session_context.d.ts +3 -1
  4. package/dist/source/session_context.js +26 -1
  5. package/dist/source/session_context.js.map +1 -1
  6. package/dist/source/ua_interface.d.ts +2 -3
  7. package/dist/source/ua_interface.js +10 -33
  8. package/dist/source/ua_interface.js.map +1 -1
  9. package/dist/src/_instantiate_helpers.d.ts +1 -1
  10. package/dist/src/_instantiate_helpers.js +32 -9
  11. package/dist/src/_instantiate_helpers.js.map +1 -1
  12. package/dist/src/_mandatory_child_or_requested_optional_filter.js +3 -3
  13. package/dist/src/_mandatory_child_or_requested_optional_filter.js.map +1 -1
  14. package/dist/src/address_space.d.ts +15 -12
  15. package/dist/src/address_space.js +63 -64
  16. package/dist/src/address_space.js.map +1 -1
  17. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js +1 -1
  18. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js.map +1 -1
  19. package/dist/src/alarms_and_conditions/ua_condition_impl.js +1 -1
  20. package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +1 -1
  21. package/dist/src/base_node_impl.d.ts +1 -0
  22. package/dist/src/base_node_impl.js +11 -0
  23. package/dist/src/base_node_impl.js.map +1 -1
  24. package/dist/src/base_node_private.d.ts +10 -7
  25. package/dist/src/base_node_private.js +74 -50
  26. package/dist/src/base_node_private.js.map +1 -1
  27. package/dist/src/check_value_rank_compatibility.js +1 -1
  28. package/dist/src/check_value_rank_compatibility.js.map +1 -1
  29. package/dist/src/event_data.d.ts +8 -21
  30. package/dist/src/event_data.js +24 -19
  31. package/dist/src/event_data.js.map +1 -1
  32. package/dist/src/namespace_impl.d.ts +2 -0
  33. package/dist/src/namespace_impl.js +13 -0
  34. package/dist/src/namespace_impl.js.map +1 -1
  35. package/dist/src/ua_method_impl.d.ts +11 -9
  36. package/dist/src/ua_method_impl.js +24 -27
  37. package/dist/src/ua_method_impl.js.map +1 -1
  38. package/dist/src/ua_object_impl.d.ts +6 -5
  39. package/dist/src/ua_object_impl.js +30 -4
  40. package/dist/src/ua_object_impl.js.map +1 -1
  41. package/dist/src/ua_object_type_impl.js +2 -2
  42. package/dist/src/ua_object_type_impl.js.map +1 -1
  43. package/dist/src/ua_variable_impl.d.ts +1 -0
  44. package/dist/src/ua_variable_impl.js +79 -1
  45. package/dist/src/ua_variable_impl.js.map +1 -1
  46. package/dist/tsconfig_base.tsbuildinfo +1 -1
  47. package/distHelpers/get_address_space_fixture.js +14 -14
  48. package/distHelpers/get_address_space_fixture.js.map +1 -1
  49. package/distHelpers/index.d.ts +2 -2
  50. package/distHelpers/index.js +2 -2
  51. package/distHelpers/index.js.map +1 -1
  52. package/package.json +34 -34
  53. package/source/loader/namespace_post_step.ts +28 -19
  54. package/source/session_context.ts +30 -1
  55. package/source/ua_interface.ts +24 -38
  56. package/src/_instantiate_helpers.ts +67 -24
  57. package/src/_mandatory_child_or_requested_optional_filter.ts +5 -5
  58. package/src/address_space.ts +127 -124
  59. package/src/alarms_and_conditions/condition_snapshot_impl.ts +3 -3
  60. package/src/alarms_and_conditions/ua_condition_impl.ts +1 -1
  61. package/src/base_node_impl.ts +13 -0
  62. package/src/base_node_private.ts +163 -139
  63. package/src/check_value_rank_compatibility.ts +1 -1
  64. package/src/event_data.ts +57 -54
  65. package/src/namespace_impl.ts +16 -0
  66. package/src/ua_method_impl.ts +43 -50
  67. package/src/ua_object_impl.ts +51 -22
  68. package/src/ua_object_type_impl.ts +3 -3
  69. package/src/ua_variable_impl.ts +79 -2
@@ -2,21 +2,41 @@
2
2
  * @module node-opcua-address-space
3
3
  */
4
4
 
5
- import { randomBytes } from "crypto";
5
+ import { randomBytes } from "node:crypto";
6
6
  import chalk from "chalk";
7
-
7
+ import type {
8
+ AddReferenceOpts,
9
+ BaseNode,
10
+ IEventData,
11
+ IHistoricalDataNodeOptions,
12
+ ISessionContext,
13
+ MethodCallInterceptor,
14
+ RaiseEventData,
15
+ ShutdownTask,
16
+ UADataType,
17
+ UAEventType,
18
+ UAMethod,
19
+ UAObject,
20
+ UAObjectType,
21
+ UAReference,
22
+ UAReferenceType,
23
+ UAVariable,
24
+ UAVariableType,
25
+ UAView
26
+ } from "node-opcua-address-space-base";
8
27
  import { assert } from "node-opcua-assert";
9
- import { ExtraDataTypeManager } from "node-opcua-client-dynamic-extension-object";
28
+ import type { ExtraDataTypeManager } from "node-opcua-client-dynamic-extension-object";
10
29
  import { DataTypeIds, VariableTypeIds } from "node-opcua-constants";
11
30
  import { BrowseDirection, NodeClass, QualifiedName } from "node-opcua-data-model";
12
- import { ExtensionObject } from "node-opcua-extension-object";
31
+ import { make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
32
+ import type { ExtensionObject } from "node-opcua-extension-object";
13
33
  import {
14
34
  coerceExpandedNodeId,
15
35
  coerceNodeId,
16
- INodeId,
36
+ type INodeId,
17
37
  makeNodeId,
18
38
  NodeId,
19
- NodeIdLike,
39
+ type NodeIdLike,
20
40
  NodeIdType,
21
41
  resolveNodeId,
22
42
  sameNodeId
@@ -24,61 +44,39 @@ import {
24
44
  import { ObjectRegistry } from "node-opcua-object-registry";
25
45
  import { BrowseResult } from "node-opcua-service-browse";
26
46
  import { StatusCodes } from "node-opcua-status-code";
27
- import {
47
+ import type {
28
48
  BrowseDescription,
29
- BrowsePath,
30
- BrowsePathResult,
31
49
  BrowsePathTargetOptions,
32
50
  BrowseResultOptions,
33
51
  ModelChangeStructureDataType,
34
52
  RelativePathElement
35
53
  } from "node-opcua-types";
36
- import { isNullOrUndefined } from "node-opcua-utils";
37
- import { lowerFirstLetter } from "node-opcua-utils";
38
- import { DataType, Variant, VariantArrayType, VariantOptions, VariantT } from "node-opcua-variant";
39
54
  import {
40
- AddReferenceOpts,
41
- IEventData,
42
- ISessionContext,
43
- UAEventType,
44
- UAReference,
45
- IHistoricalDataNodeOptions,
46
- UAVariable,
47
- UADataType,
48
- UAObjectType,
49
- BaseNode,
50
- UAMethod,
51
- UAVariableType,
52
- UAReferenceType,
53
- UAObject,
54
- UAView,
55
- IAddressSpace,
56
- ShutdownTask,
57
- RaiseEventData,
58
- UAVariableT,
59
- MethodCallInterceptor
60
- } from "node-opcua-address-space-base";
61
- import { make_debugLog, make_warningLog, make_errorLog } from "node-opcua-debug";
62
-
55
+ BrowsePath,
56
+ BrowsePathResult,
57
+ } from "node-opcua-types";
58
+ import { isNullOrUndefined, lowerFirstLetter } from "node-opcua-utils";
59
+ import { DataType, Variant, VariantArrayType, type VariantOptions, type VariantT } from "node-opcua-variant";
63
60
  import { adjustBrowseDirection } from "../source/helpers/adjust_browse_direction";
64
- import { UARootFolder } from "../source/ua_root_folder";
65
- import { ExtensionObjectConstructorFuncWithSchema } from "../source/interfaces/extension_object_constructor";
66
-
67
- import { AddressSpacePrivate } from "./address_space_private";
61
+ import type {
62
+ ExtensionObjectConstructorFuncWithSchema
63
+ } from "../source/interfaces/extension_object_constructor";
64
+ import type { UARootFolder } from "../source/ua_root_folder";
65
+ import type { AddressSpacePrivate } from "./address_space_private";
68
66
  import { UAAcknowledgeableConditionImpl, UAConditionImpl } from "./alarms_and_conditions";
67
+ import { BaseNodeImpl } from "./base_node_impl";
69
68
  import { EventData } from "./event_data";
70
- import { AddressSpace_installHistoricalDataNode } from "./historical_access/address_space_historical_data_node";
71
- import { NamespaceImpl } from "./namespace_impl";
72
- import { isNonEmptyQualifiedName } from "./namespace_impl";
73
- import { NamespacePrivate } from "./namespace_private";
69
+ import {
70
+ AddressSpace_installHistoricalDataNode
71
+ } from "./historical_access/address_space_historical_data_node";
72
+ import { isNonEmptyQualifiedName, NamespaceImpl } from "./namespace_impl";
73
+ import type { NamespacePrivate } from "./namespace_private";
74
+ import { ReferenceImpl } from "./reference_impl";
74
75
  import { UADataTypeImpl } from "./ua_data_type_impl";
75
- import { UAObjectTypeImpl } from "./ua_object_type_impl";
76
76
  import { UAObjectImpl } from "./ua_object_impl";
77
- import { ReferenceImpl } from "./reference_impl";
78
- import { UAVariableImpl } from "./ua_variable_impl";
77
+ import { UAObjectTypeImpl } from "./ua_object_type_impl";
79
78
  import { UAReferenceTypeImpl } from "./ua_reference_type_impl";
80
- import { BaseNodeImpl } from "./base_node_impl";
81
- import { resolve } from "path";
79
+ import type { UAVariableImpl } from "./ua_variable_impl";
82
80
 
83
81
  const doDebug = false;
84
82
  const errorLog = make_errorLog(__filename);
@@ -92,7 +90,7 @@ const regexNumberColumnString = /^([0-9]+):(.*)/;
92
90
  const enumerationTypeNodeId = coerceNodeId(DataTypeIds.Enumeration);
93
91
  /**
94
92
  * Extracts the namespace and browse name as a string from the given input.
95
- *
93
+ *
96
94
  * @param addressSpace The address space instance.
97
95
  * @param browseNameOrNodeId A NodeIdLike, QualifiedName, or string representing the browse name or node id.
98
96
  * @param namespaceIndex Optional namespace index.
@@ -105,15 +103,19 @@ function _extract_namespace_and_browse_name_as_string(
105
103
  ): [NamespacePrivate, string] {
106
104
  assert(!namespaceIndex || namespaceIndex >= 0);
107
105
 
108
- let result;
106
+ let result: [NamespacePrivate, string] | undefined;
109
107
 
110
108
  if (namespaceIndex !== undefined && namespaceIndex > 0) {
111
109
  assert(typeof browseNameOrNodeId === "string", "expecting a string when namespaceIndex is specified");
112
- result = [addressSpace.getNamespace(namespaceIndex), browseNameOrNodeId];
110
+ result = [addressSpace.getNamespace(namespaceIndex), browseNameOrNodeId.toString()];
113
111
  } else if (typeof browseNameOrNodeId === "string") {
114
112
  // we may have a string like "ns=1;i=1234" or "ns=1:MyBrowseName"
115
113
  if (isNodeIdString(browseNameOrNodeId)) {
116
- return _extract_namespace_and_browse_name_as_string(addressSpace, addressSpace.resolveNodeId(browseNameOrNodeId), namespaceIndex);
114
+ return _extract_namespace_and_browse_name_as_string(
115
+ addressSpace,
116
+ addressSpace.resolveNodeId(browseNameOrNodeId),
117
+ namespaceIndex
118
+ );
117
119
  }
118
120
  // we must have a BrowseName string
119
121
  if (browseNameOrNodeId.indexOf(":") >= 0) {
@@ -124,7 +126,7 @@ function _extract_namespace_and_browse_name_as_string(
124
126
  result = [addressSpace.getNamespace(namespaceIndex || 0), browseNameOrNodeId];
125
127
  } else if (browseNameOrNodeId instanceof QualifiedName) {
126
128
  namespaceIndex = browseNameOrNodeId.namespaceIndex;
127
- result = [addressSpace.getNamespace(namespaceIndex), browseNameOrNodeId.name];
129
+ result = [addressSpace.getNamespace(namespaceIndex), browseNameOrNodeId.name || ""];
128
130
  } else if (typeof browseNameOrNodeId === "number") {
129
131
  result = [addressSpace.getDefaultNamespace(), DataType[browseNameOrNodeId]];
130
132
  } else if (browseNameOrNodeId instanceof NodeId) {
@@ -201,6 +203,20 @@ export class AddressSpace implements AddressSpacePrivate {
201
203
  this.registerNamespace("http://opcfoundation.org/UA/");
202
204
  AddressSpace.registry.register(this);
203
205
  }
206
+
207
+ public toJSON(): Record<string, string | number | undefined> {
208
+ return {
209
+ namespaces: this._namespaceArray.length
210
+ };
211
+ }
212
+
213
+ public toString(): string {
214
+ return `AddressSpace({ namespaces: ${this._namespaceArray.length} })`;
215
+ }
216
+
217
+ public [Symbol.for("nodejs.util.inspect.custom")](): string {
218
+ return this.toString();
219
+ }
204
220
  /**
205
221
  * @internal
206
222
  */
@@ -266,7 +282,7 @@ export class AddressSpace implements AddressSpacePrivate {
266
282
  /**
267
283
  *
268
284
  * register a new namespace,
269
- * it is OK to call registerNamespace even if namespace has already been registered;
285
+ * it is OK to call registerNamespace even if namespace has already been registered;
270
286
  * in this case the registerNamespace has no effect and returns the existing namespace.
271
287
  *
272
288
  * @param namespaceUri {string}
@@ -478,7 +494,7 @@ export class AddressSpace implements AddressSpacePrivate {
478
494
  const resolvedDataType = this.resolveNodeId(dataTypeNode);
479
495
  /* c8 ignore next */
480
496
  if (!resolvedDataType) {
481
- throw new Error("Cannot resolve " + _orig_dataTypeNode.toString());
497
+ throw new Error(`Cannot resolve ${_orig_dataTypeNode.toString()}`);
482
498
  }
483
499
  dataTypeNode = resolvedDataType;
484
500
  }
@@ -487,7 +503,7 @@ export class AddressSpace implements AddressSpacePrivate {
487
503
  dataTypeNode = this.findDataType(dataTypeNode)!;
488
504
  /* c8 ignore next */
489
505
  if (!dataTypeNode) {
490
- throw Error("cannot find dataTypeNode " + _orig_dataTypeNode.toString());
506
+ throw Error(`cannot find dataTypeNode ${_orig_dataTypeNode.toString()}`);
491
507
  }
492
508
  }
493
509
  /* c8 ignore next */
@@ -500,7 +516,7 @@ export class AddressSpace implements AddressSpacePrivate {
500
516
  );
501
517
  }
502
518
 
503
- if (sameNodeId(enumerationTypeNodeId, dataTypeNode!.nodeId)) {
519
+ if (sameNodeId(enumerationTypeNodeId, dataTypeNode?.nodeId)) {
504
520
  return DataType.Int32;
505
521
  }
506
522
  const n = dataTypeNode.nodeId as INodeId;
@@ -559,7 +575,7 @@ export class AddressSpace implements AddressSpacePrivate {
559
575
  // +->(hasSubtype) HasEventSource/EventSourceOf
560
576
  let node: UAReferenceType | null;
561
577
 
562
- if (!(refType instanceof NodeId) && isNodeIdString(refType) || typeof refType === "number") {
578
+ if ((!(refType instanceof NodeId) && isNodeIdString(refType)) || typeof refType === "number") {
563
579
  refType = resolveNodeId(refType);
564
580
  }
565
581
  if (refType instanceof NodeId) {
@@ -593,13 +609,11 @@ export class AddressSpace implements AddressSpacePrivate {
593
609
  public inverseReferenceType(referenceType: string): string {
594
610
  assert(typeof referenceType === "string");
595
611
  const n1 = this.findReferenceType(referenceType);
596
- const n2 = this.findReferenceTypeFromInverseName(referenceType);
597
612
  if (n1) {
598
- assert(!n2);
599
- return n1.inverseName!.text as string;
613
+ return n1.inverseName?.text as string;
600
614
  } else {
601
- assert(n2);
602
- return n2!.browseName.toString();
615
+ const n2 = this.findReferenceTypeFromInverseName(referenceType);
616
+ return n2?.browseName.toString() || "";
603
617
  }
604
618
  }
605
619
 
@@ -679,53 +693,49 @@ export class AddressSpace implements AddressSpacePrivate {
679
693
  /*=
680
694
  * construct a simple javascript object with all the default properties of the event
681
695
  *
682
- * @return result.$eventDataSource {BaseNode} the event type node
683
- * @return result.eventId {NodeId} the
684
- * ...
685
- *
686
696
  *
687
697
  * eventTypeId can be a UAEventType
688
698
  *
689
699
  * @private
690
700
  */
691
- public constructEventData(eventTypeId: UAEventType, data: RaiseEventData): IEventData {
692
- data = data || {};
701
+ public constructEventData(eventTypeId: UAEventType, dataInput: Record<string, unknown>): IEventData {
702
+ const data: RaiseEventData = (dataInput || {}) as RaiseEventData;
693
703
 
694
704
  // construct the reference dataStructure to store event Data
695
- let eventTypeNode = eventTypeId;
705
+ let eventTypeNode: UAEventType | null = eventTypeId;
696
706
 
697
707
  // make sure that eventType is really a object that derived from EventType
698
708
  if (eventTypeId instanceof UAObjectTypeImpl) {
699
- eventTypeNode = this.findEventType(eventTypeId)!;
709
+ eventTypeNode = this.findEventType(eventTypeId) as UAEventType | null;
700
710
  }
701
-
702
711
  /* c8 ignore next */
703
- if (!eventTypeNode) {
704
- throw new Error(" cannot find EvenType for " + eventTypeId);
705
- }
712
+ if (!eventTypeNode) throw new Error(` cannot find EventType for ${eventTypeId}`);
713
+
714
+
706
715
  assert(eventTypeNode instanceof UAObjectTypeImpl, "eventTypeId must represent a UAObjectType");
707
716
 
708
717
  // eventId
709
- assert(
710
- !Object.prototype.hasOwnProperty.call(data, "eventId"),
711
- "eventId constructEventData : options object should not have eventId property"
712
- );
718
+ assert(!Object.hasOwn(data, "eventId"), "eventId constructEventData : options object should not have eventId property");
713
719
  data.eventId = data.eventId || this.generateEventId();
714
720
 
715
721
  // eventType
716
722
  data.eventType = { dataType: DataType.NodeId, value: eventTypeNode.nodeId };
717
723
 
718
724
  // sourceNode
719
- assert(Object.prototype.hasOwnProperty.call(data, "sourceNode"), "expecting a source node to be defined");
725
+ assert(Object.hasOwn(data, "sourceNode"), "expecting a source node to be defined");
720
726
  data.sourceNode = new Variant(data.sourceNode);
721
727
  assert(data.sourceNode.dataType === DataType.NodeId);
722
728
 
723
729
  // sourceName
724
- const sourceNode = this.findNode(data.sourceNode.value)!;
725
-
730
+ const sourceNode = this.findNode(data.sourceNode.value);
731
+ if (!sourceNode) {
732
+ warningLog(
733
+ `constructEventData: cannot find sourceNode ${data.sourceNode.value?.toString()} for event ${eventTypeNode.browseName.toString()}`
734
+ );
735
+ }
726
736
  data.sourceName = data.sourceName || {
727
737
  dataType: DataType.String,
728
- value: sourceNode.getDisplayName("en")
738
+ value: sourceNode?.getDisplayName("en") || ""
729
739
  };
730
740
 
731
741
  const nowUTC = new Date();
@@ -757,14 +767,14 @@ export class AddressSpace implements AddressSpacePrivate {
757
767
  throw new Error("BaseObjectType must be defined in the address space");
758
768
  }
759
769
 
760
- const hasProperty = (data: any, propertyName: string): boolean => Object.prototype.hasOwnProperty.call(data, propertyName);
770
+ const hasProperty = (data: any, propertyName: string): boolean => Object.hasOwn(data, propertyName);
761
771
 
762
772
  const visitedProperties: { [key: string]: number } = {};
763
- const alreadyVisited = (key: string) => Object.prototype.hasOwnProperty.call(visitedProperties, key);
773
+ const alreadyVisited = (key: string) => Object.hasOwn(visitedProperties, key);
764
774
  const markAsVisited = (key: string) => (visitedProperties[key] = 1);
765
775
 
766
776
  function _process_var(self: BaseNode, prefixLower: string, prefixStandard: string, node: BaseNode) {
767
- const lowerName = prefixLower + lowerFirstLetter(node.browseName!.name!);
777
+ const lowerName = prefixLower + lowerFirstLetter(node.browseName?.name || "");
768
778
  const fullBrowsePath = prefixStandard + node.browseName.toString();
769
779
  if (alreadyVisited(lowerName)) {
770
780
  return;
@@ -803,7 +813,7 @@ export class AddressSpace implements AddressSpacePrivate {
803
813
 
804
814
  // verify that all elements of data are valid
805
815
  function verify_data_is_valid(data1: Record<string, unknown>) {
806
- Object.keys(data1).map((k: string) => {
816
+ Object.keys(data1).forEach((k: string) => {
807
817
  if (k === "$eventDataSource") {
808
818
  return;
809
819
  }
@@ -815,21 +825,21 @@ export class AddressSpace implements AddressSpacePrivate {
815
825
  "' in [ " +
816
826
  Object.keys(visitedProperties).join(", ") +
817
827
  "] when filling " +
818
- eventTypeNode.browseName.toString()
828
+ eventTypeNode?.browseName.toString()
819
829
  );
820
830
  }
821
831
  });
822
832
  }
823
833
 
824
834
  const populate_data = (self: any, eventData1: any) => {
825
- if (sameNodeId(baseObjectType!.nodeId, self.nodeId)) {
835
+ if (sameNodeId(baseObjectType?.nodeId, self.nodeId)) {
826
836
  return; // nothing to do
827
837
  }
828
838
 
829
839
  const baseTypeNodeId = self.subtypeOf;
830
840
  /* c8 ignore next */
831
841
  if (!baseTypeNodeId) {
832
- throw new Error("Object " + self.browseName.toString() + " with nodeId " + self.nodeId + " has no Type");
842
+ throw new Error(`Object ${self.browseName.toString()} with nodeId ${self.nodeId} has no Type`);
833
843
  }
834
844
 
835
845
  const baseType = this.findNode(baseTypeNodeId);
@@ -847,7 +857,7 @@ export class AddressSpace implements AddressSpacePrivate {
847
857
 
848
858
  // c8 ignore next
849
859
  if (doDebug) {
850
- debugLog(" " + chalk.bgWhite.cyan(self.browseName.toString()));
860
+ debugLog(` ${chalk.bgWhite.cyan(self.browseName.toString())}`);
851
861
  }
852
862
 
853
863
  for (const node of children) {
@@ -867,10 +877,10 @@ export class AddressSpace implements AddressSpacePrivate {
867
877
 
868
878
  const children2 = node.getAggregates();
869
879
  if (children2.length > 0) {
870
- const lowerName = lowerFirstLetter(node.browseName.name!);
880
+ const lowerName = lowerFirstLetter(node.browseName.name || "");
871
881
  const standardName = node.browseName.toString();
872
882
  for (const child2 of children2) {
873
- _process_var(self, lowerName + ".", standardName + ".", child2);
883
+ _process_var(self, `${lowerName}.`, `${standardName}.`, child2);
874
884
  }
875
885
  }
876
886
  }
@@ -943,7 +953,7 @@ export class AddressSpace implements AddressSpacePrivate {
943
953
  const empty_targetName_not_in_lastPos = browsePath.relativePath.elements.reduce((prev, e, index) => {
944
954
  const is_last = index + 1 === elements_length;
945
955
  const isBad = !is_last && (!e.targetName || e.targetName.isEmpty());
946
- return prev + (!is_last && (!e.targetName || e.targetName.isEmpty()) ? 1 : 0);
956
+ return prev + (isBad ? 1 : 0);
947
957
  }, 0);
948
958
  if (empty_targetName_not_in_lastPos) {
949
959
  return new BrowsePathResult({ statusCode: StatusCodes.BadBrowseNameInvalid });
@@ -961,12 +971,8 @@ export class AddressSpace implements AddressSpacePrivate {
961
971
 
962
972
  const explore_element = (curNodeObject: BaseNode, elements: RelativePathElement[], index: number) => {
963
973
  const element = elements[index];
964
- assert(element instanceof RelativePathElement);
965
-
966
974
  const is_last = index + 1 === elements.length;
967
-
968
975
  const nodeIds = curNodeObject.browseNodeByTargetName(element, is_last);
969
-
970
976
  const targets = nodeIds.map((nodeId: NodeId) => {
971
977
  return {
972
978
  remainingPathIndex: elements.length - index,
@@ -1013,14 +1019,14 @@ export class AddressSpace implements AddressSpacePrivate {
1013
1019
  const tmp = this.findNode(dataType);
1014
1020
  /* c8 ignore next */
1015
1021
  if (!tmp) {
1016
- throw new Error("getExtensionObjectConstructor: cannot resolve dataType " + dataType);
1022
+ throw new Error(`getExtensionObjectConstructor: cannot resolve dataType ${dataType}`);
1017
1023
  }
1018
1024
  dataType = tmp as UADataType;
1019
1025
  }
1020
1026
  /* c8 ignore next */
1021
1027
  if (!(dataType instanceof UADataTypeImpl)) {
1022
1028
  // may be dataType was the NodeId of the "Binary Encoding" node
1023
- throw new Error("getExtensionObjectConstructor: dataType has unexpected type" + dataType);
1029
+ throw new Error(`getExtensionObjectConstructor: dataType has unexpected type${dataType}`);
1024
1030
  }
1025
1031
  const _dataType = dataType as UADataTypeImpl;
1026
1032
 
@@ -1178,7 +1184,7 @@ export class AddressSpace implements AddressSpacePrivate {
1178
1184
  folder = this._coerceNode(folder) as UAObject;
1179
1185
  /* c8 ignore next */
1180
1186
  if (folder && !_isFolder(this, folder)) {
1181
- throw new Error("Parent folder must be of FolderType " + folder.typeDefinition.toString());
1187
+ throw new Error(`Parent folder must be of FolderType ${folder.typeDefinition.toString()}`);
1182
1188
  }
1183
1189
  return folder as any as BaseNode;
1184
1190
  }
@@ -1189,7 +1195,7 @@ export class AddressSpace implements AddressSpacePrivate {
1189
1195
  * @param modelChange
1190
1196
  * @private
1191
1197
  */
1192
- public _collectModelChange(view: UAView | null, modelChange: ModelChangeStructureDataType): void {
1198
+ public _collectModelChange(_view: UAView | null, modelChange: ModelChangeStructureDataType): void {
1193
1199
  this._modelChanges.push(modelChange);
1194
1200
  }
1195
1201
 
@@ -1234,7 +1240,7 @@ export class AddressSpace implements AddressSpacePrivate {
1234
1240
  results.push(parent as UAView);
1235
1241
  } else {
1236
1242
  const key = parent.nodeId.toString();
1237
- if (Object.prototype.hasOwnProperty.call(visitedMap, key)) {
1243
+ if (Object.hasOwn(visitedMap, key)) {
1238
1244
  continue;
1239
1245
  }
1240
1246
  visitedMap[key] = parent;
@@ -1349,7 +1355,7 @@ export class AddressSpace implements AddressSpacePrivate {
1349
1355
 
1350
1356
  // ----------- now resolve target NodeId;
1351
1357
  if (params.nodeId instanceof BaseNodeImpl) {
1352
- assert(!Object.prototype.hasOwnProperty.call(params, "node"));
1358
+ assert(!Object.hasOwn(params, "node"));
1353
1359
  params.node = params.nodeId as BaseNode;
1354
1360
  params.nodeId = params.node.nodeId;
1355
1361
  } else {
@@ -1392,14 +1398,6 @@ export class AddressSpace implements AddressSpacePrivate {
1392
1398
 
1393
1399
  // -- internal stuff -----------------------------------------------------------------------------------------------
1394
1400
  public _coerceNode(node: string | BaseNode | NodeId): BaseNode | null {
1395
- function hasTypeDefinition(node1: BaseNode) {
1396
- return (
1397
- node1.nodeClass === NodeClass.Variable ||
1398
- node1.nodeClass === NodeClass.Object ||
1399
- node1.nodeClass === NodeClass.Method
1400
- );
1401
- }
1402
-
1403
1401
  // coerce to BaseNode object
1404
1402
  if (node instanceof BaseNodeImpl) {
1405
1403
  return node as BaseNode;
@@ -1424,7 +1422,7 @@ export class AddressSpace implements AddressSpacePrivate {
1424
1422
  return dataType;
1425
1423
  }
1426
1424
  if (dataType === 0) {
1427
- return NodeId.nullNodeId
1425
+ return NodeId.nullNodeId;
1428
1426
  }
1429
1427
  return this._coerce_Type(dataType, DataTypeIds, "DataTypeIds", AddressSpace.prototype.findDataType);
1430
1428
  }
@@ -1445,7 +1443,7 @@ export class AddressSpace implements AddressSpacePrivate {
1445
1443
 
1446
1444
  /* c8 ignore next */
1447
1445
  if (!topMostBaseTypeNode) {
1448
- throw new Error("Cannot find topMostBaseTypeNode " + topMostBaseType.toString());
1446
+ throw new Error(`Cannot find topMostBaseTypeNode ${topMostBaseType.toString()}`);
1449
1447
  }
1450
1448
  assert(topMostBaseTypeNode instanceof BaseNodeImpl);
1451
1449
  assert(topMostBaseTypeNode.nodeClass === nodeClass);
@@ -1463,11 +1461,11 @@ export class AddressSpace implements AddressSpacePrivate {
1463
1461
 
1464
1462
  /* c8 ignore next*/
1465
1463
  if (!baseTypeNode) {
1466
- throw new Error("Cannot find ObjectType or VariableType for " + baseType.toString());
1464
+ throw new Error(`Cannot find ObjectType or VariableType for ${baseType.toString()}`);
1467
1465
  }
1468
1466
  /* c8 ignore next */
1469
1467
  if (!(baseTypeNode as any).isSubtypeOf) {
1470
- throw new Error("Cannot find ObjectType or VariableType for " + baseType.toString());
1468
+ throw new Error(`Cannot find ObjectType or VariableType for ${baseType.toString()}`);
1471
1469
  }
1472
1470
  /* c8 ignore next */
1473
1471
  if (!(baseTypeNode as any).isSubtypeOf(topMostBaseTypeNode)) {
@@ -1494,7 +1492,7 @@ export class AddressSpace implements AddressSpacePrivate {
1494
1492
  // DataType must be one of Enumeration
1495
1493
  const dataTypeNode = this.findDataType(dataType) as UADataType;
1496
1494
  if (!dataTypeNode) {
1497
- throw new Error(" Cannot find DataType " + dataType.toString() + " in standard address Space");
1495
+ throw new Error(` Cannot find DataType ${dataType.toString()} in standard address Space`);
1498
1496
  }
1499
1497
 
1500
1498
  const enumerationNode = this.findDataType("Enumeration")!;
@@ -1504,7 +1502,12 @@ export class AddressSpace implements AddressSpacePrivate {
1504
1502
  return dataTypeNode.isSubtypeOf(enumerationNode);
1505
1503
  }
1506
1504
 
1507
- private _coerce_Type(dataType: BaseNode | string | NodeId | number, typeMap: any, typeMapName: string, finderMethod: any): NodeId {
1505
+ private _coerce_Type(
1506
+ dataType: BaseNode | string | NodeId | number,
1507
+ typeMap: any,
1508
+ typeMapName: string,
1509
+ finderMethod: any
1510
+ ): NodeId {
1508
1511
  if (typeof dataType === "number") {
1509
1512
  return this._coerce_Type(coerceNodeId(dataType), typeMap, typeMapName, finderMethod);
1510
1513
  }
@@ -1554,10 +1557,10 @@ export class AddressSpace implements AddressSpacePrivate {
1554
1557
 
1555
1558
  if (!el) {
1556
1559
  // verify that node Id exists in standard type map typeMap
1557
- const find = Object.values(typeMap).filter((a) => a === nodeId!.value);
1560
+ const find = Object.values(typeMap).filter((a) => a === nodeId?.value);
1558
1561
  /* c8 ignore next */
1559
1562
  if (find.length !== 1) {
1560
- throw new Error(" cannot find " + dataType.toString() + " in typeMap " + typeMapName + " L = " + find.length);
1563
+ throw new Error(` cannot find ${dataType.toString()} in typeMap ${typeMapName} L = ${find.length}`);
1561
1564
  }
1562
1565
  }
1563
1566
  return nodeId;
@@ -1577,7 +1580,7 @@ function _getNamespace(addressSpace: AddressSpace, nodeOrNodId: BaseNode | NodeI
1577
1580
  return addressSpace.getNamespace(nodeId.namespace);
1578
1581
  }
1579
1582
 
1580
- function _find_by_node_id<T extends BaseNode>(addressSpace: AddressSpace, nodeId: NodeId, namespaceIndex?: number): T {
1583
+ function _find_by_node_id<T extends BaseNode>(addressSpace: AddressSpace, nodeId: NodeId, _namespaceIndex?: number): T {
1581
1584
  const obj = addressSpace.findNode(nodeId);
1582
1585
  return obj as T;
1583
1586
  }
@@ -1590,16 +1593,16 @@ function _find_by_node_id<T extends BaseNode>(addressSpace: AddressSpace, nodeId
1590
1593
  * @private
1591
1594
  */
1592
1595
  function _isFolder(addressSpace: AddressSpace, folder: UAObject): boolean {
1593
- const folderType = addressSpace.findObjectType("FolderType")!;
1596
+ const folderType = addressSpace.findObjectType("FolderType") as UAObjectType;
1594
1597
  assert(folder instanceof BaseNodeImpl);
1595
1598
  assert(folder.typeDefinitionObj);
1596
1599
  return folder.typeDefinitionObj.isSubtypeOf(folderType);
1597
1600
  }
1598
1601
 
1599
1602
  function _increase_version_number(node: BaseNode | null) {
1600
- var uaNodeVersion = node?.getNodeVersion();
1603
+ const uaNodeVersion = node?.getNodeVersion();
1601
1604
  if (uaNodeVersion) {
1602
- let rawValue = uaNodeVersion.readValue().value.value || ""
1605
+ const rawValue = uaNodeVersion.readValue().value.value || "";
1603
1606
  let previousValue = parseInt(rawValue || "0", 10);
1604
1607
  if (Number.isNaN(previousValue)) {
1605
1608
  warningLog("NodeVersion was ", rawValue);
@@ -90,7 +90,7 @@ export class ConditionSnapshotImpl extends EventEmitter implements ConditionSnap
90
90
  }
91
91
  const c = this.condition as UAConditionImpl;
92
92
  const isDisabled = !c.getEnabledState();
93
- const eventData = new EventData(this.condition!);
93
+ const eventData = new EventData(this.condition);
94
94
 
95
95
  for (const fullBrowsePath of this._map.keys()) {
96
96
  const node = this._node_index.get(fullBrowsePath);
@@ -98,10 +98,10 @@ export class ConditionSnapshotImpl extends EventEmitter implements ConditionSnap
98
98
  debugLog("cannot node for find key", fullBrowsePath);
99
99
  continue;
100
100
  }
101
- if (isDisabled && !Object.prototype.hasOwnProperty.call(_varTable, fullBrowsePath)) {
101
+ if (isDisabled && !Object.hasOwn(_varTable, fullBrowsePath)) {
102
102
  eventData._createValue(fullBrowsePath, node, disabledVar);
103
103
  } else {
104
- eventData._createValue(fullBrowsePath, node, this._map.get(fullBrowsePath)!);
104
+ eventData._createValue(fullBrowsePath, node, this._map.get(fullBrowsePath) as Variant);
105
105
  }
106
106
  }
107
107
  return eventData;
@@ -185,7 +185,7 @@ export class UAConditionImpl extends UABaseEventImpl implements UAConditionEx {
185
185
  const statusCode = inner_func(eventId, comment, branch, conditionNode);
186
186
 
187
187
  // record also who did the call
188
- branch.setClientUserId(context.userIdentity || "<unknown client user id>");
188
+ branch.setClientUserId(context.getUserName());
189
189
 
190
190
  callback(null, {
191
191
  statusCode
@@ -1031,6 +1031,19 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1031
1031
  return options.toString();
1032
1032
  }
1033
1033
 
1034
+ public toJSON(): Record<string, unknown> {
1035
+ return {
1036
+ nodeId: this.nodeId.toString(),
1037
+ nodeClass: NodeClass[this.nodeClass],
1038
+ browseName: this.browseName.toString(),
1039
+ displayName: this.displayName.length ? this.displayName[0].text : ""
1040
+ };
1041
+ }
1042
+
1043
+ public [Symbol.for("nodejs.util.inspect.custom")](): string {
1044
+ return this.toString();
1045
+ }
1046
+
1034
1047
  /**
1035
1048
  * @property isFalseSubStateOf
1036
1049
  * @type {BaseNode|null}