@itwin/presentation-hierarchies 2.0.0-alpha.1 → 2.0.0-alpha.10

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 (151) hide show
  1. package/CHANGELOG.md +248 -8
  2. package/README.md +4 -22
  3. package/lib/cjs/hierarchies/HierarchyMerge.d.ts +19 -0
  4. package/lib/cjs/hierarchies/HierarchyMerge.d.ts.map +1 -0
  5. package/lib/cjs/hierarchies/HierarchyMerge.js +43 -0
  6. package/lib/cjs/hierarchies/HierarchyMerge.js.map +1 -0
  7. package/lib/cjs/hierarchies/HierarchyNode.d.ts +14 -24
  8. package/lib/cjs/hierarchies/HierarchyNode.d.ts.map +1 -1
  9. package/lib/cjs/hierarchies/HierarchyNode.js +1 -21
  10. package/lib/cjs/hierarchies/HierarchyNode.js.map +1 -1
  11. package/lib/cjs/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
  12. package/lib/cjs/hierarchies/HierarchyNodeKey.js +8 -8
  13. package/lib/cjs/hierarchies/HierarchyNodeKey.js.map +1 -1
  14. package/lib/cjs/hierarchies/HierarchyProvider.d.ts +11 -29
  15. package/lib/cjs/hierarchies/HierarchyProvider.d.ts.map +1 -1
  16. package/lib/cjs/hierarchies/HierarchyProvider.js +0 -37
  17. package/lib/cjs/hierarchies/HierarchyProvider.js.map +1 -1
  18. package/lib/cjs/hierarchies/HierarchySearch.d.ts +167 -0
  19. package/lib/cjs/hierarchies/HierarchySearch.d.ts.map +1 -0
  20. package/lib/cjs/hierarchies/HierarchySearch.js +259 -0
  21. package/lib/cjs/hierarchies/HierarchySearch.js.map +1 -0
  22. package/lib/cjs/hierarchies/imodel/HierarchyCache.js +3 -3
  23. package/lib/cjs/hierarchies/imodel/HierarchyCache.js.map +1 -1
  24. package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.d.ts +15 -4
  25. package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.d.ts.map +1 -1
  26. package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.js.map +1 -1
  27. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts +46 -11
  28. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
  29. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js +192 -65
  30. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
  31. package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.d.ts +2 -2
  32. package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
  33. package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.js +99 -40
  34. package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
  35. package/lib/cjs/hierarchies/imodel/{FilteringHierarchyDefinition.d.ts → SearchHierarchyDefinition.d.ts} +13 -14
  36. package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -0
  37. package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.js +285 -0
  38. package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -0
  39. package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts +4 -6
  40. package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
  41. package/lib/cjs/hierarchies/imodel/TreeNodesReader.js +15 -5
  42. package/lib/cjs/hierarchies/imodel/TreeNodesReader.js.map +1 -1
  43. package/lib/cjs/hierarchies/imodel/operators/HideIfNoChildren.d.ts.map +1 -1
  44. package/lib/cjs/hierarchies/imodel/operators/HideIfNoChildren.js +1 -0
  45. package/lib/cjs/hierarchies/imodel/operators/HideIfNoChildren.js.map +1 -1
  46. package/lib/cjs/hierarchies/imodel/operators/grouping/BaseClassGrouping.d.ts.map +1 -1
  47. package/lib/cjs/hierarchies/imodel/operators/grouping/BaseClassGrouping.js +6 -5
  48. package/lib/cjs/hierarchies/imodel/operators/grouping/BaseClassGrouping.js.map +1 -1
  49. package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.d.ts.map +1 -1
  50. package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.js +4 -3
  51. package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.js.map +1 -1
  52. package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts.map +1 -1
  53. package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.js +21 -16
  54. package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.js.map +1 -1
  55. package/lib/cjs/hierarchies/internal/Common.d.ts +3 -0
  56. package/lib/cjs/hierarchies/internal/Common.d.ts.map +1 -1
  57. package/lib/cjs/hierarchies/internal/Common.js +12 -1
  58. package/lib/cjs/hierarchies/internal/Common.js.map +1 -1
  59. package/lib/cjs/hierarchies/internal/EachValueFrom.d.ts.map +1 -1
  60. package/lib/cjs/hierarchies/internal/EachValueFrom.js +1 -0
  61. package/lib/cjs/hierarchies/internal/EachValueFrom.js.map +1 -1
  62. package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.d.ts +7 -3
  63. package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -1
  64. package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js +4 -3
  65. package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -1
  66. package/lib/cjs/presentation-hierarchies.d.ts +5 -4
  67. package/lib/cjs/presentation-hierarchies.d.ts.map +1 -1
  68. package/lib/cjs/presentation-hierarchies.js +7 -7
  69. package/lib/cjs/presentation-hierarchies.js.map +1 -1
  70. package/lib/esm/hierarchies/HierarchyMerge.d.ts +19 -0
  71. package/lib/esm/hierarchies/HierarchyMerge.d.ts.map +1 -0
  72. package/lib/esm/hierarchies/HierarchyMerge.js +40 -0
  73. package/lib/esm/hierarchies/HierarchyMerge.js.map +1 -0
  74. package/lib/esm/hierarchies/HierarchyNode.d.ts +14 -24
  75. package/lib/esm/hierarchies/HierarchyNode.d.ts.map +1 -1
  76. package/lib/esm/hierarchies/HierarchyNode.js +0 -20
  77. package/lib/esm/hierarchies/HierarchyNode.js.map +1 -1
  78. package/lib/esm/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
  79. package/lib/esm/hierarchies/HierarchyNodeKey.js +9 -9
  80. package/lib/esm/hierarchies/HierarchyNodeKey.js.map +1 -1
  81. package/lib/esm/hierarchies/HierarchyProvider.d.ts +11 -29
  82. package/lib/esm/hierarchies/HierarchyProvider.d.ts.map +1 -1
  83. package/lib/esm/hierarchies/HierarchyProvider.js +1 -36
  84. package/lib/esm/hierarchies/HierarchyProvider.js.map +1 -1
  85. package/lib/esm/hierarchies/HierarchySearch.d.ts +167 -0
  86. package/lib/esm/hierarchies/HierarchySearch.d.ts.map +1 -0
  87. package/lib/esm/hierarchies/HierarchySearch.js +254 -0
  88. package/lib/esm/hierarchies/HierarchySearch.js.map +1 -0
  89. package/lib/esm/hierarchies/imodel/HierarchyCache.js +3 -3
  90. package/lib/esm/hierarchies/imodel/HierarchyCache.js.map +1 -1
  91. package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.d.ts +15 -4
  92. package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.d.ts.map +1 -1
  93. package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.js.map +1 -1
  94. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts +46 -11
  95. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
  96. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js +194 -68
  97. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
  98. package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.d.ts +2 -2
  99. package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
  100. package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.js +100 -41
  101. package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
  102. package/lib/esm/hierarchies/imodel/{FilteringHierarchyDefinition.d.ts → SearchHierarchyDefinition.d.ts} +13 -14
  103. package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -0
  104. package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.js +279 -0
  105. package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -0
  106. package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts +4 -6
  107. package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
  108. package/lib/esm/hierarchies/imodel/TreeNodesReader.js +12 -3
  109. package/lib/esm/hierarchies/imodel/TreeNodesReader.js.map +1 -1
  110. package/lib/esm/hierarchies/imodel/operators/HideIfNoChildren.d.ts.map +1 -1
  111. package/lib/esm/hierarchies/imodel/operators/HideIfNoChildren.js +1 -0
  112. package/lib/esm/hierarchies/imodel/operators/HideIfNoChildren.js.map +1 -1
  113. package/lib/esm/hierarchies/imodel/operators/grouping/BaseClassGrouping.d.ts.map +1 -1
  114. package/lib/esm/hierarchies/imodel/operators/grouping/BaseClassGrouping.js +7 -6
  115. package/lib/esm/hierarchies/imodel/operators/grouping/BaseClassGrouping.js.map +1 -1
  116. package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.d.ts.map +1 -1
  117. package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.js +5 -4
  118. package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.js.map +1 -1
  119. package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts.map +1 -1
  120. package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.js +22 -17
  121. package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.js.map +1 -1
  122. package/lib/esm/hierarchies/internal/Common.d.ts +3 -0
  123. package/lib/esm/hierarchies/internal/Common.d.ts.map +1 -1
  124. package/lib/esm/hierarchies/internal/Common.js +11 -1
  125. package/lib/esm/hierarchies/internal/Common.js.map +1 -1
  126. package/lib/esm/hierarchies/internal/EachValueFrom.d.ts.map +1 -1
  127. package/lib/esm/hierarchies/internal/EachValueFrom.js +1 -0
  128. package/lib/esm/hierarchies/internal/EachValueFrom.js.map +1 -1
  129. package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.d.ts +7 -3
  130. package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -1
  131. package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js +5 -4
  132. package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -1
  133. package/lib/esm/presentation-hierarchies.d.ts +5 -4
  134. package/lib/esm/presentation-hierarchies.d.ts.map +1 -1
  135. package/lib/esm/presentation-hierarchies.js +3 -3
  136. package/lib/esm/presentation-hierarchies.js.map +1 -1
  137. package/package.json +18 -18
  138. package/lib/cjs/hierarchies/HierarchyFiltering.d.ts +0 -110
  139. package/lib/cjs/hierarchies/HierarchyFiltering.d.ts.map +0 -1
  140. package/lib/cjs/hierarchies/HierarchyFiltering.js +0 -215
  141. package/lib/cjs/hierarchies/HierarchyFiltering.js.map +0 -1
  142. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
  143. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js +0 -274
  144. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
  145. package/lib/esm/hierarchies/HierarchyFiltering.d.ts +0 -110
  146. package/lib/esm/hierarchies/HierarchyFiltering.d.ts.map +0 -1
  147. package/lib/esm/hierarchies/HierarchyFiltering.js +0 -210
  148. package/lib/esm/hierarchies/HierarchyFiltering.js.map +0 -1
  149. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
  150. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js +0 -268
  151. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { GenericInstanceFilter } from "@itwin/core-common";
2
- import { ECSqlQueryDef } from "@itwin/presentation-shared";
2
+ import { ECClassHierarchyInspector, ECSchemaProvider, ECSqlQueryDef } from "@itwin/presentation-shared";
3
3
  import { NonGroupingHierarchyNode } from "../HierarchyNode.js";
4
4
  import { ProcessedGenericHierarchyNode, ProcessedHierarchyNode, ProcessedInstanceHierarchyNode, SourceGenericHierarchyNode, SourceInstanceHierarchyNode } from "./IModelHierarchyNode.js";
5
5
  /**
@@ -46,9 +46,16 @@ export type HierarchyLevelDefinition = HierarchyNodesDefinition[];
46
46
  * A type for a function that parses a `SourceInstanceHierarchyNode` from provided ECSQL `row` object.
47
47
  * @public
48
48
  */
49
- export type NodeParser = (row: {
50
- [columnName: string]: any;
51
- }, parentNode?: HierarchyDefinitionParentNode) => SourceInstanceHierarchyNode | Promise<SourceInstanceHierarchyNode>;
49
+ export type NodeParser = (props: {
50
+ /** The ECSQL row object to parse. Keys & value types depend on the executed query. */
51
+ row: {
52
+ [columnName: string]: any;
53
+ };
54
+ /** The parent node whose child node is being parsed. */
55
+ parentNode?: HierarchyDefinitionParentNode;
56
+ /** The key of iModel which is used to run the query. */
57
+ imodelKey: string;
58
+ }) => SourceInstanceHierarchyNode | Promise<SourceInstanceHierarchyNode>;
52
59
  /**
53
60
  * A type for a function that pre-processes given node. Unless the function decides not to make any modifications,
54
61
  * it should return a new - modified - node, rather than modifying the given one. Returning `undefined` omits the node
@@ -77,6 +84,10 @@ export type HierarchyDefinitionParentNode = Omit<NonGroupingHierarchyNode, "chil
77
84
  * @public
78
85
  */
79
86
  export interface DefineHierarchyLevelProps {
87
+ /** The iModel for which the hierarchy definition is being requested for. */
88
+ imodelAccess: ECSchemaProvider & ECClassHierarchyInspector & {
89
+ imodelKey: string;
90
+ };
80
91
  /** Parent node to get children for. Pass `undefined` to get root nodes. */
81
92
  parentNode: HierarchyDefinitionParentNode | undefined;
82
93
  /** Optional hierarchy level filter. */
@@ -1 +1 @@
1
- {"version":3,"file":"IModelHierarchyDefinition.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyDefinition.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,8BAA8B,EAC9B,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAElC;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,oDAAoD;IACpD,IAAI,EAAE,0BAA0B,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,8BAA8B,GAAG,4BAA4B,CAAC;AACrG,cAAc;AAEd,yBAAiB,wBAAwB,CAAC;IACxC,SAAgB,aAAa,CAAC,GAAG,EAAE,wBAAwB,GAAG,GAAG,IAAI,8BAA8B,CAElG;IACD,SAAgB,oBAAoB,CAAC,GAAG,EAAE,wBAAwB,GAAG,GAAG,IAAI,4BAA4B,CAEvG;CACF;AAED;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,EAAE,CAAC;AAElE;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,CACvB,GAAG,EAAE;IAAE,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,EAClC,UAAU,CAAC,EAAE,6BAA6B,KACvC,2BAA2B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;AAExE;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,SAAS,6BAA6B,GAAG,8BAA8B,EAAE,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;AAEzJ;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,sBAAsB,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAElG;;;;;;GAMG;AACH,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,CAAC;AAEvF;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,2EAA2E;IAC3E,UAAU,EAAE,6BAA6B,GAAG,SAAS,CAAC;IAEtD,uCAAuC;IACvC,cAAc,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC;IAEvB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAElC;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,iBAAiB,CAAC;IAEpC,+EAA+E;IAC/E,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;CAC3F"}
1
+ {"version":3,"file":"IModelHierarchyDefinition.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyDefinition.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACxG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,8BAA8B,EAC9B,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAElC;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,oDAAoD;IACpD,IAAI,EAAE,0BAA0B,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,8BAA8B,GAAG,4BAA4B,CAAC;AACrG,cAAc;AAEd,yBAAiB,wBAAwB,CAAC;IACxC,SAAgB,aAAa,CAAC,GAAG,EAAE,wBAAwB,GAAG,GAAG,IAAI,8BAA8B,CAElG;IACD,SAAgB,oBAAoB,CAAC,GAAG,EAAE,wBAAwB,GAAG,GAAG,IAAI,4BAA4B,CAEvG;CACF;AAED;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,EAAE,CAAC;AAElE;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE;IAC/B,sFAAsF;IACtF,GAAG,EAAE;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAEnC,wDAAwD;IACxD,UAAU,CAAC,EAAE,6BAA6B,CAAC;IAE3C,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;CACnB,KAAK,2BAA2B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,SAAS,6BAA6B,GAAG,8BAA8B,EAAE,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;AAEzJ;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,sBAAsB,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAElG;;;;;;GAMG;AACH,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,CAAC;AAEvF;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,4EAA4E;IAC5E,YAAY,EAAE,gBAAgB,GAAG,yBAAyB,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAEnF,2EAA2E;IAC3E,UAAU,EAAE,6BAA6B,GAAG,SAAS,CAAC;IAEtD,uCAAuC;IACvC,cAAc,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC;IAEvB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAElC;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,iBAAiB,CAAC;IAEpC,+EAA+E;IAC/E,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;CAC3F"}
@@ -1 +1 @@
1
- {"version":3,"file":"IModelHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyDefinition.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AA6ChG,cAAc;AACd,2DAA2D;AAC3D,MAAM,KAAW,wBAAwB,CAOxC;AAPD,WAAiB,wBAAwB;IACvC,SAAgB,aAAa,CAAC,GAA6B;QACzD,OAAO,CAAC,CAAE,GAAsC,CAAC,IAAI,CAAC;IACxD,CAAC;IAFe,sCAAa,gBAE5B,CAAA;IACD,SAAgB,oBAAoB,CAAC,GAA6B;QAChE,OAAO,CAAC,CAAE,GAAoC,CAAC,KAAK,CAAC;IACvD,CAAC;IAFe,6CAAoB,uBAEnC,CAAA;AACH,CAAC,EAPgB,wBAAwB,KAAxB,wBAAwB,QAOxC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { GenericInstanceFilter } from \"@itwin/core-common\";\nimport { ECSqlQueryDef } from \"@itwin/presentation-shared\";\nimport { NonGroupingHierarchyNode } from \"../HierarchyNode.js\";\nimport {\n ProcessedGenericHierarchyNode,\n ProcessedHierarchyNode,\n ProcessedInstanceHierarchyNode,\n SourceGenericHierarchyNode,\n SourceInstanceHierarchyNode,\n} from \"./IModelHierarchyNode.js\";\n\n/**\n * A nodes definition that returns a single generic node.\n * @public\n */\nexport interface GenericHierarchyNodeDefinition {\n /** The node to be created in the hierarchy level */\n node: SourceGenericHierarchyNode;\n}\n\n/**\n * A nodes definition that returns an ECSQL query for selecting nodes from an iModel.\n * @public\n */\nexport interface InstanceNodesQueryDefinition {\n /**\n * Full name of the class whose instances are going to be returned. It's okay if the attribute\n * points to a base class of multiple different classes of instances returned by the query, however\n * the more specific this class is, the more efficient hierarchy building process is.\n */\n fullClassName: string;\n /**\n * An ECSQL query that selects nodes from an iModel. `SELECT` clause of the query is expected\n * to be built using `NodeSelectQueryFactory.createSelectClause`.\n */\n query: ECSqlQueryDef;\n}\n\n/**\n * A definition of nodes included in a hierarchy level.\n * @public\n */\nexport type HierarchyNodesDefinition = GenericHierarchyNodeDefinition | InstanceNodesQueryDefinition;\n/** @public */\n// eslint-disable-next-line @typescript-eslint/no-redeclare\nexport namespace HierarchyNodesDefinition {\n export function isGenericNode(def: HierarchyNodesDefinition): def is GenericHierarchyNodeDefinition {\n return !!(def as GenericHierarchyNodeDefinition).node;\n }\n export function isInstanceNodesQuery(def: HierarchyNodesDefinition): def is InstanceNodesQueryDefinition {\n return !!(def as InstanceNodesQueryDefinition).query;\n }\n}\n\n/**\n * A definition of a hierarchy level, which may consist of multiple node definitions.\n * @public\n */\nexport type HierarchyLevelDefinition = HierarchyNodesDefinition[];\n\n/**\n * A type for a function that parses a `SourceInstanceHierarchyNode` from provided ECSQL `row` object.\n * @public\n */\nexport type NodeParser = (\n row: { [columnName: string]: any },\n parentNode?: HierarchyDefinitionParentNode,\n) => SourceInstanceHierarchyNode | Promise<SourceInstanceHierarchyNode>;\n\n/**\n * A type for a function that pre-processes given node. Unless the function decides not to make any modifications,\n * it should return a new - modified - node, rather than modifying the given one. Returning `undefined` omits the node\n * from the hierarchy.\n *\n * @public\n */\nexport type NodePreProcessor = <TNode extends ProcessedGenericHierarchyNode | ProcessedInstanceHierarchyNode>(node: TNode) => Promise<TNode | undefined>;\n\n/**\n * A type for a function that post-processes given node. Unless the function decides not to make any modifications,\n * it should return a new - modified - node, rather than modifying the given one.\n *\n * @public\n */\nexport type NodePostProcessor = (node: ProcessedHierarchyNode) => Promise<ProcessedHierarchyNode>;\n\n/**\n * A type of node that can be passed to `HierarchyDefinition.defineHierarchyLevel`. This basically means\n * a `HierarchyNode` that:\n * - knows nothing about its children,\n * - is either an instances node (key is of `InstancesNodeKey` type) or a generic node (key is of `GenericNodeKey` type).\n * @public\n */\nexport type HierarchyDefinitionParentNode = Omit<NonGroupingHierarchyNode, \"children\">;\n\n/**\n * Props for `HierarchyDefinition.defineHierarchyLevel`.\n * @public\n */\nexport interface DefineHierarchyLevelProps {\n /** Parent node to get children for. Pass `undefined` to get root nodes. */\n parentNode: HierarchyDefinitionParentNode | undefined;\n\n /** Optional hierarchy level filter. */\n instanceFilter?: GenericInstanceFilter;\n}\n\n/**\n * An interface for a factory that knows how define a hierarchy based on a given parent node.\n * @public\n */\nexport interface HierarchyDefinition {\n /**\n * An optional function for parsing ECInstance node from ECSQL row.\n *\n * Should be used in situations when the `HierarchyDefinition` implementation\n * introduces additional ECSQL columns into the select clause and wants to assign additional\n * data to the nodes it produces.\n *\n * Defaults to a function that parses all `HierarchyNode` attributes from a query, whose SELECT\n * clause is created using `NodeSelectQueryFactory.createSelectClause`.\n */\n parseNode?: NodeParser;\n\n /**\n * An optional function for pre-processing nodes.\n *\n * Pre-processing happens immediately after the nodes are loaded based on `HierarchyLevelDefinition`\n * returned by this `HierarchyDefinition` and before their processing (hiding, grouping, sorting, etc.) starts.\n * The step allows assigning nodes additional data or excluding them from the hierarchy based on some attributes.\n */\n preProcessNode?: NodePreProcessor;\n\n /**\n * An optional function for post-processing nodes.\n *\n * Post-processing happens after the loaded nodes go through all the merging, hiding and grouping\n * steps, but before sorting them. This step allows `HierarchyDefinition` implementations to assign additional data\n * to nodes after they're processed. This is especially true for grouping nodes as they're only created during\n * processing.\n */\n postProcessNode?: NodePostProcessor;\n\n /** A function to create a hierarchy level definition for given parent node. */\n defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition>;\n}\n"]}
1
+ {"version":3,"file":"IModelHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyDefinition.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AA6ChG,cAAc;AACd,2DAA2D;AAC3D,MAAM,KAAW,wBAAwB,CAOxC;AAPD,WAAiB,wBAAwB;IACvC,SAAgB,aAAa,CAAC,GAA6B;QACzD,OAAO,CAAC,CAAE,GAAsC,CAAC,IAAI,CAAC;IACxD,CAAC;IAFe,sCAAa,gBAE5B,CAAA;IACD,SAAgB,oBAAoB,CAAC,GAA6B;QAChE,OAAO,CAAC,CAAE,GAAoC,CAAC,KAAK,CAAC;IACvD,CAAC;IAFe,6CAAoB,uBAEnC,CAAA;AACH,CAAC,EAPgB,wBAAwB,KAAxB,wBAAwB,QAOxC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { GenericInstanceFilter } from \"@itwin/core-common\";\nimport { ECClassHierarchyInspector, ECSchemaProvider, ECSqlQueryDef } from \"@itwin/presentation-shared\";\nimport { NonGroupingHierarchyNode } from \"../HierarchyNode.js\";\nimport {\n ProcessedGenericHierarchyNode,\n ProcessedHierarchyNode,\n ProcessedInstanceHierarchyNode,\n SourceGenericHierarchyNode,\n SourceInstanceHierarchyNode,\n} from \"./IModelHierarchyNode.js\";\n\n/**\n * A nodes definition that returns a single generic node.\n * @public\n */\nexport interface GenericHierarchyNodeDefinition {\n /** The node to be created in the hierarchy level */\n node: SourceGenericHierarchyNode;\n}\n\n/**\n * A nodes definition that returns an ECSQL query for selecting nodes from an iModel.\n * @public\n */\nexport interface InstanceNodesQueryDefinition {\n /**\n * Full name of the class whose instances are going to be returned. It's okay if the attribute\n * points to a base class of multiple different classes of instances returned by the query, however\n * the more specific this class is, the more efficient hierarchy building process is.\n */\n fullClassName: string;\n /**\n * An ECSQL query that selects nodes from an iModel. `SELECT` clause of the query is expected\n * to be built using `NodeSelectQueryFactory.createSelectClause`.\n */\n query: ECSqlQueryDef;\n}\n\n/**\n * A definition of nodes included in a hierarchy level.\n * @public\n */\nexport type HierarchyNodesDefinition = GenericHierarchyNodeDefinition | InstanceNodesQueryDefinition;\n/** @public */\n// eslint-disable-next-line @typescript-eslint/no-redeclare\nexport namespace HierarchyNodesDefinition {\n export function isGenericNode(def: HierarchyNodesDefinition): def is GenericHierarchyNodeDefinition {\n return !!(def as GenericHierarchyNodeDefinition).node;\n }\n export function isInstanceNodesQuery(def: HierarchyNodesDefinition): def is InstanceNodesQueryDefinition {\n return !!(def as InstanceNodesQueryDefinition).query;\n }\n}\n\n/**\n * A definition of a hierarchy level, which may consist of multiple node definitions.\n * @public\n */\nexport type HierarchyLevelDefinition = HierarchyNodesDefinition[];\n\n/**\n * A type for a function that parses a `SourceInstanceHierarchyNode` from provided ECSQL `row` object.\n * @public\n */\nexport type NodeParser = (props: {\n /** The ECSQL row object to parse. Keys & value types depend on the executed query. */\n row: { [columnName: string]: any };\n\n /** The parent node whose child node is being parsed. */\n parentNode?: HierarchyDefinitionParentNode;\n\n /** The key of iModel which is used to run the query. */\n imodelKey: string;\n}) => SourceInstanceHierarchyNode | Promise<SourceInstanceHierarchyNode>;\n\n/**\n * A type for a function that pre-processes given node. Unless the function decides not to make any modifications,\n * it should return a new - modified - node, rather than modifying the given one. Returning `undefined` omits the node\n * from the hierarchy.\n *\n * @public\n */\nexport type NodePreProcessor = <TNode extends ProcessedGenericHierarchyNode | ProcessedInstanceHierarchyNode>(node: TNode) => Promise<TNode | undefined>;\n\n/**\n * A type for a function that post-processes given node. Unless the function decides not to make any modifications,\n * it should return a new - modified - node, rather than modifying the given one.\n *\n * @public\n */\nexport type NodePostProcessor = (node: ProcessedHierarchyNode) => Promise<ProcessedHierarchyNode>;\n\n/**\n * A type of node that can be passed to `HierarchyDefinition.defineHierarchyLevel`. This basically means\n * a `HierarchyNode` that:\n * - knows nothing about its children,\n * - is either an instances node (key is of `InstancesNodeKey` type) or a generic node (key is of `GenericNodeKey` type).\n * @public\n */\nexport type HierarchyDefinitionParentNode = Omit<NonGroupingHierarchyNode, \"children\">;\n\n/**\n * Props for `HierarchyDefinition.defineHierarchyLevel`.\n * @public\n */\nexport interface DefineHierarchyLevelProps {\n /** The iModel for which the hierarchy definition is being requested for. */\n imodelAccess: ECSchemaProvider & ECClassHierarchyInspector & { imodelKey: string };\n\n /** Parent node to get children for. Pass `undefined` to get root nodes. */\n parentNode: HierarchyDefinitionParentNode | undefined;\n\n /** Optional hierarchy level filter. */\n instanceFilter?: GenericInstanceFilter;\n}\n\n/**\n * An interface for a factory that knows how define a hierarchy based on a given parent node.\n * @public\n */\nexport interface HierarchyDefinition {\n /**\n * An optional function for parsing ECInstance node from ECSQL row.\n *\n * Should be used in situations when the `HierarchyDefinition` implementation\n * introduces additional ECSQL columns into the select clause and wants to assign additional\n * data to the nodes it produces.\n *\n * Defaults to a function that parses all `HierarchyNode` attributes from a query, whose SELECT\n * clause is created using `NodeSelectQueryFactory.createSelectClause`.\n */\n parseNode?: NodeParser;\n\n /**\n * An optional function for pre-processing nodes.\n *\n * Pre-processing happens immediately after the nodes are loaded based on `HierarchyLevelDefinition`\n * returned by this `HierarchyDefinition` and before their processing (hiding, grouping, sorting, etc.) starts.\n * The step allows assigning nodes additional data or excluding them from the hierarchy based on some attributes.\n */\n preProcessNode?: NodePreProcessor;\n\n /**\n * An optional function for post-processing nodes.\n *\n * Post-processing happens after the loaded nodes go through all the merging, hiding and grouping\n * steps, but before sorting them. This step allows `HierarchyDefinition` implementations to assign additional data\n * to nodes after they're processed. This is especially true for grouping nodes as they're only created during\n * processing.\n */\n postProcessNode?: NodePostProcessor;\n\n /** A function to create a hierarchy level definition for given parent node. */\n defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition>;\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import "../internal/DisposePolyfill.js";
2
2
  import { ECClassHierarchyInspector, ECSchemaProvider, Event, IPrimitiveValueFormatter } from "@itwin/presentation-shared";
3
- import { HierarchyFilteringPath } from "../HierarchyFiltering.js";
4
3
  import { HierarchyProvider } from "../HierarchyProvider.js";
4
+ import { HierarchySearchPath } from "../HierarchySearch.js";
5
5
  import { HierarchyDefinition } from "./IModelHierarchyDefinition.js";
6
6
  import { LimitingECSqlQueryExecutor } from "./LimitingECSqlQueryExecutor.js";
7
7
  /**
@@ -37,7 +37,10 @@ interface IModelHierarchyProviderProps {
37
37
  * @see `ECClassHierarchyInspector`
38
38
  */
39
39
  imodelAccess: IModelAccess;
40
- /** An event that is raised when iModel data, that may affect the hierarchy, changes. */
40
+ /**
41
+ * An event that is raised when iModel data, that may affect the hierarchy, changes. The created provider
42
+ * subscribes to the event to know that it needs to reload the data, and unsubscribes on disposal.
43
+ */
41
44
  imodelChanged?: Event<() => void>;
42
45
  /**
43
46
  * A function that returns a hierarchy definition, describing how the hierarchy that the provider should be create. The
@@ -59,22 +62,54 @@ interface IModelHierarchyProviderProps {
59
62
  * by calling `setFormatter` on the provider instance.
60
63
  */
61
64
  formatter?: IPrimitiveValueFormatter;
62
- /** Props for filtering the hierarchy. */
63
- filtering?: {
65
+ /** Props for search the hierarchy. */
66
+ search?: {
64
67
  /** A list of node identifiers from root to target node. */
65
- paths: HierarchyFilteringPath[];
68
+ paths: HierarchySearchPath[];
66
69
  };
67
70
  }
68
71
  /**
69
- * Creates an instance of `HierarchyProvider` that creates a hierarchy based on given iModel and
72
+ * Creates an instance of `HierarchyProvider` that creates a hierarchy based on given the iModel and
70
73
  * a hierarchy definition, which defines each hierarchy level through ECSQL queries.
71
74
  *
72
75
  * @public
73
76
  */
74
- export declare function createIModelHierarchyProvider(props: IModelHierarchyProviderProps): HierarchyProvider & {
75
- /** @deprecated in 1.4. Use `[Symbol.dispose]` instead. */
76
- dispose: () => void;
77
- [Symbol.dispose]: () => void;
78
- };
77
+ export declare function createIModelHierarchyProvider(props: IModelHierarchyProviderProps): HierarchyProvider & Disposable;
78
+ /**
79
+ * Props for `createMergedIModelHierarchyProvider`.
80
+ * @alpha
81
+ */
82
+ interface MergedIModelHierarchyProviderProps extends Omit<IModelHierarchyProviderProps, "imodelAccess" | "imodelChanged"> {
83
+ /**
84
+ * A list of iModels to create merged hierarchy for.
85
+ *
86
+ * **Warning:** These **must** all be different versions of the same iModel, ordered from the earliest to the
87
+ * latest version. Not obeying this rule may result in undefined behavior.
88
+ */
89
+ imodels: Array<{
90
+ /**
91
+ * An object that provides access to iModel's data and metadata.
92
+ *
93
+ * @see `ECSchemaProvider`
94
+ * @see `LimitingECSqlQueryExecutor`
95
+ * @see `ECClassHierarchyInspector`
96
+ */
97
+ imodelAccess: IModelAccess;
98
+ /**
99
+ * An event that is raised when iModel data, that may affect the hierarchy, changes. The created provider
100
+ * subscribes to the event to know that it needs to reload the data, and unsubscribes on disposal.
101
+ */
102
+ imodelChanged?: Event<() => void>;
103
+ }>;
104
+ }
105
+ /**
106
+ * Creates an instance of `HierarchyProvider` that creates a hierarchy based on multiple version of **the same** iModel
107
+ * and a hierarchy definition, which defines each hierarchy level through ECSQL queries.
108
+ *
109
+ * **Warning:** This is an experimental API that **should not be used in production**.
110
+ *
111
+ * @alpha
112
+ */
113
+ export declare function createMergedIModelHierarchyProvider(props: MergedIModelHierarchyProviderProps): HierarchyProvider & Disposable;
79
114
  export {};
80
115
  //# sourceMappingURL=IModelHierarchyProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IModelHierarchyProvider.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyProvider.ts"],"names":[],"mappings":"AAKA,OAAO,gCAAgC,CAAC;AAuBxC,OAAO,EAGL,yBAAyB,EACzB,gBAAgB,EAGhB,KAAK,EAIL,wBAAwB,EAEzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAA0B,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAkBpF,OAAO,EAA6B,mBAAmB,EAA4B,MAAM,gCAAgC,CAAC;AAE1H,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAe7E;;;GAGG;AACH,UAAU,uCAAuC;IAC/C;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,cAAc;AACd,KAAK,YAAY,GAAG,gBAAgB,GAAG,0BAA0B,GAAG,yBAAyB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtH;;;GAGG;AACH,UAAU,4BAA4B;IACpC;;;;;;OAMG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B,wFAAwF;IACxF,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IAEzC,qGAAqG;IACrG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC,uCAAuC,CAAC,CAAC;IAEpE;;;;OAIG;IACH,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,yCAAyC;IACzC,SAAS,CAAC,EAAE;QACV,2DAA2D;QAC3D,KAAK,EAAE,sBAAsB,EAAE,CAAC;KACjC,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,GAAG;IACtG,0DAA0D;IAC1D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAEA"}
1
+ {"version":3,"file":"IModelHierarchyProvider.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyProvider.ts"],"names":[],"mappings":"AAKA,OAAO,gCAAgC,CAAC;AA4BxC,OAAO,EAGL,yBAAyB,EACzB,gBAAgB,EAGhB,KAAK,EAIL,wBAAwB,EAEzB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EAA0B,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAiB5D,OAAO,EAGL,mBAAmB,EAGpB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAgB7E;;;GAGG;AACH,UAAU,uCAAuC;IAC/C;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,cAAc;AACd,KAAK,YAAY,GAAG,gBAAgB,GAAG,0BAA0B,GAAG,yBAAyB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtH;;;GAGG;AACH,UAAU,4BAA4B;IACpC;;;;;;OAMG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IAEzC,qGAAqG;IACrG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC,uCAAuC,CAAC,CAAC;IAEpE;;;;OAIG;IACH,SAAS,CAAC,EAAE,wBAAwB,CAAC;IAErC,sCAAsC;IACtC,MAAM,CAAC,EAAE;QACP,2DAA2D;QAC3D,KAAK,EAAE,mBAAmB,EAAE,CAAC;KAC9B,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,GAAG,UAAU,CAGjH;AAED;;;GAGG;AACH,UAAU,kCAAmC,SAAQ,IAAI,CAAC,4BAA4B,EAAE,cAAc,GAAG,eAAe,CAAC;IACvH;;;;;OAKG;IACH,OAAO,EAAE,KAAK,CAAC;QACb;;;;;;WAMG;QACH,YAAY,EAAE,YAAY,CAAC;QAE3B;;;WAGG;QACH,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;KACnC,CAAC,CAAC;CACJ;AAED;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,kCAAkC,GAAG,iBAAiB,GAAG,UAAU,CAE7H"}
@@ -3,12 +3,13 @@
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import "../internal/DisposePolyfill.js";
6
- import { catchError, concat, defaultIfEmpty, EMPTY, filter, finalize, from, identity, map, merge, mergeAll, mergeMap, of, Subject, take, takeUntil, tap, } from "rxjs";
6
+ import { catchError, concat, defaultIfEmpty, defer, EMPTY, filter, finalize, from, fromEventPattern, identity, map, merge, mergeAll, mergeMap, of, reduce, Subject, take, takeUntil, tap, } from "rxjs";
7
7
  import { assert, BeEvent, Guid, StopWatch } from "@itwin/core-bentley";
8
- import { createDefaultValueFormatter, formatConcatenatedValue, normalizeFullClassName, } from "@itwin/presentation-shared";
8
+ import { createDefaultValueFormatter, formatConcatenatedValue, InstanceKey, normalizeFullClassName, } from "@itwin/presentation-shared";
9
9
  import { RowsLimitExceededError } from "../HierarchyErrors.js";
10
10
  import { HierarchyNode } from "../HierarchyNode.js";
11
11
  import { HierarchyNodeKey } from "../HierarchyNodeKey.js";
12
+ import { HierarchySearchPath } from "../HierarchySearch.js";
12
13
  import { LOGGING_NAMESPACE as BASE_LOGGING_NAMESPACE, LOGGING_NAMESPACE_INTERNAL as BASE_LOGGING_NAMESPACE_INTERNAL, LOGGING_NAMESPACE_PERFORMANCE as BASE_LOGGING_NAMESPACE_PERFORMANCE, createNodeIdentifierForLogging, hasChildren, } from "../internal/Common.js";
13
14
  import { eachValueFrom } from "../internal/EachValueFrom.js";
14
15
  import { doLog, log } from "../internal/LoggingUtils.js";
@@ -18,14 +19,14 @@ import { shareReplayWithErrors } from "../internal/operators/ShareReplayWithErro
18
19
  import { sortNodesByLabelOperator } from "../internal/operators/Sorting.js";
19
20
  import { getRxjsHierarchyDefinition } from "../internal/RxjsHierarchyDefinition.js";
20
21
  import { SubscriptionScheduler } from "../internal/SubscriptionScheduler.js";
21
- import { FilteringHierarchyDefinition } from "./FilteringHierarchyDefinition.js";
22
22
  import { HierarchyCache } from "./HierarchyCache.js";
23
- import { HierarchyNodesDefinition } from "./IModelHierarchyDefinition.js";
23
+ import { HierarchyNodesDefinition, } from "./IModelHierarchyDefinition.js";
24
24
  import { NodeSelectClauseColumnNames } from "./NodeSelectQueryFactory.js";
25
25
  import { createDetermineChildrenOperator } from "./operators/DetermineChildren.js";
26
26
  import { createGroupingOperator } from "./operators/Grouping.js";
27
27
  import { createHideIfNoChildrenOperator } from "./operators/HideIfNoChildren.js";
28
28
  import { createHideNodesInHierarchyOperator } from "./operators/HideNodesInHierarchy.js";
29
+ import { SearchHierarchyDefinition } from "./SearchHierarchyDefinition.js";
29
30
  import { readNodes } from "./TreeNodesReader.js";
30
31
  const LOGGING_NAMESPACE = `${BASE_LOGGING_NAMESPACE}.IModelHierarchyProvider`;
31
32
  const LOGGING_NAMESPACE_INTERNAL = `${BASE_LOGGING_NAMESPACE_INTERNAL}.IModelHierarchyProvider`;
@@ -33,33 +34,57 @@ const LOGGING_NAMESPACE_PERFORMANCE = `${BASE_LOGGING_NAMESPACE_PERFORMANCE}.IMo
33
34
  const DEFAULT_QUERY_CONCURRENCY = 10;
34
35
  const DEFAULT_QUERY_CACHE_SIZE = 1;
35
36
  /**
36
- * Creates an instance of `HierarchyProvider` that creates a hierarchy based on given iModel and
37
+ * Creates an instance of `HierarchyProvider` that creates a hierarchy based on given the iModel and
37
38
  * a hierarchy definition, which defines each hierarchy level through ECSQL queries.
38
39
  *
39
40
  * @public
40
41
  */
41
42
  export function createIModelHierarchyProvider(props) {
43
+ const { imodelAccess, imodelChanged, ...restProps } = props;
44
+ return createMergedIModelHierarchyProvider({ ...restProps, imodels: [{ imodelAccess, imodelChanged }] });
45
+ }
46
+ /**
47
+ * Creates an instance of `HierarchyProvider` that creates a hierarchy based on multiple version of **the same** iModel
48
+ * and a hierarchy definition, which defines each hierarchy level through ECSQL queries.
49
+ *
50
+ * **Warning:** This is an experimental API that **should not be used in production**.
51
+ *
52
+ * @alpha
53
+ */
54
+ export function createMergedIModelHierarchyProvider(props) {
42
55
  return new IModelHierarchyProviderImpl(props);
43
56
  }
44
57
  class IModelHierarchyProviderImpl {
45
- _imodelAccess;
58
+ _imodels;
46
59
  _hierarchyChanged;
47
60
  _valuesFormatter;
48
61
  _sourceHierarchyDefinition;
49
62
  _activeHierarchyDefinition;
50
63
  _localizedStrings;
51
- _queryScheduler;
64
+ _queryConcurrency;
65
+ _querySchedulers;
52
66
  _nodesCache;
53
67
  _unsubscribe;
54
68
  _dispose = new Subject();
69
+ #componentId;
70
+ #componentName;
71
+ #sourceName;
55
72
  constructor(props) {
56
- this._imodelAccess = props.imodelAccess;
73
+ if (props.imodels.length === 0) {
74
+ throw new Error(`Creating an iModel hierarchy provider requires at least one iModel.`);
75
+ }
76
+ this.#componentId = Guid.createValue();
77
+ this.#componentName = "IModelHierarchyProviderImpl";
78
+ /* c8 ignore next */
79
+ this.#sourceName = props.sourceName ?? `${this.#componentName}:${this.#componentId}`;
80
+ this._imodels = props.imodels;
57
81
  this._hierarchyChanged = new BeEvent();
58
82
  this._activeHierarchyDefinition = this._sourceHierarchyDefinition = getRxjsHierarchyDefinition(props.hierarchyDefinition);
59
83
  this._valuesFormatter = props?.formatter ?? createDefaultValueFormatter();
60
84
  this._localizedStrings = { other: "Other", unspecified: "Not specified", ...props?.localizedStrings };
61
- this._queryScheduler = new SubscriptionScheduler(props.queryConcurrency ?? DEFAULT_QUERY_CONCURRENCY);
62
- this.setHierarchyFilter(props.filtering);
85
+ this._queryConcurrency = props.queryConcurrency ?? DEFAULT_QUERY_CONCURRENCY;
86
+ this._querySchedulers = new Map();
87
+ this.setHierarchySearch(props.search);
63
88
  const queryCacheSize = props.queryCacheSize ?? DEFAULT_QUERY_CACHE_SIZE;
64
89
  if (queryCacheSize !== 0) {
65
90
  this._nodesCache = new HierarchyCache({
@@ -68,11 +93,18 @@ class IModelHierarchyProviderImpl {
68
93
  variationsCount: 1,
69
94
  });
70
95
  }
71
- this._unsubscribe = props.imodelChanged?.addListener(() => {
72
- this.invalidateHierarchyCache("Data source changed");
96
+ const imodelChangeSubscription = from(this._imodels)
97
+ .pipe(mergeMap(({ imodelAccess, imodelChanged }) => imodelChanged
98
+ ? fromEventPattern((handler) => imodelChanged.addListener(handler), (handler) => imodelChanged.removeListener(handler), () => imodelAccess)
99
+ : EMPTY))
100
+ .subscribe(({ imodelKey }) => {
101
+ this.invalidateHierarchyCache(`Data source changed: "${imodelKey}"`);
73
102
  this._dispose.next();
74
103
  this._hierarchyChanged.raiseEvent();
75
104
  });
105
+ this._unsubscribe = () => {
106
+ imodelChangeSubscription.unsubscribe();
107
+ };
76
108
  }
77
109
  [Symbol.dispose]() {
78
110
  this._dispose.next();
@@ -85,6 +117,17 @@ class IModelHierarchyProviderImpl {
85
117
  get hierarchyChanged() {
86
118
  return this._hierarchyChanged;
87
119
  }
120
+ getQueryScheduler(imodelKey) {
121
+ let scheduler = this._querySchedulers.get(imodelKey);
122
+ if (!scheduler) {
123
+ scheduler = new SubscriptionScheduler(this._queryConcurrency);
124
+ this._querySchedulers.set(imodelKey, scheduler);
125
+ }
126
+ return scheduler;
127
+ }
128
+ getPrimaryIModelAccess() {
129
+ return this._imodels[this._imodels.length - 1].imodelAccess;
130
+ }
88
131
  invalidateHierarchyCache(reason) {
89
132
  doLog({
90
133
  category: `${LOGGING_NAMESPACE}.Events`,
@@ -100,23 +143,24 @@ class IModelHierarchyProviderImpl {
100
143
  this._valuesFormatter = formatter ?? createDefaultValueFormatter();
101
144
  this._hierarchyChanged.raiseEvent({ formatterChange: { newFormatter: this._valuesFormatter } });
102
145
  }
103
- setHierarchyFilter(props) {
146
+ setHierarchySearch(props) {
104
147
  if (!props) {
105
148
  if (this._sourceHierarchyDefinition !== this._activeHierarchyDefinition) {
106
149
  this._activeHierarchyDefinition = this._sourceHierarchyDefinition;
107
- this.invalidateHierarchyCache("Hierarchy filter reset");
150
+ this.invalidateHierarchyCache("Hierarchy search reset");
108
151
  }
109
- this._hierarchyChanged.raiseEvent({ filterChange: { newFilter: undefined } });
152
+ this._hierarchyChanged.raiseEvent({ searchChange: { newSearch: undefined } });
110
153
  return;
111
154
  }
112
- this._activeHierarchyDefinition = new FilteringHierarchyDefinition({
113
- imodelAccess: this._imodelAccess,
155
+ this._activeHierarchyDefinition = new SearchHierarchyDefinition({
156
+ imodelAccess: this.getPrimaryIModelAccess(),
114
157
  source: this._sourceHierarchyDefinition,
115
- nodeIdentifierPaths: props.paths,
158
+ sourceName: this.#sourceName,
159
+ targetPaths: props.paths,
116
160
  });
117
- this.invalidateHierarchyCache("Hierarchy filter set");
161
+ this.invalidateHierarchyCache("Hierarchy search set");
118
162
  this._dispose.next();
119
- this._hierarchyChanged.raiseEvent({ filterChange: { newFilter: props } });
163
+ this._hierarchyChanged.raiseEvent({ searchChange: { newSearch: props } });
120
164
  }
121
165
  onGroupingNodeCreated(groupingNode, props) {
122
166
  this._nodesCache?.set({ ...props, parentNode: groupingNode }, { observable: from(groupingNode.children), processingStatus: "pre-processed" });
@@ -127,44 +171,53 @@ class IModelHierarchyProviderImpl {
127
171
  category: LOGGING_NAMESPACE_PERFORMANCE,
128
172
  message: /* c8 ignore next */ () => `[${requestContext.requestId}] Requesting hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
129
173
  });
130
- let parentNode = props.parentNode;
131
- if (parentNode && HierarchyNode.isGeneric(parentNode) && parentNode.key.source && parentNode.key.source !== this._imodelAccess.imodelKey) {
132
- return EMPTY;
133
- }
134
- if (parentNode && HierarchyNode.isInstancesNode(parentNode)) {
135
- parentNode = {
136
- ...parentNode,
137
- key: {
138
- ...parentNode.key,
139
- instanceKeys: parentNode.key.instanceKeys.filter((ik) => !ik.imodelKey || ik.imodelKey === this._imodelAccess.imodelKey),
140
- },
141
- };
142
- assert(HierarchyNodeKey.isInstances(parentNode.key));
143
- if (parentNode.key.instanceKeys.length === 0) {
174
+ return from(this._imodels).pipe(mergeMap(({ imodelAccess }, imodelAccessIndex) => {
175
+ let parentNode = props.parentNode;
176
+ if (parentNode && HierarchyNode.isGeneric(parentNode) && parentNode.key.source && parentNode.key.source !== this.#sourceName) {
144
177
  return EMPTY;
145
178
  }
146
- }
147
- return this._activeHierarchyDefinition.defineHierarchyLevel({ ...defineHierarchyLevelProps, parentNode }).pipe(mergeAll(), finalize(() => doLog({
179
+ if (parentNode && HierarchyNode.isInstancesNode(parentNode)) {
180
+ parentNode = {
181
+ ...parentNode,
182
+ key: {
183
+ ...parentNode.key,
184
+ instanceKeys: parentNode.key.instanceKeys.filter((ik) => !ik.imodelKey || ik.imodelKey === imodelAccess.imodelKey),
185
+ },
186
+ };
187
+ assert(HierarchyNodeKey.isInstances(parentNode.key));
188
+ if (parentNode.key.instanceKeys.length === 0) {
189
+ return EMPTY;
190
+ }
191
+ }
192
+ return this._activeHierarchyDefinition.defineHierarchyLevel({ ...defineHierarchyLevelProps, parentNode, imodelAccess }).pipe(mergeAll(), map(
193
+ /* Using `as` to work around TS not understanding that `{ x: A, y: B | C }` is the same as `{ x: A } & ({ y: B } | { y: C })` */
194
+ (hierarchyNodesDefinition) => ({ imodelAccess, imodelAccessIndex, hierarchyNodesDefinition })));
195
+ }), finalize(() => doLog({
148
196
  category: LOGGING_NAMESPACE_PERFORMANCE,
149
197
  message: /* c8 ignore next */ () => `[${requestContext.requestId}] Received all hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
150
198
  })));
151
199
  }
152
200
  createSourceNodesObservable(props) {
153
201
  // pipe definitions to nodes and put "share replay" on it
154
- return this.createHierarchyLevelDefinitionsObservable(props).pipe(mergeMap((def) => {
202
+ return this.createHierarchyLevelDefinitionsObservable(props).pipe(mergeMap(({ imodelAccess, imodelAccessIndex, hierarchyNodesDefinition: def }) => defer(() => {
155
203
  if (HierarchyNodesDefinition.isGenericNode(def)) {
156
- return of({ ...def.node, key: { type: "generic", id: def.node.key, source: this._imodelAccess.imodelKey } });
204
+ return of({
205
+ ...def.node,
206
+ key: { type: "generic", id: def.node.key, source: this.#sourceName },
207
+ });
157
208
  }
158
- return this._queryScheduler.scheduleSubscription(of(def.query).pipe(map((query) => filterQueryByInstanceKeys(query, props.filteredInstanceKeys)), mergeMap((query) => readNodes({
159
- queryExecutor: this._imodelAccess,
209
+ return this.getQueryScheduler(imodelAccess.imodelKey).scheduleSubscription(of(def.query).pipe(map((query) => createInstanceKeysFilteredQuery(query, props.targetInstanceKeys)), mergeMap((query) => readNodes({
210
+ queryExecutor: imodelAccess,
160
211
  query,
161
212
  limit: props.hierarchyLevelSizeLimit,
162
- parser: this._activeHierarchyDefinition.parseNode ? (row) => this._activeHierarchyDefinition.parseNode(row, props.parentNode) : undefined,
213
+ parser: this._activeHierarchyDefinition.parseNode
214
+ ? ({ row }) => this._activeHierarchyDefinition.parseNode({ row, parentNode: props.parentNode, imodelKey: imodelAccess.imodelKey })
215
+ : undefined,
163
216
  })), map((node) => ({
164
217
  ...node,
165
- key: { ...node.key, instanceKeys: node.key.instanceKeys.map((key) => ({ ...key, imodelKey: this._imodelAccess.imodelKey })) },
218
+ key: { ...node.key, instanceKeys: node.key.instanceKeys.map((key) => ({ ...key, imodelKey: imodelAccess.imodelKey })) },
166
219
  }))));
167
- }), finalize(() => doLog({
220
+ }).pipe(map((node) => ({ imodelAccess, imodelAccessIndex, node })))), mergeNodes, map(({ node }) => node), finalize(() => doLog({
168
221
  category: LOGGING_NAMESPACE_PERFORMANCE,
169
222
  message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Read all child nodes ${createNodeIdentifierForLogging(props.parentNode)}`,
170
223
  })), shareReplayWithErrors());
@@ -178,6 +231,7 @@ class IModelHierarchyProviderImpl {
178
231
  // format `ConcatenatedValue` labels into string labels
179
232
  mergeMap((node) => applyLabelsFormatting(node, this._valuesFormatter)),
180
233
  // we have `ProcessedHierarchyNode` from here
234
+ // let consumers step-in
181
235
  preProcessNodes(this._activeHierarchyDefinition),
182
236
  // process hiding
183
237
  createHideIfNoChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n, requestContext: props.requestContext }).hasNodes), createHideNodesInHierarchyOperator(
@@ -188,7 +242,7 @@ class IModelHierarchyProviderImpl {
188
242
  })));
189
243
  }
190
244
  createProcessedNodesObservable(preprocessedNodesObservable, props) {
191
- return preprocessedNodesObservable.pipe(createGroupingOperator(this._imodelAccess, props.parentNode, this._valuesFormatter, this._localizedStrings, undefined, (gn) => this.onGroupingNodeCreated(gn, props)), finalize(() => doLog({
245
+ return preprocessedNodesObservable.pipe(createGroupingOperator(this.getPrimaryIModelAccess(), props.parentNode, this._valuesFormatter, this._localizedStrings, undefined, (gn) => this.onGroupingNodeCreated(gn, props)), finalize(() => doLog({
192
246
  category: LOGGING_NAMESPACE_PERFORMANCE,
193
247
  message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Finished grouping child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
194
248
  })));
@@ -198,9 +252,7 @@ class IModelHierarchyProviderImpl {
198
252
  if ("processingParams" in n) {
199
253
  delete n.processingParams;
200
254
  }
201
- return Object.assign(n, {
202
- children: hasChildren(n),
203
- });
255
+ return { ...n, children: hasChildren(n) };
204
256
  }), takeUntil(this._dispose), finalize(() => doLog({
205
257
  category: LOGGING_NAMESPACE_PERFORMANCE,
206
258
  message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Finished finalizing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
@@ -234,13 +286,13 @@ class IModelHierarchyProviderImpl {
234
286
  return cached;
235
287
  }
236
288
  // if we don't find an entry for a grouping node, we load its instances by getting a query and applying
237
- // a filter based on grouped instance keys
238
- let filteredInstanceKeys;
289
+ // a search based on grouped instance keys
290
+ let targetInstanceKeys;
239
291
  let parentNonGroupingNode;
240
292
  if (parentNode) {
241
293
  if (HierarchyNode.isGroupingNode(parentNode)) {
242
294
  parentNonGroupingNode = parentNode.nonGroupingAncestor;
243
- filteredInstanceKeys = parentNode.groupedInstanceKeys;
295
+ targetInstanceKeys = parentNode.groupedInstanceKeys;
244
296
  }
245
297
  else {
246
298
  // not sure why type checker doesn't pick this up
@@ -251,7 +303,7 @@ class IModelHierarchyProviderImpl {
251
303
  const nonGroupingNodeChildrenRequestProps = {
252
304
  ...restProps,
253
305
  parentNode: parentNonGroupingNode,
254
- ...(filteredInstanceKeys ? { filteredInstanceKeys } : undefined),
306
+ ...(targetInstanceKeys ? { targetInstanceKeys } : undefined),
255
307
  };
256
308
  const value = { observable: this.createSourceNodesObservable(nonGroupingNodeChildrenRequestProps), processingStatus: "none" };
257
309
  this._nodesCache?.set(nonGroupingNodeChildrenRequestProps, value);
@@ -315,11 +367,11 @@ class IModelHierarchyProviderImpl {
315
367
  return from(parentNode.groupedInstanceKeys);
316
368
  }
317
369
  assert(!parentNode || HierarchyNode.isGeneric(parentNode) || HierarchyNode.isInstancesNode(parentNode));
318
- const hierarchyLevelDefinitions = this.createHierarchyLevelDefinitionsObservable({ parentNode, instanceFilter, requestContext });
319
370
  // split the definitions based on whether they're for generic nodes or for instance nodes
320
- const [genericDefs, instanceDefs] = partition(hierarchyLevelDefinitions, HierarchyNodesDefinition.isGenericNode);
371
+ const hierarchyLevelDefinitions = this.createHierarchyLevelDefinitionsObservable({ parentNode, instanceFilter, requestContext });
372
+ const [instanceDefs, genericDefs] = partition(hierarchyLevelDefinitions, (x) => HierarchyNodesDefinition.isInstanceNodesQuery(x.hierarchyNodesDefinition));
321
373
  // query instance keys and a flag whether they should be hidden
322
- const instanceKeys = instanceDefs.pipe(mergeMap((def) => this._queryScheduler.scheduleSubscription(of(def.query).pipe(mergeMap(async (query) => {
374
+ const instanceKeys = instanceDefs.pipe(mergeMap(({ imodelAccess, hierarchyNodesDefinition: def }) => this.getQueryScheduler(imodelAccess.imodelKey).scheduleSubscription(of(def.query).pipe(mergeMap(async (query) => {
323
375
  const ecsql = `
324
376
  SELECT
325
377
  ${NodeSelectClauseColumnNames.FullClassName},
@@ -329,12 +381,16 @@ class IModelHierarchyProviderImpl {
329
381
  ${query.ecsql}
330
382
  )
331
383
  `;
332
- const reader = this._imodelAccess.createQueryReader({ ...query, ecsql }, { rowFormat: "Indexes", limit: hierarchyLevelSizeLimit });
384
+ const reader = imodelAccess.createQueryReader({ ...query, ecsql }, {
385
+ rowFormat: "Indexes",
386
+ limit: hierarchyLevelSizeLimit,
387
+ restartToken: `${this.#componentName}/${this.#componentId}/node-instance-keys/${Guid.createValue()}`,
388
+ });
333
389
  return from(reader).pipe(map((row) => ({
334
390
  key: {
335
391
  className: normalizeFullClassName(row[0]),
336
392
  id: row[1],
337
- imodelKey: this._imodelAccess.imodelKey,
393
+ imodelKey: imodelAccess.imodelKey,
338
394
  },
339
395
  hide: !!row[2],
340
396
  })));
@@ -344,17 +400,17 @@ class IModelHierarchyProviderImpl {
344
400
  // hidden items' handling:
345
401
  // - if a generic node is hidden, we'll want to retrieve instance keys of its children, otherwise we don't care about it,
346
402
  // - if an instance key is hidden, we want to create a merged node similar to what we do in `createHideNodesInHierarchyOperator`
347
- const hiddenParentNodes = merge(genericDefs.pipe(filter((def) => !!def.node.processingParams?.hideInHierarchy), map((def) => ({
403
+ const hiddenParentNodes = merge(genericDefs.pipe(filter(({ hierarchyNodesDefinition }) => !!hierarchyNodesDefinition.node.processingParams?.hideInHierarchy), map(({ hierarchyNodesDefinition }) => ({
348
404
  type: "generic",
349
- id: def.node.key,
350
- source: this._imodelAccess.imodelKey,
405
+ id: hierarchyNodesDefinition.node.key,
406
+ source: this.#sourceName,
351
407
  }))), hiddenNodeInstanceKeys.pipe(
352
408
  // first merge all keys by class
353
- reduceToMergeMapList(({ key }) => key.className, ({ key }) => key.id),
409
+ reduceToMergeMapList(({ key }) => key.className, ({ key }) => key),
354
410
  // then, for each class, create an instance key
355
- mergeMap((mergedMap) => [...mergedMap.entries()].map(([className, ids]) => ({
411
+ mergeMap((mergedMap) => [...mergedMap.entries()].map(([className, keys]) => ({
356
412
  type: "instances",
357
- instanceKeys: ids.map((id) => ({ className, id, imodelKey: this._imodelAccess.imodelKey })),
413
+ instanceKeys: keys.map(({ id, imodelKey }) => ({ className, id, imodelKey })),
358
414
  }))))).pipe(map((key) => ({
359
415
  key,
360
416
  parentKeys: [],
@@ -415,20 +471,20 @@ function createParentNodeKeysList(parentNode) {
415
471
  }
416
472
  return [...parentNode.parentKeys, parentNode.key];
417
473
  }
418
- function filterQueryByInstanceKeys(query, filteredInstanceKeys) {
419
- if (!filteredInstanceKeys || !filteredInstanceKeys.length) {
474
+ function createInstanceKeysFilteredQuery(query, targetInstanceKeys) {
475
+ if (!targetInstanceKeys || !targetInstanceKeys.length) {
420
476
  return query;
421
477
  }
422
478
  const MAX_ALLOWED_BINDINGS = 1000;
423
- if (filteredInstanceKeys.length < MAX_ALLOWED_BINDINGS) {
479
+ if (targetInstanceKeys.length < MAX_ALLOWED_BINDINGS) {
424
480
  return {
425
481
  ...query,
426
482
  ecsql: `
427
483
  SELECT *
428
484
  FROM (${query.ecsql}) q
429
- WHERE q.ECInstanceId IN (${filteredInstanceKeys.map(() => "?").join(",")})
485
+ WHERE q.ECInstanceId IN (${targetInstanceKeys.map(() => "?").join(",")})
430
486
  `,
431
- bindings: [...(query.bindings ?? []), ...filteredInstanceKeys.map((k) => ({ type: "id", value: k.id }))],
487
+ bindings: [...(query.bindings ?? []), ...targetInstanceKeys.map((k) => ({ type: "id", value: k.id }))],
432
488
  };
433
489
  }
434
490
  /* c8 ignore start */
@@ -439,8 +495,78 @@ function filterQueryByInstanceKeys(query, filteredInstanceKeys) {
439
495
  FROM (${query.ecsql}) q
440
496
  WHERE InVirtualSet(?, q.ECInstanceId)
441
497
  `,
442
- bindings: [...(query.bindings ?? []), { type: "idset", value: filteredInstanceKeys.map((k) => k.id) }],
498
+ bindings: [...(query.bindings ?? []), { type: "idset", value: targetInstanceKeys.map((k) => k.id) }],
443
499
  };
444
500
  /* c8 ignore end */
445
501
  }
502
+ function mergeNodes(source) {
503
+ return from(source).pipe(reduce((acc, input) => {
504
+ for (let i = 0; i < acc.length; ++i) {
505
+ if (input.imodelAccess === acc[i].imodelAccess) {
506
+ // don't attempt to merge nodes if they come from the same provider
507
+ continue;
508
+ }
509
+ // the first argument for `tryMergeNodes` acts as the primary data source, so we have to make sure we pass
510
+ // the node with higher `imodelAccessIndex` first
511
+ const candidates = input.imodelAccessIndex > acc[i].imodelAccessIndex
512
+ ? { imodelAccess: input.imodelAccess, imodelAccessIndex: input.imodelAccessIndex, primary: input.node, secondary: acc[i].node }
513
+ : { imodelAccess: acc[i].imodelAccess, imodelAccessIndex: acc[i].imodelAccessIndex, primary: acc[i].node, secondary: input.node };
514
+ const merged = tryMergeNodes(candidates.primary, candidates.secondary);
515
+ if (merged) {
516
+ acc[i] = { node: merged, imodelAccess: candidates.imodelAccess, imodelAccessIndex: candidates.imodelAccessIndex };
517
+ return acc;
518
+ }
519
+ }
520
+ acc.push(input);
521
+ return acc;
522
+ }, new Array()), mergeAll());
523
+ }
524
+ function mergeSearchProps(primary, secondary) {
525
+ if (!primary || !secondary) {
526
+ return primary ?? secondary;
527
+ }
528
+ const hasSearchTargetAncestor = primary.hasSearchTargetAncestor || secondary.hasSearchTargetAncestor;
529
+ const childrenTargetPaths = [...(primary.childrenTargetPaths ?? []), ...(secondary.childrenTargetPaths ?? [])];
530
+ return {
531
+ ...(hasSearchTargetAncestor ? { hasSearchTargetAncestor } : undefined),
532
+ ...(childrenTargetPaths.length ? { childrenTargetPaths } : undefined),
533
+ ...(primary.isSearchTarget || secondary.isSearchTarget
534
+ ? {
535
+ isSearchTarget: true,
536
+ searchTargetOptions: HierarchySearchPath.mergeOptions(primary.isSearchTarget ? primary.searchTargetOptions : undefined, secondary.isSearchTarget ? secondary.searchTargetOptions : undefined),
537
+ }
538
+ : {
539
+ isSearchTarget: false,
540
+ }),
541
+ };
542
+ }
543
+ function tryMergeInstanceNodes(primary, secondary) {
544
+ if (HierarchyNode.isInstancesNode(primary) &&
545
+ HierarchyNode.isInstancesNode(secondary) &&
546
+ primary.key.instanceKeys.some((lhsKey) => secondary.key.instanceKeys.some((rhsKey) => InstanceKey.equals(lhsKey, rhsKey)))) {
547
+ const searchProps = mergeSearchProps(primary.search, secondary.search);
548
+ return {
549
+ ...primary,
550
+ key: {
551
+ type: "instances",
552
+ instanceKeys: primary.key.instanceKeys.concat(secondary.key.instanceKeys),
553
+ },
554
+ ...(searchProps ? { search: searchProps } : undefined),
555
+ };
556
+ }
557
+ return undefined;
558
+ }
559
+ function tryMergeGenericNodes(primary, secondary) {
560
+ if (HierarchyNode.isGeneric(primary) && HierarchyNode.isGeneric(secondary) && primary.key.type === secondary.key.type) {
561
+ const searchProps = mergeSearchProps(primary.search, secondary.search);
562
+ return {
563
+ ...primary,
564
+ ...(searchProps ? { search: searchProps } : undefined),
565
+ };
566
+ }
567
+ return undefined;
568
+ }
569
+ function tryMergeNodes(primary, secondary) {
570
+ return tryMergeInstanceNodes(primary, secondary) ?? tryMergeGenericNodes(primary, secondary) ?? undefined;
571
+ }
446
572
  //# sourceMappingURL=IModelHierarchyProvider.js.map