@itwin/ecschema2ts 4.0.0-dev.8 → 4.0.0-dev.81

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.
@@ -1,547 +1,547 @@
1
- "use strict";
2
- /*---------------------------------------------------------------------------------------------
3
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
- * See LICENSE.md in the project root for license terms and full copyright notice.
5
- *--------------------------------------------------------------------------------------------*/
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ECSchemaToTs = void 0;
8
- const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
9
- const customHandledPropertyCA = "BisCore.CustomHandledProperty";
10
- const elementECClassName = "BisCore.Element";
11
- const tsBentleyModules = {
12
- tsIModelJsCommon: {
13
- moduleName: "@itwin/core-common",
14
- resolvedConflictName: "BeIModelJsCommon",
15
- },
16
- tsIModelJsBackend: {
17
- moduleName: "@itwin/core-backend",
18
- resolvedConflictName: "BeIModelJsBackend",
19
- },
20
- tsGeometryCore: {
21
- moduleName: "@itwin/core-geometry",
22
- resolvedConflictName: "BeGeometryCore",
23
- },
24
- tsBentleyJsCore: {
25
- moduleName: "@itwin/core-bentley",
26
- resolvedConflictName: "BeBentleyJsCore",
27
- },
28
- };
29
- /**
30
- * @beta
31
- */
32
- class ECSchemaToTs {
33
- constructor() {
34
- this._schema = undefined;
35
- this._schemaItemList = [];
36
- this._tsBentleyModuleNames = new Set();
37
- this._tsBentleyModuleResolvedConflictNames = new Map();
38
- for (const key in tsBentleyModules) {
39
- if (tsBentleyModules.hasOwnProperty(key)) {
40
- const moduleName = tsBentleyModules[key].moduleName;
41
- const resolvedPrefix = tsBentleyModules[key].resolvedConflictName;
42
- this._tsBentleyModuleNames.add(moduleName);
43
- this._tsBentleyModuleResolvedConflictNames.set(moduleName, resolvedPrefix);
44
- }
45
- }
46
- }
47
- /**
48
- * Given the schema, the function will converted it to typescript strings
49
- * @param schema The schema to be converted to typescript strings
50
- */
51
- convertSchemaToTs(schema) {
52
- // convert schema to typescript String
53
- this._schema = schema;
54
- this.dependencyToFront();
55
- const schemaTsString = this.convertSchemaToTsClass();
56
- const elemTsString = this.convertElemToTsClasses();
57
- const propsTsString = this.convertPropsToTsInterfaces();
58
- return { schemaTsString, elemTsString, propsTsString };
59
- }
60
- /**
61
- * The function will push all the base classes to be the first ones in the schema item list.
62
- * For example, if class A extends base class B and base class C, B and C will be on the first of the list and then A at the end.
63
- * If B extends C, then B will be first and C will be next in the list and then A at the end.
64
- * If B and C does not depend on each other, the order of B and C will not be important.
65
- * The arrangement is to make sure that base class will be converted first and then, derived classes and so on
66
- */
67
- dependencyToFront() {
68
- const uniqueItemName = new Set();
69
- const schemaItemsList = [];
70
- for (const schemaItem of this._schema.getItems()) {
71
- // base class to the item list first;
72
- switch (schemaItem.schemaItemType) {
73
- case ecschema_metadata_1.SchemaItemType.StructClass:
74
- case ecschema_metadata_1.SchemaItemType.Mixin:
75
- case ecschema_metadata_1.SchemaItemType.EntityClass:
76
- const ecClass = schemaItem;
77
- const baseList = this.getAllBaseClasses(ecClass);
78
- for (let i = baseList.length - 1; i >= 0; --i) {
79
- const base = baseList[i];
80
- if (base.schema.schemaKey.compareByName(this._schema.schemaKey) && !uniqueItemName.has(base.name)) {
81
- schemaItemsList.push(baseList[i]);
82
- uniqueItemName.add(base.name);
83
- }
84
- }
85
- break;
86
- default:
87
- break;
88
- }
89
- if (!uniqueItemName.has(schemaItem.name)) {
90
- uniqueItemName.add(schemaItem.name);
91
- schemaItemsList.push(schemaItem);
92
- }
93
- }
94
- this._schemaItemList = schemaItemsList;
95
- }
96
- /**
97
- * The function converts the schema meta data to typescript Schema class
98
- */
99
- convertSchemaToTsClass() {
100
- const schemaName = this._schema.schemaKey.name;
101
- let outputString = "";
102
- // import modules
103
- outputString += "import { ClassRegistry, Schema, Schemas } from \"@itwin/core-backend\";\n";
104
- outputString += `import * as elementsModule from "./${schemaName}Elements";\n\n`;
105
- // create new schema class
106
- outputString += `export class ${schemaName} extends Schema {\n`;
107
- // schemaName() method
108
- outputString += ` public static get schemaName(): string { return "${schemaName}"; }\n\n`;
109
- // registerSchema method
110
- outputString += " public static registerSchema() {\n";
111
- outputString += ` if (!Schemas.getRegisteredSchema(${schemaName}.name))\n`;
112
- outputString += ` Schemas.registerSchema(${schemaName});\n`;
113
- outputString += " }\n\n";
114
- // constructor
115
- outputString += " protected constructor() {\n";
116
- outputString += " super();\n";
117
- outputString += ` ClassRegistry.registerModule(elementsModule, ${schemaName});\n`;
118
- outputString += " }\n";
119
- outputString += "}\n\n";
120
- return outputString;
121
- }
122
- /**
123
- * The function converts the schema item to respective typescript classes
124
- */
125
- convertElemToTsClasses() {
126
- const classNameToModule = new Map();
127
- let classTs = "";
128
- for (const schemaItem of this._schemaItemList) {
129
- switch (schemaItem.schemaItemType) {
130
- case ecschema_metadata_1.SchemaItemType.EntityClass:
131
- classTs += this.convertEntityToTs(schemaItem, classNameToModule);
132
- break;
133
- case ecschema_metadata_1.SchemaItemType.Enumeration:
134
- classTs += this.convertEnumToTs(schemaItem);
135
- break;
136
- default:
137
- continue;
138
- }
139
- }
140
- let outputString = this.convertImportToTsImport(classNameToModule);
141
- outputString += `\n${classTs}`;
142
- return outputString;
143
- }
144
- /**
145
- * The function converts the schema item properties to respective typescript props interfaces
146
- */
147
- convertPropsToTsInterfaces() {
148
- const classNameToModule = new Map();
149
- let interfacesTs = "";
150
- for (const schemaItem of this._schemaItemList) {
151
- switch (schemaItem.schemaItemType) {
152
- case ecschema_metadata_1.SchemaItemType.EntityClass:
153
- case ecschema_metadata_1.SchemaItemType.Mixin:
154
- case ecschema_metadata_1.SchemaItemType.StructClass:
155
- interfacesTs += this.convertECClassPropsToTsInterface(schemaItem, classNameToModule);
156
- break;
157
- default:
158
- continue;
159
- }
160
- }
161
- let outputString = this.convertImportToTsImport(classNameToModule);
162
- outputString += `\n${interfacesTs}`;
163
- return outputString;
164
- }
165
- /**
166
- * Convert mixin or struct class or entity class to respective typescript interface
167
- * @param ecClass Schema mixin or struct or entity to be converted typescript interface
168
- * @param classNameToModule Typescrip modules to be updated after the conversion
169
- */
170
- convertECClassPropsToTsInterface(ecClass, classNameToModule) {
171
- let interfacesTs = "";
172
- // no interface props for BisCore Element
173
- if (ecClass.fullName === elementECClassName)
174
- return interfacesTs;
175
- // only generate props interface for entity if the class has properties
176
- if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass && (!ecClass.properties || ecClass.properties.next().done))
177
- return interfacesTs;
178
- // convert description to typescript comment only for mixin or struct
179
- if (ecClass.schemaItemType !== ecschema_metadata_1.SchemaItemType.EntityClass && ecClass.description)
180
- interfacesTs += `${this.convertDescriptionToTsComment(ecClass.description)}\n`;
181
- // build interface for props in ecClass
182
- interfacesTs += `export interface ${ecClass.name}`;
183
- if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass)
184
- interfacesTs += "Props";
185
- // Extend it with base ecClass Props interface if there is any
186
- const baseClasses = this.getBaseClassWithProps(ecClass);
187
- if (baseClasses.length > 0) {
188
- interfacesTs += " extends ";
189
- let separator = "";
190
- for (const base of baseClasses) {
191
- interfacesTs += separator + this.addImportBasePropsClass(classNameToModule, base, ecClass);
192
- separator = ", ";
193
- }
194
- }
195
- else if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass)
196
- interfacesTs += ` extends ${this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsCommon.moduleName, "EntityProps")}`;
197
- // build props for ecClass
198
- interfacesTs += " {";
199
- const propertiesTs = this.convertPropsToTsVars(ecClass, classNameToModule);
200
- for (const varDeclarationLine of propertiesTs)
201
- interfacesTs += `\n ${varDeclarationLine}`;
202
- interfacesTs += "\n}\n\n";
203
- return interfacesTs;
204
- }
205
- /**
206
- * Convert schema enumeration to typescript enumeration
207
- * @param ecEnum Schema enumeration to be converted to typescript enumeration
208
- */
209
- convertEnumToTs(ecEnum) {
210
- let outputString = "";
211
- if (ecEnum.description)
212
- outputString += `${this.convertDescriptionToTsComment(ecEnum.description)}\n`;
213
- outputString += `export const enum ${ecEnum.name} {\n`;
214
- for (const ecEnumerator of ecEnum.enumerators) {
215
- outputString += ` ${ecEnumerator.label}`;
216
- if (ecEnum.isInt)
217
- outputString += ` = ${ecEnumerator.value}`;
218
- else if (ecEnum.isString)
219
- outputString += ` = "${ecEnumerator.value}"`;
220
- outputString += ",\n";
221
- }
222
- outputString += "}\n\n";
223
- return outputString;
224
- }
225
- /**
226
- * Convert schema entity to typescript entity class. The typescript class will implement respective props
227
- * typescript interface if the schema entity class has properties
228
- * @param ecClass Schema class to be converted to typescript class
229
- * @param classNameToModule Typescrip modules to be updated after the conversion
230
- */
231
- convertEntityToTs(ecClass, classNameToModule) {
232
- let outputString = "";
233
- if (ecClass.description)
234
- outputString += `${this.convertDescriptionToTsComment(ecClass.description)}\n`;
235
- let modifier = "";
236
- if (ecClass.modifier === ecschema_metadata_1.ECClassModifier.Abstract)
237
- modifier = "abstract ";
238
- outputString += `export ${modifier}class ${ecClass.name} extends `;
239
- // extend base class if there is any. Default will be Entity class defined in @itwin/core-backend
240
- const base = ecClass.getBaseClassSync();
241
- if (base)
242
- outputString += this.addImportBaseClass(classNameToModule, base, ecClass);
243
- else
244
- outputString += this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsBackend.moduleName, "Entity");
245
- // determine prop type to pass in the constructor
246
- let propsBaseTsType;
247
- const propsBase = this.getBaseClassWithProps(ecClass);
248
- if (ecClass.fullName !== elementECClassName && ecClass.properties && !ecClass.properties.next().done) {
249
- const moduleName = `${this._schema.schemaKey.name}ElementProps`;
250
- propsBaseTsType = this.addImportClass(classNameToModule, moduleName, `${ecClass.name}Props`);
251
- }
252
- else if (propsBase.length > 0)
253
- propsBaseTsType = this.addImportBasePropsClass(classNameToModule, propsBase[0], ecClass);
254
- else
255
- propsBaseTsType = this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsCommon.moduleName, "EntityProps");
256
- // implement the ecClass props if it has properties
257
- if (`${ecClass.name}Props` === propsBaseTsType)
258
- outputString += ` implements ${propsBaseTsType}`;
259
- // write constructor and className function for class
260
- const iModelDbTsType = this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsBackend.moduleName, "IModelDb");
261
- outputString += " {\n";
262
- outputString += ` public static get className(): string { return "${ecClass.name}"; }\n\n`;
263
- outputString += ` public constructor (props: ${propsBaseTsType}, iModel: ${iModelDbTsType}) {\n`;
264
- outputString += " super(props, iModel);\n";
265
- outputString += " }\n";
266
- outputString += "}\n\n";
267
- return outputString;
268
- }
269
- /**
270
- * Convert class properties to typescript member declaration
271
- * @param ecClass The schema class that has the properties to be converted to typescript member variables
272
- * @param classNameToModule Typescrip modules to be updated after the conversion
273
- */
274
- convertPropsToTsVars(ecClass, classNameToModule) {
275
- if (ecClass.properties === undefined || ecClass.properties.next().done)
276
- return [];
277
- const outputStrings = [];
278
- for (const ecProperty of ecClass.properties) {
279
- // not generate ts variable declaration for property that has CustomHandledProperty ca
280
- if (ecProperty.customAttributes && ecProperty.customAttributes.has(customHandledPropertyCA))
281
- continue;
282
- let varDeclarationLine = `${this.lowerPropertyName(ecProperty.name)}?: `;
283
- if (ecProperty.isPrimitive()) {
284
- // determine Ts type of the primitive
285
- let typeTs = "";
286
- if (ecProperty.extendedTypeName)
287
- typeTs = this.convertExtendedTypeNameToTsType(ecProperty.extendedTypeName, classNameToModule);
288
- else if (ecProperty.isEnumeration()) {
289
- const ecEnumProperty = ecProperty;
290
- const ecEnum = ecEnumProperty.enumeration;
291
- typeTs = this.addImportClass(classNameToModule, `${ecEnum.schemaKey.name}Elements`, ecEnum.name);
292
- }
293
- else {
294
- const ecPrimitiveProperty = ecProperty;
295
- typeTs = this.convertPrimitiveTypeToTsType(ecPrimitiveProperty.primitiveType, classNameToModule);
296
- }
297
- varDeclarationLine += typeTs;
298
- }
299
- else if (ecProperty.isStruct()) {
300
- // import struct class if it is in different schema
301
- const ecStructProperty = ecProperty;
302
- const structClass = ecStructProperty.structClass;
303
- if (!structClass.schema.schemaKey.compareByName(ecClass.schema.schemaKey))
304
- varDeclarationLine += this.addImportClass(classNameToModule, `${structClass.schema.schemaKey.name}ElementProps`, structClass.name);
305
- else
306
- varDeclarationLine += structClass.name;
307
- }
308
- else if (ecProperty.isNavigation())
309
- varDeclarationLine += this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsCommon.moduleName, "RelatedElementProps");
310
- if (ecProperty.isArray())
311
- varDeclarationLine += "[]";
312
- varDeclarationLine += ";";
313
- outputStrings.push(varDeclarationLine);
314
- }
315
- return outputStrings;
316
- }
317
- /**
318
- * Convert schema extended type to typescript type
319
- * @param typeName Schema extended type to be converted to typescript type
320
- * @param classNameToModule Typescrip modules to be updated after the conversion
321
- */
322
- convertExtendedTypeNameToTsType(typeName, classNameToModule) {
323
- switch (typeName) {
324
- case "Json":
325
- return "any";
326
- case "BeGuid":
327
- return this.addImportClass(classNameToModule, tsBentleyModules.tsBentleyJsCore.moduleName, "GuidString");
328
- default:
329
- return "any";
330
- }
331
- }
332
- /**
333
- * Convert schema primitive type to typescript type
334
- * @param type Schema primitive type to be converted to typescript type
335
- * @param classNameToModule Typescrip modules to be updated after the conversion
336
- */
337
- convertPrimitiveTypeToTsType(type, classNameToModule) {
338
- switch (type) {
339
- case ecschema_metadata_1.PrimitiveType.Binary:
340
- return "any";
341
- case ecschema_metadata_1.PrimitiveType.Boolean:
342
- return "boolean";
343
- case ecschema_metadata_1.PrimitiveType.DateTime:
344
- return "Date";
345
- case ecschema_metadata_1.PrimitiveType.Double:
346
- return "number";
347
- case ecschema_metadata_1.PrimitiveType.Integer:
348
- return "number";
349
- case ecschema_metadata_1.PrimitiveType.Long:
350
- // eslint-disable-next-line no-console
351
- console.log("Primitive type Long is not currently supported during conversion. It will be treated as type 'any'");
352
- return "any";
353
- case ecschema_metadata_1.PrimitiveType.String:
354
- return "string";
355
- case ecschema_metadata_1.PrimitiveType.Point2d:
356
- return this.addImportClass(classNameToModule, tsBentleyModules.tsGeometryCore.moduleName, "Point2d");
357
- case ecschema_metadata_1.PrimitiveType.Point3d:
358
- return this.addImportClass(classNameToModule, tsBentleyModules.tsGeometryCore.moduleName, "Point3d");
359
- case ecschema_metadata_1.PrimitiveType.IGeometry:
360
- // eslint-disable-next-line no-console
361
- console.log("Primitive type IGeometry is not currently supported during conversion. It will be treated as type 'any'");
362
- return "any";
363
- default:
364
- // eslint-disable-next-line no-console
365
- console.log("Unknown primitive type during conversion. It will be treated as type 'any'");
366
- return "any";
367
- }
368
- }
369
- /**
370
- * Convert schema description to typescript comment
371
- * @param description Schema description to be converted to typescript comment
372
- */
373
- convertDescriptionToTsComment(description) {
374
- let outputString = "/**\n";
375
- let wordCount = 0;
376
- let begin = 0;
377
- let spaceBegin = 0;
378
- let spaceIdx = description.indexOf(" ", spaceBegin);
379
- while (spaceIdx !== -1) {
380
- // new line for every 20 words
381
- ++wordCount;
382
- if (wordCount === 20) {
383
- wordCount = 0;
384
- outputString += ` * ${description.substr(begin, spaceIdx - begin)}\n`;
385
- begin = spaceIdx + 1;
386
- }
387
- spaceBegin = spaceIdx + 1;
388
- while (description[spaceBegin] === " ")
389
- ++spaceBegin;
390
- spaceIdx = description.indexOf(" ", spaceBegin);
391
- }
392
- // append the last word
393
- outputString += ` * ${description.substr(begin)}\n`;
394
- outputString += " */";
395
- return outputString;
396
- }
397
- /**
398
- * Convert all modules needed for the converted schema types to typescript import statements
399
- * @param classNameToModule Modules to be converted to typescript imports statement
400
- */
401
- convertImportToTsImport(classNameToModule) {
402
- const moduleToTsTypes = new Map();
403
- classNameToModule.forEach((moduleNames, className) => {
404
- if (!moduleToTsTypes.has(moduleNames))
405
- moduleToTsTypes.set(moduleNames, new Set());
406
- moduleToTsTypes.get(moduleNames).add(className);
407
- });
408
- let outputString = "";
409
- moduleToTsTypes.forEach((classNames, moduleName) => {
410
- if (!this._tsBentleyModuleNames.has(moduleName))
411
- moduleName = `./${moduleName}`;
412
- outputString += "import { ";
413
- let separator = "";
414
- for (const className of classNames) {
415
- outputString += separator + className;
416
- separator = ", ";
417
- }
418
- outputString += ` } from "${moduleName}";\n`;
419
- });
420
- return outputString;
421
- }
422
- /**
423
- * Traverse the inheritance tree to retrieve first base classes that have properties
424
- * @param ecClass Schema class to be traverse
425
- */
426
- getBaseClassWithProps(ecClass) {
427
- const res = [];
428
- const visited = new Set();
429
- visited.add(ecClass.fullName);
430
- this.traverseBaseClass(ecClass, visited, (base) => {
431
- if (base.properties && !base.properties.next().done) {
432
- res.push(base);
433
- return false;
434
- }
435
- return true;
436
- });
437
- return res;
438
- }
439
- /**
440
- * Traverse the inheritance tree to retrieve base classes of a schema class
441
- * @param ecClass Schema class to be traverse
442
- */
443
- getAllBaseClasses(ecClass) {
444
- const res = [];
445
- const visited = new Set();
446
- visited.add(ecClass.fullName);
447
- this.traverseBaseClass(ecClass, visited, (base) => {
448
- res.push(base);
449
- return true;
450
- });
451
- return res;
452
- }
453
- /**
454
- * Traverse the inheritance tree horizontally and vertically of a schema class
455
- * @param ecClass Schema class to be traverse
456
- * @param visited Set of classes that are already visited
457
- * @param shouldTraverseDown Lambda to determine if it should traverse more vertically
458
- */
459
- traverseBaseClass(ecClass, visited, shouldTraverseDown) {
460
- const base = ecClass.getBaseClassSync();
461
- if (base === undefined || visited.has(base.fullName))
462
- return;
463
- const baseList = [base];
464
- if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass) {
465
- const entity = ecClass;
466
- for (const mixin of entity.getMixinsSync())
467
- baseList.push(mixin);
468
- }
469
- for (const eachBase of baseList) {
470
- visited.add(eachBase.fullName);
471
- if (shouldTraverseDown(eachBase))
472
- this.traverseBaseClass(eachBase, visited, shouldTraverseDown);
473
- }
474
- }
475
- /**
476
- * Add required typescript class that is to be imported from a required module during Schema conversion to typescript. If there is naming conflict
477
- * it will resolve it by appending prefix name with class name, for example: import { element as BisCoreElement } from "BisCoreElement";
478
- * @param classNameToModule Typescript modules that is needed for the conversion. It maps typescript class with the required modules
479
- * @param refModule Typescript module that the typescrip class comes from
480
- * @param className Required Typescript class for the conversion
481
- */
482
- addImportClass(classNameToModule, refModule, className) {
483
- if (!classNameToModule.has(className)) {
484
- classNameToModule.set(className, refModule);
485
- return className;
486
- }
487
- if (classNameToModule.get(className) === refModule)
488
- return className;
489
- let resolvedPrefix = refModule;
490
- if (this._tsBentleyModuleResolvedConflictNames.has(refModule))
491
- resolvedPrefix = this._tsBentleyModuleResolvedConflictNames.get(refModule);
492
- const renameClassName = `${className} as ${resolvedPrefix}${className}`;
493
- if (!classNameToModule.has(renameClassName)) {
494
- classNameToModule.set(renameClassName, refModule);
495
- }
496
- return resolvedPrefix + className;
497
- }
498
- /**
499
- * Add appropriate typescript props interface to the classNameToModule and return the corresponding typescript base props interface
500
- * @param classNameToModule Typescript modules that is needed for the conversion. It maps typescript class with the required modules
501
- * @param baseECClass Base class of ecClass that has properties. Its name will be used to derived typescript base props interface
502
- * @param ecClass ECClass to be converted to Typescript
503
- */
504
- addImportBasePropsClass(classNameToModule, baseECClass, ecClass) {
505
- let baseName = baseECClass.name;
506
- if (baseECClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass)
507
- baseName += "Props";
508
- // find external module to import
509
- let externalModule = "";
510
- const shouldImportJsCommon = (baseECClass.fullName === elementECClassName) ||
511
- (baseECClass.schema.schemaKey.name === "BisCore" && ecClass.schema.schemaKey.name !== "BisCore");
512
- if (shouldImportJsCommon)
513
- externalModule = tsBentleyModules.tsIModelJsCommon.moduleName;
514
- else if (!baseECClass.schema.schemaKey.compareByName(ecClass.schema.schemaKey))
515
- externalModule = `${baseECClass.schema.schemaKey.name}ElementProps`;
516
- if (externalModule.length !== 0)
517
- baseName = this.addImportClass(classNameToModule, externalModule, baseName);
518
- return baseName;
519
- }
520
- /**
521
- * Add appropriate typescript base class to the classNameToModule and return the corresponding typescript base class
522
- * @param classNameToModule Typescript modules that is needed for the conversion. It maps typescript class with the required modules
523
- * @param baseECClass Base class of ecClass
524
- * @param ecClass ECClass to be converted to Typescript
525
- */
526
- addImportBaseClass(classNameToModule, baseECClass, ecClass) {
527
- let baseName = baseECClass.name;
528
- // find external module to import for base class
529
- let externalModule = "";
530
- if (baseECClass.schema.schemaKey.name === "BisCore" && ecClass.schema.schemaKey.name !== "BisCore")
531
- externalModule = tsBentleyModules.tsIModelJsBackend.moduleName;
532
- else if (!baseECClass.schema.schemaKey.compareByName(ecClass.schema.schemaKey))
533
- externalModule = `${baseECClass.schema.schemaKey.name}Elements`;
534
- if (externalModule.length !== 0)
535
- baseName = this.addImportClass(classNameToModule, externalModule, baseName);
536
- return baseName;
537
- }
538
- /**
539
- * Lower the first character of the property name
540
- * @param propName Property name
541
- */
542
- lowerPropertyName(propName) {
543
- return propName.charAt(0).toLowerCase() + propName.slice(1);
544
- }
545
- }
546
- exports.ECSchemaToTs = ECSchemaToTs;
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ECSchemaToTs = void 0;
8
+ const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
9
+ const customHandledPropertyCA = "BisCore.CustomHandledProperty";
10
+ const elementECClassName = "BisCore.Element";
11
+ const tsBentleyModules = {
12
+ tsIModelJsCommon: {
13
+ moduleName: "@itwin/core-common",
14
+ resolvedConflictName: "BeIModelJsCommon",
15
+ },
16
+ tsIModelJsBackend: {
17
+ moduleName: "@itwin/core-backend",
18
+ resolvedConflictName: "BeIModelJsBackend",
19
+ },
20
+ tsGeometryCore: {
21
+ moduleName: "@itwin/core-geometry",
22
+ resolvedConflictName: "BeGeometryCore",
23
+ },
24
+ tsBentleyJsCore: {
25
+ moduleName: "@itwin/core-bentley",
26
+ resolvedConflictName: "BeBentleyJsCore",
27
+ },
28
+ };
29
+ /**
30
+ * @beta
31
+ */
32
+ class ECSchemaToTs {
33
+ constructor() {
34
+ this._schema = undefined;
35
+ this._schemaItemList = [];
36
+ this._tsBentleyModuleNames = new Set();
37
+ this._tsBentleyModuleResolvedConflictNames = new Map();
38
+ for (const key in tsBentleyModules) {
39
+ if (tsBentleyModules.hasOwnProperty(key)) {
40
+ const moduleName = tsBentleyModules[key].moduleName;
41
+ const resolvedPrefix = tsBentleyModules[key].resolvedConflictName;
42
+ this._tsBentleyModuleNames.add(moduleName);
43
+ this._tsBentleyModuleResolvedConflictNames.set(moduleName, resolvedPrefix);
44
+ }
45
+ }
46
+ }
47
+ /**
48
+ * Given the schema, the function will converted it to typescript strings
49
+ * @param schema The schema to be converted to typescript strings
50
+ */
51
+ convertSchemaToTs(schema) {
52
+ // convert schema to typescript String
53
+ this._schema = schema;
54
+ this.dependencyToFront();
55
+ const schemaTsString = this.convertSchemaToTsClass();
56
+ const elemTsString = this.convertElemToTsClasses();
57
+ const propsTsString = this.convertPropsToTsInterfaces();
58
+ return { schemaTsString, elemTsString, propsTsString };
59
+ }
60
+ /**
61
+ * The function will push all the base classes to be the first ones in the schema item list.
62
+ * For example, if class A extends base class B and base class C, B and C will be on the first of the list and then A at the end.
63
+ * If B extends C, then B will be first and C will be next in the list and then A at the end.
64
+ * If B and C does not depend on each other, the order of B and C will not be important.
65
+ * The arrangement is to make sure that base class will be converted first and then, derived classes and so on
66
+ */
67
+ dependencyToFront() {
68
+ const uniqueItemName = new Set();
69
+ const schemaItemsList = [];
70
+ for (const schemaItem of this._schema.getItems()) {
71
+ // base class to the item list first;
72
+ switch (schemaItem.schemaItemType) {
73
+ case ecschema_metadata_1.SchemaItemType.StructClass:
74
+ case ecschema_metadata_1.SchemaItemType.Mixin:
75
+ case ecschema_metadata_1.SchemaItemType.EntityClass:
76
+ const ecClass = schemaItem;
77
+ const baseList = this.getAllBaseClasses(ecClass);
78
+ for (let i = baseList.length - 1; i >= 0; --i) {
79
+ const base = baseList[i];
80
+ if (base.schema.schemaKey.compareByName(this._schema.schemaKey) && !uniqueItemName.has(base.name)) {
81
+ schemaItemsList.push(baseList[i]);
82
+ uniqueItemName.add(base.name);
83
+ }
84
+ }
85
+ break;
86
+ default:
87
+ break;
88
+ }
89
+ if (!uniqueItemName.has(schemaItem.name)) {
90
+ uniqueItemName.add(schemaItem.name);
91
+ schemaItemsList.push(schemaItem);
92
+ }
93
+ }
94
+ this._schemaItemList = schemaItemsList;
95
+ }
96
+ /**
97
+ * The function converts the schema meta data to typescript Schema class
98
+ */
99
+ convertSchemaToTsClass() {
100
+ const schemaName = this._schema.schemaKey.name;
101
+ let outputString = "";
102
+ // import modules
103
+ outputString += "import { ClassRegistry, Schema, Schemas } from \"@itwin/core-backend\";\n";
104
+ outputString += `import * as elementsModule from "./${schemaName}Elements";\n\n`;
105
+ // create new schema class
106
+ outputString += `export class ${schemaName} extends Schema {\n`;
107
+ // schemaName() method
108
+ outputString += ` public static get schemaName(): string { return "${schemaName}"; }\n\n`;
109
+ // registerSchema method
110
+ outputString += " public static registerSchema() {\n";
111
+ outputString += ` if (!Schemas.getRegisteredSchema(${schemaName}.name))\n`;
112
+ outputString += ` Schemas.registerSchema(${schemaName});\n`;
113
+ outputString += " }\n\n";
114
+ // constructor
115
+ outputString += " protected constructor() {\n";
116
+ outputString += " super();\n";
117
+ outputString += ` ClassRegistry.registerModule(elementsModule, ${schemaName});\n`;
118
+ outputString += " }\n";
119
+ outputString += "}\n\n";
120
+ return outputString;
121
+ }
122
+ /**
123
+ * The function converts the schema item to respective typescript classes
124
+ */
125
+ convertElemToTsClasses() {
126
+ const classNameToModule = new Map();
127
+ let classTs = "";
128
+ for (const schemaItem of this._schemaItemList) {
129
+ switch (schemaItem.schemaItemType) {
130
+ case ecschema_metadata_1.SchemaItemType.EntityClass:
131
+ classTs += this.convertEntityToTs(schemaItem, classNameToModule);
132
+ break;
133
+ case ecschema_metadata_1.SchemaItemType.Enumeration:
134
+ classTs += this.convertEnumToTs(schemaItem);
135
+ break;
136
+ default:
137
+ continue;
138
+ }
139
+ }
140
+ let outputString = this.convertImportToTsImport(classNameToModule);
141
+ outputString += `\n${classTs}`;
142
+ return outputString;
143
+ }
144
+ /**
145
+ * The function converts the schema item properties to respective typescript props interfaces
146
+ */
147
+ convertPropsToTsInterfaces() {
148
+ const classNameToModule = new Map();
149
+ let interfacesTs = "";
150
+ for (const schemaItem of this._schemaItemList) {
151
+ switch (schemaItem.schemaItemType) {
152
+ case ecschema_metadata_1.SchemaItemType.EntityClass:
153
+ case ecschema_metadata_1.SchemaItemType.Mixin:
154
+ case ecschema_metadata_1.SchemaItemType.StructClass:
155
+ interfacesTs += this.convertECClassPropsToTsInterface(schemaItem, classNameToModule);
156
+ break;
157
+ default:
158
+ continue;
159
+ }
160
+ }
161
+ let outputString = this.convertImportToTsImport(classNameToModule);
162
+ outputString += `\n${interfacesTs}`;
163
+ return outputString;
164
+ }
165
+ /**
166
+ * Convert mixin or struct class or entity class to respective typescript interface
167
+ * @param ecClass Schema mixin or struct or entity to be converted typescript interface
168
+ * @param classNameToModule Typescrip modules to be updated after the conversion
169
+ */
170
+ convertECClassPropsToTsInterface(ecClass, classNameToModule) {
171
+ let interfacesTs = "";
172
+ // no interface props for BisCore Element
173
+ if (ecClass.fullName === elementECClassName)
174
+ return interfacesTs;
175
+ // only generate props interface for entity if the class has properties
176
+ if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass && (!ecClass.properties || ecClass.properties.next().done))
177
+ return interfacesTs;
178
+ // convert description to typescript comment only for mixin or struct
179
+ if (ecClass.schemaItemType !== ecschema_metadata_1.SchemaItemType.EntityClass && ecClass.description)
180
+ interfacesTs += `${this.convertDescriptionToTsComment(ecClass.description)}\n`;
181
+ // build interface for props in ecClass
182
+ interfacesTs += `export interface ${ecClass.name}`;
183
+ if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass)
184
+ interfacesTs += "Props";
185
+ // Extend it with base ecClass Props interface if there is any
186
+ const baseClasses = this.getBaseClassWithProps(ecClass);
187
+ if (baseClasses.length > 0) {
188
+ interfacesTs += " extends ";
189
+ let separator = "";
190
+ for (const base of baseClasses) {
191
+ interfacesTs += separator + this.addImportBasePropsClass(classNameToModule, base, ecClass);
192
+ separator = ", ";
193
+ }
194
+ }
195
+ else if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass)
196
+ interfacesTs += ` extends ${this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsCommon.moduleName, "EntityProps")}`;
197
+ // build props for ecClass
198
+ interfacesTs += " {";
199
+ const propertiesTs = this.convertPropsToTsVars(ecClass, classNameToModule);
200
+ for (const varDeclarationLine of propertiesTs)
201
+ interfacesTs += `\n ${varDeclarationLine}`;
202
+ interfacesTs += "\n}\n\n";
203
+ return interfacesTs;
204
+ }
205
+ /**
206
+ * Convert schema enumeration to typescript enumeration
207
+ * @param ecEnum Schema enumeration to be converted to typescript enumeration
208
+ */
209
+ convertEnumToTs(ecEnum) {
210
+ let outputString = "";
211
+ if (ecEnum.description)
212
+ outputString += `${this.convertDescriptionToTsComment(ecEnum.description)}\n`;
213
+ outputString += `export const enum ${ecEnum.name} {\n`;
214
+ for (const ecEnumerator of ecEnum.enumerators) {
215
+ outputString += ` ${ecEnumerator.label}`;
216
+ if (ecEnum.isInt)
217
+ outputString += ` = ${ecEnumerator.value}`;
218
+ else if (ecEnum.isString)
219
+ outputString += ` = "${ecEnumerator.value}"`;
220
+ outputString += ",\n";
221
+ }
222
+ outputString += "}\n\n";
223
+ return outputString;
224
+ }
225
+ /**
226
+ * Convert schema entity to typescript entity class. The typescript class will implement respective props
227
+ * typescript interface if the schema entity class has properties
228
+ * @param ecClass Schema class to be converted to typescript class
229
+ * @param classNameToModule Typescrip modules to be updated after the conversion
230
+ */
231
+ convertEntityToTs(ecClass, classNameToModule) {
232
+ let outputString = "";
233
+ if (ecClass.description)
234
+ outputString += `${this.convertDescriptionToTsComment(ecClass.description)}\n`;
235
+ let modifier = "";
236
+ if (ecClass.modifier === ecschema_metadata_1.ECClassModifier.Abstract)
237
+ modifier = "abstract ";
238
+ outputString += `export ${modifier}class ${ecClass.name} extends `;
239
+ // extend base class if there is any. Default will be Entity class defined in @itwin/core-backend
240
+ const base = ecClass.getBaseClassSync();
241
+ if (base)
242
+ outputString += this.addImportBaseClass(classNameToModule, base, ecClass);
243
+ else
244
+ outputString += this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsBackend.moduleName, "Entity");
245
+ // determine prop type to pass in the constructor
246
+ let propsBaseTsType;
247
+ const propsBase = this.getBaseClassWithProps(ecClass);
248
+ if (ecClass.fullName !== elementECClassName && ecClass.properties && !ecClass.properties.next().done) {
249
+ const moduleName = `${this._schema.schemaKey.name}ElementProps`;
250
+ propsBaseTsType = this.addImportClass(classNameToModule, moduleName, `${ecClass.name}Props`);
251
+ }
252
+ else if (propsBase.length > 0)
253
+ propsBaseTsType = this.addImportBasePropsClass(classNameToModule, propsBase[0], ecClass);
254
+ else
255
+ propsBaseTsType = this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsCommon.moduleName, "EntityProps");
256
+ // implement the ecClass props if it has properties
257
+ if (`${ecClass.name}Props` === propsBaseTsType)
258
+ outputString += ` implements ${propsBaseTsType}`;
259
+ // write constructor and className function for class
260
+ const iModelDbTsType = this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsBackend.moduleName, "IModelDb");
261
+ outputString += " {\n";
262
+ outputString += ` public static get className(): string { return "${ecClass.name}"; }\n\n`;
263
+ outputString += ` public constructor (props: ${propsBaseTsType}, iModel: ${iModelDbTsType}) {\n`;
264
+ outputString += " super(props, iModel);\n";
265
+ outputString += " }\n";
266
+ outputString += "}\n\n";
267
+ return outputString;
268
+ }
269
+ /**
270
+ * Convert class properties to typescript member declaration
271
+ * @param ecClass The schema class that has the properties to be converted to typescript member variables
272
+ * @param classNameToModule Typescrip modules to be updated after the conversion
273
+ */
274
+ convertPropsToTsVars(ecClass, classNameToModule) {
275
+ if (ecClass.properties === undefined || ecClass.properties.next().done)
276
+ return [];
277
+ const outputStrings = [];
278
+ for (const ecProperty of ecClass.properties) {
279
+ // not generate ts variable declaration for property that has CustomHandledProperty ca
280
+ if (ecProperty.customAttributes && ecProperty.customAttributes.has(customHandledPropertyCA))
281
+ continue;
282
+ let varDeclarationLine = `${this.lowerPropertyName(ecProperty.name)}?: `;
283
+ if (ecProperty.isPrimitive()) {
284
+ // determine Ts type of the primitive
285
+ let typeTs = "";
286
+ if (ecProperty.extendedTypeName)
287
+ typeTs = this.convertExtendedTypeNameToTsType(ecProperty.extendedTypeName, classNameToModule);
288
+ else if (ecProperty.isEnumeration()) {
289
+ const ecEnumProperty = ecProperty;
290
+ const ecEnum = ecEnumProperty.enumeration;
291
+ typeTs = this.addImportClass(classNameToModule, `${ecEnum.schemaKey.name}Elements`, ecEnum.name);
292
+ }
293
+ else {
294
+ const ecPrimitiveProperty = ecProperty;
295
+ typeTs = this.convertPrimitiveTypeToTsType(ecPrimitiveProperty.primitiveType, classNameToModule);
296
+ }
297
+ varDeclarationLine += typeTs;
298
+ }
299
+ else if (ecProperty.isStruct()) {
300
+ // import struct class if it is in different schema
301
+ const ecStructProperty = ecProperty;
302
+ const structClass = ecStructProperty.structClass;
303
+ if (!structClass.schema.schemaKey.compareByName(ecClass.schema.schemaKey))
304
+ varDeclarationLine += this.addImportClass(classNameToModule, `${structClass.schema.schemaKey.name}ElementProps`, structClass.name);
305
+ else
306
+ varDeclarationLine += structClass.name;
307
+ }
308
+ else if (ecProperty.isNavigation())
309
+ varDeclarationLine += this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsCommon.moduleName, "RelatedElementProps");
310
+ if (ecProperty.isArray())
311
+ varDeclarationLine += "[]";
312
+ varDeclarationLine += ";";
313
+ outputStrings.push(varDeclarationLine);
314
+ }
315
+ return outputStrings;
316
+ }
317
+ /**
318
+ * Convert schema extended type to typescript type
319
+ * @param typeName Schema extended type to be converted to typescript type
320
+ * @param classNameToModule Typescrip modules to be updated after the conversion
321
+ */
322
+ convertExtendedTypeNameToTsType(typeName, classNameToModule) {
323
+ switch (typeName) {
324
+ case "Json":
325
+ return "any";
326
+ case "BeGuid":
327
+ return this.addImportClass(classNameToModule, tsBentleyModules.tsBentleyJsCore.moduleName, "GuidString");
328
+ default:
329
+ return "any";
330
+ }
331
+ }
332
+ /**
333
+ * Convert schema primitive type to typescript type
334
+ * @param type Schema primitive type to be converted to typescript type
335
+ * @param classNameToModule Typescrip modules to be updated after the conversion
336
+ */
337
+ convertPrimitiveTypeToTsType(type, classNameToModule) {
338
+ switch (type) {
339
+ case ecschema_metadata_1.PrimitiveType.Binary:
340
+ return "any";
341
+ case ecschema_metadata_1.PrimitiveType.Boolean:
342
+ return "boolean";
343
+ case ecschema_metadata_1.PrimitiveType.DateTime:
344
+ return "Date";
345
+ case ecschema_metadata_1.PrimitiveType.Double:
346
+ return "number";
347
+ case ecschema_metadata_1.PrimitiveType.Integer:
348
+ return "number";
349
+ case ecschema_metadata_1.PrimitiveType.Long:
350
+ // eslint-disable-next-line no-console
351
+ console.log("Primitive type Long is not currently supported during conversion. It will be treated as type 'any'");
352
+ return "any";
353
+ case ecschema_metadata_1.PrimitiveType.String:
354
+ return "string";
355
+ case ecschema_metadata_1.PrimitiveType.Point2d:
356
+ return this.addImportClass(classNameToModule, tsBentleyModules.tsGeometryCore.moduleName, "Point2d");
357
+ case ecschema_metadata_1.PrimitiveType.Point3d:
358
+ return this.addImportClass(classNameToModule, tsBentleyModules.tsGeometryCore.moduleName, "Point3d");
359
+ case ecschema_metadata_1.PrimitiveType.IGeometry:
360
+ // eslint-disable-next-line no-console
361
+ console.log("Primitive type IGeometry is not currently supported during conversion. It will be treated as type 'any'");
362
+ return "any";
363
+ default:
364
+ // eslint-disable-next-line no-console
365
+ console.log("Unknown primitive type during conversion. It will be treated as type 'any'");
366
+ return "any";
367
+ }
368
+ }
369
+ /**
370
+ * Convert schema description to typescript comment
371
+ * @param description Schema description to be converted to typescript comment
372
+ */
373
+ convertDescriptionToTsComment(description) {
374
+ let outputString = "/**\n";
375
+ let wordCount = 0;
376
+ let begin = 0;
377
+ let spaceBegin = 0;
378
+ let spaceIdx = description.indexOf(" ", spaceBegin);
379
+ while (spaceIdx !== -1) {
380
+ // new line for every 20 words
381
+ ++wordCount;
382
+ if (wordCount === 20) {
383
+ wordCount = 0;
384
+ outputString += ` * ${description.substring(begin, spaceIdx)}\n`;
385
+ begin = spaceIdx + 1;
386
+ }
387
+ spaceBegin = spaceIdx + 1;
388
+ while (description[spaceBegin] === " ")
389
+ ++spaceBegin;
390
+ spaceIdx = description.indexOf(" ", spaceBegin);
391
+ }
392
+ // append the last word
393
+ outputString += ` * ${description.substring(begin)}\n`;
394
+ outputString += " */";
395
+ return outputString;
396
+ }
397
+ /**
398
+ * Convert all modules needed for the converted schema types to typescript import statements
399
+ * @param classNameToModule Modules to be converted to typescript imports statement
400
+ */
401
+ convertImportToTsImport(classNameToModule) {
402
+ const moduleToTsTypes = new Map();
403
+ classNameToModule.forEach((moduleNames, className) => {
404
+ if (!moduleToTsTypes.has(moduleNames))
405
+ moduleToTsTypes.set(moduleNames, new Set());
406
+ moduleToTsTypes.get(moduleNames).add(className);
407
+ });
408
+ let outputString = "";
409
+ moduleToTsTypes.forEach((classNames, moduleName) => {
410
+ if (!this._tsBentleyModuleNames.has(moduleName))
411
+ moduleName = `./${moduleName}`;
412
+ outputString += "import { ";
413
+ let separator = "";
414
+ for (const className of classNames) {
415
+ outputString += separator + className;
416
+ separator = ", ";
417
+ }
418
+ outputString += ` } from "${moduleName}";\n`;
419
+ });
420
+ return outputString;
421
+ }
422
+ /**
423
+ * Traverse the inheritance tree to retrieve first base classes that have properties
424
+ * @param ecClass Schema class to be traverse
425
+ */
426
+ getBaseClassWithProps(ecClass) {
427
+ const res = [];
428
+ const visited = new Set();
429
+ visited.add(ecClass.fullName);
430
+ this.traverseBaseClass(ecClass, visited, (base) => {
431
+ if (base.properties && !base.properties.next().done) {
432
+ res.push(base);
433
+ return false;
434
+ }
435
+ return true;
436
+ });
437
+ return res;
438
+ }
439
+ /**
440
+ * Traverse the inheritance tree to retrieve base classes of a schema class
441
+ * @param ecClass Schema class to be traverse
442
+ */
443
+ getAllBaseClasses(ecClass) {
444
+ const res = [];
445
+ const visited = new Set();
446
+ visited.add(ecClass.fullName);
447
+ this.traverseBaseClass(ecClass, visited, (base) => {
448
+ res.push(base);
449
+ return true;
450
+ });
451
+ return res;
452
+ }
453
+ /**
454
+ * Traverse the inheritance tree horizontally and vertically of a schema class
455
+ * @param ecClass Schema class to be traverse
456
+ * @param visited Set of classes that are already visited
457
+ * @param shouldTraverseDown Lambda to determine if it should traverse more vertically
458
+ */
459
+ traverseBaseClass(ecClass, visited, shouldTraverseDown) {
460
+ const base = ecClass.getBaseClassSync();
461
+ if (base === undefined || visited.has(base.fullName))
462
+ return;
463
+ const baseList = [base];
464
+ if (ecClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass) {
465
+ const entity = ecClass;
466
+ for (const mixin of entity.getMixinsSync())
467
+ baseList.push(mixin);
468
+ }
469
+ for (const eachBase of baseList) {
470
+ visited.add(eachBase.fullName);
471
+ if (shouldTraverseDown(eachBase))
472
+ this.traverseBaseClass(eachBase, visited, shouldTraverseDown);
473
+ }
474
+ }
475
+ /**
476
+ * Add required typescript class that is to be imported from a required module during Schema conversion to typescript. If there is naming conflict
477
+ * it will resolve it by appending prefix name with class name, for example: import { element as BisCoreElement } from "BisCoreElement";
478
+ * @param classNameToModule Typescript modules that is needed for the conversion. It maps typescript class with the required modules
479
+ * @param refModule Typescript module that the typescrip class comes from
480
+ * @param className Required Typescript class for the conversion
481
+ */
482
+ addImportClass(classNameToModule, refModule, className) {
483
+ if (!classNameToModule.has(className)) {
484
+ classNameToModule.set(className, refModule);
485
+ return className;
486
+ }
487
+ if (classNameToModule.get(className) === refModule)
488
+ return className;
489
+ let resolvedPrefix = refModule;
490
+ if (this._tsBentleyModuleResolvedConflictNames.has(refModule))
491
+ resolvedPrefix = this._tsBentleyModuleResolvedConflictNames.get(refModule);
492
+ const renameClassName = `${className} as ${resolvedPrefix}${className}`;
493
+ if (!classNameToModule.has(renameClassName)) {
494
+ classNameToModule.set(renameClassName, refModule);
495
+ }
496
+ return resolvedPrefix + className;
497
+ }
498
+ /**
499
+ * Add appropriate typescript props interface to the classNameToModule and return the corresponding typescript base props interface
500
+ * @param classNameToModule Typescript modules that is needed for the conversion. It maps typescript class with the required modules
501
+ * @param baseECClass Base class of ecClass that has properties. Its name will be used to derived typescript base props interface
502
+ * @param ecClass ECClass to be converted to Typescript
503
+ */
504
+ addImportBasePropsClass(classNameToModule, baseECClass, ecClass) {
505
+ let baseName = baseECClass.name;
506
+ if (baseECClass.schemaItemType === ecschema_metadata_1.SchemaItemType.EntityClass)
507
+ baseName += "Props";
508
+ // find external module to import
509
+ let externalModule = "";
510
+ const shouldImportJsCommon = (baseECClass.fullName === elementECClassName) ||
511
+ (baseECClass.schema.schemaKey.name === "BisCore" && ecClass.schema.schemaKey.name !== "BisCore");
512
+ if (shouldImportJsCommon)
513
+ externalModule = tsBentleyModules.tsIModelJsCommon.moduleName;
514
+ else if (!baseECClass.schema.schemaKey.compareByName(ecClass.schema.schemaKey))
515
+ externalModule = `${baseECClass.schema.schemaKey.name}ElementProps`;
516
+ if (externalModule.length !== 0)
517
+ baseName = this.addImportClass(classNameToModule, externalModule, baseName);
518
+ return baseName;
519
+ }
520
+ /**
521
+ * Add appropriate typescript base class to the classNameToModule and return the corresponding typescript base class
522
+ * @param classNameToModule Typescript modules that is needed for the conversion. It maps typescript class with the required modules
523
+ * @param baseECClass Base class of ecClass
524
+ * @param ecClass ECClass to be converted to Typescript
525
+ */
526
+ addImportBaseClass(classNameToModule, baseECClass, ecClass) {
527
+ let baseName = baseECClass.name;
528
+ // find external module to import for base class
529
+ let externalModule = "";
530
+ if (baseECClass.schema.schemaKey.name === "BisCore" && ecClass.schema.schemaKey.name !== "BisCore")
531
+ externalModule = tsBentleyModules.tsIModelJsBackend.moduleName;
532
+ else if (!baseECClass.schema.schemaKey.compareByName(ecClass.schema.schemaKey))
533
+ externalModule = `${baseECClass.schema.schemaKey.name}Elements`;
534
+ if (externalModule.length !== 0)
535
+ baseName = this.addImportClass(classNameToModule, externalModule, baseName);
536
+ return baseName;
537
+ }
538
+ /**
539
+ * Lower the first character of the property name
540
+ * @param propName Property name
541
+ */
542
+ lowerPropertyName(propName) {
543
+ return propName.charAt(0).toLowerCase() + propName.slice(1);
544
+ }
545
+ }
546
+ exports.ECSchemaToTs = ECSchemaToTs;
547
547
  //# sourceMappingURL=ecschema2ts.js.map