@metriport/fhir-sdk 0.30.0-alpha.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 (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +564 -0
  3. package/dist/__tests__/careplan.test.d.ts +2 -0
  4. package/dist/__tests__/careplan.test.d.ts.map +1 -0
  5. package/dist/__tests__/careplan.test.js +544 -0
  6. package/dist/__tests__/careplan.test.js.map +1 -0
  7. package/dist/__tests__/clinical-dates.test.d.ts +2 -0
  8. package/dist/__tests__/clinical-dates.test.d.ts.map +1 -0
  9. package/dist/__tests__/clinical-dates.test.js +341 -0
  10. package/dist/__tests__/clinical-dates.test.js.map +1 -0
  11. package/dist/__tests__/coding-utilities.test.d.ts +2 -0
  12. package/dist/__tests__/coding-utilities.test.d.ts.map +1 -0
  13. package/dist/__tests__/coding-utilities.test.js +482 -0
  14. package/dist/__tests__/coding-utilities.test.js.map +1 -0
  15. package/dist/__tests__/date-range-performance.test.d.ts +2 -0
  16. package/dist/__tests__/date-range-performance.test.d.ts.map +1 -0
  17. package/dist/__tests__/date-range-performance.test.js +218 -0
  18. package/dist/__tests__/date-range-performance.test.js.map +1 -0
  19. package/dist/__tests__/date-range-search.test.d.ts +2 -0
  20. package/dist/__tests__/date-range-search.test.d.ts.map +1 -0
  21. package/dist/__tests__/date-range-search.test.js +215 -0
  22. package/dist/__tests__/date-range-search.test.js.map +1 -0
  23. package/dist/__tests__/env-setup.d.ts +2 -0
  24. package/dist/__tests__/env-setup.d.ts.map +1 -0
  25. package/dist/__tests__/env-setup.js +37 -0
  26. package/dist/__tests__/env-setup.js.map +1 -0
  27. package/dist/__tests__/fhir-bundle-sdk-basic.test.d.ts +2 -0
  28. package/dist/__tests__/fhir-bundle-sdk-basic.test.d.ts.map +1 -0
  29. package/dist/__tests__/fhir-bundle-sdk-basic.test.js +19 -0
  30. package/dist/__tests__/fhir-bundle-sdk-basic.test.js.map +1 -0
  31. package/dist/__tests__/fhir-bundle-sdk.test.d.ts +2 -0
  32. package/dist/__tests__/fhir-bundle-sdk.test.d.ts.map +1 -0
  33. package/dist/__tests__/fhir-bundle-sdk.test.js +953 -0
  34. package/dist/__tests__/fhir-bundle-sdk.test.js.map +1 -0
  35. package/dist/__tests__/fixtures/fhir-bundles.d.ts +31 -0
  36. package/dist/__tests__/fixtures/fhir-bundles.d.ts.map +1 -0
  37. package/dist/__tests__/fixtures/fhir-bundles.js +487 -0
  38. package/dist/__tests__/fixtures/fhir-bundles.js.map +1 -0
  39. package/dist/__tests__/phase1-verification.test.d.ts +2 -0
  40. package/dist/__tests__/phase1-verification.test.d.ts.map +1 -0
  41. package/dist/__tests__/phase1-verification.test.js +141 -0
  42. package/dist/__tests__/phase1-verification.test.js.map +1 -0
  43. package/dist/__tests__/phase2-verification.test.d.ts +2 -0
  44. package/dist/__tests__/phase2-verification.test.d.ts.map +1 -0
  45. package/dist/__tests__/phase2-verification.test.js +234 -0
  46. package/dist/__tests__/phase2-verification.test.js.map +1 -0
  47. package/dist/__tests__/phase3-verification.test.d.ts +2 -0
  48. package/dist/__tests__/phase3-verification.test.d.ts.map +1 -0
  49. package/dist/__tests__/phase3-verification.test.js +121 -0
  50. package/dist/__tests__/phase3-verification.test.js.map +1 -0
  51. package/dist/__tests__/phase4-verification.test.d.ts +2 -0
  52. package/dist/__tests__/phase4-verification.test.d.ts.map +1 -0
  53. package/dist/__tests__/phase4-verification.test.js +168 -0
  54. package/dist/__tests__/phase4-verification.test.js.map +1 -0
  55. package/dist/__tests__/phase5-verification.test.d.ts +2 -0
  56. package/dist/__tests__/phase5-verification.test.d.ts.map +1 -0
  57. package/dist/__tests__/phase5-verification.test.js +397 -0
  58. package/dist/__tests__/phase5-verification.test.js.map +1 -0
  59. package/dist/__tests__/reverse-references.test.d.ts +2 -0
  60. package/dist/__tests__/reverse-references.test.d.ts.map +1 -0
  61. package/dist/__tests__/reverse-references.test.js +294 -0
  62. package/dist/__tests__/reverse-references.test.js.map +1 -0
  63. package/dist/__tests__/type-guards.test.d.ts +2 -0
  64. package/dist/__tests__/type-guards.test.d.ts.map +1 -0
  65. package/dist/__tests__/type-guards.test.js +163 -0
  66. package/dist/__tests__/type-guards.test.js.map +1 -0
  67. package/dist/clinical-dates.d.ts +26 -0
  68. package/dist/clinical-dates.d.ts.map +1 -0
  69. package/dist/clinical-dates.js +571 -0
  70. package/dist/clinical-dates.js.map +1 -0
  71. package/dist/fhir-bundle-sdk.d.ts +233 -0
  72. package/dist/fhir-bundle-sdk.d.ts.map +1 -0
  73. package/dist/fhir-bundle-sdk.js +545 -0
  74. package/dist/fhir-bundle-sdk.js.map +1 -0
  75. package/dist/index.d.ts +8 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +23 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/internal/bundle-operations.d.ts +14 -0
  80. package/dist/internal/bundle-operations.d.ts.map +1 -0
  81. package/dist/internal/bundle-operations.js +55 -0
  82. package/dist/internal/bundle-operations.js.map +1 -0
  83. package/dist/internal/coding-systems.d.ts +48 -0
  84. package/dist/internal/coding-systems.d.ts.map +1 -0
  85. package/dist/internal/coding-systems.js +55 -0
  86. package/dist/internal/coding-systems.js.map +1 -0
  87. package/dist/internal/coding-utilities.d.ts +27 -0
  88. package/dist/internal/coding-utilities.d.ts.map +1 -0
  89. package/dist/internal/coding-utilities.js +297 -0
  90. package/dist/internal/coding-utilities.js.map +1 -0
  91. package/dist/internal/date-extraction.d.ts +12 -0
  92. package/dist/internal/date-extraction.d.ts.map +1 -0
  93. package/dist/internal/date-extraction.js +629 -0
  94. package/dist/internal/date-extraction.js.map +1 -0
  95. package/dist/internal/graph-traversal.d.ts +13 -0
  96. package/dist/internal/graph-traversal.d.ts.map +1 -0
  97. package/dist/internal/graph-traversal.js +89 -0
  98. package/dist/internal/graph-traversal.js.map +1 -0
  99. package/dist/internal/indexing.d.ts +17 -0
  100. package/dist/internal/indexing.d.ts.map +1 -0
  101. package/dist/internal/indexing.js +129 -0
  102. package/dist/internal/indexing.js.map +1 -0
  103. package/dist/internal/llm-context.d.ts +40 -0
  104. package/dist/internal/llm-context.d.ts.map +1 -0
  105. package/dist/internal/llm-context.js +214 -0
  106. package/dist/internal/llm-context.js.map +1 -0
  107. package/dist/internal/reference-resolution.d.ts +29 -0
  108. package/dist/internal/reference-resolution.d.ts.map +1 -0
  109. package/dist/internal/reference-resolution.js +338 -0
  110. package/dist/internal/reference-resolution.js.map +1 -0
  111. package/dist/internal/reference-utils.d.ts +26 -0
  112. package/dist/internal/reference-utils.d.ts.map +1 -0
  113. package/dist/internal/reference-utils.js +89 -0
  114. package/dist/internal/reference-utils.js.map +1 -0
  115. package/dist/internal/transparent-proxy.d.ts +12 -0
  116. package/dist/internal/transparent-proxy.d.ts.map +1 -0
  117. package/dist/internal/transparent-proxy.js +81 -0
  118. package/dist/internal/transparent-proxy.js.map +1 -0
  119. package/dist/internal/validation.d.ts +16 -0
  120. package/dist/internal/validation.d.ts.map +1 -0
  121. package/dist/internal/validation.js +45 -0
  122. package/dist/internal/validation.js.map +1 -0
  123. package/dist/type-guards.d.ts +212 -0
  124. package/dist/type-guards.d.ts.map +1 -0
  125. package/dist/type-guards.js +375 -0
  126. package/dist/type-guards.js.map +1 -0
  127. package/dist/types/coding-fields.d.ts +311 -0
  128. package/dist/types/coding-fields.d.ts.map +1 -0
  129. package/dist/types/coding-fields.js +3 -0
  130. package/dist/types/coding-fields.js.map +1 -0
  131. package/dist/types/sdk-types.d.ts +107 -0
  132. package/dist/types/sdk-types.d.ts.map +1 -0
  133. package/dist/types/sdk-types.js +17 -0
  134. package/dist/types/sdk-types.js.map +1 -0
  135. package/dist/types/smart-resources.d.ts +470 -0
  136. package/dist/types/smart-resources.d.ts.map +1 -0
  137. package/dist/types/smart-resources.js +249 -0
  138. package/dist/types/smart-resources.js.map +1 -0
  139. package/dist/utils/interval-tree/index.d.ts +87 -0
  140. package/dist/utils/interval-tree/index.d.ts.map +1 -0
  141. package/dist/utils/interval-tree/index.js +774 -0
  142. package/dist/utils/interval-tree/index.js.map +1 -0
  143. package/dist/utils/interval-tree/shallowequal/arrays.d.ts +3 -0
  144. package/dist/utils/interval-tree/shallowequal/arrays.d.ts.map +1 -0
  145. package/dist/utils/interval-tree/shallowequal/arrays.js +25 -0
  146. package/dist/utils/interval-tree/shallowequal/arrays.js.map +1 -0
  147. package/dist/utils/interval-tree/shallowequal/index.d.ts +6 -0
  148. package/dist/utils/interval-tree/shallowequal/index.d.ts.map +1 -0
  149. package/dist/utils/interval-tree/shallowequal/index.js +28 -0
  150. package/dist/utils/interval-tree/shallowequal/index.js.map +1 -0
  151. package/dist/utils/interval-tree/shallowequal/objects.d.ts +3 -0
  152. package/dist/utils/interval-tree/shallowequal/objects.d.ts.map +1 -0
  153. package/dist/utils/interval-tree/shallowequal/objects.js +28 -0
  154. package/dist/utils/interval-tree/shallowequal/objects.js.map +1 -0
  155. package/package.json +70 -0
@@ -0,0 +1,774 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5
+ // @ts-nocheck
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.PreOrder = exports.ReverseInOrder = exports.InOrder = exports.IntervalTree = exports.Node = void 0;
8
+ // This file is a modified version of the original node-interval-tree library.
9
+ // We want to make as few / minimal changes as possible, and ignore lint errors.
10
+ // An augmented AVL Tree where each node maintains a list of records and their search intervals.
11
+ // Record is composed of an interval and its underlying data, sent by a client. This allows the
12
+ // interval tree to have the same interval inserted multiple times, as long its data is different.
13
+ // Both insertion and deletion require O(log n) time. Searching requires O(k*logn) time, where `k`
14
+ // is the number of intervals in the output list.
15
+ const shallowequal_1 = require("./shallowequal");
16
+ function max(a, b) {
17
+ return a < b ? b : a;
18
+ }
19
+ function height(node) {
20
+ if (node === undefined) {
21
+ return -1;
22
+ }
23
+ else {
24
+ return node.height;
25
+ }
26
+ }
27
+ class Node {
28
+ constructor(intervalTree, record) {
29
+ this.intervalTree = intervalTree;
30
+ this.records = [];
31
+ this.height = 0;
32
+ this.key = record.low;
33
+ this.max = record.high;
34
+ // Save the array of all records with the same key for this node
35
+ this.records.push(record);
36
+ }
37
+ // Gets the highest record.high value for this node
38
+ getNodeHigh() {
39
+ let high = this.records[0].high;
40
+ for (let i = 1; i < this.records.length; i++) {
41
+ if (this.records[i].high > high) {
42
+ high = this.records[i].high;
43
+ }
44
+ }
45
+ return high;
46
+ }
47
+ // Updates height value of the node. Called during insertion, rebalance, removal
48
+ updateHeight() {
49
+ this.height = max(height(this.left), height(this.right)) + 1;
50
+ }
51
+ // Updates the max value of all the parents after inserting into already existing node, as well as
52
+ // removing the node completely or removing the record of an already existing node. Starts with
53
+ // the parent of an affected node and bubbles up to root
54
+ updateMaxOfParents() {
55
+ if (this === undefined) {
56
+ return;
57
+ }
58
+ const thisHigh = this.getNodeHigh();
59
+ if (this.left !== undefined && this.right !== undefined) {
60
+ this.max = max(max(this.left.max, this.right.max), thisHigh);
61
+ }
62
+ else if (this.left !== undefined && this.right === undefined) {
63
+ this.max = max(this.left.max, thisHigh);
64
+ }
65
+ else if (this.left === undefined && this.right !== undefined) {
66
+ this.max = max(this.right.max, thisHigh);
67
+ }
68
+ else {
69
+ this.max = thisHigh;
70
+ }
71
+ if (this.parent) {
72
+ this.parent.updateMaxOfParents();
73
+ }
74
+ }
75
+ /*
76
+ Left-Left case:
77
+
78
+ z y
79
+ / \ / \
80
+ y T4 Right Rotate (z) x z
81
+ / \ - - - - - - - - -> / \ / \
82
+ x T3 T1 T2 T3 T4
83
+ / \
84
+ T1 T2
85
+
86
+ Left-Right case:
87
+
88
+ z z x
89
+ / \ / \ / \
90
+ y T4 Left Rotate (y) x T4 Right Rotate(z) y z
91
+ / \ - - - - - - - - -> / \ - - - - - - - -> / \ / \
92
+ T1 x y T3 T1 T2 T3 T4
93
+ / \ / \
94
+ T2 T3 T1 T2
95
+ */
96
+ // Handles Left-Left case and Left-Right case after rebalancing AVL tree
97
+ _updateMaxAfterRightRotate() {
98
+ const parent = this.parent;
99
+ const left = parent.left;
100
+ // Update max of left sibling (x in first case, y in second)
101
+ const thisParentLeftHigh = left.getNodeHigh();
102
+ if (left.left === undefined && left.right !== undefined) {
103
+ left.max = max(thisParentLeftHigh, left.right.max);
104
+ }
105
+ else if (left.left !== undefined && left.right === undefined) {
106
+ left.max = max(thisParentLeftHigh, left.left.max);
107
+ }
108
+ else if (left.left === undefined && left.right === undefined) {
109
+ left.max = thisParentLeftHigh;
110
+ }
111
+ else {
112
+ left.max = max(max(left.left.max, left.right.max), thisParentLeftHigh);
113
+ }
114
+ // Update max of itself (z)
115
+ const thisHigh = this.getNodeHigh();
116
+ if (this.left === undefined && this.right !== undefined) {
117
+ this.max = max(thisHigh, this.right.max);
118
+ }
119
+ else if (this.left !== undefined && this.right === undefined) {
120
+ this.max = max(thisHigh, this.left.max);
121
+ }
122
+ else if (this.left === undefined && this.right === undefined) {
123
+ this.max = thisHigh;
124
+ }
125
+ else {
126
+ this.max = max(max(this.left.max, this.right.max), thisHigh);
127
+ }
128
+ // Update max of parent (y in first case, x in second)
129
+ parent.max = max(max(parent.left.max, parent.right.max), parent.getNodeHigh());
130
+ }
131
+ /*
132
+ Right-Right case:
133
+
134
+ z y
135
+ / \ / \
136
+ T1 y Left Rotate(z) z x
137
+ / \ - - - - - - - -> / \ / \
138
+ T2 x T1 T2 T3 T4
139
+ / \
140
+ T3 T4
141
+
142
+ Right-Left case:
143
+
144
+ z z x
145
+ / \ / \ / \
146
+ T1 y Right Rotate (y) T1 x Left Rotate(z) z y
147
+ / \ - - - - - - - - -> / \ - - - - - - - -> / \ / \
148
+ x T4 T2 y T1 T2 T3 T4
149
+ / \ / \
150
+ T2 T3 T3 T4
151
+ */
152
+ // Handles Right-Right case and Right-Left case in rebalancing AVL tree
153
+ _updateMaxAfterLeftRotate() {
154
+ const parent = this.parent;
155
+ const right = parent.right;
156
+ // Update max of right sibling (x in first case, y in second)
157
+ const thisParentRightHigh = right.getNodeHigh();
158
+ if (right.left === undefined && right.right !== undefined) {
159
+ right.max = max(thisParentRightHigh, right.right.max);
160
+ }
161
+ else if (right.left !== undefined && right.right === undefined) {
162
+ right.max = max(thisParentRightHigh, right.left.max);
163
+ }
164
+ else if (right.left === undefined && right.right === undefined) {
165
+ right.max = thisParentRightHigh;
166
+ }
167
+ else {
168
+ right.max = max(max(right.left.max, right.right.max), thisParentRightHigh);
169
+ }
170
+ // Update max of itself (z)
171
+ const thisHigh = this.getNodeHigh();
172
+ if (this.left === undefined && this.right !== undefined) {
173
+ this.max = max(thisHigh, this.right.max);
174
+ }
175
+ else if (this.left !== undefined && this.right === undefined) {
176
+ this.max = max(thisHigh, this.left.max);
177
+ }
178
+ else if (this.left === undefined && this.right === undefined) {
179
+ this.max = thisHigh;
180
+ }
181
+ else {
182
+ this.max = max(max(this.left.max, this.right.max), thisHigh);
183
+ }
184
+ // Update max of parent (y in first case, x in second)
185
+ parent.max = max(max(parent.left.max, right.max), parent.getNodeHigh());
186
+ }
187
+ _leftRotate() {
188
+ const rightChild = this.right;
189
+ rightChild.parent = this.parent;
190
+ if (rightChild.parent === undefined) {
191
+ this.intervalTree.root = rightChild;
192
+ }
193
+ else {
194
+ if (rightChild.parent.left === this) {
195
+ rightChild.parent.left = rightChild;
196
+ }
197
+ else if (rightChild.parent.right === this) {
198
+ rightChild.parent.right = rightChild;
199
+ }
200
+ }
201
+ this.right = rightChild.left;
202
+ if (this.right !== undefined) {
203
+ this.right.parent = this;
204
+ }
205
+ rightChild.left = this;
206
+ this.parent = rightChild;
207
+ this.updateHeight();
208
+ rightChild.updateHeight();
209
+ }
210
+ _rightRotate() {
211
+ const leftChild = this.left;
212
+ leftChild.parent = this.parent;
213
+ if (leftChild.parent === undefined) {
214
+ this.intervalTree.root = leftChild;
215
+ }
216
+ else {
217
+ if (leftChild.parent.left === this) {
218
+ leftChild.parent.left = leftChild;
219
+ }
220
+ else if (leftChild.parent.right === this) {
221
+ leftChild.parent.right = leftChild;
222
+ }
223
+ }
224
+ this.left = leftChild.right;
225
+ if (this.left !== undefined) {
226
+ this.left.parent = this;
227
+ }
228
+ leftChild.right = this;
229
+ this.parent = leftChild;
230
+ this.updateHeight();
231
+ leftChild.updateHeight();
232
+ }
233
+ // Rebalances the tree if the height value between two nodes of the same parent is greater than
234
+ // two. There are 4 cases that can happen which are outlined in the graphics above
235
+ _rebalance() {
236
+ if (height(this.left) >= 2 + height(this.right)) {
237
+ const left = this.left;
238
+ if (height(left.left) >= height(left.right)) {
239
+ // Left-Left case
240
+ this._rightRotate();
241
+ this._updateMaxAfterRightRotate();
242
+ }
243
+ else {
244
+ // Left-Right case
245
+ left._leftRotate();
246
+ this._rightRotate();
247
+ this._updateMaxAfterRightRotate();
248
+ }
249
+ }
250
+ else if (height(this.right) >= 2 + height(this.left)) {
251
+ const right = this.right;
252
+ if (height(right.right) >= height(right.left)) {
253
+ // Right-Right case
254
+ this._leftRotate();
255
+ this._updateMaxAfterLeftRotate();
256
+ }
257
+ else {
258
+ // Right-Left case
259
+ right._rightRotate();
260
+ this._leftRotate();
261
+ this._updateMaxAfterLeftRotate();
262
+ }
263
+ }
264
+ }
265
+ insert(record) {
266
+ if (record.low < this.key) {
267
+ // Insert into left subtree
268
+ if (this.left === undefined) {
269
+ this.left = new Node(this.intervalTree, record);
270
+ this.left.parent = this;
271
+ }
272
+ else {
273
+ this.left.insert(record);
274
+ }
275
+ }
276
+ else {
277
+ // Insert into right subtree
278
+ if (this.right === undefined) {
279
+ this.right = new Node(this.intervalTree, record);
280
+ this.right.parent = this;
281
+ }
282
+ else {
283
+ this.right.insert(record);
284
+ }
285
+ }
286
+ // Update the max value of this ancestor if needed
287
+ if (this.max < record.high) {
288
+ this.max = record.high;
289
+ }
290
+ // Update height of each node
291
+ this.updateHeight();
292
+ // Rebalance the tree to ensure all operations are executed in O(logn) time. This is especially
293
+ // important in searching, as the tree has a high chance of degenerating without the rebalancing
294
+ this._rebalance();
295
+ }
296
+ _getOverlappingRecords(currentNode, low, high) {
297
+ if (currentNode.key <= high && low <= currentNode.getNodeHigh()) {
298
+ // Nodes are overlapping, check if individual records in the node are overlapping
299
+ const tempResults = [];
300
+ for (let i = 0; i < currentNode.records.length; i++) {
301
+ if (currentNode.records[i].high >= low) {
302
+ tempResults.push(currentNode.records[i]);
303
+ }
304
+ }
305
+ return tempResults;
306
+ }
307
+ return [];
308
+ }
309
+ search(low, high) {
310
+ // Don't search nodes that don't exist
311
+ if (this === undefined) {
312
+ return [];
313
+ }
314
+ let leftSearch = [];
315
+ let ownSearch = [];
316
+ let rightSearch = [];
317
+ // If interval is to the right of the rightmost point of any interval in this node and all its
318
+ // children, there won't be any matches
319
+ if (low > this.max) {
320
+ return [];
321
+ }
322
+ // Search left children
323
+ if (this.left !== undefined && this.left.max >= low) {
324
+ leftSearch = this.left.search(low, high);
325
+ }
326
+ // Check this node
327
+ ownSearch = this._getOverlappingRecords(this, low, high);
328
+ // If interval is to the left of the start of this interval, then it can't be in any child to
329
+ // the right
330
+ if (high < this.key) {
331
+ return leftSearch.concat(ownSearch);
332
+ }
333
+ // Otherwise, search right children
334
+ if (this.right !== undefined) {
335
+ rightSearch = this.right.search(low, high);
336
+ }
337
+ // Return accumulated results, if any
338
+ return leftSearch.concat(ownSearch, rightSearch);
339
+ }
340
+ // Searches for a node by a `key` value
341
+ searchExisting(low) {
342
+ if (this === undefined) {
343
+ return undefined;
344
+ }
345
+ if (this.key === low) {
346
+ return this;
347
+ }
348
+ else if (low < this.key) {
349
+ if (this.left !== undefined) {
350
+ return this.left.searchExisting(low);
351
+ }
352
+ }
353
+ else {
354
+ if (this.right !== undefined) {
355
+ return this.right.searchExisting(low);
356
+ }
357
+ }
358
+ return undefined;
359
+ }
360
+ // Returns the smallest node of the subtree
361
+ _minValue() {
362
+ if (this.left === undefined) {
363
+ return this;
364
+ }
365
+ else {
366
+ return this.left._minValue();
367
+ }
368
+ }
369
+ remove(node) {
370
+ const parent = this.parent;
371
+ if (node.key < this.key) {
372
+ // Node to be removed is on the left side
373
+ if (this.left !== undefined) {
374
+ return this.left.remove(node);
375
+ }
376
+ else {
377
+ return undefined;
378
+ }
379
+ }
380
+ else if (node.key > this.key) {
381
+ // Node to be removed is on the right side
382
+ if (this.right !== undefined) {
383
+ return this.right.remove(node);
384
+ }
385
+ else {
386
+ return undefined;
387
+ }
388
+ }
389
+ else {
390
+ if (this.left !== undefined && this.right !== undefined) {
391
+ // Node has two children
392
+ const minValue = this.right._minValue();
393
+ this.key = minValue.key;
394
+ this.records = minValue.records;
395
+ return this.right.remove(this);
396
+ }
397
+ else if (parent.left === this) {
398
+ // One child or no child case on left side
399
+ if (this.right !== undefined) {
400
+ parent.left = this.right;
401
+ this.right.parent = parent;
402
+ }
403
+ else {
404
+ parent.left = this.left;
405
+ if (this.left !== undefined) {
406
+ this.left.parent = parent;
407
+ }
408
+ }
409
+ parent.updateMaxOfParents();
410
+ parent.updateHeight();
411
+ parent._rebalance();
412
+ return this;
413
+ }
414
+ else if (parent.right === this) {
415
+ // One child or no child case on right side
416
+ if (this.right !== undefined) {
417
+ parent.right = this.right;
418
+ this.right.parent = parent;
419
+ }
420
+ else {
421
+ parent.right = this.left;
422
+ if (this.left !== undefined) {
423
+ this.left.parent = parent;
424
+ }
425
+ }
426
+ parent.updateMaxOfParents();
427
+ parent.updateHeight();
428
+ parent._rebalance();
429
+ return this;
430
+ }
431
+ }
432
+ // Make linter happy
433
+ return undefined;
434
+ }
435
+ }
436
+ exports.Node = Node;
437
+ class IntervalTree {
438
+ constructor() {
439
+ this.count = 0;
440
+ }
441
+ insert(record) {
442
+ if (record.low > record.high) {
443
+ throw new Error("`low` value must be lower or equal to `high` value");
444
+ }
445
+ if (this.root === undefined) {
446
+ // Base case: Tree is empty, new node becomes root
447
+ this.root = new Node(this, record);
448
+ this.count++;
449
+ return true;
450
+ }
451
+ else {
452
+ // Otherwise, check if node already exists with the same key
453
+ const node = this.root.searchExisting(record.low);
454
+ if (node !== undefined) {
455
+ // Check the records in this node if there already is the one with same low, high, data
456
+ for (let i = 0; i < node.records.length; i++) {
457
+ if ((0, shallowequal_1.shallowEqual)(node.records[i], record)) {
458
+ // This record is same as the one we're trying to insert; return false to indicate
459
+ // nothing has been inserted
460
+ return false;
461
+ }
462
+ }
463
+ // Add the record to the node
464
+ node.records.push(record);
465
+ // Update max of the node and its parents if necessary
466
+ if (record.high > node.max) {
467
+ node.max = record.high;
468
+ if (node.parent) {
469
+ node.parent.updateMaxOfParents();
470
+ }
471
+ }
472
+ this.count++;
473
+ return true;
474
+ }
475
+ else {
476
+ // Node with this key doesn't already exist. Call insert function on root's node
477
+ this.root.insert(record);
478
+ this.count++;
479
+ return true;
480
+ }
481
+ }
482
+ }
483
+ search(low, high) {
484
+ if (this.root === undefined) {
485
+ // Tree is empty; return empty array
486
+ return [];
487
+ }
488
+ else {
489
+ return this.root.search(low, high);
490
+ }
491
+ }
492
+ remove(record) {
493
+ if (this.root === undefined) {
494
+ // Tree is empty; nothing to remove
495
+ return false;
496
+ }
497
+ else {
498
+ const node = this.root.searchExisting(record.low);
499
+ if (node === undefined) {
500
+ return false;
501
+ }
502
+ else if (node.records.length > 1) {
503
+ let removedRecord;
504
+ // Node with this key has 2 or more records. Find the one we need and remove it
505
+ for (let i = 0; i < node.records.length; i++) {
506
+ if ((0, shallowequal_1.shallowEqual)(node.records[i], record)) {
507
+ removedRecord = node.records[i];
508
+ node.records.splice(i, 1);
509
+ break;
510
+ }
511
+ }
512
+ if (removedRecord) {
513
+ removedRecord = undefined;
514
+ // Update max of that node and its parents if necessary
515
+ if (record.high === node.max) {
516
+ const nodeHigh = node.getNodeHigh();
517
+ if (node.left !== undefined && node.right !== undefined) {
518
+ node.max = max(max(node.left.max, node.right.max), nodeHigh);
519
+ }
520
+ else if (node.left !== undefined && node.right === undefined) {
521
+ node.max = max(node.left.max, nodeHigh);
522
+ }
523
+ else if (node.left === undefined && node.right !== undefined) {
524
+ node.max = max(node.right.max, nodeHigh);
525
+ }
526
+ else {
527
+ node.max = nodeHigh;
528
+ }
529
+ if (node.parent) {
530
+ node.parent.updateMaxOfParents();
531
+ }
532
+ }
533
+ this.count--;
534
+ return true;
535
+ }
536
+ else {
537
+ return false;
538
+ }
539
+ }
540
+ else if (node.records.length === 1) {
541
+ // Node with this key has only 1 record. Check if the remaining record in this node is
542
+ // actually the one we want to remove
543
+ if ((0, shallowequal_1.shallowEqual)(node.records[0], record)) {
544
+ // The remaining record is the one we want to remove. Remove the whole node from the tree
545
+ if (this.root.key === node.key) {
546
+ // We're removing the root element. Create a dummy node that will temporarily take
547
+ // root's parent role
548
+ const rootParent = new Node(this, { low: record.low, high: record.low });
549
+ rootParent.left = this.root;
550
+ this.root.parent = rootParent;
551
+ let removedNode = this.root.remove(node);
552
+ this.root = rootParent.left;
553
+ if (this.root !== undefined) {
554
+ this.root.parent = undefined;
555
+ }
556
+ if (removedNode) {
557
+ removedNode = undefined;
558
+ this.count--;
559
+ return true;
560
+ }
561
+ else {
562
+ return false;
563
+ }
564
+ }
565
+ else {
566
+ let removedNode = this.root.remove(node);
567
+ if (removedNode) {
568
+ removedNode = undefined;
569
+ this.count--;
570
+ return true;
571
+ }
572
+ else {
573
+ return false;
574
+ }
575
+ }
576
+ }
577
+ else {
578
+ // The remaining record is not the one we want to remove
579
+ return false;
580
+ }
581
+ }
582
+ else {
583
+ // No records at all in this node?! Shouldn't happen
584
+ return false;
585
+ }
586
+ }
587
+ }
588
+ inOrder() {
589
+ return new InOrder(this.root);
590
+ }
591
+ reverseInOrder() {
592
+ return new ReverseInOrder(this.root);
593
+ }
594
+ preOrder() {
595
+ return new PreOrder(this.root);
596
+ }
597
+ }
598
+ exports.IntervalTree = IntervalTree;
599
+ /**
600
+ * The default export just wraps the `IntervalTree`, while providing a simpler API. Check out the
601
+ * README for description on how to use each.
602
+ */
603
+ class DataIntervalTree {
604
+ constructor() {
605
+ this.tree = new IntervalTree();
606
+ }
607
+ insert(low, high, data) {
608
+ return this.tree.insert({ low, high, data });
609
+ }
610
+ remove(low, high, data) {
611
+ return this.tree.remove({ low, high, data });
612
+ }
613
+ search(low, high) {
614
+ return this.tree.search(low, high).map(v => v.data);
615
+ }
616
+ inOrder() {
617
+ return this.tree.inOrder();
618
+ }
619
+ reverseInOrder() {
620
+ return this.tree.reverseInOrder();
621
+ }
622
+ preOrder() {
623
+ return this.tree.preOrder();
624
+ }
625
+ get count() {
626
+ return this.tree.count;
627
+ }
628
+ }
629
+ exports.default = DataIntervalTree;
630
+ class InOrder {
631
+ constructor(startNode) {
632
+ this.stack = [];
633
+ if (startNode !== undefined) {
634
+ this.push(startNode);
635
+ }
636
+ }
637
+ [Symbol.iterator]() {
638
+ return this;
639
+ }
640
+ next() {
641
+ // Will only happen if stack is empty and pop is called
642
+ if (this.currentNode === undefined) {
643
+ return {
644
+ done: true,
645
+ value: undefined,
646
+ };
647
+ }
648
+ // Process this node
649
+ if (this.i < this.currentNode.records.length) {
650
+ return {
651
+ done: false,
652
+ value: this.currentNode.records[this.i++],
653
+ };
654
+ }
655
+ if (this.currentNode.right !== undefined) {
656
+ // Can we go right?
657
+ this.push(this.currentNode.right);
658
+ }
659
+ else {
660
+ // Otherwise go up
661
+ // Might pop the last and set this.currentNode = undefined
662
+ this.pop();
663
+ }
664
+ return this.next();
665
+ }
666
+ push(node) {
667
+ this.currentNode = node;
668
+ this.i = 0;
669
+ while (this.currentNode.left !== undefined) {
670
+ this.stack.push(this.currentNode);
671
+ this.currentNode = this.currentNode.left;
672
+ }
673
+ }
674
+ pop() {
675
+ this.currentNode = this.stack.pop();
676
+ this.i = 0;
677
+ }
678
+ }
679
+ exports.InOrder = InOrder;
680
+ class ReverseInOrder {
681
+ constructor(startNode) {
682
+ this.stack = [];
683
+ if (startNode !== undefined) {
684
+ this.push(startNode);
685
+ }
686
+ }
687
+ [Symbol.iterator]() {
688
+ return this;
689
+ }
690
+ next() {
691
+ // Will only happen if stack is empty and pop is called
692
+ if (this.currentNode === undefined) {
693
+ return {
694
+ done: true,
695
+ value: undefined,
696
+ };
697
+ }
698
+ // Process this node
699
+ if (this.currentNode.records.length && this.i >= 0) {
700
+ return {
701
+ done: false,
702
+ value: this.currentNode.records[this.i--],
703
+ };
704
+ }
705
+ if (this.currentNode.left !== undefined) {
706
+ // Can we go left?
707
+ this.push(this.currentNode.left);
708
+ }
709
+ else {
710
+ // Otherwise go up
711
+ // Might pop the last and set this.currentNode = undefined
712
+ this.pop();
713
+ }
714
+ return this.next();
715
+ }
716
+ push(node) {
717
+ this.currentNode = node;
718
+ this.i = (this.currentNode?.records.length ?? 0) - 1;
719
+ while (this.currentNode.right !== undefined) {
720
+ this.stack.push(this.currentNode);
721
+ this.currentNode = this.currentNode.right;
722
+ this.i = (this.currentNode?.records.length ?? 0) - 1;
723
+ }
724
+ }
725
+ pop() {
726
+ this.currentNode = this.stack.pop();
727
+ this.i = (this.currentNode?.records.length ?? 0) - 1;
728
+ }
729
+ }
730
+ exports.ReverseInOrder = ReverseInOrder;
731
+ class PreOrder {
732
+ constructor(startNode) {
733
+ this.stack = [];
734
+ this.i = 0;
735
+ this.currentNode = startNode;
736
+ }
737
+ [Symbol.iterator]() {
738
+ return this;
739
+ }
740
+ next() {
741
+ // Will only happen if stack is empty and pop is called,
742
+ // which only happens if there is no right node (i.e we are done)
743
+ if (this.currentNode === undefined) {
744
+ return {
745
+ done: true,
746
+ value: undefined,
747
+ };
748
+ }
749
+ // Process this node
750
+ if (this.i < this.currentNode.records.length) {
751
+ return {
752
+ done: false,
753
+ value: this.currentNode.records[this.i++],
754
+ };
755
+ }
756
+ if (this.currentNode.right !== undefined) {
757
+ this.push(this.currentNode.right);
758
+ }
759
+ if (this.currentNode.left !== undefined) {
760
+ this.push(this.currentNode.left);
761
+ }
762
+ this.pop();
763
+ return this.next();
764
+ }
765
+ push(node) {
766
+ this.stack.push(node);
767
+ }
768
+ pop() {
769
+ this.currentNode = this.stack.pop();
770
+ this.i = 0;
771
+ }
772
+ }
773
+ exports.PreOrder = PreOrder;
774
+ //# sourceMappingURL=index.js.map