node-opcua-address-space 2.169.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 (49) hide show
  1. package/dist/source/ua_interface.d.ts +2 -3
  2. package/dist/source/ua_interface.js +10 -33
  3. package/dist/source/ua_interface.js.map +1 -1
  4. package/dist/src/_instantiate_helpers.d.ts +1 -1
  5. package/dist/src/_instantiate_helpers.js +32 -9
  6. package/dist/src/_instantiate_helpers.js.map +1 -1
  7. package/dist/src/_mandatory_child_or_requested_optional_filter.js +3 -3
  8. package/dist/src/_mandatory_child_or_requested_optional_filter.js.map +1 -1
  9. package/dist/src/address_space.d.ts +2 -2
  10. package/dist/src/address_space.js +9 -11
  11. package/dist/src/address_space.js.map +1 -1
  12. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js +1 -1
  13. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js.map +1 -1
  14. package/dist/src/base_node_impl.d.ts +1 -1
  15. package/dist/src/base_node_private.d.ts +10 -7
  16. package/dist/src/base_node_private.js +74 -50
  17. package/dist/src/base_node_private.js.map +1 -1
  18. package/dist/src/check_value_rank_compatibility.js +1 -1
  19. package/dist/src/check_value_rank_compatibility.js.map +1 -1
  20. package/dist/src/event_data.d.ts +8 -21
  21. package/dist/src/event_data.js +24 -19
  22. package/dist/src/event_data.js.map +1 -1
  23. package/dist/src/ua_object_impl.d.ts +6 -5
  24. package/dist/src/ua_object_impl.js +30 -4
  25. package/dist/src/ua_object_impl.js.map +1 -1
  26. package/dist/src/ua_object_type_impl.js +2 -2
  27. package/dist/src/ua_object_type_impl.js.map +1 -1
  28. package/dist/src/ua_variable_impl.d.ts +1 -0
  29. package/dist/src/ua_variable_impl.js +79 -1
  30. package/dist/src/ua_variable_impl.js.map +1 -1
  31. package/dist/tsconfig_base.tsbuildinfo +1 -1
  32. package/distHelpers/get_address_space_fixture.js +14 -14
  33. package/distHelpers/get_address_space_fixture.js.map +1 -1
  34. package/distHelpers/index.d.ts +2 -2
  35. package/distHelpers/index.js +2 -2
  36. package/distHelpers/index.js.map +1 -1
  37. package/package.json +18 -18
  38. package/source/ua_interface.ts +24 -38
  39. package/src/_instantiate_helpers.ts +67 -24
  40. package/src/_mandatory_child_or_requested_optional_filter.ts +5 -5
  41. package/src/address_space.ts +15 -16
  42. package/src/alarms_and_conditions/condition_snapshot_impl.ts +3 -3
  43. package/src/base_node_impl.ts +1 -1
  44. package/src/base_node_private.ts +163 -139
  45. package/src/check_value_rank_compatibility.ts +1 -1
  46. package/src/event_data.ts +57 -54
  47. package/src/ua_object_impl.ts +51 -22
  48. package/src/ua_object_type_impl.ts +3 -3
  49. package/src/ua_variable_impl.ts +79 -2
package/src/event_data.ts CHANGED
@@ -1,80 +1,83 @@
1
1
  /**
2
2
  * @module node-opcua-address-space.Private
3
3
  */
4
+
5
+ import type { BaseNode, IEventData } from "node-opcua-address-space-base";
4
6
  import { assert } from "node-opcua-assert";
5
7
  import { coerceExpandedNodeId, NodeId, sameNodeId } from "node-opcua-nodeid";
6
8
  import { StatusCodes } from "node-opcua-status-code";
7
- import { BrowsePath, BrowsePathResult } from "node-opcua-types";
8
- import { Variant, VariantLike } from "node-opcua-variant";
9
-
10
- import { BaseNode, IEventData } from "node-opcua-address-space-base";
9
+ import { type BrowsePath, BrowsePathResult } from "node-opcua-types";
11
10
  import { lowerFirstLetter } from "node-opcua-utils";
11
+ import { Variant, type VariantLike } from "node-opcua-variant";
12
12
 
13
13
  type NodeIdString = string;
14
14
  type FullBrowsePath = string;
15
15
 
16
-
17
16
  /**
18
17
  */
19
18
  export class EventData implements IEventData {
20
- public eventId: NodeId;
21
- public $eventDataSource: BaseNode;
19
+ public eventId: NodeId;
20
+ #eventDataSource: BaseNode;
21
+ #cache: {
22
+ __values: { [key: NodeIdString]: Variant };
23
+ __nodeIdToNode: { [key: NodeIdString]: BaseNode };
24
+ __pathToNodeId: { [key: FullBrowsePath]: NodeId };
25
+ __nodeIdToFullPath: { [key: NodeIdString]: FullBrowsePath };
26
+ };
22
27
 
23
- public $cache: {
24
- __values: { [key: NodeIdString]: Variant };
25
- __nodeIdToNode: { [key: NodeIdString]: BaseNode };
26
- __pathToNodeId: { [key: FullBrowsePath]: NodeId };
27
- __nodeIdToFullPath: { [key: NodeIdString]: FullBrowsePath };
28
+ constructor(eventTypeNode: BaseNode) {
29
+ this.#cache = {
30
+ __values: {},
31
+ __nodeIdToNode: {},
32
+ __pathToNodeId: {},
33
+ __nodeIdToFullPath: {}
28
34
  };
29
35
 
30
- constructor(eventTypeNode: BaseNode) {
31
- this.$cache = {
32
- __values: {},
33
- __nodeIdToNode: {},
34
- __pathToNodeId: {},
35
- __nodeIdToFullPath: {}
36
- };
36
+ this.eventId = new NodeId();
37
+ this.#eventDataSource = eventTypeNode;
38
+ }
37
39
 
38
- this.eventId = new NodeId();
39
- this.$eventDataSource = eventTypeNode;
40
- }
40
+ public getEventDataSource(): BaseNode {
41
+ return this.#eventDataSource;
42
+ }
43
+ public _createValue(fullBrowsePath: string, node: BaseNode, variant: VariantLike): void {
44
+ const eventData = this as Record<string, unknown>;
45
+ assert(!eventData[fullBrowsePath], `already exists ${fullBrowsePath}`);
41
46
 
42
- public _createValue(fullBrowsePath: string, node: BaseNode, variant: VariantLike): void {
43
- const eventData = this as any;
44
- assert(!eventData[fullBrowsePath], "already exists " + fullBrowsePath);
47
+ const lowerName = fullBrowsePath.split(".").map(lowerFirstLetter).join(".");
45
48
 
46
- const lowerName = fullBrowsePath.split(".").map(lowerFirstLetter).join(".");
49
+ eventData[lowerName] = Variant.coerce(variant);
47
50
 
48
- eventData[lowerName] = Variant.coerce(variant);
51
+ this.#cache.__pathToNodeId[fullBrowsePath] = node.nodeId;
52
+ this.#cache.__nodeIdToNode[node.nodeId.toString()] = node;
53
+ this.#cache.__nodeIdToFullPath[node.nodeId.toString()] = fullBrowsePath;
54
+ this.#cache.__values[node.nodeId.toString()] = eventData[lowerName] as Variant;
55
+ }
49
56
 
50
- this.$cache.__pathToNodeId[fullBrowsePath] = node.nodeId;
51
- this.$cache.__nodeIdToNode[node.nodeId.toString()] = node;
52
- this.$cache.__nodeIdToFullPath[node.nodeId.toString()] = fullBrowsePath;
53
- this.$cache.__values[node.nodeId.toString()] = eventData[lowerName];
57
+ public _browse(browsePath: BrowsePath): BrowsePathResult | null {
58
+ if (!sameNodeId(browsePath.startingNode, this.#eventDataSource.nodeId)) {
59
+ return null;
54
60
  }
55
-
56
- public _browse(browsePath: BrowsePath): BrowsePathResult | null {
57
- if (!sameNodeId(browsePath.startingNode, this.$eventDataSource.nodeId)) {
58
- return null;
61
+ const fullBrowsePath = (browsePath.relativePath.elements || []).map((b) => b.targetName.toString()).join(".");
62
+ const nodeId = this.#cache.__pathToNodeId[fullBrowsePath];
63
+ if (!nodeId) return null;
64
+ return new BrowsePathResult({
65
+ statusCode: StatusCodes.Good,
66
+ targets: [
67
+ {
68
+ remainingPathIndex: 0,
69
+ targetId: coerceExpandedNodeId(nodeId)
59
70
  }
60
- const fullBrowsePath = (browsePath.relativePath.elements || []).map((b=>b.targetName.toString())).join(".");
61
- const nodeId = this.$cache.__pathToNodeId[fullBrowsePath];
62
- if (!nodeId) return null;
63
- return new BrowsePathResult({
64
- statusCode: StatusCodes.Good,
65
- targets: [{
66
- remainingPathIndex: 0,
67
- targetId: coerceExpandedNodeId(nodeId),
68
- }]
69
- })
70
- }
71
+ ]
72
+ });
73
+ }
71
74
 
72
- public _readValue(nodeId: NodeId): Variant | null {
73
- const key = nodeId.toString();
74
- const cached_value = this.$cache.__values[key];
75
- if (cached_value) {
76
- return cached_value;
77
- }
78
- return null;
75
+ public _readValue(nodeId: NodeId): Variant | null {
76
+ const key = nodeId.toString();
77
+ const cached_value = this.#cache.__values[key];
78
+ if (cached_value) {
79
+ return cached_value;
79
80
  }
80
- }
81
+ return null;
82
+ }
83
+ }
@@ -5,36 +5,36 @@ import chalk from "chalk";
5
5
 
6
6
  import { assert } from "node-opcua-assert";
7
7
  import { isValidByte } from "node-opcua-basic-types";
8
- import { NodeClass, QualifiedNameLike, QualifiedNameOptions } from "node-opcua-data-model";
8
+ import { NodeClass, type QualifiedNameLike, type QualifiedNameOptions } from "node-opcua-data-model";
9
9
  import { AttributeIds } from "node-opcua-data-model";
10
- import { DataValue, DataValueLike } from "node-opcua-data-value";
10
+ import { DataValue, type DataValueLike } from "node-opcua-data-value";
11
11
  import { getCurrentClock } from "node-opcua-date-time";
12
12
  import { NodeId } from "node-opcua-nodeid";
13
- import { NumericRange } from "node-opcua-numeric-range";
13
+ import type { NumericRange } from "node-opcua-numeric-range";
14
14
  import { StatusCodes } from "node-opcua-status-code";
15
15
  import { DataType } from "node-opcua-variant";
16
16
  import {
17
- EventTypeLike,
18
- RaiseEventData,
19
- ISessionContext,
20
- UAMethod,
21
- UAObject,
22
- UAObjectType,
23
- CloneOptions,
24
- CloneFilter,
25
- CloneExtraInfo,
26
- BaseNode,
27
- UAEventType,
28
- IEventData,
17
+ type EventTypeLike,
18
+ type RaiseEventData,
19
+ type ISessionContext,
20
+ type UAMethod,
21
+ type UAObject,
22
+ type UAObjectType,
23
+ type CloneOptions,
24
+ type CloneFilter,
25
+ type CloneExtraInfo,
26
+ type BaseNode,
27
+ type UAEventType,
28
+ type IEventData,
29
29
  defaultCloneFilter,
30
30
  makeDefaultCloneExtraInfo,
31
31
  EventNotifierFlags
32
32
  } from "node-opcua-address-space-base";
33
33
  import { make_errorLog } from "node-opcua-debug";
34
34
 
35
- import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
35
+ import { BaseNodeImpl, type InternalBaseNodeOptions } from "./base_node_impl";
36
36
  import { _clone, ToStringBuilder, UAObject_toString } from "./base_node_private";
37
- import { apply_condition_refresh, ConditionRefreshCache } from "./apply_condition_refresh";
37
+ import { apply_condition_refresh, type ConditionRefreshCache } from "./apply_condition_refresh";
38
38
 
39
39
  const errorLog = make_errorLog(__filename);
40
40
 
@@ -159,11 +159,11 @@ export class UAObjectImpl extends BaseNodeImpl implements UAObject {
159
159
  } else if (eventType instanceof NodeId) {
160
160
  const eventTypeFound = addressSpace.findNode(eventType) as BaseNode;
161
161
  if (!eventTypeFound) {
162
- throw new Error("raiseEvent: eventType cannot find event Type " + eventType.toString());
162
+ throw new Error(`raiseEvent: eventType cannot find event Type ${eventType.toString()}`);
163
163
  }
164
164
  eventType = eventTypeFound!;
165
165
  if (!eventType || eventType.nodeClass !== NodeClass.ObjectType) {
166
- throw new Error("eventType must exist and be an UAObjectType" + eventType.toString());
166
+ throw new Error(`eventType must exist and be an UAObjectType: ${eventType.toString()}`);
167
167
  }
168
168
  }
169
169
 
@@ -172,14 +172,14 @@ export class UAObjectImpl extends BaseNodeImpl implements UAObject {
172
172
  let eventTypeNode: UAEventType = eventType as UAEventType;
173
173
  // c8 ignore next
174
174
  if (!eventTypeNode) {
175
- throw new Error("UAObject#raiseEventType : Cannot find event type :" + eventType.toString());
175
+ throw new Error(`UAObject#raiseEventType : Cannot find event type : ${eventType.toString()}`);
176
176
  }
177
177
 
178
178
  // coerce EventType
179
179
  eventTypeNode = addressSpace.findEventType(eventType as UAEventType) as UAEventType;
180
- const baseEventType = addressSpace.findEventType("BaseEventType")!;
180
+ const _baseEventType = addressSpace.findEventType("BaseEventType");
181
181
 
182
- data.$eventDataSource = eventTypeNode;
182
+ data.$eventDataSource =eventTypeNode;
183
183
  data.sourceNode = data.sourceNode || { dataType: DataType.NodeId, value: this.nodeId };
184
184
 
185
185
  const eventData1 = addressSpace.constructEventData(eventTypeNode, data);
@@ -241,4 +241,33 @@ export class UAObjectImpl extends BaseNodeImpl implements UAObject {
241
241
  UAObject_toString.call(this, options);
242
242
  return options.toString();
243
243
  }
244
+
245
+ public toJSON(): Record<string, unknown> {
246
+ return {
247
+ ...super.toJSON(),
248
+ typeDefinition: this.typeDefinitionObj ? this.typeDefinitionObj.browseName.toString() : undefined,
249
+ eventNotifier: this._eventNotifier
250
+ };
251
+ }
252
+
253
+ public [Symbol.for("nodejs.util.inspect.custom")](depth: number | null, inspectOptions: { colors?: boolean }): string {
254
+ const c = inspectOptions?.colors === false ? plainChalk : chalk;
255
+ const typeName = this.typeDefinitionObj?.browseName.toString() ?? "?";
256
+ const displayName = this.displayName.length ? this.displayName.map((d) => d.text).join(" | ") : "";
257
+ if (depth !== null && depth <= 0) {
258
+ return `${c.cyan("UAObject<")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}${c.cyan(">")}`;
259
+ }
260
+ const lines = [
261
+ `${c.cyan("UAObject ")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}`,
262
+ c.yellow(" typeDefinition : ") + typeName,
263
+ c.yellow(" displayName : ") + displayName,
264
+ c.yellow(" eventNotifier : ") + this._eventNotifier
265
+ ];
266
+ if (this.description?.text) {
267
+ lines.push(c.yellow(" description : ") + this.description.text);
268
+ }
269
+ return lines.join("\n");
270
+ }
244
271
  }
272
+
273
+ const plainChalk = new Proxy(chalk, { get: () => (s: string) => s }) as typeof chalk;
@@ -112,12 +112,12 @@ export class UAObjectTypeImpl extends BaseNodeImpl implements UAObjectType {
112
112
  "expecting a browse name"
113
113
  );
114
114
 
115
- assert(!Object.prototype.hasOwnProperty.call(options, "propertyOf"), "an Object shall not be a PropertyOf an other object");
116
- assert(!Object.prototype.hasOwnProperty.call(options, "optional"), "do you mean optionals ?");
115
+ assert(!Object.hasOwn(options, "propertyOf"), "an Object shall not be a PropertyOf an other object");
116
+ assert(!Object.hasOwn(options, "optional"), "do you mean optionals ?");
117
117
 
118
118
  assertUnusedChildBrowseName(addressSpace, options);
119
119
 
120
- const baseObjectType = addressSpace.findObjectType("BaseObjectType")!;
120
+ const baseObjectType = addressSpace.findObjectType("BaseObjectType") as UAObjectType;
121
121
  assert(baseObjectType, "BaseObjectType must be defined in the address space");
122
122
 
123
123
  const references: UAReference[] = [];
@@ -76,7 +76,7 @@ import { UAHistoricalDataConfiguration } from "node-opcua-nodeset-ua";
76
76
  import { SessionContext } from "../source/session_context";
77
77
  import { convertToCallbackFunction1 } from "../source/helpers/multiform_func";
78
78
  import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
79
- import { _clone, ToStringBuilder, UAVariable_toString } from "./base_node_private";
79
+ import { _clone, ToStringBuilder, UAVariable_toString, valueRankToString } from "./base_node_private";
80
80
  import { EnumerationInfo, IEnumItem, UADataTypeImpl } from "./ua_data_type_impl";
81
81
  import { apply_condition_refresh, ConditionRefreshCache } from "./apply_condition_refresh";
82
82
  import {
@@ -101,6 +101,8 @@ const warningLog = make_warningLog(__filename);
101
101
  const doDebug = checkDebugFlag(__filename);
102
102
  const errorLog = make_errorLog(__filename);
103
103
 
104
+ const plainChalk = new Proxy(chalk, { get: () => (s: string) => s }) as typeof chalk;
105
+
104
106
  export function adjust_accessLevel(accessLevel: string | number | null): AccessLevelFlag {
105
107
  accessLevel = isNullOrUndefined(accessLevel) ? "CurrentRead | CurrentWrite" : accessLevel;
106
108
  accessLevel = makeAccessLevelFlag(accessLevel);
@@ -239,7 +241,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
239
241
  // this could happen in faulty external nodeset and has been seen once
240
242
  // in an nano server
241
243
  warningLog(super.typeDefinitionObj.toString());
242
- return this.addressSpace.findVariableType("BaseVariableType")!;
244
+ const baseVariableType= this.addressSpace.findVariableType("BaseVariableType");
245
+ if (!baseVariableType) throw new Error("Cannot find BaseVariableType in address space");
246
+ return baseVariableType;
243
247
  }
244
248
  return super.typeDefinitionObj as UAVariableType;
245
249
  }
@@ -1522,6 +1526,79 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1522
1526
  return options.toString();
1523
1527
  }
1524
1528
 
1529
+ public toJSON(): Record<string, unknown> {
1530
+ let value: unknown;
1531
+ let statusCode: string | undefined;
1532
+ try {
1533
+ const dv = this.$dataValue;
1534
+ if (dv) {
1535
+ statusCode = dv.statusCode?.toString();
1536
+ if (dv.value && !(dv.value.value instanceof OpaqueStructure)) {
1537
+ value = dv.value.value;
1538
+ }
1539
+ }
1540
+ } catch {
1541
+ // ignore — value access may fail for bound variables
1542
+ }
1543
+ return {
1544
+ ...super.toJSON(),
1545
+ typeDefinition: this.typeDefinitionObj?.browseName.toString(),
1546
+ dataType: this.dataType?.toString(),
1547
+ valueRank: this.valueRank,
1548
+ arrayDimensions: this.arrayDimensions,
1549
+ accessLevel: AccessLevelFlag[this.accessLevel],
1550
+ statusCode,
1551
+ value
1552
+ };
1553
+ }
1554
+
1555
+ public [Symbol.for("nodejs.util.inspect.custom")](depth: number | null, inspectOptions: { colors?: boolean }): string {
1556
+ const c = inspectOptions?.colors === false ? plainChalk : chalk;
1557
+ const typeName = this.typeDefinitionObj?.browseName.toString() ?? "?";
1558
+ const displayName = this.displayName.length ? this.displayName.map((d) => d.text).join(" | ") : "";
1559
+ if (depth !== null && depth <= 0) {
1560
+ return `${c.cyan("UAVariable<")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}${c.cyan(">")}`;
1561
+ }
1562
+ const dt = this.dataType?.toString() ?? "?";
1563
+ let valueStr = "";
1564
+ let statusStr = "";
1565
+ try {
1566
+ const dv = this.$dataValue;
1567
+ if (dv) {
1568
+ if (dv.statusCode) statusStr = dv.statusCode.toString();
1569
+ if (dv.value && dv.value.value !== undefined && dv.value.value !== null && !(dv.value.value instanceof OpaqueStructure)) {
1570
+ const v = dv.value.value;
1571
+ valueStr = typeof v === "object" ? Object.prototype.toString.call(v) : String(v);
1572
+ if (valueStr.length > 80) valueStr = `${valueStr.slice(0, 77)}...`;
1573
+ }
1574
+ }
1575
+ } catch {
1576
+ // ignore
1577
+ }
1578
+ const lines = [
1579
+ `${c.cyan("UAVariable ")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}`,
1580
+ c.yellow(" typeDefinition : ") + typeName,
1581
+ c.yellow(" displayName : ") + displayName,
1582
+ c.yellow(" dataType : ") + dt,
1583
+ c.yellow(" valueRank : ") + valueRankToString(this.valueRank),
1584
+ c.yellow(" accessLevel : ") + AccessLevelFlag[this.accessLevel]
1585
+ ];
1586
+ if (this.arrayDimensions?.length) {
1587
+ lines.push(c.yellow(" arrayDimensions: ") + JSON.stringify(this.arrayDimensions));
1588
+ }
1589
+ if (valueStr) {
1590
+ lines.push(c.yellow(" value : ") + valueStr);
1591
+ }
1592
+ if (statusStr && statusStr !== "Good (0x00000000)") {
1593
+ lines.push(c.yellow(" statusCode : ") + statusStr);
1594
+ }
1595
+ if (this.description?.text) {
1596
+ lines.push(c.yellow(" description : ") + this.description.text);
1597
+ }
1598
+ return lines.join("\n");
1599
+ }
1600
+
1601
+
1525
1602
  // ---------------------------------------------------------------------------------------------------
1526
1603
  // History
1527
1604
  // ---------------------------------------------------------------------------------------------------