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
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
+ }
@@ -287,6 +287,22 @@ export class NamespaceImpl implements NamespacePrivate {
287
287
  return this.index === 0 ? this : this.addressSpace.getDefaultNamespace();
288
288
  }
289
289
 
290
+ public toJSON(): Record<string, string | number | undefined> {
291
+ return {
292
+ index: this.index,
293
+ namespaceUri: this.namespaceUri,
294
+ version: this.version
295
+ };
296
+ }
297
+
298
+ public toString(): string {
299
+ return `Namespace({ index: ${this.index}, namespaceUri: "${this.namespaceUri}" })`;
300
+ }
301
+
302
+ public [Symbol.for("nodejs.util.inspect.custom")](): string {
303
+ return this.toString();
304
+ }
305
+
290
306
  public dispose(): void {
291
307
  for (const node of this.nodeIterator()) {
292
308
  (<BaseNodeImpl>node).dispose();
@@ -1,41 +1,39 @@
1
1
  /**
2
2
  * @module node-opcua-address-space
3
3
  */
4
- import { callbackify } from "util";
5
- import chalk from "chalk";
6
- import { assert } from "node-opcua-assert";
7
4
 
8
- import { AttributeIds, QualifiedNameLike } from "node-opcua-data-model";
9
- import { DiagnosticInfo, NodeClass } from "node-opcua-data-model";
10
- import { DataValue, DataValueLike } from "node-opcua-data-value";
11
- import { make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
12
- import { NodeId } from "node-opcua-nodeid";
13
- import { NumericRange } from "node-opcua-numeric-range";
14
- import { Argument } from "node-opcua-service-call";
15
- import { CallbackT, StatusCode, StatusCodes } from "node-opcua-status-code";
16
- import { CallMethodResultOptions, PermissionType } from "node-opcua-types";
17
- import { Variant } from "node-opcua-variant";
18
- import { DataType, VariantLike } from "node-opcua-variant";
5
+ import { callbackify } from "node:util";
6
+ import chalk from "chalk";
19
7
  import {
20
- MethodFunctor,
21
- MethodFunctorA,
22
- MethodFunctorC,
23
- UAMethod,
24
- UAObject,
25
- CloneExtraInfo,
26
- CloneFilter,
27
- CloneOptions,
28
- UAObjectType,
29
- ISessionContext,
30
- UAVariable,
8
+ type CloneExtraInfo,
9
+ type CloneFilter,
10
+ type CloneOptions,
31
11
  defaultCloneFilter,
32
- makeDefaultCloneExtraInfo
12
+ type ISessionContext,
13
+ type MethodFunctor,
14
+ type MethodFunctorA,
15
+ type MethodFunctorC,
16
+ makeDefaultCloneExtraInfo,
17
+ type UAMethod,
18
+ type UAObject,
19
+ type UAObjectType,
20
+ type UAVariable
33
21
  } from "node-opcua-address-space-base";
34
- import { SessionContext } from "../source/session_context";
22
+ import { assert } from "node-opcua-assert";
23
+ import { AttributeIds, type DiagnosticInfo, NodeClass, type QualifiedNameLike } from "node-opcua-data-model";
24
+ import { DataValue, type DataValueLike } from "node-opcua-data-value";
25
+ import { make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
26
+ import type { NodeId } from "node-opcua-nodeid";
27
+ import type { NumericRange } from "node-opcua-numeric-range";
28
+ import { Argument } from "node-opcua-service-call";
29
+ import { type CallbackT, type StatusCode, StatusCodes } from "node-opcua-status-code";
30
+ import { type CallMethodResultOptions, PermissionType } from "node-opcua-types";
31
+ import { DataType, Variant, type VariantLike } from "node-opcua-variant";
32
+ import type { SessionContext } from "../source/session_context";
33
+ import type { AddressSpacePrivate } from "./address_space_private";
34
+ import { BaseNodeImpl } from "./base_node_impl";
35
35
  import { _clone } from "./base_node_private";
36
36
  import { _handle_hierarchy_parent } from "./namespace_impl";
37
- import { BaseNodeImpl } from "./base_node_impl";
38
- import { AddressSpacePrivate } from "./address_space_private";
39
37
 
40
38
  const warningLog = make_warningLog(__filename);
41
39
  const debugLog = make_debugLog(__filename);
@@ -135,7 +133,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
135
133
  if (async_func.length === 2) {
136
134
  async_func = callbackify(async_func as MethodFunctorA) as MethodFunctorC;
137
135
  }
138
- assert(async_func.length === 3, " a method with callback should have 3 arguments : got " + async_func.length);
136
+ assert(async_func.length === 3, ` a method with callback should have 3 arguments : got ${async_func.length}`);
139
137
  this._asyncExecutionFunction = async_func;
140
138
  }
141
139
  public execute(
@@ -181,17 +179,17 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
181
179
  " " +
182
180
  this.browseName.toString() +
183
181
  " called for a node that is not a Object/ObjectType but " +
184
- NodeClass[context.object!.nodeClass]
182
+ NodeClass[context.object?.nodeClass as number]
185
183
  );
186
184
  return callback(null, { statusCode: StatusCodes.BadNodeIdInvalid });
187
185
  }
188
186
  if (!this._asyncExecutionFunction) {
189
- warningLog("Method " + this.nodeId.toString() + " " + this.browseName.toString() + " has not been bound");
187
+ warningLog(`Method ${this.nodeId.toString()} ${this.browseName.toString()} has not been bound`);
190
188
  return callback(null, { statusCode: StatusCodes.BadInternalError });
191
189
  }
192
190
 
193
191
  if (!this.getExecutableFlag(context)) {
194
- warningLog("Method " + this.nodeId.toString() + " " + this.browseName.toString() + " is not executable");
192
+ warningLog(`Method ${this.nodeId.toString()} ${this.browseName.toString()} is not executable`);
195
193
  return callback(null, { statusCode: StatusCodes.BadNotExecutable });
196
194
  }
197
195
 
@@ -212,7 +210,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
212
210
  // ── method call interceptors ──
213
211
  const addressSpace = this.addressSpace as AddressSpacePrivate;
214
212
  const interceptors = addressSpace._methodCallInterceptors;
215
- const self = this;
213
+
216
214
  const coercedInputArguments = inputArguments as Variant[];
217
215
  const callObject = object;
218
216
 
@@ -221,13 +219,13 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
221
219
  for (const interceptor of interceptors) {
222
220
  let status: StatusCode;
223
221
  try {
224
- status = await interceptor(context, callObject, self, coercedInputArguments);
222
+ status = await interceptor(context, callObject, this, coercedInputArguments);
225
223
  } catch (err) {
226
224
  if (err instanceof Error) {
227
225
  warningLog(chalk.red("ERR in method interceptor"), err.message);
228
226
  }
229
227
  const callMethodResponse = { statusCode: StatusCodes.BadInternalError };
230
- callback!(err as Error, callMethodResponse);
228
+ callback?.(err as Error, callMethodResponse);
231
229
  return;
232
230
  }
233
231
  if (status !== StatusCodes.Good) {
@@ -237,14 +235,14 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
237
235
  inputArgumentResults: coercedInputArguments?.map(() => status) || [],
238
236
  inputArgumentDiagnosticInfos
239
237
  };
240
- return callback!(null, callMethodResult);
238
+ return callback?.(null, callMethodResult);
241
239
  }
242
240
  }
243
241
 
244
242
  // All interceptors passed — execute the method body
245
243
  try {
246
- self._asyncExecutionFunction!.call(
247
- self as UAMethodImpl,
244
+ this._asyncExecutionFunction?.call(
245
+ this as UAMethodImpl,
248
246
  coercedInputArguments,
249
247
  context,
250
248
  (err: Error | null, callMethodResult?: CallMethodResultOptions) => {
@@ -266,14 +264,14 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
266
264
 
267
265
  // ── afterCall event ──
268
266
  try {
269
- self.emit("afterCall", context, coercedInputArguments, callMethodResult);
267
+ this.emit("afterCall", context, coercedInputArguments, callMethodResult);
270
268
  } catch (afterCallErr) {
271
269
  if (afterCallErr instanceof Error) {
272
270
  warningLog(chalk.red("ERR in afterCall listener"), afterCallErr.message);
273
271
  }
274
272
  }
275
273
 
276
- callback!(err, callMethodResult);
274
+ callback?.(err, callMethodResult);
277
275
  }
278
276
  );
279
277
  } catch (err) {
@@ -282,7 +280,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
282
280
  warningLog(err.stack);
283
281
  }
284
282
  const callMethodResponse = { statusCode: StatusCodes.BadInternalError };
285
- callback!(err as Error, callMethodResponse);
283
+ callback?.(err as Error, callMethodResponse);
286
284
  }
287
285
  };
288
286
 
@@ -291,7 +289,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
291
289
  warningLog(chalk.red("ERR in method interceptor"), err.message);
292
290
  }
293
291
  const callMethodResponse = { statusCode: StatusCodes.BadInternalError };
294
- callback!(err as Error, callMethodResponse);
292
+ callback?.(err as Error, callMethodResponse);
295
293
  });
296
294
  }
297
295
 
@@ -310,13 +308,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
310
308
  if (!extraInfo) {
311
309
  extraInfo = makeDefaultCloneExtraInfo(this);
312
310
  }
313
- const clonedMethod = _clone(
314
- this,
315
- UAMethodImpl,
316
- options,
317
- optionalFilter || defaultCloneFilter,
318
- extraInfo
319
- ) as UAMethodImpl;
311
+ const clonedMethod = _clone(this, UAMethodImpl, options, optionalFilter || defaultCloneFilter, extraInfo) as UAMethodImpl;
320
312
 
321
313
  clonedMethod._asyncExecutionFunction = this._asyncExecutionFunction;
322
314
  clonedMethod._getExecutableFlag = this._getExecutableFlag;
@@ -351,4 +343,5 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
351
343
  // tslint:disable:no-var-requires
352
344
  // tslint:disable:max-line-length
353
345
  import { withCallback } from "thenify-ex";
346
+
354
347
  UAMethodImpl.prototype.execute = withCallback(UAMethodImpl.prototype.execute);
@@ -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
  // ---------------------------------------------------------------------------------------------------