@itwin/ecschema-metadata 5.10.0-dev.9 → 5.11.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/lib/cjs/Constants.js.map +1 -1
  3. package/lib/cjs/DelayedPromise.js.map +1 -1
  4. package/lib/cjs/Deserialization/AbstractParser.js.map +1 -1
  5. package/lib/cjs/Deserialization/Helper.js.map +1 -1
  6. package/lib/cjs/Deserialization/JsonParser.js.map +1 -1
  7. package/lib/cjs/Deserialization/JsonProps.js.map +1 -1
  8. package/lib/cjs/Deserialization/SchemaGraphUtil.js.map +1 -1
  9. package/lib/cjs/Deserialization/XmlParser.js.map +1 -1
  10. package/lib/cjs/Deserialization/XmlSerializationUtils.js.map +1 -1
  11. package/lib/cjs/ECName.js.map +1 -1
  12. package/lib/cjs/ECObjects.js.map +1 -1
  13. package/lib/cjs/Exception.js.map +1 -1
  14. package/lib/cjs/Formatting/FormatSetFormatsProvider.js.map +1 -1
  15. package/lib/cjs/Formatting/SchemaFormatsProvider.js.map +1 -1
  16. package/lib/cjs/IncrementalLoading/ClassParsers.js.map +1 -1
  17. package/lib/cjs/IncrementalLoading/ECSqlSchemaLocater.js.map +1 -1
  18. package/lib/cjs/IncrementalLoading/FullSchemaQueries.js +466 -466
  19. package/lib/cjs/IncrementalLoading/FullSchemaQueries.js.map +1 -1
  20. package/lib/cjs/IncrementalLoading/IncrementalSchemaLocater.js.map +1 -1
  21. package/lib/cjs/IncrementalLoading/IncrementalSchemaReader.js.map +1 -1
  22. package/lib/cjs/IncrementalLoading/SchemaItemParsers.js.map +1 -1
  23. package/lib/cjs/IncrementalLoading/SchemaItemQueries.js +235 -235
  24. package/lib/cjs/IncrementalLoading/SchemaItemQueries.js.map +1 -1
  25. package/lib/cjs/IncrementalLoading/SchemaParser.js.map +1 -1
  26. package/lib/cjs/IncrementalLoading/SchemaStubQueries.js +309 -309
  27. package/lib/cjs/IncrementalLoading/SchemaStubQueries.js.map +1 -1
  28. package/lib/cjs/Interfaces.js.map +1 -1
  29. package/lib/cjs/Metadata/Class.js.map +1 -1
  30. package/lib/cjs/Metadata/Constant.js.map +1 -1
  31. package/lib/cjs/Metadata/CustomAttribute.js.map +1 -1
  32. package/lib/cjs/Metadata/CustomAttributeClass.js.map +1 -1
  33. package/lib/cjs/Metadata/EntityClass.js.map +1 -1
  34. package/lib/cjs/Metadata/Enumeration.js.map +1 -1
  35. package/lib/cjs/Metadata/Format.js.map +1 -1
  36. package/lib/cjs/Metadata/InvertedUnit.js.map +1 -1
  37. package/lib/cjs/Metadata/KindOfQuantity.js.map +1 -1
  38. package/lib/cjs/Metadata/Mixin.js.map +1 -1
  39. package/lib/cjs/Metadata/OverrideFormat.js.map +1 -1
  40. package/lib/cjs/Metadata/Phenomenon.js.map +1 -1
  41. package/lib/cjs/Metadata/Property.js.map +1 -1
  42. package/lib/cjs/Metadata/PropertyCategory.js.map +1 -1
  43. package/lib/cjs/Metadata/RelationshipClass.js.map +1 -1
  44. package/lib/cjs/Metadata/Schema.js.map +1 -1
  45. package/lib/cjs/Metadata/SchemaItem.js.map +1 -1
  46. package/lib/cjs/Metadata/UnitSystem.js.map +1 -1
  47. package/lib/cjs/PropertyTypes.js.map +1 -1
  48. package/lib/cjs/SchemaJsonLocater.js.map +1 -1
  49. package/lib/cjs/SchemaKey.js.map +1 -1
  50. package/lib/cjs/SchemaLoader.js.map +1 -1
  51. package/lib/cjs/SchemaPartVisitorDelegate.js.map +1 -1
  52. package/lib/cjs/SchemaView.d.ts +653 -0
  53. package/lib/cjs/SchemaView.d.ts.map +1 -0
  54. package/lib/cjs/SchemaView.js +1204 -0
  55. package/lib/cjs/SchemaView.js.map +1 -0
  56. package/lib/cjs/SchemaViewBinaryReader.d.ts +16 -0
  57. package/lib/cjs/SchemaViewBinaryReader.d.ts.map +1 -0
  58. package/lib/cjs/SchemaViewBinaryReader.js +610 -0
  59. package/lib/cjs/SchemaViewBinaryReader.js.map +1 -0
  60. package/lib/cjs/SchemaViewInterfaces.d.ts +220 -0
  61. package/lib/cjs/SchemaViewInterfaces.d.ts.map +1 -0
  62. package/lib/cjs/SchemaViewInterfaces.js +69 -0
  63. package/lib/cjs/SchemaViewInterfaces.js.map +1 -0
  64. package/lib/cjs/UnitConversion/UnitConverter.js.map +1 -1
  65. package/lib/cjs/UnitConversion/UnitTree.js.map +1 -1
  66. package/lib/cjs/UnitProvider/SchemaUnitProvider.js.map +1 -1
  67. package/lib/cjs/Validation/SchemaWalker.js.map +1 -1
  68. package/lib/cjs/ecschema-metadata.d.ts +3 -0
  69. package/lib/cjs/ecschema-metadata.d.ts.map +1 -1
  70. package/lib/cjs/ecschema-metadata.js +3 -0
  71. package/lib/cjs/ecschema-metadata.js.map +1 -1
  72. package/lib/cjs/utils/ECClassHierarchy.js.map +1 -1
  73. package/lib/cjs/utils/SchemaGraph.js.map +1 -1
  74. package/lib/cjs/utils/SchemaLoadingController.js.map +1 -1
  75. package/lib/esm/Constants.js.map +1 -1
  76. package/lib/esm/DelayedPromise.js.map +1 -1
  77. package/lib/esm/Deserialization/AbstractParser.js.map +1 -1
  78. package/lib/esm/Deserialization/Helper.js.map +1 -1
  79. package/lib/esm/Deserialization/JsonParser.js.map +1 -1
  80. package/lib/esm/Deserialization/JsonProps.js.map +1 -1
  81. package/lib/esm/Deserialization/SchemaGraphUtil.js.map +1 -1
  82. package/lib/esm/Deserialization/XmlParser.js.map +1 -1
  83. package/lib/esm/Deserialization/XmlSerializationUtils.js.map +1 -1
  84. package/lib/esm/ECName.js.map +1 -1
  85. package/lib/esm/ECObjects.js.map +1 -1
  86. package/lib/esm/Exception.js.map +1 -1
  87. package/lib/esm/Formatting/FormatSetFormatsProvider.js.map +1 -1
  88. package/lib/esm/Formatting/SchemaFormatsProvider.js.map +1 -1
  89. package/lib/esm/IncrementalLoading/ClassParsers.js.map +1 -1
  90. package/lib/esm/IncrementalLoading/ECSqlSchemaLocater.js.map +1 -1
  91. package/lib/esm/IncrementalLoading/FullSchemaQueries.js +466 -466
  92. package/lib/esm/IncrementalLoading/FullSchemaQueries.js.map +1 -1
  93. package/lib/esm/IncrementalLoading/IncrementalSchemaLocater.js.map +1 -1
  94. package/lib/esm/IncrementalLoading/IncrementalSchemaReader.js.map +1 -1
  95. package/lib/esm/IncrementalLoading/SchemaItemParsers.js.map +1 -1
  96. package/lib/esm/IncrementalLoading/SchemaItemQueries.js +235 -235
  97. package/lib/esm/IncrementalLoading/SchemaItemQueries.js.map +1 -1
  98. package/lib/esm/IncrementalLoading/SchemaParser.js.map +1 -1
  99. package/lib/esm/IncrementalLoading/SchemaStubQueries.js +309 -309
  100. package/lib/esm/IncrementalLoading/SchemaStubQueries.js.map +1 -1
  101. package/lib/esm/Interfaces.js.map +1 -1
  102. package/lib/esm/Metadata/Class.js.map +1 -1
  103. package/lib/esm/Metadata/Constant.js.map +1 -1
  104. package/lib/esm/Metadata/CustomAttribute.js.map +1 -1
  105. package/lib/esm/Metadata/CustomAttributeClass.js.map +1 -1
  106. package/lib/esm/Metadata/EntityClass.js.map +1 -1
  107. package/lib/esm/Metadata/Enumeration.js.map +1 -1
  108. package/lib/esm/Metadata/Format.js.map +1 -1
  109. package/lib/esm/Metadata/InvertedUnit.js.map +1 -1
  110. package/lib/esm/Metadata/KindOfQuantity.js.map +1 -1
  111. package/lib/esm/Metadata/Mixin.js.map +1 -1
  112. package/lib/esm/Metadata/OverrideFormat.js.map +1 -1
  113. package/lib/esm/Metadata/Phenomenon.js.map +1 -1
  114. package/lib/esm/Metadata/Property.js.map +1 -1
  115. package/lib/esm/Metadata/PropertyCategory.js.map +1 -1
  116. package/lib/esm/Metadata/RelationshipClass.js.map +1 -1
  117. package/lib/esm/Metadata/Schema.js.map +1 -1
  118. package/lib/esm/Metadata/SchemaItem.js.map +1 -1
  119. package/lib/esm/Metadata/UnitSystem.js.map +1 -1
  120. package/lib/esm/PropertyTypes.js.map +1 -1
  121. package/lib/esm/SchemaJsonLocater.js.map +1 -1
  122. package/lib/esm/SchemaKey.js.map +1 -1
  123. package/lib/esm/SchemaLoader.js.map +1 -1
  124. package/lib/esm/SchemaPartVisitorDelegate.js.map +1 -1
  125. package/lib/esm/SchemaView.d.ts +653 -0
  126. package/lib/esm/SchemaView.d.ts.map +1 -0
  127. package/lib/esm/SchemaView.js +1199 -0
  128. package/lib/esm/SchemaView.js.map +1 -0
  129. package/lib/esm/SchemaViewBinaryReader.d.ts +16 -0
  130. package/lib/esm/SchemaViewBinaryReader.d.ts.map +1 -0
  131. package/lib/esm/SchemaViewBinaryReader.js +607 -0
  132. package/lib/esm/SchemaViewBinaryReader.js.map +1 -0
  133. package/lib/esm/SchemaViewInterfaces.d.ts +220 -0
  134. package/lib/esm/SchemaViewInterfaces.d.ts.map +1 -0
  135. package/lib/esm/SchemaViewInterfaces.js +66 -0
  136. package/lib/esm/SchemaViewInterfaces.js.map +1 -0
  137. package/lib/esm/UnitConversion/UnitConverter.js.map +1 -1
  138. package/lib/esm/UnitConversion/UnitTree.js.map +1 -1
  139. package/lib/esm/UnitProvider/SchemaUnitProvider.js.map +1 -1
  140. package/lib/esm/Validation/SchemaWalker.js.map +1 -1
  141. package/lib/esm/ecschema-metadata.d.ts +3 -0
  142. package/lib/esm/ecschema-metadata.d.ts.map +1 -1
  143. package/lib/esm/ecschema-metadata.js +3 -0
  144. package/lib/esm/ecschema-metadata.js.map +1 -1
  145. package/lib/esm/utils/ECClassHierarchy.js.map +1 -1
  146. package/lib/esm/utils/SchemaGraph.js.map +1 -1
  147. package/lib/esm/utils/SchemaLoadingController.js.map +1 -1
  148. package/package.json +7 -7
@@ -0,0 +1,1204 @@
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
+ /** @packageDocumentation
7
+ * @module Schema
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SchemaViewBuilder = exports.SchemaView = void 0;
11
+ const SchemaViewInterfaces_1 = require("./SchemaViewInterfaces");
12
+ const SchemaViewBinaryReader_1 = require("./SchemaViewBinaryReader");
13
+ // Module-local symbol used as the storage key on SchemaView instances. Mirrors the pattern in
14
+ // core-backend/src/internal/Symbols.ts (e.g. `_nativeDb` on IModelDb): the data is reachable
15
+ // only by code in this module, since the symbol is not exported and not registered globally.
16
+ // The flyweight view classes (SchemaView.Schema, SchemaView.Class, etc.) live in the same file
17
+ // and access the storage through this symbol.
18
+ const _storage = Symbol("SchemaView.storage");
19
+ /** Read-only schema metadata view. Optimized for fast lookup and low memory usage.
20
+ *
21
+ * All data is stored in flat arrays. View objects (`SchemaView.Schema`, `SchemaView.Class`, etc.) are
22
+ * stateless wrappers that hold a reference to this view plus an index. They allocate nothing
23
+ * and cache nothing.
24
+ *
25
+ * The view is immutable after construction. Build it via `SchemaViewBuilder` or parse
26
+ * from a binary blob via `fromBinary`.
27
+ * @beta
28
+ */
29
+ class SchemaView {
30
+ /** @internal */
31
+ [_storage];
32
+ _schemaToken;
33
+ _outdated = false;
34
+ /** @internal */
35
+ constructor(data, schemaToken) {
36
+ this[_storage] = {
37
+ ...data,
38
+ transitiveBaseCache: new Map(),
39
+ derivedClassMap: undefined,
40
+ };
41
+ this._schemaToken = schemaToken ?? "";
42
+ }
43
+ /** SHA3-256 content hash of the ec_ schema tables at the time this view was built.
44
+ * Empty string if not set (e.g., when built from a builder without a token).
45
+ * @beta
46
+ */
47
+ get schemaToken() { return this._schemaToken; }
48
+ /** True if the host (`IModelDb` / `IModelConnection`) has replaced this view with a newer one.
49
+ * The view remains fully functional - it returns stale data rather than throwing.
50
+ * Consumers who stored a reference can check this flag for diagnostics.
51
+ * @beta
52
+ */
53
+ get isOutdated() { return this._outdated; }
54
+ /** Mark this view as outdated. Called by the host when a newer view replaces it.
55
+ * @internal
56
+ */
57
+ markOutdated() { this._outdated = true; }
58
+ /** Number of schemas in the view. */
59
+ get schemaCount() { return this[_storage].schemas.length; }
60
+ /** Number of classes across all schemas. */
61
+ get classCount() { return this[_storage].classes.length; }
62
+ /** Get a schema by name (case-insensitive). */
63
+ getSchema(name) {
64
+ const idx = this[_storage].schemaByName.get(name.toLowerCase());
65
+ return idx !== undefined ? new SchemaView.Schema(this, idx) : undefined;
66
+ }
67
+ /** Get a schema by alias (case-insensitive). */
68
+ getSchemaByAlias(alias) {
69
+ const idx = this[_storage].schemaByAlias.get(alias.toLowerCase());
70
+ return idx !== undefined ? new SchemaView.Schema(this, idx) : undefined;
71
+ }
72
+ /** Iterate all schemas. */
73
+ *getSchemas() {
74
+ for (let i = 0; i < this[_storage].schemas.length; i++)
75
+ yield new SchemaView.Schema(this, i);
76
+ }
77
+ /** Find a class by qualified name ("SchemaName:ClassName" or "SchemaName.ClassName").
78
+ * The namespace part matches schema name first, then alias. Case-insensitive.
79
+ */
80
+ findClass(qualifiedName) {
81
+ const idx = this.resolveClassIdx(qualifiedName);
82
+ return idx !== -1 ? SchemaView.createClass(this, idx) : undefined;
83
+ }
84
+ /** Find an enumeration by qualified name ("SchemaName:EnumName" or "SchemaName.EnumName").
85
+ * The namespace part matches schema name first, then alias. Case-insensitive.
86
+ */
87
+ findEnumeration(qualifiedName) {
88
+ const idx = this._resolveSchemaItemIdx(qualifiedName, this[_storage].enumByName);
89
+ return idx !== undefined ? new SchemaView.Enumeration(this, idx) : undefined;
90
+ }
91
+ /** Find a KindOfQuantity by qualified name ("SchemaName:KoqName" or "SchemaName.KoqName").
92
+ * The namespace part matches schema name first, then alias. Case-insensitive.
93
+ */
94
+ findKindOfQuantity(qualifiedName) {
95
+ const idx = this._resolveSchemaItemIdx(qualifiedName, this[_storage].koqByName);
96
+ return idx !== undefined ? new SchemaView.KindOfQuantity(this, idx) : undefined;
97
+ }
98
+ /** Find a PropertyCategory by qualified name ("SchemaName:CategoryName" or "SchemaName.CategoryName").
99
+ * The namespace part matches schema name first, then alias. Case-insensitive.
100
+ */
101
+ findPropertyCategory(qualifiedName) {
102
+ const idx = this._resolveSchemaItemIdx(qualifiedName, this[_storage].catByName);
103
+ return idx !== undefined ? new SchemaView.PropertyCategory(this, idx) : undefined;
104
+ }
105
+ /** Parse a binary blob into a SchemaView. Synchronous.
106
+ * @param blob - The binary blob from `PRAGMA schema_view`.
107
+ * @param schemaToken - Optional SHA3-256 content hash for cache invalidation.
108
+ * @beta
109
+ */
110
+ static fromBinary(blob, schemaToken) {
111
+ return (0, SchemaViewBinaryReader_1.parseSchemaViewBlob)(blob, schemaToken);
112
+ }
113
+ /** Build from a pre-populated builder (used by the binary parser).
114
+ * @internal
115
+ */
116
+ static fromBuilder(builder, schemaToken) {
117
+ return builder.build(schemaToken);
118
+ }
119
+ // --- Internal helpers used by view objects ---
120
+ /** Resolve a qualified "SchemaName:ItemName" (or dot-separated) to an index using the given
121
+ * per-schema name map. Returns undefined if not found. @internal */
122
+ _resolveSchemaItemIdx(qualifiedName, itemByName) {
123
+ const sep = qualifiedName.indexOf(":");
124
+ const dotSep = sep === -1 ? qualifiedName.indexOf(".") : -1;
125
+ const splitAt = sep !== -1 ? sep : dotSep;
126
+ if (splitAt === -1)
127
+ return undefined;
128
+ const ns = qualifiedName.substring(0, splitAt).toLowerCase();
129
+ const itemName = qualifiedName.substring(splitAt + 1).toLowerCase();
130
+ let schemaIdx = this[_storage].schemaByName.get(ns);
131
+ if (schemaIdx === undefined)
132
+ schemaIdx = this[_storage].schemaByAlias.get(ns);
133
+ if (schemaIdx === undefined)
134
+ return undefined;
135
+ return itemByName.get(schemaIdx)?.get(itemName);
136
+ }
137
+ /** @internal */
138
+ resolveClassIdx(qualifiedName) {
139
+ const sep = qualifiedName.indexOf(":");
140
+ const dotSep = sep === -1 ? qualifiedName.indexOf(".") : -1;
141
+ const splitAt = sep !== -1 ? sep : dotSep;
142
+ if (splitAt === -1)
143
+ return -1;
144
+ const ns = qualifiedName.substring(0, splitAt).toLowerCase();
145
+ const cn = qualifiedName.substring(splitAt + 1).toLowerCase();
146
+ let schemaIdx = this[_storage].schemaByName.get(ns);
147
+ if (schemaIdx === undefined)
148
+ schemaIdx = this[_storage].schemaByAlias.get(ns);
149
+ if (schemaIdx === undefined)
150
+ return -1;
151
+ const classMap = this[_storage].classByName.get(schemaIdx);
152
+ const classIdx = classMap?.get(cn);
153
+ return classIdx ?? -1;
154
+ }
155
+ /** @internal */
156
+ getTransitiveBases(classIdx) {
157
+ const cached = this[_storage].transitiveBaseCache.get(classIdx);
158
+ if (cached !== undefined)
159
+ return cached;
160
+ const result = new Set();
161
+ this._buildTransitiveBases(classIdx, result);
162
+ this[_storage].transitiveBaseCache.set(classIdx, result);
163
+ return result;
164
+ }
165
+ _buildTransitiveBases(classIdx, result) {
166
+ const cls = this[_storage].classes[classIdx];
167
+ if (cls === undefined)
168
+ return; // safety: dangling index from excluded schema
169
+ if (cls.baseClassIdx !== -1 && !result.has(cls.baseClassIdx)) {
170
+ result.add(cls.baseClassIdx);
171
+ this._buildTransitiveBases(cls.baseClassIdx, result);
172
+ }
173
+ for (let i = 0; i < cls.mixinCount; i++) {
174
+ const mixinIdx = this[_storage].classMixins[cls.mixinStartIdx + i];
175
+ if (mixinIdx === -1 || mixinIdx === undefined)
176
+ continue; // safety: dangling mixin ref
177
+ if (!result.has(mixinIdx)) {
178
+ result.add(mixinIdx);
179
+ this._buildTransitiveBases(mixinIdx, result);
180
+ }
181
+ }
182
+ }
183
+ /** @internal */
184
+ resolveAllProperties(classIdx) {
185
+ const cls = this[_storage].classes[classIdx];
186
+ if (cls.type === SchemaViewInterfaces_1.ClassType.View) {
187
+ // Views don't participate in property inheritance - own properties only
188
+ const result = [];
189
+ for (let i = 0; i < cls.ownPropCount; i++) {
190
+ const ref = this[_storage].propertyRefs[cls.ownPropStart + i];
191
+ result.push({ ref, classIdx: -1 });
192
+ }
193
+ return result;
194
+ }
195
+ const merged = new Map();
196
+ this._collectProperties(classIdx, merged);
197
+ return Array.from(merged.values());
198
+ }
199
+ _collectProperties(classIdx, merged) {
200
+ const cls = this[_storage].classes[classIdx];
201
+ if (cls === undefined)
202
+ return; // safety: dangling index from excluded schema
203
+ // 1. Base class (recursive, depth-first)
204
+ if (cls.baseClassIdx !== -1)
205
+ this._collectProperties(cls.baseClassIdx, merged);
206
+ // 2. Mixins in declaration order
207
+ for (let i = 0; i < cls.mixinCount; i++) {
208
+ const mixinIdx = this[_storage].classMixins[cls.mixinStartIdx + i];
209
+ if (mixinIdx === -1 || mixinIdx === undefined)
210
+ continue; // safety: dangling mixin ref
211
+ this._collectMixinProperties(mixinIdx, merged);
212
+ }
213
+ // 3. Own properties - always override
214
+ for (let i = 0; i < cls.ownPropCount; i++) {
215
+ const ref = this[_storage].propertyRefs[cls.ownPropStart + i];
216
+ const nameKey = this[_storage].lowerStrings[this[_storage].propDefs[ref.defIdx].nameStringIdx];
217
+ merged.set(nameKey, { ref, classIdx });
218
+ }
219
+ }
220
+ _collectMixinProperties(mixinIdx, merged) {
221
+ const mixin = this[_storage].classes[mixinIdx];
222
+ if (mixin === undefined)
223
+ return; // safety: dangling index from excluded schema
224
+ // Walk mixin's own base chain (mixins can extend other mixins)
225
+ if (mixin.baseClassIdx !== -1)
226
+ this._collectMixinProperties(mixin.baseClassIdx, merged);
227
+ // Mixin's own mixins
228
+ for (let i = 0; i < mixin.mixinCount; i++) {
229
+ const subMixinIdx = this[_storage].classMixins[mixin.mixinStartIdx + i];
230
+ if (subMixinIdx === -1 || subMixinIdx === undefined)
231
+ continue; // safety: dangling mixin ref
232
+ this._collectMixinProperties(subMixinIdx, merged);
233
+ }
234
+ // Mixin's own properties - only set if not already present (first mixin wins)
235
+ for (let i = 0; i < mixin.ownPropCount; i++) {
236
+ const ref = this[_storage].propertyRefs[mixin.ownPropStart + i];
237
+ const nameKey = this[_storage].lowerStrings[this[_storage].propDefs[ref.defIdx].nameStringIdx];
238
+ if (!merged.has(nameKey))
239
+ merged.set(nameKey, { ref, classIdx: mixinIdx });
240
+ }
241
+ }
242
+ /** @internal */
243
+ buildDerivedClassMap() {
244
+ if (this[_storage].derivedClassMap !== undefined)
245
+ return this[_storage].derivedClassMap;
246
+ const map = new Map();
247
+ for (let i = 0; i < this[_storage].classes.length; i++) {
248
+ const baseIdx = this[_storage].classes[i].baseClassIdx;
249
+ if (baseIdx !== -1) {
250
+ let arr = map.get(baseIdx);
251
+ if (arr === undefined) {
252
+ arr = [];
253
+ map.set(baseIdx, arr);
254
+ }
255
+ arr.push(i);
256
+ }
257
+ }
258
+ this[_storage].derivedClassMap = map;
259
+ return map;
260
+ }
261
+ }
262
+ exports.SchemaView = SchemaView;
263
+ // =====================================================================================
264
+ // SchemaView namespace - flyweight view types
265
+ // =====================================================================================
266
+ /** @beta */
267
+ (function (SchemaView) {
268
+ /** Lightweight view over a schema in a `SchemaView`. Holds only a view reference and
269
+ * an index - no data duplication, no mutable state.
270
+ * @beta
271
+ */
272
+ class Schema {
273
+ _ctx;
274
+ idx;
275
+ /** @internal */
276
+ constructor(_ctx,
277
+ /** @internal */ idx) {
278
+ this._ctx = _ctx;
279
+ this.idx = idx;
280
+ }
281
+ get _data() { return this._ctx[_storage].schemas[this.idx]; }
282
+ /** Row ID from ec_Schema. Matches `ECInstanceId` in ECDbMeta views, e.g.
283
+ * `SELECT * FROM meta.ECSchemaDef WHERE ECInstanceId = ?`.
284
+ *
285
+ * This is not an array index or internal handle - it is the database row ID from the ec_Schema
286
+ * table, carried through the binary blob so consumers can fall back to ECSQL meta-queries for
287
+ * data not included in the schema view (custom attributes, schema references, etc.).
288
+ */
289
+ get ecInstanceId() { return this._data.ecInstanceId; }
290
+ get name() { return this._ctx[_storage].strings[this._data.nameStringIdx]; }
291
+ get alias() { return this._ctx[_storage].strings[this._data.aliasStringIdx]; }
292
+ get label() {
293
+ const sid = this._data.labelStringIdx;
294
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : this.name;
295
+ }
296
+ get description() {
297
+ const sid = this._data.descriptionStringIdx;
298
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
299
+ }
300
+ get readVersion() { return this._data.versionRead; }
301
+ get writeVersion() { return this._data.versionWrite; }
302
+ get minorVersion() { return this._data.versionMinor; }
303
+ /** Reflects the `HiddenSchema` custom attribute from `CoreCustomAttributes`.
304
+ * Schemas marked hidden are typically excluded from UI display but remain accessible programmatically. */
305
+ get isHidden() { return this._data.isHidden; }
306
+ /** "SchemaName.RR.WW.mm" - dot-separated, matching the EC schema versioning convention. */
307
+ get fullName() {
308
+ const d = this._data;
309
+ return `${this._ctx[_storage].strings[d.nameStringIdx]}.${String(d.versionRead).padStart(2, "0")}.${String(d.versionWrite).padStart(2, "0")}.${String(d.versionMinor).padStart(2, "0")}`;
310
+ }
311
+ /** Find a class by name within this schema (case-insensitive). */
312
+ getClass(name) {
313
+ const classMap = this._ctx[_storage].classByName.get(this.idx);
314
+ const classIdx = classMap?.get(name.toLowerCase());
315
+ return classIdx !== undefined ? createClass(this._ctx, classIdx) : undefined;
316
+ }
317
+ /** Iterate classes in this schema. Pass a `ClassType` to filter to a single kind
318
+ * (e.g. `getClasses(ClassType.View)`). Omit the argument to iterate every class
319
+ * regardless of type.
320
+ */
321
+ *getClasses(filter) {
322
+ const d = this._data;
323
+ const classes = this._ctx[_storage].classes;
324
+ for (let i = d.classRangeStart; i < d.classRangeStart + d.classCount; i++) {
325
+ if (filter === undefined || classes[i].type === filter)
326
+ yield createClass(this._ctx, i);
327
+ }
328
+ }
329
+ /** Find an enumeration by name within this schema (case-insensitive). */
330
+ getEnumeration(name) {
331
+ const map = this._ctx[_storage].enumByName.get(this.idx);
332
+ const idx = map?.get(name.toLowerCase());
333
+ return idx !== undefined ? new Enumeration(this._ctx, idx) : undefined;
334
+ }
335
+ /** Find a KindOfQuantity by name within this schema (case-insensitive). */
336
+ getKindOfQuantity(name) {
337
+ const map = this._ctx[_storage].koqByName.get(this.idx);
338
+ const idx = map?.get(name.toLowerCase());
339
+ return idx !== undefined ? new KindOfQuantity(this._ctx, idx) : undefined;
340
+ }
341
+ /** Find a PropertyCategory by name within this schema (case-insensitive). */
342
+ getPropertyCategory(name) {
343
+ const map = this._ctx[_storage].catByName.get(this.idx);
344
+ const idx = map?.get(name.toLowerCase());
345
+ return idx !== undefined ? new PropertyCategory(this._ctx, idx) : undefined;
346
+ }
347
+ /** Iterate all enumerations in this schema. */
348
+ *getEnumerations() {
349
+ const d = this._data;
350
+ for (let i = d.enumRangeStart; i < d.enumRangeStart + d.enumCount; i++)
351
+ yield new Enumeration(this._ctx, i);
352
+ }
353
+ /** Iterate all KindOfQuantity items in this schema. */
354
+ *getKindOfQuantities() {
355
+ const d = this._data;
356
+ for (let i = d.koqRangeStart; i < d.koqRangeStart + d.koqCount; i++)
357
+ yield new KindOfQuantity(this._ctx, i);
358
+ }
359
+ /** Iterate all PropertyCategory items in this schema. */
360
+ *getPropertyCategories() {
361
+ const d = this._data;
362
+ for (let i = d.catRangeStart; i < d.catRangeStart + d.catCount; i++)
363
+ yield new PropertyCategory(this._ctx, i);
364
+ }
365
+ }
366
+ SchemaView.Schema = Schema;
367
+ /** Lightweight view over a class in a `SchemaView`. For relationship-specific
368
+ * fields (strength, direction, source/target constraints), narrow via `isRelationship()`
369
+ * or `assertRelationship()` to get a `SchemaView.RelationshipClass`.
370
+ * @beta
371
+ */
372
+ class Class {
373
+ _ctx;
374
+ idx;
375
+ /** @internal */
376
+ constructor(_ctx,
377
+ /** @internal */ idx) {
378
+ this._ctx = _ctx;
379
+ this.idx = idx;
380
+ }
381
+ /** @internal */
382
+ get _data() { return this._ctx[_storage].classes[this.idx]; }
383
+ /** Row ID from ec_Class. Matches `ECInstanceId` in ECDbMeta views, e.g.
384
+ * `SELECT * FROM meta.ECClassDef WHERE ECInstanceId = ?`.
385
+ */
386
+ get ecInstanceId() { return this._data.ecInstanceId; }
387
+ get name() { return this._ctx[_storage].strings[this._data.nameStringIdx]; }
388
+ get label() {
389
+ const sid = this._data.labelStringIdx;
390
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : this.name;
391
+ }
392
+ get description() {
393
+ const sid = this._data.descriptionStringIdx;
394
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
395
+ }
396
+ /** "SchemaName:ClassName" - colon-separated, matching the EC class full name convention.
397
+ * Use either ":" or "." as separator when passing to `findClass()`. */
398
+ get fullName() {
399
+ const d = this._data;
400
+ return `${this._ctx[_storage].strings[this._ctx[_storage].schemas[d.schemaIdx].nameStringIdx]}:${this._ctx[_storage].strings[d.nameStringIdx]}`;
401
+ }
402
+ get schema() { return new Schema(this._ctx, this._data.schemaIdx); }
403
+ get type() { return this._data.type; }
404
+ get modifier() { return this._data.modifier; }
405
+ // Type check methods
406
+ // disabling lint rule for these because we explicitly want them to mirror same methods in ecschema-metadata, to make the APIs more compatible
407
+ // eslint-disable-next-line @itwin/prefer-get
408
+ isEntity() { return this._data.type === SchemaViewInterfaces_1.ClassType.Entity; }
409
+ /** Type predicate - narrows to `SchemaView.RelationshipClass` for access to strength, direction,
410
+ * source, and target constraint fields. */
411
+ isRelationship() { return this._data.type === SchemaViewInterfaces_1.ClassType.Relationship; }
412
+ // eslint-disable-next-line @itwin/prefer-get
413
+ isStruct() { return this._data.type === SchemaViewInterfaces_1.ClassType.Struct; }
414
+ // eslint-disable-next-line @itwin/prefer-get
415
+ isMixin() { return this._data.type === SchemaViewInterfaces_1.ClassType.Mixin; }
416
+ // eslint-disable-next-line @itwin/prefer-get
417
+ isCustomAttribute() { return this._data.type === SchemaViewInterfaces_1.ClassType.CustomAttribute; }
418
+ // eslint-disable-next-line @itwin/prefer-get
419
+ isView() { return this._data.type === SchemaViewInterfaces_1.ClassType.View; }
420
+ /** @see isRelationship */
421
+ assertRelationship() {
422
+ if (!this.isRelationship())
423
+ throw new Error(`Expected a relationship class, got type ${this.type} for "${this.fullName}"`);
424
+ }
425
+ // Modifier checks
426
+ get isAbstract() { return this._data.modifier === SchemaViewInterfaces_1.ClassModifier.Abstract; }
427
+ get isSealed() { return this._data.modifier === SchemaViewInterfaces_1.ClassModifier.Sealed; }
428
+ /** Reflects the `HiddenClass` custom attribute from `CoreCustomAttributes`.
429
+ * Returns `true` when this class is directly hidden (via `HiddenClass(Show!=true)` or
430
+ * schema-level `HiddenSchema(ShowClasses!=true)`). Does NOT consider base class inheritance -
431
+ * use `isEffectivelyHidden` for that.
432
+ *
433
+ * Note: `false` means explicitly shown via `HiddenClass(Show=true)`. `undefined` means
434
+ * no `HiddenClass` CA and the schema does not hide its classes. Both are "not hidden" for
435
+ * this property, but `isEffectivelyHidden` distinguishes them when walking the hierarchy. */
436
+ get isHidden() { return this._data.isHidden; }
437
+ /** Computed hidden status that walks the base class chain (not mixins).
438
+ *
439
+ * Returns `true` if this class is hidden or any ancestor in the base class chain is hidden,
440
+ * unless this class or an intermediate class explicitly breaks the chain with
441
+ * `HiddenClass(Show=true)` (i.e. `isHidden === false`).
442
+ *
443
+ * Mixins are intentionally excluded - a hidden mixin represents a hidden capability,
444
+ * not a hidden identity. */
445
+ get isEffectivelyHidden() {
446
+ let data = this._data;
447
+ while (data !== undefined) {
448
+ if (data.isHidden === false)
449
+ return false; // explicit Show=true breaks the chain
450
+ if (data.isHidden === true)
451
+ return true;
452
+ // undefined: walk to base class via internal array (avoids allocating Class objects)
453
+ data = data.baseClassIdx !== -1 ? this._ctx[_storage].classes[data.baseClassIdx] : undefined;
454
+ }
455
+ return false;
456
+ }
457
+ // Hierarchy
458
+ /** Single base class. undefined for root classes. */
459
+ get baseClass() {
460
+ const idx = this._data.baseClassIdx;
461
+ return idx !== -1 ? createClass(this._ctx, idx) : undefined;
462
+ }
463
+ /** Applied mixins in declaration order. Only meaningful for entity classes. */
464
+ get mixins() {
465
+ const d = this._data;
466
+ if (d.mixinCount === 0)
467
+ return [];
468
+ const result = [];
469
+ for (let i = 0; i < d.mixinCount; i++) {
470
+ const mixinIdx = this._ctx[_storage].classMixins[d.mixinStartIdx + i];
471
+ if (mixinIdx === -1 || mixinIdx === undefined)
472
+ continue; // safety: dangling mixin ref from excluded schema
473
+ result.push(createClass(this._ctx, mixinIdx));
474
+ }
475
+ return result;
476
+ }
477
+ /** IS-A check. Returns true if this class is, or derives from, `other` (transitively, including mixins).
478
+ * Accepts a `SchemaView.Class` or a qualified name string ("SchemaName:ClassName").
479
+ */
480
+ is(classOrName) {
481
+ let targetIdx;
482
+ if (typeof classOrName === "string") {
483
+ targetIdx = this._ctx.resolveClassIdx(classOrName);
484
+ }
485
+ else if (classOrName._ctx === this._ctx) {
486
+ targetIdx = classOrName.idx;
487
+ }
488
+ else {
489
+ // Cross-view input: indices are not comparable across SchemaView instances.
490
+ // Resolve by qualified name against this view.
491
+ targetIdx = this._ctx.resolveClassIdx(classOrName.fullName);
492
+ }
493
+ if (targetIdx === -1)
494
+ return false;
495
+ if (this.idx === targetIdx)
496
+ return true;
497
+ return this._ctx.getTransitiveBases(this.idx).has(targetIdx);
498
+ }
499
+ /** Direct derived classes. Expensive on first call (builds reverse map across all classes). */
500
+ get derivedClasses() {
501
+ const map = this._ctx.buildDerivedClassMap();
502
+ const indices = map.get(this.idx);
503
+ if (indices === undefined)
504
+ return [];
505
+ return indices.map((i) => createClass(this._ctx, i));
506
+ }
507
+ // Properties
508
+ /** Find a property by name (case-insensitive). Searches own + inherited.
509
+ *
510
+ * Note: this resolves the full property list and linear-scans it on every call. For workloads
511
+ * that hit `getProperty` repeatedly on the same class with different names, a per-class
512
+ * resolved-property map cache could be added on the view. Not done now - measure before
513
+ * optimizing. */
514
+ getProperty(name) {
515
+ const allProps = this._ctx.resolveAllProperties(this.idx);
516
+ const lowerName = name.toLowerCase();
517
+ for (const rp of allProps) {
518
+ if (this._ctx[_storage].lowerStrings[this._ctx[_storage].propDefs[rp.ref.defIdx].nameStringIdx] === lowerName)
519
+ return createProperty(this._ctx, rp.ref, rp.classIdx);
520
+ }
521
+ return undefined;
522
+ }
523
+ /** All properties including inherited, in inheritance order (base first, then mixins, then own). */
524
+ getProperties() {
525
+ const allRefs = this._ctx.resolveAllProperties(this.idx);
526
+ return allRefs.map((rp) => createProperty(this._ctx, rp.ref, rp.classIdx));
527
+ }
528
+ /** Own properties only (not inherited), in ordinal order. */
529
+ getOwnProperties() {
530
+ const d = this._data;
531
+ const result = [];
532
+ for (let i = 0; i < d.ownPropCount; i++) {
533
+ const ref = this._ctx[_storage].propertyRefs[d.ownPropStart + i];
534
+ result.push(createProperty(this._ctx, ref, this.idx));
535
+ }
536
+ return result;
537
+ }
538
+ }
539
+ SchemaView.Class = Class;
540
+ /** A relationship class with constraint and strength metadata. Created by `createClass()`
541
+ * when the underlying `ClassType` is `Relationship`. Use `cls.isRelationship()` to narrow a
542
+ * `SchemaView.Class` to this type.
543
+ * @beta
544
+ */
545
+ class RelationshipClass extends Class {
546
+ get strength() { return this._data.strength; }
547
+ get strengthDirection() { return this._data.strengthDirection; }
548
+ get source() {
549
+ const idx = this._data.sourceConstraintIdx;
550
+ return idx !== -1 ? new RelConstraint(this._ctx, idx) : undefined;
551
+ }
552
+ get target() {
553
+ const idx = this._data.targetConstraintIdx;
554
+ return idx !== -1 ? new RelConstraint(this._ctx, idx) : undefined;
555
+ }
556
+ }
557
+ SchemaView.RelationshipClass = RelationshipClass;
558
+ /** @internal */
559
+ function createClass(ctx, idx) {
560
+ if (ctx[_storage].classes[idx].type === SchemaViewInterfaces_1.ClassType.Relationship)
561
+ return new RelationshipClass(ctx, idx);
562
+ return new Class(ctx, idx);
563
+ }
564
+ SchemaView.createClass = createClass;
565
+ /** Lightweight view over a property in a `SchemaView`. Subclasses provide
566
+ * type-safe access to kind-specific fields. Use `isPrimitive()`, `isStruct()`,
567
+ * `isArray()`, or `isNavigation()` to narrow, or the corresponding `assert*()` methods.
568
+ * @beta
569
+ */
570
+ class Property {
571
+ _ctx;
572
+ _ref;
573
+ _classIdx;
574
+ /** @internal */
575
+ constructor(_ctx, _ref,
576
+ /** Index of the class that declared or contributed this property through inheritance.
577
+ * For own properties, this is the class itself. For inherited properties, this is the
578
+ * base class or mixin that introduced it. -1 for view properties. */
579
+ _classIdx) {
580
+ this._ctx = _ctx;
581
+ this._ref = _ref;
582
+ this._classIdx = _classIdx;
583
+ }
584
+ /** @internal */
585
+ get _def() { return this._ctx[_storage].propDefs[this._ref.defIdx]; }
586
+ /** Row ID from ec_Property. Matches `ECInstanceId` in ECDbMeta views, e.g.
587
+ * `SELECT * FROM meta.ECPropertyDef WHERE ECInstanceId = ?`.
588
+ *
589
+ * Stored per-reference (not per-definition) because each class-property pair has a unique
590
+ * ec_Property row even when the structural definition is deduplicated.
591
+ */
592
+ get ecInstanceId() { return this._ref.ecInstanceId; }
593
+ get name() { return this._ctx[_storage].strings[this._def.nameStringIdx]; }
594
+ /** Display label. Falls back to the property name if no explicit label is set.
595
+ * Labels are stored per-reference (not per-definition) because EC allows class overrides. */
596
+ get label() {
597
+ const labelStringIdx = this._ref.labelStringIdx;
598
+ return labelStringIdx !== 0 ? this._ctx[_storage].strings[labelStringIdx] : this.name;
599
+ }
600
+ get description() {
601
+ const sid = this._def.descriptionStringIdx;
602
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
603
+ }
604
+ get kind() { return this._def.kind; }
605
+ get isReadOnly() { return this._def.isReadOnly; }
606
+ /** Reflects the `HiddenProperty` custom attribute from `CoreCustomAttributes`.
607
+ * Properties marked hidden are typically excluded from UI display but remain accessible programmatically. */
608
+ get isHidden() { return this._def.isHidden; }
609
+ /** Display priority. Higher values should be displayed more prominently. 0 means default. */
610
+ get priority() { return this._ref.priority; }
611
+ /** The class that declared or contributed this property through inheritance.
612
+ * For own properties, returns the class itself. For inherited properties, returns the
613
+ * base class or mixin that introduced it. Returns `undefined` for view properties.
614
+ * This is the class array index, not the ec_Class.Id from the database.
615
+ * @beta
616
+ */
617
+ get declaringClass() {
618
+ return this._classIdx !== -1 ? createClass(this._ctx, this._classIdx) : undefined;
619
+ }
620
+ /** Property category, or undefined if none assigned. Available on all property kinds. */
621
+ get category() {
622
+ const idx = this._def.categoryIdx;
623
+ return idx !== -1 ? new PropertyCategory(this._ctx, idx) : undefined;
624
+ }
625
+ // Type guards - real type predicates that narrow `this`
626
+ /** True for `SchemaView.PrimitiveProperty` and `SchemaView.PrimitiveArrayProperty`.
627
+ * Matches ecschema-metadata behavior where `isPrimitive()` includes primitive arrays. */
628
+ isPrimitive() {
629
+ return this._def.kind === SchemaViewInterfaces_1.PropertyKind.Primitive || this._def.kind === SchemaViewInterfaces_1.PropertyKind.PrimitiveArray;
630
+ }
631
+ /** True for `SchemaView.StructProperty` and `SchemaView.StructArrayProperty`. */
632
+ isStruct() {
633
+ return this._def.kind === SchemaViewInterfaces_1.PropertyKind.Struct || this._def.kind === SchemaViewInterfaces_1.PropertyKind.StructArray;
634
+ }
635
+ /** True for `SchemaView.PrimitiveArrayProperty` and `SchemaView.StructArrayProperty`. */
636
+ isArray() {
637
+ return this._def.kind === SchemaViewInterfaces_1.PropertyKind.PrimitiveArray || this._def.kind === SchemaViewInterfaces_1.PropertyKind.StructArray;
638
+ }
639
+ /** True for `SchemaView.NavigationProperty`. */
640
+ isNavigation() {
641
+ return this._def.kind === SchemaViewInterfaces_1.PropertyKind.Navigation;
642
+ }
643
+ /** True if this property is backed by an enumeration. Enumerations are a facet of primitive
644
+ * properties - an enum property IS a primitive property with an enum binding. Narrows to
645
+ * `AnyPrimitiveProperty` so you can access `enumeration`, `primitiveType`, etc. */
646
+ isEnumeration() {
647
+ return this._def.enumIdx !== -1;
648
+ }
649
+ // Assert methods - throw on mismatch, narrow `this`
650
+ /** @see isPrimitive */
651
+ assertPrimitive() {
652
+ if (!this.isPrimitive())
653
+ throw new Error(`Expected a primitive property, got ${SchemaViewInterfaces_1.PropertyKind[this.kind]}`);
654
+ }
655
+ /** @see isStruct */
656
+ assertStruct() {
657
+ if (!this.isStruct())
658
+ throw new Error(`Expected a struct property, got ${SchemaViewInterfaces_1.PropertyKind[this.kind]}`);
659
+ }
660
+ /** @see isArray */
661
+ assertArray() {
662
+ if (!this.isArray())
663
+ throw new Error(`Expected an array property, got ${SchemaViewInterfaces_1.PropertyKind[this.kind]}`);
664
+ }
665
+ /** @see isNavigation */
666
+ assertNavigation() {
667
+ if (!this.isNavigation())
668
+ throw new Error(`Expected a navigation property, got ${SchemaViewInterfaces_1.PropertyKind[this.kind]}`);
669
+ }
670
+ }
671
+ SchemaView.Property = Property;
672
+ /** A scalar primitive property. May optionally be backed by an enumeration -
673
+ * check `isEnumeration()` or `enumeration`.
674
+ * @beta
675
+ */
676
+ class PrimitiveProperty extends Property {
677
+ get primitiveType() { return this._def.primitiveType; }
678
+ get extendedTypeName() {
679
+ const sid = this._def.extTypeStringIdx;
680
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : undefined;
681
+ }
682
+ get enumeration() {
683
+ const idx = this._def.enumIdx;
684
+ return idx !== -1 ? new Enumeration(this._ctx, idx) : undefined;
685
+ }
686
+ get kindOfQuantity() {
687
+ const idx = this._def.koqIdx;
688
+ return idx !== -1 ? new KindOfQuantity(this._ctx, idx) : undefined;
689
+ }
690
+ }
691
+ SchemaView.PrimitiveProperty = PrimitiveProperty;
692
+ /** An array of primitive values. Same primitive/enum fields as `PrimitiveProperty`,
693
+ * plus array bounds.
694
+ * @beta
695
+ */
696
+ class PrimitiveArrayProperty extends Property {
697
+ get primitiveType() { return this._def.primitiveType; }
698
+ get extendedTypeName() {
699
+ const sid = this._def.extTypeStringIdx;
700
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : undefined;
701
+ }
702
+ get enumeration() {
703
+ const idx = this._def.enumIdx;
704
+ return idx !== -1 ? new Enumeration(this._ctx, idx) : undefined;
705
+ }
706
+ get kindOfQuantity() {
707
+ const idx = this._def.koqIdx;
708
+ return idx !== -1 ? new KindOfQuantity(this._ctx, idx) : undefined;
709
+ }
710
+ get arrayMinOccurs() { return this._def.arrayMinOccurs; }
711
+ get arrayMaxOccurs() { return this._def.arrayMaxOccurs; }
712
+ }
713
+ SchemaView.PrimitiveArrayProperty = PrimitiveArrayProperty;
714
+ /** A scalar struct property. `structClass` is non-nullable - the binary parser drops
715
+ * properties whose struct class can't be resolved (e.g. from excluded schemas).
716
+ * @beta
717
+ */
718
+ class StructProperty extends Property {
719
+ get structClass() {
720
+ return createClass(this._ctx, this._def.structClassIdx);
721
+ }
722
+ }
723
+ SchemaView.StructProperty = StructProperty;
724
+ /** An array of struct values. Same struct field as `StructProperty`, plus array bounds.
725
+ * @beta
726
+ */
727
+ class StructArrayProperty extends Property {
728
+ get structClass() {
729
+ return createClass(this._ctx, this._def.structClassIdx);
730
+ }
731
+ get arrayMinOccurs() { return this._def.arrayMinOccurs; }
732
+ get arrayMaxOccurs() { return this._def.arrayMaxOccurs; }
733
+ }
734
+ SchemaView.StructArrayProperty = StructArrayProperty;
735
+ /** A navigation property. `relationshipClass` is non-nullable - the binary parser drops
736
+ * properties whose relationship class can't be resolved.
737
+ * @beta
738
+ */
739
+ class NavigationProperty extends Property {
740
+ get direction() { return this._def.navDirection; }
741
+ get relationshipClass() {
742
+ return createClass(this._ctx, this._def.navRelClassIdx);
743
+ }
744
+ }
745
+ SchemaView.NavigationProperty = NavigationProperty;
746
+ /** @internal */
747
+ function createProperty(ctx, ref, classIdx) {
748
+ const kind = ctx[_storage].propDefs[ref.defIdx].kind;
749
+ switch (kind) {
750
+ case SchemaViewInterfaces_1.PropertyKind.Primitive: return new PrimitiveProperty(ctx, ref, classIdx);
751
+ case SchemaViewInterfaces_1.PropertyKind.PrimitiveArray: return new PrimitiveArrayProperty(ctx, ref, classIdx);
752
+ case SchemaViewInterfaces_1.PropertyKind.Struct: return new StructProperty(ctx, ref, classIdx);
753
+ case SchemaViewInterfaces_1.PropertyKind.StructArray: return new StructArrayProperty(ctx, ref, classIdx);
754
+ case SchemaViewInterfaces_1.PropertyKind.Navigation: return new NavigationProperty(ctx, ref, classIdx);
755
+ default: throw new Error(`Unknown PropertyKind ${kind} for property "${ctx[_storage].strings[ctx[_storage].propDefs[ref.defIdx].nameStringIdx]}"`);
756
+ }
757
+ }
758
+ SchemaView.createProperty = createProperty;
759
+ /** Lightweight view over an enumeration in a `SchemaView`.
760
+ * @beta
761
+ */
762
+ class Enumeration {
763
+ _ctx;
764
+ idx;
765
+ /** @internal */
766
+ constructor(_ctx,
767
+ /** @internal */ idx) {
768
+ this._ctx = _ctx;
769
+ this.idx = idx;
770
+ }
771
+ get _data() { return this._ctx[_storage].enumerations[this.idx]; }
772
+ /** Row ID from ec_Enumeration. Matches `ECInstanceId` in ECDbMeta views, e.g.
773
+ * `SELECT * FROM meta.ECEnumerationDef WHERE ECInstanceId = ?`.
774
+ */
775
+ get ecInstanceId() { return this._data.ecInstanceId; }
776
+ get name() { return this._ctx[_storage].strings[this._data.nameStringIdx]; }
777
+ get label() {
778
+ const sid = this._data.labelStringIdx;
779
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : this.name;
780
+ }
781
+ get description() {
782
+ const sid = this._data.descriptionStringIdx;
783
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
784
+ }
785
+ /** "SchemaName:EnumName" - colon-separated. */
786
+ get fullName() {
787
+ const d = this._data;
788
+ return `${this._ctx[_storage].strings[this._ctx[_storage].schemas[d.schemaIdx].nameStringIdx]}:${this._ctx[_storage].strings[d.nameStringIdx]}`;
789
+ }
790
+ get schema() { return new Schema(this._ctx, this._data.schemaIdx); }
791
+ get primitiveType() { return this._data.primitiveType; }
792
+ get isStrict() { return this._data.isStrict; }
793
+ /** Iterate enumerators in declaration order. */
794
+ *getEnumerators() {
795
+ const d = this._data;
796
+ for (let i = d.enumeratorStart; i < d.enumeratorStart + d.enumeratorCount; i++)
797
+ yield new Enumerator(this._ctx, i);
798
+ }
799
+ /** Find enumerator by name (case-insensitive). */
800
+ getEnumeratorByName(name) {
801
+ const lower = name.toLowerCase();
802
+ const d = this._data;
803
+ for (let i = d.enumeratorStart; i < d.enumeratorStart + d.enumeratorCount; i++) {
804
+ if (this._ctx[_storage].lowerStrings[this._ctx[_storage].enumerators[i].nameStringIdx] === lower)
805
+ return new Enumerator(this._ctx, i);
806
+ }
807
+ return undefined;
808
+ }
809
+ /** Find enumerator by value. */
810
+ getEnumerator(value) {
811
+ const d = this._data;
812
+ for (let i = d.enumeratorStart; i < d.enumeratorStart + d.enumeratorCount; i++) {
813
+ if (this._ctx[_storage].enumerators[i].value === value)
814
+ return new Enumerator(this._ctx, i);
815
+ }
816
+ return undefined;
817
+ }
818
+ }
819
+ SchemaView.Enumeration = Enumeration;
820
+ /** Thin view over an enumerator.
821
+ * @beta
822
+ */
823
+ class Enumerator {
824
+ _ctx;
825
+ idx;
826
+ /** @internal */
827
+ constructor(_ctx,
828
+ /** @internal */ idx) {
829
+ this._ctx = _ctx;
830
+ this.idx = idx;
831
+ }
832
+ get _data() { return this._ctx[_storage].enumerators[this.idx]; }
833
+ get name() { return this._ctx[_storage].strings[this._data.nameStringIdx]; }
834
+ get label() {
835
+ const sid = this._data.labelStringIdx;
836
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : this.name;
837
+ }
838
+ get description() {
839
+ const sid = this._data.descriptionStringIdx;
840
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
841
+ }
842
+ get value() { return this._data.value; }
843
+ }
844
+ SchemaView.Enumerator = Enumerator;
845
+ /** Parse a single format override string into a `PresentationFormat`.
846
+ * @internal
847
+ */
848
+ function parseFormatString(formatString) {
849
+ const nameMatch = /^([\w.:]+)/.exec(formatString);
850
+ if (!nameMatch)
851
+ return { name: formatString };
852
+ const name = nameMatch[1];
853
+ const precMatch = /\((\d+)\)/.exec(formatString);
854
+ const precision = precMatch ? parseInt(precMatch[1], 10) : undefined;
855
+ const bracketRgx = /\[([^\]]+)\]/g;
856
+ const units = [];
857
+ let m;
858
+ while ((m = bracketRgx.exec(formatString)) !== null) {
859
+ const pipeIdx = m[1].indexOf("|");
860
+ units.push(pipeIdx < 0 ? [m[1], undefined] : [m[1].substring(0, pipeIdx), m[1].substring(pipeIdx + 1)]);
861
+ }
862
+ return { name, precision, unitAndLabels: units.length > 0 ? units : undefined };
863
+ }
864
+ SchemaView.parseFormatString = parseFormatString;
865
+ /** Lightweight view over a KindOfQuantity in a `SchemaView`.
866
+ * @beta
867
+ */
868
+ class KindOfQuantity {
869
+ _ctx;
870
+ idx;
871
+ /** @internal */
872
+ constructor(_ctx,
873
+ /** @internal */ idx) {
874
+ this._ctx = _ctx;
875
+ this.idx = idx;
876
+ }
877
+ get _data() { return this._ctx[_storage].koqs[this.idx]; }
878
+ /** Row ID from ec_KindOfQuantity. Matches `ECInstanceId` in ECDbMeta views, e.g.
879
+ * `SELECT * FROM meta.ECKindOfQuantityDef WHERE ECInstanceId = ?`.
880
+ */
881
+ get ecInstanceId() { return this._data.ecInstanceId; }
882
+ get name() { return this._ctx[_storage].strings[this._data.nameStringIdx]; }
883
+ get label() {
884
+ const sid = this._data.labelStringIdx;
885
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : this.name;
886
+ }
887
+ get description() {
888
+ const sid = this._data.descriptionStringIdx;
889
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
890
+ }
891
+ /** "SchemaName:KoqName" - colon-separated. */
892
+ get fullName() {
893
+ const d = this._data;
894
+ return `${this._ctx[_storage].strings[this._ctx[_storage].schemas[d.schemaIdx].nameStringIdx]}:${this._ctx[_storage].strings[d.nameStringIdx]}`;
895
+ }
896
+ get schema() { return new Schema(this._ctx, this._data.schemaIdx); }
897
+ get relativeError() { return this._data.relativeError; }
898
+ /** Persistence unit as a full name string, e.g. "Units:M".
899
+ *
900
+ * On iModels still on ECDb profile `4.0.0.1` (predates the 2018 EC3.2 Units/Formats migration)
901
+ * this string is in legacy FUS format rather than the EC3.2 alias-qualified form.
902
+ * Upgrade the iModel's ECDb profile to get EC3.2 strings.
903
+ */
904
+ get persistenceUnit() {
905
+ const sid = this._data.persistenceUnitStringIdx;
906
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
907
+ }
908
+ // EC XML serializes this as "presentationUnits"; we use "presentationFormats" to align with KindOfQuantity.presentationFormats in ecschema-metadata.
909
+ /** Raw presentation format string as stored in ECDb (`ec_KindOfQuantity.PresentationUnits`).
910
+ * This is a JSON array of format override strings. Empty string if none are defined.
911
+ * Prefer `presentationFormats` for structured access.
912
+ *
913
+ * On iModels still on ECDb profile `4.0.0.1` (predates the 2018 EC3.2 Units/Formats migration)
914
+ * the strings are in legacy FUS format and will not parse via `presentationFormats`.
915
+ * Upgrade the iModel's ECDb profile to get EC3.2 strings.
916
+ */
917
+ get presentationFormatsRaw() {
918
+ const sid = this._data.presentationFormatsStringIdx;
919
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
920
+ }
921
+ /** Presentation formats parsed into structured overrides. Each entry has the format name
922
+ * (alias-qualified, e.g. `"f:DefaultRealU"`), optional precision override, and optional
923
+ * unit-and-label overrides. Returns an empty array if no presentation formats are defined.
924
+ *
925
+ * Example - given a raw string of `["f:DefaultRealU(4)[u:M_PER_SEC_SQ]","f:DefaultRealU(4)[u:CM_PER_SEC_SQ]"]`:
926
+ * ```ts
927
+ * // [
928
+ * // { name: "f:DefaultRealU", precision: 4, unitAndLabels: [["u:M_PER_SEC_SQ", undefined]] },
929
+ * // { name: "f:DefaultRealU", precision: 4, unitAndLabels: [["u:CM_PER_SEC_SQ", undefined]] },
930
+ * // ]
931
+ * ```
932
+ */
933
+ get presentationFormats() {
934
+ const raw = this.presentationFormatsRaw;
935
+ if (raw === "")
936
+ return [];
937
+ const formats = JSON.parse(raw);
938
+ return formats.map((f) => parseFormatString(f));
939
+ }
940
+ }
941
+ SchemaView.KindOfQuantity = KindOfQuantity;
942
+ /** Lightweight view over a PropertyCategory in a `SchemaView`.
943
+ * @beta
944
+ */
945
+ class PropertyCategory {
946
+ _ctx;
947
+ idx;
948
+ /** @internal */
949
+ constructor(_ctx,
950
+ /** @internal */ idx) {
951
+ this._ctx = _ctx;
952
+ this.idx = idx;
953
+ }
954
+ get _data() { return this._ctx[_storage].propCategories[this.idx]; }
955
+ /** Row ID from ec_PropertyCategory. Matches `ECInstanceId` in ECDbMeta views, e.g.
956
+ * `SELECT * FROM meta.ECPropertyCategoryDef WHERE ECInstanceId = ?`.
957
+ */
958
+ get ecInstanceId() { return this._data.ecInstanceId; }
959
+ get name() { return this._ctx[_storage].strings[this._data.nameStringIdx]; }
960
+ get label() {
961
+ const sid = this._data.labelStringIdx;
962
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : this.name;
963
+ }
964
+ get description() {
965
+ const sid = this._data.descriptionStringIdx;
966
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
967
+ }
968
+ /** "SchemaName:CategoryName" - colon-separated. */
969
+ get fullName() {
970
+ const d = this._data;
971
+ return `${this._ctx[_storage].strings[this._ctx[_storage].schemas[d.schemaIdx].nameStringIdx]}:${this._ctx[_storage].strings[d.nameStringIdx]}`;
972
+ }
973
+ get schema() { return new Schema(this._ctx, this._data.schemaIdx); }
974
+ get priority() { return this._data.priority; }
975
+ }
976
+ SchemaView.PropertyCategory = PropertyCategory;
977
+ /** Lightweight view over a relationship constraint in a `SchemaView`.
978
+ * @beta
979
+ */
980
+ class RelConstraint {
981
+ _ctx;
982
+ _idx;
983
+ /** @internal */
984
+ constructor(_ctx, _idx) {
985
+ this._ctx = _ctx;
986
+ this._idx = _idx;
987
+ }
988
+ get _data() { return this._ctx[_storage].relConstraints[this._idx]; }
989
+ get abstractConstraint() {
990
+ const idx = this._data.abstractConstraintIdx;
991
+ return idx !== -1 ? createClass(this._ctx, idx) : undefined;
992
+ }
993
+ get polymorphic() { return this._data.polymorphic; }
994
+ /** Multiplicity lower bound (0 = unbounded). */
995
+ get multiplicityLower() { return this._data.multiplicityLower; }
996
+ /** Multiplicity upper bound (0 = unbounded). */
997
+ get multiplicityUpper() { return this._data.multiplicityUpper; }
998
+ /** Role label string, or empty if not set. */
999
+ get roleLabel() {
1000
+ const sid = this._data.roleLabelStringIdx;
1001
+ return sid !== 0 ? this._ctx[_storage].strings[sid] : "";
1002
+ }
1003
+ get constraintClasses() {
1004
+ const d = this._data;
1005
+ const result = [];
1006
+ for (let i = 0; i < d.classRefCount; i++)
1007
+ result.push(createClass(this._ctx, this._ctx[_storage].constraintClassRefs[d.classRefStart + i]));
1008
+ return result;
1009
+ }
1010
+ }
1011
+ SchemaView.RelConstraint = RelConstraint;
1012
+ })(SchemaView || (exports.SchemaView = SchemaView = {}));
1013
+ // =====================================================================================
1014
+ // SchemaViewBuilder
1015
+ // =====================================================================================
1016
+ /** Builder for constructing an immutable `SchemaView`.
1017
+ *
1018
+ * Collects data during binary blob parsing, then freezes it into a view.
1019
+ * Handles string interning and property definition deduplication.
1020
+ *
1021
+ * Consumers should not use this directly - read views via `IModelDb.getSchemaView`
1022
+ * / `IModelConnection.getSchemaView` (or `SchemaView.fromBinary` if you have a raw blob).
1023
+ * @internal
1024
+ */
1025
+ class SchemaViewBuilder {
1026
+ _strings = [""]; // SID 0 = empty string
1027
+ _lowerStrings = [""];
1028
+ _stringMap = new Map(); // original value -> SID
1029
+ _schemas = [];
1030
+ _classes = [];
1031
+ _classMixins = [];
1032
+ _propDefs = [];
1033
+ _propertyRefs = [];
1034
+ _relConstraints = [];
1035
+ _constraintClassRefs = [];
1036
+ _enumerations = [];
1037
+ _enumerators = [];
1038
+ _koqs = [];
1039
+ _propCategories = [];
1040
+ // For PropertyDef dedup
1041
+ _propDefMap = new Map(); // signature string -> defIdx
1042
+ /** Intern a string, returning its SID. Empty/undefined strings return 0.
1043
+ * Interning is case-sensitive - "MyLabel" and "MYLABEL" get distinct SIDs.
1044
+ * The `lowerStrings` array provides case-insensitive lookup without mutating display values.
1045
+ */
1046
+ internString(value) {
1047
+ if (value === undefined || value === "")
1048
+ return 0;
1049
+ const existing = this._stringMap.get(value);
1050
+ if (existing !== undefined)
1051
+ return existing;
1052
+ const sid = this._strings.length;
1053
+ this._strings.push(value);
1054
+ this._lowerStrings.push(value.toLowerCase());
1055
+ this._stringMap.set(value, sid);
1056
+ return sid;
1057
+ }
1058
+ /** Add a schema. Returns its index. */
1059
+ addSchema(data) {
1060
+ const idx = this._schemas.length;
1061
+ this._schemas.push(data);
1062
+ return idx;
1063
+ }
1064
+ /** Add a class. Returns its index. Must be called after the owning schema. */
1065
+ addClass(data) {
1066
+ const idx = this._classes.length;
1067
+ this._classes.push(data);
1068
+ return idx;
1069
+ }
1070
+ /** Add a property definition with deduplication. Returns the def index (possibly existing). */
1071
+ addPropertyDef(data) {
1072
+ const sig = this._propDefSignature(data);
1073
+ const existing = this._propDefMap.get(sig);
1074
+ if (existing !== undefined)
1075
+ return existing;
1076
+ const idx = this._propDefs.length;
1077
+ this._propDefs.push(data);
1078
+ this._propDefMap.set(sig, idx);
1079
+ return idx;
1080
+ }
1081
+ /** Append a property reference to the flat refs array. */
1082
+ addPropertyRef(ref) {
1083
+ this._propertyRefs.push(ref);
1084
+ }
1085
+ /** Add an enumeration. Returns its index. */
1086
+ addEnumeration(data) {
1087
+ const idx = this._enumerations.length;
1088
+ this._enumerations.push(data);
1089
+ return idx;
1090
+ }
1091
+ /** Append an enumerator to the flat enumerators array. */
1092
+ addEnumerator(data) {
1093
+ this._enumerators.push(data);
1094
+ }
1095
+ /** Add a KindOfQuantity. Returns its index. */
1096
+ addKoq(data) {
1097
+ const idx = this._koqs.length;
1098
+ this._koqs.push(data);
1099
+ return idx;
1100
+ }
1101
+ /** Add a PropertyCategory. Returns its index. */
1102
+ addPropertyCategory(data) {
1103
+ const idx = this._propCategories.length;
1104
+ this._propCategories.push(data);
1105
+ return idx;
1106
+ }
1107
+ /** Add a relationship constraint. Returns its index. */
1108
+ addRelConstraint(data) {
1109
+ const idx = this._relConstraints.length;
1110
+ this._relConstraints.push(data);
1111
+ return idx;
1112
+ }
1113
+ /** Append a constraint class reference to the flat array. */
1114
+ addConstraintClassRef(classIdx) {
1115
+ this._constraintClassRefs.push(classIdx);
1116
+ }
1117
+ /** Append a mixin class reference to the flat array. */
1118
+ addClassMixin(classIdx) {
1119
+ this._classMixins.push(classIdx);
1120
+ }
1121
+ /** The current count of property refs (used to set ownPropStart on ClassData). */
1122
+ get propertyRefCount() { return this._propertyRefs.length; }
1123
+ /** The current count of enumerators (used to set enumeratorStart on EnumerationData). */
1124
+ get enumeratorCount() { return this._enumerators.length; }
1125
+ /** The current count of constraint class refs (used to set classRefStart). */
1126
+ get constraintClassRefCount() { return this._constraintClassRefs.length; }
1127
+ /** The current count of class mixins (used to set mixinStartIdx). */
1128
+ get classMixinCount() { return this._classMixins.length; }
1129
+ /** Get a string by SID. @internal */
1130
+ getString(sid) { return this._strings[sid]; }
1131
+ /** Replace class data at the given index (used during deferred cross-ref resolution). @internal */
1132
+ updateClass(classIdx, data) { this._classes[classIdx] = data; }
1133
+ /** Update range fields on a schema (used after all items for a schema are collected). @internal */
1134
+ updateSchemaRanges(schemaIdx, ranges) {
1135
+ const s = this._schemas[schemaIdx];
1136
+ this._schemas[schemaIdx] = { ...s, ...ranges };
1137
+ }
1138
+ /** Freeze all data and produce an immutable SchemaView. */
1139
+ build(schemaToken) {
1140
+ const schemaByName = new Map();
1141
+ const schemaByAlias = new Map();
1142
+ const classByName = new Map();
1143
+ const enumByName = new Map();
1144
+ const koqByName = new Map();
1145
+ const catByName = new Map();
1146
+ // Build schema lookup maps
1147
+ for (let i = 0; i < this._schemas.length; i++) {
1148
+ const s = this._schemas[i];
1149
+ schemaByName.set(this._lowerStrings[s.nameStringIdx], i);
1150
+ if (s.aliasStringIdx !== 0)
1151
+ schemaByAlias.set(this._lowerStrings[s.aliasStringIdx], i);
1152
+ // Build class-by-name map for this schema
1153
+ const classMap = new Map();
1154
+ for (let c = s.classRangeStart; c < s.classRangeStart + s.classCount; c++)
1155
+ classMap.set(this._lowerStrings[this._classes[c].nameStringIdx], c);
1156
+ classByName.set(i, classMap);
1157
+ // Build enum-by-name map for this schema
1158
+ const eMap = new Map();
1159
+ for (let e = s.enumRangeStart; e < s.enumRangeStart + s.enumCount; e++)
1160
+ eMap.set(this._lowerStrings[this._enumerations[e].nameStringIdx], e);
1161
+ enumByName.set(i, eMap);
1162
+ // Build koq-by-name map for this schema
1163
+ const kMap = new Map();
1164
+ for (let k = s.koqRangeStart; k < s.koqRangeStart + s.koqCount; k++)
1165
+ kMap.set(this._lowerStrings[this._koqs[k].nameStringIdx], k);
1166
+ koqByName.set(i, kMap);
1167
+ // Build category-by-name map for this schema
1168
+ const cMap = new Map();
1169
+ for (let p = s.catRangeStart; p < s.catRangeStart + s.catCount; p++)
1170
+ cMap.set(this._lowerStrings[this._propCategories[p].nameStringIdx], p);
1171
+ catByName.set(i, cMap);
1172
+ }
1173
+ return new SchemaView({
1174
+ strings: this._strings,
1175
+ lowerStrings: this._lowerStrings,
1176
+ schemas: this._schemas,
1177
+ classes: this._classes,
1178
+ classMixins: this._classMixins,
1179
+ propDefs: this._propDefs,
1180
+ propertyRefs: this._propertyRefs,
1181
+ relConstraints: this._relConstraints,
1182
+ constraintClassRefs: this._constraintClassRefs,
1183
+ enumerations: this._enumerations,
1184
+ enumerators: this._enumerators,
1185
+ koqs: this._koqs,
1186
+ propCategories: this._propCategories,
1187
+ schemaByName,
1188
+ schemaByAlias,
1189
+ classByName,
1190
+ enumByName,
1191
+ koqByName,
1192
+ catByName,
1193
+ }, schemaToken);
1194
+ }
1195
+ /** Produce a dedup signature for a PropertyDef. Label and priority are excluded because
1196
+ * they are per-PropertyRef overrides, not part of the structural definition.
1197
+ * Uses SIDs (not lowercase strings) for name/description so that case-preserving names
1198
+ * stay distinct - matching the C++ writer's dedup behavior. */
1199
+ _propDefSignature(def) {
1200
+ return `${def.nameStringIdx}|${def.kind}|${def.primitiveType}|${def.extTypeStringIdx}|${def.enumIdx}|${def.koqIdx}|${def.structClassIdx}|${def.navRelClassIdx}|${def.navDirection}|${def.categoryIdx}|${def.isReadOnly ? 1 : 0}|${def.isHidden ? 1 : 0}|${def.arrayMinOccurs}|${def.arrayMaxOccurs}|${def.descriptionStringIdx}`;
1201
+ }
1202
+ }
1203
+ exports.SchemaViewBuilder = SchemaViewBuilder;
1204
+ //# sourceMappingURL=SchemaView.js.map