Mirror: 🎩 A tiny but capable push & pull stream library for TypeScript and Flow
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Uncurry most external API predicates/transform callbacks

+50 -50
+17 -17
__tests__/wonka_test.re
··· 162 162 let nums = [||]; 163 163 let talkback = ref((._: Wonka_types.talkbackT) => ()); 164 164 165 - Wonka.map((_) => { 165 + Wonka.map((._) => { 166 166 let res = num^; 167 167 num := num^ + 1; 168 168 res ··· 191 191 }); 192 192 193 193 testPromise("follows the spec for listenables", () => { 194 - Wonka_thelpers.testWithListenable(Wonka.map(x => x)) 194 + Wonka_thelpers.testWithListenable(Wonka.map((.x) => x)) 195 195 |> Js.Promise.then_(x => { 196 196 expect(x) 197 197 |> toEqual(([||], [| Push(1), Push(2), End |])) ··· 202 202 testPromise("ends itself and source when its talkback receives the End signal", () => { 203 203 let end_: talkbackT = Close; 204 204 205 - Wonka_thelpers.testTalkbackEnd(Wonka.map(x => x)) 205 + Wonka_thelpers.testTalkbackEnd(Wonka.map((.x) => x)) 206 206 |> Js.Promise.then_(x => { 207 207 expect(x) 208 208 |> toEqual(([| end_ |], [| Push(1) |])) ··· 219 219 let nums = [||]; 220 220 let talkback = ref((._: Wonka_types.talkbackT) => ()); 221 221 222 - Wonka.filter(x => x mod 2 === 0, sink => { 222 + Wonka.filter((.x) => x mod 2 === 0, sink => { 223 223 sink(.Start((.signal) => { 224 224 switch (signal) { 225 225 | Pull => { ··· 248 248 }); 249 249 250 250 testPromise("follows the spec for listenables", () => { 251 - Wonka_thelpers.testWithListenable(Wonka.filter((_) => true)) 251 + Wonka_thelpers.testWithListenable(Wonka.filter((._) => true)) 252 252 |> Js.Promise.then_(x => { 253 253 expect(x) 254 254 |> toEqual(([||], [| Push(1), Push(2), End |])) ··· 257 257 }); 258 258 259 259 testPromise("follows the spec for listenables when filtering", () => { 260 - Wonka_thelpers.testWithListenable(Wonka.filter((_) => false)) 260 + Wonka_thelpers.testWithListenable(Wonka.filter((._) => false)) 261 261 |> Js.Promise.then_(x => { 262 262 expect(x) 263 263 |> toEqual(([| Pull, Pull |], [| End |])) ··· 268 268 testPromise("ends itself and source when its talkback receives the End signal", () => { 269 269 let end_: talkbackT = Close; 270 270 271 - Wonka_thelpers.testTalkbackEnd(Wonka.filter((_) => true)) 271 + Wonka_thelpers.testTalkbackEnd(Wonka.filter((._) => true)) 272 272 |> Js.Promise.then_(x => { 273 273 expect(x) 274 274 |> toEqual(([| end_ |], [| Push(1) |])) ··· 742 742 let talkback = ref((._: Wonka_types.talkbackT) => ()); 743 743 let num = ref(1); 744 744 745 - let source = Wonka.takeWhile(x => x <= 2, sink => sink(.Start((.signal) => { 745 + let source = Wonka.takeWhile((.x) => x <= 2, sink => sink(.Start((.signal) => { 746 746 switch (signal) { 747 747 | Pull => { 748 748 let i = num^; ··· 774 774 let talkback = ref((._: Wonka_types.talkbackT) => ()); 775 775 let num = ref(1); 776 776 777 - let source = Wonka.takeWhile(x => x <= 5, sink => sink(.Start((.signal) => { 777 + let source = Wonka.takeWhile((.x) => x <= 5, sink => sink(.Start((.signal) => { 778 778 switch (signal) { 779 779 | Pull => { 780 780 let i = num^; ··· 806 806 }); 807 807 808 808 testPromise("follows the spec for listenables", () => { 809 - Wonka_thelpers.testWithListenable(Wonka.takeWhile((_) => true)) 809 + Wonka_thelpers.testWithListenable(Wonka.takeWhile((._) => true)) 810 810 |> Js.Promise.then_(x => { 811 811 expect(x) 812 812 |> toEqual(([||], [| Push(1), Push(2), End |])) ··· 817 817 testPromise("follows the spec for listenables when ending the source", () => { 818 818 let end_: talkbackT = Close; 819 819 820 - Wonka_thelpers.testWithListenable(Wonka.takeWhile((_) => false)) 820 + Wonka_thelpers.testWithListenable(Wonka.takeWhile((._) => false)) 821 821 |> Js.Promise.then_(x => { 822 822 expect(x) 823 823 |> toEqual(([| end_ |], [| End |])) ··· 828 828 testPromise("ends itself and source when its talkback receives the End signal", () => { 829 829 let end_: talkbackT = Close; 830 830 831 - Wonka_thelpers.testTalkbackEnd(Wonka.takeWhile((_) => true)) 831 + Wonka_thelpers.testTalkbackEnd(Wonka.takeWhile((._) => true)) 832 832 |> Js.Promise.then_(x => { 833 833 expect(x) 834 834 |> toEqual(([| end_ |], [| Push(1) |])) ··· 1023 1023 let talkback = ref((._: Wonka_types.talkbackT) => ()); 1024 1024 let num = ref(1); 1025 1025 1026 - let source = Wonka.skipWhile(x => x <= 2, sink => sink(.Start((.signal) => { 1026 + let source = Wonka.skipWhile((.x) => x <= 2, sink => sink(.Start((.signal) => { 1027 1027 switch (signal) { 1028 1028 | Pull when num^ <= 4 => { 1029 1029 let i = num^; ··· 1051 1051 }); 1052 1052 1053 1053 testPromise("follows the spec for listenables", () => { 1054 - Wonka_thelpers.testWithListenable(Wonka.skipWhile((_) => false)) 1054 + Wonka_thelpers.testWithListenable(Wonka.skipWhile((._) => false)) 1055 1055 |> Js.Promise.then_(x => { 1056 1056 expect(x) 1057 1057 |> toEqual(([||], [| Push(1), Push(2), End |])) ··· 1060 1060 }); 1061 1061 1062 1062 testPromise("follows the spec for listenables when skipping the source", () => { 1063 - Wonka_thelpers.testWithListenable(Wonka.skipWhile((_) => true)) 1063 + Wonka_thelpers.testWithListenable(Wonka.skipWhile((._) => true)) 1064 1064 |> Js.Promise.then_(x => { 1065 1065 expect(x) 1066 1066 |> toEqual(([| Pull, Pull |], [| End |])) ··· 1071 1071 testPromise("ends itself and source when its talkback receives the End signal", () => { 1072 1072 let end_: talkbackT = Close; 1073 1073 1074 - Wonka_thelpers.testTalkbackEnd(Wonka.skipWhile((_) => false)) 1074 + Wonka_thelpers.testTalkbackEnd(Wonka.skipWhile((._) => false)) 1075 1075 |> Js.Promise.then_(x => { 1076 1076 expect(x) 1077 1077 |> toEqual(([| end_ |], [| Push(1) |])) ··· 1288 1288 1289 1289 input 1290 1290 |> Wonka.fromArray 1291 - |> Wonka.map(x => string_of_int(x)) 1291 + |> Wonka.map((.x) => string_of_int(x)) 1292 1292 |> Wonka.forEach((.x) => ignore(Js.Array.push(x, actual))); 1293 1293 1294 1294 expect(output) |> toEqual(output)
+4 -4
src/web/wonkaJs.re
··· 77 77 })); 78 78 }); 79 79 80 - let debounce = debounceF => curry(source => curry(sink => { 80 + let debounce = f => curry(source => curry(sink => { 81 81 let gotEndSignal = ref(false); 82 82 let id: ref(option(Js.Global.timeoutId)) = ref(None); 83 83 ··· 109 109 id := None; 110 110 sink(.signal); 111 111 if (gotEndSignal^) sink(.End); 112 - }, debounceF(x))); 112 + }, f(.x))); 113 113 } 114 114 | End => { 115 115 gotEndSignal := true; ··· 123 123 }); 124 124 })); 125 125 126 - let throttle = throttleF => curry(source => curry(sink => { 126 + let throttle = f => curry(source => curry(sink => { 127 127 let skip = ref(false); 128 128 let id: ref(option(Js.Global.timeoutId)) = ref(None); 129 129 let clearTimeout = () => ··· 155 155 id := Some(Js.Global.setTimeout(() => { 156 156 id := None; 157 157 skip := false; 158 - }, throttleF(x))); 158 + }, f(.x))); 159 159 sink(.signal); 160 160 } 161 161 | Push(_) => ()
+3 -3
src/web/wonkaJs.rei
··· 44 44 /* Takes a projection to a period in milliseconds and a source, and creates 45 45 a listenable source that emits the last emitted value if no other value 46 46 has been emitted during the passed debounce period. */ 47 - let debounce: ('a => int, sourceT('a), sinkT('a)) => unit; 47 + let debounce: ((.'a) => int, sourceT('a), sinkT('a)) => unit; 48 48 49 49 /* Takes a projection to a period in milliseconds and a source, and creates 50 50 a listenable source that ignores values after the last emitted value for 51 51 the duration of the returned throttle period. */ 52 - let throttle: ('a => int, sourceT('a), sinkT('a)) => unit; 52 + let throttle: ((.'a) => int, sourceT('a), sinkT('a)) => unit; 53 53 54 54 /* Takes a notifier source and an input source, and creates a sink & source. 55 55 When the notifier emits a value, it will emit the value that it most recently ··· 63 63 64 64 /* Converts a stream into a promise by resolving to the last value of the 65 65 stream. */ 66 - let toPromise: (sourceT('a)) => Js.Promise.t('a); 66 + let toPromise: sourceT('a) => Js.Promise.t('a);
+16 -16
src/wonka.re
··· 38 38 }; 39 39 40 40 let make = f => curry(sink => { 41 - let teardown = f({ 41 + let teardown = f(.{ 42 42 next: value => sink(.Push(value)), 43 43 complete: () => sink(.End) 44 44 }); 45 45 46 46 sink(.Start((.signal) => { 47 47 switch (signal) { 48 - | Close => teardown() 48 + | Close => teardown(.) 49 49 | Pull => () 50 50 } 51 51 })); ··· 176 176 source((.signal) => sink(. 177 177 switch (signal) { 178 178 | Start(x) => Start(x) 179 - | Push(x) => Push(f(x)) 179 + | Push(x) => Push(f(.x)) 180 180 | End => End 181 181 } 182 182 )); ··· 185 185 let filter = f => curry(source => curry(sink => { 186 186 captureTalkback(source, (.signal, talkback) => { 187 187 switch (signal) { 188 - | Push(x) when !f(x) => talkback(.Pull) 188 + | Push(x) when !f(.x) => talkback(.Pull) 189 189 | _ => sink(.signal) 190 190 } 191 191 }); ··· 258 258 tb(.Pull); 259 259 } 260 260 | Push(x) when !state.ended => { 261 - applyInnerSource(f(x)); 261 + applyInnerSource(f(.x)); 262 262 state.outerTalkback(.Pull); 263 263 } 264 264 | Push(_) => () ··· 281 281 })); 282 282 })); 283 283 284 - let merge = sources => mergeMap(identity, fromArray(sources)); 285 - let mergeAll = source => mergeMap(identity, source); 284 + let merge = sources => mergeMap((.x) => x, fromArray(sources)); 285 + let mergeAll = source => mergeMap((.x) => x, source); 286 286 let flatten = mergeAll; 287 287 288 288 type concatMapStateT('a) = { ··· 312 312 state.innerTalkback = talkbackPlaceholder; 313 313 314 314 switch (Rebel.MutableQueue.pop(state.inputQueue)) { 315 - | Some(input) => applyInnerSource(f(input)) 315 + | Some(input) => applyInnerSource(f(.input)) 316 316 | None when state.ended => sink(.End) 317 317 | None => () 318 318 }; ··· 347 347 if (state.innerActive) { 348 348 Rebel.MutableQueue.add(state.inputQueue, x); 349 349 } else { 350 - applyInnerSource(f(x)); 350 + applyInnerSource(f(.x)); 351 351 } 352 352 353 353 state.outerTalkback(.Pull); ··· 370 370 })); 371 371 })); 372 372 373 - let concatAll = source => concatMap(identity, source); 374 - let concat = sources => concatMap(identity, fromArray(sources)); 373 + let concatAll = source => concatMap((.x) => x, source); 374 + let concat = sources => concatMap((.x) => x, fromArray(sources)); 375 375 376 376 type switchMapStateT('a) = { 377 377 mutable outerTalkback: (.talkbackT) => unit, ··· 427 427 state.innerTalkback(.Close); 428 428 state.innerTalkback = talkbackPlaceholder; 429 429 } 430 - applyInnerSource(f(x)); 430 + applyInnerSource(f(.x)); 431 431 state.outerTalkback(.Pull); 432 432 } 433 433 | Push(_) => () ··· 649 649 }); 650 650 })); 651 651 652 - let takeWhile = predicate => curry(source => curry(sink => { 652 + let takeWhile = f => curry(source => curry(sink => { 653 653 let ended = ref(false); 654 654 let talkback = ref(talkbackPlaceholder); 655 655 ··· 665 665 } 666 666 | End => () 667 667 | Push(x) when !ended^ => { 668 - if (!predicate(x)) { 668 + if (!f(.x)) { 669 669 ended := true; 670 670 sink(.End); 671 671 talkback^(.Close); ··· 762 762 }); 763 763 })); 764 764 765 - let skipWhile = predicate => curry(source => curry(sink => { 765 + let skipWhile = f => curry(source => curry(sink => { 766 766 let skip = ref(true); 767 767 768 768 captureTalkback(source, (.signal, talkback) => { 769 769 switch (signal) { 770 770 | Push(x) when skip^ => { 771 - if (predicate(x)) { 771 + if (f(.x)) { 772 772 talkback(.Pull); 773 773 } else { 774 774 skip := false;
+8 -8
src/wonka.rei
··· 13 13 for constructing any kind of asynchronous stream. The return 14 14 callback from the passed observer function will be called when 15 15 the stream is closed or ends */ 16 - let make: (observerT('a) => (unit => unit), sinkT('a)) => unit; 16 + let make: ((.observerT('a)) => teardownT, sinkT('a)) => unit; 17 17 18 18 /* Accepts a list and creates a pullable source for that list. 19 19 The source will emit events when being pulled until the list ··· 45 45 and creates a sink & source. 46 46 All values that it receives will be transformed using the mapping 47 47 function and emitted on the new source */ 48 - let map: ('a => 'b, sourceT('a), sinkT('b)) => unit; 48 + let map: ((.'a) => 'b, sourceT('a), sinkT('b)) => unit; 49 49 50 50 /* Takes a predicate function returning a boolean, and a source, 51 51 and creates a sink & source. 52 52 All values that it receives will be filtered using the predicate, 53 53 and only truthy values will be passed on to the new source. 54 54 The sink will attempt to pull a new value when one was filtered. */ 55 - let filter: ('a => bool, sourceT('a), sinkT('a)) => unit; 55 + let filter: ((.'a) => bool, sourceT('a), sinkT('a)) => unit; 56 56 57 57 /* Takes a reducer function, a seed value, and a source, and creates 58 58 a sink & source. ··· 66 66 and a source, and creates a sink & source. 67 67 The mapping function is called with each value it receives and 68 68 the resulting inner source is merged into the output source. */ 69 - let mergeMap: ('a => sourceT('b), sourceT('a), sinkT('b)) => unit; 69 + let mergeMap: ((.'a) => sourceT('b), sourceT('a), sinkT('b)) => unit; 70 70 71 71 /* Takes a mapping function from one types to a source output, 72 72 and a source, and creates a sink & source. 73 73 The mapping function is called with each value it receives and 74 74 the latest inner source is merged into the output source. When 75 75 a new value comes in the previous source is dicarded. */ 76 - let switchMap: ('a => sourceT('b), sourceT('a), sinkT('b)) => unit; 76 + let switchMap: ((.'a) => sourceT('b), sourceT('a), sinkT('b)) => unit; 77 77 78 78 /* Takes a mapping function from one types to a source output, 79 79 and a source, and creates a sink & source. 80 80 The mapping function is called with each value it receives and 81 81 the resulting inner sources are subscribed to and piped through 82 82 to the output source in order. */ 83 - let concatMap: ('a => sourceT('b), sourceT('a), sinkT('b)) => unit; 83 + let concatMap: ((.'a) => sourceT('b), sourceT('a), sinkT('b)) => unit; 84 84 85 85 /* Takes an array of sources and creates a sink & source. 86 86 All values that the sink receives from all sources will be passed through ··· 127 127 It will emit values that the sink receives until the predicate returns false 128 128 for a value, at which point it will end the source and the returned, new 129 129 source. */ 130 - let takeWhile: ('a => bool, sourceT('a), sinkT('a)) => unit; 130 + let takeWhile: ((.'a) => bool, sourceT('a), sinkT('a)) => unit; 131 131 132 132 /* Takes a notifier source and an input source, and creates a sink & source. 133 133 It will not emit values that the sink receives until the notifier source ··· 150 150 It will not emit values that the sink receives until the passed predicate 151 151 returns false for a value, at which point it will start acting like a noop 152 152 operator, passing through every signal. */ 153 - let skipWhile: ('a => bool, sourceT('a), sinkT('a)) => unit; 153 + let skipWhile: ((.'a) => bool, sourceT('a), sinkT('a)) => unit; 154 154 155 155 /* Takes a notifier source and an input source, and creates a sink & source. 156 156 It will not emit values that the sink receives until the notifier source
-2
src/wonka_helpers.re
··· 1 1 open Wonka_types; 2 2 3 - external identity: 'a => 'a = "%identity"; 4 - 5 3 let talkbackPlaceholder = (._: talkbackT) => (); 6 4 7 5 let captureTalkback = (
+2
src/wonka_types.re
··· 38 38 type sinkT('a) = (.signalT('a)) => unit; 39 39 type sourceT('a) = sinkT('a) => unit; 40 40 41 + type teardownT = (.unit) => unit; 42 + 41 43 type subscriptionT = { 42 44 unsubscribe: unit => unit 43 45 };