@itwin/presentation-hierarchies 2.0.0-alpha.0 → 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 (153) hide show
  1. package/CHANGELOG.md +306 -7
  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 -72
  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/SearchHierarchyDefinition.d.ts +35 -0
  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 +5 -7
  40. package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
  41. package/lib/cjs/hierarchies/imodel/TreeNodesReader.js +15 -8
  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 +68 -0
  63. package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -0
  64. package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js +26 -0
  65. package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -0
  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 -75
  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/SearchHierarchyDefinition.d.ts +35 -0
  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 +5 -7
  107. package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
  108. package/lib/esm/hierarchies/imodel/TreeNodesReader.js +13 -7
  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 +68 -0
  130. package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -0
  131. package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js +23 -0
  132. package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -0
  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 +19 -19
  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 -210
  141. package/lib/cjs/hierarchies/HierarchyFiltering.js.map +0 -1
  142. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts +0 -34
  143. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
  144. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js +0 -270
  145. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
  146. package/lib/esm/hierarchies/HierarchyFiltering.d.ts +0 -110
  147. package/lib/esm/hierarchies/HierarchyFiltering.d.ts.map +0 -1
  148. package/lib/esm/hierarchies/HierarchyFiltering.js +0 -205
  149. package/lib/esm/hierarchies/HierarchyFiltering.js.map +0 -1
  150. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts +0 -34
  151. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
  152. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js +0 -264
  153. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
@@ -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;AAiBpF,OAAO,EAA6B,mBAAmB,EAA4B,MAAM,gCAAgC,CAAC;AAS1H,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, defer, EMPTY, filter, finalize, from, 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";
@@ -16,15 +17,16 @@ import { partition } from "../internal/operators/Partition.js";
16
17
  import { reduceToMergeMapList } from "../internal/operators/ReduceToMergeMap.js";
17
18
  import { shareReplayWithErrors } from "../internal/operators/ShareReplayWithErrors.js";
18
19
  import { sortNodesByLabelOperator } from "../internal/operators/Sorting.js";
20
+ import { getRxjsHierarchyDefinition } from "../internal/RxjsHierarchyDefinition.js";
19
21
  import { SubscriptionScheduler } from "../internal/SubscriptionScheduler.js";
20
- import { FilteringHierarchyDefinition } from "./FilteringHierarchyDefinition.js";
21
22
  import { HierarchyCache } from "./HierarchyCache.js";
22
- import { HierarchyNodesDefinition } from "./IModelHierarchyDefinition.js";
23
+ import { HierarchyNodesDefinition, } from "./IModelHierarchyDefinition.js";
23
24
  import { NodeSelectClauseColumnNames } from "./NodeSelectQueryFactory.js";
24
25
  import { createDetermineChildrenOperator } from "./operators/DetermineChildren.js";
25
26
  import { createGroupingOperator } from "./operators/Grouping.js";
26
27
  import { createHideIfNoChildrenOperator } from "./operators/HideIfNoChildren.js";
27
28
  import { createHideNodesInHierarchyOperator } from "./operators/HideNodesInHierarchy.js";
29
+ import { SearchHierarchyDefinition } from "./SearchHierarchyDefinition.js";
28
30
  import { readNodes } from "./TreeNodesReader.js";
29
31
  const LOGGING_NAMESPACE = `${BASE_LOGGING_NAMESPACE}.IModelHierarchyProvider`;
30
32
  const LOGGING_NAMESPACE_INTERNAL = `${BASE_LOGGING_NAMESPACE_INTERNAL}.IModelHierarchyProvider`;
@@ -32,33 +34,57 @@ const LOGGING_NAMESPACE_PERFORMANCE = `${BASE_LOGGING_NAMESPACE_PERFORMANCE}.IMo
32
34
  const DEFAULT_QUERY_CONCURRENCY = 10;
33
35
  const DEFAULT_QUERY_CACHE_SIZE = 1;
34
36
  /**
35
- * 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
36
38
  * a hierarchy definition, which defines each hierarchy level through ECSQL queries.
37
39
  *
38
40
  * @public
39
41
  */
40
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) {
41
55
  return new IModelHierarchyProviderImpl(props);
42
56
  }
43
57
  class IModelHierarchyProviderImpl {
44
- _imodelAccess;
58
+ _imodels;
45
59
  _hierarchyChanged;
46
60
  _valuesFormatter;
47
61
  _sourceHierarchyDefinition;
48
62
  _activeHierarchyDefinition;
49
63
  _localizedStrings;
50
- _queryScheduler;
64
+ _queryConcurrency;
65
+ _querySchedulers;
51
66
  _nodesCache;
52
67
  _unsubscribe;
53
68
  _dispose = new Subject();
69
+ #componentId;
70
+ #componentName;
71
+ #sourceName;
54
72
  constructor(props) {
55
- 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;
56
81
  this._hierarchyChanged = new BeEvent();
57
- this._activeHierarchyDefinition = this._sourceHierarchyDefinition = props.hierarchyDefinition;
82
+ this._activeHierarchyDefinition = this._sourceHierarchyDefinition = getRxjsHierarchyDefinition(props.hierarchyDefinition);
58
83
  this._valuesFormatter = props?.formatter ?? createDefaultValueFormatter();
59
84
  this._localizedStrings = { other: "Other", unspecified: "Not specified", ...props?.localizedStrings };
60
- this._queryScheduler = new SubscriptionScheduler(props.queryConcurrency ?? DEFAULT_QUERY_CONCURRENCY);
61
- this.setHierarchyFilter(props.filtering);
85
+ this._queryConcurrency = props.queryConcurrency ?? DEFAULT_QUERY_CONCURRENCY;
86
+ this._querySchedulers = new Map();
87
+ this.setHierarchySearch(props.search);
62
88
  const queryCacheSize = props.queryCacheSize ?? DEFAULT_QUERY_CACHE_SIZE;
63
89
  if (queryCacheSize !== 0) {
64
90
  this._nodesCache = new HierarchyCache({
@@ -67,11 +93,18 @@ class IModelHierarchyProviderImpl {
67
93
  variationsCount: 1,
68
94
  });
69
95
  }
70
- this._unsubscribe = props.imodelChanged?.addListener(() => {
71
- 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}"`);
72
102
  this._dispose.next();
73
103
  this._hierarchyChanged.raiseEvent();
74
104
  });
105
+ this._unsubscribe = () => {
106
+ imodelChangeSubscription.unsubscribe();
107
+ };
75
108
  }
76
109
  [Symbol.dispose]() {
77
110
  this._dispose.next();
@@ -84,6 +117,17 @@ class IModelHierarchyProviderImpl {
84
117
  get hierarchyChanged() {
85
118
  return this._hierarchyChanged;
86
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
+ }
87
131
  invalidateHierarchyCache(reason) {
88
132
  doLog({
89
133
  category: `${LOGGING_NAMESPACE}.Events`,
@@ -99,23 +143,24 @@ class IModelHierarchyProviderImpl {
99
143
  this._valuesFormatter = formatter ?? createDefaultValueFormatter();
100
144
  this._hierarchyChanged.raiseEvent({ formatterChange: { newFormatter: this._valuesFormatter } });
101
145
  }
102
- setHierarchyFilter(props) {
146
+ setHierarchySearch(props) {
103
147
  if (!props) {
104
148
  if (this._sourceHierarchyDefinition !== this._activeHierarchyDefinition) {
105
149
  this._activeHierarchyDefinition = this._sourceHierarchyDefinition;
106
- this.invalidateHierarchyCache("Hierarchy filter reset");
150
+ this.invalidateHierarchyCache("Hierarchy search reset");
107
151
  }
108
- this._hierarchyChanged.raiseEvent({ filterChange: { newFilter: undefined } });
152
+ this._hierarchyChanged.raiseEvent({ searchChange: { newSearch: undefined } });
109
153
  return;
110
154
  }
111
- this._activeHierarchyDefinition = new FilteringHierarchyDefinition({
112
- imodelAccess: this._imodelAccess,
155
+ this._activeHierarchyDefinition = new SearchHierarchyDefinition({
156
+ imodelAccess: this.getPrimaryIModelAccess(),
113
157
  source: this._sourceHierarchyDefinition,
114
- nodeIdentifierPaths: props.paths,
158
+ sourceName: this.#sourceName,
159
+ targetPaths: props.paths,
115
160
  });
116
- this.invalidateHierarchyCache("Hierarchy filter set");
161
+ this.invalidateHierarchyCache("Hierarchy search set");
117
162
  this._dispose.next();
118
- this._hierarchyChanged.raiseEvent({ filterChange: { newFilter: props } });
163
+ this._hierarchyChanged.raiseEvent({ searchChange: { newSearch: props } });
119
164
  }
120
165
  onGroupingNodeCreated(groupingNode, props) {
121
166
  this._nodesCache?.set({ ...props, parentNode: groupingNode }, { observable: from(groupingNode.children), processingStatus: "pre-processed" });
@@ -126,48 +171,53 @@ class IModelHierarchyProviderImpl {
126
171
  category: LOGGING_NAMESPACE_PERFORMANCE,
127
172
  message: /* c8 ignore next */ () => `[${requestContext.requestId}] Requesting hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
128
173
  });
129
- return from(defer(async () => {
174
+ return from(this._imodels).pipe(mergeMap(({ imodelAccess }, imodelAccessIndex) => {
130
175
  let parentNode = props.parentNode;
131
- if (parentNode && HierarchyNode.isGeneric(parentNode) && parentNode.key.source && parentNode.key.source !== this._imodelAccess.imodelKey) {
132
- return [];
176
+ if (parentNode && HierarchyNode.isGeneric(parentNode) && parentNode.key.source && parentNode.key.source !== this.#sourceName) {
177
+ return EMPTY;
133
178
  }
134
179
  if (parentNode && HierarchyNode.isInstancesNode(parentNode)) {
135
180
  parentNode = {
136
181
  ...parentNode,
137
182
  key: {
138
183
  ...parentNode.key,
139
- instanceKeys: parentNode.key.instanceKeys.filter((ik) => !ik.imodelKey || ik.imodelKey === this._imodelAccess.imodelKey),
184
+ instanceKeys: parentNode.key.instanceKeys.filter((ik) => !ik.imodelKey || ik.imodelKey === imodelAccess.imodelKey),
140
185
  },
141
186
  };
142
187
  assert(HierarchyNodeKey.isInstances(parentNode.key));
143
188
  if (parentNode.key.instanceKeys.length === 0) {
144
- return [];
189
+ return EMPTY;
145
190
  }
146
191
  }
147
- return this._activeHierarchyDefinition.defineHierarchyLevel({ ...defineHierarchyLevelProps, parentNode });
148
- })).pipe(mergeAll(), finalize(() => doLog({
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({
149
196
  category: LOGGING_NAMESPACE_PERFORMANCE,
150
197
  message: /* c8 ignore next */ () => `[${requestContext.requestId}] Received all hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
151
198
  })));
152
199
  }
153
200
  createSourceNodesObservable(props) {
154
201
  // pipe definitions to nodes and put "share replay" on it
155
- return this.createHierarchyLevelDefinitionsObservable(props).pipe(mergeMap((def) => {
202
+ return this.createHierarchyLevelDefinitionsObservable(props).pipe(mergeMap(({ imodelAccess, imodelAccessIndex, hierarchyNodesDefinition: def }) => defer(() => {
156
203
  if (HierarchyNodesDefinition.isGenericNode(def)) {
157
- 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
+ });
158
208
  }
159
- return this._queryScheduler.scheduleSubscription(of(def.query).pipe(map((query) => filterQueryByInstanceKeys(query, props.filteredInstanceKeys)), mergeMap((query) => readNodes({
160
- 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,
161
211
  query,
162
212
  limit: props.hierarchyLevelSizeLimit,
163
213
  parser: this._activeHierarchyDefinition.parseNode
164
- ? async (row) => this._activeHierarchyDefinition.parseNode(row, props.parentNode)
214
+ ? ({ row }) => this._activeHierarchyDefinition.parseNode({ row, parentNode: props.parentNode, imodelKey: imodelAccess.imodelKey })
165
215
  : undefined,
166
216
  })), map((node) => ({
167
217
  ...node,
168
- 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 })) },
169
219
  }))));
170
- }), finalize(() => doLog({
220
+ }).pipe(map((node) => ({ imodelAccess, imodelAccessIndex, node })))), mergeNodes, map(({ node }) => node), finalize(() => doLog({
171
221
  category: LOGGING_NAMESPACE_PERFORMANCE,
172
222
  message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Read all child nodes ${createNodeIdentifierForLogging(props.parentNode)}`,
173
223
  })), shareReplayWithErrors());
@@ -179,8 +229,9 @@ class IModelHierarchyProviderImpl {
179
229
  // set parent node keys on the source node
180
230
  map((node) => Object.assign(node, { parentKeys: createParentNodeKeysList(props.parentNode) })),
181
231
  // format `ConcatenatedValue` labels into string labels
182
- mergeMap(async (node) => applyLabelsFormatting(node, this._valuesFormatter)),
232
+ mergeMap((node) => applyLabelsFormatting(node, this._valuesFormatter)),
183
233
  // we have `ProcessedHierarchyNode` from here
234
+ // let consumers step-in
184
235
  preProcessNodes(this._activeHierarchyDefinition),
185
236
  // process hiding
186
237
  createHideIfNoChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n, requestContext: props.requestContext }).hasNodes), createHideNodesInHierarchyOperator(
@@ -191,7 +242,7 @@ class IModelHierarchyProviderImpl {
191
242
  })));
192
243
  }
193
244
  createProcessedNodesObservable(preprocessedNodesObservable, props) {
194
- 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({
195
246
  category: LOGGING_NAMESPACE_PERFORMANCE,
196
247
  message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Finished grouping child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
197
248
  })));
@@ -201,9 +252,7 @@ class IModelHierarchyProviderImpl {
201
252
  if ("processingParams" in n) {
202
253
  delete n.processingParams;
203
254
  }
204
- return Object.assign(n, {
205
- children: hasChildren(n),
206
- });
255
+ return { ...n, children: hasChildren(n) };
207
256
  }), takeUntil(this._dispose), finalize(() => doLog({
208
257
  category: LOGGING_NAMESPACE_PERFORMANCE,
209
258
  message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Finished finalizing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
@@ -237,13 +286,13 @@ class IModelHierarchyProviderImpl {
237
286
  return cached;
238
287
  }
239
288
  // if we don't find an entry for a grouping node, we load its instances by getting a query and applying
240
- // a filter based on grouped instance keys
241
- let filteredInstanceKeys;
289
+ // a search based on grouped instance keys
290
+ let targetInstanceKeys;
242
291
  let parentNonGroupingNode;
243
292
  if (parentNode) {
244
293
  if (HierarchyNode.isGroupingNode(parentNode)) {
245
294
  parentNonGroupingNode = parentNode.nonGroupingAncestor;
246
- filteredInstanceKeys = parentNode.groupedInstanceKeys;
295
+ targetInstanceKeys = parentNode.groupedInstanceKeys;
247
296
  }
248
297
  else {
249
298
  // not sure why type checker doesn't pick this up
@@ -254,7 +303,7 @@ class IModelHierarchyProviderImpl {
254
303
  const nonGroupingNodeChildrenRequestProps = {
255
304
  ...restProps,
256
305
  parentNode: parentNonGroupingNode,
257
- ...(filteredInstanceKeys ? { filteredInstanceKeys } : undefined),
306
+ ...(targetInstanceKeys ? { targetInstanceKeys } : undefined),
258
307
  };
259
308
  const value = { observable: this.createSourceNodesObservable(nonGroupingNodeChildrenRequestProps), processingStatus: "none" };
260
309
  this._nodesCache?.set(nonGroupingNodeChildrenRequestProps, value);
@@ -318,11 +367,11 @@ class IModelHierarchyProviderImpl {
318
367
  return from(parentNode.groupedInstanceKeys);
319
368
  }
320
369
  assert(!parentNode || HierarchyNode.isGeneric(parentNode) || HierarchyNode.isInstancesNode(parentNode));
321
- const hierarchyLevelDefinitions = this.createHierarchyLevelDefinitionsObservable({ parentNode, instanceFilter, requestContext });
322
370
  // split the definitions based on whether they're for generic nodes or for instance nodes
323
- 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));
324
373
  // query instance keys and a flag whether they should be hidden
325
- 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) => {
326
375
  const ecsql = `
327
376
  SELECT
328
377
  ${NodeSelectClauseColumnNames.FullClassName},
@@ -332,12 +381,16 @@ class IModelHierarchyProviderImpl {
332
381
  ${query.ecsql}
333
382
  )
334
383
  `;
335
- 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
+ });
336
389
  return from(reader).pipe(map((row) => ({
337
390
  key: {
338
391
  className: normalizeFullClassName(row[0]),
339
392
  id: row[1],
340
- imodelKey: this._imodelAccess.imodelKey,
393
+ imodelKey: imodelAccess.imodelKey,
341
394
  },
342
395
  hide: !!row[2],
343
396
  })));
@@ -347,17 +400,17 @@ class IModelHierarchyProviderImpl {
347
400
  // hidden items' handling:
348
401
  // - if a generic node is hidden, we'll want to retrieve instance keys of its children, otherwise we don't care about it,
349
402
  // - if an instance key is hidden, we want to create a merged node similar to what we do in `createHideNodesInHierarchyOperator`
350
- 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 }) => ({
351
404
  type: "generic",
352
- id: def.node.key,
353
- source: this._imodelAccess.imodelKey,
405
+ id: hierarchyNodesDefinition.node.key,
406
+ source: this.#sourceName,
354
407
  }))), hiddenNodeInstanceKeys.pipe(
355
408
  // first merge all keys by class
356
- reduceToMergeMapList(({ key }) => key.className, ({ key }) => key.id),
409
+ reduceToMergeMapList(({ key }) => key.className, ({ key }) => key),
357
410
  // then, for each class, create an instance key
358
- mergeMap((mergedMap) => [...mergedMap.entries()].map(([className, ids]) => ({
411
+ mergeMap((mergedMap) => [...mergedMap.entries()].map(([className, keys]) => ({
359
412
  type: "instances",
360
- instanceKeys: ids.map((id) => ({ className, id, imodelKey: this._imodelAccess.imodelKey })),
413
+ instanceKeys: keys.map(({ id, imodelKey }) => ({ className, id, imodelKey })),
361
414
  }))))).pipe(map((key) => ({
362
415
  key,
363
416
  parentKeys: [],
@@ -395,26 +448,22 @@ class IModelHierarchyProviderImpl {
395
448
  }
396
449
  }
397
450
  function preProcessNodes(hierarchyFactory) {
398
- return hierarchyFactory.preProcessNode
399
- ? processNodes(hierarchyFactory.preProcessNode.bind(hierarchyFactory))
400
- : (o) => o;
451
+ return hierarchyFactory.preProcessNode ? processNodes(hierarchyFactory.preProcessNode) : identity;
401
452
  }
402
453
  function postProcessNodes(hierarchyFactory) {
403
- return hierarchyFactory.postProcessNode
404
- ? processNodes(hierarchyFactory.postProcessNode.bind(hierarchyFactory))
405
- : (o) => o;
454
+ return hierarchyFactory.postProcessNode ? processNodes(hierarchyFactory.postProcessNode) : identity;
406
455
  }
407
456
  function processNodes(processor) {
408
- return (nodes) => nodes.pipe(mergeMap(processor), filter((n) => !!n));
457
+ return (nodes) => nodes.pipe(mergeMap(processor));
409
458
  }
410
- async function applyLabelsFormatting(node, valueFormatter) {
411
- return {
459
+ function applyLabelsFormatting(node, valueFormatter) {
460
+ return from(formatConcatenatedValue({
461
+ value: node.label,
462
+ valueFormatter,
463
+ })).pipe(map((label) => ({
412
464
  ...node,
413
- label: await formatConcatenatedValue({
414
- value: node.label,
415
- valueFormatter,
416
- }),
417
- };
465
+ label,
466
+ })));
418
467
  }
419
468
  function createParentNodeKeysList(parentNode) {
420
469
  if (!parentNode) {
@@ -422,20 +471,20 @@ function createParentNodeKeysList(parentNode) {
422
471
  }
423
472
  return [...parentNode.parentKeys, parentNode.key];
424
473
  }
425
- function filterQueryByInstanceKeys(query, filteredInstanceKeys) {
426
- if (!filteredInstanceKeys || !filteredInstanceKeys.length) {
474
+ function createInstanceKeysFilteredQuery(query, targetInstanceKeys) {
475
+ if (!targetInstanceKeys || !targetInstanceKeys.length) {
427
476
  return query;
428
477
  }
429
478
  const MAX_ALLOWED_BINDINGS = 1000;
430
- if (filteredInstanceKeys.length < MAX_ALLOWED_BINDINGS) {
479
+ if (targetInstanceKeys.length < MAX_ALLOWED_BINDINGS) {
431
480
  return {
432
481
  ...query,
433
482
  ecsql: `
434
483
  SELECT *
435
484
  FROM (${query.ecsql}) q
436
- WHERE q.ECInstanceId IN (${filteredInstanceKeys.map(() => "?").join(",")})
485
+ WHERE q.ECInstanceId IN (${targetInstanceKeys.map(() => "?").join(",")})
437
486
  `,
438
- bindings: [...(query.bindings ?? []), ...filteredInstanceKeys.map((k) => ({ type: "id", value: k.id }))],
487
+ bindings: [...(query.bindings ?? []), ...targetInstanceKeys.map((k) => ({ type: "id", value: k.id }))],
439
488
  };
440
489
  }
441
490
  /* c8 ignore start */
@@ -446,8 +495,78 @@ function filterQueryByInstanceKeys(query, filteredInstanceKeys) {
446
495
  FROM (${query.ecsql}) q
447
496
  WHERE InVirtualSet(?, q.ECInstanceId)
448
497
  `,
449
- bindings: [...(query.bindings ?? []), { type: "idset", value: filteredInstanceKeys.map((k) => k.id) }],
498
+ bindings: [...(query.bindings ?? []), { type: "idset", value: targetInstanceKeys.map((k) => k.id) }],
450
499
  };
451
500
  /* c8 ignore end */
452
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
+ }
453
572
  //# sourceMappingURL=IModelHierarchyProvider.js.map