node-opcua-address-space-base 2.169.0 → 2.172.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.
Files changed (54) hide show
  1. package/dist/address_space.d.ts +21 -24
  2. package/dist/base_node.d.ts +61 -23
  3. package/dist/base_node.js +3 -0
  4. package/dist/base_node.js.map +1 -1
  5. package/dist/bind_variable.d.ts +8 -8
  6. package/dist/clone_helper.d.ts +7 -7
  7. package/dist/clone_helper.js +44 -23
  8. package/dist/clone_helper.js.map +1 -1
  9. package/dist/clone_options.d.ts +10 -10
  10. package/dist/clone_options.js +2 -2
  11. package/dist/clone_options.js.map +1 -1
  12. package/dist/continuation_point.d.ts +1 -1
  13. package/dist/i_event_data.d.ts +5 -8
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.js +3 -3
  16. package/dist/index.js.map +1 -1
  17. package/dist/instantiate_options.d.ts +5 -5
  18. package/dist/ua_data_type.d.ts +6 -6
  19. package/dist/ua_dynamic_variable_array.d.ts +6 -6
  20. package/dist/ua_event_type.d.ts +1 -1
  21. package/dist/ua_method.d.ts +16 -12
  22. package/dist/ua_object.d.ts +16 -18
  23. package/dist/ua_object_type.d.ts +9 -9
  24. package/dist/ua_property.d.ts +3 -3
  25. package/dist/ua_reference.d.ts +3 -3
  26. package/dist/ua_reference_type.d.ts +5 -5
  27. package/dist/ua_variable.d.ts +19 -19
  28. package/dist/ua_variable_t.d.ts +7 -7
  29. package/dist/ua_variable_type.d.ts +14 -14
  30. package/dist/ua_view.d.ts +3 -3
  31. package/package.json +15 -15
  32. package/source/address_space.ts +21 -24
  33. package/source/base_node.ts +128 -80
  34. package/source/bind_variable.ts +8 -9
  35. package/source/clone_helper.ts +67 -44
  36. package/source/clone_options.ts +13 -14
  37. package/source/continuation_point.ts +1 -2
  38. package/source/i_event_data.ts +7 -8
  39. package/source/index.ts +3 -3
  40. package/source/instantiate_options.ts +5 -6
  41. package/source/namespace.ts +1 -1
  42. package/source/ua_data_type.ts +6 -7
  43. package/source/ua_dynamic_variable_array.ts +6 -6
  44. package/source/ua_event_type.ts +1 -1
  45. package/source/ua_method.ts +33 -29
  46. package/source/ua_object.ts +22 -20
  47. package/source/ua_object_type.ts +9 -10
  48. package/source/ua_property.ts +5 -3
  49. package/source/ua_reference.ts +3 -3
  50. package/source/ua_reference_type.ts +14 -14
  51. package/source/ua_variable.ts +35 -30
  52. package/source/ua_variable_t.ts +7 -7
  53. package/source/ua_variable_type.ts +27 -28
  54. package/source/ua_view.ts +3 -3
@@ -1,8 +1,7 @@
1
- import { EventEmitter } from "events";
2
-
3
- export type Duration = number;
4
-
5
- import {
1
+ import { EventEmitter } from "node:events";
2
+ import type { UAString, UInt32 } from "node-opcua-basic-types";
3
+ import type { ReferenceTypeIds } from "node-opcua-constants";
4
+ import type {
6
5
  AccessRestrictionsFlag,
7
6
  AttributeIds,
8
7
  BrowseDirection,
@@ -13,14 +12,11 @@ import {
13
12
  QualifiedNameLike,
14
13
  QualifiedNameOptions
15
14
  } from "node-opcua-data-model";
16
- import { DataType } from "node-opcua-variant";
17
- import { DataValue, DataValueOptions } from "node-opcua-data-value";
18
- import { NodeId, NodeIdLike } from "node-opcua-nodeid";
19
- import { NumericRange } from "node-opcua-numeric-range";
20
- import { StatusCode } from "node-opcua-status-code";
21
-
22
- import {
23
- BrowseDescription,
15
+ import type { DataValue } from "node-opcua-data-value";
16
+ import type { NodeId, NodeIdLike } from "node-opcua-nodeid";
17
+ import type { NumericRange } from "node-opcua-numeric-range";
18
+ import type { StatusCode } from "node-opcua-status-code";
19
+ import type {
24
20
  BrowseDescriptionOptions,
25
21
  ReferenceDescription,
26
22
  RelativePathElement,
@@ -28,20 +24,19 @@ import {
28
24
  RolePermissionTypeOptions,
29
25
  WriteValueOptions
30
26
  } from "node-opcua-types";
27
+ import type { DataType } from "node-opcua-variant";
28
+ import type { IAddressSpace } from "./address_space";
29
+ import type { IEventData } from "./i_event_data";
30
+ import type { ModellingRuleType } from "./modelling_rule_type";
31
+ import type { INamespace } from "./namespace";
32
+ import type { ISessionContext } from "./session_context";
33
+ import type { UAObject } from "./ua_object";
34
+ import type { UAProperty } from "./ua_property";
35
+ import type { UAReference } from "./ua_reference";
36
+ import type { UAReferenceType } from "./ua_reference_type";
37
+ import type { UAVariable } from "./ua_variable";
31
38
 
32
- import { UAString, UInt32 } from "node-opcua-basic-types";
33
- import { ReferenceTypeIds } from "node-opcua-constants";
34
-
35
- import { INamespace } from "./namespace";
36
- import { IAddressSpace } from "./address_space";
37
- import { ModellingRuleType } from "./modelling_rule_type";
38
- import { ISessionContext } from "./session_context";
39
- import { UAObject } from "./ua_object";
40
- import { UAReferenceType } from "./ua_reference_type";
41
- import { UAVariable } from "./ua_variable";
42
- import { UAVariableT } from "./ua_variable_t";
43
- import { UAReference } from "./ua_reference";
44
- import { UAProperty } from "./ua_property";
39
+ export type Duration = number;
45
40
 
46
41
  export declare interface AddReferenceOpts {
47
42
  referenceType: keyof ReferenceTypeIds | NodeIdLike | UAReferenceType;
@@ -85,45 +80,104 @@ export interface BrowseDescriptionOptions2 extends BrowseDescriptionOptions {
85
80
  resultMask: UInt32;
86
81
  }
87
82
 
88
- export declare class BaseNode extends EventEmitter {
89
- public get addressSpace(): IAddressSpace;
90
- public readonly browseName: QualifiedName;
91
- public get displayName(): LocalizedText[];
92
- public get description(): LocalizedText;
93
- public readonly nodeClass: NodeClass;
94
- public readonly nodeId: NodeId;
95
- public get modellingRule(): ModellingRuleType | undefined;
96
- public get parentNodeId(): NodeId | undefined;
97
- public get accessRestrictions(): AccessRestrictionsFlag | undefined;
98
- public get rolePermissions(): RolePermissionType[] | undefined;
83
+ export type AttributeEventName =
84
+ | "Value_changed"
85
+ | "DisplayName_changed"
86
+ | "Description_changed"
87
+ | "BrowseName_changed"
88
+ | "RolePermissions_changed"
89
+ | "AccessRestrictions_changed";
90
+
91
+ export interface BaseNodeEvents_ {
92
+ dispose: [];
93
+ event: [attribute: IEventData];
94
+ Value_changed: [attribute: DataValue];
95
+ DisplayName_changed: [attribute: DataValue];
96
+ Description_changed: [attribute: DataValue];
97
+ BrowseName_changed: [attribute: DataValue];
98
+ RolePermissions_changed: [attribute: DataValue];
99
+ AccessRestrictions_changed: [attribute: DataValue];
100
+ }
101
+
102
+ export interface BaseNodeEvents {
103
+ dispose: () => void;
104
+ event: (attribute: IEventData) => void;
105
+ Value_changed: (attribute: DataValue) => void;
106
+ DisplayName_changed: (attribute: DataValue) => void;
107
+ Description_changed: (attribute: DataValue) => void;
108
+ BrowseName_changed: (attribute: DataValue) => void;
109
+ RolePermissions_changed: (attribute: DataValue) => void;
110
+ AccessRestrictions_changed: (attribute: DataValue) => void;
111
+ }
112
+
113
+ // Self-referential constraint: every property of L must be a function.
114
+ // Lets us drop the broken `T[K] extends (...) => ...` conditionals while
115
+ // preserving exact callback signatures (named params, optional args) for IntelliSense.
116
+ export type ListenerSignature<L> = {
117
+ // biome-ignore lint/suspicious/noExplicitAny: any is required to bypass function-parameter contravariance; using unknown breaks T[K] assignability
118
+ [E in keyof L]: (...args: any[]) => any;
119
+ };
120
+
121
+ export interface ITypedEventEmitter<T extends ListenerSignature<T>> {
122
+ on<K extends keyof T>(event: K, listener: T[K]): this;
123
+ once<K extends keyof T>(event: K, listener: T[K]): this;
124
+ emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): boolean;
125
+ off<K extends keyof T>(event: K, listener: T[K]): this;
126
+
127
+ listenerCount<K extends keyof T>(event: K): number;
128
+
129
+ setMaxListeners(n: number): void;
130
+ removeAllListeners(): void;
131
+ removeListener<K extends keyof T>(event: K, listener: T[K]): void;
132
+ }
133
+
134
+ // Aliases Node's EventEmitter directly so listeners receive `this === <emitter>`, matching
135
+ // the standard EventEmitter contract. The previous composition-based implementation invoked
136
+ // listeners with `this` bound to a private inner emitter, breaking that contract.
137
+ export type TypedEventEmitter<T extends ListenerSignature<T>> = ITypedEventEmitter<T>;
138
+ export const TypedEventEmitter = EventEmitter as unknown as {
139
+ new <T extends ListenerSignature<T>>(): ITypedEventEmitter<T>;
140
+ };
141
+ export interface BaseNode<T extends BaseNodeEvents & ListenerSignature<T> = BaseNodeEvents> extends ITypedEventEmitter<T> {
142
+
143
+ readonly nodeClass: NodeClass;
144
+ get addressSpace(): IAddressSpace;
145
+ readonly browseName: QualifiedName;
146
+ get displayName(): LocalizedText[];
147
+ get description(): LocalizedText;
148
+ readonly nodeId: NodeId;
149
+ get modellingRule(): ModellingRuleType | undefined;
150
+ get parentNodeId(): NodeId | undefined;
151
+ get accessRestrictions(): AccessRestrictionsFlag | undefined;
152
+ get rolePermissions(): RolePermissionType[] | undefined;
99
153
 
100
154
  // access to parent namespace
101
- public get namespaceIndex(): number;
102
- public get namespaceUri(): string;
103
- public get namespace(): INamespace;
155
+ get namespaceIndex(): number;
156
+ get namespaceUri(): string;
157
+ get namespace(): INamespace;
104
158
 
105
- public isDisposed(): boolean;
159
+ isDisposed(): boolean;
106
160
 
107
- public onFirstBrowseAction?: (this: BaseNode) => Promise<void>;
161
+ onFirstBrowseAction?: (this: BaseNode) => Promise<void>;
108
162
 
109
163
  /**
110
164
  * return a complete name of this object by pre-pending
111
165
  * name of its parent(s) to its own name
112
166
  */
113
- public fullName(): string;
167
+ fullName(): string;
114
168
 
115
- public addReference(options: AddReferenceOpts): void;
169
+ addReference(options: AddReferenceOpts): void;
116
170
 
117
- public removeReference(referenceOpts: AddReferenceOpts): void;
171
+ removeReference(referenceOpts: AddReferenceOpts): void;
118
172
 
119
- public readAttribute(
173
+ readAttribute(
120
174
  context: ISessionContext | null,
121
175
  attributeId: AttributeIds,
122
176
  indexRange?: NumericRange,
123
177
  dataEncoding?: QualifiedNameLike | null
124
178
  ): DataValue;
125
179
 
126
- public writeAttribute(
180
+ writeAttribute(
127
181
  context: ISessionContext | null,
128
182
  writeValue: WriteValueOptions,
129
183
  callback: (err: Error | null, statusCode?: StatusCode) => void
@@ -133,26 +187,26 @@ export declare class BaseNode extends EventEmitter {
133
187
  * return a array with the event source of this object.
134
188
  * self = HasEventSource => nodes
135
189
  */
136
- public getEventSources(): BaseNode[];
190
+ getEventSources(): BaseNode[];
137
191
 
138
192
  /**
139
193
  * return a array of the objects for which this node is an EventSource
140
194
  * nodes = HasEventSource => self
141
195
  */
142
- public getEventSourceOfs(): BaseNode[];
196
+ getEventSourceOfs(): BaseNode[];
143
197
 
144
198
  /**
145
199
  *
146
200
  * @param locale the locale of the text to return (e.g. en-EN)
147
201
  */
148
- public getDisplayName(locale?: string): string;
202
+ getDisplayName(locale?: string): string;
149
203
 
150
204
  /**
151
205
  * private
152
206
  */
153
- public install_extra_properties(): void;
207
+ install_extra_properties(): void;
154
208
 
155
- public browseNodeByTargetName(relativePathElement: RelativePathElement, isLast: boolean): NodeId[];
209
+ browseNodeByTargetName(relativePathElement: RelativePathElement, isLast: boolean): NodeId[];
156
210
 
157
211
  /**
158
212
  * find all the references that are of type **`reference`** or a sub type of **`reference`**, in the
@@ -160,7 +214,7 @@ export declare class BaseNode extends EventEmitter {
160
214
  *
161
215
  * * BrowseDirection.Forward direction is implied if browseDirection flags is omitted.
162
216
  */
163
- public findReferencesEx(referenceType: string | NodeId | UAReferenceType, browseDirection?: BrowseDirection): UAReference[];
217
+ findReferencesEx(referenceType: string | NodeId | UAReferenceType, browseDirection?: BrowseDirection): UAReference[];
164
218
 
165
219
  /**
166
220
  * find all the references that are strictly of type **`reference`**.
@@ -168,7 +222,7 @@ export declare class BaseNode extends EventEmitter {
168
222
  *
169
223
  * Forward direction is implied if omitted.
170
224
  */
171
- public findReferences(referenceType: string | NodeId | UAReferenceType, isForward?: boolean): UAReference[];
225
+ findReferences(referenceType: string | NodeId | UAReferenceType, isForward?: boolean): UAReference[];
172
226
 
173
227
  /**
174
228
  * find the the references that are strictly of type **`reference`**.
@@ -180,18 +234,15 @@ export declare class BaseNode extends EventEmitter {
180
234
  * * will throw an exception if more than one reference exists with the referenceType.
181
235
  * * will return null if no reference exists.
182
236
  */
183
- public findReference(referenceType: string | NodeId | UAReferenceType, isForward?: boolean): UAReference | null;
237
+ findReference(referenceType: string | NodeId | UAReferenceType, isForward?: boolean): UAReference | null;
184
238
 
185
239
  /**
186
- * find all the nodes that are referenced by references of type **`reference`** or a
240
+ * find all the nodes that are referenced by references of type **`reference`** or a
187
241
  * sub type of **`reference`**, in the direction specified by **`browseDirection`**
188
242
  *
189
243
  * * BrowseDirection.Forward direction is implied if browseDirection flags is omitted.
190
244
  */
191
- public findReferencesExAsObject(
192
- referenceType: string | NodeId | UAReferenceType,
193
- browseDirection?: BrowseDirection
194
- ): BaseNode[];
245
+ findReferencesExAsObject(referenceType: string | NodeId | UAReferenceType, browseDirection?: BrowseDirection): BaseNode[];
195
246
 
196
247
  /**
197
248
  * find all the nodes that are referenced by references strictly of type **`reference`**.
@@ -203,19 +254,18 @@ export declare class BaseNode extends EventEmitter {
203
254
  * * will throw an exception if more than one reference exists with the referenceType.
204
255
  * * will return null if no reference exists.
205
256
  */
206
- public findReferencesAsObject(referenceType: string | NodeId | UAReferenceType, isForward?: boolean): BaseNode[];
257
+ findReferencesAsObject(referenceType: string | NodeId | UAReferenceType, isForward?: boolean): BaseNode[];
207
258
 
208
- public allReferences(): UAReference[];
259
+ allReferences(): UAReference[];
209
260
 
210
261
  /**
211
262
  * Get the Child by name, if browseName is string and namespaceIndex undefined
212
263
  * then the search doesn't care about namespace matching
213
- *
214
- * @param browseName
264
+ *
265
+ * @param browseName
215
266
  */
216
- public getChildByName(browseName: QualifiedNameOptions): BaseNode | null;
217
- public getChildByName(browseName: string, namespaceIndex?: number): BaseNode | null;
218
-
267
+ getChildByName(browseName: QualifiedNameOptions): BaseNode | null;
268
+ getChildByName(browseName: string, namespaceIndex?: number): BaseNode | null;
219
269
 
220
270
  /**
221
271
  * this methods propagates the forward references to the pointed node
@@ -223,12 +273,12 @@ export declare class BaseNode extends EventEmitter {
223
273
  *
224
274
  * @private
225
275
  */
226
- public propagate_back_references(): void;
276
+ propagate_back_references(): void;
227
277
 
228
278
  /**
229
279
  * browse the node to extract information requested in browseDescription
230
280
  */
231
- public browseNode(browseDescription: BrowseDescriptionOptions2, session?: ISessionContext): ReferenceDescription[];
281
+ browseNode(browseDescription: BrowseDescriptionOptions2, session?: ISessionContext): ReferenceDescription[];
232
282
 
233
283
  /**
234
284
  *
@@ -253,28 +303,26 @@ export declare class BaseNode extends EventEmitter {
253
303
  getAccessRestrictions(inherited: boolean): AccessRestrictionsFlag;
254
304
  /**
255
305
  * NodeVersion (Optional) String The NodeVersion Property is used to indicate the version of a Node.
256
- *
257
- * The NodeVersion Property is updated each time a Reference is added or deleted
258
- * to the Node the Property belongs to.
259
- *
306
+ *
307
+ * The NodeVersion Property is updated each time a Reference is added or deleted
308
+ * to the Node the Property belongs to.
309
+ *
260
310
  * Attribute value changes do not cause the NodeVersion to change.
261
- *
262
- * Clients may read the NodeVersion Property or subscribe to it to determine when the
311
+ *
312
+ * Clients may read the NodeVersion Property or subscribe to it to determine when the
263
313
  * structure of a Node has changed.
264
314
  */
265
315
  // nodeVersion?: UAProperty<UAString, DataType.String>;
266
- /**
316
+ /**
267
317
  * return the versioning node
268
318
  */
269
319
  getNodeVersion(): UAProperty<UAString, DataType.String> | null;
270
320
 
271
-
272
-
273
321
  /**
274
322
  *
275
323
  */
276
324
  getAggregates(): BaseNode[];
277
325
 
278
- public setDisplayName(value: LocalizedTextLike[] | LocalizedTextLike): void;
279
- public setDescription(value: LocalizedTextLike | null): void;
326
+ setDisplayName(value: LocalizedTextLike[] | LocalizedTextLike): void;
327
+ setDescription(value: LocalizedTextLike | null): void;
280
328
  }
@@ -1,18 +1,17 @@
1
- import { Variant, VariantLike } from "node-opcua-variant";
2
- import { CallbackT, StatusCode, StatusCodeCallback } from "node-opcua-status-code";
3
- import {
1
+ import type { QualifiedNameLike } from "node-opcua-data-model";
2
+ import type { DataValue } from "node-opcua-data-value";
3
+ import type { NumericRange } from "node-opcua-numeric-range";
4
+ import type { CallbackT, StatusCode } from "node-opcua-status-code";
5
+ import type {
4
6
  HistoryReadResult,
5
7
  ReadAtTimeDetails,
6
8
  ReadEventDetails,
7
9
  ReadProcessedDetails,
8
10
  ReadRawModifiedDetails
9
11
  } from "node-opcua-types";
10
- import { NumericRange } from "node-opcua-numeric-range";
11
- import { QualifiedNameLike } from "node-opcua-data-model";
12
- import { DataValue } from "node-opcua-data-value";
13
-
14
- import { UAVariable } from "./ua_variable";
15
- import { ContinuationData, ISessionContext } from "./session_context";
12
+ import type { Variant, VariantLike } from "node-opcua-variant";
13
+ import type { ContinuationData, ISessionContext } from "./session_context";
14
+ import type { UAVariable } from "./ua_variable";
16
15
 
17
16
  export type VariableSetterVariation1 = (this: UAVariable, value: Variant) => StatusCode;
18
17
 
@@ -1,55 +1,55 @@
1
1
  import { assert } from "node-opcua-assert";
2
- import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
3
- import { BrowseDirection, NodeClass, QualifiedName } from "node-opcua-data-model";
4
- import { makeNodeId, sameNodeId } from "node-opcua-nodeid";
5
2
  import { ReferenceTypeIds } from "node-opcua-constants";
6
- import { UAObject } from "./ua_object";
7
- import { UAVariable } from "./ua_variable";
8
- import { UAMethod } from "./ua_method";
9
- import { UAObjectType } from "./ua_object_type";
10
- import { UAVariableType } from "./ua_variable_type";
11
- import { BaseNode } from "./base_node";
12
- import { UAReference } from "./ua_reference";
13
- import { IAddressSpace } from "./address_space";
14
-
15
- const warningLog = make_warningLog("CLONE");
16
-
17
- const errorLog = make_errorLog(__filename);
3
+ import { BrowseDirection, NodeClass, type QualifiedName } from "node-opcua-data-model";
4
+ import { checkDebugFlag, make_errorLog, make_warningLog } from "node-opcua-debug";
5
+ import { makeNodeId, type NodeIdLike, sameNodeId } from "node-opcua-nodeid";
6
+ import type { IAddressSpace } from "./address_space";
7
+ import type { BaseNode } from "./base_node";
8
+ import type { UAMethod } from "./ua_method";
9
+ import type { UAObject } from "./ua_object";
10
+ import type { UAObjectType } from "./ua_object_type";
11
+ import type { UAReference } from "./ua_reference";
12
+ import type { UAVariable } from "./ua_variable";
13
+ import type { UAVariableType } from "./ua_variable_type";
14
+
15
+ const warningLog = make_warningLog("INSTANTIATE");
16
+ const errorLog = make_errorLog("INSTANTIATE");
18
17
  const doTrace = checkDebugFlag("INSTANTIATE");
19
18
  const traceLog = errorLog;
20
19
 
21
20
  type UAConcrete = UAVariable | UAObject | UAMethod;
22
21
 
23
22
  /* c8 ignore start */
24
- /**
25
- * @private
23
+ /**
24
+ * @private
26
25
  */
27
26
  export function fullPath(node: BaseNode): string {
28
27
  const browseName = node.browseName.toString();
29
28
 
30
29
  const parent = node.findReferencesExAsObject("Aggregates", BrowseDirection.Inverse)[0];
31
30
  if (parent) {
32
- return fullPath(parent) + "/" + browseName;
31
+ return `${fullPath(parent)}/${browseName}`;
33
32
  }
34
33
  const containingFolder = node.findReferencesExAsObject("Organizes", BrowseDirection.Inverse)[0];
35
34
  if (containingFolder) {
36
- return fullPath(containingFolder) + "@" + browseName;
35
+ return `${fullPath(containingFolder)}@${browseName}`;
37
36
  }
38
37
  return browseName;
39
38
  }
40
39
  /** @private */
41
- export function fullPath2(node: BaseNode): string {
42
- return fullPath(node) + " (" + node.nodeId.toString() + ")";
40
+ export function fullPath2(node: BaseNode | null | undefined): string {
41
+ if (!node) return "(unknown)";
42
+ return `${fullPath(node)} (${node.nodeId.toString()})`;
43
43
  }
44
44
  /** @private */
45
45
  export function exploreNode(node: BaseNode) {
46
46
  const f = (n: BaseNode) => {
47
- return `${n.browseName.toString()} (${n.nodeId.toString()})${n.modellingRule ? " - " + n.modellingRule : ""}`;
47
+ return `${n.browseName.toString()} (${n.nodeId.toString()})${n.modellingRule ? ` - ${n.modellingRule}` : ""}`;
48
48
  };
49
- const r = (r: any) => {
49
+ const r = (r: NodeIdLike) => {
50
50
  const ref = node.addressSpace.findNode(r);
51
- if (!ref) return `${r.nodeId.toString()} (unknown)`;
52
- return ref?.browseName.toString() + " " + ref!.nodeId.toString();
51
+ if (!ref) return `(unknown)`;
52
+ return `${ref?.browseName.toString()} ${ref?.nodeId.toString()}`;
53
53
  };
54
54
  const map = new Set();
55
55
  const _explore = (node: BaseNode, pad: string) => {
@@ -57,20 +57,21 @@ export function exploreNode(node: BaseNode) {
57
57
  const b = node.findReferencesEx("Organizes", BrowseDirection.Forward);
58
58
 
59
59
  for (const ref of [...a, ...b]) {
60
+ if (!ref.node) continue;
60
61
  const alreadyVisited = map.has(ref.nodeId.toString());
61
62
  traceLog(
62
63
  pad,
63
64
  " +-- ",
64
65
  r(ref.referenceType).padEnd(20),
65
66
  "-->",
66
- f(ref.node!).padEnd(10),
67
+ f(ref.node).padEnd(10),
67
68
  alreadyVisited ? " (already visited)" : ""
68
69
  );
69
70
  if (alreadyVisited) {
70
71
  continue;
71
72
  }
72
73
  map.add(ref.nodeId.toString());
73
- _explore(ref.node!, pad + " ");
74
+ _explore(ref.node, `${pad} `);
74
75
  }
75
76
  };
76
77
  traceLog("exploring ", f(node));
@@ -90,9 +91,8 @@ export function exploreNode(node: BaseNode) {
90
91
  // |
91
92
  // +-------------------------------|- EnabledState <
92
93
  //
93
- // find also child object with the same browse name that are
94
- // overridden in the SuperType
95
-
94
+ // find also child object with the same browse name that is overridden in the SuperType
95
+ //
96
96
  // case 2:
97
97
  //
98
98
  // /-----------------------------\
@@ -115,7 +115,7 @@ export function exploreNode(node: BaseNode) {
115
115
  // | |
116
116
  // | +--------------|- (EnabledState)
117
117
  //
118
- // find also child object with the same browse name that are
118
+ // find also child object with the same browse name that is overridden in the same child of the SuperType
119
119
 
120
120
  function _get_parent_type_and_path(originalObject: BaseNode): {
121
121
  parentType: null | UAVariableType | UAObjectType;
@@ -124,17 +124,40 @@ function _get_parent_type_and_path(originalObject: BaseNode): {
124
124
  if (originalObject.nodeClass === NodeClass.Method) {
125
125
  return { parentType: null, path: [] };
126
126
  }
127
-
128
127
  const addressSpace = originalObject.addressSpace;
129
-
130
128
  const parents = originalObject.findReferencesEx("HasChild", BrowseDirection.Inverse);
131
129
  // c8 ignore next
132
130
  if (parents.length > 1) {
133
- warningLog(" object ", originalObject.browseName.toString(), " has more than one parent !");
131
+ // it could be a tricky buggy situation like that we have seen with SIOME
132
+ //
133
+ // AnalogUnitTyoe
134
+ // |-- HasProperty --> EngineeringUnits (i=17052)
135
+ // MyObjectType
136
+ // |-- HasComponent --> ActualSpeed
137
+ // |-- HasComponent --> EngineeringUnits (i=17052) <== BUGGY !!!
138
+
139
+ const parentTypes = parents.filter((p) => {
140
+ const n = addressSpace.findNode(p.nodeId);
141
+ return n && (n.nodeClass === NodeClass.ObjectType || n.nodeClass === NodeClass.VariableType);
142
+ });
143
+
144
+ if (parentTypes.length === 1) {
145
+ return {
146
+ parentType: addressSpace.findNode(parentTypes[0].nodeId) as UAObjectType | UAVariableType,
147
+ path: [originalObject.browseName]
148
+ };
149
+ }
150
+
151
+ warningLog(
152
+ " object ",
153
+ originalObject.browseName.toString(),
154
+ originalObject.nodeId.toString(),
155
+ " has more than one parent !"
156
+ );
134
157
  warningLog(originalObject.toString());
135
158
  warningLog(" parents : ");
136
159
  for (const parent of parents) {
137
- warningLog(" ", parent.toString(), addressSpace.findNode(parent.nodeId)!.browseName.toString());
160
+ warningLog(" ", parent.toString(), addressSpace.findNode(parent.nodeId)?.browseName.toString());
138
161
  }
139
162
  return { parentType: null, path: [] };
140
163
  }
@@ -143,12 +166,12 @@ function _get_parent_type_and_path(originalObject: BaseNode): {
143
166
  if (parents.length === 0) {
144
167
  return { parentType: null, path: [] };
145
168
  }
146
- const theParent = addressSpace.findNode(parents[0]!.nodeId)!;
169
+ const theParent = addressSpace.findNode(parents[0]?.nodeId) as BaseNode;
147
170
  if (theParent && (theParent.nodeClass === NodeClass.VariableType || theParent.nodeClass === NodeClass.ObjectType)) {
148
171
  return { parentType: theParent as UAVariableType | UAObjectType, path: [originalObject.browseName] };
149
172
  }
150
173
  // walk up
151
- const { parentType, path } = _get_parent_type_and_path(theParent!);
174
+ const { parentType, path } = _get_parent_type_and_path(theParent);
152
175
  return { parentType, path: [...path, originalObject.browseName] };
153
176
  }
154
177
  /* c8 ignore stop */
@@ -220,7 +243,7 @@ export class CloneHelper {
220
243
  }
221
244
  public popContext() {
222
245
  assert(this._contextStack.length > 0);
223
- this._context = this._contextStack.pop()!;
246
+ this._context = this._contextStack.pop() || null;
224
247
  }
225
248
  public registerClonedObject<
226
249
  TO extends UAObject | UAVariable | UAMethod | UAObjectType | UAVariableType,
@@ -294,7 +317,7 @@ export class CloneHelper {
294
317
  fullPath2(clonedParent)
295
318
  );
296
319
 
297
- const info = this._context!.get(originalNode.nodeId.toString());
320
+ const info = this._context?.get(originalNode.nodeId.toString());
298
321
  if (info) {
299
322
  return info.cloned;
300
323
  }
@@ -324,7 +347,7 @@ function _remove_unwanted_ref(references: UAReference[]): UAReference[] {
324
347
  */
325
348
  function findNonHierarchicalReferences(originalObject: BaseNode): UAReference[] {
326
349
  // todo: MEMOIZE this method
327
- const addressSpace: IAddressSpace = originalObject.addressSpace;
350
+ const _addressSpace: IAddressSpace = originalObject.addressSpace;
328
351
 
329
352
  // we need to explore the non hierarchical references backwards
330
353
  let references = originalObject.findReferencesEx("NonHierarchicalReferences", BrowseDirection.Inverse);
@@ -336,7 +359,7 @@ function findNonHierarchicalReferences(originalObject: BaseNode): UAReference[]
336
359
 
337
360
  const { parentType, path } = _get_parent_type_and_path(originalObject);
338
361
 
339
- if (parentType && parentType.subtypeOfObj) {
362
+ if (parentType?.subtypeOfObj) {
340
363
  // parent is a ObjectType or VariableType and is not a root type
341
364
  assert(parentType.nodeClass === NodeClass.VariableType || parentType.nodeClass === NodeClass.ObjectType);
342
365
 
@@ -392,14 +415,14 @@ export function reconstructNonHierarchicalReferences(extraInfo: CloneHelper): vo
392
415
 
393
416
  // if the object pointed by this reference is also cloned ...
394
417
 
395
- const originalDest = info.original;
418
+ const _originalDest = info.original;
396
419
  const cloneDest = info.cloned;
397
420
 
398
421
  // c8 ignore next
399
422
  doTrace &&
400
423
  traceLog(
401
424
  " adding reference ",
402
- fullPath2(addressSpace.findNode(ref.referenceType)!),
425
+ fullPath2(addressSpace.findNode(ref.referenceType)),
403
426
  " from cloned ",
404
427
  fullPath2(cloned),
405
428
  " to cloned ",
@@ -450,7 +473,7 @@ export function reconstructFunctionalGroupType(extraInfo: CloneHelper) {
450
473
 
451
474
  if (!folder.typeDefinitionObj) continue;
452
475
 
453
- if (folder.typeDefinitionObj.browseName.name!.toString() !== "FunctionalGroupType") {
476
+ if (folder.typeDefinitionObj.browseName.name?.toString() !== "FunctionalGroupType") {
454
477
  continue;
455
478
  }
456
479
 
@@ -1,15 +1,14 @@
1
- import { NodeId, NodeIdLike } from "node-opcua-nodeid";
2
- import { LocalizedText, NodeClass, QualifiedName } from "node-opcua-data-model";
3
-
4
- import { BaseNode } from "./base_node";
5
- import { ModellingRuleType } from "./modelling_rule_type";
6
- import { INamespace } from "./namespace";
7
- import { UAMethod } from "./ua_method";
8
- import { UAObject } from "./ua_object";
9
- import { UAObjectType } from "./ua_object_type";
10
- import { UAReference } from "./ua_reference";
11
- import { UAVariable } from "./ua_variable";
1
+ import type { LocalizedText, NodeClass, QualifiedName } from "node-opcua-data-model";
2
+ import type { NodeId, NodeIdLike } from "node-opcua-nodeid";
3
+ import type { BaseNode } from "./base_node";
12
4
  import { CloneHelper } from "./clone_helper";
5
+ import type { ModellingRuleType } from "./modelling_rule_type";
6
+ import type { INamespace } from "./namespace";
7
+ import type { UAMethod } from "./ua_method";
8
+ import type { UAObject } from "./ua_object";
9
+ import type { UAObjectType } from "./ua_object_type";
10
+ import type { UAReference } from "./ua_reference";
11
+ import type { UAVariable } from "./ua_variable";
13
12
 
14
13
  export interface CloneFilter {
15
14
  shouldKeep(node: BaseNode): boolean;
@@ -22,8 +21,8 @@ export const defaultCloneFilter: CloneFilter = {
22
21
  }
23
22
  return true;
24
23
  },
25
- filterFor(node: BaseNode) {
26
- return this;
24
+ filterFor(_childInstance: UAVariable | UAObject | UAMethod): CloneFilter {
25
+ return defaultCloneFilter;
27
26
  }
28
27
  };
29
28
 
@@ -46,7 +45,7 @@ export interface CloneExtraInfo {
46
45
  export const makeDefaultCloneExtraInfo = (node: UAVariable | UAMethod | UAObject): CloneExtraInfo => {
47
46
  const extraInfo = new CloneHelper();
48
47
  extraInfo.pushContext({ originalParent: node, clonedParent: node });
49
- return extraInfo;
48
+ return extraInfo as CloneExtraInfo;
50
49
  };
51
50
 
52
51
  export interface CloneOptions /* extends ConstructNodeIdOptions */ {
@@ -1,3 +1,2 @@
1
- import { ByteString } from "node-opcua-basic-types";
2
-
1
+ import type { ByteString } from "node-opcua-basic-types";
3
2
  export type ContinuationPoint = ByteString;