-
Notifications
You must be signed in to change notification settings - Fork 6
/
map.ts
95 lines (90 loc) · 2.39 KB
/
map.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
import {
EventStream,
EventStreamSeed,
Observer,
Property,
PropertySeed,
Event,
isValue,
valueEvent,
AtomSeed,
Subscribe,
isProperty,
isEventStream,
isEventStreamSeed,
isPropertySeed,
Desc,
} from "./abstractions"
import { cachedFn } from "./cachedFn"
import { StatelessEventStream } from "./eventstream"
import { EventStreamSeedImpl } from "./eventstream"
import { PropertySeedImpl } from "./property"
import { StatelessProperty } from "./property"
import { In } from "./transform"
export type MapResult<A, B, O> = O extends Property<any>
? Property<B>
: O extends PropertySeed<any>
? PropertySeed<B>
: O extends EventStream<any>
? EventStream<B>
: EventStreamSeed<B>
export interface MapOp<A, B> {
<O>(o: In<O, A>): MapResult<A, B, O>
}
export function map<A, B>(fn: (value: A) => B): MapOp<A, B>
export function map<A, B>(sampledProperty: Property<B>): MapOp<A, B>
export function map<A, B>(x: ((value: A) => B) | Property<B>): any {
return (o: any) => {
const desc = [o, "map", [x]] as Desc
let fn = isProperty(x) ? () => x.get() : x
if (isEventStream<A>(o)) {
return new StatelessEventStream(
desc,
mapSubscribe(o.subscribe.bind(o), fn),
o.getScope()
)
} else if (isEventStreamSeed<A>(o)) {
const source = o.consume()
return new EventStreamSeedImpl(
desc,
mapSubscribe(source.subscribe.bind(source), fn)
)
} else if (isProperty<A>(o)) {
fn = cachedFn(fn)
return new StatelessProperty(
desc,
() => fn(o.get()),
mapSubscribe(o.onChange.bind(o), fn),
o.getScope()
)
} else if (isPropertySeed<A>(o)) {
const source = o.consume()
fn = cachedFn(fn)
return new PropertySeedImpl(
desc,
() => fn(source.get()),
mapSubscribe(source.onChange.bind(source), fn)
)
}
throw Error("Unknown observable")
}
}
export function mapSubscribe<A, B>(
subscribe: Subscribe<A>,
fn: (value: A) => B
): Subscribe<B> {
return (onValue, onEnd) => subscribe(mapObserver(onValue, fn), onEnd)
}
export function mapObserver<A, B>(
observer: Observer<B>,
fn: (value: A) => B
): Observer<A> {
return (event: A) => observer(fn(event))
}
export function mapEvent<A, B>(event: Event<A>, fn: (value: A) => B): Event<B> {
if (isValue(event)) {
return valueEvent(fn(event.value))
} else {
return event
}
}