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