/
data-snapshot-observable.ts
117 lines (98 loc) · 3.46 KB
/
data-snapshot-observable.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { database } from 'firebase'
import { Observable } from 'rxjs/Observable'
import { map } from 'rxjs/operator/map'
import { mergeMap } from 'rxjs/operator/mergeMap'
import { toArray } from 'rxjs/operator/toArray'
export interface ExtendedDataSnapshot extends database.DataSnapshot {
prevKey?: string
}
export class DataSnapshotObservable<T> extends Observable<ExtendedDataSnapshot> {
exists(): Observable<boolean> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.exists());
}
children(): Observable<DataSnapshotObservable<T[keyof T]>> {
return map.call(this,
(snapshot: ExtendedDataSnapshot) => new DataSnapshotObservable<T[keyof T]>(sub => {
snapshot.forEach(childSnapshot => {
sub.next(childSnapshot);
return false
})
sub.complete()
}))
}
/**
* This operator takes the result of .val() for all children of the snapshot and emits
* them as an array.
* Contents of source snapshot:
* ```
* {
* childA: { prop: 'Hello' },
* childB: { prop: 'World!' },
* }
* ```
* Result of operator:
* ```
* [
* { prop: 'Hello' },
* { prop: 'World!' },
* ]
* ```
* @returns {Observable<C[]>}
*/
toValArray(): Observable<T[keyof T][]> {
return mergeMap.call(this.children(),
(children: DataSnapshotObservable<T[keyof T]>) => toArray.call(children.val()))
}
values(): Observable<T[keyof T][]> {
return this.toValArray();
}
keys(): Observable<string[]> {
return mergeMap.call(this.children(),
(children: DataSnapshotObservable<T[keyof T]>) => toArray.call(children.key()))
}
list(): Observable<{ val: T[keyof T], key: string }[]> {
return mergeMap.call(this.children(),
(children: DataSnapshotObservable<T[keyof T]>) => toArray.call(children.entry()))
}
entry(): Observable<{ val: T, key: string }> {
return map.call(this,
(snapshot: ExtendedDataSnapshot) => ({ val: snapshot.val(), key: snapshot.key }))
}
key(): Observable<string> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.key)
}
/**
* When listening to events such as {@link Event.ChildMoved} the snapshot includes
* the key of the child before this snapshots one. This operator maps to this key.
* @returns {Observable<string>}
*/
prevKey(): Observable<string> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.prevKey)
}
val(): Observable<T> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.val())
}
getPriority(): Observable<number | string> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.getPriority())
}
exportVal(): Observable<T> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.exportVal())
}
hasChild(path: string): Observable<boolean> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.hasChild(path))
}
hasChildren(): Observable<boolean> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.hasChildren())
}
numChildren(): Observable<number> {
return map.call(this, (snapshot: ExtendedDataSnapshot) => snapshot.numChildren())
}
child<P extends keyof T>(path: P): DataSnapshotObservable<T[P]> {
return new DataSnapshotObservable<T[P]>(sub => {
const subscription = map.call(this,
(snapshot: ExtendedDataSnapshot) => snapshot.child(path))
.subscribe(sub)
return () => subscription.unsubscribe()
})
}
}