@itwin/presentation-frontend 4.5.0-dev.8 → 4.6.0-dev.0

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 (122) hide show
  1. package/CHANGELOG.md +55 -1
  2. package/LICENSE.md +1 -1
  3. package/README.md +1 -1
  4. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.d.ts.map +1 -1
  5. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js +10 -6
  6. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  7. package/lib/cjs/presentation-frontend/Diagnostics.d.ts.map +1 -1
  8. package/lib/cjs/presentation-frontend/Diagnostics.js +18 -13
  9. package/lib/cjs/presentation-frontend/Diagnostics.js.map +1 -1
  10. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js +3 -3
  11. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  12. package/lib/cjs/presentation-frontend/IpcRequestsHandler.d.ts.map +1 -1
  13. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js +3 -3
  14. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  15. package/lib/cjs/presentation-frontend/LocalizationHelper.js +3 -3
  16. package/lib/cjs/presentation-frontend/LocalizationHelper.js.map +1 -1
  17. package/lib/cjs/presentation-frontend/Presentation.d.ts.map +1 -1
  18. package/lib/cjs/presentation-frontend/Presentation.js +26 -16
  19. package/lib/cjs/presentation-frontend/Presentation.js.map +1 -1
  20. package/lib/cjs/presentation-frontend/PresentationManager.d.ts +84 -21
  21. package/lib/cjs/presentation-frontend/PresentationManager.d.ts.map +1 -1
  22. package/lib/cjs/presentation-frontend/PresentationManager.js +245 -154
  23. package/lib/cjs/presentation-frontend/PresentationManager.js.map +1 -1
  24. package/lib/cjs/presentation-frontend/RulesetManager.d.ts.map +1 -1
  25. package/lib/cjs/presentation-frontend/RulesetManager.js +11 -7
  26. package/lib/cjs/presentation-frontend/RulesetManager.js.map +1 -1
  27. package/lib/cjs/presentation-frontend/RulesetVariablesManager.d.ts.map +1 -1
  28. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js +53 -31
  29. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  30. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.d.ts +30 -0
  31. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.d.ts.map +1 -0
  32. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.js +117 -0
  33. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.js.map +1 -0
  34. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +33 -4
  35. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts.map +1 -1
  36. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +172 -67
  37. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  38. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts.map +1 -1
  39. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +54 -25
  40. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  41. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.d.ts.map +1 -1
  42. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js +23 -13
  43. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  44. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js +3 -3
  45. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  46. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.d.ts.map +1 -1
  47. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js +3 -3
  48. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  49. package/lib/cjs/presentation-frontend/selection/SelectionHandler.d.ts.map +1 -1
  50. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js +15 -9
  51. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  52. package/lib/cjs/presentation-frontend/selection/SelectionHelper.d.ts.map +1 -1
  53. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js +7 -5
  54. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  55. package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts.map +1 -1
  56. package/lib/cjs/presentation-frontend/selection/SelectionManager.js +31 -16
  57. package/lib/cjs/presentation-frontend/selection/SelectionManager.js.map +1 -1
  58. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.d.ts.map +1 -1
  59. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js +25 -14
  60. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  61. package/lib/cjs/presentation-frontend.js +3 -3
  62. package/lib/cjs/presentation-frontend.js.map +1 -1
  63. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.d.ts.map +1 -1
  64. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js +10 -6
  65. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  66. package/lib/esm/presentation-frontend/Diagnostics.d.ts.map +1 -1
  67. package/lib/esm/presentation-frontend/Diagnostics.js +18 -13
  68. package/lib/esm/presentation-frontend/Diagnostics.js.map +1 -1
  69. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js +3 -3
  70. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  71. package/lib/esm/presentation-frontend/IpcRequestsHandler.d.ts.map +1 -1
  72. package/lib/esm/presentation-frontend/IpcRequestsHandler.js +3 -3
  73. package/lib/esm/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  74. package/lib/esm/presentation-frontend/LocalizationHelper.js +3 -3
  75. package/lib/esm/presentation-frontend/LocalizationHelper.js.map +1 -1
  76. package/lib/esm/presentation-frontend/Presentation.d.ts.map +1 -1
  77. package/lib/esm/presentation-frontend/Presentation.js +26 -16
  78. package/lib/esm/presentation-frontend/Presentation.js.map +1 -1
  79. package/lib/esm/presentation-frontend/PresentationManager.d.ts +84 -21
  80. package/lib/esm/presentation-frontend/PresentationManager.d.ts.map +1 -1
  81. package/lib/esm/presentation-frontend/PresentationManager.js +244 -152
  82. package/lib/esm/presentation-frontend/PresentationManager.js.map +1 -1
  83. package/lib/esm/presentation-frontend/RulesetManager.d.ts.map +1 -1
  84. package/lib/esm/presentation-frontend/RulesetManager.js +11 -7
  85. package/lib/esm/presentation-frontend/RulesetManager.js.map +1 -1
  86. package/lib/esm/presentation-frontend/RulesetVariablesManager.d.ts.map +1 -1
  87. package/lib/esm/presentation-frontend/RulesetVariablesManager.js +53 -31
  88. package/lib/esm/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  89. package/lib/esm/presentation-frontend/StreamedResponseGenerator.d.ts +30 -0
  90. package/lib/esm/presentation-frontend/StreamedResponseGenerator.d.ts.map +1 -0
  91. package/lib/esm/presentation-frontend/StreamedResponseGenerator.js +113 -0
  92. package/lib/esm/presentation-frontend/StreamedResponseGenerator.js.map +1 -0
  93. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +33 -4
  94. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts.map +1 -1
  95. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +172 -67
  96. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  97. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts.map +1 -1
  98. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +54 -25
  99. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  100. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.d.ts.map +1 -1
  101. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js +24 -14
  102. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  103. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js +3 -3
  104. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  105. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.d.ts.map +1 -1
  106. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js +3 -3
  107. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  108. package/lib/esm/presentation-frontend/selection/SelectionHandler.d.ts.map +1 -1
  109. package/lib/esm/presentation-frontend/selection/SelectionHandler.js +15 -9
  110. package/lib/esm/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  111. package/lib/esm/presentation-frontend/selection/SelectionHelper.d.ts.map +1 -1
  112. package/lib/esm/presentation-frontend/selection/SelectionHelper.js +7 -5
  113. package/lib/esm/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  114. package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts.map +1 -1
  115. package/lib/esm/presentation-frontend/selection/SelectionManager.js +31 -16
  116. package/lib/esm/presentation-frontend/selection/SelectionManager.js.map +1 -1
  117. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.d.ts.map +1 -1
  118. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js +25 -14
  119. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  120. package/lib/esm/presentation-frontend.js +3 -3
  121. package/lib/esm/presentation-frontend.js.map +1 -1
  122. package/package.json +19 -16
@@ -1,7 +1,7 @@
1
1
  /*---------------------------------------------------------------------------------------------
2
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
- * See LICENSE.md in the project root for license terms and full copyright notice.
4
- *--------------------------------------------------------------------------------------------*/
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
5
  /** @packageDocumentation
6
6
  * @module Core
7
7
  */
@@ -13,6 +13,7 @@ import { FrontendLocalizationHelper } from "./LocalizationHelper";
13
13
  import { RulesetManagerImpl } from "./RulesetManager";
14
14
  import { RulesetVariablesManagerImpl } from "./RulesetVariablesManager";
15
15
  import { TRANSIENT_ELEMENT_CLASSNAME } from "./selection/SelectionManager";
16
+ import { StreamedResponseGenerator } from "./StreamedResponseGenerator";
16
17
  /**
17
18
  * Frontend Presentation manager which basically just forwards all calls to
18
19
  * the backend implementation.
@@ -30,7 +31,9 @@ export class PresentationManager {
30
31
  get activeUnitSystem() {
31
32
  return this._explicitActiveUnitSystem ?? IModelApp.quantityFormatter.activeUnitSystem;
32
33
  }
33
- set activeUnitSystem(value) { this._explicitActiveUnitSystem = value; }
34
+ set activeUnitSystem(value) {
35
+ this._explicitActiveUnitSystem = value;
36
+ }
34
37
  constructor(props) {
35
38
  /**
36
39
  * An event raised when hierarchies created using specific ruleset change
@@ -51,11 +54,11 @@ export class PresentationManager {
51
54
  // eslint-disable-next-line deprecation/deprecation
52
55
  this._explicitActiveUnitSystem = props.activeUnitSystem;
53
56
  }
54
- this._requestsHandler = props?.rpcRequestsHandler ?? new RpcRequestsHandler(props ? { clientId: props.clientId, timeout: props.requestTimeout } : undefined);
57
+ this._requestsHandler =
58
+ props?.rpcRequestsHandler ?? new RpcRequestsHandler(props ? { clientId: props.clientId, timeout: props.requestTimeout } : undefined);
55
59
  this._rulesetVars = new Map();
56
60
  this._rulesets = RulesetManagerImpl.create();
57
61
  this._localizationHelper = new FrontendLocalizationHelper(props?.activeLocale);
58
- this._connections = new Map();
59
62
  this._schemaContextProvider = props?.schemaContextProvider;
60
63
  this._defaultFormats = props?.defaultFormats;
61
64
  if (IpcApp.isValid) {
@@ -65,41 +68,38 @@ export class PresentationManager {
65
68
  }
66
69
  }
67
70
  /** Get / set active locale used for localizing presentation data */
68
- get activeLocale() { return this._localizationHelper.locale; }
69
- set activeLocale(locale) { this._localizationHelper.locale = locale; }
71
+ get activeLocale() {
72
+ return this._localizationHelper.locale;
73
+ }
74
+ set activeLocale(locale) {
75
+ this._localizationHelper.locale = locale;
76
+ }
70
77
  dispose() {
71
78
  if (this._clearEventListener) {
72
79
  this._clearEventListener();
73
80
  this._clearEventListener = undefined;
74
81
  }
75
82
  }
76
- async onConnection(imodel) {
77
- if (!this._connections.has(imodel))
78
- this._connections.set(imodel, this.initializeIModel(imodel));
79
- await this._connections.get(imodel);
80
- }
81
- async initializeIModel(imodel) {
82
- imodel.onClose.addOnce(() => {
83
- this._connections.delete(imodel);
84
- });
85
- await this.onNewiModelConnection(imodel);
86
- }
87
83
  /** @note This is only called in native apps after changes in iModels */
88
84
  async handleUpdateAsync(report) {
89
85
  for (const imodelKey in report) {
90
86
  // istanbul ignore if
91
- if (!report.hasOwnProperty(imodelKey))
87
+ if (!report.hasOwnProperty(imodelKey)) {
92
88
  continue;
89
+ }
93
90
  const imodelReport = report[imodelKey];
94
91
  for (const rulesetId in imodelReport) {
95
92
  // istanbul ignore if
96
- if (!imodelReport.hasOwnProperty(rulesetId))
93
+ if (!imodelReport.hasOwnProperty(rulesetId)) {
97
94
  continue;
95
+ }
98
96
  const updateInfo = imodelReport[rulesetId];
99
- if (updateInfo.content)
97
+ if (updateInfo.content) {
100
98
  this.onIModelContentChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.content, imodelKey });
101
- if (updateInfo.hierarchy)
99
+ }
100
+ if (updateInfo.hierarchy) {
102
101
  this.onIModelHierarchyChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.hierarchy, imodelKey });
102
+ }
103
103
  }
104
104
  }
105
105
  }
@@ -107,7 +107,13 @@ export class PresentationManager {
107
107
  * Function that is called when a new IModelConnection is used to retrieve data.
108
108
  * @internal
109
109
  */
110
- async onNewiModelConnection(_) { }
110
+ startIModelInitialization(_) { }
111
+ /**
112
+ * Function that should be called to finish initialization that was started at [[PresentationManager.startIModelInitialization]].
113
+ * Can be removed when [[FavoritePropertiesManager.has]] and [[FavoritePropertiesManager.sortFields]] are removed.
114
+ * @internal
115
+ */
116
+ async ensureIModelInitialized(_) { }
111
117
  /**
112
118
  * Create a new PresentationManager instance
113
119
  * @param props Optional properties used to configure the manager
@@ -116,13 +122,19 @@ export class PresentationManager {
116
122
  return new PresentationManager(props);
117
123
  }
118
124
  /** @internal */
119
- get rpcRequestsHandler() { return this._requestsHandler; }
125
+ get rpcRequestsHandler() {
126
+ return this._requestsHandler;
127
+ }
120
128
  /** @internal */
121
- get ipcRequestsHandler() { return this._ipcRequestsHandler; }
129
+ get ipcRequestsHandler() {
130
+ return this._ipcRequestsHandler;
131
+ }
122
132
  /**
123
133
  * Get rulesets manager
124
134
  */
125
- rulesets() { return this._rulesets; }
135
+ rulesets() {
136
+ return this._rulesets;
137
+ }
126
138
  /**
127
139
  * Get ruleset variables manager for specific ruleset
128
140
  * @param rulesetId Id of the ruleset to get the vars manager for
@@ -139,8 +151,9 @@ export class PresentationManager {
139
151
  // 2. put all `requestOptions` members (if `locale` or `unitSystem` are set, they'll override the defaults put at #1)
140
152
  // 3. put `imodel` of type `IModelRpcProps` which overwrites the `imodel` from `requestOptions` put at #2
141
153
  const defaultOptions = {};
142
- if (this.activeLocale)
154
+ if (this.activeLocale) {
143
155
  defaultOptions.locale = this.activeLocale;
156
+ }
144
157
  defaultOptions.unitSystem = this.activeUnitSystem; // eslint-disable-line deprecation/deprecation
145
158
  const { imodel, rulesetVariables, ...rpcRequestOptions } = requestOptions;
146
159
  return {
@@ -160,13 +173,14 @@ export class PresentationManager {
160
173
  const foundRuleset = await this._rulesets.get(rulesetOrId);
161
174
  foundRulesetOrId = foundRuleset ? foundRuleset.toJSON() : rulesetOrId;
162
175
  }
163
- const rulesetId = (typeof foundRulesetOrId === "object") ? foundRulesetOrId.id : foundRulesetOrId;
176
+ const rulesetId = typeof foundRulesetOrId === "object" ? foundRulesetOrId.id : foundRulesetOrId;
164
177
  // All Id64Array variable values must be sorted for serialization to JSON to work. RulesetVariablesManager
165
178
  // sorts them before storing, so that part is taken care of, but we need to ensure that variables coming from
166
179
  // request options are also sorted.
167
180
  const variables = (rulesetVariables ?? []).map((variable) => {
168
- if (variable.type === VariableValueTypes.Id64Array)
181
+ if (variable.type === VariableValueTypes.Id64Array) {
169
182
  return { ...variable, value: OrderedId64Iterable.sortArray(variable.value) };
183
+ }
170
184
  return variable;
171
185
  });
172
186
  if (!this._ipcRequestsHandler) {
@@ -176,32 +190,48 @@ export class PresentationManager {
176
190
  }
177
191
  return { ...options, rulesetOrId: foundRulesetOrId, rulesetVariables: variables };
178
192
  }
179
- /** Retrieves nodes */
180
- async getNodes(requestOptions) {
181
- await this.onConnection(requestOptions.imodel);
193
+ /** Returns an iterator that polls nodes asynchronously. */
194
+ async getNodesIterator(requestOptions) {
195
+ this.startIModelInitialization(requestOptions.imodel);
182
196
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
183
197
  const rpcOptions = this.toRpcTokenOptions({ ...options });
184
- const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions) => this._requestsHandler.getPagedNodes({ ...rpcOptions, paging: partialPageOptions }));
185
- // eslint-disable-next-line deprecation/deprecation
186
- return this._localizationHelper.getLocalizedNodes(result.items.map(Node.fromJSON));
198
+ const generator = new StreamedResponseGenerator({
199
+ ...requestOptions,
200
+ getBatch: async (paging) => {
201
+ const result = await this._requestsHandler.getPagedNodes({ ...rpcOptions, paging });
202
+ return {
203
+ total: result.total,
204
+ // eslint-disable-next-line deprecation/deprecation
205
+ items: this._localizationHelper.getLocalizedNodes(result.items.map(Node.fromJSON)),
206
+ };
207
+ },
208
+ });
209
+ return generator.createAsyncIteratorResponse();
210
+ }
211
+ /**
212
+ * Retrieves nodes
213
+ * @deprecated in 4.5. Use [[getNodesIterator]] instead.
214
+ */
215
+ async getNodes(requestOptions) {
216
+ const result = await this.getNodesIterator(requestOptions);
217
+ return collect(result.items);
187
218
  }
188
219
  /** Retrieves nodes count. */
189
220
  async getNodesCount(requestOptions) {
190
- await this.onConnection(requestOptions.imodel);
221
+ this.startIModelInitialization(requestOptions.imodel);
191
222
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
192
223
  const rpcOptions = this.toRpcTokenOptions({ ...options });
193
224
  return this._requestsHandler.getNodesCount(rpcOptions);
194
225
  }
195
- /** Retrieves total nodes count and a single page of nodes. */
226
+ /**
227
+ * Retrieves total nodes count and a single page of nodes.
228
+ * @deprecated in 4.5. Use [[getNodesIterator]] instead.
229
+ */
196
230
  async getNodesAndCount(requestOptions) {
197
- await this.onConnection(requestOptions.imodel);
198
- const options = await this.addRulesetAndVariablesToOptions(requestOptions);
199
- const rpcOptions = this.toRpcTokenOptions({ ...options });
200
- const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions) => this._requestsHandler.getPagedNodes({ ...rpcOptions, paging: partialPageOptions }));
231
+ const result = await this.getNodesIterator(requestOptions);
201
232
  return {
202
233
  count: result.total,
203
- // eslint-disable-next-line deprecation/deprecation
204
- nodes: this._localizationHelper.getLocalizedNodes(result.items.map(Node.fromJSON)),
234
+ nodes: await collect(result.items),
205
235
  };
206
236
  }
207
237
  /**
@@ -209,16 +239,21 @@ export class PresentationManager {
209
239
  * @beta
210
240
  */
211
241
  async getNodesDescriptor(requestOptions) {
212
- await this.onConnection(requestOptions.imodel);
213
- const options = await this.addRulesetAndVariablesToOptions(requestOptions);
214
- const rpcOptions = this.toRpcTokenOptions({ ...options });
215
- const result = await this._requestsHandler.getNodesDescriptor(rpcOptions);
216
- const descriptor = Descriptor.fromJSON(result);
217
- return descriptor ? this._localizationHelper.getLocalizedContentDescriptor(descriptor) : undefined;
242
+ this.startIModelInitialization(requestOptions.imodel);
243
+ try {
244
+ const options = await this.addRulesetAndVariablesToOptions(requestOptions);
245
+ const rpcOptions = this.toRpcTokenOptions({ ...options });
246
+ const result = await this._requestsHandler.getNodesDescriptor(rpcOptions);
247
+ const descriptor = Descriptor.fromJSON(result);
248
+ return descriptor ? this._localizationHelper.getLocalizedContentDescriptor(descriptor) : undefined;
249
+ }
250
+ finally {
251
+ await this.ensureIModelInitialized(requestOptions.imodel);
252
+ }
218
253
  }
219
254
  /** Retrieves paths from root nodes to children nodes according to specified keys. Intersecting paths will be merged. */
220
255
  async getNodePaths(requestOptions) {
221
- await this.onConnection(requestOptions.imodel);
256
+ this.startIModelInitialization(requestOptions.imodel);
222
257
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
223
258
  const rpcOptions = this.toRpcTokenOptions({ ...options });
224
259
  const result = await this._requestsHandler.getNodePaths(rpcOptions);
@@ -227,7 +262,7 @@ export class PresentationManager {
227
262
  }
228
263
  /** Retrieves paths from root nodes to nodes containing filter text in their label. */
229
264
  async getFilteredNodePaths(requestOptions) {
230
- await this.onConnection(requestOptions.imodel);
265
+ this.startIModelInitialization(requestOptions.imodel);
231
266
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
232
267
  const result = await this._requestsHandler.getFilteredNodePaths(this.toRpcTokenOptions(options));
233
268
  // eslint-disable-next-line deprecation/deprecation
@@ -239,26 +274,31 @@ export class PresentationManager {
239
274
  * @public
240
275
  */
241
276
  async getContentSources(requestOptions) {
242
- await this.onConnection(requestOptions.imodel);
277
+ this.startIModelInitialization(requestOptions.imodel);
243
278
  const rpcOptions = this.toRpcTokenOptions(requestOptions);
244
279
  const result = await this._requestsHandler.getContentSources(rpcOptions);
245
280
  return SelectClassInfo.listFromCompressedJSON(result.sources, result.classesMap);
246
281
  }
247
282
  /** Retrieves the content descriptor which describes the content and can be used to customize it. */
248
283
  async getContentDescriptor(requestOptions) {
249
- await this.onConnection(requestOptions.imodel);
250
- const options = await this.addRulesetAndVariablesToOptions(requestOptions);
251
- const rpcOptions = this.toRpcTokenOptions({
252
- ...options,
253
- keys: stripTransientElementKeys(options.keys).toJSON(),
254
- });
255
- const result = await this._requestsHandler.getContentDescriptor(rpcOptions);
256
- const descriptor = Descriptor.fromJSON(result);
257
- return descriptor ? this._localizationHelper.getLocalizedContentDescriptor(descriptor) : undefined;
284
+ this.startIModelInitialization(requestOptions.imodel);
285
+ try {
286
+ const options = await this.addRulesetAndVariablesToOptions(requestOptions);
287
+ const rpcOptions = this.toRpcTokenOptions({
288
+ ...options,
289
+ keys: stripTransientElementKeys(options.keys).toJSON(),
290
+ });
291
+ const result = await this._requestsHandler.getContentDescriptor(rpcOptions);
292
+ const descriptor = Descriptor.fromJSON(result);
293
+ return descriptor ? this._localizationHelper.getLocalizedContentDescriptor(descriptor) : undefined;
294
+ }
295
+ finally {
296
+ await this.ensureIModelInitialized(requestOptions.imodel);
297
+ }
258
298
  }
259
299
  /** Retrieves overall content set size. */
260
300
  async getContentSetSize(requestOptions) {
261
- await this.onConnection(requestOptions.imodel);
301
+ this.startIModelInitialization(requestOptions.imodel);
262
302
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
263
303
  const rpcOptions = this.toRpcTokenOptions({
264
304
  ...options,
@@ -267,13 +307,7 @@ export class PresentationManager {
267
307
  });
268
308
  return this._requestsHandler.getContentSetSize(rpcOptions);
269
309
  }
270
- /** Retrieves content which consists of a content descriptor and a page of records. */
271
- async getContent(requestOptions) {
272
- return (await this.getContentAndSize(requestOptions))?.content;
273
- }
274
- /** Retrieves content set size and content which consists of a content descriptor and a page of records. */
275
- async getContentAndSize(requestOptions) {
276
- await this.onConnection(requestOptions.imodel);
310
+ async getContentIteratorInternal(requestOptions) {
277
311
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
278
312
  const rpcOptions = this.toRpcTokenOptions({
279
313
  ...options,
@@ -281,46 +315,113 @@ export class PresentationManager {
281
315
  keys: stripTransientElementKeys(requestOptions.keys).toJSON(),
282
316
  ...(!requestOptions.omitFormattedValues && this._schemaContextProvider !== undefined ? { omitFormattedValues: true } : undefined),
283
317
  });
284
- let descriptor = (requestOptions.descriptor instanceof Descriptor) ? requestOptions.descriptor : undefined;
285
- const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions, requestIndex) => {
286
- if (0 === requestIndex && !descriptor) {
287
- const content = await this._requestsHandler.getPagedContent({ ...rpcOptions, paging: partialPageOptions });
288
- if (content) {
289
- descriptor = Descriptor.fromJSON(content.descriptor);
290
- return content.contentSet;
291
- }
292
- return { total: 0, items: [] };
318
+ let contentFormatter;
319
+ if (!requestOptions.omitFormattedValues && this._schemaContextProvider) {
320
+ const koqPropertyFormatter = new KoqPropertyValueFormatter(this._schemaContextProvider(requestOptions.imodel), this._defaultFormats);
321
+ contentFormatter = new ContentFormatter(new ContentPropertyValueFormatter(koqPropertyFormatter), requestOptions.unitSystem ?? this._explicitActiveUnitSystem ?? IModelApp.quantityFormatter.activeUnitSystem);
322
+ }
323
+ let descriptor = requestOptions.descriptor instanceof Descriptor ? requestOptions.descriptor : undefined;
324
+ let firstPage;
325
+ if (!descriptor) {
326
+ const firstPageResponse = await this._requestsHandler.getPagedContent(rpcOptions);
327
+ if (!firstPageResponse?.descriptor || !firstPageResponse.contentSet) {
328
+ return undefined;
293
329
  }
294
- return this._requestsHandler.getPagedContentSet({ ...rpcOptions, paging: partialPageOptions });
330
+ descriptor = Descriptor.fromJSON(firstPageResponse?.descriptor);
331
+ firstPage = firstPageResponse?.contentSet;
332
+ }
333
+ // istanbul ignore if
334
+ if (!descriptor) {
335
+ return undefined;
336
+ }
337
+ descriptor = this._localizationHelper.getLocalizedContentDescriptor(descriptor);
338
+ const getPage = async (paging, requestIndex) => {
339
+ let contentSet = requestIndex === 0 ? firstPage : undefined;
340
+ contentSet ??= await this._requestsHandler.getPagedContentSet({ ...rpcOptions, paging });
341
+ let items = contentSet.items.map((x) => Item.fromJSON(x)).filter((x) => x !== undefined);
342
+ if (contentFormatter) {
343
+ items = await contentFormatter.formatContentItems(items, descriptor);
344
+ }
345
+ items = this._localizationHelper.getLocalizedContentItems(items);
346
+ return {
347
+ total: contentSet.total,
348
+ items,
349
+ };
350
+ };
351
+ const generator = new StreamedResponseGenerator({
352
+ ...requestOptions,
353
+ getBatch: getPage,
295
354
  });
296
- if (!descriptor)
355
+ return {
356
+ ...(await generator.createAsyncIteratorResponse()),
357
+ descriptor,
358
+ };
359
+ }
360
+ /** Retrieves a content descriptor, item count and async generator for the items themselves. */
361
+ async getContentIterator(requestOptions) {
362
+ this.startIModelInitialization(requestOptions.imodel);
363
+ const response = await this.getContentIteratorInternal(requestOptions);
364
+ if (!response) {
365
+ return undefined;
366
+ }
367
+ await this.ensureIModelInitialized(requestOptions.imodel);
368
+ return response;
369
+ }
370
+ /**
371
+ * Retrieves content which consists of a content descriptor and a page of records.
372
+ * @deprecated in 4.5. Use [[getContentIterator]] instead.
373
+ */
374
+ async getContent(requestOptions) {
375
+ // eslint-disable-next-line deprecation/deprecation
376
+ return (await this.getContentAndSize(requestOptions))?.content;
377
+ }
378
+ /**
379
+ * Retrieves content set size and content which consists of a content descriptor and a page of records.
380
+ * @deprecated in 4.5. Use [[getContentIterator]] instead.
381
+ */
382
+ async getContentAndSize(requestOptions) {
383
+ const response = await this.getContentIterator(requestOptions);
384
+ if (!response) {
297
385
  return undefined;
298
- const items = result.items.map((itemJson) => Item.fromJSON(itemJson)).filter((item) => (item !== undefined));
299
- const resultContent = new Content(descriptor, items);
300
- if (!requestOptions.omitFormattedValues && this._schemaContextProvider) {
301
- const koqPropertyFormatter = new KoqPropertyValueFormatter(this._schemaContextProvider(requestOptions.imodel), this._defaultFormats);
302
- const contentFormatter = new ContentFormatter(new ContentPropertyValueFormatter(koqPropertyFormatter), requestOptions.unitSystem ?? this._explicitActiveUnitSystem ?? IModelApp.quantityFormatter.activeUnitSystem);
303
- await contentFormatter.formatContent(resultContent);
304
386
  }
387
+ const { descriptor, total } = response;
388
+ const items = await collect(response.items);
305
389
  return {
306
- size: result.total,
307
- content: this._localizationHelper.getLocalizedContent(resultContent),
390
+ content: new Content(descriptor, items),
391
+ size: total,
308
392
  };
309
393
  }
310
- /** Retrieves distinct values of specific field from the content. */
311
- async getPagedDistinctValues(requestOptions) {
312
- await this.onConnection(requestOptions.imodel);
394
+ /** Returns an iterator that asynchronously polls distinct values of specific field from the content. */
395
+ async getDistinctValuesIterator(requestOptions) {
396
+ this.startIModelInitialization(requestOptions.imodel);
313
397
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
314
398
  const rpcOptions = {
315
399
  ...this.toRpcTokenOptions(options),
316
400
  descriptor: getDescriptorOverrides(options.descriptor),
317
401
  keys: stripTransientElementKeys(options.keys).toJSON(),
318
402
  };
319
- const result = await buildPagedArrayResponse(requestOptions.paging, async (partialPageOptions) => this._requestsHandler.getPagedDistinctValues({ ...rpcOptions, paging: partialPageOptions }));
403
+ const generator = new StreamedResponseGenerator({
404
+ ...requestOptions,
405
+ getBatch: async (paging) => {
406
+ const response = await this._requestsHandler.getPagedDistinctValues({ ...rpcOptions, paging });
407
+ return {
408
+ total: response.total,
409
+ // eslint-disable-next-line deprecation/deprecation
410
+ items: response.items.map((x) => this._localizationHelper.getLocalizedDisplayValueGroup(DisplayValueGroup.fromJSON(x))),
411
+ };
412
+ },
413
+ });
414
+ return generator.createAsyncIteratorResponse();
415
+ }
416
+ /**
417
+ * Retrieves distinct values of specific field from the content.
418
+ * @deprecated in 4.5. Use [[getDistinctValuesIterator]] instead.
419
+ */
420
+ async getPagedDistinctValues(requestOptions) {
421
+ const result = await this.getDistinctValuesIterator(requestOptions);
320
422
  return {
321
- ...result,
322
- // eslint-disable-next-line deprecation/deprecation
323
- items: result.items.map(DisplayValueGroup.fromJSON).map((g) => this._localizationHelper.getLocalizedDisplayValueGroup(g)),
423
+ total: result.total,
424
+ items: await collect(result.items),
324
425
  };
325
426
  }
326
427
  /**
@@ -328,11 +429,12 @@ export class PresentationManager {
328
429
  * @public
329
430
  */
330
431
  async getElementProperties(requestOptions) {
331
- await this.onConnection(requestOptions.imodel);
432
+ this.startIModelInitialization(requestOptions.imodel);
332
433
  const results = await this._requestsHandler.getElementProperties(this.toRpcTokenOptions(requestOptions));
333
434
  // istanbul ignore if
334
- if (!results)
435
+ if (!results) {
335
436
  return undefined;
437
+ }
336
438
  return this._localizationHelper.getLocalizedElementProperties(results);
337
439
  }
338
440
  /**
@@ -340,15 +442,15 @@ export class PresentationManager {
340
442
  * @public
341
443
  */
342
444
  async getContentInstanceKeys(requestOptions) {
343
- await this.onConnection(requestOptions.imodel);
445
+ this.startIModelInitialization(requestOptions.imodel);
344
446
  const options = await this.addRulesetAndVariablesToOptions(requestOptions);
345
447
  const rpcOptions = {
346
448
  ...this.toRpcTokenOptions(options),
347
449
  keys: stripTransientElementKeys(options.keys).toJSON(),
348
450
  };
349
- const props = {
350
- page: requestOptions.paging,
351
- get: async (page) => {
451
+ const generator = new StreamedResponseGenerator({
452
+ ...requestOptions,
453
+ getBatch: async (page) => {
352
454
  const keys = await this._requestsHandler.getContentInstanceKeys({ ...rpcOptions, paging: page });
353
455
  return {
354
456
  total: keys.total,
@@ -360,82 +462,72 @@ export class PresentationManager {
360
462
  }, new Array()),
361
463
  };
362
464
  },
465
+ });
466
+ const { total, items } = await generator.createAsyncIteratorResponse();
467
+ return {
468
+ total,
469
+ async *items() {
470
+ yield* items;
471
+ },
363
472
  };
364
- return createPagedGeneratorResponse(props);
365
473
  }
366
474
  /** Retrieves display label definition of specific item. */
367
475
  async getDisplayLabelDefinition(requestOptions) {
368
- await this.onConnection(requestOptions.imodel);
476
+ this.startIModelInitialization(requestOptions.imodel);
369
477
  const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
370
478
  const result = await this._requestsHandler.getDisplayLabelDefinition(rpcOptions);
371
479
  return this._localizationHelper.getLocalizedLabelDefinition(result);
372
480
  }
373
481
  /** Retrieves display label definition of specific items. */
374
- async getDisplayLabelDefinitions(requestOptions) {
375
- await this.onConnection(requestOptions.imodel);
482
+ async getDisplayLabelDefinitionsIterator(requestOptions) {
483
+ this.startIModelInitialization(requestOptions.imodel);
376
484
  const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
377
- const result = await buildPagedArrayResponse(undefined, async (partialPageOptions) => {
378
- const partialKeys = (!partialPageOptions.start) ? rpcOptions.keys : rpcOptions.keys.slice(partialPageOptions.start);
379
- return this._requestsHandler.getPagedDisplayLabelDefinitions({ ...rpcOptions, keys: partialKeys });
485
+ const generator = new StreamedResponseGenerator({
486
+ ...requestOptions,
487
+ getBatch: async (page) => {
488
+ const partialKeys = !page.start ? rpcOptions.keys : rpcOptions.keys.slice(page.start);
489
+ const result = await this._requestsHandler.getPagedDisplayLabelDefinitions({ ...rpcOptions, keys: partialKeys });
490
+ result.items = this._localizationHelper.getLocalizedLabelDefinitions(result.items);
491
+ return result;
492
+ },
380
493
  });
381
- return this._localizationHelper.getLocalizedLabelDefinitions(result.items);
494
+ return generator.createAsyncIteratorResponse();
495
+ }
496
+ /**
497
+ * Retrieves display label definition of specific items.
498
+ * @deprecated in 4.5. Use [[getDisplayLabelDefinitionsIterator]] instead.
499
+ */
500
+ async getDisplayLabelDefinitions(requestOptions) {
501
+ const { items } = await this.getDisplayLabelDefinitionsIterator(requestOptions);
502
+ return collect(items);
382
503
  }
383
504
  }
384
505
  const getDescriptorOverrides = (descriptorOrOverrides) => {
385
- if (descriptorOrOverrides instanceof Descriptor)
506
+ if (descriptorOrOverrides instanceof Descriptor) {
386
507
  return descriptorOrOverrides.createDescriptorOverrides();
508
+ }
387
509
  return descriptorOrOverrides;
388
510
  };
389
- async function createPagedGeneratorResponse(props) {
390
- let pageStart = props.page?.start ?? 0;
391
- let pageSize = props.page?.size ?? 0;
392
- let requestIndex = 0;
393
- const firstPage = await props.get({ start: pageStart, size: pageSize }, requestIndex++);
394
- return {
395
- total: firstPage.total,
396
- async *items() {
397
- let partialResult = firstPage;
398
- while (true) {
399
- for (const item of partialResult.items) {
400
- yield item;
401
- }
402
- const receivedItemsCount = partialResult.items.length;
403
- if (partialResult.total !== 0 && receivedItemsCount === 0) {
404
- if (pageStart >= partialResult.total)
405
- throw new Error(`Requested page with start index ${pageStart} is out of bounds. Total number of items: ${partialResult.total}`);
406
- throw new Error("Paged request returned non zero total count but no items");
407
- }
408
- if (pageSize !== 0 && receivedItemsCount >= pageSize || receivedItemsCount >= (partialResult.total - pageStart))
409
- break;
410
- if (pageSize !== 0)
411
- pageSize -= receivedItemsCount;
412
- pageStart += receivedItemsCount;
413
- partialResult = await props.get({ start: pageStart, size: pageSize }, requestIndex++);
414
- }
415
- },
416
- };
417
- }
418
- /** @internal */
419
- export const buildPagedArrayResponse = async (requestedPage, getter) => {
420
- const items = new Array();
421
- const gen = await createPagedGeneratorResponse({ page: requestedPage, get: getter });
422
- for await (const item of gen.items()) {
423
- items.push(item);
424
- }
425
- return { total: gen.total, items };
426
- };
427
511
  const stripTransientElementKeys = (keys) => {
428
- if (!keys.some((key) => Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME))
512
+ if (!keys.some((key) => Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME)) {
429
513
  return keys;
514
+ }
430
515
  const copy = new KeySet();
431
516
  copy.add(keys, (key) => {
432
517
  // the callback is not going to be called with EntityProps as KeySet converts them
433
518
  // to InstanceKeys, but we want to keep the EntityProps case for correctness
434
519
  // istanbul ignore next
435
- const isTransient = Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME
436
- || Key.isEntityProps(key) && key.classFullName === TRANSIENT_ELEMENT_CLASSNAME;
520
+ const isTransient = (Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME) ||
521
+ (Key.isEntityProps(key) && key.classFullName === TRANSIENT_ELEMENT_CLASSNAME);
437
522
  return !isTransient;
438
523
  });
439
524
  return copy;
440
525
  };
526
+ async function collect(iter) {
527
+ const result = new Array();
528
+ for await (const value of iter) {
529
+ result.push(value);
530
+ }
531
+ return result;
532
+ }
441
533
  //# sourceMappingURL=PresentationManager.js.map