Skip to content

Commit 903c929

Browse files
volivaVictor Oliva
authored andcommitted
feat(utils/combineKeys): emit set with changed keys
1 parent 13fa3af commit 903c929

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

packages/utils/src/combineKeys.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,60 @@ describe("combineKeys", () => {
204204
})
205205
})
206206
})
207+
208+
describe("change set", () => {
209+
it("contains all of the keys initially present in the stream", () => {
210+
scheduler().run(({ expectObservable }) => {
211+
const keys = concat(of(["a", "b", "c"]), NEVER)
212+
213+
const result = combineKeys(keys, (v) => of(v)).pipe(
214+
map((x) => Array.from(x.changes)),
215+
)
216+
217+
expectObservable(result).toBe("x", {
218+
x: ["a", "b", "c"],
219+
})
220+
})
221+
})
222+
223+
it("only contains those values that have changed from the previous emission", () => {
224+
scheduler().run(({ expectObservable, cold }) => {
225+
const keys = concat(of(["a", "b", "c"]), NEVER)
226+
const a = concat(["1"], cold("--2--"))
227+
const b = concat(["1"], cold("---2-"))
228+
const c = concat(["1"], cold("-----"))
229+
const expected = " x-yz-"
230+
const streams: Record<string, Observable<string>> = { a, b, c }
231+
232+
const result = combineKeys(keys, (v) => streams[v]).pipe(
233+
map((x) => Array.from(x.changes)),
234+
)
235+
236+
expectObservable(result).toBe(expected, {
237+
x: ["a", "b", "c"],
238+
y: ["a"],
239+
z: ["b"],
240+
})
241+
})
242+
})
243+
244+
it("contains removed keys", () => {
245+
scheduler().run(({ expectObservable, cold }) => {
246+
const keys = cold("x--y-", {
247+
x: ["a", "b", "c"],
248+
y: ["b"],
249+
})
250+
const expected = " x--y-"
251+
252+
const result = combineKeys(keys, (v) => of(v)).pipe(
253+
map((x) => Array.from(x.changes)),
254+
)
255+
256+
expectObservable(result).toBe(expected, {
257+
x: ["a", "b", "c"],
258+
y: ["a", "c"],
259+
})
260+
})
261+
})
262+
})
207263
})

packages/utils/src/combineKeys.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { Observable, Subscription } from "rxjs"
22

3+
export interface MapWithChanges<K, V> extends Map<K, V> {
4+
changes: Set<K>
5+
}
6+
37
/**
48
* Creates a stream that combines the result of the streams from each key of the input stream.
59
*
@@ -10,26 +14,32 @@ import { Observable, Subscription } from "rxjs"
1014
export const combineKeys = <K, T>(
1115
keys$: Observable<Array<K> | Set<K>>,
1216
getInner$: (key: K) => Observable<T>,
13-
): Observable<Map<K, T>> =>
17+
): Observable<MapWithChanges<K, T>> =>
1418
new Observable((observer) => {
1519
const innerSubscriptions = new Map<K, Subscription>()
20+
let changes = new Set<K>()
1621
const currentValue = new Map<K, T>()
1722
let updatingSource = false
1823
const next = () => {
19-
if (!updatingSource) observer.next(new Map(currentValue))
24+
if (!updatingSource) {
25+
const result = Object.assign(new Map(currentValue), {
26+
changes,
27+
})
28+
changes = new Set<K>()
29+
observer.next(result)
30+
}
2031
}
2132

2233
const subscription = keys$.subscribe(
2334
(nextKeysArr) => {
2435
updatingSource = true
2536
const nextKeys = new Set(nextKeysArr)
26-
let changes = false
2737
innerSubscriptions.forEach((sub, key) => {
2838
if (!nextKeys.has(key)) {
2939
sub.unsubscribe()
3040
innerSubscriptions.delete(key)
3141
if (currentValue.has(key)) {
32-
changes = true
42+
changes.add(key)
3343
currentValue.delete(key)
3444
}
3545
} else {
@@ -42,7 +52,7 @@ export const combineKeys = <K, T>(
4252
getInner$(key).subscribe(
4353
(x) => {
4454
if (!currentValue.has(key) || currentValue.get(key) !== x) {
45-
changes = true
55+
changes.add(key)
4656
currentValue.set(key, x)
4757
next()
4858
}
@@ -54,7 +64,7 @@ export const combineKeys = <K, T>(
5464
)
5565
})
5666
updatingSource = false
57-
if (changes) next()
67+
if (changes.size) next()
5868
},
5969
(e) => {
6070
observer.error(e)

packages/utils/src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export { collectValues } from "./collectValues"
22
export { collect } from "./collect"
3-
export { combineKeys } from "./combineKeys"
3+
export { combineKeys, MapWithChanges } from "./combineKeys"
44
export { getGroupedObservable } from "./getGroupedObservable"
55
export { createSignal } from "./createSignal"
66
export { createKeyedSignal } from "./createKeyedSignal"

0 commit comments

Comments
 (0)