mindoodb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/README.md +263 -0
  2. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.d.ts +5 -0
  3. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.d.ts.map +1 -0
  4. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.js +17 -0
  5. package/dist/appendonlystores/InMemoryContentAddressedStoreFactory.js.map +1 -0
  6. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts +111 -0
  7. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -0
  8. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +237 -0
  9. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -0
  10. package/dist/appendonlystores/network/HttpTransport.d.ts +78 -0
  11. package/dist/appendonlystores/network/HttpTransport.d.ts.map +1 -0
  12. package/dist/appendonlystores/network/HttpTransport.js +356 -0
  13. package/dist/appendonlystores/network/HttpTransport.js.map +1 -0
  14. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +131 -0
  15. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -0
  16. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +248 -0
  17. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js.map +1 -0
  18. package/dist/appendonlystores/network/index.d.ts +8 -0
  19. package/dist/appendonlystores/network/index.d.ts.map +1 -0
  20. package/dist/appendonlystores/network/index.js +21 -0
  21. package/dist/appendonlystores/network/index.js.map +1 -0
  22. package/dist/browser/crypto/BrowserCryptoAdapter.d.ts +14 -0
  23. package/dist/browser/crypto/BrowserCryptoAdapter.d.ts.map +1 -0
  24. package/dist/browser/crypto/BrowserCryptoAdapter.js +30 -0
  25. package/dist/browser/crypto/BrowserCryptoAdapter.js.map +1 -0
  26. package/dist/browser/index.d.ts +3 -0
  27. package/dist/browser/index.d.ts.map +1 -0
  28. package/dist/browser/index.js +26 -0
  29. package/dist/browser/index.js.map +1 -0
  30. package/dist/core/BaseMindooDB.d.ts +182 -0
  31. package/dist/core/BaseMindooDB.d.ts.map +1 -0
  32. package/dist/core/BaseMindooDB.js +1701 -0
  33. package/dist/core/BaseMindooDB.js.map +1 -0
  34. package/dist/core/BaseMindooTenant.d.ts +155 -0
  35. package/dist/core/BaseMindooTenant.d.ts.map +1 -0
  36. package/dist/core/BaseMindooTenant.js +673 -0
  37. package/dist/core/BaseMindooTenant.js.map +1 -0
  38. package/dist/core/BaseMindooTenantDirectory.d.ts +99 -0
  39. package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -0
  40. package/dist/core/BaseMindooTenantDirectory.js +776 -0
  41. package/dist/core/BaseMindooTenantDirectory.js.map +1 -0
  42. package/dist/core/BaseMindooTenantFactory.d.ts +91 -0
  43. package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -0
  44. package/dist/core/BaseMindooTenantFactory.js +297 -0
  45. package/dist/core/BaseMindooTenantFactory.js.map +1 -0
  46. package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts +111 -0
  47. package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts.map +1 -0
  48. package/dist/core/appendonlystores/InMemoryContentAddressedStore.js +293 -0
  49. package/dist/core/appendonlystores/InMemoryContentAddressedStore.js.map +1 -0
  50. package/dist/core/appendonlystores/network/AuthenticationService.d.ts +78 -0
  51. package/dist/core/appendonlystores/network/AuthenticationService.d.ts.map +1 -0
  52. package/dist/core/appendonlystores/network/AuthenticationService.js +297 -0
  53. package/dist/core/appendonlystores/network/AuthenticationService.js.map +1 -0
  54. package/dist/core/appendonlystores/network/NetworkTransport.d.ts +174 -0
  55. package/dist/core/appendonlystores/network/NetworkTransport.d.ts.map +1 -0
  56. package/dist/core/appendonlystores/network/NetworkTransport.js +3 -0
  57. package/dist/core/appendonlystores/network/NetworkTransport.js.map +1 -0
  58. package/dist/core/appendonlystores/network/types.d.ts +135 -0
  59. package/dist/core/appendonlystores/network/types.d.ts.map +1 -0
  60. package/dist/core/appendonlystores/network/types.js +35 -0
  61. package/dist/core/appendonlystores/network/types.js.map +1 -0
  62. package/dist/core/appendonlystores/types.d.ts +157 -0
  63. package/dist/core/appendonlystores/types.d.ts.map +1 -0
  64. package/dist/core/appendonlystores/types.js +3 -0
  65. package/dist/core/appendonlystores/types.js.map +1 -0
  66. package/dist/core/crypto/CryptoAdapter.d.ts +19 -0
  67. package/dist/core/crypto/CryptoAdapter.d.ts.map +1 -0
  68. package/dist/core/crypto/CryptoAdapter.js +3 -0
  69. package/dist/core/crypto/CryptoAdapter.js.map +1 -0
  70. package/dist/core/crypto/MindooDocSigner.d.ts +106 -0
  71. package/dist/core/crypto/MindooDocSigner.d.ts.map +1 -0
  72. package/dist/core/crypto/MindooDocSigner.js +192 -0
  73. package/dist/core/crypto/MindooDocSigner.js.map +1 -0
  74. package/dist/core/crypto/RSAEncryption.d.ts +62 -0
  75. package/dist/core/crypto/RSAEncryption.d.ts.map +1 -0
  76. package/dist/core/crypto/RSAEncryption.js +167 -0
  77. package/dist/core/crypto/RSAEncryption.js.map +1 -0
  78. package/dist/core/errors.d.ts +10 -0
  79. package/dist/core/errors.d.ts.map +1 -0
  80. package/dist/core/errors.js +17 -0
  81. package/dist/core/errors.js.map +1 -0
  82. package/dist/core/index.d.ts +14 -0
  83. package/dist/core/index.d.ts.map +1 -0
  84. package/dist/core/index.js +53 -0
  85. package/dist/core/index.js.map +1 -0
  86. package/dist/core/indexing/virtualviews/IViewEntryAccessCheck.d.ts +33 -0
  87. package/dist/core/indexing/virtualviews/IViewEntryAccessCheck.d.ts.map +1 -0
  88. package/dist/core/indexing/virtualviews/IViewEntryAccessCheck.js +27 -0
  89. package/dist/core/indexing/virtualviews/IViewEntryAccessCheck.js.map +1 -0
  90. package/dist/core/indexing/virtualviews/IVirtualViewDataProvider.d.ts +31 -0
  91. package/dist/core/indexing/virtualviews/IVirtualViewDataProvider.d.ts.map +1 -0
  92. package/dist/core/indexing/virtualviews/IVirtualViewDataProvider.js +3 -0
  93. package/dist/core/indexing/virtualviews/IVirtualViewDataProvider.js.map +1 -0
  94. package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.d.ts +52 -0
  95. package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.d.ts.map +1 -0
  96. package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js +106 -0
  97. package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js.map +1 -0
  98. package/dist/core/indexing/virtualviews/ViewEntrySortKey.d.ts +44 -0
  99. package/dist/core/indexing/virtualviews/ViewEntrySortKey.d.ts.map +1 -0
  100. package/dist/core/indexing/virtualviews/ViewEntrySortKey.js +107 -0
  101. package/dist/core/indexing/virtualviews/ViewEntrySortKey.js.map +1 -0
  102. package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.d.ts +28 -0
  103. package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.d.ts.map +1 -0
  104. package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.js +133 -0
  105. package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.js.map +1 -0
  106. package/dist/core/indexing/virtualviews/VirtualView.d.ts +109 -0
  107. package/dist/core/indexing/virtualviews/VirtualView.d.ts.map +1 -0
  108. package/dist/core/indexing/virtualviews/VirtualView.js +504 -0
  109. package/dist/core/indexing/virtualviews/VirtualView.js.map +1 -0
  110. package/dist/core/indexing/virtualviews/VirtualViewColumn.d.ts +59 -0
  111. package/dist/core/indexing/virtualviews/VirtualViewColumn.d.ts.map +1 -0
  112. package/dist/core/indexing/virtualviews/VirtualViewColumn.js +70 -0
  113. package/dist/core/indexing/virtualviews/VirtualViewColumn.js.map +1 -0
  114. package/dist/core/indexing/virtualviews/VirtualViewDataChange.d.ts +49 -0
  115. package/dist/core/indexing/virtualviews/VirtualViewDataChange.d.ts.map +1 -0
  116. package/dist/core/indexing/virtualviews/VirtualViewDataChange.js +69 -0
  117. package/dist/core/indexing/virtualviews/VirtualViewDataChange.js.map +1 -0
  118. package/dist/core/indexing/virtualviews/VirtualViewEntryData.d.ts +121 -0
  119. package/dist/core/indexing/virtualviews/VirtualViewEntryData.d.ts.map +1 -0
  120. package/dist/core/indexing/virtualviews/VirtualViewEntryData.js +365 -0
  121. package/dist/core/indexing/virtualviews/VirtualViewEntryData.js.map +1 -0
  122. package/dist/core/indexing/virtualviews/VirtualViewFactory.d.ts +131 -0
  123. package/dist/core/indexing/virtualviews/VirtualViewFactory.d.ts.map +1 -0
  124. package/dist/core/indexing/virtualviews/VirtualViewFactory.js +236 -0
  125. package/dist/core/indexing/virtualviews/VirtualViewFactory.js.map +1 -0
  126. package/dist/core/indexing/virtualviews/VirtualViewNavigator.d.ts +330 -0
  127. package/dist/core/indexing/virtualviews/VirtualViewNavigator.d.ts.map +1 -0
  128. package/dist/core/indexing/virtualviews/VirtualViewNavigator.js +1010 -0
  129. package/dist/core/indexing/virtualviews/VirtualViewNavigator.js.map +1 -0
  130. package/dist/core/indexing/virtualviews/index.d.ts +53 -0
  131. package/dist/core/indexing/virtualviews/index.d.ts.map +1 -0
  132. package/dist/core/indexing/virtualviews/index.js +89 -0
  133. package/dist/core/indexing/virtualviews/index.js.map +1 -0
  134. package/dist/core/indexing/virtualviews/types.d.ts +115 -0
  135. package/dist/core/indexing/virtualviews/types.d.ts.map +1 -0
  136. package/dist/core/indexing/virtualviews/types.js +175 -0
  137. package/dist/core/indexing/virtualviews/types.js.map +1 -0
  138. package/dist/core/keys/KeyBag.d.ts +122 -0
  139. package/dist/core/keys/KeyBag.d.ts.map +1 -0
  140. package/dist/core/keys/KeyBag.js +401 -0
  141. package/dist/core/keys/KeyBag.js.map +1 -0
  142. package/dist/core/types.d.ts +1004 -0
  143. package/dist/core/types.d.ts.map +1 -0
  144. package/dist/core/types.js +10 -0
  145. package/dist/core/types.js.map +1 -0
  146. package/dist/core/userid/index.d.ts +53 -0
  147. package/dist/core/userid/index.d.ts.map +1 -0
  148. package/dist/core/userid/index.js +3 -0
  149. package/dist/core/userid/index.js.map +1 -0
  150. package/dist/core/utils/idGeneration.d.ts +109 -0
  151. package/dist/core/utils/idGeneration.d.ts.map +1 -0
  152. package/dist/core/utils/idGeneration.js +182 -0
  153. package/dist/core/utils/idGeneration.js.map +1 -0
  154. package/dist/core/utils/index.d.ts +5 -0
  155. package/dist/core/utils/index.d.ts.map +1 -0
  156. package/dist/core/utils/index.js +19 -0
  157. package/dist/core/utils/index.js.map +1 -0
  158. package/dist/index.d.ts +7 -0
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +40 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/node/crypto/NodeCryptoAdapter.d.ts +16 -0
  163. package/dist/node/crypto/NodeCryptoAdapter.d.ts.map +1 -0
  164. package/dist/node/crypto/NodeCryptoAdapter.js +53 -0
  165. package/dist/node/crypto/NodeCryptoAdapter.js.map +1 -0
  166. package/dist/node/index.d.ts +3 -0
  167. package/dist/node/index.d.ts.map +1 -0
  168. package/dist/node/index.js +26 -0
  169. package/dist/node/index.js.map +1 -0
  170. package/package.json +58 -0
@@ -0,0 +1,1010 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VirtualViewNavigator = void 0;
4
+ const types_1 = require("./types");
5
+ /**
6
+ * Navigator for traversing a VirtualView tree structure.
7
+ * Handles expanded/collapsed states, selection, and access control.
8
+ */
9
+ class VirtualViewNavigator {
10
+ constructor(view, topEntry, withCategories, withDocuments, accessCheck = null, dontShowEmptyCategories = false) {
11
+ /** Stack of traversal states for navigation */
12
+ this.currentEntryStack = [];
13
+ /** Selection state - if selectAll is true, this is a deselection list */
14
+ this.selectedOrDeselectedEntries = new Set();
15
+ this.selectAll = false;
16
+ /** Expansion state - if expandAllByDefault is true, this is a collapse list */
17
+ this.expandedOrCollapsedEntries = new Set();
18
+ this.expandAllByDefault = false;
19
+ this.expandLevel = 0;
20
+ this.view = view;
21
+ this.topEntry = topEntry;
22
+ this.withCategories = withCategories === types_1.WithCategories.YES;
23
+ this.withDocuments = withDocuments === types_1.WithDocuments.YES;
24
+ this.accessCheck = accessCheck;
25
+ this.dontShowEmptyCategories = dontShowEmptyCategories;
26
+ if (!this.withCategories && !this.withDocuments) {
27
+ throw new Error("Navigator must include categories, documents, or both");
28
+ }
29
+ // Initialize traversal at top entry
30
+ this.initializeTraversal();
31
+ }
32
+ initializeTraversal() {
33
+ this.currentEntryStack = [];
34
+ if (this.topEntry) {
35
+ this.currentEntryStack.push(this.createTraversalInfo(this.topEntry));
36
+ }
37
+ }
38
+ createTraversalInfo(parentEntry) {
39
+ // Always get all child entries for traversal purposes
40
+ // Filtering happens when we return entries (getCurrentEntry)
41
+ const childEntries = parentEntry.getChildEntries();
42
+ return {
43
+ parentEntry,
44
+ withCategories: this.withCategories,
45
+ withDocuments: this.withDocuments,
46
+ childEntries,
47
+ currentIndex: -1, // Before first entry
48
+ };
49
+ }
50
+ getView() {
51
+ return this.view;
52
+ }
53
+ isDontShowEmptyCategories() {
54
+ return this.dontShowEmptyCategories;
55
+ }
56
+ /**
57
+ * Set a new root for navigation (restrict to subtree)
58
+ */
59
+ setRoot(newRoot) {
60
+ this.topEntry = newRoot;
61
+ this.initializeTraversal();
62
+ return this;
63
+ }
64
+ // ===== Navigation Methods =====
65
+ /**
66
+ * Get the current entry at the cursor position
67
+ */
68
+ getCurrentEntry() {
69
+ if (this.currentEntryStack.length === 0) {
70
+ return null;
71
+ }
72
+ const info = this.currentEntryStack[this.currentEntryStack.length - 1];
73
+ if (info.currentIndex < 0 || info.currentIndex >= info.childEntries.length) {
74
+ return null;
75
+ }
76
+ const entry = info.childEntries[info.currentIndex];
77
+ // Check visibility
78
+ if (!this.isVisible(entry)) {
79
+ return null;
80
+ }
81
+ // Filter by type
82
+ if (entry.isCategory() && !this.withCategories) {
83
+ return null;
84
+ }
85
+ if (entry.isDocument() && !this.withDocuments) {
86
+ return null;
87
+ }
88
+ return entry;
89
+ }
90
+ /**
91
+ * Move to the first entry
92
+ */
93
+ gotoFirst() {
94
+ // Reset to top level
95
+ while (this.currentEntryStack.length > 1) {
96
+ this.currentEntryStack.pop();
97
+ }
98
+ const info = this.currentEntryStack[0];
99
+ if (!info || info.childEntries.length === 0) {
100
+ return false;
101
+ }
102
+ // Find first visible entry (raw visibility)
103
+ for (let i = 0; i < info.childEntries.length; i++) {
104
+ info.currentIndex = i;
105
+ if (this.isVisibleRaw(info.childEntries[i])) {
106
+ // Check if this matches our type filter
107
+ const entry = this.getCurrentEntry();
108
+ if (entry) {
109
+ return true;
110
+ }
111
+ // Entry doesn't match filter, continue to navigate into it or past it
112
+ return this.gotoNext();
113
+ }
114
+ }
115
+ return false;
116
+ }
117
+ /**
118
+ * Move to the last entry (taking expansion into account)
119
+ */
120
+ gotoLast() {
121
+ // Reset to top level
122
+ while (this.currentEntryStack.length > 1) {
123
+ this.currentEntryStack.pop();
124
+ }
125
+ const info = this.currentEntryStack[0];
126
+ if (!info || info.childEntries.length === 0) {
127
+ return false;
128
+ }
129
+ // Find last visible entry
130
+ for (let i = info.childEntries.length - 1; i >= 0; i--) {
131
+ info.currentIndex = i;
132
+ if (this.isVisible(info.childEntries[i])) {
133
+ // Navigate to deepest expanded descendant
134
+ this.gotoDeepestExpandedDescendant(info.childEntries[i]);
135
+ return true;
136
+ }
137
+ }
138
+ return false;
139
+ }
140
+ /**
141
+ * Move to the next entry (respecting expand states)
142
+ */
143
+ gotoNext() {
144
+ const currEntry = this.getCurrentEntryRaw();
145
+ if (!currEntry) {
146
+ // No current entry - try to find one by moving through the tree
147
+ if (this.gotoNextSibling()) {
148
+ // Check if this entry should be returned
149
+ const entry = this.getCurrentEntry();
150
+ if (entry)
151
+ return true;
152
+ // Keep searching
153
+ return this.gotoNext();
154
+ }
155
+ return false;
156
+ }
157
+ // If expanded and has children, go to first child
158
+ if (this.isExpanded(currEntry) && currEntry.getChildCount() > 0) {
159
+ const childInfo = this.createTraversalInfo(currEntry);
160
+ if (childInfo.childEntries.length > 0) {
161
+ childInfo.currentIndex = 0;
162
+ // Find first visible child (visibility check only, not type filter)
163
+ while (childInfo.currentIndex < childInfo.childEntries.length &&
164
+ !this.isVisibleRaw(childInfo.childEntries[childInfo.currentIndex])) {
165
+ childInfo.currentIndex++;
166
+ }
167
+ if (childInfo.currentIndex < childInfo.childEntries.length) {
168
+ this.currentEntryStack.push(childInfo);
169
+ // Check if this entry matches our filter
170
+ const entry = this.getCurrentEntry();
171
+ if (entry) {
172
+ return true;
173
+ }
174
+ // Entry doesn't match filter (e.g., it's a category but we want documents)
175
+ // Continue navigating
176
+ return this.gotoNext();
177
+ }
178
+ }
179
+ }
180
+ // Try next sibling
181
+ if (this.gotoNextSiblingRaw()) {
182
+ // Check if this entry matches our filter
183
+ const entry = this.getCurrentEntry();
184
+ if (entry) {
185
+ return true;
186
+ }
187
+ // Keep searching
188
+ return this.gotoNext();
189
+ }
190
+ // Go up and try next sibling of parent
191
+ while (this.gotoParent()) {
192
+ if (this.gotoNextSiblingRaw()) {
193
+ // Check if this entry matches our filter
194
+ const entry = this.getCurrentEntry();
195
+ if (entry) {
196
+ return true;
197
+ }
198
+ // Keep searching
199
+ return this.gotoNext();
200
+ }
201
+ }
202
+ return false;
203
+ }
204
+ /**
205
+ * Get the current entry without type filtering (for internal navigation)
206
+ */
207
+ getCurrentEntryRaw() {
208
+ if (this.currentEntryStack.length === 0) {
209
+ return null;
210
+ }
211
+ const info = this.currentEntryStack[this.currentEntryStack.length - 1];
212
+ if (info.currentIndex < 0 || info.currentIndex >= info.childEntries.length) {
213
+ return null;
214
+ }
215
+ return info.childEntries[info.currentIndex];
216
+ }
217
+ /**
218
+ * Check visibility without type filtering
219
+ */
220
+ isVisibleRaw(entry) {
221
+ // Check access control
222
+ if (this.accessCheck && !this.accessCheck.isVisible(this, entry)) {
223
+ return false;
224
+ }
225
+ return true;
226
+ }
227
+ /**
228
+ * Move to next sibling without checking type filter
229
+ */
230
+ gotoNextSiblingRaw() {
231
+ if (this.currentEntryStack.length === 0) {
232
+ return false;
233
+ }
234
+ const info = this.currentEntryStack[this.currentEntryStack.length - 1];
235
+ // Find next visible entry
236
+ for (let i = info.currentIndex + 1; i < info.childEntries.length; i++) {
237
+ if (this.isVisibleRaw(info.childEntries[i])) {
238
+ info.currentIndex = i;
239
+ return true;
240
+ }
241
+ }
242
+ return false;
243
+ }
244
+ /**
245
+ * Move to the previous entry (respecting expand states)
246
+ */
247
+ gotoPrev() {
248
+ const currEntry = this.getCurrentEntry();
249
+ if (!currEntry) {
250
+ return false;
251
+ }
252
+ // Try previous sibling
253
+ if (this.gotoPrevSibling()) {
254
+ // Navigate to deepest expanded descendant of prev sibling
255
+ const prevEntry = this.getCurrentEntry();
256
+ if (prevEntry) {
257
+ this.gotoDeepestExpandedDescendant(prevEntry);
258
+ }
259
+ return true;
260
+ }
261
+ // Go up to parent
262
+ return this.gotoParent();
263
+ }
264
+ /**
265
+ * Move to the next sibling
266
+ */
267
+ gotoNextSibling() {
268
+ if (this.currentEntryStack.length === 0) {
269
+ return false;
270
+ }
271
+ const info = this.currentEntryStack[this.currentEntryStack.length - 1];
272
+ // Find next visible entry
273
+ for (let i = info.currentIndex + 1; i < info.childEntries.length; i++) {
274
+ if (this.isVisible(info.childEntries[i])) {
275
+ info.currentIndex = i;
276
+ return true;
277
+ }
278
+ }
279
+ return false;
280
+ }
281
+ /**
282
+ * Move to the previous sibling
283
+ */
284
+ gotoPrevSibling() {
285
+ if (this.currentEntryStack.length === 0) {
286
+ return false;
287
+ }
288
+ const info = this.currentEntryStack[this.currentEntryStack.length - 1];
289
+ // Find previous visible entry
290
+ for (let i = info.currentIndex - 1; i >= 0; i--) {
291
+ if (this.isVisible(info.childEntries[i])) {
292
+ info.currentIndex = i;
293
+ return true;
294
+ }
295
+ }
296
+ return false;
297
+ }
298
+ /**
299
+ * Move to the parent entry
300
+ */
301
+ gotoParent() {
302
+ if (this.currentEntryStack.length > 1) {
303
+ this.currentEntryStack.pop();
304
+ return true;
305
+ }
306
+ return false;
307
+ }
308
+ /**
309
+ * Move to the first child of current entry
310
+ */
311
+ gotoFirstChild() {
312
+ const currEntry = this.getCurrentEntry();
313
+ if (!currEntry) {
314
+ return false;
315
+ }
316
+ const childInfo = this.createTraversalInfo(currEntry);
317
+ if (childInfo.childEntries.length === 0) {
318
+ return false;
319
+ }
320
+ // Find first visible child
321
+ for (let i = 0; i < childInfo.childEntries.length; i++) {
322
+ if (this.isVisible(childInfo.childEntries[i])) {
323
+ childInfo.currentIndex = i;
324
+ this.currentEntryStack.push(childInfo);
325
+ return true;
326
+ }
327
+ }
328
+ return false;
329
+ }
330
+ /**
331
+ * Move to the last child of current entry
332
+ */
333
+ gotoLastChild() {
334
+ const currEntry = this.getCurrentEntry();
335
+ if (!currEntry) {
336
+ return false;
337
+ }
338
+ const childInfo = this.createTraversalInfo(currEntry);
339
+ if (childInfo.childEntries.length === 0) {
340
+ return false;
341
+ }
342
+ // Find last visible child
343
+ for (let i = childInfo.childEntries.length - 1; i >= 0; i--) {
344
+ if (this.isVisible(childInfo.childEntries[i])) {
345
+ childInfo.currentIndex = i;
346
+ this.currentEntryStack.push(childInfo);
347
+ return true;
348
+ }
349
+ }
350
+ return false;
351
+ }
352
+ gotoDeepestExpandedDescendant(entry) {
353
+ if (entry.getChildCount() > 0 && this.isExpanded(entry)) {
354
+ const childInfo = this.createTraversalInfo(entry);
355
+ // Find last visible child
356
+ for (let i = childInfo.childEntries.length - 1; i >= 0; i--) {
357
+ if (this.isVisible(childInfo.childEntries[i])) {
358
+ childInfo.currentIndex = i;
359
+ this.currentEntryStack.push(childInfo);
360
+ this.gotoDeepestExpandedDescendant(childInfo.childEntries[i]);
361
+ return;
362
+ }
363
+ }
364
+ }
365
+ }
366
+ /**
367
+ * Move to a specific position (e.g., "1.2.3")
368
+ */
369
+ gotoPos(posStr) {
370
+ const pos = posStr.split(".").map(p => parseInt(p, 10));
371
+ return this.gotoPosArray(pos);
372
+ }
373
+ /**
374
+ * Move to a specific position array (e.g., [1, 2, 3])
375
+ */
376
+ gotoPosArray(pos) {
377
+ // Reset to top level
378
+ this.initializeTraversal();
379
+ let currentInfo = this.currentEntryStack[0];
380
+ if (!currentInfo) {
381
+ return false;
382
+ }
383
+ for (let i = 0; i < pos.length; i++) {
384
+ const targetSiblingIndex = pos[i];
385
+ // Find entry with matching sibling index
386
+ let found = false;
387
+ for (let j = 0; j < currentInfo.childEntries.length; j++) {
388
+ const entry = currentInfo.childEntries[j];
389
+ if (entry.getSiblingIndex() === targetSiblingIndex && this.isVisible(entry)) {
390
+ currentInfo.currentIndex = j;
391
+ found = true;
392
+ // If more levels to go, push new traversal info
393
+ if (i < pos.length - 1) {
394
+ const nextInfo = this.createTraversalInfo(entry);
395
+ this.currentEntryStack.push(nextInfo);
396
+ currentInfo = nextInfo;
397
+ }
398
+ break;
399
+ }
400
+ }
401
+ if (!found) {
402
+ return false;
403
+ }
404
+ }
405
+ return true;
406
+ }
407
+ /**
408
+ * Get the entry at a specific position without moving the cursor
409
+ *
410
+ * @param posStr Position string e.g. "1.2.3"
411
+ * @returns The entry at the position or null if not found
412
+ */
413
+ getPos(posStr) {
414
+ const pos = posStr.split(".").map(p => parseInt(p, 10));
415
+ return this.getPosArray(pos);
416
+ }
417
+ /**
418
+ * Get the entry at a specific position array without moving the cursor
419
+ *
420
+ * @param pos Position array e.g. [1, 2, 3]
421
+ * @returns The entry at the position or null if not found
422
+ */
423
+ getPosArray(pos) {
424
+ // Save current state
425
+ const savedStack = this.currentEntryStack.map(info => ({
426
+ ...info,
427
+ childEntries: info.childEntries,
428
+ }));
429
+ // Navigate to position
430
+ const found = this.gotoPosArray(pos);
431
+ const entry = found ? this.getCurrentEntry() : null;
432
+ // Restore state
433
+ this.currentEntryStack = savedStack;
434
+ return entry;
435
+ }
436
+ // ===== Category Finding Methods =====
437
+ /**
438
+ * Find a category entry by path string (e.g., "Category1\\Category1.1")
439
+ * Navigates through the category tree from the top entry.
440
+ *
441
+ * @param category Category path with backslash separators
442
+ * @returns The category entry or null if not found
443
+ */
444
+ findCategoryEntry(category) {
445
+ const categoryParts = category.split("\\");
446
+ return this.findCategoryEntryByParts(categoryParts);
447
+ }
448
+ /**
449
+ * Find a category entry by array of category parts
450
+ * Navigates through the category tree from the top entry.
451
+ *
452
+ * @param categoryParts Array of category values e.g. ["Category1", "Category1.1"]
453
+ * @returns The category entry or null if not found
454
+ */
455
+ findCategoryEntryByParts(categoryParts) {
456
+ let currentEntry = this.topEntry;
457
+ for (const part of categoryParts) {
458
+ if (!currentEntry) {
459
+ return null;
460
+ }
461
+ // Find matching subcategory
462
+ const matchingCategory = this.childCategoriesByKey(currentEntry, String(part), true, false)
463
+ .find(() => true); // Get first match
464
+ if (!matchingCategory) {
465
+ return null;
466
+ }
467
+ currentEntry = matchingCategory;
468
+ }
469
+ return currentEntry;
470
+ }
471
+ // ===== Iteration Methods =====
472
+ /**
473
+ * Iterate forward through entries
474
+ */
475
+ async *entriesForward(selectedOnly = types_1.SelectedOnly.NO) {
476
+ if (!this.gotoFirst()) {
477
+ return;
478
+ }
479
+ do {
480
+ const entry = this.getCurrentEntry();
481
+ if (entry) {
482
+ if (selectedOnly === types_1.SelectedOnly.NO || this.isSelected(entry.origin, entry.docId)) {
483
+ yield entry;
484
+ }
485
+ }
486
+ } while (selectedOnly === types_1.SelectedOnly.YES ? this.gotoNextSelected() : this.gotoNext());
487
+ }
488
+ /**
489
+ * Iterate forward through entries starting from a specific position
490
+ *
491
+ * @param startPos Starting position string e.g. "1.2.3"
492
+ * @param selectedOnly Whether to only yield selected entries
493
+ */
494
+ async *entriesForwardFromPosition(startPos, selectedOnly = types_1.SelectedOnly.NO) {
495
+ if (!this.gotoPos(startPos)) {
496
+ return;
497
+ }
498
+ do {
499
+ const entry = this.getCurrentEntry();
500
+ if (entry) {
501
+ if (selectedOnly === types_1.SelectedOnly.NO || this.isSelected(entry.origin, entry.docId)) {
502
+ yield entry;
503
+ }
504
+ }
505
+ } while (selectedOnly === types_1.SelectedOnly.YES ? this.gotoNextSelected() : this.gotoNext());
506
+ }
507
+ /**
508
+ * Iterate backward through entries
509
+ */
510
+ async *entriesBackward(selectedOnly = types_1.SelectedOnly.NO) {
511
+ if (!this.gotoLast()) {
512
+ return;
513
+ }
514
+ do {
515
+ const entry = this.getCurrentEntry();
516
+ if (entry) {
517
+ if (selectedOnly === types_1.SelectedOnly.NO || this.isSelected(entry.origin, entry.docId)) {
518
+ yield entry;
519
+ }
520
+ }
521
+ } while (selectedOnly === types_1.SelectedOnly.YES ? this.gotoPrevSelected() : this.gotoPrev());
522
+ }
523
+ /**
524
+ * Move to next selected entry
525
+ */
526
+ gotoNextSelected() {
527
+ while (this.gotoNext()) {
528
+ const entry = this.getCurrentEntry();
529
+ if (entry && this.isSelected(entry.origin, entry.docId)) {
530
+ return true;
531
+ }
532
+ }
533
+ return false;
534
+ }
535
+ /**
536
+ * Move to previous selected entry
537
+ */
538
+ gotoPrevSelected() {
539
+ while (this.gotoPrev()) {
540
+ const entry = this.getCurrentEntry();
541
+ if (entry && this.isSelected(entry.origin, entry.docId)) {
542
+ return true;
543
+ }
544
+ }
545
+ return false;
546
+ }
547
+ // ===== Visibility Check =====
548
+ isVisible(entry) {
549
+ // Check access control
550
+ if (this.accessCheck && !this.accessCheck.isVisible(this, entry)) {
551
+ return false;
552
+ }
553
+ // Check empty categories
554
+ if (this.dontShowEmptyCategories && entry.isCategory()) {
555
+ if (entry.getDescendantDocumentCount() === 0) {
556
+ return false;
557
+ }
558
+ }
559
+ return true;
560
+ }
561
+ // ===== Selection Methods =====
562
+ /**
563
+ * Select an entry
564
+ */
565
+ select(origin, docId, selectParentCategories = false) {
566
+ const key = (0, types_1.scopedDocIdKey)((0, types_1.createScopedDocId)(origin, docId));
567
+ if (this.selectAll) {
568
+ this.selectedOrDeselectedEntries.delete(key);
569
+ }
570
+ else {
571
+ this.selectedOrDeselectedEntries.add(key);
572
+ }
573
+ if (selectParentCategories) {
574
+ const entries = this.view.getEntries(origin, docId);
575
+ for (const entry of entries) {
576
+ let parent = entry.getParent();
577
+ while (parent && !parent.isRoot()) {
578
+ const parentKey = (0, types_1.scopedDocIdKey)((0, types_1.createScopedDocId)(parent.origin, parent.docId));
579
+ if (this.selectAll) {
580
+ this.selectedOrDeselectedEntries.delete(parentKey);
581
+ }
582
+ else {
583
+ this.selectedOrDeselectedEntries.add(parentKey);
584
+ }
585
+ parent = parent.getParent();
586
+ }
587
+ }
588
+ }
589
+ return this;
590
+ }
591
+ /**
592
+ * Deselect an entry
593
+ */
594
+ deselect(origin, docId) {
595
+ const key = (0, types_1.scopedDocIdKey)((0, types_1.createScopedDocId)(origin, docId));
596
+ if (this.selectAll) {
597
+ this.selectedOrDeselectedEntries.add(key);
598
+ }
599
+ else {
600
+ this.selectedOrDeselectedEntries.delete(key);
601
+ }
602
+ return this;
603
+ }
604
+ /**
605
+ * Select all entries
606
+ */
607
+ selectAllEntries() {
608
+ this.selectedOrDeselectedEntries.clear();
609
+ this.selectAll = true;
610
+ return this;
611
+ }
612
+ /**
613
+ * Deselect all entries
614
+ */
615
+ deselectAllEntries() {
616
+ this.selectedOrDeselectedEntries.clear();
617
+ this.selectAll = false;
618
+ return this;
619
+ }
620
+ /**
621
+ * Check if an entry is selected
622
+ */
623
+ isSelected(origin, docId) {
624
+ const key = (0, types_1.scopedDocIdKey)((0, types_1.createScopedDocId)(origin, docId));
625
+ if (this.selectAll) {
626
+ return !this.selectedOrDeselectedEntries.has(key);
627
+ }
628
+ else {
629
+ return this.selectedOrDeselectedEntries.has(key);
630
+ }
631
+ }
632
+ isSelectAllByDefault() {
633
+ return this.selectAll;
634
+ }
635
+ /**
636
+ * Returns whether all entries are deselected by default
637
+ */
638
+ isDeselectAllByDefault() {
639
+ return !this.selectAll;
640
+ }
641
+ // ===== Expand/Collapse Methods =====
642
+ /**
643
+ * Expand an entry
644
+ */
645
+ expand(origin, docId) {
646
+ const key = (0, types_1.scopedDocIdKey)((0, types_1.createScopedDocId)(origin, docId));
647
+ if (!this.expandAllByDefault) {
648
+ this.expandedOrCollapsedEntries.add(key);
649
+ }
650
+ else {
651
+ this.expandedOrCollapsedEntries.delete(key);
652
+ }
653
+ return this;
654
+ }
655
+ /**
656
+ * Collapse an entry
657
+ */
658
+ collapse(origin, docId) {
659
+ const key = (0, types_1.scopedDocIdKey)((0, types_1.createScopedDocId)(origin, docId));
660
+ if (this.expandAllByDefault) {
661
+ this.expandedOrCollapsedEntries.add(key);
662
+ }
663
+ else {
664
+ this.expandedOrCollapsedEntries.delete(key);
665
+ }
666
+ return this;
667
+ }
668
+ /**
669
+ * Expand by position string
670
+ */
671
+ expandPos(posStr) {
672
+ const entry = this.getEntryAtPos(posStr);
673
+ if (entry) {
674
+ this.expand(entry.origin, entry.docId);
675
+ }
676
+ return this;
677
+ }
678
+ /**
679
+ * Collapse by position string
680
+ */
681
+ collapsePos(posStr) {
682
+ const entry = this.getEntryAtPos(posStr);
683
+ if (entry) {
684
+ this.collapse(entry.origin, entry.docId);
685
+ }
686
+ return this;
687
+ }
688
+ /**
689
+ * Expand by position array
690
+ *
691
+ * @param pos Position array e.g. [1, 2, 3]
692
+ */
693
+ expandPosArray(pos) {
694
+ const entry = this.getPosArray(pos);
695
+ if (entry) {
696
+ this.expand(entry.origin, entry.docId);
697
+ }
698
+ return this;
699
+ }
700
+ /**
701
+ * Collapse by position array
702
+ *
703
+ * @param pos Position array e.g. [1, 2, 3]
704
+ */
705
+ collapsePosArray(pos) {
706
+ const entry = this.getPosArray(pos);
707
+ if (entry) {
708
+ this.collapse(entry.origin, entry.docId);
709
+ }
710
+ return this;
711
+ }
712
+ getEntryAtPos(posStr) {
713
+ // Save current position
714
+ const savedStack = [...this.currentEntryStack];
715
+ const found = this.gotoPos(posStr);
716
+ const entry = found ? this.getCurrentEntry() : null;
717
+ // Restore position
718
+ this.currentEntryStack = savedStack;
719
+ return entry;
720
+ }
721
+ /**
722
+ * Collapse all entries
723
+ */
724
+ collapseAll() {
725
+ this.expandedOrCollapsedEntries.clear();
726
+ this.expandAllByDefault = false;
727
+ return this;
728
+ }
729
+ /**
730
+ * Expand all entries
731
+ */
732
+ expandAll() {
733
+ this.expandedOrCollapsedEntries.clear();
734
+ this.expandAllByDefault = true;
735
+ return this;
736
+ }
737
+ /**
738
+ * Expand entries up to a specific level
739
+ */
740
+ expandToLevel(level) {
741
+ this.expandLevel = level;
742
+ return this;
743
+ }
744
+ /**
745
+ * Check if an entry is expanded
746
+ */
747
+ isExpanded(entry) {
748
+ // Root is always expanded
749
+ if (entry.isRoot()) {
750
+ return true;
751
+ }
752
+ // Check level-based expansion
753
+ if (this.expandLevel > 0 && entry.getLevel() <= this.expandLevel) {
754
+ return true;
755
+ }
756
+ return this.isExpandedByDocId(entry.origin, entry.docId);
757
+ }
758
+ /**
759
+ * Check if an entry is expanded by origin and docId
760
+ * Does not check expandLevel - only checks the expand/collapse state
761
+ *
762
+ * @param origin Origin of the entry
763
+ * @param docId Document ID of the entry
764
+ * @returns true if expanded
765
+ */
766
+ isExpandedByDocId(origin, docId) {
767
+ const key = (0, types_1.scopedDocIdKey)((0, types_1.createScopedDocId)(origin, docId));
768
+ // Check if this is the root
769
+ const root = this.view.getRoot();
770
+ if (root.docId === docId && root.origin === origin) {
771
+ return true;
772
+ }
773
+ if (this.expandAllByDefault) {
774
+ return !this.expandedOrCollapsedEntries.has(key);
775
+ }
776
+ else {
777
+ return this.expandedOrCollapsedEntries.has(key);
778
+ }
779
+ }
780
+ isExpandAllByDefault() {
781
+ return this.expandAllByDefault;
782
+ }
783
+ isCollapseAllByDefault() {
784
+ return !this.expandAllByDefault;
785
+ }
786
+ getExpandLevel() {
787
+ return this.expandLevel;
788
+ }
789
+ // ===== State Getters/Setters =====
790
+ getSelectedOrDeselectedEntries() {
791
+ return new Set(this.selectedOrDeselectedEntries);
792
+ }
793
+ setSelectedOrDeselectedEntries(entries) {
794
+ this.selectedOrDeselectedEntries = new Set(entries);
795
+ return this;
796
+ }
797
+ getExpandedOrCollapsedEntries() {
798
+ return new Set(this.expandedOrCollapsedEntries);
799
+ }
800
+ setExpandedOrCollapsedEntries(entries) {
801
+ this.expandedOrCollapsedEntries = new Set(entries);
802
+ return this;
803
+ }
804
+ // ===== Child Entry Methods =====
805
+ /**
806
+ * Get child documents of an entry
807
+ */
808
+ childDocuments(entry, descending = false) {
809
+ const docs = entry.getChildDocuments();
810
+ const filtered = docs.filter(e => this.isVisible(e));
811
+ return descending ? filtered.reverse() : filtered;
812
+ }
813
+ /**
814
+ * Get child categories of an entry
815
+ */
816
+ childCategories(entry, descending = false) {
817
+ const cats = entry.getChildCategories();
818
+ const filtered = cats.filter(e => this.isVisible(e));
819
+ return descending ? filtered.reverse() : filtered;
820
+ }
821
+ /**
822
+ * Get all child entries of an entry
823
+ */
824
+ childEntries(entry, descending = false) {
825
+ const entries = entry.getChildEntries();
826
+ const filtered = entries.filter(e => this.isVisible(e));
827
+ return descending ? filtered.reverse() : filtered;
828
+ }
829
+ // ===== Range/Key-based Child Queries =====
830
+ /**
831
+ * Get child documents within a key range (inclusive)
832
+ *
833
+ * @param entry Parent entry
834
+ * @param startKey Start key value
835
+ * @param endKey End key value
836
+ * @param descending Whether to return in descending order
837
+ * @returns Filtered child documents within the range
838
+ */
839
+ childDocumentsBetween(entry, startKey, endKey, descending = false) {
840
+ const docs = entry.getChildDocuments();
841
+ const filtered = docs.filter(e => {
842
+ if (!this.isVisible(e))
843
+ return false;
844
+ const sortKey = e.getSortKey();
845
+ const firstValue = sortKey.values.length > 0 ? sortKey.values[0] : null;
846
+ // Check if value is within range
847
+ const afterStart = (0, types_1.compareValues)(firstValue, startKey, false) >= 0;
848
+ const beforeEnd = (0, types_1.compareValues)(firstValue, endKey, false) <= 0;
849
+ return afterStart && beforeEnd;
850
+ });
851
+ return descending ? filtered.reverse() : filtered;
852
+ }
853
+ /**
854
+ * Get child documents by key (exact or prefix match)
855
+ *
856
+ * @param entry Parent entry
857
+ * @param key Key value to search for
858
+ * @param isExact Whether to match exactly or by prefix
859
+ * @param descending Whether to return in descending order
860
+ * @returns Matching child documents
861
+ */
862
+ childDocumentsByKey(entry, key, isExact, descending = false) {
863
+ if (isExact) {
864
+ return this.childDocumentsBetween(entry, key, key, descending);
865
+ }
866
+ // Prefix match - use key to key + max char
867
+ const endKey = key + String.fromCharCode(0xFFFF);
868
+ return this.childDocumentsBetween(entry, key, endKey, descending);
869
+ }
870
+ /**
871
+ * Get child categories within a key range (inclusive)
872
+ *
873
+ * @param entry Parent entry
874
+ * @param startKey Start key value
875
+ * @param endKey End key value
876
+ * @param descending Whether to return in descending order
877
+ * @returns Filtered child categories within the range
878
+ */
879
+ childCategoriesBetween(entry, startKey, endKey, descending = false) {
880
+ const cats = entry.getChildCategories();
881
+ const filtered = cats.filter(e => {
882
+ if (!this.isVisible(e))
883
+ return false;
884
+ const catValue = e.getCategoryValue();
885
+ // Check if value is within range
886
+ const afterStart = (0, types_1.compareValues)(catValue, startKey, false) >= 0;
887
+ const beforeEnd = (0, types_1.compareValues)(catValue, endKey, false) <= 0;
888
+ return afterStart && beforeEnd;
889
+ });
890
+ return descending ? filtered.reverse() : filtered;
891
+ }
892
+ /**
893
+ * Get child categories by key (exact or prefix match)
894
+ *
895
+ * @param entry Parent entry
896
+ * @param key Key value to search for
897
+ * @param isExact Whether to match exactly or by prefix
898
+ * @param descending Whether to return in descending order
899
+ * @returns Matching child categories
900
+ */
901
+ childCategoriesByKey(entry, key, isExact, descending = false) {
902
+ if (isExact) {
903
+ return this.childCategoriesBetween(entry, key, key, descending);
904
+ }
905
+ // Prefix match - use key to key + max char
906
+ const endKey = key + String.fromCharCode(0xFFFF);
907
+ return this.childCategoriesBetween(entry, key, endKey, descending);
908
+ }
909
+ // ===== Sorted Entry Lookup =====
910
+ /**
911
+ * Compare two position arrays for sorting
912
+ */
913
+ static comparePositions(pos1, pos2) {
914
+ const len = Math.min(pos1.length, pos2.length);
915
+ for (let i = 0; i < len; i++) {
916
+ if (pos1[i] !== pos2[i]) {
917
+ return pos1[i] - pos2[i];
918
+ }
919
+ }
920
+ return pos1.length - pos2.length;
921
+ }
922
+ /**
923
+ * Get all occurrences of a document in the view, sorted by position
924
+ *
925
+ * @param origin Origin of the document
926
+ * @param docId Document ID
927
+ * @returns Array of entries sorted by position
928
+ */
929
+ getSortedEntries(origin, docId) {
930
+ const entries = this.view.getEntries(origin, docId);
931
+ return entries
932
+ .filter(e => this.isVisible(e))
933
+ .sort((a, b) => VirtualViewNavigator.comparePositions(a.getPosition(), b.getPosition()));
934
+ }
935
+ /**
936
+ * Get all occurrences of multiple documents in the view, sorted by position
937
+ *
938
+ * @param origin Origin of the documents
939
+ * @param docIds Set of document IDs
940
+ * @returns Array of entries sorted by position
941
+ */
942
+ getSortedEntriesMultiple(origin, docIds) {
943
+ const allEntries = [];
944
+ for (const docId of docIds) {
945
+ const entries = this.view.getEntries(origin, docId);
946
+ allEntries.push(...entries);
947
+ }
948
+ return allEntries
949
+ .filter(e => this.isVisible(e))
950
+ .sort((a, b) => VirtualViewNavigator.comparePositions(a.getPosition(), b.getPosition()));
951
+ }
952
+ /**
953
+ * Get all occurrences of scoped document IDs in the view, sorted by position
954
+ *
955
+ * @param scopedDocIds Set of scoped document IDs (origin + docId)
956
+ * @returns Array of entries sorted by position
957
+ */
958
+ getSortedEntriesScoped(scopedDocIds) {
959
+ const allEntries = [];
960
+ for (const scopedId of scopedDocIds) {
961
+ const entries = this.view.getEntries(scopedId.origin, scopedId.docId);
962
+ allEntries.push(...entries);
963
+ }
964
+ return allEntries
965
+ .filter(e => this.isVisible(e))
966
+ .sort((a, b) => VirtualViewNavigator.comparePositions(a.getPosition(), b.getPosition()));
967
+ }
968
+ /**
969
+ * Get document IDs sorted by their position in the view
970
+ *
971
+ * @param origin Origin of the documents
972
+ * @param docIds Set of document IDs
973
+ * @returns Array of document IDs sorted by their position in the view
974
+ */
975
+ getSortedDocIds(origin, docIds) {
976
+ const sortedEntries = this.getSortedEntriesMultiple(origin, docIds);
977
+ // Use a Set to track seen docIds and maintain order
978
+ const seen = new Set();
979
+ const result = [];
980
+ for (const entry of sortedEntries) {
981
+ if (!seen.has(entry.docId)) {
982
+ seen.add(entry.docId);
983
+ result.push(entry.docId);
984
+ }
985
+ }
986
+ return result;
987
+ }
988
+ /**
989
+ * Get scoped document IDs sorted by their position in the view
990
+ *
991
+ * @param scopedDocIds Set of scoped document IDs
992
+ * @returns Array of scoped document IDs sorted by their position in the view
993
+ */
994
+ getSortedDocIdsScoped(scopedDocIds) {
995
+ const sortedEntries = this.getSortedEntriesScoped(scopedDocIds);
996
+ // Use a Set to track seen docIds and maintain order
997
+ const seen = new Set();
998
+ const result = [];
999
+ for (const entry of sortedEntries) {
1000
+ const key = (0, types_1.scopedDocIdKey)({ origin: entry.origin, docId: entry.docId });
1001
+ if (!seen.has(key)) {
1002
+ seen.add(key);
1003
+ result.push({ origin: entry.origin, docId: entry.docId });
1004
+ }
1005
+ }
1006
+ return result;
1007
+ }
1008
+ }
1009
+ exports.VirtualViewNavigator = VirtualViewNavigator;
1010
+ //# sourceMappingURL=VirtualViewNavigator.js.map