node-opcua-client-dynamic-extension-object 2.162.0 → 2.163.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 (31) hide show
  1. package/dist/convert_data_type_definition_to_structuretype_schema.d.ts +4 -3
  2. package/dist/convert_data_type_definition_to_structuretype_schema.js +96 -66
  3. package/dist/convert_data_type_definition_to_structuretype_schema.js.map +1 -1
  4. package/dist/extra_data_type_manager.d.ts +10 -1
  5. package/dist/extra_data_type_manager.js +96 -2
  6. package/dist/extra_data_type_manager.js.map +1 -1
  7. package/dist/get_extension_object_constructor.js +4 -4
  8. package/dist/get_extension_object_constructor.js.map +1 -1
  9. package/dist/get_extra_data_type_manager.d.ts +2 -1
  10. package/dist/get_extra_data_type_manager.js +8 -2
  11. package/dist/get_extra_data_type_manager.js.map +1 -1
  12. package/dist/populate_data_type_manager.d.ts +2 -4
  13. package/dist/populate_data_type_manager.js +88 -81
  14. package/dist/populate_data_type_manager.js.map +1 -1
  15. package/dist/private/populate_data_type_manager_103.js +5 -4
  16. package/dist/private/populate_data_type_manager_103.js.map +1 -1
  17. package/dist/private/populate_data_type_manager_104.d.ts +1 -2
  18. package/dist/private/populate_data_type_manager_104.js +41 -18
  19. package/dist/private/populate_data_type_manager_104.js.map +1 -1
  20. package/dist/resolve_dynamic_extension_object.d.ts +2 -2
  21. package/dist/resolve_dynamic_extension_object.js +66 -91
  22. package/dist/resolve_dynamic_extension_object.js.map +1 -1
  23. package/package.json +12 -12
  24. package/source/convert_data_type_definition_to_structuretype_schema.ts +116 -79
  25. package/source/extra_data_type_manager.ts +113 -4
  26. package/source/get_extension_object_constructor.ts +5 -4
  27. package/source/get_extra_data_type_manager.ts +15 -7
  28. package/source/populate_data_type_manager.ts +99 -89
  29. package/source/private/populate_data_type_manager_103.ts +6 -4
  30. package/source/private/populate_data_type_manager_104.ts +67 -28
  31. package/source/resolve_dynamic_extension_object.ts +79 -110
@@ -1,92 +1,62 @@
1
1
  import { BinaryStream } from "node-opcua-binary-stream";
2
2
  import { ExtensionObject, OpaqueStructure } from "node-opcua-extension-object";
3
3
  import { DataType, Variant, VariantArrayType } from "node-opcua-variant";
4
- import { hexDump, make_warningLog } from "node-opcua-debug";
4
+ import { make_warningLog } from "node-opcua-debug";
5
5
  import { IBasicSessionAsync2 } from "node-opcua-pseudo-session";
6
- import { NodeId } from "node-opcua-nodeid";
7
- import { ConstructorFunc, StructuredTypeField } from "node-opcua-factory";
8
- import { BrowseDirection, NodeClassMask, ResultMask } from "node-opcua-data-model";
6
+ import { StructuredTypeField } from "node-opcua-factory";
9
7
  //
10
8
  import { ExtraDataTypeManager } from "./extra_data_type_manager";
11
- import { readDataTypeDefinitionAndBuildType } from "./private/populate_data_type_manager_104";
12
9
 
13
10
  const warningLog = make_warningLog(__filename);
14
11
 
15
- async function getOrExtractConstructor(
16
- session: IBasicSessionAsync2,
17
- binaryEncodingNodeId: NodeId,
18
- dataTypeManager: ExtraDataTypeManager
19
- ): Promise<ConstructorFunc> {
20
- const dataTypeFactory = dataTypeManager.getDataTypeFactoryForNamespace(binaryEncodingNodeId.namespace);
21
-
22
- const Constructor = dataTypeFactory.getConstructor(binaryEncodingNodeId);
23
- if (Constructor) {
24
- return Constructor;
25
- }
26
- if (binaryEncodingNodeId.namespace === 0) {
27
- throw new Error("Internal Error");
28
- }
29
- // need to extract it
30
- const browseResult = await session.browse({
31
- nodeId: binaryEncodingNodeId,
32
- referenceTypeId: "HasEncoding",
33
- browseDirection: BrowseDirection.Inverse,
34
- includeSubtypes: false,
35
- nodeClassMask: NodeClassMask.DataType,
36
- resultMask: ResultMask.BrowseName
37
- });
38
- if (browseResult.statusCode.isNotGood() || browseResult.references!.length !== 1) {
39
- throw new Error("browse failed");
40
- }
41
- const r = browseResult.references![0];
42
- const dataTypeNodeId = r.nodeId;
43
-
44
- if (dataTypeFactory.getStructureInfoForDataType(dataTypeNodeId)) {
45
- throw new Error("Internal Error: we are not expecting this dataType to be processed already " + dataTypeNodeId.toString());
46
- }
47
- await readDataTypeDefinitionAndBuildType(session, dataTypeNodeId, r.browseName.name!, dataTypeFactory, {});
48
-
49
- const structureInfo = dataTypeFactory.getStructureInfoForDataType(dataTypeNodeId)!;
50
- if (!structureInfo.constructor) {
51
- throw new Error("Cannot find constructor for abstract DataType");
52
- }
53
- return structureInfo.constructor;
54
- }
55
-
56
12
  export async function resolveOpaqueStructureInExtensionObject(
57
13
  session: IBasicSessionAsync2,
58
14
  dataTypeManager: ExtraDataTypeManager,
59
- object: ExtensionObject
15
+ object: ExtensionObject,
16
+ visited?: Set<any>
60
17
  ): Promise<void> {
61
- const schema = object.schema;
18
+
19
+ visited = visited || new Set();
20
+ if (visited.has(object)) {
21
+ return;
22
+ }
23
+ visited.add(object);
24
+
62
25
  interface D {
63
26
  dataTypeManager: ExtraDataTypeManager;
64
27
  promises: Promise<void>[];
28
+ visited: Set<any>;
65
29
  }
66
30
  async function fixOpaqueStructureOnElement(
67
- element: Record<string, unknown>,
31
+ element: any,
68
32
  field: StructuredTypeField,
69
33
  data: D,
70
34
  args?: any
71
35
  ): Promise<unknown> {
72
- if (element instanceof Variant) {
73
- await resolveDynamicExtensionObject(session, element, dataTypeManager);
36
+
37
+
38
+ if (!element) {
74
39
  return element;
75
40
  }
76
- if (!(element instanceof OpaqueStructure)) {
41
+
42
+ if (element instanceof Variant || element.constructor?.name === "Variant") {
43
+ await resolveDynamicExtensionObject(session, element, dataTypeManager, data.visited);
77
44
  return element;
78
45
  }
79
- const variant = new Variant({ dataType: DataType.ExtensionObject, value: element });
80
- await resolveDynamicExtensionObject(session, variant, dataTypeManager);
81
- return variant.value as unknown;
46
+ if (element instanceof ExtensionObject || element?.constructor?.schema?.name === "ExtensionObject") {
47
+ if (element instanceof OpaqueStructure) {
48
+ const variant = new Variant({ dataType: DataType.ExtensionObject, value: element });
49
+ await resolveDynamicExtensionObject(session, variant, dataTypeManager, data.visited);
50
+ return variant.value as unknown;
51
+ } else {
52
+ await resolveOpaqueStructureInExtensionObject(session, dataTypeManager, element, data.visited);
53
+ return element;
54
+ }
55
+ }
56
+ return element;
82
57
  }
83
58
  function fixOpaqueStructure(object: any, field: StructuredTypeField, data: D, args?: any) {
84
- if (field.category === "complex" && !field.allowSubType) {
85
- return;
86
- }
87
- if (field.category === "basic" && field.fieldType !== "Variant") {
88
- return;
89
- }
59
+
90
60
  const a = object[field.name];
91
61
  if (!a) {
92
62
  return;
@@ -94,14 +64,14 @@ export async function resolveOpaqueStructureInExtensionObject(
94
64
  if (field.isArray) {
95
65
  for (let i = 0; i < a.length; i++) {
96
66
  const x = a[i];
97
- promises.push(
67
+ data.promises.push(
98
68
  (async () => {
99
69
  a[i] = await fixOpaqueStructureOnElement(x, field, data, args);
100
70
  })()
101
71
  );
102
72
  }
103
73
  } else {
104
- promises.push(
74
+ data.promises.push(
105
75
  (async () => {
106
76
  object[field.name] = await fixOpaqueStructureOnElement(a, field, data, args);
107
77
  })()
@@ -109,64 +79,63 @@ export async function resolveOpaqueStructureInExtensionObject(
109
79
  }
110
80
  }
111
81
  const promises: Promise<void>[] = [];
112
- object.applyOnAllFields<D>(fixOpaqueStructure, { dataTypeManager, promises });
82
+ object.applyOnAllFields<D>(fixOpaqueStructure, { dataTypeManager, promises, visited });
113
83
  await Promise.all(promises);
114
84
  }
115
85
 
116
- async function resolveDynamicExtensionObjectV(
117
- session: IBasicSessionAsync2,
118
- opaque: OpaqueStructure,
119
- dataTypeManager: ExtraDataTypeManager
120
- ): Promise<ExtensionObject> {
121
- try {
122
- const Constructor = await getOrExtractConstructor(session, opaque.nodeId, dataTypeManager);
123
- const object = new Constructor();
124
- const stream = new BinaryStream(opaque.buffer);
125
- try {
126
- object.decode(stream);
127
- await resolveOpaqueStructureInExtensionObject(session, dataTypeManager, object);
128
- return object;
129
- } catch (err) {
130
- warningLog("Constructor = ", Constructor.name);
131
- warningLog("opaqueStructure = ", opaque?.nodeId?.toString());
132
- warningLog("opaqueStructure = ", hexDump(opaque.buffer, 132, 100));
133
- warningLog(hexDump(opaque.buffer));
134
- warningLog("resolveDynamicExtensionObjectV err = ", err);
135
- // try again for debugging
136
- object.decode(stream);
137
- return opaque;
138
- }
139
- } catch (err) {
140
- warningLog("err", err);
141
- warningLog("opaqueStructure = ", opaque.nodeId.toString());
142
- warningLog("opaqueStructure = ", "0x" + hexDump(opaque.buffer, 132, 100));
143
- warningLog(hexDump(opaque.buffer));
144
- warningLog(dataTypeManager.toString());
145
- throw err;
146
- }
147
- }
148
-
149
86
  export async function resolveDynamicExtensionObject(
150
87
  session: IBasicSessionAsync2,
151
88
  variant: Variant,
152
- dataTypeManager: ExtraDataTypeManager
89
+ dataTypeManager: ExtraDataTypeManager,
90
+ visited?: Set<any>
153
91
  ): Promise<void> {
154
- if (variant.dataType !== DataType.ExtensionObject) {
155
- return;
156
- }
157
- if (variant.arrayType !== VariantArrayType.Scalar) {
158
- if (variant.value instanceof Array) {
159
- for (let i = 0; i < variant.value.length; i++) {
160
- if (variant.value[i] instanceof OpaqueStructure) {
161
- variant.value[i] = await resolveDynamicExtensionObjectV(session, variant.value[i], dataTypeManager);
92
+ visited = visited || new Set();
93
+
94
+ const handleValue = async (value: any): Promise<any> => {
95
+ if (!value) {
96
+ return value;
97
+ }
98
+ if (value instanceof OpaqueStructure) {
99
+ try {
100
+ const Constructor = await dataTypeManager.getExtensionObjectConstructorFromBinaryEncodingAsync(value.nodeId);
101
+ const object = new Constructor();
102
+ const stream = new BinaryStream(value.buffer);
103
+ try {
104
+ object.decode(stream);
105
+ await resolveOpaqueStructureInExtensionObject(session, dataTypeManager, object, visited!);
106
+ return object;
107
+ } catch (err) {
108
+ warningLog("resolveDynamicExtensionObjectV: error decoding or resolving inner structures");
109
+ warningLog("Constructor = ", Constructor.name);
110
+ warningLog("opaqueStructure = ", value?.nodeId?.toString());
111
+ warningLog("resolveDynamicExtensionObjectV err = ", (err as Error).message, (err as Error).stack);
112
+ return value;
162
113
  }
114
+ } catch (err) {
115
+ warningLog("resolveDynamicExtensionObjectV: error getting constructor");
116
+ warningLog("opaqueStructure = ", value.nodeId.toString());
117
+ warningLog("err", (err as Error).message, (err as Error).stack);
118
+ return value;
163
119
  }
164
120
  }
165
- return;
121
+ if (value instanceof ExtensionObject) {
122
+ await resolveOpaqueStructureInExtensionObject(session, dataTypeManager, value, visited!);
123
+ return value;
124
+ }
125
+ if (value instanceof Variant) {
126
+ await resolveDynamicExtensionObject(session, value, dataTypeManager, visited!);
127
+ return value;
128
+ }
129
+ return value;
166
130
  }
167
131
 
168
- if (!(variant.value instanceof OpaqueStructure)) {
169
- return;
132
+ if (variant.arrayType !== VariantArrayType.Scalar) {
133
+ if (Array.isArray(variant.value)) {
134
+ for (let i = 0; i < variant.value.length; i++) {
135
+ variant.value[i] = await handleValue(variant.value[i]);
136
+ }
137
+ }
138
+ } else {
139
+ variant.value = await handleValue(variant.value);
170
140
  }
171
- variant.value = await resolveDynamicExtensionObjectV(session, variant.value, dataTypeManager);
172
141
  }