node-opcua-client-dynamic-extension-object 2.127.0 → 2.128.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 (32) hide show
  1. package/dist/convert_data_type_definition_to_structuretype_schema.d.ts +14 -3
  2. package/dist/convert_data_type_definition_to_structuretype_schema.js +285 -204
  3. package/dist/convert_data_type_definition_to_structuretype_schema.js.map +1 -1
  4. package/dist/convert_structuretype_schema_to_structure_definition.js +1 -2
  5. package/dist/convert_structuretype_schema_to_structure_definition.js.map +1 -1
  6. package/dist/get_extension_object_constructor.js +1 -2
  7. package/dist/get_extension_object_constructor.js.map +1 -1
  8. package/dist/get_extra_data_type_manager.d.ts +3 -1
  9. package/dist/get_extra_data_type_manager.js +18 -7
  10. package/dist/get_extra_data_type_manager.js.map +1 -1
  11. package/dist/populate_data_type_manager.d.ts +7 -1
  12. package/dist/populate_data_type_manager.js +26 -9
  13. package/dist/populate_data_type_manager.js.map +1 -1
  14. package/dist/private/find_encodings.js +1 -2
  15. package/dist/private/find_encodings.js.map +1 -1
  16. package/dist/private/populate_data_type_manager_103.js +49 -46
  17. package/dist/private/populate_data_type_manager_103.js.map +1 -1
  18. package/dist/private/populate_data_type_manager_104.d.ts +2 -4
  19. package/dist/private/populate_data_type_manager_104.js +29 -102
  20. package/dist/private/populate_data_type_manager_104.js.map +1 -1
  21. package/dist/promote_opaque_structure.js +2 -3
  22. package/dist/promote_opaque_structure.js.map +1 -1
  23. package/dist/promote_opaque_structure_in_notification_data.js +1 -2
  24. package/dist/promote_opaque_structure_in_notification_data.js.map +1 -1
  25. package/dist/resolve_dynamic_extension_object.js +2 -3
  26. package/dist/resolve_dynamic_extension_object.js.map +1 -1
  27. package/package.json +16 -16
  28. package/source/convert_data_type_definition_to_structuretype_schema.ts +361 -236
  29. package/source/get_extra_data_type_manager.ts +17 -5
  30. package/source/populate_data_type_manager.ts +26 -6
  31. package/source/private/populate_data_type_manager_103.ts +68 -60
  32. package/source/private/populate_data_type_manager_104.ts +46 -119
@@ -3,6 +3,7 @@ import { NodeId } from "node-opcua-nodeid";
3
3
  import { IBasicSessionAsync2 } from "node-opcua-pseudo-session";
4
4
  import { DataTypeDefinition } from "node-opcua-types";
5
5
  import { DataTypeAndEncodingId } from "node-opcua-schemas";
6
+ import { DataType } from "node-opcua-variant";
6
7
  export interface CacheForFieldResolution {
7
8
  fieldTypeName: string;
8
9
  schema: TypeDefinition;
@@ -10,10 +11,20 @@ export interface CacheForFieldResolution {
10
11
  allowSubType?: boolean;
11
12
  dataType?: NodeId;
12
13
  }
14
+ export type ResolveReject = [
15
+ resolve: (value: any) => void,
16
+ reject: (err: Error) => void
17
+ ];
18
+ export interface ICache {
19
+ superType?: Map<string, NodeId>;
20
+ fieldResolution?: Map<string, CacheForFieldResolution>;
21
+ dataTypes?: Map<string, DataType>;
22
+ browseNameCache?: Map<string, string>;
23
+ hitCount?: number;
24
+ $$resolveStuff?: Map<string, ResolveReject[]>;
25
+ }
13
26
  export interface IDataTypeDescriptionMini {
14
27
  encodings?: DataTypeAndEncodingId;
15
28
  isAbstract?: boolean;
16
29
  }
17
- export declare function convertDataTypeDefinitionToStructureTypeSchema(session: IBasicSessionAsync2, dataTypeNodeId: NodeId, name: string, definition: DataTypeDefinition, dataTypeDescription: IDataTypeDescriptionMini | null, dataTypeFactory: DataTypeFactory, isAbstract: boolean, cache: {
18
- [key: string]: CacheForFieldResolution;
19
- }): Promise<IStructuredTypeSchema>;
30
+ export declare function convertDataTypeDefinitionToStructureTypeSchema(session: IBasicSessionAsync2, dataTypeNodeId: NodeId, name: string, definition: DataTypeDefinition, dataTypeDescription: IDataTypeDescriptionMini | null, dataTypeFactory: DataTypeFactory, isAbstract: boolean, cache: ICache): Promise<IStructuredTypeSchema>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertDataTypeDefinitionToStructureTypeSchema = void 0;
3
+ exports.convertDataTypeDefinitionToStructureTypeSchema = convertDataTypeDefinitionToStructureTypeSchema;
4
4
  const node_opcua_data_model_1 = require("node-opcua-data-model");
5
5
  const node_opcua_debug_1 = require("node-opcua-debug");
6
6
  const node_opcua_nodeid_1 = require("node-opcua-nodeid");
@@ -16,38 +16,62 @@ const find_encodings_1 = require("./private/find_encodings");
16
16
  const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
17
17
  const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
18
18
  const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
19
- async function findSuperType(session, dataTypeNodeId) {
19
+ const doDebug = false;
20
+ async function memoize(cache, cacheName, nodeId, func) {
21
+ const key = nodeId.toString();
22
+ if (cache[cacheName]?.has(key)) {
23
+ cache.hitCount = cache.hitCount === undefined ? 0 : cache.hitCount + 1;
24
+ return cache[cacheName]?.get(key);
25
+ }
26
+ const value = await func();
27
+ if (!cache[cacheName]) {
28
+ cache[cacheName] = new Map();
29
+ }
30
+ cache[cacheName].set(key, value);
31
+ return value;
32
+ }
33
+ function fromCache(cache, cacheName, nodeId) {
34
+ const key = nodeId.toString();
35
+ if (cache[cacheName]?.has(key)) {
36
+ cache.hitCount = cache.hitCount === undefined ? 0 : cache.hitCount + 1;
37
+ return cache[cacheName]?.get(key);
38
+ }
39
+ return null;
40
+ }
41
+ async function findSuperType(session, dataTypeNodeId, cache) {
20
42
  if (dataTypeNodeId.namespace === 0 && dataTypeNodeId.value === 24) {
21
43
  // BaseDataType !
22
44
  return (0, node_opcua_nodeid_2.coerceNodeId)(0);
23
45
  }
24
- const nodeToBrowse3 = {
25
- browseDirection: node_opcua_data_model_1.BrowseDirection.Inverse,
26
- includeSubtypes: false,
27
- nodeClassMask: node_opcua_data_model_1.NodeClassMask.DataType,
28
- nodeId: dataTypeNodeId,
29
- referenceTypeId: (0, node_opcua_nodeid_2.resolveNodeId)("HasSubtype"),
30
- resultMask: (0, node_opcua_data_model_1.makeResultMask)("NodeId | ReferenceType | BrowseName | NodeClass")
31
- };
32
- const result3 = await (0, node_opcua_pseudo_session_1.browseAll)(session, nodeToBrowse3);
33
- /* istanbul ignore next */
34
- if (result3.statusCode.isNotGood()) {
35
- throw new Error("Cannot find superType for " + dataTypeNodeId.toString());
36
- }
37
- result3.references = result3.references || [];
38
- /* istanbul ignore next */
39
- if (result3.references.length !== 1) {
40
- errorLog("Invalid dataType with more than one (or 0) superType", result3.toString());
41
- throw new Error("Invalid dataType with more than one (or 0) superType " + dataTypeNodeId.toString() + " l=" + result3.references.length);
42
- }
43
- return result3.references[0].nodeId;
46
+ return await memoize(cache, "superType", dataTypeNodeId, async () => {
47
+ const nodeToBrowse3 = {
48
+ browseDirection: node_opcua_data_model_1.BrowseDirection.Inverse,
49
+ includeSubtypes: false,
50
+ nodeClassMask: node_opcua_data_model_1.NodeClassMask.DataType,
51
+ nodeId: dataTypeNodeId,
52
+ referenceTypeId: (0, node_opcua_nodeid_2.resolveNodeId)("HasSubtype"),
53
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("NodeId | ReferenceType | BrowseName | NodeClass")
54
+ };
55
+ const result3 = await (0, node_opcua_pseudo_session_1.browseAll)(session, nodeToBrowse3);
56
+ /* istanbul ignore next */
57
+ if (result3.statusCode.isNotGood()) {
58
+ throw new Error("Cannot find superType for " + dataTypeNodeId.toString());
59
+ }
60
+ result3.references = result3.references || [];
61
+ /* istanbul ignore next */
62
+ if (result3.references.length !== 1) {
63
+ errorLog("Invalid dataType with more than one (or 0) superType", result3.toString());
64
+ throw new Error("Invalid dataType with more than one (or 0) superType " + dataTypeNodeId.toString() + " l=" + result3.references.length);
65
+ }
66
+ return result3.references[0].nodeId;
67
+ });
44
68
  }
45
- async function findDataTypeCategory(session, cache, dataTypeNodeId) {
46
- const subTypeNodeId = await findSuperType(session, dataTypeNodeId);
47
- debugLog("subTypeNodeId of ", dataTypeNodeId.toString(), " is ", subTypeNodeId.toString());
48
- const key = subTypeNodeId.toString();
49
- if (cache[key]) {
50
- return cache[key].category;
69
+ async function findDataTypeCategory(session, dataTypeFactory, cache, dataTypeNodeId) {
70
+ const subTypeNodeId = await findSuperType(session, dataTypeNodeId, cache);
71
+ doDebug && debugLog("subTypeNodeId of ", dataTypeNodeId.toString(), " is ", subTypeNodeId.toString());
72
+ const fieldResolution = fromCache(cache, "fieldResolution", subTypeNodeId);
73
+ if (fieldResolution) {
74
+ return fieldResolution.category;
51
75
  }
52
76
  let category;
53
77
  const n = subTypeNodeId;
@@ -67,14 +91,14 @@ async function findDataTypeCategory(session, cache, dataTypeNodeId) {
67
91
  return category;
68
92
  }
69
93
  // must drill down ...
70
- return await findDataTypeCategory(session, cache, subTypeNodeId);
94
+ return await findDataTypeCategory(session, dataTypeFactory, cache, subTypeNodeId);
71
95
  }
72
96
  async function findDataTypeBasicType(session, cache, dataTypeNodeId) {
73
- const subTypeNodeId = await findSuperType(session, dataTypeNodeId);
97
+ const subTypeNodeId = await findSuperType(session, dataTypeNodeId, cache);
74
98
  debugLog("subTypeNodeId of ", dataTypeNodeId.toString(), " is ", subTypeNodeId.toString());
75
- const key = subTypeNodeId.toString();
76
- if (cache[key]) {
77
- return cache[key].schema;
99
+ const fieldResolution = fromCache(cache, "fieldResolution", subTypeNodeId);
100
+ if (fieldResolution) {
101
+ return fieldResolution.schema;
78
102
  }
79
103
  const n = subTypeNodeId;
80
104
  if (n.identifierType === node_opcua_nodeid_1.NodeIdType.NUMERIC && n.namespace === 0 && n.value < 29) {
@@ -93,19 +117,22 @@ async function findDataTypeBasicType(session, cache, dataTypeNodeId) {
93
117
  return (0, node_opcua_factory_1.getBuiltInType)(name);
94
118
  }
95
119
  // must drill down ...
96
- return await findDataTypeBasicType(session, cache, subTypeNodeId);
120
+ const td = await findDataTypeBasicType(session, cache, subTypeNodeId);
121
+ return td;
97
122
  }
98
- async function readBrowseName(session, nodeId) {
99
- const dataValue = await session.read({ nodeId, attributeId: node_opcua_data_model_1.AttributeIds.BrowseName });
100
- if (dataValue.statusCode.isNotGood()) {
101
- const message = "cannot extract BrowseName of nodeId = " + nodeId.toString() + " statusCode = " + dataValue.statusCode.toString();
102
- debugLog(message);
103
- throw new Error(message);
104
- }
105
- return dataValue.value.value.name;
123
+ async function readBrowseNameWithCache(session, nodeId, cache) {
124
+ return await memoize(cache, "browseNameCache", nodeId, async () => {
125
+ const dataValue = await session.read({ nodeId, attributeId: node_opcua_data_model_1.AttributeIds.BrowseName });
126
+ if (dataValue.statusCode.isNotGood()) {
127
+ const message = "cannot extract BrowseName of nodeId = " + nodeId.toString() + " statusCode = " + dataValue.statusCode.toString();
128
+ debugLog(message);
129
+ throw new Error(message);
130
+ }
131
+ return dataValue.value.value.name;
132
+ });
106
133
  }
107
134
  async function resolve2(session, dataTypeNodeId, dataTypeFactory, fieldTypeName, cache) {
108
- const category = await findDataTypeCategory(session, cache, dataTypeNodeId);
135
+ const category = await findDataTypeCategory(session, dataTypeFactory, cache, dataTypeNodeId);
109
136
  debugLog(" type " + fieldTypeName + " has not been seen yet, let resolve it => (category = ", category, " )");
110
137
  let schema = undefined;
111
138
  switch (category) {
@@ -154,11 +181,11 @@ async function resolve2(session, dataTypeNodeId, dataTypeFactory, fieldTypeName,
154
181
  }
155
182
  return { schema, category };
156
183
  }
157
- const isExtensionObject = async (session, dataTypeNodeId) => {
184
+ const isExtensionObject = async (session, dataTypeNodeId, cache) => {
158
185
  if (dataTypeNodeId.namespace === 0 && dataTypeNodeId.value === node_opcua_variant_1.DataType.ExtensionObject) {
159
186
  return true;
160
187
  }
161
- const baseDataType = await findSuperType(session, dataTypeNodeId);
188
+ const baseDataType = await findSuperType(session, dataTypeNodeId, cache);
162
189
  const bn = baseDataType;
163
190
  if (bn.identifierType === node_opcua_nodeid_1.NodeIdType.NUMERIC) {
164
191
  if (bn.namespace === 0 && bn.value === node_opcua_variant_1.DataType.ExtensionObject) {
@@ -168,98 +195,96 @@ const isExtensionObject = async (session, dataTypeNodeId) => {
168
195
  return false;
169
196
  }
170
197
  }
171
- return await isExtensionObject(session, baseDataType);
198
+ return await isExtensionObject(session, baseDataType, cache);
172
199
  };
173
200
  // eslint-disable-next-line max-statements
174
201
  async function resolveFieldType(session, dataTypeNodeId, dataTypeFactory, cache) {
175
- if (dataTypeNodeId.namespace === 0 && dataTypeNodeId.value === 22) {
176
- // ERN return null;
177
- const category = node_opcua_factory_1.FieldCategory.complex;
178
- const fieldTypeName = "Structure";
179
- const schema = node_opcua_extension_object_1.ExtensionObject.schema;
180
- return {
181
- category,
182
- fieldTypeName,
183
- schema,
184
- allowSubType: true,
185
- dataType: (0, node_opcua_nodeid_2.coerceNodeId)(node_opcua_variant_1.DataType.ExtensionObject)
186
- };
187
- }
188
- const key = dataTypeNodeId.toString();
189
- const v = cache[key];
190
- if (v) {
191
- return v;
192
- }
193
- if (dataTypeNodeId.value === 0) {
194
- const v3 = {
195
- category: node_opcua_factory_1.FieldCategory.basic,
196
- fieldTypeName: "Variant",
197
- schema: dataTypeFactory.getBuiltInType("Variant")
198
- };
199
- cache[key] = v3;
200
- return v3;
201
- }
202
- const isAbstract = (await session.read({ nodeId: dataTypeNodeId, attributeId: node_opcua_data_model_1.AttributeIds.IsAbstract })).value.value;
203
- const fieldTypeName = await readBrowseName(session, dataTypeNodeId);
204
- if (isAbstract) {
205
- const _isExtensionObject = await isExtensionObject(session, dataTypeNodeId);
206
- debugLog(" dataType " + dataTypeNodeId.toString() + " " + fieldTypeName + " is abstract => extObj ?= " + _isExtensionObject);
207
- if (_isExtensionObject) {
208
- // we could have complex => Structure
209
- const v3 = {
210
- category: node_opcua_factory_1.FieldCategory.complex,
211
- fieldTypeName: fieldTypeName,
212
- schema: node_opcua_extension_object_1.ExtensionObject.schema,
202
+ return await memoize(cache, "fieldResolution", dataTypeNodeId, async () => {
203
+ if (dataTypeNodeId.namespace === 0 && dataTypeNodeId.value === 22) {
204
+ // ERN return null;
205
+ const category = node_opcua_factory_1.FieldCategory.complex;
206
+ const fieldTypeName = "Structure";
207
+ const schema = node_opcua_extension_object_1.ExtensionObject.schema;
208
+ return {
209
+ category,
210
+ fieldTypeName,
211
+ schema,
213
212
  allowSubType: true,
214
- dataType: dataTypeNodeId
213
+ dataType: (0, node_opcua_nodeid_2.coerceNodeId)(node_opcua_variant_1.DataType.ExtensionObject)
215
214
  };
216
- cache[key] = v3;
217
- return v3;
218
215
  }
219
- else {
220
- // we could have basic => Variant
216
+ if (dataTypeNodeId.value === 0) {
221
217
  const v3 = {
222
218
  category: node_opcua_factory_1.FieldCategory.basic,
223
- fieldTypeName: fieldTypeName,
224
- schema: dataTypeFactory.getBuiltInType("Variant"),
225
- allowSubType: true,
226
- dataType: dataTypeNodeId
219
+ fieldTypeName: "Variant",
220
+ schema: dataTypeFactory.getBuiltInType("Variant")
227
221
  };
228
- cache[key] = v3;
229
222
  return v3;
230
223
  }
231
- }
232
- let schema;
233
- let category = node_opcua_factory_1.FieldCategory.enumeration;
234
- if (dataTypeFactory.hasStructureByTypeName(fieldTypeName)) {
235
- schema = dataTypeFactory.getStructuredTypeSchema(fieldTypeName);
236
- category = node_opcua_factory_1.FieldCategory.complex;
237
- }
238
- else if (dataTypeFactory.hasBuiltInType(fieldTypeName)) {
239
- category = node_opcua_factory_1.FieldCategory.basic;
240
- schema = dataTypeFactory.getBuiltInType(fieldTypeName);
241
- }
242
- else if (dataTypeFactory.hasEnumeration(fieldTypeName)) {
243
- category = node_opcua_factory_1.FieldCategory.enumeration;
244
- schema = dataTypeFactory.getEnumeration(fieldTypeName);
245
- }
246
- else {
247
- debugLog(" type " + fieldTypeName + " has not been seen yet, let resolve it");
248
- const res = await resolve2(session, dataTypeNodeId, dataTypeFactory, fieldTypeName, cache);
249
- schema = res.schema;
250
- category = res.category;
251
- }
252
- /* istanbul ignore next */
253
- if (!schema) {
254
- throw new Error("expecting a schema here fieldTypeName=" + fieldTypeName + " " + dataTypeNodeId.toString() + " category = " + category);
255
- }
256
- const v2 = {
257
- category,
258
- fieldTypeName,
259
- schema
260
- };
261
- cache[key] = v2;
262
- return v2;
224
+ const readIsAbstract = async (dataTypeNodeId) => {
225
+ return (await session.read({ nodeId: dataTypeNodeId, attributeId: node_opcua_data_model_1.AttributeIds.IsAbstract })).value.value;
226
+ };
227
+ const [isAbstract, fieldTypeName] = await Promise.all([
228
+ readIsAbstract(dataTypeNodeId),
229
+ readBrowseNameWithCache(session, dataTypeNodeId, cache)
230
+ ]);
231
+ if (isAbstract) {
232
+ const _isExtensionObject = await isExtensionObject(session, dataTypeNodeId, cache);
233
+ debugLog(" dataType " + dataTypeNodeId.toString() + " " + fieldTypeName + " is abstract => extObj ?= " + _isExtensionObject);
234
+ if (_isExtensionObject) {
235
+ // we could have complex => Structure
236
+ const v3 = {
237
+ category: node_opcua_factory_1.FieldCategory.complex,
238
+ fieldTypeName: fieldTypeName,
239
+ schema: node_opcua_extension_object_1.ExtensionObject.schema,
240
+ allowSubType: true,
241
+ dataType: dataTypeNodeId
242
+ };
243
+ return v3;
244
+ }
245
+ else {
246
+ // we could have basic => Variant
247
+ const v3 = {
248
+ category: node_opcua_factory_1.FieldCategory.basic,
249
+ fieldTypeName: fieldTypeName,
250
+ schema: dataTypeFactory.getBuiltInType("Variant"),
251
+ allowSubType: true,
252
+ dataType: dataTypeNodeId
253
+ };
254
+ return v3;
255
+ }
256
+ }
257
+ let schema;
258
+ let category = node_opcua_factory_1.FieldCategory.enumeration;
259
+ if (dataTypeFactory.hasStructureByTypeName(fieldTypeName)) {
260
+ schema = dataTypeFactory.getStructuredTypeSchema(fieldTypeName);
261
+ category = node_opcua_factory_1.FieldCategory.complex;
262
+ }
263
+ else if (dataTypeFactory.hasBuiltInType(fieldTypeName)) {
264
+ category = node_opcua_factory_1.FieldCategory.basic;
265
+ schema = dataTypeFactory.getBuiltInType(fieldTypeName);
266
+ }
267
+ else if (dataTypeFactory.hasEnumeration(fieldTypeName)) {
268
+ category = node_opcua_factory_1.FieldCategory.enumeration;
269
+ schema = dataTypeFactory.getEnumeration(fieldTypeName);
270
+ }
271
+ else {
272
+ debugLog(" type " + fieldTypeName + " has not been seen yet, let resolve it");
273
+ const res = await resolve2(session, dataTypeNodeId, dataTypeFactory, fieldTypeName, cache);
274
+ schema = res.schema;
275
+ category = res.category;
276
+ }
277
+ /* istanbul ignore next */
278
+ if (!schema) {
279
+ throw new Error("expecting a schema here fieldTypeName=" + fieldTypeName + " " + dataTypeNodeId.toString() + " category = " + category);
280
+ }
281
+ const v2 = {
282
+ category,
283
+ fieldTypeName,
284
+ schema
285
+ };
286
+ return v2;
287
+ });
263
288
  }
264
289
  async function _setupEncodings(session, dataTypeNodeId, dataTypeDescription, schema) {
265
290
  // read abstract flag
@@ -276,89 +301,146 @@ async function _setupEncodings(session, dataTypeNodeId, dataTypeDescription, sch
276
301
  }
277
302
  return schema;
278
303
  }
279
- // eslint-disable-next-line max-statements, max-params
280
- async function convertDataTypeDefinitionToStructureTypeSchema(session, dataTypeNodeId, name, definition, dataTypeDescription, dataTypeFactory, isAbstract, cache) {
281
- if (definition instanceof node_opcua_types_1.StructureDefinition) {
282
- let fieldCountToIgnore = 0;
283
- const structureInfo = dataTypeFactory.getStructureInfoForDataType(definition.baseDataType);
284
- const baseSchema = structureInfo?.schema;
285
- if (baseSchema) {
286
- const possibleFields = (0, node_opcua_factory_1.extractAllPossibleFields)(baseSchema);
287
- fieldCountToIgnore += possibleFields.length;
304
+ async function findBasicDataTypeEx(session, dataTypeNodeId, cache) {
305
+ return await memoize(cache, "dataTypes", dataTypeNodeId, async () => {
306
+ const sessionEx = session;
307
+ if (!sessionEx._$$cache2) {
308
+ sessionEx._$$cache2 = new Map();
288
309
  }
289
- // while (base && !(base.dataTypeNodeId.value === DataType.ExtensionObject && base.dataTypeNodeId.namespace === 0)) {
290
- // fieldCountToIgnore += base..length;
291
- // base = base.getBaseSchema();
292
- // }
293
- const fields = [];
294
- const isUnion = definition.structureType === node_opcua_types_1.StructureType.Union;
295
- switch (definition.structureType) {
296
- case node_opcua_types_1.StructureType.Union:
297
- fields.push({
298
- fieldType: "UInt32",
299
- name: "SwitchField"
300
- });
301
- break;
302
- case node_opcua_types_1.StructureType.Structure:
303
- case node_opcua_types_1.StructureType.StructureWithOptionalFields:
304
- break;
310
+ const key = dataTypeNodeId.toString();
311
+ if (sessionEx._$$cache2.has(key)) {
312
+ sessionEx._$$cacheHits = sessionEx._$$cacheHits == undefined ? 0 : sessionEx._$$cacheHits + 1;
313
+ // console.log("cache hit 2", key);
314
+ return sessionEx._$$cache2.get(key);
305
315
  }
306
- let switchValue = 1;
307
- let switchBit = 0;
308
- const bitFields = isUnion ? undefined : [];
309
- const postActions = [];
310
- if (definition.fields) {
311
- for (let i = fieldCountToIgnore; i < definition.fields.length; i++) {
312
- const fieldD = definition.fields[i];
313
- // we need to skip fields that have already been handled in base class
314
- let field;
315
- ({ field, switchBit, switchValue } = createField(fieldD, switchBit, bitFields, isUnion, switchValue));
316
- if (fieldD.dataType.value === dataTypeNodeId.value && fieldD.dataType.namespace === dataTypeNodeId.namespace) {
317
- // this is a structure with a field of the same type
318
- // push an empty placeholder that we will fill later
319
- const fieldTypeName = await readBrowseName(session, dataTypeNodeId);
320
- (field.fieldType = fieldTypeName), (field.category = node_opcua_factory_1.FieldCategory.complex);
321
- fields.push(field);
322
- const capturedField = field;
323
- postActions.push((schema) => {
324
- capturedField.schema = schema;
325
- });
326
- continue;
316
+ const d = await (0, node_opcua_pseudo_session_1.findBasicDataType)(session, dataTypeNodeId);
317
+ sessionEx._$$cache2.set(key, d);
318
+ return d;
319
+ });
320
+ }
321
+ async function nonReentrant(cache, prefix, dataTypeNodeId, func) {
322
+ const key = prefix + dataTypeNodeId.toString();
323
+ if (cache.$$resolveStuff?.has(key)) {
324
+ doDebug && console.log(" re-entering !" + key);
325
+ return await new Promise((resolve, reject) => {
326
+ cache.$$resolveStuff?.get(key).push([resolve, reject]);
327
+ });
328
+ }
329
+ cache.$$resolveStuff = cache.$$resolveStuff || new Map();
330
+ cache.$$resolveStuff.set(key, []);
331
+ return await new Promise((_resolve, _reject) => {
332
+ cache.$$resolveStuff.get(key).push([_resolve, _reject]);
333
+ (async () => {
334
+ try {
335
+ const result = await func();
336
+ const tmp = cache.$$resolveStuff.get(key);
337
+ cache.$$resolveStuff.delete(key);
338
+ for (const [resolve] of tmp) {
339
+ resolve(result);
327
340
  }
328
- const rt = (await resolveFieldType(session, fieldD.dataType, dataTypeFactory, cache));
329
- if (!rt) {
330
- errorLog("convertDataTypeDefinitionToStructureTypeSchema cannot handle field", fieldD.name, "in", name, "because " + fieldD.dataType.toString() + " cannot be resolved");
331
- continue;
341
+ }
342
+ catch (err) {
343
+ const tmp = cache.$$resolveStuff.get(key);
344
+ cache.$$resolveStuff.delete(key);
345
+ for (const [_resolve, reject] of tmp) {
346
+ reject(err);
332
347
  }
333
- const { schema, category, fieldTypeName, dataType, allowSubType } = rt;
334
- field.fieldType = fieldTypeName;
335
- field.category = category;
336
- field.schema = schema;
337
- field.dataType = dataType || fieldD.dataType;
338
- field.allowSubType = allowSubType || false;
339
- field.basicDataType = await (0, node_opcua_pseudo_session_1.findBasicDataType)(session, field.dataType);
340
- fields.push(field);
341
348
  }
349
+ })();
350
+ });
351
+ }
352
+ // eslint-disable-next-line max-statements, max-params
353
+ async function convertDataTypeDefinitionToStructureTypeSchema(session, dataTypeNodeId, name, definition, dataTypeDescription, dataTypeFactory, isAbstract, cache) {
354
+ return await nonReentrant(cache, "convertDataTypeDefinitionToStructureTypeSchema", dataTypeNodeId, async () => {
355
+ // warningLog(">> convertDataTypeDefinitionToStructureTypeSchema = ", dataTypeNodeId.toString());
356
+ if (definition instanceof node_opcua_types_1.StructureDefinition) {
357
+ let fieldCountToIgnore = 0;
358
+ const structureInfo = dataTypeFactory.getStructureInfoForDataType(definition.baseDataType);
359
+ const baseSchema = structureInfo?.schema;
360
+ if (baseSchema) {
361
+ const possibleFields = (0, node_opcua_factory_1.extractAllPossibleFields)(baseSchema);
362
+ fieldCountToIgnore += possibleFields.length;
363
+ }
364
+ // while (base && !(base.dataTypeNodeId.value === DataType.ExtensionObject && base.dataTypeNodeId.namespace === 0)) {
365
+ // fieldCountToIgnore += base..length;
366
+ // base = base.getBaseSchema();
367
+ // }
368
+ const fields = [];
369
+ const isUnion = definition.structureType === node_opcua_types_1.StructureType.Union;
370
+ switch (definition.structureType) {
371
+ case node_opcua_types_1.StructureType.Union:
372
+ fields.push({
373
+ fieldType: "UInt32",
374
+ name: "SwitchField"
375
+ });
376
+ break;
377
+ case node_opcua_types_1.StructureType.Structure:
378
+ case node_opcua_types_1.StructureType.StructureWithOptionalFields:
379
+ break;
380
+ }
381
+ let switchValue = 1;
382
+ let switchBit = 0;
383
+ const bitFields = isUnion ? undefined : [];
384
+ const postActions = [];
385
+ if (definition.fields) {
386
+ for (let i = fieldCountToIgnore; i < definition.fields.length; i++) {
387
+ const fieldD = definition.fields[i];
388
+ // we need to skip fields that have already been handled in base class
389
+ // promises.push((
390
+ await (async () => {
391
+ let field;
392
+ ({ field, switchBit, switchValue } = createField(fieldD, switchBit, bitFields, isUnion, switchValue));
393
+ if (fieldD.dataType.value === dataTypeNodeId.value && fieldD.dataType.namespace === dataTypeNodeId.namespace) {
394
+ // this is a structure with a field of the same type
395
+ // push an empty placeholder that we will fill later
396
+ const fieldTypeName = await readBrowseNameWithCache(session, dataTypeNodeId, cache);
397
+ (field.fieldType = fieldTypeName), (field.category = node_opcua_factory_1.FieldCategory.complex);
398
+ fields.push(field);
399
+ const capturedField = field;
400
+ postActions.push((schema) => {
401
+ capturedField.schema = schema;
402
+ });
403
+ return;
404
+ ;
405
+ }
406
+ const rt = (await resolveFieldType(session, fieldD.dataType, dataTypeFactory, cache));
407
+ if (!rt) {
408
+ errorLog("convertDataTypeDefinitionToStructureTypeSchema cannot handle field", fieldD.name, "in", name, "because " + fieldD.dataType.toString() + " cannot be resolved");
409
+ return;
410
+ }
411
+ const { schema, category, fieldTypeName, dataType, allowSubType } = rt;
412
+ field.fieldType = fieldTypeName;
413
+ field.category = category;
414
+ field.schema = schema;
415
+ field.dataType = dataType || fieldD.dataType;
416
+ field.allowSubType = allowSubType || false;
417
+ field.basicDataType = await findBasicDataTypeEx(session, field.dataType, cache);
418
+ fields.push(field);
419
+ })();
420
+ // ));
421
+ }
422
+ }
423
+ /// some server may provide definition.baseDataType to be i=22 (ExtensionObject)
424
+ /// instead of 12756 Union;
425
+ if (isUnion && (0, node_opcua_nodeid_1.sameNodeId)(definition.baseDataType, (0, node_opcua_nodeid_2.coerceNodeId)("i=22"))) {
426
+ definition.baseDataType = (0, node_opcua_nodeid_2.resolveNodeId)("i=1276"); // aka DataTypeIds.Union
427
+ }
428
+ const a = await resolveFieldType(session, definition.baseDataType, dataTypeFactory, cache);
429
+ const baseType = a ? a.fieldTypeName : isUnion ? "Union" : "ExtensionObject";
430
+ const os = new node_opcua_factory_1.StructuredTypeSchema({
431
+ baseType,
432
+ bitFields,
433
+ fields,
434
+ name,
435
+ dataTypeFactory
436
+ });
437
+ const structuredTypeSchema = await _setupEncodings(session, dataTypeNodeId, dataTypeDescription, os);
438
+ postActions.forEach((action) => action(structuredTypeSchema));
439
+ doDebug && console.log("DONE ! convertDataTypeDefinitionToStructureTypeSchema = ", dataTypeNodeId.toString());
440
+ return structuredTypeSchema;
342
441
  }
343
- /// some server may provide definition.baseDataType to be i=22 (ExtensionObject)
344
- /// instead of 12756 Union;
345
- if (isUnion && (0, node_opcua_nodeid_1.sameNodeId)(definition.baseDataType, (0, node_opcua_nodeid_2.coerceNodeId)("i=22"))) {
346
- definition.baseDataType = (0, node_opcua_nodeid_2.resolveNodeId)("i=1276"); // aka DataTypeIds.Union
347
- }
348
- const a = await resolveFieldType(session, definition.baseDataType, dataTypeFactory, cache);
349
- const baseType = a ? a.fieldTypeName : isUnion ? "Union" : "ExtensionObject";
350
- const os = new node_opcua_factory_1.StructuredTypeSchema({
351
- baseType,
352
- bitFields,
353
- fields,
354
- name,
355
- dataTypeFactory
356
- });
357
- const structuredTypeSchema = await _setupEncodings(session, dataTypeNodeId, dataTypeDescription, os);
358
- postActions.forEach((action) => action(structuredTypeSchema));
359
- return structuredTypeSchema;
360
- }
361
- throw new Error("Not Implemented");
442
+ throw new Error("Not Implemented");
443
+ });
362
444
  function createField(fieldD, switchBit, bitFields, isUnion, switchValue) {
363
445
  const field = {
364
446
  fieldType: "",
@@ -384,5 +466,4 @@ async function convertDataTypeDefinitionToStructureTypeSchema(session, dataTypeN
384
466
  return { field, switchBit, switchValue };
385
467
  }
386
468
  }
387
- exports.convertDataTypeDefinitionToStructureTypeSchema = convertDataTypeDefinitionToStructureTypeSchema;
388
469
  //# sourceMappingURL=convert_data_type_definition_to_structuretype_schema.js.map