node-opcua-client-dynamic-extension-object 2.56.2 → 2.61.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.
- package/LICENSE +20 -20
- package/dist/convert_data_type_definition_to_structuretype_schema.js +51 -40
- package/dist/convert_data_type_definition_to_structuretype_schema.js.map +1 -1
- package/dist/private/find_encodings.js +3 -3
- package/dist/private/find_encodings.js.map +1 -1
- package/dist/private/populate_data_type_manager_103.js +6 -2
- package/dist/private/populate_data_type_manager_103.js.map +1 -1
- package/package.json +14 -14
- package/source/convert_data_type_definition_to_structuretype_schema.ts +83 -56
- package/source/private/find_encodings.ts +3 -4
- package/source/private/populate_data_type_manager_103.ts +7 -3
- package/dist/client_dynamic_extension_object.d.ts +0 -25
- package/dist/client_dynamic_extension_object.js +0 -1064
- package/dist/client_dynamic_extension_object.js.map +0 -1
|
@@ -1,1064 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.getExtensionObjectConstructor = exports.extractNamespaceDataType = exports.convertDataTypeDefinitionToStructureTypeSchema = exports.getDataTypeDefinition = exports.populateDataTypeManager = void 0;
|
|
13
|
-
// tslint:disable: no-console
|
|
14
|
-
/**
|
|
15
|
-
* @module node-opcua-client-dynamic-extension-object
|
|
16
|
-
*/
|
|
17
|
-
const chalk = require("chalk");
|
|
18
|
-
const PrettyError = require("pretty-error");
|
|
19
|
-
const pe = new PrettyError();
|
|
20
|
-
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
21
|
-
const node_opcua_data_model_1 = require("node-opcua-data-model");
|
|
22
|
-
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
23
|
-
const node_opcua_factory_1 = require("node-opcua-factory");
|
|
24
|
-
const node_opcua_nodeid_1 = require("node-opcua-nodeid");
|
|
25
|
-
const node_opcua_pseudo_session_1 = require("node-opcua-pseudo-session");
|
|
26
|
-
const node_opcua_schemas_1 = require("node-opcua-schemas");
|
|
27
|
-
const node_opcua_service_browse_1 = require("node-opcua-service-browse");
|
|
28
|
-
const node_opcua_service_translate_browse_path_1 = require("node-opcua-service-translate-browse-path");
|
|
29
|
-
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
30
|
-
const node_opcua_types_1 = require("node-opcua-types");
|
|
31
|
-
const extra_data_type_manager_1 = require("./extra_data_type_manager");
|
|
32
|
-
const doDebug = node_opcua_debug_1.checkDebugFlag(__filename);
|
|
33
|
-
const debugLog = node_opcua_debug_1.make_debugLog(__filename);
|
|
34
|
-
const errorLog = node_opcua_debug_1.make_errorLog(__filename);
|
|
35
|
-
function _readDeprecatedFlag(session, dataTypeDictionary) {
|
|
36
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
const browsePath = node_opcua_service_translate_browse_path_1.makeBrowsePath(dataTypeDictionary, ".Deprecated");
|
|
38
|
-
const a = yield session.translateBrowsePath(browsePath);
|
|
39
|
-
/* istanbul ignore next */
|
|
40
|
-
if (!a.targets || a.targets.length === 0) {
|
|
41
|
-
// the server is probably version < 1.04.
|
|
42
|
-
debugLog("Cannot find Deprecated property for dataTypeDictionary " + dataTypeDictionary.toString());
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
const deprecatedFlagNodeId = a.targets[0].targetId;
|
|
46
|
-
const dataValue = yield session.read({ nodeId: deprecatedFlagNodeId, attributeId: node_opcua_data_model_1.AttributeIds.Value });
|
|
47
|
-
return dataValue.value.value;
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
function _readNamespaceUriProperty(session, dataTypeDictionary) {
|
|
51
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
-
const a = yield session.translateBrowsePath(node_opcua_service_translate_browse_path_1.makeBrowsePath(dataTypeDictionary, ".NamespaceUri"));
|
|
53
|
-
/* istanbul ignore next */
|
|
54
|
-
if (!a.targets || a.targets.length === 0) {
|
|
55
|
-
return "??dataTypeDictionary doesn't expose NamespaceUri property??";
|
|
56
|
-
}
|
|
57
|
-
const namespaceUriProp = a.targets[0].targetId;
|
|
58
|
-
const dataValue = yield session.read({ nodeId: namespaceUriProp, attributeId: node_opcua_data_model_1.AttributeIds.Value });
|
|
59
|
-
return dataValue.value.value || "<not set>";
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
function _getDataTypeDescriptions(session, dataTypeDictionaryNodeId) {
|
|
63
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
const nodeToBrowse2 = {
|
|
65
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
|
|
66
|
-
includeSubtypes: false,
|
|
67
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Variable"),
|
|
68
|
-
nodeId: dataTypeDictionaryNodeId,
|
|
69
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasComponent"),
|
|
70
|
-
// resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
|
|
71
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId | BrowseName")
|
|
72
|
-
};
|
|
73
|
-
const result2 = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse2);
|
|
74
|
-
result2.references = result2.references || [];
|
|
75
|
-
return result2.references.map((r) => ({ nodeId: r.nodeId, browseName: r.browseName }));
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
function _enrichWithDescriptionOf(session, dataTypeDescriptions) {
|
|
79
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
-
const nodesToBrowse3 = [];
|
|
81
|
-
for (const ref of dataTypeDescriptions) {
|
|
82
|
-
ref.browseName.toString();
|
|
83
|
-
nodesToBrowse3.push({
|
|
84
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
|
|
85
|
-
includeSubtypes: false,
|
|
86
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Object"),
|
|
87
|
-
nodeId: ref.nodeId.toString(),
|
|
88
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasDescription"),
|
|
89
|
-
// resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
|
|
90
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId")
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
/* istanbul ignore next */
|
|
94
|
-
if (nodesToBrowse3.length === 0) {
|
|
95
|
-
return [];
|
|
96
|
-
}
|
|
97
|
-
const results3 = yield node_opcua_pseudo_session_1.browseAll(session, nodesToBrowse3);
|
|
98
|
-
const binaryEncodings = [];
|
|
99
|
-
const nodesToBrowseDataType = [];
|
|
100
|
-
let i = 0;
|
|
101
|
-
for (const result3 of results3) {
|
|
102
|
-
const dataTypeDescription = dataTypeDescriptions[i++];
|
|
103
|
-
result3.references = result3.references || [];
|
|
104
|
-
node_opcua_assert_1.assert(result3.references.length === 1);
|
|
105
|
-
for (const ref of result3.references) {
|
|
106
|
-
const binaryEncodingNodeId = ref.nodeId;
|
|
107
|
-
dataTypeDescription.encodings = dataTypeDescription.encodings || {
|
|
108
|
-
binaryEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
|
|
109
|
-
dataTypeNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
|
|
110
|
-
jsonEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
|
|
111
|
-
xmlEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId
|
|
112
|
-
};
|
|
113
|
-
dataTypeDescription.encodings.binaryEncodingNodeId = binaryEncodingNodeId;
|
|
114
|
-
binaryEncodings.push(binaryEncodingNodeId);
|
|
115
|
-
nodesToBrowseDataType.push({
|
|
116
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
|
|
117
|
-
includeSubtypes: false,
|
|
118
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("DataType"),
|
|
119
|
-
nodeId: ref.nodeId.toString(),
|
|
120
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasEncoding"),
|
|
121
|
-
// resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
|
|
122
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId | BrowseName")
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
const dataTypeNodeIds = [];
|
|
127
|
-
if (nodesToBrowseDataType.length > 0) {
|
|
128
|
-
const results4 = yield node_opcua_pseudo_session_1.browseAll(session, nodesToBrowseDataType);
|
|
129
|
-
i = 0;
|
|
130
|
-
for (const result4 of results4) {
|
|
131
|
-
result4.references = result4.references || [];
|
|
132
|
-
/* istanbul ignore next */
|
|
133
|
-
if (result4.references.length !== 1) {
|
|
134
|
-
console.log("What's going on ?", result4.toString());
|
|
135
|
-
}
|
|
136
|
-
for (const ref of result4.references) {
|
|
137
|
-
const dataTypeNodeId = ref.nodeId;
|
|
138
|
-
dataTypeNodeIds.push(dataTypeNodeId);
|
|
139
|
-
const dataTypeDescription = dataTypeDescriptions[i++];
|
|
140
|
-
dataTypeDescription.encodings.dataTypeNodeId = dataTypeNodeId;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return dataTypeNodeIds;
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
function _findEncodings(session, dataTypeNodeId) {
|
|
148
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
149
|
-
const nodeToBrowse = {
|
|
150
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
|
|
151
|
-
includeSubtypes: true,
|
|
152
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Object"),
|
|
153
|
-
nodeId: dataTypeNodeId,
|
|
154
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasEncoding"),
|
|
155
|
-
resultMask: node_opcua_data_model_1.makeResultMask("ReferenceType | IsForward | BrowseName | NodeClass | TypeDefinition")
|
|
156
|
-
};
|
|
157
|
-
const result = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse);
|
|
158
|
-
const references = result.references || [];
|
|
159
|
-
if (references.length === 0) {
|
|
160
|
-
// xx throw new Error("Cannot find encodings on type " + dataTypeNodeId.toString() + " statusCode " + result.statusCode.toString());
|
|
161
|
-
}
|
|
162
|
-
const encodings = {
|
|
163
|
-
dataTypeNodeId,
|
|
164
|
-
binaryEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
|
|
165
|
-
jsonEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
|
|
166
|
-
xmlEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId
|
|
167
|
-
};
|
|
168
|
-
for (const ref of references) {
|
|
169
|
-
switch (ref.browseName.name) {
|
|
170
|
-
case "Default Binary":
|
|
171
|
-
encodings.binaryEncodingNodeId = ref.nodeId;
|
|
172
|
-
break;
|
|
173
|
-
case "Default XML":
|
|
174
|
-
encodings.xmlEncodingNodeId = ref.nodeId;
|
|
175
|
-
break;
|
|
176
|
-
case "Default JSON":
|
|
177
|
-
encodings.jsonEncodingNodeId = ref.nodeId;
|
|
178
|
-
break;
|
|
179
|
-
default:
|
|
180
|
-
console.log(" ignoring encoding ", ref.browseName.toString());
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return encodings;
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
function sortStructure(dataTypeDefinitions) {
|
|
187
|
-
const dataTypeDefinitionsSorted = [];
|
|
188
|
-
const _visited = {};
|
|
189
|
-
const _map = {};
|
|
190
|
-
for (const d of dataTypeDefinitions) {
|
|
191
|
-
_map[d.dataTypeNodeId.toString()] = d;
|
|
192
|
-
}
|
|
193
|
-
function _visit(d) {
|
|
194
|
-
const hash = d.dataTypeNodeId.toString();
|
|
195
|
-
if (_visited[hash]) {
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const bbb = _map[d.dataTypeDefinition.baseDataType.toString()];
|
|
199
|
-
if (bbb) {
|
|
200
|
-
_visit(bbb);
|
|
201
|
-
}
|
|
202
|
-
for (const f of d.dataTypeDefinition.fields || []) {
|
|
203
|
-
const ddd = _map[f.dataType.toString()];
|
|
204
|
-
if (!ddd) {
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
_visit(ddd);
|
|
208
|
-
}
|
|
209
|
-
_visited[hash] = d;
|
|
210
|
-
dataTypeDefinitionsSorted.push(d);
|
|
211
|
-
}
|
|
212
|
-
for (const d of dataTypeDefinitions) {
|
|
213
|
-
_visit(d);
|
|
214
|
-
}
|
|
215
|
-
return dataTypeDefinitionsSorted;
|
|
216
|
-
}
|
|
217
|
-
function _extractDataTypeDictionaryFromDefinition(session, dataTypeDictionaryNodeId, dataTypeFactory) {
|
|
218
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
219
|
-
node_opcua_assert_1.assert(dataTypeFactory, "expecting a dataTypeFactory");
|
|
220
|
-
const dataTypeDescriptions = yield _getDataTypeDescriptions(session, dataTypeDictionaryNodeId);
|
|
221
|
-
const dataTypeNodeIds = yield _enrichWithDescriptionOf(session, dataTypeDescriptions);
|
|
222
|
-
// now read DataTypeDefinition attributes of all the dataTypeNodeIds, this will only contains concrete structure
|
|
223
|
-
const nodesToRead = dataTypeNodeIds.map((nodeId) => ({
|
|
224
|
-
attributeId: node_opcua_data_model_1.AttributeIds.DataTypeDefinition,
|
|
225
|
-
nodeId
|
|
226
|
-
}));
|
|
227
|
-
const cache = {};
|
|
228
|
-
const dataValuesWithDataTypeDefinition = nodesToRead.length > 0 ? yield session.read(nodesToRead) : [];
|
|
229
|
-
// in some circumstances like Euromap, this assert fails:
|
|
230
|
-
// assert(dataValuesWithDataTypeDefinition.length === dataTypeDescriptions.length);
|
|
231
|
-
const dataTypeDefinitions = [];
|
|
232
|
-
let index = 0;
|
|
233
|
-
for (const dataValue of dataValuesWithDataTypeDefinition) {
|
|
234
|
-
const dataTypeNodeId = dataTypeNodeIds[index];
|
|
235
|
-
const dataTypeDescription = dataTypeDescriptions[index];
|
|
236
|
-
/* istanbul ignore else */
|
|
237
|
-
if (dataValue.statusCode === node_opcua_status_code_1.StatusCodes.Good) {
|
|
238
|
-
const dataTypeDefinition = dataValue.value.value;
|
|
239
|
-
if (dataTypeDefinition && dataTypeDefinition instanceof node_opcua_types_1.StructureDefinition) {
|
|
240
|
-
const className = dataTypeDescription.browseName.name;
|
|
241
|
-
dataTypeDefinitions.push({ className, dataTypeNodeId, dataTypeDefinition });
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
debugLog("dataTypeNodeId ", dataTypeNodeId.toString(), " has no DataTypeDescription attribute", dataValue.statusCode.toString());
|
|
246
|
-
}
|
|
247
|
-
index++;
|
|
248
|
-
}
|
|
249
|
-
// to do put in logical order
|
|
250
|
-
const dataTypeDefinitionsSorted = sortStructure(dataTypeDefinitions);
|
|
251
|
-
if (doDebug) {
|
|
252
|
-
debugLog("order ", dataTypeDefinitionsSorted.map((a) => a.className + " " + a.dataTypeNodeId).join(" -> "));
|
|
253
|
-
}
|
|
254
|
-
for (const { className, dataTypeNodeId, dataTypeDefinition } of dataTypeDefinitionsSorted) {
|
|
255
|
-
// istanbul ignore next
|
|
256
|
-
if (doDebug) {
|
|
257
|
-
debugLog(chalk.yellow("--------------------------------------- "), className, dataTypeNodeId.toString());
|
|
258
|
-
}
|
|
259
|
-
if (dataTypeFactory.hasStructuredType(className)) {
|
|
260
|
-
continue; // this structure has already been seen
|
|
261
|
-
}
|
|
262
|
-
// now fill typeDictionary
|
|
263
|
-
try {
|
|
264
|
-
const schema = yield convertDataTypeDefinitionToStructureTypeSchema(session, dataTypeNodeId, className, dataTypeDefinition, dataTypeFactory, cache);
|
|
265
|
-
// istanbul ignore next
|
|
266
|
-
if (doDebug) {
|
|
267
|
-
debugLog(chalk.red("Registering "), chalk.cyan(className.padEnd(30, " ")), schema.dataTypeNodeId.toString());
|
|
268
|
-
}
|
|
269
|
-
const Constructor = node_opcua_schemas_1.createDynamicObjectConstructor(schema, dataTypeFactory);
|
|
270
|
-
node_opcua_assert_1.assert(Constructor.schema === schema);
|
|
271
|
-
}
|
|
272
|
-
catch (err) {
|
|
273
|
-
console.log("Constructor verification err: ", err.message);
|
|
274
|
-
console.log("For this reason class " + className + " has not been registered");
|
|
275
|
-
console.log(err);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
function _extractNodeIds(session, dataTypeDictionaryNodeId) {
|
|
281
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
282
|
-
const map = {};
|
|
283
|
-
const dataTypeDescriptions = yield _getDataTypeDescriptions(session, dataTypeDictionaryNodeId);
|
|
284
|
-
/* const dataTypeNodeIds = */
|
|
285
|
-
yield _enrichWithDescriptionOf(session, dataTypeDescriptions);
|
|
286
|
-
for (const dataTypeDescription of dataTypeDescriptions) {
|
|
287
|
-
map[dataTypeDescription.browseName.name.toString()] = dataTypeDescription.encodings;
|
|
288
|
-
}
|
|
289
|
-
return {
|
|
290
|
-
getDataTypeAndEncodingId(key) {
|
|
291
|
-
return map[key] || null;
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
function _extractDataTypeDictionary(session, d, dataTypeManager) {
|
|
297
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
298
|
-
const dataTypeDictionaryNodeId = d.reference.nodeId;
|
|
299
|
-
const isDictionaryDeprecated = d.isDictionaryDeprecated; // await _readDeprecatedFlag(session, dataTypeDictionaryNodeId);
|
|
300
|
-
const rawSchema = d.rawSchema; // DataValue = await session.read({ nodeId: dataTypeDictionaryNodeId, attributeId: AttributeIds.Value });
|
|
301
|
-
const name = yield session.read({ nodeId: dataTypeDictionaryNodeId, attributeId: node_opcua_data_model_1.AttributeIds.BrowseName });
|
|
302
|
-
const namespace = yield _readNamespaceUriProperty(session, dataTypeDictionaryNodeId);
|
|
303
|
-
if (isDictionaryDeprecated || rawSchema.length === 0) {
|
|
304
|
-
debugLog("DataTypeDictionary is deprecated or BSD schema stored in dataValue is null !", chalk.cyan(name.value.value.toString()), "namespace =", namespace);
|
|
305
|
-
debugLog("let's use the new way (1.04) and let's crawl all dataTypes exposed by this name space");
|
|
306
|
-
// dataType definition in store directly in UADataType under the $definition property
|
|
307
|
-
const dataTypeFactory2 = dataTypeManager.getDataTypeFactory(dataTypeDictionaryNodeId.namespace);
|
|
308
|
-
if (!dataTypeFactory2) {
|
|
309
|
-
throw new Error("cannot find dataTypeFactory for namespace " + dataTypeDictionaryNodeId.namespace);
|
|
310
|
-
}
|
|
311
|
-
yield _extractDataTypeDictionaryFromDefinition(session, dataTypeDictionaryNodeId, dataTypeFactory2);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
else {
|
|
315
|
-
debugLog(" ----- Using old method for extracting schema => with BSD files");
|
|
316
|
-
// old method ( until 1.03 )
|
|
317
|
-
// one need to read the schema file store in the dataTypeDictionary node and parse it !
|
|
318
|
-
/* istanbul ignore next */
|
|
319
|
-
if (doDebug) {
|
|
320
|
-
debugLog("---------------------------------------------");
|
|
321
|
-
debugLog(rawSchema.toString());
|
|
322
|
-
debugLog("---------------------------------------------");
|
|
323
|
-
}
|
|
324
|
-
const idProvider = yield _extractNodeIds(session, dataTypeDictionaryNodeId);
|
|
325
|
-
const dataTypeFactory1 = dataTypeManager.getDataTypeFactory(dataTypeDictionaryNodeId.namespace);
|
|
326
|
-
yield node_opcua_schemas_1.parseBinaryXSDAsync(rawSchema, idProvider, dataTypeFactory1);
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
function _exploreDataTypeDefinition(session, dataTypeDictionaryTypeNode, dataTypeFactory, namespaces) {
|
|
331
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
332
|
-
const nodeToBrowse = {
|
|
333
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
|
|
334
|
-
includeSubtypes: false,
|
|
335
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Variable"),
|
|
336
|
-
nodeId: dataTypeDictionaryTypeNode,
|
|
337
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasComponent"),
|
|
338
|
-
resultMask: node_opcua_data_model_1.makeResultMask("ReferenceType | IsForward | BrowseName | NodeClass | TypeDefinition")
|
|
339
|
-
};
|
|
340
|
-
const result = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse);
|
|
341
|
-
const references = result.references || [];
|
|
342
|
-
/* istanbul ignore next */
|
|
343
|
-
if (references.length === 0) {
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
// request the Definition of each nodes
|
|
347
|
-
const nodesToBrowse2 = references.map((ref) => {
|
|
348
|
-
return {
|
|
349
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
|
|
350
|
-
includeSubtypes: false,
|
|
351
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Object | Variable"),
|
|
352
|
-
nodeId: ref.nodeId,
|
|
353
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasDescription"),
|
|
354
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
|
|
355
|
-
};
|
|
356
|
-
});
|
|
357
|
-
const results2 = yield node_opcua_pseudo_session_1.browseAll(session, nodesToBrowse2);
|
|
358
|
-
const binaryEncodingNodeIds = results2.map((br) => {
|
|
359
|
-
const defaultBin = br.references.filter((r) => r.browseName.toString() === "Default Binary");
|
|
360
|
-
/* istanbul ignore next */
|
|
361
|
-
if (defaultBin.length < 1) {
|
|
362
|
-
return node_opcua_nodeid_1.ExpandedNodeId;
|
|
363
|
-
}
|
|
364
|
-
return node_opcua_nodeid_1.ExpandedNodeId.fromNodeId(defaultBin[0].nodeId, namespaces[defaultBin[0].nodeId.namespace]);
|
|
365
|
-
});
|
|
366
|
-
// follow now Default Binary <= [Has Encoding] = [DataType]
|
|
367
|
-
/* istanbul ignore next */
|
|
368
|
-
if (doDebug) {
|
|
369
|
-
console.log(chalk.bgWhite.red("testing new constructors"));
|
|
370
|
-
for (let i = 0; i < references.length; i++) {
|
|
371
|
-
const ref = references[i];
|
|
372
|
-
const binaryEncoding = binaryEncodingNodeIds[i];
|
|
373
|
-
const name = ref.browseName.name.toString();
|
|
374
|
-
if (doDebug) {
|
|
375
|
-
debugLog(" type ", name.padEnd(30, " "), binaryEncoding.toString());
|
|
376
|
-
}
|
|
377
|
-
// let's verify that constructor is operational
|
|
378
|
-
try {
|
|
379
|
-
const constructor = dataTypeFactory.getStructureTypeConstructor(name);
|
|
380
|
-
// xx const constructor = getOrCreateConstructor(name, dataTypeFactory, defaultBinary);
|
|
381
|
-
const testObject = new constructor();
|
|
382
|
-
debugLog(testObject.toString());
|
|
383
|
-
}
|
|
384
|
-
catch (err) {
|
|
385
|
-
debugLog(" Error cannot construct Extension Object " + name);
|
|
386
|
-
debugLog(" " + err.message);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
const regexTargetNamespaceAttribute = /TargetNamespace="([^\"]+)"|TargetNamespace='([^\"]+)'/;
|
|
393
|
-
function extractTargetNamespaceAttribute(xmlElement) {
|
|
394
|
-
// warning TargetNamespace could have ' or " , Wago PLC for instance uses simple quotes
|
|
395
|
-
const c2 = xmlElement.match(regexTargetNamespaceAttribute);
|
|
396
|
-
if (c2) {
|
|
397
|
-
return c2[1] || c2[2];
|
|
398
|
-
}
|
|
399
|
-
return "";
|
|
400
|
-
}
|
|
401
|
-
const regexNamespaceRef = /xmlns:(.*)=(("([^"]+)")|('([^']+)'))/;
|
|
402
|
-
function extraNamespaceRef(attribute) {
|
|
403
|
-
const c = attribute.match(regexNamespaceRef);
|
|
404
|
-
if (c) {
|
|
405
|
-
const xmlns = c[1];
|
|
406
|
-
const namespace = c[3] || c[4];
|
|
407
|
-
return { xmlns, namespace };
|
|
408
|
-
}
|
|
409
|
-
return null;
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Extract all custom dataType
|
|
413
|
-
* @param session
|
|
414
|
-
* @param dataTypeManager
|
|
415
|
-
* @async
|
|
416
|
-
*/
|
|
417
|
-
function populateDataTypeManager(session, dataTypeManager) {
|
|
418
|
-
var _a;
|
|
419
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
420
|
-
debugLog("in ... populateDataTypeManager");
|
|
421
|
-
// read namespace array
|
|
422
|
-
const dataValueNamespaceArray = yield session.read({
|
|
423
|
-
attributeId: node_opcua_data_model_1.AttributeIds.Value,
|
|
424
|
-
nodeId: node_opcua_nodeid_1.resolveNodeId("Server_NamespaceArray")
|
|
425
|
-
});
|
|
426
|
-
const namespaceArray = dataValueNamespaceArray.value.value;
|
|
427
|
-
// istanbul ignore next
|
|
428
|
-
if (!namespaceArray) {
|
|
429
|
-
debugLog("session: cannot read Server_NamespaceArray");
|
|
430
|
-
// throw new Error("Cannot get Server_NamespaceArray as a array of string");
|
|
431
|
-
return;
|
|
432
|
-
}
|
|
433
|
-
// istanbul ignore next
|
|
434
|
-
if (doDebug) {
|
|
435
|
-
debugLog("namespaceArray ", namespaceArray.map((a, index) => " " + index.toString().padEnd(3) + ":" + a).join(" "));
|
|
436
|
-
}
|
|
437
|
-
if (dataValueNamespaceArray.statusCode === node_opcua_status_code_1.StatusCodes.Good && namespaceArray && namespaceArray.length > 0) {
|
|
438
|
-
dataTypeManager.setNamespaceArray(namespaceArray);
|
|
439
|
-
for (let namespaceIndex = 1; namespaceIndex < namespaceArray.length; namespaceIndex++) {
|
|
440
|
-
if (!dataTypeManager.hasDataTypeFactory(namespaceIndex)) {
|
|
441
|
-
const dataTypeFactory1 = new node_opcua_factory_1.DataTypeFactory([node_opcua_factory_1.getStandardDataTypeFactory()]);
|
|
442
|
-
dataTypeManager.registerDataTypeFactory(namespaceIndex, dataTypeFactory1);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
/// to do :: may be not useful
|
|
447
|
-
if (!dataValueNamespaceArray.value.value && dataTypeManager.namespaceArray.length === 0) {
|
|
448
|
-
dataTypeManager.setNamespaceArray([]);
|
|
449
|
-
}
|
|
450
|
-
const dataTypeDictionaryType = node_opcua_nodeid_1.resolveNodeId("DataTypeDictionaryType");
|
|
451
|
-
// DataType/OPCBinary => i=93 [OPCBinarySchema_TypeSystem]
|
|
452
|
-
// "OPC Binary"[DataSystemType]
|
|
453
|
-
const opcBinaryNodeId = node_opcua_nodeid_1.resolveNodeId("OPCBinarySchema_TypeSystem");
|
|
454
|
-
// let find all DataType dictionary node corresponding to a given namespace
|
|
455
|
-
// (have DataTypeDictionaryType)
|
|
456
|
-
const nodeToBrowse = {
|
|
457
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
|
|
458
|
-
includeSubtypes: false,
|
|
459
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Variable"),
|
|
460
|
-
nodeId: opcBinaryNodeId,
|
|
461
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasComponent"),
|
|
462
|
-
resultMask: node_opcua_data_model_1.makeResultMask("ReferenceType | IsForward | BrowseName | NodeClass | TypeDefinition")
|
|
463
|
-
};
|
|
464
|
-
const result = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse);
|
|
465
|
-
if (doDebug) {
|
|
466
|
-
debugLog(result.statusCode.toString());
|
|
467
|
-
debugLog((_a = result.references) === null || _a === void 0 ? void 0 : _a.map((r) => { var _a; return (_a = r.browseName) === null || _a === void 0 ? void 0 : _a.toString(); }).join(" "));
|
|
468
|
-
}
|
|
469
|
-
// filter nodes that have the expected namespace Index
|
|
470
|
-
// ( more specifically we want to filter out DataStructure from namespace 0)
|
|
471
|
-
// we also want to keep only object of type DataTypeDictionaryType
|
|
472
|
-
const references = result.references.filter((e) => e.nodeId.namespace !== 0 && node_opcua_nodeid_1.sameNodeId(e.typeDefinition, dataTypeDictionaryType));
|
|
473
|
-
debugLog(`found ${references.length} dictionary`);
|
|
474
|
-
function putInCorrectOrder() {
|
|
475
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
476
|
-
const infos = [];
|
|
477
|
-
const innerMap = {};
|
|
478
|
-
for (const reference of references) {
|
|
479
|
-
const dataTypeDictionaryNodeId = reference.nodeId;
|
|
480
|
-
const isDictionaryDeprecated = yield _readDeprecatedFlag(session, dataTypeDictionaryNodeId);
|
|
481
|
-
const rawSchemaDataValue = yield session.read({
|
|
482
|
-
attributeId: node_opcua_data_model_1.AttributeIds.Value,
|
|
483
|
-
nodeId: dataTypeDictionaryNodeId
|
|
484
|
-
});
|
|
485
|
-
const rawSchema = rawSchemaDataValue.value.value ? rawSchemaDataValue.value.value.toString() : "";
|
|
486
|
-
const info = {
|
|
487
|
-
dataTypeDictionaryNodeId,
|
|
488
|
-
dependencies: {},
|
|
489
|
-
isDictionaryDeprecated,
|
|
490
|
-
rawSchema,
|
|
491
|
-
reference,
|
|
492
|
-
targetNamespace: ""
|
|
493
|
-
};
|
|
494
|
-
infos.push(info);
|
|
495
|
-
if (!isDictionaryDeprecated && rawSchema.length > 0) {
|
|
496
|
-
if (doDebug) {
|
|
497
|
-
console.log("schema", rawSchema);
|
|
498
|
-
}
|
|
499
|
-
const matches = rawSchema.match(/<opc:TypeDictionary([^\>]+)>/);
|
|
500
|
-
if (matches) {
|
|
501
|
-
// extract xml:NS="namespace" from attribute list
|
|
502
|
-
// for instance:
|
|
503
|
-
// <opc:TypeDictionary
|
|
504
|
-
// xmlns:opc="http://opcfoundation.org/BinarySchema/"
|
|
505
|
-
// xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
506
|
-
// xmlns:ua="http://opcfoundation.org/UA/"
|
|
507
|
-
// xmlns:tns="urn:SomeName:Ua:Types:GlobalTypes"
|
|
508
|
-
// DefaultByteOrder="LittleEndian"
|
|
509
|
-
// TargetNamespace="urn:SomeName:Ua:Types:GlobalTypes">
|
|
510
|
-
const typeDictionaryElementAttributes = matches[1];
|
|
511
|
-
info.targetNamespace = extractTargetNamespaceAttribute(typeDictionaryElementAttributes);
|
|
512
|
-
const nsKeyNamespace = {};
|
|
513
|
-
for (const attribute of typeDictionaryElementAttributes.split(" ")) {
|
|
514
|
-
const r = extraNamespaceRef(attribute);
|
|
515
|
-
if (r) {
|
|
516
|
-
const { xmlns, namespace } = r;
|
|
517
|
-
nsKeyNamespace[xmlns] = namespace;
|
|
518
|
-
debugLog("xxxx ns= ", xmlns, "=>", namespace);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
info.dependencies = nsKeyNamespace;
|
|
522
|
-
debugLog("xxx targetNamespace = ", info.targetNamespace);
|
|
523
|
-
innerMap[info.targetNamespace] = info;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
else {
|
|
527
|
-
// may be 1.04 => the rawSchema is no more needed in new version
|
|
528
|
-
info.targetNamespace = namespaceArray[dataTypeDictionaryNodeId.namespace];
|
|
529
|
-
debugLog("xxx targetNamespace = ", info.targetNamespace);
|
|
530
|
-
innerMap[info.targetNamespace] = info;
|
|
531
|
-
}
|
|
532
|
-
// assert(info.targetNamespace.length !== 0);
|
|
533
|
-
}
|
|
534
|
-
// ----------------------------------
|
|
535
|
-
const orderedList = [];
|
|
536
|
-
const visited = {};
|
|
537
|
-
function explore(d) {
|
|
538
|
-
if (visited[d.targetNamespace]) {
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
visited[d.targetNamespace] = 1;
|
|
542
|
-
for (const [xmlns, namespace] of Object.entries(d.dependencies)) {
|
|
543
|
-
if (!innerMap[namespace] || namespace === d.targetNamespace) {
|
|
544
|
-
continue;
|
|
545
|
-
}
|
|
546
|
-
explore(innerMap[namespace]);
|
|
547
|
-
}
|
|
548
|
-
orderedList.push(d);
|
|
549
|
-
}
|
|
550
|
-
for (const d of infos) {
|
|
551
|
-
explore(d);
|
|
552
|
-
}
|
|
553
|
-
debugLog(" Ordered List = ", orderedList.map((a) => a.targetNamespace).join(" "));
|
|
554
|
-
return orderedList;
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
const dataTypeDictionaryInfo = yield putInCorrectOrder();
|
|
558
|
-
// setup dependencies
|
|
559
|
-
const map = {};
|
|
560
|
-
for (const d of dataTypeDictionaryInfo) {
|
|
561
|
-
map[d.targetNamespace] = d;
|
|
562
|
-
debugLog(" fixing based dataTypeFactory dependencies for ", d.targetNamespace, "index = ", d.dataTypeDictionaryNodeId.namespace);
|
|
563
|
-
const baseDataFactories = [node_opcua_factory_1.getStandardDataTypeFactory()];
|
|
564
|
-
for (const namespace of Object.values(d.dependencies)) {
|
|
565
|
-
if (namespace === d.targetNamespace) {
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
const baseDataFactory = map[namespace];
|
|
569
|
-
if (!baseDataFactory) {
|
|
570
|
-
// xx console.log("xxxxx baseDataFactory = ", namespace);
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
|
-
const namespaceIndex = baseDataFactory.dataTypeDictionaryNodeId.namespace;
|
|
574
|
-
if (dataTypeManager.hasDataTypeFactory(namespaceIndex)) {
|
|
575
|
-
const dep = dataTypeManager.getDataTypeFactory(namespaceIndex);
|
|
576
|
-
baseDataFactories.push(dep);
|
|
577
|
-
debugLog(" considering , ", baseDataFactory.targetNamespace, "index = ", baseDataFactory.dataTypeDictionaryNodeId.namespace);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
const dataTypeFactory = dataTypeManager.getDataTypeFactory(d.dataTypeDictionaryNodeId.namespace);
|
|
581
|
-
if (dataTypeFactory) {
|
|
582
|
-
dataTypeFactory.repairBaseDataFactories(baseDataFactories);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
// --------------------
|
|
586
|
-
// now investigate DataTypeDescriptionType
|
|
587
|
-
function processReferenceOnDataTypeDictionaryType(d) {
|
|
588
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
589
|
-
debugLog(chalk.cyan("processReferenceOnDataTypeDictionaryType on "), d.targetNamespace);
|
|
590
|
-
const ref = d.reference;
|
|
591
|
-
const dataTypeDictionaryNodeId = d.reference.nodeId;
|
|
592
|
-
yield _extractDataTypeDictionary(session, d, dataTypeManager);
|
|
593
|
-
/* istanbul ignore next */
|
|
594
|
-
if (doDebug) {
|
|
595
|
-
debugLog(chalk.bgWhite(" => "), ref.browseName.toString(), ref.nodeId.toString());
|
|
596
|
-
}
|
|
597
|
-
const dataTypeFactory = dataTypeManager.getDataTypeFactoryForNamespace(dataTypeDictionaryNodeId.namespace);
|
|
598
|
-
yield _exploreDataTypeDefinition(session, dataTypeDictionaryNodeId, dataTypeFactory, dataTypeManager.namespaceArray);
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
// https://medium.com/swlh/dealing-with-multiple-promises-in-javascript-41d6c21f20ff
|
|
602
|
-
for (const d of dataTypeDictionaryInfo) {
|
|
603
|
-
try {
|
|
604
|
-
yield processReferenceOnDataTypeDictionaryType(d).catch((e) => {
|
|
605
|
-
console.log(e);
|
|
606
|
-
debugLog("processReferenceOnDataTypeDictionaryType has failed ");
|
|
607
|
-
debugLog("Error", e.message);
|
|
608
|
-
debugLog(e);
|
|
609
|
-
return e;
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
catch (err) {
|
|
613
|
-
debugLog(chalk.red("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "), err);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
debugLog("out ... populateDataTypeManager");
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
exports.populateDataTypeManager = populateDataTypeManager;
|
|
620
|
-
function getHasEncodingDefaultBinary(session, dataTypeNodeId) {
|
|
621
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
622
|
-
const nodeToBrowse1 = {
|
|
623
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
|
|
624
|
-
includeSubtypes: false,
|
|
625
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Object"),
|
|
626
|
-
nodeId: dataTypeNodeId,
|
|
627
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasEncoding"),
|
|
628
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
|
|
629
|
-
};
|
|
630
|
-
const result1 = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse1);
|
|
631
|
-
if (result1.references && result1.references.length > 1) {
|
|
632
|
-
// we have more than one possible Encoding .... only keep "Default Binary"
|
|
633
|
-
result1.references = result1.references.filter((r) => r.browseName.toString() === "Default Binary");
|
|
634
|
-
}
|
|
635
|
-
/* istanbul ignore next */
|
|
636
|
-
if (!(result1.references && result1.references.length === 1)) {
|
|
637
|
-
// may be dataTypeNodeId is not a dataType,
|
|
638
|
-
// let's verify this.
|
|
639
|
-
const nodeClass = yield session.read({
|
|
640
|
-
attributeId: node_opcua_data_model_1.AttributeIds.NodeClass,
|
|
641
|
-
nodeId: dataTypeNodeId
|
|
642
|
-
});
|
|
643
|
-
const browseName = yield session.read({
|
|
644
|
-
attributeId: node_opcua_data_model_1.AttributeIds.BrowseName,
|
|
645
|
-
nodeId: dataTypeNodeId
|
|
646
|
-
});
|
|
647
|
-
// tslint:disable:no-console
|
|
648
|
-
console.log("node-id :", dataTypeNodeId ? dataTypeNodeId.toString() : null);
|
|
649
|
-
console.log("nodeClass :", node_opcua_data_model_1.NodeClass[nodeClass.value.value]);
|
|
650
|
-
console.log("browseName :", browseName.toString());
|
|
651
|
-
console.log(result1.toString());
|
|
652
|
-
throw new Error("getDataTypeDefinition invalid HasEncoding reference dataTypeNodeId must be NodeClass.DataType but was " +
|
|
653
|
-
node_opcua_data_model_1.NodeClass[nodeClass.value.value]);
|
|
654
|
-
}
|
|
655
|
-
const encodingReference = result1.references[0];
|
|
656
|
-
node_opcua_assert_1.assert(encodingReference.browseName.toString() === "Default Binary");
|
|
657
|
-
/* istanbul ignore next */
|
|
658
|
-
if (doDebug) {
|
|
659
|
-
const browseName = yield session.read({
|
|
660
|
-
attributeId: node_opcua_data_model_1.AttributeIds.BrowseName,
|
|
661
|
-
nodeId: dataTypeNodeId
|
|
662
|
-
});
|
|
663
|
-
debugLog(browseName.value.value.toString(), "Has Encoding ", encodingReference.browseName.toString(), encodingReference.nodeId.toString());
|
|
664
|
-
}
|
|
665
|
-
return encodingReference.nodeId;
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
function getDefinition(session, defaultBinaryEncodingNodeId) {
|
|
669
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
670
|
-
const nodeToBrowse2 = {
|
|
671
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
|
|
672
|
-
includeSubtypes: false,
|
|
673
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Variable"),
|
|
674
|
-
nodeId: defaultBinaryEncodingNodeId,
|
|
675
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasDescription"),
|
|
676
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
|
|
677
|
-
};
|
|
678
|
-
const result2 = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse2);
|
|
679
|
-
node_opcua_assert_1.assert(result2.references && result2.references.length === 1);
|
|
680
|
-
const definitionRef = result2.references[0];
|
|
681
|
-
const nameDataValue = yield session.read({
|
|
682
|
-
attributeId: node_opcua_data_model_1.AttributeIds.Value,
|
|
683
|
-
nodeId: definitionRef.nodeId
|
|
684
|
-
});
|
|
685
|
-
if (nameDataValue.statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
686
|
-
throw new Error("Cannot find ... " + definitionRef.nodeId.toString());
|
|
687
|
-
}
|
|
688
|
-
/*
|
|
689
|
-
const name = nameDataValue.value.value as string;
|
|
690
|
-
if (!name) {
|
|
691
|
-
console.log(nameDataValue.toString());
|
|
692
|
-
throw new Error("Cannot find ... " + name + " " + definitionRef.nodeId.toString());
|
|
693
|
-
}
|
|
694
|
-
*/
|
|
695
|
-
return definitionRef.nodeId;
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
function getSchemaNode(session, definitionRefNodeId) {
|
|
699
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
700
|
-
// find parent node to access the xsd File
|
|
701
|
-
const nodeToBrowse3 = {
|
|
702
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
|
|
703
|
-
includeSubtypes: false,
|
|
704
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("Variable"),
|
|
705
|
-
nodeId: definitionRefNodeId,
|
|
706
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasComponent"),
|
|
707
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
|
|
708
|
-
};
|
|
709
|
-
const result3 = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse3);
|
|
710
|
-
node_opcua_assert_1.assert(result3.references && result3.references.length === 1);
|
|
711
|
-
const schemaNode = result3.references[0].nodeId;
|
|
712
|
-
return schemaNode;
|
|
713
|
-
});
|
|
714
|
-
}
|
|
715
|
-
function getDataTypeDefinition(session, dataTypeNodeId,
|
|
716
|
-
// tslint:disable-next-line: no-shadowed-variable
|
|
717
|
-
dataTypeManager) {
|
|
718
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
719
|
-
// DataType
|
|
720
|
-
// | 1
|
|
721
|
-
// | n
|
|
722
|
-
// +- HasEncoding-> "Default Binary" (O)[DataTypeEncodingType]
|
|
723
|
-
// |
|
|
724
|
-
// +-- HasDescription -> "MyItemType" (V)[DataTypeDescriptionType]
|
|
725
|
-
// |
|
|
726
|
-
// +- ComponentOf -> Schema(V) []
|
|
727
|
-
// |
|
|
728
|
-
// +- ComponentOf -> OPC Binary(V)[DataTypeSystemType]
|
|
729
|
-
//
|
|
730
|
-
// Note that in 1.04 compliant server, DataType definition might be available
|
|
731
|
-
// in a DataTypeDefinition attributes of the DataType object
|
|
732
|
-
// However this is a brand new aspect of the specification and is not widely implemented
|
|
733
|
-
// it is also optional
|
|
734
|
-
// It will takes time for old opcua server to be refurbished and we may have to
|
|
735
|
-
// keep the current method to access type definition from embedded xsd.
|
|
736
|
-
//
|
|
737
|
-
const defaultBinaryEncodingNodeId = yield getHasEncodingDefaultBinary(session, dataTypeNodeId);
|
|
738
|
-
const definitionRefNodeId = yield getDefinition(session, defaultBinaryEncodingNodeId);
|
|
739
|
-
const schemaNode = yield getSchemaNode(session, definitionRefNodeId);
|
|
740
|
-
const dataTypeFactory = dataTypeManager.getDataTypeFactoryForNamespace(schemaNode.namespace);
|
|
741
|
-
/* istanbul ignore next */
|
|
742
|
-
if (!dataTypeFactory) {
|
|
743
|
-
throw new Error(" cannot find typeDictionary for " + schemaNode.toString());
|
|
744
|
-
}
|
|
745
|
-
const nameDataValue = yield session.read({
|
|
746
|
-
attributeId: node_opcua_data_model_1.AttributeIds.BrowseName,
|
|
747
|
-
nodeId: dataTypeNodeId
|
|
748
|
-
});
|
|
749
|
-
const name = nameDataValue.value.value.name;
|
|
750
|
-
const schema = dataTypeFactory.getStructuredTypeSchema(name);
|
|
751
|
-
return schema;
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
|
-
exports.getDataTypeDefinition = getDataTypeDefinition;
|
|
755
|
-
function findSuperType(session, dataTypeNodeId) {
|
|
756
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
757
|
-
const nodeToBrowse3 = {
|
|
758
|
-
browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
|
|
759
|
-
includeSubtypes: false,
|
|
760
|
-
nodeClassMask: node_opcua_data_model_1.makeNodeClassMask("DataType"),
|
|
761
|
-
nodeId: dataTypeNodeId,
|
|
762
|
-
referenceTypeId: node_opcua_nodeid_1.resolveNodeId("HasSubtype"),
|
|
763
|
-
resultMask: node_opcua_data_model_1.makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass")
|
|
764
|
-
};
|
|
765
|
-
const result3 = yield node_opcua_pseudo_session_1.browseAll(session, nodeToBrowse3);
|
|
766
|
-
/* istanbul ignore next */
|
|
767
|
-
if (result3.statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
768
|
-
throw new Error("Cannot find superType for " + dataTypeNodeId.toString());
|
|
769
|
-
}
|
|
770
|
-
result3.references = result3.references || [];
|
|
771
|
-
/* istanbul ignore next */
|
|
772
|
-
if (result3.references.length !== 1) {
|
|
773
|
-
console.log(result3.toString());
|
|
774
|
-
throw new Error("Invalid dataType with more than one superType " + dataTypeNodeId.toString());
|
|
775
|
-
}
|
|
776
|
-
return result3.references[0].nodeId;
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
function findDataTypeCategory(session, cache, dataTypeNodeId) {
|
|
780
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
781
|
-
const subTypeNodeId = yield findSuperType(session, dataTypeNodeId);
|
|
782
|
-
debugLog("subTypeNodeId of ", dataTypeNodeId.toString(), " is ", subTypeNodeId.toString());
|
|
783
|
-
const key = subTypeNodeId.toString();
|
|
784
|
-
if (cache[key]) {
|
|
785
|
-
return cache[key].category;
|
|
786
|
-
}
|
|
787
|
-
let category;
|
|
788
|
-
if (subTypeNodeId.namespace === 0 && subTypeNodeId.value <= 29) {
|
|
789
|
-
// well known node ID !
|
|
790
|
-
switch (subTypeNodeId.value) {
|
|
791
|
-
case 22 /* Structure */:
|
|
792
|
-
category = node_opcua_factory_1.FieldCategory.complex;
|
|
793
|
-
break;
|
|
794
|
-
case 29 /* Enumeration */:
|
|
795
|
-
category = node_opcua_factory_1.FieldCategory.enumeration;
|
|
796
|
-
break;
|
|
797
|
-
default:
|
|
798
|
-
category = node_opcua_factory_1.FieldCategory.basic;
|
|
799
|
-
break;
|
|
800
|
-
}
|
|
801
|
-
return category;
|
|
802
|
-
}
|
|
803
|
-
// must drill down ...
|
|
804
|
-
return yield findDataTypeCategory(session, cache, subTypeNodeId);
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
|
-
function findDataTypeBasicType(session, cache, dataTypeNodeId) {
|
|
808
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
809
|
-
const subTypeNodeId = yield findSuperType(session, dataTypeNodeId);
|
|
810
|
-
debugLog("subTypeNodeId of ", dataTypeNodeId.toString(), " is ", subTypeNodeId.toString());
|
|
811
|
-
const key = subTypeNodeId.toString();
|
|
812
|
-
if (cache[key]) {
|
|
813
|
-
return cache[key].schema;
|
|
814
|
-
}
|
|
815
|
-
if (subTypeNodeId.namespace === 0 && subTypeNodeId.value < 29) {
|
|
816
|
-
switch (subTypeNodeId.value) {
|
|
817
|
-
case 22: /* Structure */
|
|
818
|
-
case 29 /* Enumeration */:
|
|
819
|
-
throw new Error("Not expecting Structure or Enumeration");
|
|
820
|
-
default:
|
|
821
|
-
break;
|
|
822
|
-
}
|
|
823
|
-
const nameDataValue = yield session.read({
|
|
824
|
-
attributeId: node_opcua_data_model_1.AttributeIds.BrowseName,
|
|
825
|
-
nodeId: subTypeNodeId
|
|
826
|
-
});
|
|
827
|
-
const name = nameDataValue.value.value.name;
|
|
828
|
-
return node_opcua_factory_1.getBuildInType(name);
|
|
829
|
-
}
|
|
830
|
-
// must drill down ...
|
|
831
|
-
return yield findDataTypeBasicType(session, cache, subTypeNodeId);
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
function readBrowseName(session, nodeId) {
|
|
835
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
836
|
-
const dataValue = yield session.read({ nodeId, attributeId: node_opcua_data_model_1.AttributeIds.BrowseName });
|
|
837
|
-
if (dataValue.statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
838
|
-
const message = "cannot extract BrowseName of nodeId = " + nodeId.toString() + " statusCode = " + dataValue.statusCode.toString();
|
|
839
|
-
debugLog(message);
|
|
840
|
-
throw new Error(message);
|
|
841
|
-
}
|
|
842
|
-
return dataValue.value.value.name;
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
function resolveFieldType(session, dataTypeNodeId, dataTypeFactory, cache) {
|
|
846
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
847
|
-
if (dataTypeNodeId.namespace === 0 && dataTypeNodeId.value === 22) {
|
|
848
|
-
return null;
|
|
849
|
-
}
|
|
850
|
-
const key = dataTypeNodeId.toString();
|
|
851
|
-
const v = cache[key];
|
|
852
|
-
if (v) {
|
|
853
|
-
return v;
|
|
854
|
-
}
|
|
855
|
-
if (dataTypeNodeId.value === 0) {
|
|
856
|
-
const v3 = {
|
|
857
|
-
category: node_opcua_factory_1.FieldCategory.basic,
|
|
858
|
-
fieldTypeName: "Variant",
|
|
859
|
-
schema: dataTypeFactory.getSimpleType("Variant")
|
|
860
|
-
};
|
|
861
|
-
cache[key] = v3;
|
|
862
|
-
return v3;
|
|
863
|
-
}
|
|
864
|
-
const fieldTypeName = yield readBrowseName(session, dataTypeNodeId);
|
|
865
|
-
let schema;
|
|
866
|
-
let category = node_opcua_factory_1.FieldCategory.enumeration;
|
|
867
|
-
if (dataTypeFactory.hasStructuredType(fieldTypeName)) {
|
|
868
|
-
schema = dataTypeFactory.getStructuredTypeSchema(fieldTypeName);
|
|
869
|
-
category = node_opcua_factory_1.FieldCategory.complex;
|
|
870
|
-
}
|
|
871
|
-
else if (dataTypeFactory.hasSimpleType(fieldTypeName)) {
|
|
872
|
-
category = node_opcua_factory_1.FieldCategory.basic;
|
|
873
|
-
schema = dataTypeFactory.getSimpleType(fieldTypeName);
|
|
874
|
-
}
|
|
875
|
-
else if (dataTypeFactory.hasEnumeration(fieldTypeName)) {
|
|
876
|
-
category = node_opcua_factory_1.FieldCategory.enumeration;
|
|
877
|
-
schema = dataTypeFactory.getEnumeration(fieldTypeName);
|
|
878
|
-
}
|
|
879
|
-
else {
|
|
880
|
-
debugLog(" type " + fieldTypeName + " has not been seen yet, let resolve it");
|
|
881
|
-
category = yield findDataTypeCategory(session, cache, dataTypeNodeId);
|
|
882
|
-
debugLog(" type " + fieldTypeName + " has not been seen yet, let resolve it => (category = ", category, " )");
|
|
883
|
-
switch (category) {
|
|
884
|
-
case node_opcua_factory_1.FieldCategory.basic:
|
|
885
|
-
schema = yield findDataTypeBasicType(session, cache, dataTypeNodeId);
|
|
886
|
-
/* istanbul ignore next */
|
|
887
|
-
if (!schema) {
|
|
888
|
-
console.log("Cannot find basic type " + fieldTypeName);
|
|
889
|
-
}
|
|
890
|
-
break;
|
|
891
|
-
default:
|
|
892
|
-
case node_opcua_factory_1.FieldCategory.enumeration:
|
|
893
|
-
case node_opcua_factory_1.FieldCategory.complex:
|
|
894
|
-
const dataTypeDefinitionDataValue = yield session.read({
|
|
895
|
-
attributeId: node_opcua_data_model_1.AttributeIds.DataTypeDefinition,
|
|
896
|
-
nodeId: dataTypeNodeId
|
|
897
|
-
});
|
|
898
|
-
/* istanbul ignore next */
|
|
899
|
-
if (dataTypeDefinitionDataValue.statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
900
|
-
throw new Error(" Cannot find dataType Definition ! with nodeId =" + dataTypeNodeId.toString());
|
|
901
|
-
}
|
|
902
|
-
const definition = dataTypeDefinitionDataValue.value.value;
|
|
903
|
-
if (category === node_opcua_factory_1.FieldCategory.enumeration) {
|
|
904
|
-
if (definition instanceof node_opcua_types_1.EnumDefinition) {
|
|
905
|
-
const e = new node_opcua_factory_1.EnumerationDefinitionSchema({
|
|
906
|
-
enumValues: definition.fields,
|
|
907
|
-
name: fieldTypeName
|
|
908
|
-
});
|
|
909
|
-
dataTypeFactory.registerEnumeration(e);
|
|
910
|
-
schema = e;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
else {
|
|
914
|
-
schema = yield convertDataTypeDefinitionToStructureTypeSchema(session, dataTypeNodeId, fieldTypeName, definition, dataTypeFactory, cache);
|
|
915
|
-
}
|
|
916
|
-
// xx const schema1 = dataTypeFactory.getStructuredTypeSchema(fieldTypeName);
|
|
917
|
-
break;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
/* istanbul ignore next */
|
|
921
|
-
if (!schema) {
|
|
922
|
-
throw new Error("expecting a schema here fieldTypeName=" + fieldTypeName + " " + dataTypeNodeId.toString() + " category = " + category);
|
|
923
|
-
}
|
|
924
|
-
const v2 = {
|
|
925
|
-
category,
|
|
926
|
-
fieldTypeName,
|
|
927
|
-
schema
|
|
928
|
-
};
|
|
929
|
-
cache[key] = v2;
|
|
930
|
-
return v2;
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
function _setupEncodings(session, dataTypeNodeId, schema) {
|
|
934
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
935
|
-
// read abstract flag
|
|
936
|
-
const isAbstractDV = yield session.read({ nodeId: dataTypeNodeId, attributeId: node_opcua_data_model_1.AttributeIds.IsAbstract });
|
|
937
|
-
schema.dataTypeNodeId = dataTypeNodeId;
|
|
938
|
-
schema.id = dataTypeNodeId;
|
|
939
|
-
if (isAbstractDV.statusCode === node_opcua_status_code_1.StatusCodes.Good && isAbstractDV.value.value === false) {
|
|
940
|
-
const encodings = yield _findEncodings(session, dataTypeNodeId);
|
|
941
|
-
schema.encodingDefaultBinary = node_opcua_nodeid_1.makeExpandedNodeId(encodings.binaryEncodingNodeId);
|
|
942
|
-
schema.encodingDefaultXml = node_opcua_nodeid_1.makeExpandedNodeId(encodings.xmlEncodingNodeId);
|
|
943
|
-
schema.encodingDefaultJson = node_opcua_nodeid_1.makeExpandedNodeId(encodings.jsonEncodingNodeId);
|
|
944
|
-
}
|
|
945
|
-
return schema;
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
function convertDataTypeDefinitionToStructureTypeSchema(session, dataTypeNodeId, name, definition, dataTypeFactory, cache) {
|
|
949
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
950
|
-
if (definition instanceof node_opcua_types_1.StructureDefinition) {
|
|
951
|
-
const fields = [];
|
|
952
|
-
const isUnion = definition.structureType === node_opcua_types_1.StructureType.Union;
|
|
953
|
-
switch (definition.structureType) {
|
|
954
|
-
case node_opcua_types_1.StructureType.Union:
|
|
955
|
-
// xx console.log("Union Found : ", name);
|
|
956
|
-
fields.push({
|
|
957
|
-
fieldType: "UInt32",
|
|
958
|
-
name: "SwitchField"
|
|
959
|
-
});
|
|
960
|
-
break;
|
|
961
|
-
case node_opcua_types_1.StructureType.Structure:
|
|
962
|
-
case node_opcua_types_1.StructureType.StructureWithOptionalFields:
|
|
963
|
-
break;
|
|
964
|
-
}
|
|
965
|
-
let switchValue = 1;
|
|
966
|
-
let switchBit = 0;
|
|
967
|
-
const bitFields = isUnion ? undefined : [];
|
|
968
|
-
for (const fieldD of definition.fields) {
|
|
969
|
-
const rt = (yield resolveFieldType(session, fieldD.dataType, dataTypeFactory, cache));
|
|
970
|
-
if (!rt) {
|
|
971
|
-
console.log("convertDataTypeDefinitionToStructureTypeSchema cannot handle field", fieldD.name, "in", name);
|
|
972
|
-
continue;
|
|
973
|
-
}
|
|
974
|
-
const { schema, category, fieldTypeName } = rt;
|
|
975
|
-
const field = {
|
|
976
|
-
fieldType: fieldTypeName,
|
|
977
|
-
name: fieldD.name,
|
|
978
|
-
schema
|
|
979
|
-
};
|
|
980
|
-
if (fieldD.isOptional) {
|
|
981
|
-
field.switchBit = switchBit++;
|
|
982
|
-
bitFields === null || bitFields === void 0 ? void 0 : bitFields.push({ name: fieldD.name + "Specified", length: 1 });
|
|
983
|
-
}
|
|
984
|
-
if (isUnion) {
|
|
985
|
-
field.switchValue = switchValue;
|
|
986
|
-
switchValue += 1;
|
|
987
|
-
}
|
|
988
|
-
node_opcua_assert_1.assert(fieldD.valueRank === -1 || fieldD.valueRank === 1 || fieldD.valueRank === 0);
|
|
989
|
-
if (fieldD.valueRank === 1) {
|
|
990
|
-
field.isArray = true;
|
|
991
|
-
}
|
|
992
|
-
else {
|
|
993
|
-
field.isArray = false;
|
|
994
|
-
}
|
|
995
|
-
field.category = category;
|
|
996
|
-
field.schema = schema;
|
|
997
|
-
fields.push(field);
|
|
998
|
-
}
|
|
999
|
-
const a = yield resolveFieldType(session, definition.baseDataType, dataTypeFactory, cache);
|
|
1000
|
-
const baseType = a ? a.fieldTypeName : "ExtensionObject";
|
|
1001
|
-
const os = new node_opcua_factory_1.StructuredTypeSchema({
|
|
1002
|
-
baseType,
|
|
1003
|
-
bitFields,
|
|
1004
|
-
fields,
|
|
1005
|
-
id: 0,
|
|
1006
|
-
name
|
|
1007
|
-
});
|
|
1008
|
-
const structuredTypeSchema = yield _setupEncodings(session, dataTypeNodeId, os);
|
|
1009
|
-
return structuredTypeSchema;
|
|
1010
|
-
}
|
|
1011
|
-
throw new Error("Not Implemented");
|
|
1012
|
-
});
|
|
1013
|
-
}
|
|
1014
|
-
exports.convertDataTypeDefinitionToStructureTypeSchema = convertDataTypeDefinitionToStructureTypeSchema;
|
|
1015
|
-
function extractNamespaceDataType(session) {
|
|
1016
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1017
|
-
const sessionPriv = session;
|
|
1018
|
-
if (!sessionPriv.$$extraDataTypeManager) {
|
|
1019
|
-
const dataTypeManager = new extra_data_type_manager_1.ExtraDataTypeManager();
|
|
1020
|
-
const namespaceArray = yield node_opcua_pseudo_session_1.readNamespaceArray(sessionPriv);
|
|
1021
|
-
if (namespaceArray.length === 0) {
|
|
1022
|
-
errorLog("namespaceArray is not populated ! check your code !");
|
|
1023
|
-
}
|
|
1024
|
-
debugLog("Namespace Array = ", namespaceArray.join("\n "));
|
|
1025
|
-
sessionPriv.$$extraDataTypeManager = dataTypeManager;
|
|
1026
|
-
dataTypeManager.setNamespaceArray(namespaceArray);
|
|
1027
|
-
for (let namespaceIndex = 1; namespaceIndex < namespaceArray.length; namespaceIndex++) {
|
|
1028
|
-
const dataTypeFactory1 = new node_opcua_factory_1.DataTypeFactory([node_opcua_factory_1.getStandardDataTypeFactory()]);
|
|
1029
|
-
dataTypeManager.registerDataTypeFactory(namespaceIndex, dataTypeFactory1);
|
|
1030
|
-
}
|
|
1031
|
-
yield populateDataTypeManager(session, dataTypeManager);
|
|
1032
|
-
}
|
|
1033
|
-
return sessionPriv.$$extraDataTypeManager;
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
|
-
exports.extractNamespaceDataType = extractNamespaceDataType;
|
|
1037
|
-
function getExtensionObjectConstructor(session, dataTypeNodeId) {
|
|
1038
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1039
|
-
if (!dataTypeNodeId)
|
|
1040
|
-
throw new Error("Invalid dataType");
|
|
1041
|
-
const sessionPriv = session;
|
|
1042
|
-
if (!sessionPriv.dataTypeConstructor) {
|
|
1043
|
-
sessionPriv.dataTypeConstructor = {};
|
|
1044
|
-
}
|
|
1045
|
-
const c = sessionPriv.dataTypeConstructor[dataTypeNodeId.toString()];
|
|
1046
|
-
if (c) {
|
|
1047
|
-
return c;
|
|
1048
|
-
}
|
|
1049
|
-
yield extractNamespaceDataType(session);
|
|
1050
|
-
if (!sessionPriv.$$extraDataTypeManager) {
|
|
1051
|
-
throw new Error("Make sure to call await session.extractNamespaceDataType(); ");
|
|
1052
|
-
}
|
|
1053
|
-
const extraDataTypeManager = sessionPriv.$$extraDataTypeManager;
|
|
1054
|
-
// make sure schema has been extracted
|
|
1055
|
-
const schema = yield getDataTypeDefinition(session, dataTypeNodeId, extraDataTypeManager);
|
|
1056
|
-
// now resolve it
|
|
1057
|
-
const constructor = extraDataTypeManager.getExtensionObjectConstructorFromDataType(dataTypeNodeId);
|
|
1058
|
-
// put it in cache
|
|
1059
|
-
sessionPriv.dataTypeConstructor[dataTypeNodeId.toString()] = constructor;
|
|
1060
|
-
return constructor;
|
|
1061
|
-
});
|
|
1062
|
-
}
|
|
1063
|
-
exports.getExtensionObjectConstructor = getExtensionObjectConstructor;
|
|
1064
|
-
//# sourceMappingURL=client_dynamic_extension_object.js.map
|