@itwin/tree-widget-react 3.16.1 → 3.17.1

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 (142) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/lib/cjs/tree-widget-react/components/SelectableTree.js.map +1 -1
  3. package/lib/cjs/tree-widget-react/components/TreeSelector.js.map +1 -1
  4. package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
  5. package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  6. package/lib/cjs/tree-widget-react/components/tree-header/TreeHeader.js.map +1 -1
  7. package/lib/cjs/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
  8. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  9. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
  10. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  11. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  12. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  13. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  14. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
  15. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +92 -74
  16. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  17. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +3 -1
  18. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +21 -8
  19. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  20. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +21 -9
  21. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +300 -251
  22. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  23. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +2 -0
  24. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +66 -107
  25. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  26. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +22 -12
  27. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  28. package/lib/cjs/tree-widget-react/components/trees/common/UseActiveViewport.js.map +1 -1
  29. package/lib/cjs/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  30. package/lib/cjs/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  31. package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
  32. package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  33. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.d.ts +1 -1
  34. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
  35. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
  36. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
  37. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  38. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
  39. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  40. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
  41. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  42. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
  43. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js +83 -0
  44. package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  45. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
  46. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  47. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  48. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  49. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  50. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +86 -28
  51. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  52. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js +2 -1
  53. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  54. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.d.ts +5 -6
  55. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js +5 -17
  56. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  57. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +5 -4
  58. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  59. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
  60. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
  61. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  62. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +28 -12
  63. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +382 -278
  64. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  65. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
  66. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
  67. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +272 -139
  68. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  69. package/lib/cjs/tree-widget-react-internal.d.ts +2 -1
  70. package/lib/cjs/tree-widget-react-internal.js +4 -1
  71. package/lib/cjs/tree-widget-react-internal.js.map +1 -1
  72. package/lib/esm/tree-widget-react/components/SelectableTree.js.map +1 -1
  73. package/lib/esm/tree-widget-react/components/TreeSelector.js.map +1 -1
  74. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
  75. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  76. package/lib/esm/tree-widget-react/components/tree-header/TreeHeader.js.map +1 -1
  77. package/lib/esm/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
  78. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  79. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
  80. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  81. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  82. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  83. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  84. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
  85. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +92 -74
  86. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  87. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +3 -1
  88. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +22 -9
  89. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  90. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +21 -9
  91. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +301 -252
  92. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  93. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +2 -0
  94. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +67 -108
  95. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +23 -13
  97. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  98. package/lib/esm/tree-widget-react/components/trees/common/UseActiveViewport.js.map +1 -1
  99. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  100. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  101. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
  102. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  103. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.d.ts +1 -1
  104. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
  105. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
  106. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
  107. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  108. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
  109. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  110. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
  111. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  112. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
  113. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +74 -0
  114. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  115. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
  116. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  117. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  118. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  119. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  120. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +83 -25
  121. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  122. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +2 -1
  123. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  124. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +5 -6
  125. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +4 -16
  126. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  127. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +4 -3
  128. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  129. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
  130. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
  131. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  132. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +28 -12
  133. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +382 -278
  134. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  135. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
  136. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
  137. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +257 -124
  138. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  139. package/lib/esm/tree-widget-react-internal.d.ts +2 -1
  140. package/lib/esm/tree-widget-react-internal.js +2 -1
  141. package/lib/esm/tree-widget-react-internal.js.map +1 -1
  142. package/package.json +1 -1
@@ -8,8 +8,9 @@ exports.ModelsTreeIdsCache = void 0;
8
8
  const rxjs_1 = require("rxjs");
9
9
  const core_bentley_1 = require("@itwin/core-bentley");
10
10
  const core_common_1 = require("@itwin/core-common");
11
- const Rxjs_js_1 = require("../../common/Rxjs.js");
12
- const Utils_js_1 = require("../../common/Utils.js");
11
+ const Utils_js_1 = require("../../common/internal/Utils.js");
12
+ const Utils_js_2 = require("../../common/Utils.js");
13
+ const Utils_js_3 = require("../Utils.js");
13
14
  /** @internal */
14
15
  class ModelsTreeIdsCache {
15
16
  #categoryElementCounts;
@@ -22,93 +23,221 @@ class ModelsTreeIdsCache {
22
23
  #categoryKeyPaths;
23
24
  #queryExecutor;
24
25
  #hierarchyConfig;
26
+ #childrenMap;
27
+ /** Stores element ids which have children query scheduled to execute. */
28
+ #childrenLoadingMap;
25
29
  #componentId;
26
30
  #componentName;
27
31
  constructor(queryExecutor, hierarchyConfig, componentId) {
28
32
  this.#hierarchyConfig = hierarchyConfig;
29
33
  this.#queryExecutor = queryExecutor;
30
- this.#categoryElementCounts = new ModelCategoryElementsCountCache(async (input) => this.queryCategoryElementCounts(input));
34
+ this.#categoryElementCounts = new ModelCategoryElementsCountCache((input) => this.queryCategoryElementCounts(input));
31
35
  this.#modelKeyPaths = new Map();
32
36
  this.#subjectKeyPaths = new Map();
33
37
  this.#categoryKeyPaths = new Map();
38
+ this.#childrenMap = new Map();
39
+ this.#childrenLoadingMap = new Map();
34
40
  this.#componentId = componentId ?? core_bentley_1.Guid.createValue();
35
41
  this.#componentName = "ModelsTreeIdsCache";
36
42
  }
37
43
  [Symbol.dispose]() {
38
44
  this.#categoryElementCounts[Symbol.dispose]();
39
45
  }
40
- async *querySubjects() {
41
- const subjectsQuery = `
42
- SELECT
43
- s.ECInstanceId id,
44
- s.Parent.Id parentId,
45
- (
46
- SELECT m.ECInstanceId
47
- FROM bis.GeometricModel3d m
48
- WHERE m.ECInstanceId = HexToId(json_extract(s.JsonProperties, '$.Subject.Model.TargetPartition'))
49
- AND NOT m.IsPrivate
50
- AND EXISTS (SELECT 1 FROM ${this.#hierarchyConfig.elementClassSpecification} WHERE Model.Id = m.ECInstanceId)
51
- ) targetPartitionId,
52
- CASE
53
- WHEN (
54
- json_extract(s.JsonProperties, '$.Subject.Job.Bridge') IS NOT NULL
55
- OR json_extract(s.JsonProperties, '$.Subject.Model.Type') = 'Hierarchy'
56
- ) THEN 1
57
- ELSE 0
58
- END hideInHierarchy
59
- FROM bis.Subject s
60
- `;
61
- for await (const row of this.#queryExecutor.createQueryReader({ ecsql: subjectsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/subjects` })) {
62
- yield { id: row.id, parentId: row.parentId, targetPartitionId: row.targetPartitionId, hideInHierarchy: !!row.hideInHierarchy };
63
- }
46
+ querySubjects() {
47
+ return (0, rxjs_1.defer)(() => {
48
+ const subjectsQuery = `
49
+ SELECT
50
+ s.ECInstanceId id,
51
+ s.Parent.Id parentId,
52
+ (
53
+ SELECT m.ECInstanceId
54
+ FROM bis.GeometricModel3d m
55
+ WHERE m.ECInstanceId = HexToId(json_extract(s.JsonProperties, '$.Subject.Model.TargetPartition'))
56
+ AND NOT m.IsPrivate
57
+ AND EXISTS (SELECT 1 FROM ${this.#hierarchyConfig.elementClassSpecification} WHERE Model.Id = m.ECInstanceId)
58
+ ) targetPartitionId,
59
+ CASE
60
+ WHEN (
61
+ json_extract(s.JsonProperties, '$.Subject.Job.Bridge') IS NOT NULL
62
+ OR json_extract(s.JsonProperties, '$.Subject.Model.Type') = 'Hierarchy'
63
+ ) THEN 1
64
+ ELSE 0
65
+ END hideInHierarchy
66
+ FROM bis.Subject s
67
+ `;
68
+ return this.#queryExecutor.createQueryReader({ ecsql: subjectsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/subjects` });
69
+ }).pipe((0, rxjs_1.map)((row) => {
70
+ return { id: row.id, parentId: row.parentId, targetPartitionId: row.targetPartitionId, hideInHierarchy: !!row.hideInHierarchy };
71
+ }));
64
72
  }
65
- async *queryModels() {
66
- const modelsQuery = `
73
+ queryModels() {
74
+ return (0, rxjs_1.defer)(() => {
75
+ const modelsQuery = `
67
76
  SELECT p.ECInstanceId id, p.Parent.Id parentId
68
- FROM bis.InformationPartitionElement p
69
- INNER JOIN bis.GeometricModel3d m ON m.ModeledElement.Id = p.ECInstanceId
70
- WHERE
71
- NOT m.IsPrivate
72
- ${this.#hierarchyConfig.showEmptyModels ? "" : `AND EXISTS (SELECT 1 FROM ${this.#hierarchyConfig.elementClassSpecification} WHERE Model.Id = m.ECInstanceId)`}
73
- `;
74
- for await (const row of this.#queryExecutor.createQueryReader({ ecsql: modelsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/models` })) {
75
- yield { id: row.id, parentId: row.parentId };
77
+ FROM bis.InformationPartitionElement p
78
+ INNER JOIN bis.GeometricModel3d m ON m.ModeledElement.Id = p.ECInstanceId
79
+ WHERE
80
+ NOT m.IsPrivate
81
+ ${this.#hierarchyConfig.showEmptyModels ? "" : `AND EXISTS (SELECT 1 FROM ${this.#hierarchyConfig.elementClassSpecification} WHERE Model.Id = m.ECInstanceId)`}
82
+ `;
83
+ return this.#queryExecutor.createQueryReader({ ecsql: modelsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/models` });
84
+ }).pipe((0, rxjs_1.map)((row) => {
85
+ return { id: row.id, parentId: row.parentId };
86
+ }));
87
+ }
88
+ queryChildren({ elementIds }) {
89
+ if (elementIds.length === 0) {
90
+ return rxjs_1.EMPTY;
76
91
  }
92
+ return (0, rxjs_1.defer)(() => {
93
+ const ctes = [
94
+ `
95
+ ElementChildren(id, parentId) AS (
96
+ SELECT ECInstanceId id, Parent.Id parentId
97
+ FROM ${this.#hierarchyConfig.elementClassSpecification}
98
+ WHERE Parent.Id IN (${elementIds.join(", ")})
99
+
100
+ UNION ALL
101
+
102
+ SELECT c.ECInstanceId id, c.Parent.Id
103
+ FROM ${this.#hierarchyConfig.elementClassSpecification} c
104
+ JOIN ElementChildren p ON c.Parent.Id = p.id
105
+ )
106
+ `,
107
+ ];
108
+ const ecsql = `
109
+ SELECT id, parentId
110
+ FROM ElementChildren
111
+ `;
112
+ return this.#queryExecutor.createQueryReader({ ecsql, ctes }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/children/${core_bentley_1.Guid.createValue()}` });
113
+ }).pipe((0, rxjs_1.map)((row) => {
114
+ return { id: row.id, parentId: row.parentId };
115
+ }));
77
116
  }
78
- async getSubjectInfos() {
79
- this.#subjectInfos ??= (async () => {
80
- const [subjectInfos, targetPartitionSubjects] = await Promise.all([
81
- (async () => {
82
- const result = new Map();
83
- for await (const subject of this.querySubjects()) {
84
- const subjectInfo = {
85
- parentSubject: subject.parentId,
86
- hideInHierarchy: subject.hideInHierarchy,
87
- childSubjects: new Set(),
88
- childModels: new Set(),
89
- };
90
- if (subject.targetPartitionId) {
91
- subjectInfo.childModels.add(subject.targetPartitionId);
92
- }
93
- result.set(subject.id, subjectInfo);
94
- }
95
- return result;
96
- })(),
97
- (async () => {
98
- const result = new Map();
99
- for await (const model of this.queryModels()) {
100
- (0, Utils_js_1.pushToMap)(result, model.id, model.parentId);
117
+ getChildrenTreeFromMap({ elementIds }) {
118
+ const result = new Map();
119
+ if (core_bentley_1.Id64.sizeOf(elementIds) === 0 || this.#childrenMap.size === 0) {
120
+ return result;
121
+ }
122
+ for (const elementId of core_bentley_1.Id64.iterable(elementIds)) {
123
+ const entry = this.#childrenMap.get(elementId);
124
+ if (!entry?.children) {
125
+ continue;
126
+ }
127
+ const elementChildrenTree = new Map();
128
+ result.set(elementId, { children: elementChildrenTree });
129
+ entry.children.forEach((childId) => {
130
+ const childrenTreeOfChild = this.getChildrenTreeFromMap({ elementIds: childId });
131
+ // Need to add children tree created from childId. This tree includes childId as root element
132
+ // If child does not have children, children tree won't be created. Need to add childId with undefined children
133
+ elementChildrenTree.set(childId, { children: childrenTreeOfChild.size > 0 ? childrenTreeOfChild : undefined });
134
+ });
135
+ }
136
+ return result;
137
+ }
138
+ getChildrenCountMap({ elementIds }) {
139
+ const result = new Map();
140
+ for (const elementId of core_bentley_1.Id64.iterable(elementIds)) {
141
+ const entry = this.#childrenMap.get(elementId);
142
+ if (entry?.children) {
143
+ let totalChildrenCount = entry.children.length;
144
+ this.getChildrenCountMap({ elementIds: entry.children }).forEach((childrenOfChildCount) => (totalChildrenCount += childrenOfChildCount));
145
+ result.set(elementId, totalChildrenCount);
146
+ }
147
+ }
148
+ return result;
149
+ }
150
+ /**
151
+ * Populates #childrenLoadingMap with promises. When these promises resolve, they will populate #childrenMap with values and delete entries from #childrenLoadingMap.
152
+ */
153
+ createChildrenLoadingMapEntries({ elementsToQuery }) {
154
+ const getElementsToQueryPromise = async (batchedElementsToQuery) => (0, rxjs_1.firstValueFrom)(this.queryChildren({ elementIds: batchedElementsToQuery }).pipe(
155
+ // Want to have void at the end instead of void[], so using reduce
156
+ (0, rxjs_1.reduce)((acc, { parentId, id }) => {
157
+ let entry = this.#childrenMap.get(parentId);
158
+ if (!entry) {
159
+ entry = { children: [] };
160
+ this.#childrenMap.set(parentId, entry);
161
+ }
162
+ if (!entry.children) {
163
+ entry.children = [];
164
+ }
165
+ // Add child to parent's entry and add child to children map
166
+ entry.children.push(id);
167
+ if (!this.#childrenMap.has(id)) {
168
+ this.#childrenMap.set(id, { children: undefined });
169
+ }
170
+ return acc;
171
+ }, (() => { })()), (0, rxjs_1.tap)({ complete: () => batchedElementsToQuery.forEach((elementId) => this.#childrenLoadingMap.delete(elementId)) }), (0, rxjs_1.defaultIfEmpty)((() => { })())));
172
+ const maximumBatchSize = 1000;
173
+ const totalSize = elementsToQuery.length;
174
+ const optimalBatchSize = (0, Utils_js_3.getOptimalBatchSize)({ totalSize, maximumBatchSize });
175
+ const loadingMapEntries = new Array();
176
+ // Don't want to slice if its not necessary
177
+ if (totalSize <= maximumBatchSize) {
178
+ loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery));
179
+ }
180
+ else {
181
+ for (let i = 0; i < elementsToQuery.length; i += optimalBatchSize) {
182
+ loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery.slice(i, i + optimalBatchSize)));
183
+ }
184
+ }
185
+ elementsToQuery.forEach((elementId, index) => this.#childrenLoadingMap.set(elementId, loadingMapEntries[Math.floor(index / optimalBatchSize)]));
186
+ return { loadingMapEntries: Promise.all(loadingMapEntries).then(() => { }) };
187
+ }
188
+ createChildrenMapEntries({ elementIds }) {
189
+ return (0, rxjs_1.from)(core_bentley_1.Id64.iterable(elementIds)).pipe((0, rxjs_1.reduce)((acc, elementId) => {
190
+ if (this.#childrenMap.has(elementId)) {
191
+ return acc;
192
+ }
193
+ const loadingPromise = this.#childrenLoadingMap.get(elementId);
194
+ if (loadingPromise) {
195
+ acc.existingPromises.push(loadingPromise);
196
+ }
197
+ else {
198
+ acc.elementsToQuery.push(elementId);
199
+ }
200
+ return acc;
201
+ }, { existingPromises: new Array(), elementsToQuery: new Array() }), (0, rxjs_1.mergeMap)(async ({ elementsToQuery, existingPromises }) => {
202
+ existingPromises.push(this.createChildrenLoadingMapEntries({ elementsToQuery }).loadingMapEntries);
203
+ return Promise.all(existingPromises);
204
+ }));
205
+ }
206
+ getChildrenTree({ elementIds }) {
207
+ return this.createChildrenMapEntries({ elementIds }).pipe((0, rxjs_1.map)(() => this.getChildrenTreeFromMap({ elementIds })));
208
+ }
209
+ getAllChildrenCount({ elementIds }) {
210
+ return this.createChildrenMapEntries({ elementIds }).pipe((0, rxjs_1.map)(() => this.getChildrenCountMap({ elementIds })));
211
+ }
212
+ getSubjectInfos() {
213
+ this.#subjectInfos ??= (0, rxjs_1.forkJoin)({
214
+ subjectInfos: this.querySubjects().pipe((0, rxjs_1.reduce)((acc, subject) => {
215
+ const subjectInfo = {
216
+ parentSubject: subject.parentId,
217
+ hideInHierarchy: subject.hideInHierarchy,
218
+ childSubjects: new Set(),
219
+ childModels: new Set(),
220
+ };
221
+ if (subject.targetPartitionId) {
222
+ subjectInfo.childModels.add(subject.targetPartitionId);
223
+ }
224
+ acc.set(subject.id, subjectInfo);
225
+ return acc;
226
+ }, new Map()), (0, rxjs_1.map)((subjectInfos) => {
227
+ for (const [subjectId, { parentSubject: parentSubjectId }] of subjectInfos.entries()) {
228
+ if (parentSubjectId) {
229
+ const parentSubjectInfo = subjectInfos.get(parentSubjectId);
230
+ (0, core_bentley_1.assert)(!!parentSubjectInfo);
231
+ parentSubjectInfo.childSubjects.add(subjectId);
101
232
  }
102
- return result;
103
- })(),
104
- ]);
105
- for (const [subjectId, { parentSubject: parentSubjectId }] of subjectInfos.entries()) {
106
- if (parentSubjectId) {
107
- const parentSubjectInfo = subjectInfos.get(parentSubjectId);
108
- (0, core_bentley_1.assert)(!!parentSubjectInfo);
109
- parentSubjectInfo.childSubjects.add(subjectId);
110
233
  }
111
- }
234
+ return subjectInfos;
235
+ })),
236
+ targetPartitionSubjects: this.queryModels().pipe((0, rxjs_1.reduce)((acc, model) => {
237
+ (0, Utils_js_2.pushToMap)(acc, model.id, model.parentId);
238
+ return acc;
239
+ }, new Map())),
240
+ }).pipe((0, rxjs_1.map)(({ subjectInfos, targetPartitionSubjects }) => {
112
241
  for (const [partitionId, subjectIds] of targetPartitionSubjects) {
113
242
  subjectIds.forEach((subjectId) => {
114
243
  const subjectInfo = subjectInfos.get(subjectId);
@@ -117,13 +246,12 @@ class ModelsTreeIdsCache {
117
246
  });
118
247
  }
119
248
  return subjectInfos;
120
- })();
249
+ }), (0, rxjs_1.shareReplay)());
121
250
  return this.#subjectInfos;
122
251
  }
123
252
  /** Returns ECInstanceIDs of Subjects that either have direct Model or at least one child Subject with a Model. */
124
- async getParentSubjectIds() {
125
- this.#parentSubjectIds ??= (async () => {
126
- const subjectInfos = await this.getSubjectInfos();
253
+ getParentSubjectIds() {
254
+ this.#parentSubjectIds ??= this.getSubjectInfos().pipe((0, rxjs_1.map)((subjectInfos) => {
127
255
  const parentSubjectIds = new Set();
128
256
  subjectInfos.forEach((subjectInfo, subjectId) => {
129
257
  if (subjectInfo.childModels.size > 0) {
@@ -136,71 +264,73 @@ class ModelsTreeIdsCache {
136
264
  }
137
265
  });
138
266
  return [...parentSubjectIds];
139
- })();
267
+ }), (0, rxjs_1.shareReplay)());
140
268
  return this.#parentSubjectIds;
141
269
  }
142
270
  /**
143
271
  * Returns child subjects of the specified parent subjects as they're displayed in the hierarchy - taking into
144
272
  * account `hideInHierarchy` flag.
145
273
  */
146
- async getChildSubjectIds(parentSubjectIds) {
147
- const childSubjectIds = new Array();
148
- const subjectInfos = await this.getSubjectInfos();
149
- parentSubjectIds.forEach((subjectId) => {
150
- forEachChildSubject(subjectInfos, subjectId, (childSubjectId, childSubjectInfo) => {
151
- if (!childSubjectInfo.hideInHierarchy) {
152
- childSubjectIds.push(childSubjectId);
153
- return "break";
154
- }
155
- return "continue";
274
+ getChildSubjectIds(parentSubjectIds) {
275
+ return this.getSubjectInfos().pipe((0, rxjs_1.map)((subjectInfos) => {
276
+ const childSubjectIds = new Array();
277
+ parentSubjectIds.forEach((subjectId) => {
278
+ forEachChildSubject(subjectInfos, subjectId, (childSubjectId, childSubjectInfo) => {
279
+ if (!childSubjectInfo.hideInHierarchy) {
280
+ childSubjectIds.push(childSubjectId);
281
+ return "break";
282
+ }
283
+ return "continue";
284
+ });
156
285
  });
157
- });
158
- return childSubjectIds;
286
+ return childSubjectIds;
287
+ }));
159
288
  }
160
289
  /** Returns ECInstanceIDs of all Models under specific parent Subjects, including their child Subjects, etc. */
161
- async getSubjectModelIds(subjectIds) {
162
- const subjectInfos = await this.getSubjectInfos();
163
- const subjectStack = [...subjectIds];
164
- const result = new Array();
165
- while (true) {
166
- const subjectId = subjectStack.pop();
167
- if (subjectId === undefined) {
168
- break;
169
- }
170
- const subjectInfo = subjectInfos.get(subjectId);
171
- if (!subjectInfo) {
172
- continue;
290
+ getSubjectModelIds(subjectIds) {
291
+ return this.getSubjectInfos().pipe((0, rxjs_1.map)((subjectInfos) => {
292
+ const subjectStack = [...subjectIds];
293
+ const result = new Array();
294
+ while (true) {
295
+ const subjectId = subjectStack.pop();
296
+ if (subjectId === undefined) {
297
+ break;
298
+ }
299
+ const subjectInfo = subjectInfos.get(subjectId);
300
+ if (!subjectInfo) {
301
+ continue;
302
+ }
303
+ result.push(...subjectInfo.childModels);
304
+ subjectStack.push(...subjectInfo.childSubjects);
173
305
  }
174
- result.push(...subjectInfo.childModels);
175
- subjectStack.push(...subjectInfo.childSubjects);
176
- }
177
- return result;
306
+ return result;
307
+ }));
178
308
  }
179
309
  /** Returns ECInstanceIDs of Models under specific parent Subjects as they are displayed in the hierarchy. */
180
- async getChildSubjectModelIds(parentSubjectIds) {
181
- const subjectInfos = await this.getSubjectInfos();
182
- const hiddenSubjectIds = new Array();
183
- parentSubjectIds.forEach((subjectId) => {
184
- forEachChildSubject(subjectInfos, subjectId, (childSubjectId, childSubjectInfo) => {
185
- if (childSubjectInfo.hideInHierarchy) {
186
- hiddenSubjectIds.push(childSubjectId);
187
- return "continue";
188
- }
189
- return "break";
310
+ getChildSubjectModelIds(parentSubjectIds) {
311
+ return this.getSubjectInfos().pipe((0, rxjs_1.map)((subjectInfos) => {
312
+ const hiddenSubjectIds = new Array();
313
+ parentSubjectIds.forEach((subjectId) => {
314
+ forEachChildSubject(subjectInfos, subjectId, (childSubjectId, childSubjectInfo) => {
315
+ if (childSubjectInfo.hideInHierarchy) {
316
+ hiddenSubjectIds.push(childSubjectId);
317
+ return "continue";
318
+ }
319
+ return "break";
320
+ });
190
321
  });
191
- });
192
- const modelIds = new Array();
193
- [...parentSubjectIds, ...hiddenSubjectIds].forEach((subjectId) => {
194
- const subjectInfo = subjectInfos.get(subjectId);
195
- subjectInfo && modelIds.push(...subjectInfo.childModels);
196
- });
197
- return modelIds;
322
+ const modelIds = new Array();
323
+ [...parentSubjectIds, ...hiddenSubjectIds].forEach((subjectId) => {
324
+ const subjectInfo = subjectInfos.get(subjectId);
325
+ subjectInfo && modelIds.push(...subjectInfo.childModels);
326
+ });
327
+ return modelIds;
328
+ }));
198
329
  }
199
- async createSubjectInstanceKeysPath(targetSubjectId) {
330
+ createSubjectInstanceKeysPath(targetSubjectId) {
200
331
  let entry = this.#subjectKeyPaths.get(targetSubjectId);
201
332
  if (!entry) {
202
- entry = (async () => {
203
- const subjectInfos = await this.getSubjectInfos();
333
+ entry = this.getSubjectInfos().pipe((0, rxjs_1.map)((subjectInfos) => {
204
334
  const result = new Array();
205
335
  let currParentId = targetSubjectId;
206
336
  while (currParentId) {
@@ -214,128 +344,111 @@ class ModelsTreeIdsCache {
214
344
  currParentId = parentInfo?.parentSubject;
215
345
  }
216
346
  return result.reverse();
217
- })();
347
+ }), (0, rxjs_1.shareReplay)());
218
348
  this.#subjectKeyPaths.set(targetSubjectId, entry);
219
349
  }
220
350
  return entry;
221
351
  }
222
- async *queryModelCategories() {
223
- const query = `
224
- SELECT
225
- this.Model.Id modelId,
226
- this.Category.Id categoryId,
227
- m.IsPrivate isModelPrivate,
228
- MAX(IIF(this.Parent.Id IS NULL, 1, 0)) isRootElementCategory
229
- FROM BisCore.Model m
230
- JOIN ${this.#hierarchyConfig.elementClassSpecification} this ON m.ECInstanceId = this.Model.Id
231
- GROUP BY modelId, categoryId, isModelPrivate
232
- `;
233
- for await (const row of this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/model-categories` })) {
234
- yield { modelId: row.modelId, categoryId: row.categoryId, isModelPrivate: !!row.isModelPrivate, isRootElementCategory: !!row.isRootElementCategory };
235
- }
352
+ queryModelCategories() {
353
+ return (0, rxjs_1.defer)(() => {
354
+ const query = `
355
+ SELECT
356
+ this.Model.Id modelId,
357
+ this.Category.Id categoryId,
358
+ m.IsPrivate isModelPrivate,
359
+ MAX(IIF(this.Parent.Id IS NULL, 1, 0)) isRootElementCategory
360
+ FROM BisCore.Model m
361
+ JOIN ${this.#hierarchyConfig.elementClassSpecification} this ON m.ECInstanceId = this.Model.Id
362
+ GROUP BY modelId, categoryId, isModelPrivate
363
+ `;
364
+ return this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/model-categories` });
365
+ }).pipe((0, rxjs_1.map)((row) => {
366
+ return { modelId: row.modelId, categoryId: row.categoryId, isModelPrivate: !!row.isModelPrivate, isRootElementCategory: !!row.isRootElementCategory };
367
+ }));
236
368
  }
237
- async *queryModeledElements() {
238
- const query = `
239
- SELECT
240
- pe.ECInstanceId modeledElementId,
241
- pe.Category.Id categoryId,
242
- pe.Model.Id modelId
243
- FROM BisCore.Model m
244
- JOIN ${this.#hierarchyConfig.elementClassSpecification} pe ON pe.ECInstanceId = m.ModeledElement.Id
245
- WHERE
246
- m.IsPrivate = false
247
- AND m.ECInstanceId IN (SELECT Model.Id FROM ${this.#hierarchyConfig.elementClassSpecification})
248
- `;
249
- for await (const row of this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/modeled-elements` })) {
250
- yield { modelId: row.modelId, categoryId: row.categoryId, modeledElementId: row.modeledElementId };
251
- }
369
+ queryModeledElements() {
370
+ return (0, rxjs_1.defer)(() => {
371
+ const query = `
372
+ SELECT
373
+ pe.ECInstanceId modeledElementId,
374
+ pe.Category.Id categoryId,
375
+ pe.Model.Id modelId
376
+ FROM BisCore.Model m
377
+ JOIN ${this.#hierarchyConfig.elementClassSpecification} pe ON pe.ECInstanceId = m.ModeledElement.Id
378
+ WHERE
379
+ m.IsPrivate = false
380
+ AND m.ECInstanceId IN (SELECT Model.Id FROM ${this.#hierarchyConfig.elementClassSpecification})
381
+ `;
382
+ return this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/modeled-elements` });
383
+ }).pipe((0, rxjs_1.map)((row) => {
384
+ return { modelId: row.modelId, categoryId: row.categoryId, modeledElementId: row.modeledElementId };
385
+ }));
252
386
  }
253
- async getModelWithCategoryModeledElements() {
254
- this.#modelWithCategoryModeledElements ??= (async () => {
255
- const modelWithCategoryModeledElements = new Map();
256
- for await (const { modelId, categoryId, modeledElementId } of this.queryModeledElements()) {
257
- const key = `${modelId}-${categoryId}`;
258
- const entry = modelWithCategoryModeledElements.get(key);
259
- if (entry === undefined) {
260
- modelWithCategoryModeledElements.set(key, new Set([modeledElementId]));
261
- }
262
- else {
263
- entry.add(modeledElementId);
264
- }
387
+ getModelWithCategoryModeledElements() {
388
+ this.#modelWithCategoryModeledElements ??= this.queryModeledElements().pipe((0, rxjs_1.reduce)((acc, { modelId, categoryId, modeledElementId }) => {
389
+ const key = `${modelId}-${categoryId}`;
390
+ const entry = acc.get(key);
391
+ if (entry === undefined) {
392
+ acc.set(key, new Set([modeledElementId]));
265
393
  }
266
- return modelWithCategoryModeledElements;
267
- })();
394
+ else {
395
+ entry.add(modeledElementId);
396
+ }
397
+ return acc;
398
+ }, new Map()), (0, rxjs_1.shareReplay)());
268
399
  return this.#modelWithCategoryModeledElements;
269
400
  }
270
- async getModelInfos() {
271
- this.#modelInfos ??= (async () => {
272
- const modelInfos = new Map();
273
- for await (const { modelId, categoryId, isModelPrivate, isRootElementCategory } of this.queryModelCategories()) {
274
- const entry = modelInfos.get(modelId);
275
- if (entry) {
276
- entry.categories.set(categoryId, { isRootElementCategory });
277
- entry.isModelPrivate = isModelPrivate;
278
- }
279
- else {
280
- modelInfos.set(modelId, { categories: new Map([[categoryId, { isRootElementCategory }]]), isModelPrivate });
281
- }
401
+ getModelInfos() {
402
+ this.#modelInfos ??= this.queryModelCategories().pipe((0, rxjs_1.reduce)((acc, { modelId, categoryId, isModelPrivate, isRootElementCategory }) => {
403
+ const entry = acc.get(modelId);
404
+ if (entry) {
405
+ entry.categories.set(categoryId, { isRootElementCategory });
406
+ entry.isModelPrivate = isModelPrivate;
407
+ }
408
+ else {
409
+ acc.set(modelId, { categories: new Map([[categoryId, { isRootElementCategory }]]), isModelPrivate });
282
410
  }
283
- return modelInfos;
284
- })();
411
+ return acc;
412
+ }, new Map()), (0, rxjs_1.shareReplay)());
285
413
  return this.#modelInfos;
286
414
  }
287
- async getAllCategories() {
288
- const modelInfos = await this.getModelInfos();
289
- const result = new Set();
290
- modelInfos.forEach(({ categories }) => {
291
- categories.forEach((_, categoryId) => result.add(categoryId));
292
- });
293
- return result;
415
+ getAllCategories() {
416
+ return this.getModelInfos().pipe((0, rxjs_1.mergeMap)((modelInfos) => modelInfos.values()), (0, rxjs_1.mergeMap)(({ categories }) => categories.keys()), (0, rxjs_1.reduce)((acc, categoryId) => {
417
+ acc.add(categoryId);
418
+ return acc;
419
+ }, new Set()));
294
420
  }
295
- async getModelCategories(modelId) {
296
- const modelInfos = await this.getModelInfos();
297
- const categories = modelInfos.get(modelId)?.categories.keys();
298
- return categories ? [...categories] : [];
421
+ getModelCategories(modelId) {
422
+ return this.getModelInfos().pipe((0, rxjs_1.mergeMap)((modelInfos) => modelInfos.get(modelId)?.categories.keys() ?? []), (0, rxjs_1.toArray)());
299
423
  }
300
- async hasSubModel(elementId) {
301
- const modelInfos = await this.getModelInfos();
302
- const modeledElementInfo = modelInfos.get(elementId);
303
- if (!modeledElementInfo) {
304
- return false;
305
- }
306
- return !modeledElementInfo.isModelPrivate;
424
+ hasSubModel(elementId) {
425
+ return this.getModelInfos().pipe((0, rxjs_1.map)((modelInfos) => {
426
+ const modeledElementInfo = modelInfos.get(elementId);
427
+ if (!modeledElementInfo) {
428
+ return false;
429
+ }
430
+ return !modeledElementInfo.isModelPrivate;
431
+ }));
307
432
  }
308
- async getCategoriesModeledElements(modelId, categoryIds) {
309
- const modelWithCategoryModeledElements = await this.getModelWithCategoryModeledElements();
310
- const result = new Array();
311
- for (const categoryId of core_bentley_1.Id64.iterable(categoryIds)) {
433
+ getCategoriesModeledElements(modelId, categoryIds) {
434
+ return this.getModelWithCategoryModeledElements().pipe((0, rxjs_1.mergeMap)((modelWithCategoryModeledElements) => (0, rxjs_1.from)(core_bentley_1.Id64.iterable(categoryIds)).pipe((0, rxjs_1.reduce)((acc, categoryId) => {
312
435
  const entry = modelWithCategoryModeledElements.get(`${modelId}-${categoryId}`);
313
436
  if (entry !== undefined) {
314
- result.push(...entry);
437
+ acc.push(...entry);
315
438
  }
316
- }
317
- return result;
439
+ return acc;
440
+ }, new Array()))));
318
441
  }
319
- async createModelInstanceKeyPaths(modelId) {
442
+ createModelInstanceKeyPaths(modelId) {
320
443
  let entry = this.#modelKeyPaths.get(modelId);
321
444
  if (!entry) {
322
- entry = (async () => {
323
- const result = new Array();
324
- const subjectInfos = (await this.getSubjectInfos()).entries();
325
- for (const [modelSubjectId, subjectInfo] of subjectInfos) {
326
- if (subjectInfo.childModels.has(modelId)) {
327
- const subjectPath = await this.createSubjectInstanceKeysPath(modelSubjectId);
328
- result.push([...subjectPath, { className: "BisCore.GeometricModel3d", id: modelId }]);
329
- }
330
- }
331
- return result;
332
- })();
445
+ entry = this.getSubjectInfos().pipe((0, rxjs_1.mergeMap)((subjectInfos) => subjectInfos.entries()), (0, rxjs_1.filter)(([_, subjectInfo]) => subjectInfo.childModels.has(modelId)), (0, rxjs_1.mergeMap)(([modelSubjectId]) => this.createSubjectInstanceKeysPath(modelSubjectId).pipe((0, rxjs_1.map)((path) => [...path, { className: "BisCore.GeometricModel3d", id: modelId }]))), (0, rxjs_1.toArray)(), (0, rxjs_1.shareReplay)());
333
446
  this.#modelKeyPaths.set(modelId, entry);
334
447
  }
335
448
  return entry;
336
449
  }
337
- async queryCategoryElementCounts(input) {
338
- return (0, Rxjs_js_1.collect)((0, rxjs_1.from)(input).pipe((0, rxjs_1.reduce)((acc, { modelId, categoryId }) => {
450
+ queryCategoryElementCounts(input) {
451
+ return (0, rxjs_1.from)(input).pipe((0, rxjs_1.reduce)((acc, { modelId, categoryId }) => {
339
452
  const entry = acc.get(modelId);
340
453
  if (!entry) {
341
454
  acc.set(modelId, new Set([categoryId]));
@@ -347,73 +460,64 @@ class ModelsTreeIdsCache {
347
460
  }, new Map()), (0, rxjs_1.mergeMap)((modelCategoryMap) => modelCategoryMap.entries()), (0, rxjs_1.map)(([modelId, categoryIds]) => `Model.Id = ${modelId} AND Category.Id IN (${[...categoryIds].join(", ")})`),
348
461
  // we may have thousands of where clauses here, and sending a single query with all of them could take a
349
462
  // long time - instead, split it into smaller chunks
350
- (0, rxjs_1.bufferCount)(100), (0, rxjs_1.mergeMap)(async (whereClauses) => {
351
- const reader = this.#queryExecutor.createQueryReader({
352
- ctes: [
353
- `
354
- CategoryElements(id, modelId, categoryId) AS (
355
- SELECT ECInstanceId, Model.Id, Category.Id
356
- FROM ${this.#hierarchyConfig.elementClassSpecification}
357
- WHERE
358
- Parent.Id IS NULL
359
- AND (
360
- ${whereClauses.join(" OR ")}
361
- )
463
+ (0, rxjs_1.bufferCount)(100), (0, rxjs_1.mergeMap)((whereClauses) => (0, rxjs_1.defer)(() => this.#queryExecutor.createQueryReader({
464
+ ctes: [
465
+ `
466
+ CategoryElements(id, modelId, categoryId) AS (
467
+ SELECT ECInstanceId, Model.Id, Category.Id
468
+ FROM ${this.#hierarchyConfig.elementClassSpecification}
469
+ WHERE
470
+ Parent.Id IS NULL
471
+ AND (
472
+ ${whereClauses.join(" OR ")}
473
+ )
362
474
 
363
- UNION ALL
475
+ UNION ALL
364
476
 
365
- SELECT c.ECInstanceId, p.modelId, p.categoryId
366
- FROM ${this.#hierarchyConfig.elementClassSpecification} c
367
- JOIN CategoryElements p ON c.Parent.Id = p.id
368
- )
477
+ SELECT c.ECInstanceId, p.modelId, p.categoryId
478
+ FROM ${this.#hierarchyConfig.elementClassSpecification} c
479
+ JOIN CategoryElements p ON c.Parent.Id = p.id
480
+ )
481
+ `,
482
+ ],
483
+ ecsql: `
484
+ SELECT modelId, categoryId, COUNT(id) elementsCount
485
+ FROM CategoryElements
486
+ GROUP BY modelId, categoryId
369
487
  `,
370
- ],
371
- ecsql: `
372
- SELECT modelId, categoryId, COUNT(id) elementsCount
373
- FROM CategoryElements
374
- GROUP BY modelId, categoryId
375
- `,
376
- }, {
377
- rowFormat: "ECSqlPropertyNames",
378
- limit: "unbounded",
379
- restartToken: `${this.#componentName}/${this.#componentId}/category-element-counts/${core_bentley_1.Guid.createValue()}`,
488
+ }, {
489
+ rowFormat: "ECSqlPropertyNames",
490
+ limit: "unbounded",
491
+ restartToken: `${this.#componentName}/${this.#componentId}/category-element-counts/${core_bentley_1.Guid.createValue()}`,
492
+ }))), (0, Utils_js_1.releaseMainThreadOnItemsCount)(500), (0, rxjs_1.reduce)(({ acc, createKey }, row) => {
493
+ acc.set(createKey({ modelId: row.modelId, categoryId: row.categoryId }), {
494
+ modelId: row.modelId,
495
+ categoryId: row.categoryId,
496
+ elementsCount: row.elementsCount,
380
497
  });
381
- const result = new Array();
382
- for await (const row of reader) {
383
- result.push({ modelId: row.modelId, categoryId: row.categoryId, elementsCount: row.elementsCount });
384
- }
498
+ return { acc, createKey };
499
+ }, {
500
+ acc: new Map(),
501
+ createKey: (keyProps) => `${keyProps.modelId}-${keyProps.categoryId}`,
502
+ }), (0, rxjs_1.mergeMap)(({ acc: result, createKey }) => {
385
503
  input.forEach(({ modelId, categoryId }) => {
386
- if (!result.some((queriedResult) => queriedResult.categoryId === categoryId && queriedResult.modelId === modelId)) {
387
- result.push({ categoryId, modelId, elementsCount: 0 });
504
+ if (!result.has(createKey({ modelId, categoryId }))) {
505
+ result.set(createKey({ modelId, categoryId }), { categoryId, modelId, elementsCount: 0 });
388
506
  }
389
507
  });
390
- return result;
391
- }), (0, rxjs_1.mergeAll)()));
508
+ return (0, rxjs_1.from)(result.values());
509
+ }), (0, rxjs_1.toArray)());
392
510
  }
393
- async getCategoryElementsCount(modelId, categoryId) {
511
+ getCategoryElementsCount(modelId, categoryId) {
394
512
  return this.#categoryElementCounts.getCategoryElementsCount(modelId, categoryId);
395
513
  }
396
- async createCategoryInstanceKeyPaths(categoryId) {
514
+ createCategoryInstanceKeyPaths(categoryId) {
397
515
  let entry = this.#categoryKeyPaths.get(categoryId);
398
516
  if (!entry) {
399
- entry = (async () => {
400
- const result = new Set();
401
- const modelInfos = await this.getModelInfos();
402
- modelInfos?.forEach((modelInfo, modelId) => {
403
- const categoryEntry = modelInfo.categories.get(categoryId);
404
- if (categoryEntry?.isRootElementCategory) {
405
- result.add(modelId);
406
- }
407
- });
408
- const categoryPaths = new Array();
409
- for (const categoryModelId of [...result]) {
410
- const modelPaths = await this.createModelInstanceKeyPaths(categoryModelId);
411
- for (const modelPath of modelPaths) {
412
- categoryPaths.push([...modelPath, { className: "BisCore.SpatialCategory", id: categoryId }]);
413
- }
414
- }
415
- return categoryPaths;
416
- })();
517
+ entry = this.getModelInfos().pipe((0, rxjs_1.mergeMap)((modelInfos) => modelInfos.entries()), (0, rxjs_1.filter)(([_, modelInfo]) => !!modelInfo.categories.get(categoryId)?.isRootElementCategory), (0, rxjs_1.mergeMap)(([categoryModelId]) => this.createModelInstanceKeyPaths(categoryModelId)), (0, rxjs_1.mergeMap)((modelPaths) => modelPaths), (0, rxjs_1.reduce)((acc, modelPath) => {
518
+ acc.push([...modelPath, { className: "BisCore.SpatialCategory", id: categoryId }]);
519
+ return acc;
520
+ }, new Array()), (0, rxjs_1.shareReplay)());
417
521
  this.#categoryKeyPaths.set(categoryId, entry);
418
522
  }
419
523
  return entry;
@@ -437,7 +541,7 @@ class ModelCategoryElementsCountCache {
437
541
  #subscription;
438
542
  constructor(loader) {
439
543
  this.#subscription = this.#requestsStream
440
- .pipe((0, rxjs_1.bufferTime)(20), (0, rxjs_1.filter)((requests) => requests.length > 0), (0, rxjs_1.mergeMap)(async (requests) => loader(requests)), (0, rxjs_1.mergeAll)())
544
+ .pipe((0, rxjs_1.bufferTime)(20), (0, rxjs_1.filter)((requests) => requests.length > 0), (0, rxjs_1.mergeMap)((requests) => loader(requests)), (0, rxjs_1.mergeAll)())
441
545
  .subscribe({
442
546
  next: ({ modelId, categoryId, elementsCount }) => {
443
547
  const subject = this.#cache.get(`${modelId}${categoryId}`);
@@ -449,16 +553,16 @@ class ModelCategoryElementsCountCache {
449
553
  [Symbol.dispose]() {
450
554
  this.#subscription.unsubscribe();
451
555
  }
452
- async getCategoryElementsCount(modelId, categoryId) {
556
+ getCategoryElementsCount(modelId, categoryId) {
453
557
  const cacheKey = `${modelId}${categoryId}`;
454
558
  let result = this.#cache.get(cacheKey);
455
559
  if (result !== undefined) {
456
- return (0, rxjs_1.firstValueFrom)(result);
560
+ return (0, rxjs_1.from)(result).pipe((0, rxjs_1.take)(1));
457
561
  }
458
562
  result = new rxjs_1.ReplaySubject(1);
459
563
  this.#cache.set(cacheKey, result);
460
564
  this.#requestsStream.next({ modelId, categoryId });
461
- return (0, rxjs_1.firstValueFrom)(result);
565
+ return (0, rxjs_1.from)(result).pipe((0, rxjs_1.take)(1));
462
566
  }
463
567
  }
464
568
  //# sourceMappingURL=ModelsTreeIdsCache.js.map