node-opcua-client-dynamic-extension-object 2.178.0 → 2.180.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 (51) hide show
  1. package/dist/convert_data_type_definition_to_structuretype_schema.d.ts +8 -11
  2. package/dist/convert_data_type_definition_to_structuretype_schema.js +81 -48
  3. package/dist/convert_data_type_definition_to_structuretype_schema.js.map +1 -1
  4. package/dist/convert_structuretype_schema_to_structure_definition.d.ts +1 -1
  5. package/dist/convert_structuretype_schema_to_structure_definition.js +5 -3
  6. package/dist/convert_structuretype_schema_to_structure_definition.js.map +1 -1
  7. package/dist/extra_data_type_manager.d.ts +4 -5
  8. package/dist/extra_data_type_manager.js +15 -16
  9. package/dist/extra_data_type_manager.js.map +1 -1
  10. package/dist/get_extension_object_constructor.d.ts +3 -3
  11. package/dist/get_extension_object_constructor.js +3 -0
  12. package/dist/get_extension_object_constructor.js.map +1 -1
  13. package/dist/get_extra_data_type_manager.d.ts +2 -2
  14. package/dist/get_extra_data_type_manager.js +8 -8
  15. package/dist/get_extra_data_type_manager.js.map +1 -1
  16. package/dist/index.d.ts +5 -6
  17. package/dist/index.js +20 -21
  18. package/dist/index.js.map +1 -1
  19. package/dist/populate_data_type_manager.d.ts +2 -2
  20. package/dist/populate_data_type_manager.js +10 -10
  21. package/dist/populate_data_type_manager.js.map +1 -1
  22. package/dist/private/find_encodings.d.ts +2 -2
  23. package/dist/private/find_encodings.js.map +1 -1
  24. package/dist/private/populate_data_type_manager_103.d.ts +4 -4
  25. package/dist/private/populate_data_type_manager_103.js +97 -53
  26. package/dist/private/populate_data_type_manager_103.js.map +1 -1
  27. package/dist/private/populate_data_type_manager_104.d.ts +18 -4
  28. package/dist/private/populate_data_type_manager_104.js +48 -17
  29. package/dist/private/populate_data_type_manager_104.js.map +1 -1
  30. package/dist/promote_opaque_structure.d.ts +2 -2
  31. package/dist/promote_opaque_structure.js.map +1 -1
  32. package/dist/promote_opaque_structure_in_notification_data.d.ts +2 -2
  33. package/dist/promote_opaque_structure_in_notification_data.js +0 -2
  34. package/dist/promote_opaque_structure_in_notification_data.js.map +1 -1
  35. package/dist/resolve_dynamic_extension_object.d.ts +4 -4
  36. package/dist/resolve_dynamic_extension_object.js +15 -12
  37. package/dist/resolve_dynamic_extension_object.js.map +1 -1
  38. package/package.json +18 -18
  39. package/source/convert_data_type_definition_to_structuretype_schema.ts +146 -123
  40. package/source/convert_structuretype_schema_to_structure_definition.ts +9 -9
  41. package/source/extra_data_type_manager.ts +24 -22
  42. package/source/get_extension_object_constructor.ts +12 -7
  43. package/source/get_extra_data_type_manager.ts +21 -24
  44. package/source/index.ts +8 -8
  45. package/source/populate_data_type_manager.ts +17 -25
  46. package/source/private/find_encodings.ts +2 -2
  47. package/source/private/populate_data_type_manager_103.ts +166 -105
  48. package/source/private/populate_data_type_manager_104.ts +102 -45
  49. package/source/promote_opaque_structure.ts +3 -3
  50. package/source/promote_opaque_structure_in_notification_data.ts +3 -5
  51. package/source/resolve_dynamic_extension_object.ts +28 -29
@@ -1,32 +1,39 @@
1
- /* eslint-disable max-statements */
2
- // tslint:disable: no-console
3
1
  /**
4
2
  * @module node-opcua-client-dynamic-extension-object
5
3
  */
6
4
  import chalk from "chalk";
7
5
 
8
6
  import { assert } from "node-opcua-assert";
9
- import { AttributeIds, makeNodeClassMask, makeResultMask, NodeClassMask, QualifiedName } from "node-opcua-data-model";
7
+ import { AttributeIds, makeNodeClassMask, makeResultMask, NodeClassMask, type QualifiedName } from "node-opcua-data-model";
8
+ import type { DataValue } from "node-opcua-data-value";
10
9
  import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
11
- import { ConstructorFuncWithSchema, DataTypeFactory, getStandardDataTypeFactory } from "node-opcua-factory";
10
+ import { type ConstructorFuncWithSchema, DataTypeFactory, getStandardDataTypeFactory } from "node-opcua-factory";
12
11
  import { ExpandedNodeId, NodeId, resolveNodeId, sameNodeId } from "node-opcua-nodeid";
13
- import { browseAll, BrowseDescriptionLike, IBasicSessionAsync, IBasicSessionAsync2 } from "node-opcua-pseudo-session";
12
+ import {
13
+ type BrowseDescriptionLike,
14
+ browseAll,
15
+ type IBasicSessionAsync,
16
+ type IBasicSessionAsync2
17
+ } from "node-opcua-pseudo-session";
14
18
  import {
15
19
  createDynamicObjectConstructor,
16
- DataTypeAndEncodingId,
17
- MapDataTypeAndEncodingIdProvider,
20
+ type DataTypeAndEncodingId,
21
+ type MapDataTypeAndEncodingIdProvider,
18
22
  parseBinaryXSD
19
23
  } from "node-opcua-schemas";
20
- import { BrowseDescriptionOptions, BrowseDirection, BrowseResult, ReferenceDescription } from "node-opcua-service-browse";
24
+ import {
25
+ type BrowseDescriptionOptions,
26
+ BrowseDirection,
27
+ type BrowseResult,
28
+ type ReferenceDescription
29
+ } from "node-opcua-service-browse";
21
30
  import { makeBrowsePath } from "node-opcua-service-translate-browse-path";
22
- import { ReadValueIdOptions, StructureDefinition } from "node-opcua-types";
23
-
24
- import { ExtraDataTypeManager } from "../extra_data_type_manager";
31
+ import { type ReadValueIdOptions, StructureDefinition } from "node-opcua-types";
25
32
  import {
26
- CacheForFieldResolution,
33
+ type CacheForFieldResolution,
27
34
  convertDataTypeDefinitionToStructureTypeSchema
28
35
  } from "../convert_data_type_definition_to_structuretype_schema";
29
- import { DataValue } from "node-opcua-data-value";
36
+ import type { ExtraDataTypeManager } from "../extra_data_type_manager";
30
37
 
31
38
  const doDebug = checkDebugFlag(__filename);
32
39
  const debugLog = make_debugLog(__filename);
@@ -58,7 +65,8 @@ async function _readDeprecatedFlag(session: IBasicSessionAsync, dataTypeDictiona
58
65
  /* c8 ignore next */
59
66
  if (!a.targets || a.targets.length === 0) {
60
67
  // the server is probably version < 1.04.
61
- debugLog("Cannot find Deprecated property for dataTypeDictionary " + dataTypeDictionary.toString());
68
+ // c8 ignore next
69
+ doDebug && debugLog(`Cannot find Deprecated property for dataTypeDictionary ${dataTypeDictionary.toString()}`);
62
70
  return false;
63
71
  }
64
72
  const deprecatedFlagNodeId = a.targets[0].targetId;
@@ -103,21 +111,34 @@ async function _getDataTypeDescriptions(
103
111
  return result2.references.map((r) => ({ nodeId: r.nodeId, browseName: r.browseName }));
104
112
  }
105
113
 
114
+ /**
115
+ * A DataType together with the DataTypeDescription it was reached through.
116
+ *
117
+ * These used to be two arrays paired by index, which only holds while nothing is
118
+ * skipped - and descriptions are skipped, since an abstract type has no DescriptionOf
119
+ * reference. After the first skip every index named a different type in each array, so
120
+ * encodings were written onto the wrong description and the caller's lookup missed. That
121
+ * surfaced as "cannot find dataTypeDescription for ns=..;i=..", caught and logged, with
122
+ * the class silently left unregistered. Keeping the two together makes it unrepresentable.
123
+ */
124
+ interface IDataTypeAndDescription {
125
+ dataTypeNodeId: NodeId;
126
+ dataTypeDescription: IDataTypeDescription;
127
+ }
128
+
106
129
  async function _enrichWithDescriptionOf(
107
130
  session: IBasicSessionAsync2,
108
131
  dataTypeDescriptions: IDataTypeDescription[]
109
- ): Promise<NodeId[]> {
110
- const nodesToBrowse3: BrowseDescriptionOptions[] =
111
- dataTypeDescriptions.map((dataTypeDescription) => ({
112
- browseDirection: BrowseDirection.Inverse,
113
- includeSubtypes: false,
114
- nodeClassMask: makeNodeClassMask("Object"),
115
- nodeId: dataTypeDescription.nodeId.toString(),
116
- referenceTypeId: resolveNodeId("HasDescription"),
117
- // resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
118
- resultMask: makeResultMask("NodeId")
119
- }))
120
- ;
132
+ ): Promise<IDataTypeAndDescription[]> {
133
+ const nodesToBrowse3: BrowseDescriptionOptions[] = dataTypeDescriptions.map((dataTypeDescription) => ({
134
+ browseDirection: BrowseDirection.Inverse,
135
+ includeSubtypes: false,
136
+ nodeClassMask: makeNodeClassMask("Object"),
137
+ nodeId: dataTypeDescription.nodeId.toString(),
138
+ referenceTypeId: resolveNodeId("HasDescription"),
139
+ // resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
140
+ resultMask: makeResultMask("NodeId")
141
+ }));
121
142
 
122
143
  /* c8 ignore next */
123
144
  if (nodesToBrowse3.length === 0) {
@@ -127,6 +148,8 @@ async function _enrichWithDescriptionOf(
127
148
 
128
149
  const binaryEncodings = [];
129
150
  const nodesToBrowseDataType: BrowseDescriptionOptions[] = [];
151
+ // parallel to nodesToBrowseDataType, so the pairing survives the skips below
152
+ const browsedDescriptions: IDataTypeDescription[] = [];
130
153
 
131
154
  for (let i = 0; i < results3.length; i++) {
132
155
  const result3 = results3[i];
@@ -153,6 +176,7 @@ async function _enrichWithDescriptionOf(
153
176
  };
154
177
  dataTypeDescription.encodings.binaryEncodingNodeId = binaryEncodingNodeId;
155
178
  binaryEncodings.push(binaryEncodingNodeId);
179
+ browsedDescriptions.push(dataTypeDescription);
156
180
  nodesToBrowseDataType.push({
157
181
  browseDirection: BrowseDirection.Inverse,
158
182
  includeSubtypes: false,
@@ -165,7 +189,7 @@ async function _enrichWithDescriptionOf(
165
189
  }
166
190
  }
167
191
 
168
- const dataTypeNodeIds: NodeId[] = [];
192
+ const pairs: IDataTypeAndDescription[] = [];
169
193
 
170
194
  if (nodesToBrowseDataType.length > 0) {
171
195
  const results4 = await browseAll(session, nodesToBrowseDataType);
@@ -177,16 +201,21 @@ async function _enrichWithDescriptionOf(
177
201
  if (result4.references.length !== 1) {
178
202
  errorLog("What's going on ?", result4.toString(), "result4.references.length = ", result4.references.length);
179
203
  }
204
+ // Nothing to pair with, and reading references[0] would throw.
205
+ if (result4.references.length === 0) {
206
+ continue;
207
+ }
180
208
 
181
- const ref = result4.references![0];
209
+ const ref = result4.references[0];
182
210
  const dataTypeNodeId = ref.nodeId;
183
- dataTypeNodeIds[i] = dataTypeNodeId;
184
- const dataTypeDescription = dataTypeDescriptions[i];
211
+ const dataTypeDescription = browsedDescriptions[i];
212
+ // biome-ignore lint/style/noNonNullAssertion: encodings is always populated for entries that reached nodesToBrowseDataType (see loop above)
185
213
  dataTypeDescription.encodings!.dataTypeNodeId = dataTypeNodeId;
214
+ pairs.push({ dataTypeNodeId, dataTypeDescription });
186
215
  }
187
216
  }
188
217
 
189
- const otherEncodingBrowse = dataTypeNodeIds.map((dataTypeNodeId) => ({
218
+ const otherEncodingBrowse = pairs.map(({ dataTypeNodeId }) => ({
190
219
  browseDirection: BrowseDirection.Forward,
191
220
  includeSubtypes: false,
192
221
  nodeClassMask: NodeClassMask.Object,
@@ -199,20 +228,22 @@ async function _enrichWithDescriptionOf(
199
228
  const results5 = await browseAll(session, otherEncodingBrowse);
200
229
  for (let i = 0; i < results5.length; i++) {
201
230
  const result5 = results5[i];
202
- const dataTypeDescription = dataTypeDescriptions[i];
231
+ const { dataTypeDescription } = pairs[i];
203
232
  let encodingCounter = 0;
233
+ // biome-ignore lint/style/noNonNullAssertion: encodings is always populated by the earlier enrichment pass for these dataTypeDescriptions
234
+ const encodings = dataTypeDescription.encodings!;
204
235
  for (const ref of result5.references || []) {
205
236
  switch (ref.browseName.name) {
206
237
  case "Default XML":
207
- dataTypeDescription.encodings!.xmlEncodingNodeId = ref.nodeId;
238
+ encodings.xmlEncodingNodeId = ref.nodeId;
208
239
  encodingCounter++;
209
240
  break;
210
241
  case "Default Binary":
211
- dataTypeDescription.encodings!.binaryEncodingNodeId = ref.nodeId;
242
+ encodings.binaryEncodingNodeId = ref.nodeId;
212
243
  encodingCounter++;
213
244
  break;
214
245
  case "Default JSON":
215
- dataTypeDescription.encodings!.jsonEncodingNodeId = ref.nodeId;
246
+ encodings.jsonEncodingNodeId = ref.nodeId;
216
247
  encodingCounter++;
217
248
  break;
218
249
  default:
@@ -223,7 +254,7 @@ async function _enrichWithDescriptionOf(
223
254
  dataTypeDescription.isAbstract = true;
224
255
  }
225
256
  }
226
- return dataTypeNodeIds;
257
+ return pairs;
227
258
  }
228
259
 
229
260
  interface IDataTypeDefInfo {
@@ -231,6 +262,8 @@ interface IDataTypeDefInfo {
231
262
  dataTypeNodeId: NodeId;
232
263
  dataTypeDefinition: StructureDefinition;
233
264
  isAbstract: boolean;
265
+ /** the description this type was reached through; carried so nothing has to find it again */
266
+ dataTypeDescription: IDataTypeDescription;
234
267
  }
235
268
  type DataTypeDefinitions = IDataTypeDefInfo[];
236
269
 
@@ -283,19 +316,22 @@ async function _extractDataTypeDictionaryFromDefinition(
283
316
  assert(dataTypeManager, "expecting a dataTypeManager");
284
317
 
285
318
  const dataTypeDescriptions = await _getDataTypeDescriptions(session, dataTypeDictionaryNodeId);
286
- const dataTypeNodeIds = await _enrichWithDescriptionOf(session, dataTypeDescriptions);
319
+ const dataTypeAndDescriptions = await _enrichWithDescriptionOf(session, dataTypeDescriptions);
287
320
 
288
- // now read DataTypeDefinition attributes of all the dataTypeNodeIds, this will only contains concrete structure
289
- const nodesToRead: ReadValueIdOptions[] = dataTypeNodeIds.map((nodeId: NodeId) => ({
321
+ // now read DataTypeDefinition attributes of all the dataTypes, this will only contains concrete structure
322
+ const nodesToRead: ReadValueIdOptions[] = dataTypeAndDescriptions.map(({ dataTypeNodeId }) => ({
290
323
  attributeId: AttributeIds.DataTypeDefinition,
291
- nodeId
324
+ nodeId: dataTypeNodeId
292
325
  }));
293
326
 
294
327
  const cache: { [key: string]: CacheForFieldResolution } = {};
295
328
  const dataValuesWithDataTypeDefinition = nodesToRead.length > 0 ? await session.read(nodesToRead) : [];
296
329
 
297
- // in some circumstances like Euromap, this assert fails:
298
- // assert(dataValuesWithDataTypeDefinition.length === dataTypeDescriptions.length);
330
+ // The commented-out assert here compared against dataTypeDescriptions.length and
331
+ // was reported to fail on nodesets such as Euromap. It was right to fail: the two
332
+ // lists are not the same length, because abstract types are skipped. The read is
333
+ // driven by dataTypeAndDescriptions, so this is the invariant that does hold.
334
+ assert(dataValuesWithDataTypeDefinition.length === dataTypeAndDescriptions.length);
299
335
 
300
336
  const dataTypeDefinitions: DataTypeDefinitions = [];
301
337
 
@@ -303,31 +339,39 @@ async function _extractDataTypeDictionaryFromDefinition(
303
339
 
304
340
  const promise: Promise<void>[] = [];
305
341
  for (const dataValue of dataValuesWithDataTypeDefinition) {
306
- const dataTypeNodeId = dataTypeNodeIds[index];
307
- const dataTypeDescription = dataTypeDescriptions[index];
308
-
342
+ const { dataTypeNodeId, dataTypeDescription } = dataTypeAndDescriptions[index];
309
343
 
310
344
  if (dataValue.statusCode.isGood()) {
311
345
  const dataTypeDefinition = dataValue.value.value;
312
346
 
313
347
  if (dataTypeDefinition && dataTypeDefinition instanceof StructureDefinition) {
314
- const className = dataTypeDescription.browseName.name!;
348
+ if (!dataTypeDescription.browseName.name) {
349
+ throw new Error(`Unexpected: BrowseName has no name for nodeId ${dataTypeNodeId.toString()}`);
350
+ }
351
+ const className = dataTypeDescription.browseName.name;
315
352
  promise.push(
316
353
  (async () => {
317
354
  const isAbstract = await readIsAbstract(session, dataTypeNodeId);
318
- dataTypeDefinitions.push({ className, dataTypeNodeId, dataTypeDefinition, isAbstract });
355
+ dataTypeDefinitions.push({
356
+ className,
357
+ dataTypeNodeId,
358
+ dataTypeDefinition,
359
+ isAbstract,
360
+ dataTypeDescription
361
+ });
319
362
  })()
320
363
  );
321
364
  }
322
- }
323
- /* c8 ignore next */
324
- else {
325
- debugLog(
326
- "dataTypeNodeId ",
327
- dataTypeNodeId.toString(),
328
- " has no DataTypeDescription attribute",
329
- dataValue.statusCode.toString()
330
- );
365
+ } else {
366
+ /* c8 ignore next */
367
+ // c8 ignore next
368
+ doDebug &&
369
+ debugLog(
370
+ "dataTypeNodeId ",
371
+ dataTypeNodeId.toString(),
372
+ " has no DataTypeDescription attribute",
373
+ dataValue.statusCode.toString()
374
+ );
331
375
  }
332
376
  index++;
333
377
  }
@@ -337,15 +381,14 @@ async function _extractDataTypeDictionaryFromDefinition(
337
381
  const dataTypeDefinitionsSorted = sortStructure(dataTypeDefinitions);
338
382
  // c8 ignore next
339
383
  if (doDebug) {
340
- debugLog("order ", dataTypeDefinitionsSorted.map((a) => a.className + " " + a.dataTypeNodeId).join(" -> "));
384
+ debugLog("order ", dataTypeDefinitionsSorted.map((a) => `${a.className} ${a.dataTypeNodeId}`).join(" -> "));
341
385
  }
342
386
 
343
387
  const promises2: Promise<void>[] = [];
344
388
 
345
- for (const { className, dataTypeNodeId, dataTypeDefinition, isAbstract } of dataTypeDefinitionsSorted) {
389
+ for (const { className, dataTypeNodeId, dataTypeDefinition, isAbstract, dataTypeDescription } of dataTypeDefinitionsSorted) {
346
390
  promises2.push(
347
391
  (async () => {
348
-
349
392
  const dataTypeFactory = dataTypeManager.getDataTypeFactoryForNamespace(dataTypeNodeId.namespace);
350
393
  // c8 ignore next
351
394
  if (doDebug) {
@@ -356,16 +399,22 @@ async function _extractDataTypeDictionaryFromDefinition(
356
399
  }
357
400
  // now fill typeDictionary
358
401
  try {
359
- const dataTypeDescription = dataTypeDescriptions.find((a) => a.nodeId.toString() === dataTypeNodeId.toString());
402
+ // Previously this searched dataTypeDescriptions for one whose nodeId
403
+ // equalled dataTypeNodeId - comparing a description node against a
404
+ // DataType node, which only ever matched by accident. The description
405
+ // now travels with the type it belongs to.
360
406
  if (!dataTypeDefinition) {
361
- throw new Error("cannot find dataTypeDefinition for " + dataTypeNodeId.toString());
407
+ throw new Error(`cannot find dataTypeDefinition for ${dataTypeNodeId.toString()}`);
408
+ }
409
+ if (!dataTypeDescription) {
410
+ throw new Error(`cannot find dataTypeDescription for ${dataTypeNodeId.toString()}`);
362
411
  }
363
412
  const schema = await convertDataTypeDefinitionToStructureTypeSchema(
364
413
  session,
365
414
  dataTypeNodeId,
366
415
  className,
367
416
  dataTypeDefinition,
368
- dataTypeDescription!, // for encodings
417
+ dataTypeDescription, // for encodings
369
418
  dataTypeManager,
370
419
  isAbstract,
371
420
  cache
@@ -393,7 +442,7 @@ async function _extractDataTypeDictionaryFromDefinition(
393
442
  }
394
443
  } catch (err) {
395
444
  errorLog("Constructor verification err: ", (<Error>err).message);
396
- errorLog("For this reason class " + className + " has not been registered");
445
+ errorLog(`For this reason class ${className} has not been registered`);
397
446
  errorLog(err);
398
447
  }
399
448
  })()
@@ -414,7 +463,10 @@ async function _extractNodeIds(
414
463
  await _enrichWithDescriptionOf(session, dataTypeDescriptions);
415
464
 
416
465
  for (const dataTypeDescription of dataTypeDescriptions) {
417
- map[dataTypeDescription.browseName.name!.toString()] = dataTypeDescription.encodings!;
466
+ if (!dataTypeDescription.browseName.name || !dataTypeDescription.encodings) {
467
+ continue;
468
+ }
469
+ map[dataTypeDescription.browseName.name.toString()] = dataTypeDescription.encodings;
418
470
  }
419
471
 
420
472
  return {
@@ -465,7 +517,7 @@ async function _extractDataTypeDictionary(
465
517
  // dataType definition in store directly in UADataType under the definition attribute
466
518
  const dataTypeFactory2 = dataTypeManager.getDataTypeFactory(dataTypeDictionaryNodeId.namespace);
467
519
  if (!dataTypeFactory2) {
468
- throw new Error("cannot find dataTypeFactory for namespace " + dataTypeDictionaryNodeId.namespace);
520
+ throw new Error(`cannot find dataTypeFactory for namespace ${dataTypeDictionaryNodeId.namespace}`);
469
521
  }
470
522
  await _extractDataTypeDictionaryFromDefinition(session, dataTypeDictionaryNodeId, dataTypeManager);
471
523
  } else {
@@ -525,7 +577,7 @@ async function _exploreDataTypeDefinition(
525
577
  const results2 = await browseAll(session, nodesToBrowse2);
526
578
 
527
579
  const binaryEncodingNodeIds = results2.map((br: BrowseResult) => {
528
- const defaultBin = br.references!.filter((r: ReferenceDescription) => r.browseName.toString() === "Default Binary");
580
+ const defaultBin = (br.references || []).filter((r: ReferenceDescription) => r.browseName.toString() === "Default Binary");
529
581
 
530
582
  /* c8 ignore next */
531
583
  if (defaultBin.length < 1) {
@@ -542,7 +594,10 @@ async function _exploreDataTypeDefinition(
542
594
  for (let i = 0; i < references.length; i++) {
543
595
  const ref = references[i];
544
596
  const binaryEncoding = binaryEncodingNodeIds[i];
545
- const name = ref.browseName!.name!.toString();
597
+ const name = ref.browseName?.name?.toString();
598
+ if (!name) {
599
+ continue;
600
+ }
546
601
  debugLog(" type ", name.padEnd(30, " "), binaryEncoding.toString());
547
602
  // let's verify that constructor is operational
548
603
  try {
@@ -558,8 +613,8 @@ async function _exploreDataTypeDefinition(
558
613
  const testObject = new Constructor();
559
614
  debugLog(testObject.toString());
560
615
  } catch (err) {
561
- debugLog(" Error cannot construct Extension Object " + name);
562
- debugLog(" " + (<Error>err).message);
616
+ debugLog(` Error cannot construct Extension Object ${name}`);
617
+ debugLog(` ${(<Error>err).message}`);
563
618
  }
564
619
  }
565
620
  }
@@ -594,7 +649,8 @@ export async function populateDataTypeManager103(
594
649
  session: IBasicSessionAsync2,
595
650
  dataTypeManager: ExtraDataTypeManager
596
651
  ): Promise<void> {
597
- debugLog("in ... populateDataTypeManager");
652
+ // c8 ignore next
653
+ doDebug && debugLog("in ... populateDataTypeManager");
598
654
 
599
655
  // read namespace array
600
656
  const dataValueNamespaceArray = await session.read({
@@ -606,14 +662,15 @@ export async function populateDataTypeManager103(
606
662
 
607
663
  // c8 ignore next
608
664
  if (!namespaceArray) {
609
- debugLog("session: cannot read Server_NamespaceArray");
665
+ // c8 ignore next
666
+ doDebug && debugLog("session: cannot read Server_NamespaceArray");
610
667
  // throw new Error("Cannot get Server_NamespaceArray as a array of string");
611
668
  return;
612
669
  }
613
670
 
614
671
  // c8 ignore next
615
672
  if (doDebug) {
616
- debugLog("namespaceArray ", namespaceArray.map((a, index) => " " + index.toString().padEnd(3) + ":" + a).join(" "));
673
+ debugLog("namespaceArray ", namespaceArray.map((a, index) => ` ${index.toString().padEnd(3)}:${a}`).join(" "));
617
674
  }
618
675
 
619
676
  if (dataValueNamespaceArray.statusCode.isGood() && namespaceArray && namespaceArray.length > 0) {
@@ -653,17 +710,18 @@ export async function populateDataTypeManager103(
653
710
  // c8 ignore next
654
711
  if (doDebug) {
655
712
  debugLog(result.statusCode.toString());
656
- debugLog(result.references?.map((r: any) => r.browseName?.toString()).join(" "));
713
+ debugLog(result.references?.map((r) => r.browseName?.toString()).join(" "));
657
714
  }
658
715
 
659
716
  // filter nodes that have the expected namespace Index
660
717
  // ( more specifically we want to filter out DataStructure from namespace 0)
661
718
  // we also want to keep only object of type DataTypeDictionaryType
662
- const references = result.references!.filter(
719
+ const references = (result.references || []).filter(
663
720
  (e: ReferenceDescription) => e.nodeId.namespace !== 0 && sameNodeId(e.typeDefinition, dataTypeDictionaryType)
664
721
  );
665
722
 
666
- debugLog(`found ${references.length} dictionaries`);
723
+ // c8 ignore next
724
+ doDebug && debugLog(`found ${references.length} dictionaries`);
667
725
 
668
726
  async function putInCorrectOrder(): Promise<TypeDictionaryInfo[]> {
669
727
  const infos: TypeDictionaryInfo[] = [];
@@ -673,11 +731,11 @@ export async function populateDataTypeManager103(
673
731
  const dataTypeDictionaryNodeId = reference.nodeId;
674
732
 
675
733
  const promises: [Promise<boolean>, Promise<DataValue>] = [
676
- /* isDictionaryDeprecated: bool = await */ _readDeprecatedFlag(session, dataTypeDictionaryNodeId),
677
- /* rawSchemaDataValue!: DataValue = await */ session.read({
678
- attributeId: AttributeIds.Value,
679
- nodeId: dataTypeDictionaryNodeId
680
- })
734
+ /* isDictionaryDeprecated: bool = await */ _readDeprecatedFlag(session, dataTypeDictionaryNodeId),
735
+ /* rawSchemaDataValue!: DataValue = await */ session.read({
736
+ attributeId: AttributeIds.Value,
737
+ nodeId: dataTypeDictionaryNodeId
738
+ })
681
739
  ];
682
740
 
683
741
  const [isDictionaryDeprecated, rawSchemaDataValue] = await Promise.all(promises);
@@ -721,17 +779,20 @@ export async function populateDataTypeManager103(
721
779
  if (r) {
722
780
  const { xmlns, namespace } = r;
723
781
  nsKeyNamespace[xmlns] = namespace;
724
- debugLog("xxxx ns= ", xmlns, "=>", namespace);
782
+ // c8 ignore next
783
+ doDebug && debugLog("xxxx ns= ", xmlns, "=>", namespace);
725
784
  }
726
785
  }
727
786
  info.dependencies = nsKeyNamespace;
728
- debugLog("xxx targetNamespace = ", info.targetNamespace);
787
+ // c8 ignore next
788
+ doDebug && debugLog("xxx targetNamespace = ", info.targetNamespace);
729
789
  innerMap[info.targetNamespace] = info;
730
790
  }
731
791
  } else {
732
792
  // may be 1.04 => the rawSchema is no more needed in new version
733
793
  info.targetNamespace = namespaceArray[dataTypeDictionaryNodeId.namespace];
734
- debugLog("xxx targetNamespace = ", info.targetNamespace);
794
+ // c8 ignore next
795
+ doDebug && debugLog("xxx targetNamespace = ", info.targetNamespace);
735
796
  innerMap[info.targetNamespace] = info;
736
797
  }
737
798
  // assert(info.targetNamespace.length !== 0);
@@ -741,13 +802,13 @@ export async function populateDataTypeManager103(
741
802
 
742
803
  // ----------------------------------
743
804
  const orderedList: TypeDictionaryInfo[] = [];
744
- const visited: any = {};
805
+ const visited: Record<string, number> = {};
745
806
  function explore(d: TypeDictionaryInfo): void {
746
807
  if (visited[d.targetNamespace]) {
747
808
  return;
748
809
  }
749
810
  visited[d.targetNamespace] = 1;
750
- for (const [xmlns, namespace] of Object.entries(d.dependencies)) {
811
+ for (const [_xmlns, namespace] of Object.entries(d.dependencies)) {
751
812
  if (!innerMap[namespace] || namespace === d.targetNamespace) {
752
813
  continue;
753
814
  }
@@ -759,7 +820,8 @@ export async function populateDataTypeManager103(
759
820
  explore(d);
760
821
  }
761
822
 
762
- debugLog(" Ordered List = ", orderedList.map((a) => a.targetNamespace).join(" "));
823
+ // c8 ignore next
824
+ doDebug && debugLog(" Ordered List = ", orderedList.map((a) => a.targetNamespace).join(" "));
763
825
 
764
826
  return orderedList;
765
827
  }
@@ -811,8 +873,8 @@ export async function populateDataTypeManager103(
811
873
  const set = new Set<DataTypeFactory>();
812
874
  set.add(getStandardDataTypeFactory());
813
875
 
814
- var visited: Set<string> = new Set();
815
- function explore(d: TypeDictionaryInfo): void {
876
+ const visited: Set<string> = new Set();
877
+ const explore = (d: TypeDictionaryInfo): void => {
816
878
  if (visited.has(d.targetNamespace)) {
817
879
  return;
818
880
  }
@@ -825,10 +887,10 @@ export async function populateDataTypeManager103(
825
887
  if (namespaceUri === d.targetNamespace) {
826
888
  continue;
827
889
  }
828
- var index = namespaceArray.indexOf(namespaceUri);
829
- if (index == -1) continue;
890
+ const index = namespaceArray.indexOf(namespaceUri);
891
+ if (index === -1) continue;
830
892
 
831
- var dd = dataTypeManager.getDataTypeFactory(index);
893
+ const dd = dataTypeManager.getDataTypeFactory(index);
832
894
  set.add(dd);
833
895
 
834
896
  const base = map[namespaceUri];
@@ -836,7 +898,7 @@ export async function populateDataTypeManager103(
836
898
  explore(base);
837
899
  }
838
900
  }
839
- }
901
+ };
840
902
  explore(d);
841
903
  const baseDataFactories = Array.from(set);
842
904
  const dataTypeFactory = dataTypeManager.getDataTypeFactory(d.dataTypeDictionaryNodeId.namespace);
@@ -848,7 +910,8 @@ export async function populateDataTypeManager103(
848
910
 
849
911
  // now investigate DataTypeDescriptionType
850
912
  async function processReferenceOnDataTypeDictionaryType(d: TypeDictionaryInfo): Promise<void> {
851
- debugLog(chalk.cyan("processReferenceOnDataTypeDictionaryType on "), d.targetNamespace);
913
+ // c8 ignore next
914
+ doDebug && debugLog(chalk.cyan("processReferenceOnDataTypeDictionaryType on "), d.targetNamespace);
852
915
  const ref = d.reference;
853
916
  const dataTypeDictionaryNodeId = d.reference.nodeId;
854
917
 
@@ -872,8 +935,8 @@ export async function populateDataTypeManager103(
872
935
  }
873
936
  }
874
937
 
875
-
876
938
  // https://medium.com/swlh/dealing-with-multiple-promises-in-javascript-41d6c21f20ff
939
+ // biome-ignore lint/correctness/noConstantCondition: deliberate debug on/off toggle, not dead code
877
940
  if (false) {
878
941
  // we need to read sequentially the dataTypeDictionaryInfo
879
942
  // to esnsure that dependencies are resolved in the correct order
@@ -897,11 +960,10 @@ export async function populateDataTypeManager103(
897
960
  s = s.substring(0, s.length - 1);
898
961
  }
899
962
  return s;
900
- }
963
+ };
901
964
  // check if all dependencies have been processed for this dataTypeDictionary
902
965
  const allDependenciesAlreadyProcessed = (typeDictionaryInfo: TypeDictionaryInfo) => {
903
-
904
- for (const [key, namespace1] of Object.entries(typeDictionaryInfo.dependencies)) {
966
+ for (const [_key, namespace1] of Object.entries(typeDictionaryInfo.dependencies)) {
905
967
  // codesys may add quotes around the namespace
906
968
  const namespace = unquote(namespace1);
907
969
  if (typeDictionaryInfo.targetNamespace === namespace) {
@@ -913,11 +975,11 @@ export async function populateDataTypeManager103(
913
975
  }
914
976
  }
915
977
  return true;
916
- }
978
+ };
917
979
 
918
980
  const queue: TypeDictionaryInfo[] = [...dataTypeDictionaryInfo];
919
981
 
920
- // we load typeDictionary in parallel by processing all
982
+ // we load typeDictionary in parallel by processing all
921
983
  // typeDictionary that have all their dependencies resolved
922
984
  const extractIndependantTypeInfo = (queue: TypeDictionaryInfo[]): TypeDictionaryInfo[] => {
923
985
  const toProcess = queue.splice(0);
@@ -932,7 +994,7 @@ export async function populateDataTypeManager103(
932
994
  }
933
995
  }
934
996
  return result;
935
- }
997
+ };
936
998
  const processFunc = async (typeDictionaryInfo: TypeDictionaryInfo) => {
937
999
  try {
938
1000
  doDebug && debugLog("processing ", typeDictionaryInfo.targetNamespace);
@@ -941,9 +1003,8 @@ export async function populateDataTypeManager103(
941
1003
  errorLog("Error in processReferenceOnDataTypeDictionaryType", err);
942
1004
  }
943
1005
  alreadyProcessed.add(unquote(typeDictionaryInfo.targetNamespace));
944
- }
1006
+ };
945
1007
  while (queue.length > 0) {
946
-
947
1008
  // c8 ignore next
948
1009
  if (doDebug) {
949
1010
  for (const d of queue) {
@@ -959,10 +1020,10 @@ export async function populateDataTypeManager103(
959
1020
  errorLog("Cannot process any more dataTypeDictionary");
960
1021
  break;
961
1022
  }
962
- const promises: Promise<void>[] =
963
- readyToProcess.map((typeDictionaryInfo) => processFunc(typeDictionaryInfo));
1023
+ const promises: Promise<void>[] = readyToProcess.map((typeDictionaryInfo) => processFunc(typeDictionaryInfo));
964
1024
  await Promise.all(promises);
965
1025
  }
966
1026
  }
967
- debugLog("out ... populateDataTypeManager103");
1027
+ // c8 ignore next
1028
+ doDebug && debugLog("out ... populateDataTypeManager103");
968
1029
  }