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

Update docs for TS-only

+5 -16
README.md
···
# Wonka
-
A fast push & pull stream library for Reason, loosely following the [callbag spec](https://github.com/callbag/callbag)
-
> **NOTE:** The `master` branch currently points to the v4 Release Candidate version!
-
> If you're looking for v3, [please check the `v3.2.2`](https://github.com/kitten/wonka/tree/v3.2.2)
<br>
<a href="https://npmjs.com/package/wonka">
···
the [callbag spec](https://github.com/callbag/callbag). It exposes a set of helpers to create streams,
which are sources of multiple values, which allow you to create, transform
and consume event streams or iterable sets of data.
-
-
Wonka is written in [Reason](https://reasonml.github.io/), a dialect of OCaml, and can hence be used
-
for native applications. It is also compiled using [BuckleScript](https://bucklescript.github.io) to plain
-
JavaScript and has typings for [TypeScript](https://www.typescriptlang.org/) and [Flow](https://flow.org/).
-
-
This means that out of the box Wonka is usable in any project that use the following:
-
-
- Plain JavaScript
-
- TypeScript
-
- Flow
-
- Reason/OCaml with BuckleScript
-
- Reason/OCaml with `bs-native`
-
- Reason/OCaml with Dune and Esy
## [Documentation](https://wonka.kitten.sh/)
···
# Wonka
+
A tiny but capable push & pull stream library for TypeScript and Flow,
+
loosely following the [callbag spec](https://github.com/callbag/callbag)
+
> **NOTE:** The currently released version v6 is only compatible now with TypeScript, Flow, and JavaScript.
+
> If you're looking for Reason/OCaml/esy/dune support, please check v5, and if you're looking for the legacy version
+
> of this library check v4.
<br>
<a href="https://npmjs.com/package/wonka">
···
the [callbag spec](https://github.com/callbag/callbag). It exposes a set of helpers to create streams,
which are sources of multiple values, which allow you to create, transform
and consume event streams or iterable sets of data.
## [Documentation](https://wonka.kitten.sh/)
+37 -328
docs/api/operators.md
···
In combination with `interval` this can be used to group values in chunks regularly.
-
```reason
-
Wonka.interval(50)
-
|> Wonka.buffer(Wonka.interval(100))
-
|> Wonka.take(2)
-
|> Wonka.subscribe((. buffer) => {
-
Js.Array.forEach(num => print_int(num), buffer);
-
print_endline(";");
-
});
-
/* Prints 1 2; 2 3 to the console. */
-
```
-
-
``` typescript
import { pipe, interval, buffer, take, subscribe } from 'wonka';
pipe(
interval(50),
buffer(interval(100)),
take(2),
-
subscribe(buffer => {
-
buffer.forEach(x => console.log(x));
console.log(';');
})
); // Prints 1 2; 2 3 to the console.
···
`combine` two sources together to a single source. The emitted value will be a combination of the two sources, with all values from the first source being emitted with the first value of the second source _before_ values of the second source are emitted.
-
```reason
-
let sourceOne = Wonka.fromArray([|1, 2, 3|]);
-
let sourceTwo = Wonka.fromArray([|4, 5, 6|]);
-
-
Wonka.combine(sourceOne)
-
|> sourceTwo
-
|> Wonka.subscribe((. (a, b)) => print_int(a + b));
-
-
/* Prints 56789 (1+4, 2+4, 3+4, 3+5, 3+6) to the console. */
-
```
-
```typescript
import { fromArray, pipe, combine, subscribe } from 'wonka';
···
`concat` will combine two sources together, subscribing to the next source after the previous source completes.
-
```reason
-
let sourceOne = Wonka.fromArray([|1, 2, 3|]);
-
let sourceTwo = Wonka.fromArray([|6, 5, 4|]);
-
-
Wonka.concat([|sourceOne, sourceTwo|])
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 2 3 6 5 4 to the console. */
-
```
-
```typescript
import { fromArray, pipe, concat, subscribe } from 'wonka';
···
pipe(
concat([sourceOne, sourceTwo]),
-
subscribe(val => console.log(val))
); // Prints 1 2 3 6 5 4 to the console.
```
···
It's very similar to `concat`, but instead accepts a source of sources as an input.
-
```reason
-
let sourceOne = Wonka.fromArray([|1, 2, 3|]);
-
let sourceTwo = Wonka.fromArray([|6, 5, 4|]);
-
-
Wonka.fromList([sourceOne, sourceTwo])
-
|> Wonka.concatAll
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 2 3 6 5 4 to the console. */
-
```
-
```typescript
import { pipe, fromArray, concatAll, subscribe } from 'wonka';
···
pipe(
fromArray([sourceOne, sourceTwo]),
concatAll,
-
subscribe(val => console.log(val))
); // Prints 1 2 3 6 5 4 to the console.
```
···
`concatMap` allows you to map values of an outer source to an inner source. The sink will not dispatch the `Pull` signal until the previous value has been emitted. This is in contrast to `mergeMap`, which will dispatch the `Pull` signal for new values even if the previous value has not yet been emitted.
-
```reason
-
let source = Wonka.fromArray([|1, 2, 3, 4, 5, 6|]);
-
-
source
-
|> Wonka.concatMap((. _val) =>
-
Wonka.delay(_val * 1000, Wonka.fromValue(_val))
-
)
-
|> Wonka.subscribe((. _val) => print_int(_val));
-
-
/* After 1s, 1 will be emitted. After an additional 2s, 2 will be emitted.
-
After an additional 3s, 3 will be emitted. After an additional 4s, 4 will be emitted.
-
After an additional 5s, 5 will be emitted. After an additional 6s, 6 will be emitted. */
-
```
-
```typescript
import { fromArray, pipe, concatMap, delay, fromValue, subscribe } from 'wonka';
···
pipe(
source,
-
concatMap(val => {
-
return pipe(
-
fromValue(val),
-
delay(val * 1000)
-
);
}),
-
subscribe(val => console.log(val))
);
```
-
## delay
`delay` delays all emitted values of a source by the given amount of milliseconds.
-
> _Note:_ This operator is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
Wonka.fromList([1, 2])
-
|> Wonka.delay(10)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* waits 10ms then prints 1, waits 10ms then prints 2, waits 10ms then ends */
-
```
-
```typescript
import { pipe, fromArray, delay, subscribe } from 'wonka';
···
a given amount of milliseconds. Once this threshold of silence has been reached, the
last value that has been received will be emitted.
-
> _Note:_ This operator is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
let sourceA = Wonka.interval(10)
-
|> Wonka.take(5);
-
let sourceB = Wonka.fromValue(1);
-
-
Wonka.concat([|sourceA, sourceB|])
-
|> Wonka.debounce((. _x) => 20)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* The five values from sourceA will be omitted */
-
/* After these values and after 20ms `1` will be logged */
-
```
-
```typescript
import { pipe, interval, take, fromValue, concat, debounce, subscribe } from 'wonka';
···
`filter` will remove values from a source by passing them through an iteratee that returns a `bool`.
-
```reason
-
let isEven = (. n) => n mod 2 === 0;
-
-
Wonka.fromArray([|1, 2, 3, 4, 5, 6|])
-
|> Wonka.filter(isEven)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 246 to the console. */
-
```
-
```typescript
import { fromArray, filter, subscribe } from 'wonka';
-
const isEven = n => n % 2 === 0;
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
filter(isEven),
-
subscribe(val => console.log(val))
);
// Prints 246 to the console.
···
`map` will transform values from a source by passing them through an iteratee that returns a new value.
-
```reason
-
let square = (. n) => n * n;
-
-
Wonka.fromArray([|1, 2, 3, 4, 5, 6|])
-
|> Wonka.map(square)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 4 9 16 25 36 to the console. */
-
```
-
```typescript
import { fromArray, pipe, map, subscribe } from 'wonka';
-
const square = n => n * n;
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
map(square),
-
subscribe(val => console.log(val))
);
// Prints 1 4 9 16 25 36 to the console.
···
`merge` merges an array of sources together into a single source. It subscribes
to all sources that it's passed and emits all their values on the output source.
-
```reason
-
let sourceA = Wonka.fromArray([|1, 2, 3|]);
-
let sourceB = Wonka.fromArray([|4, 5, 6|]);
-
-
Wonka.merge([|sourceA, sourceB|])
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 2 3 4 5 6 to the console. */
-
```
-
```typescript
import { fromArray, pipe, merge, subscribe } from 'wonka';
···
> _Note:_ This operator is also exported as `flatten` which is just an alias for `mergeAll`
-
```reason
-
let sourceA = Wonka.fromArray([|1, 2, 3|]);
-
let sourceB = Wonka.fromArray([|4, 5, 6|]);
-
-
Wonka.fromList([sourceA, sourceB])
-
|> Wonka.mergeAll
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 2 3 4 5 6 to the console. */
-
```
-
```typescript
import { pipe, fromArray, mergeAll, subscribe } from 'wonka';
···
pipe(
fromArray([sourceOne, sourceTwo]),
mergeAll,
-
subscribe(val => console.log(val))
); // Prints 1 2 3 4 5 6 to the console.
```
···
Unlike `concatMap` all inner sources will be subscribed to at the same time
and all their values will be emitted on the output source as they come in.
-
```reason
-
Wonka.fromList([1, 2])
-
|> Wonka.mergeMap((. value) =>
-
Wonka.fromList([value - 1, value]))
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 0 1 1 2 to the console. */
-
```
-
```typescript
import { pipe, fromArray, mergeMap, subscribe } from 'wonka';
pipe(
fromArray([1, 2]),
-
mergeMap(x => fromArray([x - 1, x])),
-
subscribe(val => console.log(val))
); // Prints 0 1 1 2 to the console.
```
···
Run a callback when the `End` signal has been sent to the sink by the source, whether by way of the talkback passing the `End` signal or the source being exhausted of values.
-
```reason
-
let promiseOne =
-
Js.Promise.make((~resolve, ~reject as _) =>
-
Js.Global.setTimeout(() => resolve(. "ResolveOne"), 1000) |> ignore
-
);
-
-
let promiseTwo =
-
Js.Promise.make((~resolve, ~reject as _) =>
-
Js.Global.setTimeout(() => resolve(. "ResolveTwo"), 2000) |> ignore
-
);
-
-
let sourceOne = Wonka.fromPromise(promiseOne);
-
let sourceTwo = Wonka.fromPromise(promiseTwo);
-
-
Wonka.concat([|sourceOne, sourceTwo|])
-
|> Wonka.onEnd((.) => print_endline("onEnd"))
-
|> Wonka.subscribe((. x) => print_endline(x));
-
-
/* Logs ResolveOne after one second, then ResolveTwo after an additional second, then onEnd immediately. */
-
```
-
```typescript
import { fromPromise, pipe, concat, onEnd, subscribe } from 'wonka';
-
const promiseOne = new Promise(resolve => {
setTimeout(() => {
resolve('ResolveOne');
}, 1000);
});
-
const promiseTwo = new Promise(resolve => {
setTimeout(() => {
resolve('ResolveTwo');
}, 2000);
···
pipe(
concat([sourceOne, sourceTwo]),
onEnd(() => console.log('onEnd')),
-
subscribe(val => console.log(val))
);
// Logs ResolveOne after one second, then ResolveTwo after an additional second, then onEnd immediately.
···
> _Note:_ This operator is also exported as `tap` which is just an alias for `onPush`
-
```reason
-
Wonka.fromArray([|1, 2, 3, 4, 5, 6|])
-
|> Wonka.onPush((. x) => print_string({j|Push $x|j}))
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints Push 1 1 Push 2 2 Push 3 3 Push 4 4 Push 5 5 Push 6 6 to the console. */
-
```
-
```typescript
import { fromArray, pipe, onPush, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
-
onPush(val => console.log(`Push ${val}`)),
-
subscribe(val => console.log(val))
); // Prints Push 1 1 Push 2 2 Push 3 3 Push 4 4 Push 5 5 Push 6 6 to the console.
```
···
Run a callback when the `Start` signal is sent to the sink by the source.
-
```reason
-
let promise =
-
Js.Promise.make((~resolve, ~reject as _) =>
-
Js.Global.setTimeout(() => resolve(. "Resolve"), 1000) |> ignore
-
);
-
-
Wonka.fromPromise(promise)
-
|> Wonka.onStart((.) => print_endline("onStart"))
-
|> Wonka.subscribe((. _val) => print_endline(_val));
-
/* Logs onStart to the console, pauses for one second to allow the timeout to finish,
-
then logs "Resolve" to the console. */
-
```
-
```typescript
import { pipe, onStart, fromPromise, subscribe } from 'wonka';
-
const promise = new Promise(resolve => {
setTimeout(() => {
resolve('Resolve');
}, 1000);
···
pipe(
fromPromise(promise),
onStart(() => console.log('onStart')),
-
subscribe(val => console.log(val))
);
// Logs onStart to the console, pauses for one second to allow the timeout to finish,
···
In combination with `interval` it can be used to get values from a noisy source
more regularly.
-
```reason
-
Wonka.interval(10)
-
|> Wonka.sample(Wonka.interval(100))
-
|> Wonka.take(2)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 10 20 to the console. */
-
```
-
-
``` typescript
import { pipe, interval, sample, take, subscribe } from 'wonka';
pipe(
interval(10),
sample(interval(100)),
take(2),
-
subscribe(x => console.log(x))
); // Prints 10 20 to the console.
```
···
Accumulate emitted values of a source in a accumulator, similar to JavaScript `reduce`.
-
```reason
-
Wonka.fromArray([|1, 2, 3, 4, 5, 6|])
-
|> Wonka.scan((. acc, x) => acc + x, 0)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 3 6 10 15 21 to the console. */
-
```
-
```typescript
import { fromArray, pipe, scan, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
scan((acc, val) => acc + val, 0),
-
subscribe(val => console.log(val))
);
// Prints 1 3 6 10 15 21 to the console.
···
This is especially useful if you introduce side-effects to your sources,
for instance with `onStart`.
-
```reason
-
let source = Wonka.never
-
|> Wonka.onStart((.) => print_endline("start"))
-
|> Wonka.share;
-
-
/* Without share this would print "start" twice: */
-
Wonka.publish(source);
-
Wonka.publish(source);
-
```
-
```typescript
import { pipe, never, onStart, share, publish } from 'wonka';
···
## skip
`skip` the specified number of emissions from the source.
-
-
```reason
-
Wonka.fromArray([|1, 2, 3, 4, 5, 6|])
-
|> Wonka.skip(2)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 3 4 5 6 to the console, since the first two emissions from the source were skipped.
-
```
```typescript
import { fromArray, pipe, skip, subscribe } from 'wonka';
···
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
skip(2),
-
subscribe(val => console.log(val))
);
```
···
Skip emissions from an outer source until an inner source (notifier) emits.
-
```reason
-
let source = Wonka.interval(100);
-
let notifier = Wonka.interval(500);
-
-
source
-
|> Wonka.skipUntil(notifier)
-
|> Wonka.subscribe((. x) => print_int(x));
-
-
/* Skips all values emitted by source (0, 1, 2, 3) until notifier emits at 500ms.
-
Then logs 4 5 6 7 8 9 10... to the console every 500ms. */
-
```
-
```typescript
import { interval, pipe, skipUntil, subscribe } from 'wonka';
···
pipe(
source,
skipUntil(notifier),
-
subscribe(val => console.log(val))
);
// Skips all values emitted by source (0, 1, 2, 3) until notifier emits at 500ms.
···
Skip values emitted from the source while they return `true` for the provided predicate function.
-
```reason
-
let source = Wonka.fromArray([|1, 2, 3, 4, 5, 6|]);
-
-
source
-
|> Wonka.skipWhile((. _val) => _val < 5)
-
|> Wonka.subscribe((. _val) => print_int(_val));
-
-
/* Prints 5 6 to the console, as 1 2 3 4 all return true for the predicate function. */
-
```
-
```typescript
import { fromArray, pipe, skipWhile, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
-
skipWhile(val => val < 5),
-
subscribe(val => console.log(val))
);
// Prints 5 6 to the console, as 1 2 3 4 all return true for the predicate function.
···
This is similar to `concatMap` but instead of waiting for the last inner source to complete
before emitting values from the next, `switchMap` just cancels the previous inner source.
-
```reason
-
Wonka.interval(50)
-
|> Wonka.switchMap((. _value) =>
-
Wonka.interval(40))
-
|> Wonka.take(3)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 2 3 to the console. */
-
/* The inner interval is cancelled after its first value every time */
-
```
-
```typescript
import { pipe, interval, switchMap, take, subscribe } from 'wonka';
pipe(
interval(50),
// The inner interval is cancelled after its first value every time
-
switchMap(value => interval(40)),
take(3),
-
subscribe(x => console.log(x))
); // Prints 1 2 3 to the console
```
···
It's very similar to `switchMap`, but instead accepts a source of sources.
-
```reason
-
Wonka.interval(50)
-
|> Wonka.map((. _value) =>
-
Wonka.interval(40))
-
|> Wonka.switchAll
-
|> Wonka.take(3)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 2 3 to the console. */
-
```
-
```typescript
import { pipe, interval, map, switchAll, take, subscribe } from 'wonka';
···
map(() => interval(40)),
switchAll,
take(3),
-
subscribe(x => console.log(x))
); // Prints 1 2 3 to the console
```
···
`take` only a specified number of emissions from the source before completing. `take` is the opposite of `skip`.
-
```reason
-
Wonka.fromArray([|1, 2, 3, 4, 5, 6|])
-
|> Wonka.take(3)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 1 2 3 to the console. */
-
```
-
```typescript
import { fromArray, pipe, take, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
take(3),
-
subscribe(val => console.log(val))
);
// Prints 1 2 3 to the console.
···
`takeLast` will take only the last n emissions from the source.
-
```reason
-
Wonka.fromArray([|1, 2, 3, 4, 5, 6|]);
-
|> Wonka.takeLast(3)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 4 5 6 to the console. */
-
```
-
```typescript
import { fromArray, pipe, takeLast, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
takeLast(3),
-
subscribe(val => console.log(val))
);
// Prints 4 5 6 to the console.
···
Take emissions from an outer source until an inner source (notifier) emits.
-
```reason
-
let source = Wonka.interval(100);
-
let notifier = Wonka.interval(500);
-
-
source
-
|> Wonka.takeUntil(notifier)
-
|> Wonka.subscribe((. x) => print_int(x));
-
-
/* Pauses 100ms, prints 0, pauses 100ms, prints 1, pauses 100ms, prints 2, pauses 100ms,
-
prints 3, pauses 100, then completes (notifier emits). */
-
```
-
```typescript
import { interval, pipe, takeUntil, subscribe } from 'wonka';
···
pipe(
source,
takeUntil(notifier),
-
subscribe(val => console.log(val))
);
// Pauses 100ms, prints 0, pauses 100ms, prints 1, pauses 100ms, prints 2, pauses 100ms,
···
Take emissions from the stream while they return `true` for the provided predicate function. If the first emission does not return `true`, no values will be `Push`ed to the sink.
-
```reason
-
let source = Wonka.fromArray([|1, 2, 3, 4, 5, 6|]);
-
-
source
-
|> Wonka.takeWhile((. x) => x < 5)
-
|> Wonka.subscribe((. x) => print_int(x));
-
-
/* Prints 1 2 3 4 to the console. */
-
```
-
```typescript
import { pipe, fromArray, takeWhile, subscribe } from 'wonka';
···
pipe(
source,
-
takeWhile(val => val < 5),
-
subscribe(val => console.log(val))
);
// Prints 1 2 3 4 to the console.
···
This is very similar to `debounce` but instead of waiting for leading time before a
value it waits for trailing time after a value.
-
-
> _Note:_ This operator is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
Wonka.interval(10)
-
|> Wonka.throttle((. _x) => 50)
-
|> Wonka.take(2)
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Outputs 0 6 to the console. */
-
```
```typescript
import { pipe, interval, throttle, take, subscribe } from 'wonka';
···
In combination with `interval` this can be used to group values in chunks regularly.
+
```typescript
import { pipe, interval, buffer, take, subscribe } from 'wonka';
pipe(
interval(50),
buffer(interval(100)),
take(2),
+
subscribe((buffer) => {
+
buffer.forEach((x) => console.log(x));
console.log(';');
})
); // Prints 1 2; 2 3 to the console.
···
`combine` two sources together to a single source. The emitted value will be a combination of the two sources, with all values from the first source being emitted with the first value of the second source _before_ values of the second source are emitted.
```typescript
import { fromArray, pipe, combine, subscribe } from 'wonka';
···
`concat` will combine two sources together, subscribing to the next source after the previous source completes.
```typescript
import { fromArray, pipe, concat, subscribe } from 'wonka';
···
pipe(
concat([sourceOne, sourceTwo]),
+
subscribe((val) => console.log(val))
); // Prints 1 2 3 6 5 4 to the console.
```
···
It's very similar to `concat`, but instead accepts a source of sources as an input.
```typescript
import { pipe, fromArray, concatAll, subscribe } from 'wonka';
···
pipe(
fromArray([sourceOne, sourceTwo]),
concatAll,
+
subscribe((val) => console.log(val))
); // Prints 1 2 3 6 5 4 to the console.
```
···
`concatMap` allows you to map values of an outer source to an inner source. The sink will not dispatch the `Pull` signal until the previous value has been emitted. This is in contrast to `mergeMap`, which will dispatch the `Pull` signal for new values even if the previous value has not yet been emitted.
```typescript
import { fromArray, pipe, concatMap, delay, fromValue, subscribe } from 'wonka';
···
pipe(
source,
+
concatMap((val) => {
+
return pipe(fromValue(val), delay(val * 1000));
}),
+
subscribe((val) => console.log(val))
);
```
## delay
`delay` delays all emitted values of a source by the given amount of milliseconds.
```typescript
import { pipe, fromArray, delay, subscribe } from 'wonka';
···
a given amount of milliseconds. Once this threshold of silence has been reached, the
last value that has been received will be emitted.
```typescript
import { pipe, interval, take, fromValue, concat, debounce, subscribe } from 'wonka';
···
`filter` will remove values from a source by passing them through an iteratee that returns a `bool`.
```typescript
import { fromArray, filter, subscribe } from 'wonka';
+
const isEven = (n) => n % 2 === 0;
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
filter(isEven),
+
subscribe((val) => console.log(val))
);
// Prints 246 to the console.
···
`map` will transform values from a source by passing them through an iteratee that returns a new value.
```typescript
import { fromArray, pipe, map, subscribe } from 'wonka';
+
const square = (n) => n * n;
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
map(square),
+
subscribe((val) => console.log(val))
);
// Prints 1 4 9 16 25 36 to the console.
···
`merge` merges an array of sources together into a single source. It subscribes
to all sources that it's passed and emits all their values on the output source.
```typescript
import { fromArray, pipe, merge, subscribe } from 'wonka';
···
> _Note:_ This operator is also exported as `flatten` which is just an alias for `mergeAll`
```typescript
import { pipe, fromArray, mergeAll, subscribe } from 'wonka';
···
pipe(
fromArray([sourceOne, sourceTwo]),
mergeAll,
+
subscribe((val) => console.log(val))
); // Prints 1 2 3 4 5 6 to the console.
```
···
Unlike `concatMap` all inner sources will be subscribed to at the same time
and all their values will be emitted on the output source as they come in.
```typescript
import { pipe, fromArray, mergeMap, subscribe } from 'wonka';
pipe(
fromArray([1, 2]),
+
mergeMap((x) => fromArray([x - 1, x])),
+
subscribe((val) => console.log(val))
); // Prints 0 1 1 2 to the console.
```
···
Run a callback when the `End` signal has been sent to the sink by the source, whether by way of the talkback passing the `End` signal or the source being exhausted of values.
```typescript
import { fromPromise, pipe, concat, onEnd, subscribe } from 'wonka';
+
const promiseOne = new Promise((resolve) => {
setTimeout(() => {
resolve('ResolveOne');
}, 1000);
});
+
const promiseTwo = new Promise((resolve) => {
setTimeout(() => {
resolve('ResolveTwo');
}, 2000);
···
pipe(
concat([sourceOne, sourceTwo]),
onEnd(() => console.log('onEnd')),
+
subscribe((val) => console.log(val))
);
// Logs ResolveOne after one second, then ResolveTwo after an additional second, then onEnd immediately.
···
> _Note:_ This operator is also exported as `tap` which is just an alias for `onPush`
```typescript
import { fromArray, pipe, onPush, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
+
onPush((val) => console.log(`Push ${val}`)),
+
subscribe((val) => console.log(val))
); // Prints Push 1 1 Push 2 2 Push 3 3 Push 4 4 Push 5 5 Push 6 6 to the console.
```
···
Run a callback when the `Start` signal is sent to the sink by the source.
```typescript
import { pipe, onStart, fromPromise, subscribe } from 'wonka';
+
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve('Resolve');
}, 1000);
···
pipe(
fromPromise(promise),
onStart(() => console.log('onStart')),
+
subscribe((val) => console.log(val))
);
// Logs onStart to the console, pauses for one second to allow the timeout to finish,
···
In combination with `interval` it can be used to get values from a noisy source
more regularly.
+
```typescript
import { pipe, interval, sample, take, subscribe } from 'wonka';
pipe(
interval(10),
sample(interval(100)),
take(2),
+
subscribe((x) => console.log(x))
); // Prints 10 20 to the console.
```
···
Accumulate emitted values of a source in a accumulator, similar to JavaScript `reduce`.
```typescript
import { fromArray, pipe, scan, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
scan((acc, val) => acc + val, 0),
+
subscribe((val) => console.log(val))
);
// Prints 1 3 6 10 15 21 to the console.
···
This is especially useful if you introduce side-effects to your sources,
for instance with `onStart`.
```typescript
import { pipe, never, onStart, share, publish } from 'wonka';
···
## skip
`skip` the specified number of emissions from the source.
```typescript
import { fromArray, pipe, skip, subscribe } from 'wonka';
···
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
skip(2),
+
subscribe((val) => console.log(val))
);
```
···
Skip emissions from an outer source until an inner source (notifier) emits.
```typescript
import { interval, pipe, skipUntil, subscribe } from 'wonka';
···
pipe(
source,
skipUntil(notifier),
+
subscribe((val) => console.log(val))
);
// Skips all values emitted by source (0, 1, 2, 3) until notifier emits at 500ms.
···
Skip values emitted from the source while they return `true` for the provided predicate function.
```typescript
import { fromArray, pipe, skipWhile, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
+
skipWhile((val) => val < 5),
+
subscribe((val) => console.log(val))
);
// Prints 5 6 to the console, as 1 2 3 4 all return true for the predicate function.
···
This is similar to `concatMap` but instead of waiting for the last inner source to complete
before emitting values from the next, `switchMap` just cancels the previous inner source.
```typescript
import { pipe, interval, switchMap, take, subscribe } from 'wonka';
pipe(
interval(50),
// The inner interval is cancelled after its first value every time
+
switchMap((value) => interval(40)),
take(3),
+
subscribe((x) => console.log(x))
); // Prints 1 2 3 to the console
```
···
It's very similar to `switchMap`, but instead accepts a source of sources.
```typescript
import { pipe, interval, map, switchAll, take, subscribe } from 'wonka';
···
map(() => interval(40)),
switchAll,
take(3),
+
subscribe((x) => console.log(x))
); // Prints 1 2 3 to the console
```
···
`take` only a specified number of emissions from the source before completing. `take` is the opposite of `skip`.
```typescript
import { fromArray, pipe, take, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
take(3),
+
subscribe((val) => console.log(val))
);
// Prints 1 2 3 to the console.
···
`takeLast` will take only the last n emissions from the source.
```typescript
import { fromArray, pipe, takeLast, subscribe } from 'wonka';
pipe(
fromArray([1, 2, 3, 4, 5, 6]),
takeLast(3),
+
subscribe((val) => console.log(val))
);
// Prints 4 5 6 to the console.
···
Take emissions from an outer source until an inner source (notifier) emits.
```typescript
import { interval, pipe, takeUntil, subscribe } from 'wonka';
···
pipe(
source,
takeUntil(notifier),
+
subscribe((val) => console.log(val))
);
// Pauses 100ms, prints 0, pauses 100ms, prints 1, pauses 100ms, prints 2, pauses 100ms,
···
Take emissions from the stream while they return `true` for the provided predicate function. If the first emission does not return `true`, no values will be `Push`ed to the sink.
```typescript
import { pipe, fromArray, takeWhile, subscribe } from 'wonka';
···
pipe(
source,
+
takeWhile((val) => val < 5),
+
subscribe((val) => console.log(val))
);
// Prints 1 2 3 4 to the console.
···
This is very similar to `debounce` but instead of waiting for leading time before a
value it waits for trailing time after a value.
```typescript
import { pipe, interval, throttle, take, subscribe } from 'wonka';
+7 -93
docs/api/sinks.md
···
`subscribe` accepts a callback function to execute when data is received from the source, in addition to the source itself.
-
```reason
-
Wonka.fromArray([|1, 2, 3|])
-
|> Wonka.subscribe((. x) => print_int(x));
-
/* Prints 123 to the console. */
-
```
-
```typescript
import { pipe, fromArray, subscribe } from 'wonka';
···
`subscribe` also returns a "subscription" type, which can be used to
unsubscribe from the source. This allows you to cancel a source and stop receiving
new incoming values.
-
-
```reason
-
let subscription = source
-
|> Wonka.subscribe((. x) => print_int(x));
-
-
subscription.unsubscribe();
-
```
```typescript
import { pipe, subscribe } from 'wonka';
···
`forEach` works the same as `subscribe` but doesn't return a subscription.
It will just call the passed callback for each incoming value.
-
```reason
-
Wonka.fromArray([|1, 2, 3|])
-
|> Wonka.forEach((. x) => print_int(x));
-
/* Returns unit; Prints 123 to the console. */
-
```
-
```typescript
import { pipe, fromArray, forEach } from 'wonka';
···
In this example we're using [`onPush`](./operators.md#onpush) to pass a callback to react to incoming
values instead.
-
```reason
-
Wonka.fromArray([|1, 2, 3|])
-
|> Wonka.onPush((. x) => print_int(x))
-
|> Wonka.publish;
-
/* Prints 123 to the console. */
-
```
-
```typescript
import { pipe, fromArray, onPush, publish } from 'wonka';
···
> _Note:_ If you're using this sink, make sure that your input source streams
> the values you're collecting partly or fully synchronously.
-
```reason
-
Wonka.fromArray([|1, 2, 3|])
-
|> Wonka.map((. x) => x * 2)
-
|> Wonka.toArray
-
/* Returns [|2, 4, 6|] */
-
```
-
```typescript
import { pipe, fromArray, map, toArray } from 'wonka';
pipe(
fromArray([1, 2, 3]),
-
map(x => x * 2),
toArray
); // Returns [2, 4, 6]
```
···
`toPromise` returns a promise, which resolves on the last value of a source.
-
> _Note:_ This source is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
Wonka.fromArray([|1, 2, 3|])
-
|> Wonka.toPromise
-
|> Js.Promise.then_(x => {
-
print_int(x);
-
Js.Promise.resolve(())
-
})
-
/* Prints 3 to the console. */
-
```
-
```typescript
import { pipe, fromArray, toPromise } from 'wonka';
-
const promise = pipe(
-
fromArray([1, 2, 3]),
-
toPromise,
-
);
-
promise.then(x => console.log(x));
// Prints 3 to the console.
```
···
As per the specification, the Observable is annotated using `Symbol.observable`.
-
> _Note:_ This sink is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
let observable = Wonka.fromArray([|1, 2, 3|])
-
|> Wonka.toObservable;
-
-
observable##subscribe([@bs] {
-
as _;
-
pub next = value => print_int(value);
-
pub complete = () => ();
-
pub error = _ => ();
-
}); /* Prints 1 2 3 to the console. */
-
```
-
```typescript
import { pipe, fromArray, toObservable } from 'wonka';
-
const observable = pipe(
-
fromArray([1, 2, 3]),
-
toObservable,
-
);
observable.subscribe({
-
next: value => console.log(value),
complete: () => {},
error: () => {},
}); // Prints 1 2 3 to the console.
···
minimally, Callbags map to Wonka's sources very closely and `toCallbag` only creates a thin
wrapper which is mostly concerned with converting between the type signatures.
-
> _Note:_ This sink is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
/* This example uses the callbag-iterate package for illustrative purposes */
-
[@bs.module] external callbagIterate:
-
(. ('a => unit)) => (. Wonka.callbagT('a)) => unit = "callbag-iterate";
-
-
let callbag = Wonka.fromArray([|1, 2, 3|])
-
|> Wonka.toCallbag;
-
-
callbagIterate(. value => {
-
print_int(value);
-
})(. callbag); /* Prints 1 2 3 to the console. */
-
```
-
```typescript
import { pipe, fromArray, toCallbag } from 'wonka';
// This example uses the callbag-iterate package for illustrative purposes
import callbagIterate from 'callbag-iterate';
-
const callbag = pipe(
-
fromArray([1, 2, 3]),
-
toCallbag,
-
);
-
callbagIterate(value => console.log(value))(callbag);
// Prints 1 2 3 to the console.
```
···
`subscribe` accepts a callback function to execute when data is received from the source, in addition to the source itself.
```typescript
import { pipe, fromArray, subscribe } from 'wonka';
···
`subscribe` also returns a "subscription" type, which can be used to
unsubscribe from the source. This allows you to cancel a source and stop receiving
new incoming values.
```typescript
import { pipe, subscribe } from 'wonka';
···
`forEach` works the same as `subscribe` but doesn't return a subscription.
It will just call the passed callback for each incoming value.
```typescript
import { pipe, fromArray, forEach } from 'wonka';
···
In this example we're using [`onPush`](./operators.md#onpush) to pass a callback to react to incoming
values instead.
```typescript
import { pipe, fromArray, onPush, publish } from 'wonka';
···
> _Note:_ If you're using this sink, make sure that your input source streams
> the values you're collecting partly or fully synchronously.
```typescript
import { pipe, fromArray, map, toArray } from 'wonka';
pipe(
fromArray([1, 2, 3]),
+
map((x) => x * 2),
toArray
); // Returns [2, 4, 6]
```
···
`toPromise` returns a promise, which resolves on the last value of a source.
```typescript
import { pipe, fromArray, toPromise } from 'wonka';
+
const promise = pipe(fromArray([1, 2, 3]), toPromise);
+
promise.then((x) => console.log(x));
// Prints 3 to the console.
```
···
As per the specification, the Observable is annotated using `Symbol.observable`.
```typescript
import { pipe, fromArray, toObservable } from 'wonka';
+
const observable = pipe(fromArray([1, 2, 3]), toObservable);
observable.subscribe({
+
next: (value) => console.log(value),
complete: () => {},
error: () => {},
}); // Prints 1 2 3 to the console.
···
minimally, Callbags map to Wonka's sources very closely and `toCallbag` only creates a thin
wrapper which is mostly concerned with converting between the type signatures.
```typescript
import { pipe, fromArray, toCallbag } from 'wonka';
// This example uses the callbag-iterate package for illustrative purposes
import callbagIterate from 'callbag-iterate';
+
const callbag = pipe(fromArray([1, 2, 3]), toCallbag);
+
callbagIterate((value) => console.log(value))(callbag);
// Prints 1 2 3 to the console.
```
+13 -150
docs/api/sources.md
···
`fromArray` transforms an array into a source, emitting each item synchronously.
-
```reason
-
Wonka.fromArray([|1, 2, 3|]);
-
```
-
```typescript
import { fromArray } from 'wonka';
fromArray([1, 2, 3]);
```
-
## fromList
-
-
`fromList` transforms a list into a source, emitting each item synchronously.
-
-
> _Note:_ This operator is only useful in Reason / OCaml where lists are a builtin
-
> data structure.
-
-
This is otherwise functionally the same as `fromArray`.
-
-
```reason
-
Wonka.fromList([1, 2, 3]);
-
```
-
## fromValue
`fromValue` takes a single value and creates a source that emits the value and
completes immediately afterwards.
-
```reason
-
Wonka.fromValue("a value");
```
## make
···
In this example we create a source that waits for a promise to resolve and emits
values from the array of that promise.
-
-
```reason
-
let waitForArray = () => Js.Promise.resolve([|1, 2, 3|]);
-
-
let source = Wonka.make((. observer) => {
-
let (next, complete) = observer;
-
let cancelled = ref(false);
-
let promise = waitForArray();
-
-
Js.Promise.then_(arr => {
-
if (!cancelled^) {
-
Array.iter(next, arr);
-
complete();
-
}
-
}, promise);
-
-
() => cancelled := true;
-
});
-
```
```typescript
import { make } from 'wonka';
const waitForArray = () => Promise.resolve([1, 2, 3]);
-
const source = make(observer => {
const { next, complete } = observer;
let cancelled = false;
-
waitForArray().then(arr => {
if (!cancelled) {
arr.forEach(next);
complete();
···
around but also have access to the observer functions to emit events away from
the source itself.
-
```reason
-
let subject = Wonka.makeSubject();
-
let { source, next, complete } = subject;
-
-
/* This will push the values synchronously to any subscribers of source */
-
next(1);
-
next(2);
-
next(complete);
-
```
-
```typescript
-
import { makeSubject } from 'wonka'
const subject = makeSubject();
const { source, next, complete } = subject;
···
`fromDomEvent` will turn a DOM event into a Wonka source, emitting the DOM events
on the source whenever the DOM emits them on the passed element.
-
> _Note:_ This source is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
open Webapi.Dom;
-
open Document;
-
-
let element = getElementById("root", document)->Belt.Option.getExn;
-
-
Wonka.fromDomEvent(element, "click")
-
|> Wonka.subscribe((. click) => Js.log(click));
-
```
-
```typescript
import { pipe, fromDomEvent, subscribe } from 'wonka';
···
pipe(
fromDomEvent(element, 'click'),
-
subscribe(e => console.log(e))
);
```
···
`fromPromise` transforms a promise into a source, emitting the promisified value on
the source once it resolves.
-
> _Note:_ This source is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
let promise = Js.Promise.make(1); /* Just an example promise */
-
-
Wonka.fromPromise(promise)
-
|> Wonka.subscribe((. x) => Js.log(x));
-
/* Prints 1 to the console. */
-
```
-
```typescript
import { pipe, fromPromise, subscribe } from 'wonka';
···
pipe(
fromPromise(promise),
-
subscribe(e => console.log(e))
); // Prints 1 to the console.
```
···
`fromObservable` transforms a [spec-compliant JS Observable](https://github.com/tc39/proposal-observable) into a source.
The resulting source will behave exactly the same as the Observable that it was
passed, so it will start, end, and push values identically.
-
-
> _Note:_ This source is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
```typescript
import { pipe, fromObservable, subscribe } from 'wonka';
···
pipe(
fromObservable(observable),
-
subscribe(e => console.log(e))
); // Prints 1 2 3 to the console
```
-
If you're using Reason in a JavaScript environment and you're interested in this
-
operator, you may be using a library to create or get Observables.
-
-
Some libraries don't expose Observables with the same BuckleScript type signature
-
that Wonka uses to type them. So while Wonka's `observableT` type is fairly
-
lenient it may not work for you.
-
-
```reason
-
type observableT('a) = {.
-
[@bs.meth] "subscribe": observerT('a) => subscriptionT
-
};
-
```
-
-
To work around this you can create a function that casts your observable type
-
to Wonka's `observableT`.
-
-
```reason
-
type yourObservableType('a);
-
external asObservable: yourObservableType('a) => Wonka.observableT('a) = "%identity";
-
```
-
-
This snippet would create an `asObservable` function, which can type-cast your
-
Observable type to `Wonka.observableT` and compiles away completely.
-
## fromCallbag
`fromCallbag` transforms a [spec-compliant JS Callbag](https://github.com/callbag/callbag) into a source.
···
minimally, Callbags map to Wonka's sources very closely and the `fromCallbag` wrapper
is very thin and mostly concerned with converting between the type signatures.
-
> _Note:_ This source is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
/* This example uses the callbag-from-iter package for illustrative purposes */
-
[@bs.module] external callbagFromArray:
-
array('a) => Wonka.callbagT('a) = "callbag-from-iter";
-
-
let callbag = callbagFromArray([|1, 2, 3|]);
-
-
Wonka.fromCallbag(callbag)
-
|> Wonka.subscribe((. x) => Js.log(x));
-
/* Prints 1 2 3 to the console. */
-
```
-
```typescript
import { pipe, fromCallbag, subscribe } from 'wonka';
···
pipe(
fromCallbag(callbag),
-
subscribe(e => console.log(e))
); // Prints 1 2 3 to the console.
```
···
`interval` creates a source that emits values after the given amount of milliseconds.
Internally it uses `setInterval` to accomplish this.
-
> _Note:_ This source is only available in JavaScript environments, and will be excluded
-
> when compiling natively.
-
-
```reason
-
Wonka.interval(50)
-
|> Wonka.subscribe((. x) => Js.log(x));
-
/* Prints 0 1 2... to the console. */
-
/* The incrementing number is logged every 50ms */
-
```
-
```typescript
import { pipe, interval, subscribe } from 'wonka';
pipe(
interval(50),
-
subscribe(e => console.log(e))
); // Prints 0 1 2... to the console.
// The incrementing number is logged every 50ms
```
···
This is a source that doesn't emit any values when subscribed to and
immediately completes.
-
```reason
-
Wonka.empty
-
|> Wonka.forEach((. value) => {
-
/* This will never be called */
-
()
-
});
-
```
-
```typescript
import { pipe, empty, forEach } from 'wonka';
pipe(
empty,
-
forEach(value => {
/* This will never be called */
})
);
···
This is source is similar to [`empty`](#empty).
It doesn't emit any values but also never completes.
-
```reason
-
Wonka.never
-
|> Wonka.forEach((. value) => {
-
/* This will never be called */
-
()
-
});
-
```
-
```typescript
import { pipe, never, forEach } from 'wonka';
pipe(
never,
-
forEach(value => {
/* This will never be called */
})
);
···
`fromArray` transforms an array into a source, emitting each item synchronously.
```typescript
import { fromArray } from 'wonka';
fromArray([1, 2, 3]);
```
## fromValue
`fromValue` takes a single value and creates a source that emits the value and
completes immediately afterwards.
+
```typescript
+
import { fromValue } from 'wonka';
+
fromValue(1);
```
## make
···
In this example we create a source that waits for a promise to resolve and emits
values from the array of that promise.
```typescript
import { make } from 'wonka';
const waitForArray = () => Promise.resolve([1, 2, 3]);
+
const source = make((observer) => {
const { next, complete } = observer;
let cancelled = false;
+
waitForArray().then((arr) => {
if (!cancelled) {
arr.forEach(next);
complete();
···
around but also have access to the observer functions to emit events away from
the source itself.
```typescript
+
import { makeSubject } from 'wonka';
const subject = makeSubject();
const { source, next, complete } = subject;
···
`fromDomEvent` will turn a DOM event into a Wonka source, emitting the DOM events
on the source whenever the DOM emits them on the passed element.
```typescript
import { pipe, fromDomEvent, subscribe } from 'wonka';
···
pipe(
fromDomEvent(element, 'click'),
+
subscribe((e) => console.log(e))
);
```
···
`fromPromise` transforms a promise into a source, emitting the promisified value on
the source once it resolves.
```typescript
import { pipe, fromPromise, subscribe } from 'wonka';
···
pipe(
fromPromise(promise),
+
subscribe((e) => console.log(e))
); // Prints 1 to the console.
```
···
`fromObservable` transforms a [spec-compliant JS Observable](https://github.com/tc39/proposal-observable) into a source.
The resulting source will behave exactly the same as the Observable that it was
passed, so it will start, end, and push values identically.
```typescript
import { pipe, fromObservable, subscribe } from 'wonka';
···
pipe(
fromObservable(observable),
+
subscribe((e) => console.log(e))
); // Prints 1 2 3 to the console
```
## fromCallbag
`fromCallbag` transforms a [spec-compliant JS Callbag](https://github.com/callbag/callbag) into a source.
···
minimally, Callbags map to Wonka's sources very closely and the `fromCallbag` wrapper
is very thin and mostly concerned with converting between the type signatures.
```typescript
import { pipe, fromCallbag, subscribe } from 'wonka';
···
pipe(
fromCallbag(callbag),
+
subscribe((e) => console.log(e))
); // Prints 1 2 3 to the console.
```
···
`interval` creates a source that emits values after the given amount of milliseconds.
Internally it uses `setInterval` to accomplish this.
```typescript
import { pipe, interval, subscribe } from 'wonka';
pipe(
interval(50),
+
subscribe((e) => console.log(e))
); // Prints 0 1 2... to the console.
// The incrementing number is logged every 50ms
```
···
This is a source that doesn't emit any values when subscribed to and
immediately completes.
```typescript
import { pipe, empty, forEach } from 'wonka';
pipe(
empty,
+
forEach((value) => {
/* This will never be called */
})
);
···
This is source is similar to [`empty`](#empty).
It doesn't emit any values but also never completes.
```typescript
import { pipe, never, forEach } from 'wonka';
pipe(
never,
+
forEach((value) => {
/* This will never be called */
})
);
+27 -27
docs/basics/architecture.md
···
Because a sink has a start, incoming values, and an end, there are three
signals that a sink can receive: `Start`, `Push`, and `End`.
-
``` reason
-
type signalT('a) =
-
| Start
-
| Push('a)
-
| End;
-
type sinkT('a) = (. signalT('a)) => unit;
```
As shown, the sink is just a function accepting a signal as its argument.
When the stream starts then the sink is called with `Start`,
-
Then for every incoming, new value it's called with `Push('a)`,
and when the stream ends it's finally called with `End`.
Since we want a source to send these values to the sink, the source is
also just a function and it accepts a sink as its argument.
-
``` reason
-
type sourceT('a) = sinkT('a) => unit;
```
This is completely sufficient to represent simple "push" streams, where
···
The type signature of an operator with no other arguments is thus:
-
``` reason
-
type operatorT('a, 'b) = sourceT('a) => sourceT('b);
/* which is the same as: */
-
type operatorT('a, 'b) = (sourceT('a), sinkT('b)) => unit;
```
## Adding Callbacks
···
In Wonka, a sink's `Start` signal also carries a callback that is used to communicate
back to the source, making these "talkback signals" flow from the bottom to the top.
-
``` reason
-
type talkbackT =
-
| Pull
-
| Close;
-
type signalT('a) =
-
| Start((. talkbackT) => unit)
-
| Push('a)
-
| End;
```
-
This is like the previous `signalT('a)` definition, but the `Start` signal has the
callback definition now. The callback accepts one of two signals: `Pull` or `Close`.
`Close` is a signal that will cancel the stream. It tells the source to stop sending
···
In Wonka there's a separate type for subjects however, since this reduces the
complexity of its streams a lot:
-
``` reason
-
type subjectT('a) = {
-
source: sourceT('a),
-
next: 'a => unit,
-
complete: unit => unit,
-
};
```
Hence in Wonka a subject is simply a wrapper around a source and a `next` and `complete`
···
Because a sink has a start, incoming values, and an end, there are three
signals that a sink can receive: `Start`, `Push`, and `End`.
+
```typescript
+
type Start = { tag: 0 }; // & [TalkbackFn]
+
type Push<T> = { tag: 1 } & [T];
+
type End = 0;
+
+
type Signal<T> = Start | Push<T> | End;
+
type Sink<T> = (signal: Signal<T>) => void;
```
As shown, the sink is just a function accepting a signal as its argument.
When the stream starts then the sink is called with `Start`,
+
Then for every incoming, new value it's called with `Push<T>`,
and when the stream ends it's finally called with `End`.
Since we want a source to send these values to the sink, the source is
also just a function and it accepts a sink as its argument.
+
```typescript
+
type Source<T> = (sink: Sink<T>) => void;
```
This is completely sufficient to represent simple "push" streams, where
···
The type signature of an operator with no other arguments is thus:
+
```typescript
+
type Operator<In, Out> = (source: Source<In>) => Source<Out>;
/* which is the same as: */
+
type Operator<In, Out> = (source: Source<In>) => (sink: Sink<Out>) => void;
```
## Adding Callbacks
···
In Wonka, a sink's `Start` signal also carries a callback that is used to communicate
back to the source, making these "talkback signals" flow from the bottom to the top.
+
```typescript
+
const enum TalkbackKind {
+
Pull = 0,
+
Close = 1,
+
}
+
type TalkbackFn = (signal: TalkbackKind) => void;
+
type Start = { tag: 0 } & [TalkbackFn];
```
+
This is like the previous `Signal<T>` definition, but the `Start` signal has the
callback definition now. The callback accepts one of two signals: `Pull` or `Close`.
`Close` is a signal that will cancel the stream. It tells the source to stop sending
···
In Wonka there's a separate type for subjects however, since this reduces the
complexity of its streams a lot:
+
```reason
+
interface Subject<T> {
+
next(value: T): void;
+
complete(): void;
+
source: Source<T>;
+
}
```
Hence in Wonka a subject is simply a wrapper around a source and a `next` and `complete`
+6 -15
docs/index.md
···
It also comes with many operators that users from [RxJS](https://github.com/ReactiveX/rxjs) will be used to.
-
## Compatibility
-
Wonka is written in [Reason](https://reasonml.github.io/), a dialect of OCaml, and can hence be used
-
for native applications. It is also compiled using [BuckleScript](https://bucklescript.github.io) to plain
-
JavaScript and has typings for [TypeScript](https://www.typescriptlang.org/) and [Flow](https://flow.org/).
-
This means that out of the box Wonka is usable in any project that use the following:
-
-
- Plain JavaScript
-
- TypeScript
-
- Flow
-
- Reason/OCaml with BuckleScript
-
- Reason/OCaml with `bs-native`
-
- Reason/OCaml with Dune and Esy
-
-
In summary, Wonka provides a consistent interface in and works across
-
TypeScript/Flow/Reason/OCaml environments with full type safety.
## About the docs
···
It also comes with many operators that users from [RxJS](https://github.com/ReactiveX/rxjs) will be used to.
+
## Reason Support
+
Wonka used to be written in [Reason](https://reasonml.github.io/),, a dialect of OCaml, and was usable
+
for native development and compileable with [BuckleScript](https://bucklescript.github.io).
+
Out of the box it supported usage with BuckleScript, `bs-native`, Dune, and Esy.
+
If you're looking for the legacy version that supported this, you may want to install v4 or v5 rather
+
than v6 onwards, which converted the project to TypeScript.
## About the docs
+17
docs/migration.md
···
This page lists breaking changes and migration guides for
various major releases of Wonka.
## v4.0.0
In `v4.0.0` of Wonka, we've migrated to BuckleScript v7 and
···
This page lists breaking changes and migration guides for
various major releases of Wonka.
+
## v6.0.0
+
+
In `v6.0.0` of Wonka, we've migrated fully to TypeScript.
+
If you're using this project with Reason or OCaml before, we're sorry for
+
the inconvenience. However, v4 and v5-rc will remain usable for these
+
platforms and languages.
+
+
The internal API and data structures of Wonka haven't changed in `v6.0.0`
+
compared to the prior releases and are based on `v4.0.14`. This means that
+
from a TypeScript, Flow, and JS perspective, `v6.0.0` is backwards compatible
+
and continues to function as before.
+
+
However, the `fromList` API has been removed so far, and we reserve ourselves
+
room to make more breaking changes were behaviour before was broken.
+
+
We're also dropping IE11 support and are now bundling against an ES2015 target.
+
## v4.0.0
In `v4.0.0` of Wonka, we've migrated to BuckleScript v7 and
-30
gatsby/theme.css
···
-
@font-face {
-
font-family: 'phantom-sans';
-
src: url("https://phantomsans.kitten.sh/PhantomSans05VAR.woff2") format("woff2-variations"),
-
url("https://phantomsans.kitten.sh/PhantomSans05VAR.ttf") format("truetype-variations"),
-
url("https://phantomsans.kitten.sh/PhantomSans-Regular.woff2") format("woff2"),
-
url("https://phantomsans.kitten.sh/PhantomSans-Regular.ttf") format("truetype");
-
font-weight: 1 999;
-
font-display: swap;
-
font-style: normal;
-
}
-
-
@font-face {
-
font-family: 'space-mono';
-
font-style: italic;
-
font-weight: 400;
-
font-display: swap;
-
src: local('Space Mono Italic'),
-
local('SpaceMono-Italic'),
-
url(https://fonts.gstatic.com/s/spacemono/v4/i7dNIFZifjKcF5UAWdDRYERMR3K_MQacbw.woff2) format('woff2');
-
}
-
-
@font-face {
-
font-family: 'space-mono';
-
font-style: normal;
-
font-weight: 400;
-
font-display: swap;
-
src: local('Space Mono'),
-
local('SpaceMono-Regular'),
-
url(https://fonts.gstatic.com/s/spacemono/v4/i7dPIFZifjKcF5UAWdDRYEF8RXi4EwQ.woff2) format('woff2');
-
}
···
-50
gatsby/theme.js
···
-
import nightOwlLight from 'prism-react-renderer/themes/nightOwlLight';
-
import './theme.css';
-
-
const systemFonts = [
-
'-apple-system',
-
'BlinkMacSystemFont',
-
'Segoe UI',
-
'Roboto',
-
'Helvetica Neue',
-
'Arial',
-
'Noto Sans',
-
'sans-serif',
-
'Apple Color Emoji',
-
'Segoe UI Emoji',
-
'Segoe UI Symbol',
-
'Noto Color Emoji',
-
];
-
-
export const fonts = {
-
header: ['phantom-sans', ...systemFonts],
-
code: ['space-mono', 'monospace'],
-
body: systemFonts,
-
};
-
-
export const colors = {
-
bg: '#ffffff',
-
bgPassive: '#f0f0f2',
-
bgActive: '#fcfafe',
-
fg: '#36313d',
-
fgHeading: '#000000',
-
fgPassive: '#78757a',
-
fgActive: '#f5735f',
-
};
-
-
export const prismTheme = nightOwlLight;
-
export const fontSizes = [12, 14, 16, 20, 24, 32, 48, 64, 96];
-
export const fontWeights = ['300', '400', '500', '700', '800'];
-
export const letterSpacings = ['normal', '0.01em', '0.05em', '0.1em'];
-
export const borderWidths = ['1px', '0.1rem', '0.25rem'];
-
export const space = [0, 4, 8, 16, 32, 64];
-
export const sizes = [0, 64, 260, 430, 540, 650, 870, 980, 1400];
-
export const breakpoints = ['55em', '70em'];
-
export const radii = [4, 8, 16];
-
export const zIndices = [0, 1, 2, 3];
-
-
export const borders = [
-
`${borderWidths[0]} solid ${colors.bgPassive}`,
-
`${borderWidths[1]} solid ${colors.bgPassive}`,
-
`${borderWidths[2]} solid ${colors.bgPassive}`,
-
];
···
-15
gatsby/typography.js
···
-
import Typography from 'typography';
-
import * as theme from './theme';
-
-
const typography = new Typography({
-
includeNormalize: false,
-
baseFontSize: '18px',
-
baseLineHeight: 1.5,
-
scaleRatio: 46 / 18,
-
headerFontFamily: theme.fonts.header,
-
headerWeight: '500',
-
bodyFontFamily: theme.fonts.body,
-
bodyWeight: '400',
-
});
-
-
export default typography;
···