@tanstack/db-ivm 0.0.0 → 0.1.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 (157) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/d2.cjs +111 -0
  3. package/dist/cjs/d2.cjs.map +1 -0
  4. package/dist/cjs/d2.d.cts +45 -0
  5. package/dist/cjs/graph.cjs +90 -0
  6. package/dist/cjs/graph.cjs.map +1 -0
  7. package/dist/cjs/graph.d.cts +57 -0
  8. package/dist/cjs/index.cjs +72 -0
  9. package/dist/cjs/index.cjs.map +1 -0
  10. package/dist/cjs/index.d.cts +4 -0
  11. package/dist/cjs/indexes.cjs +104 -0
  12. package/dist/cjs/indexes.cjs.map +1 -0
  13. package/dist/cjs/indexes.d.cts +20 -0
  14. package/dist/cjs/multiset.cjs +173 -0
  15. package/dist/cjs/multiset.cjs.map +1 -0
  16. package/dist/cjs/multiset.d.cts +36 -0
  17. package/dist/cjs/operators/concat.cjs +37 -0
  18. package/dist/cjs/operators/concat.cjs.map +1 -0
  19. package/dist/cjs/operators/concat.d.cts +13 -0
  20. package/dist/cjs/operators/consolidate.cjs +40 -0
  21. package/dist/cjs/operators/consolidate.cjs.map +1 -0
  22. package/dist/cjs/operators/consolidate.d.cts +12 -0
  23. package/dist/cjs/operators/count.cjs +36 -0
  24. package/dist/cjs/operators/count.cjs.map +1 -0
  25. package/dist/cjs/operators/count.d.cts +13 -0
  26. package/dist/cjs/operators/debug.cjs +50 -0
  27. package/dist/cjs/operators/debug.cjs.map +1 -0
  28. package/dist/cjs/operators/debug.d.cts +16 -0
  29. package/dist/cjs/operators/distinct.cjs +78 -0
  30. package/dist/cjs/operators/distinct.cjs.map +1 -0
  31. package/dist/cjs/operators/distinct.d.cts +14 -0
  32. package/dist/cjs/operators/filter.cjs +43 -0
  33. package/dist/cjs/operators/filter.cjs.map +1 -0
  34. package/dist/cjs/operators/filter.d.cts +16 -0
  35. package/dist/cjs/operators/filterBy.cjs +19 -0
  36. package/dist/cjs/operators/filterBy.cjs.map +1 -0
  37. package/dist/cjs/operators/filterBy.d.cts +10 -0
  38. package/dist/cjs/operators/groupBy.cjs +225 -0
  39. package/dist/cjs/operators/groupBy.cjs.map +1 -0
  40. package/dist/cjs/operators/groupBy.d.cts +68 -0
  41. package/dist/cjs/operators/index.d.cts +18 -0
  42. package/dist/cjs/operators/join.cjs +145 -0
  43. package/dist/cjs/operators/join.cjs.map +1 -0
  44. package/dist/cjs/operators/join.d.cts +48 -0
  45. package/dist/cjs/operators/keying.cjs +16 -0
  46. package/dist/cjs/operators/keying.cjs.map +1 -0
  47. package/dist/cjs/operators/keying.d.cts +19 -0
  48. package/dist/cjs/operators/map.cjs +43 -0
  49. package/dist/cjs/operators/map.cjs.map +1 -0
  50. package/dist/cjs/operators/map.d.cts +16 -0
  51. package/dist/cjs/operators/negate.cjs +28 -0
  52. package/dist/cjs/operators/negate.cjs.map +1 -0
  53. package/dist/cjs/operators/negate.d.cts +13 -0
  54. package/dist/cjs/operators/orderBy.cjs +102 -0
  55. package/dist/cjs/operators/orderBy.cjs.map +1 -0
  56. package/dist/cjs/operators/orderBy.d.cts +38 -0
  57. package/dist/cjs/operators/orderByBTree.d.cts +3 -0
  58. package/dist/cjs/operators/output.cjs +46 -0
  59. package/dist/cjs/operators/output.cjs.map +1 -0
  60. package/dist/cjs/operators/output.d.cts +16 -0
  61. package/dist/cjs/operators/pipe.cjs +9 -0
  62. package/dist/cjs/operators/pipe.cjs.map +1 -0
  63. package/dist/cjs/operators/pipe.d.cts +21 -0
  64. package/dist/cjs/operators/reduce.cjs +99 -0
  65. package/dist/cjs/operators/reduce.cjs.map +1 -0
  66. package/dist/cjs/operators/reduce.d.cts +14 -0
  67. package/dist/cjs/operators/topK.cjs +39 -0
  68. package/dist/cjs/operators/topK.cjs.map +1 -0
  69. package/dist/cjs/operators/topK.d.cts +32 -0
  70. package/dist/cjs/operators/topKWithFractionalIndex.cjs +218 -0
  71. package/dist/cjs/operators/topKWithFractionalIndex.cjs.map +1 -0
  72. package/dist/cjs/operators/topKWithFractionalIndex.d.cts +58 -0
  73. package/dist/cjs/operators/topKWithFractionalIndexBTree.d.cts +27 -0
  74. package/dist/cjs/types.d.cts +30 -0
  75. package/dist/cjs/utils.cjs +125 -0
  76. package/dist/cjs/utils.cjs.map +1 -0
  77. package/dist/cjs/utils.d.cts +40 -0
  78. package/dist/esm/d2.d.ts +45 -0
  79. package/dist/esm/d2.js +111 -0
  80. package/dist/esm/d2.js.map +1 -0
  81. package/dist/esm/graph.d.ts +57 -0
  82. package/dist/esm/graph.js +90 -0
  83. package/dist/esm/graph.js.map +1 -0
  84. package/dist/esm/index.d.ts +4 -0
  85. package/dist/esm/index.js +72 -0
  86. package/dist/esm/index.js.map +1 -0
  87. package/dist/esm/indexes.d.ts +20 -0
  88. package/dist/esm/indexes.js +104 -0
  89. package/dist/esm/indexes.js.map +1 -0
  90. package/dist/esm/multiset.d.ts +36 -0
  91. package/dist/esm/multiset.js +173 -0
  92. package/dist/esm/multiset.js.map +1 -0
  93. package/dist/esm/operators/concat.d.ts +13 -0
  94. package/dist/esm/operators/concat.js +37 -0
  95. package/dist/esm/operators/concat.js.map +1 -0
  96. package/dist/esm/operators/consolidate.d.ts +12 -0
  97. package/dist/esm/operators/consolidate.js +40 -0
  98. package/dist/esm/operators/consolidate.js.map +1 -0
  99. package/dist/esm/operators/count.d.ts +13 -0
  100. package/dist/esm/operators/count.js +36 -0
  101. package/dist/esm/operators/count.js.map +1 -0
  102. package/dist/esm/operators/debug.d.ts +16 -0
  103. package/dist/esm/operators/debug.js +50 -0
  104. package/dist/esm/operators/debug.js.map +1 -0
  105. package/dist/esm/operators/distinct.d.ts +14 -0
  106. package/dist/esm/operators/distinct.js +78 -0
  107. package/dist/esm/operators/distinct.js.map +1 -0
  108. package/dist/esm/operators/filter.d.ts +16 -0
  109. package/dist/esm/operators/filter.js +43 -0
  110. package/dist/esm/operators/filter.js.map +1 -0
  111. package/dist/esm/operators/filterBy.d.ts +10 -0
  112. package/dist/esm/operators/filterBy.js +19 -0
  113. package/dist/esm/operators/filterBy.js.map +1 -0
  114. package/dist/esm/operators/groupBy.d.ts +68 -0
  115. package/dist/esm/operators/groupBy.js +225 -0
  116. package/dist/esm/operators/groupBy.js.map +1 -0
  117. package/dist/esm/operators/index.d.ts +18 -0
  118. package/dist/esm/operators/join.d.ts +48 -0
  119. package/dist/esm/operators/join.js +145 -0
  120. package/dist/esm/operators/join.js.map +1 -0
  121. package/dist/esm/operators/keying.d.ts +19 -0
  122. package/dist/esm/operators/keying.js +16 -0
  123. package/dist/esm/operators/keying.js.map +1 -0
  124. package/dist/esm/operators/map.d.ts +16 -0
  125. package/dist/esm/operators/map.js +43 -0
  126. package/dist/esm/operators/map.js.map +1 -0
  127. package/dist/esm/operators/negate.d.ts +13 -0
  128. package/dist/esm/operators/negate.js +28 -0
  129. package/dist/esm/operators/negate.js.map +1 -0
  130. package/dist/esm/operators/orderBy.d.ts +38 -0
  131. package/dist/esm/operators/orderBy.js +102 -0
  132. package/dist/esm/operators/orderBy.js.map +1 -0
  133. package/dist/esm/operators/orderByBTree.d.ts +3 -0
  134. package/dist/esm/operators/output.d.ts +16 -0
  135. package/dist/esm/operators/output.js +46 -0
  136. package/dist/esm/operators/output.js.map +1 -0
  137. package/dist/esm/operators/pipe.d.ts +21 -0
  138. package/dist/esm/operators/pipe.js +9 -0
  139. package/dist/esm/operators/pipe.js.map +1 -0
  140. package/dist/esm/operators/reduce.d.ts +14 -0
  141. package/dist/esm/operators/reduce.js +99 -0
  142. package/dist/esm/operators/reduce.js.map +1 -0
  143. package/dist/esm/operators/topK.d.ts +32 -0
  144. package/dist/esm/operators/topK.js +39 -0
  145. package/dist/esm/operators/topK.js.map +1 -0
  146. package/dist/esm/operators/topKWithFractionalIndex.d.ts +58 -0
  147. package/dist/esm/operators/topKWithFractionalIndex.js +218 -0
  148. package/dist/esm/operators/topKWithFractionalIndex.js.map +1 -0
  149. package/dist/esm/operators/topKWithFractionalIndexBTree.d.ts +27 -0
  150. package/dist/esm/types.d.ts +30 -0
  151. package/dist/esm/utils.d.ts +40 -0
  152. package/dist/esm/utils.js +125 -0
  153. package/dist/esm/utils.js.map +1 -0
  154. package/package.json +6 -7
  155. package/src/operators/orderBy.ts +11 -29
  156. package/src/operators/topKWithFractionalIndex.ts +69 -57
  157. package/src/operators/topKWithFractionalIndexBTree.ts +14 -19
@@ -138,6 +138,9 @@ export function orderByWithFractionalIndexBase<
138
138
  ) => Ve,
139
139
  options?: OrderByOptions<Ve>
140
140
  ) {
141
+ type KeyType = T extends KeyValue<infer K, unknown> ? K : never
142
+ type ValueType = T extends KeyValue<unknown, infer V> ? V : never
143
+
141
144
  const limit = options?.limit ?? Infinity
142
145
  const offset = options?.offset ?? 0
143
146
  const comparator =
@@ -151,37 +154,16 @@ export function orderByWithFractionalIndexBase<
151
154
 
152
155
  return (
153
156
  stream: IStreamBuilder<T>
154
- ): IStreamBuilder<
155
- KeyValue<
156
- T extends KeyValue<infer K, unknown> ? K : never,
157
- [T extends KeyValue<unknown, infer V> ? V : never, string]
158
- >
159
- > => {
160
- type KeyType = T extends KeyValue<infer K, unknown> ? K : never
161
- type ValueType = T extends KeyValue<unknown, infer V> ? V : never
162
-
157
+ ): IStreamBuilder<[KeyType, [ValueType, string]]> => {
163
158
  return stream.pipe(
164
- map(
165
- ([key, value]) =>
166
- [
167
- null,
168
- [
169
- key,
170
- valueExtractor(
171
- value as T extends KeyValue<unknown, infer V> ? V : never
172
- ),
173
- ],
174
- ] as KeyValue<null, [KeyType, Ve]>
159
+ topKFunction(
160
+ (a: ValueType, b: ValueType) =>
161
+ comparator(valueExtractor(a), valueExtractor(b)),
162
+ {
163
+ limit,
164
+ offset,
165
+ }
175
166
  ),
176
- topKFunction((a, b) => comparator(a[1], b[1]), {
177
- limit,
178
- offset,
179
- }),
180
- map(([_, [[key], index]]) => [key, index] as KeyValue<KeyType, string>),
181
- innerJoin(stream),
182
- map(([key, [index, value]]) => {
183
- return [key, [value, index]] as KeyValue<KeyType, [ValueType, string]>
184
- }),
185
167
  consolidate()
186
168
  )
187
169
  }
@@ -2,10 +2,9 @@ import { generateKeyBetween } from "fractional-indexing"
2
2
  import { DifferenceStreamWriter, UnaryOperator } from "../graph.js"
3
3
  import { StreamBuilder } from "../d2.js"
4
4
  import { MultiSet } from "../multiset.js"
5
- import { Index } from "../indexes.js"
6
5
  import { binarySearch, globalObjectIdGenerator } from "../utils.js"
7
6
  import type { DifferenceStreamReader } from "../graph.js"
8
- import type { IStreamBuilder, KeyValue, PipedOperator } from "../types.js"
7
+ import type { IStreamBuilder, PipedOperator } from "../types.js"
9
8
 
10
9
  export interface TopKWithFractionalIndexOptions {
11
10
  limit?: number
@@ -158,31 +157,34 @@ class TopKArray<V> implements TopK<V> {
158
157
  * This operator maintains fractional indices for sorted elements
159
158
  * and only updates indices when elements move position
160
159
  */
161
- export class TopKWithFractionalIndexOperator<K, V1> extends UnaryOperator<
162
- [K, V1],
163
- [K, IndexedValue<V1>]
160
+ export class TopKWithFractionalIndexOperator<K, T> extends UnaryOperator<
161
+ [K, T],
162
+ [K, IndexedValue<T>]
164
163
  > {
165
- #index = new Index<K, V1>()
164
+ #index: Map<K, number> = new Map() // maps keys to their multiplicity
166
165
 
167
166
  /**
168
167
  * topK data structure that supports insertions and deletions
169
168
  * and returns changes to the topK.
170
169
  */
171
- #topK: TopK<TaggedValue<V1>>
170
+ #topK: TopK<TaggedValue<K, T>>
172
171
 
173
172
  constructor(
174
173
  id: number,
175
- inputA: DifferenceStreamReader<[K, V1]>,
176
- output: DifferenceStreamWriter<[K, [V1, string]]>,
177
- comparator: (a: V1, b: V1) => number,
174
+ inputA: DifferenceStreamReader<[K, T]>,
175
+ output: DifferenceStreamWriter<[K, IndexedValue<T>]>,
176
+ comparator: (a: T, b: T) => number,
178
177
  options: TopKWithFractionalIndexOptions
179
178
  ) {
180
179
  super(id, inputA, output)
181
180
  const limit = options.limit ?? Infinity
182
181
  const offset = options.offset ?? 0
183
- const compareTaggedValues = (a: TaggedValue<V1>, b: TaggedValue<V1>) => {
182
+ const compareTaggedValues = (
183
+ a: TaggedValue<K, T>,
184
+ b: TaggedValue<K, T>
185
+ ) => {
184
186
  // First compare on the value
185
- const valueComparison = comparator(untagValue(a), untagValue(b))
187
+ const valueComparison = comparator(getVal(a), getVal(b))
186
188
  if (valueComparison !== 0) {
187
189
  return valueComparison
188
190
  }
@@ -197,13 +199,13 @@ export class TopKWithFractionalIndexOperator<K, V1> extends UnaryOperator<
197
199
  protected createTopK(
198
200
  offset: number,
199
201
  limit: number,
200
- comparator: (a: TaggedValue<V1>, b: TaggedValue<V1>) => number
201
- ): TopK<TaggedValue<V1>> {
202
+ comparator: (a: TaggedValue<K, T>, b: TaggedValue<K, T>) => number
203
+ ): TopK<TaggedValue<K, T>> {
202
204
  return new TopKArray(offset, limit, comparator)
203
205
  }
204
206
 
205
207
  run(): void {
206
- const result: Array<[[K, [V1, string]], number]> = []
208
+ const result: Array<[[K, IndexedValue<T>], number]> = []
207
209
  for (const message of this.inputMessages()) {
208
210
  for (const [item, multiplicity] of message.getInner()) {
209
211
  const [key, value] = item
@@ -218,27 +220,25 @@ export class TopKWithFractionalIndexOperator<K, V1> extends UnaryOperator<
218
220
 
219
221
  processElement(
220
222
  key: K,
221
- value: V1,
223
+ value: T,
222
224
  multiplicity: number,
223
- result: Array<[[K, [V1, string]], number]>
225
+ result: Array<[[K, IndexedValue<T>], number]>
224
226
  ): void {
225
- const oldMultiplicity = this.#index.getMultiplicity(key, value)
226
- this.#index.addValue(key, [value, multiplicity])
227
- const newMultiplicity = this.#index.getMultiplicity(key, value)
227
+ const { oldMultiplicity, newMultiplicity } = this.addKey(key, multiplicity)
228
228
 
229
- let res: TopKChanges<TaggedValue<V1>> = {
229
+ let res: TopKChanges<TaggedValue<K, T>> = {
230
230
  moveIn: null,
231
231
  moveOut: null,
232
232
  }
233
233
  if (oldMultiplicity <= 0 && newMultiplicity > 0) {
234
234
  // The value was invisible but should now be visible
235
235
  // Need to insert it into the array of sorted values
236
- const taggedValue = tagValue(value)
236
+ const taggedValue = tagValue(key, value)
237
237
  res = this.#topK.insert(taggedValue)
238
238
  } else if (oldMultiplicity > 0 && newMultiplicity <= 0) {
239
239
  // The value was visible but should now be invisible
240
240
  // Need to remove it from the array of sorted values
241
- const taggedValue = tagValue(value)
241
+ const taggedValue = tagValue(key, value)
242
242
  res = this.#topK.delete(taggedValue)
243
243
  } else {
244
244
  // The value was invisible and it remains invisible
@@ -247,26 +247,45 @@ export class TopKWithFractionalIndexOperator<K, V1> extends UnaryOperator<
247
247
  }
248
248
 
249
249
  if (res.moveIn) {
250
- const valueWithoutTieBreaker = mapValue(res.moveIn, untagValue)
251
- result.push([[key, valueWithoutTieBreaker], 1])
250
+ const index = getIndex(res.moveIn)
251
+ const taggedValue = getValue(res.moveIn)
252
+ const k = getKey(taggedValue)
253
+ const val = getVal(taggedValue)
254
+ result.push([[k, [val, index]], 1])
252
255
  }
253
256
 
254
257
  if (res.moveOut) {
255
- const valueWithoutTieBreaker = mapValue(res.moveOut, untagValue)
256
- result.push([[key, valueWithoutTieBreaker], -1])
258
+ const index = getIndex(res.moveOut)
259
+ const taggedValue = getValue(res.moveOut)
260
+ const k = getKey(taggedValue)
261
+ const val = getVal(taggedValue)
262
+ result.push([[k, [val, index]], -1])
257
263
  }
258
264
 
259
265
  return
260
266
  }
267
+
268
+ private getMultiplicity(key: K): number {
269
+ return this.#index.get(key) ?? 0
270
+ }
271
+
272
+ private addKey(
273
+ key: K,
274
+ multiplicity: number
275
+ ): { oldMultiplicity: number; newMultiplicity: number } {
276
+ const oldMultiplicity = this.getMultiplicity(key)
277
+ const newMultiplicity = oldMultiplicity + multiplicity
278
+ if (newMultiplicity === 0) {
279
+ this.#index.delete(key)
280
+ } else {
281
+ this.#index.set(key, newMultiplicity)
282
+ }
283
+ return { oldMultiplicity, newMultiplicity }
284
+ }
261
285
  }
262
286
 
263
287
  /**
264
288
  * Limits the number of results based on a comparator, with optional offset.
265
- * This works on a keyed stream, where the key is the first element of the tuple.
266
- * The ordering is within a key group, i.e. elements are sorted within a key group
267
- * and the limit + offset is applied to that sorted group.
268
- * To order the entire stream, key by the same value for all elements such as null.
269
- *
270
289
  * Uses fractional indexing to minimize the number of changes when elements move positions.
271
290
  * Each element is assigned a fractional index that is lexicographically sortable.
272
291
  * When elements move, only the indices of the moved elements are updated, not all elements.
@@ -275,26 +294,22 @@ export class TopKWithFractionalIndexOperator<K, V1> extends UnaryOperator<
275
294
  * @param options - An optional object containing limit and offset properties
276
295
  * @returns A piped operator that orders the elements and limits the number of results
277
296
  */
278
- export function topKWithFractionalIndex<
279
- KType extends T extends KeyValue<infer K, infer _V> ? K : never,
280
- V1Type extends T extends KeyValue<KType, infer V> ? V : never,
281
- T,
282
- >(
283
- comparator: (a: V1Type, b: V1Type) => number,
297
+ export function topKWithFractionalIndex<KType, T>(
298
+ comparator: (a: T, b: T) => number,
284
299
  options?: TopKWithFractionalIndexOptions
285
- ): PipedOperator<T, KeyValue<KType, [V1Type, string]>> {
300
+ ): PipedOperator<[KType, T], [KType, IndexedValue<T>]> {
286
301
  const opts = options || {}
287
302
 
288
303
  return (
289
- stream: IStreamBuilder<T>
290
- ): IStreamBuilder<KeyValue<KType, [V1Type, string]>> => {
291
- const output = new StreamBuilder<KeyValue<KType, [V1Type, string]>>(
304
+ stream: IStreamBuilder<[KType, T]>
305
+ ): IStreamBuilder<[KType, IndexedValue<T>]> => {
306
+ const output = new StreamBuilder<[KType, IndexedValue<T>]>(
292
307
  stream.graph,
293
- new DifferenceStreamWriter<KeyValue<KType, [V1Type, string]>>()
308
+ new DifferenceStreamWriter<[KType, IndexedValue<T>]>()
294
309
  )
295
- const operator = new TopKWithFractionalIndexOperator<KType, V1Type>(
310
+ const operator = new TopKWithFractionalIndexOperator<KType, T>(
296
311
  stream.graph.getNextOperatorId(),
297
- stream.connectReader() as DifferenceStreamReader<KeyValue<KType, V1Type>>,
312
+ stream.connectReader(),
298
313
  output.writer,
299
314
  comparator,
300
315
  opts
@@ -324,24 +339,21 @@ export function getIndex<V>(indexedVal: IndexedValue<V>): FractionalIndex {
324
339
  return indexedVal[1]
325
340
  }
326
341
 
327
- function mapValue<V, W>(
328
- indexedVal: IndexedValue<V>,
329
- f: (value: V) => W
330
- ): IndexedValue<W> {
331
- return [f(getValue(indexedVal)), getIndex(indexedVal)]
332
- }
333
-
334
342
  export type Tag = number
335
- export type TaggedValue<V> = [V, Tag]
343
+ export type TaggedValue<K, V> = [K, V, Tag]
336
344
 
337
- function tagValue<V>(value: V): TaggedValue<V> {
338
- return [value, globalObjectIdGenerator.getId(value)]
345
+ function tagValue<K, V>(key: K, value: V): TaggedValue<K, V> {
346
+ return [key, value, globalObjectIdGenerator.getId(key)]
339
347
  }
340
348
 
341
- function untagValue<V>(tieBreakerTaggedValue: TaggedValue<V>): V {
349
+ function getKey<K, V>(tieBreakerTaggedValue: TaggedValue<K, V>): K {
342
350
  return tieBreakerTaggedValue[0]
343
351
  }
344
352
 
345
- function getTag<V>(tieBreakerTaggedValue: TaggedValue<V>): Tag {
353
+ function getVal<K, V>(tieBreakerTaggedValue: TaggedValue<K, V>): V {
346
354
  return tieBreakerTaggedValue[1]
347
355
  }
356
+
357
+ function getTag<K, V>(tieBreakerTaggedValue: TaggedValue<K, V>): Tag {
358
+ return tieBreakerTaggedValue[2]
359
+ }
@@ -7,8 +7,7 @@ import {
7
7
  getValue,
8
8
  indexedValue,
9
9
  } from "./topKWithFractionalIndex.js"
10
- import type { IStreamBuilder, KeyValue, PipedOperator } from "../types.js"
11
- import type { DifferenceStreamReader } from "../graph.js"
10
+ import type { IStreamBuilder, PipedOperator } from "../types.js"
12
11
  import type {
13
12
  IndexedValue,
14
13
  TaggedValue,
@@ -238,13 +237,13 @@ class TopKTree<V> implements TopK<V> {
238
237
  */
239
238
  export class TopKWithFractionalIndexBTreeOperator<
240
239
  K,
241
- V1,
242
- > extends TopKWithFractionalIndexOperator<K, V1> {
240
+ T,
241
+ > extends TopKWithFractionalIndexOperator<K, T> {
243
242
  protected override createTopK(
244
243
  offset: number,
245
244
  limit: number,
246
- comparator: (a: TaggedValue<V1>, b: TaggedValue<V1>) => number
247
- ): TopK<TaggedValue<V1>> {
245
+ comparator: (a: TaggedValue<K, T>, b: TaggedValue<K, T>) => number
246
+ ): TopK<TaggedValue<K, T>> {
248
247
  if (BTree === undefined) {
249
248
  throw new Error(
250
249
  `B+ tree not loaded. You need to call loadBTree() before using TopKWithFractionalIndexBTreeOperator.`
@@ -269,14 +268,10 @@ export class TopKWithFractionalIndexBTreeOperator<
269
268
  * @param options - An optional object containing limit and offset properties
270
269
  * @returns A piped operator that orders the elements and limits the number of results
271
270
  */
272
- export function topKWithFractionalIndexBTree<
273
- KType extends T extends KeyValue<infer K, infer _V> ? K : never,
274
- V1Type extends T extends KeyValue<KType, infer V> ? V : never,
275
- T,
276
- >(
277
- comparator: (a: V1Type, b: V1Type) => number,
271
+ export function topKWithFractionalIndexBTree<KType, T>(
272
+ comparator: (a: T, b: T) => number,
278
273
  options?: TopKWithFractionalIndexOptions
279
- ): PipedOperator<T, KeyValue<KType, [V1Type, string]>> {
274
+ ): PipedOperator<[KType, T], [KType, IndexedValue<T>]> {
280
275
  const opts = options || {}
281
276
 
282
277
  if (BTree === undefined) {
@@ -286,15 +281,15 @@ export function topKWithFractionalIndexBTree<
286
281
  }
287
282
 
288
283
  return (
289
- stream: IStreamBuilder<T>
290
- ): IStreamBuilder<KeyValue<KType, [V1Type, string]>> => {
291
- const output = new StreamBuilder<KeyValue<KType, [V1Type, string]>>(
284
+ stream: IStreamBuilder<[KType, T]>
285
+ ): IStreamBuilder<[KType, IndexedValue<T>]> => {
286
+ const output = new StreamBuilder<[KType, IndexedValue<T>]>(
292
287
  stream.graph,
293
- new DifferenceStreamWriter<KeyValue<KType, [V1Type, string]>>()
288
+ new DifferenceStreamWriter<[KType, IndexedValue<T>]>()
294
289
  )
295
- const operator = new TopKWithFractionalIndexOperator<KType, V1Type>(
290
+ const operator = new TopKWithFractionalIndexBTreeOperator<KType, T>(
296
291
  stream.graph.getNextOperatorId(),
297
- stream.connectReader() as DifferenceStreamReader<KeyValue<KType, V1Type>>,
292
+ stream.connectReader(),
298
293
  output.writer,
299
294
  comparator,
300
295
  opts